@burdenoff/microfe-devportal 2026.625.4 → 2026.625.5
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.
|
@@ -7,138 +7,181 @@ import "../components/index.js";
|
|
|
7
7
|
import { DEVPORTAL_PERMISSIONS as c } from "../constants/permissions.js";
|
|
8
8
|
import { useDevportalPermission as ee } from "../hooks/usePermission.js";
|
|
9
9
|
import "../hooks/index.js";
|
|
10
|
-
import { useEffect as
|
|
11
|
-
import { useI18n as
|
|
12
|
-
import { AlertTriangle as
|
|
13
|
-
import { useParams as
|
|
14
|
-
import { Fragment as
|
|
15
|
-
import { gql as
|
|
16
|
-
import { useQuery as
|
|
10
|
+
import { useEffect as l, useMemo as u, useState as d } from "react";
|
|
11
|
+
import { useI18n as te } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
12
|
+
import { AlertTriangle as f, ArrowRight as ne, CheckCircle as p, Eye as re, FileText as m, Globe as ie, Image as h, KeyRound as ae, Link as g, Loader2 as _, PartyPopper as oe, Send as se, Shield as v, Webhook as ce, XCircle as y } from "lucide-react";
|
|
13
|
+
import { useParams as le } from "react-router-dom";
|
|
14
|
+
import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
|
|
15
|
+
import { gql as C } from "@apollo/client";
|
|
16
|
+
import { useQuery as w } from "@apollo/client/react";
|
|
17
17
|
//#region src/devportal/pages/PublishPage.tsx
|
|
18
|
-
var
|
|
18
|
+
var T = C`query PublishPagePublisher { myPublisher { id } }`, ue = C`
|
|
19
19
|
query PublishPageProducts($publisherId: String!) {
|
|
20
20
|
products(filter: { publisherId: $publisherId }) { id productId }
|
|
21
21
|
}
|
|
22
|
-
`,
|
|
22
|
+
`, de = C`
|
|
23
|
+
query PublishPageWebhooks($applicationId: ID!) {
|
|
24
|
+
webhooks(applicationId: $applicationId) { id }
|
|
25
|
+
}
|
|
26
|
+
`, fe = [
|
|
23
27
|
"SUBMITTED",
|
|
24
28
|
"IN_REVIEW",
|
|
25
29
|
"APPROVED",
|
|
26
30
|
"PUBLISHED"
|
|
27
|
-
],
|
|
28
|
-
let { appId:
|
|
29
|
-
let n =
|
|
31
|
+
], E = () => {
|
|
32
|
+
let { appId: C } = le(), { navigate: E, basePath: D } = e(), { t: pe } = te(), O = (e, t) => {
|
|
33
|
+
let n = pe(e);
|
|
30
34
|
return n === e ? t : n;
|
|
31
|
-
}, [
|
|
32
|
-
variables: { id:
|
|
33
|
-
skip: !
|
|
35
|
+
}, [k, A] = d(!1), [j, M] = d(null), [me, N] = d(!1), [P, F] = d(""), I = ee(c.APP_SUBMIT), { data: L, loading: R, error: z } = t({
|
|
36
|
+
variables: { id: C },
|
|
37
|
+
skip: !C,
|
|
34
38
|
fetchPolicy: "network-only"
|
|
35
|
-
}), [
|
|
36
|
-
variables: { publisherId:
|
|
37
|
-
skip: !
|
|
39
|
+
}), [he] = r(), [ge] = n(), { data: _e } = w(T, { fetchPolicy: "cache-first" }), B = _e?.myPublisher?.id ?? null, { data: ve } = w(ue, {
|
|
40
|
+
variables: { publisherId: B ?? "" },
|
|
41
|
+
skip: !B,
|
|
38
42
|
fetchPolicy: "cache-first"
|
|
39
43
|
});
|
|
40
|
-
|
|
41
|
-
let
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
ve?.products?.find((e) => e.productId === C)?.id;
|
|
45
|
+
let V = L?.application?.appType === "API_INTEGRATION", H = L?.application?.manifest?.oauth, U = !!(H?.authorizationUrl && H?.tokenUrl && H?.clientId), { data: ye } = w(de, {
|
|
46
|
+
variables: { applicationId: C },
|
|
47
|
+
skip: !C || !V,
|
|
48
|
+
fetchPolicy: "network-only"
|
|
49
|
+
}), W = ye?.webhooks?.length ?? 0, G = L?.application;
|
|
50
|
+
l(() => {
|
|
51
|
+
let e = G?.name;
|
|
52
|
+
if (!C || !e) return;
|
|
45
53
|
let t = window.__breadcrumbRegistry;
|
|
46
|
-
return t?.register(
|
|
47
|
-
}, [
|
|
48
|
-
let
|
|
49
|
-
if (!
|
|
50
|
-
let e =
|
|
54
|
+
return t?.register(C, e), () => t?.unregister(C);
|
|
55
|
+
}, [C, G?.name]);
|
|
56
|
+
let K = fe.includes(G?.status ?? ""), q = G?.appType === "NODE" || G?.appType === "WORKFLOW", J = G?.versions?.totalCount ?? 0, Y = u(() => {
|
|
57
|
+
if (!G) return [];
|
|
58
|
+
let e = G.screenshots?.length ?? 0, t = `/apps/${C}?tab=store-listing`, n = `/apps/${C}/versions`, r = `/apps/${C}/edit`, i = `/apps/${C}?tab=webhooks`, a = [
|
|
51
59
|
{
|
|
52
60
|
id: "name",
|
|
53
|
-
label:
|
|
54
|
-
description:
|
|
55
|
-
status:
|
|
56
|
-
icon: /* @__PURE__ */
|
|
61
|
+
label: O("devportal.checklistNameLabel", "Name & Short Description"),
|
|
62
|
+
description: O("devportal.checklistNameDesc", "Name and short description are required for the store card"),
|
|
63
|
+
status: G.name && G.shortDescription ? "passed" : "failed",
|
|
64
|
+
icon: /* @__PURE__ */ x(m, { size: 20 }),
|
|
57
65
|
actionLabel: "Edit store listing →",
|
|
58
66
|
actionPath: t
|
|
59
67
|
},
|
|
60
68
|
{
|
|
61
69
|
id: "category",
|
|
62
|
-
label:
|
|
63
|
-
description:
|
|
64
|
-
status:
|
|
65
|
-
icon: /* @__PURE__ */
|
|
70
|
+
label: O("devportal.checklistCategoryLabel", "Category"),
|
|
71
|
+
description: O("devportal.checklistCategoryDesc", "A category helps users find your item in the marketplace"),
|
|
72
|
+
status: G.category ? "passed" : "failed",
|
|
73
|
+
icon: /* @__PURE__ */ x(ie, { size: 20 }),
|
|
66
74
|
actionLabel: "Edit app info →",
|
|
67
|
-
actionPath: `/apps/${
|
|
75
|
+
actionPath: `/apps/${C}/edit`
|
|
68
76
|
},
|
|
69
77
|
{
|
|
70
78
|
id: "privacy",
|
|
71
|
-
label:
|
|
72
|
-
description:
|
|
73
|
-
status:
|
|
74
|
-
icon: /* @__PURE__ */
|
|
79
|
+
label: O("devportal.checklistPrivacyLabel", "Privacy Policy"),
|
|
80
|
+
description: O("devportal.checklistPrivacyDesc", "Privacy policy URL is required for store submission"),
|
|
81
|
+
status: G.privacyPolicyUrl ? "passed" : "failed",
|
|
82
|
+
icon: /* @__PURE__ */ x(v, { size: 20 }),
|
|
75
83
|
actionLabel: "Edit store listing →",
|
|
76
84
|
actionPath: t
|
|
77
85
|
},
|
|
78
86
|
{
|
|
79
87
|
id: "terms",
|
|
80
|
-
label:
|
|
81
|
-
description:
|
|
82
|
-
status:
|
|
83
|
-
icon: /* @__PURE__ */
|
|
88
|
+
label: O("devportal.checklistTermsLabel", "Terms of Service"),
|
|
89
|
+
description: O("devportal.checklistTermsDesc", "Terms of service URL is required for store submission"),
|
|
90
|
+
status: G.termsOfServiceUrl ? "passed" : "failed",
|
|
91
|
+
icon: /* @__PURE__ */ x(m, { size: 20 }),
|
|
84
92
|
actionLabel: "Edit store listing →",
|
|
85
93
|
actionPath: t
|
|
86
94
|
},
|
|
87
95
|
{
|
|
88
96
|
id: "icon",
|
|
89
|
-
label:
|
|
90
|
-
description:
|
|
91
|
-
status:
|
|
92
|
-
icon: /* @__PURE__ */
|
|
97
|
+
label: O("devportal.checklistIconLabel", "App Icon"),
|
|
98
|
+
description: O("devportal.checklistIconDesc", "An icon makes your listing stand out in the marketplace"),
|
|
99
|
+
status: G.iconUrl ? "passed" : "warning",
|
|
100
|
+
icon: /* @__PURE__ */ x(h, { size: 20 }),
|
|
93
101
|
actionLabel: "Edit store listing →",
|
|
94
102
|
actionPath: t
|
|
95
103
|
},
|
|
96
104
|
{
|
|
97
105
|
id: "screenshots",
|
|
98
|
-
label:
|
|
99
|
-
description:
|
|
106
|
+
label: O("devportal.checklistScreenshotsLabel", "Screenshots"),
|
|
107
|
+
description: O("devportal.checklistScreenshotsDesc", "At least 3 screenshots are recommended"),
|
|
100
108
|
status: e >= 3 ? "passed" : "warning",
|
|
101
|
-
icon: /* @__PURE__ */
|
|
109
|
+
icon: /* @__PURE__ */ x(h, { size: 20 }),
|
|
102
110
|
actionLabel: "Edit store listing →",
|
|
103
111
|
actionPath: t
|
|
104
112
|
}
|
|
105
113
|
];
|
|
106
|
-
return
|
|
114
|
+
return q && a.push({
|
|
107
115
|
id: "version",
|
|
108
|
-
label:
|
|
109
|
-
description:
|
|
110
|
-
status:
|
|
111
|
-
icon: /* @__PURE__ */
|
|
116
|
+
label: O("devportal.checklistVersionLabel", "Published Version"),
|
|
117
|
+
description: O("devportal.checklistVersionDesc", G?.appType === "WORKFLOW" ? "At least one published version (manifest JSON) is required before submitting to the store" : "At least one published version (ZIP + manifest) is required before submitting to the store"),
|
|
118
|
+
status: J > 0 ? "passed" : "failed",
|
|
119
|
+
icon: /* @__PURE__ */ x(p, { size: 20 }),
|
|
112
120
|
actionLabel: "Create a version →",
|
|
113
121
|
actionPath: n
|
|
114
|
-
}),
|
|
122
|
+
}), G.appType === "API_INTEGRATION" && (a.push({
|
|
123
|
+
id: "oauth",
|
|
124
|
+
label: O("devportal.checklistOAuthLabel", "OAuth Configuration"),
|
|
125
|
+
description: O("devportal.checklistOAuthDesc", "Authorization URL, Token URL and Client ID are required so users can connect their accounts. Without these the Connect button does not work."),
|
|
126
|
+
status: U ? "passed" : "failed",
|
|
127
|
+
icon: /* @__PURE__ */ x(ae, { size: 20 }),
|
|
128
|
+
actionLabel: "Add OAuth endpoints →",
|
|
129
|
+
actionPath: r
|
|
130
|
+
}), a.push({
|
|
131
|
+
id: "webhook",
|
|
132
|
+
label: O("devportal.checklistWebhookLabel", "Webhook Endpoint"),
|
|
133
|
+
description: O("devportal.checklistWebhookDesc", "At least one webhook endpoint must be configured so your server receives platform events after users connect. Without this the integration does nothing."),
|
|
134
|
+
status: W > 0 ? "passed" : "failed",
|
|
135
|
+
icon: /* @__PURE__ */ x(ce, { size: 20 }),
|
|
136
|
+
actionLabel: "Add a webhook →",
|
|
137
|
+
actionPath: i
|
|
138
|
+
}), a.push({
|
|
139
|
+
id: "documentation",
|
|
140
|
+
label: O("devportal.checklistDocsLabel", "Documentation URL"),
|
|
141
|
+
description: O("devportal.checklistDocsDesc", "Users need to know how to use and configure this integration. A documentation link is required for API integrations."),
|
|
142
|
+
status: G.documentationUrl ? "passed" : "failed",
|
|
143
|
+
icon: /* @__PURE__ */ x(m, { size: 20 }),
|
|
144
|
+
actionLabel: "Add documentation URL →",
|
|
145
|
+
actionPath: r
|
|
146
|
+
}), a.push({
|
|
147
|
+
id: "website",
|
|
148
|
+
label: O("devportal.checklistWebsiteLabel", "Website URL"),
|
|
149
|
+
description: O("devportal.checklistWebsiteDesc", "Users need to verify who built this integration. A website URL is required so users know where to get support."),
|
|
150
|
+
status: G.websiteUrl ? "passed" : "failed",
|
|
151
|
+
icon: /* @__PURE__ */ x(g, { size: 20 }),
|
|
152
|
+
actionLabel: "Add website URL →",
|
|
153
|
+
actionPath: r
|
|
154
|
+
})), a.push({
|
|
115
155
|
id: "status",
|
|
116
|
-
label:
|
|
117
|
-
description:
|
|
118
|
-
status: ["DRAFT", "REJECTED"].includes(
|
|
119
|
-
icon: /* @__PURE__ */
|
|
120
|
-
}),
|
|
156
|
+
label: O("devportal.checklistStatusLabel", "App Status"),
|
|
157
|
+
description: O("devportal.checklistStatusDesc", "App must be in DRAFT or REJECTED state to submit"),
|
|
158
|
+
status: ["DRAFT", "REJECTED"].includes(G.status ?? "") ? "passed" : "warning",
|
|
159
|
+
icon: /* @__PURE__ */ x(p, { size: 20 })
|
|
160
|
+
}), a;
|
|
121
161
|
}, [
|
|
122
|
-
|
|
162
|
+
G,
|
|
163
|
+
q,
|
|
123
164
|
J,
|
|
124
|
-
|
|
125
|
-
|
|
165
|
+
W,
|
|
166
|
+
U,
|
|
167
|
+
C
|
|
168
|
+
]), X = Y.filter((e) => e.status === "passed").length, Z = Y.filter((e) => e.status === "failed").length, Q = Y.filter((e) => e.status === "warning").length, be = ["DRAFT", "REJECTED"].includes(G?.status ?? ""), $ = !R && !z && Z === 0 && !!G && !K && be, xe = (e) => {
|
|
126
169
|
switch (e) {
|
|
127
|
-
case "passed": return /* @__PURE__ */
|
|
170
|
+
case "passed": return /* @__PURE__ */ x(p, {
|
|
128
171
|
size: 20,
|
|
129
172
|
className: "text-status-success-text"
|
|
130
173
|
});
|
|
131
|
-
case "failed": return /* @__PURE__ */
|
|
174
|
+
case "failed": return /* @__PURE__ */ x(y, {
|
|
132
175
|
size: 20,
|
|
133
176
|
className: "text-status-error-text"
|
|
134
177
|
});
|
|
135
|
-
case "warning": return /* @__PURE__ */
|
|
178
|
+
case "warning": return /* @__PURE__ */ x(f, {
|
|
136
179
|
size: 20,
|
|
137
180
|
className: "text-status-warning-text"
|
|
138
181
|
});
|
|
139
|
-
default: return /* @__PURE__ */
|
|
182
|
+
default: return /* @__PURE__ */ x("div", { className: "h-5 w-5 rounded-full border-2 border-border-default" });
|
|
140
183
|
}
|
|
141
|
-
},
|
|
184
|
+
}, Se = (e) => {
|
|
142
185
|
switch (e) {
|
|
143
186
|
case "passed": return "bg-status-success-bg-subtle border-border-subtle";
|
|
144
187
|
case "failed": return "bg-status-error-bg-subtle border-border-subtle";
|
|
@@ -146,76 +189,76 @@ var w = S`query PublishPagePublisher { myPublisher { id } }`, T = S`
|
|
|
146
189
|
default: return "bg-bg-canvas border-border-subtle";
|
|
147
190
|
}
|
|
148
191
|
};
|
|
149
|
-
return
|
|
150
|
-
title:
|
|
151
|
-
description:
|
|
152
|
-
backLink: `/apps/${
|
|
153
|
-
backLabel:
|
|
154
|
-
children: /* @__PURE__ */
|
|
192
|
+
return R ? /* @__PURE__ */ x(i, {
|
|
193
|
+
title: O("devportal.publishToStoreTitle", "Publish to Store"),
|
|
194
|
+
description: O("devportal.loadingApplicationDetails", "Loading application details..."),
|
|
195
|
+
backLink: `/apps/${C}`,
|
|
196
|
+
backLabel: O("devportal.backToApplication", "Back to Application"),
|
|
197
|
+
children: /* @__PURE__ */ x("div", {
|
|
155
198
|
className: "flex items-center justify-center py-12",
|
|
156
|
-
children: /* @__PURE__ */
|
|
199
|
+
children: /* @__PURE__ */ x(_, { className: "animate-spin h-8 w-8 text-muted-foreground" })
|
|
157
200
|
})
|
|
158
|
-
}) :
|
|
159
|
-
title:
|
|
160
|
-
description:
|
|
161
|
-
backLink: `/apps/${
|
|
162
|
-
backLabel:
|
|
163
|
-
children: /* @__PURE__ */
|
|
201
|
+
}) : z || !G ? /* @__PURE__ */ x(i, {
|
|
202
|
+
title: O("devportal.publishToStoreTitle", "Publish to Store"),
|
|
203
|
+
description: O("devportal.couldNotLoadApplication", "Could not load application"),
|
|
204
|
+
backLink: `/apps/${C}`,
|
|
205
|
+
backLabel: O("devportal.backToApplication", "Back to Application"),
|
|
206
|
+
children: /* @__PURE__ */ x(o, {
|
|
164
207
|
variant: "error",
|
|
165
|
-
title:
|
|
166
|
-
children:
|
|
208
|
+
title: O("devportal.failedToLoadApplication", "Failed to load application"),
|
|
209
|
+
children: z?.message ?? O("devportal.applicationNotFound", "Application not found")
|
|
167
210
|
})
|
|
168
|
-
}) :
|
|
211
|
+
}) : me ? /* @__PURE__ */ x(s, {
|
|
169
212
|
permission: c.APP_SUBMIT,
|
|
170
|
-
children: /* @__PURE__ */
|
|
171
|
-
title:
|
|
172
|
-
backLink: `/apps/${
|
|
173
|
-
backLabel:
|
|
174
|
-
children: /* @__PURE__ */
|
|
213
|
+
children: /* @__PURE__ */ x(i, {
|
|
214
|
+
title: O("devportal.publishToStoreTitle", "Publish to Store"),
|
|
215
|
+
backLink: `/apps/${C}`,
|
|
216
|
+
backLabel: O("devportal.backToApplication", "Back to Application"),
|
|
217
|
+
children: /* @__PURE__ */ S("div", {
|
|
175
218
|
className: "flex flex-col items-center justify-center py-16 gap-6 text-center",
|
|
176
219
|
children: [
|
|
177
|
-
/* @__PURE__ */
|
|
220
|
+
/* @__PURE__ */ x("div", {
|
|
178
221
|
className: "rounded-full bg-status-success-bg p-4",
|
|
179
|
-
children: /* @__PURE__ */
|
|
222
|
+
children: /* @__PURE__ */ x(oe, {
|
|
180
223
|
size: 40,
|
|
181
224
|
className: "text-status-success-text"
|
|
182
225
|
})
|
|
183
226
|
}),
|
|
184
|
-
/* @__PURE__ */
|
|
227
|
+
/* @__PURE__ */ S("div", {
|
|
185
228
|
className: "space-y-2",
|
|
186
|
-
children: [/* @__PURE__ */
|
|
229
|
+
children: [/* @__PURE__ */ x("h2", {
|
|
187
230
|
className: "text-2xl font-bold",
|
|
188
|
-
children:
|
|
189
|
-
}), /* @__PURE__ */
|
|
231
|
+
children: O("devportal.submittedSuccessTitle", "Submitted for Review!")
|
|
232
|
+
}), /* @__PURE__ */ x("p", {
|
|
190
233
|
className: "text-muted-foreground max-w-md",
|
|
191
|
-
children:
|
|
234
|
+
children: O("devportal.submittedSuccessMsg", "Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.")
|
|
192
235
|
})]
|
|
193
236
|
}),
|
|
194
|
-
/* @__PURE__ */
|
|
237
|
+
/* @__PURE__ */ S("div", {
|
|
195
238
|
className: "rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full",
|
|
196
|
-
children: [/* @__PURE__ */
|
|
239
|
+
children: [/* @__PURE__ */ x("p", {
|
|
197
240
|
className: "font-medium",
|
|
198
241
|
children: "What happens next:"
|
|
199
|
-
}), /* @__PURE__ */
|
|
242
|
+
}), /* @__PURE__ */ S("ul", {
|
|
200
243
|
className: "space-y-1 text-muted-foreground list-none",
|
|
201
244
|
children: [
|
|
202
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ S("li", {
|
|
203
246
|
className: "flex items-start gap-2",
|
|
204
|
-
children: [/* @__PURE__ */
|
|
247
|
+
children: [/* @__PURE__ */ x(p, {
|
|
205
248
|
size: 14,
|
|
206
249
|
className: "mt-0.5 text-status-success-text shrink-0"
|
|
207
250
|
}), " Our team reviews your submission"]
|
|
208
251
|
}),
|
|
209
|
-
/* @__PURE__ */
|
|
252
|
+
/* @__PURE__ */ S("li", {
|
|
210
253
|
className: "flex items-start gap-2",
|
|
211
|
-
children: [/* @__PURE__ */
|
|
254
|
+
children: [/* @__PURE__ */ x(p, {
|
|
212
255
|
size: 14,
|
|
213
256
|
className: "mt-0.5 text-status-success-text shrink-0"
|
|
214
257
|
}), " You'll get an email on approval or if changes are needed"]
|
|
215
258
|
}),
|
|
216
|
-
/* @__PURE__ */
|
|
259
|
+
/* @__PURE__ */ S("li", {
|
|
217
260
|
className: "flex items-start gap-2",
|
|
218
|
-
children: [/* @__PURE__ */
|
|
261
|
+
children: [/* @__PURE__ */ x(p, {
|
|
219
262
|
size: 14,
|
|
220
263
|
className: "mt-0.5 text-status-success-text shrink-0"
|
|
221
264
|
}), " Once approved, your app goes live in the marketplace"]
|
|
@@ -223,253 +266,266 @@ var w = S`query PublishPagePublisher { myPublisher { id } }`, T = S`
|
|
|
223
266
|
]
|
|
224
267
|
})]
|
|
225
268
|
}),
|
|
226
|
-
/* @__PURE__ */
|
|
227
|
-
onClick: () =>
|
|
269
|
+
/* @__PURE__ */ x("button", {
|
|
270
|
+
onClick: () => E?.(`${D}/apps/${C}`),
|
|
228
271
|
className: "inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted",
|
|
229
272
|
children: "Back to App"
|
|
230
273
|
})
|
|
231
274
|
]
|
|
232
275
|
})
|
|
233
276
|
})
|
|
234
|
-
}) : /* @__PURE__ */
|
|
277
|
+
}) : /* @__PURE__ */ x(s, {
|
|
235
278
|
permission: c.APP_SUBMIT,
|
|
236
|
-
children: /* @__PURE__ */
|
|
237
|
-
title:
|
|
238
|
-
description: `${
|
|
239
|
-
backLink: `/apps/${
|
|
240
|
-
backLabel:
|
|
241
|
-
actions: /* @__PURE__ */
|
|
242
|
-
onClick: () =>
|
|
279
|
+
children: /* @__PURE__ */ S(i, {
|
|
280
|
+
title: O("devportal.publishToStoreTitle", "Publish to Store"),
|
|
281
|
+
description: `${O("devportal.submitAppForReview", "Submit")} "${G.name}" ${O("devportal.forReviewAndPublication", "for review and publication")}`,
|
|
282
|
+
backLink: `/apps/${C}`,
|
|
283
|
+
backLabel: O("devportal.backToApplication", "Back to Application"),
|
|
284
|
+
actions: /* @__PURE__ */ S("button", {
|
|
285
|
+
onClick: () => E?.(`${D}/apps/${C}/listing`),
|
|
243
286
|
className: "inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-muted",
|
|
244
|
-
children: [/* @__PURE__ */
|
|
287
|
+
children: [/* @__PURE__ */ x(re, { size: 16 }), O("devportal.previewListing", "Preview Listing")]
|
|
245
288
|
}),
|
|
246
289
|
children: [
|
|
247
|
-
|
|
290
|
+
K && /* @__PURE__ */ S(o, {
|
|
248
291
|
variant: "warning",
|
|
249
|
-
title:
|
|
292
|
+
title: O("devportal.alreadySubmittedTitle", "Already Submitted"),
|
|
250
293
|
children: [
|
|
251
|
-
|
|
294
|
+
O("devportal.alreadySubmittedMsg1", "This app is currently in"),
|
|
252
295
|
" ",
|
|
253
|
-
/* @__PURE__ */
|
|
296
|
+
/* @__PURE__ */ x("strong", { children: G.status }),
|
|
254
297
|
" ",
|
|
255
|
-
|
|
298
|
+
O("devportal.alreadySubmittedMsg2", "state and cannot be re-submitted until the review process is complete or the app is rejected.")
|
|
256
299
|
]
|
|
257
300
|
}),
|
|
258
|
-
/* @__PURE__ */
|
|
301
|
+
/* @__PURE__ */ S("div", {
|
|
259
302
|
className: "rounded-lg border bg-card p-6",
|
|
260
303
|
children: [
|
|
261
|
-
/* @__PURE__ */
|
|
304
|
+
/* @__PURE__ */ x("h2", {
|
|
262
305
|
className: "text-lg font-semibold",
|
|
263
|
-
children:
|
|
306
|
+
children: O("devportal.preSubmissionChecklist", "Pre-submission Checklist")
|
|
264
307
|
}),
|
|
265
|
-
/* @__PURE__ */
|
|
308
|
+
/* @__PURE__ */ x("p", {
|
|
266
309
|
className: "mt-1 text-sm text-muted-foreground",
|
|
267
|
-
children:
|
|
310
|
+
children: O("devportal.completeAllRequiredItems", "Complete all required items before submitting for review")
|
|
268
311
|
}),
|
|
269
|
-
/* @__PURE__ */
|
|
312
|
+
/* @__PURE__ */ S("div", {
|
|
270
313
|
className: "mt-4 flex gap-6",
|
|
271
314
|
children: [
|
|
272
|
-
/* @__PURE__ */
|
|
315
|
+
/* @__PURE__ */ S("div", {
|
|
273
316
|
className: "flex items-center gap-2",
|
|
274
|
-
children: [/* @__PURE__ */
|
|
317
|
+
children: [/* @__PURE__ */ x(p, {
|
|
275
318
|
size: 20,
|
|
276
319
|
className: "text-status-success-text"
|
|
277
|
-
}), /* @__PURE__ */
|
|
278
|
-
|
|
320
|
+
}), /* @__PURE__ */ S("span", { children: [
|
|
321
|
+
X,
|
|
279
322
|
" ",
|
|
280
|
-
|
|
323
|
+
O("devportal.passed", "Passed")
|
|
281
324
|
] })]
|
|
282
325
|
}),
|
|
283
|
-
/* @__PURE__ */
|
|
326
|
+
/* @__PURE__ */ S("div", {
|
|
284
327
|
className: "flex items-center gap-2",
|
|
285
|
-
children: [/* @__PURE__ */
|
|
328
|
+
children: [/* @__PURE__ */ x(y, {
|
|
286
329
|
size: 20,
|
|
287
330
|
className: "text-status-error-text"
|
|
288
|
-
}), /* @__PURE__ */
|
|
331
|
+
}), /* @__PURE__ */ S("span", { children: [
|
|
289
332
|
Z,
|
|
290
333
|
" ",
|
|
291
|
-
|
|
334
|
+
O("devportal.failed", "Failed")
|
|
292
335
|
] })]
|
|
293
336
|
}),
|
|
294
|
-
/* @__PURE__ */
|
|
337
|
+
/* @__PURE__ */ S("div", {
|
|
295
338
|
className: "flex items-center gap-2",
|
|
296
|
-
children: [/* @__PURE__ */
|
|
339
|
+
children: [/* @__PURE__ */ x(f, {
|
|
297
340
|
size: 20,
|
|
298
341
|
className: "text-status-warning-text"
|
|
299
|
-
}), /* @__PURE__ */
|
|
342
|
+
}), /* @__PURE__ */ S("span", { children: [
|
|
300
343
|
Q,
|
|
301
344
|
" ",
|
|
302
|
-
|
|
345
|
+
O("devportal.warnings", "Warnings")
|
|
303
346
|
] })]
|
|
304
347
|
})
|
|
305
348
|
]
|
|
306
349
|
})
|
|
307
350
|
]
|
|
308
351
|
}),
|
|
309
|
-
/* @__PURE__ */
|
|
352
|
+
/* @__PURE__ */ x(a, { children: /* @__PURE__ */ x("div", {
|
|
310
353
|
className: "space-y-3",
|
|
311
|
-
children:
|
|
312
|
-
className: `flex items-center gap-4 rounded-lg border p-4 ${
|
|
354
|
+
children: Y.map((e) => /* @__PURE__ */ S("div", {
|
|
355
|
+
className: `flex items-center gap-4 rounded-lg border p-4 ${Se(e.status)}`,
|
|
313
356
|
children: [
|
|
314
|
-
/* @__PURE__ */
|
|
357
|
+
/* @__PURE__ */ x("div", {
|
|
315
358
|
className: "rounded-lg bg-background p-2",
|
|
316
359
|
children: e.icon
|
|
317
360
|
}),
|
|
318
|
-
/* @__PURE__ */
|
|
361
|
+
/* @__PURE__ */ S("div", {
|
|
319
362
|
className: "flex-1",
|
|
320
363
|
children: [
|
|
321
|
-
/* @__PURE__ */
|
|
364
|
+
/* @__PURE__ */ x("p", {
|
|
322
365
|
className: "font-medium",
|
|
323
366
|
children: e.label
|
|
324
367
|
}),
|
|
325
|
-
/* @__PURE__ */
|
|
368
|
+
/* @__PURE__ */ x("p", {
|
|
326
369
|
className: "text-sm text-muted-foreground",
|
|
327
370
|
children: e.description
|
|
328
371
|
}),
|
|
329
|
-
e.status !== "passed" && e.actionPath && /* @__PURE__ */
|
|
372
|
+
e.status !== "passed" && e.actionPath && /* @__PURE__ */ S("button", {
|
|
330
373
|
type: "button",
|
|
331
|
-
onClick: () =>
|
|
374
|
+
onClick: () => E?.(`${D}${e.actionPath}`),
|
|
332
375
|
className: "mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline",
|
|
333
376
|
children: [
|
|
334
377
|
e.actionLabel ?? "Fix this",
|
|
335
378
|
" ",
|
|
336
|
-
/* @__PURE__ */
|
|
379
|
+
/* @__PURE__ */ x(ne, { size: 11 })
|
|
337
380
|
]
|
|
338
381
|
})
|
|
339
382
|
]
|
|
340
383
|
}),
|
|
341
|
-
|
|
384
|
+
xe(e.status)
|
|
342
385
|
]
|
|
343
386
|
}, e.id))
|
|
344
387
|
}) }),
|
|
345
|
-
!
|
|
346
|
-
title:
|
|
347
|
-
description:
|
|
348
|
-
children: [/* @__PURE__ */
|
|
349
|
-
value:
|
|
350
|
-
onChange: (e) =>
|
|
351
|
-
placeholder:
|
|
388
|
+
!K && /* @__PURE__ */ S(a, {
|
|
389
|
+
title: O("devportal.notesForReviewerTitle", "Notes for Reviewer"),
|
|
390
|
+
description: O("devportal.notesForReviewerDesc", "Optional message to the review team"),
|
|
391
|
+
children: [/* @__PURE__ */ x("textarea", {
|
|
392
|
+
value: P,
|
|
393
|
+
onChange: (e) => F(e.target.value),
|
|
394
|
+
placeholder: O("devportal.notesForReviewerPlaceholder", "Describe what your app does, any special review considerations, or testing instructions..."),
|
|
352
395
|
rows: 4,
|
|
353
396
|
maxLength: 1e3,
|
|
354
397
|
className: "w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring resize-none"
|
|
355
|
-
}), /* @__PURE__ */
|
|
398
|
+
}), /* @__PURE__ */ S("p", {
|
|
356
399
|
className: "mt-1 text-xs text-muted-foreground text-right",
|
|
357
|
-
children: [
|
|
400
|
+
children: [P.length, "/1000"]
|
|
358
401
|
})]
|
|
359
402
|
}),
|
|
360
|
-
|
|
403
|
+
j && /* @__PURE__ */ x(o, {
|
|
361
404
|
variant: "error",
|
|
362
|
-
title:
|
|
363
|
-
children:
|
|
405
|
+
title: O("devportal.submissionFailedTitle", "Submission Failed"),
|
|
406
|
+
children: j
|
|
364
407
|
}),
|
|
365
|
-
Z > 0 && !
|
|
408
|
+
Z > 0 && !K && /* @__PURE__ */ S(o, {
|
|
366
409
|
variant: "error",
|
|
367
|
-
title:
|
|
410
|
+
title: O("devportal.cannotSubmitTitle", "Cannot Submit Yet"),
|
|
368
411
|
children: [
|
|
369
|
-
|
|
412
|
+
O("devportal.pleaseFixItems1", "Please fix"),
|
|
370
413
|
" ",
|
|
371
414
|
Z,
|
|
372
415
|
" ",
|
|
373
|
-
|
|
374
|
-
/* @__PURE__ */
|
|
416
|
+
O("devportal.pleaseFixItems2", "required item(s) before submitting for review."),
|
|
417
|
+
/* @__PURE__ */ S("div", {
|
|
375
418
|
className: "mt-2 flex flex-wrap gap-3",
|
|
376
|
-
children: [
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
419
|
+
children: [
|
|
420
|
+
/* @__PURE__ */ x("button", {
|
|
421
|
+
onClick: () => E?.(`${D}/apps/${C}`),
|
|
422
|
+
className: "text-sm underline hover:no-underline",
|
|
423
|
+
children: O("devportal.goToMarketplaceListing", "Update marketplace listing →")
|
|
424
|
+
}),
|
|
425
|
+
q && J === 0 && /* @__PURE__ */ x("button", {
|
|
426
|
+
onClick: () => E?.(`${D}/apps/${C}/versions`),
|
|
427
|
+
className: "text-sm underline hover:no-underline",
|
|
428
|
+
children: O("devportal.goToVersions", "Add a published version →")
|
|
429
|
+
}),
|
|
430
|
+
V && !U && /* @__PURE__ */ x("button", {
|
|
431
|
+
onClick: () => E?.(`${D}/apps/${C}/edit`),
|
|
432
|
+
className: "text-sm underline hover:no-underline",
|
|
433
|
+
children: "Configure OAuth endpoints →"
|
|
434
|
+
}),
|
|
435
|
+
V && W === 0 && /* @__PURE__ */ x("button", {
|
|
436
|
+
onClick: () => E?.(`${D}/apps/${C}?tab=webhooks`),
|
|
437
|
+
className: "text-sm underline hover:no-underline",
|
|
438
|
+
children: "Add a webhook →"
|
|
439
|
+
})
|
|
440
|
+
]
|
|
385
441
|
})
|
|
386
442
|
]
|
|
387
443
|
}),
|
|
388
|
-
Q > 0 && Z === 0 && !
|
|
444
|
+
Q > 0 && Z === 0 && !K && /* @__PURE__ */ S(o, {
|
|
389
445
|
variant: "warning",
|
|
390
|
-
title:
|
|
446
|
+
title: O("devportal.warningsTitle", "Warnings"),
|
|
391
447
|
children: [
|
|
392
|
-
|
|
448
|
+
O("devportal.warningsMsg1", "You have"),
|
|
393
449
|
" ",
|
|
394
450
|
Q,
|
|
395
451
|
" ",
|
|
396
|
-
|
|
452
|
+
O("devportal.warningsMsg2", "warning(s). While you can submit, addressing these may improve your app's chances of approval.")
|
|
397
453
|
]
|
|
398
454
|
}),
|
|
399
|
-
/* @__PURE__ */
|
|
400
|
-
title:
|
|
401
|
-
children: /* @__PURE__ */
|
|
455
|
+
/* @__PURE__ */ x(a, {
|
|
456
|
+
title: O("devportal.reviewProcessTitle", "Review Process"),
|
|
457
|
+
children: /* @__PURE__ */ x("div", {
|
|
402
458
|
className: "rounded-lg border bg-muted/50 p-4",
|
|
403
|
-
children: /* @__PURE__ */
|
|
459
|
+
children: /* @__PURE__ */ S("ul", {
|
|
404
460
|
className: "space-y-2 text-sm",
|
|
405
461
|
children: [
|
|
406
|
-
/* @__PURE__ */
|
|
462
|
+
/* @__PURE__ */ S("li", {
|
|
407
463
|
className: "flex items-start gap-2",
|
|
408
|
-
children: [/* @__PURE__ */
|
|
464
|
+
children: [/* @__PURE__ */ x(p, {
|
|
409
465
|
size: 16,
|
|
410
466
|
className: "mt-0.5 text-primary"
|
|
411
|
-
}), /* @__PURE__ */
|
|
467
|
+
}), /* @__PURE__ */ x("span", { children: O("devportal.reviewProcessInfo1", "Review typically takes 3-5 business days") })]
|
|
412
468
|
}),
|
|
413
|
-
/* @__PURE__ */
|
|
469
|
+
/* @__PURE__ */ S("li", {
|
|
414
470
|
className: "flex items-start gap-2",
|
|
415
|
-
children: [/* @__PURE__ */
|
|
471
|
+
children: [/* @__PURE__ */ x(p, {
|
|
416
472
|
size: 16,
|
|
417
473
|
className: "mt-0.5 text-primary"
|
|
418
|
-
}), /* @__PURE__ */
|
|
474
|
+
}), /* @__PURE__ */ x("span", { children: O("devportal.reviewProcessInfo2", "You'll receive notifications about review status changes") })]
|
|
419
475
|
}),
|
|
420
|
-
/* @__PURE__ */
|
|
476
|
+
/* @__PURE__ */ S("li", {
|
|
421
477
|
className: "flex items-start gap-2",
|
|
422
|
-
children: [/* @__PURE__ */
|
|
478
|
+
children: [/* @__PURE__ */ x(p, {
|
|
423
479
|
size: 16,
|
|
424
480
|
className: "mt-0.5 text-primary"
|
|
425
|
-
}), /* @__PURE__ */
|
|
481
|
+
}), /* @__PURE__ */ x("span", { children: O("devportal.reviewProcessInfo3", "If changes are requested, you can resubmit without losing your place in the queue") })]
|
|
426
482
|
}),
|
|
427
|
-
/* @__PURE__ */
|
|
483
|
+
/* @__PURE__ */ S("li", {
|
|
428
484
|
className: "flex items-start gap-2",
|
|
429
|
-
children: [/* @__PURE__ */
|
|
485
|
+
children: [/* @__PURE__ */ x(p, {
|
|
430
486
|
size: 16,
|
|
431
487
|
className: "mt-0.5 text-primary"
|
|
432
|
-
}), /* @__PURE__ */
|
|
488
|
+
}), /* @__PURE__ */ x("span", { children: O("devportal.reviewProcessInfo4", "Once approved and published, your app will be visible in the marketplace") })]
|
|
433
489
|
})
|
|
434
490
|
]
|
|
435
491
|
})
|
|
436
492
|
})
|
|
437
493
|
}),
|
|
438
|
-
/* @__PURE__ */
|
|
494
|
+
/* @__PURE__ */ S("div", {
|
|
439
495
|
className: "flex gap-3",
|
|
440
|
-
children: [/* @__PURE__ */
|
|
441
|
-
onClick: () =>
|
|
496
|
+
children: [/* @__PURE__ */ x("button", {
|
|
497
|
+
onClick: () => E?.(`${D}/apps/${C}`),
|
|
442
498
|
className: "rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted",
|
|
443
|
-
children:
|
|
444
|
-
}), /* @__PURE__ */
|
|
499
|
+
children: O("devportal.cancelButton", "Cancel")
|
|
500
|
+
}), /* @__PURE__ */ x("button", {
|
|
445
501
|
onClick: async () => {
|
|
446
|
-
if (
|
|
447
|
-
|
|
502
|
+
if (C) {
|
|
503
|
+
A(!0), M(null);
|
|
448
504
|
try {
|
|
449
|
-
let e = await
|
|
450
|
-
id:
|
|
451
|
-
notes:
|
|
505
|
+
let e = await he({ variables: {
|
|
506
|
+
id: C,
|
|
507
|
+
notes: P.trim() || void 0
|
|
452
508
|
} });
|
|
453
509
|
if (e.error) throw e.error;
|
|
454
|
-
await
|
|
455
|
-
id:
|
|
456
|
-
notes:
|
|
457
|
-
} }),
|
|
510
|
+
await ge({ variables: {
|
|
511
|
+
id: C,
|
|
512
|
+
notes: P.trim() || void 0
|
|
513
|
+
} }), N(!0);
|
|
458
514
|
} catch (e) {
|
|
459
|
-
|
|
515
|
+
M(e instanceof Error ? e.message : O("devportal.submitFailedDefault", "Failed to submit for review"));
|
|
460
516
|
} finally {
|
|
461
|
-
|
|
517
|
+
A(!1);
|
|
462
518
|
}
|
|
463
519
|
}
|
|
464
520
|
},
|
|
465
|
-
disabled: !$ ||
|
|
466
|
-
"aria-disabled": !$ ||
|
|
467
|
-
title:
|
|
521
|
+
disabled: !$ || k || !I.allowed,
|
|
522
|
+
"aria-disabled": !$ || k || !I.allowed,
|
|
523
|
+
title: I.allowed ? void 0 : O("devportal.common.noPermission", "You do not have permission to perform this action"),
|
|
468
524
|
className: "inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary",
|
|
469
|
-
children:
|
|
525
|
+
children: k ? /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(_, {
|
|
470
526
|
size: 16,
|
|
471
527
|
className: "animate-spin"
|
|
472
|
-
}),
|
|
528
|
+
}), O("devportal.submittingButton", "Submitting...")] }) : /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x(se, { size: 16 }), O("devportal.submitForReviewButton", "Submit for Review")] })
|
|
473
529
|
})]
|
|
474
530
|
})
|
|
475
531
|
]
|
|
@@ -477,6 +533,6 @@ var w = S`query PublishPagePublisher { myPublisher { id } }`, T = S`
|
|
|
477
533
|
});
|
|
478
534
|
};
|
|
479
535
|
//#endregion
|
|
480
|
-
export {
|
|
536
|
+
export { E as PublishPage };
|
|
481
537
|
|
|
482
538
|
//# sourceMappingURL=PublishPage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PublishPage.js","names":[],"sources":["../../../src/devportal/pages/PublishPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n XCircle,\n AlertTriangle,\n Send,\n FileText,\n Shield,\n Image,\n Globe,\n Loader2,\n Eye,\n ArrowRight,\n PartyPopper,\n} from \"lucide-react\";\nimport { gql } from \"@apollo/client\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { Alert } from \"../components/ConfirmDialog\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport {\n useGetApplicationQuery,\n useSubmitApplicationMutation,\n useSubmitApplicationForReviewMutation,\n} from \"../../generated/global-operations\";\nimport { useDevportalPermission } from \"../hooks\";\n\nconst MY_PUBLISHER_QUERY = gql`query PublishPagePublisher { myPublisher { id } }`;\nconst PUBLISHER_PRODUCTS_QUERY = gql`\n query PublishPageProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId }) { id productId }\n }\n`;\n\ninterface ChecklistItem {\n id: string;\n label: string;\n description: string;\n status: \"passed\" | \"failed\" | \"warning\" | \"pending\";\n icon: React.ReactNode;\n actionLabel?: string;\n actionPath?: string;\n}\n\nconst ALREADY_SUBMITTED_STATUSES = [\n \"SUBMITTED\",\n \"IN_REVIEW\",\n \"APPROVED\",\n \"PUBLISHED\",\n];\n\nexport const PublishPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n\n const {\n data,\n loading,\n error: queryError,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n fetchPolicy: \"network-only\",\n });\n\n const [submitApplication] = useSubmitApplicationMutation();\n const [submitApplicationForReview] = useSubmitApplicationForReviewMutation();\n\n // Two-step publisher lookup to find linked StoreProduct\n const { data: publisherData } = useQuery<{ myPublisher: { id: string } | null }>(\n MY_PUBLISHER_QUERY,\n { fetchPolicy: \"cache-first\" },\n );\n const publisherId = publisherData?.myPublisher?.id ?? null;\n const { data: productsData } = useQuery<{ products: { id: string; productId?: string | null }[] }>(\n PUBLISHER_PRODUCTS_QUERY,\n {\n variables: { publisherId: publisherId ?? \"\" },\n skip: !publisherId,\n fetchPolicy: \"cache-first\",\n },\n );\n const linkedStoreProductId =\n productsData?.products?.find(\n (p: { id: string; productId?: string | null }) => p.productId === appId,\n )?.id ?? null;\n\n const app = data?.application;\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const isAlreadySubmitted = ALREADY_SUBMITTED_STATUSES.includes(\n app?.status ?? \"\",\n );\n\n const isPackageType =\n app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\";\n const publishedVersionCount = app?.versions?.totalCount ?? 0;\n\n const checklist = useMemo((): ChecklistItem[] => {\n if (!app) return [];\n\n const screenshotCount = app.screenshots?.length ?? 0;\n\n const storeListingPath = `/apps/${appId}?tab=store-listing`;\n const versionsPath = `/apps/${appId}/versions`;\n\n const items: ChecklistItem[] = [\n {\n id: \"name\",\n label: tr(\"devportal.checklistNameLabel\", \"Name & Short Description\"),\n description: tr(\n \"devportal.checklistNameDesc\",\n \"Name and short description are required for the store card\",\n ),\n status: app.name && app.shortDescription ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"category\",\n label: tr(\"devportal.checklistCategoryLabel\", \"Category\"),\n description: tr(\n \"devportal.checklistCategoryDesc\",\n \"A category helps users find your item in the marketplace\",\n ),\n status: app.category ? \"passed\" : \"failed\",\n icon: <Globe size={20} />,\n actionLabel: \"Edit app info →\",\n actionPath: `/apps/${appId}/edit`,\n },\n {\n id: \"privacy\",\n label: tr(\"devportal.checklistPrivacyLabel\", \"Privacy Policy\"),\n description: tr(\n \"devportal.checklistPrivacyDesc\",\n \"Privacy policy URL is required for store submission\",\n ),\n status: app.privacyPolicyUrl ? \"passed\" : \"failed\",\n icon: <Shield size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"terms\",\n label: tr(\"devportal.checklistTermsLabel\", \"Terms of Service\"),\n description: tr(\n \"devportal.checklistTermsDesc\",\n \"Terms of service URL is required for store submission\",\n ),\n status: app.termsOfServiceUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"icon\",\n label: tr(\"devportal.checklistIconLabel\", \"App Icon\"),\n description: tr(\n \"devportal.checklistIconDesc\",\n \"An icon makes your listing stand out in the marketplace\",\n ),\n status: app.iconUrl ? \"passed\" : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"screenshots\",\n label: tr(\"devportal.checklistScreenshotsLabel\", \"Screenshots\"),\n description: tr(\n \"devportal.checklistScreenshotsDesc\",\n \"At least 3 screenshots are recommended\",\n ),\n status:\n screenshotCount >= 3\n ? \"passed\"\n : screenshotCount > 0\n ? \"warning\"\n : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n ];\n\n if (isPackageType) {\n items.push({\n id: \"version\",\n label: tr(\"devportal.checklistVersionLabel\", \"Published Version\"),\n description: tr(\n \"devportal.checklistVersionDesc\",\n app?.appType === \"WORKFLOW\"\n ? \"At least one published version (manifest JSON) is required before submitting to the store\"\n : \"At least one published version (ZIP + manifest) is required before submitting to the store\",\n ),\n status: publishedVersionCount > 0 ? \"passed\" : \"failed\",\n icon: <CheckCircle size={20} />,\n actionLabel: \"Create a version →\",\n actionPath: versionsPath,\n });\n }\n\n items.push({\n id: \"status\",\n label: tr(\"devportal.checklistStatusLabel\", \"App Status\"),\n description: tr(\n \"devportal.checklistStatusDesc\",\n \"App must be in DRAFT or REJECTED state to submit\",\n ),\n status: [\"DRAFT\", \"REJECTED\"].includes(app.status ?? \"\")\n ? \"passed\"\n : \"warning\",\n icon: <CheckCircle size={20} />,\n });\n\n return items;\n }, [app, isPackageType, publishedVersionCount]);\n\n const passedCount = checklist.filter((i) => i.status === \"passed\").length;\n const failedCount = checklist.filter((i) => i.status === \"failed\").length;\n const warningCount = checklist.filter((i) => i.status === \"warning\").length;\n const isSubmittableStatus = [\"DRAFT\", \"REJECTED\"].includes(app?.status ?? \"\");\n const canSubmit =\n !loading &&\n !queryError &&\n failedCount === 0 &&\n !!app &&\n !isAlreadySubmitted &&\n isSubmittableStatus;\n\n const getStatusIcon = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return <CheckCircle size={20} className=\"text-status-success-text\" />;\n case \"failed\":\n return <XCircle size={20} className=\"text-status-error-text\" />;\n case \"warning\":\n return <AlertTriangle size={20} className=\"text-status-warning-text\" />;\n default:\n return (\n <div className=\"h-5 w-5 rounded-full border-2 border-border-default\" />\n );\n }\n };\n\n const getStatusBg = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return \"bg-status-success-bg-subtle border-border-subtle\";\n case \"failed\":\n return \"bg-status-error-bg-subtle border-border-subtle\";\n case \"warning\":\n return \"bg-status-warning-bg-subtle border-border-subtle\";\n default:\n return \"bg-bg-canvas border-border-subtle\";\n }\n };\n\n const handleSubmit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n // Submit Application for devportal review (sets Application.status = SUBMITTED)\n const result = await submitApplication({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n if (result.error) throw result.error;\n\n // Also submit ApplicationForReview to set StoreProduct.status = PENDING_REVIEW\n // so it appears in the store admin review queue at /store/dashboard/submissions\n await submitApplicationForReview({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n\n setSubmitted(true);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.submitFailedDefault\", \"Failed to submit for review\"),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.loadingApplicationDetails\",\n \"Loading application details...\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"animate-spin h-8 w-8 text-muted-foreground\" />\n </div>\n </PageLayout>\n );\n }\n\n if (queryError || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.couldNotLoadApplication\",\n \"Could not load application\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <Alert\n variant=\"error\"\n title={tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n >\n {queryError?.message ??\n tr(\"devportal.applicationNotFound\", \"Application not found\")}\n </Alert>\n </PageLayout>\n );\n }\n\n if (submitted) {\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex flex-col items-center justify-center py-16 gap-6 text-center\">\n <div className=\"rounded-full bg-status-success-bg p-4\">\n <PartyPopper size={40} className=\"text-status-success-text\" />\n </div>\n <div className=\"space-y-2\">\n <h2 className=\"text-2xl font-bold\">\n {tr(\"devportal.submittedSuccessTitle\", \"Submitted for Review!\")}\n </h2>\n <p className=\"text-muted-foreground max-w-md\">\n {tr(\n \"devportal.submittedSuccessMsg\",\n \"Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.\",\n )}\n </p>\n </div>\n <div className=\"rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full\">\n <p className=\"font-medium\">What happens next:</p>\n <ul className=\"space-y-1 text-muted-foreground list-none\">\n <li className=\"flex items-start gap-2\"><CheckCircle size={14} className=\"mt-0.5 text-status-success-text shrink-0\" /> Our team reviews your submission</li>\n <li className=\"flex items-start gap-2\"><CheckCircle size={14} className=\"mt-0.5 text-status-success-text shrink-0\" /> You'll get an email on approval or if changes are needed</li>\n <li className=\"flex items-start gap-2\"><CheckCircle size={14} className=\"mt-0.5 text-status-success-text shrink-0\" /> Once approved, your app goes live in the marketplace</li>\n </ul>\n </div>\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Back to App\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n }\n\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={`${tr(\"devportal.submitAppForReview\", \"Submit\")} \"${app.name}\" ${tr(\"devportal.forReviewAndPublication\", \"for review and publication\")}`}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/listing`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-muted\"\n >\n <Eye size={16} />\n {tr(\"devportal.previewListing\", \"Preview Listing\")}\n </button>\n }\n >\n {isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.alreadySubmittedTitle\", \"Already Submitted\")}\n >\n {tr(\"devportal.alreadySubmittedMsg1\", \"This app is currently in\")}{\" \"}\n <strong>{app.status}</strong>{\" \"}\n {tr(\n \"devportal.alreadySubmittedMsg2\",\n \"state and cannot be re-submitted until the review process is complete or the app is rejected.\",\n )}\n </Alert>\n )}\n\n {/* Progress Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.preSubmissionChecklist\", \"Pre-submission Checklist\")}\n </h2>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {tr(\n \"devportal.completeAllRequiredItems\",\n \"Complete all required items before submitting for review\",\n )}\n </p>\n <div className=\"mt-4 flex gap-6\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle size={20} className=\"text-status-success-text\" />\n <span>\n {passedCount} {tr(\"devportal.passed\", \"Passed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <XCircle size={20} className=\"text-status-error-text\" />\n <span>\n {failedCount} {tr(\"devportal.failed\", \"Failed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AlertTriangle size={20} className=\"text-status-warning-text\" />\n <span>\n {warningCount} {tr(\"devportal.warnings\", \"Warnings\")}\n </span>\n </div>\n </div>\n </div>\n\n {/* Checklist Items */}\n <PageSection>\n <div className=\"space-y-3\">\n {checklist.map((item) => (\n <div\n key={item.id}\n className={`flex items-center gap-4 rounded-lg border p-4 ${getStatusBg(item.status)}`}\n >\n <div className=\"rounded-lg bg-background p-2\">{item.icon}</div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{item.label}</p>\n <p className=\"text-sm text-muted-foreground\">\n {item.description}\n </p>\n {item.status !== \"passed\" && item.actionPath && (\n <button\n type=\"button\"\n onClick={() => navigate?.(`${basePath}${item.actionPath}`)}\n className=\"mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n {item.actionLabel ?? \"Fix this\"} <ArrowRight size={11} />\n </button>\n )}\n </div>\n {getStatusIcon(item.status)}\n </div>\n ))}\n </div>\n </PageSection>\n\n {/* Submission Notes */}\n {!isAlreadySubmitted && (\n <PageSection\n title={tr(\"devportal.notesForReviewerTitle\", \"Notes for Reviewer\")}\n description={tr(\n \"devportal.notesForReviewerDesc\",\n \"Optional message to the review team\",\n )}\n >\n <textarea\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder={tr(\n \"devportal.notesForReviewerPlaceholder\",\n \"Describe what your app does, any special review considerations, or testing instructions...\",\n )}\n rows={4}\n maxLength={1000}\n className=\"w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring resize-none\"\n />\n <p className=\"mt-1 text-xs text-muted-foreground text-right\">\n {notes.length}/1000\n </p>\n </PageSection>\n )}\n\n {/* Alerts */}\n {submitError && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.submissionFailedTitle\", \"Submission Failed\")}\n >\n {submitError}\n </Alert>\n )}\n\n {failedCount > 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.cannotSubmitTitle\", \"Cannot Submit Yet\")}\n >\n {tr(\"devportal.pleaseFixItems1\", \"Please fix\")} {failedCount}{\" \"}\n {tr(\n \"devportal.pleaseFixItems2\",\n \"required item(s) before submitting for review.\",\n )}\n <div className=\"mt-2 flex flex-wrap gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToMarketplaceListing\",\n \"Update marketplace listing →\",\n )}\n </button>\n {isPackageType && publishedVersionCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/versions`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToVersions\",\n \"Add a published version →\",\n )}\n </button>\n )}\n </div>\n </Alert>\n )}\n\n {warningCount > 0 && failedCount === 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.warningsTitle\", \"Warnings\")}\n >\n {tr(\"devportal.warningsMsg1\", \"You have\")} {warningCount}{\" \"}\n {tr(\n \"devportal.warningsMsg2\",\n \"warning(s). While you can submit, addressing these may improve your app's chances of approval.\",\n )}\n </Alert>\n )}\n\n {/* Review Process Info */}\n <PageSection\n title={tr(\"devportal.reviewProcessTitle\", \"Review Process\")}\n >\n <div className=\"rounded-lg border bg-muted/50 p-4\">\n <ul className=\"space-y-2 text-sm\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo1\",\n \"Review typically takes 3-5 business days\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo2\",\n \"You'll receive notifications about review status changes\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo3\",\n \"If changes are requested, you can resubmit without losing your place in the queue\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo4\",\n \"Once approved and published, your app will be visible in the marketplace\",\n )}\n </span>\n </li>\n </ul>\n </div>\n </PageSection>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n {tr(\"devportal.cancelButton\", \"Cancel\")}\n </button>\n <button\n onClick={handleSubmit}\n disabled={!canSubmit || submitting || !submitPerm.allowed}\n aria-disabled={!canSubmit || submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submittingButton\", \"Submitting...\")}\n </>\n ) : (\n <>\n <Send size={16} />\n {tr(\"devportal.submitForReviewButton\", \"Submit for Review\")}\n </>\n )}\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PublishPage.js","names":[],"sources":["../../../src/devportal/pages/PublishPage.tsx"],"sourcesContent":["import type { FC } from \"react\";\nimport { useEffect, useState, useMemo } from \"react\";\nimport { useParams } from \"react-router-dom\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport {\n CheckCircle,\n XCircle,\n AlertTriangle,\n Send,\n FileText,\n Shield,\n Image,\n Globe,\n Loader2,\n Eye,\n ArrowRight,\n PartyPopper,\n Link,\n Webhook,\n KeyRound,\n} from \"lucide-react\";\nimport { gql } from \"@apollo/client\";\nimport { useQuery } from \"@apollo/client/react\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { Alert } from \"../components/ConfirmDialog\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { PermissionGuard } from \"../components\";\nimport { DEVPORTAL_PERMISSIONS } from \"../constants/permissions\";\nimport {\n useGetApplicationQuery,\n useSubmitApplicationMutation,\n useSubmitApplicationForReviewMutation,\n} from \"../../generated/global-operations\";\nimport { useDevportalPermission } from \"../hooks\";\n\nconst MY_PUBLISHER_QUERY = gql`query PublishPagePublisher { myPublisher { id } }`;\nconst PUBLISHER_PRODUCTS_QUERY = gql`\n query PublishPageProducts($publisherId: String!) {\n products(filter: { publisherId: $publisherId }) { id productId }\n }\n`;\nconst APP_WEBHOOKS_QUERY = gql`\n query PublishPageWebhooks($applicationId: ID!) {\n webhooks(applicationId: $applicationId) { id }\n }\n`;\n\ninterface ChecklistItem {\n id: string;\n label: string;\n description: string;\n status: \"passed\" | \"failed\" | \"warning\" | \"pending\";\n icon: React.ReactNode;\n actionLabel?: string;\n actionPath?: string;\n}\n\nconst ALREADY_SUBMITTED_STATUSES = [\n \"SUBMITTED\",\n \"IN_REVIEW\",\n \"APPROVED\",\n \"PUBLISHED\",\n];\n\nexport const PublishPage: FC = () => {\n const { appId } = useParams<{ appId: string }>();\n const { navigate, basePath } = useDevportal();\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const value = t(key);\n return value === key ? fallback : value;\n };\n const [submitting, setSubmitting] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [submitted, setSubmitted] = useState(false);\n const [notes, setNotes] = useState(\"\");\n const submitPerm = useDevportalPermission(DEVPORTAL_PERMISSIONS.APP_SUBMIT);\n\n const {\n data,\n loading,\n error: queryError,\n } = useGetApplicationQuery({\n variables: { id: appId! },\n skip: !appId,\n fetchPolicy: \"network-only\",\n });\n\n const [submitApplication] = useSubmitApplicationMutation();\n const [submitApplicationForReview] = useSubmitApplicationForReviewMutation();\n\n // Two-step publisher lookup to find linked StoreProduct\n const { data: publisherData } = useQuery<{ myPublisher: { id: string } | null }>(\n MY_PUBLISHER_QUERY,\n { fetchPolicy: \"cache-first\" },\n );\n const publisherId = publisherData?.myPublisher?.id ?? null;\n const { data: productsData } = useQuery<{ products: { id: string; productId?: string | null }[] }>(\n PUBLISHER_PRODUCTS_QUERY,\n {\n variables: { publisherId: publisherId ?? \"\" },\n skip: !publisherId,\n fetchPolicy: \"cache-first\",\n },\n );\n const linkedStoreProductId =\n productsData?.products?.find(\n (p: { id: string; productId?: string | null }) => p.productId === appId,\n )?.id ?? null;\n\n const isApiIntegration = data?.application?.appType === \"API_INTEGRATION\";\n const appManifest = data?.application?.manifest as Record<string, unknown> | null | undefined;\n const appOauth = appManifest?.['oauth'] as Record<string, unknown> | undefined;\n const hasOAuthUrl = !!(appOauth?.['authorizationUrl'] && appOauth?.['tokenUrl'] && appOauth?.['clientId']);\n\n const { data: webhooksData } = useQuery<{ webhooks: { id: string }[] }>(\n APP_WEBHOOKS_QUERY,\n {\n variables: { applicationId: appId! },\n skip: !appId || !isApiIntegration,\n fetchPolicy: \"network-only\",\n },\n );\n const webhookCount = webhooksData?.webhooks?.length ?? 0;\n\n const app = data?.application;\n\n useEffect(() => {\n const name = app?.name;\n if (!appId || !name) return;\n const reg = (\n window as unknown as {\n __breadcrumbRegistry?: {\n register: (id: string, name: string) => void;\n unregister: (id: string) => void;\n };\n }\n ).__breadcrumbRegistry;\n reg?.register(appId, name);\n return () => reg?.unregister(appId);\n }, [appId, app?.name]);\n\n const isAlreadySubmitted = ALREADY_SUBMITTED_STATUSES.includes(\n app?.status ?? \"\",\n );\n\n const isPackageType =\n app?.appType === \"NODE\" || app?.appType === \"WORKFLOW\";\n const publishedVersionCount = app?.versions?.totalCount ?? 0;\n\n const checklist = useMemo((): ChecklistItem[] => {\n if (!app) return [];\n\n const screenshotCount = app.screenshots?.length ?? 0;\n\n const storeListingPath = `/apps/${appId}?tab=store-listing`;\n const versionsPath = `/apps/${appId}/versions`;\n const editPath = `/apps/${appId}/edit`;\n const webhooksPath = `/apps/${appId}?tab=webhooks`;\n\n const items: ChecklistItem[] = [\n {\n id: \"name\",\n label: tr(\"devportal.checklistNameLabel\", \"Name & Short Description\"),\n description: tr(\n \"devportal.checklistNameDesc\",\n \"Name and short description are required for the store card\",\n ),\n status: app.name && app.shortDescription ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"category\",\n label: tr(\"devportal.checklistCategoryLabel\", \"Category\"),\n description: tr(\n \"devportal.checklistCategoryDesc\",\n \"A category helps users find your item in the marketplace\",\n ),\n status: app.category ? \"passed\" : \"failed\",\n icon: <Globe size={20} />,\n actionLabel: \"Edit app info →\",\n actionPath: `/apps/${appId}/edit`,\n },\n {\n id: \"privacy\",\n label: tr(\"devportal.checklistPrivacyLabel\", \"Privacy Policy\"),\n description: tr(\n \"devportal.checklistPrivacyDesc\",\n \"Privacy policy URL is required for store submission\",\n ),\n status: app.privacyPolicyUrl ? \"passed\" : \"failed\",\n icon: <Shield size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"terms\",\n label: tr(\"devportal.checklistTermsLabel\", \"Terms of Service\"),\n description: tr(\n \"devportal.checklistTermsDesc\",\n \"Terms of service URL is required for store submission\",\n ),\n status: app.termsOfServiceUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"icon\",\n label: tr(\"devportal.checklistIconLabel\", \"App Icon\"),\n description: tr(\n \"devportal.checklistIconDesc\",\n \"An icon makes your listing stand out in the marketplace\",\n ),\n status: app.iconUrl ? \"passed\" : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n {\n id: \"screenshots\",\n label: tr(\"devportal.checklistScreenshotsLabel\", \"Screenshots\"),\n description: tr(\n \"devportal.checklistScreenshotsDesc\",\n \"At least 3 screenshots are recommended\",\n ),\n status:\n screenshotCount >= 3\n ? \"passed\"\n : screenshotCount > 0\n ? \"warning\"\n : \"warning\",\n icon: <Image size={20} />,\n actionLabel: \"Edit store listing →\",\n actionPath: storeListingPath,\n },\n ];\n\n if (isPackageType) {\n items.push({\n id: \"version\",\n label: tr(\"devportal.checklistVersionLabel\", \"Published Version\"),\n description: tr(\n \"devportal.checklistVersionDesc\",\n app?.appType === \"WORKFLOW\"\n ? \"At least one published version (manifest JSON) is required before submitting to the store\"\n : \"At least one published version (ZIP + manifest) is required before submitting to the store\",\n ),\n status: publishedVersionCount > 0 ? \"passed\" : \"failed\",\n icon: <CheckCircle size={20} />,\n actionLabel: \"Create a version →\",\n actionPath: versionsPath,\n });\n }\n\n if (app.appType === \"API_INTEGRATION\") {\n items.push({\n id: \"oauth\",\n label: tr(\"devportal.checklistOAuthLabel\", \"OAuth Configuration\"),\n description: tr(\n \"devportal.checklistOAuthDesc\",\n \"Authorization URL, Token URL and Client ID are required so users can connect their accounts. Without these the Connect button does not work.\",\n ),\n status: hasOAuthUrl ? \"passed\" : \"failed\",\n icon: <KeyRound size={20} />,\n actionLabel: \"Add OAuth endpoints →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"webhook\",\n label: tr(\"devportal.checklistWebhookLabel\", \"Webhook Endpoint\"),\n description: tr(\n \"devportal.checklistWebhookDesc\",\n \"At least one webhook endpoint must be configured so your server receives platform events after users connect. Without this the integration does nothing.\",\n ),\n status: webhookCount > 0 ? \"passed\" : \"failed\",\n icon: <Webhook size={20} />,\n actionLabel: \"Add a webhook →\",\n actionPath: webhooksPath,\n });\n\n items.push({\n id: \"documentation\",\n label: tr(\"devportal.checklistDocsLabel\", \"Documentation URL\"),\n description: tr(\n \"devportal.checklistDocsDesc\",\n \"Users need to know how to use and configure this integration. A documentation link is required for API integrations.\",\n ),\n status: app.documentationUrl ? \"passed\" : \"failed\",\n icon: <FileText size={20} />,\n actionLabel: \"Add documentation URL →\",\n actionPath: editPath,\n });\n\n items.push({\n id: \"website\",\n label: tr(\"devportal.checklistWebsiteLabel\", \"Website URL\"),\n description: tr(\n \"devportal.checklistWebsiteDesc\",\n \"Users need to verify who built this integration. A website URL is required so users know where to get support.\",\n ),\n status: app.websiteUrl ? \"passed\" : \"failed\",\n icon: <Link size={20} />,\n actionLabel: \"Add website URL →\",\n actionPath: editPath,\n });\n }\n\n items.push({\n id: \"status\",\n label: tr(\"devportal.checklistStatusLabel\", \"App Status\"),\n description: tr(\n \"devportal.checklistStatusDesc\",\n \"App must be in DRAFT or REJECTED state to submit\",\n ),\n status: [\"DRAFT\", \"REJECTED\"].includes(app.status ?? \"\")\n ? \"passed\"\n : \"warning\",\n icon: <CheckCircle size={20} />,\n });\n\n return items;\n }, [app, isPackageType, publishedVersionCount, webhookCount, hasOAuthUrl, appId]);\n\n const passedCount = checklist.filter((i) => i.status === \"passed\").length;\n const failedCount = checklist.filter((i) => i.status === \"failed\").length;\n const warningCount = checklist.filter((i) => i.status === \"warning\").length;\n const isSubmittableStatus = [\"DRAFT\", \"REJECTED\"].includes(app?.status ?? \"\");\n const canSubmit =\n !loading &&\n !queryError &&\n failedCount === 0 &&\n !!app &&\n !isAlreadySubmitted &&\n isSubmittableStatus;\n\n const getStatusIcon = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return <CheckCircle size={20} className=\"text-status-success-text\" />;\n case \"failed\":\n return <XCircle size={20} className=\"text-status-error-text\" />;\n case \"warning\":\n return <AlertTriangle size={20} className=\"text-status-warning-text\" />;\n default:\n return (\n <div className=\"h-5 w-5 rounded-full border-2 border-border-default\" />\n );\n }\n };\n\n const getStatusBg = (status: ChecklistItem[\"status\"]) => {\n switch (status) {\n case \"passed\":\n return \"bg-status-success-bg-subtle border-border-subtle\";\n case \"failed\":\n return \"bg-status-error-bg-subtle border-border-subtle\";\n case \"warning\":\n return \"bg-status-warning-bg-subtle border-border-subtle\";\n default:\n return \"bg-bg-canvas border-border-subtle\";\n }\n };\n\n const handleSubmit = async () => {\n if (!appId) return;\n setSubmitting(true);\n setSubmitError(null);\n try {\n // Submit Application for devportal review (sets Application.status = SUBMITTED)\n const result = await submitApplication({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n if (result.error) throw result.error;\n\n // Also submit ApplicationForReview to set StoreProduct.status = PENDING_REVIEW\n // so it appears in the store admin review queue at /store/dashboard/submissions\n await submitApplicationForReview({\n variables: { id: appId, notes: notes.trim() || undefined },\n });\n\n setSubmitted(true);\n } catch (err) {\n setSubmitError(\n err instanceof Error\n ? err.message\n : tr(\"devportal.submitFailedDefault\", \"Failed to submit for review\"),\n );\n } finally {\n setSubmitting(false);\n }\n };\n\n if (loading) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.loadingApplicationDetails\",\n \"Loading application details...\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"animate-spin h-8 w-8 text-muted-foreground\" />\n </div>\n </PageLayout>\n );\n }\n\n if (queryError || !app) {\n return (\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={tr(\n \"devportal.couldNotLoadApplication\",\n \"Could not load application\",\n )}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <Alert\n variant=\"error\"\n title={tr(\n \"devportal.failedToLoadApplication\",\n \"Failed to load application\",\n )}\n >\n {queryError?.message ??\n tr(\"devportal.applicationNotFound\", \"Application not found\")}\n </Alert>\n </PageLayout>\n );\n }\n\n if (submitted) {\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n >\n <div className=\"flex flex-col items-center justify-center py-16 gap-6 text-center\">\n <div className=\"rounded-full bg-status-success-bg p-4\">\n <PartyPopper size={40} className=\"text-status-success-text\" />\n </div>\n <div className=\"space-y-2\">\n <h2 className=\"text-2xl font-bold\">\n {tr(\"devportal.submittedSuccessTitle\", \"Submitted for Review!\")}\n </h2>\n <p className=\"text-muted-foreground max-w-md\">\n {tr(\n \"devportal.submittedSuccessMsg\",\n \"Your app has been submitted to the marketplace review queue. You'll receive email notifications as the review progresses — typically 3–5 business days.\",\n )}\n </p>\n </div>\n <div className=\"rounded-lg border bg-muted/40 px-6 py-4 text-sm text-left space-y-2 max-w-md w-full\">\n <p className=\"font-medium\">What happens next:</p>\n <ul className=\"space-y-1 text-muted-foreground list-none\">\n <li className=\"flex items-start gap-2\"><CheckCircle size={14} className=\"mt-0.5 text-status-success-text shrink-0\" /> Our team reviews your submission</li>\n <li className=\"flex items-start gap-2\"><CheckCircle size={14} className=\"mt-0.5 text-status-success-text shrink-0\" /> You'll get an email on approval or if changes are needed</li>\n <li className=\"flex items-start gap-2\"><CheckCircle size={14} className=\"mt-0.5 text-status-success-text shrink-0\" /> Once approved, your app goes live in the marketplace</li>\n </ul>\n </div>\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n Back to App\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n }\n\n return (\n <PermissionGuard permission={DEVPORTAL_PERMISSIONS.APP_SUBMIT}>\n <PageLayout\n title={tr(\"devportal.publishToStoreTitle\", \"Publish to Store\")}\n description={`${tr(\"devportal.submitAppForReview\", \"Submit\")} \"${app.name}\" ${tr(\"devportal.forReviewAndPublication\", \"for review and publication\")}`}\n backLink={`/apps/${appId}`}\n backLabel={tr(\"devportal.backToApplication\", \"Back to Application\")}\n actions={\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/listing`)}\n className=\"inline-flex items-center gap-2 rounded-md border px-3 py-2 text-sm font-medium hover:bg-muted\"\n >\n <Eye size={16} />\n {tr(\"devportal.previewListing\", \"Preview Listing\")}\n </button>\n }\n >\n {isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.alreadySubmittedTitle\", \"Already Submitted\")}\n >\n {tr(\"devportal.alreadySubmittedMsg1\", \"This app is currently in\")}{\" \"}\n <strong>{app.status}</strong>{\" \"}\n {tr(\n \"devportal.alreadySubmittedMsg2\",\n \"state and cannot be re-submitted until the review process is complete or the app is rejected.\",\n )}\n </Alert>\n )}\n\n {/* Progress Summary */}\n <div className=\"rounded-lg border bg-card p-6\">\n <h2 className=\"text-lg font-semibold\">\n {tr(\"devportal.preSubmissionChecklist\", \"Pre-submission Checklist\")}\n </h2>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n {tr(\n \"devportal.completeAllRequiredItems\",\n \"Complete all required items before submitting for review\",\n )}\n </p>\n <div className=\"mt-4 flex gap-6\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle size={20} className=\"text-status-success-text\" />\n <span>\n {passedCount} {tr(\"devportal.passed\", \"Passed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <XCircle size={20} className=\"text-status-error-text\" />\n <span>\n {failedCount} {tr(\"devportal.failed\", \"Failed\")}\n </span>\n </div>\n <div className=\"flex items-center gap-2\">\n <AlertTriangle size={20} className=\"text-status-warning-text\" />\n <span>\n {warningCount} {tr(\"devportal.warnings\", \"Warnings\")}\n </span>\n </div>\n </div>\n </div>\n\n {/* Checklist Items */}\n <PageSection>\n <div className=\"space-y-3\">\n {checklist.map((item) => (\n <div\n key={item.id}\n className={`flex items-center gap-4 rounded-lg border p-4 ${getStatusBg(item.status)}`}\n >\n <div className=\"rounded-lg bg-background p-2\">{item.icon}</div>\n <div className=\"flex-1\">\n <p className=\"font-medium\">{item.label}</p>\n <p className=\"text-sm text-muted-foreground\">\n {item.description}\n </p>\n {item.status !== \"passed\" && item.actionPath && (\n <button\n type=\"button\"\n onClick={() => navigate?.(`${basePath}${item.actionPath}`)}\n className=\"mt-1 inline-flex items-center gap-1 text-xs text-primary hover:underline\"\n >\n {item.actionLabel ?? \"Fix this\"} <ArrowRight size={11} />\n </button>\n )}\n </div>\n {getStatusIcon(item.status)}\n </div>\n ))}\n </div>\n </PageSection>\n\n {/* Submission Notes */}\n {!isAlreadySubmitted && (\n <PageSection\n title={tr(\"devportal.notesForReviewerTitle\", \"Notes for Reviewer\")}\n description={tr(\n \"devportal.notesForReviewerDesc\",\n \"Optional message to the review team\",\n )}\n >\n <textarea\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder={tr(\n \"devportal.notesForReviewerPlaceholder\",\n \"Describe what your app does, any special review considerations, or testing instructions...\",\n )}\n rows={4}\n maxLength={1000}\n className=\"w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring resize-none\"\n />\n <p className=\"mt-1 text-xs text-muted-foreground text-right\">\n {notes.length}/1000\n </p>\n </PageSection>\n )}\n\n {/* Alerts */}\n {submitError && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.submissionFailedTitle\", \"Submission Failed\")}\n >\n {submitError}\n </Alert>\n )}\n\n {failedCount > 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"error\"\n title={tr(\"devportal.cannotSubmitTitle\", \"Cannot Submit Yet\")}\n >\n {tr(\"devportal.pleaseFixItems1\", \"Please fix\")} {failedCount}{\" \"}\n {tr(\n \"devportal.pleaseFixItems2\",\n \"required item(s) before submitting for review.\",\n )}\n <div className=\"mt-2 flex flex-wrap gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToMarketplaceListing\",\n \"Update marketplace listing →\",\n )}\n </button>\n {isPackageType && publishedVersionCount === 0 && (\n <button\n onClick={() =>\n navigate?.(`${basePath}/apps/${appId}/versions`)\n }\n className=\"text-sm underline hover:no-underline\"\n >\n {tr(\n \"devportal.goToVersions\",\n \"Add a published version →\",\n )}\n </button>\n )}\n {isApiIntegration && !hasOAuthUrl && (\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}/edit`)}\n className=\"text-sm underline hover:no-underline\"\n >\n Configure OAuth endpoints →\n </button>\n )}\n {isApiIntegration && webhookCount === 0 && (\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}?tab=webhooks`)}\n className=\"text-sm underline hover:no-underline\"\n >\n Add a webhook →\n </button>\n )}\n </div>\n </Alert>\n )}\n\n {warningCount > 0 && failedCount === 0 && !isAlreadySubmitted && (\n <Alert\n variant=\"warning\"\n title={tr(\"devportal.warningsTitle\", \"Warnings\")}\n >\n {tr(\"devportal.warningsMsg1\", \"You have\")} {warningCount}{\" \"}\n {tr(\n \"devportal.warningsMsg2\",\n \"warning(s). While you can submit, addressing these may improve your app's chances of approval.\",\n )}\n </Alert>\n )}\n\n {/* Review Process Info */}\n <PageSection\n title={tr(\"devportal.reviewProcessTitle\", \"Review Process\")}\n >\n <div className=\"rounded-lg border bg-muted/50 p-4\">\n <ul className=\"space-y-2 text-sm\">\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo1\",\n \"Review typically takes 3-5 business days\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo2\",\n \"You'll receive notifications about review status changes\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo3\",\n \"If changes are requested, you can resubmit without losing your place in the queue\",\n )}\n </span>\n </li>\n <li className=\"flex items-start gap-2\">\n <CheckCircle size={16} className=\"mt-0.5 text-primary\" />\n <span>\n {tr(\n \"devportal.reviewProcessInfo4\",\n \"Once approved and published, your app will be visible in the marketplace\",\n )}\n </span>\n </li>\n </ul>\n </div>\n </PageSection>\n\n {/* Actions */}\n <div className=\"flex gap-3\">\n <button\n onClick={() => navigate?.(`${basePath}/apps/${appId}`)}\n className=\"rounded-md border px-4 py-2 text-sm font-medium hover:bg-muted\"\n >\n {tr(\"devportal.cancelButton\", \"Cancel\")}\n </button>\n <button\n onClick={handleSubmit}\n disabled={!canSubmit || submitting || !submitPerm.allowed}\n aria-disabled={!canSubmit || submitting || !submitPerm.allowed}\n title={\n !submitPerm.allowed\n ? tr(\n \"devportal.common.noPermission\",\n \"You do not have permission to perform this action\",\n )\n : undefined\n }\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary\"\n >\n {submitting ? (\n <>\n <Loader2 size={16} className=\"animate-spin\" />\n {tr(\"devportal.submittingButton\", \"Submitting...\")}\n </>\n ) : (\n <>\n <Send size={16} />\n {tr(\"devportal.submitForReviewButton\", \"Submit for Review\")}\n </>\n )}\n </button>\n </div>\n </PageLayout>\n </PermissionGuard>\n );\n};\n"],"mappings":"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"}
|