@burdenoff/microfe-devportal 2026.609.4 → 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.
- package/dist/devportal/DevportalRoot.js +6 -1
- package/dist/devportal/DevportalRoot.js.map +1 -1
- package/dist/devportal/DevportalRoutes.js +169 -158
- package/dist/devportal/DevportalRoutes.js.map +1 -1
- package/dist/devportal/hooks/usePackageUpload.js +120 -0
- package/dist/devportal/hooks/usePackageUpload.js.map +1 -0
- package/dist/devportal/pages/AnalyticsDashboardPage.js +73 -62
- package/dist/devportal/pages/AnalyticsDashboardPage.js.map +1 -1
- package/dist/devportal/pages/AppLogsPage.js +89 -82
- package/dist/devportal/pages/AppLogsPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationDetailPage.js +948 -367
- package/dist/devportal/pages/ApplicationDetailPage.js.map +1 -1
- package/dist/devportal/pages/ApplicationVersionsPage.js +56 -45
- package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
- package/dist/devportal/pages/CreateApiKeyPage.js +30 -32
- package/dist/devportal/pages/CreateApiKeyPage.js.map +1 -1
- package/dist/devportal/pages/CreateApplicationPage.js +8 -3
- package/dist/devportal/pages/CreateApplicationPage.js.map +1 -1
- package/dist/devportal/pages/CreateOAuthClientPage.js +4 -4
- package/dist/devportal/pages/CreateOAuthClientPage.js.map +1 -1
- package/dist/devportal/pages/CreateOrganizationPage.js +233 -228
- package/dist/devportal/pages/CreateOrganizationPage.js.map +1 -1
- package/dist/devportal/pages/CreateWebhookPage.js +159 -148
- package/dist/devportal/pages/CreateWebhookPage.js.map +1 -1
- package/dist/devportal/pages/DelegationsPage.js +1 -1
- package/dist/devportal/pages/DelegationsPage.js.map +1 -1
- package/dist/devportal/pages/EditApplicationPage.js +25 -17
- package/dist/devportal/pages/EditApplicationPage.js.map +1 -1
- package/dist/devportal/pages/ListingPreviewPage.js +159 -153
- package/dist/devportal/pages/ListingPreviewPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientDetailPage.js.map +1 -1
- package/dist/devportal/pages/OAuthClientsPage.js +2 -2
- package/dist/devportal/pages/OAuthClientsPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationDetailPage.js +158 -153
- package/dist/devportal/pages/OrganizationDetailPage.js.map +1 -1
- package/dist/devportal/pages/OrganizationMembersPage.js +223 -212
- package/dist/devportal/pages/OrganizationMembersPage.js.map +1 -1
- package/dist/devportal/pages/PublishPage.js +172 -165
- package/dist/devportal/pages/PublishPage.js.map +1 -1
- package/dist/devportal/pages/ResourcesPage.js.map +1 -1
- package/dist/devportal/pages/RevenueDashboardPage.js +405 -0
- package/dist/devportal/pages/RevenueDashboardPage.js.map +1 -0
- package/dist/devportal/pages/SetupPage.js +186 -181
- package/dist/devportal/pages/SetupPage.js.map +1 -1
- package/dist/devportal/pages/StoreSubmissionPage.js +76 -97
- package/dist/devportal/pages/StoreSubmissionPage.js.map +1 -1
- package/dist/devportal/pages/WebhookDetailPage.js +172 -154
- package/dist/devportal/pages/WebhookDetailPage.js.map +1 -1
- package/dist/devportal/pages/WebhooksPage.js +218 -200
- package/dist/devportal/pages/WebhooksPage.js.map +1 -1
- package/dist/devportal/providers/DevportalProvider.js +16 -13
- package/dist/devportal/providers/DevportalProvider.js.map +1 -1
- package/dist/devportal/types/index.js.map +1 -1
- package/dist/generated/global-operations.js +310 -225
- package/dist/generated/global-operations.js.map +1 -1
- package/package.json +1 -1
- package/dist/devportal/pages/RevenueRedirectPage.js +0 -14
- package/dist/devportal/pages/RevenueRedirectPage.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SetupPage.js","names":[],"sources":["../../../src/devportal/pages/SetupPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n ArrowRight,\n Building2,\n AppWindow,\n Rocket,\n Check,\n Key,\n BookOpen,\n ChevronRight,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n} from \"../components/FormField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useDevportalEventBus } from \"../events\";\nimport type { AppType } from \"../types\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useCreateOrganizationMutation,\n useCreateApplicationMutation,\n} from \"../../generated/global-operations\";\n\ntype SetupStep = \"org\" | \"app\" | \"done\";\n\nconst APP_TYPE_OPTIONS = [\n { value: \"\", label: \"Select type…\" },\n ...Object.entries(APP_TYPE_LABELS).map(([value, label]) => ({\n value,\n label,\n })),\n];\n\nconst CATEGORY_OPTIONS = [\n { value: \"\", label: \"Select category…\" },\n { value: \"productivity\", label: \"Productivity\" },\n { value: \"communication\", label: \"Communication\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"automation\", label: \"Automation\" },\n { value: \"developer-tools\", label: \"Developer Tools\" },\n { value: \"finance\", label: \"Finance\" },\n { value: \"hr\", label: \"HR & People\" },\n { value: \"marketing\", label: \"Marketing\" },\n { value: \"project-management\", label: \"Project Management\" },\n { value: \"security\", label: \"Security\" },\n { value: \"support\", label: \"Support\" },\n { value: \"other\", label: \"Other\" },\n];\n\nfunction generateSlug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/** Mark that the user has interacted with setup so the dashboard gate won't redirect again. */\nfunction markSetupSeen() {\n try {\n localStorage.setItem(\"devportal_setup_dismissed\", \"1\");\n } catch {\n // localStorage unavailable — not critical\n }\n}\n\n// ─── Step indicator ────────────────────────────────────────────────────────\n\nconst STEPS: { key: SetupStep; label: string }[] = [\n { key: \"org\", label: \"Organization\" },\n { key: \"app\", label: \"First app\" },\n { key: \"done\", label: \"Done\" },\n];\n\nconst StepIndicator: FC<{ current: SetupStep }> = ({ current }) => {\n const currentIdx = STEPS.findIndex((s) => s.key === current);\n return (\n <div className=\"flex items-center gap-0\">\n {STEPS.map((step, idx) => {\n const isCompleted = idx < currentIdx;\n const isActive = idx === currentIdx;\n return (\n <div key={step.key} className=\"flex items-center\">\n <div className=\"flex flex-col items-center gap-1.5\">\n <div\n className={[\n \"flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold transition-colors\",\n isCompleted\n ? \"bg-primary text-primary-foreground\"\n : isActive\n ? \"bg-primary text-primary-foreground ring-4 ring-primary/20\"\n : \"bg-muted text-muted-foreground\",\n ].join(\" \")}\n >\n {isCompleted ? <Check size={14} /> : idx + 1}\n </div>\n <span\n className={[\n \"text-xs font-medium whitespace-nowrap\",\n isActive ? \"text-foreground\" : \"text-muted-foreground\",\n ].join(\" \")}\n >\n {step.label}\n </span>\n </div>\n {idx < STEPS.length - 1 && (\n <div\n className={[\n \"mx-3 mb-5 h-px w-16 flex-shrink-0 transition-colors\",\n idx < currentIdx ? \"bg-primary\" : \"bg-border\",\n ].join(\" \")}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n};\n\n// ─── Main component ────────────────────────────────────────────────────────\n\nexport const SetupPage: FC = () => {\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const bus = useDevportalEventBus();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const handleNavigate = (path: string) => navigate?.(`${basePath}${path}`);\n\n const [step, setStep] = useState<SetupStep>(\"org\");\n\n // IDs created during wizard — carried forward for success CTAs\n const [createdOrgId, setCreatedOrgId] = useState<string | null>(null);\n const [createdAppId, setCreatedAppId] = useState<string | null>(null);\n\n // ── Step 1: org ──────────────────────────────────────────────\n const [orgName, setOrgName] = useState(\"\");\n const [orgSlug, setOrgSlug] = useState(\"\");\n const [orgDescription, setOrgDescription] = useState(\"\");\n const [orgErrors, setOrgErrors] = useState<{ name?: string; slug?: string }>(\n {},\n );\n\n const [createOrg, { loading: creatingOrg }] = useCreateOrganizationMutation();\n\n const validateOrg = () => {\n const errs: { name?: string; slug?: string } = {};\n if (!orgName.trim())\n errs.name = tr(\n \"devportal.orgNameRequired\",\n \"Organization name is required\",\n );\n else if (orgName.length < 2)\n errs.name = tr(\n \"devportal.orgNameTooShort\",\n \"Name must be at least 2 characters\",\n );\n if (!orgSlug.trim())\n errs.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n else if (!/^[a-z0-9-]+$/.test(orgSlug))\n errs.slug = tr(\n \"devportal.slugInvalid\",\n \"Lowercase letters, numbers, and hyphens only\",\n );\n setOrgErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleOrgSubmit = async () => {\n if (!validateOrg()) return;\n try {\n const result = await createOrg({\n variables: {\n input: {\n name: orgName,\n slug: orgSlug || undefined,\n description: orgDescription || undefined,\n },\n },\n });\n const id = result.data?.createDeveloperOrganization?.id;\n if (id) {\n bus.emit(\"devportal.org.created\", {\n organizationId: id,\n name: orgName,\n });\n setCreatedOrgId(id);\n setStep(\"app\");\n }\n } catch {\n // error surfaced via Apollo cache; leave the form open\n }\n };\n\n // ── Step 2: app ──────────────────────────────────────────────\n const [appName, setAppName] = useState(\"\");\n const [appSlug, setAppSlug] = useState(\"\");\n const [appType, setAppType] = useState<AppType | \"\">(\"\");\n const [appCategory, setAppCategory] = useState(\"\");\n const [appShortDesc, setAppShortDesc] = useState(\"\");\n const [appErrors, setAppErrors] = useState<{\n name?: string;\n appType?: string;\n category?: string;\n shortDescription?: string;\n }>({});\n\n const [createApp, { loading: creatingApp }] = useCreateApplicationMutation();\n\n const validateApp = () => {\n const errs: typeof appErrors = {};\n if (!appName.trim())\n errs.name = tr(\n \"devportal.appNameRequired\",\n \"Application name is required\",\n );\n else if (appName.length < 3)\n errs.name = tr(\n \"devportal.nameTooShort\",\n \"Name must be at least 3 characters\",\n );\n if (!appType)\n errs.appType = tr(\n \"devportal.appTypeRequired\",\n \"Application type is required\",\n );\n if (!appCategory)\n errs.category = tr(\"devportal.categoryRequired\", \"Category is required\");\n if (!appShortDesc.trim())\n errs.shortDescription = tr(\n \"devportal.shortDescriptionRequired\",\n \"Short description is required\",\n );\n setAppErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleAppSubmit = async () => {\n if (!validateApp()) return;\n try {\n const result = await createApp({\n variables: {\n input: {\n name: appName,\n slug: appSlug || undefined,\n appType: appType as AppType,\n category: appCategory || undefined,\n shortDescription: appShortDesc || undefined,\n visibility: \"PRIVATE\",\n developerOrganizationId: createdOrgId || undefined,\n },\n },\n });\n const id = result.data?.createApplication?.id;\n if (id) {\n bus.emit(\"devportal.app.created\", {\n appId: id,\n name: appName,\n appType,\n organizationId: createdOrgId,\n });\n setCreatedAppId(id);\n markSetupSeen();\n setStep(\"done\");\n }\n } catch {\n // error surfaced via Apollo cache\n }\n };\n\n const handleSkip = () => {\n markSetupSeen();\n handleNavigate(\"/\");\n };\n\n // ─── Render ─────────────────────────────────────────────────\n\n return (\n <main className=\"min-h-screen bg-surface-default\">\n {/* Header */}\n <div className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-2xl px-6 py-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Rocket size={20} />\n </div>\n <div>\n <p className=\"text-xs font-medium text-muted-foreground\">\n {tr(\"devportal.developerPortal\", \"Developer Portal\")}\n </p>\n <h1 className=\"text-base font-semibold text-foreground\">\n {tr(\"devportal.setup.title\", \"Get set up\")}\n </h1>\n </div>\n </div>\n {step !== \"done\" && (\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"mx-auto max-w-2xl px-6 py-10\">\n {/* Step indicator */}\n <div className=\"mb-10 flex justify-center\">\n <StepIndicator current={step} />\n </div>\n\n {/* ── Step 1: Organization ─────────────────────── */}\n {step === \"org\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Building2 size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr(\"devportal.setup.orgTitle\", \"Set up your organization\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\n \"devportal.setup.orgSubtitle\",\n \"This groups your apps and teams under one publisher identity.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.organizationName\", \"Organization Name\")}\n value={orgName}\n onChange={(e) => {\n setOrgName(e.target.value);\n if (!orgSlug || orgSlug === generateSlug(orgName)) {\n setOrgSlug(generateSlug(e.target.value));\n }\n setOrgErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.organizationNamePlaceholder\",\n \"Acme Development\",\n )}\n required\n error={orgErrors.name}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={orgSlug}\n onChange={(e) => {\n setOrgSlug(e.target.value.toLowerCase());\n setOrgErrors((p) => ({ ...p, slug: undefined }));\n }}\n placeholder=\"acme-dev\"\n required\n error={orgErrors.slug}\n hint={tr(\n \"devportal.slugHint\",\n \"URL-friendly identifier — auto-generated from name\",\n )}\n />\n\n <TextareaField\n label={tr(\"devportal.description\", \"Description\")}\n value={orgDescription}\n onChange={(e) => setOrgDescription(e.target.value)}\n placeholder={tr(\n \"devportal.orgDescriptionPlaceholder\",\n \"Tell us about your organization…\",\n )}\n rows={2}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleOrgSubmit()}\n disabled={creatingOrg}\n className=\"inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-60 transition-colors\"\n >\n {creatingOrg ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createAndContinue\", \"Create & Continue\")}\n {!creatingOrg && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 2: First app ─────────────────────── */}\n {step === \"app\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <AppWindow size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr(\"devportal.setup.appTitle\", \"Create your first app\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\n \"devportal.setup.appSubtitle\",\n \"Register the app you want to publish or integrate.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.applicationName\", \"Application Name\")}\n value={appName}\n onChange={(e) => {\n setAppName(e.target.value);\n if (!appSlug || appSlug === generateSlug(appName)) {\n setAppSlug(generateSlug(e.target.value));\n }\n setAppErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.applicationNamePlaceholder\",\n \"My Awesome App\",\n )}\n required\n error={appErrors.name}\n />\n\n <div className=\"grid grid-cols-2 gap-4\">\n <SelectField\n label={tr(\"devportal.applicationType\", \"Application Type\")}\n value={appType}\n onChange={(e) => {\n setAppType(e.target.value as AppType);\n setAppErrors((p) => ({ ...p, appType: undefined }));\n }}\n options={APP_TYPE_OPTIONS}\n required\n error={appErrors.appType}\n />\n <SelectField\n label={tr(\"devportal.category\", \"Category\")}\n value={appCategory}\n onChange={(e) => {\n setAppCategory(e.target.value);\n setAppErrors((p) => ({ ...p, category: undefined }));\n }}\n options={CATEGORY_OPTIONS}\n required\n error={appErrors.category}\n />\n </div>\n\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={appShortDesc}\n onChange={(e) => {\n setAppShortDesc(e.target.value);\n setAppErrors((p) => ({ ...p, shortDescription: undefined }));\n }}\n placeholder={tr(\n \"devportal.shortDescriptionPlaceholder\",\n \"A brief description of what your app does\",\n )}\n required\n error={appErrors.shortDescription}\n rows={2}\n hint={`${appShortDesc.length}/200`}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleAppSubmit()}\n disabled={creatingApp}\n className=\"inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-60 transition-colors\"\n >\n {creatingApp ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createApp\", \"Create App\")}\n {!creatingApp && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 3: Done ─────────────────────────── */}\n {step === \"done\" && (\n <div className=\"text-center\">\n <div className=\"mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10 text-primary\">\n <Rocket size={32} />\n </div>\n <h2 className=\"text-2xl font-bold text-foreground\">\n {tr(\"devportal.setup.doneTitle\", \"You're all set!\")}\n </h2>\n <p className=\"mt-2 text-muted-foreground\">\n {tr(\n \"devportal.setup.doneSubtitle\",\n \"Your organization and first app are ready. Here's what to do next.\",\n )}\n </p>\n\n <div className=\"mt-8 grid gap-3 sm:grid-cols-2\">\n {createdAppId && (\n <NextStepCard\n icon={<AppWindow size={20} />}\n title={tr(\"devportal.setup.viewApp\", \"View your app\")}\n description={tr(\n \"devportal.setup.viewAppDesc\",\n \"Configure OAuth, webhooks, and versioning\",\n )}\n onClick={() => handleNavigate(`/apps/${createdAppId}`)}\n primary\n />\n )}\n <NextStepCard\n icon={<Key size={20} />}\n title={tr(\"devportal.setup.generateApiKey\", \"Generate API key\")}\n description={tr(\n \"devportal.setup.generateApiKeyDesc\",\n \"Create credentials to start calling APIs\",\n )}\n onClick={() => handleNavigate(\"/api-keys/new\")}\n />\n <NextStepCard\n icon={<BookOpen size={20} />}\n title={tr(\"devportal.setup.browseDocs\", \"Browse docs\")}\n description={tr(\n \"devportal.setup.browseDocsDesc\",\n \"Learn about publishing, SDKs, and webhooks\",\n )}\n onClick={() => handleNavigate(\"/docs\")}\n />\n {createdOrgId && (\n <NextStepCard\n icon={<Building2 size={20} />}\n title={tr(\"devportal.setup.inviteTeam\", \"Invite your team\")}\n description={tr(\n \"devportal.setup.inviteTeamDesc\",\n \"Add members to collaborate on your apps\",\n )}\n onClick={() =>\n handleNavigate(`/organizations/${createdOrgId}/members`)\n }\n />\n )}\n </div>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/\")}\n className=\"mt-8 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.goToDashboard\", \"Go to dashboard\")}\n <ArrowRight size={14} />\n </button>\n </div>\n )}\n </div>\n </main>\n );\n};\n\n// ─── Next-step card ────────────────────────────────────────────────────────\n\nconst NextStepCard: FC<{\n icon: React.ReactNode;\n title: string;\n description: string;\n onClick: () => void;\n primary?: boolean;\n}> = ({ icon, title, description, onClick, primary }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={[\n \"flex items-start gap-4 rounded-xl border p-5 text-left transition-colors\",\n primary\n ? \"border-primary bg-primary/5 hover:bg-primary/10\"\n : \"border-border-default bg-surface-raised hover:bg-surface-hover\",\n ].join(\" \")}\n >\n <div\n className={[\n \"flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg\",\n primary\n ? \"bg-primary/20 text-primary\"\n : \"bg-muted text-muted-foreground\",\n ].join(\" \")}\n >\n {icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-semibold text-foreground\">{title}</p>\n <p className=\"mt-0.5 text-sm text-muted-foreground\">{description}</p>\n </div>\n <ChevronRight\n size={16}\n className=\"mt-0.5 flex-shrink-0 text-muted-foreground\"\n />\n </button>\n);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SetupPage.js","names":[],"sources":["../../../src/devportal/pages/SetupPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n ArrowRight,\n Building2,\n AppWindow,\n Rocket,\n Check,\n Key,\n BookOpen,\n ChevronRight,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n InputField,\n TextareaField,\n SelectField,\n} from \"../components/FormField\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useDevportalEventBus } from \"../events\";\nimport type { AppType } from \"../types\";\nimport { APP_TYPE_LABELS } from \"../utils/constants\";\nimport {\n useCreateOrganizationMutation,\n useCreateApplicationMutation,\n} from \"../../generated/global-operations\";\nimport { useCreateBillingAccountMutation } from \"../hooks\";\n\ntype SetupStep = \"org\" | \"app\" | \"done\";\n\nconst APP_TYPE_OPTIONS = Object.entries(APP_TYPE_LABELS).map(\n ([value, label]) => ({\n value,\n label,\n }),\n);\n\nconst CATEGORY_OPTIONS = [\n { value: \"productivity\", label: \"Productivity\" },\n { value: \"communication\", label: \"Communication\" },\n { value: \"analytics\", label: \"Analytics\" },\n { value: \"automation\", label: \"Automation\" },\n { value: \"developer-tools\", label: \"Developer Tools\" },\n { value: \"finance\", label: \"Finance\" },\n { value: \"hr\", label: \"HR & People\" },\n { value: \"marketing\", label: \"Marketing\" },\n { value: \"project-management\", label: \"Project Management\" },\n { value: \"security\", label: \"Security\" },\n { value: \"support\", label: \"Support\" },\n { value: \"other\", label: \"Other\" },\n];\n\nfunction generateSlug(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/^-|-$/g, \"\");\n}\n\n/** Mark that the user has interacted with setup so the dashboard gate won't redirect again. */\nfunction markSetupSeen() {\n try {\n localStorage.setItem(\"devportal_setup_dismissed\", \"1\");\n } catch {\n // localStorage unavailable — not critical\n }\n}\n\n// ─── Step indicator ────────────────────────────────────────────────────────\n\nconst STEPS: { key: SetupStep; label: string }[] = [\n { key: \"org\", label: \"Organization\" },\n { key: \"app\", label: \"First app\" },\n { key: \"done\", label: \"Done\" },\n];\n\nconst StepIndicator: FC<{ current: SetupStep }> = ({ current }) => {\n const currentIdx = STEPS.findIndex((s) => s.key === current);\n return (\n <div className=\"flex items-center gap-0\">\n {STEPS.map((step, idx) => {\n const isCompleted = idx < currentIdx;\n const isActive = idx === currentIdx;\n return (\n <div key={step.key} className=\"flex items-center\">\n <div className=\"flex flex-col items-center gap-1.5\">\n <div\n className={[\n \"flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold transition-colors\",\n isCompleted\n ? \"bg-primary text-primary-foreground\"\n : isActive\n ? \"bg-primary text-primary-foreground ring-4 ring-primary/20\"\n : \"bg-muted text-muted-foreground\",\n ].join(\" \")}\n >\n {isCompleted ? <Check size={14} /> : idx + 1}\n </div>\n <span\n className={[\n \"text-xs font-medium whitespace-nowrap\",\n isActive ? \"text-foreground\" : \"text-muted-foreground\",\n ].join(\" \")}\n >\n {step.label}\n </span>\n </div>\n {idx < STEPS.length - 1 && (\n <div\n className={[\n \"mx-3 mb-5 h-px w-16 flex-shrink-0 transition-colors\",\n idx < currentIdx ? \"bg-primary\" : \"bg-border\",\n ].join(\" \")}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n};\n\n// ─── Main component ────────────────────────────────────────────────────────\n\nexport const SetupPage: FC = () => {\n const { navigate, basePath, currentUser } = useDevportal();\n const { t } = useI18n();\n const bus = useDevportalEventBus();\n const tr = (key: string, fallback: string): string => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n\n const handleNavigate = (path: string) => navigate?.(`${basePath}${path}`);\n\n const [step, setStep] = useState<SetupStep>(\"org\");\n\n // IDs created during wizard — carried forward for success CTAs\n const [createdOrgId, setCreatedOrgId] = useState<string | null>(null);\n const [createdAppId, setCreatedAppId] = useState<string | null>(null);\n\n // ── Step 1: org ──────────────────────────────────────────────\n const [orgName, setOrgName] = useState(\"\");\n const [orgSlug, setOrgSlug] = useState(\"\");\n const [orgDescription, setOrgDescription] = useState(\"\");\n const [orgErrors, setOrgErrors] = useState<{ name?: string; slug?: string }>(\n {},\n );\n\n const [createOrg, { loading: creatingOrg }] = useCreateOrganizationMutation();\n const [createBillingAccountMutation] = useCreateBillingAccountMutation();\n\n const validateOrg = () => {\n const errs: { name?: string; slug?: string } = {};\n if (!orgName.trim())\n errs.name = tr(\n \"devportal.orgNameRequired\",\n \"Organization name is required\",\n );\n else if (orgName.length < 2)\n errs.name = tr(\n \"devportal.orgNameTooShort\",\n \"Name must be at least 2 characters\",\n );\n if (!orgSlug.trim())\n errs.slug = tr(\"devportal.slugRequired\", \"Slug is required\");\n else if (!/^[a-z0-9-]+$/.test(orgSlug))\n errs.slug = tr(\n \"devportal.slugInvalid\",\n \"Lowercase letters, numbers, and hyphens only\",\n );\n setOrgErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleOrgSubmit = async () => {\n if (!validateOrg()) return;\n try {\n const result = await createOrg({\n variables: {\n input: {\n name: orgName,\n slug: orgSlug || undefined,\n description: orgDescription || undefined,\n },\n },\n });\n const id = result.data?.createDeveloperOrganization?.id;\n if (id) {\n bus.emit(\"devportal.org.created\", {\n organizationId: id,\n name: orgName,\n });\n setCreatedOrgId(id);\n // Fire-and-forget: create a billing account for the new org\n try {\n createBillingAccountMutation({\n variables: {\n input: {\n name: orgName,\n email: currentUser?.email ?? \"\",\n },\n },\n }).catch(() => {});\n } catch {\n // silent failure — billing account creation is non-blocking\n }\n setStep(\"app\");\n }\n } catch {\n // error surfaced via Apollo cache; leave the form open\n }\n };\n\n // ── Step 2: app ──────────────────────────────────────────────\n const [appName, setAppName] = useState(\"\");\n const [appSlug, setAppSlug] = useState(\"\");\n const [appType, setAppType] = useState<AppType | \"\">(\"\");\n const [appCategory, setAppCategory] = useState(\"\");\n const [appShortDesc, setAppShortDesc] = useState(\"\");\n const [appErrors, setAppErrors] = useState<{\n name?: string;\n appType?: string;\n category?: string;\n shortDescription?: string;\n }>({});\n\n const [createApp, { loading: creatingApp }] = useCreateApplicationMutation();\n\n const validateApp = () => {\n const errs: typeof appErrors = {};\n if (!appName.trim())\n errs.name = tr(\n \"devportal.appNameRequired\",\n \"Application name is required\",\n );\n else if (appName.length < 3)\n errs.name = tr(\n \"devportal.nameTooShort\",\n \"Name must be at least 3 characters\",\n );\n if (!appType)\n errs.appType = tr(\n \"devportal.appTypeRequired\",\n \"Application type is required\",\n );\n if (!appCategory)\n errs.category = tr(\"devportal.categoryRequired\", \"Category is required\");\n if (!appShortDesc.trim())\n errs.shortDescription = tr(\n \"devportal.shortDescriptionRequired\",\n \"Short description is required\",\n );\n setAppErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleAppSubmit = async () => {\n if (!validateApp()) return;\n try {\n const result = await createApp({\n variables: {\n input: {\n name: appName,\n slug: appSlug || undefined,\n appType: appType as AppType,\n category: appCategory || undefined,\n shortDescription: appShortDesc || undefined,\n visibility: \"PRIVATE\",\n developerOrganizationId: createdOrgId || undefined,\n },\n },\n });\n const id = result.data?.createApplication?.id;\n if (id) {\n bus.emit(\"devportal.app.created\", {\n appId: id,\n name: appName,\n appType,\n organizationId: createdOrgId,\n });\n setCreatedAppId(id);\n markSetupSeen();\n setStep(\"done\");\n }\n } catch {\n // error surfaced via Apollo cache\n }\n };\n\n const handleSkip = () => {\n markSetupSeen();\n handleNavigate(\"/\");\n };\n\n // ─── Render ─────────────────────────────────────────────────\n\n return (\n <main className=\"min-h-screen bg-surface-default\">\n {/* Header */}\n <div className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-2xl px-6 py-5\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex h-9 w-9 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Rocket size={20} />\n </div>\n <div>\n <p className=\"text-xs font-medium text-muted-foreground\">\n {tr(\"devportal.developerPortal\", \"Developer Portal\")}\n </p>\n <h1 className=\"text-base font-semibold text-foreground\">\n {tr(\"devportal.setup.title\", \"Get set up\")}\n </h1>\n </div>\n </div>\n {step !== \"done\" && (\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n )}\n </div>\n </div>\n </div>\n\n {/* Content */}\n <div className=\"mx-auto max-w-2xl px-6 py-10\">\n {/* Step indicator */}\n <div className=\"mb-10 flex justify-center\">\n <StepIndicator current={step} />\n </div>\n\n {/* ── Step 1: Organization ─────────────────────── */}\n {step === \"org\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Building2 size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr(\"devportal.setup.orgTitle\", \"Set up your organization\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\n \"devportal.setup.orgSubtitle\",\n \"This groups your apps and teams under one publisher identity.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.organizationName\", \"Organization Name\")}\n value={orgName}\n onChange={(e) => {\n setOrgName(e.target.value);\n if (!orgSlug || orgSlug === generateSlug(orgName)) {\n setOrgSlug(generateSlug(e.target.value));\n }\n setOrgErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.organizationNamePlaceholder\",\n \"Acme Development\",\n )}\n required\n error={orgErrors.name}\n />\n\n <InputField\n label={tr(\"devportal.slug\", \"Slug\")}\n value={orgSlug}\n onChange={(e) => {\n setOrgSlug(e.target.value.toLowerCase());\n setOrgErrors((p) => ({ ...p, slug: undefined }));\n }}\n placeholder=\"acme-dev\"\n required\n error={orgErrors.slug}\n hint={tr(\n \"devportal.slugHint\",\n \"URL-friendly identifier — auto-generated from name\",\n )}\n />\n\n <TextareaField\n label={tr(\"devportal.description\", \"Description\")}\n value={orgDescription}\n onChange={(e) => setOrgDescription(e.target.value)}\n placeholder={tr(\n \"devportal.orgDescriptionPlaceholder\",\n \"Tell us about your organization…\",\n )}\n rows={2}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleOrgSubmit()}\n disabled={creatingOrg}\n className=\"inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-60 transition-colors\"\n >\n {creatingOrg ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createAndContinue\", \"Create & Continue\")}\n {!creatingOrg && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 2: First app ─────────────────────── */}\n {step === \"app\" && (\n <div className=\"rounded-xl border border-border-default bg-surface-raised p-8 shadow-sm\">\n <div className=\"mb-6 flex items-center gap-3\">\n <div className=\"flex h-10 w-10 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <AppWindow size={20} />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold text-foreground\">\n {tr(\"devportal.setup.appTitle\", \"Create your first app\")}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {tr(\n \"devportal.setup.appSubtitle\",\n \"Register the app you want to publish or integrate.\",\n )}\n </p>\n </div>\n </div>\n\n <div className=\"space-y-5\">\n <InputField\n label={tr(\"devportal.applicationName\", \"Application Name\")}\n value={appName}\n onChange={(e) => {\n setAppName(e.target.value);\n if (!appSlug || appSlug === generateSlug(appName)) {\n setAppSlug(generateSlug(e.target.value));\n }\n setAppErrors((p) => ({ ...p, name: undefined }));\n }}\n placeholder={tr(\n \"devportal.applicationNamePlaceholder\",\n \"My Awesome App\",\n )}\n required\n error={appErrors.name}\n />\n\n <div className=\"grid grid-cols-2 gap-4\">\n <SelectField\n label={tr(\"devportal.applicationType\", \"Application Type\")}\n value={appType}\n onChange={(e) => {\n setAppType(e.target.value as AppType);\n setAppErrors((p) => ({ ...p, appType: undefined }));\n }}\n options={APP_TYPE_OPTIONS}\n placeholder={tr(\"devportal.selectType\", \"Select type…\")}\n required\n error={appErrors.appType}\n />\n <SelectField\n label={tr(\"devportal.category\", \"Category\")}\n value={appCategory}\n onChange={(e) => {\n setAppCategory(e.target.value);\n setAppErrors((p) => ({ ...p, category: undefined }));\n }}\n options={CATEGORY_OPTIONS}\n placeholder={tr(\n \"devportal.selectCategory\",\n \"Select category…\",\n )}\n required\n error={appErrors.category}\n />\n </div>\n\n <TextareaField\n label={tr(\"devportal.shortDescription\", \"Short Description\")}\n value={appShortDesc}\n onChange={(e) => {\n setAppShortDesc(e.target.value);\n setAppErrors((p) => ({ ...p, shortDescription: undefined }));\n }}\n placeholder={tr(\n \"devportal.shortDescriptionPlaceholder\",\n \"A brief description of what your app does\",\n )}\n required\n error={appErrors.shortDescription}\n rows={2}\n hint={`${appShortDesc.length}/200`}\n />\n </div>\n\n <div className=\"mt-8 flex items-center justify-between border-t border-border-default pt-6\">\n <button\n type=\"button\"\n onClick={handleSkip}\n className=\"text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.skipForNow\", \"Skip for now\")}\n </button>\n <button\n type=\"button\"\n onClick={() => void handleAppSubmit()}\n disabled={creatingApp}\n className=\"inline-flex items-center gap-2 rounded-lg bg-primary px-5 py-2.5 text-sm font-semibold text-primary-foreground hover:bg-primary/90 disabled:opacity-60 transition-colors\"\n >\n {creatingApp ? (\n <span className=\"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n ) : null}\n {tr(\"devportal.setup.createApp\", \"Create App\")}\n {!creatingApp && <ChevronRight size={16} />}\n </button>\n </div>\n </div>\n )}\n\n {/* ── Step 3: Done ─────────────────────────── */}\n {step === \"done\" && (\n <div className=\"text-center\">\n <div className=\"mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10 text-primary\">\n <Rocket size={32} />\n </div>\n <h2 className=\"text-2xl font-bold text-foreground\">\n {tr(\"devportal.setup.doneTitle\", \"You're all set!\")}\n </h2>\n <p className=\"mt-2 text-muted-foreground\">\n {tr(\n \"devportal.setup.doneSubtitle\",\n \"Your organization and first app are ready. Here's what to do next.\",\n )}\n </p>\n\n <div className=\"mt-8 grid gap-3 sm:grid-cols-2\">\n {createdAppId && (\n <NextStepCard\n icon={<AppWindow size={20} />}\n title={tr(\"devportal.setup.viewApp\", \"View your app\")}\n description={tr(\n \"devportal.setup.viewAppDesc\",\n \"Configure OAuth, webhooks, and versioning\",\n )}\n onClick={() => handleNavigate(`/apps/${createdAppId}`)}\n primary\n />\n )}\n <NextStepCard\n icon={<Key size={20} />}\n title={tr(\"devportal.setup.generateApiKey\", \"Generate API key\")}\n description={tr(\n \"devportal.setup.generateApiKeyDesc\",\n \"Create credentials to start calling APIs\",\n )}\n onClick={() => handleNavigate(\"/api-keys/new\")}\n />\n <NextStepCard\n icon={<BookOpen size={20} />}\n title={tr(\"devportal.setup.browseDocs\", \"Browse docs\")}\n description={tr(\n \"devportal.setup.browseDocsDesc\",\n \"Learn about publishing, SDKs, and webhooks\",\n )}\n onClick={() => handleNavigate(\"/docs\")}\n />\n {createdOrgId && (\n <NextStepCard\n icon={<Building2 size={20} />}\n title={tr(\"devportal.setup.inviteTeam\", \"Invite your team\")}\n description={tr(\n \"devportal.setup.inviteTeamDesc\",\n \"Add members to collaborate on your apps\",\n )}\n onClick={() =>\n handleNavigate(`/organizations/${createdOrgId}/members`)\n }\n />\n )}\n </div>\n\n <button\n type=\"button\"\n onClick={() => handleNavigate(\"/\")}\n className=\"mt-8 inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors\"\n >\n {tr(\"devportal.setup.goToDashboard\", \"Go to dashboard\")}\n <ArrowRight size={14} />\n </button>\n </div>\n )}\n </div>\n </main>\n );\n};\n\n// ─── Next-step card ────────────────────────────────────────────────────────\n\nconst NextStepCard: FC<{\n icon: React.ReactNode;\n title: string;\n description: string;\n onClick: () => void;\n primary?: boolean;\n}> = ({ icon, title, description, onClick, primary }) => (\n <button\n type=\"button\"\n onClick={onClick}\n className={[\n \"flex items-start gap-4 rounded-xl border p-5 text-left transition-colors\",\n primary\n ? \"border-primary bg-primary/5 hover:bg-primary/10\"\n : \"border-border-default bg-surface-raised hover:bg-surface-hover\",\n ].join(\" \")}\n >\n <div\n className={[\n \"flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-lg\",\n primary\n ? \"bg-primary/20 text-primary\"\n : \"bg-muted text-muted-foreground\",\n ].join(\" \")}\n >\n {icon}\n </div>\n <div className=\"min-w-0 flex-1\">\n <p className=\"font-semibold text-foreground\">{title}</p>\n <p className=\"mt-0.5 text-sm text-muted-foreground\">{description}</p>\n </div>\n <ChevronRight\n size={16}\n className=\"mt-0.5 flex-shrink-0 text-muted-foreground\"\n />\n </button>\n);\n"],"mappings":"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"}
|
|
@@ -8,11 +8,9 @@ import { AlertTriangle as o, ArrowLeft as s, CheckCircle2 as c, Clock as l, Refr
|
|
|
8
8
|
import { useNavigate as p, useParams as m } from "react-router-dom";
|
|
9
9
|
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
10
10
|
import { graphqlFetch as _ } from "@burdenoff/fe-libs/shared/graphql";
|
|
11
|
-
import { useApolloClient as v } from "@apollo/client/react";
|
|
12
|
-
import { gql as y } from "@apollo/client/core";
|
|
13
11
|
//#region src/devportal/pages/StoreSubmissionPage.tsx
|
|
14
|
-
var
|
|
15
|
-
function
|
|
12
|
+
var v = "\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", y = "\n mutation DevportalSubmitForReview($id: ID!, $notes: String) {\n submitApplicationForReview(id: $id, notes: $notes) {\n id\n status\n submittedAt\n metadata\n }\n }\n";
|
|
13
|
+
function b(e) {
|
|
16
14
|
if (!e) return null;
|
|
17
15
|
let t = e.metadata ?? {}, n = typeof t.storeProductId == "string" ? t.storeProductId : "", r = typeof t.storeSubmissionStatus == "string" ? t.storeSubmissionStatus : null;
|
|
18
16
|
return {
|
|
@@ -25,7 +23,7 @@ function S(e) {
|
|
|
25
23
|
rejectedReason: null
|
|
26
24
|
};
|
|
27
25
|
}
|
|
28
|
-
var
|
|
26
|
+
var x = {
|
|
29
27
|
DRAFT: {
|
|
30
28
|
i18nKey: "devportal.storeSubmission.status.draft",
|
|
31
29
|
fallback: "Draft",
|
|
@@ -56,73 +54,54 @@ var C = {
|
|
|
56
54
|
icon: o,
|
|
57
55
|
tone: "text-text-tertiary"
|
|
58
56
|
}
|
|
59
|
-
},
|
|
60
|
-
let { appId: o } = m(), f = p(),
|
|
57
|
+
}, S = () => {
|
|
58
|
+
let { appId: o } = m(), f = p(), S = e(), C = r(), w = n(t.APP_SUBMIT), [T, E] = a(null), [D, O] = a(!0), [k, A] = a(null), [j, M] = a(!1), [N, P] = a(""), F = async () => {
|
|
61
59
|
if (o) {
|
|
62
|
-
|
|
60
|
+
O(!0), A(null);
|
|
63
61
|
try {
|
|
64
62
|
let e = await _({
|
|
65
63
|
gateway: "global",
|
|
66
|
-
query:
|
|
64
|
+
query: v,
|
|
67
65
|
variables: { id: o }
|
|
68
66
|
});
|
|
69
|
-
if (e.errors?.length) throw Error(e.errors[0]?.message ??
|
|
70
|
-
|
|
67
|
+
if (e.errors?.length) throw Error(e.errors[0]?.message ?? C("devportal.storeSubmission.errors.loadFailed", "Failed to load application"));
|
|
68
|
+
E(e.data?.application ?? null);
|
|
71
69
|
} catch (e) {
|
|
72
|
-
|
|
70
|
+
A(e instanceof Error ? e.message : C("devportal.storeSubmission.errors.loadFailed", "Failed to load application"));
|
|
73
71
|
} finally {
|
|
74
|
-
|
|
72
|
+
O(!1);
|
|
75
73
|
}
|
|
76
74
|
}
|
|
77
75
|
};
|
|
78
76
|
i(() => {
|
|
79
|
-
|
|
77
|
+
F();
|
|
80
78
|
}, [o]), i(() => {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
status
|
|
88
|
-
reviewNotes
|
|
89
|
-
rejectedReason
|
|
90
|
-
updatedAt
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
`,
|
|
94
|
-
variables: { applicationId: o }
|
|
95
|
-
}).subscribe({
|
|
96
|
-
next: () => {
|
|
97
|
-
R();
|
|
98
|
-
},
|
|
99
|
-
error: (e) => {
|
|
100
|
-
console.warn("[StoreSubmissionPage] subscription error:", e);
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
return () => e.unsubscribe();
|
|
104
|
-
}, [o, L]);
|
|
105
|
-
let z = async () => {
|
|
79
|
+
let e = T?.name;
|
|
80
|
+
if (!o || !e) return;
|
|
81
|
+
let t = window.__breadcrumbRegistry;
|
|
82
|
+
return t?.register(o, e), () => t?.unregister(o);
|
|
83
|
+
}, [o, T?.name]);
|
|
84
|
+
let I = async () => {
|
|
106
85
|
if (o) {
|
|
107
|
-
|
|
86
|
+
M(!0), A(null);
|
|
108
87
|
try {
|
|
109
88
|
let e = await _({
|
|
110
89
|
gateway: "global",
|
|
111
|
-
query:
|
|
90
|
+
query: y,
|
|
112
91
|
variables: {
|
|
113
92
|
id: o,
|
|
114
|
-
notes:
|
|
93
|
+
notes: N || null
|
|
115
94
|
}
|
|
116
95
|
});
|
|
117
|
-
if (e.errors?.length) throw Error(e.errors[0]?.message ??
|
|
118
|
-
|
|
96
|
+
if (e.errors?.length) throw Error(e.errors[0]?.message ?? C("devportal.storeSubmission.errors.submitFailed", "Submission failed"));
|
|
97
|
+
S.emit("devportal.app.submitted", { appId: o }), await F();
|
|
119
98
|
} catch (e) {
|
|
120
|
-
|
|
99
|
+
A(e instanceof Error ? e.message : C("devportal.storeSubmission.errors.submitFailed", "Submission failed"));
|
|
121
100
|
} finally {
|
|
122
|
-
|
|
101
|
+
M(!1);
|
|
123
102
|
}
|
|
124
103
|
}
|
|
125
|
-
},
|
|
104
|
+
}, L = b(T), R = L ? x[L.status] : x.UNKNOWN, z = R.icon;
|
|
126
105
|
return /* @__PURE__ */ g("main", {
|
|
127
106
|
className: "min-h-screen bg-surface-default",
|
|
128
107
|
"aria-labelledby": "store-submission-heading",
|
|
@@ -139,7 +118,7 @@ var C = {
|
|
|
139
118
|
children: [/* @__PURE__ */ h(s, {
|
|
140
119
|
className: "h-4 w-4",
|
|
141
120
|
"aria-hidden": "true"
|
|
142
|
-
}),
|
|
121
|
+
}), C("devportal.common.back", "Back")]
|
|
143
122
|
}), /* @__PURE__ */ g("div", {
|
|
144
123
|
className: "flex items-center gap-2",
|
|
145
124
|
children: [/* @__PURE__ */ h(d, {
|
|
@@ -148,23 +127,23 @@ var C = {
|
|
|
148
127
|
}), /* @__PURE__ */ h("h1", {
|
|
149
128
|
id: "store-submission-heading",
|
|
150
129
|
className: "text-xl font-semibold text-text-primary",
|
|
151
|
-
children:
|
|
130
|
+
children: C("devportal.storeSubmission.title", "Store submission")
|
|
152
131
|
})]
|
|
153
132
|
})]
|
|
154
133
|
})
|
|
155
134
|
})
|
|
156
135
|
}), /* @__PURE__ */ g("div", {
|
|
157
136
|
className: "mx-auto max-w-3xl px-6 py-6",
|
|
158
|
-
children: [
|
|
137
|
+
children: [k && /* @__PURE__ */ h("div", {
|
|
159
138
|
role: "alert",
|
|
160
139
|
className: "mb-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
|
|
161
|
-
children:
|
|
162
|
-
}),
|
|
140
|
+
children: k
|
|
141
|
+
}), D && !T ? /* @__PURE__ */ h("div", {
|
|
163
142
|
className: "py-16 text-center text-text-secondary",
|
|
164
143
|
role: "status",
|
|
165
144
|
"aria-live": "polite",
|
|
166
|
-
children:
|
|
167
|
-
}) :
|
|
145
|
+
children: C("devportal.storeSubmission.loading", "Loading application…")
|
|
146
|
+
}) : T ? /* @__PURE__ */ g("div", {
|
|
168
147
|
className: "space-y-4",
|
|
169
148
|
children: [
|
|
170
149
|
/* @__PURE__ */ h("div", {
|
|
@@ -172,49 +151,49 @@ var C = {
|
|
|
172
151
|
children: /* @__PURE__ */ g("div", {
|
|
173
152
|
className: "flex items-center gap-3",
|
|
174
153
|
children: [
|
|
175
|
-
|
|
176
|
-
src:
|
|
154
|
+
T.iconUrl ? /* @__PURE__ */ h("img", {
|
|
155
|
+
src: T.iconUrl,
|
|
177
156
|
alt: "",
|
|
178
157
|
className: "h-14 w-14 flex-shrink-0 rounded-md object-cover"
|
|
179
158
|
}) : /* @__PURE__ */ h("div", {
|
|
180
159
|
className: "flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-text-secondary",
|
|
181
|
-
children:
|
|
160
|
+
children: T.name.slice(0, 2).toUpperCase()
|
|
182
161
|
}),
|
|
183
162
|
/* @__PURE__ */ g("div", {
|
|
184
163
|
className: "min-w-0 flex-1",
|
|
185
164
|
children: [/* @__PURE__ */ h("h2", {
|
|
186
165
|
className: "text-lg font-semibold text-text-primary",
|
|
187
|
-
children:
|
|
166
|
+
children: T.name
|
|
188
167
|
}), /* @__PURE__ */ h("p", {
|
|
189
168
|
className: "font-mono text-xs text-text-tertiary",
|
|
190
|
-
children:
|
|
169
|
+
children: T.slug
|
|
191
170
|
})]
|
|
192
171
|
}),
|
|
193
172
|
/* @__PURE__ */ g("div", {
|
|
194
|
-
className: `flex items-center gap-1.5 ${
|
|
173
|
+
className: `flex items-center gap-1.5 ${R.tone}`,
|
|
195
174
|
role: "status",
|
|
196
|
-
children: [/* @__PURE__ */ h(
|
|
175
|
+
children: [/* @__PURE__ */ h(z, {
|
|
197
176
|
className: "h-5 w-5",
|
|
198
177
|
"aria-hidden": "true"
|
|
199
178
|
}), /* @__PURE__ */ h("span", {
|
|
200
179
|
className: "text-sm font-medium",
|
|
201
|
-
children:
|
|
180
|
+
children: C(R.i18nKey, R.fallback)
|
|
202
181
|
})]
|
|
203
182
|
})
|
|
204
183
|
]
|
|
205
184
|
})
|
|
206
185
|
}),
|
|
207
|
-
|
|
186
|
+
L && L.status !== "UNKNOWN" && /* @__PURE__ */ g("div", {
|
|
208
187
|
className: "rounded-lg border border-border-default bg-surface-raised p-4",
|
|
209
188
|
children: [
|
|
210
189
|
/* @__PURE__ */ h("h3", {
|
|
211
190
|
className: "mb-3 text-sm font-semibold text-text-primary",
|
|
212
|
-
children:
|
|
191
|
+
children: C("devportal.storeSubmission.timeline", "Submission timeline")
|
|
213
192
|
}),
|
|
214
193
|
/* @__PURE__ */ g("ul", {
|
|
215
194
|
className: "space-y-2 text-sm",
|
|
216
195
|
children: [
|
|
217
|
-
|
|
196
|
+
L.submittedAt && /* @__PURE__ */ g("li", {
|
|
218
197
|
className: "flex items-center gap-2",
|
|
219
198
|
children: [
|
|
220
199
|
/* @__PURE__ */ h(l, {
|
|
@@ -223,15 +202,15 @@ var C = {
|
|
|
223
202
|
}),
|
|
224
203
|
/* @__PURE__ */ h("span", {
|
|
225
204
|
className: "text-text-secondary",
|
|
226
|
-
children:
|
|
205
|
+
children: C("devportal.storeSubmission.submitted", "Submitted:")
|
|
227
206
|
}),
|
|
228
207
|
/* @__PURE__ */ h("span", {
|
|
229
208
|
className: "text-text-primary",
|
|
230
|
-
children: new Date(
|
|
209
|
+
children: new Date(L.submittedAt).toLocaleString()
|
|
231
210
|
})
|
|
232
211
|
]
|
|
233
212
|
}),
|
|
234
|
-
|
|
213
|
+
L.reviewedAt && /* @__PURE__ */ g("li", {
|
|
235
214
|
className: "flex items-center gap-2",
|
|
236
215
|
children: [
|
|
237
216
|
/* @__PURE__ */ h(c, {
|
|
@@ -240,15 +219,15 @@ var C = {
|
|
|
240
219
|
}),
|
|
241
220
|
/* @__PURE__ */ h("span", {
|
|
242
221
|
className: "text-text-secondary",
|
|
243
|
-
children:
|
|
222
|
+
children: C("devportal.storeSubmission.reviewed", "Reviewed:")
|
|
244
223
|
}),
|
|
245
224
|
/* @__PURE__ */ h("span", {
|
|
246
225
|
className: "text-text-primary",
|
|
247
|
-
children: new Date(
|
|
226
|
+
children: new Date(L.reviewedAt).toLocaleString()
|
|
248
227
|
})
|
|
249
228
|
]
|
|
250
229
|
}),
|
|
251
|
-
|
|
230
|
+
L.publishedAt && /* @__PURE__ */ g("li", {
|
|
252
231
|
className: "flex items-center gap-2",
|
|
253
232
|
children: [
|
|
254
233
|
/* @__PURE__ */ h(c, {
|
|
@@ -257,99 +236,99 @@ var C = {
|
|
|
257
236
|
}),
|
|
258
237
|
/* @__PURE__ */ h("span", {
|
|
259
238
|
className: "text-text-secondary",
|
|
260
|
-
children:
|
|
239
|
+
children: C("devportal.storeSubmission.published", "Published:")
|
|
261
240
|
}),
|
|
262
241
|
/* @__PURE__ */ h("span", {
|
|
263
242
|
className: "text-text-primary",
|
|
264
|
-
children: new Date(
|
|
243
|
+
children: new Date(L.publishedAt).toLocaleString()
|
|
265
244
|
})
|
|
266
245
|
]
|
|
267
246
|
})
|
|
268
247
|
]
|
|
269
248
|
}),
|
|
270
|
-
|
|
249
|
+
L.reviewNotes && /* @__PURE__ */ g("div", {
|
|
271
250
|
className: "mt-3 rounded-md bg-surface-muted p-3",
|
|
272
251
|
children: [/* @__PURE__ */ h("p", {
|
|
273
252
|
className: "text-xs font-medium text-text-secondary",
|
|
274
|
-
children:
|
|
253
|
+
children: C("devportal.storeSubmission.reviewerNotes", "Reviewer notes")
|
|
275
254
|
}), /* @__PURE__ */ h("p", {
|
|
276
255
|
className: "mt-1 text-sm text-text-primary",
|
|
277
|
-
children:
|
|
256
|
+
children: L.reviewNotes
|
|
278
257
|
})]
|
|
279
258
|
}),
|
|
280
|
-
|
|
259
|
+
L.rejectedReason && /* @__PURE__ */ g("div", {
|
|
281
260
|
className: "mt-3 rounded-md border border-border-danger bg-surface-danger-muted p-3",
|
|
282
261
|
role: "alert",
|
|
283
262
|
children: [/* @__PURE__ */ h("p", {
|
|
284
263
|
className: "text-xs font-medium text-text-danger",
|
|
285
|
-
children:
|
|
264
|
+
children: C("devportal.storeSubmission.rejectionReason", "Rejection reason")
|
|
286
265
|
}), /* @__PURE__ */ h("p", {
|
|
287
266
|
className: "mt-1 text-sm text-text-primary",
|
|
288
|
-
children:
|
|
267
|
+
children: L.rejectedReason
|
|
289
268
|
})]
|
|
290
269
|
})
|
|
291
270
|
]
|
|
292
271
|
}),
|
|
293
|
-
(!
|
|
272
|
+
(!L || L.status === "UNKNOWN" || L.status === "DRAFT" || L.status === "REJECTED") && /* @__PURE__ */ g("div", {
|
|
294
273
|
className: "rounded-lg border border-border-default bg-surface-raised p-4",
|
|
295
274
|
children: [
|
|
296
275
|
/* @__PURE__ */ h("h3", {
|
|
297
276
|
className: "mb-2 text-sm font-semibold text-text-primary",
|
|
298
|
-
children:
|
|
277
|
+
children: L?.status === "REJECTED" ? C("devportal.storeSubmission.resubmitForReview", "Resubmit for review") : C("devportal.storeSubmission.submitForReview", "Submit for review")
|
|
299
278
|
}),
|
|
300
279
|
/* @__PURE__ */ h("p", {
|
|
301
280
|
className: "mb-3 text-sm text-text-secondary",
|
|
302
|
-
children:
|
|
281
|
+
children: C("devportal.storeSubmission.help", "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.")
|
|
303
282
|
}),
|
|
304
283
|
/* @__PURE__ */ h("label", {
|
|
305
284
|
className: "block",
|
|
306
285
|
htmlFor: "store-submission-notes",
|
|
307
286
|
children: /* @__PURE__ */ h("span", {
|
|
308
287
|
className: "sr-only",
|
|
309
|
-
children:
|
|
288
|
+
children: C("devportal.storeSubmission.notesLabel", "Notes for the reviewer (optional)")
|
|
310
289
|
})
|
|
311
290
|
}),
|
|
312
291
|
/* @__PURE__ */ h("textarea", {
|
|
313
292
|
id: "store-submission-notes",
|
|
314
|
-
value:
|
|
315
|
-
onChange: (e) =>
|
|
293
|
+
value: N,
|
|
294
|
+
onChange: (e) => P(e.target.value),
|
|
316
295
|
rows: 3,
|
|
317
|
-
placeholder:
|
|
296
|
+
placeholder: C("devportal.storeSubmission.notesLabel", "Notes for the reviewer (optional)"),
|
|
318
297
|
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"
|
|
319
298
|
}),
|
|
320
299
|
/* @__PURE__ */ g("button", {
|
|
321
300
|
type: "button",
|
|
322
|
-
onClick: () => void
|
|
323
|
-
disabled:
|
|
324
|
-
"aria-disabled":
|
|
325
|
-
title:
|
|
301
|
+
onClick: () => void I(),
|
|
302
|
+
disabled: j || !w.allowed,
|
|
303
|
+
"aria-disabled": j || !w.allowed,
|
|
304
|
+
title: w.allowed ? void 0 : C("devportal.common.noPermission", "You do not have permission to perform this action"),
|
|
326
305
|
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",
|
|
327
|
-
children: [
|
|
306
|
+
children: [j && /* @__PURE__ */ h(u, {
|
|
328
307
|
className: "h-4 w-4 animate-spin",
|
|
329
308
|
"aria-hidden": "true"
|
|
330
|
-
}),
|
|
309
|
+
}), L?.status === "REJECTED" ? C("devportal.storeSubmission.resubmit", "Resubmit") : C("devportal.storeSubmission.submitForReview", "Submit for review")]
|
|
331
310
|
})
|
|
332
311
|
]
|
|
333
312
|
}),
|
|
334
|
-
|
|
313
|
+
L?.productId && /* @__PURE__ */ g("div", {
|
|
335
314
|
className: "rounded-lg border border-border-default bg-surface-raised p-4",
|
|
336
315
|
children: [/* @__PURE__ */ h("p", {
|
|
337
316
|
className: "text-xs font-medium text-text-secondary",
|
|
338
|
-
children:
|
|
317
|
+
children: C("devportal.storeSubmission.storeProductId", "Store product ID")
|
|
339
318
|
}), /* @__PURE__ */ h("code", {
|
|
340
319
|
className: "mt-1 block break-all font-mono text-xs text-text-primary",
|
|
341
|
-
children:
|
|
320
|
+
children: L.productId
|
|
342
321
|
})]
|
|
343
322
|
})
|
|
344
323
|
]
|
|
345
324
|
}) : /* @__PURE__ */ h("div", {
|
|
346
325
|
className: "py-16 text-center text-text-secondary",
|
|
347
|
-
children:
|
|
326
|
+
children: C("devportal.storeSubmission.notFound", "Application not found.")
|
|
348
327
|
})]
|
|
349
328
|
})]
|
|
350
329
|
});
|
|
351
330
|
};
|
|
352
331
|
//#endregion
|
|
353
|
-
export {
|
|
332
|
+
export { S as StoreSubmissionPage };
|
|
354
333
|
|
|
355
334
|
//# sourceMappingURL=StoreSubmissionPage.js.map
|