@burdenoff/microfe-devportal 2026.1108.2 → 2026.1109.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/devportal/DevportalRoot.js +68 -61
- package/dist/devportal/DevportalRoot.js.map +1 -1
- package/dist/devportal/DevportalRoutes.js +137 -133
- package/dist/devportal/DevportalRoutes.js.map +1 -1
- package/dist/devportal/components/SectionNav.js.map +1 -1
- package/dist/devportal/pages/ApplicationVersionsPage.js +229 -217
- package/dist/devportal/pages/ApplicationVersionsPage.js.map +1 -1
- package/dist/devportal/pages/NodeLifecyclePage.js +2 -0
- package/dist/devportal/pages/NodeLifecyclePage.js.map +1 -1
- package/dist/devportal/pages/TimeCampusAppletsPage.d.ts +2 -0
- package/dist/devportal/pages/TimeCampusAppletsPage.js +490 -0
- package/dist/devportal/pages/TimeCampusAppletsPage.js.map +1 -0
- package/dist/devportal/utils/constants.js +5 -1
- package/dist/devportal/utils/constants.js.map +1 -1
- package/dist/devportal/utils/timecampusApplets.d.ts +98 -0
- package/dist/devportal/utils/timecampusApplets.js +130 -0
- package/dist/devportal/utils/timecampusApplets.js.map +1 -0
- package/dist/generated/global-operations.d.ts +46 -5
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +3901 -638
- package/dist/generated/global-types.js.map +1 -1
- package/dist/generated/wspace-operations.d.ts +678 -2
- package/dist/generated/wspace-operations.js +203 -4
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.d.ts +166197 -34713
- package/dist/translations/en.d.ts +46 -0
- package/dist/translations/en.js +47 -1
- package/dist/translations/en.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
import { PageLayout as e, PageSection as t } from "../components/PageLayout.js";
|
|
2
|
+
import { EmptyState as n } from "../components/EmptyState.js";
|
|
3
|
+
import { LoadingState as r } from "../components/LoadingState.js";
|
|
4
|
+
import { StatusBadge as i } from "../components/StatusBadge.js";
|
|
5
|
+
import { useDevportal as a } from "../providers/DevportalProvider.js";
|
|
6
|
+
import { useTr as o } from "../utils/i18n.js";
|
|
7
|
+
import { TIMECAMPUS_APPLETS_DOCS_URL as s, TIMECAMPUS_MANIFEST_DOCS_URL as c, TIMECAMPUS_SAMPLE_WIDGET_URL as l, canAddVersion as u, canEditVersion as d, canWithdrawFromMarketplace as f, errorText as p, formatDate as m, manifestForNextVersion as h, manifestText as g, marketplaceOffer as _, parseManifestText as v, starterManifest as y, versionAction as b } from "../utils/timecampusApplets.js";
|
|
8
|
+
import { useDevportalAddTimeCampusAppletVersionMutation as x, useDevportalCreateTimeCampusAppletMutation as S, useDevportalSubmitTimeCampusAppletToMarketplaceMutation as C, useDevportalSubmitTimeCampusAppletVersionMutation as w, useDevportalTimeCampusAppletsQuery as T, useDevportalUpdateTimeCampusAppletVersionMutation as E, useDevportalValidateTimeCampusAppletManifestLazyQuery as D, useDevportalWithdrawTimeCampusAppletFromMarketplaceMutation as O, useDevportalWithdrawTimeCampusAppletVersionMutation as k, useMyWorkspacesQuery as A } from "../../generated/wspace-operations.js";
|
|
9
|
+
import { useState as j } from "react";
|
|
10
|
+
import { BookOpen as M, CheckCircle2 as N, ExternalLink as P, FilePlus2 as F, Globe as I, Pencil as L, Puzzle as R, Send as z, Undo2 as B, Upload as V } from "lucide-react";
|
|
11
|
+
import { Fragment as H, jsx as U, jsxs as W } from "react/jsx-runtime";
|
|
12
|
+
import { GlassCard as G } from "@burdenoff/fe-libs/ui";
|
|
13
|
+
import { useSafeGatewayClient as K } from "@burdenoff/fe-libs/shared/graphql";
|
|
14
|
+
// src/devportal/pages/TimeCampusAppletsPage.tsx
|
|
15
|
+
var q = ["DevportalTimeCampusApplets"], J = "inline-flex items-center justify-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50", Y = "inline-flex items-center justify-center gap-1.5 rounded-md border border-border-subtle bg-bg-surface px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-surface-hover disabled:opacity-50";
|
|
16
|
+
function X(e) {
|
|
17
|
+
return e.kind === "new" ? "new" : e.kind === "version" ? `version-${e.appletId}` : `edit-${e.versionId}`;
|
|
18
|
+
}
|
|
19
|
+
var ee = ({ target: e, initialText: t, onClose: n, onSaved: r }) => {
|
|
20
|
+
let i = o(), a = K("workspace") ?? void 0, [s, l] = j(t), [u, d] = j([]), [f, m] = j(!1), [h, { loading: g }] = D({
|
|
21
|
+
client: a,
|
|
22
|
+
fetchPolicy: "no-cache"
|
|
23
|
+
}), [_, { loading: y }] = S({
|
|
24
|
+
client: a,
|
|
25
|
+
refetchQueries: q,
|
|
26
|
+
awaitRefetchQueries: !0
|
|
27
|
+
}), [b, { loading: C }] = x({
|
|
28
|
+
client: a,
|
|
29
|
+
refetchQueries: q,
|
|
30
|
+
awaitRefetchQueries: !0
|
|
31
|
+
}), [w, { loading: T }] = E({
|
|
32
|
+
client: a,
|
|
33
|
+
refetchQueries: q,
|
|
34
|
+
awaitRefetchQueries: !0
|
|
35
|
+
}), O = y || C || T, k = () => {
|
|
36
|
+
let e = v(s);
|
|
37
|
+
return e.ok ? e.manifest : (d([e.error]), m(!1), null);
|
|
38
|
+
}, A = async () => {
|
|
39
|
+
let e = k();
|
|
40
|
+
if (e) try {
|
|
41
|
+
let { data: t } = await h({ variables: { manifest: e } }), n = t?.validateTimeCampusAppletManifest;
|
|
42
|
+
d(n?.errors ?? []), m(n?.valid === !0);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
d([p(e)]), m(!1);
|
|
45
|
+
}
|
|
46
|
+
}, M = async () => {
|
|
47
|
+
let t = k();
|
|
48
|
+
if (t) try {
|
|
49
|
+
e.kind === "new" ? (await _({ variables: { manifest: t } }), r(i("devportal.timecampusApplets.registered", "Applet registered as a draft. Submit it for review when it is ready."))) : e.kind === "edit" ? (await w({ variables: {
|
|
50
|
+
versionId: e.versionId,
|
|
51
|
+
manifest: t
|
|
52
|
+
} }), r(i("devportal.timecampusApplets.versionUpdated", "Manifest saved. The version is a draft."))) : (await b({ variables: {
|
|
53
|
+
appletId: e.appletId,
|
|
54
|
+
manifest: t
|
|
55
|
+
} }), r(i("devportal.timecampusApplets.versionAdded", "New version saved as a draft.")));
|
|
56
|
+
} catch (e) {
|
|
57
|
+
d([p(e)]), m(!1);
|
|
58
|
+
}
|
|
59
|
+
}, F = e.kind === "new" ? i("devportal.timecampusApplets.registerTitle", "Register an applet") : e.kind === "edit" ? i("devportal.timecampusApplets.editVersionTitle", "Edit v{{version}} of {{name}}", {
|
|
60
|
+
name: e.appletName,
|
|
61
|
+
version: e.version
|
|
62
|
+
}) : i("devportal.timecampusApplets.newVersionTitle", "Upload a new version of {{name}}", { name: e.appletName });
|
|
63
|
+
return /* @__PURE__ */ W(G, {
|
|
64
|
+
className: "flex flex-col gap-3 p-4",
|
|
65
|
+
"data-testid": "tc-manifest-editor",
|
|
66
|
+
children: [
|
|
67
|
+
/* @__PURE__ */ W("div", {
|
|
68
|
+
className: "flex flex-wrap items-center justify-between gap-2",
|
|
69
|
+
children: [/* @__PURE__ */ U("h2", {
|
|
70
|
+
className: "text-base font-semibold text-text-primary",
|
|
71
|
+
children: F
|
|
72
|
+
}), /* @__PURE__ */ W("a", {
|
|
73
|
+
href: c,
|
|
74
|
+
target: "_blank",
|
|
75
|
+
rel: "noopener noreferrer",
|
|
76
|
+
className: "inline-flex items-center gap-1 text-sm text-primary hover:underline",
|
|
77
|
+
children: [i("devportal.timecampusApplets.manifestReference", "Manifest reference"), /* @__PURE__ */ U(P, {
|
|
78
|
+
className: "h-3.5 w-3.5",
|
|
79
|
+
"aria-hidden": "true"
|
|
80
|
+
})]
|
|
81
|
+
})]
|
|
82
|
+
}),
|
|
83
|
+
/* @__PURE__ */ W("label", {
|
|
84
|
+
className: "flex flex-col gap-1 text-sm text-text-secondary",
|
|
85
|
+
children: [i("devportal.timecampusApplets.manifestLabel", "Manifest (JSON)"), /* @__PURE__ */ U("textarea", {
|
|
86
|
+
value: s,
|
|
87
|
+
onChange: (e) => {
|
|
88
|
+
l(e.target.value), m(!1);
|
|
89
|
+
},
|
|
90
|
+
spellCheck: !1,
|
|
91
|
+
rows: 18,
|
|
92
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-sunken p-3 font-mono text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg",
|
|
93
|
+
"data-testid": "tc-manifest-text"
|
|
94
|
+
})]
|
|
95
|
+
}),
|
|
96
|
+
u.length > 0 && /* @__PURE__ */ U("ul", {
|
|
97
|
+
className: "list-disc space-y-1 rounded-md bg-status-error-bg-subtle py-2 pl-6 pr-3 text-xs text-status-error-text",
|
|
98
|
+
role: "alert",
|
|
99
|
+
"data-testid": "tc-manifest-problems",
|
|
100
|
+
children: u.map((e, t) => /* @__PURE__ */ U("li", { children: e }, `${t}-${e}`))
|
|
101
|
+
}),
|
|
102
|
+
f && u.length === 0 && /* @__PURE__ */ W("p", {
|
|
103
|
+
className: "flex items-center gap-1.5 text-xs text-status-success-text",
|
|
104
|
+
"data-testid": "tc-manifest-valid",
|
|
105
|
+
children: [/* @__PURE__ */ U(N, {
|
|
106
|
+
className: "h-4 w-4",
|
|
107
|
+
"aria-hidden": "true"
|
|
108
|
+
}), i("devportal.timecampusApplets.manifestValid", "The manifest is valid.")]
|
|
109
|
+
}),
|
|
110
|
+
/* @__PURE__ */ W("div", {
|
|
111
|
+
className: "flex flex-wrap justify-end gap-2",
|
|
112
|
+
children: [
|
|
113
|
+
/* @__PURE__ */ U("button", {
|
|
114
|
+
type: "button",
|
|
115
|
+
className: Y,
|
|
116
|
+
onClick: n,
|
|
117
|
+
children: i("devportal.cancel", "Cancel")
|
|
118
|
+
}),
|
|
119
|
+
/* @__PURE__ */ W("button", {
|
|
120
|
+
type: "button",
|
|
121
|
+
className: Y,
|
|
122
|
+
onClick: () => void A(),
|
|
123
|
+
disabled: g || O,
|
|
124
|
+
children: [/* @__PURE__ */ U(N, {
|
|
125
|
+
className: "h-4 w-4",
|
|
126
|
+
"aria-hidden": "true"
|
|
127
|
+
}), i("devportal.timecampusApplets.validate", "Validate")]
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ W("button", {
|
|
130
|
+
type: "button",
|
|
131
|
+
className: J,
|
|
132
|
+
onClick: () => void M(),
|
|
133
|
+
disabled: O,
|
|
134
|
+
"data-testid": "tc-manifest-save",
|
|
135
|
+
children: [/* @__PURE__ */ U(V, {
|
|
136
|
+
className: "h-4 w-4",
|
|
137
|
+
"aria-hidden": "true"
|
|
138
|
+
}), e.kind === "new" ? i("devportal.timecampusApplets.register", "Register applet") : i("devportal.timecampusApplets.uploadVersion", "Upload version")]
|
|
139
|
+
})
|
|
140
|
+
]
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
}, te = ({ applet: e, busy: t, onNewVersion: n, onEditVersion: r, onSubmitVersion: a, onWithdrawVersion: s, onOffer: c, onWithdrawOffer: l }) => {
|
|
145
|
+
let p = o(), h = e.latestVersion, g = b(e), v = _(e), y = e.marketplace, x = y?.latestSubmission;
|
|
146
|
+
return /* @__PURE__ */ W(G, {
|
|
147
|
+
className: "flex flex-col gap-4 p-4",
|
|
148
|
+
"data-testid": `tc-applet-${e.key}`,
|
|
149
|
+
children: [/* @__PURE__ */ W("div", {
|
|
150
|
+
className: "flex flex-wrap items-start justify-between gap-3",
|
|
151
|
+
children: [/* @__PURE__ */ W("div", {
|
|
152
|
+
className: "min-w-0",
|
|
153
|
+
children: [
|
|
154
|
+
/* @__PURE__ */ W("div", {
|
|
155
|
+
className: "flex flex-wrap items-center gap-2",
|
|
156
|
+
children: [/* @__PURE__ */ U("h3", {
|
|
157
|
+
className: "text-base font-semibold text-text-primary",
|
|
158
|
+
children: e.name
|
|
159
|
+
}), /* @__PURE__ */ U(i, { status: e.status })]
|
|
160
|
+
}),
|
|
161
|
+
/* @__PURE__ */ U("p", {
|
|
162
|
+
className: "mt-0.5 font-mono text-xs text-text-tertiary",
|
|
163
|
+
children: e.key
|
|
164
|
+
}),
|
|
165
|
+
/* @__PURE__ */ U("p", {
|
|
166
|
+
className: "mt-1 text-sm text-text-secondary",
|
|
167
|
+
children: e.description
|
|
168
|
+
})
|
|
169
|
+
]
|
|
170
|
+
}), /* @__PURE__ */ W("button", {
|
|
171
|
+
type: "button",
|
|
172
|
+
className: Y,
|
|
173
|
+
onClick: n,
|
|
174
|
+
disabled: t || !u(e),
|
|
175
|
+
title: u(e) ? void 0 : p("devportal.timecampusApplets.openVersionHint", "Finish or withdraw the open version first."),
|
|
176
|
+
children: [/* @__PURE__ */ U(F, {
|
|
177
|
+
className: "h-4 w-4",
|
|
178
|
+
"aria-hidden": "true"
|
|
179
|
+
}), p("devportal.timecampusApplets.newVersion", "New version")]
|
|
180
|
+
})]
|
|
181
|
+
}), /* @__PURE__ */ W("div", {
|
|
182
|
+
className: "grid gap-3 md:grid-cols-2",
|
|
183
|
+
children: [/* @__PURE__ */ W("div", {
|
|
184
|
+
className: "flex flex-col gap-2 rounded-md border border-border-subtle bg-bg-sunken/40 p-3",
|
|
185
|
+
"data-testid": `tc-applet-version-${e.key}`,
|
|
186
|
+
children: [
|
|
187
|
+
/* @__PURE__ */ W("div", {
|
|
188
|
+
className: "flex flex-wrap items-center gap-2",
|
|
189
|
+
children: [/* @__PURE__ */ W("p", {
|
|
190
|
+
className: "text-sm font-medium text-text-primary",
|
|
191
|
+
children: [
|
|
192
|
+
p("devportal.timecampusApplets.latestVersion", "Latest version"),
|
|
193
|
+
" ",
|
|
194
|
+
"v",
|
|
195
|
+
h.version
|
|
196
|
+
]
|
|
197
|
+
}), /* @__PURE__ */ U(i, { status: h.status })]
|
|
198
|
+
}),
|
|
199
|
+
e.liveVersion && e.liveVersion.id !== h.id && /* @__PURE__ */ U("p", {
|
|
200
|
+
className: "text-xs text-text-secondary",
|
|
201
|
+
children: p("devportal.timecampusApplets.liveInWorkspace", "v{{version}} is live in your workspace.", { version: e.liveVersion.version })
|
|
202
|
+
}),
|
|
203
|
+
h.submittedAt && /* @__PURE__ */ W("p", {
|
|
204
|
+
className: "text-xs text-text-secondary",
|
|
205
|
+
children: [
|
|
206
|
+
p("devportal.timecampusApplets.submitted", "Submitted"),
|
|
207
|
+
" ",
|
|
208
|
+
m(h.submittedAt)
|
|
209
|
+
]
|
|
210
|
+
}),
|
|
211
|
+
h.reviewNotes && /* @__PURE__ */ W("p", {
|
|
212
|
+
className: "text-xs text-text-secondary",
|
|
213
|
+
children: [
|
|
214
|
+
/* @__PURE__ */ W("span", {
|
|
215
|
+
className: "font-medium text-text-primary",
|
|
216
|
+
children: [p("devportal.timecampusApplets.reviewNotes", "Review notes"), ":"]
|
|
217
|
+
}),
|
|
218
|
+
" ",
|
|
219
|
+
h.reviewNotes
|
|
220
|
+
]
|
|
221
|
+
}),
|
|
222
|
+
h.suspendedReason && /* @__PURE__ */ U("p", {
|
|
223
|
+
className: "text-xs text-status-warning-text",
|
|
224
|
+
children: h.suspendedReason
|
|
225
|
+
}),
|
|
226
|
+
d(e) && /* @__PURE__ */ W("button", {
|
|
227
|
+
type: "button",
|
|
228
|
+
className: Y,
|
|
229
|
+
onClick: r,
|
|
230
|
+
disabled: t,
|
|
231
|
+
"data-testid": `tc-edit-version-${e.key}`,
|
|
232
|
+
children: [/* @__PURE__ */ U(L, {
|
|
233
|
+
className: "h-4 w-4",
|
|
234
|
+
"aria-hidden": "true"
|
|
235
|
+
}), p("devportal.timecampusApplets.editManifest", "Edit manifest")]
|
|
236
|
+
}),
|
|
237
|
+
g.kind === "submit" && /* @__PURE__ */ W("button", {
|
|
238
|
+
type: "button",
|
|
239
|
+
className: J,
|
|
240
|
+
onClick: () => a(g.versionId),
|
|
241
|
+
disabled: t,
|
|
242
|
+
children: [/* @__PURE__ */ U(z, {
|
|
243
|
+
className: "h-4 w-4",
|
|
244
|
+
"aria-hidden": "true"
|
|
245
|
+
}), p("devportal.timecampusApplets.submitForReview", "Submit for review")]
|
|
246
|
+
}),
|
|
247
|
+
g.kind === "withdraw" && /* @__PURE__ */ W("button", {
|
|
248
|
+
type: "button",
|
|
249
|
+
className: Y,
|
|
250
|
+
onClick: () => s(g.versionId),
|
|
251
|
+
disabled: t,
|
|
252
|
+
children: [/* @__PURE__ */ U(B, {
|
|
253
|
+
className: "h-4 w-4",
|
|
254
|
+
"aria-hidden": "true"
|
|
255
|
+
}), p("devportal.timecampusApplets.withdrawReview", "Withdraw from review")]
|
|
256
|
+
})
|
|
257
|
+
]
|
|
258
|
+
}), /* @__PURE__ */ W("div", {
|
|
259
|
+
className: "flex flex-col gap-2 rounded-md border border-border-subtle bg-bg-sunken/40 p-3",
|
|
260
|
+
"data-testid": `tc-applet-marketplace-${e.key}`,
|
|
261
|
+
children: [
|
|
262
|
+
/* @__PURE__ */ W("div", {
|
|
263
|
+
className: "flex flex-wrap items-center gap-2",
|
|
264
|
+
children: [
|
|
265
|
+
/* @__PURE__ */ U(I, {
|
|
266
|
+
className: "h-4 w-4 text-text-tertiary",
|
|
267
|
+
"aria-hidden": "true"
|
|
268
|
+
}),
|
|
269
|
+
/* @__PURE__ */ U("p", {
|
|
270
|
+
className: "text-sm font-medium text-text-primary",
|
|
271
|
+
children: p("devportal.timecampusApplets.marketplace", "Public marketplace")
|
|
272
|
+
}),
|
|
273
|
+
y ? /* @__PURE__ */ U(i, { status: y.status }) : /* @__PURE__ */ U(i, { status: "NOT_LISTED" })
|
|
274
|
+
]
|
|
275
|
+
}),
|
|
276
|
+
y?.liveSubmission && /* @__PURE__ */ U("p", {
|
|
277
|
+
className: "text-xs text-text-secondary",
|
|
278
|
+
children: p("devportal.timecampusApplets.certifiedLive", "v{{version}} is certified and live in the marketplace.", { version: y.liveSubmission.version })
|
|
279
|
+
}),
|
|
280
|
+
x && /* @__PURE__ */ W("p", {
|
|
281
|
+
className: "flex flex-wrap items-center gap-2 text-xs text-text-secondary",
|
|
282
|
+
children: [p("devportal.timecampusApplets.latestSubmission", "Latest submission v{{version}}", { version: x.version }), /* @__PURE__ */ U(i, { status: x.status })]
|
|
283
|
+
}),
|
|
284
|
+
x?.reviewNotes && /* @__PURE__ */ W("p", {
|
|
285
|
+
className: "text-xs text-text-secondary",
|
|
286
|
+
children: [
|
|
287
|
+
/* @__PURE__ */ W("span", {
|
|
288
|
+
className: "font-medium text-text-primary",
|
|
289
|
+
children: [p("devportal.timecampusApplets.certificationNotes", "Certification notes"), ":"]
|
|
290
|
+
}),
|
|
291
|
+
" ",
|
|
292
|
+
x.reviewNotes
|
|
293
|
+
]
|
|
294
|
+
}),
|
|
295
|
+
y?.suspendedReason && /* @__PURE__ */ U("p", {
|
|
296
|
+
className: "text-xs text-status-warning-text",
|
|
297
|
+
children: y.suspendedReason
|
|
298
|
+
}),
|
|
299
|
+
f(e) ? /* @__PURE__ */ W("button", {
|
|
300
|
+
type: "button",
|
|
301
|
+
className: Y,
|
|
302
|
+
onClick: l,
|
|
303
|
+
disabled: t,
|
|
304
|
+
children: [/* @__PURE__ */ U(B, {
|
|
305
|
+
className: "h-4 w-4",
|
|
306
|
+
"aria-hidden": "true"
|
|
307
|
+
}), p("devportal.timecampusApplets.withdrawSubmission", "Withdraw submission")]
|
|
308
|
+
}) : v.canOffer ? /* @__PURE__ */ W("button", {
|
|
309
|
+
type: "button",
|
|
310
|
+
className: J,
|
|
311
|
+
onClick: c,
|
|
312
|
+
disabled: t,
|
|
313
|
+
children: [/* @__PURE__ */ U(I, {
|
|
314
|
+
className: "h-4 w-4",
|
|
315
|
+
"aria-hidden": "true"
|
|
316
|
+
}), p("devportal.timecampusApplets.offer", "Offer v{{version}} to the marketplace", { version: v.version })]
|
|
317
|
+
}) : /* @__PURE__ */ U("p", {
|
|
318
|
+
className: "text-xs text-text-tertiary",
|
|
319
|
+
children: v.reason
|
|
320
|
+
})
|
|
321
|
+
]
|
|
322
|
+
})]
|
|
323
|
+
})]
|
|
324
|
+
});
|
|
325
|
+
}, ne = () => {
|
|
326
|
+
let e = o(), t = [
|
|
327
|
+
{
|
|
328
|
+
href: c,
|
|
329
|
+
label: e("devportal.timecampusApplets.docsManifest", "Applet manifest reference"),
|
|
330
|
+
icon: M
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
href: l,
|
|
334
|
+
label: e("devportal.timecampusApplets.docsSample", "Sample widget (view source)"),
|
|
335
|
+
icon: R
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
href: s,
|
|
339
|
+
label: e("devportal.timecampusApplets.docsApplets", "How applets work in TimeCampus"),
|
|
340
|
+
icon: I
|
|
341
|
+
}
|
|
342
|
+
];
|
|
343
|
+
return /* @__PURE__ */ U("ul", {
|
|
344
|
+
className: "flex flex-wrap gap-2",
|
|
345
|
+
"data-testid": "tc-applet-resources",
|
|
346
|
+
children: t.map(({ href: e, label: t, icon: n }) => /* @__PURE__ */ U("li", { children: /* @__PURE__ */ W("a", {
|
|
347
|
+
href: e,
|
|
348
|
+
target: "_blank",
|
|
349
|
+
rel: "noopener noreferrer",
|
|
350
|
+
className: Y,
|
|
351
|
+
children: [
|
|
352
|
+
/* @__PURE__ */ U(n, {
|
|
353
|
+
className: "h-4 w-4",
|
|
354
|
+
"aria-hidden": "true"
|
|
355
|
+
}),
|
|
356
|
+
t,
|
|
357
|
+
/* @__PURE__ */ U(P, {
|
|
358
|
+
className: "h-3.5 w-3.5",
|
|
359
|
+
"aria-hidden": "true"
|
|
360
|
+
})
|
|
361
|
+
]
|
|
362
|
+
}) }, e))
|
|
363
|
+
});
|
|
364
|
+
}, Z = () => {
|
|
365
|
+
let i = o(), { workspaceId: s } = a(), l = K("workspace"), u = l ?? void 0, d = !!s && !!l, [f, m] = j(null), _ = f && f.workspaceId === s ? f : null, v = (e, t) => {
|
|
366
|
+
s && (x(null), m({
|
|
367
|
+
target: e,
|
|
368
|
+
text: t,
|
|
369
|
+
workspaceId: s
|
|
370
|
+
}));
|
|
371
|
+
}, [b, x] = j(null), { data: S, loading: E, error: D } = T({
|
|
372
|
+
client: u,
|
|
373
|
+
skip: !d,
|
|
374
|
+
fetchPolicy: "cache-and-network"
|
|
375
|
+
}), { data: M } = A({
|
|
376
|
+
client: u,
|
|
377
|
+
skip: !d,
|
|
378
|
+
variables: { pagination: {
|
|
379
|
+
limit: 100,
|
|
380
|
+
offset: 0
|
|
381
|
+
} }
|
|
382
|
+
}), N = (M?.myWorkspaces?.items ?? []).find((e) => e.id === s)?.name ?? null, P = {
|
|
383
|
+
client: u,
|
|
384
|
+
refetchQueries: q,
|
|
385
|
+
awaitRefetchQueries: !0
|
|
386
|
+
}, [I, L] = w(P), [z, B] = k(P), [V, G] = C(P), [Y, Z] = O(P), re = L.loading || B.loading || G.loading || Z.loading, Q = async (e, t) => {
|
|
387
|
+
x(null);
|
|
388
|
+
try {
|
|
389
|
+
await e(), x({
|
|
390
|
+
tone: "success",
|
|
391
|
+
text: t
|
|
392
|
+
});
|
|
393
|
+
} catch (e) {
|
|
394
|
+
x({
|
|
395
|
+
tone: "error",
|
|
396
|
+
text: p(e)
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}, $ = S?.timeCampusMyThirdPartyApplets ?? [];
|
|
400
|
+
return /* @__PURE__ */ W(e, {
|
|
401
|
+
title: i("devportal.timecampusApplets.title", "TimeCampus applets"),
|
|
402
|
+
description: i("devportal.timecampusApplets.description", "Build widgets for TimeCampus, publish them in your workspace and offer them to every TimeCampus workspace."),
|
|
403
|
+
purpose: i("devportal.timecampusApplets.purpose", "Register an applet from a JSON manifest, upload new versions, send each version to your workspace's reviewers, and once it is live offer it to the public marketplace. The TimeCampus platform team certifies every marketplace version before other workspaces can install it."),
|
|
404
|
+
purposeLearnMoreHref: c,
|
|
405
|
+
actions: d ? /* @__PURE__ */ W("button", {
|
|
406
|
+
type: "button",
|
|
407
|
+
className: J,
|
|
408
|
+
onClick: () => v({ kind: "new" }, y()),
|
|
409
|
+
"data-testid": "tc-register-applet",
|
|
410
|
+
children: [/* @__PURE__ */ U(F, {
|
|
411
|
+
className: "h-4 w-4",
|
|
412
|
+
"aria-hidden": "true"
|
|
413
|
+
}), i("devportal.timecampusApplets.register", "Register applet")]
|
|
414
|
+
}) : void 0,
|
|
415
|
+
children: [/* @__PURE__ */ U(t, {
|
|
416
|
+
title: i("devportal.timecampusApplets.resources", "Build an applet"),
|
|
417
|
+
children: /* @__PURE__ */ U(ne, {})
|
|
418
|
+
}), d ? /* @__PURE__ */ W(H, { children: [
|
|
419
|
+
/* @__PURE__ */ U("p", {
|
|
420
|
+
className: "text-sm text-text-secondary",
|
|
421
|
+
"data-testid": "tc-workspace",
|
|
422
|
+
children: N ? i("devportal.timecampusApplets.inWorkspace", "Your applets in {{workspace}}. Switch workspace with the context switcher.", { workspace: N }) : i("devportal.timecampusApplets.inActiveWorkspace", "Your applets in the active workspace. Switch workspace with the context switcher.")
|
|
423
|
+
}),
|
|
424
|
+
b && /* @__PURE__ */ U("p", {
|
|
425
|
+
role: b.tone === "error" ? "alert" : "status",
|
|
426
|
+
className: b.tone === "error" ? "rounded-md bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text" : "rounded-md bg-status-success-bg-subtle px-3 py-2 text-sm text-status-success-text",
|
|
427
|
+
"data-testid": "tc-feedback",
|
|
428
|
+
children: b.text
|
|
429
|
+
}),
|
|
430
|
+
_ && /* @__PURE__ */ U(ee, {
|
|
431
|
+
target: _.target,
|
|
432
|
+
initialText: _.text,
|
|
433
|
+
onClose: () => m(null),
|
|
434
|
+
onSaved: (e) => {
|
|
435
|
+
m(null), x({
|
|
436
|
+
tone: "success",
|
|
437
|
+
text: e
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}, `${_.workspaceId}-${X(_.target)}`),
|
|
441
|
+
/* @__PURE__ */ U(t, {
|
|
442
|
+
title: i("devportal.timecampusApplets.yourApplets", "Your applets"),
|
|
443
|
+
"data-testid": "tc-applet-list",
|
|
444
|
+
children: E && $.length === 0 ? /* @__PURE__ */ U(r, { message: i("devportal.timecampusApplets.loading", "Loading your applets...") }) : D && $.length === 0 ? /* @__PURE__ */ U("p", {
|
|
445
|
+
role: "alert",
|
|
446
|
+
className: "rounded-md bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text",
|
|
447
|
+
children: p(D)
|
|
448
|
+
}) : $.length === 0 ? /* @__PURE__ */ U(n, {
|
|
449
|
+
icon: /* @__PURE__ */ U(R, {
|
|
450
|
+
className: "h-8 w-8",
|
|
451
|
+
"aria-hidden": "true"
|
|
452
|
+
}),
|
|
453
|
+
title: i("devportal.timecampusApplets.emptyTitle", "No applets yet"),
|
|
454
|
+
description: i("devportal.timecampusApplets.empty", "Register your first applet. The starter manifest points at the sample widget, so it validates as is.")
|
|
455
|
+
}) : /* @__PURE__ */ U("div", {
|
|
456
|
+
className: "flex flex-col gap-4",
|
|
457
|
+
children: $.map((e) => /* @__PURE__ */ U(te, {
|
|
458
|
+
applet: e,
|
|
459
|
+
busy: re,
|
|
460
|
+
onNewVersion: () => v({
|
|
461
|
+
kind: "version",
|
|
462
|
+
appletId: e.id,
|
|
463
|
+
appletName: e.name
|
|
464
|
+
}, h(e.latestVersion.manifest)),
|
|
465
|
+
onEditVersion: () => v({
|
|
466
|
+
kind: "edit",
|
|
467
|
+
versionId: e.latestVersion.id,
|
|
468
|
+
appletName: e.name,
|
|
469
|
+
version: e.latestVersion.version
|
|
470
|
+
}, g(e.latestVersion.manifest)),
|
|
471
|
+
onSubmitVersion: (e) => void Q(() => I({ variables: { versionId: e } }), i("devportal.timecampusApplets.submittedForReview", "Sent to your workspace's reviewers.")),
|
|
472
|
+
onWithdrawVersion: (e) => void Q(() => z({ variables: { versionId: e } }), i("devportal.timecampusApplets.withdrawnFromReview", "Withdrawn from review. The version is a draft again.")),
|
|
473
|
+
onOffer: () => void Q(() => V({ variables: { appletId: e.id } }), i("devportal.timecampusApplets.offered", "Sent to the TimeCampus platform team for certification.")),
|
|
474
|
+
onWithdrawOffer: () => void Q(() => Y({ variables: { appletId: e.id } }), i("devportal.timecampusApplets.offerWithdrawn", "Marketplace submission withdrawn."))
|
|
475
|
+
}, e.id))
|
|
476
|
+
})
|
|
477
|
+
})
|
|
478
|
+
] }) : /* @__PURE__ */ U(n, {
|
|
479
|
+
icon: /* @__PURE__ */ U(R, {
|
|
480
|
+
className: "h-8 w-8",
|
|
481
|
+
"aria-hidden": "true"
|
|
482
|
+
}),
|
|
483
|
+
title: i("devportal.timecampusApplets.noWorkspaceTitle", "Choose a workspace"),
|
|
484
|
+
description: i("devportal.timecampusApplets.noWorkspace", "TimeCampus applets belong to a workspace. Pick the workspace you develop in with the context switcher at the top of the page.")
|
|
485
|
+
})]
|
|
486
|
+
});
|
|
487
|
+
};
|
|
488
|
+
export { Z as TimeCampusAppletsPage };
|
|
489
|
+
|
|
490
|
+
//# sourceMappingURL=TimeCampusAppletsPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeCampusAppletsPage.js","names":["EmptyState","_Fragment","EmptyState$1","REFRESH_QUERIES","primaryButton","outlineButton","editorKey","target","ManifestEditor","tr","useTr","client","useSafeGatewayClient","text","setText","useState","initialText","problems","setProblems","validated","setValidated","validate","validating","useDevportalValidateTimeCampusAppletManifestLazyQuery","createApplet","creating","useDevportalCreateTimeCampusAppletMutation","addVersion","adding","useDevportalAddTimeCampusAppletVersionMutation","updateVersion","updating","useDevportalUpdateTimeCampusAppletVersionMutation","saving","parsed","result","parseManifestText","handleValidate","manifest","data","err","errorText","handleSave","onSaved","title","GlassCard","TIMECAMPUS_MANIFEST_DOCS_URL","ExternalLink","event","problem","index","CheckCircle2","onClose","Upload","AppletCard","latest","applet","action","versionAction","offer","marketplaceOffer","listing","submission","StatusBadge","onNewVersion","busy","canAddVersion","FilePlus2","formatDate","canEditVersion","onEditVersion","Pencil","onSubmitVersion","Send","onWithdrawVersion","Undo2","Globe","canWithdrawFromMarketplace","onWithdrawOffer","onOffer","ResourceLinks","links","BookOpen","TIMECAMPUS_SAMPLE_WIDGET_URL","Puzzle","TIMECAMPUS_APPLETS_DOCS_URL","Icon","label","href","TimeCampusAppletsPage","useDevportal","workspaceClient","hasWorkspace","workspaceId","editorState","setEditorState","editor","openEditor","setFeedback","feedback","useDevportalTimeCampusAppletsQuery","workspacesData","useMyWorkspacesQuery","workspaceName","item","mutationOptions","submitVersion","submitState","useDevportalSubmitTimeCampusAppletVersionMutation","withdrawVersion","withdrawState","useDevportalWithdrawTimeCampusAppletVersionMutation","offerToMarketplace","offerState","useDevportalSubmitTimeCampusAppletToMarketplaceMutation","withdrawOffer","withdrawOfferState","useDevportalWithdrawTimeCampusAppletFromMarketplaceMutation","run","success","applets","PageLayout","starterManifest","PageSection","Fragment","message","loading","LoadingState","error","manifestForNextVersion","manifestText"],"sources":["../../../src/devportal/pages/TimeCampusAppletsPage.tsx"],"sourcesContent":["/**\n * TimeCampus applets (BOFF-11005)\n *\n * The developer portal's home for third-party TimeCampus applet developers.\n * It lists the applets the developer registered in their active workspace\n * with each one's workspace review state, public marketplace listing,\n * latest submission and review notes, and it covers the developer flow end\n * to end: register an applet from a JSON manifest, upload new manifest\n * versions, submit a version for workspace review, and offer the live\n * version to the public TimeCampus marketplace for platform certification.\n *\n * Every call goes to the TimeCampus subgraph through the workspace gateway\n * with the developer's own session and active workspace (the shell's context\n * switcher picks the workspace), so the gateway's @rbac checks on the\n * timecampus-applet-developer resource apply exactly as they do in the\n * TimeCampus app. Certification itself stays with the TimeCampus platform\n * team.\n */\nimport type { FC } from \"react\";\nimport { useState } from \"react\";\nimport {\n BookOpen,\n CheckCircle2,\n ExternalLink,\n FilePlus2,\n Globe,\n Pencil,\n Puzzle,\n Send,\n Undo2,\n Upload,\n} from \"lucide-react\";\nimport { useSafeGatewayClient } from \"@burdenoff/fe-libs/shared/graphql\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport { PageLayout, PageSection } from \"../components/PageLayout\";\nimport { EmptyState } from \"../components/EmptyState\";\nimport { LoadingState } from \"../components/LoadingState\";\nimport { StatusBadge } from \"../components/StatusBadge\";\nimport { useDevportal } from \"../providers/DevportalProvider\";\nimport { useTr } from \"../utils/i18n\";\nimport {\n TIMECAMPUS_APPLETS_DOCS_URL,\n TIMECAMPUS_MANIFEST_DOCS_URL,\n TIMECAMPUS_SAMPLE_WIDGET_URL,\n canAddVersion,\n canEditVersion,\n canWithdrawFromMarketplace,\n errorText,\n formatDate,\n manifestForNextVersion,\n manifestText,\n marketplaceOffer,\n parseManifestText,\n starterManifest,\n versionAction,\n} from \"../utils/timecampusApplets\";\nimport {\n useDevportalAddTimeCampusAppletVersionMutation,\n useDevportalCreateTimeCampusAppletMutation,\n useDevportalSubmitTimeCampusAppletToMarketplaceMutation,\n useDevportalSubmitTimeCampusAppletVersionMutation,\n useDevportalTimeCampusAppletsQuery,\n useDevportalUpdateTimeCampusAppletVersionMutation,\n useDevportalValidateTimeCampusAppletManifestLazyQuery,\n useDevportalWithdrawTimeCampusAppletFromMarketplaceMutation,\n useDevportalWithdrawTimeCampusAppletVersionMutation,\n useMyWorkspacesQuery,\n type DevportalTimeCampusAppletFragment,\n type DevportalTimeCampusAppletsQuery,\n type DevportalValidateTimeCampusAppletManifestQuery,\n type MyWorkspacesQuery,\n} from \"../../generated/wspace-operations\";\n\nconst REFRESH_QUERIES = [\"DevportalTimeCampusApplets\"];\n\nconst primaryButton =\n \"inline-flex items-center justify-center gap-1.5 rounded-md bg-action-primary-bg px-3 py-1.5 text-sm font-medium text-action-primary-text hover:bg-action-primary-bg/90 disabled:opacity-50\";\nconst outlineButton =\n \"inline-flex items-center justify-center gap-1.5 rounded-md border border-border-subtle bg-bg-surface px-3 py-1.5 text-sm font-medium text-text-primary hover:bg-bg-surface-hover disabled:opacity-50\";\n\n/** What the manifest editor saves to. */\ntype EditorTarget =\n | { kind: \"new\" }\n | { kind: \"version\"; appletId: string; appletName: string }\n | { kind: \"edit\"; versionId: string; appletName: string; version: string };\n\n/**\n * An open manifest editor, tied to the workspace it was opened in. The page\n * only renders it while that workspace is still active, so switching\n * workspace can never save a manifest into a different workspace.\n */\ntype EditorState = { target: EditorTarget; text: string; workspaceId: string };\n\nfunction editorKey(target: EditorTarget): string {\n if (target.kind === \"new\") return \"new\";\n if (target.kind === \"version\") return `version-${target.appletId}`;\n return `edit-${target.versionId}`;\n}\n\ntype Feedback = { tone: \"success\" | \"error\"; text: string } | null;\n\n// =============================================================================\n// Manifest editor\n// =============================================================================\n\nconst ManifestEditor: FC<{\n target: EditorTarget;\n initialText: string;\n onClose: () => void;\n onSaved: (message: string) => void;\n}> = ({ target, initialText, onClose, onSaved }) => {\n const tr = useTr();\n const workspaceClient = useSafeGatewayClient(\"workspace\");\n const client = workspaceClient ?? undefined;\n const [text, setText] = useState(initialText);\n const [problems, setProblems] = useState<string[]>([]);\n const [validated, setValidated] = useState(false);\n const [validate, { loading: validating }] =\n useDevportalValidateTimeCampusAppletManifestLazyQuery({\n client,\n fetchPolicy: \"no-cache\",\n });\n const [createApplet, { loading: creating }] =\n useDevportalCreateTimeCampusAppletMutation({\n client,\n refetchQueries: REFRESH_QUERIES,\n awaitRefetchQueries: true,\n });\n const [addVersion, { loading: adding }] =\n useDevportalAddTimeCampusAppletVersionMutation({\n client,\n refetchQueries: REFRESH_QUERIES,\n awaitRefetchQueries: true,\n });\n const [updateVersion, { loading: updating }] =\n useDevportalUpdateTimeCampusAppletVersionMutation({\n client,\n refetchQueries: REFRESH_QUERIES,\n awaitRefetchQueries: true,\n });\n const saving = creating || adding || updating;\n\n const parsed = () => {\n const result = parseManifestText(text);\n if (!result.ok) {\n setProblems([result.error]);\n setValidated(false);\n return null;\n }\n return result.manifest;\n };\n\n const handleValidate = async () => {\n const manifest = parsed();\n if (!manifest) return;\n try {\n const { data } = await validate({ variables: { manifest } });\n const result:\n | DevportalValidateTimeCampusAppletManifestQuery[\"validateTimeCampusAppletManifest\"]\n | undefined = data?.validateTimeCampusAppletManifest;\n setProblems(result?.errors ?? []);\n setValidated(result?.valid === true);\n } catch (err) {\n setProblems([errorText(err)]);\n setValidated(false);\n }\n };\n\n const handleSave = async () => {\n const manifest = parsed();\n if (!manifest) return;\n try {\n if (target.kind === \"new\") {\n await createApplet({ variables: { manifest } });\n onSaved(\n tr(\n \"devportal.timecampusApplets.registered\",\n \"Applet registered as a draft. Submit it for review when it is ready.\",\n ),\n );\n } else if (target.kind === \"edit\") {\n await updateVersion({\n variables: { versionId: target.versionId, manifest },\n });\n onSaved(\n tr(\n \"devportal.timecampusApplets.versionUpdated\",\n \"Manifest saved. The version is a draft.\",\n ),\n );\n } else {\n await addVersion({\n variables: { appletId: target.appletId, manifest },\n });\n onSaved(\n tr(\n \"devportal.timecampusApplets.versionAdded\",\n \"New version saved as a draft.\",\n ),\n );\n }\n } catch (err) {\n setProblems([errorText(err)]);\n setValidated(false);\n }\n };\n\n const title =\n target.kind === \"new\"\n ? tr(\"devportal.timecampusApplets.registerTitle\", \"Register an applet\")\n : target.kind === \"edit\"\n ? tr(\n \"devportal.timecampusApplets.editVersionTitle\",\n \"Edit v{{version}} of {{name}}\",\n { name: target.appletName, version: target.version },\n )\n : tr(\n \"devportal.timecampusApplets.newVersionTitle\",\n \"Upload a new version of {{name}}\",\n { name: target.appletName },\n );\n\n return (\n <GlassCard\n className=\"flex flex-col gap-3 p-4\"\n data-testid=\"tc-manifest-editor\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n <a\n href={TIMECAMPUS_MANIFEST_DOCS_URL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center gap-1 text-sm text-primary hover:underline\"\n >\n {tr(\n \"devportal.timecampusApplets.manifestReference\",\n \"Manifest reference\",\n )}\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </a>\n </div>\n <label className=\"flex flex-col gap-1 text-sm text-text-secondary\">\n {tr(\"devportal.timecampusApplets.manifestLabel\", \"Manifest (JSON)\")}\n <textarea\n value={text}\n onChange={(event) => {\n setText(event.target.value);\n setValidated(false);\n }}\n spellCheck={false}\n rows={18}\n className=\"w-full rounded-md border border-border-subtle bg-bg-sunken p-3 font-mono text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-action-primary-bg\"\n data-testid=\"tc-manifest-text\"\n />\n </label>\n {problems.length > 0 && (\n <ul\n className=\"list-disc space-y-1 rounded-md bg-status-error-bg-subtle py-2 pl-6 pr-3 text-xs text-status-error-text\"\n role=\"alert\"\n data-testid=\"tc-manifest-problems\"\n >\n {problems.map((problem, index) => (\n // Validation errors can repeat (two widgets failing the same\n // check), so the message alone is not a unique key.\n <li key={`${index}-${problem}`}>{problem}</li>\n ))}\n </ul>\n )}\n {validated && problems.length === 0 && (\n <p\n className=\"flex items-center gap-1.5 text-xs text-status-success-text\"\n data-testid=\"tc-manifest-valid\"\n >\n <CheckCircle2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\n \"devportal.timecampusApplets.manifestValid\",\n \"The manifest is valid.\",\n )}\n </p>\n )}\n <div className=\"flex flex-wrap justify-end gap-2\">\n <button type=\"button\" className={outlineButton} onClick={onClose}>\n {tr(\"devportal.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n className={outlineButton}\n onClick={() => void handleValidate()}\n disabled={validating || saving}\n >\n <CheckCircle2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\"devportal.timecampusApplets.validate\", \"Validate\")}\n </button>\n <button\n type=\"button\"\n className={primaryButton}\n onClick={() => void handleSave()}\n disabled={saving}\n data-testid=\"tc-manifest-save\"\n >\n <Upload className=\"h-4 w-4\" aria-hidden=\"true\" />\n {target.kind === \"new\"\n ? tr(\"devportal.timecampusApplets.register\", \"Register applet\")\n : tr(\"devportal.timecampusApplets.uploadVersion\", \"Upload version\")}\n </button>\n </div>\n </GlassCard>\n );\n};\n\n// =============================================================================\n// Applet card\n// =============================================================================\n\nconst AppletCard: FC<{\n applet: DevportalTimeCampusAppletFragment;\n busy: boolean;\n onNewVersion: () => void;\n onEditVersion: () => void;\n onSubmitVersion: (versionId: string) => void;\n onWithdrawVersion: (versionId: string) => void;\n onOffer: () => void;\n onWithdrawOffer: () => void;\n}> = ({\n applet,\n busy,\n onNewVersion,\n onEditVersion,\n onSubmitVersion,\n onWithdrawVersion,\n onOffer,\n onWithdrawOffer,\n}) => {\n const tr = useTr();\n const latest = applet.latestVersion;\n const action = versionAction(applet);\n const offer = marketplaceOffer(applet);\n const listing = applet.marketplace;\n const submission = listing?.latestSubmission;\n\n return (\n <GlassCard\n className=\"flex flex-col gap-4 p-4\"\n data-testid={`tc-applet-${applet.key}`}\n >\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <h3 className=\"text-base font-semibold text-text-primary\">\n {applet.name}\n </h3>\n <StatusBadge status={applet.status} />\n </div>\n <p className=\"mt-0.5 font-mono text-xs text-text-tertiary\">\n {applet.key}\n </p>\n <p className=\"mt-1 text-sm text-text-secondary\">\n {applet.description}\n </p>\n </div>\n <button\n type=\"button\"\n className={outlineButton}\n onClick={onNewVersion}\n disabled={busy || !canAddVersion(applet)}\n title={\n canAddVersion(applet)\n ? undefined\n : tr(\n \"devportal.timecampusApplets.openVersionHint\",\n \"Finish or withdraw the open version first.\",\n )\n }\n >\n <FilePlus2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\"devportal.timecampusApplets.newVersion\", \"New version\")}\n </button>\n </div>\n\n <div className=\"grid gap-3 md:grid-cols-2\">\n {/* Workspace review of the latest version */}\n <div\n className=\"flex flex-col gap-2 rounded-md border border-border-subtle bg-bg-sunken/40 p-3\"\n data-testid={`tc-applet-version-${applet.key}`}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <p className=\"text-sm font-medium text-text-primary\">\n {tr(\n \"devportal.timecampusApplets.latestVersion\",\n \"Latest version\",\n )}{\" \"}\n v{latest.version}\n </p>\n <StatusBadge status={latest.status} />\n </div>\n {applet.liveVersion && applet.liveVersion.id !== latest.id && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.timecampusApplets.liveInWorkspace\",\n \"v{{version}} is live in your workspace.\",\n { version: applet.liveVersion.version },\n )}\n </p>\n )}\n {latest.submittedAt && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\"devportal.timecampusApplets.submitted\", \"Submitted\")}{\" \"}\n {formatDate(latest.submittedAt)}\n </p>\n )}\n {latest.reviewNotes && (\n <p className=\"text-xs text-text-secondary\">\n <span className=\"font-medium text-text-primary\">\n {tr(\"devportal.timecampusApplets.reviewNotes\", \"Review notes\")}:\n </span>{\" \"}\n {latest.reviewNotes}\n </p>\n )}\n {latest.suspendedReason && (\n <p className=\"text-xs text-status-warning-text\">\n {latest.suspendedReason}\n </p>\n )}\n {canEditVersion(applet) && (\n <button\n type=\"button\"\n className={outlineButton}\n onClick={onEditVersion}\n disabled={busy}\n data-testid={`tc-edit-version-${applet.key}`}\n >\n <Pencil className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\"devportal.timecampusApplets.editManifest\", \"Edit manifest\")}\n </button>\n )}\n {action.kind === \"submit\" && (\n <button\n type=\"button\"\n className={primaryButton}\n onClick={() => onSubmitVersion(action.versionId)}\n disabled={busy}\n >\n <Send className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\n \"devportal.timecampusApplets.submitForReview\",\n \"Submit for review\",\n )}\n </button>\n )}\n {action.kind === \"withdraw\" && (\n <button\n type=\"button\"\n className={outlineButton}\n onClick={() => onWithdrawVersion(action.versionId)}\n disabled={busy}\n >\n <Undo2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\n \"devportal.timecampusApplets.withdrawReview\",\n \"Withdraw from review\",\n )}\n </button>\n )}\n </div>\n\n {/* Public marketplace listing */}\n <div\n className=\"flex flex-col gap-2 rounded-md border border-border-subtle bg-bg-sunken/40 p-3\"\n data-testid={`tc-applet-marketplace-${applet.key}`}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <Globe className=\"h-4 w-4 text-text-tertiary\" aria-hidden=\"true\" />\n <p className=\"text-sm font-medium text-text-primary\">\n {tr(\n \"devportal.timecampusApplets.marketplace\",\n \"Public marketplace\",\n )}\n </p>\n {listing ? (\n <StatusBadge status={listing.status} />\n ) : (\n <StatusBadge status=\"NOT_LISTED\" />\n )}\n </div>\n {listing?.liveSubmission && (\n <p className=\"text-xs text-text-secondary\">\n {tr(\n \"devportal.timecampusApplets.certifiedLive\",\n \"v{{version}} is certified and live in the marketplace.\",\n { version: listing.liveSubmission.version },\n )}\n </p>\n )}\n {submission && (\n <p className=\"flex flex-wrap items-center gap-2 text-xs text-text-secondary\">\n {tr(\n \"devportal.timecampusApplets.latestSubmission\",\n \"Latest submission v{{version}}\",\n { version: submission.version },\n )}\n <StatusBadge status={submission.status} />\n </p>\n )}\n {submission?.reviewNotes && (\n <p className=\"text-xs text-text-secondary\">\n <span className=\"font-medium text-text-primary\">\n {tr(\n \"devportal.timecampusApplets.certificationNotes\",\n \"Certification notes\",\n )}\n :\n </span>{\" \"}\n {submission.reviewNotes}\n </p>\n )}\n {listing?.suspendedReason && (\n <p className=\"text-xs text-status-warning-text\">\n {listing.suspendedReason}\n </p>\n )}\n {canWithdrawFromMarketplace(applet) ? (\n <button\n type=\"button\"\n className={outlineButton}\n onClick={onWithdrawOffer}\n disabled={busy}\n >\n <Undo2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\n \"devportal.timecampusApplets.withdrawSubmission\",\n \"Withdraw submission\",\n )}\n </button>\n ) : offer.canOffer ? (\n <button\n type=\"button\"\n className={primaryButton}\n onClick={onOffer}\n disabled={busy}\n >\n <Globe className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\n \"devportal.timecampusApplets.offer\",\n \"Offer v{{version}} to the marketplace\",\n { version: offer.version },\n )}\n </button>\n ) : (\n <p className=\"text-xs text-text-tertiary\">{offer.reason}</p>\n )}\n </div>\n </div>\n </GlassCard>\n );\n};\n\n// =============================================================================\n// Page\n// =============================================================================\n\nconst ResourceLinks: FC = () => {\n const tr = useTr();\n const links = [\n {\n href: TIMECAMPUS_MANIFEST_DOCS_URL,\n label: tr(\n \"devportal.timecampusApplets.docsManifest\",\n \"Applet manifest reference\",\n ),\n icon: BookOpen,\n },\n {\n href: TIMECAMPUS_SAMPLE_WIDGET_URL,\n label: tr(\n \"devportal.timecampusApplets.docsSample\",\n \"Sample widget (view source)\",\n ),\n icon: Puzzle,\n },\n {\n href: TIMECAMPUS_APPLETS_DOCS_URL,\n label: tr(\n \"devportal.timecampusApplets.docsApplets\",\n \"How applets work in TimeCampus\",\n ),\n icon: Globe,\n },\n ];\n return (\n <ul className=\"flex flex-wrap gap-2\" data-testid=\"tc-applet-resources\">\n {links.map(({ href, label, icon: Icon }) => (\n <li key={href}>\n <a\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={outlineButton}\n >\n <Icon className=\"h-4 w-4\" aria-hidden=\"true\" />\n {label}\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </a>\n </li>\n ))}\n </ul>\n );\n};\n\nexport const TimeCampusAppletsPage: FC = () => {\n const tr = useTr();\n const { workspaceId } = useDevportal();\n const workspaceClient = useSafeGatewayClient(\"workspace\");\n const client = workspaceClient ?? undefined;\n const hasWorkspace = Boolean(workspaceId) && Boolean(workspaceClient);\n\n const [editorState, setEditorState] = useState<EditorState | null>(null);\n // An editor opened in another workspace is dropped, not carried over.\n const editor =\n editorState && editorState.workspaceId === workspaceId ? editorState : null;\n const openEditor = (target: EditorTarget, text: string) => {\n if (!workspaceId) return;\n setFeedback(null);\n setEditorState({ target, text, workspaceId });\n };\n const [feedback, setFeedback] = useState<Feedback>(null);\n\n const { data, loading, error } = useDevportalTimeCampusAppletsQuery({\n client,\n skip: !hasWorkspace,\n fetchPolicy: \"cache-and-network\",\n });\n const { data: workspacesData } = useMyWorkspacesQuery({\n client,\n skip: !hasWorkspace,\n variables: { pagination: { limit: 100, offset: 0 } },\n });\n // The generated hooks resolve their result types loosely (the codegen\n // preset types them against wspace-types), so pin the shapes here.\n const workspaceItems: MyWorkspacesQuery[\"myWorkspaces\"][\"items\"] =\n workspacesData?.myWorkspaces?.items ?? [];\n const workspaceName =\n workspaceItems.find((item) => item.id === workspaceId)?.name ?? null;\n\n const mutationOptions = {\n client,\n refetchQueries: REFRESH_QUERIES,\n awaitRefetchQueries: true,\n };\n const [submitVersion, submitState] =\n useDevportalSubmitTimeCampusAppletVersionMutation(mutationOptions);\n const [withdrawVersion, withdrawState] =\n useDevportalWithdrawTimeCampusAppletVersionMutation(mutationOptions);\n const [offerToMarketplace, offerState] =\n useDevportalSubmitTimeCampusAppletToMarketplaceMutation(mutationOptions);\n const [withdrawOffer, withdrawOfferState] =\n useDevportalWithdrawTimeCampusAppletFromMarketplaceMutation(\n mutationOptions,\n );\n const busy =\n submitState.loading ||\n withdrawState.loading ||\n offerState.loading ||\n withdrawOfferState.loading;\n\n const run = async (action: () => Promise<unknown>, success: string) => {\n setFeedback(null);\n try {\n await action();\n setFeedback({ tone: \"success\", text: success });\n } catch (err) {\n setFeedback({ tone: \"error\", text: errorText(err) });\n }\n };\n\n const applets: DevportalTimeCampusAppletsQuery[\"timeCampusMyThirdPartyApplets\"] =\n data?.timeCampusMyThirdPartyApplets ?? [];\n\n return (\n <PageLayout\n title={tr(\"devportal.timecampusApplets.title\", \"TimeCampus applets\")}\n description={tr(\n \"devportal.timecampusApplets.description\",\n \"Build widgets for TimeCampus, publish them in your workspace and offer them to every TimeCampus workspace.\",\n )}\n purpose={tr(\n \"devportal.timecampusApplets.purpose\",\n \"Register an applet from a JSON manifest, upload new versions, send each version to your workspace's reviewers, and once it is live offer it to the public marketplace. The TimeCampus platform team certifies every marketplace version before other workspaces can install it.\",\n )}\n purposeLearnMoreHref={TIMECAMPUS_MANIFEST_DOCS_URL}\n actions={\n hasWorkspace ? (\n <button\n type=\"button\"\n className={primaryButton}\n onClick={() => openEditor({ kind: \"new\" }, starterManifest())}\n data-testid=\"tc-register-applet\"\n >\n <FilePlus2 className=\"h-4 w-4\" aria-hidden=\"true\" />\n {tr(\"devportal.timecampusApplets.register\", \"Register applet\")}\n </button>\n ) : undefined\n }\n >\n <PageSection\n title={tr(\"devportal.timecampusApplets.resources\", \"Build an applet\")}\n >\n <ResourceLinks />\n </PageSection>\n\n {!hasWorkspace ? (\n <EmptyState\n icon={<Puzzle className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={tr(\n \"devportal.timecampusApplets.noWorkspaceTitle\",\n \"Choose a workspace\",\n )}\n description={tr(\n \"devportal.timecampusApplets.noWorkspace\",\n \"TimeCampus applets belong to a workspace. Pick the workspace you develop in with the context switcher at the top of the page.\",\n )}\n />\n ) : (\n <>\n <p className=\"text-sm text-text-secondary\" data-testid=\"tc-workspace\">\n {workspaceName\n ? tr(\n \"devportal.timecampusApplets.inWorkspace\",\n \"Your applets in {{workspace}}. Switch workspace with the context switcher.\",\n { workspace: workspaceName },\n )\n : tr(\n \"devportal.timecampusApplets.inActiveWorkspace\",\n \"Your applets in the active workspace. Switch workspace with the context switcher.\",\n )}\n </p>\n\n {feedback && (\n <p\n role={feedback.tone === \"error\" ? \"alert\" : \"status\"}\n className={\n feedback.tone === \"error\"\n ? \"rounded-md bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n : \"rounded-md bg-status-success-bg-subtle px-3 py-2 text-sm text-status-success-text\"\n }\n data-testid=\"tc-feedback\"\n >\n {feedback.text}\n </p>\n )}\n\n {editor && (\n <ManifestEditor\n key={`${editor.workspaceId}-${editorKey(editor.target)}`}\n target={editor.target}\n initialText={editor.text}\n onClose={() => setEditorState(null)}\n onSaved={(message) => {\n setEditorState(null);\n setFeedback({ tone: \"success\", text: message });\n }}\n />\n )}\n\n <PageSection\n title={tr(\n \"devportal.timecampusApplets.yourApplets\",\n \"Your applets\",\n )}\n data-testid=\"tc-applet-list\"\n >\n {loading && applets.length === 0 ? (\n <LoadingState\n message={tr(\n \"devportal.timecampusApplets.loading\",\n \"Loading your applets...\",\n )}\n />\n ) : error && applets.length === 0 ? (\n <p\n role=\"alert\"\n className=\"rounded-md bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {errorText(error)}\n </p>\n ) : applets.length === 0 ? (\n <EmptyState\n icon={<Puzzle className=\"h-8 w-8\" aria-hidden=\"true\" />}\n title={tr(\n \"devportal.timecampusApplets.emptyTitle\",\n \"No applets yet\",\n )}\n description={tr(\n \"devportal.timecampusApplets.empty\",\n \"Register your first applet. The starter manifest points at the sample widget, so it validates as is.\",\n )}\n />\n ) : (\n <div className=\"flex flex-col gap-4\">\n {applets.map((applet) => (\n <AppletCard\n key={applet.id}\n applet={applet}\n busy={busy}\n onNewVersion={() =>\n openEditor(\n {\n kind: \"version\",\n appletId: applet.id,\n appletName: applet.name,\n },\n manifestForNextVersion(applet.latestVersion.manifest),\n )\n }\n onEditVersion={() =>\n openEditor(\n {\n kind: \"edit\",\n versionId: applet.latestVersion.id,\n appletName: applet.name,\n version: applet.latestVersion.version,\n },\n manifestText(applet.latestVersion.manifest),\n )\n }\n onSubmitVersion={(versionId) =>\n void run(\n () => submitVersion({ variables: { versionId } }),\n tr(\n \"devportal.timecampusApplets.submittedForReview\",\n \"Sent to your workspace's reviewers.\",\n ),\n )\n }\n onWithdrawVersion={(versionId) =>\n void run(\n () => withdrawVersion({ variables: { versionId } }),\n tr(\n \"devportal.timecampusApplets.withdrawnFromReview\",\n \"Withdrawn from review. The version is a draft again.\",\n ),\n )\n }\n onOffer={() =>\n void run(\n () =>\n offerToMarketplace({\n variables: { appletId: applet.id },\n }),\n tr(\n \"devportal.timecampusApplets.offered\",\n \"Sent to the TimeCampus platform team for certification.\",\n ),\n )\n }\n onWithdrawOffer={() =>\n void run(\n () =>\n withdrawOffer({ variables: { appletId: applet.id } }),\n tr(\n \"devportal.timecampusApplets.offerWithdrawn\",\n \"Marketplace submission withdrawn.\",\n ),\n )\n }\n />\n ))}\n </div>\n )}\n </PageSection>\n </>\n )}\n </PageLayout>\n );\n};\n"],"mappings":"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"}
|
|
@@ -10,7 +10,11 @@ var e = {
|
|
|
10
10
|
DEPRECATED: "bg-bg-sunken text-text-secondary",
|
|
11
11
|
ACTIVE: "bg-status-success-bg-subtle text-status-success-text",
|
|
12
12
|
INACTIVE: "bg-bg-sunken text-text-secondary",
|
|
13
|
-
REVOKED: "bg-status-error-bg-subtle text-status-error-text"
|
|
13
|
+
REVOKED: "bg-status-error-bg-subtle text-status-error-text",
|
|
14
|
+
CERTIFIED: "bg-status-success-bg-subtle text-status-success-text",
|
|
15
|
+
WITHDRAWN: "bg-bg-sunken text-text-secondary",
|
|
16
|
+
SUPERSEDED: "bg-bg-sunken text-text-secondary",
|
|
17
|
+
NOT_LISTED: "bg-bg-sunken text-text-secondary"
|
|
14
18
|
}, t = {
|
|
15
19
|
ACTIVE: "bg-status-success-bg-subtle text-status-success-text",
|
|
16
20
|
PAUSED: "bg-status-warning-bg-subtle text-status-warning-text",
|