@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.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { createContext, useContext, useState, useId, useTransition,
|
|
2
|
+
import { createContext, useContext, useState, useEffect, useId, useTransition, Suspense, useMemo, useRef, useCallback, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
|
|
5
5
|
import { createBrowserClient } from '@supabase/ssr';
|
|
@@ -154,6 +154,32 @@ function Sidebar({ items, pinned = [], activeHref, basePath }) {
|
|
|
154
154
|
)
|
|
155
155
|
] });
|
|
156
156
|
}
|
|
157
|
+
function buttonClass(variant = "secondary", size = "md", extra) {
|
|
158
|
+
return ["rz-btn", `rz-btn--${variant}`, `rz-btn--${size}`, extra].filter(Boolean).join(" ");
|
|
159
|
+
}
|
|
160
|
+
function Button({ variant = "secondary", size = "md", className, type = "button", ...rest }) {
|
|
161
|
+
return /* @__PURE__ */ jsx("button", { type, className: buttonClass(variant, size, className), ...rest });
|
|
162
|
+
}
|
|
163
|
+
function LinkButton({ variant = "secondary", size = "md", className, external, forward, children, ...rest }) {
|
|
164
|
+
const extra = external ? { target: "_blank", rel: "noreferrer", ...rest } : rest;
|
|
165
|
+
return /* @__PURE__ */ jsxs("a", { className: buttonClass(variant, size, className), ...extra, children: [
|
|
166
|
+
children,
|
|
167
|
+
external && /* @__PURE__ */ jsx(OutboundArrow, {}),
|
|
168
|
+
forward && !external && /* @__PURE__ */ jsx(ForwardArrow, {})
|
|
169
|
+
] });
|
|
170
|
+
}
|
|
171
|
+
function ForwardArrow() {
|
|
172
|
+
return /* @__PURE__ */ 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: [
|
|
173
|
+
/* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
|
|
174
|
+
/* @__PURE__ */ jsx("path", { d: "m13 6 6 6-6 6" })
|
|
175
|
+
] });
|
|
176
|
+
}
|
|
177
|
+
function OutboundArrow() {
|
|
178
|
+
return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "rz-arrow", children: [
|
|
179
|
+
/* @__PURE__ */ jsx("path", { d: "M7 17 17 7" }),
|
|
180
|
+
/* @__PURE__ */ jsx("path", { d: "M7 7h10v10" })
|
|
181
|
+
] });
|
|
182
|
+
}
|
|
157
183
|
var THEME_KEY = "rz-admin-theme";
|
|
158
184
|
function useTheme(defaultTheme = "light") {
|
|
159
185
|
const [theme, setTheme] = useState(defaultTheme);
|
|
@@ -205,12 +231,16 @@ var HelpIcon = () => /* @__PURE__ */ jsxs("svg", { ...ico, children: [
|
|
|
205
231
|
/* @__PURE__ */ jsx("path", { d: "M2 4h6a4 4 0 0 1 4 4v12a3 3 0 0 0-3-3H2z" }),
|
|
206
232
|
/* @__PURE__ */ jsx("path", { d: "M22 4h-6a4 4 0 0 0-4 4v12a3 3 0 0 1 3-3h7z" })
|
|
207
233
|
] });
|
|
234
|
+
var GlobeIcon = () => /* @__PURE__ */ jsxs("svg", { ...ico, children: [
|
|
235
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
236
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18" })
|
|
237
|
+
] });
|
|
208
238
|
var OutIcon = () => /* @__PURE__ */ jsxs("svg", { ...ico, children: [
|
|
209
239
|
/* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" }),
|
|
210
240
|
/* @__PURE__ */ jsx("path", { d: "M16 17l5-5-5-5" }),
|
|
211
241
|
/* @__PURE__ */ jsx("path", { d: "M21 12H9" })
|
|
212
242
|
] });
|
|
213
|
-
function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, helpHref }) {
|
|
243
|
+
function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, helpHref, siteUrl }) {
|
|
214
244
|
const [open, setOpen] = useState(false);
|
|
215
245
|
const wrap = useRef(null);
|
|
216
246
|
useEffect(() => {
|
|
@@ -245,7 +275,12 @@ function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, hel
|
|
|
245
275
|
/* @__PURE__ */ jsx("span", { children: "Theme" }),
|
|
246
276
|
/* @__PURE__ */ jsx("span", { className: "rz-menu__end", children: /* @__PURE__ */ jsx(ThemeToggle, { theme, onChange: onTheme }) })
|
|
247
277
|
] }),
|
|
248
|
-
(accountHref || helpHref) && /* @__PURE__ */ jsx("div", { className: "rz-menu__sep" }),
|
|
278
|
+
(siteUrl || accountHref || helpHref) && /* @__PURE__ */ jsx("div", { className: "rz-menu__sep" }),
|
|
279
|
+
siteUrl && /* @__PURE__ */ jsxs("a", { href: siteUrl, target: "_blank", rel: "noreferrer", role: "menuitem", className: "rz-menu__item", children: [
|
|
280
|
+
/* @__PURE__ */ jsx(GlobeIcon, {}),
|
|
281
|
+
"View website",
|
|
282
|
+
/* @__PURE__ */ jsx("span", { className: "rz-menu__end", children: /* @__PURE__ */ jsx(OutboundArrow, {}) })
|
|
283
|
+
] }),
|
|
249
284
|
accountHref && /* @__PURE__ */ jsxs("a", { href: accountHref, role: "menuitem", className: "rz-menu__item", children: [
|
|
250
285
|
/* @__PURE__ */ jsx(UserIcon, {}),
|
|
251
286
|
"Account"
|
|
@@ -262,19 +297,28 @@ function AccountMenu({ user, role, theme, onTheme, signOutPath, accountHref, hel
|
|
|
262
297
|
] })
|
|
263
298
|
] });
|
|
264
299
|
}
|
|
265
|
-
function TopBar({ siteName, productName, logoUrl, homeHref, user, role, theme, onTheme, signOutPath, accountHref, helpHref }) {
|
|
300
|
+
function TopBar({ siteName, productName, logoUrl, homeHref, siteUrl, user, role, theme, onTheme, signOutPath, accountHref, helpHref }) {
|
|
266
301
|
return /* @__PURE__ */ jsxs("header", { className: "rz-topbar", children: [
|
|
267
|
-
/* @__PURE__ */ jsxs(
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
302
|
+
/* @__PURE__ */ jsxs(
|
|
303
|
+
"a",
|
|
304
|
+
{
|
|
305
|
+
href: siteUrl || homeHref,
|
|
306
|
+
className: "rz-topbar__brand",
|
|
307
|
+
...siteUrl ? { target: "_blank", rel: "noreferrer", title: "Open the live website in a new tab" } : {},
|
|
308
|
+
children: [
|
|
309
|
+
logoUrl && /* @__PURE__ */ jsx("img", { src: logoUrl, alt: "", className: "rz-topbar__logo" }),
|
|
310
|
+
/* @__PURE__ */ jsx("span", { children: siteName }),
|
|
311
|
+
/* @__PURE__ */ jsx("span", { className: "rz-topbar__product", children: productName }),
|
|
312
|
+
siteUrl && /* @__PURE__ */ jsx(OutboundArrow, {})
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
),
|
|
272
316
|
user && role && /* @__PURE__ */ jsxs("div", { className: "rz-topbar__right", children: [
|
|
273
317
|
/* @__PURE__ */ jsxs("span", { className: "rz-topbar__greeting", "data-testid": "rz-greeting", children: [
|
|
274
318
|
"Welcome back, ",
|
|
275
319
|
firstNameOf(user)
|
|
276
320
|
] }),
|
|
277
|
-
/* @__PURE__ */ jsx(AccountMenu, { user, role, theme, onTheme, signOutPath, accountHref, helpHref })
|
|
321
|
+
/* @__PURE__ */ jsx(AccountMenu, { user, role, theme, onTheme, signOutPath, accountHref, helpHref, siteUrl })
|
|
278
322
|
] })
|
|
279
323
|
] });
|
|
280
324
|
}
|
|
@@ -334,6 +378,8 @@ var SHELL_CSS = `
|
|
|
334
378
|
.rz-topbar__brand { display: flex; align-items: center; gap: .6rem; font-weight: 600; font-size: .9375rem; text-decoration: none; }
|
|
335
379
|
.rz-topbar__logo { height: 22px; width: auto; display: block; }
|
|
336
380
|
.rz-topbar__product { font-weight: 400; color: var(--text-secondary); }
|
|
381
|
+
.rz-topbar__brand .rz-arrow { color: var(--text-muted); opacity: 0; transition: opacity .15s, transform .15s; }
|
|
382
|
+
.rz-topbar__brand:hover .rz-arrow { opacity: 1; }
|
|
337
383
|
.rz-topbar__right { margin-left: auto; display: flex; align-items: center; gap: 1rem; }
|
|
338
384
|
.rz-topbar__greeting { color: var(--text-secondary); font-size: .8rem; }
|
|
339
385
|
.rz-body { display: flex; flex: 1; min-height: 0; }
|
|
@@ -545,6 +591,7 @@ function AdminShell({
|
|
|
545
591
|
signOutPath,
|
|
546
592
|
accountHref,
|
|
547
593
|
helpHref,
|
|
594
|
+
siteUrl,
|
|
548
595
|
branding,
|
|
549
596
|
defaultTheme = "light",
|
|
550
597
|
children
|
|
@@ -561,6 +608,7 @@ function AdminShell({
|
|
|
561
608
|
siteName: shownName,
|
|
562
609
|
productName,
|
|
563
610
|
logoUrl: shownLogo,
|
|
611
|
+
siteUrl,
|
|
564
612
|
homeHref: basePath,
|
|
565
613
|
user,
|
|
566
614
|
role,
|
|
@@ -577,32 +625,6 @@ function AdminShell({
|
|
|
577
625
|
] })
|
|
578
626
|
] });
|
|
579
627
|
}
|
|
580
|
-
function buttonClass(variant = "secondary", size = "md", extra) {
|
|
581
|
-
return ["rz-btn", `rz-btn--${variant}`, `rz-btn--${size}`, extra].filter(Boolean).join(" ");
|
|
582
|
-
}
|
|
583
|
-
function Button({ variant = "secondary", size = "md", className, type = "button", ...rest }) {
|
|
584
|
-
return /* @__PURE__ */ jsx("button", { type, className: buttonClass(variant, size, className), ...rest });
|
|
585
|
-
}
|
|
586
|
-
function LinkButton({ variant = "secondary", size = "md", className, external, forward, children, ...rest }) {
|
|
587
|
-
const extra = external ? { target: "_blank", rel: "noreferrer", ...rest } : rest;
|
|
588
|
-
return /* @__PURE__ */ jsxs("a", { className: buttonClass(variant, size, className), ...extra, children: [
|
|
589
|
-
children,
|
|
590
|
-
external && /* @__PURE__ */ jsx(OutboundArrow, {}),
|
|
591
|
-
forward && !external && /* @__PURE__ */ jsx(ForwardArrow, {})
|
|
592
|
-
] });
|
|
593
|
-
}
|
|
594
|
-
function ForwardArrow() {
|
|
595
|
-
return /* @__PURE__ */ 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: [
|
|
596
|
-
/* @__PURE__ */ jsx("path", { d: "M5 12h14" }),
|
|
597
|
-
/* @__PURE__ */ jsx("path", { d: "m13 6 6 6-6 6" })
|
|
598
|
-
] });
|
|
599
|
-
}
|
|
600
|
-
function OutboundArrow() {
|
|
601
|
-
return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "rz-arrow", children: [
|
|
602
|
-
/* @__PURE__ */ jsx("path", { d: "M7 17 17 7" }),
|
|
603
|
-
/* @__PURE__ */ jsx("path", { d: "M7 7h10v10" })
|
|
604
|
-
] });
|
|
605
|
-
}
|
|
606
628
|
function Card({ title, meta, note, children, actions, className }) {
|
|
607
629
|
return /* @__PURE__ */ jsxs("div", { className: ["rz-card", className].filter(Boolean).join(" "), children: [
|
|
608
630
|
title && /* @__PURE__ */ jsx("div", { className: "rz-card__title", children: title }),
|
|
@@ -866,12 +888,149 @@ var STUDIO_CSS = `
|
|
|
866
888
|
.rz-admin .rz-help__pager a:hover { color: var(--signal); }
|
|
867
889
|
.rz-admin .rz-arrow--back { transform: none; }
|
|
868
890
|
@media (prefers-reduced-motion: no-preference) { .rz-admin a:hover .rz-arrow--back { transform: translateX(-4px); } }
|
|
891
|
+
|
|
892
|
+
/* ---- Studio update strip / Settings \u2192 Studio ---------------------------- */
|
|
893
|
+
.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; }
|
|
894
|
+
.rz-admin .rz-update--strip { margin: 0 0 1.25rem; }
|
|
895
|
+
.rz-admin .rz-update__row { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1rem; }
|
|
896
|
+
.rz-admin .rz-update__title { font-weight: 600; color: var(--text-primary); }
|
|
897
|
+
.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; }
|
|
898
|
+
.rz-admin .rz-update__link:hover { color: var(--text-primary); }
|
|
899
|
+
.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; }
|
|
900
|
+
.rz-admin .rz-update__later:hover { color: var(--text-primary); }
|
|
901
|
+
.rz-admin .rz-update__notes { margin: .6rem 0 0; font-size: .875rem; line-height: 1.55; color: var(--text-secondary); white-space: pre-line; }
|
|
902
|
+
.rz-admin .rz-update__problem { margin: .6rem 0 0; font-size: .875rem; color: var(--status-down); }
|
|
903
|
+
.rz-admin .rz-update__done { display: block; margin-top: .5rem; font-size: .875rem; color: var(--text-secondary); }
|
|
869
904
|
`;
|
|
870
|
-
|
|
905
|
+
var POLL_MS = 8e3;
|
|
906
|
+
var LOCAL_FALLBACK_MS = 15e4;
|
|
907
|
+
var GIVE_UP_MS = 15 * 6e4;
|
|
908
|
+
function useDeployed(active, mergedSha) {
|
|
909
|
+
const [state, setState] = useState("waiting");
|
|
910
|
+
useEffect(() => {
|
|
911
|
+
if (!active) return;
|
|
912
|
+
let stop = false;
|
|
913
|
+
let baseline;
|
|
914
|
+
const started = Date.now();
|
|
915
|
+
const read2 = async () => {
|
|
916
|
+
try {
|
|
917
|
+
const r = await fetch("/api/version", { cache: "no-store" });
|
|
918
|
+
const j = await r.json();
|
|
919
|
+
return j.sha;
|
|
920
|
+
} catch {
|
|
921
|
+
return null;
|
|
922
|
+
}
|
|
923
|
+
};
|
|
924
|
+
const tick = async () => {
|
|
925
|
+
if (stop) return;
|
|
926
|
+
const sha = await read2();
|
|
927
|
+
if (stop) return;
|
|
928
|
+
if (baseline === void 0) baseline = sha;
|
|
929
|
+
const elapsed = Date.now() - started;
|
|
930
|
+
const matched = sha !== null && mergedSha !== null && sha === mergedSha;
|
|
931
|
+
const moved = sha !== null && baseline !== null && sha !== baseline;
|
|
932
|
+
const localDone = sha === null && elapsed >= LOCAL_FALLBACK_MS;
|
|
933
|
+
if (matched || moved || localDone) {
|
|
934
|
+
setState("live");
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
if (elapsed >= GIVE_UP_MS) {
|
|
938
|
+
setState("slow");
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
setTimeout(tick, POLL_MS);
|
|
942
|
+
};
|
|
943
|
+
void tick();
|
|
944
|
+
return () => {
|
|
945
|
+
stop = true;
|
|
946
|
+
};
|
|
947
|
+
}, [active, mergedSha]);
|
|
948
|
+
return state;
|
|
949
|
+
}
|
|
950
|
+
var HIDE_KEY = "rz-update-later";
|
|
951
|
+
function canSeeUpdates(role) {
|
|
952
|
+
return role === "owner" || role === "staff";
|
|
953
|
+
}
|
|
954
|
+
function UpdateStrip({ update, role }) {
|
|
955
|
+
const [hidden, setHidden] = useState(true);
|
|
956
|
+
useEffect(() => {
|
|
957
|
+
try {
|
|
958
|
+
setHidden(sessionStorage.getItem(HIDE_KEY) === update?.version);
|
|
959
|
+
} catch {
|
|
960
|
+
setHidden(false);
|
|
961
|
+
}
|
|
962
|
+
}, [update?.version]);
|
|
963
|
+
if (!update || update.state !== "ready" || !canSeeUpdates(role) || hidden) return null;
|
|
964
|
+
const later = () => {
|
|
965
|
+
try {
|
|
966
|
+
sessionStorage.setItem(HIDE_KEY, update.version);
|
|
967
|
+
} catch {
|
|
968
|
+
}
|
|
969
|
+
setHidden(true);
|
|
970
|
+
};
|
|
971
|
+
return /* @__PURE__ */ jsx(UpdateBody, { update, onLater: later, compact: true });
|
|
972
|
+
}
|
|
973
|
+
function UpdateBody({ update, onLater, compact = false }) {
|
|
974
|
+
const { actions } = useStudio();
|
|
975
|
+
const [showNotes, setShowNotes] = useState(!compact);
|
|
976
|
+
const [busy, setBusy] = useState(false);
|
|
977
|
+
const [outcome, setOutcome] = useState(null);
|
|
978
|
+
const merged = outcome?.state === "merged";
|
|
979
|
+
const deploy = useDeployed(merged, merged ? outcome.sha : null);
|
|
980
|
+
const run = async () => {
|
|
981
|
+
setBusy(true);
|
|
982
|
+
try {
|
|
983
|
+
setOutcome(await actions.updateStudio(update.number));
|
|
984
|
+
} finally {
|
|
985
|
+
setBusy(false);
|
|
986
|
+
}
|
|
987
|
+
};
|
|
988
|
+
if (merged) {
|
|
989
|
+
const live = deploy === "live";
|
|
990
|
+
const steps = [
|
|
991
|
+
{ label: "Updated", state: "done", note: `Studio ${update.version}` },
|
|
992
|
+
{ label: "Live", state: live ? "done" : "active", note: live ? "On the site now" : deploy === "slow" ? "Taking longer than usual" : "Rebuilding, about two minutes" }
|
|
993
|
+
];
|
|
994
|
+
return /* @__PURE__ */ jsxs("div", { className: `rz-update${compact ? " rz-update--strip" : ""}`, role: "status", children: [
|
|
995
|
+
/* @__PURE__ */ jsx(Steps, { steps }),
|
|
996
|
+
live && /* @__PURE__ */ jsxs("span", { className: "rz-update__done", children: [
|
|
997
|
+
"Studio updated to ",
|
|
998
|
+
update.version,
|
|
999
|
+
". Reload to see it."
|
|
1000
|
+
] })
|
|
1001
|
+
] });
|
|
1002
|
+
}
|
|
1003
|
+
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;
|
|
1004
|
+
return /* @__PURE__ */ jsxs("div", { className: `rz-update${compact ? " rz-update--strip" : ""}`, role: "status", children: [
|
|
1005
|
+
/* @__PURE__ */ jsxs("div", { className: "rz-update__row", children: [
|
|
1006
|
+
/* @__PURE__ */ jsxs("span", { className: "rz-update__title", children: [
|
|
1007
|
+
"Studio ",
|
|
1008
|
+
update.version,
|
|
1009
|
+
" is available"
|
|
1010
|
+
] }),
|
|
1011
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "rz-update__link", onClick: () => setShowNotes((v) => !v), "aria-expanded": showNotes, children: "What\u2019s new" }),
|
|
1012
|
+
update.previewUrl && /* @__PURE__ */ jsxs("a", { href: update.previewUrl, target: "_blank", rel: "noreferrer", className: "rz-update__link", children: [
|
|
1013
|
+
"Preview ",
|
|
1014
|
+
/* @__PURE__ */ jsx(OutboundArrow, {})
|
|
1015
|
+
] }),
|
|
1016
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: run, disabled: busy, children: busy ? "Updating\u2026" : "Update" }),
|
|
1017
|
+
onLater && /* @__PURE__ */ jsx("button", { type: "button", className: "rz-update__later", onClick: onLater, children: "Later" })
|
|
1018
|
+
] }),
|
|
1019
|
+
showNotes && /* @__PURE__ */ 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.` }),
|
|
1020
|
+
problem && /* @__PURE__ */ jsx("p", { className: "rz-update__problem", children: problem })
|
|
1021
|
+
] });
|
|
1022
|
+
}
|
|
1023
|
+
function StudioShellFrame({ siteName, logoUrl, siteUrl = "/", user, role, nav, pinnedNav, branding, update = null, children }) {
|
|
871
1024
|
const pathname = usePathname() ?? "/admin";
|
|
1025
|
+
useEffect(() => {
|
|
1026
|
+
if (user) document.cookie = "rz-studio=1; Path=/; Max-Age=2592000; SameSite=Lax";
|
|
1027
|
+
}, [user]);
|
|
872
1028
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
873
1029
|
/* @__PURE__ */ jsx("style", { children: STUDIO_CSS }),
|
|
874
|
-
/* @__PURE__ */
|
|
1030
|
+
/* @__PURE__ */ jsxs(AdminShell, { siteName, logoUrl: logoUrl ?? void 0, siteUrl, user, role, nav, pinnedNav, branding, accountHref: null, activeHref: pathname, children: [
|
|
1031
|
+
/* @__PURE__ */ jsx(UpdateStrip, { update, role }),
|
|
1032
|
+
children
|
|
1033
|
+
] })
|
|
875
1034
|
] });
|
|
876
1035
|
}
|
|
877
1036
|
|
|
@@ -2883,51 +3042,6 @@ function RemoveItem({ typeId, slug }) {
|
|
|
2883
3042
|
error && /* @__PURE__ */ jsx("div", { className: "rz-alert admin__alert", children: error })
|
|
2884
3043
|
] });
|
|
2885
3044
|
}
|
|
2886
|
-
var POLL_MS = 8e3;
|
|
2887
|
-
var LOCAL_FALLBACK_MS = 15e4;
|
|
2888
|
-
var GIVE_UP_MS = 15 * 6e4;
|
|
2889
|
-
function useDeployed(active, mergedSha) {
|
|
2890
|
-
const [state, setState] = useState("waiting");
|
|
2891
|
-
useEffect(() => {
|
|
2892
|
-
if (!active) return;
|
|
2893
|
-
let stop = false;
|
|
2894
|
-
let baseline;
|
|
2895
|
-
const started = Date.now();
|
|
2896
|
-
const read2 = async () => {
|
|
2897
|
-
try {
|
|
2898
|
-
const r = await fetch("/api/version", { cache: "no-store" });
|
|
2899
|
-
const j = await r.json();
|
|
2900
|
-
return j.sha;
|
|
2901
|
-
} catch {
|
|
2902
|
-
return null;
|
|
2903
|
-
}
|
|
2904
|
-
};
|
|
2905
|
-
const tick = async () => {
|
|
2906
|
-
if (stop) return;
|
|
2907
|
-
const sha = await read2();
|
|
2908
|
-
if (stop) return;
|
|
2909
|
-
if (baseline === void 0) baseline = sha;
|
|
2910
|
-
const elapsed = Date.now() - started;
|
|
2911
|
-
const matched = sha !== null && mergedSha !== null && sha === mergedSha;
|
|
2912
|
-
const moved = sha !== null && baseline !== null && sha !== baseline;
|
|
2913
|
-
const localDone = sha === null && elapsed >= LOCAL_FALLBACK_MS;
|
|
2914
|
-
if (matched || moved || localDone) {
|
|
2915
|
-
setState("live");
|
|
2916
|
-
return;
|
|
2917
|
-
}
|
|
2918
|
-
if (elapsed >= GIVE_UP_MS) {
|
|
2919
|
-
setState("slow");
|
|
2920
|
-
return;
|
|
2921
|
-
}
|
|
2922
|
-
setTimeout(tick, POLL_MS);
|
|
2923
|
-
};
|
|
2924
|
-
void tick();
|
|
2925
|
-
return () => {
|
|
2926
|
-
stop = true;
|
|
2927
|
-
};
|
|
2928
|
-
}, [active, mergedSha]);
|
|
2929
|
-
return state;
|
|
2930
|
-
}
|
|
2931
3045
|
var REFRESH_MS = 1e4;
|
|
2932
3046
|
function PublishPanel({ number, htmlUrl, merged, closed = false, branch, removal = false, mergedSha = null, status, item }) {
|
|
2933
3047
|
const { mergeContentPr, discardChange } = useStudio().actions;
|
|
@@ -3826,12 +3940,46 @@ function BusinessTab({ initial }) {
|
|
|
3826
3940
|
] })
|
|
3827
3941
|
] });
|
|
3828
3942
|
}
|
|
3829
|
-
|
|
3830
|
-
|
|
3943
|
+
function StudioTab({ update, version, role }) {
|
|
3944
|
+
const { supportName } = useStudio();
|
|
3945
|
+
return /* @__PURE__ */ jsxs("div", { className: "acct-stack", children: [
|
|
3946
|
+
/* @__PURE__ */ jsxs(Card, { className: "acct-card", children: [
|
|
3947
|
+
/* @__PURE__ */ jsxs("h2", { className: "acct-title", children: [
|
|
3948
|
+
"Studio ",
|
|
3949
|
+
version
|
|
3950
|
+
] }),
|
|
3951
|
+
!update && /* @__PURE__ */ 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." }),
|
|
3952
|
+
update?.state === "checking" && /* @__PURE__ */ jsxs("p", { className: "acct-blurb", children: [
|
|
3953
|
+
"Studio ",
|
|
3954
|
+
update.version,
|
|
3955
|
+
" is on its way \u2014 the checks are still running. Come back in a couple of minutes."
|
|
3956
|
+
] }),
|
|
3957
|
+
update?.state === "failed" && /* @__PURE__ */ jsxs("p", { className: "acct-blurb", children: [
|
|
3958
|
+
"Studio ",
|
|
3959
|
+
update.version,
|
|
3960
|
+
" is available, but its checks failed, so it can\u2019t be installed yet.",
|
|
3961
|
+
role === "staff" && update.failingCheck ? ` Failing check: ${update.failingCheck}.` : ` ${supportName} has been able to see this and will sort it out.`
|
|
3962
|
+
] }),
|
|
3963
|
+
update?.state === "ready" && /* @__PURE__ */ jsx(UpdateBody, { update })
|
|
3964
|
+
] }),
|
|
3965
|
+
/* @__PURE__ */ jsxs(Card, { className: "acct-card", children: [
|
|
3966
|
+
/* @__PURE__ */ jsx("h2", { className: "acct-title", children: "How updates work" }),
|
|
3967
|
+
/* @__PURE__ */ jsxs("p", { className: "acct-blurb", children: [
|
|
3968
|
+
"Studio is a small package inside your website. When ",
|
|
3969
|
+
supportName,
|
|
3970
|
+
" 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 ",
|
|
3971
|
+
/* @__PURE__ */ jsx("b", { children: "Update" }),
|
|
3972
|
+
". If the update would break anything, the button never unlocks."
|
|
3973
|
+
] })
|
|
3974
|
+
] })
|
|
3975
|
+
] });
|
|
3976
|
+
}
|
|
3977
|
+
var LABELS = { profile: "My Profile", password: "Change Password", team: "Team", business: "Business", studio: "Studio" };
|
|
3978
|
+
function AccountTabs({ me, manages, team, branding, myUserId, myRole, update = null, version = "" }) {
|
|
3831
3979
|
const router = useRouter();
|
|
3832
3980
|
const pathname = usePathname();
|
|
3833
3981
|
const params = useSearchParams();
|
|
3834
|
-
const ids = manages ? ["profile", "password", "team", "business"] : ["profile", "password"];
|
|
3982
|
+
const ids = manages ? ["profile", "password", "team", "business", "studio"] : ["profile", "password"];
|
|
3835
3983
|
const requested = params.get("tab");
|
|
3836
3984
|
const active = requested && ids.includes(requested) ? requested : "profile";
|
|
3837
3985
|
const setActive = (v) => router.replace(`${pathname}?tab=${v}`, { scroll: false });
|
|
@@ -3840,14 +3988,15 @@ function AccountTabs({ me, manages, team, branding, myUserId, myRole }) {
|
|
|
3840
3988
|
active === "profile" && /* @__PURE__ */ jsx(ProfileTab, { email: me.email, name: me.name, displayName: me.displayName, avatarUrl: me.avatarUrl }),
|
|
3841
3989
|
active === "password" && /* @__PURE__ */ jsx(PasswordTab, {}),
|
|
3842
3990
|
active === "team" && manages && (team?.ok ? /* @__PURE__ */ jsx(TeamTab, { members: team.members, canInvite: team.canInvite, myUserId, myRole }) : /* @__PURE__ */ jsx("div", { className: "rz-alert admin__alert", children: team?.error ?? "Couldn\u2019t load the team." })),
|
|
3843
|
-
active === "business" && manages && /* @__PURE__ */ jsx(BusinessTab, { initial: branding })
|
|
3991
|
+
active === "business" && manages && /* @__PURE__ */ jsx(BusinessTab, { initial: branding }),
|
|
3992
|
+
active === "studio" && manages && /* @__PURE__ */ jsx(StudioTab, { update, version, role: myRole })
|
|
3844
3993
|
] });
|
|
3845
3994
|
}
|
|
3846
|
-
function StudioAccount({ me, manages, team, branding, myUserId, myRole }) {
|
|
3995
|
+
function StudioAccount({ me, manages, team, branding, myUserId, myRole, update = null, version = "" }) {
|
|
3847
3996
|
return /* @__PURE__ */ jsxs("div", { className: "acct", children: [
|
|
3848
3997
|
/* @__PURE__ */ jsx("h1", { className: "acct-h1", children: "Account" }),
|
|
3849
3998
|
/* @__PURE__ */ jsx("p", { className: "acct-email", children: me.email }),
|
|
3850
|
-
/* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AccountTabs, { me, manages, team, branding, myUserId, myRole }) })
|
|
3999
|
+
/* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(AccountTabs, { me, manages, team, branding, myUserId, myRole, update, version }) })
|
|
3851
4000
|
] });
|
|
3852
4001
|
}
|
|
3853
4002
|
|
|
@@ -3920,7 +4069,7 @@ Open the avatar menu (top right) and choose **Sign out**.
|
|
|
3920
4069
|
section: "start",
|
|
3921
4070
|
title: "Finding your way around",
|
|
3922
4071
|
summary: "The sidebar, the dashboard, the lists, and the avatar menu.",
|
|
3923
|
-
keywords: ["sidebar", "dashboard", "navigation", "menu", "settings"],
|
|
4072
|
+
keywords: ["sidebar", "dashboard", "navigation", "menu", "settings", "view website", "live site", "visit site"],
|
|
3924
4073
|
body: `
|
|
3925
4074
|
## The sidebar
|
|
3926
4075
|
|
|
@@ -3932,9 +4081,13 @@ On a narrow screen the sidebar collapses to icons; press the arrow at the bottom
|
|
|
3932
4081
|
|
|
3933
4082
|
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.
|
|
3934
4083
|
|
|
4084
|
+
## Getting to the live website
|
|
4085
|
+
|
|
4086
|
+
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.
|
|
4087
|
+
|
|
3935
4088
|
## The avatar menu
|
|
3936
4089
|
|
|
3937
|
-
Top right, your photo or initials. From here: **Account**, **Help center** (this page),
|
|
4090
|
+
Top right, your photo or initials. From here: a light/dark toggle, **View website**, **Account**, **Help center** (this page), and **Sign out**.
|
|
3938
4091
|
|
|
3939
4092
|
## The Ask bubble
|
|
3940
4093
|
|
|
@@ -3981,6 +4134,28 @@ The status becomes **Needs fixing** and the message names the problem. Open the
|
|
|
3981
4134
|
| **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. |
|
|
3982
4135
|
|
|
3983
4136
|
One item has at most one change waiting at a time. Saving again updates that same change rather than starting a second one.
|
|
4137
|
+
`
|
|
4138
|
+
},
|
|
4139
|
+
{
|
|
4140
|
+
id: "studio-pill",
|
|
4141
|
+
section: "start",
|
|
4142
|
+
title: "Getting back to Studio from the website",
|
|
4143
|
+
summary: "A small Studio pill appears bottom-left on the website while you're signed in \u2014 Edit this page, or Dashboard.",
|
|
4144
|
+
keywords: ["pill", "edit this page", "admin bar", "back to studio", "website"],
|
|
4145
|
+
body: `
|
|
4146
|
+
## What it is
|
|
4147
|
+
|
|
4148
|
+
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.
|
|
4149
|
+
|
|
4150
|
+
## Why it's useful
|
|
4151
|
+
|
|
4152
|
+
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.
|
|
4153
|
+
|
|
4154
|
+
## Good to know
|
|
4155
|
+
|
|
4156
|
+
- **Edit this page** only shows on pages Studio manages (a blog post, an event). On the home page or About, you get **Dashboard** only.
|
|
4157
|
+
- The \xD7 hides the pill for that browser tab; it comes back next time you open the site.
|
|
4158
|
+
- 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.
|
|
3984
4159
|
`
|
|
3985
4160
|
}
|
|
3986
4161
|
];
|
|
@@ -4801,6 +4976,38 @@ Pictures save the moment you choose them (**Choose a picture**, **Replace**, **R
|
|
|
4801
4976
|
## Where the pictures live
|
|
4802
4977
|
|
|
4803
4978
|
In Studio's own secure storage \u2014 not in your website's files, so they don't go through Save/Publish.
|
|
4979
|
+
`
|
|
4980
|
+
},
|
|
4981
|
+
{
|
|
4982
|
+
id: "updating-studio",
|
|
4983
|
+
section: "account",
|
|
4984
|
+
title: "Updating Studio",
|
|
4985
|
+
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.",
|
|
4986
|
+
keywords: ["update", "upgrade", "new version", "release", "what's new", "studio version"],
|
|
4987
|
+
body: `
|
|
4988
|
+
## What it is
|
|
4989
|
+
|
|
4990
|
+
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.
|
|
4991
|
+
|
|
4992
|
+
## Where you see it
|
|
4993
|
+
|
|
4994
|
+
- 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.
|
|
4995
|
+
- **Settings \u2192 Studio**: the version you're running, the pending update with its notes, and the same Update button.
|
|
4996
|
+
|
|
4997
|
+
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.
|
|
4998
|
+
|
|
4999
|
+
## How to update
|
|
5000
|
+
|
|
5001
|
+
1. Read **What's new** (a few lines, plain English).
|
|
5002
|
+
2. Optional: press **Preview** to open your website running the new Studio.
|
|
5003
|
+
3. Press **Update**. The tracker shows *Updated \u2192 Live*; about two minutes later the website has rebuilt.
|
|
5004
|
+
4. Reload Studio to use the new version.
|
|
5005
|
+
|
|
5006
|
+
## Good to know
|
|
5007
|
+
|
|
5008
|
+
- **Later** hides the strip for this browser tab; it comes back next time.
|
|
5009
|
+
- Nothing on your public website changes because of a Studio update \u2014 only the dashboard does.
|
|
5010
|
+
- You can't skip a version or go back from here; if something looks wrong after an update, tell {supportName}.
|
|
4804
5011
|
`
|
|
4805
5012
|
}
|
|
4806
5013
|
];
|
|
@@ -5239,8 +5446,12 @@ function BackArrow() {
|
|
|
5239
5446
|
] });
|
|
5240
5447
|
}
|
|
5241
5448
|
|
|
5449
|
+
// src/version.ts
|
|
5450
|
+
var ADMIN_VERSION = "0.15.0" ;
|
|
5451
|
+
|
|
5242
5452
|
// src/studio-ui/types.ts
|
|
5243
5453
|
var ACTION_NAMES = [
|
|
5454
|
+
"updateStudio",
|
|
5244
5455
|
"publishContent",
|
|
5245
5456
|
"removeContent",
|
|
5246
5457
|
"mergeContentPr",
|
|
@@ -5260,6 +5471,6 @@ var ACTION_NAMES = [
|
|
|
5260
5471
|
"remove"
|
|
5261
5472
|
];
|
|
5262
5473
|
|
|
5263
|
-
export { ACTION_NAMES, ContentEditor, GLOSSARY, HELP_ARTICLES, HELP_SECTIONS, Jargon, PublishPanel, RemoveItem, STUDIO_CSS, STUDIO_FACTS, StudioAcceptInvite, StudioAccount, StudioDashboard, StudioEdit, StudioHelp, StudioList, StudioNew, StudioNoAccess, StudioNotConfigured, StudioProvider, StudioPullRequest, StudioShellFrame, StudioSignIn, StudioTerm, copyFor, fillVars, helpAsText, joinTypes, publicDirOf, searchHelp, useEntry, useStudio };
|
|
5474
|
+
export { ACTION_NAMES, ADMIN_VERSION, ContentEditor, GLOSSARY, HELP_ARTICLES, HELP_SECTIONS, Jargon, PublishPanel, RemoveItem, STUDIO_CSS, STUDIO_FACTS, StudioAcceptInvite, StudioAccount, StudioDashboard, StudioEdit, StudioHelp, StudioList, StudioNew, StudioNoAccess, StudioNotConfigured, StudioProvider, StudioPullRequest, StudioShellFrame, StudioSignIn, StudioTerm, UpdateBody, UpdateStrip, canSeeUpdates, copyFor, fillVars, helpAsText, joinTypes, publicDirOf, searchHelp, useEntry, useStudio };
|
|
5264
5475
|
//# sourceMappingURL=index.js.map
|
|
5265
5476
|
//# sourceMappingURL=index.js.map
|