@burdenoff/microfe-devportal 2026.720.2 → 2026.720.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/devportal/hooks/usePackageUpload.d.ts.map +1 -1
  2. package/dist/devportal/hooks/usePackageUpload.js.map +1 -1
  3. package/dist/devportal/pages/ApplicationDetailPage.d.ts.map +1 -1
  4. package/dist/devportal/pages/ApplicationDetailPage.js +29 -1
  5. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  6. package/dist/devportal/pages/ApplicationsPage.d.ts.map +1 -1
  7. package/dist/devportal/pages/ApplicationsPage.js +281 -214
  8. package/dist/devportal/pages/ApplicationsPage.js.map +1 -1
  9. package/dist/devportal/pages/CreateApplicationPage.d.ts.map +1 -1
  10. package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
  11. package/dist/devportal/pages/EditApplicationPage.d.ts.map +1 -1
  12. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  13. package/dist/devportal/pages/PublishPage.d.ts.map +1 -1
  14. package/dist/devportal/pages/PublishPage.js.map +1 -1
  15. package/dist/devportal/pages/SellerDashboardPage.d.ts.map +1 -1
  16. package/dist/devportal/pages/SellerDashboardPage.js.map +1 -1
  17. package/dist/devportal/pages/SellerItemsPage.d.ts.map +1 -1
  18. package/dist/devportal/pages/SellerItemsPage.js.map +1 -1
  19. package/dist/devportal/types/index.d.ts +1 -1
  20. package/dist/devportal/types/index.d.ts.map +1 -1
  21. package/dist/devportal/types/index.js.map +1 -1
  22. package/dist/generated/global-operations.d.ts +30 -0
  23. package/dist/generated/global-operations.d.ts.map +1 -1
  24. package/dist/generated/global-operations.js +222 -210
  25. package/dist/generated/global-operations.js.map +1 -1
  26. package/dist/generated/global-types.d.ts +7 -1
  27. package/dist/generated/global-types.d.ts.map +1 -1
  28. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"EditApplicationPage.js","names":[],"sources":["../../../src/devportal/pages/EditApplicationPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState, useEffect } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useParams } from \"react-router-dom\";\nimport {\n Save,\n Trash2,\n AlertTriangle,\n Archive,\n Send,\n AlertCircle,\n AppWindow,\n Power,\n Check,\n Copy,\n Eye,\n EyeOff,\n RefreshCw,\n} from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n TagInput,\n CheckboxField,\n} from \"../components/FormField\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { LoadingState } from \"../components/LoadingState\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { cn } from \"../utils/cn\";\nimport { nativeImpact, nativeNotify } from \"../../utils/nativeBridge\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport type { Application, AppType, AppVisibility, AppStatus } from \"../types\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useGetApplicationQuery,\n useUpdateApplicationMutation,\n useDeleteApplicationMutation,\n useDeactivateAppMutation,\n useRotateApplicationSigningSecretMutation,\n} from \"../../generated/global-operations\";\n\ninterface EditApplicationFormData {\n name: string;\n slug: string;\n shortDescription: string;\n description: string;\n appType: AppType;\n visibility: AppVisibility;\n category: string;\n tags: string[];\n keywords: string[];\n websiteUrl: string;\n documentationUrl: string;\n supportUrl: string;\n privacyPolicyUrl: string;\n termsOfServiceUrl: string;\n githubUrl: string;\n oauthAuthUrl: string;\n oauthRevokeUrl: string;\n requiresApproval: boolean;\n}\n\ninterface FormErrors {\n name?: string;\n slug?: string;\n shortDescription?: string;\n appType?: string;\n category?: string;\n}\n\nconst COMPATIBLE_PRODUCTS = [\n { value: \"fluidgrids\", label: \"FluidGrids\" },\n { value: \"workspaces\", label: \"Workspaces\" },\n { value: \"bigconsole\", label: \"BigConsole\" },\n { value: \"botlit\", label: \"Botlit\" },\n];\n\nconst APP_TYPE_OPTIONS = Object.entries(APP_TYPE_LABELS).map(\n ([value, label]) => ({\n value,\n label,\n }),\n);\n\nconst BASE_VISIBILITY_OPTIONS = [\n { value: \"PUBLIC\", label: \"Public — listed in the marketplace after review\" },\n { value: \"PRIVATE\", label: \"Private — only you (the creator) can see it\" },\n { value: \"INTERNAL\", label: \"Internal — visible to your entire dev org\" },\n];\n\nconst WORKFLOW_VISIBILITY_OPTIONS = [\n ...BASE_VISIBILITY_OPTIONS,\n {\n value: \"UNLISTED\",\n label: \"Unlisted — shareable via link, not listed in store\",\n },\n];\n\nconst CATEGORY_OPTIONS = [\n { value: \"ai\", label: \"AI & Automation\" },\n { value: \"integration\", label: \"Action in an App\" },\n { value: \"data\", label: \"Data & Transform\" },\n { value: \"flow\", label: \"Flow & Logic\" },\n { value: \"core\", label: \"Core\" },\n { value: \"communication\", label: \"Communication\" },\n { value: \"trigger\", label: \"Triggers\" },\n];\n\n/**\n * Helper to safely map GraphQL response to Application type\n */\nfunction mapToApplication(\n data: NonNullable<\n ReturnType<typeof useGetApplicationQuery>[\"data\"]\n >[\"application\"],\n): Application | null {\n if (!data) return null;\n return {\n id: data.id,\n name: data.name,\n slug: data.slug,\n shortDescription: data.shortDescription || undefined,\n description: data.description || undefined,\n appType: data.appType,\n status: data.status,\n visibility: data.visibility,\n tenantId: data.tenantId,\n developerId: data.developerId,\n developerOrganizationId: data.developerOrganizationId || undefined,\n category: data.category || undefined,\n tags: data.tags || [],\n keywords: data.keywords || [],\n iconUrl: data.iconUrl || undefined,\n websiteUrl: data.websiteUrl || undefined,\n documentationUrl: data.documentationUrl || undefined,\n supportUrl: data.supportUrl || undefined,\n privacyPolicyUrl: data.privacyPolicyUrl || undefined,\n termsOfServiceUrl: data.termsOfServiceUrl || undefined,\n githubUrl: data.githubUrl || undefined,\n pricingType: data.pricingType || undefined,\n installCount: data.installCount,\n activeInstallCount: data.activeInstallCount,\n averageRating: data.averageRating ?? undefined,\n reviewCount: data.reviewCount,\n submittedAt: data.submittedAt || undefined,\n publishedAt: data.publishedAt || undefined,\n lastReviewedAt: data.lastReviewedAt || undefined,\n reviewStatus: data.reviewStatus,\n reviewNotes: data.reviewNotes || undefined,\n reviewedBy: data.reviewedBy || undefined,\n isFeatured: data.isFeatured,\n isVerified: data.isVerified,\n requiresApproval: data.requiresApproval,\n oauthAuthUrl: data.oauthAuthUrl || undefined,\n oauthRevokeUrl: data.oauthRevokeUrl || undefined,\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n };\n}\n\n/**\n * Edit application page — wired to real GraphQL mutations.\n */\nexport const EditApplicationPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { appId } = useParams<{ appId: string }>();\n const { t } = useI18n();\n const { allowed: canUpdate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_UPDATE,\n );\n const { allowed: canDelete } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_DELETE,\n );\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errors, setErrors] = useState<FormErrors>({});\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [showDeprecateDialog, setShowDeprecateDialog] = useState(false);\n const [showDeactivateDialog, setShowDeactivateDialog] = useState(false);\n const [hasChanges, setHasChanges] = useState(false);\n const [showSecret, setShowSecret] = useState(false);\n const [isRotating, setIsRotating] = useState(false);\n const [rotatedSecret, setRotatedSecret] = useState<string | null>(null);\n const [copiedSecret, setCopiedSecret] = useState(false);\n\n // ---------------------------------------------------------------------------\n // GraphQL queries & mutations\n // ---------------------------------------------------------------------------\n const {\n data,\n loading,\n error: queryError,\n refetch,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n });\n\n const [updateApplication] = useUpdateApplicationMutation();\n const [deleteApplication] = useDeleteApplicationMutation();\n const [deactivateApp] = useDeactivateAppMutation();\n const [rotateSigningSecret] = useRotateApplicationSigningSecretMutation();\n\n // ---------------------------------------------------------------------------\n // Derive application from query data\n // ---------------------------------------------------------------------------\n const app = mapToApplication(data?.application);\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n // ---------------------------------------------------------------------------\n // Form state — initialised from fetched app once available\n // ---------------------------------------------------------------------------\n const [formData, setFormData] = useState<EditApplicationFormData>({\n name: \"\",\n slug: \"\",\n shortDescription: \"\",\n description: \"\",\n appType: \"WEB_APP\",\n visibility: \"PUBLIC\",\n category: \"\",\n tags: [],\n keywords: [],\n websiteUrl: \"\",\n documentationUrl: \"\",\n supportUrl: \"\",\n privacyPolicyUrl: \"\",\n termsOfServiceUrl: \"\",\n githubUrl: \"\",\n oauthAuthUrl: \"\",\n oauthRevokeUrl: \"\",\n requiresApproval: false,\n });\n const [compatibleProducts, setCompatibleProducts] = useState<string[]>([]);\n\n useEffect(() => {\n if (app) {\n setFormData({\n name: app.name,\n slug: app.slug,\n shortDescription: app.shortDescription || \"\",\n description: app.description || \"\",\n appType: app.appType,\n visibility: app.visibility,\n category: app.category || \"\",\n tags: app.tags,\n keywords: app.keywords,\n websiteUrl: app.websiteUrl || \"\",\n documentationUrl: app.documentationUrl || \"\",\n supportUrl: app.supportUrl || \"\",\n privacyPolicyUrl: app.privacyPolicyUrl || \"\",\n termsOfServiceUrl: app.termsOfServiceUrl || \"\",\n githubUrl: app.githubUrl || \"\",\n oauthAuthUrl: app.oauthAuthUrl || \"\",\n oauthRevokeUrl: app.oauthRevokeUrl || \"\",\n requiresApproval: app.requiresApproval,\n });\n // Load compatibleProducts from manifest.compatibility.products\n // Note: mapToApplication doesn't copy manifest, so read from raw query data directly.\n const manifest = data?.application?.manifest as\n | Record<string, unknown>\n | null\n | undefined;\n const compatibility = manifest?.compatibility as\n | Record<string, unknown>\n | undefined;\n const products = Array.isArray(compatibility?.products)\n ? (compatibility.products as string[])\n : [];\n setCompatibleProducts(products);\n setHasChanges(false);\n }\n // Re-sync form when the underlying application data changes (e.g. after\n // a refetch triggered by a mutation). We intentionally depend on\n // `data?.application` rather than the derived `app` object so that the\n // effect fires when the query cache updates.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [data?.application]);\n\n // ---------------------------------------------------------------------------\n // Handlers\n // ---------------------------------------------------------------------------\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const handleChange = (\n field: keyof EditApplicationFormData,\n value: string | string[] | boolean,\n ) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n setHasChanges(true);\n if (errors[field as keyof FormErrors]) {\n setErrors((prev) => ({ ...prev, [field]: undefined }));\n }\n };\n\n const handleRotateSecret = async () => {\n if (!appId) return;\n setIsRotating(true);\n try {\n const result = await rotateSigningSecret({ variables: { id: appId } });\n const newSecret =\n result.data?.rotateApplicationSigningSecret?.signingSecret;\n if (newSecret) {\n setRotatedSecret(newSecret);\n setShowSecret(true);\n }\n } catch {\n nativeNotify(\"error\");\n } finally {\n setIsRotating(false);\n }\n };\n\n const handleCopySecret = async (secret: string) => {\n await navigator.clipboard.writeText(secret);\n setCopiedSecret(true);\n setTimeout(() => setCopiedSecret(false), 2000);\n };\n\n const validateForm = (): boolean => {\n const newErrors: FormErrors = {};\n\n if (!formData.name.trim()) {\n newErrors.name = tr(\n \"devportal.appNameRequired\",\n \"Application name is required\",\n );\n } else if (formData.name.length < 3) {\n newErrors.name = tr(\n \"devportal.appNameMinLength\",\n \"Name must be at least 3 characters\",\n );\n } else if (formData.name.length > 100) {\n newErrors.name = tr(\n \"devportal.appNameMaxLength\",\n \"Name must be less than 100 characters\",\n );\n }\n\n if (!formData.slug.trim()) {\n newErrors.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n } else if (!/^[a-z0-9-]+$/.test(formData.slug)) {\n newErrors.slug = tr(\n \"devportal.slugInvalidChars\",\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n );\n }\n\n if (!formData.shortDescription.trim()) {\n newErrors.shortDescription = tr(\n \"devportal.shortDescriptionRequired\",\n \"Short description is required\",\n );\n } else if (formData.shortDescription.length > 200) {\n newErrors.shortDescription = tr(\n \"devportal.shortDescriptionMaxLength\",\n \"Short description must be less than 200 characters\",\n );\n }\n\n if (!formData.appType) {\n newErrors.appType = tr(\n \"devportal.appTypeRequired\",\n \"Application type is required\",\n );\n }\n\n if (!formData.category) {\n newErrors.category = tr(\n \"devportal.categoryRequired\",\n \"Category is required\",\n );\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n if (!validateForm() || !app) {\n return;\n }\n\n setIsSubmitting(true);\n\n try {\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n name: formData.name,\n shortDescription: formData.shortDescription,\n description: formData.description,\n appType: formData.appType,\n visibility: formData.visibility,\n category: formData.category,\n tags: formData.tags,\n keywords: formData.keywords,\n websiteUrl: formData.websiteUrl || null,\n documentationUrl: formData.documentationUrl || null,\n supportUrl: formData.supportUrl || null,\n privacyPolicyUrl: formData.privacyPolicyUrl || null,\n termsOfServiceUrl: formData.termsOfServiceUrl || null,\n githubUrl: formData.githubUrl || null,\n oauthAuthUrl: formData.oauthAuthUrl || null,\n oauthRevokeUrl: formData.oauthRevokeUrl || null,\n compatibleProducts,\n },\n },\n });\n setHasChanges(false);\n } catch (err) {\n console.error(\"Failed to update application:\", err);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleDelete = async () => {\n if (!app) return;\n void nativeImpact(\"medium\");\n try {\n await deleteApplication({\n variables: { id: app.id },\n });\n void nativeNotify(\"success\");\n handleNavigate(\"/apps\");\n } catch (err) {\n void nativeNotify(\"error\");\n console.error(\"Failed to delete application:\", err);\n }\n };\n\n const handleDeprecate = async () => {\n if (!app) return;\n try {\n // Deprecate is modelled as a status transition via update. The backend\n // treats a visibility change to PRIVATE + status mutation or a dedicated\n // deprecation endpoint. Here we use submitApplication with a status note\n // as the deprecate action since there is no separate `deprecateApplication`\n // mutation. If a dedicated mutation is added later, swap it in here.\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n visibility: \"PRIVATE\",\n },\n },\n });\n setShowDeprecateDialog(false);\n } catch (err) {\n console.error(\"Failed to deprecate application:\", err);\n }\n };\n\n const handleDeactivate = async () => {\n if (!app) return;\n try {\n await deactivateApp({\n variables: { id: app.id },\n });\n setShowDeactivateDialog(false);\n handleNavigate(\"/apps\");\n } catch (err) {\n console.error(\"Failed to deactivate application:\", err);\n }\n };\n\n // ---------------------------------------------------------------------------\n // Loading / Error / Not-found states\n // ---------------------------------------------------------------------------\n if (loading) {\n return (\n <LoadingState\n message={tr(\"devportal.loadingApplication\", \"Loading application...\")}\n />\n );\n }\n\n if (queryError) {\n return (\n <PageLayout\n title={tr(\"devportal.error\", \"Error\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <AlertCircle size={48} className=\"text-status-error-text mb-4\" />\n <h3 className=\"text-lg font-semibold mb-2\">\n {tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n </h3>\n <p className=\"text-sm text-text-secondary\">{queryError.message}</p>\n </div>\n </PageLayout>\n );\n }\n\n if (!app) {\n return (\n <PageLayout\n title={tr(\"devportal.notFound\", \"Not Found\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <EmptyState\n illustration=\"empty-generic\"\n icon={<AppWindow size={48} />}\n title={tr(\"devportal.applicationNotFound\", \"Application not found\")}\n description={tr(\n \"devportal.applicationNotFoundDescription\",\n \"The application you're looking for doesn't exist or you don't have access to it.\",\n )}\n />\n </PageLayout>\n );\n }\n\n // ---------------------------------------------------------------------------\n // Derived flags\n // ---------------------------------------------------------------------------\n const canSubmitForReview =\n app.status === \"DRAFT\" || app.status === \"REJECTED\";\n const canDeprecate = app.status === \"PUBLISHED\";\n const canDeactivate = app.status === \"ACTIVE\" || app.status === \"PUBLISHED\";\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_UPDATE}>\n <PageLayout\n title={`${tr(\"devportal.editAppTitlePrefix\", \"Edit:\")} ${app.name}`}\n description={tr(\n \"devportal.editAppDescription\",\n \"Update your application settings\",\n )}\n purpose={tr(\n \"devportal.editAppPurpose\",\n \"Change how this app appears and behaves — its name, description, classification, links, and lifecycle settings. Use the danger zone at the bottom to deprecate or delete it when it is retired.\",\n )}\n backLink={`${basePath}/apps/${app.id}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <div className=\"flex items-center gap-2\">\n <StatusBadge status={app.status} type=\"app\" />\n </div>\n }\n >\n <form onSubmit={handleSubmit} className=\"space-y-8 max-w-3xl\">\n {/* Status banner for published apps */}\n {app.status === \"PUBLISHED\" && (\n <div className=\"rounded-lg border border-border-subtle bg-status-warning-bg-subtle p-4 flex gap-3\">\n <AlertTriangle\n size={20}\n className=\"text-status-warning-text flex-shrink-0 mt-0.5\"\n />\n <div className=\"text-sm text-status-warning-text\">\n <p className=\"font-medium\">\n {tr(\n \"devportal.appIsPublished\",\n \"This application is published\",\n )}\n </p>\n <p className=\"mt-1 text-status-warning-text\">\n {tr(\n \"devportal.publishedAppChangesWarning\",\n \"Changes to published apps may require re-review. Major changes will put the app back into review status.\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {/* Basic Information */}\n <PageSection\n title={tr(\"devportal.basicInformation\", \"Basic Information\")}\n description={tr(\n \"devportal.basicInformationDescription\",\n \"Core details about your application\",\n )}\n >\n <div className=\"space-y-4\">\n <InputField\n label={tr(\"devportal.applicationName\", \"Application Name\")}\n value={formData.name}\n onChange={(e) => handleChange(\"name\", e.target.value)}\n placeholder={tr(\n \"devportal.applicationNamePlaceholder\",\n \"My Awesome App\",\n )}\n required\n error={errors.name}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={formData.slug}\n onChange={(e) =>\n handleChange(\"slug\", e.target.value.toLowerCase())\n }\n placeholder={tr(\"devportal.slugPlaceholder\", \"my-awesome-app\")}\n required\n error={errors.slug}\n hint={tr(\n \"devportal.slugChangeWarning\",\n \"Changing the slug may break existing integrations\",\n )}\n />\n\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={formData.shortDescription}\n onChange={(e) =>\n handleChange(\"shortDescription\", e.target.value)\n }\n placeholder={tr(\n \"devportal.shortDescriptionPlaceholder\",\n \"A brief description of what your app does\",\n )}\n required\n error={errors.shortDescription}\n hint={`${formData.shortDescription.length}/200 ${tr(\"devportal.characters\", \"characters\")}`}\n rows={2}\n />\n\n <TextareaField\n label={tr(\"devportal.fullDescription\", \"Full Description\")}\n value={formData.description}\n onChange={(e) => handleChange(\"description\", e.target.value)}\n placeholder={tr(\n \"devportal.fullDescriptionPlaceholder\",\n \"Detailed description of your application, features, and use cases...\",\n )}\n rows={6}\n hint={tr(\n \"devportal.markdownSupported\",\n \"Markdown formatting is supported\",\n )}\n />\n </div>\n </PageSection>\n\n {/* Classification */}\n <PageSection\n title={tr(\"devportal.classification\", \"Classification\")}\n description={tr(\n \"devportal.classificationDescription\",\n \"Categorize your application\",\n )}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <SelectField\n label={tr(\"devportal.applicationType\", \"Application Type\")}\n value={formData.appType}\n onChange={(e) => handleChange(\"appType\", e.target.value)}\n options={APP_TYPE_OPTIONS}\n required\n error={errors.appType}\n />\n\n <SelectField\n label={tr(\"devportal.category\", \"Category\")}\n value={formData.category}\n onChange={(e) => handleChange(\"category\", e.target.value)}\n options={CATEGORY_OPTIONS}\n required\n error={errors.category}\n />\n\n <SelectField\n label={tr(\"devportal.visibility\", \"Visibility\")}\n value={formData.visibility}\n onChange={(e) =>\n handleChange(\"visibility\", e.target.value as AppVisibility)\n }\n options={\n app?.appType === \"WORKFLOW\"\n ? WORKFLOW_VISIBILITY_OPTIONS\n : BASE_VISIBILITY_OPTIONS\n }\n hint={\n formData.visibility === \"PUBLIC\"\n ? tr(\n \"devportal.visibilityHintPublic\",\n \"Listed in the marketplace after review approval — anyone can discover and install it\",\n )\n : formData.visibility === \"UNLISTED\"\n ? tr(\n \"devportal.visibilityHintUnlisted\",\n \"Not in the store, but accessible via a direct link. You can still submit for marketplace review\",\n )\n : formData.visibility === \"INTERNAL\"\n ? tr(\n \"devportal.visibilityHintInternal\",\n \"Visible to all members of your developer organization — no one outside can access it\",\n )\n : tr(\n \"devportal.visibilityHintPrivate\",\n \"Only you (the creator) can see this — other org members cannot access it\",\n )\n }\n />\n </div>\n\n <TagInput\n label={tr(\"devportal.tags\", \"Tags\")}\n value={formData.tags}\n onChange={(tags) => handleChange(\"tags\", tags)}\n placeholder={tr(\n \"devportal.addTagsPlaceholder\",\n \"Add tags (press Enter)\",\n )}\n />\n\n <TagInput\n label={tr(\"devportal.keywords\", \"Keywords\")}\n value={formData.keywords}\n onChange={(keywords) => handleChange(\"keywords\", keywords)}\n placeholder={tr(\n \"devportal.addKeywordsPlaceholder\",\n \"Add keywords (press Enter)\",\n )}\n />\n\n {/* Compatible Products — NODE and WORKFLOW only */}\n {(formData.appType === \"NODE\" ||\n formData.appType === \"WORKFLOW\") && (\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-text-primary\">\n Compatible Products\n </label>\n <p className=\"text-xs text-text-secondary\">\n Select which products this {formData.appType.toLowerCase()}{\" \"}\n works with. Users will see it in those products&apos; node\n stores.\n </p>\n <div className=\"flex flex-wrap gap-3\">\n {COMPATIBLE_PRODUCTS.map((product) => {\n const checked = compatibleProducts.includes(product.value);\n return (\n <label\n key={product.value}\n className={cn(\n \"flex items-center gap-2 cursor-pointer rounded-md border px-3 py-2 text-sm transition-colors\",\n checked\n ? \"border-primary bg-primary/10 text-text-primary\"\n : \"border-border-subtle hover:border-border text-text-secondary hover:text-text-primary\",\n )}\n >\n <input\n type=\"checkbox\"\n className=\"sr-only\"\n checked={checked}\n onChange={() => {\n setCompatibleProducts((prev) =>\n checked\n ? prev.filter((v) => v !== product.value)\n : [...prev, product.value],\n );\n setHasChanges(true);\n }}\n />\n {checked && (\n <Check\n size={14}\n className=\"text-primary flex-shrink-0\"\n />\n )}\n {product.label}\n </label>\n );\n })}\n </div>\n </div>\n )}\n </PageSection>\n\n {/* URLs */}\n <PageSection\n title={tr(\"devportal.links\", \"Links\")}\n description={tr(\n \"devportal.linksDescription\",\n \"External resources for your application\",\n )}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.websiteUrl\", \"Website URL\")}\n type=\"url\"\n value={formData.websiteUrl}\n onChange={(e) => handleChange(\"websiteUrl\", e.target.value)}\n placeholder={tr(\n \"devportal.websiteUrlPlaceholder\",\n \"https://example.com\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.documentationUrl\", \"Documentation URL\")}\n type=\"url\"\n value={formData.documentationUrl}\n onChange={(e) =>\n handleChange(\"documentationUrl\", e.target.value)\n }\n placeholder={tr(\n \"devportal.documentationUrlPlaceholder\",\n \"https://docs.example.com\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.supportUrl\", \"Support URL\")}\n type=\"url\"\n value={formData.supportUrl}\n onChange={(e) => handleChange(\"supportUrl\", e.target.value)}\n placeholder={tr(\n \"devportal.supportUrlPlaceholder\",\n \"https://support.example.com\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.githubUrl\", \"GitHub URL\")}\n type=\"url\"\n value={formData.githubUrl}\n onChange={(e) => handleChange(\"githubUrl\", e.target.value)}\n placeholder={tr(\n \"devportal.githubUrlPlaceholder\",\n \"https://github.com/org/repo\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.privacyPolicyUrl\", \"Privacy Policy URL\")}\n type=\"url\"\n value={formData.privacyPolicyUrl}\n onChange={(e) =>\n handleChange(\"privacyPolicyUrl\", e.target.value)\n }\n placeholder={tr(\n \"devportal.privacyPolicyUrlPlaceholder\",\n \"https://example.com/privacy\",\n )}\n />\n\n <InputField\n label={tr(\n \"devportal.termsOfServiceUrl\",\n \"Terms of Service URL\",\n )}\n type=\"url\"\n value={formData.termsOfServiceUrl}\n onChange={(e) =>\n handleChange(\"termsOfServiceUrl\", e.target.value)\n }\n placeholder={tr(\n \"devportal.termsOfServiceUrlPlaceholder\",\n \"https://example.com/terms\",\n )}\n />\n </div>\n </PageSection>\n\n {/* Integration Setup — INTEGRATION / API_INTEGRATION only */}\n {(formData.appType === \"INTEGRATION\" ||\n formData.appType === \"API_INTEGRATION\") && (\n <PageSection\n title=\"Integration Setup\"\n description=\"Configure the endpoints for your integration. After a user installs, we redirect them to your callback URL so your server can complete the connection.\"\n >\n <div className=\"space-y-4\">\n <InputField\n label=\"Post-install Callback URL\"\n type=\"url\"\n value={formData.oauthAuthUrl}\n onChange={(e) => handleChange(\"oauthAuthUrl\", e.target.value)}\n placeholder=\"https://yourapp.com/callback\"\n hint=\"Users land here after install with ?installation_id=xxx appended\"\n />\n <InputField\n label=\"Revoke URL\"\n type=\"url\"\n value={formData.oauthRevokeUrl}\n onChange={(e) =>\n handleChange(\"oauthRevokeUrl\", e.target.value)\n }\n placeholder=\"https://yourapp.com/oauth/revoke\"\n hint=\"We POST to this URL when a user uninstalls your integration\"\n />\n {/* Signing secret — read-only, rotate-only */}\n {(() => {\n const displaySecret =\n rotatedSecret ?? data?.application?.signingSecret;\n const masked = \"boff_sk_\" + \"•\".repeat(32);\n return (\n <div className=\"space-y-1.5\">\n <label className=\"block text-sm font-medium text-text-primary\">\n Signing Secret\n </label>\n <p className=\"text-xs text-text-secondary\">\n Use this secret to authenticate{\" \"}\n <code className=\"font-mono text-xs bg-bg-sunken px-1 py-0.5 rounded\">\n verifyInstallation\n </code>{\" \"}\n calls from your integration server. Store it securely —\n it is only shown immediately after generation or\n rotation.\n </p>\n {displaySecret ? (\n <div className=\"flex items-center gap-2\">\n <div className=\"flex-1 flex items-center gap-0 rounded-md border border-border-default bg-bg-sunken overflow-hidden\">\n <code className=\"flex-1 px-3 py-2 text-xs font-mono text-text-primary truncate\">\n {showSecret ? displaySecret : masked}\n </code>\n <button\n type=\"button\"\n onClick={() => setShowSecret((v) => !v)}\n className=\"px-2 py-2 text-text-secondary hover:text-text-primary border-l border-border-default\"\n title={showSecret ? \"Hide\" : \"Reveal\"}\n >\n {showSecret ? (\n <EyeOff size={14} />\n ) : (\n <Eye size={14} />\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => handleCopySecret(displaySecret)}\n className=\"px-2 py-2 text-text-secondary hover:text-text-primary border-l border-border-default\"\n title=\"Copy to clipboard\"\n >\n {copiedSecret ? (\n <Check size={14} className=\"text-green-500\" />\n ) : (\n <Copy size={14} />\n )}\n </button>\n </div>\n <button\n type=\"button\"\n onClick={handleRotateSecret}\n disabled={isRotating}\n className=\"flex items-center gap-1.5 px-3 py-2 text-xs rounded-md border border-border-default bg-bg-default text-text-primary hover:bg-bg-subtle disabled:opacity-50\"\n title=\"Rotate signing secret\"\n >\n <RefreshCw\n size={12}\n className={isRotating ? \"animate-spin\" : \"\"}\n />\n Rotate\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={handleRotateSecret}\n disabled={isRotating}\n className=\"flex items-center gap-1.5 px-3 py-2 text-xs rounded-md border border-border-default bg-bg-default text-text-primary hover:bg-bg-subtle disabled:opacity-50\"\n >\n <RefreshCw\n size={12}\n className={isRotating ? \"animate-spin\" : \"\"}\n />\n Generate Signing Secret\n </button>\n )}\n {rotatedSecret && (\n <p className=\"text-xs text-amber-600 dark:text-amber-400\">\n New secret generated. Copy it now — the old secret is\n already invalidated.\n </p>\n )}\n </div>\n );\n })()}\n </div>\n </PageSection>\n )}\n\n {/* Settings */}\n <PageSection\n title={tr(\"devportal.settings\", \"Settings\")}\n description={tr(\n \"devportal.settingsDescription\",\n \"Additional configuration options\",\n )}\n >\n <div className=\"space-y-4\">\n <CheckboxField\n label={tr(\n \"devportal.requireWorkspaceAdminApproval\",\n \"Require workspace admin approval\",\n )}\n description={tr(\n \"devportal.requireWorkspaceAdminApprovalDescription\",\n \"When enabled, workspace admins must approve installations before users can access this app\",\n )}\n checked={formData.requiresApproval}\n onChange={(e) =>\n handleChange(\"requiresApproval\", e.target.checked)\n }\n />\n </div>\n </PageSection>\n\n {/* Submission readiness checklist */}\n {canSubmitForReview && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken p-4 space-y-2\">\n <p className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Send size={14} />\n {tr(\"devportal.submissionChecklist\", \"Submission Checklist\")}\n </p>\n {[\n {\n label: tr(\"devportal.checkName\", \"Name set\"),\n ok: !!formData.name.trim(),\n },\n {\n label: tr(\n \"devportal.checkShortDesc\",\n \"Short description set\",\n ),\n ok: !!formData.shortDescription.trim(),\n },\n {\n label: tr(\n \"devportal.checkFullDesc\",\n \"Full description added\",\n ),\n ok: !!formData.description.trim(),\n },\n {\n label: tr(\"devportal.checkCategory\", \"Category selected\"),\n ok: !!formData.category,\n },\n {\n label: tr(\n \"devportal.checkVisibility\",\n \"Visibility set to Public or Unlisted\",\n ),\n ok:\n !!formData.visibility && formData.visibility !== \"PRIVATE\",\n },\n {\n label: tr(\"devportal.checkSaved\", \"All changes saved\"),\n ok: !hasChanges,\n },\n ...(app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\"\n ? [\n {\n label: tr(\n \"devportal.checkVersion\",\n \"At least one version uploaded\",\n ),\n ok: (data?.application?.versions?.totalCount ?? 0) > 0,\n },\n ]\n : []),\n ].map((item) => (\n <div\n key={item.label}\n className=\"flex items-center gap-2 text-sm\"\n >\n {item.ok ? (\n <span className=\"text-status-success-text\">✓</span>\n ) : (\n <span className=\"text-status-error-text\">✗</span>\n )}\n <span\n className={\n item.ok\n ? \"text-text-secondary line-through\"\n : \"text-text-primary\"\n }\n >\n {item.label}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col gap-4 border-t pt-6\">\n {/* Primary actions */}\n <div className=\"flex items-center justify-end\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !hasChanges || !canUpdate}\n aria-disabled={!canUpdate}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {isSubmitting ? (\n <>\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n {tr(\"devportal.saving\", \"Saving...\")}\n </>\n ) : (\n <>\n <Save size={16} />\n {tr(\"devportal.saveChanges\", \"Save Changes\")}\n </>\n )}\n </button>\n </div>\n\n {/* Danger zone */}\n <div className=\"rounded-lg border border-border-subtle bg-status-error-bg-subtle p-4\">\n <h3 className=\"text-sm font-medium text-status-error-text\">\n {tr(\"devportal.dangerZone\", \"Danger Zone\")}\n </h3>\n <p className=\"mt-1 text-sm text-status-error-text\">\n {tr(\n \"devportal.dangerZoneWarning\",\n \"These actions are irreversible. Please proceed with caution.\",\n )}\n </p>\n <div className=\"mt-4 flex gap-3\">\n {canDeprecate && (\n <button\n type=\"button\"\n onClick={() => setShowDeprecateDialog(true)}\n className=\"inline-flex items-center gap-2 rounded-md border border-accent-orange bg-bg-surface px-3 py-1.5 text-sm font-medium text-accent-orange hover:bg-accent-orange-subtle transition-colors\"\n >\n <Archive size={14} />\n {tr(\"devportal.deprecateApp\", \"Deprecate App\")}\n </button>\n )}\n {canDeactivate && (\n <button\n type=\"button\"\n onClick={() => setShowDeactivateDialog(true)}\n className=\"inline-flex items-center gap-2 rounded-md border border-accent-orange bg-bg-surface px-3 py-1.5 text-sm font-medium text-accent-orange hover:bg-accent-orange-subtle transition-colors\"\n >\n <Power size={14} />\n {tr(\"devportal.deactivateApp\", \"Deactivate App\")}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => setShowDeleteDialog(true)}\n disabled={!canDelete}\n aria-disabled={!canDelete}\n className=\"inline-flex items-center gap-2 rounded-md border border-status-error-bg bg-bg-surface px-3 py-1.5 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors disabled:opacity-50\"\n >\n <Trash2 size={14} />\n {tr(\"devportal.deleteApp\", \"Delete App\")}\n </button>\n </div>\n </div>\n </div>\n </form>\n\n {/* Delete confirmation dialog */}\n <ConfirmDialog\n open={showDeleteDialog}\n onOpenChange={setShowDeleteDialog}\n title={tr(\"devportal.deleteApplication\", \"Delete Application\")}\n description={tr(\n \"devportal.deleteApplicationConfirm\",\n `Are you sure you want to delete \"${app.name}\"? This action cannot be undone. All OAuth clients, API keys, webhooks, and analytics data will be permanently deleted.`,\n )}\n confirmLabel={tr(\"devportal.deleteApplication\", \"Delete Application\")}\n variant=\"destructive\"\n onConfirm={handleDelete}\n />\n\n {/* Deprecate confirmation dialog */}\n <ConfirmDialog\n open={showDeprecateDialog}\n onOpenChange={setShowDeprecateDialog}\n title={tr(\"devportal.deprecateApplication\", \"Deprecate Application\")}\n description={tr(\n \"devportal.deprecateApplicationConfirm\",\n `Are you sure you want to deprecate \"${app.name}\"? Existing users will still be able to use the app, but it will no longer be visible in the marketplace and new installations will be disabled.`,\n )}\n confirmLabel={tr(\n \"devportal.deprecateApplication\",\n \"Deprecate Application\",\n )}\n variant=\"warning\"\n onConfirm={handleDeprecate}\n />\n\n {/* Deactivate confirmation dialog */}\n <ConfirmDialog\n open={showDeactivateDialog}\n onOpenChange={setShowDeactivateDialog}\n title={tr(\n \"devportal.deactivateApplication\",\n \"Deactivate Application\",\n )}\n description={tr(\n \"devportal.deactivateApplicationConfirm\",\n `Are you sure you want to deactivate \"${app.name}\"? This will revoke all active tokens and disable the app from the auth-svc layer. The app will no longer be able to authenticate or act on behalf of users.`,\n )}\n confirmLabel={tr(\n \"devportal.deactivateApplication\",\n \"Deactivate Application\",\n )}\n variant=\"destructive\"\n onConfirm={handleDeactivate}\n />\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"EditApplicationPage.js","names":[],"sources":["../../../src/devportal/pages/EditApplicationPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState, useEffect } from \"react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { useParams } from \"react-router-dom\";\nimport {\n Save,\n Trash2,\n AlertTriangle,\n Archive,\n Send,\n AlertCircle,\n AppWindow,\n Power,\n Check,\n Copy,\n Eye,\n EyeOff,\n RefreshCw,\n} from \"lucide-react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n TagInput,\n CheckboxField,\n} from \"../components/FormField\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { LoadingState } from \"../components/LoadingState\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { cn } from \"../utils/cn\";\nimport { nativeImpact, nativeNotify } from \"../../utils/nativeBridge\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport type { Application, AppType, AppVisibility, AppStatus } from \"../types\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useGetApplicationQuery,\n useUpdateApplicationMutation,\n useDeleteApplicationMutation,\n useDeactivateAppMutation,\n useRotateApplicationSigningSecretMutation,\n} from \"../../generated/global-operations\";\n\ninterface EditApplicationFormData {\n name: string;\n slug: string;\n shortDescription: string;\n description: string;\n appType: AppType;\n visibility: AppVisibility;\n category: string;\n tags: string[];\n keywords: string[];\n websiteUrl: string;\n documentationUrl: string;\n supportUrl: string;\n privacyPolicyUrl: string;\n termsOfServiceUrl: string;\n githubUrl: string;\n oauthAuthUrl: string;\n oauthRevokeUrl: string;\n requiresApproval: boolean;\n}\n\ninterface FormErrors {\n name?: string;\n slug?: string;\n shortDescription?: string;\n appType?: string;\n category?: string;\n}\n\nconst COMPATIBLE_PRODUCTS = [\n { value: \"fluidgrids\", label: \"FluidGrids\" },\n { value: \"workspaces\", label: \"Workspaces\" },\n { value: \"bigconsole\", label: \"BigConsole\" },\n { value: \"botlit\", label: \"Botlit\" },\n];\n\nconst APP_TYPE_OPTIONS = Object.entries(APP_TYPE_LABELS).map(\n ([value, label]) => ({\n value,\n label,\n }),\n);\n\nconst BASE_VISIBILITY_OPTIONS = [\n { value: \"PUBLIC\", label: \"Public — listed in the marketplace after review\" },\n { value: \"PRIVATE\", label: \"Private — only you (the creator) can see it\" },\n { value: \"INTERNAL\", label: \"Internal — visible to your entire dev org\" },\n];\n\nconst WORKFLOW_VISIBILITY_OPTIONS = [\n ...BASE_VISIBILITY_OPTIONS,\n {\n value: \"UNLISTED\",\n label: \"Unlisted — shareable via link, not listed in store\",\n },\n];\n\nconst CATEGORY_OPTIONS = [\n { value: \"ai\", label: \"AI & Automation\" },\n { value: \"integration\", label: \"Action in an App\" },\n { value: \"data\", label: \"Data & Transform\" },\n { value: \"flow\", label: \"Flow & Logic\" },\n { value: \"core\", label: \"Core\" },\n { value: \"communication\", label: \"Communication\" },\n { value: \"trigger\", label: \"Triggers\" },\n];\n\n/**\n * Helper to safely map GraphQL response to Application type\n */\nfunction mapToApplication(\n data: NonNullable<\n ReturnType<typeof useGetApplicationQuery>[\"data\"]\n >[\"application\"],\n): Application | null {\n if (!data) return null;\n return {\n id: data.id,\n name: data.name,\n slug: data.slug,\n shortDescription: data.shortDescription || undefined,\n description: data.description || undefined,\n appType: data.appType,\n status: data.status,\n visibility: data.visibility,\n tenantId: data.tenantId,\n developerId: data.developerId,\n developerOrganizationId: data.developerOrganizationId || undefined,\n category: data.category || undefined,\n tags: data.tags || [],\n keywords: data.keywords || [],\n iconUrl: data.iconUrl || undefined,\n websiteUrl: data.websiteUrl || undefined,\n documentationUrl: data.documentationUrl || undefined,\n supportUrl: data.supportUrl || undefined,\n privacyPolicyUrl: data.privacyPolicyUrl || undefined,\n termsOfServiceUrl: data.termsOfServiceUrl || undefined,\n githubUrl: data.githubUrl || undefined,\n pricingType: data.pricingType || undefined,\n installCount: data.installCount,\n activeInstallCount: data.activeInstallCount,\n averageRating: data.averageRating ?? undefined,\n reviewCount: data.reviewCount,\n submittedAt: data.submittedAt || undefined,\n publishedAt: data.publishedAt || undefined,\n lastReviewedAt: data.lastReviewedAt || undefined,\n reviewStatus: data.reviewStatus,\n reviewNotes: data.reviewNotes || undefined,\n reviewedBy: data.reviewedBy || undefined,\n isFeatured: data.isFeatured,\n isVerified: data.isVerified,\n requiresApproval: data.requiresApproval,\n oauthAuthUrl: data.oauthAuthUrl || undefined,\n oauthRevokeUrl: data.oauthRevokeUrl || undefined,\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n };\n}\n\n/**\n * Edit application page — wired to real GraphQL mutations.\n */\nexport const EditApplicationPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { appId } = useParams<{ appId: string }>();\n const { t } = useI18n();\n const { allowed: canUpdate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_UPDATE,\n );\n const { allowed: canDelete } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_DELETE,\n );\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [errors, setErrors] = useState<FormErrors>({});\n const [showDeleteDialog, setShowDeleteDialog] = useState(false);\n const [showDeprecateDialog, setShowDeprecateDialog] = useState(false);\n const [showDeactivateDialog, setShowDeactivateDialog] = useState(false);\n const [hasChanges, setHasChanges] = useState(false);\n const [showSecret, setShowSecret] = useState(false);\n const [isRotating, setIsRotating] = useState(false);\n const [rotatedSecret, setRotatedSecret] = useState<string | null>(null);\n const [copiedSecret, setCopiedSecret] = useState(false);\n\n // ---------------------------------------------------------------------------\n // GraphQL queries & mutations\n // ---------------------------------------------------------------------------\n const {\n data,\n loading,\n error: queryError,\n refetch,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n });\n\n const [updateApplication] = useUpdateApplicationMutation();\n const [deleteApplication] = useDeleteApplicationMutation();\n const [deactivateApp] = useDeactivateAppMutation();\n const [rotateSigningSecret] = useRotateApplicationSigningSecretMutation();\n\n // ---------------------------------------------------------------------------\n // Derive application from query data\n // ---------------------------------------------------------------------------\n const app = mapToApplication(data?.application);\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n // ---------------------------------------------------------------------------\n // Form state — initialised from fetched app once available\n // ---------------------------------------------------------------------------\n const [formData, setFormData] = useState<EditApplicationFormData>({\n name: \"\",\n slug: \"\",\n shortDescription: \"\",\n description: \"\",\n appType: \"WEB_APP\",\n visibility: \"PUBLIC\",\n category: \"\",\n tags: [],\n keywords: [],\n websiteUrl: \"\",\n documentationUrl: \"\",\n supportUrl: \"\",\n privacyPolicyUrl: \"\",\n termsOfServiceUrl: \"\",\n githubUrl: \"\",\n oauthAuthUrl: \"\",\n oauthRevokeUrl: \"\",\n requiresApproval: false,\n });\n const [compatibleProducts, setCompatibleProducts] = useState<string[]>([]);\n\n useEffect(() => {\n if (app) {\n setFormData({\n name: app.name,\n slug: app.slug,\n shortDescription: app.shortDescription || \"\",\n description: app.description || \"\",\n appType: app.appType,\n visibility: app.visibility,\n category: app.category || \"\",\n tags: app.tags,\n keywords: app.keywords,\n websiteUrl: app.websiteUrl || \"\",\n documentationUrl: app.documentationUrl || \"\",\n supportUrl: app.supportUrl || \"\",\n privacyPolicyUrl: app.privacyPolicyUrl || \"\",\n termsOfServiceUrl: app.termsOfServiceUrl || \"\",\n githubUrl: app.githubUrl || \"\",\n oauthAuthUrl: app.oauthAuthUrl || \"\",\n oauthRevokeUrl: app.oauthRevokeUrl || \"\",\n requiresApproval: app.requiresApproval,\n });\n // Load compatibleProducts from manifest.compatibility.products\n // Note: mapToApplication doesn't copy manifest, so read from raw query data directly.\n const manifest = data?.application?.manifest as\n Record<string, unknown> | null | undefined;\n const compatibility = manifest?.compatibility as\n Record<string, unknown> | undefined;\n const products = Array.isArray(compatibility?.products)\n ? (compatibility.products as string[])\n : [];\n setCompatibleProducts(products);\n setHasChanges(false);\n }\n // Re-sync form when the underlying application data changes (e.g. after\n // a refetch triggered by a mutation). We intentionally depend on\n // `data?.application` rather than the derived `app` object so that the\n // effect fires when the query cache updates.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [data?.application]);\n\n // ---------------------------------------------------------------------------\n // Handlers\n // ---------------------------------------------------------------------------\n const handleNavigate = (path: string) => {\n navigate?.(`${basePath}${path}`);\n };\n\n const handleChange = (\n field: keyof EditApplicationFormData,\n value: string | string[] | boolean,\n ) => {\n setFormData((prev) => ({ ...prev, [field]: value }));\n setHasChanges(true);\n if (errors[field as keyof FormErrors]) {\n setErrors((prev) => ({ ...prev, [field]: undefined }));\n }\n };\n\n const handleRotateSecret = async () => {\n if (!appId) return;\n setIsRotating(true);\n try {\n const result = await rotateSigningSecret({ variables: { id: appId } });\n const newSecret =\n result.data?.rotateApplicationSigningSecret?.signingSecret;\n if (newSecret) {\n setRotatedSecret(newSecret);\n setShowSecret(true);\n }\n } catch {\n nativeNotify(\"error\");\n } finally {\n setIsRotating(false);\n }\n };\n\n const handleCopySecret = async (secret: string) => {\n await navigator.clipboard.writeText(secret);\n setCopiedSecret(true);\n setTimeout(() => setCopiedSecret(false), 2000);\n };\n\n const validateForm = (): boolean => {\n const newErrors: FormErrors = {};\n\n if (!formData.name.trim()) {\n newErrors.name = tr(\n \"devportal.appNameRequired\",\n \"Application name is required\",\n );\n } else if (formData.name.length < 3) {\n newErrors.name = tr(\n \"devportal.appNameMinLength\",\n \"Name must be at least 3 characters\",\n );\n } else if (formData.name.length > 100) {\n newErrors.name = tr(\n \"devportal.appNameMaxLength\",\n \"Name must be less than 100 characters\",\n );\n }\n\n if (!formData.slug.trim()) {\n newErrors.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n } else if (!/^[a-z0-9-]+$/.test(formData.slug)) {\n newErrors.slug = tr(\n \"devportal.slugInvalidChars\",\n \"Slug can only contain lowercase letters, numbers, and hyphens\",\n );\n }\n\n if (!formData.shortDescription.trim()) {\n newErrors.shortDescription = tr(\n \"devportal.shortDescriptionRequired\",\n \"Short description is required\",\n );\n } else if (formData.shortDescription.length > 200) {\n newErrors.shortDescription = tr(\n \"devportal.shortDescriptionMaxLength\",\n \"Short description must be less than 200 characters\",\n );\n }\n\n if (!formData.appType) {\n newErrors.appType = tr(\n \"devportal.appTypeRequired\",\n \"Application type is required\",\n );\n }\n\n if (!formData.category) {\n newErrors.category = tr(\n \"devportal.categoryRequired\",\n \"Category is required\",\n );\n }\n\n setErrors(newErrors);\n return Object.keys(newErrors).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n\n if (!validateForm() || !app) {\n return;\n }\n\n setIsSubmitting(true);\n\n try {\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n name: formData.name,\n shortDescription: formData.shortDescription,\n description: formData.description,\n appType: formData.appType,\n visibility: formData.visibility,\n category: formData.category,\n tags: formData.tags,\n keywords: formData.keywords,\n websiteUrl: formData.websiteUrl || null,\n documentationUrl: formData.documentationUrl || null,\n supportUrl: formData.supportUrl || null,\n privacyPolicyUrl: formData.privacyPolicyUrl || null,\n termsOfServiceUrl: formData.termsOfServiceUrl || null,\n githubUrl: formData.githubUrl || null,\n oauthAuthUrl: formData.oauthAuthUrl || null,\n oauthRevokeUrl: formData.oauthRevokeUrl || null,\n compatibleProducts,\n },\n },\n });\n setHasChanges(false);\n } catch (err) {\n console.error(\"Failed to update application:\", err);\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleDelete = async () => {\n if (!app) return;\n void nativeImpact(\"medium\");\n try {\n await deleteApplication({\n variables: { id: app.id },\n });\n void nativeNotify(\"success\");\n handleNavigate(\"/apps\");\n } catch (err) {\n void nativeNotify(\"error\");\n console.error(\"Failed to delete application:\", err);\n }\n };\n\n const handleDeprecate = async () => {\n if (!app) return;\n try {\n // Deprecate is modelled as a status transition via update. The backend\n // treats a visibility change to PRIVATE + status mutation or a dedicated\n // deprecation endpoint. Here we use submitApplication with a status note\n // as the deprecate action since there is no separate `deprecateApplication`\n // mutation. If a dedicated mutation is added later, swap it in here.\n await updateApplication({\n variables: {\n id: app.id,\n input: {\n visibility: \"PRIVATE\",\n },\n },\n });\n setShowDeprecateDialog(false);\n } catch (err) {\n console.error(\"Failed to deprecate application:\", err);\n }\n };\n\n const handleDeactivate = async () => {\n if (!app) return;\n try {\n await deactivateApp({\n variables: { id: app.id },\n });\n setShowDeactivateDialog(false);\n handleNavigate(\"/apps\");\n } catch (err) {\n console.error(\"Failed to deactivate application:\", err);\n }\n };\n\n // ---------------------------------------------------------------------------\n // Loading / Error / Not-found states\n // ---------------------------------------------------------------------------\n if (loading) {\n return (\n <LoadingState\n message={tr(\"devportal.loadingApplication\", \"Loading application...\")}\n />\n );\n }\n\n if (queryError) {\n return (\n <PageLayout\n title={tr(\"devportal.error\", \"Error\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <AlertCircle size={48} className=\"text-status-error-text mb-4\" />\n <h3 className=\"text-lg font-semibold mb-2\">\n {tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n </h3>\n <p className=\"text-sm text-text-secondary\">{queryError.message}</p>\n </div>\n </PageLayout>\n );\n }\n\n if (!app) {\n return (\n <PageLayout\n title={tr(\"devportal.notFound\", \"Not Found\")}\n backLink={`${basePath}/apps`}\n backLabel={tr(\"devportal.backToApplications\", \"Back to Applications\")}\n >\n <EmptyState\n illustration=\"empty-generic\"\n icon={<AppWindow size={48} />}\n title={tr(\"devportal.applicationNotFound\", \"Application not found\")}\n description={tr(\n \"devportal.applicationNotFoundDescription\",\n \"The application you're looking for doesn't exist or you don't have access to it.\",\n )}\n />\n </PageLayout>\n );\n }\n\n // ---------------------------------------------------------------------------\n // Derived flags\n // ---------------------------------------------------------------------------\n const canSubmitForReview =\n app.status === \"DRAFT\" || app.status === \"REJECTED\";\n const canDeprecate = app.status === \"PUBLISHED\";\n const canDeactivate = app.status === \"ACTIVE\" || app.status === \"PUBLISHED\";\n\n // ---------------------------------------------------------------------------\n // Render\n // ---------------------------------------------------------------------------\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_UPDATE}>\n <PageLayout\n title={`${tr(\"devportal.editAppTitlePrefix\", \"Edit:\")} ${app.name}`}\n description={tr(\n \"devportal.editAppDescription\",\n \"Update your application settings\",\n )}\n purpose={tr(\n \"devportal.editAppPurpose\",\n \"Change how this app appears and behaves — its name, description, classification, links, and lifecycle settings. Use the danger zone at the bottom to deprecate or delete it when it is retired.\",\n )}\n backLink={`${basePath}/apps/${app.id}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <div className=\"flex items-center gap-2\">\n <StatusBadge status={app.status} type=\"app\" />\n </div>\n }\n >\n <form onSubmit={handleSubmit} className=\"space-y-8 max-w-3xl\">\n {/* Status banner for published apps */}\n {app.status === \"PUBLISHED\" && (\n <div className=\"rounded-lg border border-border-subtle bg-status-warning-bg-subtle p-4 flex gap-3\">\n <AlertTriangle\n size={20}\n className=\"text-status-warning-text flex-shrink-0 mt-0.5\"\n />\n <div className=\"text-sm text-status-warning-text\">\n <p className=\"font-medium\">\n {tr(\n \"devportal.appIsPublished\",\n \"This application is published\",\n )}\n </p>\n <p className=\"mt-1 text-status-warning-text\">\n {tr(\n \"devportal.publishedAppChangesWarning\",\n \"Changes to published apps may require re-review. Major changes will put the app back into review status.\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {/* Basic Information */}\n <PageSection\n title={tr(\"devportal.basicInformation\", \"Basic Information\")}\n description={tr(\n \"devportal.basicInformationDescription\",\n \"Core details about your application\",\n )}\n >\n <div className=\"space-y-4\">\n <InputField\n label={tr(\"devportal.applicationName\", \"Application Name\")}\n value={formData.name}\n onChange={(e) => handleChange(\"name\", e.target.value)}\n placeholder={tr(\n \"devportal.applicationNamePlaceholder\",\n \"My Awesome App\",\n )}\n required\n error={errors.name}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={formData.slug}\n onChange={(e) =>\n handleChange(\"slug\", e.target.value.toLowerCase())\n }\n placeholder={tr(\"devportal.slugPlaceholder\", \"my-awesome-app\")}\n required\n error={errors.slug}\n hint={tr(\n \"devportal.slugChangeWarning\",\n \"Changing the slug may break existing integrations\",\n )}\n />\n\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={formData.shortDescription}\n onChange={(e) =>\n handleChange(\"shortDescription\", e.target.value)\n }\n placeholder={tr(\n \"devportal.shortDescriptionPlaceholder\",\n \"A brief description of what your app does\",\n )}\n required\n error={errors.shortDescription}\n hint={`${formData.shortDescription.length}/200 ${tr(\"devportal.characters\", \"characters\")}`}\n rows={2}\n />\n\n <TextareaField\n label={tr(\"devportal.fullDescription\", \"Full Description\")}\n value={formData.description}\n onChange={(e) => handleChange(\"description\", e.target.value)}\n placeholder={tr(\n \"devportal.fullDescriptionPlaceholder\",\n \"Detailed description of your application, features, and use cases...\",\n )}\n rows={6}\n hint={tr(\n \"devportal.markdownSupported\",\n \"Markdown formatting is supported\",\n )}\n />\n </div>\n </PageSection>\n\n {/* Classification */}\n <PageSection\n title={tr(\"devportal.classification\", \"Classification\")}\n description={tr(\n \"devportal.classificationDescription\",\n \"Categorize your application\",\n )}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <SelectField\n label={tr(\"devportal.applicationType\", \"Application Type\")}\n value={formData.appType}\n onChange={(e) => handleChange(\"appType\", e.target.value)}\n options={APP_TYPE_OPTIONS}\n required\n error={errors.appType}\n />\n\n <SelectField\n label={tr(\"devportal.category\", \"Category\")}\n value={formData.category}\n onChange={(e) => handleChange(\"category\", e.target.value)}\n options={CATEGORY_OPTIONS}\n required\n error={errors.category}\n />\n\n <SelectField\n label={tr(\"devportal.visibility\", \"Visibility\")}\n value={formData.visibility}\n onChange={(e) =>\n handleChange(\"visibility\", e.target.value as AppVisibility)\n }\n options={\n app?.appType === \"WORKFLOW\"\n ? WORKFLOW_VISIBILITY_OPTIONS\n : BASE_VISIBILITY_OPTIONS\n }\n hint={\n formData.visibility === \"PUBLIC\"\n ? tr(\n \"devportal.visibilityHintPublic\",\n \"Listed in the marketplace after review approval — anyone can discover and install it\",\n )\n : formData.visibility === \"UNLISTED\"\n ? tr(\n \"devportal.visibilityHintUnlisted\",\n \"Not in the store, but accessible via a direct link. You can still submit for marketplace review\",\n )\n : formData.visibility === \"INTERNAL\"\n ? tr(\n \"devportal.visibilityHintInternal\",\n \"Visible to all members of your developer organization — no one outside can access it\",\n )\n : tr(\n \"devportal.visibilityHintPrivate\",\n \"Only you (the creator) can see this — other org members cannot access it\",\n )\n }\n />\n </div>\n\n <TagInput\n label={tr(\"devportal.tags\", \"Tags\")}\n value={formData.tags}\n onChange={(tags) => handleChange(\"tags\", tags)}\n placeholder={tr(\n \"devportal.addTagsPlaceholder\",\n \"Add tags (press Enter)\",\n )}\n />\n\n <TagInput\n label={tr(\"devportal.keywords\", \"Keywords\")}\n value={formData.keywords}\n onChange={(keywords) => handleChange(\"keywords\", keywords)}\n placeholder={tr(\n \"devportal.addKeywordsPlaceholder\",\n \"Add keywords (press Enter)\",\n )}\n />\n\n {/* Compatible Products — NODE and WORKFLOW only */}\n {(formData.appType === \"NODE\" ||\n formData.appType === \"WORKFLOW\") && (\n <div className=\"space-y-2\">\n <label className=\"block text-sm font-medium text-text-primary\">\n Compatible Products\n </label>\n <p className=\"text-xs text-text-secondary\">\n Select which products this {formData.appType.toLowerCase()}{\" \"}\n works with. Users will see it in those products&apos; node\n stores.\n </p>\n <div className=\"flex flex-wrap gap-3\">\n {COMPATIBLE_PRODUCTS.map((product) => {\n const checked = compatibleProducts.includes(product.value);\n return (\n <label\n key={product.value}\n className={cn(\n \"flex items-center gap-2 cursor-pointer rounded-md border px-3 py-2 text-sm transition-colors\",\n checked\n ? \"border-primary bg-primary/10 text-text-primary\"\n : \"border-border-subtle hover:border-border text-text-secondary hover:text-text-primary\",\n )}\n >\n <input\n type=\"checkbox\"\n className=\"sr-only\"\n checked={checked}\n onChange={() => {\n setCompatibleProducts((prev) =>\n checked\n ? prev.filter((v) => v !== product.value)\n : [...prev, product.value],\n );\n setHasChanges(true);\n }}\n />\n {checked && (\n <Check\n size={14}\n className=\"text-primary flex-shrink-0\"\n />\n )}\n {product.label}\n </label>\n );\n })}\n </div>\n </div>\n )}\n </PageSection>\n\n {/* URLs */}\n <PageSection\n title={tr(\"devportal.links\", \"Links\")}\n description={tr(\n \"devportal.linksDescription\",\n \"External resources for your application\",\n )}\n >\n <div className=\"grid gap-4 sm:grid-cols-2\">\n <InputField\n label={tr(\"devportal.websiteUrl\", \"Website URL\")}\n type=\"url\"\n value={formData.websiteUrl}\n onChange={(e) => handleChange(\"websiteUrl\", e.target.value)}\n placeholder={tr(\n \"devportal.websiteUrlPlaceholder\",\n \"https://example.com\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.documentationUrl\", \"Documentation URL\")}\n type=\"url\"\n value={formData.documentationUrl}\n onChange={(e) =>\n handleChange(\"documentationUrl\", e.target.value)\n }\n placeholder={tr(\n \"devportal.documentationUrlPlaceholder\",\n \"https://docs.example.com\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.supportUrl\", \"Support URL\")}\n type=\"url\"\n value={formData.supportUrl}\n onChange={(e) => handleChange(\"supportUrl\", e.target.value)}\n placeholder={tr(\n \"devportal.supportUrlPlaceholder\",\n \"https://support.example.com\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.githubUrl\", \"GitHub URL\")}\n type=\"url\"\n value={formData.githubUrl}\n onChange={(e) => handleChange(\"githubUrl\", e.target.value)}\n placeholder={tr(\n \"devportal.githubUrlPlaceholder\",\n \"https://github.com/org/repo\",\n )}\n />\n\n <InputField\n label={tr(\"devportal.privacyPolicyUrl\", \"Privacy Policy URL\")}\n type=\"url\"\n value={formData.privacyPolicyUrl}\n onChange={(e) =>\n handleChange(\"privacyPolicyUrl\", e.target.value)\n }\n placeholder={tr(\n \"devportal.privacyPolicyUrlPlaceholder\",\n \"https://example.com/privacy\",\n )}\n />\n\n <InputField\n label={tr(\n \"devportal.termsOfServiceUrl\",\n \"Terms of Service URL\",\n )}\n type=\"url\"\n value={formData.termsOfServiceUrl}\n onChange={(e) =>\n handleChange(\"termsOfServiceUrl\", e.target.value)\n }\n placeholder={tr(\n \"devportal.termsOfServiceUrlPlaceholder\",\n \"https://example.com/terms\",\n )}\n />\n </div>\n </PageSection>\n\n {/* Integration Setup — INTEGRATION / API_INTEGRATION only */}\n {(formData.appType === \"INTEGRATION\" ||\n formData.appType === \"API_INTEGRATION\") && (\n <PageSection\n title=\"Integration Setup\"\n description=\"Configure the endpoints for your integration. After a user installs, we redirect them to your callback URL so your server can complete the connection.\"\n >\n <div className=\"space-y-4\">\n <InputField\n label=\"Post-install Callback URL\"\n type=\"url\"\n value={formData.oauthAuthUrl}\n onChange={(e) => handleChange(\"oauthAuthUrl\", e.target.value)}\n placeholder=\"https://yourapp.com/callback\"\n hint=\"Users land here after install with ?installation_id=xxx appended\"\n />\n <InputField\n label=\"Revoke URL\"\n type=\"url\"\n value={formData.oauthRevokeUrl}\n onChange={(e) =>\n handleChange(\"oauthRevokeUrl\", e.target.value)\n }\n placeholder=\"https://yourapp.com/oauth/revoke\"\n hint=\"We POST to this URL when a user uninstalls your integration\"\n />\n {/* Signing secret — read-only, rotate-only */}\n {(() => {\n const displaySecret =\n rotatedSecret ?? data?.application?.signingSecret;\n const masked = \"boff_sk_\" + \"•\".repeat(32);\n return (\n <div className=\"space-y-1.5\">\n <label className=\"block text-sm font-medium text-text-primary\">\n Signing Secret\n </label>\n <p className=\"text-xs text-text-secondary\">\n Use this secret to authenticate{\" \"}\n <code className=\"font-mono text-xs bg-bg-sunken px-1 py-0.5 rounded\">\n verifyInstallation\n </code>{\" \"}\n calls from your integration server. Store it securely —\n it is only shown immediately after generation or\n rotation.\n </p>\n {displaySecret ? (\n <div className=\"flex items-center gap-2\">\n <div className=\"flex-1 flex items-center gap-0 rounded-md border border-border-default bg-bg-sunken overflow-hidden\">\n <code className=\"flex-1 px-3 py-2 text-xs font-mono text-text-primary truncate\">\n {showSecret ? displaySecret : masked}\n </code>\n <button\n type=\"button\"\n onClick={() => setShowSecret((v) => !v)}\n className=\"px-2 py-2 text-text-secondary hover:text-text-primary border-l border-border-default\"\n title={showSecret ? \"Hide\" : \"Reveal\"}\n >\n {showSecret ? (\n <EyeOff size={14} />\n ) : (\n <Eye size={14} />\n )}\n </button>\n <button\n type=\"button\"\n onClick={() => handleCopySecret(displaySecret)}\n className=\"px-2 py-2 text-text-secondary hover:text-text-primary border-l border-border-default\"\n title=\"Copy to clipboard\"\n >\n {copiedSecret ? (\n <Check size={14} className=\"text-green-500\" />\n ) : (\n <Copy size={14} />\n )}\n </button>\n </div>\n <button\n type=\"button\"\n onClick={handleRotateSecret}\n disabled={isRotating}\n className=\"flex items-center gap-1.5 px-3 py-2 text-xs rounded-md border border-border-default bg-bg-default text-text-primary hover:bg-bg-subtle disabled:opacity-50\"\n title=\"Rotate signing secret\"\n >\n <RefreshCw\n size={12}\n className={isRotating ? \"animate-spin\" : \"\"}\n />\n Rotate\n </button>\n </div>\n ) : (\n <button\n type=\"button\"\n onClick={handleRotateSecret}\n disabled={isRotating}\n className=\"flex items-center gap-1.5 px-3 py-2 text-xs rounded-md border border-border-default bg-bg-default text-text-primary hover:bg-bg-subtle disabled:opacity-50\"\n >\n <RefreshCw\n size={12}\n className={isRotating ? \"animate-spin\" : \"\"}\n />\n Generate Signing Secret\n </button>\n )}\n {rotatedSecret && (\n <p className=\"text-xs text-amber-600 dark:text-amber-400\">\n New secret generated. Copy it now — the old secret is\n already invalidated.\n </p>\n )}\n </div>\n );\n })()}\n </div>\n </PageSection>\n )}\n\n {/* Settings */}\n <PageSection\n title={tr(\"devportal.settings\", \"Settings\")}\n description={tr(\n \"devportal.settingsDescription\",\n \"Additional configuration options\",\n )}\n >\n <div className=\"space-y-4\">\n <CheckboxField\n label={tr(\n \"devportal.requireWorkspaceAdminApproval\",\n \"Require workspace admin approval\",\n )}\n description={tr(\n \"devportal.requireWorkspaceAdminApprovalDescription\",\n \"When enabled, workspace admins must approve installations before users can access this app\",\n )}\n checked={formData.requiresApproval}\n onChange={(e) =>\n handleChange(\"requiresApproval\", e.target.checked)\n }\n />\n </div>\n </PageSection>\n\n {/* Submission readiness checklist */}\n {canSubmitForReview && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken p-4 space-y-2\">\n <p className=\"text-sm font-medium text-text-primary flex items-center gap-2\">\n <Send size={14} />\n {tr(\"devportal.submissionChecklist\", \"Submission Checklist\")}\n </p>\n {[\n {\n label: tr(\"devportal.checkName\", \"Name set\"),\n ok: !!formData.name.trim(),\n },\n {\n label: tr(\n \"devportal.checkShortDesc\",\n \"Short description set\",\n ),\n ok: !!formData.shortDescription.trim(),\n },\n {\n label: tr(\n \"devportal.checkFullDesc\",\n \"Full description added\",\n ),\n ok: !!formData.description.trim(),\n },\n {\n label: tr(\"devportal.checkCategory\", \"Category selected\"),\n ok: !!formData.category,\n },\n {\n label: tr(\n \"devportal.checkVisibility\",\n \"Visibility set to Public or Unlisted\",\n ),\n ok:\n !!formData.visibility && formData.visibility !== \"PRIVATE\",\n },\n {\n label: tr(\"devportal.checkSaved\", \"All changes saved\"),\n ok: !hasChanges,\n },\n ...(app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\"\n ? [\n {\n label: tr(\n \"devportal.checkVersion\",\n \"At least one version uploaded\",\n ),\n ok: (data?.application?.versions?.totalCount ?? 0) > 0,\n },\n ]\n : []),\n ].map((item) => (\n <div\n key={item.label}\n className=\"flex items-center gap-2 text-sm\"\n >\n {item.ok ? (\n <span className=\"text-status-success-text\">✓</span>\n ) : (\n <span className=\"text-status-error-text\">✗</span>\n )}\n <span\n className={\n item.ok\n ? \"text-text-secondary line-through\"\n : \"text-text-primary\"\n }\n >\n {item.label}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {/* Actions */}\n <div className=\"flex flex-col gap-4 border-t pt-6\">\n {/* Primary actions */}\n <div className=\"flex items-center justify-end\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !hasChanges || !canUpdate}\n aria-disabled={!canUpdate}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 transition-colors disabled:opacity-50\"\n >\n {isSubmitting ? (\n <>\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n {tr(\"devportal.saving\", \"Saving...\")}\n </>\n ) : (\n <>\n <Save size={16} />\n {tr(\"devportal.saveChanges\", \"Save Changes\")}\n </>\n )}\n </button>\n </div>\n\n {/* Danger zone */}\n <div className=\"rounded-lg border border-border-subtle bg-status-error-bg-subtle p-4\">\n <h3 className=\"text-sm font-medium text-status-error-text\">\n {tr(\"devportal.dangerZone\", \"Danger Zone\")}\n </h3>\n <p className=\"mt-1 text-sm text-status-error-text\">\n {tr(\n \"devportal.dangerZoneWarning\",\n \"These actions are irreversible. Please proceed with caution.\",\n )}\n </p>\n <div className=\"mt-4 flex gap-3\">\n {canDeprecate && (\n <button\n type=\"button\"\n onClick={() => setShowDeprecateDialog(true)}\n className=\"inline-flex items-center gap-2 rounded-md border border-accent-orange bg-bg-surface px-3 py-1.5 text-sm font-medium text-accent-orange hover:bg-accent-orange-subtle transition-colors\"\n >\n <Archive size={14} />\n {tr(\"devportal.deprecateApp\", \"Deprecate App\")}\n </button>\n )}\n {canDeactivate && (\n <button\n type=\"button\"\n onClick={() => setShowDeactivateDialog(true)}\n className=\"inline-flex items-center gap-2 rounded-md border border-accent-orange bg-bg-surface px-3 py-1.5 text-sm font-medium text-accent-orange hover:bg-accent-orange-subtle transition-colors\"\n >\n <Power size={14} />\n {tr(\"devportal.deactivateApp\", \"Deactivate App\")}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => setShowDeleteDialog(true)}\n disabled={!canDelete}\n aria-disabled={!canDelete}\n className=\"inline-flex items-center gap-2 rounded-md border border-status-error-bg bg-bg-surface px-3 py-1.5 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle transition-colors disabled:opacity-50\"\n >\n <Trash2 size={14} />\n {tr(\"devportal.deleteApp\", \"Delete App\")}\n </button>\n </div>\n </div>\n </div>\n </form>\n\n {/* Delete confirmation dialog */}\n <ConfirmDialog\n open={showDeleteDialog}\n onOpenChange={setShowDeleteDialog}\n title={tr(\"devportal.deleteApplication\", \"Delete Application\")}\n description={tr(\n \"devportal.deleteApplicationConfirm\",\n `Are you sure you want to delete \"${app.name}\"? This action cannot be undone. All OAuth clients, API keys, webhooks, and analytics data will be permanently deleted.`,\n )}\n confirmLabel={tr(\"devportal.deleteApplication\", \"Delete Application\")}\n variant=\"destructive\"\n onConfirm={handleDelete}\n />\n\n {/* Deprecate confirmation dialog */}\n <ConfirmDialog\n open={showDeprecateDialog}\n onOpenChange={setShowDeprecateDialog}\n title={tr(\"devportal.deprecateApplication\", \"Deprecate Application\")}\n description={tr(\n \"devportal.deprecateApplicationConfirm\",\n `Are you sure you want to deprecate \"${app.name}\"? Existing users will still be able to use the app, but it will no longer be visible in the marketplace and new installations will be disabled.`,\n )}\n confirmLabel={tr(\n \"devportal.deprecateApplication\",\n \"Deprecate Application\",\n )}\n variant=\"warning\"\n onConfirm={handleDeprecate}\n />\n\n {/* Deactivate confirmation dialog */}\n <ConfirmDialog\n open={showDeactivateDialog}\n onOpenChange={setShowDeactivateDialog}\n title={tr(\n \"devportal.deactivateApplication\",\n \"Deactivate Application\",\n )}\n description={tr(\n \"devportal.deactivateApplicationConfirm\",\n `Are you sure you want to deactivate \"${app.name}\"? This will revoke all active tokens and disable the app from the auth-svc layer. The app will no longer be able to authenticate or act on behalf of users.`,\n )}\n confirmLabel={tr(\n \"devportal.deactivateApplication\",\n \"Deactivate Application\",\n )}\n variant=\"destructive\"\n onConfirm={handleDeactivate}\n />\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PublishPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/PublishPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA2EhC,eAAO,MAAM,WAAW,EAAE,EAguBzB,CAAC"}
1
+ {"version":3,"file":"PublishPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/PublishPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AA2EhC,eAAO,MAAM,WAAW,EAAE,EA6tBzB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PublishPage.js","names":[],"sources":["../../../src/devportal/pages/PublishPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n XCircle,\n AlertTriangle,\n Send,\n FileText,\n Shield,\n Image,\n Globe,\n Loader2,\n Eye,\n ArrowRight,\n PartyPopper,\n Link,\n Webhook,\n KeyRound,\n} from \"lucide-react\";\nimport { gql } from \"@apollo/client\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { Alert } from \"../components/ConfirmDialog\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport {\n useGetApplicationQuery,\n useSubmitApplicationMutation,\n useSubmitApplicationForReviewMutation,\n} from \"../../generated/global-operations\";\nimport { useDevportalPermission } from \"../hooks\";\n\nconst MY_PUBLISHER_QUERY = gql`\n query PublishPagePublisher {\n myPublisher {\n id\n }\n }\n`;\nconst PUBLISHER_PRODUCTS_QUERY = gql`\n query PublishPageProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId }) {\n id\n productId\n }\n }\n`;\nconst APP_WEBHOOKS_QUERY = gql`\n query PublishPageWebhooks($applicationId: ID!) {\n webhooks(applicationId: $applicationId) {\n id\n }\n }\n`;\n\ninterface ChecklistItem {\n id: string;\n label: string;\n description: string;\n status: \"passed\" | \"failed\" | \"warning\" | \"pending\";\n icon: React.ReactNode;\n actionLabel?: string;\n actionPath?: string;\n}\n\nconst ALREADY_SUBMITTED_STATUSES = [\n \"SUBMITTED\",\n \"IN_REVIEW\",\n \"APPROVED\",\n \"PUBLISHED\",\n];\n\nexport const PublishPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n\n const {\n data,\n loading,\n error: queryError,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n fetchPolicy: \"network-only\",\n });\n\n const [submitApplication] = useSubmitApplicationMutation();\n const [submitApplicationForReview] = useSubmitApplicationForReviewMutation();\n\n // Two-step publisher lookup to find linked StoreProduct\n const { data: publisherData } = useQuery<{\n myPublisher: { id: string } | null;\n }>(MY_PUBLISHER_QUERY, { fetchPolicy: \"cache-first\" });\n const publisherId = publisherData?.myPublisher?.id ?? null;\n const { data: productsData } = useQuery<{\n products: { id: string; productId?: string | null }[];\n }>(PUBLISHER_PRODUCTS_QUERY, {\n variables: { publisherId: publisherId ?? \"\" },\n skip: !publisherId,\n fetchPolicy: \"cache-first\",\n });\n const linkedStoreProductId =\n productsData?.products?.find(\n (p: { id: string; productId?: string | null }) => p.productId === appId,\n )?.id ?? null;\n\n const isApiIntegration = data?.application?.appType === \"API_INTEGRATION\";\n const appManifest = data?.application?.manifest as\n | Record<string, unknown>\n | null\n | undefined;\n const appOauth = appManifest?.[\"oauth\"] as\n | Record<string, unknown>\n | undefined;\n const hasOAuthUrl = !!(\n appOauth?.[\"authorizationUrl\"] &&\n appOauth?.[\"tokenUrl\"] &&\n appOauth?.[\"clientId\"]\n );\n\n const { data: webhooksData } = useQuery<{ webhooks: { id: string }[] }>(\n APP_WEBHOOKS_QUERY,\n {\n variables: { applicationId: appId! },\n skip: !appId || !isApiIntegration,\n fetchPolicy: \"network-only\",\n },\n );\n const webhookCount = webhooksData?.webhooks?.length ?? 0;\n\n const app = data?.application;\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const isAlreadySubmitted = ALREADY_SUBMITTED_STATUSES.includes(\n app?.status ?? \"\",\n );\n\n const isPackageType = app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\";\n const publishedVersionCount = app?.versions?.totalCount ?? 0;\n\n const checklist = useMemo((): ChecklistItem[] => {\n if (!app) return [];\n\n const screenshotCount = app.screenshots?.length ?? 0;\n\n const storeListingPath = `/apps/${appId}?tab=store-listing`;\n const versionsPath = `/apps/${appId}/versions`;\n const editPath = `/apps/${appId}/edit#oauth-config`;\n const webhooksPath = `/apps/${appId}/webhooks`;\n\n const items: ChecklistItem[] = [\n {\n id: \"name\",\n label: tr(\"devportal.checklistNameLabel\", \"Name & Short Description\"),\n description: tr(\n \"devportal.checklistNameDesc\",\n \"Name and short description are required for the store card\",\n ),\n status: app.name && app.shortDescription ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"category\",\n label: tr(\"devportal.checklistCategoryLabel\", \"Category\"),\n description: tr(\n \"devportal.checklistCategoryDesc\",\n \"A category helps users find your item in the marketplace\",\n ),\n status: app.category ? \"passed\" : \"failed\",\n icon: <Globe size={20} />,\n actionLabel: \"Edit app info →\",\n actionPath: `/apps/${appId}/edit`,\n },\n {\n id: \"privacy\",\n label: tr(\"devportal.checklistPrivacyLabel\", \"Privacy Policy\"),\n description: tr(\n \"devportal.checklistPrivacyDesc\",\n \"Privacy policy URL is required for store submission\",\n ),\n status: app.privacyPolicyUrl ? \"passed\" : \"failed\",\n icon: <Shield size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"terms\",\n label: tr(\"devportal.checklistTermsLabel\", \"Terms of Service\"),\n description: tr(\n \"devportal.checklistTermsDesc\",\n \"Terms of service URL is required for store submission\",\n ),\n status: app.termsOfServiceUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"icon\",\n label: tr(\"devportal.checklistIconLabel\", \"App Icon\"),\n description: tr(\n \"devportal.checklistIconDesc\",\n \"An icon makes your listing stand out in the marketplace\",\n ),\n status: app.iconUrl ? \"passed\" : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"screenshots\",\n label: tr(\"devportal.checklistScreenshotsLabel\", \"Screenshots\"),\n description: tr(\n \"devportal.checklistScreenshotsDesc\",\n \"At least 3 screenshots are recommended\",\n ),\n status:\n screenshotCount >= 3\n ? \"passed\"\n : screenshotCount > 0\n ? \"warning\"\n : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n ];\n\n if (isPackageType) {\n items.push({\n id: \"version\",\n label: tr(\"devportal.checklistVersionLabel\", \"Published Version\"),\n description: tr(\n \"devportal.checklistVersionDesc\",\n app?.appType === \"WORKFLOW\"\n ? \"At least one published version (manifest JSON) is required before submitting to the store\"\n : \"At least one published version (ZIP + manifest) is required before submitting to the store\",\n ),\n status: publishedVersionCount > 0 ? \"passed\" : \"failed\",\n icon: <CheckCircle size={20} />,\n actionLabel: \"Create a version →\",\n actionPath: versionsPath,\n });\n }\n\n if (app.appType === \"API_INTEGRATION\") {\n items.push({\n id: \"oauth\",\n label: tr(\"devportal.checklistOAuthLabel\", \"OAuth Configuration\"),\n description: tr(\n \"devportal.checklistOAuthDesc\",\n \"Authorization URL, Token URL and Client ID are required so users can connect their accounts. Without these the Connect button does not work.\",\n ),\n status: hasOAuthUrl ? \"passed\" : \"failed\",\n icon: <KeyRound size={20} />,\n actionLabel: \"Configure in Edit App →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"webhook\",\n label: tr(\"devportal.checklistWebhookLabel\", \"Webhook Endpoint\"),\n description: tr(\n \"devportal.checklistWebhookDesc\",\n \"At least one webhook endpoint must be configured so your server receives platform events after users connect. Without this the integration does nothing.\",\n ),\n status: webhookCount > 0 ? \"passed\" : \"failed\",\n icon: <Webhook size={20} />,\n actionLabel: \"Add a webhook →\",\n actionPath: webhooksPath,\n });\n\n items.push({\n id: \"documentation\",\n label: tr(\"devportal.checklistDocsLabel\", \"Documentation URL\"),\n description: tr(\n \"devportal.checklistDocsDesc\",\n \"Users need to know how to use and configure this integration. A documentation link is required for API integrations.\",\n ),\n status: app.documentationUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Add documentation URL →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"website\",\n label: tr(\"devportal.checklistWebsiteLabel\", \"Website URL\"),\n description: tr(\n \"devportal.checklistWebsiteDesc\",\n \"Users need to verify who built this integration. A website URL is required so users know where to get support.\",\n ),\n status: app.websiteUrl ? \"passed\" : \"failed\",\n icon: <Link size={20} />,\n actionLabel: \"Add website URL →\",\n actionPath: editPath,\n });\n }\n\n items.push({\n id: \"status\",\n label: tr(\"devportal.checklistStatusLabel\", \"App Status\"),\n description: tr(\n \"devportal.checklistStatusDesc\",\n \"App must be in DRAFT or REJECTED state to submit\",\n ),\n status: [\"DRAFT\", \"REJECTED\"].includes(app.status ?? \"\")\n ? \"passed\"\n : \"warning\",\n icon: <CheckCircle size={20} />,\n });\n\n return items;\n }, [\n app,\n isPackageType,\n publishedVersionCount,\n webhookCount,\n hasOAuthUrl,\n appId,\n ]);\n\n const passedCount = checklist.filter((i) => i.status === \"passed\").length;\n const failedCount = checklist.filter((i) => i.status === \"failed\").length;\n const warningCount = checklist.filter((i) => i.status === \"warning\").length;\n const isSubmittableStatus = [\"DRAFT\", \"REJECTED\"].includes(app?.status ?? \"\");\n const canSubmit =\n !loading &&\n !queryError &&\n failedCount === 0 &&\n !!app &&\n !isAlreadySubmitted &&\n isSubmittableStatus;\n\n const getStatusIcon = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return <CheckCircle size={20} className=\"text-status-success-text\" />;\n case \"failed\":\n return <XCircle size={20} className=\"text-status-error-text\" />;\n case \"warning\":\n return <AlertTriangle size={20} className=\"text-status-warning-text\" />;\n default:\n return (\n <div className=\"h-5 w-5 rounded-full border-2 border-border-default\" />\n );\n }\n };\n\n const getStatusBg = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return \"bg-status-success-bg-subtle border-border-subtle\";\n case \"failed\":\n return \"bg-status-error-bg-subtle border-border-subtle\";\n case \"warning\":\n return \"bg-status-warning-bg-subtle border-border-subtle\";\n default:\n return \"bg-bg-canvas border-border-subtle\";\n }\n };\n\n const handleSubmit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n // Submit Application for devportal review (sets Application.status = SUBMITTED)\n const result = await submitApplication({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n if (result.error) throw result.error;\n\n // Also submit ApplicationForReview to set StoreProduct.status = PENDING_REVIEW\n // so it appears in the store admin review queue at /store/dashboard/submissions\n await submitApplicationForReview({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n\n setSubmitted(true);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.submitFailedDefault\", \"Failed to submit for review\"),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.loadingApplicationDetails\",\n \"Loading application details...\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"animate-spin h-8 w-8 text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (queryError || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.couldNotLoadApplication\",\n \"Could not load application\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <Alert\n variant=\"error\"\n title={tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n >\n {queryError?.message ??\n tr(\"devportal.applicationNotFound\", \"Application not found\")}\n </Alert>\n </PageLayout>\n );\n }\n\n if (submitted) {\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex flex-col items-center justify-center py-16 gap-6 text-center\">\n <div className=\"rounded-full bg-status-success-bg p-4\">\n <PartyPopper size={40} className=\"text-status-success-text\" />\n </div>\n <div className=\"space-y-2\">\n <h2 className=\"text-2xl font-bold\">\n {tr(\"devportal.submittedSuccessTitle\", \"Submitted for Review!\")}\n </h2>\n <p className=\"text-muted-foreground max-w-md\">\n {tr(\n \"devportal.submittedSuccessMsg\",\n \"Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.\",\n )}\n </p>\n </div>\n <div className=\"rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full\">\n <p className=\"font-medium\">What happens next:</p>\n <ul className=\"space-y-1 text-muted-foreground list-none\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Our team reviews your submission\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n You'll get an email on approval or if changes are needed\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Once approved, your app goes live in the marketplace\n </li>\n </ul>\n </div>\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Back to App\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n }\n\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={`${tr(\"devportal.submitAppForReview\", \"Submit\")} \"${app.name}\" ${tr(\"devportal.forReviewAndPublication\", \"for review and publication\")}`}\n purpose={tr(\n \"devportal.publishPurpose\",\n \"Submitting sends your app to the review team, who check it against the marketplace guidelines before it goes live to users. Make sure the listing, screenshots, and permissions are final — preview the listing first, since changes after approval need another review.\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/listing`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n <Eye size={16} />\n {tr(\"devportal.previewListing\", \"Preview Listing\")}\n </button>\n }\n >\n {isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.alreadySubmittedTitle\", \"Already Submitted\")}\n >\n {tr(\"devportal.alreadySubmittedMsg1\", \"This app is currently in\")}{\" \"}\n <strong>{app.status}</strong>{\" \"}\n {tr(\n \"devportal.alreadySubmittedMsg2\",\n \"state and cannot be re-submitted until the review process is complete or the app is rejected.\",\n )}\n </Alert>\n )}\n\n {/* Progress Summary */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.preSubmissionChecklist\", \"Pre-submission Checklist\")}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.completeAllRequiredItems\",\n \"Complete all required items before submitting for review\",\n )}\n </p>\n <div className=\"mt-4 flex gap-6\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle size={20} className=\"text-status-success-text\" />\n <span>\n {passedCount} {tr(\"devportal.passed\", \"Passed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <XCircle size={20} className=\"text-status-error-text\" />\n <span>\n {failedCount} {tr(\"devportal.failed\", \"Failed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AlertTriangle size={20} className=\"text-status-warning-text\" />\n <span>\n {warningCount} {tr(\"devportal.warnings\", \"Warnings\")}\n </span>\n </div>\n </div>\n </div>\n\n {/* Checklist Items */}\n <PageSection>\n <div className=\"space-y-3\">\n {checklist.map((item) => (\n <div\n key={item.id}\n className={`flex items-center gap-4 rounded-lg border p-4 ${getStatusBg(item.status)}`}\n >\n <div className=\"rounded-lg bg-bg-surface p-2\">{item.icon}</div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{item.label}</p>\n <p className=\"text-sm text-text-secondary\">\n {item.description}\n </p>\n {item.status !== \"passed\" && item.actionPath && (\n <button\n type=\"button\"\n onClick={() =>\n navigate?.(`${basePath}${item.actionPath}`)\n }\n className=\"mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n {item.actionLabel ?? \"Fix this\"} <ArrowRight size={11} />\n </button>\n )}\n </div>\n {getStatusIcon(item.status)}\n </div>\n ))}\n </div>\n </PageSection>\n\n {/* Submission Notes */}\n {!isAlreadySubmitted && (\n <PageSection\n title={tr(\"devportal.notesForReviewerTitle\", \"Notes for Reviewer\")}\n description={tr(\n \"devportal.notesForReviewerDesc\",\n \"Optional message to the review team\",\n )}\n >\n <textarea\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder={tr(\n \"devportal.notesForReviewerPlaceholder\",\n \"Describe what your app does, any special review considerations, or testing instructions...\",\n )}\n rows={4}\n maxLength={1000}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm ring-offset-background placeholder:text-text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] resize-none\"\n />\n <p className=\"mt-1 text-xs text-text-secondary text-right\">\n {notes.length}/1000\n </p>\n </PageSection>\n )}\n\n {/* Alerts */}\n {submitError && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.submissionFailedTitle\", \"Submission Failed\")}\n >\n {submitError}\n </Alert>\n )}\n\n {failedCount > 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.cannotSubmitTitle\", \"Cannot Submit Yet\")}\n >\n {tr(\"devportal.pleaseFixItems1\", \"Please fix\")} {failedCount}{\" \"}\n {tr(\n \"devportal.pleaseFixItems2\",\n \"required item(s) before submitting for review.\",\n )}\n <div className=\"mt-2 flex flex-wrap gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToMarketplaceListing\",\n \"Update marketplace listing →\",\n )}\n </button>\n {isPackageType && publishedVersionCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/versions`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\"devportal.goToVersions\", \"Add a published version →\")}\n </button>\n )}\n {isApiIntegration && !hasOAuthUrl && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/edit#oauth-config`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Configure OAuth endpoints →\n </button>\n )}\n {isApiIntegration && webhookCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/webhooks`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Add a webhook →\n </button>\n )}\n </div>\n </Alert>\n )}\n\n {warningCount > 0 && failedCount === 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.warningsTitle\", \"Warnings\")}\n >\n {tr(\"devportal.warningsMsg1\", \"You have\")} {warningCount}{\" \"}\n {tr(\n \"devportal.warningsMsg2\",\n \"warning(s). While you can submit, addressing these may improve your app's chances of approval.\",\n )}\n </Alert>\n )}\n\n {/* Review Process Info */}\n <PageSection\n title={tr(\"devportal.reviewProcessTitle\", \"Review Process\")}\n >\n <div className=\"rounded-lg border bg-bg-sunken/50 p-4\">\n <ul className=\"space-y-2 text-sm\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo1\",\n \"Review typically takes 3-5 business days\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo2\",\n \"You'll receive notifications about review status changes\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo3\",\n \"If changes are requested, you can resubmit without losing your place in the queue\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo4\",\n \"Once approved and published, your app will be visible in the marketplace\",\n )}\n </span>\n </li>\n </ul>\n </div>\n </PageSection>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n {tr(\"devportal.cancelButton\", \"Cancel\")}\n </button>\n <button\n onClick={handleSubmit}\n disabled={!canSubmit || submitting || !submitPerm.allowed}\n aria-disabled={!canSubmit || submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submittingButton\", \"Submitting...\")}\n </>\n ) : (\n <>\n <Send size={16} />\n {tr(\"devportal.submitForReviewButton\", \"Submit for Review\")}\n </>\n )}\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"PublishPage.js","names":[],"sources":["../../../src/devportal/pages/PublishPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n XCircle,\n AlertTriangle,\n Send,\n FileText,\n Shield,\n Image,\n Globe,\n Loader2,\n Eye,\n ArrowRight,\n PartyPopper,\n Link,\n Webhook,\n KeyRound,\n} from \"lucide-react\";\nimport { gql } from \"@apollo/client\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { Alert } from \"../components/ConfirmDialog\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport {\n useGetApplicationQuery,\n useSubmitApplicationMutation,\n useSubmitApplicationForReviewMutation,\n} from \"../../generated/global-operations\";\nimport { useDevportalPermission } from \"../hooks\";\n\nconst MY_PUBLISHER_QUERY = gql`\n query PublishPagePublisher {\n myPublisher {\n id\n }\n }\n`;\nconst PUBLISHER_PRODUCTS_QUERY = gql`\n query PublishPageProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId }) {\n id\n productId\n }\n }\n`;\nconst APP_WEBHOOKS_QUERY = gql`\n query PublishPageWebhooks($applicationId: ID!) {\n webhooks(applicationId: $applicationId) {\n id\n }\n }\n`;\n\ninterface ChecklistItem {\n id: string;\n label: string;\n description: string;\n status: \"passed\" | \"failed\" | \"warning\" | \"pending\";\n icon: React.ReactNode;\n actionLabel?: string;\n actionPath?: string;\n}\n\nconst ALREADY_SUBMITTED_STATUSES = [\n \"SUBMITTED\",\n \"IN_REVIEW\",\n \"APPROVED\",\n \"PUBLISHED\",\n];\n\nexport const PublishPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n\n const {\n data,\n loading,\n error: queryError,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n fetchPolicy: \"network-only\",\n });\n\n const [submitApplication] = useSubmitApplicationMutation();\n const [submitApplicationForReview] = useSubmitApplicationForReviewMutation();\n\n // Two-step publisher lookup to find linked StoreProduct\n const { data: publisherData } = useQuery<{\n myPublisher: { id: string } | null;\n }>(MY_PUBLISHER_QUERY, { fetchPolicy: \"cache-first\" });\n const publisherId = publisherData?.myPublisher?.id ?? null;\n const { data: productsData } = useQuery<{\n products: { id: string; productId?: string | null }[];\n }>(PUBLISHER_PRODUCTS_QUERY, {\n variables: { publisherId: publisherId ?? \"\" },\n skip: !publisherId,\n fetchPolicy: \"cache-first\",\n });\n const linkedStoreProductId =\n productsData?.products?.find(\n (p: { id: string; productId?: string | null }) => p.productId === appId,\n )?.id ?? null;\n\n const isApiIntegration = data?.application?.appType === \"API_INTEGRATION\";\n const appManifest = data?.application?.manifest as\n Record<string, unknown> | null | undefined;\n const appOauth = appManifest?.[\"oauth\"] as\n Record<string, unknown> | undefined;\n const hasOAuthUrl = !!(\n appOauth?.[\"authorizationUrl\"] &&\n appOauth?.[\"tokenUrl\"] &&\n appOauth?.[\"clientId\"]\n );\n\n const { data: webhooksData } = useQuery<{ webhooks: { id: string }[] }>(\n APP_WEBHOOKS_QUERY,\n {\n variables: { applicationId: appId! },\n skip: !appId || !isApiIntegration,\n fetchPolicy: \"network-only\",\n },\n );\n const webhookCount = webhooksData?.webhooks?.length ?? 0;\n\n const app = data?.application;\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const isAlreadySubmitted = ALREADY_SUBMITTED_STATUSES.includes(\n app?.status ?? \"\",\n );\n\n const isPackageType = app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\";\n const publishedVersionCount = app?.versions?.totalCount ?? 0;\n\n const checklist = useMemo((): ChecklistItem[] => {\n if (!app) return [];\n\n const screenshotCount = app.screenshots?.length ?? 0;\n\n const storeListingPath = `/apps/${appId}?tab=store-listing`;\n const versionsPath = `/apps/${appId}/versions`;\n const editPath = `/apps/${appId}/edit#oauth-config`;\n const webhooksPath = `/apps/${appId}/webhooks`;\n\n const items: ChecklistItem[] = [\n {\n id: \"name\",\n label: tr(\"devportal.checklistNameLabel\", \"Name & Short Description\"),\n description: tr(\n \"devportal.checklistNameDesc\",\n \"Name and short description are required for the store card\",\n ),\n status: app.name && app.shortDescription ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"category\",\n label: tr(\"devportal.checklistCategoryLabel\", \"Category\"),\n description: tr(\n \"devportal.checklistCategoryDesc\",\n \"A category helps users find your item in the marketplace\",\n ),\n status: app.category ? \"passed\" : \"failed\",\n icon: <Globe size={20} />,\n actionLabel: \"Edit app info →\",\n actionPath: `/apps/${appId}/edit`,\n },\n {\n id: \"privacy\",\n label: tr(\"devportal.checklistPrivacyLabel\", \"Privacy Policy\"),\n description: tr(\n \"devportal.checklistPrivacyDesc\",\n \"Privacy policy URL is required for store submission\",\n ),\n status: app.privacyPolicyUrl ? \"passed\" : \"failed\",\n icon: <Shield size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"terms\",\n label: tr(\"devportal.checklistTermsLabel\", \"Terms of Service\"),\n description: tr(\n \"devportal.checklistTermsDesc\",\n \"Terms of service URL is required for store submission\",\n ),\n status: app.termsOfServiceUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"icon\",\n label: tr(\"devportal.checklistIconLabel\", \"App Icon\"),\n description: tr(\n \"devportal.checklistIconDesc\",\n \"An icon makes your listing stand out in the marketplace\",\n ),\n status: app.iconUrl ? \"passed\" : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"screenshots\",\n label: tr(\"devportal.checklistScreenshotsLabel\", \"Screenshots\"),\n description: tr(\n \"devportal.checklistScreenshotsDesc\",\n \"At least 3 screenshots are recommended\",\n ),\n status:\n screenshotCount >= 3\n ? \"passed\"\n : screenshotCount > 0\n ? \"warning\"\n : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n ];\n\n if (isPackageType) {\n items.push({\n id: \"version\",\n label: tr(\"devportal.checklistVersionLabel\", \"Published Version\"),\n description: tr(\n \"devportal.checklistVersionDesc\",\n app?.appType === \"WORKFLOW\"\n ? \"At least one published version (manifest JSON) is required before submitting to the store\"\n : \"At least one published version (ZIP + manifest) is required before submitting to the store\",\n ),\n status: publishedVersionCount > 0 ? \"passed\" : \"failed\",\n icon: <CheckCircle size={20} />,\n actionLabel: \"Create a version →\",\n actionPath: versionsPath,\n });\n }\n\n if (app.appType === \"API_INTEGRATION\") {\n items.push({\n id: \"oauth\",\n label: tr(\"devportal.checklistOAuthLabel\", \"OAuth Configuration\"),\n description: tr(\n \"devportal.checklistOAuthDesc\",\n \"Authorization URL, Token URL and Client ID are required so users can connect their accounts. Without these the Connect button does not work.\",\n ),\n status: hasOAuthUrl ? \"passed\" : \"failed\",\n icon: <KeyRound size={20} />,\n actionLabel: \"Configure in Edit App →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"webhook\",\n label: tr(\"devportal.checklistWebhookLabel\", \"Webhook Endpoint\"),\n description: tr(\n \"devportal.checklistWebhookDesc\",\n \"At least one webhook endpoint must be configured so your server receives platform events after users connect. Without this the integration does nothing.\",\n ),\n status: webhookCount > 0 ? \"passed\" : \"failed\",\n icon: <Webhook size={20} />,\n actionLabel: \"Add a webhook →\",\n actionPath: webhooksPath,\n });\n\n items.push({\n id: \"documentation\",\n label: tr(\"devportal.checklistDocsLabel\", \"Documentation URL\"),\n description: tr(\n \"devportal.checklistDocsDesc\",\n \"Users need to know how to use and configure this integration. A documentation link is required for API integrations.\",\n ),\n status: app.documentationUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Add documentation URL →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"website\",\n label: tr(\"devportal.checklistWebsiteLabel\", \"Website URL\"),\n description: tr(\n \"devportal.checklistWebsiteDesc\",\n \"Users need to verify who built this integration. A website URL is required so users know where to get support.\",\n ),\n status: app.websiteUrl ? \"passed\" : \"failed\",\n icon: <Link size={20} />,\n actionLabel: \"Add website URL →\",\n actionPath: editPath,\n });\n }\n\n items.push({\n id: \"status\",\n label: tr(\"devportal.checklistStatusLabel\", \"App Status\"),\n description: tr(\n \"devportal.checklistStatusDesc\",\n \"App must be in DRAFT or REJECTED state to submit\",\n ),\n status: [\"DRAFT\", \"REJECTED\"].includes(app.status ?? \"\")\n ? \"passed\"\n : \"warning\",\n icon: <CheckCircle size={20} />,\n });\n\n return items;\n }, [\n app,\n isPackageType,\n publishedVersionCount,\n webhookCount,\n hasOAuthUrl,\n appId,\n ]);\n\n const passedCount = checklist.filter((i) => i.status === \"passed\").length;\n const failedCount = checklist.filter((i) => i.status === \"failed\").length;\n const warningCount = checklist.filter((i) => i.status === \"warning\").length;\n const isSubmittableStatus = [\"DRAFT\", \"REJECTED\"].includes(app?.status ?? \"\");\n const canSubmit =\n !loading &&\n !queryError &&\n failedCount === 0 &&\n !!app &&\n !isAlreadySubmitted &&\n isSubmittableStatus;\n\n const getStatusIcon = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return <CheckCircle size={20} className=\"text-status-success-text\" />;\n case \"failed\":\n return <XCircle size={20} className=\"text-status-error-text\" />;\n case \"warning\":\n return <AlertTriangle size={20} className=\"text-status-warning-text\" />;\n default:\n return (\n <div className=\"h-5 w-5 rounded-full border-2 border-border-default\" />\n );\n }\n };\n\n const getStatusBg = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return \"bg-status-success-bg-subtle border-border-subtle\";\n case \"failed\":\n return \"bg-status-error-bg-subtle border-border-subtle\";\n case \"warning\":\n return \"bg-status-warning-bg-subtle border-border-subtle\";\n default:\n return \"bg-bg-canvas border-border-subtle\";\n }\n };\n\n const handleSubmit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n // Submit Application for devportal review (sets Application.status = SUBMITTED)\n const result = await submitApplication({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n if (result.error) throw result.error;\n\n // Also submit ApplicationForReview to set StoreProduct.status = PENDING_REVIEW\n // so it appears in the store admin review queue at /store/dashboard/submissions\n await submitApplicationForReview({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n\n setSubmitted(true);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.submitFailedDefault\", \"Failed to submit for review\"),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.loadingApplicationDetails\",\n \"Loading application details...\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"animate-spin h-8 w-8 text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n if (queryError || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.couldNotLoadApplication\",\n \"Could not load application\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <Alert\n variant=\"error\"\n title={tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n >\n {queryError?.message ??\n tr(\"devportal.applicationNotFound\", \"Application not found\")}\n </Alert>\n </PageLayout>\n );\n }\n\n if (submitted) {\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex flex-col items-center justify-center py-16 gap-6 text-center\">\n <div className=\"rounded-full bg-status-success-bg p-4\">\n <PartyPopper size={40} className=\"text-status-success-text\" />\n </div>\n <div className=\"space-y-2\">\n <h2 className=\"text-2xl font-bold\">\n {tr(\"devportal.submittedSuccessTitle\", \"Submitted for Review!\")}\n </h2>\n <p className=\"text-muted-foreground max-w-md\">\n {tr(\n \"devportal.submittedSuccessMsg\",\n \"Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.\",\n )}\n </p>\n </div>\n <div className=\"rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full\">\n <p className=\"font-medium\">What happens next:</p>\n <ul className=\"space-y-1 text-muted-foreground list-none\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Our team reviews your submission\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n You'll get an email on approval or if changes are needed\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle\n size={14}\n className=\"mt-0.5 text-status-success-text shrink-0\"\n />{\" \"}\n Once approved, your app goes live in the marketplace\n </li>\n </ul>\n </div>\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Back to App\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n }\n\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={`${tr(\"devportal.submitAppForReview\", \"Submit\")} \"${app.name}\" ${tr(\"devportal.forReviewAndPublication\", \"for review and publication\")}`}\n purpose={tr(\n \"devportal.publishPurpose\",\n \"Submitting sends your app to the review team, who check it against the marketplace guidelines before it goes live to users. Make sure the listing, screenshots, and permissions are final — preview the listing first, since changes after approval need another review.\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/listing`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n <Eye size={16} />\n {tr(\"devportal.previewListing\", \"Preview Listing\")}\n </button>\n }\n >\n {isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.alreadySubmittedTitle\", \"Already Submitted\")}\n >\n {tr(\"devportal.alreadySubmittedMsg1\", \"This app is currently in\")}{\" \"}\n <strong>{app.status}</strong>{\" \"}\n {tr(\n \"devportal.alreadySubmittedMsg2\",\n \"state and cannot be re-submitted until the review process is complete or the app is rejected.\",\n )}\n </Alert>\n )}\n\n {/* Progress Summary */}\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-6\">\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.preSubmissionChecklist\", \"Pre-submission Checklist\")}\n </h2>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {tr(\n \"devportal.completeAllRequiredItems\",\n \"Complete all required items before submitting for review\",\n )}\n </p>\n <div className=\"mt-4 flex gap-6\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle size={20} className=\"text-status-success-text\" />\n <span>\n {passedCount} {tr(\"devportal.passed\", \"Passed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <XCircle size={20} className=\"text-status-error-text\" />\n <span>\n {failedCount} {tr(\"devportal.failed\", \"Failed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AlertTriangle size={20} className=\"text-status-warning-text\" />\n <span>\n {warningCount} {tr(\"devportal.warnings\", \"Warnings\")}\n </span>\n </div>\n </div>\n </div>\n\n {/* Checklist Items */}\n <PageSection>\n <div className=\"space-y-3\">\n {checklist.map((item) => (\n <div\n key={item.id}\n className={`flex items-center gap-4 rounded-lg border p-4 ${getStatusBg(item.status)}`}\n >\n <div className=\"rounded-lg bg-bg-surface p-2\">{item.icon}</div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{item.label}</p>\n <p className=\"text-sm text-text-secondary\">\n {item.description}\n </p>\n {item.status !== \"passed\" && item.actionPath && (\n <button\n type=\"button\"\n onClick={() =>\n navigate?.(`${basePath}${item.actionPath}`)\n }\n className=\"mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n {item.actionLabel ?? \"Fix this\"} <ArrowRight size={11} />\n </button>\n )}\n </div>\n {getStatusIcon(item.status)}\n </div>\n ))}\n </div>\n </PageSection>\n\n {/* Submission Notes */}\n {!isAlreadySubmitted && (\n <PageSection\n title={tr(\"devportal.notesForReviewerTitle\", \"Notes for Reviewer\")}\n description={tr(\n \"devportal.notesForReviewerDesc\",\n \"Optional message to the review team\",\n )}\n >\n <textarea\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder={tr(\n \"devportal.notesForReviewerPlaceholder\",\n \"Describe what your app does, any special review considerations, or testing instructions...\",\n )}\n rows={4}\n maxLength={1000}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm ring-offset-background placeholder:text-text-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] resize-none\"\n />\n <p className=\"mt-1 text-xs text-text-secondary text-right\">\n {notes.length}/1000\n </p>\n </PageSection>\n )}\n\n {/* Alerts */}\n {submitError && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.submissionFailedTitle\", \"Submission Failed\")}\n >\n {submitError}\n </Alert>\n )}\n\n {failedCount > 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.cannotSubmitTitle\", \"Cannot Submit Yet\")}\n >\n {tr(\"devportal.pleaseFixItems1\", \"Please fix\")} {failedCount}{\" \"}\n {tr(\n \"devportal.pleaseFixItems2\",\n \"required item(s) before submitting for review.\",\n )}\n <div className=\"mt-2 flex flex-wrap gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToMarketplaceListing\",\n \"Update marketplace listing →\",\n )}\n </button>\n {isPackageType && publishedVersionCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/versions`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\"devportal.goToVersions\", \"Add a published version →\")}\n </button>\n )}\n {isApiIntegration && !hasOAuthUrl && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/edit#oauth-config`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Configure OAuth endpoints →\n </button>\n )}\n {isApiIntegration && webhookCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/webhooks`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n Add a webhook →\n </button>\n )}\n </div>\n </Alert>\n )}\n\n {warningCount > 0 && failedCount === 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.warningsTitle\", \"Warnings\")}\n >\n {tr(\"devportal.warningsMsg1\", \"You have\")} {warningCount}{\" \"}\n {tr(\n \"devportal.warningsMsg2\",\n \"warning(s). While you can submit, addressing these may improve your app's chances of approval.\",\n )}\n </Alert>\n )}\n\n {/* Review Process Info */}\n <PageSection\n title={tr(\"devportal.reviewProcessTitle\", \"Review Process\")}\n >\n <div className=\"rounded-lg border bg-bg-sunken/50 p-4\">\n <ul className=\"space-y-2 text-sm\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo1\",\n \"Review typically takes 3-5 business days\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo2\",\n \"You'll receive notifications about review status changes\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo3\",\n \"If changes are requested, you can resubmit without losing your place in the queue\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo4\",\n \"Once approved and published, your app will be visible in the marketplace\",\n )}\n </span>\n </li>\n </ul>\n </div>\n </PageSection>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-bg-sunken\"\n >\n {tr(\"devportal.cancelButton\", \"Cancel\")}\n </button>\n <button\n onClick={handleSubmit}\n disabled={!canSubmit || submitting || !submitPerm.allowed}\n aria-disabled={!canSubmit || submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submittingButton\", \"Submitting...\")}\n </>\n ) : (\n <>\n <Send size={16} />\n {tr(\"devportal.submitForReviewButton\", \"Submit for Review\")}\n </>\n )}\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SellerDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/SellerDashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AA8I3C,eAAO,MAAM,mBAAmB,EAAE,EAwSjC,CAAC"}
1
+ {"version":3,"file":"SellerDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/devportal/pages/SellerDashboardPage.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAa,MAAM,OAAO,CAAC;AA0I3C,eAAO,MAAM,mBAAmB,EAAE,EAwSjC,CAAC"}