@hachej/boring-core 0.1.59 → 0.1.61
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/app/front/chatFirst/chatFirstPublicShell.css +105 -2
- package/dist/app/front/index.d.ts +10 -0
- package/dist/app/front/index.js +38 -106
- package/dist/app/server/index.js +1 -0
- package/dist/{chunk-Q53N4QUK.js → chunk-NC46VGXS.js} +411 -258
- package/dist/front/index.d.ts +38 -3
- package/dist/front/index.js +3 -1
- package/package.json +4 -4
|
@@ -2102,7 +2102,7 @@ function AuthGate({
|
|
|
2102
2102
|
}
|
|
2103
2103
|
|
|
2104
2104
|
// src/front/CoreFront.tsx
|
|
2105
|
-
import { Suspense, useCallback as useCallback9, useMemo as
|
|
2105
|
+
import { Suspense, useCallback as useCallback9, useMemo as useMemo7 } from "react";
|
|
2106
2106
|
import { BrowserRouter, Routes, Route, useLocation as useLocation2, useNavigate as useNavigate6 } from "react-router-dom";
|
|
2107
2107
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
2108
2108
|
import { Helmet, HelmetProvider } from "react-helmet-async";
|
|
@@ -2120,6 +2120,7 @@ import {
|
|
|
2120
2120
|
} from "@hachej/boring-ui-kit";
|
|
2121
2121
|
import {
|
|
2122
2122
|
ChevronDown,
|
|
2123
|
+
ChevronsUpDown,
|
|
2123
2124
|
Check,
|
|
2124
2125
|
LogOut,
|
|
2125
2126
|
Monitor,
|
|
@@ -2146,7 +2147,7 @@ function initialsFor2(name, email) {
|
|
|
2146
2147
|
}
|
|
2147
2148
|
return email.slice(0, 2).toUpperCase();
|
|
2148
2149
|
}
|
|
2149
|
-
function UserMenu() {
|
|
2150
|
+
function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "compact" } = {}) {
|
|
2150
2151
|
const identity = useUser();
|
|
2151
2152
|
const signOut = useSignOut();
|
|
2152
2153
|
const navigate = useNavigate3();
|
|
@@ -2167,7 +2168,23 @@ function UserMenu() {
|
|
|
2167
2168
|
}
|
|
2168
2169
|
}
|
|
2169
2170
|
return /* @__PURE__ */ jsxs8(DropdownMenu, { children: [
|
|
2170
|
-
/* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
|
|
2171
|
+
/* @__PURE__ */ jsx16(DropdownMenuTrigger, { asChild: true, children: variant === "bar" ? /* @__PURE__ */ jsxs8(
|
|
2172
|
+
Button10,
|
|
2173
|
+
{
|
|
2174
|
+
type: "button",
|
|
2175
|
+
variant: "ghost",
|
|
2176
|
+
"aria-label": "Account menu",
|
|
2177
|
+
className: "h-10 w-full justify-start gap-2.5 rounded-lg border border-transparent bg-transparent px-2 text-left text-foreground shadow-none hover:bg-foreground/[0.06] focus-visible:ring-1 focus-visible:ring-ring",
|
|
2178
|
+
children: [
|
|
2179
|
+
/* @__PURE__ */ jsx16("span", { className: "inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full border border-border/60 bg-foreground/[0.12] text-[10px] font-semibold text-foreground", children: initials }),
|
|
2180
|
+
/* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5 leading-snug", children: [
|
|
2181
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate text-[13px] font-medium text-foreground", children: userName }),
|
|
2182
|
+
/* @__PURE__ */ jsx16("span", { className: "truncate text-[11px] text-muted-foreground/80", children: userEmail })
|
|
2183
|
+
] }),
|
|
2184
|
+
/* @__PURE__ */ jsx16(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
|
|
2185
|
+
]
|
|
2186
|
+
}
|
|
2187
|
+
) : /* @__PURE__ */ jsxs8(
|
|
2171
2188
|
Button10,
|
|
2172
2189
|
{
|
|
2173
2190
|
type: "button",
|
|
@@ -2183,7 +2200,8 @@ function UserMenu() {
|
|
|
2183
2200
|
/* @__PURE__ */ jsxs8(
|
|
2184
2201
|
DropdownMenuContent,
|
|
2185
2202
|
{
|
|
2186
|
-
align:
|
|
2203
|
+
align: contentAlign,
|
|
2204
|
+
side: contentSide,
|
|
2187
2205
|
sideOffset: 8,
|
|
2188
2206
|
className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
|
|
2189
2207
|
children: [
|
|
@@ -2278,7 +2296,7 @@ import {
|
|
|
2278
2296
|
Label as Label7,
|
|
2279
2297
|
useToast
|
|
2280
2298
|
} from "@hachej/boring-ui-kit";
|
|
2281
|
-
import { ChevronsUpDown, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
|
|
2299
|
+
import { ChevronsUpDown as ChevronsUpDown2, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
|
|
2282
2300
|
import { useNavigate as useNavigate4 } from "react-router-dom";
|
|
2283
2301
|
import { z as z6 } from "zod";
|
|
2284
2302
|
import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
@@ -2326,7 +2344,8 @@ function OpenInNewTabIcon({ className }) {
|
|
|
2326
2344
|
}
|
|
2327
2345
|
function WorkspaceSwitcher({
|
|
2328
2346
|
appTitle,
|
|
2329
|
-
workspacePathPrefix = "/workspace"
|
|
2347
|
+
workspacePathPrefix = "/workspace",
|
|
2348
|
+
displayMode = "full"
|
|
2330
2349
|
}) {
|
|
2331
2350
|
const config = useOptionalConfig();
|
|
2332
2351
|
const resolvedAppTitle = appTitle ?? config?.appName ?? "Boring UI";
|
|
@@ -2424,7 +2443,19 @@ function WorkspaceSwitcher({
|
|
|
2424
2443
|
]
|
|
2425
2444
|
}
|
|
2426
2445
|
) : /* @__PURE__ */ jsxs9(DropdownMenu2, { children: [
|
|
2427
|
-
/* @__PURE__ */ jsx17(DropdownMenuTrigger2, { asChild: true, children: /* @__PURE__ */ jsxs9(
|
|
2446
|
+
/* @__PURE__ */ jsx17(DropdownMenuTrigger2, { asChild: true, children: displayMode === "workspace" ? /* @__PURE__ */ jsxs9(
|
|
2447
|
+
Button11,
|
|
2448
|
+
{
|
|
2449
|
+
type: "button",
|
|
2450
|
+
variant: "ghost",
|
|
2451
|
+
"aria-label": `Workspace menu: ${switcherLabel}`,
|
|
2452
|
+
className: "h-8 w-full min-w-0 justify-start gap-1.5 rounded-lg border border-transparent px-2 text-left hover:bg-foreground/[0.06] focus-visible:ring-1 focus-visible:ring-ring",
|
|
2453
|
+
children: [
|
|
2454
|
+
/* @__PURE__ */ jsx17("span", { className: "min-w-0 flex-1 truncate text-[13px] font-medium text-foreground/85", children: switcherLabel }),
|
|
2455
|
+
/* @__PURE__ */ jsx17(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
|
|
2456
|
+
]
|
|
2457
|
+
}
|
|
2458
|
+
) : /* @__PURE__ */ jsxs9(
|
|
2428
2459
|
Button11,
|
|
2429
2460
|
{
|
|
2430
2461
|
type: "button",
|
|
@@ -2437,15 +2468,11 @@ function WorkspaceSwitcher({
|
|
|
2437
2468
|
{
|
|
2438
2469
|
"aria-hidden": "true",
|
|
2439
2470
|
className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background",
|
|
2440
|
-
children:
|
|
2471
|
+
children: workspaceInitial(switcherLabel)
|
|
2441
2472
|
}
|
|
2442
2473
|
),
|
|
2443
|
-
/* @__PURE__ */
|
|
2444
|
-
|
|
2445
|
-
/* @__PURE__ */ jsx17("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
2446
|
-
/* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-normal text-muted-foreground", children: switcherLabel })
|
|
2447
|
-
] }),
|
|
2448
|
-
/* @__PURE__ */ jsx17(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
|
|
2474
|
+
/* @__PURE__ */ jsx17("span", { className: "min-w-0 truncate text-[13px] font-medium text-foreground", children: switcherLabel }),
|
|
2475
|
+
/* @__PURE__ */ jsx17(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
|
|
2449
2476
|
]
|
|
2450
2477
|
}
|
|
2451
2478
|
) }),
|
|
@@ -2596,9 +2623,134 @@ function WorkspaceSwitcher({
|
|
|
2596
2623
|
] });
|
|
2597
2624
|
}
|
|
2598
2625
|
|
|
2626
|
+
// src/front/components/CreateWorkspaceDialog.tsx
|
|
2627
|
+
import { useMemo as useMemo6, useState as useState17 } from "react";
|
|
2628
|
+
import { useQueryClient as useQueryClient4 } from "@tanstack/react-query";
|
|
2629
|
+
import {
|
|
2630
|
+
Button as Button12,
|
|
2631
|
+
Dialog as Dialog2,
|
|
2632
|
+
DialogContent as DialogContent2,
|
|
2633
|
+
DialogDescription as DialogDescription2,
|
|
2634
|
+
DialogFooter as DialogFooter2,
|
|
2635
|
+
DialogHeader as DialogHeader2,
|
|
2636
|
+
DialogTitle as DialogTitle2,
|
|
2637
|
+
Input as Input8,
|
|
2638
|
+
Label as Label8,
|
|
2639
|
+
useToast as useToast2
|
|
2640
|
+
} from "@hachej/boring-ui-kit";
|
|
2641
|
+
import { z as z7 } from "zod";
|
|
2642
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2643
|
+
var workspaceNameSchema2 = z7.object({
|
|
2644
|
+
name: z7.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
|
|
2645
|
+
});
|
|
2646
|
+
function CreateWorkspaceDialog({
|
|
2647
|
+
open,
|
|
2648
|
+
onOpenChange,
|
|
2649
|
+
onCreated,
|
|
2650
|
+
title = "Create workspace",
|
|
2651
|
+
description = "Choose a name for your new workspace.",
|
|
2652
|
+
entityNoun = "workspace"
|
|
2653
|
+
}) {
|
|
2654
|
+
const queryClient = useQueryClient4();
|
|
2655
|
+
const { toast } = useToast2();
|
|
2656
|
+
const [name, setName] = useState17("");
|
|
2657
|
+
const [attemptedSubmit, setAttemptedSubmit] = useState17(false);
|
|
2658
|
+
const [isSubmitting, setIsSubmitting] = useState17(false);
|
|
2659
|
+
const [serverError, setServerError] = useState17(null);
|
|
2660
|
+
const validation = useMemo6(() => workspaceNameSchema2.safeParse({ name }), [name]);
|
|
2661
|
+
const shouldShowNameError = name.length > 100 || attemptedSubmit && !validation.success;
|
|
2662
|
+
const nameError = shouldShowNameError && !validation.success ? validation.error.issues[0]?.message ?? "Invalid workspace name" : null;
|
|
2663
|
+
function reset() {
|
|
2664
|
+
setName("");
|
|
2665
|
+
setAttemptedSubmit(false);
|
|
2666
|
+
setIsSubmitting(false);
|
|
2667
|
+
setServerError(null);
|
|
2668
|
+
}
|
|
2669
|
+
function handleOpenChange(next) {
|
|
2670
|
+
onOpenChange(next);
|
|
2671
|
+
if (!next) reset();
|
|
2672
|
+
}
|
|
2673
|
+
async function handleSubmit(event) {
|
|
2674
|
+
event.preventDefault();
|
|
2675
|
+
setAttemptedSubmit(true);
|
|
2676
|
+
setServerError(null);
|
|
2677
|
+
const parsed = workspaceNameSchema2.safeParse({ name });
|
|
2678
|
+
if (!parsed.success) return;
|
|
2679
|
+
setIsSubmitting(true);
|
|
2680
|
+
try {
|
|
2681
|
+
const data = await apiFetchJson("/api/v1/workspaces", {
|
|
2682
|
+
method: "POST",
|
|
2683
|
+
headers: { "content-type": "application/json" },
|
|
2684
|
+
body: JSON.stringify({ name: parsed.data.name })
|
|
2685
|
+
});
|
|
2686
|
+
queryClient.setQueryData(workspaceQueryKey(data.workspace.id), data);
|
|
2687
|
+
queryClient.setQueryData(WORKSPACES_QUERY_KEY, (current = []) => {
|
|
2688
|
+
if (current.some((workspace) => workspace.id === data.workspace.id)) return current;
|
|
2689
|
+
return [...current, data.workspace];
|
|
2690
|
+
});
|
|
2691
|
+
handleOpenChange(false);
|
|
2692
|
+
onCreated?.(data.workspace);
|
|
2693
|
+
void queryClient.invalidateQueries({ queryKey: WORKSPACES_QUERY_KEY });
|
|
2694
|
+
void queryClient.invalidateQueries({ queryKey: workspaceQueryKey(data.workspace.id) });
|
|
2695
|
+
} catch (error) {
|
|
2696
|
+
const detail = getHttpErrorDetail(error);
|
|
2697
|
+
if (typeof detail.status === "number" && detail.status >= 400 && detail.status < 500) {
|
|
2698
|
+
toast({
|
|
2699
|
+
title: `Unable to create ${entityNoun}`,
|
|
2700
|
+
description: detail.message,
|
|
2701
|
+
variant: "destructive"
|
|
2702
|
+
});
|
|
2703
|
+
} else {
|
|
2704
|
+
setServerError(detail.message);
|
|
2705
|
+
}
|
|
2706
|
+
} finally {
|
|
2707
|
+
setIsSubmitting(false);
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
return /* @__PURE__ */ jsx18(Dialog2, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent2, { children: [
|
|
2711
|
+
/* @__PURE__ */ jsxs10(DialogHeader2, { children: [
|
|
2712
|
+
/* @__PURE__ */ jsx18(DialogTitle2, { children: title }),
|
|
2713
|
+
/* @__PURE__ */ jsx18(DialogDescription2, { children: description })
|
|
2714
|
+
] }),
|
|
2715
|
+
/* @__PURE__ */ jsxs10("form", { onSubmit: (event) => void handleSubmit(event), className: "space-y-4", children: [
|
|
2716
|
+
/* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
|
|
2717
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2718
|
+
/* @__PURE__ */ jsx18(Label8, { htmlFor: "create-workspace-name", children: "Name" }),
|
|
2719
|
+
/* @__PURE__ */ jsxs10("span", { className: "text-xs text-muted-foreground", children: [
|
|
2720
|
+
name.length,
|
|
2721
|
+
"/100"
|
|
2722
|
+
] })
|
|
2723
|
+
] }),
|
|
2724
|
+
/* @__PURE__ */ jsx18(
|
|
2725
|
+
Input8,
|
|
2726
|
+
{
|
|
2727
|
+
id: "create-workspace-name",
|
|
2728
|
+
name: "name",
|
|
2729
|
+
value: name,
|
|
2730
|
+
maxLength: 101,
|
|
2731
|
+
onChange: (event) => {
|
|
2732
|
+
setName(event.target.value);
|
|
2733
|
+
if (serverError) setServerError(null);
|
|
2734
|
+
},
|
|
2735
|
+
placeholder: "Default workspace",
|
|
2736
|
+
"aria-invalid": nameError ? "true" : "false",
|
|
2737
|
+
autoFocus: true
|
|
2738
|
+
}
|
|
2739
|
+
),
|
|
2740
|
+
nameError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
|
|
2741
|
+
serverError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
|
|
2742
|
+
] }),
|
|
2743
|
+
/* @__PURE__ */ jsxs10(DialogFooter2, { children: [
|
|
2744
|
+
/* @__PURE__ */ jsx18(Button12, { type: "button", variant: "ghost", onClick: () => handleOpenChange(false), disabled: isSubmitting, children: "Cancel" }),
|
|
2745
|
+
/* @__PURE__ */ jsx18(Button12, { type: "submit", disabled: isSubmitting || !validation.success, children: isSubmitting ? "Creating..." : title })
|
|
2746
|
+
] })
|
|
2747
|
+
] })
|
|
2748
|
+
] }) });
|
|
2749
|
+
}
|
|
2750
|
+
|
|
2599
2751
|
// src/front/components/ThemeToggle.tsx
|
|
2600
|
-
import { Button as
|
|
2601
|
-
import { jsxs as
|
|
2752
|
+
import { Button as Button13 } from "@hachej/boring-ui-kit";
|
|
2753
|
+
import { jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2602
2754
|
var THEME_ORDER2 = ["light", "dark", "system"];
|
|
2603
2755
|
function nextTheme(preference) {
|
|
2604
2756
|
const index = THEME_ORDER2.indexOf(preference);
|
|
@@ -2612,8 +2764,8 @@ function labelForTheme2(preference) {
|
|
|
2612
2764
|
}
|
|
2613
2765
|
function ThemeToggle() {
|
|
2614
2766
|
const { preference, setTheme } = useTheme();
|
|
2615
|
-
return /* @__PURE__ */
|
|
2616
|
-
|
|
2767
|
+
return /* @__PURE__ */ jsxs11(
|
|
2768
|
+
Button13,
|
|
2617
2769
|
{
|
|
2618
2770
|
type: "button",
|
|
2619
2771
|
variant: "outline",
|
|
@@ -2630,42 +2782,42 @@ function ThemeToggle() {
|
|
|
2630
2782
|
|
|
2631
2783
|
// src/front/auth/AuthErrorPage.tsx
|
|
2632
2784
|
import { Card as Card7, CardContent as CardContent7, CardDescription as CardDescription7, CardFooter as CardFooter7, CardHeader as CardHeader7, CardTitle as CardTitle7 } from "@hachej/boring-ui-kit";
|
|
2633
|
-
import { jsx as
|
|
2785
|
+
import { jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2634
2786
|
function readAuthErrorCode() {
|
|
2635
2787
|
if (typeof window === "undefined") return null;
|
|
2636
2788
|
return new URLSearchParams(window.location.search).get("error");
|
|
2637
2789
|
}
|
|
2638
2790
|
function AuthErrorPage() {
|
|
2639
2791
|
const errorCode = readAuthErrorCode();
|
|
2640
|
-
return /* @__PURE__ */
|
|
2641
|
-
/* @__PURE__ */
|
|
2642
|
-
/* @__PURE__ */
|
|
2643
|
-
/* @__PURE__ */
|
|
2792
|
+
return /* @__PURE__ */ jsx19("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12(Card7, { className: "w-full max-w-sm", children: [
|
|
2793
|
+
/* @__PURE__ */ jsxs12(CardHeader7, { children: [
|
|
2794
|
+
/* @__PURE__ */ jsx19(CardTitle7, { children: "Authentication error" }),
|
|
2795
|
+
/* @__PURE__ */ jsx19(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
|
|
2644
2796
|
] }),
|
|
2645
|
-
errorCode && /* @__PURE__ */
|
|
2797
|
+
errorCode && /* @__PURE__ */ jsx19(CardContent7, { children: /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground break-all", children: [
|
|
2646
2798
|
"Error: ",
|
|
2647
2799
|
errorCode
|
|
2648
2800
|
] }) }),
|
|
2649
|
-
/* @__PURE__ */
|
|
2650
|
-
/* @__PURE__ */
|
|
2651
|
-
/* @__PURE__ */
|
|
2801
|
+
/* @__PURE__ */ jsxs12(CardFooter7, { className: "flex justify-between gap-4 text-sm", children: [
|
|
2802
|
+
/* @__PURE__ */ jsx19("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
|
|
2803
|
+
/* @__PURE__ */ jsx19("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
|
|
2652
2804
|
] })
|
|
2653
2805
|
] }) });
|
|
2654
2806
|
}
|
|
2655
2807
|
|
|
2656
2808
|
// src/front/workspace/InvitesPage.tsx
|
|
2657
|
-
import { useCallback as useCallback6, useState as
|
|
2658
|
-
import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as
|
|
2809
|
+
import { useCallback as useCallback6, useState as useState18 } from "react";
|
|
2810
|
+
import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
|
|
2659
2811
|
import {
|
|
2660
|
-
Button as
|
|
2812
|
+
Button as Button14,
|
|
2661
2813
|
Card as Card8,
|
|
2662
2814
|
CardContent as CardContent8,
|
|
2663
2815
|
CardDescription as CardDescription8,
|
|
2664
2816
|
CardFooter as CardFooter8,
|
|
2665
2817
|
CardHeader as CardHeader8,
|
|
2666
2818
|
CardTitle as CardTitle8,
|
|
2667
|
-
Input as
|
|
2668
|
-
Label as
|
|
2819
|
+
Input as Input9,
|
|
2820
|
+
Label as Label9,
|
|
2669
2821
|
LoadingState as LoadingState2,
|
|
2670
2822
|
Notice as Notice3,
|
|
2671
2823
|
Select,
|
|
@@ -2675,7 +2827,7 @@ import {
|
|
|
2675
2827
|
SelectValue,
|
|
2676
2828
|
StatusBadge
|
|
2677
2829
|
} from "@hachej/boring-ui-kit";
|
|
2678
|
-
import { jsx as
|
|
2830
|
+
import { jsx as jsx20, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2679
2831
|
function invitesQueryKey(workspaceId) {
|
|
2680
2832
|
return ["invites", workspaceId];
|
|
2681
2833
|
}
|
|
@@ -2695,11 +2847,11 @@ var STATUS_TONES = {
|
|
|
2695
2847
|
function InvitesPage() {
|
|
2696
2848
|
const workspace = useCurrentWorkspace();
|
|
2697
2849
|
const role = useWorkspaceRole();
|
|
2698
|
-
const queryClient =
|
|
2699
|
-
const [email, setEmail] =
|
|
2700
|
-
const [inviteRole, setInviteRole] =
|
|
2701
|
-
const [formError, setFormError] =
|
|
2702
|
-
const [successMessage, setSuccessMessage] =
|
|
2850
|
+
const queryClient = useQueryClient5();
|
|
2851
|
+
const [email, setEmail] = useState18("");
|
|
2852
|
+
const [inviteRole, setInviteRole] = useState18("editor");
|
|
2853
|
+
const [formError, setFormError] = useState18(null);
|
|
2854
|
+
const [successMessage, setSuccessMessage] = useState18(null);
|
|
2703
2855
|
const workspaceId = workspace?.id ?? "";
|
|
2704
2856
|
const encodedWorkspaceId = encodeURIComponent(workspaceId);
|
|
2705
2857
|
const invitesQuery = useQuery5({
|
|
@@ -2735,7 +2887,7 @@ function InvitesPage() {
|
|
|
2735
2887
|
setFormError(detail.message);
|
|
2736
2888
|
}
|
|
2737
2889
|
});
|
|
2738
|
-
const [revokeError, setRevokeError] =
|
|
2890
|
+
const [revokeError, setRevokeError] = useState18(null);
|
|
2739
2891
|
const revokeMutation = useMutation2({
|
|
2740
2892
|
mutationFn: async (inviteId) => {
|
|
2741
2893
|
await apiFetch(
|
|
@@ -2767,29 +2919,29 @@ function InvitesPage() {
|
|
|
2767
2919
|
[email, inviteRole, createMutation]
|
|
2768
2920
|
);
|
|
2769
2921
|
if (role !== "owner") {
|
|
2770
|
-
return /* @__PURE__ */
|
|
2771
|
-
/* @__PURE__ */
|
|
2772
|
-
/* @__PURE__ */
|
|
2922
|
+
return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx20(Card8, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs13(CardHeader8, { children: [
|
|
2923
|
+
/* @__PURE__ */ jsx20(CardTitle8, { children: "Access denied" }),
|
|
2924
|
+
/* @__PURE__ */ jsx20(CardDescription8, { children: "Only workspace owners can manage invites." })
|
|
2773
2925
|
] }) }) });
|
|
2774
2926
|
}
|
|
2775
|
-
return /* @__PURE__ */
|
|
2776
|
-
/* @__PURE__ */
|
|
2777
|
-
/* @__PURE__ */
|
|
2778
|
-
/* @__PURE__ */
|
|
2779
|
-
/* @__PURE__ */
|
|
2927
|
+
return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-2xl space-y-6", children: [
|
|
2928
|
+
/* @__PURE__ */ jsxs13(Card8, { children: [
|
|
2929
|
+
/* @__PURE__ */ jsxs13(CardHeader8, { children: [
|
|
2930
|
+
/* @__PURE__ */ jsx20(CardTitle8, { children: "Invite a member" }),
|
|
2931
|
+
/* @__PURE__ */ jsxs13(CardDescription8, { children: [
|
|
2780
2932
|
"Send an invite to join ",
|
|
2781
2933
|
workspace?.name ?? "this workspace",
|
|
2782
2934
|
"."
|
|
2783
2935
|
] })
|
|
2784
2936
|
] }),
|
|
2785
|
-
/* @__PURE__ */
|
|
2786
|
-
/* @__PURE__ */
|
|
2787
|
-
formError && /* @__PURE__ */
|
|
2788
|
-
successMessage && /* @__PURE__ */
|
|
2789
|
-
/* @__PURE__ */
|
|
2790
|
-
/* @__PURE__ */
|
|
2791
|
-
/* @__PURE__ */
|
|
2792
|
-
|
|
2937
|
+
/* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
|
|
2938
|
+
/* @__PURE__ */ jsxs13(CardContent8, { className: "space-y-4", children: [
|
|
2939
|
+
formError && /* @__PURE__ */ jsx20(Notice3, { role: "alert", tone: "error", description: formError }),
|
|
2940
|
+
successMessage && /* @__PURE__ */ jsx20(Notice3, { role: "status", tone: "success", description: successMessage }),
|
|
2941
|
+
/* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
|
|
2942
|
+
/* @__PURE__ */ jsx20(Label9, { htmlFor: "invite-email", children: "Email address" }),
|
|
2943
|
+
/* @__PURE__ */ jsx20(
|
|
2944
|
+
Input9,
|
|
2793
2945
|
{
|
|
2794
2946
|
id: "invite-email",
|
|
2795
2947
|
type: "email",
|
|
@@ -2800,20 +2952,20 @@ function InvitesPage() {
|
|
|
2800
2952
|
}
|
|
2801
2953
|
)
|
|
2802
2954
|
] }),
|
|
2803
|
-
/* @__PURE__ */
|
|
2804
|
-
/* @__PURE__ */
|
|
2805
|
-
/* @__PURE__ */
|
|
2806
|
-
/* @__PURE__ */
|
|
2807
|
-
/* @__PURE__ */
|
|
2808
|
-
/* @__PURE__ */
|
|
2809
|
-
/* @__PURE__ */
|
|
2810
|
-
/* @__PURE__ */
|
|
2955
|
+
/* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
|
|
2956
|
+
/* @__PURE__ */ jsx20(Label9, { htmlFor: "invite-role", children: "Role" }),
|
|
2957
|
+
/* @__PURE__ */ jsxs13(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
|
|
2958
|
+
/* @__PURE__ */ jsx20(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx20(SelectValue, { placeholder: "Select role" }) }),
|
|
2959
|
+
/* @__PURE__ */ jsxs13(SelectContent, { children: [
|
|
2960
|
+
/* @__PURE__ */ jsx20(SelectItem, { value: "editor", children: "Editor" }),
|
|
2961
|
+
/* @__PURE__ */ jsx20(SelectItem, { value: "viewer", children: "Viewer" }),
|
|
2962
|
+
/* @__PURE__ */ jsx20(SelectItem, { value: "owner", children: "Owner" })
|
|
2811
2963
|
] })
|
|
2812
2964
|
] })
|
|
2813
2965
|
] })
|
|
2814
2966
|
] }),
|
|
2815
|
-
/* @__PURE__ */
|
|
2816
|
-
|
|
2967
|
+
/* @__PURE__ */ jsx20(CardFooter8, { children: /* @__PURE__ */ jsx20(
|
|
2968
|
+
Button14,
|
|
2817
2969
|
{
|
|
2818
2970
|
type: "submit",
|
|
2819
2971
|
className: "w-full",
|
|
@@ -2823,37 +2975,37 @@ function InvitesPage() {
|
|
|
2823
2975
|
) })
|
|
2824
2976
|
] })
|
|
2825
2977
|
] }),
|
|
2826
|
-
/* @__PURE__ */
|
|
2827
|
-
/* @__PURE__ */
|
|
2828
|
-
/* @__PURE__ */
|
|
2829
|
-
/* @__PURE__ */
|
|
2978
|
+
/* @__PURE__ */ jsxs13(Card8, { children: [
|
|
2979
|
+
/* @__PURE__ */ jsxs13(CardHeader8, { children: [
|
|
2980
|
+
/* @__PURE__ */ jsx20(CardTitle8, { children: "Pending invites" }),
|
|
2981
|
+
/* @__PURE__ */ jsx20(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
|
|
2830
2982
|
] }),
|
|
2831
|
-
/* @__PURE__ */
|
|
2832
|
-
revokeError && /* @__PURE__ */
|
|
2833
|
-
invitesQuery.isLoading && /* @__PURE__ */
|
|
2834
|
-
invitesQuery.isError && /* @__PURE__ */
|
|
2835
|
-
invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */
|
|
2983
|
+
/* @__PURE__ */ jsxs13(CardContent8, { children: [
|
|
2984
|
+
revokeError && /* @__PURE__ */ jsx20(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
|
|
2985
|
+
invitesQuery.isLoading && /* @__PURE__ */ jsx20(LoadingState2, {}),
|
|
2986
|
+
invitesQuery.isError && /* @__PURE__ */ jsx20(Notice3, { tone: "error", description: "Failed to load invites." }),
|
|
2987
|
+
invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx20("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
|
|
2836
2988
|
const status = getInviteStatus(invite);
|
|
2837
|
-
return /* @__PURE__ */
|
|
2989
|
+
return /* @__PURE__ */ jsxs13(
|
|
2838
2990
|
"div",
|
|
2839
2991
|
{
|
|
2840
2992
|
className: "flex items-center justify-between py-3",
|
|
2841
2993
|
"data-testid": `invite-row-${invite.id}`,
|
|
2842
2994
|
children: [
|
|
2843
|
-
/* @__PURE__ */
|
|
2844
|
-
/* @__PURE__ */
|
|
2845
|
-
/* @__PURE__ */
|
|
2846
|
-
/* @__PURE__ */
|
|
2847
|
-
/* @__PURE__ */
|
|
2848
|
-
/* @__PURE__ */
|
|
2995
|
+
/* @__PURE__ */ jsxs13("div", { className: "space-y-1", children: [
|
|
2996
|
+
/* @__PURE__ */ jsx20("p", { className: "text-sm font-medium", children: invite.email }),
|
|
2997
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
2998
|
+
/* @__PURE__ */ jsx20("span", { children: invite.role }),
|
|
2999
|
+
/* @__PURE__ */ jsx20(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
|
|
3000
|
+
/* @__PURE__ */ jsxs13("span", { children: [
|
|
2849
3001
|
"expires",
|
|
2850
3002
|
" ",
|
|
2851
3003
|
new Date(invite.expiresAt).toLocaleDateString()
|
|
2852
3004
|
] })
|
|
2853
3005
|
] })
|
|
2854
3006
|
] }),
|
|
2855
|
-
status === "pending" && /* @__PURE__ */
|
|
2856
|
-
|
|
3007
|
+
status === "pending" && /* @__PURE__ */ jsx20(
|
|
3008
|
+
Button14,
|
|
2857
3009
|
{
|
|
2858
3010
|
variant: "destructive",
|
|
2859
3011
|
size: "sm",
|
|
@@ -2874,8 +3026,8 @@ function InvitesPage() {
|
|
|
2874
3026
|
}
|
|
2875
3027
|
|
|
2876
3028
|
// src/front/workspace/MembersPage.tsx
|
|
2877
|
-
import { useCallback as useCallback7, useState as
|
|
2878
|
-
import { useMutation as useMutation3, useQueryClient as
|
|
3029
|
+
import { useCallback as useCallback7, useState as useState19 } from "react";
|
|
3030
|
+
import { useMutation as useMutation3, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
|
|
2879
3031
|
import {
|
|
2880
3032
|
AlertDialog as AlertDialog2,
|
|
2881
3033
|
AlertDialogCancel as AlertDialogCancel2,
|
|
@@ -2884,7 +3036,7 @@ import {
|
|
|
2884
3036
|
AlertDialogFooter as AlertDialogFooter2,
|
|
2885
3037
|
AlertDialogHeader as AlertDialogHeader2,
|
|
2886
3038
|
AlertDialogTitle as AlertDialogTitle2,
|
|
2887
|
-
Button as
|
|
3039
|
+
Button as Button15,
|
|
2888
3040
|
Card as Card9,
|
|
2889
3041
|
CardContent as CardContent9,
|
|
2890
3042
|
CardDescription as CardDescription9,
|
|
@@ -2899,19 +3051,19 @@ import {
|
|
|
2899
3051
|
LoadingState as LoadingState3,
|
|
2900
3052
|
Notice as Notice4
|
|
2901
3053
|
} from "@hachej/boring-ui-kit";
|
|
2902
|
-
import { jsx as
|
|
3054
|
+
import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2903
3055
|
var ROLE_OPTIONS = ["owner", "editor", "viewer"];
|
|
2904
3056
|
function MembersPage() {
|
|
2905
3057
|
const workspace = useCurrentWorkspace();
|
|
2906
3058
|
const myRole = useWorkspaceRole();
|
|
2907
3059
|
const session = useSession();
|
|
2908
|
-
const queryClient =
|
|
3060
|
+
const queryClient = useQueryClient6();
|
|
2909
3061
|
const workspaceId = workspace?.id ?? "";
|
|
2910
3062
|
const currentUserId = session.data?.user?.id ?? "";
|
|
2911
3063
|
const encodedWorkspaceId = encodeURIComponent(workspaceId);
|
|
2912
3064
|
const membersQuery = useWorkspaceMembers(workspaceId);
|
|
2913
|
-
const [toast, setToast] =
|
|
2914
|
-
const [confirmTarget, setConfirmTarget] =
|
|
3065
|
+
const [toast, setToast] = useState19(null);
|
|
3066
|
+
const [confirmTarget, setConfirmTarget] = useState19(null);
|
|
2915
3067
|
const showToast = useCallback7((msg) => {
|
|
2916
3068
|
setToast(msg);
|
|
2917
3069
|
setTimeout(() => setToast(null), 4e3);
|
|
@@ -2972,11 +3124,11 @@ function MembersPage() {
|
|
|
2972
3124
|
removeMutation.mutate(confirmTarget.userId);
|
|
2973
3125
|
}, [confirmTarget, removeMutation]);
|
|
2974
3126
|
const isOwner = myRole === "owner";
|
|
2975
|
-
return /* @__PURE__ */
|
|
2976
|
-
/* @__PURE__ */
|
|
2977
|
-
/* @__PURE__ */
|
|
2978
|
-
/* @__PURE__ */
|
|
2979
|
-
/* @__PURE__ */
|
|
3127
|
+
return /* @__PURE__ */ jsx21("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs14("div", { className: "w-full max-w-2xl space-y-6", children: [
|
|
3128
|
+
/* @__PURE__ */ jsxs14(Card9, { children: [
|
|
3129
|
+
/* @__PURE__ */ jsxs14(CardHeader9, { children: [
|
|
3130
|
+
/* @__PURE__ */ jsx21(CardTitle9, { children: "Members" }),
|
|
3131
|
+
/* @__PURE__ */ jsxs14(CardDescription9, { children: [
|
|
2980
3132
|
workspace?.name ?? "Workspace",
|
|
2981
3133
|
" \xB7",
|
|
2982
3134
|
" ",
|
|
@@ -2985,45 +3137,45 @@ function MembersPage() {
|
|
|
2985
3137
|
(membersQuery.data?.length ?? 0) !== 1 ? "s" : ""
|
|
2986
3138
|
] })
|
|
2987
3139
|
] }),
|
|
2988
|
-
/* @__PURE__ */
|
|
2989
|
-
toast && /* @__PURE__ */
|
|
2990
|
-
membersQuery.isLoading && /* @__PURE__ */
|
|
2991
|
-
membersQuery.isError && /* @__PURE__ */
|
|
2992
|
-
membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */
|
|
3140
|
+
/* @__PURE__ */ jsxs14(CardContent9, { children: [
|
|
3141
|
+
toast && /* @__PURE__ */ jsx21(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
|
|
3142
|
+
membersQuery.isLoading && /* @__PURE__ */ jsx21(LoadingState3, {}),
|
|
3143
|
+
membersQuery.isError && /* @__PURE__ */ jsx21(Notice4, { tone: "error", description: "Failed to load members." }),
|
|
3144
|
+
membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx21("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
|
|
2993
3145
|
const isSelf = member.userId === currentUserId;
|
|
2994
3146
|
const canChangeRole = isOwner && !isSelf;
|
|
2995
3147
|
const canRemove = isOwner || isSelf;
|
|
2996
|
-
return /* @__PURE__ */
|
|
3148
|
+
return /* @__PURE__ */ jsxs14(
|
|
2997
3149
|
"div",
|
|
2998
3150
|
{
|
|
2999
3151
|
className: "flex items-center justify-between py-3",
|
|
3000
3152
|
"data-testid": `member-row-${member.userId}`,
|
|
3001
3153
|
children: [
|
|
3002
|
-
/* @__PURE__ */
|
|
3003
|
-
/* @__PURE__ */
|
|
3004
|
-
/* @__PURE__ */
|
|
3005
|
-
/* @__PURE__ */
|
|
3154
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3", children: [
|
|
3155
|
+
/* @__PURE__ */ jsx21(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
|
|
3156
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
3157
|
+
/* @__PURE__ */ jsxs14("p", { className: "text-sm font-medium", children: [
|
|
3006
3158
|
member.user.name ?? member.user.email,
|
|
3007
|
-
isSelf && /* @__PURE__ */
|
|
3159
|
+
isSelf && /* @__PURE__ */ jsx21("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
|
|
3008
3160
|
] }),
|
|
3009
|
-
/* @__PURE__ */
|
|
3161
|
+
/* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground", children: member.user.email })
|
|
3010
3162
|
] })
|
|
3011
3163
|
] }),
|
|
3012
|
-
/* @__PURE__ */
|
|
3013
|
-
/* @__PURE__ */
|
|
3164
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
3165
|
+
/* @__PURE__ */ jsxs14(
|
|
3014
3166
|
Select2,
|
|
3015
3167
|
{
|
|
3016
3168
|
value: member.role,
|
|
3017
3169
|
disabled: !canChangeRole,
|
|
3018
3170
|
onValueChange: (value) => handleRoleChange(member.userId, value),
|
|
3019
3171
|
children: [
|
|
3020
|
-
/* @__PURE__ */
|
|
3021
|
-
/* @__PURE__ */
|
|
3172
|
+
/* @__PURE__ */ jsx21(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx21(SelectValue2, { placeholder: "Role" }) }),
|
|
3173
|
+
/* @__PURE__ */ jsx21(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx21(SelectItem2, { value: r, children: r }, r)) })
|
|
3022
3174
|
]
|
|
3023
3175
|
}
|
|
3024
3176
|
),
|
|
3025
|
-
canRemove && /* @__PURE__ */
|
|
3026
|
-
|
|
3177
|
+
canRemove && /* @__PURE__ */ jsx21(
|
|
3178
|
+
Button15,
|
|
3027
3179
|
{
|
|
3028
3180
|
variant: "destructive",
|
|
3029
3181
|
size: "sm",
|
|
@@ -3040,22 +3192,22 @@ function MembersPage() {
|
|
|
3040
3192
|
}) })
|
|
3041
3193
|
] })
|
|
3042
3194
|
] }),
|
|
3043
|
-
/* @__PURE__ */
|
|
3195
|
+
/* @__PURE__ */ jsx21(
|
|
3044
3196
|
AlertDialog2,
|
|
3045
3197
|
{
|
|
3046
3198
|
open: confirmTarget !== null,
|
|
3047
3199
|
onOpenChange: (open) => {
|
|
3048
3200
|
if (!open) setConfirmTarget(null);
|
|
3049
3201
|
},
|
|
3050
|
-
children: /* @__PURE__ */
|
|
3051
|
-
/* @__PURE__ */
|
|
3052
|
-
/* @__PURE__ */
|
|
3053
|
-
/* @__PURE__ */
|
|
3202
|
+
children: /* @__PURE__ */ jsxs14(AlertDialogContent2, { children: [
|
|
3203
|
+
/* @__PURE__ */ jsxs14(AlertDialogHeader2, { children: [
|
|
3204
|
+
/* @__PURE__ */ jsx21(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
|
|
3205
|
+
/* @__PURE__ */ jsx21(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
|
|
3054
3206
|
] }),
|
|
3055
|
-
/* @__PURE__ */
|
|
3056
|
-
/* @__PURE__ */
|
|
3057
|
-
/* @__PURE__ */
|
|
3058
|
-
|
|
3207
|
+
/* @__PURE__ */ jsxs14(AlertDialogFooter2, { children: [
|
|
3208
|
+
/* @__PURE__ */ jsx21(AlertDialogCancel2, { children: "Cancel" }),
|
|
3209
|
+
/* @__PURE__ */ jsx21(
|
|
3210
|
+
Button15,
|
|
3059
3211
|
{
|
|
3060
3212
|
variant: "destructive",
|
|
3061
3213
|
disabled: removeMutation.isPending,
|
|
@@ -3072,8 +3224,8 @@ function MembersPage() {
|
|
|
3072
3224
|
}
|
|
3073
3225
|
|
|
3074
3226
|
// src/front/workspace/WorkspaceSettingsPage.tsx
|
|
3075
|
-
import { useCallback as useCallback8, useEffect as useEffect10, useState as
|
|
3076
|
-
import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as
|
|
3227
|
+
import { useCallback as useCallback8, useEffect as useEffect10, useState as useState20 } from "react";
|
|
3228
|
+
import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
|
|
3077
3229
|
import { useNavigate as useNavigate5 } from "react-router-dom";
|
|
3078
3230
|
import {
|
|
3079
3231
|
AlertDialog as AlertDialog3,
|
|
@@ -3083,14 +3235,14 @@ import {
|
|
|
3083
3235
|
AlertDialogFooter as AlertDialogFooter3,
|
|
3084
3236
|
AlertDialogHeader as AlertDialogHeader3,
|
|
3085
3237
|
AlertDialogTitle as AlertDialogTitle3,
|
|
3086
|
-
Button as
|
|
3238
|
+
Button as Button16,
|
|
3087
3239
|
IconButton,
|
|
3088
3240
|
SettingsActionRow as UiSettingsActionRow2,
|
|
3089
3241
|
SettingsNav as UiSettingsNav2,
|
|
3090
3242
|
SettingsPanel as UiSettingsPanel2,
|
|
3091
3243
|
StatusBadge as StatusBadge2,
|
|
3092
|
-
Input as
|
|
3093
|
-
Label as
|
|
3244
|
+
Input as Input10,
|
|
3245
|
+
Label as Label10,
|
|
3094
3246
|
Notice as Notice5
|
|
3095
3247
|
} from "@hachej/boring-ui-kit";
|
|
3096
3248
|
import {
|
|
@@ -3102,7 +3254,7 @@ import {
|
|
|
3102
3254
|
ShieldAlert as ShieldAlert2,
|
|
3103
3255
|
Trash2 as Trash22
|
|
3104
3256
|
} from "lucide-react";
|
|
3105
|
-
import { Fragment as Fragment5, jsx as
|
|
3257
|
+
import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3106
3258
|
var STATE_TONES = {
|
|
3107
3259
|
pending: "info",
|
|
3108
3260
|
ready: "success",
|
|
@@ -3114,13 +3266,13 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
|
|
|
3114
3266
|
const appInitial = (appTitle.trim().charAt(0) || "B").toUpperCase();
|
|
3115
3267
|
const navigate = useNavigate5();
|
|
3116
3268
|
const workspaceHref = workspaceId ? `/workspace/${encodeURIComponent(workspaceId)}` : "/";
|
|
3117
|
-
return /* @__PURE__ */
|
|
3269
|
+
return /* @__PURE__ */ jsx22(
|
|
3118
3270
|
"header",
|
|
3119
3271
|
{
|
|
3120
3272
|
className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
|
|
3121
3273
|
"aria-label": "App top bar",
|
|
3122
|
-
children: /* @__PURE__ */
|
|
3123
|
-
/* @__PURE__ */
|
|
3274
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
|
|
3275
|
+
/* @__PURE__ */ jsx22(
|
|
3124
3276
|
IconButton,
|
|
3125
3277
|
{
|
|
3126
3278
|
type: "button",
|
|
@@ -3133,11 +3285,11 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
|
|
|
3133
3285
|
children: appInitial
|
|
3134
3286
|
}
|
|
3135
3287
|
),
|
|
3136
|
-
/* @__PURE__ */
|
|
3137
|
-
/* @__PURE__ */
|
|
3138
|
-
/* @__PURE__ */
|
|
3139
|
-
/* @__PURE__ */
|
|
3140
|
-
/* @__PURE__ */
|
|
3288
|
+
/* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
|
|
3289
|
+
/* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
3290
|
+
/* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
|
|
3291
|
+
/* @__PURE__ */ jsx22("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
3292
|
+
/* @__PURE__ */ jsx22("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
|
|
3141
3293
|
] })
|
|
3142
3294
|
}
|
|
3143
3295
|
);
|
|
@@ -3148,26 +3300,26 @@ function SettingsPageHeader2({
|
|
|
3148
3300
|
role,
|
|
3149
3301
|
isDefault
|
|
3150
3302
|
}) {
|
|
3151
|
-
return /* @__PURE__ */
|
|
3152
|
-
/* @__PURE__ */
|
|
3153
|
-
/* @__PURE__ */
|
|
3154
|
-
/* @__PURE__ */
|
|
3155
|
-
/* @__PURE__ */
|
|
3156
|
-
/* @__PURE__ */
|
|
3157
|
-
/* @__PURE__ */
|
|
3158
|
-
isDefault ? /* @__PURE__ */
|
|
3303
|
+
return /* @__PURE__ */ jsxs15("header", { className: "boring-settings-page-header", children: [
|
|
3304
|
+
/* @__PURE__ */ jsxs15("div", { className: "boring-settings-context", children: [
|
|
3305
|
+
/* @__PURE__ */ jsx22("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: workspaceInitial2 }),
|
|
3306
|
+
/* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
|
|
3307
|
+
/* @__PURE__ */ jsx22("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
|
|
3308
|
+
/* @__PURE__ */ jsxs15("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
|
|
3309
|
+
/* @__PURE__ */ jsx22("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
|
|
3310
|
+
isDefault ? /* @__PURE__ */ jsx22("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
|
|
3159
3311
|
] })
|
|
3160
3312
|
] })
|
|
3161
3313
|
] }),
|
|
3162
|
-
/* @__PURE__ */
|
|
3163
|
-
/* @__PURE__ */
|
|
3164
|
-
/* @__PURE__ */
|
|
3165
|
-
/* @__PURE__ */
|
|
3314
|
+
/* @__PURE__ */ jsxs15("div", { className: "max-w-2xl", children: [
|
|
3315
|
+
/* @__PURE__ */ jsx22("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
|
|
3316
|
+
/* @__PURE__ */ jsx22("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
|
|
3317
|
+
/* @__PURE__ */ jsx22("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
|
|
3166
3318
|
] })
|
|
3167
3319
|
] });
|
|
3168
3320
|
}
|
|
3169
3321
|
function FieldNote({ children }) {
|
|
3170
|
-
return /* @__PURE__ */
|
|
3322
|
+
return /* @__PURE__ */ jsx22("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
|
|
3171
3323
|
}
|
|
3172
3324
|
function roleLabel(role) {
|
|
3173
3325
|
if (!role) return "Loading role";
|
|
@@ -3182,17 +3334,17 @@ var WORKSPACE_NAV_ITEMS = [
|
|
|
3182
3334
|
function WorkspaceSettingsPage({ topBar } = {}) {
|
|
3183
3335
|
const workspace = useCurrentWorkspace();
|
|
3184
3336
|
const role = useWorkspaceRole();
|
|
3185
|
-
const queryClient =
|
|
3337
|
+
const queryClient = useQueryClient7();
|
|
3186
3338
|
const navigate = useNavigate5();
|
|
3187
3339
|
const workspaceId = workspace?.id ?? "";
|
|
3188
|
-
const [nameValue, setNameValue] =
|
|
3189
|
-
const [nameError, setNameError] =
|
|
3190
|
-
const [retryError, setRetryError] =
|
|
3191
|
-
const [deleteConfirmName, setDeleteConfirmName] =
|
|
3192
|
-
const [deleteDialogOpen, setDeleteDialogOpen] =
|
|
3193
|
-
const [deleteError, setDeleteError] =
|
|
3194
|
-
const [imageUploadDirValue, setImageUploadDirValue] =
|
|
3195
|
-
const [fileSettingsError, setFileSettingsError] =
|
|
3340
|
+
const [nameValue, setNameValue] = useState20(null);
|
|
3341
|
+
const [nameError, setNameError] = useState20(null);
|
|
3342
|
+
const [retryError, setRetryError] = useState20(null);
|
|
3343
|
+
const [deleteConfirmName, setDeleteConfirmName] = useState20("");
|
|
3344
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = useState20(false);
|
|
3345
|
+
const [deleteError, setDeleteError] = useState20(null);
|
|
3346
|
+
const [imageUploadDirValue, setImageUploadDirValue] = useState20(null);
|
|
3347
|
+
const [fileSettingsError, setFileSettingsError] = useState20(null);
|
|
3196
3348
|
const displayName = nameValue ?? workspace?.name ?? "";
|
|
3197
3349
|
const encodedWorkspaceId = encodeURIComponent(workspaceId);
|
|
3198
3350
|
const requestHeaders = workspaceId ? { "x-boring-workspace-id": workspaceId } : void 0;
|
|
@@ -3338,18 +3490,18 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3338
3490
|
const canDeleteWorkspace = role === "owner" || role === null;
|
|
3339
3491
|
const workspaceName = workspace?.name ?? "Workspace";
|
|
3340
3492
|
const workspaceInitial2 = (workspace?.name?.trim()?.[0] ?? "W").toUpperCase();
|
|
3341
|
-
const topBarNode = topBar === void 0 ? /* @__PURE__ */
|
|
3493
|
+
const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx22(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
|
|
3342
3494
|
const navItems = WORKSPACE_NAV_ITEMS.filter((item) => {
|
|
3343
3495
|
if (item.href === "#runtime") return hasRuntime;
|
|
3344
3496
|
if (item.href === "#files") return hasFileSettings;
|
|
3345
3497
|
return true;
|
|
3346
3498
|
});
|
|
3347
|
-
return /* @__PURE__ */
|
|
3499
|
+
return /* @__PURE__ */ jsxs15("main", { className: "boring-settings-shell", children: [
|
|
3348
3500
|
topBarNode,
|
|
3349
|
-
/* @__PURE__ */
|
|
3350
|
-
/* @__PURE__ */
|
|
3351
|
-
/* @__PURE__ */
|
|
3352
|
-
/* @__PURE__ */
|
|
3501
|
+
/* @__PURE__ */ jsx22("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs15("div", { className: "boring-settings-layout", children: [
|
|
3502
|
+
/* @__PURE__ */ jsx22("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx22(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
|
|
3503
|
+
/* @__PURE__ */ jsxs15("div", { className: "boring-settings-content space-y-4", children: [
|
|
3504
|
+
/* @__PURE__ */ jsx22(
|
|
3353
3505
|
SettingsPageHeader2,
|
|
3354
3506
|
{
|
|
3355
3507
|
workspaceName,
|
|
@@ -3358,16 +3510,16 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3358
3510
|
isDefault: Boolean(workspace?.isDefault)
|
|
3359
3511
|
}
|
|
3360
3512
|
),
|
|
3361
|
-
/* @__PURE__ */
|
|
3513
|
+
/* @__PURE__ */ jsx22(
|
|
3362
3514
|
UiSettingsPanel2,
|
|
3363
3515
|
{
|
|
3364
3516
|
id: "general",
|
|
3365
|
-
icon: /* @__PURE__ */
|
|
3517
|
+
icon: /* @__PURE__ */ jsx22(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3366
3518
|
title: "General",
|
|
3367
3519
|
description: "Keep the workspace name clear enough to scan in menus.",
|
|
3368
|
-
footer: /* @__PURE__ */
|
|
3369
|
-
nameChanged ? /* @__PURE__ */
|
|
3370
|
-
|
|
3520
|
+
footer: /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
3521
|
+
nameChanged ? /* @__PURE__ */ jsx22(
|
|
3522
|
+
Button16,
|
|
3371
3523
|
{
|
|
3372
3524
|
type: "button",
|
|
3373
3525
|
variant: "ghost",
|
|
@@ -3380,8 +3532,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3380
3532
|
children: "Reset"
|
|
3381
3533
|
}
|
|
3382
3534
|
) : null,
|
|
3383
|
-
/* @__PURE__ */
|
|
3384
|
-
|
|
3535
|
+
/* @__PURE__ */ jsx22(
|
|
3536
|
+
Button16,
|
|
3385
3537
|
{
|
|
3386
3538
|
"data-testid": "save-name",
|
|
3387
3539
|
size: "sm",
|
|
@@ -3391,12 +3543,12 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3391
3543
|
}
|
|
3392
3544
|
)
|
|
3393
3545
|
] }),
|
|
3394
|
-
children: /* @__PURE__ */
|
|
3395
|
-
nameError && /* @__PURE__ */
|
|
3396
|
-
/* @__PURE__ */
|
|
3397
|
-
/* @__PURE__ */
|
|
3398
|
-
/* @__PURE__ */
|
|
3399
|
-
|
|
3546
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
3547
|
+
nameError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
|
|
3548
|
+
/* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
|
|
3549
|
+
/* @__PURE__ */ jsx22(Label10, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
|
|
3550
|
+
/* @__PURE__ */ jsx22(
|
|
3551
|
+
Input10,
|
|
3400
3552
|
{
|
|
3401
3553
|
id: "workspace-name",
|
|
3402
3554
|
"data-testid": "workspace-name-input",
|
|
@@ -3407,50 +3559,50 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3407
3559
|
"aria-invalid": nameError ? "true" : "false"
|
|
3408
3560
|
}
|
|
3409
3561
|
),
|
|
3410
|
-
/* @__PURE__ */
|
|
3562
|
+
/* @__PURE__ */ jsx22(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
|
|
3411
3563
|
] })
|
|
3412
3564
|
] })
|
|
3413
3565
|
}
|
|
3414
3566
|
),
|
|
3415
|
-
hasRuntime && /* @__PURE__ */
|
|
3567
|
+
hasRuntime && /* @__PURE__ */ jsx22(
|
|
3416
3568
|
UiSettingsPanel2,
|
|
3417
3569
|
{
|
|
3418
3570
|
id: "runtime",
|
|
3419
3571
|
testId: "runtime-card",
|
|
3420
|
-
icon: /* @__PURE__ */
|
|
3572
|
+
icon: /* @__PURE__ */ jsx22(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3421
3573
|
title: "Runtime",
|
|
3422
3574
|
description: "Provisioning status for this workspace.",
|
|
3423
|
-
children: /* @__PURE__ */
|
|
3424
|
-
/* @__PURE__ */
|
|
3425
|
-
/* @__PURE__ */
|
|
3426
|
-
/* @__PURE__ */
|
|
3575
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
|
|
3576
|
+
/* @__PURE__ */ jsxs15("div", { className: "flex min-h-10 flex-wrap items-center justify-between gap-3 rounded-md border border-border/50 bg-muted/10 px-3 py-2", children: [
|
|
3577
|
+
/* @__PURE__ */ jsx22("span", { className: "text-[13px] font-medium", children: "State" }),
|
|
3578
|
+
/* @__PURE__ */ jsx22(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
|
|
3427
3579
|
] }),
|
|
3428
|
-
runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */
|
|
3580
|
+
runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs15(
|
|
3429
3581
|
"div",
|
|
3430
3582
|
{
|
|
3431
3583
|
"data-testid": "volume-path",
|
|
3432
3584
|
className: "space-y-1 rounded-md border border-border/50 bg-muted/10 px-3 py-2",
|
|
3433
3585
|
children: [
|
|
3434
|
-
/* @__PURE__ */
|
|
3435
|
-
/* @__PURE__ */
|
|
3586
|
+
/* @__PURE__ */ jsx22("p", { className: "text-[13px] font-medium", children: "Volume" }),
|
|
3587
|
+
/* @__PURE__ */ jsx22("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
|
|
3436
3588
|
]
|
|
3437
3589
|
}
|
|
3438
3590
|
),
|
|
3439
|
-
runtime.state === "error" && runtime.lastError && /* @__PURE__ */
|
|
3591
|
+
runtime.state === "error" && runtime.lastError && /* @__PURE__ */ jsxs15(
|
|
3440
3592
|
"div",
|
|
3441
3593
|
{
|
|
3442
3594
|
"data-testid": "runtime-error",
|
|
3443
3595
|
role: "alert",
|
|
3444
3596
|
className: "flex gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[13px] leading-5 text-destructive",
|
|
3445
3597
|
children: [
|
|
3446
|
-
/* @__PURE__ */
|
|
3598
|
+
/* @__PURE__ */ jsx22(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
3447
3599
|
runtime.lastError
|
|
3448
3600
|
]
|
|
3449
3601
|
}
|
|
3450
3602
|
),
|
|
3451
|
-
runtime.state === "error" && runtime.lastErrorOp === "provision" && /* @__PURE__ */
|
|
3452
|
-
/* @__PURE__ */
|
|
3453
|
-
|
|
3603
|
+
runtime.state === "error" && runtime.lastErrorOp === "provision" && /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
|
|
3604
|
+
/* @__PURE__ */ jsxs15(
|
|
3605
|
+
Button16,
|
|
3454
3606
|
{
|
|
3455
3607
|
"data-testid": "retry-provision",
|
|
3456
3608
|
variant: "outline",
|
|
@@ -3458,14 +3610,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3458
3610
|
disabled: retryMutation.isPending,
|
|
3459
3611
|
onClick: () => retryMutation.mutate(),
|
|
3460
3612
|
children: [
|
|
3461
|
-
/* @__PURE__ */
|
|
3613
|
+
/* @__PURE__ */ jsx22(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
3462
3614
|
retryMutation.isPending ? "Retrying..." : "Retry provisioning"
|
|
3463
3615
|
]
|
|
3464
3616
|
}
|
|
3465
3617
|
),
|
|
3466
|
-
retryError && /* @__PURE__ */
|
|
3618
|
+
retryError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
|
|
3467
3619
|
] }),
|
|
3468
|
-
runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */
|
|
3620
|
+
runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx22(
|
|
3469
3621
|
"p",
|
|
3470
3622
|
{
|
|
3471
3623
|
"data-testid": "destroy-guidance",
|
|
@@ -3476,16 +3628,16 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3476
3628
|
] })
|
|
3477
3629
|
}
|
|
3478
3630
|
),
|
|
3479
|
-
hasFileSettings && /* @__PURE__ */
|
|
3631
|
+
hasFileSettings && /* @__PURE__ */ jsx22(
|
|
3480
3632
|
UiSettingsPanel2,
|
|
3481
3633
|
{
|
|
3482
3634
|
id: "files",
|
|
3483
3635
|
testId: "file-settings-card",
|
|
3484
|
-
icon: /* @__PURE__ */
|
|
3636
|
+
icon: /* @__PURE__ */ jsx22(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3485
3637
|
title: "Files",
|
|
3486
3638
|
description: "Configure where markdown editor image uploads are stored. Direct/local workspaces can also edit .boring/settings.",
|
|
3487
|
-
footer: /* @__PURE__ */
|
|
3488
|
-
|
|
3639
|
+
footer: /* @__PURE__ */ jsx22(
|
|
3640
|
+
Button16,
|
|
3489
3641
|
{
|
|
3490
3642
|
"data-testid": "save-file-settings",
|
|
3491
3643
|
size: "sm",
|
|
@@ -3494,12 +3646,12 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3494
3646
|
children: fileSettingsMutation.isPending ? "Saving..." : "Save file settings"
|
|
3495
3647
|
}
|
|
3496
3648
|
),
|
|
3497
|
-
children: /* @__PURE__ */
|
|
3498
|
-
fileSettingsError && /* @__PURE__ */
|
|
3499
|
-
/* @__PURE__ */
|
|
3500
|
-
/* @__PURE__ */
|
|
3501
|
-
/* @__PURE__ */
|
|
3502
|
-
|
|
3649
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
3650
|
+
fileSettingsError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
|
|
3651
|
+
/* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
|
|
3652
|
+
/* @__PURE__ */ jsx22(Label10, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
|
|
3653
|
+
/* @__PURE__ */ jsx22(
|
|
3654
|
+
Input10,
|
|
3503
3655
|
{
|
|
3504
3656
|
id: "markdown-image-upload-dir",
|
|
3505
3657
|
"data-testid": "markdown-image-upload-dir-input",
|
|
@@ -3509,35 +3661,35 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3509
3661
|
disabled: !canEditName
|
|
3510
3662
|
}
|
|
3511
3663
|
),
|
|
3512
|
-
/* @__PURE__ */
|
|
3664
|
+
/* @__PURE__ */ jsxs15(FieldNote, { children: [
|
|
3513
3665
|
"Relative workspace path used by markdown image uploads. Stored in ",
|
|
3514
|
-
/* @__PURE__ */
|
|
3666
|
+
/* @__PURE__ */ jsx22("code", { children: ".boring/settings" }),
|
|
3515
3667
|
"."
|
|
3516
3668
|
] })
|
|
3517
3669
|
] })
|
|
3518
3670
|
] })
|
|
3519
3671
|
}
|
|
3520
3672
|
),
|
|
3521
|
-
/* @__PURE__ */
|
|
3673
|
+
/* @__PURE__ */ jsx22(
|
|
3522
3674
|
UiSettingsPanel2,
|
|
3523
3675
|
{
|
|
3524
3676
|
id: "danger-zone",
|
|
3525
3677
|
testId: "danger-zone",
|
|
3526
|
-
icon: /* @__PURE__ */
|
|
3678
|
+
icon: /* @__PURE__ */ jsx22(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3527
3679
|
title: "Danger zone",
|
|
3528
3680
|
description: "Permanently delete this workspace and all provisioned data.",
|
|
3529
3681
|
danger: true,
|
|
3530
|
-
children: /* @__PURE__ */
|
|
3531
|
-
deleteError && /* @__PURE__ */
|
|
3532
|
-
!canDeleteWorkspace ? /* @__PURE__ */
|
|
3533
|
-
/* @__PURE__ */
|
|
3682
|
+
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
3683
|
+
deleteError && /* @__PURE__ */ jsx22(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
|
|
3684
|
+
!canDeleteWorkspace ? /* @__PURE__ */ jsx22("div", { className: "rounded-md border border-border/50 bg-muted/10 px-3 py-2 text-[13px] leading-5 text-muted-foreground", children: "Only workspace owners can delete this workspace." }) : null,
|
|
3685
|
+
/* @__PURE__ */ jsx22(
|
|
3534
3686
|
UiSettingsActionRow2,
|
|
3535
3687
|
{
|
|
3536
3688
|
title: "Delete workspace",
|
|
3537
3689
|
description: "Delete the workspace record and re-issue cleanup for provisioned runtime data.",
|
|
3538
|
-
action: /* @__PURE__ */
|
|
3539
|
-
/* @__PURE__ */
|
|
3540
|
-
|
|
3690
|
+
action: /* @__PURE__ */ jsxs15(AlertDialog3, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
|
|
3691
|
+
/* @__PURE__ */ jsxs15(
|
|
3692
|
+
Button16,
|
|
3541
3693
|
{
|
|
3542
3694
|
variant: "destructive",
|
|
3543
3695
|
size: "sm",
|
|
@@ -3548,22 +3700,22 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3548
3700
|
setDeleteConfirmName("");
|
|
3549
3701
|
},
|
|
3550
3702
|
children: [
|
|
3551
|
-
/* @__PURE__ */
|
|
3703
|
+
/* @__PURE__ */ jsx22(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
3552
3704
|
"Delete workspace"
|
|
3553
3705
|
]
|
|
3554
3706
|
}
|
|
3555
3707
|
),
|
|
3556
|
-
/* @__PURE__ */
|
|
3557
|
-
/* @__PURE__ */
|
|
3558
|
-
/* @__PURE__ */
|
|
3559
|
-
/* @__PURE__ */
|
|
3708
|
+
/* @__PURE__ */ jsxs15(AlertDialogContent3, { children: [
|
|
3709
|
+
/* @__PURE__ */ jsxs15(AlertDialogHeader3, { children: [
|
|
3710
|
+
/* @__PURE__ */ jsx22(AlertDialogTitle3, { children: "Delete workspace?" }),
|
|
3711
|
+
/* @__PURE__ */ jsxs15(AlertDialogDescription3, { children: [
|
|
3560
3712
|
"This action cannot be undone. Type ",
|
|
3561
|
-
/* @__PURE__ */
|
|
3713
|
+
/* @__PURE__ */ jsx22("strong", { children: workspace?.name }),
|
|
3562
3714
|
" to confirm."
|
|
3563
3715
|
] })
|
|
3564
3716
|
] }),
|
|
3565
|
-
/* @__PURE__ */
|
|
3566
|
-
|
|
3717
|
+
/* @__PURE__ */ jsx22("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx22(
|
|
3718
|
+
Input10,
|
|
3567
3719
|
{
|
|
3568
3720
|
"data-testid": "delete-confirm-input",
|
|
3569
3721
|
className: "h-8 text-[13px]",
|
|
@@ -3573,10 +3725,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3573
3725
|
autoComplete: "off"
|
|
3574
3726
|
}
|
|
3575
3727
|
) }),
|
|
3576
|
-
/* @__PURE__ */
|
|
3577
|
-
/* @__PURE__ */
|
|
3578
|
-
/* @__PURE__ */
|
|
3579
|
-
|
|
3728
|
+
/* @__PURE__ */ jsxs15(AlertDialogFooter3, { children: [
|
|
3729
|
+
/* @__PURE__ */ jsx22(AlertDialogCancel3, { children: "Cancel" }),
|
|
3730
|
+
/* @__PURE__ */ jsx22(
|
|
3731
|
+
Button16,
|
|
3580
3732
|
{
|
|
3581
3733
|
variant: "destructive",
|
|
3582
3734
|
size: "sm",
|
|
@@ -3600,10 +3752,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3600
3752
|
}
|
|
3601
3753
|
|
|
3602
3754
|
// src/front/CoreFront.tsx
|
|
3603
|
-
import { Fragment as Fragment6, jsx as
|
|
3755
|
+
import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3604
3756
|
var CSP_NONCE_META_NAME = "boring-csp-nonce";
|
|
3605
3757
|
function PlaceholderPage({ name }) {
|
|
3606
|
-
return /* @__PURE__ */
|
|
3758
|
+
return /* @__PURE__ */ jsxs16("div", { "data-testid": `placeholder-${name}`, children: [
|
|
3607
3759
|
name,
|
|
3608
3760
|
" (not yet implemented)"
|
|
3609
3761
|
] });
|
|
@@ -3628,7 +3780,7 @@ function RouterAuthGate({ children, publicPaths }) {
|
|
|
3628
3780
|
const config = useConfig();
|
|
3629
3781
|
const location = useLocation2();
|
|
3630
3782
|
const navigate = useNavigate6();
|
|
3631
|
-
const authLocation =
|
|
3783
|
+
const authLocation = useMemo7(
|
|
3632
3784
|
() => ({ pathname: location.pathname, search: location.search, hash: location.hash }),
|
|
3633
3785
|
[location.hash, location.pathname, location.search]
|
|
3634
3786
|
);
|
|
@@ -3638,7 +3790,7 @@ function RouterAuthGate({ children, publicPaths }) {
|
|
|
3638
3790
|
},
|
|
3639
3791
|
[navigate]
|
|
3640
3792
|
);
|
|
3641
|
-
return /* @__PURE__ */
|
|
3793
|
+
return /* @__PURE__ */ jsx23(
|
|
3642
3794
|
AuthGate,
|
|
3643
3795
|
{
|
|
3644
3796
|
location: authLocation,
|
|
@@ -3650,8 +3802,8 @@ function RouterAuthGate({ children, publicPaths }) {
|
|
|
3650
3802
|
);
|
|
3651
3803
|
}
|
|
3652
3804
|
function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdParam, publicPaths }) {
|
|
3653
|
-
const queryClient =
|
|
3654
|
-
const resolvedCspNonce =
|
|
3805
|
+
const queryClient = useMemo7(createDefaultQueryClient, []);
|
|
3806
|
+
const resolvedCspNonce = useMemo7(
|
|
3655
3807
|
() => cspNonce ?? readCspNonceFromDom(),
|
|
3656
3808
|
[cspNonce]
|
|
3657
3809
|
);
|
|
@@ -3662,10 +3814,10 @@ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdP
|
|
|
3662
3814
|
const VerifyEmailPage2 = authPages?.verifyEmail ?? VerifyEmailPage;
|
|
3663
3815
|
const AuthErrorPage2 = authPages?.authError ?? AuthErrorPage;
|
|
3664
3816
|
const UserSettingsPage2 = authPages?.userSettings ?? UserSettingsPage;
|
|
3665
|
-
return /* @__PURE__ */
|
|
3666
|
-
/* @__PURE__ */
|
|
3667
|
-
/* @__PURE__ */
|
|
3668
|
-
/* @__PURE__ */
|
|
3817
|
+
return /* @__PURE__ */ jsx23(HelmetProvider, { children: /* @__PURE__ */ jsx23(AppErrorBoundary, { children: /* @__PURE__ */ jsx23(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx23(ConfigProvider, { children: /* @__PURE__ */ jsx23(ThemeProvider, { children: /* @__PURE__ */ jsx23(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx23(UserIdentityProvider, { children: /* @__PURE__ */ jsx23(BrowserRouter, { children: /* @__PURE__ */ jsx23(WorkspaceAuthProvider, { workspaceRoute, workspaceIdParam, children: /* @__PURE__ */ jsxs16(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx23(UserMenu, {}), children: [
|
|
3818
|
+
/* @__PURE__ */ jsx23(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsxs16(Fragment6, { children: [
|
|
3819
|
+
/* @__PURE__ */ jsx23("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }),
|
|
3820
|
+
/* @__PURE__ */ jsx23(
|
|
3669
3821
|
"script",
|
|
3670
3822
|
{
|
|
3671
3823
|
type: "application/json",
|
|
@@ -3675,30 +3827,30 @@ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdP
|
|
|
3675
3827
|
}
|
|
3676
3828
|
)
|
|
3677
3829
|
] }) : null }),
|
|
3678
|
-
/* @__PURE__ */
|
|
3679
|
-
/* @__PURE__ */
|
|
3680
|
-
/* @__PURE__ */
|
|
3681
|
-
/* @__PURE__ */
|
|
3682
|
-
/* @__PURE__ */
|
|
3683
|
-
/* @__PURE__ */
|
|
3684
|
-
/* @__PURE__ */
|
|
3685
|
-
/* @__PURE__ */
|
|
3686
|
-
/* @__PURE__ */
|
|
3687
|
-
/* @__PURE__ */
|
|
3688
|
-
/* @__PURE__ */
|
|
3689
|
-
/* @__PURE__ */
|
|
3690
|
-
/* @__PURE__ */
|
|
3691
|
-
/* @__PURE__ */
|
|
3692
|
-
/* @__PURE__ */
|
|
3693
|
-
/* @__PURE__ */
|
|
3694
|
-
/* @__PURE__ */
|
|
3830
|
+
/* @__PURE__ */ jsx23(RouterAuthGate, { publicPaths: ["/invites", ...publicPaths ?? []], children: /* @__PURE__ */ jsx23(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs16(Routes, { children: [
|
|
3831
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.signin, element: /* @__PURE__ */ jsx23(SignInPage2, {}) }),
|
|
3832
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.signup, element: /* @__PURE__ */ jsx23(SignUpPage2, {}) }),
|
|
3833
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx23(ForgotPasswordPage2, {}) }),
|
|
3834
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx23(ResetPasswordPage2, {}) }),
|
|
3835
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx23(VerifyEmailPage2, {}) }),
|
|
3836
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.authError, element: /* @__PURE__ */ jsx23(AuthErrorPage2, {}) }),
|
|
3837
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx23(PlaceholderPage, { name: "github-callback" }) }),
|
|
3838
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx23(PlaceholderPage, { name: "google-callback" }) }),
|
|
3839
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.me, element: /* @__PURE__ */ jsx23(UserSettingsPage2, {}) }),
|
|
3840
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx23(MembersPage, {}) }),
|
|
3841
|
+
/* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx23(MembersPage, {}) }),
|
|
3842
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx23(InvitesPage, {}) }),
|
|
3843
|
+
/* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx23(InvitesPage, {}) }),
|
|
3844
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx23(WorkspaceSettingsPage, {}) }),
|
|
3845
|
+
/* @__PURE__ */ jsx23(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx23(WorkspaceSettingsPage, {}) }),
|
|
3846
|
+
/* @__PURE__ */ jsx23(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx23(InviteAcceptPage, {}) }),
|
|
3695
3847
|
children
|
|
3696
3848
|
] }) }) })
|
|
3697
3849
|
] }) }) }) }) }) }) }) }) }) });
|
|
3698
3850
|
}
|
|
3699
3851
|
|
|
3700
3852
|
// src/front/commands/CoreCommandContributions.tsx
|
|
3701
|
-
import { useMemo as
|
|
3853
|
+
import { useMemo as useMemo8, useState as useState21 } from "react";
|
|
3702
3854
|
import { useNavigate as useNavigate7 } from "react-router-dom";
|
|
3703
3855
|
|
|
3704
3856
|
// src/front/workspace/commands.ts
|
|
@@ -3740,8 +3892,8 @@ function useCoreCommands() {
|
|
|
3740
3892
|
const navigate = useNavigate7();
|
|
3741
3893
|
const signOut = useSignOut();
|
|
3742
3894
|
const workspace = useCurrentWorkspace();
|
|
3743
|
-
const [isSigningOut, setIsSigningOut] =
|
|
3744
|
-
return
|
|
3895
|
+
const [isSigningOut, setIsSigningOut] = useState21(false);
|
|
3896
|
+
return useMemo8(() => {
|
|
3745
3897
|
const result = [
|
|
3746
3898
|
{
|
|
3747
3899
|
id: "user:settings",
|
|
@@ -3887,6 +4039,7 @@ export {
|
|
|
3887
4039
|
AuthGate,
|
|
3888
4040
|
UserMenu,
|
|
3889
4041
|
WorkspaceSwitcher,
|
|
4042
|
+
CreateWorkspaceDialog,
|
|
3890
4043
|
ThemeToggle,
|
|
3891
4044
|
InvitesPage,
|
|
3892
4045
|
MembersPage,
|