@burdenoff/microfe-devportal 2026.1109.1 → 2026.1109.2
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.
- package/dist/devportal/pages/ApplicationVersionsPage.js +229 -217
- package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
- package/dist/devportal/pages/NodeLifecyclePage.js +2 -0
- package/dist/devportal/pages/NodeLifecyclePage.js.map +1 -1
- package/dist/generated/global-operations.d.ts +21 -0
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +24 -2
- package/dist/generated/global-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApplicationVersionsPage.js","names":["_Fragment","format","extractVersionFromManifest","manifestJson","parsed","identity","isOrganizationPublished","metadata","record","ApplicationVersionsPage","useI18n","tr","value","t","key","fallback","canCreate","useDevportalPermission","DEVPORTAL_PERMISSIONS","canPublish","canDeprecate","useParams","useDevportal","uploadZip","zipUploading","zipProgress","zipUploadError","usePackageUpload","workspacesGatewayUrl","authToken","workspaceId","getWorkspaceToken","zipInputRef","useRef","manifestInputRef","editZipInputRef","editManifestInputRef","manifestFileName","setManifestFileName","useState","editManifestFileName","setEditManifestFileName","showCreateDialog","setShowCreateDialog","editDialog","setEditDialog","newVersion","setNewVersion","actionError","setActionError","actionSuccess","setActionSuccess","createDialogError","setCreateDialogError","editDialogError","setEditDialogError","selectedVersionIds","setSelectedVersionIds","rejectDialog","setRejectDialog","rejectReason","setRejectReason","handleManifestFileUpload","useCallback","file","reader","text","evt","extractedVersion","prev","bulkAction","setBulkAction","orgPublishTarget","setOrgPublishTarget","appData","useGetApplicationQuery","appId","isWorkflowApp","isNodeApp","isManifestOnlyType","isIntegrationApp","isPrivateNodeApp","app","pricingDetailsRaw","pricingDone","storeDone","appReadyForSubmission","appReadinessBlockers","name","reg","versionsData","versionsLoading","versionsError","useGetApplicationVersionsQuery","createVersion","creating","useCreateApplicationVersionMutation","updateVersion","updating","useUpdateApplicationVersionMutation","publishVersion","usePublishApplicationVersionMutation","publishToOrganization","publishingToOrganization","usePublishApplicationVersionToOrganizationMutation","deprecateVersion","useDeprecateApplicationVersionMutation","approveVersion","useApproveApplicationVersionMutation","rejectVersion","useRejectApplicationVersionMutation","versions","useMemo","edge","selectedVersions","version","publishableVersions","hasPendingVersion","deprecatableVersions","allVisibleSelected","partiallySelected","openLifecycle","basePath","versionId","handleCreate","parsedManifest","requiredScopes","s","created","createdId","err","handleZipUpload","result","handleEditZipUpload","handleEditManifestUpload","handleEditSave","manifestChanged","input","handlePublish","handlePublishToOrganization","target","handleDeprecate","handleRejectConfirm","getStatusIcon","CheckCircle","Send","XCircle","Clock","Archive","Package","toggleVersionSelection","next","checked","toggleAllVisibleVersions","clearSelection","handleBulkPublish","results","succeeded","failed","handleBulkDeprecate","manifestDerivedVersion","PageLayout","Loader2","EmptyState","AlertCircle","PermissionGuard","Plus","b","v","SelectionCheckbox","DataTable","event","StatusBadge","PackageValidationPanel","Building2","ManifestViewer","Rocket","existingManifest","readPackageValidationState","ConfirmDialog","open","InputField","Fragment","Upload","MarkdownEditor"],"sources":["../../../src/devportal/pages/ApplicationVersionsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Plus,\n Package,\n CheckCircle,\n XCircle,\n Clock,\n Archive,\n Loader2,\n AlertCircle,\n Upload,\n Send,\n Building2,\n Rocket,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { InputField, TextareaField } from \"../components/FormField\";\nimport { MarkdownEditor } from \"../components/MarkdownEditor\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { SelectionCheckbox } from \"../components/SelectionCheckbox\";\nimport { ManifestViewer } from \"../components/ManifestViewer\";\nimport {\n PackageValidationPanel,\n readPackageValidationState,\n} from \"../components/PackageValidationPanel\";\nimport { format } from \"date-fns\";\nimport {\n useGetApplicationQuery,\n useGetApplicationVersionsQuery,\n useCreateApplicationVersionMutation,\n useUpdateApplicationVersionMutation,\n usePublishApplicationVersionMutation,\n usePublishApplicationVersionToOrganizationMutation,\n useDeprecateApplicationVersionMutation,\n useApproveApplicationVersionMutation,\n useRejectApplicationVersionMutation,\n type ApplicationVersionFieldsFragment,\n} from \"../hooks\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\n\n/**\n * Pulls the version string out of an uploaded manifest so the developer\n * doesn't have to retype what's already declared in the file. Checks the\n * FluidGrids node manifest shape (`nodeVersion`, e.g.\n * fluidgrids-nodes/nodes/*\\/manifest.json) first, then the generic\n * `identity.version` / top-level `version` shapes used by other manifest types.\n */\nconst extractVersionFromManifest = (\n manifestJson: string,\n): string | undefined => {\n if (!manifestJson.trim()) return undefined;\n try {\n const parsed = JSON.parse(manifestJson) as Record<string, unknown>;\n if (typeof parsed.nodeVersion === \"string\" && parsed.nodeVersion.trim()) {\n return parsed.nodeVersion.trim();\n }\n const identity = parsed.identity as Record<string, unknown> | undefined;\n if (\n identity &&\n typeof identity.version === \"string\" &&\n identity.version.trim()\n ) {\n return identity.version.trim();\n }\n if (typeof parsed.version === \"string\" && parsed.version.trim()) {\n return parsed.version.trim();\n }\n } catch {\n // Manifest isn't valid JSON yet (still being typed/pasted) — ignore.\n }\n return undefined;\n};\n\n/** BOFF-9657: whether a version was published to its organization (not through review). */\nfunction isOrganizationPublished(metadata: unknown): boolean {\n if (typeof metadata !== \"object\" || metadata === null) return false;\n const record = (metadata as Record<string, unknown>).organizationPublish;\n return typeof record === \"object\" && record !== null;\n}\n\nexport const ApplicationVersionsPage: FC = () => {\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 { allowed: canCreate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_VERSION_CREATE,\n );\n const { allowed: canPublish } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_VERSION_PUBLISH,\n );\n const { allowed: canDeprecate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_VERSION_DEPRECATE,\n );\n const { appId } = useParams<{ appId: string }>();\n const {\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n navigate,\n basePath,\n } = useDevportal();\n const {\n upload: uploadZip,\n uploading: zipUploading,\n progress: zipProgress,\n error: zipUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n );\n const zipInputRef = useRef<HTMLInputElement>(null);\n const manifestInputRef = useRef<HTMLInputElement>(null);\n const editZipInputRef = useRef<HTMLInputElement>(null);\n const editManifestInputRef = useRef<HTMLInputElement>(null);\n const [manifestFileName, setManifestFileName] = useState<string | null>(null);\n const [editManifestFileName, setEditManifestFileName] = useState<\n string | null\n >(null);\n const [showCreateDialog, setShowCreateDialog] = useState(false);\n const [editDialog, setEditDialog] = useState<{\n versionId: string;\n version: string;\n hasExistingZip: boolean;\n newPackageUrl: string;\n newPackageSize: string;\n manifestJson: string;\n originalManifestJson: string;\n releaseNotes: string;\n changelog: string;\n } | null>(null);\n const [newVersion, setNewVersion] = useState({\n version: \"\",\n releaseNotes: \"\",\n changelog: \"\",\n packageUrl: \"\",\n packageSize: \"\",\n manifestJson: \"\",\n requiredScopes: \"\",\n });\n const [actionError, setActionError] = useState<string | null>(null);\n const [actionSuccess, setActionSuccess] = useState<string | null>(null);\n const [createDialogError, setCreateDialogError] = useState<string | null>(\n null,\n );\n const [editDialogError, setEditDialogError] = useState<string | null>(null);\n const [selectedVersionIds, setSelectedVersionIds] = useState<Set<string>>(\n new Set(),\n );\n const [rejectDialog, setRejectDialog] = useState<{\n versionId: string;\n version: string;\n } | null>(null);\n const [rejectReason, setRejectReason] = useState(\"\");\n\n const handleManifestFileUpload = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (evt) => {\n const text = evt.target?.result;\n if (typeof text === \"string\") {\n const extractedVersion = extractVersionFromManifest(text);\n setNewVersion((prev) => ({\n ...prev,\n manifestJson: text,\n ...(extractedVersion ? { version: extractedVersion } : {}),\n }));\n setManifestFileName(file.name);\n }\n };\n reader.readAsText(file);\n // reset so re-uploading same file triggers onChange\n e.target.value = \"\";\n },\n [],\n );\n const [bulkAction, setBulkAction] = useState<\"publish\" | \"deprecate\" | null>(\n null,\n );\n // BOFF-9657: the version a developer is about to publish to their organization.\n const [orgPublishTarget, setOrgPublishTarget] =\n useState<ApplicationVersionFieldsFragment | null>(null);\n\n const { data: appData } = useGetApplicationQuery({\n variables: { id: appId ?? \"\" },\n skip: !appId,\n fetchPolicy: \"cache-first\",\n });\n const isWorkflowApp = appData?.application?.appType === \"WORKFLOW\";\n const isNodeApp = appData?.application?.appType === \"NODE\";\n // Manifest-only types (no zip): Workflow plus its sibling types Parser/Widget/Dashboard.\n const isManifestOnlyType = [\n \"WORKFLOW\",\n \"PARSER\",\n \"WIDGET\",\n \"DASHBOARD\",\n ].includes(appData?.application?.appType ?? \"\");\n const isIntegrationApp = !isManifestOnlyType && !isNodeApp;\n // BOFF-9657: a PRIVATE node can be published to the developer's own\n // organization without platform review, once its package has validated.\n const isPrivateNodeApp =\n isNodeApp && appData?.application?.visibility === \"PRIVATE\";\n\n // App-level readiness checks — version submission is blocked until the app is ready\n const app = appData?.application;\n const pricingDetailsRaw = (app?.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDone =\n app?.pricingType === \"FREE\" ||\n (app?.pricingType === \"PAID\" &&\n typeof pricingDetailsRaw.price === \"number\" &&\n (pricingDetailsRaw.price as number) > 0);\n const storeDone =\n !!app?.shortDescription?.trim() &&\n !!app?.privacyPolicyUrl?.trim() &&\n !!app?.termsOfServiceUrl?.trim();\n const appReadyForSubmission = pricingDone && storeDone;\n const appReadinessBlockers: string[] = [\n ...(!storeDone\n ? [\n \"Complete your store listing (short description, privacy policy, terms of service)\",\n ]\n : []),\n ...(!pricingDone ? [\"Set pricing in the Pricing tab\"] : []),\n ];\n\n useEffect(() => {\n const name = appData?.application?.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, appData?.application?.name]);\n\n // Query\n const {\n data: versionsData,\n loading: versionsLoading,\n error: versionsError,\n } = useGetApplicationVersionsQuery({\n variables: { applicationId: appId! },\n skip: !appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n // Mutations\n const [createVersion, { loading: creating }] =\n useCreateApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [updateVersion, { loading: updating }] =\n useUpdateApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [publishVersion] = usePublishApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [publishToOrganization, { loading: publishingToOrganization }] =\n usePublishApplicationVersionToOrganizationMutation({\n refetchQueries: [\"GetApplicationVersions\", \"GetApplication\"],\n });\n\n const [deprecateVersion] = useDeprecateApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [approveVersion] = useApproveApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [rejectVersion] = useRejectApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const versions: ApplicationVersionFieldsFragment[] = useMemo(\n () =>\n versionsData?.application?.versions?.edges?.map(\n (edge: { node: ApplicationVersionFieldsFragment }) => edge.node,\n ) ?? [],\n [versionsData?.application?.versions],\n );\n\n const selectedVersions = useMemo(\n () => versions.filter((version) => selectedVersionIds.has(version.id)),\n [versions, selectedVersionIds],\n );\n const publishableVersions = useMemo(\n () =>\n selectedVersions.filter(\n (version) =>\n version.status === \"draft\" || version.status === \"rejected\",\n ),\n [selectedVersions],\n );\n // Only one version should be in the admin review queue at a time — otherwise\n // an admin can't tell which pending version a developer actually wants\n // reviewed. This is a UI-only guard (no backend change): once a version is\n // pending_review, block submitting another until it's approved or rejected.\n const hasPendingVersion = useMemo(\n () => versions.some((version) => version.status === \"pending_review\"),\n [versions],\n );\n const deprecatableVersions = useMemo(\n () =>\n selectedVersions.filter(\n (version) =>\n version.status?.toUpperCase() === \"PUBLISHED\" && !version.isLatest,\n ),\n [selectedVersions],\n );\n const allVisibleSelected =\n versions.length > 0 &&\n versions.every((version) => selectedVersionIds.has(version.id));\n const partiallySelected =\n versions.some((version) => selectedVersionIds.has(version.id)) &&\n !allVisibleSelected;\n\n const openLifecycle = (versionId: string) => {\n navigate?.(`${basePath}/apps/${appId}/versions/${versionId}/lifecycle`);\n };\n\n const handleCreate = async () => {\n if (!appId || !newVersion.version.trim()) return;\n setCreateDialogError(null);\n\n let parsedManifest: Record<string, unknown> | undefined;\n if (isManifestOnlyType) {\n if (!newVersion.manifestJson.trim()) {\n setCreateDialogError(\n isWorkflowApp\n ? \"Workflow Definition (JSON) is required — paste the {nodes, edges} object.\"\n : \"Manifest (JSON) is required.\",\n );\n return;\n }\n try {\n parsedManifest = JSON.parse(newVersion.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setCreateDialogError(\n isWorkflowApp\n ? \"Invalid JSON in Workflow Definition — please check your input.\"\n : \"Invalid JSON in Manifest — please check your input.\",\n );\n return;\n }\n } else if (isNodeApp) {\n if (!newVersion.packageUrl) {\n setCreateDialogError(\n \"Package zip is required for Node versions — upload a .zip file before creating.\",\n );\n return;\n }\n if (!newVersion.manifestJson.trim()) {\n setCreateDialogError(\n \"manifest.json is required for Node versions — upload or paste your manifest before creating.\",\n );\n return;\n }\n try {\n parsedManifest = JSON.parse(newVersion.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setCreateDialogError(\n \"Invalid JSON in manifest — please check your input.\",\n );\n return;\n }\n } else if (newVersion.manifestJson.trim()) {\n try {\n parsedManifest = JSON.parse(newVersion.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setCreateDialogError(\n \"Invalid JSON in manifest — please check your input.\",\n );\n return;\n }\n }\n\n const requiredScopes =\n isIntegrationApp && newVersion.requiredScopes.trim()\n ? newVersion.requiredScopes\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\n\n try {\n const created = await createVersion({\n variables: {\n applicationId: appId,\n input: {\n version: newVersion.version,\n releaseNotes: newVersion.releaseNotes || undefined,\n changelog: newVersion.changelog || undefined,\n packageUrl: newVersion.packageUrl || undefined,\n packageSize: newVersion.packageSize || undefined,\n manifest: parsedManifest,\n requiredScopes,\n },\n },\n });\n setShowCreateDialog(false);\n setManifestFileName(null);\n setNewVersion({\n version: \"\",\n releaseNotes: \"\",\n changelog: \"\",\n packageUrl: \"\",\n packageSize: \"\",\n manifestJson: \"\",\n requiredScopes: \"\",\n });\n setActionSuccess(\n tr(\"devportal.versionCreatedSuccess\", \"Version created successfully\"),\n );\n // BOFF-4076: a new custom-node version continues on its lifecycle page,\n // where validation, the sandbox build and the tests show up as they run.\n const createdId = created.data?.createApplicationVersion?.id;\n if (isNodeApp && createdId) openLifecycle(createdId);\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionCreateFailed\", \"Failed to create version\"),\n );\n }\n };\n\n const handleZipUpload = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n e.target.value = \"\";\n try {\n const result = await uploadZip(file);\n setNewVersion((prev) => ({\n ...prev,\n packageUrl: result.downloadUrl,\n packageSize: String(file.size),\n }));\n } catch {\n // error shown via zipUploadError prop\n }\n },\n [uploadZip],\n );\n\n const handleEditZipUpload = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n e.target.value = \"\";\n try {\n const result = await uploadZip(file);\n setEditDialog((prev) =>\n prev\n ? {\n ...prev,\n newPackageUrl: result.downloadUrl,\n newPackageSize: String(file.size),\n }\n : prev,\n );\n } catch {\n // error shown via zipUploadError prop\n }\n },\n [uploadZip],\n );\n\n const handleEditManifestUpload = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (evt) => {\n const text = evt.target?.result;\n if (typeof text === \"string\") {\n setEditDialog((prev) =>\n prev ? { ...prev, manifestJson: text } : prev,\n );\n setEditManifestFileName(file.name);\n }\n };\n reader.readAsText(file);\n e.target.value = \"\";\n },\n [],\n );\n\n const handleEditSave = async () => {\n if (!editDialog) return;\n setEditDialogError(null);\n\n const manifestChanged =\n editDialog.manifestJson.trim() !== editDialog.originalManifestJson.trim();\n\n let parsedManifest: Record<string, unknown> | undefined;\n if (manifestChanged && editDialog.manifestJson.trim()) {\n try {\n parsedManifest = JSON.parse(editDialog.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setEditDialogError(\n \"Invalid JSON in manifest — please check your input.\",\n );\n return;\n }\n }\n\n const input: {\n releaseNotes?: string;\n changelog?: string;\n packageUrl?: string;\n packageSize?: string;\n manifest?: Record<string, unknown>;\n } = {};\n\n if (editDialog.releaseNotes.trim())\n input.releaseNotes = editDialog.releaseNotes;\n if (editDialog.changelog.trim()) input.changelog = editDialog.changelog;\n if (editDialog.newPackageUrl) {\n input.packageUrl = editDialog.newPackageUrl;\n input.packageSize = editDialog.newPackageSize;\n }\n if (parsedManifest) input.manifest = parsedManifest;\n\n try {\n await updateVersion({\n variables: { id: editDialog.versionId, input },\n });\n setEditDialog(null);\n setEditManifestFileName(null);\n setActionSuccess(\n tr(\"devportal.versionUpdatedSuccess\", \"Version updated successfully\"),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionUpdateFailed\", \"Failed to update version\"),\n );\n }\n };\n\n const handlePublish = async (versionId: string) => {\n setActionError(null);\n setActionSuccess(null);\n try {\n const result = await publishVersion({ variables: { id: versionId } });\n if (result.error || !result.data?.publishApplicationVersion) {\n throw (\n result.error ??\n new Error(\n tr(\n \"devportal.versionPublishFailed\",\n \"Failed to submit version for review\",\n ),\n )\n );\n }\n setActionSuccess(\n tr(\n \"devportal.versionSubmittedSuccess\",\n \"Version submitted for review — you'll be notified when approved\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.versionPublishFailed\",\n \"Failed to submit version for review\",\n ),\n );\n }\n };\n\n const handlePublishToOrganization = async () => {\n const target = orgPublishTarget;\n setOrgPublishTarget(null);\n if (!target || !workspaceId) return;\n setActionError(null);\n setActionSuccess(null);\n try {\n // The host shell's Apollo client may resolve a refused mutation with\n // `error` set instead of throwing; never report success without data.\n const result = await publishToOrganization({\n variables: { id: target.id, workspaceId },\n });\n if (\n result.error ||\n !result.data?.publishApplicationVersionToOrganization\n ) {\n throw (\n result.error ??\n new Error(\n tr(\n \"devportal.versionPublishToOrganizationFailed\",\n \"Failed to publish the version to your organization\",\n ),\n )\n );\n }\n setActionSuccess(\n tr(\n \"devportal.versionPublishedToOrganizationSuccess\",\n \"Version published to your organization. Workspace admins in your organization can now install it.\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.versionPublishToOrganizationFailed\",\n \"Failed to publish the version to your organization\",\n ),\n );\n }\n };\n\n const handleDeprecate = async (versionId: string) => {\n setActionError(null);\n setActionSuccess(null);\n try {\n await deprecateVersion({ variables: { id: versionId } });\n setActionSuccess(\n tr(\n \"devportal.versionDeprecatedSuccess\",\n \"Version deprecated successfully\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.versionDeprecateFailed\",\n \"Failed to deprecate version\",\n ),\n );\n }\n };\n\n const handleApprove = async (versionId: string) => {\n setActionError(null);\n setActionSuccess(null);\n try {\n await approveVersion({ variables: { id: versionId } });\n setActionSuccess(\n tr(\n \"devportal.versionApprovedSuccess\",\n \"Version approved and published to store\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionApproveFailed\", \"Failed to approve version\"),\n );\n }\n };\n\n const handleRejectConfirm = async () => {\n if (!rejectDialog || !rejectReason.trim()) return;\n setActionError(null);\n setActionSuccess(null);\n try {\n await rejectVersion({\n variables: { id: rejectDialog.versionId, reason: rejectReason },\n });\n setActionSuccess(\n tr(\n \"devportal.versionRejectedSuccess\",\n \"Version rejected — developer has been notified\",\n ),\n );\n setRejectDialog(null);\n setRejectReason(\"\");\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionRejectFailed\", \"Failed to reject version\"),\n );\n }\n };\n\n const getStatusIcon = (version: ApplicationVersionFieldsFragment) => {\n if (version.status === \"published\" && version.isLatest) {\n return <CheckCircle size={16} className=\"text-status-success-text\" />;\n }\n if (version.status === \"pending_review\") {\n return <Send size={16} className=\"text-status-info-text\" />;\n }\n if (version.status === \"rejected\") {\n return <XCircle size={16} className=\"text-status-error-text\" />;\n }\n if (version.status === \"draft\") {\n return <Clock size={16} className=\"text-status-warning-text\" />;\n }\n if (version.status === \"deprecated\") {\n return <Archive size={16} className=\"text-text-secondary\" />;\n }\n return <Package size={16} className=\"text-accent-blue\" />;\n };\n\n const toggleVersionSelection = (versionId: string, checked: boolean) => {\n setSelectedVersionIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(versionId);\n } else {\n next.delete(versionId);\n }\n return next;\n });\n };\n\n const toggleAllVisibleVersions = (checked: boolean) => {\n setSelectedVersionIds((prev) => {\n const next = new Set(prev);\n versions.forEach((version) => {\n if (checked) {\n next.add(version.id);\n } else {\n next.delete(version.id);\n }\n });\n return next;\n });\n };\n\n const clearSelection = () => setSelectedVersionIds(new Set());\n\n const handleBulkPublish = async () => {\n if (publishableVersions.length === 0) return;\n setActionError(null);\n const results = await Promise.allSettled(\n publishableVersions.map((version) =>\n publishVersion({ variables: { id: version.id } }),\n ),\n );\n const succeeded = results.filter(\n (result: PromiseSettledResult<unknown>) => result.status === \"fulfilled\",\n ).length;\n const failed = results.length - succeeded;\n setActionSuccess(\n `Published ${succeeded} version${succeeded === 1 ? \"\" : \"s\"}${failed > 0 ? ` • ${failed} failed` : \"\"}`,\n );\n clearSelection();\n setBulkAction(null);\n };\n\n const handleBulkDeprecate = async () => {\n if (deprecatableVersions.length === 0) return;\n setActionError(null);\n const results = await Promise.allSettled(\n deprecatableVersions.map((version) =>\n deprecateVersion({ variables: { id: version.id } }),\n ),\n );\n const succeeded = results.filter(\n (result: PromiseSettledResult<unknown>) => result.status === \"fulfilled\",\n ).length;\n const failed = results.length - succeeded;\n setActionSuccess(\n `Deprecated ${succeeded} version${succeeded === 1 ? \"\" : \"s\"}${failed > 0 ? ` • ${failed} failed` : \"\"}`,\n );\n clearSelection();\n setBulkAction(null);\n };\n\n // The version number is meant to come from the manifest itself, not be\n // retyped by hand — surface whatever we could parse out of it so the field\n // can be locked once the manifest supplies one.\n const manifestDerivedVersion = extractVersionFromManifest(\n newVersion.manifestJson,\n );\n\n // Loading state\n if (versionsLoading && !versionsData) {\n return (\n <PageLayout\n title={tr(\"devportal.versionManagement\", \"Version Management\")}\n description={tr(\n \"devportal.versionManagementDescription\",\n \"Manage your application versions\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-16\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (versionsError && !versionsData) {\n return (\n <PageLayout\n title={tr(\"devportal.versionManagement\", \"Version Management\")}\n description={tr(\n \"devportal.versionManagementDescription\",\n \"Manage your application versions\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.failedToLoadVersions\",\n \"Failed to load versions\",\n )}\n description={\n versionsError.message ||\n tr(\n \"devportal.versionsLoadError\",\n \"An error occurred while loading versions\",\n )\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.versionManagement\", \"Version Management\")}\n description={tr(\n \"devportal.versionManagementDescription\",\n \"Manage your application versions\",\n )}\n purpose={\n isWorkflowApp\n ? tr(\n \"devportal.versionManagementPurposeWorkflow\",\n \"Versions track releases of your workflow. Create a version for each significant change and paste the workflow definition JSON. No zip is needed — the manifest is the workflow.\",\n )\n : isNodeApp\n ? tr(\n \"devportal.versionManagementPurposeNode\",\n \"Versions are the releases of your node that users install. Upload a new zip whenever the node implementation changes, and update the manifest if the node's inputs, outputs, or operations change. Bump the version for any change users will see.\",\n )\n : isManifestOnlyType\n ? tr(\n \"devportal.versionManagementPurposeManifestOnly\",\n \"Versions track releases of this item. Create a version for each significant change and paste the manifest JSON. No zip is needed.\",\n )\n : tr(\n \"devportal.versionManagementPurposeIntegration\",\n \"Versions track permission and webhook changes for your integration. No zip or manifest is needed — create a new version whenever you add or change required scopes so users can review and accept the updated permissions.\",\n )\n }\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => {\n setCreateDialogError(null);\n setShowCreateDialog(true);\n }}\n disabled={!canCreate}\n aria-disabled={!canCreate}\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.newVersion\", \"New Version\")}\n </button>\n }\n >\n {/* Action Error Banner */}\n {actionError && (\n <div className=\"rounded-lg border border-border-subtle bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text\">\n <AlertCircle size={16} className=\"flex-shrink-0\" />\n {actionError}\n <button\n onClick={() => setActionError(null)}\n className=\"ml-auto text-status-error-text hover:text-status-error-text\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n )}\n\n {actionSuccess && (\n <div className=\"rounded-lg border border-border-subtle bg-status-success-bg-subtle p-3 flex items-center gap-2 text-sm text-status-success-text\">\n <CheckCircle size={16} className=\"flex-shrink-0\" />\n {actionSuccess}\n <button\n onClick={() => setActionSuccess(null)}\n className=\"ml-auto text-status-success-text hover:text-status-success-text\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n )}\n\n {/* App setup incomplete — block version submission with a clear warning */}\n {app && !appReadyForSubmission && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text\">\n <AlertCircle size={16} className=\"mt-0.5 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n Complete your app setup before submitting for review\n </p>\n <ul className=\"mt-1 list-disc pl-4 text-xs opacity-80\">\n {appReadinessBlockers.map((b) => (\n <li key={b}>{b}</li>\n ))}\n </ul>\n </div>\n </div>\n )}\n\n {/* First-time submission explainer — shown when app is not yet published and there are draft versions */}\n {app &&\n app.status !== \"PUBLISHED\" &&\n versions.some((v) => v.status === \"draft\") && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-info-bg bg-status-info-bg-subtle px-4 py-3 text-sm text-status-info-text\">\n <Send size={16} className=\"mt-0.5 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n Ready to submit? Go to the Submit tab\n </p>\n <p className=\"mt-1 text-xs opacity-80\">\n For your first submission the app and its version are reviewed\n together. Head to the <strong>Submit</strong> tab — your draft\n version will be included automatically. The per-version\n "Submit for Review" button is only for new versions\n after the app is already live in the marketplace.\n </p>\n </div>\n </div>\n )}\n\n {/* A version is already awaiting admin review — block submitting another\n so admins never have more than one pending version per app to sort out. */}\n {app && hasPendingVersion && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text\">\n <Send size={16} className=\"mt-0.5 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n {tr(\n \"devportal.versionAlreadyPending\",\n \"A version is already pending review\",\n )}\n </p>\n <p className=\"mt-1 text-xs opacity-80\">\n {tr(\n \"devportal.versionAlreadyPendingDetail\",\n \"Submitting another version is disabled until it's approved or rejected.\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {versions.length > 0 && (\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllVisibleVersions}\n ariaLabel=\"Select all visible versions\"\n />\n <span className=\"text-sm font-medium\">\n {tr(\"devportal.selectAllVisible\", \"Select all visible\")}\n </span>\n </div>\n {selectedVersionIds.size > 0 && (\n <button\n onClick={clearSelection}\n className=\"text-sm text-text-secondary hover:text-text-primary\"\n >\n {tr(\"devportal.clearSelection\", \"Clear selection\")}\n </button>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary\">\n {selectedVersionIds.size} selected\n </span>\n <button\n onClick={() => setBulkAction(\"publish\")}\n disabled={\n publishableVersions.length === 0 ||\n !canPublish ||\n !appReadyForSubmission ||\n hasPendingVersion\n }\n aria-disabled={\n !canPublish || !appReadyForSubmission || hasPendingVersion\n }\n title={\n hasPendingVersion\n ? tr(\n \"devportal.versionAlreadyPending\",\n \"A version is already pending review\",\n )\n : !appReadyForSubmission\n ? appReadinessBlockers.join(\" · \")\n : undefined\n }\n className=\"rounded-md border border-status-success-bg px-3 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {tr(\"devportal.submitForReview\", \"Submit for Review\")}\n {publishableVersions.length > 0\n ? ` (${publishableVersions.length})`\n : \"\"}\n </button>\n <button\n onClick={() => setBulkAction(\"deprecate\")}\n disabled={deprecatableVersions.length === 0 || !canDeprecate}\n aria-disabled={!canDeprecate}\n className=\"rounded-md border border-status-warning-bg px-3 py-2 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg-subtle disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {tr(\"devportal.deprecateSelected\", \"Deprecate Selected\")}\n {deprecatableVersions.length > 0\n ? ` (${deprecatableVersions.length})`\n : \"\"}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {versions.length > 0 ? (\n <DataTable\n data={versions}\n keyField=\"id\"\n columns={[\n {\n key: \"select\",\n header: (\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllVisibleVersions}\n ariaLabel=\"Select all visible versions\"\n />\n ),\n className: \"w-12\",\n render: (v) => (\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedVersionIds.has(v.id)}\n onChange={(checked) =>\n toggleVersionSelection(v.id, checked)\n }\n ariaLabel={`Select version ${v.version}`}\n />\n </div>\n ),\n },\n {\n key: \"version\",\n header: tr(\"devportal.version\", \"Version\"),\n render: (v) => (\n <div className=\"flex items-center gap-2\">\n {getStatusIcon(v)}\n <span className=\"font-mono font-medium\">{v.version}</span>\n {v.isLatest && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text\">\n {tr(\"devportal.latest\", \"Latest\")}\n </span>\n )}\n {!v.isStable && (\n <span className=\"rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs text-status-warning-text\">\n {tr(\"devportal.beta\", \"Beta\")}\n </span>\n )}\n </div>\n ),\n },\n {\n key: \"releaseNotes\",\n header: tr(\"devportal.releaseNotes\", \"Release Notes\"),\n render: (v) => (\n <p className=\"max-w-md truncate text-sm text-text-secondary\">\n {v.releaseNotes ||\n tr(\"devportal.noReleaseNotes\", \"No release notes\")}\n </p>\n ),\n },\n {\n key: \"status\",\n header: tr(\"devportal.status\", \"Status\"),\n render: (v) => (\n <div className=\"space-y-1\">\n <StatusBadge\n status={\n v.status === \"pending_review\" ? \"In Review\" : v.status\n }\n />\n {v.status === \"pending_review\" && (\n <p className=\"text-xs text-status-info-text\">\n Awaiting platform review\n </p>\n )}\n {v.status === \"rejected\" && v.reviewNotes && (\n <p className=\"text-xs text-status-error-text max-w-xs\">\n {v.reviewNotes}\n </p>\n )}\n {isNodeApp && v.packageUrl && (\n <PackageValidationPanel metadata={v.metadata} />\n )}\n {isPrivateNodeApp &&\n isOrganizationPublished(v.metadata) && (\n <p className=\"inline-flex items-center gap-1 text-xs text-status-success-text\">\n <Building2 size={11} />\n {tr(\n \"devportal.publishedToOrganization\",\n \"Published to your organization\",\n )}\n </p>\n )}\n </div>\n ),\n },\n {\n key: \"publishedAt\",\n header: tr(\"devportal.published\", \"Published\"),\n render: (v) =>\n v.publishedAt\n ? format(new Date(v.publishedAt), \"MMM d, yyyy\")\n : \"-\",\n },\n {\n key: \"manifest\",\n header: tr(\"devportal.manifest\", \"Manifest\"),\n render: (v) =>\n v.manifest ? (\n <ManifestViewer\n manifest={v.manifest as Record<string, unknown>}\n tr={tr}\n />\n ) : (\n <span className=\"text-xs text-text-secondary\">\n {tr(\"devportal.noManifest\", \"No manifest\")}\n </span>\n ),\n },\n {\n key: \"actions\",\n header: \"\",\n className: \"w-48\",\n render: (v) => (\n <div className=\"flex flex-wrap gap-2\">\n {isNodeApp && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n data-testid={`version-lifecycle-${v.id}`}\n onClick={() => openLifecycle(v.id)}\n >\n <Rocket size={11} />\n {tr(\"devportal.nodeLifecycle.open\", \"Lifecycle\")}\n </button>\n )}\n {/* Edit draft/rejected versions before submission */}\n {(v.status === \"draft\" || v.status === \"rejected\") &&\n canCreate && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary hover:underline\"\n onClick={() => {\n const existingManifest = v.manifest\n ? JSON.stringify(v.manifest, null, 2)\n : \"\";\n setEditDialog({\n versionId: v.id,\n version: v.version,\n hasExistingZip: !!v.packageUrl,\n newPackageUrl: \"\",\n newPackageSize: \"\",\n manifestJson: existingManifest,\n originalManifestJson: existingManifest,\n releaseNotes: v.releaseNotes ?? \"\",\n changelog: v.changelog ?? \"\",\n });\n setEditManifestFileName(null);\n setEditDialogError(null);\n }}\n >\n Edit\n </button>\n )}\n {/* Only show \"Submit for Review\" on a version when the app is already\n published — for a first-time app the whole submission goes through\n the app-level \"Submit for Review\" (store listing + pricing + version). */}\n {(v.status === \"draft\" || v.status === \"rejected\") &&\n app?.status === \"PUBLISHED\" && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline disabled:opacity-50 disabled:cursor-not-allowed\"\n disabled={\n !canPublish ||\n !appReadyForSubmission ||\n hasPendingVersion\n }\n aria-disabled={\n !canPublish ||\n !appReadyForSubmission ||\n hasPendingVersion\n }\n title={\n hasPendingVersion\n ? tr(\n \"devportal.versionAlreadyPending\",\n \"A version is already pending review\",\n )\n : !appReadyForSubmission\n ? appReadinessBlockers.join(\" · \")\n : undefined\n }\n onClick={() => handlePublish(v.id)}\n >\n <Send size={11} />\n {tr(\"devportal.submitForReview\", \"Submit for Review\")}\n </button>\n )}\n {isPrivateNodeApp &&\n (v.status === \"draft\" || v.status === \"rejected\") && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline disabled:opacity-50 disabled:cursor-not-allowed\"\n disabled={\n !canPublish ||\n !workspaceId ||\n publishingToOrganization ||\n readPackageValidationState(v.metadata).kind !==\n \"passed\"\n }\n aria-disabled={\n !canPublish ||\n !workspaceId ||\n publishingToOrganization ||\n readPackageValidationState(v.metadata).kind !==\n \"passed\"\n }\n title={\n readPackageValidationState(v.metadata).kind !==\n \"passed\"\n ? tr(\n \"devportal.publishToOrganizationNeedsValidation\",\n \"Upload a package that passes validation first\",\n )\n : undefined\n }\n onClick={() => setOrgPublishTarget(v)}\n >\n <Building2 size={11} />\n {tr(\n \"devportal.publishToOrganization\",\n \"Publish to my organization\",\n )}\n </button>\n )}\n {v.status === \"published\" && !v.isLatest && (\n <button\n className=\"text-xs text-status-warning-text hover:underline disabled:opacity-50\"\n disabled={!canDeprecate}\n aria-disabled={!canDeprecate}\n onClick={() => handleDeprecate(v.id)}\n >\n {tr(\"devportal.deprecate\", \"Deprecate\")}\n </button>\n )}\n </div>\n ),\n },\n ]}\n />\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title={tr(\"devportal.noVersionsYet\", \"No versions yet\")}\n description={tr(\n \"devportal.noVersionsYetDescription\",\n \"Create your first version to start distributing your app\",\n )}\n action={\n <button\n onClick={() => {\n setCreateDialogError(null);\n setShowCreateDialog(true);\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.createVersion\", \"Create Version\")}\n </button>\n }\n />\n )}\n\n {/* Create Version Dialog */}\n {showCreateDialog && (\n <ConfirmDialog\n open={showCreateDialog}\n onOpenChange={(open) => {\n setShowCreateDialog(open);\n if (!open) setCreateDialogError(null);\n }}\n onConfirm={handleCreate}\n title={tr(\"devportal.createNewVersion\", \"Create New Version\")}\n confirmLabel={\n creating\n ? tr(\"devportal.creating\", \"Creating...\")\n : tr(\"devportal.createVersion\", \"Create Version\")\n }\n >\n <div className=\"space-y-4\">\n {createDialogError && (\n <div className=\"rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n {createDialogError}\n </div>\n )}\n <InputField\n label={tr(\"devportal.versionNumber\", \"Version Number\")}\n value={newVersion.version}\n onChange={(e) =>\n setNewVersion({ ...newVersion, version: e.target.value })\n }\n placeholder=\"e.g., 2.2.0\"\n hint={\n manifestDerivedVersion\n ? tr(\n \"devportal.versionHintAutoFilled\",\n \"Filled in from the manifest's version — edit it there if this is wrong.\",\n )\n : tr(\n \"devportal.versionHint\",\n \"Use semantic versioning (major.minor.patch). Upload a manifest.json/manifest with a version to fill this in automatically.\",\n )\n }\n readOnly={!!manifestDerivedVersion}\n required\n />\n {isManifestOnlyType && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {isWorkflowApp\n ? \"Workflow Definition (JSON)\"\n : \"Manifest (JSON)\"}{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <textarea\n rows={10}\n required\n placeholder={\n isWorkflowApp\n ? `{\\n \"nodes\": [],\\n \"edges\": []\\n}`\n : `{\\n \"manifestVersion\": \"1.0\",\\n \"identity\": { \"name\": \"My Item\", \"version\": \"1.0.0\" }\\n}`\n }\n value={newVersion.manifestJson}\n onChange={(e) => {\n const extractedVersion = extractVersionFromManifest(\n e.target.value,\n );\n setNewVersion({\n ...newVersion,\n manifestJson: e.target.value,\n ...(extractedVersion\n ? { version: extractedVersion }\n : {}),\n });\n }}\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <p className=\"text-xs text-text-secondary\">\n {isWorkflowApp ? (\n <>\n Paste the full <code>{`{nodes, edges}`}</code> JSON.\n Saved as this version's manifest — no zip needed.\n </>\n ) : (\n \"Paste the manifest JSON for this version. No zip needed.\"\n )}\n </p>\n </div>\n )}\n {/* Zip upload — node apps only */}\n {isNodeApp && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n Package (.zip){\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <div className=\"flex gap-2 items-center\">\n <input\n ref={zipInputRef}\n type=\"file\"\n accept=\".zip\"\n className=\"hidden\"\n onChange={handleZipUpload}\n />\n <button\n type=\"button\"\n disabled={zipUploading}\n onClick={() => zipInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {zipUploading ? (\n <>\n <Loader2 size={14} className=\"animate-spin\" />{\" \"}\n Uploading… {zipProgress}%\n </>\n ) : (\n <>\n <Upload size={14} />{\" \"}\n {newVersion.packageUrl ? \"Replace zip\" : \"Upload zip\"}\n </>\n )}\n </button>\n {newVersion.packageUrl && !zipUploading && (\n <span className=\"text-xs text-status-success-text\">\n ✓ Uploaded\n </span>\n )}\n </div>\n {zipUploadError && (\n <p className=\"text-xs text-status-error-text\">\n {zipUploadError}\n </p>\n )}\n <p className=\"text-xs text-text-tertiary\">\n The zip is the node executable. Upload it before publishing\n — users install exactly this artifact.\n </p>\n </div>\n )}\n\n {/* Manifest JSON — node apps only (required) */}\n {isNodeApp && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-2 flex-wrap\">\n <label className=\"text-sm font-medium\">\n manifest.json{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <div className=\"flex items-center gap-2\">\n {manifestFileName && (\n <span className=\"text-xs text-status-success-text\">\n ✓ {manifestFileName}\n </span>\n )}\n <input\n ref={manifestInputRef}\n type=\"file\"\n accept=\".json,application/json\"\n className=\"hidden\"\n onChange={handleManifestFileUpload}\n />\n <button\n type=\"button\"\n onClick={() => manifestInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors\"\n >\n <Upload size={12} />\n Upload manifest.json\n </button>\n </div>\n </div>\n <textarea\n rows={5}\n placeholder={`{\\n \"manifestVersion\": \"1.0\",\\n \"itemType\": \"node\",\\n \"identity\": { \"version\": \"1.0.0\", \"displayName\": \"My Node\" }\\n}`}\n value={newVersion.manifestJson}\n onChange={(e) => {\n setManifestFileName(null);\n const extractedVersion = extractVersionFromManifest(\n e.target.value,\n );\n setNewVersion({\n ...newVersion,\n manifestJson: e.target.value,\n ...(extractedVersion\n ? { version: extractedVersion }\n : {}),\n });\n }}\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <p className=\"text-xs text-text-tertiary\">\n Upload or paste your <code>manifest.json</code> — required\n so the platform knows your node's inputs, outputs, and\n operations. Not extracted from the zip automatically.\n </p>\n </div>\n )}\n\n {/* Required scopes — integration/app types only */}\n {isIntegrationApp && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n Required scopes{\" \"}\n <span className=\"text-xs font-normal text-text-secondary\">\n (optional)\n </span>\n </label>\n <input\n type=\"text\"\n value={newVersion.requiredScopes}\n onChange={(e) =>\n setNewVersion({\n ...newVersion,\n requiredScopes: e.target.value,\n })\n }\n placeholder=\"e.g. read:contacts, write:messages\"\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-sm placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <p className=\"text-xs text-text-tertiary\">\n Comma-separated. List every permission this version needs —\n users will be prompted to accept any new or changed scopes\n on update.\n </p>\n </div>\n )}\n <MarkdownEditor\n label={tr(\"devportal.releaseNotes\", \"Release Notes\")}\n value={newVersion.releaseNotes}\n onChange={(value) =>\n setNewVersion({ ...newVersion, releaseNotes: value })\n }\n placeholder={tr(\n \"devportal.releaseNotesPlaceholder\",\n \"What changed in this release?\",\n )}\n rows={3}\n />\n <MarkdownEditor\n label={tr(\"devportal.changelog\", \"Changelog\")}\n value={newVersion.changelog}\n onChange={(value) =>\n setNewVersion({ ...newVersion, changelog: value })\n }\n placeholder={tr(\n \"devportal.changelogPlaceholder\",\n \"Detailed changelog for this version...\",\n )}\n rows={3}\n />\n </div>\n </ConfirmDialog>\n )}\n\n {/* Reject version dialog */}\n {rejectDialog && (\n <ConfirmDialog\n open={!!rejectDialog}\n onOpenChange={(open) => {\n if (!open) {\n setRejectDialog(null);\n setRejectReason(\"\");\n }\n }}\n onConfirm={handleRejectConfirm}\n title={`Reject version ${rejectDialog.version}`}\n confirmLabel=\"Reject Version\"\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"danger\"\n >\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n The developer will be notified and can fix and resubmit. Please\n provide a clear reason.\n </p>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n Rejection reason{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <textarea\n rows={3}\n value={rejectReason}\n onChange={(e) => setRejectReason(e.target.value)}\n placeholder=\"e.g. Manifest contains disallowed network calls to external domains...\"\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-sm placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </div>\n </ConfirmDialog>\n )}\n\n {/* Edit Version Dialog */}\n {editDialog && (\n <ConfirmDialog\n open={!!editDialog}\n onOpenChange={(open) => {\n if (!open) {\n setEditDialog(null);\n setEditManifestFileName(null);\n setEditDialogError(null);\n }\n }}\n onConfirm={handleEditSave}\n title={`Edit Version ${editDialog.version}`}\n confirmLabel={updating ? \"Saving…\" : \"Save Changes\"}\n >\n <div className=\"space-y-4\">\n {editDialogError && (\n <div className=\"rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n {editDialogError}\n </div>\n )}\n <div className=\"rounded-lg border border-status-info-bg bg-status-info-bg-subtle px-3 py-2 text-xs text-status-info-text\">\n You can fix the zip, manifest, or release notes before\n submitting for review. Once submitted for review these fields\n are locked.\n </div>\n\n {/* ZIP replacement — node apps */}\n {isNodeApp && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">Package (.zip)</label>\n <div className=\"flex gap-2 items-center\">\n <input\n ref={editZipInputRef}\n type=\"file\"\n accept=\".zip\"\n className=\"hidden\"\n onChange={handleEditZipUpload}\n />\n <button\n type=\"button\"\n disabled={zipUploading}\n onClick={() => editZipInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {zipUploading ? (\n <>\n <Loader2 size={14} className=\"animate-spin\" />{\" \"}\n Uploading… {zipProgress}%\n </>\n ) : (\n <>\n <Upload size={14} />\n {editDialog.newPackageUrl\n ? \"Replace zip again\"\n : editDialog.hasExistingZip\n ? \"Replace zip\"\n : \"Upload zip\"}\n </>\n )}\n </button>\n {editDialog.newPackageUrl && !zipUploading && (\n <span className=\"text-xs text-status-success-text\">\n ✓ New zip ready\n </span>\n )}\n {!editDialog.newPackageUrl && editDialog.hasExistingZip && (\n <span className=\"text-xs text-text-secondary\">\n Current zip kept\n </span>\n )}\n </div>\n {zipUploadError && (\n <p className=\"text-xs text-status-error-text\">\n {zipUploadError}\n </p>\n )}\n </div>\n )}\n\n {/* Manifest replacement — node apps */}\n {isNodeApp && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-2 flex-wrap\">\n <label className=\"text-sm font-medium\">\n manifest.json{\" \"}\n <span className=\"text-xs font-normal text-text-secondary\">\n (edit below or upload a new file)\n </span>\n </label>\n <div className=\"flex items-center gap-2\">\n {editManifestFileName && (\n <span className=\"text-xs text-status-success-text\">\n ✓ {editManifestFileName}\n </span>\n )}\n <input\n ref={editManifestInputRef}\n type=\"file\"\n accept=\".json,application/json\"\n className=\"hidden\"\n onChange={handleEditManifestUpload}\n />\n <button\n type=\"button\"\n onClick={() => editManifestInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors\"\n >\n <Upload size={12} /> Upload manifest.json\n </button>\n </div>\n </div>\n <textarea\n rows={5}\n placeholder={`{\\n \"manifestVersion\": \"1.0\",\\n \"itemType\": \"node\",\\n \"identity\": { \"version\": \"1.0.0\", \"displayName\": \"My Node\" }\\n}`}\n value={editDialog.manifestJson}\n onChange={(e) => {\n setEditManifestFileName(null);\n setEditDialog((prev) =>\n prev ? { ...prev, manifestJson: e.target.value } : prev,\n );\n }}\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n )}\n\n {/* Workflow definition replacement */}\n {isManifestOnlyType && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {isWorkflowApp\n ? \"Workflow Definition (JSON)\"\n : \"Manifest (JSON)\"}{\" \"}\n <span className=\"text-xs font-normal text-text-secondary\">\n (leave empty to keep existing)\n </span>\n </label>\n <textarea\n rows={10}\n placeholder={\n isWorkflowApp\n ? `{\\n \"nodes\": [],\\n \"edges\": []\\n}`\n : `{\\n \"manifestVersion\": \"1.0\",\\n \"identity\": { \"name\": \"My Item\", \"version\": \"1.0.0\" }\\n}`\n }\n value={editDialog.manifestJson}\n onChange={(e) =>\n setEditDialog((prev) =>\n prev ? { ...prev, manifestJson: e.target.value } : prev,\n )\n }\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n )}\n\n <MarkdownEditor\n label={tr(\"devportal.releaseNotes\", \"Release Notes\")}\n value={editDialog.releaseNotes}\n onChange={(value) =>\n setEditDialog((prev) =>\n prev ? { ...prev, releaseNotes: value } : prev,\n )\n }\n placeholder={tr(\n \"devportal.releaseNotesPlaceholder\",\n \"What changed in this release?\",\n )}\n rows={3}\n />\n <MarkdownEditor\n label={tr(\"devportal.changelog\", \"Changelog\")}\n value={editDialog.changelog}\n onChange={(value) =>\n setEditDialog((prev) =>\n prev ? { ...prev, changelog: value } : prev,\n )\n }\n placeholder={tr(\n \"devportal.changelogPlaceholder\",\n \"Detailed changelog for this version...\",\n )}\n rows={3}\n />\n </div>\n </ConfirmDialog>\n )}\n\n <ConfirmDialog\n open={bulkAction === \"publish\"}\n onOpenChange={(open) => {\n if (!open) setBulkAction(null);\n }}\n onConfirm={handleBulkPublish}\n title={tr(\n \"devportal.submitSelectedVersions\",\n \"Submit selected versions for review\",\n )}\n description={`Submit ${publishableVersions.length} selected version${publishableVersions.length === 1 ? \"\" : \"s\"} for platform review?`}\n confirmLabel={tr(\"devportal.submitForReview\", \"Submit for Review\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"success\"\n />\n\n <ConfirmDialog\n open={orgPublishTarget !== null}\n onOpenChange={(open) => {\n if (!open) setOrgPublishTarget(null);\n }}\n onConfirm={handlePublishToOrganization}\n title={tr(\n \"devportal.publishToOrganizationTitle\",\n \"Publish to my organization\",\n )}\n description={`${tr(\n \"devportal.publishToOrganizationDescription\",\n \"Version {version} goes live for the workspaces of your organization without platform review. It is never listed in the public Node Store. Workspace admins in your organization can install it from this app.\",\n ).replace(\"{version}\", orgPublishTarget?.version ?? \"\")}`}\n confirmLabel={tr(\n \"devportal.publishToOrganization\",\n \"Publish to my organization\",\n )}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"success\"\n />\n\n <ConfirmDialog\n open={bulkAction === \"deprecate\"}\n onOpenChange={(open) => {\n if (!open) setBulkAction(null);\n }}\n onConfirm={handleBulkDeprecate}\n title={tr(\n \"devportal.deprecateSelectedVersions\",\n \"Deprecate selected versions\",\n )}\n description={`${tr(\"devportal.deprecate\", \"Deprecate\")} ${deprecatableVersions.length} selected version${deprecatableVersions.length === 1 ? \"\" : \"s\"}? ${tr(\"devportal.deprecateVersionsWarning\", \"Deprecated versions remain visible but should no longer be promoted.\")}`}\n confirmLabel={tr(\"devportal.deprecate\", \"Deprecate\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"warning\"\n />\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ApplicationVersionsPage.js","names":["_Fragment","format","extractVersionFromManifest","manifestJson","parsed","identity","isOrganizationPublished","metadata","record","ApplicationVersionsPage","useI18n","tr","value","t","key","fallback","canCreate","useDevportalPermission","DEVPORTAL_PERMISSIONS","canPublish","canDeprecate","useParams","useDevportal","uploadZip","zipUploading","zipProgress","zipUploadError","usePackageUpload","workspacesGatewayUrl","authToken","workspaceId","getWorkspaceToken","zipInputRef","useRef","manifestInputRef","editZipInputRef","editManifestInputRef","manifestFileName","setManifestFileName","useState","editManifestFileName","setEditManifestFileName","showCreateDialog","setShowCreateDialog","editDialog","setEditDialog","newVersion","setNewVersion","actionError","setActionError","actionSuccess","setActionSuccess","createDialogError","setCreateDialogError","editDialogError","setEditDialogError","selectedVersionIds","setSelectedVersionIds","rejectDialog","setRejectDialog","rejectReason","setRejectReason","handleManifestFileUpload","useCallback","file","reader","text","evt","extractedVersion","prev","bulkAction","setBulkAction","orgPublishTarget","setOrgPublishTarget","appData","useGetApplicationQuery","appId","isWorkflowApp","isNodeApp","isManifestOnlyType","isIntegrationApp","isPrivateNodeApp","app","pricingDetailsRaw","pricingDone","storeDone","appReadyForSubmission","appReadinessBlockers","name","reg","versionsData","versionsLoading","versionsError","useGetApplicationVersionsQuery","createVersion","creating","useCreateApplicationVersionMutation","updateVersion","updating","useUpdateApplicationVersionMutation","publishVersion","usePublishApplicationVersionMutation","publishToOrganization","publishingToOrganization","usePublishApplicationVersionToOrganizationMutation","deprecateVersion","useDeprecateApplicationVersionMutation","approveVersion","useApproveApplicationVersionMutation","rejectVersion","useRejectApplicationVersionMutation","versions","useMemo","edge","selectedVersions","version","publishableVersions","hasPendingVersion","deprecatableVersions","allVisibleSelected","partiallySelected","openLifecycle","basePath","versionId","handleCreate","parsedManifest","requiredScopes","s","created","createdId","err","handleZipUpload","result","handleEditZipUpload","handleEditManifestUpload","handleEditSave","manifestChanged","input","handlePublish","handlePublishToOrganization","target","handleDeprecate","handleRejectConfirm","getStatusIcon","CheckCircle","Send","XCircle","Clock","Archive","Package","toggleVersionSelection","next","checked","toggleAllVisibleVersions","clearSelection","handleBulkPublish","results","succeeded","failed","handleBulkDeprecate","manifestDerivedVersion","PageLayout","Loader2","EmptyState","AlertCircle","PermissionGuard","Plus","b","v","SelectionCheckbox","DataTable","event","StatusBadge","PackageValidationPanel","Building2","ManifestViewer","Rocket","existingManifest","readPackageValidationState","ConfirmDialog","open","InputField","Fragment","Upload","MarkdownEditor"],"sources":["../../../src/devportal/pages/ApplicationVersionsPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { useParams } from \"react-router\";\nimport {\n Plus,\n Package,\n CheckCircle,\n XCircle,\n Clock,\n Archive,\n Loader2,\n AlertCircle,\n Upload,\n Send,\n Building2,\n Rocket,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { PageLayout } from \"../components/PageLayout\";\nimport { DataTable } from \"../components/DataTable\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { InputField, TextareaField } from \"../components/FormField\";\nimport { MarkdownEditor } from \"../components/MarkdownEditor\";\nimport { ConfirmDialog } from \"../components/ConfirmDialog\";\nimport { SelectionCheckbox } from \"../components/SelectionCheckbox\";\nimport { ManifestViewer } from \"../components/ManifestViewer\";\nimport {\n PackageValidationPanel,\n readPackageValidationState,\n} from \"../components/PackageValidationPanel\";\nimport { format } from \"date-fns\";\nimport {\n useGetApplicationQuery,\n useGetApplicationVersionsQuery,\n useCreateApplicationVersionMutation,\n useUpdateApplicationVersionMutation,\n usePublishApplicationVersionMutation,\n usePublishApplicationVersionToOrganizationMutation,\n useDeprecateApplicationVersionMutation,\n useApproveApplicationVersionMutation,\n useRejectApplicationVersionMutation,\n type ApplicationVersionFieldsFragment,\n} from \"../hooks\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport { useDevportalPermission } from \"../hooks/usePermission\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { usePackageUpload } from \"../hooks/usePackageUpload\";\n\n/**\n * Pulls the version string out of an uploaded manifest so the developer\n * doesn't have to retype what's already declared in the file. Checks the\n * FluidGrids node manifest shape (`nodeVersion`, e.g.\n * fluidgrids-nodes/nodes/*\\/manifest.json) first, then the generic\n * `identity.version` / top-level `version` shapes used by other manifest types.\n */\nconst extractVersionFromManifest = (\n manifestJson: string,\n): string | undefined => {\n if (!manifestJson.trim()) return undefined;\n try {\n const parsed = JSON.parse(manifestJson) as Record<string, unknown>;\n if (typeof parsed.nodeVersion === \"string\" && parsed.nodeVersion.trim()) {\n return parsed.nodeVersion.trim();\n }\n const identity = parsed.identity as Record<string, unknown> | undefined;\n if (\n identity &&\n typeof identity.version === \"string\" &&\n identity.version.trim()\n ) {\n return identity.version.trim();\n }\n if (typeof parsed.version === \"string\" && parsed.version.trim()) {\n return parsed.version.trim();\n }\n } catch {\n // Manifest isn't valid JSON yet (still being typed/pasted) — ignore.\n }\n return undefined;\n};\n\n/** BOFF-9657: whether a version was published to its organization (not through review). */\nfunction isOrganizationPublished(metadata: unknown): boolean {\n if (typeof metadata !== \"object\" || metadata === null) return false;\n const record = (metadata as Record<string, unknown>).organizationPublish;\n return typeof record === \"object\" && record !== null;\n}\n\nexport const ApplicationVersionsPage: FC = () => {\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 { allowed: canCreate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_VERSION_CREATE,\n );\n const { allowed: canPublish } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_VERSION_PUBLISH,\n );\n const { allowed: canDeprecate } = useDevportalPermission(\n DEVPORTAL_PERMISSIONS.APP_VERSION_DEPRECATE,\n );\n const { appId } = useParams<{ appId: string }>();\n const {\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n navigate,\n basePath,\n } = useDevportal();\n const {\n upload: uploadZip,\n uploading: zipUploading,\n progress: zipProgress,\n error: zipUploadError,\n } = usePackageUpload(\n workspacesGatewayUrl,\n authToken,\n workspaceId,\n getWorkspaceToken,\n );\n const zipInputRef = useRef<HTMLInputElement>(null);\n const manifestInputRef = useRef<HTMLInputElement>(null);\n const editZipInputRef = useRef<HTMLInputElement>(null);\n const editManifestInputRef = useRef<HTMLInputElement>(null);\n const [manifestFileName, setManifestFileName] = useState<string | null>(null);\n const [editManifestFileName, setEditManifestFileName] = useState<\n string | null\n >(null);\n const [showCreateDialog, setShowCreateDialog] = useState(false);\n const [editDialog, setEditDialog] = useState<{\n versionId: string;\n version: string;\n hasExistingZip: boolean;\n newPackageUrl: string;\n newPackageFileId: string;\n newPackageWorkspaceId: string;\n newPackageSize: string;\n manifestJson: string;\n originalManifestJson: string;\n releaseNotes: string;\n changelog: string;\n } | null>(null);\n const [newVersion, setNewVersion] = useState({\n version: \"\",\n releaseNotes: \"\",\n changelog: \"\",\n packageUrl: \"\",\n packageFileId: \"\",\n packageWorkspaceId: \"\",\n packageSize: \"\",\n manifestJson: \"\",\n requiredScopes: \"\",\n });\n const [actionError, setActionError] = useState<string | null>(null);\n const [actionSuccess, setActionSuccess] = useState<string | null>(null);\n const [createDialogError, setCreateDialogError] = useState<string | null>(\n null,\n );\n const [editDialogError, setEditDialogError] = useState<string | null>(null);\n const [selectedVersionIds, setSelectedVersionIds] = useState<Set<string>>(\n new Set(),\n );\n const [rejectDialog, setRejectDialog] = useState<{\n versionId: string;\n version: string;\n } | null>(null);\n const [rejectReason, setRejectReason] = useState(\"\");\n\n const handleManifestFileUpload = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (evt) => {\n const text = evt.target?.result;\n if (typeof text === \"string\") {\n const extractedVersion = extractVersionFromManifest(text);\n setNewVersion((prev) => ({\n ...prev,\n manifestJson: text,\n ...(extractedVersion ? { version: extractedVersion } : {}),\n }));\n setManifestFileName(file.name);\n }\n };\n reader.readAsText(file);\n // reset so re-uploading same file triggers onChange\n e.target.value = \"\";\n },\n [],\n );\n const [bulkAction, setBulkAction] = useState<\"publish\" | \"deprecate\" | null>(\n null,\n );\n // BOFF-9657: the version a developer is about to publish to their organization.\n const [orgPublishTarget, setOrgPublishTarget] =\n useState<ApplicationVersionFieldsFragment | null>(null);\n\n const { data: appData } = useGetApplicationQuery({\n variables: { id: appId ?? \"\" },\n skip: !appId,\n fetchPolicy: \"cache-first\",\n });\n const isWorkflowApp = appData?.application?.appType === \"WORKFLOW\";\n const isNodeApp = appData?.application?.appType === \"NODE\";\n // Manifest-only types (no zip): Workflow plus its sibling types Parser/Widget/Dashboard.\n const isManifestOnlyType = [\n \"WORKFLOW\",\n \"PARSER\",\n \"WIDGET\",\n \"DASHBOARD\",\n ].includes(appData?.application?.appType ?? \"\");\n const isIntegrationApp = !isManifestOnlyType && !isNodeApp;\n // BOFF-9657: a PRIVATE node can be published to the developer's own\n // organization without platform review, once its package has validated.\n const isPrivateNodeApp =\n isNodeApp && appData?.application?.visibility === \"PRIVATE\";\n\n // App-level readiness checks — version submission is blocked until the app is ready\n const app = appData?.application;\n const pricingDetailsRaw = (app?.pricingDetails ?? {}) as Record<\n string,\n unknown\n >;\n const pricingDone =\n app?.pricingType === \"FREE\" ||\n (app?.pricingType === \"PAID\" &&\n typeof pricingDetailsRaw.price === \"number\" &&\n (pricingDetailsRaw.price as number) > 0);\n const storeDone =\n !!app?.shortDescription?.trim() &&\n !!app?.privacyPolicyUrl?.trim() &&\n !!app?.termsOfServiceUrl?.trim();\n const appReadyForSubmission = pricingDone && storeDone;\n const appReadinessBlockers: string[] = [\n ...(!storeDone\n ? [\n \"Complete your store listing (short description, privacy policy, terms of service)\",\n ]\n : []),\n ...(!pricingDone ? [\"Set pricing in the Pricing tab\"] : []),\n ];\n\n useEffect(() => {\n const name = appData?.application?.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, appData?.application?.name]);\n\n // Query\n const {\n data: versionsData,\n loading: versionsLoading,\n error: versionsError,\n } = useGetApplicationVersionsQuery({\n variables: { applicationId: appId! },\n skip: !appId,\n fetchPolicy: \"cache-and-network\",\n });\n\n // Mutations\n const [createVersion, { loading: creating }] =\n useCreateApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [updateVersion, { loading: updating }] =\n useUpdateApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [publishVersion] = usePublishApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [publishToOrganization, { loading: publishingToOrganization }] =\n usePublishApplicationVersionToOrganizationMutation({\n refetchQueries: [\"GetApplicationVersions\", \"GetApplication\"],\n });\n\n const [deprecateVersion] = useDeprecateApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [approveVersion] = useApproveApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const [rejectVersion] = useRejectApplicationVersionMutation({\n refetchQueries: [\"GetApplicationVersions\"],\n });\n\n const versions: ApplicationVersionFieldsFragment[] = useMemo(\n () =>\n versionsData?.application?.versions?.edges?.map(\n (edge: { node: ApplicationVersionFieldsFragment }) => edge.node,\n ) ?? [],\n [versionsData?.application?.versions],\n );\n\n const selectedVersions = useMemo(\n () => versions.filter((version) => selectedVersionIds.has(version.id)),\n [versions, selectedVersionIds],\n );\n const publishableVersions = useMemo(\n () =>\n selectedVersions.filter(\n (version) =>\n version.status === \"draft\" || version.status === \"rejected\",\n ),\n [selectedVersions],\n );\n // Only one version should be in the admin review queue at a time — otherwise\n // an admin can't tell which pending version a developer actually wants\n // reviewed. This is a UI-only guard (no backend change): once a version is\n // pending_review, block submitting another until it's approved or rejected.\n const hasPendingVersion = useMemo(\n () => versions.some((version) => version.status === \"pending_review\"),\n [versions],\n );\n const deprecatableVersions = useMemo(\n () =>\n selectedVersions.filter(\n (version) =>\n version.status?.toUpperCase() === \"PUBLISHED\" && !version.isLatest,\n ),\n [selectedVersions],\n );\n const allVisibleSelected =\n versions.length > 0 &&\n versions.every((version) => selectedVersionIds.has(version.id));\n const partiallySelected =\n versions.some((version) => selectedVersionIds.has(version.id)) &&\n !allVisibleSelected;\n\n const openLifecycle = (versionId: string) => {\n navigate?.(`${basePath}/apps/${appId}/versions/${versionId}/lifecycle`);\n };\n\n const handleCreate = async () => {\n if (!appId || !newVersion.version.trim()) return;\n setCreateDialogError(null);\n\n let parsedManifest: Record<string, unknown> | undefined;\n if (isManifestOnlyType) {\n if (!newVersion.manifestJson.trim()) {\n setCreateDialogError(\n isWorkflowApp\n ? \"Workflow Definition (JSON) is required — paste the {nodes, edges} object.\"\n : \"Manifest (JSON) is required.\",\n );\n return;\n }\n try {\n parsedManifest = JSON.parse(newVersion.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setCreateDialogError(\n isWorkflowApp\n ? \"Invalid JSON in Workflow Definition — please check your input.\"\n : \"Invalid JSON in Manifest — please check your input.\",\n );\n return;\n }\n } else if (isNodeApp) {\n if (!newVersion.packageUrl) {\n setCreateDialogError(\n \"Package zip is required for Node versions — upload a .zip file before creating.\",\n );\n return;\n }\n if (!newVersion.manifestJson.trim()) {\n setCreateDialogError(\n \"manifest.json is required for Node versions — upload or paste your manifest before creating.\",\n );\n return;\n }\n try {\n parsedManifest = JSON.parse(newVersion.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setCreateDialogError(\n \"Invalid JSON in manifest — please check your input.\",\n );\n return;\n }\n } else if (newVersion.manifestJson.trim()) {\n try {\n parsedManifest = JSON.parse(newVersion.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setCreateDialogError(\n \"Invalid JSON in manifest — please check your input.\",\n );\n return;\n }\n }\n\n const requiredScopes =\n isIntegrationApp && newVersion.requiredScopes.trim()\n ? newVersion.requiredScopes\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\n\n try {\n const created = await createVersion({\n variables: {\n applicationId: appId,\n input: {\n version: newVersion.version,\n releaseNotes: newVersion.releaseNotes || undefined,\n changelog: newVersion.changelog || undefined,\n packageUrl: newVersion.packageUrl || undefined,\n packageFileId: newVersion.packageFileId || undefined,\n packageWorkspaceId: newVersion.packageWorkspaceId || undefined,\n packageSize: newVersion.packageSize || undefined,\n manifest: parsedManifest,\n requiredScopes,\n },\n },\n });\n setShowCreateDialog(false);\n setManifestFileName(null);\n setNewVersion({\n version: \"\",\n releaseNotes: \"\",\n changelog: \"\",\n packageUrl: \"\",\n packageFileId: \"\",\n packageWorkspaceId: \"\",\n packageSize: \"\",\n manifestJson: \"\",\n requiredScopes: \"\",\n });\n setActionSuccess(\n tr(\"devportal.versionCreatedSuccess\", \"Version created successfully\"),\n );\n // BOFF-4076: a new custom-node version continues on its lifecycle page,\n // where validation, the sandbox build and the tests show up as they run.\n const createdId = created.data?.createApplicationVersion?.id;\n if (isNodeApp && createdId) openLifecycle(createdId);\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionCreateFailed\", \"Failed to create version\"),\n );\n }\n };\n\n const handleZipUpload = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n e.target.value = \"\";\n try {\n const result = await uploadZip(file);\n setNewVersion((prev) => ({\n ...prev,\n packageUrl: result.downloadUrl,\n packageFileId: result.fileId,\n packageWorkspaceId: workspaceId ?? \"\",\n packageSize: String(file.size),\n }));\n } catch {\n // error shown via zipUploadError prop\n }\n },\n [uploadZip, workspaceId],\n );\n\n const handleEditZipUpload = useCallback(\n async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n e.target.value = \"\";\n try {\n const result = await uploadZip(file);\n setEditDialog((prev) =>\n prev\n ? {\n ...prev,\n newPackageUrl: result.downloadUrl,\n newPackageFileId: result.fileId,\n newPackageWorkspaceId: workspaceId ?? \"\",\n newPackageSize: String(file.size),\n }\n : prev,\n );\n } catch {\n // error shown via zipUploadError prop\n }\n },\n [uploadZip, workspaceId],\n );\n\n const handleEditManifestUpload = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = (evt) => {\n const text = evt.target?.result;\n if (typeof text === \"string\") {\n setEditDialog((prev) =>\n prev ? { ...prev, manifestJson: text } : prev,\n );\n setEditManifestFileName(file.name);\n }\n };\n reader.readAsText(file);\n e.target.value = \"\";\n },\n [],\n );\n\n const handleEditSave = async () => {\n if (!editDialog) return;\n setEditDialogError(null);\n\n const manifestChanged =\n editDialog.manifestJson.trim() !== editDialog.originalManifestJson.trim();\n\n let parsedManifest: Record<string, unknown> | undefined;\n if (manifestChanged && editDialog.manifestJson.trim()) {\n try {\n parsedManifest = JSON.parse(editDialog.manifestJson) as Record<\n string,\n unknown\n >;\n } catch {\n setEditDialogError(\n \"Invalid JSON in manifest — please check your input.\",\n );\n return;\n }\n }\n\n const input: {\n releaseNotes?: string;\n changelog?: string;\n packageUrl?: string;\n packageFileId?: string;\n packageWorkspaceId?: string;\n packageSize?: string;\n manifest?: Record<string, unknown>;\n } = {};\n\n if (editDialog.releaseNotes.trim())\n input.releaseNotes = editDialog.releaseNotes;\n if (editDialog.changelog.trim()) input.changelog = editDialog.changelog;\n if (editDialog.newPackageUrl) {\n input.packageUrl = editDialog.newPackageUrl;\n input.packageFileId = editDialog.newPackageFileId || undefined;\n input.packageWorkspaceId = editDialog.newPackageWorkspaceId || undefined;\n input.packageSize = editDialog.newPackageSize;\n }\n if (parsedManifest) input.manifest = parsedManifest;\n\n try {\n await updateVersion({\n variables: { id: editDialog.versionId, input },\n });\n setEditDialog(null);\n setEditManifestFileName(null);\n setActionSuccess(\n tr(\"devportal.versionUpdatedSuccess\", \"Version updated successfully\"),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionUpdateFailed\", \"Failed to update version\"),\n );\n }\n };\n\n const handlePublish = async (versionId: string) => {\n setActionError(null);\n setActionSuccess(null);\n try {\n const result = await publishVersion({ variables: { id: versionId } });\n if (result.error || !result.data?.publishApplicationVersion) {\n throw (\n result.error ??\n new Error(\n tr(\n \"devportal.versionPublishFailed\",\n \"Failed to submit version for review\",\n ),\n )\n );\n }\n setActionSuccess(\n tr(\n \"devportal.versionSubmittedSuccess\",\n \"Version submitted for review — you'll be notified when approved\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.versionPublishFailed\",\n \"Failed to submit version for review\",\n ),\n );\n }\n };\n\n const handlePublishToOrganization = async () => {\n const target = orgPublishTarget;\n setOrgPublishTarget(null);\n if (!target || !workspaceId) return;\n setActionError(null);\n setActionSuccess(null);\n try {\n // The host shell's Apollo client may resolve a refused mutation with\n // `error` set instead of throwing; never report success without data.\n const result = await publishToOrganization({\n variables: { id: target.id, workspaceId },\n });\n if (\n result.error ||\n !result.data?.publishApplicationVersionToOrganization\n ) {\n throw (\n result.error ??\n new Error(\n tr(\n \"devportal.versionPublishToOrganizationFailed\",\n \"Failed to publish the version to your organization\",\n ),\n )\n );\n }\n setActionSuccess(\n tr(\n \"devportal.versionPublishedToOrganizationSuccess\",\n \"Version published to your organization. Workspace admins in your organization can now install it.\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.versionPublishToOrganizationFailed\",\n \"Failed to publish the version to your organization\",\n ),\n );\n }\n };\n\n const handleDeprecate = async (versionId: string) => {\n setActionError(null);\n setActionSuccess(null);\n try {\n await deprecateVersion({ variables: { id: versionId } });\n setActionSuccess(\n tr(\n \"devportal.versionDeprecatedSuccess\",\n \"Version deprecated successfully\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.versionDeprecateFailed\",\n \"Failed to deprecate version\",\n ),\n );\n }\n };\n\n const handleApprove = async (versionId: string) => {\n setActionError(null);\n setActionSuccess(null);\n try {\n await approveVersion({ variables: { id: versionId } });\n setActionSuccess(\n tr(\n \"devportal.versionApprovedSuccess\",\n \"Version approved and published to store\",\n ),\n );\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionApproveFailed\", \"Failed to approve version\"),\n );\n }\n };\n\n const handleRejectConfirm = async () => {\n if (!rejectDialog || !rejectReason.trim()) return;\n setActionError(null);\n setActionSuccess(null);\n try {\n await rejectVersion({\n variables: { id: rejectDialog.versionId, reason: rejectReason },\n });\n setActionSuccess(\n tr(\n \"devportal.versionRejectedSuccess\",\n \"Version rejected — developer has been notified\",\n ),\n );\n setRejectDialog(null);\n setRejectReason(\"\");\n } catch (err) {\n setActionError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.versionRejectFailed\", \"Failed to reject version\"),\n );\n }\n };\n\n const getStatusIcon = (version: ApplicationVersionFieldsFragment) => {\n if (version.status === \"published\" && version.isLatest) {\n return <CheckCircle size={16} className=\"text-status-success-text\" />;\n }\n if (version.status === \"pending_review\") {\n return <Send size={16} className=\"text-status-info-text\" />;\n }\n if (version.status === \"rejected\") {\n return <XCircle size={16} className=\"text-status-error-text\" />;\n }\n if (version.status === \"draft\") {\n return <Clock size={16} className=\"text-status-warning-text\" />;\n }\n if (version.status === \"deprecated\") {\n return <Archive size={16} className=\"text-text-secondary\" />;\n }\n return <Package size={16} className=\"text-accent-blue\" />;\n };\n\n const toggleVersionSelection = (versionId: string, checked: boolean) => {\n setSelectedVersionIds((prev) => {\n const next = new Set(prev);\n if (checked) {\n next.add(versionId);\n } else {\n next.delete(versionId);\n }\n return next;\n });\n };\n\n const toggleAllVisibleVersions = (checked: boolean) => {\n setSelectedVersionIds((prev) => {\n const next = new Set(prev);\n versions.forEach((version) => {\n if (checked) {\n next.add(version.id);\n } else {\n next.delete(version.id);\n }\n });\n return next;\n });\n };\n\n const clearSelection = () => setSelectedVersionIds(new Set());\n\n const handleBulkPublish = async () => {\n if (publishableVersions.length === 0) return;\n setActionError(null);\n const results = await Promise.allSettled(\n publishableVersions.map((version) =>\n publishVersion({ variables: { id: version.id } }),\n ),\n );\n const succeeded = results.filter(\n (result: PromiseSettledResult<unknown>) => result.status === \"fulfilled\",\n ).length;\n const failed = results.length - succeeded;\n setActionSuccess(\n `Published ${succeeded} version${succeeded === 1 ? \"\" : \"s\"}${failed > 0 ? ` • ${failed} failed` : \"\"}`,\n );\n clearSelection();\n setBulkAction(null);\n };\n\n const handleBulkDeprecate = async () => {\n if (deprecatableVersions.length === 0) return;\n setActionError(null);\n const results = await Promise.allSettled(\n deprecatableVersions.map((version) =>\n deprecateVersion({ variables: { id: version.id } }),\n ),\n );\n const succeeded = results.filter(\n (result: PromiseSettledResult<unknown>) => result.status === \"fulfilled\",\n ).length;\n const failed = results.length - succeeded;\n setActionSuccess(\n `Deprecated ${succeeded} version${succeeded === 1 ? \"\" : \"s\"}${failed > 0 ? ` • ${failed} failed` : \"\"}`,\n );\n clearSelection();\n setBulkAction(null);\n };\n\n // The version number is meant to come from the manifest itself, not be\n // retyped by hand — surface whatever we could parse out of it so the field\n // can be locked once the manifest supplies one.\n const manifestDerivedVersion = extractVersionFromManifest(\n newVersion.manifestJson,\n );\n\n // Loading state\n if (versionsLoading && !versionsData) {\n return (\n <PageLayout\n title={tr(\"devportal.versionManagement\", \"Version Management\")}\n description={tr(\n \"devportal.versionManagementDescription\",\n \"Manage your application versions\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-16\">\n <Loader2 className=\"h-8 w-8 animate-spin text-text-secondary\" />\n </div>\n </PageLayout>\n );\n }\n\n // Error state\n if (versionsError && !versionsData) {\n return (\n <PageLayout\n title={tr(\"devportal.versionManagement\", \"Version Management\")}\n description={tr(\n \"devportal.versionManagementDescription\",\n \"Manage your application versions\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <EmptyState\n icon={<AlertCircle size={32} className=\"text-status-error-text\" />}\n title={tr(\n \"devportal.failedToLoadVersions\",\n \"Failed to load versions\",\n )}\n description={\n versionsError.message ||\n tr(\n \"devportal.versionsLoadError\",\n \"An error occurred while loading versions\",\n )\n }\n />\n </PageLayout>\n );\n }\n\n return (\n <PermissionGuard authOnly>\n <PageLayout\n title={tr(\"devportal.versionManagement\", \"Version Management\")}\n description={tr(\n \"devportal.versionManagementDescription\",\n \"Manage your application versions\",\n )}\n purpose={\n isWorkflowApp\n ? tr(\n \"devportal.versionManagementPurposeWorkflow\",\n \"Versions track releases of your workflow. Create a version for each significant change and paste the workflow definition JSON. No zip is needed — the manifest is the workflow.\",\n )\n : isNodeApp\n ? tr(\n \"devportal.versionManagementPurposeNode\",\n \"Versions are the releases of your node that users install. Upload a new zip whenever the node implementation changes, and update the manifest if the node's inputs, outputs, or operations change. Bump the version for any change users will see.\",\n )\n : isManifestOnlyType\n ? tr(\n \"devportal.versionManagementPurposeManifestOnly\",\n \"Versions track releases of this item. Create a version for each significant change and paste the manifest JSON. No zip is needed.\",\n )\n : tr(\n \"devportal.versionManagementPurposeIntegration\",\n \"Versions track permission and webhook changes for your integration. No zip or manifest is needed — create a new version whenever you add or change required scopes so users can review and accept the updated permissions.\",\n )\n }\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => {\n setCreateDialogError(null);\n setShowCreateDialog(true);\n }}\n disabled={!canCreate}\n aria-disabled={!canCreate}\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.newVersion\", \"New Version\")}\n </button>\n }\n >\n {/* Action Error Banner */}\n {actionError && (\n <div className=\"rounded-lg border border-border-subtle bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text\">\n <AlertCircle size={16} className=\"flex-shrink-0\" />\n {actionError}\n <button\n onClick={() => setActionError(null)}\n className=\"ml-auto text-status-error-text hover:text-status-error-text\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n )}\n\n {actionSuccess && (\n <div className=\"rounded-lg border border-border-subtle bg-status-success-bg-subtle p-3 flex items-center gap-2 text-sm text-status-success-text\">\n <CheckCircle size={16} className=\"flex-shrink-0\" />\n {actionSuccess}\n <button\n onClick={() => setActionSuccess(null)}\n className=\"ml-auto text-status-success-text hover:text-status-success-text\"\n >\n {tr(\"devportal.dismiss\", \"Dismiss\")}\n </button>\n </div>\n )}\n\n {/* App setup incomplete — block version submission with a clear warning */}\n {app && !appReadyForSubmission && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text\">\n <AlertCircle size={16} className=\"mt-0.5 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n Complete your app setup before submitting for review\n </p>\n <ul className=\"mt-1 list-disc pl-4 text-xs opacity-80\">\n {appReadinessBlockers.map((b) => (\n <li key={b}>{b}</li>\n ))}\n </ul>\n </div>\n </div>\n )}\n\n {/* First-time submission explainer — shown when app is not yet published and there are draft versions */}\n {app &&\n app.status !== \"PUBLISHED\" &&\n versions.some((v) => v.status === \"draft\") && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-info-bg bg-status-info-bg-subtle px-4 py-3 text-sm text-status-info-text\">\n <Send size={16} className=\"mt-0.5 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n Ready to submit? Go to the Submit tab\n </p>\n <p className=\"mt-1 text-xs opacity-80\">\n For your first submission the app and its version are reviewed\n together. Head to the <strong>Submit</strong> tab — your draft\n version will be included automatically. The per-version\n "Submit for Review" button is only for new versions\n after the app is already live in the marketplace.\n </p>\n </div>\n </div>\n )}\n\n {/* A version is already awaiting admin review — block submitting another\n so admins never have more than one pending version per app to sort out. */}\n {app && hasPendingVersion && (\n <div className=\"flex items-start gap-3 rounded-lg border border-status-warning-bg bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text\">\n <Send size={16} className=\"mt-0.5 shrink-0\" />\n <div>\n <p className=\"font-medium\">\n {tr(\n \"devportal.versionAlreadyPending\",\n \"A version is already pending review\",\n )}\n </p>\n <p className=\"mt-1 text-xs opacity-80\">\n {tr(\n \"devportal.versionAlreadyPendingDetail\",\n \"Submitting another version is disabled until it's approved or rejected.\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {versions.length > 0 && (\n <div className=\"rounded-card border border-border-seam bg-bg-surface p-4\">\n <div className=\"flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <div className=\"flex items-center gap-2\">\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllVisibleVersions}\n ariaLabel=\"Select all visible versions\"\n />\n <span className=\"text-sm font-medium\">\n {tr(\"devportal.selectAllVisible\", \"Select all visible\")}\n </span>\n </div>\n {selectedVersionIds.size > 0 && (\n <button\n onClick={clearSelection}\n className=\"text-sm text-text-secondary hover:text-text-primary\"\n >\n {tr(\"devportal.clearSelection\", \"Clear selection\")}\n </button>\n )}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"rounded-full bg-bg-sunken px-3 py-1 text-sm font-medium text-text-secondary\">\n {selectedVersionIds.size} selected\n </span>\n <button\n onClick={() => setBulkAction(\"publish\")}\n disabled={\n publishableVersions.length === 0 ||\n !canPublish ||\n !appReadyForSubmission ||\n hasPendingVersion\n }\n aria-disabled={\n !canPublish || !appReadyForSubmission || hasPendingVersion\n }\n title={\n hasPendingVersion\n ? tr(\n \"devportal.versionAlreadyPending\",\n \"A version is already pending review\",\n )\n : !appReadyForSubmission\n ? appReadinessBlockers.join(\" · \")\n : undefined\n }\n className=\"rounded-md border border-status-success-bg px-3 py-2 text-sm font-medium text-status-success-text hover:bg-status-success-bg-subtle disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {tr(\"devportal.submitForReview\", \"Submit for Review\")}\n {publishableVersions.length > 0\n ? ` (${publishableVersions.length})`\n : \"\"}\n </button>\n <button\n onClick={() => setBulkAction(\"deprecate\")}\n disabled={deprecatableVersions.length === 0 || !canDeprecate}\n aria-disabled={!canDeprecate}\n className=\"rounded-md border border-status-warning-bg px-3 py-2 text-sm font-medium text-status-warning-text hover:bg-status-warning-bg-subtle disabled:cursor-not-allowed disabled:opacity-50\"\n >\n {tr(\"devportal.deprecateSelected\", \"Deprecate Selected\")}\n {deprecatableVersions.length > 0\n ? ` (${deprecatableVersions.length})`\n : \"\"}\n </button>\n </div>\n </div>\n </div>\n )}\n\n {versions.length > 0 ? (\n <DataTable\n data={versions}\n keyField=\"id\"\n columns={[\n {\n key: \"select\",\n header: (\n <SelectionCheckbox\n checked={allVisibleSelected}\n indeterminate={partiallySelected}\n onChange={toggleAllVisibleVersions}\n ariaLabel=\"Select all visible versions\"\n />\n ),\n className: \"w-12\",\n render: (v) => (\n <div onClick={(event) => event.stopPropagation()}>\n <SelectionCheckbox\n checked={selectedVersionIds.has(v.id)}\n onChange={(checked) =>\n toggleVersionSelection(v.id, checked)\n }\n ariaLabel={`Select version ${v.version}`}\n />\n </div>\n ),\n },\n {\n key: \"version\",\n header: tr(\"devportal.version\", \"Version\"),\n render: (v) => (\n <div className=\"flex items-center gap-2\">\n {getStatusIcon(v)}\n <span className=\"font-mono font-medium\">{v.version}</span>\n {v.isLatest && (\n <span className=\"rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs text-status-success-text\">\n {tr(\"devportal.latest\", \"Latest\")}\n </span>\n )}\n {!v.isStable && (\n <span className=\"rounded-full bg-status-warning-bg-subtle px-2 py-0.5 text-xs text-status-warning-text\">\n {tr(\"devportal.beta\", \"Beta\")}\n </span>\n )}\n </div>\n ),\n },\n {\n key: \"releaseNotes\",\n header: tr(\"devportal.releaseNotes\", \"Release Notes\"),\n render: (v) => (\n <p className=\"max-w-md truncate text-sm text-text-secondary\">\n {v.releaseNotes ||\n tr(\"devportal.noReleaseNotes\", \"No release notes\")}\n </p>\n ),\n },\n {\n key: \"status\",\n header: tr(\"devportal.status\", \"Status\"),\n render: (v) => (\n <div className=\"space-y-1\">\n <StatusBadge\n status={\n v.status === \"pending_review\" ? \"In Review\" : v.status\n }\n />\n {v.status === \"pending_review\" && (\n <p className=\"text-xs text-status-info-text\">\n Awaiting platform review\n </p>\n )}\n {v.status === \"rejected\" && v.reviewNotes && (\n <p className=\"text-xs text-status-error-text max-w-xs\">\n {v.reviewNotes}\n </p>\n )}\n {isNodeApp && v.packageUrl && (\n <PackageValidationPanel metadata={v.metadata} />\n )}\n {isPrivateNodeApp &&\n isOrganizationPublished(v.metadata) && (\n <p className=\"inline-flex items-center gap-1 text-xs text-status-success-text\">\n <Building2 size={11} />\n {tr(\n \"devportal.publishedToOrganization\",\n \"Published to your organization\",\n )}\n </p>\n )}\n </div>\n ),\n },\n {\n key: \"publishedAt\",\n header: tr(\"devportal.published\", \"Published\"),\n render: (v) =>\n v.publishedAt\n ? format(new Date(v.publishedAt), \"MMM d, yyyy\")\n : \"-\",\n },\n {\n key: \"manifest\",\n header: tr(\"devportal.manifest\", \"Manifest\"),\n render: (v) =>\n v.manifest ? (\n <ManifestViewer\n manifest={v.manifest as Record<string, unknown>}\n tr={tr}\n />\n ) : (\n <span className=\"text-xs text-text-secondary\">\n {tr(\"devportal.noManifest\", \"No manifest\")}\n </span>\n ),\n },\n {\n key: \"actions\",\n header: \"\",\n className: \"w-48\",\n render: (v) => (\n <div className=\"flex flex-wrap gap-2\">\n {isNodeApp && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n data-testid={`version-lifecycle-${v.id}`}\n onClick={() => openLifecycle(v.id)}\n >\n <Rocket size={11} />\n {tr(\"devportal.nodeLifecycle.open\", \"Lifecycle\")}\n </button>\n )}\n {/* Edit draft/rejected versions before submission */}\n {(v.status === \"draft\" || v.status === \"rejected\") &&\n canCreate && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary hover:underline\"\n onClick={() => {\n const existingManifest = v.manifest\n ? JSON.stringify(v.manifest, null, 2)\n : \"\";\n setEditDialog({\n versionId: v.id,\n version: v.version,\n hasExistingZip: !!v.packageUrl,\n newPackageUrl: \"\",\n newPackageFileId: \"\",\n newPackageWorkspaceId: \"\",\n newPackageSize: \"\",\n manifestJson: existingManifest,\n originalManifestJson: existingManifest,\n releaseNotes: v.releaseNotes ?? \"\",\n changelog: v.changelog ?? \"\",\n });\n setEditManifestFileName(null);\n setEditDialogError(null);\n }}\n >\n Edit\n </button>\n )}\n {/* Only show \"Submit for Review\" on a version when the app is already\n published — for a first-time app the whole submission goes through\n the app-level \"Submit for Review\" (store listing + pricing + version). */}\n {(v.status === \"draft\" || v.status === \"rejected\") &&\n app?.status === \"PUBLISHED\" && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline disabled:opacity-50 disabled:cursor-not-allowed\"\n disabled={\n !canPublish ||\n !appReadyForSubmission ||\n hasPendingVersion\n }\n aria-disabled={\n !canPublish ||\n !appReadyForSubmission ||\n hasPendingVersion\n }\n title={\n hasPendingVersion\n ? tr(\n \"devportal.versionAlreadyPending\",\n \"A version is already pending review\",\n )\n : !appReadyForSubmission\n ? appReadinessBlockers.join(\" · \")\n : undefined\n }\n onClick={() => handlePublish(v.id)}\n >\n <Send size={11} />\n {tr(\"devportal.submitForReview\", \"Submit for Review\")}\n </button>\n )}\n {isPrivateNodeApp &&\n (v.status === \"draft\" || v.status === \"rejected\") && (\n <button\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline disabled:opacity-50 disabled:cursor-not-allowed\"\n disabled={\n !canPublish ||\n !workspaceId ||\n publishingToOrganization ||\n readPackageValidationState(v.metadata).kind !==\n \"passed\"\n }\n aria-disabled={\n !canPublish ||\n !workspaceId ||\n publishingToOrganization ||\n readPackageValidationState(v.metadata).kind !==\n \"passed\"\n }\n title={\n readPackageValidationState(v.metadata).kind !==\n \"passed\"\n ? tr(\n \"devportal.publishToOrganizationNeedsValidation\",\n \"Upload a package that passes validation first\",\n )\n : undefined\n }\n onClick={() => setOrgPublishTarget(v)}\n >\n <Building2 size={11} />\n {tr(\n \"devportal.publishToOrganization\",\n \"Publish to my organization\",\n )}\n </button>\n )}\n {v.status === \"published\" && !v.isLatest && (\n <button\n className=\"text-xs text-status-warning-text hover:underline disabled:opacity-50\"\n disabled={!canDeprecate}\n aria-disabled={!canDeprecate}\n onClick={() => handleDeprecate(v.id)}\n >\n {tr(\"devportal.deprecate\", \"Deprecate\")}\n </button>\n )}\n </div>\n ),\n },\n ]}\n />\n ) : (\n <EmptyState\n illustration=\"empty-data\"\n title={tr(\"devportal.noVersionsYet\", \"No versions yet\")}\n description={tr(\n \"devportal.noVersionsYetDescription\",\n \"Create your first version to start distributing your app\",\n )}\n action={\n <button\n onClick={() => {\n setCreateDialogError(null);\n setShowCreateDialog(true);\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\"\n >\n <Plus size={16} />\n {tr(\"devportal.createVersion\", \"Create Version\")}\n </button>\n }\n />\n )}\n\n {/* Create Version Dialog */}\n {showCreateDialog && (\n <ConfirmDialog\n open={showCreateDialog}\n onOpenChange={(open) => {\n setShowCreateDialog(open);\n if (!open) setCreateDialogError(null);\n }}\n onConfirm={handleCreate}\n title={tr(\"devportal.createNewVersion\", \"Create New Version\")}\n confirmLabel={\n creating\n ? tr(\"devportal.creating\", \"Creating...\")\n : tr(\"devportal.createVersion\", \"Create Version\")\n }\n >\n <div className=\"space-y-4\">\n {createDialogError && (\n <div className=\"rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n {createDialogError}\n </div>\n )}\n <InputField\n label={tr(\"devportal.versionNumber\", \"Version Number\")}\n value={newVersion.version}\n onChange={(e) =>\n setNewVersion({ ...newVersion, version: e.target.value })\n }\n placeholder=\"e.g., 2.2.0\"\n hint={\n manifestDerivedVersion\n ? tr(\n \"devportal.versionHintAutoFilled\",\n \"Filled in from the manifest's version — edit it there if this is wrong.\",\n )\n : tr(\n \"devportal.versionHint\",\n \"Use semantic versioning (major.minor.patch). Upload a manifest.json/manifest with a version to fill this in automatically.\",\n )\n }\n readOnly={!!manifestDerivedVersion}\n required\n />\n {isManifestOnlyType && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {isWorkflowApp\n ? \"Workflow Definition (JSON)\"\n : \"Manifest (JSON)\"}{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <textarea\n rows={10}\n required\n placeholder={\n isWorkflowApp\n ? `{\\n \"nodes\": [],\\n \"edges\": []\\n}`\n : `{\\n \"manifestVersion\": \"1.0\",\\n \"identity\": { \"name\": \"My Item\", \"version\": \"1.0.0\" }\\n}`\n }\n value={newVersion.manifestJson}\n onChange={(e) => {\n const extractedVersion = extractVersionFromManifest(\n e.target.value,\n );\n setNewVersion({\n ...newVersion,\n manifestJson: e.target.value,\n ...(extractedVersion\n ? { version: extractedVersion }\n : {}),\n });\n }}\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <p className=\"text-xs text-text-secondary\">\n {isWorkflowApp ? (\n <>\n Paste the full <code>{`{nodes, edges}`}</code> JSON.\n Saved as this version's manifest — no zip needed.\n </>\n ) : (\n \"Paste the manifest JSON for this version. No zip needed.\"\n )}\n </p>\n </div>\n )}\n {/* Zip upload — node apps only */}\n {isNodeApp && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n Package (.zip){\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <div className=\"flex gap-2 items-center\">\n <input\n ref={zipInputRef}\n type=\"file\"\n accept=\".zip\"\n className=\"hidden\"\n onChange={handleZipUpload}\n />\n <button\n type=\"button\"\n disabled={zipUploading}\n onClick={() => zipInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {zipUploading ? (\n <>\n <Loader2 size={14} className=\"animate-spin\" />{\" \"}\n Uploading… {zipProgress}%\n </>\n ) : (\n <>\n <Upload size={14} />{\" \"}\n {newVersion.packageUrl ? \"Replace zip\" : \"Upload zip\"}\n </>\n )}\n </button>\n {newVersion.packageUrl && !zipUploading && (\n <span className=\"text-xs text-status-success-text\">\n ✓ Uploaded\n </span>\n )}\n </div>\n {zipUploadError && (\n <p className=\"text-xs text-status-error-text\">\n {zipUploadError}\n </p>\n )}\n <p className=\"text-xs text-text-tertiary\">\n The zip is the node executable. Upload it before publishing\n — users install exactly this artifact.\n </p>\n </div>\n )}\n\n {/* Manifest JSON — node apps only (required) */}\n {isNodeApp && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-2 flex-wrap\">\n <label className=\"text-sm font-medium\">\n manifest.json{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <div className=\"flex items-center gap-2\">\n {manifestFileName && (\n <span className=\"text-xs text-status-success-text\">\n ✓ {manifestFileName}\n </span>\n )}\n <input\n ref={manifestInputRef}\n type=\"file\"\n accept=\".json,application/json\"\n className=\"hidden\"\n onChange={handleManifestFileUpload}\n />\n <button\n type=\"button\"\n onClick={() => manifestInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors\"\n >\n <Upload size={12} />\n Upload manifest.json\n </button>\n </div>\n </div>\n <textarea\n rows={5}\n placeholder={`{\\n \"manifestVersion\": \"1.0\",\\n \"itemType\": \"node\",\\n \"identity\": { \"version\": \"1.0.0\", \"displayName\": \"My Node\" }\\n}`}\n value={newVersion.manifestJson}\n onChange={(e) => {\n setManifestFileName(null);\n const extractedVersion = extractVersionFromManifest(\n e.target.value,\n );\n setNewVersion({\n ...newVersion,\n manifestJson: e.target.value,\n ...(extractedVersion\n ? { version: extractedVersion }\n : {}),\n });\n }}\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <p className=\"text-xs text-text-tertiary\">\n Upload or paste your <code>manifest.json</code> — required\n so the platform knows your node's inputs, outputs, and\n operations. Not extracted from the zip automatically.\n </p>\n </div>\n )}\n\n {/* Required scopes — integration/app types only */}\n {isIntegrationApp && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n Required scopes{\" \"}\n <span className=\"text-xs font-normal text-text-secondary\">\n (optional)\n </span>\n </label>\n <input\n type=\"text\"\n value={newVersion.requiredScopes}\n onChange={(e) =>\n setNewVersion({\n ...newVersion,\n requiredScopes: e.target.value,\n })\n }\n placeholder=\"e.g. read:contacts, write:messages\"\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-sm placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n <p className=\"text-xs text-text-tertiary\">\n Comma-separated. List every permission this version needs —\n users will be prompted to accept any new or changed scopes\n on update.\n </p>\n </div>\n )}\n <MarkdownEditor\n label={tr(\"devportal.releaseNotes\", \"Release Notes\")}\n value={newVersion.releaseNotes}\n onChange={(value) =>\n setNewVersion({ ...newVersion, releaseNotes: value })\n }\n placeholder={tr(\n \"devportal.releaseNotesPlaceholder\",\n \"What changed in this release?\",\n )}\n rows={3}\n />\n <MarkdownEditor\n label={tr(\"devportal.changelog\", \"Changelog\")}\n value={newVersion.changelog}\n onChange={(value) =>\n setNewVersion({ ...newVersion, changelog: value })\n }\n placeholder={tr(\n \"devportal.changelogPlaceholder\",\n \"Detailed changelog for this version...\",\n )}\n rows={3}\n />\n </div>\n </ConfirmDialog>\n )}\n\n {/* Reject version dialog */}\n {rejectDialog && (\n <ConfirmDialog\n open={!!rejectDialog}\n onOpenChange={(open) => {\n if (!open) {\n setRejectDialog(null);\n setRejectReason(\"\");\n }\n }}\n onConfirm={handleRejectConfirm}\n title={`Reject version ${rejectDialog.version}`}\n confirmLabel=\"Reject Version\"\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"danger\"\n >\n <div className=\"space-y-3\">\n <p className=\"text-sm text-text-secondary\">\n The developer will be notified and can fix and resubmit. Please\n provide a clear reason.\n </p>\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n Rejection reason{\" \"}\n <span className=\"text-status-error-text\">*</span>\n </label>\n <textarea\n rows={3}\n value={rejectReason}\n onChange={(e) => setRejectReason(e.target.value)}\n placeholder=\"e.g. Manifest contains disallowed network calls to external domains...\"\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-sm placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n </div>\n </ConfirmDialog>\n )}\n\n {/* Edit Version Dialog */}\n {editDialog && (\n <ConfirmDialog\n open={!!editDialog}\n onOpenChange={(open) => {\n if (!open) {\n setEditDialog(null);\n setEditManifestFileName(null);\n setEditDialogError(null);\n }\n }}\n onConfirm={handleEditSave}\n title={`Edit Version ${editDialog.version}`}\n confirmLabel={updating ? \"Saving…\" : \"Save Changes\"}\n >\n <div className=\"space-y-4\">\n {editDialogError && (\n <div className=\"rounded-lg border border-status-error-bg bg-status-error-bg-subtle p-3 flex items-center gap-2 text-sm text-status-error-text\">\n <AlertCircle size={14} className=\"flex-shrink-0\" />\n {editDialogError}\n </div>\n )}\n <div className=\"rounded-lg border border-status-info-bg bg-status-info-bg-subtle px-3 py-2 text-xs text-status-info-text\">\n You can fix the zip, manifest, or release notes before\n submitting for review. Once submitted for review these fields\n are locked.\n </div>\n\n {/* ZIP replacement — node apps */}\n {isNodeApp && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">Package (.zip)</label>\n <div className=\"flex gap-2 items-center\">\n <input\n ref={editZipInputRef}\n type=\"file\"\n accept=\".zip\"\n className=\"hidden\"\n onChange={handleEditZipUpload}\n />\n <button\n type=\"button\"\n disabled={zipUploading}\n onClick={() => editZipInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm font-medium hover:bg-bg-sunken transition-colors disabled:opacity-50\"\n >\n {zipUploading ? (\n <>\n <Loader2 size={14} className=\"animate-spin\" />{\" \"}\n Uploading… {zipProgress}%\n </>\n ) : (\n <>\n <Upload size={14} />\n {editDialog.newPackageUrl\n ? \"Replace zip again\"\n : editDialog.hasExistingZip\n ? \"Replace zip\"\n : \"Upload zip\"}\n </>\n )}\n </button>\n {editDialog.newPackageUrl && !zipUploading && (\n <span className=\"text-xs text-status-success-text\">\n ✓ New zip ready\n </span>\n )}\n {!editDialog.newPackageUrl && editDialog.hasExistingZip && (\n <span className=\"text-xs text-text-secondary\">\n Current zip kept\n </span>\n )}\n </div>\n {zipUploadError && (\n <p className=\"text-xs text-status-error-text\">\n {zipUploadError}\n </p>\n )}\n </div>\n )}\n\n {/* Manifest replacement — node apps */}\n {isNodeApp && (\n <div className=\"space-y-2\">\n <div className=\"flex items-center justify-between gap-2 flex-wrap\">\n <label className=\"text-sm font-medium\">\n manifest.json{\" \"}\n <span className=\"text-xs font-normal text-text-secondary\">\n (edit below or upload a new file)\n </span>\n </label>\n <div className=\"flex items-center gap-2\">\n {editManifestFileName && (\n <span className=\"text-xs text-status-success-text\">\n ✓ {editManifestFileName}\n </span>\n )}\n <input\n ref={editManifestInputRef}\n type=\"file\"\n accept=\".json,application/json\"\n className=\"hidden\"\n onChange={handleEditManifestUpload}\n />\n <button\n type=\"button\"\n onClick={() => editManifestInputRef.current?.click()}\n className=\"inline-flex items-center gap-1.5 rounded-md border border-border-subtle px-2.5 py-1 text-xs font-medium hover:bg-bg-sunken transition-colors\"\n >\n <Upload size={12} /> Upload manifest.json\n </button>\n </div>\n </div>\n <textarea\n rows={5}\n placeholder={`{\\n \"manifestVersion\": \"1.0\",\\n \"itemType\": \"node\",\\n \"identity\": { \"version\": \"1.0.0\", \"displayName\": \"My Node\" }\\n}`}\n value={editDialog.manifestJson}\n onChange={(e) => {\n setEditManifestFileName(null);\n setEditDialog((prev) =>\n prev ? { ...prev, manifestJson: e.target.value } : prev,\n );\n }}\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n )}\n\n {/* Workflow definition replacement */}\n {isManifestOnlyType && (\n <div className=\"space-y-1\">\n <label className=\"text-sm font-medium\">\n {isWorkflowApp\n ? \"Workflow Definition (JSON)\"\n : \"Manifest (JSON)\"}{\" \"}\n <span className=\"text-xs font-normal text-text-secondary\">\n (leave empty to keep existing)\n </span>\n </label>\n <textarea\n rows={10}\n placeholder={\n isWorkflowApp\n ? `{\\n \"nodes\": [],\\n \"edges\": []\\n}`\n : `{\\n \"manifestVersion\": \"1.0\",\\n \"identity\": { \"name\": \"My Item\", \"version\": \"1.0.0\" }\\n}`\n }\n value={editDialog.manifestJson}\n onChange={(e) =>\n setEditDialog((prev) =>\n prev ? { ...prev, manifestJson: e.target.value } : prev,\n )\n }\n className=\"w-full rounded-md border bg-transparent px-3 py-2 text-xs font-mono resize-y placeholder:text-text-secondary focus:outline-none focus:ring-1 focus:ring-[var(--color-focus-ring)]\"\n />\n </div>\n )}\n\n <MarkdownEditor\n label={tr(\"devportal.releaseNotes\", \"Release Notes\")}\n value={editDialog.releaseNotes}\n onChange={(value) =>\n setEditDialog((prev) =>\n prev ? { ...prev, releaseNotes: value } : prev,\n )\n }\n placeholder={tr(\n \"devportal.releaseNotesPlaceholder\",\n \"What changed in this release?\",\n )}\n rows={3}\n />\n <MarkdownEditor\n label={tr(\"devportal.changelog\", \"Changelog\")}\n value={editDialog.changelog}\n onChange={(value) =>\n setEditDialog((prev) =>\n prev ? { ...prev, changelog: value } : prev,\n )\n }\n placeholder={tr(\n \"devportal.changelogPlaceholder\",\n \"Detailed changelog for this version...\",\n )}\n rows={3}\n />\n </div>\n </ConfirmDialog>\n )}\n\n <ConfirmDialog\n open={bulkAction === \"publish\"}\n onOpenChange={(open) => {\n if (!open) setBulkAction(null);\n }}\n onConfirm={handleBulkPublish}\n title={tr(\n \"devportal.submitSelectedVersions\",\n \"Submit selected versions for review\",\n )}\n description={`Submit ${publishableVersions.length} selected version${publishableVersions.length === 1 ? \"\" : \"s\"} for platform review?`}\n confirmLabel={tr(\"devportal.submitForReview\", \"Submit for Review\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"success\"\n />\n\n <ConfirmDialog\n open={orgPublishTarget !== null}\n onOpenChange={(open) => {\n if (!open) setOrgPublishTarget(null);\n }}\n onConfirm={handlePublishToOrganization}\n title={tr(\n \"devportal.publishToOrganizationTitle\",\n \"Publish to my organization\",\n )}\n description={`${tr(\n \"devportal.publishToOrganizationDescription\",\n \"Version {version} goes live for the workspaces of your organization without platform review. It is never listed in the public Node Store. Workspace admins in your organization can install it from this app.\",\n ).replace(\"{version}\", orgPublishTarget?.version ?? \"\")}`}\n confirmLabel={tr(\n \"devportal.publishToOrganization\",\n \"Publish to my organization\",\n )}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"success\"\n />\n\n <ConfirmDialog\n open={bulkAction === \"deprecate\"}\n onOpenChange={(open) => {\n if (!open) setBulkAction(null);\n }}\n onConfirm={handleBulkDeprecate}\n title={tr(\n \"devportal.deprecateSelectedVersions\",\n \"Deprecate selected versions\",\n )}\n description={`${tr(\"devportal.deprecate\", \"Deprecate\")} ${deprecatableVersions.length} selected version${deprecatableVersions.length === 1 ? \"\" : \"s\"}? ${tr(\"devportal.deprecateVersionsWarning\", \"Deprecated versions remain visible but should no longer be promoted.\")}`}\n confirmLabel={tr(\"devportal.deprecate\", \"Deprecate\")}\n cancelLabel={tr(\"devportal.cancel\", \"Cancel\")}\n variant=\"warning\"\n />\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|