@realiizlabs/admin 0.14.0 → 0.15.0
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/LICENSE +21 -0
- package/dist/{Sidebar-Dvrc9_xR.d.cts → Sidebar-Dz_qJOSx.d.cts} +3 -1
- package/dist/{Sidebar-Dvrc9_xR.d.ts → Sidebar-Dz_qJOSx.d.ts} +3 -1
- package/dist/bar/index.cjs +82 -0
- package/dist/bar/index.cjs.map +1 -0
- package/dist/bar/index.d.cts +18 -0
- package/dist/bar/index.d.ts +18 -0
- package/dist/bar/index.js +77 -0
- package/dist/bar/index.js.map +1 -0
- package/dist/shell/index.cjs +60 -38
- package/dist/shell/index.cjs.map +1 -1
- package/dist/shell/index.d.cts +9 -5
- package/dist/shell/index.d.ts +9 -5
- package/dist/shell/index.js +60 -38
- package/dist/shell/index.js.map +1 -1
- package/dist/studio/index.cjs +80 -2
- package/dist/studio/index.cjs.map +1 -1
- package/dist/studio/index.d.cts +32 -1
- package/dist/studio/index.d.ts +32 -1
- package/dist/studio/index.js +78 -3
- package/dist/studio/index.js.map +1 -1
- package/dist/studio-ui/index.cjs +305 -90
- package/dist/studio-ui/index.cjs.map +1 -1
- package/dist/studio-ui/index.d.cts +37 -6
- package/dist/studio-ui/index.d.ts +37 -6
- package/dist/studio-ui/index.js +303 -92
- package/dist/studio-ui/index.js.map +1 -1
- package/dist/version-DMS0azUx.d.cts +3 -0
- package/dist/version-DMS0azUx.d.ts +3 -0
- package/package.json +12 -5
package/dist/studio-ui/index.cjs
CHANGED
|
@@ -160,6 +160,32 @@ function Sidebar({ items, pinned = [], activeHref, basePath }) {
|
|
|
160
160
|
)
|
|
161
161
|
] });
|
|
162
162
|
}
|
|
163
|
+
function buttonClass(variant = "secondary", size = "md", extra) {
|
|
164
|
+
return ["rz-btn", `rz-btn--${variant}`, `rz-btn--${size}`, extra].filter(Boolean).join(" ");
|
|
165
|
+
}
|
|
166
|
+
function Button({ variant = "secondary", size = "md", className, type = "button", ...rest }) {
|
|
167
|
+
return /* @__PURE__ */ jsxRuntime.jsx("button", { type, className: buttonClass(variant, size, className), ...rest });
|
|
168
|
+
}
|
|
169
|
+
function LinkButton({ variant = "secondary", size = "md", className, external, forward, children, ...rest }) {
|
|
170
|
+
const extra = external ? { target: "_blank", rel: "noreferrer", ...rest } : rest;
|
|
171
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("a", { className: buttonClass(variant, size, className), ...extra, children: [
|
|
172
|
+
children,
|
|
173
|
+
external && /* @__PURE__ */ jsxRuntime.jsx(OutboundArrow, {}),
|
|
174
|
+
forward && !external && /* @__PURE__ */ jsxRuntime.jsx(ForwardArrow, {})
|
|
175
|
+
] });
|
|
176
|
+
}
|
|
177
|
+
function ForwardArrow() {
|
|
178
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "rz-arrow rz-arrow--fwd", children: [
|
|
179
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14" }),
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m13 6 6 6-6 6" })
|
|
181
|
+
] });
|
|
182
|
+
}
|
|
183
|
+
function OutboundArrow() {
|
|
184
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "rz-arrow", children: [
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 17 17 7" }),
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 7h10v10" })
|
|
187
|
+
] });
|
|
188
|
+
}
|
|
163
189
|
var THEME_KEY = "rz-admin-theme";
|
|
164
190
|
function useTheme(defaultTheme = "light") {
|
|
165
191
|
const [theme, setTheme] = react.useState(defaultTheme);
|
|
@@ -211,12 +237,16 @@ var HelpIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...ico, children:
|
|
|
211
237
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 4h6a4 4 0 0 1 4 4v12a3 3 0 0 0-3-3H2z" }),
|
|
212
238
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M22 4h-6a4 4 0 0 0-4 4v12a3 3 0 0 1 3-3h7z" })
|
|
213
239
|
] });
|
|
240
|
+
var GlobeIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...ico, children: [
|
|
241
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
242
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18" })
|
|
243
|
+
] });
|
|
214
244
|
var OutIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { ...ico, children: [
|
|
215
245
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
|
|
216
246
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16 17l5-5-5-5" }),
|
|
217
247
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12H9" })
|
|
218
248
|
] });
|
|
219
|
-
function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, helpHref }) {
|
|
249
|
+
function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, helpHref, siteUrl }) {
|
|
220
250
|
const [open, setOpen] = react.useState(false);
|
|
221
251
|
const wrap = react.useRef(null);
|
|
222
252
|
react.useEffect(() => {
|
|
@@ -251,7 +281,12 @@ function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, hel
|
|
|
251
281
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Theme" }),
|
|
252
282
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rz-menu__end", children: /* @__PURE__ */ jsxRuntime.jsx(ThemeToggle, { theme, onChange: onTheme }) })
|
|
253
283
|
] }),
|
|
254
|
-
(accountHref || helpHref) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rz-menu__sep" }),
|
|
284
|
+
(siteUrl || accountHref || helpHref) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rz-menu__sep" }),
|
|
285
|
+
siteUrl && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: siteUrl, target: "_blank", rel: "noreferrer", role: "menuitem", className: "rz-menu__item", children: [
|
|
286
|
+
/* @__PURE__ */ jsxRuntime.jsx(GlobeIcon, {}),
|
|
287
|
+
"View website",
|
|
288
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rz-menu__end", children: /* @__PURE__ */ jsxRuntime.jsx(OutboundArrow, {}) })
|
|
289
|
+
] }),
|
|
255
290
|
accountHref && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: accountHref, role: "menuitem", className: "rz-menu__item", children: [
|
|
256
291
|
/* @__PURE__ */ jsxRuntime.jsx(UserIcon, {}),
|
|
257
292
|
"Account"
|
|
@@ -268,19 +303,28 @@ function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, hel
|
|
|
268
303
|
] })
|
|
269
304
|
] });
|
|
270
305
|
}
|
|
271
|
-
function TopBar({ siteName, productName, logoUrl, homeHref, user, role, theme, onTheme, signOutPath, accountHref, helpHref }) {
|
|
306
|
+
function TopBar({ siteName, productName, logoUrl, homeHref, siteUrl, user, role, theme, onTheme, signOutPath, accountHref, helpHref }) {
|
|
272
307
|
return /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "rz-topbar", children: [
|
|
273
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
308
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
309
|
+
"a",
|
|
310
|
+
{
|
|
311
|
+
href: siteUrl || homeHref,
|
|
312
|
+
className: "rz-topbar__brand",
|
|
313
|
+
...siteUrl ? { target: "_blank", rel: "noreferrer", title: "Open the live website in a new tab" } : {},
|
|
314
|
+
children: [
|
|
315
|
+
logoUrl && /* @__PURE__ */ jsxRuntime.jsx("img", { src: logoUrl, alt: "", className: "rz-topbar__logo" }),
|
|
316
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: siteName }),
|
|
317
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "rz-topbar__product", children: productName }),
|
|
318
|
+
siteUrl && /* @__PURE__ */ jsxRuntime.jsx(OutboundArrow, {})
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
),
|
|
278
322
|
user && role && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rz-topbar__right", children: [
|
|
279
323
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rz-topbar__greeting", "data-testid": "rz-greeting", children: [
|
|
280
324
|
"Welcome back, ",
|
|
281
325
|
firstNameOf(user)
|
|
282
326
|
] }),
|
|
283
|
-
/* @__PURE__ */ jsxRuntime.jsx(AccountMenu, { user, role, theme, onTheme, signOutPath, accountHref, helpHref })
|
|
327
|
+
/* @__PURE__ */ jsxRuntime.jsx(AccountMenu, { user, role, theme, onTheme, signOutPath, accountHref, helpHref, siteUrl })
|
|
284
328
|
] })
|
|
285
329
|
] });
|
|
286
330
|
}
|
|
@@ -340,6 +384,8 @@ var SHELL_CSS = `
|
|
|
340
384
|
.rz-topbar__brand { display: flex; align-items: center; gap: .6rem; font-weight: 600; font-size: .9375rem; text-decoration: none; }
|
|
341
385
|
.rz-topbar__logo { height: 22px; width: auto; display: block; }
|
|
342
386
|
.rz-topbar__product { font-weight: 400; color: var(--text-secondary); }
|
|
387
|
+
.rz-topbar__brand .rz-arrow { color: var(--text-muted); opacity: 0; transition: opacity .15s, transform .15s; }
|
|
388
|
+
.rz-topbar__brand:hover .rz-arrow { opacity: 1; }
|
|
343
389
|
.rz-topbar__right { margin-left: auto; display: flex; align-items: center; gap: 1rem; }
|
|
344
390
|
.rz-topbar__greeting { color: var(--text-secondary); font-size: .8rem; }
|
|
345
391
|
.rz-body { display: flex; flex: 1; min-height: 0; }
|
|
@@ -551,6 +597,7 @@ function AdminShell({
|
|
|
551
597
|
signOutPath,
|
|
552
598
|
accountHref,
|
|
553
599
|
helpHref,
|
|
600
|
+
siteUrl,
|
|
554
601
|
branding,
|
|
555
602
|
defaultTheme = "light",
|
|
556
603
|
children
|
|
@@ -567,6 +614,7 @@ function AdminShell({
|
|
|
567
614
|
siteName: shownName,
|
|
568
615
|
productName,
|
|
569
616
|
logoUrl: shownLogo,
|
|
617
|
+
siteUrl,
|
|
570
618
|
homeHref: basePath,
|
|
571
619
|
user,
|
|
572
620
|
role,
|
|
@@ -583,32 +631,6 @@ function AdminShell({
|
|
|
583
631
|
] })
|
|
584
632
|
] });
|
|
585
633
|
}
|
|
586
|
-
function buttonClass(variant = "secondary", size = "md", extra) {
|
|
587
|
-
return ["rz-btn", `rz-btn--${variant}`, `rz-btn--${size}`, extra].filter(Boolean).join(" ");
|
|
588
|
-
}
|
|
589
|
-
function Button({ variant = "secondary", size = "md", className, type = "button", ...rest }) {
|
|
590
|
-
return /* @__PURE__ */ jsxRuntime.jsx("button", { type, className: buttonClass(variant, size, className), ...rest });
|
|
591
|
-
}
|
|
592
|
-
function LinkButton({ variant = "secondary", size = "md", className, external, forward, children, ...rest }) {
|
|
593
|
-
const extra = external ? { target: "_blank", rel: "noreferrer", ...rest } : rest;
|
|
594
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("a", { className: buttonClass(variant, size, className), ...extra, children: [
|
|
595
|
-
children,
|
|
596
|
-
external && /* @__PURE__ */ jsxRuntime.jsx(OutboundArrow, {}),
|
|
597
|
-
forward && !external && /* @__PURE__ */ jsxRuntime.jsx(ForwardArrow, {})
|
|
598
|
-
] });
|
|
599
|
-
}
|
|
600
|
-
function ForwardArrow() {
|
|
601
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "rz-arrow rz-arrow--fwd", children: [
|
|
602
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12h14" }),
|
|
603
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m13 6 6 6-6 6" })
|
|
604
|
-
] });
|
|
605
|
-
}
|
|
606
|
-
function OutboundArrow() {
|
|
607
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "rz-arrow", children: [
|
|
608
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 17 17 7" }),
|
|
609
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 7h10v10" })
|
|
610
|
-
] });
|
|
611
|
-
}
|
|
612
634
|
function Card({ title, meta, note, children, actions, className }) {
|
|
613
635
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: ["rz-card", className].filter(Boolean).join(" "), children: [
|
|
614
636
|
title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rz-card__title", children: title }),
|
|
@@ -872,12 +894,149 @@ var STUDIO_CSS = `
|
|
|
872
894
|
.rz-admin .rz-help__pager a:hover { color: var(--signal); }
|
|
873
895
|
.rz-admin .rz-arrow--back { transform: none; }
|
|
874
896
|
@media (prefers-reduced-motion: no-preference) { .rz-admin a:hover .rz-arrow--back { transform: translateX(-4px); } }
|
|
897
|
+
|
|
898
|
+
/* ---- Studio update strip / Settings \u2192 Studio ---------------------------- */
|
|
899
|
+
.rz-admin .rz-update { border: 1px solid var(--border); border-left: 3px solid var(--signal); border-radius: var(--rz-radius); background: var(--surface-1); padding: .7rem 1rem; }
|
|
900
|
+
.rz-admin .rz-update--strip { margin: 0 0 1.25rem; }
|
|
901
|
+
.rz-admin .rz-update__row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }
|
|
902
|
+
.rz-admin .rz-update__title { font-weight: 600; color: var(--text-primary); }
|
|
903
|
+
.rz-admin .rz-update__link { display: inline-flex; align-items: center; gap: .3rem; background: none; border: 0; padding: 0; font: inherit; font-size: .875rem; color: var(--signal); cursor: pointer; text-decoration: none; }
|
|
904
|
+
.rz-admin .rz-update__link:hover { color: var(--text-primary); }
|
|
905
|
+
.rz-admin .rz-update__later { margin-left: auto; background: none; border: 0; padding: 0; font: inherit; font-size: .8rem; color: var(--text-muted); cursor: pointer; }
|
|
906
|
+
.rz-admin .rz-update__later:hover { color: var(--text-primary); }
|
|
907
|
+
.rz-admin .rz-update__notes { margin: .6rem 0 0; font-size: .875rem; line-height: 1.55; color: var(--text-secondary); white-space: pre-line; }
|
|
908
|
+
.rz-admin .rz-update__problem { margin: .6rem 0 0; font-size: .875rem; color: var(--status-down); }
|
|
909
|
+
.rz-admin .rz-update__done { display: block; margin-top: .5rem; font-size: .875rem; color: var(--text-secondary); }
|
|
875
910
|
`;
|
|
876
|
-
|
|
911
|
+
var POLL_MS = 8e3;
|
|
912
|
+
var LOCAL_FALLBACK_MS = 15e4;
|
|
913
|
+
var GIVE_UP_MS = 15 * 6e4;
|
|
914
|
+
function useDeployed(active, mergedSha) {
|
|
915
|
+
const [state, setState] = react.useState("waiting");
|
|
916
|
+
react.useEffect(() => {
|
|
917
|
+
if (!active) return;
|
|
918
|
+
let stop = false;
|
|
919
|
+
let baseline;
|
|
920
|
+
const started = Date.now();
|
|
921
|
+
const read2 = async () => {
|
|
922
|
+
try {
|
|
923
|
+
const r = await fetch("/api/version", { cache: "no-store" });
|
|
924
|
+
const j = await r.json();
|
|
925
|
+
return j.sha;
|
|
926
|
+
} catch {
|
|
927
|
+
return null;
|
|
928
|
+
}
|
|
929
|
+
};
|
|
930
|
+
const tick = async () => {
|
|
931
|
+
if (stop) return;
|
|
932
|
+
const sha = await read2();
|
|
933
|
+
if (stop) return;
|
|
934
|
+
if (baseline === void 0) baseline = sha;
|
|
935
|
+
const elapsed = Date.now() - started;
|
|
936
|
+
const matched = sha !== null && mergedSha !== null && sha === mergedSha;
|
|
937
|
+
const moved = sha !== null && baseline !== null && sha !== baseline;
|
|
938
|
+
const localDone = sha === null && elapsed >= LOCAL_FALLBACK_MS;
|
|
939
|
+
if (matched || moved || localDone) {
|
|
940
|
+
setState("live");
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
if (elapsed >= GIVE_UP_MS) {
|
|
944
|
+
setState("slow");
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
setTimeout(tick, POLL_MS);
|
|
948
|
+
};
|
|
949
|
+
void tick();
|
|
950
|
+
return () => {
|
|
951
|
+
stop = true;
|
|
952
|
+
};
|
|
953
|
+
}, [active, mergedSha]);
|
|
954
|
+
return state;
|
|
955
|
+
}
|
|
956
|
+
var HIDE_KEY = "rz-update-later";
|
|
957
|
+
function canSeeUpdates(role) {
|
|
958
|
+
return role === "owner" || role === "staff";
|
|
959
|
+
}
|
|
960
|
+
function UpdateStrip({ update, role }) {
|
|
961
|
+
const [hidden, setHidden] = react.useState(true);
|
|
962
|
+
react.useEffect(() => {
|
|
963
|
+
try {
|
|
964
|
+
setHidden(sessionStorage.getItem(HIDE_KEY) === update?.version);
|
|
965
|
+
} catch {
|
|
966
|
+
setHidden(false);
|
|
967
|
+
}
|
|
968
|
+
}, [update?.version]);
|
|
969
|
+
if (!update || update.state !== "ready" || !canSeeUpdates(role) || hidden) return null;
|
|
970
|
+
const later = () => {
|
|
971
|
+
try {
|
|
972
|
+
sessionStorage.setItem(HIDE_KEY, update.version);
|
|
973
|
+
} catch {
|
|
974
|
+
}
|
|
975
|
+
setHidden(true);
|
|
976
|
+
};
|
|
977
|
+
return /* @__PURE__ */ jsxRuntime.jsx(UpdateBody, { update, onLater: later, compact: true });
|
|
978
|
+
}
|
|
979
|
+
function UpdateBody({ update, onLater, compact = false }) {
|
|
980
|
+
const { actions } = useStudio();
|
|
981
|
+
const [showNotes, setShowNotes] = react.useState(!compact);
|
|
982
|
+
const [busy, setBusy] = react.useState(false);
|
|
983
|
+
const [outcome, setOutcome] = react.useState(null);
|
|
984
|
+
const merged = outcome?.state === "merged";
|
|
985
|
+
const deploy = useDeployed(merged, merged ? outcome.sha : null);
|
|
986
|
+
const run = async () => {
|
|
987
|
+
setBusy(true);
|
|
988
|
+
try {
|
|
989
|
+
setOutcome(await actions.updateStudio(update.number));
|
|
990
|
+
} finally {
|
|
991
|
+
setBusy(false);
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
if (merged) {
|
|
995
|
+
const live = deploy === "live";
|
|
996
|
+
const steps = [
|
|
997
|
+
{ label: "Updated", state: "done", note: `Studio ${update.version}` },
|
|
998
|
+
{ label: "Live", state: live ? "done" : "active", note: live ? "On the site now" : deploy === "slow" ? "Taking longer than usual" : "Rebuilding, about two minutes" }
|
|
999
|
+
];
|
|
1000
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `rz-update${compact ? " rz-update--strip" : ""}`, role: "status", children: [
|
|
1001
|
+
/* @__PURE__ */ jsxRuntime.jsx(Steps, { steps }),
|
|
1002
|
+
live && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rz-update__done", children: [
|
|
1003
|
+
"Studio updated to ",
|
|
1004
|
+
update.version,
|
|
1005
|
+
". Reload to see it."
|
|
1006
|
+
] })
|
|
1007
|
+
] });
|
|
1008
|
+
}
|
|
1009
|
+
const problem = outcome && outcome.state !== "pending" ? outcome.state === "stale" ? "The site changed since the checks ran. Try again in a minute." : outcome.state === "red" ? `The checks failed${outcome.failingCheck ? ` (${outcome.failingCheck})` : ""}. Your web team has been able to see this.` : outcome.state === "error" ? outcome.message : null : null;
|
|
1010
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `rz-update${compact ? " rz-update--strip" : ""}`, role: "status", children: [
|
|
1011
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rz-update__row", children: [
|
|
1012
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rz-update__title", children: [
|
|
1013
|
+
"Studio ",
|
|
1014
|
+
update.version,
|
|
1015
|
+
" is available"
|
|
1016
|
+
] }),
|
|
1017
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "rz-update__link", onClick: () => setShowNotes((v) => !v), "aria-expanded": showNotes, children: "What\u2019s new" }),
|
|
1018
|
+
update.previewUrl && /* @__PURE__ */ jsxRuntime.jsxs("a", { href: update.previewUrl, target: "_blank", rel: "noreferrer", className: "rz-update__link", children: [
|
|
1019
|
+
"Preview ",
|
|
1020
|
+
/* @__PURE__ */ jsxRuntime.jsx(OutboundArrow, {})
|
|
1021
|
+
] }),
|
|
1022
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { size: "sm", onClick: run, disabled: busy, children: busy ? "Updating\u2026" : "Update" }),
|
|
1023
|
+
onLater && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "rz-update__later", onClick: onLater, children: "Later" })
|
|
1024
|
+
] }),
|
|
1025
|
+
showNotes && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rz-update__notes", children: update.notes ?? `Version ${update.version} of Studio, replacing ${update.currentVersion}. Nothing changes on your website until you press Update.` }),
|
|
1026
|
+
problem && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rz-update__problem", children: problem })
|
|
1027
|
+
] });
|
|
1028
|
+
}
|
|
1029
|
+
function StudioShellFrame({ siteName, logoUrl, siteUrl = "/", user, role, nav, pinnedNav, branding, update = null, children }) {
|
|
877
1030
|
const pathname = navigation.usePathname() ?? "/admin";
|
|
1031
|
+
react.useEffect(() => {
|
|
1032
|
+
if (user) document.cookie = "rz-studio=1; Path=/; Max-Age=2592000; SameSite=Lax";
|
|
1033
|
+
}, [user]);
|
|
878
1034
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
879
1035
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: STUDIO_CSS }),
|
|
880
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1036
|
+
/* @__PURE__ */ jsxRuntime.jsxs(AdminShell, { siteName, logoUrl: logoUrl ?? void 0, siteUrl, user, role, nav, pinnedNav, branding, accountHref: null, activeHref: pathname, children: [
|
|
1037
|
+
/* @__PURE__ */ jsxRuntime.jsx(UpdateStrip, { update, role }),
|
|
1038
|
+
children
|
|
1039
|
+
] })
|
|
881
1040
|
] });
|
|
882
1041
|
}
|
|
883
1042
|
|
|
@@ -2889,51 +3048,6 @@ function RemoveItem({ typeId, slug }) {
|
|
|
2889
3048
|
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rz-alert admin__alert", children: error })
|
|
2890
3049
|
] });
|
|
2891
3050
|
}
|
|
2892
|
-
var POLL_MS = 8e3;
|
|
2893
|
-
var LOCAL_FALLBACK_MS = 15e4;
|
|
2894
|
-
var GIVE_UP_MS = 15 * 6e4;
|
|
2895
|
-
function useDeployed(active, mergedSha) {
|
|
2896
|
-
const [state, setState] = react.useState("waiting");
|
|
2897
|
-
react.useEffect(() => {
|
|
2898
|
-
if (!active) return;
|
|
2899
|
-
let stop = false;
|
|
2900
|
-
let baseline;
|
|
2901
|
-
const started = Date.now();
|
|
2902
|
-
const read2 = async () => {
|
|
2903
|
-
try {
|
|
2904
|
-
const r = await fetch("/api/version", { cache: "no-store" });
|
|
2905
|
-
const j = await r.json();
|
|
2906
|
-
return j.sha;
|
|
2907
|
-
} catch {
|
|
2908
|
-
return null;
|
|
2909
|
-
}
|
|
2910
|
-
};
|
|
2911
|
-
const tick = async () => {
|
|
2912
|
-
if (stop) return;
|
|
2913
|
-
const sha = await read2();
|
|
2914
|
-
if (stop) return;
|
|
2915
|
-
if (baseline === void 0) baseline = sha;
|
|
2916
|
-
const elapsed = Date.now() - started;
|
|
2917
|
-
const matched = sha !== null && mergedSha !== null && sha === mergedSha;
|
|
2918
|
-
const moved = sha !== null && baseline !== null && sha !== baseline;
|
|
2919
|
-
const localDone = sha === null && elapsed >= LOCAL_FALLBACK_MS;
|
|
2920
|
-
if (matched || moved || localDone) {
|
|
2921
|
-
setState("live");
|
|
2922
|
-
return;
|
|
2923
|
-
}
|
|
2924
|
-
if (elapsed >= GIVE_UP_MS) {
|
|
2925
|
-
setState("slow");
|
|
2926
|
-
return;
|
|
2927
|
-
}
|
|
2928
|
-
setTimeout(tick, POLL_MS);
|
|
2929
|
-
};
|
|
2930
|
-
void tick();
|
|
2931
|
-
return () => {
|
|
2932
|
-
stop = true;
|
|
2933
|
-
};
|
|
2934
|
-
}, [active, mergedSha]);
|
|
2935
|
-
return state;
|
|
2936
|
-
}
|
|
2937
3051
|
var REFRESH_MS = 1e4;
|
|
2938
3052
|
function PublishPanel({ number, htmlUrl, merged, closed = false, branch, removal = false, mergedSha = null, status, item }) {
|
|
2939
3053
|
const { mergeContentPr, discardChange } = useStudio().actions;
|
|
@@ -3832,12 +3946,46 @@ function BusinessTab({ initial }) {
|
|
|
3832
3946
|
] })
|
|
3833
3947
|
] });
|
|
3834
3948
|
}
|
|
3835
|
-
|
|
3836
|
-
|
|
3949
|
+
function StudioTab({ update, version, role }) {
|
|
3950
|
+
const { supportName } = useStudio();
|
|
3951
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "acct-stack", children: [
|
|
3952
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "acct-card", children: [
|
|
3953
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "acct-title", children: [
|
|
3954
|
+
"Studio ",
|
|
3955
|
+
version
|
|
3956
|
+
] }),
|
|
3957
|
+
!update && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "acct-blurb", children: "You\u2019re up to date. When a new version comes out, it appears here and as a strip at the top of every Studio page." }),
|
|
3958
|
+
update?.state === "checking" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "acct-blurb", children: [
|
|
3959
|
+
"Studio ",
|
|
3960
|
+
update.version,
|
|
3961
|
+
" is on its way \u2014 the checks are still running. Come back in a couple of minutes."
|
|
3962
|
+
] }),
|
|
3963
|
+
update?.state === "failed" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "acct-blurb", children: [
|
|
3964
|
+
"Studio ",
|
|
3965
|
+
update.version,
|
|
3966
|
+
" is available, but its checks failed, so it can\u2019t be installed yet.",
|
|
3967
|
+
role === "staff" && update.failingCheck ? ` Failing check: ${update.failingCheck}.` : ` ${supportName} has been able to see this and will sort it out.`
|
|
3968
|
+
] }),
|
|
3969
|
+
update?.state === "ready" && /* @__PURE__ */ jsxRuntime.jsx(UpdateBody, { update })
|
|
3970
|
+
] }),
|
|
3971
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Card, { className: "acct-card", children: [
|
|
3972
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "acct-title", children: "How updates work" }),
|
|
3973
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "acct-blurb", children: [
|
|
3974
|
+
"Studio is a small package inside your website. When ",
|
|
3975
|
+
supportName,
|
|
3976
|
+
" releases a new version, your site prepares the update as a checked change \u2014 the same way a blog post is checked before it goes live \u2014 and builds a private preview. Nothing changes until you press ",
|
|
3977
|
+
/* @__PURE__ */ jsxRuntime.jsx("b", { children: "Update" }),
|
|
3978
|
+
". If the update would break anything, the button never unlocks."
|
|
3979
|
+
] })
|
|
3980
|
+
] })
|
|
3981
|
+
] });
|
|
3982
|
+
}
|
|
3983
|
+
var LABELS = { profile: "My Profile", password: "Change Password", team: "Team", business: "Business", studio: "Studio" };
|
|
3984
|
+
function AccountTabs({ me, manages, team, branding, myUserId, myRole, update = null, version = "" }) {
|
|
3837
3985
|
const router = navigation.useRouter();
|
|
3838
3986
|
const pathname = navigation.usePathname();
|
|
3839
3987
|
const params = navigation.useSearchParams();
|
|
3840
|
-
const ids = manages ? ["profile", "password", "team", "business"] : ["profile", "password"];
|
|
3988
|
+
const ids = manages ? ["profile", "password", "team", "business", "studio"] : ["profile", "password"];
|
|
3841
3989
|
const requested = params.get("tab");
|
|
3842
3990
|
const active = requested && ids.includes(requested) ? requested : "profile";
|
|
3843
3991
|
const setActive = (v) => router.replace(`${pathname}?tab=${v}`, { scroll: false });
|
|
@@ -3846,14 +3994,15 @@ function AccountTabs({ me, manages, team, branding, myUserId, myRole }) {
|
|
|
3846
3994
|
active === "profile" && /* @__PURE__ */ jsxRuntime.jsx(ProfileTab, { email: me.email, name: me.name, displayName: me.displayName, avatarUrl: me.avatarUrl }),
|
|
3847
3995
|
active === "password" && /* @__PURE__ */ jsxRuntime.jsx(PasswordTab, {}),
|
|
3848
3996
|
active === "team" && manages && (team?.ok ? /* @__PURE__ */ jsxRuntime.jsx(TeamTab, { members: team.members, canInvite: team.canInvite, myUserId, myRole }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rz-alert admin__alert", children: team?.error ?? "Couldn\u2019t load the team." })),
|
|
3849
|
-
active === "business" && manages && /* @__PURE__ */ jsxRuntime.jsx(BusinessTab, { initial: branding })
|
|
3997
|
+
active === "business" && manages && /* @__PURE__ */ jsxRuntime.jsx(BusinessTab, { initial: branding }),
|
|
3998
|
+
active === "studio" && manages && /* @__PURE__ */ jsxRuntime.jsx(StudioTab, { update, version, role: myRole })
|
|
3850
3999
|
] });
|
|
3851
4000
|
}
|
|
3852
|
-
function StudioAccount({ me, manages, team, branding, myUserId, myRole }) {
|
|
4001
|
+
function StudioAccount({ me, manages, team, branding, myUserId, myRole, update = null, version = "" }) {
|
|
3853
4002
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "acct", children: [
|
|
3854
4003
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "acct-h1", children: "Account" }),
|
|
3855
4004
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "acct-email", children: me.email }),
|
|
3856
|
-
/* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(AccountTabs, { me, manages, team, branding, myUserId, myRole }) })
|
|
4005
|
+
/* @__PURE__ */ jsxRuntime.jsx(react.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsx(AccountTabs, { me, manages, team, branding, myUserId, myRole, update, version }) })
|
|
3857
4006
|
] });
|
|
3858
4007
|
}
|
|
3859
4008
|
|
|
@@ -3926,7 +4075,7 @@ Open the avatar menu (top right) and choose **Sign out**.
|
|
|
3926
4075
|
section: "start",
|
|
3927
4076
|
title: "Finding your way around",
|
|
3928
4077
|
summary: "The sidebar, the dashboard, the lists, and the avatar menu.",
|
|
3929
|
-
keywords: ["sidebar", "dashboard", "navigation", "menu", "settings"],
|
|
4078
|
+
keywords: ["sidebar", "dashboard", "navigation", "menu", "settings", "view website", "live site", "visit site"],
|
|
3930
4079
|
body: `
|
|
3931
4080
|
## The sidebar
|
|
3932
4081
|
|
|
@@ -3938,9 +4087,13 @@ On a narrow screen the sidebar collapses to icons; press the arrow at the bottom
|
|
|
3938
4087
|
|
|
3939
4088
|
Every row is one item: its title, date, status and a **View live** link. **+ New** at the top starts a new one. Click a title to edit it. The **Status** column links straight to a waiting change.
|
|
3940
4089
|
|
|
4090
|
+
## Getting to the live website
|
|
4091
|
+
|
|
4092
|
+
Click the site name at the top left \u2014 it opens the live website in a new tab (hover and an arrow appears). The avatar menu has the same thing as **View website**. Each item's list row also has **View live** for that one page.
|
|
4093
|
+
|
|
3941
4094
|
## The avatar menu
|
|
3942
4095
|
|
|
3943
|
-
Top right, your photo or initials. From here: **Account**, **Help center** (this page),
|
|
4096
|
+
Top right, your photo or initials. From here: a light/dark toggle, **View website**, **Account**, **Help center** (this page), and **Sign out**.
|
|
3944
4097
|
|
|
3945
4098
|
## The Ask bubble
|
|
3946
4099
|
|
|
@@ -3987,6 +4140,28 @@ The status becomes **Needs fixing** and the message names the problem. Open the
|
|
|
3987
4140
|
| **Removing\u2026** / **Removal ready** | You asked to take an item down; same steps as any change. | Publish to make the removal live, or discard to keep the item. |
|
|
3988
4141
|
|
|
3989
4142
|
One item has at most one change waiting at a time. Saving again updates that same change rather than starting a second one.
|
|
4143
|
+
`
|
|
4144
|
+
},
|
|
4145
|
+
{
|
|
4146
|
+
id: "studio-pill",
|
|
4147
|
+
section: "start",
|
|
4148
|
+
title: "Getting back to Studio from the website",
|
|
4149
|
+
summary: "A small Studio pill appears bottom-left on the website while you're signed in \u2014 Edit this page, or Dashboard.",
|
|
4150
|
+
keywords: ["pill", "edit this page", "admin bar", "back to studio", "website"],
|
|
4151
|
+
body: `
|
|
4152
|
+
## What it is
|
|
4153
|
+
|
|
4154
|
+
While you're signed in to Studio, your public website shows a small dark pill in the bottom-left corner: **Studio \xB7 Edit this page \xB7 Dashboard**. Visitors never see it \u2014 it only appears in a browser where you've signed in.
|
|
4155
|
+
|
|
4156
|
+
## Why it's useful
|
|
4157
|
+
|
|
4158
|
+
Spot a typo while reading your own site? **Edit this page** opens that exact post or event in Studio. **Dashboard** takes you to the Studio home.
|
|
4159
|
+
|
|
4160
|
+
## Good to know
|
|
4161
|
+
|
|
4162
|
+
- **Edit this page** only shows on pages Studio manages (a blog post, an event). On the home page or About, you get **Dashboard** only.
|
|
4163
|
+
- The \xD7 hides the pill for that browser tab; it comes back next time you open the site.
|
|
4164
|
+
- It disappears when you sign out of Studio. If you see it but Studio asks you to sign in again, your session simply expired \u2014 sign in and carry on.
|
|
3990
4165
|
`
|
|
3991
4166
|
}
|
|
3992
4167
|
];
|
|
@@ -4807,6 +4982,38 @@ Pictures save the moment you choose them (**Choose a picture**, **Replace**, **R
|
|
|
4807
4982
|
## Where the pictures live
|
|
4808
4983
|
|
|
4809
4984
|
In Studio's own secure storage \u2014 not in your website's files, so they don't go through Save/Publish.
|
|
4985
|
+
`
|
|
4986
|
+
},
|
|
4987
|
+
{
|
|
4988
|
+
id: "updating-studio",
|
|
4989
|
+
section: "account",
|
|
4990
|
+
title: "Updating Studio",
|
|
4991
|
+
summary: "When a new version is out, owners see a strip with what's new, a preview and an Update button. Nothing installs until you press it.",
|
|
4992
|
+
keywords: ["update", "upgrade", "new version", "release", "what's new", "studio version"],
|
|
4993
|
+
body: `
|
|
4994
|
+
## What it is
|
|
4995
|
+
|
|
4996
|
+
Studio is a small package inside your website, and it improves over time. When {supportName} releases a new version, your website prepares the update automatically as a **checked change** \u2014 exactly like a blog post is checked before it goes live \u2014 and builds a private preview of your site with the new Studio in it.
|
|
4997
|
+
|
|
4998
|
+
## Where you see it
|
|
4999
|
+
|
|
5000
|
+
- A quiet strip at the top of every Studio page: **Studio 0.15 is available \xB7 What's new \xB7 Preview \xB7 Update \xB7 Later**. Only owners and {supportName} see it; editors don't.
|
|
5001
|
+
- **Settings \u2192 Studio**: the version you're running, the pending update with its notes, and the same Update button.
|
|
5002
|
+
|
|
5003
|
+
The strip appears only once the update's checks have passed. If they fail, nothing is offered \u2014 {supportName} sees the failure and fixes it.
|
|
5004
|
+
|
|
5005
|
+
## How to update
|
|
5006
|
+
|
|
5007
|
+
1. Read **What's new** (a few lines, plain English).
|
|
5008
|
+
2. Optional: press **Preview** to open your website running the new Studio.
|
|
5009
|
+
3. Press **Update**. The tracker shows *Updated \u2192 Live*; about two minutes later the website has rebuilt.
|
|
5010
|
+
4. Reload Studio to use the new version.
|
|
5011
|
+
|
|
5012
|
+
## Good to know
|
|
5013
|
+
|
|
5014
|
+
- **Later** hides the strip for this browser tab; it comes back next time.
|
|
5015
|
+
- Nothing on your public website changes because of a Studio update \u2014 only the dashboard does.
|
|
5016
|
+
- You can't skip a version or go back from here; if something looks wrong after an update, tell {supportName}.
|
|
4810
5017
|
`
|
|
4811
5018
|
}
|
|
4812
5019
|
];
|
|
@@ -5245,8 +5452,12 @@ function BackArrow() {
|
|
|
5245
5452
|
] });
|
|
5246
5453
|
}
|
|
5247
5454
|
|
|
5455
|
+
// src/version.ts
|
|
5456
|
+
var ADMIN_VERSION = "0.15.0" ;
|
|
5457
|
+
|
|
5248
5458
|
// src/studio-ui/types.ts
|
|
5249
5459
|
var ACTION_NAMES = [
|
|
5460
|
+
"updateStudio",
|
|
5250
5461
|
"publishContent",
|
|
5251
5462
|
"removeContent",
|
|
5252
5463
|
"mergeContentPr",
|
|
@@ -5267,6 +5478,7 @@ var ACTION_NAMES = [
|
|
|
5267
5478
|
];
|
|
5268
5479
|
|
|
5269
5480
|
exports.ACTION_NAMES = ACTION_NAMES;
|
|
5481
|
+
exports.ADMIN_VERSION = ADMIN_VERSION;
|
|
5270
5482
|
exports.ContentEditor = ContentEditor;
|
|
5271
5483
|
exports.GLOSSARY = GLOSSARY;
|
|
5272
5484
|
exports.HELP_ARTICLES = HELP_ARTICLES;
|
|
@@ -5290,6 +5502,9 @@ exports.StudioPullRequest = StudioPullRequest;
|
|
|
5290
5502
|
exports.StudioShellFrame = StudioShellFrame;
|
|
5291
5503
|
exports.StudioSignIn = StudioSignIn;
|
|
5292
5504
|
exports.StudioTerm = StudioTerm;
|
|
5505
|
+
exports.UpdateBody = UpdateBody;
|
|
5506
|
+
exports.UpdateStrip = UpdateStrip;
|
|
5507
|
+
exports.canSeeUpdates = canSeeUpdates;
|
|
5293
5508
|
exports.copyFor = copyFor;
|
|
5294
5509
|
exports.fillVars = fillVars;
|
|
5295
5510
|
exports.helpAsText = helpAsText;
|