@burdenoff/microfe-devportal 2026.609.3 → 2026.611.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/devportal/DevportalRoot.js +6 -1
  2. package/dist/devportal/DevportalRoot.js.map +1 -1
  3. package/dist/devportal/DevportalRoutes.js +169 -158
  4. package/dist/devportal/DevportalRoutes.js.map +1 -1
  5. package/dist/devportal/hooks/usePackageUpload.js +120 -0
  6. package/dist/devportal/hooks/usePackageUpload.js.map +1 -0
  7. package/dist/devportal/pages/AnalyticsDashboardPage.js +73 -62
  8. package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
  9. package/dist/devportal/pages/AppLogsPage.js +89 -82
  10. package/dist/devportal/pages/AppLogsPage.js.map +1 -1
  11. package/dist/devportal/pages/ApplicationDetailPage.js +948 -367
  12. package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
  13. package/dist/devportal/pages/ApplicationVersionsPage.js +56 -45
  14. package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
  15. package/dist/devportal/pages/CreateApiKeyPage.js +30 -32
  16. package/dist/devportal/pages/CreateApiKeyPage.js.map +1 -1
  17. package/dist/devportal/pages/CreateApplicationPage.js +8 -3
  18. package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
  19. package/dist/devportal/pages/CreateOAuthClientPage.js +4 -4
  20. package/dist/devportal/pages/CreateOAuthClientPage.js.map +1 -1
  21. package/dist/devportal/pages/CreateOrganizationPage.js +233 -228
  22. package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
  23. package/dist/devportal/pages/CreateWebhookPage.js +159 -148
  24. package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
  25. package/dist/devportal/pages/DelegationsPage.js +1 -1
  26. package/dist/devportal/pages/DelegationsPage.js.map +1 -1
  27. package/dist/devportal/pages/EditApplicationPage.js +25 -17
  28. package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
  29. package/dist/devportal/pages/ListingPreviewPage.js +159 -153
  30. package/dist/devportal/pages/ListingPreviewPage.js.map +1 -1
  31. package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
  32. package/dist/devportal/pages/OAuthClientsPage.js +2 -2
  33. package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
  34. package/dist/devportal/pages/OrganizationDetailPage.js +158 -153
  35. package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
  36. package/dist/devportal/pages/OrganizationMembersPage.js +223 -212
  37. package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
  38. package/dist/devportal/pages/PublishPage.js +172 -165
  39. package/dist/devportal/pages/PublishPage.js.map +1 -1
  40. package/dist/devportal/pages/ResourcesPage.js.map +1 -1
  41. package/dist/devportal/pages/RevenueDashboardPage.js +405 -0
  42. package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -0
  43. package/dist/devportal/pages/SetupPage.js +170 -217
  44. package/dist/devportal/pages/SetupPage.js.map +1 -1
  45. package/dist/devportal/pages/StoreSubmissionPage.js +76 -97
  46. package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
  47. package/dist/devportal/pages/WebhookDetailPage.js +172 -154
  48. package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
  49. package/dist/devportal/pages/WebhooksPage.js +218 -200
  50. package/dist/devportal/pages/WebhooksPage.js.map +1 -1
  51. package/dist/devportal/providers/DevportalProvider.js +16 -13
  52. package/dist/devportal/providers/DevportalProvider.js.map +1 -1
  53. package/dist/devportal/types/index.js.map +1 -1
  54. package/dist/generated/global-operations.js +310 -225
  55. package/dist/generated/global-operations.js.map +1 -1
  56. package/package.json +1 -1
  57. package/dist/devportal/pages/RevenueRedirectPage.js +0 -14
  58. package/dist/devportal/pages/RevenueRedirectPage.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"StoreSubmissionPage.js","names":[],"sources":["../../../src/devportal/pages/StoreSubmissionPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useNavigate, useParams } from \"react-router-dom\";\nimport {\n ArrowLeft,\n CheckCircle2,\n Clock,\n RefreshCw,\n XCircle,\n AlertTriangle,\n Store as StoreIcon,\n} from \"lucide-react\";\nimport { useApolloClient } from \"@apollo/client/react\";\nimport { gql } from \"@apollo/client/core\";\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { useDevportalEventBus } from \"../events\";\nimport { useTr } from \"../utils/i18n\";\nimport { useDevportalPermission } from \"../hooks\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\n\ntype SubmissionStatus =\n | \"DRAFT\"\n | \"PENDING_REVIEW\"\n | \"PUBLISHED\"\n | \"REJECTED\"\n | \"UNKNOWN\";\n\ntype StoreSubmission = {\n productId: string;\n status: SubmissionStatus;\n submittedAt: string | null;\n reviewedAt: string | null;\n publishedAt: string | null;\n reviewNotes: string | null;\n rejectedReason: string | null;\n};\n\ntype Application = {\n id: string;\n name: string;\n slug: string;\n status: string;\n reviewStatus: string;\n iconUrl: string | null;\n metadata: Record<string, unknown> | null;\n};\n\nconst APP_QUERY = /* GraphQL */ `\n query DevportalAppForSubmission($id: ID!) {\n application(id: $id) {\n id\n name\n slug\n status\n reviewStatus\n iconUrl\n metadata\n }\n }\n`;\n\nconst SUBMIT_MUTATION = /* GraphQL */ `\n mutation DevportalSubmitForReview($id: ID!, $notes: String) {\n submitApplicationForReview(id: $id, notes: $notes) {\n id\n status\n submittedAt\n metadata\n }\n }\n`;\n\nfunction inferSubmission(app: Application | null): StoreSubmission | null {\n if (!app) return null;\n const metadata = (app.metadata ?? {}) as Record<string, unknown>;\n const productId =\n typeof metadata.storeProductId === \"string\" ? metadata.storeProductId : \"\";\n const rawStatus =\n typeof metadata.storeSubmissionStatus === \"string\"\n ? metadata.storeSubmissionStatus\n : null;\n const status: SubmissionStatus =\n rawStatus === \"PENDING_REVIEW\" ||\n rawStatus === \"PUBLISHED\" ||\n rawStatus === \"REJECTED\" ||\n rawStatus === \"DRAFT\"\n ? rawStatus\n : \"UNKNOWN\";\n return {\n productId,\n status,\n submittedAt:\n typeof metadata.storeSubmissionAt === \"string\"\n ? metadata.storeSubmissionAt\n : null,\n reviewedAt: null,\n publishedAt: null,\n reviewNotes: null,\n rejectedReason: null,\n };\n}\n\ntype StatusMeta = {\n i18nKey: string;\n fallback: string;\n icon: typeof CheckCircle2;\n tone: string;\n};\n\nconst statusLabels: Record<SubmissionStatus, StatusMeta> = {\n DRAFT: {\n i18nKey: \"devportal.storeSubmission.status.draft\",\n fallback: \"Draft\",\n icon: Clock,\n tone: \"text-text-secondary\",\n },\n PENDING_REVIEW: {\n i18nKey: \"devportal.storeSubmission.status.pending\",\n fallback: \"Pending review\",\n icon: Clock,\n tone: \"text-status-warning-text\",\n },\n PUBLISHED: {\n i18nKey: \"devportal.storeSubmission.status.published\",\n fallback: \"Published\",\n icon: CheckCircle2,\n tone: \"text-status-success-text\",\n },\n REJECTED: {\n i18nKey: \"devportal.storeSubmission.status.rejected\",\n fallback: \"Rejected\",\n icon: XCircle,\n tone: \"text-status-danger-text\",\n },\n UNKNOWN: {\n i18nKey: \"devportal.storeSubmission.status.unknown\",\n fallback: \"Not yet submitted\",\n icon: AlertTriangle,\n tone: \"text-text-tertiary\",\n },\n};\n\nexport const StoreSubmissionPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const navigate = useNavigate();\n const bus = useDevportalEventBus();\n const tr = useTr();\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n const [app, setApp] = useState<Application | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const storeClient = useApolloClient();\n\n const load = async () => {\n if (!appId) return;\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{ application: Application | null }>({\n gateway: \"global\",\n query: APP_QUERY,\n variables: { id: appId },\n });\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr(\n \"devportal.storeSubmission.errors.loadFailed\",\n \"Failed to load application\",\n ),\n );\n }\n setApp(result.data?.application ?? null);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.storeSubmission.errors.loadFailed\",\n \"Failed to load application\",\n ),\n );\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void load();\n }, [appId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n if (!appId) return;\n const sub = storeClient.subscribe({\n query: gql`\n subscription ApplicationStoreStatusChanged($applicationId: ID!) {\n applicationStoreStatusChanged(applicationId: $applicationId) {\n applicationId\n status\n reviewNotes\n rejectedReason\n updatedAt\n }\n }\n `,\n variables: { applicationId: appId },\n });\n const subscription = sub.subscribe({\n next: () => {\n void load();\n },\n error: (err: unknown) => {\n console.warn(\"[StoreSubmissionPage] subscription error:\", err);\n },\n });\n return () => subscription.unsubscribe();\n }, [appId, storeClient]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const submit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: \"global\",\n query: SUBMIT_MUTATION,\n variables: { id: appId, notes: notes || null },\n });\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr(\n \"devportal.storeSubmission.errors.submitFailed\",\n \"Submission failed\",\n ),\n );\n }\n bus.emit(\"devportal.app.submitted\", { appId });\n await load();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.storeSubmission.errors.submitFailed\",\n \"Submission failed\",\n ),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n const submission = inferSubmission(app);\n const statusMeta = submission\n ? statusLabels[submission.status]\n : statusLabels.UNKNOWN;\n const StatusIcon = statusMeta.icon;\n\n return (\n <main\n className=\"min-h-screen bg-surface-default\"\n aria-labelledby=\"store-submission-heading\"\n >\n <div className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-3xl px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n className=\"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\"devportal.common.back\", \"Back\")}\n </button>\n <div className=\"flex items-center gap-2\">\n <StoreIcon\n className=\"h-5 w-5 text-text-primary\"\n aria-hidden=\"true\"\n />\n <h1\n id=\"store-submission-heading\"\n className=\"text-xl font-semibold text-text-primary\"\n >\n {tr(\"devportal.storeSubmission.title\", \"Store submission\")}\n </h1>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"mx-auto max-w-3xl px-6 py-6\">\n {error && (\n <div\n role=\"alert\"\n className=\"mb-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {error}\n </div>\n )}\n\n {loading && !app ? (\n <div\n className=\"py-16 text-center text-text-secondary\"\n role=\"status\"\n aria-live=\"polite\"\n >\n {tr(\"devportal.storeSubmission.loading\", \"Loading application…\")}\n </div>\n ) : !app ? (\n <div className=\"py-16 text-center text-text-secondary\">\n {tr(\"devportal.storeSubmission.notFound\", \"Application not found.\")}\n </div>\n ) : (\n <div className=\"space-y-4\">\n {/* App header */}\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <div className=\"flex items-center gap-3\">\n {app.iconUrl ? (\n <img\n src={app.iconUrl}\n alt=\"\"\n className=\"h-14 w-14 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-text-secondary\">\n {app.name.slice(0, 2).toUpperCase()}\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {app.name}\n </h2>\n <p className=\"font-mono text-xs text-text-tertiary\">\n {app.slug}\n </p>\n </div>\n <div\n className={`flex items-center gap-1.5 ${statusMeta.tone}`}\n role=\"status\"\n >\n <StatusIcon className=\"h-5 w-5\" aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">\n {tr(statusMeta.i18nKey, statusMeta.fallback)}\n </span>\n </div>\n </div>\n </div>\n\n {/* Timeline */}\n {submission && submission.status !== \"UNKNOWN\" && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {tr(\n \"devportal.storeSubmission.timeline\",\n \"Submission timeline\",\n )}\n </h3>\n <ul className=\"space-y-2 text-sm\">\n {submission.submittedAt && (\n <li className=\"flex items-center gap-2\">\n <Clock\n className=\"h-4 w-4 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <span className=\"text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.submitted\",\n \"Submitted:\",\n )}\n </span>\n <span className=\"text-text-primary\">\n {new Date(submission.submittedAt).toLocaleString()}\n </span>\n </li>\n )}\n {submission.reviewedAt && (\n <li className=\"flex items-center gap-2\">\n <CheckCircle2\n className=\"h-4 w-4 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <span className=\"text-text-secondary\">\n {tr(\"devportal.storeSubmission.reviewed\", \"Reviewed:\")}\n </span>\n <span className=\"text-text-primary\">\n {new Date(submission.reviewedAt).toLocaleString()}\n </span>\n </li>\n )}\n {submission.publishedAt && (\n <li className=\"flex items-center gap-2\">\n <CheckCircle2\n className=\"h-4 w-4 text-status-success-text\"\n aria-hidden=\"true\"\n />\n <span className=\"text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.published\",\n \"Published:\",\n )}\n </span>\n <span className=\"text-text-primary\">\n {new Date(submission.publishedAt).toLocaleString()}\n </span>\n </li>\n )}\n </ul>\n {submission.reviewNotes && (\n <div className=\"mt-3 rounded-md bg-surface-muted p-3\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.reviewerNotes\",\n \"Reviewer notes\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-text-primary\">\n {submission.reviewNotes}\n </p>\n </div>\n )}\n {submission.rejectedReason && (\n <div\n className=\"mt-3 rounded-md border border-border-danger bg-surface-danger-muted p-3\"\n role=\"alert\"\n >\n <p className=\"text-xs font-medium text-text-danger\">\n {tr(\n \"devportal.storeSubmission.rejectionReason\",\n \"Rejection reason\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-text-primary\">\n {submission.rejectedReason}\n </p>\n </div>\n )}\n </div>\n )}\n\n {/* Submit / resubmit */}\n {(!submission ||\n submission.status === \"UNKNOWN\" ||\n submission.status === \"DRAFT\" ||\n submission.status === \"REJECTED\") && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {submission?.status === \"REJECTED\"\n ? tr(\n \"devportal.storeSubmission.resubmitForReview\",\n \"Resubmit for review\",\n )\n : tr(\n \"devportal.storeSubmission.submitForReview\",\n \"Submit for review\",\n )}\n </h3>\n <p className=\"mb-3 text-sm text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.help\",\n \"Your application will be sent to the store's review queue. Whether it's auto-published or requires admin approval depends on the target store's configuration.\",\n )}\n </p>\n <label className=\"block\" htmlFor=\"store-submission-notes\">\n <span className=\"sr-only\">\n {tr(\n \"devportal.storeSubmission.notesLabel\",\n \"Notes for the reviewer (optional)\",\n )}\n </span>\n </label>\n <textarea\n id=\"store-submission-notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n rows={3}\n placeholder={tr(\n \"devportal.storeSubmission.notesLabel\",\n \"Notes for the reviewer (optional)\",\n )}\n className=\"mb-3 w-full rounded-md border border-border-default bg-surface-default px-3 py-2 text-sm text-text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n />\n <button\n type=\"button\"\n onClick={() => void submit()}\n disabled={submitting || !submitPerm.allowed}\n aria-disabled={submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90 disabled:opacity-60 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting && (\n <RefreshCw\n className=\"h-4 w-4 animate-spin\"\n aria-hidden=\"true\"\n />\n )}\n {submission?.status === \"REJECTED\"\n ? tr(\"devportal.storeSubmission.resubmit\", \"Resubmit\")\n : tr(\n \"devportal.storeSubmission.submitForReview\",\n \"Submit for review\",\n )}\n </button>\n </div>\n )}\n\n {submission?.productId && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.storeProductId\",\n \"Store product ID\",\n )}\n </p>\n <code className=\"mt-1 block break-all font-mono text-xs text-text-primary\">\n {submission.productId}\n </code>\n </div>\n )}\n </div>\n )}\n </div>\n </main>\n );\n};\n"],"mappings":";;;;;;;;;;;;;AA+CA,IAAM,IAA0B,gMAc1B,IAAgC;AAWtC,SAAS,EAAgB,GAAiD;AACxE,KAAI,CAAC,EAAK,QAAO;CACjB,IAAM,IAAY,EAAI,YAAY,EAAE,EAC9B,IACJ,OAAO,EAAS,kBAAmB,WAAW,EAAS,iBAAiB,IACpE,IACJ,OAAO,EAAS,yBAA0B,WACtC,EAAS,wBACT;AAQN,QAAO;EACL;EACA,QARA,MAAc,oBACd,MAAc,eACd,MAAc,cACd,MAAc,UACV,IACA;EAIJ,aACE,OAAO,EAAS,qBAAsB,WAClC,EAAS,oBACT;EACN,YAAY;EACZ,aAAa;EACb,aAAa;EACb,gBAAgB;EACjB;;AAUH,IAAM,IAAqD;CACzD,OAAO;EACL,SAAS;EACT,UAAU;EACV,MAAM;EACN,MAAM;EACP;CACD,gBAAgB;EACd,SAAS;EACT,UAAU;EACV,MAAM;EACN,MAAM;EACP;CACD,WAAW;EACT,SAAS;EACT,UAAU;EACV,MAAM;EACN,MAAM;EACP;CACD,UAAU;EACR,SAAS;EACT,UAAU;EACV,MAAM;EACN,MAAM;EACP;CACD,SAAS;EACP,SAAS;EACT,UAAU;EACV,MAAM;EACN,MAAM;EACP;CACF,EAEY,UAAgC;CAC3C,IAAM,EAAE,aAAU,GAA8B,EAC1C,IAAW,GAAa,EACxB,IAAM,GAAsB,EAC5B,IAAK,GAAO,EACZ,IAAa,EAAuB,EAAsB,WAAW,EACrE,CAAC,GAAK,KAAU,EAA6B,KAAK,EAClD,CAAC,GAAS,KAAc,EAAS,GAAK,EACtC,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,IAAc,GAAiB,EAE/B,IAAO,YAAY;AAClB,SAEL;GADA,EAAW,GAAK,EAChB,EAAS,KAAK;AACd,OAAI;IACF,IAAM,IAAS,MAAM,EAAkD;KACrE,SAAS;KACT,OAAO;KACP,WAAW,EAAE,IAAI,GAAO;KACzB,CAAC;AACF,QAAI,EAAO,QAAQ,OACjB,OAAU,MACR,EAAO,OAAO,IAAI,WAChB,EACE,+CACA,6BACD,CACJ;AAEH,MAAO,EAAO,MAAM,eAAe,KAAK;YACjC,GAAK;AACZ,MACE,aAAe,QACX,EAAI,UACJ,EACE,+CACA,6BACD,CACN;aACO;AACR,MAAW,GAAM;;;;AAQrB,CAJA,QAAgB;AACT,KAAM;IACV,CAAC,EAAM,CAAC,EAEX,QAAgB;AACd,MAAI,CAAC,EAAO;EAeZ,IAAM,IAdM,EAAY,UAAU;GAChC,OAAO,CAAG;;;;;;;;;;;GAWV,WAAW,EAAE,eAAe,GAAO;GACpC,CAAC,CACuB,UAAU;GACjC,YAAY;AACL,OAAM;;GAEb,QAAQ,MAAiB;AACvB,YAAQ,KAAK,6CAA6C,EAAI;;GAEjE,CAAC;AACF,eAAa,EAAa,aAAa;IACtC,CAAC,GAAO,EAAY,CAAC;CAExB,IAAM,IAAS,YAAY;AACpB,SAEL;GADA,EAAc,GAAK,EACnB,EAAS,KAAK;AACd,OAAI;IACF,IAAM,IAAS,MAAM,EAAa;KAChC,SAAS;KACT,OAAO;KACP,WAAW;MAAE,IAAI;MAAO,OAAO,KAAS;MAAM;KAC/C,CAAC;AACF,QAAI,EAAO,QAAQ,OACjB,OAAU,MACR,EAAO,OAAO,IAAI,WAChB,EACE,iDACA,oBACD,CACJ;AAGH,IADA,EAAI,KAAK,2BAA2B,EAAE,UAAO,CAAC,EAC9C,MAAM,GAAM;YACL,GAAK;AACZ,MACE,aAAe,QACX,EAAI,UACJ,EACE,iDACA,oBACD,CACN;aACO;AACR,MAAc,GAAM;;;IAIlB,IAAa,EAAgB,EAAI,EACjC,IAAa,IACf,EAAa,EAAW,UACxB,EAAa,SACX,IAAa,EAAW;AAE9B,QACE,kBAAC,QAAD;EACE,WAAU;EACV,mBAAgB;YAFlB,CAIE,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAS,GAAG;MAC3B,WAAU;gBAHZ,CAKE,kBAAC,GAAD;OAAW,WAAU;OAAU,eAAY;OAAS,CAAA,EACnD,EAAG,yBAAyB,OAAO,CAC7B;SACT,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD;OACE,WAAU;OACV,eAAY;OACZ,CAAA,EACF,kBAAC,MAAD;OACE,IAAG;OACH,WAAU;iBAET,EAAG,mCAAmC,mBAAmB;OACvD,CAAA,CACD;QACF;;IACF,CAAA;GACF,CAAA,EAEN,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,KACC,kBAAC,OAAD;IACE,MAAK;IACL,WAAU;cAET;IACG,CAAA,EAGP,KAAW,CAAC,IACX,kBAAC,OAAD;IACE,WAAU;IACV,MAAK;IACL,aAAU;cAET,EAAG,qCAAqC,uBAAuB;IAC5D,CAAA,GACH,IAKH,kBAAC,OAAD;IAAK,WAAU;cAAf;KAEE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACG,EAAI,UACH,kBAAC,OAAD;SACE,KAAK,EAAI;SACT,KAAI;SACJ,WAAU;SACV,CAAA,GAEF,kBAAC,OAAD;SAAK,WAAU;mBACZ,EAAI,KAAK,MAAM,GAAG,EAAE,CAAC,aAAa;SAC/B,CAAA;QAER,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,MAAD;UAAI,WAAU;oBACX,EAAI;UACF,CAAA,EACL,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAI;UACH,CAAA,CACA;;QACN,kBAAC,OAAD;SACE,WAAW,6BAA6B,EAAW;SACnD,MAAK;mBAFP,CAIE,kBAAC,GAAD;UAAY,WAAU;UAAU,eAAY;UAAS,CAAA,EACrD,kBAAC,QAAD;UAAM,WAAU;oBACb,EAAG,EAAW,SAAS,EAAW,SAAS;UACvC,CAAA,CACH;;QACF;;MACF,CAAA;KAGL,KAAc,EAAW,WAAW,aACnC,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,MAAD;QAAI,WAAU;kBACX,EACC,sCACA,sBACD;QACE,CAAA;OACL,kBAAC,MAAD;QAAI,WAAU;kBAAd;SACG,EAAW,eACV,kBAAC,MAAD;UAAI,WAAU;oBAAd;WACE,kBAAC,GAAD;YACE,WAAU;YACV,eAAY;YACZ,CAAA;WACF,kBAAC,QAAD;YAAM,WAAU;sBACb,EACC,uCACA,aACD;YACI,CAAA;WACP,kBAAC,QAAD;YAAM,WAAU;sBACb,IAAI,KAAK,EAAW,YAAY,CAAC,gBAAgB;YAC7C,CAAA;WACJ;;SAEN,EAAW,cACV,kBAAC,MAAD;UAAI,WAAU;oBAAd;WACE,kBAAC,GAAD;YACE,WAAU;YACV,eAAY;YACZ,CAAA;WACF,kBAAC,QAAD;YAAM,WAAU;sBACb,EAAG,sCAAsC,YAAY;YACjD,CAAA;WACP,kBAAC,QAAD;YAAM,WAAU;sBACb,IAAI,KAAK,EAAW,WAAW,CAAC,gBAAgB;YAC5C,CAAA;WACJ;;SAEN,EAAW,eACV,kBAAC,MAAD;UAAI,WAAU;oBAAd;WACE,kBAAC,GAAD;YACE,WAAU;YACV,eAAY;YACZ,CAAA;WACF,kBAAC,QAAD;YAAM,WAAU;sBACb,EACC,uCACA,aACD;YACI,CAAA;WACP,kBAAC,QAAD;YAAM,WAAU;sBACb,IAAI,KAAK,EAAW,YAAY,CAAC,gBAAgB;YAC7C,CAAA;WACJ;;SAEJ;;OACJ,EAAW,eACV,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,KAAD;SAAG,WAAU;mBACV,EACC,2CACA,iBACD;SACC,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAW;SACV,CAAA,CACA;;OAEP,EAAW,kBACV,kBAAC,OAAD;QACE,WAAU;QACV,MAAK;kBAFP,CAIE,kBAAC,KAAD;SAAG,WAAU;mBACV,EACC,6CACA,mBACD;SACC,CAAA,EACJ,kBAAC,KAAD;SAAG,WAAU;mBACV,EAAW;SACV,CAAA,CACA;;OAEJ;;MAIN,CAAC,KACD,EAAW,WAAW,aACtB,EAAW,WAAW,WACtB,EAAW,WAAW,eACtB,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,MAAD;QAAI,WAAU;kBACX,GAAY,WAAW,aACpB,EACE,+CACA,sBACD,GACD,EACE,6CACA,oBACD;QACF,CAAA;OACL,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,kCACA,iKACD;QACC,CAAA;OACJ,kBAAC,SAAD;QAAO,WAAU;QAAQ,SAAQ;kBAC/B,kBAAC,QAAD;SAAM,WAAU;mBACb,EACC,wCACA,oCACD;SACI,CAAA;QACD,CAAA;OACR,kBAAC,YAAD;QACE,IAAG;QACH,OAAO;QACP,WAAW,MAAM,EAAS,EAAE,OAAO,MAAM;QACzC,MAAM;QACN,aAAa,EACX,wCACA,oCACD;QACD,WAAU;QACV,CAAA;OACF,kBAAC,UAAD;QACE,MAAK;QACL,eAAe,KAAK,GAAQ;QAC5B,UAAU,KAAc,CAAC,EAAW;QACpC,iBAAe,KAAc,CAAC,EAAW;QACzC,OACG,EAAW,UAKR,KAAA,IAJA,EACE,iCACA,oDACD;QAGP,WAAU;kBAbZ,CAeG,KACC,kBAAC,GAAD;SACE,WAAU;SACV,eAAY;SACZ,CAAA,EAEH,GAAY,WAAW,aACpB,EAAG,sCAAsC,WAAW,GACpD,EACE,6CACA,oBACD,CACE;;OACL;;KAGP,GAAY,aACX,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,4CACA,mBACD;OACC,CAAA,EACJ,kBAAC,QAAD;OAAM,WAAU;iBACb,EAAW;OACP,CAAA,CACH;;KAEJ;QAxNN,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAG,sCAAsC,yBAAyB;IAC/D,CAAA,CAwNJ;KACD"}
1
+ {"version":3,"file":"StoreSubmissionPage.js","names":[],"sources":["../../../src/devportal/pages/StoreSubmissionPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport { useNavigate, useParams } from \"react-router-dom\";\nimport {\n ArrowLeft,\n CheckCircle2,\n Clock,\n RefreshCw,\n XCircle,\n AlertTriangle,\n Store as StoreIcon,\n} from \"lucide-react\";\nimport { graphqlFetch } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { useDevportalEventBus } from \"../events\";\nimport { useTr } from \"../utils/i18n\";\nimport { useDevportalPermission } from \"../hooks\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\n\ntype SubmissionStatus =\n | \"DRAFT\"\n | \"PENDING_REVIEW\"\n | \"PUBLISHED\"\n | \"REJECTED\"\n | \"UNKNOWN\";\n\ntype StoreSubmission = {\n productId: string;\n status: SubmissionStatus;\n submittedAt: string | null;\n reviewedAt: string | null;\n publishedAt: string | null;\n reviewNotes: string | null;\n rejectedReason: string | null;\n};\n\ntype Application = {\n id: string;\n name: string;\n slug: string;\n status: string;\n reviewStatus: string;\n iconUrl: string | null;\n metadata: Record<string, unknown> | null;\n};\n\nconst APP_QUERY = /* GraphQL */ `\n query DevportalAppForSubmission($id: ID!) {\n application(id: $id) {\n id\n name\n slug\n status\n reviewStatus\n iconUrl\n metadata\n }\n }\n`;\n\nconst SUBMIT_MUTATION = /* GraphQL */ `\n mutation DevportalSubmitForReview($id: ID!, $notes: String) {\n submitApplicationForReview(id: $id, notes: $notes) {\n id\n status\n submittedAt\n metadata\n }\n }\n`;\n\nfunction inferSubmission(app: Application | null): StoreSubmission | null {\n if (!app) return null;\n const metadata = (app.metadata ?? {}) as Record<string, unknown>;\n const productId =\n typeof metadata.storeProductId === \"string\" ? metadata.storeProductId : \"\";\n const rawStatus =\n typeof metadata.storeSubmissionStatus === \"string\"\n ? metadata.storeSubmissionStatus\n : null;\n const status: SubmissionStatus =\n rawStatus === \"PENDING_REVIEW\" ||\n rawStatus === \"PUBLISHED\" ||\n rawStatus === \"REJECTED\" ||\n rawStatus === \"DRAFT\"\n ? rawStatus\n : \"UNKNOWN\";\n return {\n productId,\n status,\n submittedAt:\n typeof metadata.storeSubmissionAt === \"string\"\n ? metadata.storeSubmissionAt\n : null,\n reviewedAt: null,\n publishedAt: null,\n reviewNotes: null,\n rejectedReason: null,\n };\n}\n\ntype StatusMeta = {\n i18nKey: string;\n fallback: string;\n icon: typeof CheckCircle2;\n tone: string;\n};\n\nconst statusLabels: Record<SubmissionStatus, StatusMeta> = {\n DRAFT: {\n i18nKey: \"devportal.storeSubmission.status.draft\",\n fallback: \"Draft\",\n icon: Clock,\n tone: \"text-text-secondary\",\n },\n PENDING_REVIEW: {\n i18nKey: \"devportal.storeSubmission.status.pending\",\n fallback: \"Pending review\",\n icon: Clock,\n tone: \"text-status-warning-text\",\n },\n PUBLISHED: {\n i18nKey: \"devportal.storeSubmission.status.published\",\n fallback: \"Published\",\n icon: CheckCircle2,\n tone: \"text-status-success-text\",\n },\n REJECTED: {\n i18nKey: \"devportal.storeSubmission.status.rejected\",\n fallback: \"Rejected\",\n icon: XCircle,\n tone: \"text-status-danger-text\",\n },\n UNKNOWN: {\n i18nKey: \"devportal.storeSubmission.status.unknown\",\n fallback: \"Not yet submitted\",\n icon: AlertTriangle,\n tone: \"text-text-tertiary\",\n },\n};\n\nexport const StoreSubmissionPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const navigate = useNavigate();\n const bus = useDevportalEventBus();\n const tr = useTr();\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n const [app, setApp] = useState<Application | null>(null);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [submitting, setSubmitting] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const load = async () => {\n if (!appId) return;\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{ application: Application | null }>({\n gateway: \"global\",\n query: APP_QUERY,\n variables: { id: appId },\n });\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr(\n \"devportal.storeSubmission.errors.loadFailed\",\n \"Failed to load application\",\n ),\n );\n }\n setApp(result.data?.application ?? null);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.storeSubmission.errors.loadFailed\",\n \"Failed to load application\",\n ),\n );\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void load();\n }, [appId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const submit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: \"global\",\n query: SUBMIT_MUTATION,\n variables: { id: appId, notes: notes || null },\n });\n if (result.errors?.length) {\n throw new Error(\n result.errors[0]?.message ??\n tr(\n \"devportal.storeSubmission.errors.submitFailed\",\n \"Submission failed\",\n ),\n );\n }\n bus.emit(\"devportal.app.submitted\", { appId });\n await load();\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : tr(\n \"devportal.storeSubmission.errors.submitFailed\",\n \"Submission failed\",\n ),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n const submission = inferSubmission(app);\n const statusMeta = submission\n ? statusLabels[submission.status]\n : statusLabels.UNKNOWN;\n const StatusIcon = statusMeta.icon;\n\n return (\n <main\n className=\"min-h-screen bg-surface-default\"\n aria-labelledby=\"store-submission-heading\"\n >\n <div className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-3xl px-6 py-4\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n className=\"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\"devportal.common.back\", \"Back\")}\n </button>\n <div className=\"flex items-center gap-2\">\n <StoreIcon\n className=\"h-5 w-5 text-text-primary\"\n aria-hidden=\"true\"\n />\n <h1\n id=\"store-submission-heading\"\n className=\"text-xl font-semibold text-text-primary\"\n >\n {tr(\"devportal.storeSubmission.title\", \"Store submission\")}\n </h1>\n </div>\n </div>\n </div>\n </div>\n\n <div className=\"mx-auto max-w-3xl px-6 py-6\">\n {error && (\n <div\n role=\"alert\"\n className=\"mb-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {error}\n </div>\n )}\n\n {loading && !app ? (\n <div\n className=\"py-16 text-center text-text-secondary\"\n role=\"status\"\n aria-live=\"polite\"\n >\n {tr(\"devportal.storeSubmission.loading\", \"Loading application…\")}\n </div>\n ) : !app ? (\n <div className=\"py-16 text-center text-text-secondary\">\n {tr(\"devportal.storeSubmission.notFound\", \"Application not found.\")}\n </div>\n ) : (\n <div className=\"space-y-4\">\n {/* App header */}\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <div className=\"flex items-center gap-3\">\n {app.iconUrl ? (\n <img\n src={app.iconUrl}\n alt=\"\"\n className=\"h-14 w-14 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-text-secondary\">\n {app.name.slice(0, 2).toUpperCase()}\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {app.name}\n </h2>\n <p className=\"font-mono text-xs text-text-tertiary\">\n {app.slug}\n </p>\n </div>\n <div\n className={`flex items-center gap-1.5 ${statusMeta.tone}`}\n role=\"status\"\n >\n <StatusIcon className=\"h-5 w-5\" aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">\n {tr(statusMeta.i18nKey, statusMeta.fallback)}\n </span>\n </div>\n </div>\n </div>\n\n {/* Timeline */}\n {submission && submission.status !== \"UNKNOWN\" && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <h3 className=\"mb-3 text-sm font-semibold text-text-primary\">\n {tr(\n \"devportal.storeSubmission.timeline\",\n \"Submission timeline\",\n )}\n </h3>\n <ul className=\"space-y-2 text-sm\">\n {submission.submittedAt && (\n <li className=\"flex items-center gap-2\">\n <Clock\n className=\"h-4 w-4 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <span className=\"text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.submitted\",\n \"Submitted:\",\n )}\n </span>\n <span className=\"text-text-primary\">\n {new Date(submission.submittedAt).toLocaleString()}\n </span>\n </li>\n )}\n {submission.reviewedAt && (\n <li className=\"flex items-center gap-2\">\n <CheckCircle2\n className=\"h-4 w-4 text-text-tertiary\"\n aria-hidden=\"true\"\n />\n <span className=\"text-text-secondary\">\n {tr(\"devportal.storeSubmission.reviewed\", \"Reviewed:\")}\n </span>\n <span className=\"text-text-primary\">\n {new Date(submission.reviewedAt).toLocaleString()}\n </span>\n </li>\n )}\n {submission.publishedAt && (\n <li className=\"flex items-center gap-2\">\n <CheckCircle2\n className=\"h-4 w-4 text-status-success-text\"\n aria-hidden=\"true\"\n />\n <span className=\"text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.published\",\n \"Published:\",\n )}\n </span>\n <span className=\"text-text-primary\">\n {new Date(submission.publishedAt).toLocaleString()}\n </span>\n </li>\n )}\n </ul>\n {submission.reviewNotes && (\n <div className=\"mt-3 rounded-md bg-surface-muted p-3\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.reviewerNotes\",\n \"Reviewer notes\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-text-primary\">\n {submission.reviewNotes}\n </p>\n </div>\n )}\n {submission.rejectedReason && (\n <div\n className=\"mt-3 rounded-md border border-border-danger bg-surface-danger-muted p-3\"\n role=\"alert\"\n >\n <p className=\"text-xs font-medium text-text-danger\">\n {tr(\n \"devportal.storeSubmission.rejectionReason\",\n \"Rejection reason\",\n )}\n </p>\n <p className=\"mt-1 text-sm text-text-primary\">\n {submission.rejectedReason}\n </p>\n </div>\n )}\n </div>\n )}\n\n {/* Submit / resubmit */}\n {(!submission ||\n submission.status === \"UNKNOWN\" ||\n submission.status === \"DRAFT\" ||\n submission.status === \"REJECTED\") && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <h3 className=\"mb-2 text-sm font-semibold text-text-primary\">\n {submission?.status === \"REJECTED\"\n ? tr(\n \"devportal.storeSubmission.resubmitForReview\",\n \"Resubmit for review\",\n )\n : tr(\n \"devportal.storeSubmission.submitForReview\",\n \"Submit for review\",\n )}\n </h3>\n <p className=\"mb-3 text-sm text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.help\",\n \"Your application will be sent to the store's review queue. Whether it's auto-published or requires admin approval depends on the target store's configuration.\",\n )}\n </p>\n <label className=\"block\" htmlFor=\"store-submission-notes\">\n <span className=\"sr-only\">\n {tr(\n \"devportal.storeSubmission.notesLabel\",\n \"Notes for the reviewer (optional)\",\n )}\n </span>\n </label>\n <textarea\n id=\"store-submission-notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n rows={3}\n placeholder={tr(\n \"devportal.storeSubmission.notesLabel\",\n \"Notes for the reviewer (optional)\",\n )}\n className=\"mb-3 w-full rounded-md border border-border-default bg-surface-default px-3 py-2 text-sm text-text-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n />\n <button\n type=\"button\"\n onClick={() => void submit()}\n disabled={submitting || !submitPerm.allowed}\n aria-disabled={submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text hover:opacity-90 disabled:opacity-60 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting && (\n <RefreshCw\n className=\"h-4 w-4 animate-spin\"\n aria-hidden=\"true\"\n />\n )}\n {submission?.status === \"REJECTED\"\n ? tr(\"devportal.storeSubmission.resubmit\", \"Resubmit\")\n : tr(\n \"devportal.storeSubmission.submitForReview\",\n \"Submit for review\",\n )}\n </button>\n </div>\n )}\n\n {submission?.productId && (\n <div className=\"rounded-lg border border-border-default bg-surface-raised p-4\">\n <p className=\"text-xs font-medium text-text-secondary\">\n {tr(\n \"devportal.storeSubmission.storeProductId\",\n \"Store product ID\",\n )}\n </p>\n <code className=\"mt-1 block break-all font-mono text-xs text-text-primary\">\n {submission.productId}\n </code>\n </div>\n )}\n </div>\n )}\n </div>\n </main>\n );\n};\n"],"mappings":"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"}
@@ -4,216 +4,234 @@ import { PageLayout as n, PageSection as r } from "../components/PageLayout.js";
4
4
  import { StatCard as i, StatCardGrid as a } from "../components/StatCard.js";
5
5
  import { StatusBadge as o } from "../components/StatusBadge.js";
6
6
  import { nativeImpact as s, nativeNotify as c } from "../../utils/nativeBridge.js";
7
- import { SecretDisplay as l } from "../components/SecretDisplay.js";
8
- import { DataTable as u, DetailList as d } from "../components/DataTable.js";
9
- import { Alert as ee, ConfirmDialog as f } from "../components/ConfirmDialog.js";
10
- import { useDeleteWebhookMutation as p, useGetWebhookDetailQuery as m, useTestWebhookMutation as h, useUpdateWebhookMutation as g } from "../../generated/global-operations.js";
11
- import { DEVPORTAL_PERMISSIONS as _ } from "../constants/permissions.js";
12
- import { getErrorMessage as v } from "../hooks/useGraphQL.js";
13
- import { useDevportalPermission as y } from "../hooks/usePermission.js";
7
+ import { SecretDisplay as ee } from "../components/SecretDisplay.js";
8
+ import { DataTable as te, DetailList as l } from "../components/DataTable.js";
9
+ import { Alert as ne, ConfirmDialog as u } from "../components/ConfirmDialog.js";
10
+ import { useDeleteWebhookMutation as d, useGetApplicationQuery as f, useGetWebhookDetailQuery as p, useTestWebhookMutation as m, useUpdateWebhookMutation as h } from "../../generated/global-operations.js";
11
+ import { DEVPORTAL_PERMISSIONS as g } from "../constants/permissions.js";
12
+ import { getErrorMessage as _ } from "../hooks/useGraphQL.js";
13
+ import { useDevportalPermission as v } from "../hooks/usePermission.js";
14
14
  import "../hooks/index.js";
15
- import b from "../../node_modules/date-fns/format.js";
16
- import { useMemo as x, useState as S } from "react";
17
- import { useI18n as te } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
18
- import { AlertCircle as ne, CheckCircle as C, Clock as re, ExternalLink as ie, Loader2 as ae, Pause as oe, Play as se, Send as ce, Trash2 as w, Webhook as T, XCircle as E } from "lucide-react";
19
- import { useParams as D } from "react-router-dom";
20
- import { jsx as O, jsxs as k } from "react/jsx-runtime";
15
+ import y from "../../node_modules/date-fns/format.js";
16
+ import { useEffect as b, useMemo as x, useState as S } from "react";
17
+ import { useI18n as C } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
18
+ import { AlertCircle as w, CheckCircle as T, Clock as re, ExternalLink as ie, Loader2 as ae, Pause as oe, Play as se, Send as ce, Trash2 as le, Webhook as E, XCircle as D } from "lucide-react";
19
+ import { useParams as O } from "react-router-dom";
20
+ import { jsx as k, jsxs as A } from "react/jsx-runtime";
21
21
  //#region src/devportal/pages/WebhookDetailPage.tsx
22
- var A = (e) => e ? b(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
23
- let { appId: j, webhookId: M } = D(), { navigate: N, basePath: P } = e(), { t: F } = te(), I = (e, t) => {
24
- let n = F(e);
22
+ var j = (e) => e ? y(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", M = () => {
23
+ let { appId: M, webhookId: N } = O(), { navigate: P, basePath: F } = e(), { t: I } = C(), L = (e, t) => {
24
+ let n = I(e);
25
25
  return n === e ? t : n;
26
- }, { allowed: L } = y(_.WEBHOOK_UPDATE), { allowed: R } = y(_.WEBHOOK_DELETE), [z, B] = S(!1), [V, H] = S(!1), [U, W] = S(null), [G, K] = S(!1), { data: q, loading: le, error: J, refetch: Y } = m({
26
+ }, { allowed: R } = v(g.WEBHOOK_UPDATE), { allowed: z } = v(g.WEBHOOK_DELETE), [B, V] = S(!1), [H, U] = S(!1), [W, G] = S(null), [ue, K] = S(!1), { data: q } = f({
27
+ variables: { id: M ?? "" },
28
+ skip: !M,
29
+ fetchPolicy: "cache-first"
30
+ });
31
+ b(() => {
32
+ let e = q?.application?.name;
33
+ if (!M || !e) return;
34
+ let t = window.__breadcrumbRegistry;
35
+ return t?.register(M, e), () => t?.unregister(M);
36
+ }, [M, q?.application?.name]);
37
+ let { data: J, loading: de, error: Y, refetch: X } = p({
27
38
  variables: {
28
- id: M || "",
39
+ id: N || "",
29
40
  limit: 20,
30
41
  offset: 0
31
42
  },
32
- skip: !M,
43
+ skip: !N,
33
44
  fetchPolicy: "cache-and-network"
34
- }), [ue, { loading: de }] = g(), [fe, { loading: pe }] = p(), [me, { loading: he }] = h(), X = q?.webhook, Z = q?.webhookDeliveries?.edges?.map((e) => e.node) ?? [], Q = j || X?.applicationId, ge = x(() => {
35
- if (!X) return 0;
36
- let e = (X.successCount ?? 0) + (X.failureCount ?? 0);
37
- return e === 0 ? 100 : Math.round((X.successCount ?? 0) / e * 100);
38
- }, [X]), $ = (e) => {
39
- N?.(`${P}${e}`);
40
- }, _e = async () => {
41
- X && (await ue({ variables: {
42
- id: X.id,
43
- input: { isActive: !X.isActive }
44
- } }), await Y());
45
- }, ve = async () => {
46
- if (X) {
45
+ }), [fe, { loading: pe }] = h(), [me, { loading: he }] = d(), [ge, { loading: _e }] = m(), Z = J?.webhook;
46
+ b(() => {
47
+ let e = Z?.name;
48
+ if (!N || !e) return;
49
+ let t = window.__breadcrumbRegistry;
50
+ return t?.register(N, e), () => t?.unregister(N);
51
+ }, [N, Z?.name]);
52
+ let Q = J?.webhookDeliveries?.edges?.map((e) => e.node) ?? [], $ = M || Z?.applicationId, ve = x(() => {
53
+ if (!Z) return 0;
54
+ let e = (Z.successCount ?? 0) + (Z.failureCount ?? 0);
55
+ return e === 0 ? 100 : Math.round((Z.successCount ?? 0) / e * 100);
56
+ }, [Z]), ye = (e) => {
57
+ P?.(`${F}${e}`);
58
+ }, be = async () => {
59
+ Z && (await fe({ variables: {
60
+ id: Z.id,
61
+ input: { isActive: !Z.isActive }
62
+ } }), await X());
63
+ }, xe = async () => {
64
+ if (Z) {
47
65
  s("medium");
48
66
  try {
49
- await fe({ variables: { id: X.id } }), c("success"), $(`/apps/${X.applicationId}/webhooks`);
67
+ await me({ variables: { id: Z.id } }), c("success"), ye(`/apps/${Z.applicationId}/webhooks`);
50
68
  } catch {
51
69
  c("error");
52
70
  }
53
71
  }
54
- }, ye = async () => {
55
- if (!X) return;
56
- let e = (await me({ variables: {
57
- id: X.id,
58
- eventType: X.events[0] || "application.updated"
72
+ }, Se = async () => {
73
+ if (!Z) return;
74
+ let e = (await ge({ variables: {
75
+ id: Z.id,
76
+ eventType: Z.events[0] || "application.updated"
59
77
  } })).data?.testWebhook;
60
78
  if (!e) {
61
- K(!1), W("Test request did not return a response.");
79
+ K(!1), G("Test request did not return a response.");
62
80
  return;
63
81
  }
64
- K(e.success), W(e.success ? `Test delivery succeeded with HTTP ${e.statusCode ?? 200}.` : e.error || "Webhook test failed."), await Y();
82
+ K(e.success), G(e.success ? `Test delivery succeeded with HTTP ${e.statusCode ?? 200}.` : e.error || "Webhook test failed."), await X();
65
83
  };
66
- return le && !X ? /* @__PURE__ */ O(n, {
67
- title: I("devportal.webhook", "Webhook"),
68
- description: I("devportal.loadingWebhookDetails", "Loading webhook details"),
69
- backLink: Q ? `/apps/${Q}/webhooks` : "/webhooks",
70
- backLabel: I("devportal.backToWebhooks", "Back to Webhooks"),
71
- children: /* @__PURE__ */ O("div", {
84
+ return de && !Z ? /* @__PURE__ */ k(n, {
85
+ title: L("devportal.webhook", "Webhook"),
86
+ description: L("devportal.loadingWebhookDetails", "Loading webhook details"),
87
+ backLink: $ ? `/apps/${$}/webhooks` : "/webhooks",
88
+ backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
89
+ children: /* @__PURE__ */ k("div", {
72
90
  className: "flex items-center justify-center py-16 text-muted-foreground",
73
- children: /* @__PURE__ */ O(ae, { className: "h-8 w-8 animate-spin" })
91
+ children: /* @__PURE__ */ k(ae, { className: "h-8 w-8 animate-spin" })
74
92
  })
75
- }) : J || !X ? /* @__PURE__ */ O(n, {
76
- title: I("devportal.webhook", "Webhook"),
77
- description: I("devportal.webhookDetails", "Webhook details"),
78
- backLink: Q ? `/apps/${Q}/webhooks` : "/webhooks",
79
- backLabel: I("devportal.backToWebhooks", "Back to Webhooks"),
80
- children: /* @__PURE__ */ O(t, {
81
- icon: /* @__PURE__ */ O(ne, {
93
+ }) : Y || !Z ? /* @__PURE__ */ k(n, {
94
+ title: L("devportal.webhook", "Webhook"),
95
+ description: L("devportal.webhookDetails", "Webhook details"),
96
+ backLink: $ ? `/apps/${$}/webhooks` : "/webhooks",
97
+ backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
98
+ children: /* @__PURE__ */ k(t, {
99
+ icon: /* @__PURE__ */ k(w, {
82
100
  size: 32,
83
101
  className: "text-status-error-text"
84
102
  }),
85
- title: I("devportal.unableToLoadWebhook", "Unable to load webhook"),
86
- description: J ? v(J) : I("devportal.webhookNotFound", "Webhook not found")
103
+ title: L("devportal.unableToLoadWebhook", "Unable to load webhook"),
104
+ description: Y ? _(Y) : L("devportal.webhookNotFound", "Webhook not found")
87
105
  })
88
- }) : /* @__PURE__ */ k(n, {
89
- title: X.name,
90
- description: X.description || "Webhook configuration and delivery history",
91
- backLink: `/apps/${Q}/webhooks`,
92
- backLabel: I("devportal.backToWebhooks", "Back to Webhooks"),
93
- actions: /* @__PURE__ */ k("div", {
106
+ }) : /* @__PURE__ */ A(n, {
107
+ title: Z.name,
108
+ description: Z.description || "Webhook configuration and delivery history",
109
+ backLink: `/apps/${$}/webhooks`,
110
+ backLabel: L("devportal.backToWebhooks", "Back to Webhooks"),
111
+ actions: /* @__PURE__ */ A("div", {
94
112
  className: "flex flex-wrap gap-2",
95
113
  children: [
96
- /* @__PURE__ */ k("button", {
114
+ /* @__PURE__ */ A("button", {
97
115
  type: "button",
98
116
  onClick: () => {
99
- W(null), H(!0);
117
+ G(null), U(!0);
100
118
  },
101
119
  className: "inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent",
102
- children: [/* @__PURE__ */ O(ce, { size: 16 }), I("devportal.test", "Test")]
120
+ children: [/* @__PURE__ */ k(ce, { size: 16 }), L("devportal.test", "Test")]
103
121
  }),
104
- /* @__PURE__ */ k("button", {
122
+ /* @__PURE__ */ A("button", {
105
123
  type: "button",
106
- disabled: de || !L,
107
- "aria-disabled": !L,
108
- onClick: () => void _e(),
124
+ disabled: pe || !R,
125
+ "aria-disabled": !R,
126
+ onClick: () => void be(),
109
127
  className: "inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50",
110
- children: [X.isActive ? /* @__PURE__ */ O(oe, { size: 16 }) : /* @__PURE__ */ O(se, { size: 16 }), X.isActive ? I("devportal.pauseWebhook", "Pause") : I("devportal.resumeWebhook", "Resume")]
128
+ children: [Z.isActive ? /* @__PURE__ */ k(oe, { size: 16 }) : /* @__PURE__ */ k(se, { size: 16 }), Z.isActive ? L("devportal.pauseWebhook", "Pause") : L("devportal.resumeWebhook", "Resume")]
111
129
  }),
112
- /* @__PURE__ */ k("button", {
130
+ /* @__PURE__ */ A("button", {
113
131
  type: "button",
114
- onClick: () => B(!0),
115
- disabled: !R,
116
- "aria-disabled": !R,
132
+ onClick: () => V(!0),
133
+ disabled: !z,
134
+ "aria-disabled": !z,
117
135
  className: "inline-flex items-center gap-2 rounded-md border border-status-error-border px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle disabled:opacity-50",
118
- children: [/* @__PURE__ */ O(w, { size: 16 }), I("devportal.deleteWebhook", "Delete")]
136
+ children: [/* @__PURE__ */ k(le, { size: 16 }), L("devportal.deleteWebhook", "Delete")]
119
137
  })
120
138
  ]
121
139
  }),
122
140
  children: [
123
- /* @__PURE__ */ k(a, {
141
+ /* @__PURE__ */ A(a, {
124
142
  columns: 4,
125
143
  children: [
126
- /* @__PURE__ */ O(i, {
127
- title: I("devportal.successRate", "Success Rate"),
128
- value: `${ge}%`,
129
- icon: /* @__PURE__ */ O(C, { size: 20 })
144
+ /* @__PURE__ */ k(i, {
145
+ title: L("devportal.successRate", "Success Rate"),
146
+ value: `${ve}%`,
147
+ icon: /* @__PURE__ */ k(T, { size: 20 })
130
148
  }),
131
- /* @__PURE__ */ O(i, {
132
- title: I("devportal.successfulDeliveries", "Successful Deliveries"),
133
- value: (X.successCount ?? 0).toLocaleString(),
134
- icon: /* @__PURE__ */ O(C, { size: 20 })
149
+ /* @__PURE__ */ k(i, {
150
+ title: L("devportal.successfulDeliveries", "Successful Deliveries"),
151
+ value: (Z.successCount ?? 0).toLocaleString(),
152
+ icon: /* @__PURE__ */ k(T, { size: 20 })
135
153
  }),
136
- /* @__PURE__ */ O(i, {
137
- title: I("devportal.failedDeliveries", "Failed Deliveries"),
138
- value: (X.failureCount ?? 0).toLocaleString(),
139
- icon: /* @__PURE__ */ O(E, { size: 20 })
154
+ /* @__PURE__ */ k(i, {
155
+ title: L("devportal.failedDeliveries", "Failed Deliveries"),
156
+ value: (Z.failureCount ?? 0).toLocaleString(),
157
+ icon: /* @__PURE__ */ k(D, { size: 20 })
140
158
  }),
141
- /* @__PURE__ */ O(i, {
142
- title: I("devportal.lastTriggered", "Last Triggered"),
143
- value: X.lastTriggeredAt ? b(new Date(X.lastTriggeredAt), "MMM d, HH:mm") : I("devportal.never", "Never"),
144
- icon: /* @__PURE__ */ O(re, { size: 20 })
159
+ /* @__PURE__ */ k(i, {
160
+ title: L("devportal.lastTriggered", "Last Triggered"),
161
+ value: Z.lastTriggeredAt ? y(new Date(Z.lastTriggeredAt), "MMM d, HH:mm") : L("devportal.never", "Never"),
162
+ icon: /* @__PURE__ */ k(re, { size: 20 })
145
163
  })
146
164
  ]
147
165
  }),
148
- /* @__PURE__ */ O(r, {
149
- title: I("devportal.configuration", "Configuration"),
150
- children: /* @__PURE__ */ O(d, { items: [
166
+ /* @__PURE__ */ k(r, {
167
+ title: L("devportal.configuration", "Configuration"),
168
+ children: /* @__PURE__ */ k(l, { items: [
151
169
  {
152
- label: I("devportal.status", "Status"),
153
- value: /* @__PURE__ */ O(o, {
154
- status: X.status,
170
+ label: L("devportal.status", "Status"),
171
+ value: /* @__PURE__ */ k(o, {
172
+ status: Z.status,
155
173
  type: "webhook"
156
174
  })
157
175
  },
158
176
  {
159
- label: I("devportal.endpointUrl", "Endpoint URL"),
160
- value: /* @__PURE__ */ k("span", {
177
+ label: L("devportal.endpointUrl", "Endpoint URL"),
178
+ value: /* @__PURE__ */ A("span", {
161
179
  className: "flex flex-wrap items-center gap-2 font-mono text-sm",
162
- children: [/* @__PURE__ */ O("span", {
180
+ children: [/* @__PURE__ */ k("span", {
163
181
  className: "break-all",
164
- children: X.url
165
- }), /* @__PURE__ */ O("a", {
166
- href: X.url,
182
+ children: Z.url
183
+ }), /* @__PURE__ */ k("a", {
184
+ href: Z.url,
167
185
  target: "_blank",
168
186
  rel: "noopener noreferrer",
169
187
  className: "text-primary",
170
- children: /* @__PURE__ */ O(ie, { size: 14 })
188
+ children: /* @__PURE__ */ k(ie, { size: 14 })
171
189
  })]
172
190
  })
173
191
  },
174
192
  {
175
- label: I("devportal.signingSecret", "Signing Secret"),
176
- value: /* @__PURE__ */ O(l, {
177
- value: X.secret || "******",
193
+ label: L("devportal.signingSecret", "Signing Secret"),
194
+ value: /* @__PURE__ */ k(ee, {
195
+ value: Z.secret || "******",
178
196
  label: ""
179
197
  })
180
198
  },
181
199
  {
182
- label: I("devportal.subscribedEvents", "Subscribed Events"),
183
- value: /* @__PURE__ */ O("div", {
200
+ label: L("devportal.subscribedEvents", "Subscribed Events"),
201
+ value: /* @__PURE__ */ k("div", {
184
202
  className: "flex flex-wrap gap-1",
185
- children: X.events.map((e) => /* @__PURE__ */ O("code", {
203
+ children: Z.events.map((e) => /* @__PURE__ */ k("code", {
186
204
  className: "rounded bg-muted px-1.5 py-0.5 text-xs",
187
205
  children: e
188
206
  }, e))
189
207
  })
190
208
  },
191
209
  {
192
- label: I("devportal.retryPolicy", "Retry Policy"),
193
- value: X.retryEnabled ? I("devportal.retryPolicyEnabled", `Up to ${X.maxRetries ?? 0} retries`) : I("devportal.retriesDisabled", "Retries disabled")
210
+ label: L("devportal.retryPolicy", "Retry Policy"),
211
+ value: Z.retryEnabled ? L("devportal.retryPolicyEnabled", `Up to ${Z.maxRetries ?? 0} retries`) : L("devportal.retriesDisabled", "Retries disabled")
194
212
  },
195
213
  {
196
- label: I("devportal.created", "Created"),
197
- value: A(X.createdAt)
214
+ label: L("devportal.created", "Created"),
215
+ value: j(Z.createdAt)
198
216
  },
199
217
  {
200
- label: I("devportal.updated", "Updated"),
201
- value: A(X.updatedAt)
218
+ label: L("devportal.updated", "Updated"),
219
+ value: j(Z.updatedAt)
202
220
  }
203
221
  ] })
204
222
  }),
205
- /* @__PURE__ */ O(r, {
206
- title: I("devportal.recentDeliveries", "Recent Deliveries"),
207
- children: Z.length > 0 ? /* @__PURE__ */ O(u, {
208
- data: Z,
223
+ /* @__PURE__ */ k(r, {
224
+ title: L("devportal.recentDeliveries", "Recent Deliveries"),
225
+ children: Q.length > 0 ? /* @__PURE__ */ k(te, {
226
+ data: Q,
209
227
  keyField: "id",
210
228
  columns: [
211
229
  {
212
230
  key: "status",
213
- header: I("devportal.status", "Status"),
214
- render: (e) => /* @__PURE__ */ O("div", {
231
+ header: L("devportal.status", "Status"),
232
+ render: (e) => /* @__PURE__ */ k("div", {
215
233
  className: "flex items-center gap-2",
216
- children: /* @__PURE__ */ O(o, {
234
+ children: /* @__PURE__ */ k(o, {
217
235
  status: e.status,
218
236
  type: "delivery"
219
237
  })
@@ -221,63 +239,63 @@ var A = (e) => e ? b(new Date(e), "MMM d, yyyy HH:mm:ss") : "Never", j = () => {
221
239
  },
222
240
  {
223
241
  key: "eventType",
224
- header: I("devportal.event", "Event"),
225
- render: (e) => /* @__PURE__ */ O("code", {
242
+ header: L("devportal.event", "Event"),
243
+ render: (e) => /* @__PURE__ */ k("code", {
226
244
  className: "text-xs",
227
245
  children: e.eventType
228
246
  })
229
247
  },
230
248
  {
231
249
  key: "responseStatus",
232
- header: I("devportal.response", "Response"),
250
+ header: L("devportal.response", "Response"),
233
251
  render: (e) => e.responseStatus ?? "-"
234
252
  },
235
253
  {
236
254
  key: "attemptNumber",
237
- header: I("devportal.attempts", "Attempts"),
255
+ header: L("devportal.attempts", "Attempts"),
238
256
  render: (e) => e.attemptNumber
239
257
  },
240
258
  {
241
259
  key: "createdAt",
242
- header: I("devportal.created", "Created"),
243
- render: (e) => A(e.createdAt)
260
+ header: L("devportal.created", "Created"),
261
+ render: (e) => j(e.createdAt)
244
262
  }
245
263
  ]
246
- }) : /* @__PURE__ */ O(t, {
247
- icon: /* @__PURE__ */ O(T, { size: 24 }),
248
- title: I("devportal.noDeliveriesYet", "No deliveries yet"),
249
- description: I("devportal.noDeliveriesYetDescription", "Deliveries will appear here after the first matching event is sent to this endpoint.")
264
+ }) : /* @__PURE__ */ k(t, {
265
+ icon: /* @__PURE__ */ k(E, { size: 24 }),
266
+ title: L("devportal.noDeliveriesYet", "No deliveries yet"),
267
+ description: L("devportal.noDeliveriesYetDescription", "Deliveries will appear here after the first matching event is sent to this endpoint.")
250
268
  })
251
269
  }),
252
- /* @__PURE__ */ O(f, {
253
- open: z,
254
- onOpenChange: B,
255
- onConfirm: () => void ve(),
256
- loading: pe,
257
- title: I("devportal.deleteWebhookTitle", "Delete webhook"),
258
- description: I("devportal.deleteWebhookDescription", "Deleting this webhook stops all future deliveries for this endpoint."),
259
- confirmLabel: I("devportal.deleteWebhookConfirm", "Delete webhook"),
270
+ /* @__PURE__ */ k(u, {
271
+ open: B,
272
+ onOpenChange: V,
273
+ onConfirm: () => void xe(),
274
+ loading: he,
275
+ title: L("devportal.deleteWebhookTitle", "Delete webhook"),
276
+ description: L("devportal.deleteWebhookDescription", "Deleting this webhook stops all future deliveries for this endpoint."),
277
+ confirmLabel: L("devportal.deleteWebhookConfirm", "Delete webhook"),
260
278
  variant: "danger"
261
279
  }),
262
- /* @__PURE__ */ O(f, {
263
- open: V,
280
+ /* @__PURE__ */ k(u, {
281
+ open: H,
264
282
  onOpenChange: (e) => {
265
- H(e), e || W(null);
283
+ U(e), e || G(null);
266
284
  },
267
- onConfirm: () => void ye(),
268
- loading: he,
269
- title: I("devportal.sendTestDelivery", "Send test delivery"),
270
- description: I("devportal.sendTestDeliveryDescription", "A signed test event will be sent to the configured endpoint through the public gateway."),
271
- confirmLabel: I("devportal.sendTestEvent", "Send test event"),
272
- children: U && /* @__PURE__ */ O(ee, {
273
- variant: G ? "success" : "error",
274
- children: U
285
+ onConfirm: () => void Se(),
286
+ loading: _e,
287
+ title: L("devportal.sendTestDelivery", "Send test delivery"),
288
+ description: L("devportal.sendTestDeliveryDescription", "A signed test event will be sent to the configured endpoint through the public gateway."),
289
+ confirmLabel: L("devportal.sendTestEvent", "Send test event"),
290
+ children: W && /* @__PURE__ */ k(ne, {
291
+ variant: ue ? "success" : "error",
292
+ children: W
275
293
  })
276
294
  })
277
295
  ]
278
296
  });
279
297
  };
280
298
  //#endregion
281
- export { j as WebhookDetailPage };
299
+ export { M as WebhookDetailPage };
282
300
 
283
301
  //# sourceMappingURL=WebhookDetailPage.js.map