@hachej/boring-core 0.1.63 → 0.1.65
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/CoreFront-DB1OfNJU.d.ts +65 -0
- package/dist/{PostgresMeteringStore-qjKGmVFr.d.ts → PostgresModelBudgetStore-CFbEEdQL.d.ts} +44 -2
- package/dist/app/front/index.d.ts +9 -8
- package/dist/app/front/index.js +4 -1
- package/dist/app/server/index.d.ts +3 -3
- package/dist/app/server/index.js +4 -2
- package/dist/{authHook-BbgCBHjP.d.ts → authHook-BUSGTx_o.d.ts} +2 -2
- package/dist/{chunk-NC46VGXS.js → chunk-3B7LU76T.js} +673 -502
- package/dist/{chunk-ZMS6O4CY.js → chunk-CIRY3ZLU.js} +128 -18
- package/dist/{chunk-BVZ2YT3M.js → chunk-EFM5IWTK.js} +412 -17
- package/dist/{connection-B1iC6B-w.d.ts → connection-D9s7Td0I.d.ts} +21 -2
- package/dist/front/index.d.ts +29 -27
- package/dist/front/index.js +7 -1
- package/dist/front/top-bar-slot.d.ts +2 -2
- package/dist/server/db/index.d.ts +31 -6
- package/dist/server/db/index.js +5 -1
- package/dist/server/index.d.ts +11 -8
- package/dist/server/index.js +13 -5
- package/dist/shared/index.d.ts +2 -2
- package/dist/{types-Bb7I-83I.d.ts → types-DVgeIw1d.d.ts} +1 -0
- package/drizzle/0015_model_budget_reservations.sql +22 -0
- package/drizzle/0016_workspace_managed_by.sql +1 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +30 -30
- package/dist/CoreFront-N0QJSYaM.d.ts +0 -23
|
@@ -142,6 +142,7 @@ var routes = {
|
|
|
142
142
|
workspaceMembers: "/w/:id/members",
|
|
143
143
|
workspaceInvites: "/w/:id/invites",
|
|
144
144
|
workspaceSettings: "/w/:id/settings",
|
|
145
|
+
companyAdmin: "/w/:id/admin",
|
|
145
146
|
inviteAccept: "/invites/:token"
|
|
146
147
|
};
|
|
147
148
|
function routeHref(name, params) {
|
|
@@ -301,8 +302,77 @@ function useTheme() {
|
|
|
301
302
|
return ctx;
|
|
302
303
|
}
|
|
303
304
|
|
|
305
|
+
// src/front/CompanyAdminProvider.tsx
|
|
306
|
+
import { createContext as createContext3, useContext as useContext3, useEffect as useEffect3, useMemo as useMemo2, useState as useState3 } from "react";
|
|
307
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
308
|
+
var CompanyAdminContext = createContext3({
|
|
309
|
+
configured: false,
|
|
310
|
+
loading: false,
|
|
311
|
+
status: null,
|
|
312
|
+
error: null,
|
|
313
|
+
renderContent: null,
|
|
314
|
+
labels: {},
|
|
315
|
+
refresh: async () => {
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
function CompanyAdminProvider({ children, loadStatus, renderContent, labels, identityKey }) {
|
|
319
|
+
const [status, setStatus] = useState3(null);
|
|
320
|
+
const [loading, setLoading] = useState3(Boolean(loadStatus && identityKey !== null));
|
|
321
|
+
const [error, setError] = useState3(null);
|
|
322
|
+
async function refresh() {
|
|
323
|
+
if (!loadStatus) return;
|
|
324
|
+
setLoading(true);
|
|
325
|
+
setError(null);
|
|
326
|
+
try {
|
|
327
|
+
setStatus(await loadStatus());
|
|
328
|
+
} catch (err) {
|
|
329
|
+
setStatus(null);
|
|
330
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
331
|
+
} finally {
|
|
332
|
+
setLoading(false);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
useEffect3(() => {
|
|
336
|
+
let cancelled = false;
|
|
337
|
+
if (!loadStatus || identityKey === null) {
|
|
338
|
+
setStatus(null);
|
|
339
|
+
setError(null);
|
|
340
|
+
setLoading(false);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
setLoading(true);
|
|
344
|
+
setError(null);
|
|
345
|
+
loadStatus().then((next) => {
|
|
346
|
+
if (!cancelled) setStatus(next);
|
|
347
|
+
}).catch((err) => {
|
|
348
|
+
if (!cancelled) {
|
|
349
|
+
setStatus(null);
|
|
350
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
351
|
+
}
|
|
352
|
+
}).finally(() => {
|
|
353
|
+
if (!cancelled) setLoading(false);
|
|
354
|
+
});
|
|
355
|
+
return () => {
|
|
356
|
+
cancelled = true;
|
|
357
|
+
};
|
|
358
|
+
}, [identityKey, loadStatus]);
|
|
359
|
+
const value = useMemo2(() => ({
|
|
360
|
+
configured: Boolean(loadStatus && renderContent),
|
|
361
|
+
loading,
|
|
362
|
+
status,
|
|
363
|
+
error,
|
|
364
|
+
renderContent: renderContent ?? null,
|
|
365
|
+
labels: labels ?? {},
|
|
366
|
+
refresh
|
|
367
|
+
}), [error, labels, loadStatus, loading, renderContent, status]);
|
|
368
|
+
return /* @__PURE__ */ jsx4(CompanyAdminContext.Provider, { value, children });
|
|
369
|
+
}
|
|
370
|
+
function useCompanyAdminStatus() {
|
|
371
|
+
return useContext3(CompanyAdminContext);
|
|
372
|
+
}
|
|
373
|
+
|
|
304
374
|
// src/front/hooks/useKeyboardShortcuts.ts
|
|
305
|
-
import { useEffect as
|
|
375
|
+
import { useEffect as useEffect4, useRef as useRef2 } from "react";
|
|
306
376
|
var MAC_PLATFORM_RE = /Mac|iPod|iPhone|iPad/;
|
|
307
377
|
function normalizeKey(key) {
|
|
308
378
|
const lowered = key.toLowerCase();
|
|
@@ -351,7 +421,7 @@ function matchesBinding(event, parsed, macPlatform) {
|
|
|
351
421
|
function useKeyboardShortcuts(bindings) {
|
|
352
422
|
const bindingsRef = useRef2(bindings);
|
|
353
423
|
bindingsRef.current = bindings;
|
|
354
|
-
|
|
424
|
+
useEffect4(() => {
|
|
355
425
|
if (typeof window === "undefined") return;
|
|
356
426
|
const macPlatform = isMacPlatform();
|
|
357
427
|
const parsedBindings = bindingsRef.current.map((binding) => ({
|
|
@@ -375,7 +445,7 @@ function useKeyboardShortcuts(bindings) {
|
|
|
375
445
|
}
|
|
376
446
|
|
|
377
447
|
// src/front/hooks/useViewportBreakpoint.ts
|
|
378
|
-
import { useEffect as
|
|
448
|
+
import { useEffect as useEffect5, useState as useState4 } from "react";
|
|
379
449
|
function getBreakpoint() {
|
|
380
450
|
if (typeof window === "undefined") return "sm";
|
|
381
451
|
if (typeof window.matchMedia !== "function") return "sm";
|
|
@@ -386,8 +456,8 @@ function getBreakpoint() {
|
|
|
386
456
|
return "sm";
|
|
387
457
|
}
|
|
388
458
|
function useViewportBreakpoint() {
|
|
389
|
-
const [breakpoint, setBreakpoint] =
|
|
390
|
-
|
|
459
|
+
const [breakpoint, setBreakpoint] = useState4(getBreakpoint);
|
|
460
|
+
useEffect5(() => {
|
|
391
461
|
if (typeof window === "undefined") return;
|
|
392
462
|
const update = () => {
|
|
393
463
|
setBreakpoint(getBreakpoint());
|
|
@@ -402,7 +472,7 @@ function useViewportBreakpoint() {
|
|
|
402
472
|
}
|
|
403
473
|
|
|
404
474
|
// src/front/hooks/useReducedMotion.ts
|
|
405
|
-
import { useEffect as
|
|
475
|
+
import { useEffect as useEffect6, useState as useState5 } from "react";
|
|
406
476
|
var QUERY = "(prefers-reduced-motion: reduce)";
|
|
407
477
|
function prefersReducedMotion() {
|
|
408
478
|
if (typeof window === "undefined") return false;
|
|
@@ -410,8 +480,8 @@ function prefersReducedMotion() {
|
|
|
410
480
|
return window.matchMedia(QUERY).matches;
|
|
411
481
|
}
|
|
412
482
|
function useReducedMotion() {
|
|
413
|
-
const [reducedMotion, setReducedMotion] =
|
|
414
|
-
|
|
483
|
+
const [reducedMotion, setReducedMotion] = useState5(prefersReducedMotion);
|
|
484
|
+
useEffect6(() => {
|
|
415
485
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
416
486
|
const media = window.matchMedia(QUERY);
|
|
417
487
|
const update = (event) => {
|
|
@@ -431,10 +501,10 @@ function useReducedMotion() {
|
|
|
431
501
|
}
|
|
432
502
|
|
|
433
503
|
// src/front/hooks/useBlobUrl.ts
|
|
434
|
-
import { useEffect as
|
|
504
|
+
import { useEffect as useEffect7, useState as useState6 } from "react";
|
|
435
505
|
function useBlobUrl(blob) {
|
|
436
|
-
const [blobUrl, setBlobUrl] =
|
|
437
|
-
|
|
506
|
+
const [blobUrl, setBlobUrl] = useState6(null);
|
|
507
|
+
useEffect7(() => {
|
|
438
508
|
if (!blob) {
|
|
439
509
|
setBlobUrl(null);
|
|
440
510
|
return;
|
|
@@ -475,12 +545,12 @@ function useWorkspaceMembers(workspaceId) {
|
|
|
475
545
|
}
|
|
476
546
|
|
|
477
547
|
// src/front/WorkspaceAuthProvider.tsx
|
|
478
|
-
import { createContext as
|
|
548
|
+
import { createContext as createContext5, useContext as useContext5 } from "react";
|
|
479
549
|
import { useQuery as useQuery2, useQueryClient } from "@tanstack/react-query";
|
|
480
550
|
import { matchPath, useLocation, useParams } from "react-router-dom";
|
|
481
551
|
|
|
482
552
|
// src/front/auth/AuthProvider.tsx
|
|
483
|
-
import { createContext as
|
|
553
|
+
import { createContext as createContext4, useContext as useContext4, useCallback as useCallback2, useMemo as useMemo3 } from "react";
|
|
484
554
|
|
|
485
555
|
// src/front/auth/authClient.ts
|
|
486
556
|
import { createAuthClient } from "better-auth/react";
|
|
@@ -503,8 +573,8 @@ function getAuthClient(baseURL) {
|
|
|
503
573
|
}
|
|
504
574
|
|
|
505
575
|
// src/front/auth/AuthProvider.tsx
|
|
506
|
-
import { jsx as
|
|
507
|
-
var AuthContext =
|
|
576
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
577
|
+
var AuthContext = createContext4(null);
|
|
508
578
|
function toISOString(value) {
|
|
509
579
|
if (!value) return "";
|
|
510
580
|
if (value instanceof Date) return value.toISOString();
|
|
@@ -527,20 +597,20 @@ function AuthProvider({
|
|
|
527
597
|
queryClient,
|
|
528
598
|
navigate
|
|
529
599
|
}) {
|
|
530
|
-
const client =
|
|
600
|
+
const client = useMemo3(() => getAuthClient(baseURL), [baseURL]);
|
|
531
601
|
const signOut = useCallback2(async () => {
|
|
532
602
|
await client.signOut();
|
|
533
603
|
queryClient?.clear();
|
|
534
604
|
navigate?.(routes.signin);
|
|
535
605
|
}, [client, queryClient, navigate]);
|
|
536
|
-
const value =
|
|
606
|
+
const value = useMemo3(
|
|
537
607
|
() => ({ client, signOut }),
|
|
538
608
|
[client, signOut]
|
|
539
609
|
);
|
|
540
|
-
return /* @__PURE__ */
|
|
610
|
+
return /* @__PURE__ */ jsx5(AuthContext.Provider, { value, children });
|
|
541
611
|
}
|
|
542
612
|
function useAuthContext() {
|
|
543
|
-
const ctx =
|
|
613
|
+
const ctx = useContext4(AuthContext);
|
|
544
614
|
if (!ctx) throw new Error("useSession/signIn/signOut must be used within an AuthProvider");
|
|
545
615
|
return ctx;
|
|
546
616
|
}
|
|
@@ -606,8 +676,8 @@ function useSignOut() {
|
|
|
606
676
|
}
|
|
607
677
|
|
|
608
678
|
// src/front/WorkspaceAuthProvider.tsx
|
|
609
|
-
import { jsx as
|
|
610
|
-
var WorkspaceContext =
|
|
679
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
680
|
+
var WorkspaceContext = createContext5({
|
|
611
681
|
workspace: null,
|
|
612
682
|
role: null,
|
|
613
683
|
routeStatus: { status: "idle", workspaceId: null }
|
|
@@ -699,22 +769,22 @@ function WorkspaceAuthProvider({
|
|
|
699
769
|
if (workspace?.id === routeWorkspaceId) return { status: "matched", workspaceId: routeWorkspaceId, workspace };
|
|
700
770
|
return { status: "mismatched", workspaceId: routeWorkspaceId, currentWorkspaceId: workspace?.id ?? null };
|
|
701
771
|
})();
|
|
702
|
-
return /* @__PURE__ */
|
|
772
|
+
return /* @__PURE__ */ jsx6(WorkspaceContext.Provider, { value: { workspace, role, routeStatus }, children });
|
|
703
773
|
}
|
|
704
774
|
function useCurrentWorkspace() {
|
|
705
|
-
return
|
|
775
|
+
return useContext5(WorkspaceContext).workspace;
|
|
706
776
|
}
|
|
707
777
|
function useWorkspaceRole() {
|
|
708
|
-
return
|
|
778
|
+
return useContext5(WorkspaceContext).role;
|
|
709
779
|
}
|
|
710
780
|
function useWorkspaceRouteStatus() {
|
|
711
|
-
return
|
|
781
|
+
return useContext5(WorkspaceContext).routeStatus;
|
|
712
782
|
}
|
|
713
783
|
|
|
714
784
|
// src/front/auth/UserIdentityProvider.tsx
|
|
715
|
-
import { createContext as
|
|
716
|
-
import { jsx as
|
|
717
|
-
var UserContext =
|
|
785
|
+
import { createContext as createContext6, useContext as useContext6, useEffect as useEffect8, useState as useState7, useRef as useRef3 } from "react";
|
|
786
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
787
|
+
var UserContext = createContext6(null);
|
|
718
788
|
var STALE_MS = 6e4;
|
|
719
789
|
function UserIdentityProvider({ children }) {
|
|
720
790
|
const { data: session } = useSession();
|
|
@@ -723,10 +793,10 @@ function UserIdentityProvider({ children }) {
|
|
|
723
793
|
session?.user,
|
|
724
794
|
isRuntimeEmailVerificationEnabled(config)
|
|
725
795
|
);
|
|
726
|
-
const [identity, setIdentity] =
|
|
796
|
+
const [identity, setIdentity] = useState7(null);
|
|
727
797
|
const fetchedForRef = useRef3(null);
|
|
728
798
|
const lastFetchRef = useRef3(0);
|
|
729
|
-
|
|
799
|
+
useEffect8(() => {
|
|
730
800
|
if (!session?.user || !canFetchIdentity) {
|
|
731
801
|
setIdentity(null);
|
|
732
802
|
fetchedForRef.current = null;
|
|
@@ -751,23 +821,23 @@ function UserIdentityProvider({ children }) {
|
|
|
751
821
|
cancelled = true;
|
|
752
822
|
};
|
|
753
823
|
}, [canFetchIdentity, session?.user?.id]);
|
|
754
|
-
return /* @__PURE__ */
|
|
824
|
+
return /* @__PURE__ */ jsx7(UserContext.Provider, { value: identity, children });
|
|
755
825
|
}
|
|
756
826
|
function useUser() {
|
|
757
|
-
return
|
|
827
|
+
return useContext6(UserContext);
|
|
758
828
|
}
|
|
759
829
|
|
|
760
830
|
// src/front/auth/GoogleAuthButton.tsx
|
|
761
|
-
import { useState as
|
|
831
|
+
import { useState as useState8 } from "react";
|
|
762
832
|
import { Button as Button2 } from "@hachej/boring-ui-kit";
|
|
763
|
-
import { jsx as
|
|
833
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
764
834
|
function GoogleAuthButton({
|
|
765
835
|
callbackURL = "/",
|
|
766
836
|
errorCallbackURL = callbackURL,
|
|
767
837
|
onError
|
|
768
838
|
}) {
|
|
769
839
|
const signIn = useSignIn();
|
|
770
|
-
const [isSubmitting, setIsSubmitting] =
|
|
840
|
+
const [isSubmitting, setIsSubmitting] = useState8(false);
|
|
771
841
|
async function handleClick() {
|
|
772
842
|
setIsSubmitting(true);
|
|
773
843
|
try {
|
|
@@ -781,7 +851,7 @@ function GoogleAuthButton({
|
|
|
781
851
|
setIsSubmitting(false);
|
|
782
852
|
}
|
|
783
853
|
}
|
|
784
|
-
return /* @__PURE__ */
|
|
854
|
+
return /* @__PURE__ */ jsx8(
|
|
785
855
|
Button2,
|
|
786
856
|
{
|
|
787
857
|
type: "button",
|
|
@@ -795,12 +865,12 @@ function GoogleAuthButton({
|
|
|
795
865
|
}
|
|
796
866
|
|
|
797
867
|
// src/front/auth/SignInPage.tsx
|
|
798
|
-
import { useState as
|
|
868
|
+
import { useState as useState9 } from "react";
|
|
799
869
|
import { useForm } from "react-hook-form";
|
|
800
870
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
801
871
|
import { z } from "zod";
|
|
802
872
|
import { Button as Button3, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Input, Label } from "@hachej/boring-ui-kit";
|
|
803
|
-
import { Fragment, jsx as
|
|
873
|
+
import { Fragment, jsx as jsx9, jsxs } from "react/jsx-runtime";
|
|
804
874
|
var signInSchema = z.object({
|
|
805
875
|
email: z.string().email("Please enter a valid email"),
|
|
806
876
|
password: z.string().min(1, "Password is required")
|
|
@@ -814,9 +884,9 @@ function readGoogleAuthError() {
|
|
|
814
884
|
function SignInPage() {
|
|
815
885
|
const signIn = useSignIn();
|
|
816
886
|
const config = useOptionalConfig();
|
|
817
|
-
const [serverError, setServerError] =
|
|
818
|
-
const [oauthError, setOauthError] =
|
|
819
|
-
const [isSubmitting, setIsSubmitting] =
|
|
887
|
+
const [serverError, setServerError] = useState9(null);
|
|
888
|
+
const [oauthError, setOauthError] = useState9(() => readGoogleAuthError());
|
|
889
|
+
const [isSubmitting, setIsSubmitting] = useState9(false);
|
|
820
890
|
const showGoogleAuth = config?.features.googleOauth === true;
|
|
821
891
|
const {
|
|
822
892
|
register,
|
|
@@ -843,15 +913,15 @@ function SignInPage() {
|
|
|
843
913
|
setIsSubmitting(false);
|
|
844
914
|
}
|
|
845
915
|
}
|
|
846
|
-
return /* @__PURE__ */
|
|
916
|
+
return /* @__PURE__ */ jsx9("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-sm", children: [
|
|
847
917
|
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
848
|
-
/* @__PURE__ */
|
|
849
|
-
/* @__PURE__ */
|
|
918
|
+
/* @__PURE__ */ jsx9(CardTitle, { children: "Sign in" }),
|
|
919
|
+
/* @__PURE__ */ jsx9(CardDescription, { children: "Enter your credentials to continue" })
|
|
850
920
|
] }),
|
|
851
921
|
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
|
|
852
922
|
/* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
|
|
853
923
|
showGoogleAuth && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
854
|
-
/* @__PURE__ */
|
|
924
|
+
/* @__PURE__ */ jsx9(
|
|
855
925
|
GoogleAuthButton,
|
|
856
926
|
{
|
|
857
927
|
errorCallbackURL: routes.signin,
|
|
@@ -859,14 +929,14 @@ function SignInPage() {
|
|
|
859
929
|
}
|
|
860
930
|
),
|
|
861
931
|
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
862
|
-
/* @__PURE__ */
|
|
863
|
-
/* @__PURE__ */
|
|
932
|
+
/* @__PURE__ */ jsx9("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx9("span", { className: "w-full border-t" }) }),
|
|
933
|
+
/* @__PURE__ */ jsx9("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx9("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with email" }) })
|
|
864
934
|
] })
|
|
865
935
|
] }),
|
|
866
|
-
(serverError ?? oauthError) && /* @__PURE__ */
|
|
936
|
+
(serverError ?? oauthError) && /* @__PURE__ */ jsx9("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
|
|
867
937
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
868
|
-
/* @__PURE__ */
|
|
869
|
-
/* @__PURE__ */
|
|
938
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "email", children: "Email" }),
|
|
939
|
+
/* @__PURE__ */ jsx9(
|
|
870
940
|
Input,
|
|
871
941
|
{
|
|
872
942
|
id: "email",
|
|
@@ -876,11 +946,11 @@ function SignInPage() {
|
|
|
876
946
|
...register("email")
|
|
877
947
|
}
|
|
878
948
|
),
|
|
879
|
-
errors.email && /* @__PURE__ */
|
|
949
|
+
errors.email && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.email.message })
|
|
880
950
|
] }),
|
|
881
951
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
882
|
-
/* @__PURE__ */
|
|
883
|
-
/* @__PURE__ */
|
|
952
|
+
/* @__PURE__ */ jsx9(Label, { htmlFor: "password", children: "Password" }),
|
|
953
|
+
/* @__PURE__ */ jsx9(
|
|
884
954
|
Input,
|
|
885
955
|
{
|
|
886
956
|
id: "password",
|
|
@@ -889,14 +959,14 @@ function SignInPage() {
|
|
|
889
959
|
...register("password")
|
|
890
960
|
}
|
|
891
961
|
),
|
|
892
|
-
errors.password && /* @__PURE__ */
|
|
962
|
+
errors.password && /* @__PURE__ */ jsx9("p", { className: "text-sm text-destructive", children: errors.password.message })
|
|
893
963
|
] })
|
|
894
964
|
] }),
|
|
895
965
|
/* @__PURE__ */ jsxs(CardFooter, { className: "flex flex-col gap-4", children: [
|
|
896
|
-
/* @__PURE__ */
|
|
966
|
+
/* @__PURE__ */ jsx9(Button3, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Signing in\u2026" : "Sign in" }),
|
|
897
967
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm w-full", children: [
|
|
898
|
-
/* @__PURE__ */
|
|
899
|
-
/* @__PURE__ */
|
|
968
|
+
/* @__PURE__ */ jsx9("a", { href: routes.forgotPassword, className: "text-muted-foreground hover:underline", children: "Forgot password?" }),
|
|
969
|
+
/* @__PURE__ */ jsx9("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Sign up" })
|
|
900
970
|
] })
|
|
901
971
|
] })
|
|
902
972
|
] })
|
|
@@ -904,13 +974,13 @@ function SignInPage() {
|
|
|
904
974
|
}
|
|
905
975
|
|
|
906
976
|
// src/front/auth/SignUpPage.tsx
|
|
907
|
-
import { useState as
|
|
977
|
+
import { useState as useState10 } from "react";
|
|
908
978
|
import { useForm as useForm2 } from "react-hook-form";
|
|
909
979
|
import { useNavigate } from "react-router-dom";
|
|
910
980
|
import { zodResolver as zodResolver2 } from "@hookform/resolvers/zod";
|
|
911
981
|
import { z as z2 } from "zod";
|
|
912
982
|
import { Button as Button4, Card as Card2, CardContent as CardContent2, CardDescription as CardDescription2, CardFooter as CardFooter2, CardHeader as CardHeader2, CardTitle as CardTitle2, Input as Input2, Label as Label2 } from "@hachej/boring-ui-kit";
|
|
913
|
-
import { Fragment as Fragment2, jsx as
|
|
983
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
914
984
|
var signUpSchema = z2.object({
|
|
915
985
|
name: z2.string().min(1, "Name is required"),
|
|
916
986
|
email: z2.string().email("Please enter a valid email"),
|
|
@@ -926,10 +996,10 @@ function SignUpPage() {
|
|
|
926
996
|
const signUp = useSignUp();
|
|
927
997
|
const navigate = useNavigate();
|
|
928
998
|
const config = useOptionalConfig();
|
|
929
|
-
const [serverError, setServerError] =
|
|
930
|
-
const [oauthError, setOauthError] =
|
|
931
|
-
const [isSubmitting, setIsSubmitting] =
|
|
932
|
-
const [success, setSuccess] =
|
|
999
|
+
const [serverError, setServerError] = useState10(null);
|
|
1000
|
+
const [oauthError, setOauthError] = useState10(() => readGoogleAuthError2());
|
|
1001
|
+
const [isSubmitting, setIsSubmitting] = useState10(false);
|
|
1002
|
+
const [success, setSuccess] = useState10(false);
|
|
933
1003
|
const inviteToken = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("invite_token") : null;
|
|
934
1004
|
const showGoogleAuth = config?.features.googleOauth === true && !inviteToken;
|
|
935
1005
|
const {
|
|
@@ -963,23 +1033,23 @@ function SignUpPage() {
|
|
|
963
1033
|
}
|
|
964
1034
|
}
|
|
965
1035
|
if (success) {
|
|
966
|
-
return /* @__PURE__ */
|
|
1036
|
+
return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
|
|
967
1037
|
/* @__PURE__ */ jsxs2(CardHeader2, { children: [
|
|
968
|
-
/* @__PURE__ */
|
|
969
|
-
/* @__PURE__ */
|
|
1038
|
+
/* @__PURE__ */ jsx10(CardTitle2, { children: "Check your email" }),
|
|
1039
|
+
/* @__PURE__ */ jsx10(CardDescription2, { children: "We sent a verification link to your email address. Please check your inbox to continue." })
|
|
970
1040
|
] }),
|
|
971
|
-
/* @__PURE__ */
|
|
1041
|
+
/* @__PURE__ */ jsx10(CardFooter2, { children: /* @__PURE__ */ jsx10("a", { href: routes.signin, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
|
|
972
1042
|
] }) });
|
|
973
1043
|
}
|
|
974
|
-
return /* @__PURE__ */
|
|
1044
|
+
return /* @__PURE__ */ jsx10("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs2(Card2, { className: "w-full max-w-sm", children: [
|
|
975
1045
|
/* @__PURE__ */ jsxs2(CardHeader2, { children: [
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
/* @__PURE__ */
|
|
1046
|
+
/* @__PURE__ */ jsx10(CardTitle2, { children: "Create an account" }),
|
|
1047
|
+
/* @__PURE__ */ jsx10(CardDescription2, { children: "Enter your details to get started" })
|
|
978
1048
|
] }),
|
|
979
1049
|
/* @__PURE__ */ jsxs2("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
|
|
980
1050
|
/* @__PURE__ */ jsxs2(CardContent2, { className: "space-y-4", children: [
|
|
981
1051
|
showGoogleAuth && /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
982
|
-
/* @__PURE__ */
|
|
1052
|
+
/* @__PURE__ */ jsx10(
|
|
983
1053
|
GoogleAuthButton,
|
|
984
1054
|
{
|
|
985
1055
|
errorCallbackURL: routes.signup,
|
|
@@ -987,14 +1057,14 @@ function SignUpPage() {
|
|
|
987
1057
|
}
|
|
988
1058
|
),
|
|
989
1059
|
/* @__PURE__ */ jsxs2("div", { className: "relative", children: [
|
|
990
|
-
/* @__PURE__ */
|
|
991
|
-
/* @__PURE__ */
|
|
1060
|
+
/* @__PURE__ */ jsx10("div", { className: "absolute inset-0 flex items-center", children: /* @__PURE__ */ jsx10("span", { className: "w-full border-t" }) }),
|
|
1061
|
+
/* @__PURE__ */ jsx10("div", { className: "relative flex justify-center text-xs uppercase", children: /* @__PURE__ */ jsx10("span", { className: "bg-card px-2 text-muted-foreground", children: "Or continue with email" }) })
|
|
992
1062
|
] })
|
|
993
1063
|
] }),
|
|
994
|
-
(serverError ?? oauthError) && /* @__PURE__ */
|
|
1064
|
+
(serverError ?? oauthError) && /* @__PURE__ */ jsx10("div", { role: "alert", className: "text-sm text-destructive", children: serverError ?? oauthError }),
|
|
995
1065
|
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
996
|
-
/* @__PURE__ */
|
|
997
|
-
/* @__PURE__ */
|
|
1066
|
+
/* @__PURE__ */ jsx10(Label2, { htmlFor: "name", children: "Name" }),
|
|
1067
|
+
/* @__PURE__ */ jsx10(
|
|
998
1068
|
Input2,
|
|
999
1069
|
{
|
|
1000
1070
|
id: "name",
|
|
@@ -1004,11 +1074,11 @@ function SignUpPage() {
|
|
|
1004
1074
|
...register("name")
|
|
1005
1075
|
}
|
|
1006
1076
|
),
|
|
1007
|
-
errors.name && /* @__PURE__ */
|
|
1077
|
+
errors.name && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.name.message })
|
|
1008
1078
|
] }),
|
|
1009
1079
|
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
1010
|
-
/* @__PURE__ */
|
|
1011
|
-
/* @__PURE__ */
|
|
1080
|
+
/* @__PURE__ */ jsx10(Label2, { htmlFor: "email", children: "Email" }),
|
|
1081
|
+
/* @__PURE__ */ jsx10(
|
|
1012
1082
|
Input2,
|
|
1013
1083
|
{
|
|
1014
1084
|
id: "email",
|
|
@@ -1018,11 +1088,11 @@ function SignUpPage() {
|
|
|
1018
1088
|
...register("email")
|
|
1019
1089
|
}
|
|
1020
1090
|
),
|
|
1021
|
-
errors.email && /* @__PURE__ */
|
|
1091
|
+
errors.email && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.email.message })
|
|
1022
1092
|
] }),
|
|
1023
1093
|
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
1024
|
-
/* @__PURE__ */
|
|
1025
|
-
/* @__PURE__ */
|
|
1094
|
+
/* @__PURE__ */ jsx10(Label2, { htmlFor: "password", children: "Password" }),
|
|
1095
|
+
/* @__PURE__ */ jsx10(
|
|
1026
1096
|
Input2,
|
|
1027
1097
|
{
|
|
1028
1098
|
id: "password",
|
|
@@ -1032,14 +1102,14 @@ function SignUpPage() {
|
|
|
1032
1102
|
...register("password")
|
|
1033
1103
|
}
|
|
1034
1104
|
),
|
|
1035
|
-
errors.password && /* @__PURE__ */
|
|
1105
|
+
errors.password && /* @__PURE__ */ jsx10("p", { className: "text-sm text-destructive", children: errors.password.message })
|
|
1036
1106
|
] })
|
|
1037
1107
|
] }),
|
|
1038
1108
|
/* @__PURE__ */ jsxs2(CardFooter2, { className: "flex flex-col gap-4", children: [
|
|
1039
|
-
/* @__PURE__ */
|
|
1109
|
+
/* @__PURE__ */ jsx10(Button4, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Creating account\u2026" : "Sign up" }),
|
|
1040
1110
|
/* @__PURE__ */ jsxs2("div", { className: "text-sm text-center", children: [
|
|
1041
|
-
/* @__PURE__ */
|
|
1042
|
-
/* @__PURE__ */
|
|
1111
|
+
/* @__PURE__ */ jsx10("span", { className: "text-muted-foreground", children: "Already have an account? " }),
|
|
1112
|
+
/* @__PURE__ */ jsx10("a", { href: routes.signin, className: "hover:underline", children: "Sign in" })
|
|
1043
1113
|
] })
|
|
1044
1114
|
] })
|
|
1045
1115
|
] })
|
|
@@ -1047,19 +1117,19 @@ function SignUpPage() {
|
|
|
1047
1117
|
}
|
|
1048
1118
|
|
|
1049
1119
|
// src/front/auth/ForgotPasswordPage.tsx
|
|
1050
|
-
import { useState as
|
|
1120
|
+
import { useState as useState11 } from "react";
|
|
1051
1121
|
import { useForm as useForm3 } from "react-hook-form";
|
|
1052
1122
|
import { zodResolver as zodResolver3 } from "@hookform/resolvers/zod";
|
|
1053
1123
|
import { z as z3 } from "zod";
|
|
1054
1124
|
import { Button as Button5, Card as Card3, CardContent as CardContent3, CardDescription as CardDescription3, CardFooter as CardFooter3, CardHeader as CardHeader3, CardTitle as CardTitle3, Input as Input3, Label as Label3 } from "@hachej/boring-ui-kit";
|
|
1055
|
-
import { jsx as
|
|
1125
|
+
import { jsx as jsx11, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1056
1126
|
var forgotSchema = z3.object({
|
|
1057
1127
|
email: z3.string().email("Please enter a valid email")
|
|
1058
1128
|
});
|
|
1059
1129
|
function ForgotPasswordPage() {
|
|
1060
1130
|
const forgetPassword = useForgetPassword();
|
|
1061
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1062
|
-
const [submitted, setSubmitted] =
|
|
1131
|
+
const [isSubmitting, setIsSubmitting] = useState11(false);
|
|
1132
|
+
const [submitted, setSubmitted] = useState11(false);
|
|
1063
1133
|
const redirect = typeof window === "undefined" ? null : new URLSearchParams(window.location.search).get("redirect");
|
|
1064
1134
|
const signinHref = redirect ? `${routes.signin}?redirect=${encodeURIComponent(redirect)}` : routes.signin;
|
|
1065
1135
|
const {
|
|
@@ -1080,23 +1150,23 @@ function ForgotPasswordPage() {
|
|
|
1080
1150
|
}
|
|
1081
1151
|
}
|
|
1082
1152
|
if (submitted) {
|
|
1083
|
-
return /* @__PURE__ */
|
|
1153
|
+
return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
|
|
1084
1154
|
/* @__PURE__ */ jsxs3(CardHeader3, { children: [
|
|
1085
|
-
/* @__PURE__ */
|
|
1086
|
-
/* @__PURE__ */
|
|
1155
|
+
/* @__PURE__ */ jsx11(CardTitle3, { children: "Check your inbox" }),
|
|
1156
|
+
/* @__PURE__ */ jsx11(CardDescription3, { children: "If an account exists with that email, we sent a password reset link. Check your inbox and follow the instructions." })
|
|
1087
1157
|
] }),
|
|
1088
|
-
/* @__PURE__ */
|
|
1158
|
+
/* @__PURE__ */ jsx11(CardFooter3, { children: /* @__PURE__ */ jsx11("a", { href: signinHref, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" }) })
|
|
1089
1159
|
] }) });
|
|
1090
1160
|
}
|
|
1091
|
-
return /* @__PURE__ */
|
|
1161
|
+
return /* @__PURE__ */ jsx11("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs3(Card3, { className: "w-full max-w-sm", children: [
|
|
1092
1162
|
/* @__PURE__ */ jsxs3(CardHeader3, { children: [
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1163
|
+
/* @__PURE__ */ jsx11(CardTitle3, { children: "Forgot password" }),
|
|
1164
|
+
/* @__PURE__ */ jsx11(CardDescription3, { children: "Enter your email and we'll send you a reset link" })
|
|
1095
1165
|
] }),
|
|
1096
1166
|
/* @__PURE__ */ jsxs3("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
|
|
1097
|
-
/* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1099
|
-
/* @__PURE__ */
|
|
1167
|
+
/* @__PURE__ */ jsx11(CardContent3, { className: "space-y-4", children: /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
|
|
1168
|
+
/* @__PURE__ */ jsx11(Label3, { htmlFor: "email", children: "Email" }),
|
|
1169
|
+
/* @__PURE__ */ jsx11(
|
|
1100
1170
|
Input3,
|
|
1101
1171
|
{
|
|
1102
1172
|
id: "email",
|
|
@@ -1106,23 +1176,23 @@ function ForgotPasswordPage() {
|
|
|
1106
1176
|
...register("email")
|
|
1107
1177
|
}
|
|
1108
1178
|
),
|
|
1109
|
-
errors.email && /* @__PURE__ */
|
|
1179
|
+
errors.email && /* @__PURE__ */ jsx11("p", { className: "text-sm text-destructive", children: errors.email.message })
|
|
1110
1180
|
] }) }),
|
|
1111
1181
|
/* @__PURE__ */ jsxs3(CardFooter3, { className: "flex flex-col gap-4", children: [
|
|
1112
|
-
/* @__PURE__ */
|
|
1113
|
-
/* @__PURE__ */
|
|
1182
|
+
/* @__PURE__ */ jsx11(Button5, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Sending\u2026" : "Send reset link" }),
|
|
1183
|
+
/* @__PURE__ */ jsx11("a", { href: signinHref, className: "text-sm text-muted-foreground hover:underline", children: "Back to sign in" })
|
|
1114
1184
|
] })
|
|
1115
1185
|
] })
|
|
1116
1186
|
] }) });
|
|
1117
1187
|
}
|
|
1118
1188
|
|
|
1119
1189
|
// src/front/auth/ResetPasswordPage.tsx
|
|
1120
|
-
import { useState as
|
|
1190
|
+
import { useState as useState12 } from "react";
|
|
1121
1191
|
import { useForm as useForm4 } from "react-hook-form";
|
|
1122
1192
|
import { zodResolver as zodResolver4 } from "@hookform/resolvers/zod";
|
|
1123
1193
|
import { z as z4 } from "zod";
|
|
1124
1194
|
import { Button as Button6, Card as Card4, CardContent as CardContent4, CardDescription as CardDescription4, CardFooter as CardFooter4, CardHeader as CardHeader4, CardTitle as CardTitle4, Input as Input4, Label as Label4 } from "@hachej/boring-ui-kit";
|
|
1125
|
-
import { jsx as
|
|
1195
|
+
import { jsx as jsx12, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1126
1196
|
var resetSchema = z4.object({
|
|
1127
1197
|
password: z4.string().min(8, "Password must be at least 8 characters"),
|
|
1128
1198
|
confirmPassword: z4.string()
|
|
@@ -1132,9 +1202,9 @@ var resetSchema = z4.object({
|
|
|
1132
1202
|
});
|
|
1133
1203
|
function ResetPasswordPage() {
|
|
1134
1204
|
const resetPassword = useResetPassword();
|
|
1135
|
-
const [serverError, setServerError] =
|
|
1136
|
-
const [isSubmitting, setIsSubmitting] =
|
|
1137
|
-
const [expired, setExpired] =
|
|
1205
|
+
const [serverError, setServerError] = useState12(null);
|
|
1206
|
+
const [isSubmitting, setIsSubmitting] = useState12(false);
|
|
1207
|
+
const [expired, setExpired] = useState12(false);
|
|
1138
1208
|
const token = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null;
|
|
1139
1209
|
const {
|
|
1140
1210
|
register,
|
|
@@ -1172,25 +1242,25 @@ function ResetPasswordPage() {
|
|
|
1172
1242
|
}
|
|
1173
1243
|
}
|
|
1174
1244
|
if (!token || expired) {
|
|
1175
|
-
return /* @__PURE__ */
|
|
1245
|
+
return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
|
|
1176
1246
|
/* @__PURE__ */ jsxs4(CardHeader4, { children: [
|
|
1177
|
-
/* @__PURE__ */
|
|
1178
|
-
/* @__PURE__ */
|
|
1247
|
+
/* @__PURE__ */ jsx12(CardTitle4, { children: "Link expired" }),
|
|
1248
|
+
/* @__PURE__ */ jsx12(CardDescription4, { children: "This reset link is no longer valid. Please request a new one." })
|
|
1179
1249
|
] }),
|
|
1180
|
-
/* @__PURE__ */
|
|
1250
|
+
/* @__PURE__ */ jsx12(CardFooter4, { children: /* @__PURE__ */ jsx12("a", { href: routes.forgotPassword, children: /* @__PURE__ */ jsx12(Button6, { variant: "outline", children: "Request new link" }) }) })
|
|
1181
1251
|
] }) });
|
|
1182
1252
|
}
|
|
1183
|
-
return /* @__PURE__ */
|
|
1253
|
+
return /* @__PURE__ */ jsx12("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs4(Card4, { className: "w-full max-w-sm", children: [
|
|
1184
1254
|
/* @__PURE__ */ jsxs4(CardHeader4, { children: [
|
|
1185
|
-
/* @__PURE__ */
|
|
1186
|
-
/* @__PURE__ */
|
|
1255
|
+
/* @__PURE__ */ jsx12(CardTitle4, { children: "Reset password" }),
|
|
1256
|
+
/* @__PURE__ */ jsx12(CardDescription4, { children: "Enter your new password below" })
|
|
1187
1257
|
] }),
|
|
1188
1258
|
/* @__PURE__ */ jsxs4("form", { onSubmit: handleSubmit(onSubmit), noValidate: true, children: [
|
|
1189
1259
|
/* @__PURE__ */ jsxs4(CardContent4, { className: "space-y-4", children: [
|
|
1190
|
-
serverError && /* @__PURE__ */
|
|
1260
|
+
serverError && /* @__PURE__ */ jsx12("div", { role: "alert", className: "text-sm text-destructive", children: serverError }),
|
|
1191
1261
|
/* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
1192
|
-
/* @__PURE__ */
|
|
1193
|
-
/* @__PURE__ */
|
|
1262
|
+
/* @__PURE__ */ jsx12(Label4, { htmlFor: "password", children: "New password" }),
|
|
1263
|
+
/* @__PURE__ */ jsx12(
|
|
1194
1264
|
Input4,
|
|
1195
1265
|
{
|
|
1196
1266
|
id: "password",
|
|
@@ -1200,11 +1270,11 @@ function ResetPasswordPage() {
|
|
|
1200
1270
|
...register("password")
|
|
1201
1271
|
}
|
|
1202
1272
|
),
|
|
1203
|
-
errors.password && /* @__PURE__ */
|
|
1273
|
+
errors.password && /* @__PURE__ */ jsx12("p", { className: "text-sm text-destructive", children: errors.password.message })
|
|
1204
1274
|
] }),
|
|
1205
1275
|
/* @__PURE__ */ jsxs4("div", { className: "space-y-2", children: [
|
|
1206
|
-
/* @__PURE__ */
|
|
1207
|
-
/* @__PURE__ */
|
|
1276
|
+
/* @__PURE__ */ jsx12(Label4, { htmlFor: "confirmPassword", children: "Confirm password" }),
|
|
1277
|
+
/* @__PURE__ */ jsx12(
|
|
1208
1278
|
Input4,
|
|
1209
1279
|
{
|
|
1210
1280
|
id: "confirmPassword",
|
|
@@ -1213,18 +1283,18 @@ function ResetPasswordPage() {
|
|
|
1213
1283
|
...register("confirmPassword")
|
|
1214
1284
|
}
|
|
1215
1285
|
),
|
|
1216
|
-
errors.confirmPassword && /* @__PURE__ */
|
|
1286
|
+
errors.confirmPassword && /* @__PURE__ */ jsx12("p", { className: "text-sm text-destructive", children: errors.confirmPassword.message })
|
|
1217
1287
|
] })
|
|
1218
1288
|
] }),
|
|
1219
|
-
/* @__PURE__ */
|
|
1289
|
+
/* @__PURE__ */ jsx12(CardFooter4, { children: /* @__PURE__ */ jsx12(Button6, { type: "submit", className: "w-full", disabled: isSubmitting, children: isSubmitting ? "Resetting\u2026" : "Reset password" }) })
|
|
1220
1290
|
] })
|
|
1221
1291
|
] }) });
|
|
1222
1292
|
}
|
|
1223
1293
|
|
|
1224
1294
|
// src/front/auth/VerifyEmailPage.tsx
|
|
1225
|
-
import { useCallback as useCallback3, useEffect as
|
|
1295
|
+
import { useCallback as useCallback3, useEffect as useEffect9, useRef as useRef4, useState as useState13 } from "react";
|
|
1226
1296
|
import { Button as Button7, Card as Card5, CardContent as CardContent5, CardDescription as CardDescription5, CardFooter as CardFooter5, CardHeader as CardHeader5, CardTitle as CardTitle5, Input as Input5, Label as Label5 } from "@hachej/boring-ui-kit";
|
|
1227
|
-
import { jsx as
|
|
1297
|
+
import { jsx as jsx13, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1228
1298
|
function getCookie(name) {
|
|
1229
1299
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
1230
1300
|
return match ? decodeURIComponent(match[1]) : null;
|
|
@@ -1243,22 +1313,22 @@ function VerifyEmailPage() {
|
|
|
1243
1313
|
const sendVerificationEmail = useSendVerificationEmail();
|
|
1244
1314
|
const signOut = useSignOut();
|
|
1245
1315
|
const token = typeof window !== "undefined" ? new URLSearchParams(window.location.search).get("token") : null;
|
|
1246
|
-
const [status, setStatus] =
|
|
1247
|
-
const [inviteWarning, setInviteWarning] =
|
|
1248
|
-
const [cooldown, setCooldown] =
|
|
1249
|
-
const [resendEmail, setResendEmail] =
|
|
1250
|
-
const [resendSent, setResendSent] =
|
|
1251
|
-
const [isSigningOut, setIsSigningOut] =
|
|
1316
|
+
const [status, setStatus] = useState13(token ? "verifying" : "no-token");
|
|
1317
|
+
const [inviteWarning, setInviteWarning] = useState13(null);
|
|
1318
|
+
const [cooldown, setCooldown] = useState13(0);
|
|
1319
|
+
const [resendEmail, setResendEmail] = useState13("");
|
|
1320
|
+
const [resendSent, setResendSent] = useState13(false);
|
|
1321
|
+
const [isSigningOut, setIsSigningOut] = useState13(false);
|
|
1252
1322
|
const verifiedRef = useRef4(false);
|
|
1253
1323
|
const sessionEmail = session.data?.user?.email ?? null;
|
|
1254
|
-
|
|
1324
|
+
useEffect9(() => {
|
|
1255
1325
|
const cookie = getCookie("boring_invite_failed");
|
|
1256
1326
|
if (cookie) {
|
|
1257
1327
|
setInviteWarning(cookie || "Your invite link was invalid; you\u2019re signed in.");
|
|
1258
1328
|
deleteCookie("boring_invite_failed");
|
|
1259
1329
|
}
|
|
1260
1330
|
}, []);
|
|
1261
|
-
|
|
1331
|
+
useEffect9(() => {
|
|
1262
1332
|
if (!token || verifiedRef.current) return;
|
|
1263
1333
|
verifiedRef.current = true;
|
|
1264
1334
|
(async () => {
|
|
@@ -1280,7 +1350,7 @@ function VerifyEmailPage() {
|
|
|
1280
1350
|
}
|
|
1281
1351
|
})();
|
|
1282
1352
|
}, [token, verifyEmail]);
|
|
1283
|
-
|
|
1353
|
+
useEffect9(() => {
|
|
1284
1354
|
if (cooldown <= 0) return;
|
|
1285
1355
|
const id = setInterval(() => {
|
|
1286
1356
|
setCooldown((c) => {
|
|
@@ -1312,7 +1382,7 @@ function VerifyEmailPage() {
|
|
|
1312
1382
|
navigateToSignIn();
|
|
1313
1383
|
}
|
|
1314
1384
|
}, [isSigningOut, signOut]);
|
|
1315
|
-
const resendButton = /* @__PURE__ */
|
|
1385
|
+
const resendButton = /* @__PURE__ */ jsx13(
|
|
1316
1386
|
Button7,
|
|
1317
1387
|
{
|
|
1318
1388
|
variant: "outline",
|
|
@@ -1324,8 +1394,8 @@ function VerifyEmailPage() {
|
|
|
1324
1394
|
);
|
|
1325
1395
|
const resendSection = /* @__PURE__ */ jsxs5("div", { className: "space-y-3", children: [
|
|
1326
1396
|
!sessionEmail && /* @__PURE__ */ jsxs5("div", { className: "space-y-2", children: [
|
|
1327
|
-
/* @__PURE__ */
|
|
1328
|
-
/* @__PURE__ */
|
|
1397
|
+
/* @__PURE__ */ jsx13(Label5, { htmlFor: "resend-email", children: "Email" }),
|
|
1398
|
+
/* @__PURE__ */ jsx13(
|
|
1329
1399
|
Input5,
|
|
1330
1400
|
{
|
|
1331
1401
|
id: "resend-email",
|
|
@@ -1337,33 +1407,33 @@ function VerifyEmailPage() {
|
|
|
1337
1407
|
)
|
|
1338
1408
|
] }),
|
|
1339
1409
|
resendButton,
|
|
1340
|
-
resendSent && /* @__PURE__ */
|
|
1410
|
+
resendSent && /* @__PURE__ */ jsx13("p", { className: "text-sm text-muted-foreground text-center", children: "If an account exists with that email, we sent a new verification link." })
|
|
1341
1411
|
] });
|
|
1342
1412
|
if (status === "verifying") {
|
|
1343
|
-
return /* @__PURE__ */
|
|
1344
|
-
/* @__PURE__ */
|
|
1345
|
-
/* @__PURE__ */
|
|
1413
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx13(Card5, { className: "w-full max-w-sm", children: /* @__PURE__ */ jsxs5(CardHeader5, { children: [
|
|
1414
|
+
/* @__PURE__ */ jsx13(CardTitle5, { children: "Verifying your email" }),
|
|
1415
|
+
/* @__PURE__ */ jsx13(CardDescription5, { children: "Please wait\u2026" })
|
|
1346
1416
|
] }) }) });
|
|
1347
1417
|
}
|
|
1348
1418
|
if (status === "verified") {
|
|
1349
|
-
return /* @__PURE__ */
|
|
1350
|
-
inviteWarning && /* @__PURE__ */
|
|
1419
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
|
|
1420
|
+
inviteWarning && /* @__PURE__ */ jsx13("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx13("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
|
|
1351
1421
|
/* @__PURE__ */ jsxs5(CardHeader5, { children: [
|
|
1352
|
-
/* @__PURE__ */
|
|
1353
|
-
/* @__PURE__ */
|
|
1422
|
+
/* @__PURE__ */ jsx13(CardTitle5, { children: "Email verified" }),
|
|
1423
|
+
/* @__PURE__ */ jsx13(CardDescription5, { children: "Your email has been verified. You can now continue." })
|
|
1354
1424
|
] }),
|
|
1355
|
-
/* @__PURE__ */
|
|
1425
|
+
/* @__PURE__ */ jsx13(CardFooter5, { children: /* @__PURE__ */ jsx13("a", { href: "/", className: "w-full", children: /* @__PURE__ */ jsx13(Button7, { className: "w-full", children: "Continue" }) }) })
|
|
1356
1426
|
] }) });
|
|
1357
1427
|
}
|
|
1358
1428
|
if (status === "expired") {
|
|
1359
|
-
return /* @__PURE__ */
|
|
1360
|
-
inviteWarning && /* @__PURE__ */
|
|
1429
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
|
|
1430
|
+
inviteWarning && /* @__PURE__ */ jsx13("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx13("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
|
|
1361
1431
|
/* @__PURE__ */ jsxs5(CardHeader5, { children: [
|
|
1362
|
-
/* @__PURE__ */
|
|
1363
|
-
/* @__PURE__ */
|
|
1432
|
+
/* @__PURE__ */ jsx13(CardTitle5, { children: "Link expired" }),
|
|
1433
|
+
/* @__PURE__ */ jsx13(CardDescription5, { children: "This verification link is no longer valid. Request a new one below." })
|
|
1364
1434
|
] }),
|
|
1365
|
-
/* @__PURE__ */
|
|
1366
|
-
/* @__PURE__ */
|
|
1435
|
+
/* @__PURE__ */ jsx13(CardContent5, { children: resendSection }),
|
|
1436
|
+
/* @__PURE__ */ jsx13(CardFooter5, { children: /* @__PURE__ */ jsx13(
|
|
1367
1437
|
Button7,
|
|
1368
1438
|
{
|
|
1369
1439
|
type: "button",
|
|
@@ -1377,14 +1447,14 @@ function VerifyEmailPage() {
|
|
|
1377
1447
|
] }) });
|
|
1378
1448
|
}
|
|
1379
1449
|
const isWaitingForEmailClick = status === "no-token" && Boolean(sessionEmail);
|
|
1380
|
-
return /* @__PURE__ */
|
|
1381
|
-
inviteWarning && /* @__PURE__ */
|
|
1450
|
+
return /* @__PURE__ */ jsx13("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs5(Card5, { className: "w-full max-w-sm", children: [
|
|
1451
|
+
inviteWarning && /* @__PURE__ */ jsx13("div", { role: "status", className: "px-6 pt-4", children: /* @__PURE__ */ jsx13("div", { className: "rounded-md bg-muted px-3 py-2 text-sm text-muted-foreground", children: inviteWarning }) }),
|
|
1382
1452
|
/* @__PURE__ */ jsxs5(CardHeader5, { children: [
|
|
1383
|
-
/* @__PURE__ */
|
|
1384
|
-
/* @__PURE__ */
|
|
1453
|
+
/* @__PURE__ */ jsx13(CardTitle5, { children: isWaitingForEmailClick ? "Check your email" : "Invalid verification link" }),
|
|
1454
|
+
/* @__PURE__ */ jsx13(CardDescription5, { children: isWaitingForEmailClick ? "We sent a verification link to your email address. Please check your inbox to continue." : status === "no-token" ? "No verification token found. Check the link in your email." : "This verification link is invalid. Request a new one below." })
|
|
1385
1455
|
] }),
|
|
1386
|
-
/* @__PURE__ */
|
|
1387
|
-
/* @__PURE__ */
|
|
1456
|
+
/* @__PURE__ */ jsx13(CardContent5, { children: resendSection }),
|
|
1457
|
+
/* @__PURE__ */ jsx13(CardFooter5, { children: /* @__PURE__ */ jsx13(
|
|
1388
1458
|
Button7,
|
|
1389
1459
|
{
|
|
1390
1460
|
type: "button",
|
|
@@ -1399,7 +1469,7 @@ function VerifyEmailPage() {
|
|
|
1399
1469
|
}
|
|
1400
1470
|
|
|
1401
1471
|
// src/front/auth/UserSettingsPage.tsx
|
|
1402
|
-
import { useCallback as useCallback4, useState as
|
|
1472
|
+
import { useCallback as useCallback4, useState as useState14 } from "react";
|
|
1403
1473
|
import { useForm as useForm5 } from "react-hook-form";
|
|
1404
1474
|
import { zodResolver as zodResolver5 } from "@hookform/resolvers/zod";
|
|
1405
1475
|
import { z as z5 } from "zod";
|
|
@@ -1431,7 +1501,7 @@ import {
|
|
|
1431
1501
|
Trash2,
|
|
1432
1502
|
UserRound
|
|
1433
1503
|
} from "lucide-react";
|
|
1434
|
-
import { jsx as
|
|
1504
|
+
import { jsx as jsx14, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1435
1505
|
var changePasswordSchema = z5.object({
|
|
1436
1506
|
currentPassword: z5.string().min(1, "Current password is required"),
|
|
1437
1507
|
newPassword: z5.string().min(8, "Password must be at least 8 characters"),
|
|
@@ -1457,7 +1527,7 @@ function SettingsTopBar() {
|
|
|
1457
1527
|
const config = useOptionalConfig();
|
|
1458
1528
|
const appTitle = config?.appName ?? "Boring UI";
|
|
1459
1529
|
const appInitial = (appTitle.trim().charAt(0) || "B").toUpperCase();
|
|
1460
|
-
return /* @__PURE__ */
|
|
1530
|
+
return /* @__PURE__ */ jsx14(
|
|
1461
1531
|
"header",
|
|
1462
1532
|
{
|
|
1463
1533
|
className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
|
|
@@ -1470,7 +1540,7 @@ function SettingsTopBar() {
|
|
|
1470
1540
|
"aria-label": `${appTitle} home`,
|
|
1471
1541
|
className: "flex min-w-0 items-center gap-2.5 rounded-md outline-none transition-opacity hover:opacity-80 focus-visible:ring-2 focus-visible:ring-ring",
|
|
1472
1542
|
children: [
|
|
1473
|
-
/* @__PURE__ */
|
|
1543
|
+
/* @__PURE__ */ jsx14(
|
|
1474
1544
|
"div",
|
|
1475
1545
|
{
|
|
1476
1546
|
"aria-hidden": "true",
|
|
@@ -1478,12 +1548,12 @@ function SettingsTopBar() {
|
|
|
1478
1548
|
children: appInitial
|
|
1479
1549
|
}
|
|
1480
1550
|
),
|
|
1481
|
-
/* @__PURE__ */
|
|
1551
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle })
|
|
1482
1552
|
]
|
|
1483
1553
|
}
|
|
1484
1554
|
),
|
|
1485
|
-
/* @__PURE__ */
|
|
1486
|
-
/* @__PURE__ */
|
|
1555
|
+
/* @__PURE__ */ jsx14("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
1556
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate text-[13px] text-muted-foreground", children: "Account settings" })
|
|
1487
1557
|
] })
|
|
1488
1558
|
}
|
|
1489
1559
|
);
|
|
@@ -1495,7 +1565,7 @@ function SettingsPageHeader({
|
|
|
1495
1565
|
}) {
|
|
1496
1566
|
return /* @__PURE__ */ jsxs6("header", { className: "boring-settings-page-header", children: [
|
|
1497
1567
|
/* @__PURE__ */ jsxs6("div", { className: "boring-settings-context", children: [
|
|
1498
|
-
/* @__PURE__ */
|
|
1568
|
+
/* @__PURE__ */ jsx14("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: initials }),
|
|
1499
1569
|
/* @__PURE__ */ jsxs6("div", { className: "min-w-0", children: [
|
|
1500
1570
|
/* @__PURE__ */ jsxs6("p", { className: "truncate text-[13px] font-medium text-foreground", children: [
|
|
1501
1571
|
"Signed in as ",
|
|
@@ -1508,9 +1578,9 @@ function SettingsPageHeader({
|
|
|
1508
1578
|
] })
|
|
1509
1579
|
] }),
|
|
1510
1580
|
/* @__PURE__ */ jsxs6("div", { className: "max-w-2xl", children: [
|
|
1511
|
-
/* @__PURE__ */
|
|
1512
|
-
/* @__PURE__ */
|
|
1513
|
-
/* @__PURE__ */
|
|
1581
|
+
/* @__PURE__ */ jsx14("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Account" }),
|
|
1582
|
+
/* @__PURE__ */ jsx14("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Account settings" }),
|
|
1583
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Review your profile, change your password, and manage account-level actions." })
|
|
1514
1584
|
] })
|
|
1515
1585
|
] });
|
|
1516
1586
|
}
|
|
@@ -1525,13 +1595,13 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1525
1595
|
const signOut = useSignOut();
|
|
1526
1596
|
const changePassword = useChangePassword();
|
|
1527
1597
|
const user = identity?.user ?? session.data?.user ?? null;
|
|
1528
|
-
const [passwordError, setPasswordError] =
|
|
1529
|
-
const [passwordSuccess, setPasswordSuccess] =
|
|
1530
|
-
const [isChangingPassword, setIsChangingPassword] =
|
|
1531
|
-
const [deleteConfirm, setDeleteConfirm] =
|
|
1532
|
-
const [deleteError, setDeleteError] =
|
|
1533
|
-
const [isDeleting, setIsDeleting] =
|
|
1534
|
-
const [deleteDialogOpen, setDeleteDialogOpen] =
|
|
1598
|
+
const [passwordError, setPasswordError] = useState14(null);
|
|
1599
|
+
const [passwordSuccess, setPasswordSuccess] = useState14(false);
|
|
1600
|
+
const [isChangingPassword, setIsChangingPassword] = useState14(false);
|
|
1601
|
+
const [deleteConfirm, setDeleteConfirm] = useState14("");
|
|
1602
|
+
const [deleteError, setDeleteError] = useState14(null);
|
|
1603
|
+
const [isDeleting, setIsDeleting] = useState14(false);
|
|
1604
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = useState14(false);
|
|
1535
1605
|
const {
|
|
1536
1606
|
register,
|
|
1537
1607
|
handleSubmit,
|
|
@@ -1589,21 +1659,21 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1589
1659
|
setIsDeleting(false);
|
|
1590
1660
|
}
|
|
1591
1661
|
}, [user?.email, signOut]);
|
|
1592
|
-
const topBarNode = topBar === void 0 ? /* @__PURE__ */
|
|
1662
|
+
const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx14(SettingsTopBar, {}) : topBar;
|
|
1593
1663
|
if (!user) {
|
|
1594
1664
|
return /* @__PURE__ */ jsxs6("main", { className: "boring-settings-shell", children: [
|
|
1595
1665
|
topBarNode,
|
|
1596
|
-
/* @__PURE__ */
|
|
1597
|
-
/* @__PURE__ */
|
|
1598
|
-
/* @__PURE__ */
|
|
1666
|
+
/* @__PURE__ */ jsx14("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsx14("div", { className: "mx-auto flex min-h-full w-full max-w-5xl items-center justify-center px-4", children: /* @__PURE__ */ jsxs6("div", { className: "w-full max-w-sm rounded-lg border border-border/60 bg-background p-4", children: [
|
|
1667
|
+
/* @__PURE__ */ jsx14("h1", { className: "text-[13px] font-medium", children: "Account settings" }),
|
|
1668
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 text-[12px] text-muted-foreground", children: "Loading your account..." })
|
|
1599
1669
|
] }) }) })
|
|
1600
1670
|
] });
|
|
1601
1671
|
}
|
|
1602
1672
|
const initials = initialsFor(user.name, user.email);
|
|
1603
1673
|
return /* @__PURE__ */ jsxs6("main", { className: "boring-settings-shell", children: [
|
|
1604
1674
|
topBarNode,
|
|
1605
|
-
/* @__PURE__ */
|
|
1606
|
-
/* @__PURE__ */
|
|
1675
|
+
/* @__PURE__ */ jsx14("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs6("div", { className: "boring-settings-layout", children: [
|
|
1676
|
+
/* @__PURE__ */ jsx14("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx14(
|
|
1607
1677
|
UiSettingsNav,
|
|
1608
1678
|
{
|
|
1609
1679
|
label: "Account settings",
|
|
@@ -1615,7 +1685,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1615
1685
|
}
|
|
1616
1686
|
) }),
|
|
1617
1687
|
/* @__PURE__ */ jsxs6("div", { className: "boring-settings-content space-y-4", children: [
|
|
1618
|
-
/* @__PURE__ */
|
|
1688
|
+
/* @__PURE__ */ jsx14(
|
|
1619
1689
|
SettingsPageHeader,
|
|
1620
1690
|
{
|
|
1621
1691
|
initials,
|
|
@@ -1623,65 +1693,65 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1623
1693
|
email: user.email
|
|
1624
1694
|
}
|
|
1625
1695
|
),
|
|
1626
|
-
/* @__PURE__ */
|
|
1696
|
+
/* @__PURE__ */ jsx14(
|
|
1627
1697
|
UiSettingsPanel,
|
|
1628
1698
|
{
|
|
1629
1699
|
id: "profile",
|
|
1630
|
-
icon: /* @__PURE__ */
|
|
1700
|
+
icon: /* @__PURE__ */ jsx14(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1631
1701
|
title: "Profile",
|
|
1632
1702
|
description: "The identity shown inside this app.",
|
|
1633
1703
|
children: /* @__PURE__ */ jsxs6(DetailList, { children: [
|
|
1634
|
-
/* @__PURE__ */
|
|
1704
|
+
/* @__PURE__ */ jsx14(
|
|
1635
1705
|
UiDetailLine,
|
|
1636
1706
|
{
|
|
1637
|
-
icon: /* @__PURE__ */
|
|
1707
|
+
icon: /* @__PURE__ */ jsx14(Mail, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1638
1708
|
label: "Email",
|
|
1639
|
-
children: /* @__PURE__ */
|
|
1709
|
+
children: /* @__PURE__ */ jsx14("p", { className: "truncate", children: user.email })
|
|
1640
1710
|
}
|
|
1641
1711
|
),
|
|
1642
|
-
/* @__PURE__ */
|
|
1712
|
+
/* @__PURE__ */ jsx14(
|
|
1643
1713
|
UiDetailLine,
|
|
1644
1714
|
{
|
|
1645
|
-
icon: /* @__PURE__ */
|
|
1715
|
+
icon: /* @__PURE__ */ jsx14(UserRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1646
1716
|
label: "Name",
|
|
1647
|
-
children: /* @__PURE__ */
|
|
1717
|
+
children: /* @__PURE__ */ jsx14("p", { className: "truncate", children: user.name ?? "Not set" })
|
|
1648
1718
|
}
|
|
1649
1719
|
),
|
|
1650
|
-
/* @__PURE__ */
|
|
1720
|
+
/* @__PURE__ */ jsx14(
|
|
1651
1721
|
UiDetailLine,
|
|
1652
1722
|
{
|
|
1653
|
-
icon: /* @__PURE__ */
|
|
1723
|
+
icon: /* @__PURE__ */ jsx14(CalendarDays, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1654
1724
|
label: "Member since",
|
|
1655
|
-
children: /* @__PURE__ */
|
|
1725
|
+
children: /* @__PURE__ */ jsx14("p", { children: formatMemberSince(user.createdAt) })
|
|
1656
1726
|
}
|
|
1657
1727
|
),
|
|
1658
|
-
/* @__PURE__ */
|
|
1728
|
+
/* @__PURE__ */ jsx14(
|
|
1659
1729
|
UiDetailLine,
|
|
1660
1730
|
{
|
|
1661
|
-
icon: /* @__PURE__ */
|
|
1731
|
+
icon: /* @__PURE__ */ jsx14(CheckCircle2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1662
1732
|
label: "Email status",
|
|
1663
|
-
children: /* @__PURE__ */
|
|
1733
|
+
children: /* @__PURE__ */ jsx14("p", { children: user.emailVerified ? "Verified" : "Not verified" })
|
|
1664
1734
|
}
|
|
1665
1735
|
)
|
|
1666
1736
|
] })
|
|
1667
1737
|
}
|
|
1668
1738
|
),
|
|
1669
|
-
extraSections.map((section) => /* @__PURE__ */
|
|
1670
|
-
/* @__PURE__ */
|
|
1739
|
+
extraSections.map((section) => /* @__PURE__ */ jsx14("div", { children: section.content }, section.id)),
|
|
1740
|
+
/* @__PURE__ */ jsx14("form", { onSubmit: handleSubmit(onChangePassword), noValidate: true, children: /* @__PURE__ */ jsx14(
|
|
1671
1741
|
UiSettingsPanel,
|
|
1672
1742
|
{
|
|
1673
1743
|
id: "password",
|
|
1674
|
-
icon: /* @__PURE__ */
|
|
1744
|
+
icon: /* @__PURE__ */ jsx14(KeyRound, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1675
1745
|
title: "Change password",
|
|
1676
1746
|
description: "Update the password used for email sign-in.",
|
|
1677
|
-
footer: /* @__PURE__ */
|
|
1747
|
+
footer: /* @__PURE__ */ jsx14(Button8, { type: "submit", size: "sm", disabled: isChangingPassword, children: isChangingPassword ? "Changing..." : "Change password" }),
|
|
1678
1748
|
children: /* @__PURE__ */ jsxs6("div", { className: "space-y-4", children: [
|
|
1679
|
-
passwordError && /* @__PURE__ */
|
|
1680
|
-
passwordSuccess && /* @__PURE__ */
|
|
1749
|
+
passwordError && /* @__PURE__ */ jsx14(Notice, { role: "alert", tone: "error", description: passwordError }),
|
|
1750
|
+
passwordSuccess && /* @__PURE__ */ jsx14(Notice, { role: "status", tone: "success", description: "Password changed successfully." }),
|
|
1681
1751
|
/* @__PURE__ */ jsxs6("div", { className: "grid gap-3 sm:grid-cols-2", children: [
|
|
1682
1752
|
/* @__PURE__ */ jsxs6("div", { className: "space-y-2 sm:col-span-2", children: [
|
|
1683
|
-
/* @__PURE__ */
|
|
1684
|
-
/* @__PURE__ */
|
|
1753
|
+
/* @__PURE__ */ jsx14(Label6, { htmlFor: "currentPassword", className: "text-[12px]", children: "Current password" }),
|
|
1754
|
+
/* @__PURE__ */ jsx14(
|
|
1685
1755
|
Input6,
|
|
1686
1756
|
{
|
|
1687
1757
|
id: "currentPassword",
|
|
@@ -1692,11 +1762,11 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1692
1762
|
...register("currentPassword")
|
|
1693
1763
|
}
|
|
1694
1764
|
),
|
|
1695
|
-
errors.currentPassword && /* @__PURE__ */
|
|
1765
|
+
errors.currentPassword && /* @__PURE__ */ jsx14("p", { className: "text-[12px] text-destructive", children: errors.currentPassword.message })
|
|
1696
1766
|
] }),
|
|
1697
1767
|
/* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
|
|
1698
|
-
/* @__PURE__ */
|
|
1699
|
-
/* @__PURE__ */
|
|
1768
|
+
/* @__PURE__ */ jsx14(Label6, { htmlFor: "newPassword", className: "text-[12px]", children: "New password" }),
|
|
1769
|
+
/* @__PURE__ */ jsx14(
|
|
1700
1770
|
Input6,
|
|
1701
1771
|
{
|
|
1702
1772
|
id: "newPassword",
|
|
@@ -1708,11 +1778,11 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1708
1778
|
...register("newPassword")
|
|
1709
1779
|
}
|
|
1710
1780
|
),
|
|
1711
|
-
errors.newPassword && /* @__PURE__ */
|
|
1781
|
+
errors.newPassword && /* @__PURE__ */ jsx14("p", { className: "text-[12px] text-destructive", children: errors.newPassword.message })
|
|
1712
1782
|
] }),
|
|
1713
1783
|
/* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
|
|
1714
|
-
/* @__PURE__ */
|
|
1715
|
-
/* @__PURE__ */
|
|
1784
|
+
/* @__PURE__ */ jsx14(Label6, { htmlFor: "confirmPassword", className: "text-[12px]", children: "Confirm new password" }),
|
|
1785
|
+
/* @__PURE__ */ jsx14(
|
|
1716
1786
|
Input6,
|
|
1717
1787
|
{
|
|
1718
1788
|
id: "confirmPassword",
|
|
@@ -1723,44 +1793,44 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1723
1793
|
...register("confirmPassword")
|
|
1724
1794
|
}
|
|
1725
1795
|
),
|
|
1726
|
-
errors.confirmPassword && /* @__PURE__ */
|
|
1796
|
+
errors.confirmPassword && /* @__PURE__ */ jsx14("p", { className: "text-[12px] text-destructive", children: errors.confirmPassword.message })
|
|
1727
1797
|
] })
|
|
1728
1798
|
] })
|
|
1729
1799
|
] })
|
|
1730
1800
|
}
|
|
1731
1801
|
) }),
|
|
1732
|
-
/* @__PURE__ */
|
|
1802
|
+
/* @__PURE__ */ jsx14(
|
|
1733
1803
|
UiSettingsPanel,
|
|
1734
1804
|
{
|
|
1735
1805
|
id: "danger-zone",
|
|
1736
|
-
icon: /* @__PURE__ */
|
|
1806
|
+
icon: /* @__PURE__ */ jsx14(ShieldAlert, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
1737
1807
|
title: "Danger zone",
|
|
1738
1808
|
description: "Permanently delete this account and remove its workspace access.",
|
|
1739
1809
|
danger: true,
|
|
1740
|
-
children: /* @__PURE__ */
|
|
1810
|
+
children: /* @__PURE__ */ jsx14(
|
|
1741
1811
|
UiSettingsActionRow,
|
|
1742
1812
|
{
|
|
1743
1813
|
title: "Delete account",
|
|
1744
1814
|
description: "Delete your account, user settings, and workspace memberships after confirmation.",
|
|
1745
1815
|
action: /* @__PURE__ */ jsxs6(AlertDialog, { open: deleteDialogOpen, onOpenChange: setDeleteDialogOpen, children: [
|
|
1746
|
-
/* @__PURE__ */
|
|
1747
|
-
/* @__PURE__ */
|
|
1816
|
+
/* @__PURE__ */ jsx14(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(Button8, { variant: "destructive", size: "sm", children: [
|
|
1817
|
+
/* @__PURE__ */ jsx14(Trash2, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
1748
1818
|
"Delete account"
|
|
1749
1819
|
] }) }),
|
|
1750
1820
|
/* @__PURE__ */ jsxs6(AlertDialogContent, { children: [
|
|
1751
1821
|
/* @__PURE__ */ jsxs6(AlertDialogHeader, { children: [
|
|
1752
|
-
/* @__PURE__ */
|
|
1753
|
-
/* @__PURE__ */
|
|
1822
|
+
/* @__PURE__ */ jsx14(AlertDialogTitle, { children: "Delete your account?" }),
|
|
1823
|
+
/* @__PURE__ */ jsx14(AlertDialogDescription, { children: "This action cannot be undone. All your data, workspaces, and settings will be permanently deleted." })
|
|
1754
1824
|
] }),
|
|
1755
1825
|
/* @__PURE__ */ jsxs6("div", { className: "space-y-3 py-2", children: [
|
|
1756
|
-
deleteError && /* @__PURE__ */
|
|
1826
|
+
deleteError && /* @__PURE__ */ jsx14(Notice, { role: "alert", tone: "error", description: deleteError }),
|
|
1757
1827
|
/* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
|
|
1758
1828
|
/* @__PURE__ */ jsxs6(Label6, { htmlFor: "delete-confirm", children: [
|
|
1759
1829
|
"Type ",
|
|
1760
|
-
/* @__PURE__ */
|
|
1830
|
+
/* @__PURE__ */ jsx14("span", { className: "font-mono font-bold", children: "DELETE" }),
|
|
1761
1831
|
" to confirm"
|
|
1762
1832
|
] }),
|
|
1763
|
-
/* @__PURE__ */
|
|
1833
|
+
/* @__PURE__ */ jsx14(
|
|
1764
1834
|
Input6,
|
|
1765
1835
|
{
|
|
1766
1836
|
id: "delete-confirm",
|
|
@@ -1774,7 +1844,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1774
1844
|
] })
|
|
1775
1845
|
] }),
|
|
1776
1846
|
/* @__PURE__ */ jsxs6(AlertDialogFooter, { children: [
|
|
1777
|
-
/* @__PURE__ */
|
|
1847
|
+
/* @__PURE__ */ jsx14(
|
|
1778
1848
|
AlertDialogCancel,
|
|
1779
1849
|
{
|
|
1780
1850
|
onClick: () => {
|
|
@@ -1784,7 +1854,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1784
1854
|
children: "Cancel"
|
|
1785
1855
|
}
|
|
1786
1856
|
),
|
|
1787
|
-
/* @__PURE__ */
|
|
1857
|
+
/* @__PURE__ */ jsx14(
|
|
1788
1858
|
Button8,
|
|
1789
1859
|
{
|
|
1790
1860
|
variant: "destructive",
|
|
@@ -1807,7 +1877,7 @@ function UserSettingsPage({ topBar, extraSections = [] } = {}) {
|
|
|
1807
1877
|
}
|
|
1808
1878
|
|
|
1809
1879
|
// src/front/auth/InviteAcceptPage.tsx
|
|
1810
|
-
import { useCallback as useCallback5, useState as
|
|
1880
|
+
import { useCallback as useCallback5, useState as useState15 } from "react";
|
|
1811
1881
|
import { useParams as useParams2, useNavigate as useNavigate2 } from "react-router-dom";
|
|
1812
1882
|
import { useQuery as useQuery3, useMutation, useQueryClient as useQueryClient2 } from "@tanstack/react-query";
|
|
1813
1883
|
import {
|
|
@@ -1821,13 +1891,13 @@ import {
|
|
|
1821
1891
|
LoadingState,
|
|
1822
1892
|
Notice as Notice2
|
|
1823
1893
|
} from "@hachej/boring-ui-kit";
|
|
1824
|
-
import { jsx as
|
|
1894
|
+
import { jsx as jsx15, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1825
1895
|
function InviteAcceptPage() {
|
|
1826
1896
|
const { token } = useParams2();
|
|
1827
1897
|
const session = useSession();
|
|
1828
1898
|
const navigate = useNavigate2();
|
|
1829
1899
|
const queryClient = useQueryClient2();
|
|
1830
|
-
const [acceptError, setAcceptError] =
|
|
1900
|
+
const [acceptError, setAcceptError] = useState15(null);
|
|
1831
1901
|
const isSignedIn = Boolean(session.data);
|
|
1832
1902
|
const isSessionPending = session.isPending;
|
|
1833
1903
|
const resolveQuery = useQuery3({
|
|
@@ -1871,20 +1941,20 @@ function InviteAcceptPage() {
|
|
|
1871
1941
|
navigate("/");
|
|
1872
1942
|
}, [navigate]);
|
|
1873
1943
|
if (isSessionPending) {
|
|
1874
|
-
return /* @__PURE__ */
|
|
1944
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx15(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx15(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx15(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
|
|
1875
1945
|
}
|
|
1876
1946
|
if (!isSignedIn) {
|
|
1877
1947
|
const signinUrl = `${routes.signin}?redirect=${encodeURIComponent(`/invites/${token}`)}`;
|
|
1878
|
-
return /* @__PURE__ */
|
|
1948
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
|
|
1879
1949
|
/* @__PURE__ */ jsxs7(CardHeader6, { children: [
|
|
1880
|
-
/* @__PURE__ */
|
|
1881
|
-
/* @__PURE__ */
|
|
1950
|
+
/* @__PURE__ */ jsx15(CardTitle6, { children: "Sign in to accept this invite" }),
|
|
1951
|
+
/* @__PURE__ */ jsx15(CardDescription6, { children: "You need to sign in before you can accept a workspace invite." })
|
|
1882
1952
|
] }),
|
|
1883
|
-
/* @__PURE__ */
|
|
1953
|
+
/* @__PURE__ */ jsx15(CardFooter6, { children: /* @__PURE__ */ jsx15(Button9, { className: "w-full", onClick: () => navigate(signinUrl), "data-testid": "signin-redirect", children: "Sign in" }) })
|
|
1884
1954
|
] }) });
|
|
1885
1955
|
}
|
|
1886
1956
|
if (resolveQuery.isLoading) {
|
|
1887
|
-
return /* @__PURE__ */
|
|
1957
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx15(Card6, { className: "w-full max-w-md", children: /* @__PURE__ */ jsx15(CardContent6, { className: "py-8 text-center", children: /* @__PURE__ */ jsx15(LoadingState, { "data-testid": "loading", className: "justify-center" }) }) }) });
|
|
1888
1958
|
}
|
|
1889
1959
|
if (resolveQuery.error) {
|
|
1890
1960
|
const detail = getHttpErrorDetail(resolveQuery.error);
|
|
@@ -1898,26 +1968,26 @@ function InviteAcceptPage() {
|
|
|
1898
1968
|
} else {
|
|
1899
1969
|
message = detail.message;
|
|
1900
1970
|
}
|
|
1901
|
-
return /* @__PURE__ */
|
|
1902
|
-
/* @__PURE__ */
|
|
1903
|
-
/* @__PURE__ */
|
|
1904
|
-
/* @__PURE__ */
|
|
1971
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
|
|
1972
|
+
/* @__PURE__ */ jsx15(CardHeader6, { children: /* @__PURE__ */ jsx15(CardTitle6, { children: "Invite unavailable" }) }),
|
|
1973
|
+
/* @__PURE__ */ jsx15(CardContent6, { children: /* @__PURE__ */ jsx15(Notice2, { "data-testid": "resolve-error", tone: "error", description: message }) }),
|
|
1974
|
+
/* @__PURE__ */ jsx15(CardFooter6, { children: /* @__PURE__ */ jsx15(Button9, { variant: "outline", className: "w-full", onClick: () => navigate("/"), children: "Go home" }) })
|
|
1905
1975
|
] }) });
|
|
1906
1976
|
}
|
|
1907
1977
|
const preview = resolveQuery.data;
|
|
1908
1978
|
if (!preview) return null;
|
|
1909
|
-
return /* @__PURE__ */
|
|
1979
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs7(Card6, { className: "w-full max-w-md", children: [
|
|
1910
1980
|
/* @__PURE__ */ jsxs7(CardHeader6, { children: [
|
|
1911
|
-
/* @__PURE__ */
|
|
1981
|
+
/* @__PURE__ */ jsx15(CardTitle6, { children: "You've been invited" }),
|
|
1912
1982
|
/* @__PURE__ */ jsxs7(CardDescription6, { children: [
|
|
1913
1983
|
"Join ",
|
|
1914
|
-
/* @__PURE__ */
|
|
1984
|
+
/* @__PURE__ */ jsx15("strong", { children: preview.workspaceName }),
|
|
1915
1985
|
" as ",
|
|
1916
|
-
/* @__PURE__ */
|
|
1986
|
+
/* @__PURE__ */ jsx15("strong", { children: preview.role })
|
|
1917
1987
|
] })
|
|
1918
1988
|
] }),
|
|
1919
1989
|
/* @__PURE__ */ jsxs7(CardContent6, { className: "space-y-3", children: [
|
|
1920
|
-
acceptError && /* @__PURE__ */
|
|
1990
|
+
acceptError && /* @__PURE__ */ jsx15(Notice2, { role: "alert", "data-testid": "accept-error", tone: "error", description: acceptError }),
|
|
1921
1991
|
/* @__PURE__ */ jsxs7("div", { className: "text-sm text-muted-foreground", children: [
|
|
1922
1992
|
"This invite expires on",
|
|
1923
1993
|
" ",
|
|
@@ -1929,7 +1999,7 @@ function InviteAcceptPage() {
|
|
|
1929
1999
|
] })
|
|
1930
2000
|
] }),
|
|
1931
2001
|
/* @__PURE__ */ jsxs7(CardFooter6, { className: "flex gap-3", children: [
|
|
1932
|
-
/* @__PURE__ */
|
|
2002
|
+
/* @__PURE__ */ jsx15(
|
|
1933
2003
|
Button9,
|
|
1934
2004
|
{
|
|
1935
2005
|
variant: "outline",
|
|
@@ -1939,7 +2009,7 @@ function InviteAcceptPage() {
|
|
|
1939
2009
|
children: "Decline"
|
|
1940
2010
|
}
|
|
1941
2011
|
),
|
|
1942
|
-
/* @__PURE__ */
|
|
2012
|
+
/* @__PURE__ */ jsx15(
|
|
1943
2013
|
Button9,
|
|
1944
2014
|
{
|
|
1945
2015
|
className: "flex-1",
|
|
@@ -1954,9 +2024,9 @@ function InviteAcceptPage() {
|
|
|
1954
2024
|
}
|
|
1955
2025
|
|
|
1956
2026
|
// src/front/AuthGate.tsx
|
|
1957
|
-
import { useEffect as
|
|
2027
|
+
import { useEffect as useEffect10, useMemo as useMemo4, useRef as useRef5 } from "react";
|
|
1958
2028
|
import { matchPath as matchPath2 } from "react-router-dom";
|
|
1959
|
-
import { Fragment as Fragment3, jsx as
|
|
2029
|
+
import { Fragment as Fragment3, jsx as jsx16 } from "react/jsx-runtime";
|
|
1960
2030
|
var DEFAULT_GRACE_MS = 3e4;
|
|
1961
2031
|
var UNSAFE_REDIRECT_RE = /[\0\r\n<>"'`]/;
|
|
1962
2032
|
var UNVERIFIED_ALLOWED_PATHS = /* @__PURE__ */ new Set([
|
|
@@ -2039,19 +2109,19 @@ function AuthGate({
|
|
|
2039
2109
|
const readNow = now ?? Date.now;
|
|
2040
2110
|
const currentLocation = location ?? defaultLocation();
|
|
2041
2111
|
const goTo = navigate ?? defaultNavigate;
|
|
2042
|
-
const normalizedPublicPaths =
|
|
2112
|
+
const normalizedPublicPaths = useMemo4(
|
|
2043
2113
|
() => publicPaths.map(normalizePublicPath),
|
|
2044
2114
|
[publicPaths]
|
|
2045
2115
|
);
|
|
2046
2116
|
const isEmailVerified = session.data?.user?.emailVerified ?? false;
|
|
2047
|
-
|
|
2117
|
+
useEffect10(() => {
|
|
2048
2118
|
return () => {
|
|
2049
2119
|
if (!redirectTimerRef.current) return;
|
|
2050
2120
|
clearTimeout(redirectTimerRef.current);
|
|
2051
2121
|
redirectTimerRef.current = null;
|
|
2052
2122
|
};
|
|
2053
2123
|
}, []);
|
|
2054
|
-
|
|
2124
|
+
useEffect10(() => {
|
|
2055
2125
|
if (redirectTimerRef.current) {
|
|
2056
2126
|
clearTimeout(redirectTimerRef.current);
|
|
2057
2127
|
redirectTimerRef.current = null;
|
|
@@ -2098,17 +2168,17 @@ function AuthGate({
|
|
|
2098
2168
|
const pathname = normalizePath(currentLocation.pathname);
|
|
2099
2169
|
if (shouldBlockUnverifiedUser(pathname, Boolean(session.data), requireEmailVerification, isEmailVerified)) return null;
|
|
2100
2170
|
if (session.isPending && !isPublicPath(pathname, normalizedPublicPaths)) return null;
|
|
2101
|
-
return /* @__PURE__ */
|
|
2171
|
+
return /* @__PURE__ */ jsx16(Fragment3, { children });
|
|
2102
2172
|
}
|
|
2103
2173
|
|
|
2104
2174
|
// src/front/CoreFront.tsx
|
|
2105
|
-
import { Suspense, useCallback as useCallback9, useMemo as
|
|
2175
|
+
import { Suspense, useCallback as useCallback9, useEffect as useEffect12, useMemo as useMemo8 } from "react";
|
|
2106
2176
|
import { BrowserRouter, Routes, Route, useLocation as useLocation2, useNavigate as useNavigate6 } from "react-router-dom";
|
|
2107
2177
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
2108
2178
|
import { Helmet, HelmetProvider } from "react-helmet-async";
|
|
2109
2179
|
|
|
2110
2180
|
// src/front/components/UserMenu.tsx
|
|
2111
|
-
import { useMemo as
|
|
2181
|
+
import { useMemo as useMemo5, useState as useState16 } from "react";
|
|
2112
2182
|
import {
|
|
2113
2183
|
Button as Button10,
|
|
2114
2184
|
DropdownMenu,
|
|
@@ -2126,10 +2196,11 @@ import {
|
|
|
2126
2196
|
Monitor,
|
|
2127
2197
|
Moon,
|
|
2128
2198
|
Settings,
|
|
2199
|
+
ShieldCheck,
|
|
2129
2200
|
Sun
|
|
2130
2201
|
} from "lucide-react";
|
|
2131
2202
|
import { useNavigate as useNavigate3 } from "react-router-dom";
|
|
2132
|
-
import { jsx as
|
|
2203
|
+
import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
2133
2204
|
var THEME_ORDER = ["light", "dark", "system"];
|
|
2134
2205
|
function labelForTheme(preference) {
|
|
2135
2206
|
if (preference === "light") return "Light";
|
|
@@ -2152,11 +2223,17 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2152
2223
|
const signOut = useSignOut();
|
|
2153
2224
|
const navigate = useNavigate3();
|
|
2154
2225
|
const { preference, setTheme } = useTheme();
|
|
2155
|
-
const
|
|
2226
|
+
const workspace = useCurrentWorkspace();
|
|
2227
|
+
const companyAdmin = useCompanyAdminStatus();
|
|
2228
|
+
const [isSigningOut, setIsSigningOut] = useState16(false);
|
|
2156
2229
|
const user = identity?.user;
|
|
2230
|
+
const adminMenuLabel = companyAdmin.labels.menuLabel ?? "Admin";
|
|
2231
|
+
const companyAdminStatusPending = companyAdmin.configured && companyAdmin.loading && !companyAdmin.status;
|
|
2232
|
+
const canOpenCompanyAdmin = companyAdmin.configured && (companyAdminStatusPending || Boolean(companyAdmin.error) || companyAdmin.status?.enabled === true && companyAdmin.status.admin === true);
|
|
2233
|
+
const companyAdminWorkspaceId = canOpenCompanyAdmin ? workspace?.id ?? null : null;
|
|
2157
2234
|
const userName = user?.name ?? "Unknown user";
|
|
2158
2235
|
const userEmail = user?.email ?? "unknown@example.com";
|
|
2159
|
-
const initials =
|
|
2236
|
+
const initials = useMemo5(() => initialsFor2(user?.name ?? null, userEmail), [user?.name, userEmail]);
|
|
2160
2237
|
async function handleSignOut() {
|
|
2161
2238
|
if (isSigningOut) return;
|
|
2162
2239
|
setIsSigningOut(true);
|
|
@@ -2168,7 +2245,7 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2168
2245
|
}
|
|
2169
2246
|
}
|
|
2170
2247
|
return /* @__PURE__ */ jsxs8(DropdownMenu, { children: [
|
|
2171
|
-
/* @__PURE__ */
|
|
2248
|
+
/* @__PURE__ */ jsx17(DropdownMenuTrigger, { asChild: true, children: variant === "bar" ? /* @__PURE__ */ jsxs8(
|
|
2172
2249
|
Button10,
|
|
2173
2250
|
{
|
|
2174
2251
|
type: "button",
|
|
@@ -2176,12 +2253,12 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2176
2253
|
"aria-label": "Account menu",
|
|
2177
2254
|
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
2255
|
children: [
|
|
2179
|
-
/* @__PURE__ */
|
|
2256
|
+
/* @__PURE__ */ jsx17("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
2257
|
/* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-1 flex-col gap-0.5 leading-snug", children: [
|
|
2181
|
-
/* @__PURE__ */
|
|
2182
|
-
/* @__PURE__ */
|
|
2258
|
+
/* @__PURE__ */ jsx17("span", { className: "truncate text-[13px] font-medium text-foreground", children: userName }),
|
|
2259
|
+
/* @__PURE__ */ jsx17("span", { className: "truncate text-[11px] text-muted-foreground/80", children: userEmail })
|
|
2183
2260
|
] }),
|
|
2184
|
-
/* @__PURE__ */
|
|
2261
|
+
/* @__PURE__ */ jsx17(ChevronsUpDown, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
|
|
2185
2262
|
]
|
|
2186
2263
|
}
|
|
2187
2264
|
) : /* @__PURE__ */ jsxs8(
|
|
@@ -2192,8 +2269,8 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2192
2269
|
"aria-label": "User menu",
|
|
2193
2270
|
className: "h-8 rounded-md border border-transparent bg-transparent px-1 pr-1.5 text-foreground shadow-none hover:bg-foreground/5 focus-visible:ring-1 focus-visible:ring-ring",
|
|
2194
2271
|
children: [
|
|
2195
|
-
/* @__PURE__ */
|
|
2196
|
-
/* @__PURE__ */
|
|
2272
|
+
/* @__PURE__ */ jsx17("span", { className: "inline-flex h-7 w-7 items-center justify-center rounded-md bg-foreground text-[11px] font-semibold text-background", children: initials }),
|
|
2273
|
+
/* @__PURE__ */ jsx17(ChevronDown, { className: "h-3.5 w-3.5 text-muted-foreground", "aria-hidden": "true" })
|
|
2197
2274
|
]
|
|
2198
2275
|
}
|
|
2199
2276
|
) }),
|
|
@@ -2205,15 +2282,15 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2205
2282
|
sideOffset: 8,
|
|
2206
2283
|
className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
|
|
2207
2284
|
children: [
|
|
2208
|
-
/* @__PURE__ */
|
|
2209
|
-
/* @__PURE__ */
|
|
2285
|
+
/* @__PURE__ */ jsx17(DropdownMenuLabel, { className: "p-2", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3", children: [
|
|
2286
|
+
/* @__PURE__ */ jsx17("span", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-foreground text-[12px] font-semibold text-background", children: initials }),
|
|
2210
2287
|
/* @__PURE__ */ jsxs8("span", { className: "min-w-0 space-y-1", children: [
|
|
2211
|
-
/* @__PURE__ */
|
|
2212
|
-
/* @__PURE__ */
|
|
2288
|
+
/* @__PURE__ */ jsx17("span", { className: "block truncate text-sm font-medium leading-none", children: userName }),
|
|
2289
|
+
/* @__PURE__ */ jsx17("span", { className: "block truncate text-xs font-normal text-muted-foreground", children: userEmail })
|
|
2213
2290
|
] })
|
|
2214
2291
|
] }) }),
|
|
2215
|
-
/* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
2292
|
+
/* @__PURE__ */ jsx17(DropdownMenuSeparator, { className: "-mx-2" }),
|
|
2293
|
+
/* @__PURE__ */ jsx17(DropdownMenuLabel, { className: "px-2 pb-1 pt-2 text-[11px] font-medium text-muted-foreground", children: "Theme" }),
|
|
2217
2294
|
THEME_ORDER.map((theme) => {
|
|
2218
2295
|
const Icon = iconForTheme(theme);
|
|
2219
2296
|
const selected = preference === theme;
|
|
@@ -2228,15 +2305,15 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2228
2305
|
},
|
|
2229
2306
|
className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
|
|
2230
2307
|
children: [
|
|
2231
|
-
/* @__PURE__ */
|
|
2232
|
-
/* @__PURE__ */
|
|
2233
|
-
selected ? /* @__PURE__ */
|
|
2308
|
+
/* @__PURE__ */ jsx17(Icon, { className: "h-4 w-4 text-muted-foreground", "aria-hidden": "true" }),
|
|
2309
|
+
/* @__PURE__ */ jsx17("span", { className: "flex-1", children: labelForTheme(theme) }),
|
|
2310
|
+
selected ? /* @__PURE__ */ jsx17(Check, { className: "h-4 w-4 text-foreground", "aria-hidden": "true" }) : null
|
|
2234
2311
|
]
|
|
2235
2312
|
},
|
|
2236
2313
|
theme
|
|
2237
2314
|
);
|
|
2238
2315
|
}),
|
|
2239
|
-
/* @__PURE__ */
|
|
2316
|
+
/* @__PURE__ */ jsx17(DropdownMenuSeparator, { className: "-mx-2" }),
|
|
2240
2317
|
/* @__PURE__ */ jsxs8(
|
|
2241
2318
|
DropdownMenuItem,
|
|
2242
2319
|
{
|
|
@@ -2244,15 +2321,30 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2244
2321
|
onSelect: () => navigate(routes.me),
|
|
2245
2322
|
className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
|
|
2246
2323
|
children: [
|
|
2247
|
-
/* @__PURE__ */
|
|
2324
|
+
/* @__PURE__ */ jsx17(Settings, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2248
2325
|
/* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-col", children: [
|
|
2249
|
-
/* @__PURE__ */
|
|
2250
|
-
/* @__PURE__ */
|
|
2326
|
+
/* @__PURE__ */ jsx17("span", { children: "User settings" }),
|
|
2327
|
+
/* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Password and account controls" })
|
|
2251
2328
|
] })
|
|
2252
2329
|
]
|
|
2253
2330
|
}
|
|
2254
2331
|
),
|
|
2255
|
-
/* @__PURE__ */
|
|
2332
|
+
companyAdminWorkspaceId ? /* @__PURE__ */ jsxs8(
|
|
2333
|
+
DropdownMenuItem,
|
|
2334
|
+
{
|
|
2335
|
+
"aria-label": adminMenuLabel,
|
|
2336
|
+
onSelect: () => navigate(routeHref("companyAdmin", { id: companyAdminWorkspaceId })),
|
|
2337
|
+
className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
|
|
2338
|
+
children: [
|
|
2339
|
+
/* @__PURE__ */ jsx17(ShieldCheck, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2340
|
+
/* @__PURE__ */ jsxs8("span", { className: "flex min-w-0 flex-col", children: [
|
|
2341
|
+
/* @__PURE__ */ jsx17("span", { children: adminMenuLabel }),
|
|
2342
|
+
/* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground", children: "Admin controls" })
|
|
2343
|
+
] })
|
|
2344
|
+
]
|
|
2345
|
+
}
|
|
2346
|
+
) : null,
|
|
2347
|
+
/* @__PURE__ */ jsx17(DropdownMenuSeparator, { className: "-mx-2" }),
|
|
2256
2348
|
/* @__PURE__ */ jsxs8(
|
|
2257
2349
|
DropdownMenuItem,
|
|
2258
2350
|
{
|
|
@@ -2264,7 +2356,7 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2264
2356
|
disabled: isSigningOut,
|
|
2265
2357
|
className: "gap-3 rounded-md py-2 text-[13px]",
|
|
2266
2358
|
children: [
|
|
2267
|
-
/* @__PURE__ */
|
|
2359
|
+
/* @__PURE__ */ jsx17(LogOut, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2268
2360
|
isSigningOut ? "Signing out..." : "Sign out"
|
|
2269
2361
|
]
|
|
2270
2362
|
}
|
|
@@ -2276,7 +2368,7 @@ function UserMenu({ contentSide = "bottom", contentAlign = "end", variant = "com
|
|
|
2276
2368
|
}
|
|
2277
2369
|
|
|
2278
2370
|
// src/front/components/WorkspaceSwitcher.tsx
|
|
2279
|
-
import { useMemo as
|
|
2371
|
+
import { useMemo as useMemo6, useState as useState17 } from "react";
|
|
2280
2372
|
import { useQuery as useQuery4, useQueryClient as useQueryClient3 } from "@tanstack/react-query";
|
|
2281
2373
|
import {
|
|
2282
2374
|
Button as Button11,
|
|
@@ -2299,7 +2391,7 @@ import {
|
|
|
2299
2391
|
import { ChevronsUpDown as ChevronsUpDown2, LayoutGrid, Plus, Settings as Settings2 } from "lucide-react";
|
|
2300
2392
|
import { useNavigate as useNavigate4 } from "react-router-dom";
|
|
2301
2393
|
import { z as z6 } from "zod";
|
|
2302
|
-
import { Fragment as Fragment4, jsx as
|
|
2394
|
+
import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2303
2395
|
var workspaceNameSchema = z6.object({
|
|
2304
2396
|
name: z6.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
|
|
2305
2397
|
});
|
|
@@ -2337,9 +2429,9 @@ function workspaceInitial(name) {
|
|
|
2337
2429
|
}
|
|
2338
2430
|
function OpenInNewTabIcon({ className }) {
|
|
2339
2431
|
return /* @__PURE__ */ jsxs9("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
2340
|
-
/* @__PURE__ */
|
|
2341
|
-
/* @__PURE__ */
|
|
2342
|
-
/* @__PURE__ */
|
|
2432
|
+
/* @__PURE__ */ jsx18("path", { d: "M15 3h6v6" }),
|
|
2433
|
+
/* @__PURE__ */ jsx18("path", { d: "M10 14 21 3" }),
|
|
2434
|
+
/* @__PURE__ */ jsx18("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" })
|
|
2343
2435
|
] });
|
|
2344
2436
|
}
|
|
2345
2437
|
function WorkspaceSwitcher({
|
|
@@ -2355,12 +2447,12 @@ function WorkspaceSwitcher({
|
|
|
2355
2447
|
const currentWorkspace = useCurrentWorkspace();
|
|
2356
2448
|
const workspacesQuery = useWorkspaces();
|
|
2357
2449
|
const workspaces = workspacesQuery.data ?? [];
|
|
2358
|
-
const [isModalOpen, setIsModalOpen] =
|
|
2359
|
-
const [name, setName] =
|
|
2360
|
-
const [attemptedSubmit, setAttemptedSubmit] =
|
|
2361
|
-
const [isSubmitting, setIsSubmitting] =
|
|
2362
|
-
const [serverError, setServerError] =
|
|
2363
|
-
const nameValidation =
|
|
2450
|
+
const [isModalOpen, setIsModalOpen] = useState17(false);
|
|
2451
|
+
const [name, setName] = useState17("");
|
|
2452
|
+
const [attemptedSubmit, setAttemptedSubmit] = useState17(false);
|
|
2453
|
+
const [isSubmitting, setIsSubmitting] = useState17(false);
|
|
2454
|
+
const [serverError, setServerError] = useState17(null);
|
|
2455
|
+
const nameValidation = useMemo6(() => validateWorkspaceName(name), [name]);
|
|
2364
2456
|
const shouldShowNameError = name.length > 100 || attemptedSubmit && nameValidation.message !== null;
|
|
2365
2457
|
const nameError = shouldShowNameError ? nameValidation.message : null;
|
|
2366
2458
|
function openCreateWorkspace() {
|
|
@@ -2431,7 +2523,7 @@ function WorkspaceSwitcher({
|
|
|
2431
2523
|
onClick: openCreateWorkspace,
|
|
2432
2524
|
className: "-ml-1 h-8 gap-2 rounded-md px-1 pr-2.5 hover:bg-foreground/5 focus-visible:ring-1 focus-visible:ring-ring",
|
|
2433
2525
|
children: [
|
|
2434
|
-
/* @__PURE__ */
|
|
2526
|
+
/* @__PURE__ */ jsx18(
|
|
2435
2527
|
"span",
|
|
2436
2528
|
{
|
|
2437
2529
|
"aria-hidden": "true",
|
|
@@ -2439,11 +2531,11 @@ function WorkspaceSwitcher({
|
|
|
2439
2531
|
children: resolvedAppTitle.charAt(0).toUpperCase()
|
|
2440
2532
|
}
|
|
2441
2533
|
),
|
|
2442
|
-
/* @__PURE__ */
|
|
2534
|
+
/* @__PURE__ */ jsx18("span", { className: "text-[13px] font-medium text-foreground", children: "Create your first workspace" })
|
|
2443
2535
|
]
|
|
2444
2536
|
}
|
|
2445
2537
|
) : /* @__PURE__ */ jsxs9(DropdownMenu2, { children: [
|
|
2446
|
-
/* @__PURE__ */
|
|
2538
|
+
/* @__PURE__ */ jsx18(DropdownMenuTrigger2, { asChild: true, children: displayMode === "workspace" ? /* @__PURE__ */ jsxs9(
|
|
2447
2539
|
Button11,
|
|
2448
2540
|
{
|
|
2449
2541
|
type: "button",
|
|
@@ -2451,8 +2543,8 @@ function WorkspaceSwitcher({
|
|
|
2451
2543
|
"aria-label": `Workspace menu: ${switcherLabel}`,
|
|
2452
2544
|
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
2545
|
children: [
|
|
2454
|
-
/* @__PURE__ */
|
|
2455
|
-
/* @__PURE__ */
|
|
2546
|
+
/* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-[13px] font-medium text-foreground/85", children: switcherLabel }),
|
|
2547
|
+
/* @__PURE__ */ jsx18(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
|
|
2456
2548
|
]
|
|
2457
2549
|
}
|
|
2458
2550
|
) : /* @__PURE__ */ jsxs9(
|
|
@@ -2463,7 +2555,7 @@ function WorkspaceSwitcher({
|
|
|
2463
2555
|
"aria-label": `Workspace menu: ${switcherLabel}`,
|
|
2464
2556
|
className: "-ml-1 h-8 min-w-0 justify-start gap-2.5 border border-transparent px-1 py-1 text-left",
|
|
2465
2557
|
children: [
|
|
2466
|
-
/* @__PURE__ */
|
|
2558
|
+
/* @__PURE__ */ jsx18(
|
|
2467
2559
|
"span",
|
|
2468
2560
|
{
|
|
2469
2561
|
"aria-hidden": "true",
|
|
@@ -2471,8 +2563,8 @@ function WorkspaceSwitcher({
|
|
|
2471
2563
|
children: workspaceInitial(switcherLabel)
|
|
2472
2564
|
}
|
|
2473
2565
|
),
|
|
2474
|
-
/* @__PURE__ */
|
|
2475
|
-
/* @__PURE__ */
|
|
2566
|
+
/* @__PURE__ */ jsx18("span", { className: "min-w-0 truncate text-[13px] font-medium text-foreground", children: switcherLabel }),
|
|
2567
|
+
/* @__PURE__ */ jsx18(ChevronsUpDown2, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/55", "aria-hidden": "true" })
|
|
2476
2568
|
]
|
|
2477
2569
|
}
|
|
2478
2570
|
) }),
|
|
@@ -2483,11 +2575,11 @@ function WorkspaceSwitcher({
|
|
|
2483
2575
|
sideOffset: 8,
|
|
2484
2576
|
className: "w-80 rounded-lg border-border/70 bg-[color:var(--surface-workbench-left)] p-2 shadow-2xl",
|
|
2485
2577
|
children: [
|
|
2486
|
-
/* @__PURE__ */
|
|
2487
|
-
/* @__PURE__ */
|
|
2578
|
+
/* @__PURE__ */ jsx18(DropdownMenuLabel2, { className: "px-2 pb-2 pt-1", children: /* @__PURE__ */ jsxs9("span", { className: "flex items-center gap-2 text-xs font-medium text-muted-foreground", children: [
|
|
2579
|
+
/* @__PURE__ */ jsx18(LayoutGrid, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2488
2580
|
"Workspaces"
|
|
2489
2581
|
] }) }),
|
|
2490
|
-
/* @__PURE__ */
|
|
2582
|
+
/* @__PURE__ */ jsx18("div", { className: "max-h-72 overflow-y-auto pr-1", children: workspaces.map((workspace) => {
|
|
2491
2583
|
const isCurrent = currentWorkspace?.id === workspace.id;
|
|
2492
2584
|
return /* @__PURE__ */ jsxs9("div", { className: "group relative w-full", children: [
|
|
2493
2585
|
/* @__PURE__ */ jsxs9(
|
|
@@ -2499,12 +2591,12 @@ function WorkspaceSwitcher({
|
|
|
2499
2591
|
style: { paddingRight: 72 },
|
|
2500
2592
|
className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
|
|
2501
2593
|
children: [
|
|
2502
|
-
/* @__PURE__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2594
|
+
/* @__PURE__ */ jsx18("span", { className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-border/60 bg-background text-xs font-semibold text-muted-foreground", children: workspaceInitial(workspace.name) }),
|
|
2595
|
+
/* @__PURE__ */ jsx18("span", { className: "min-w-0 flex-1 truncate text-sm", children: workspace.name })
|
|
2504
2596
|
]
|
|
2505
2597
|
}
|
|
2506
2598
|
),
|
|
2507
|
-
/* @__PURE__ */
|
|
2599
|
+
/* @__PURE__ */ jsx18(
|
|
2508
2600
|
"button",
|
|
2509
2601
|
{
|
|
2510
2602
|
type: "button",
|
|
@@ -2522,12 +2614,12 @@ function WorkspaceSwitcher({
|
|
|
2522
2614
|
},
|
|
2523
2615
|
style: { right: 4, top: "50%", transform: "translateY(-50%)" },
|
|
2524
2616
|
className: "absolute z-10 flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground opacity-0 transition hover:bg-foreground/10 hover:text-foreground focus:opacity-100 focus:outline-none focus-visible:ring-1 focus-visible:ring-ring group-hover:opacity-100 group-focus-within:opacity-100",
|
|
2525
|
-
children: /* @__PURE__ */
|
|
2617
|
+
children: /* @__PURE__ */ jsx18(OpenInNewTabIcon, { className: "h-3.5 w-3.5" })
|
|
2526
2618
|
}
|
|
2527
2619
|
)
|
|
2528
2620
|
] }, workspace.id);
|
|
2529
2621
|
}) }),
|
|
2530
|
-
/* @__PURE__ */
|
|
2622
|
+
/* @__PURE__ */ jsx18(DropdownMenuSeparator2, { className: "-mx-2" }),
|
|
2531
2623
|
/* @__PURE__ */ jsxs9(
|
|
2532
2624
|
DropdownMenuItem2,
|
|
2533
2625
|
{
|
|
@@ -2538,10 +2630,10 @@ function WorkspaceSwitcher({
|
|
|
2538
2630
|
},
|
|
2539
2631
|
className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
|
|
2540
2632
|
children: [
|
|
2541
|
-
/* @__PURE__ */
|
|
2633
|
+
/* @__PURE__ */ jsx18(Plus, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2542
2634
|
/* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-col", children: [
|
|
2543
|
-
/* @__PURE__ */
|
|
2544
|
-
/* @__PURE__ */
|
|
2635
|
+
/* @__PURE__ */ jsx18("span", { children: "Create workspace" }),
|
|
2636
|
+
/* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground", children: "Start a clean project space" })
|
|
2545
2637
|
] })
|
|
2546
2638
|
]
|
|
2547
2639
|
}
|
|
@@ -2553,10 +2645,10 @@ function WorkspaceSwitcher({
|
|
|
2553
2645
|
onSelect: () => navigate(hrefForWorkspace(workspacePathPrefix, currentWorkspace.id, "/settings")),
|
|
2554
2646
|
className: "gap-3 rounded-md py-2 text-[13px] focus:bg-foreground/[0.06] focus:text-foreground",
|
|
2555
2647
|
children: [
|
|
2556
|
-
/* @__PURE__ */
|
|
2648
|
+
/* @__PURE__ */ jsx18(Settings2, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
2557
2649
|
/* @__PURE__ */ jsxs9("span", { className: "flex min-w-0 flex-col", children: [
|
|
2558
|
-
/* @__PURE__ */
|
|
2559
|
-
/* @__PURE__ */
|
|
2650
|
+
/* @__PURE__ */ jsx18("span", { children: "Workspace settings" }),
|
|
2651
|
+
/* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground", children: "Rename, runtime, deletion" })
|
|
2560
2652
|
] })
|
|
2561
2653
|
]
|
|
2562
2654
|
}
|
|
@@ -2565,21 +2657,21 @@ function WorkspaceSwitcher({
|
|
|
2565
2657
|
}
|
|
2566
2658
|
)
|
|
2567
2659
|
] }),
|
|
2568
|
-
/* @__PURE__ */
|
|
2660
|
+
/* @__PURE__ */ jsx18(Dialog, { open: isModalOpen, onOpenChange: onModalChange, children: /* @__PURE__ */ jsxs9(DialogContent, { children: [
|
|
2569
2661
|
/* @__PURE__ */ jsxs9(DialogHeader, { children: [
|
|
2570
|
-
/* @__PURE__ */
|
|
2571
|
-
/* @__PURE__ */
|
|
2662
|
+
/* @__PURE__ */ jsx18(DialogTitle, { children: "Create workspace" }),
|
|
2663
|
+
/* @__PURE__ */ jsx18(DialogDescription, { children: "Choose a name for your new workspace." })
|
|
2572
2664
|
] }),
|
|
2573
2665
|
/* @__PURE__ */ jsxs9("form", { onSubmit: (event) => void handleCreateWorkspace(event), className: "space-y-4", children: [
|
|
2574
2666
|
/* @__PURE__ */ jsxs9("div", { className: "space-y-2", children: [
|
|
2575
2667
|
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2576
|
-
/* @__PURE__ */
|
|
2668
|
+
/* @__PURE__ */ jsx18(Label7, { htmlFor: "workspace-name", children: "Name" }),
|
|
2577
2669
|
/* @__PURE__ */ jsxs9("span", { className: "text-xs text-muted-foreground", children: [
|
|
2578
2670
|
name.length,
|
|
2579
2671
|
"/100"
|
|
2580
2672
|
] })
|
|
2581
2673
|
] }),
|
|
2582
|
-
/* @__PURE__ */
|
|
2674
|
+
/* @__PURE__ */ jsx18(
|
|
2583
2675
|
Input7,
|
|
2584
2676
|
{
|
|
2585
2677
|
id: "workspace-name",
|
|
@@ -2595,11 +2687,11 @@ function WorkspaceSwitcher({
|
|
|
2595
2687
|
autoFocus: true
|
|
2596
2688
|
}
|
|
2597
2689
|
),
|
|
2598
|
-
nameError ? /* @__PURE__ */
|
|
2599
|
-
serverError ? /* @__PURE__ */
|
|
2690
|
+
nameError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
|
|
2691
|
+
serverError ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
|
|
2600
2692
|
] }),
|
|
2601
2693
|
/* @__PURE__ */ jsxs9(DialogFooter, { children: [
|
|
2602
|
-
/* @__PURE__ */
|
|
2694
|
+
/* @__PURE__ */ jsx18(
|
|
2603
2695
|
Button11,
|
|
2604
2696
|
{
|
|
2605
2697
|
type: "button",
|
|
@@ -2609,7 +2701,7 @@ function WorkspaceSwitcher({
|
|
|
2609
2701
|
children: "Cancel"
|
|
2610
2702
|
}
|
|
2611
2703
|
),
|
|
2612
|
-
/* @__PURE__ */
|
|
2704
|
+
/* @__PURE__ */ jsx18(
|
|
2613
2705
|
Button11,
|
|
2614
2706
|
{
|
|
2615
2707
|
type: "submit",
|
|
@@ -2624,7 +2716,7 @@ function WorkspaceSwitcher({
|
|
|
2624
2716
|
}
|
|
2625
2717
|
|
|
2626
2718
|
// src/front/components/CreateWorkspaceDialog.tsx
|
|
2627
|
-
import { useMemo as
|
|
2719
|
+
import { useMemo as useMemo7, useState as useState18 } from "react";
|
|
2628
2720
|
import { useQueryClient as useQueryClient4 } from "@tanstack/react-query";
|
|
2629
2721
|
import {
|
|
2630
2722
|
Button as Button12,
|
|
@@ -2639,7 +2731,7 @@ import {
|
|
|
2639
2731
|
useToast as useToast2
|
|
2640
2732
|
} from "@hachej/boring-ui-kit";
|
|
2641
2733
|
import { z as z7 } from "zod";
|
|
2642
|
-
import { jsx as
|
|
2734
|
+
import { jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2643
2735
|
var workspaceNameSchema2 = z7.object({
|
|
2644
2736
|
name: z7.string().trim().min(1, "Workspace name is required").max(100, "Workspace name must be 100 characters or fewer")
|
|
2645
2737
|
});
|
|
@@ -2653,11 +2745,11 @@ function CreateWorkspaceDialog({
|
|
|
2653
2745
|
}) {
|
|
2654
2746
|
const queryClient = useQueryClient4();
|
|
2655
2747
|
const { toast } = useToast2();
|
|
2656
|
-
const [name, setName] =
|
|
2657
|
-
const [attemptedSubmit, setAttemptedSubmit] =
|
|
2658
|
-
const [isSubmitting, setIsSubmitting] =
|
|
2659
|
-
const [serverError, setServerError] =
|
|
2660
|
-
const validation =
|
|
2748
|
+
const [name, setName] = useState18("");
|
|
2749
|
+
const [attemptedSubmit, setAttemptedSubmit] = useState18(false);
|
|
2750
|
+
const [isSubmitting, setIsSubmitting] = useState18(false);
|
|
2751
|
+
const [serverError, setServerError] = useState18(null);
|
|
2752
|
+
const validation = useMemo7(() => workspaceNameSchema2.safeParse({ name }), [name]);
|
|
2661
2753
|
const shouldShowNameError = name.length > 100 || attemptedSubmit && !validation.success;
|
|
2662
2754
|
const nameError = shouldShowNameError && !validation.success ? validation.error.issues[0]?.message ?? "Invalid workspace name" : null;
|
|
2663
2755
|
function reset() {
|
|
@@ -2707,21 +2799,21 @@ function CreateWorkspaceDialog({
|
|
|
2707
2799
|
setIsSubmitting(false);
|
|
2708
2800
|
}
|
|
2709
2801
|
}
|
|
2710
|
-
return /* @__PURE__ */
|
|
2802
|
+
return /* @__PURE__ */ jsx19(Dialog2, { open, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs10(DialogContent2, { children: [
|
|
2711
2803
|
/* @__PURE__ */ jsxs10(DialogHeader2, { children: [
|
|
2712
|
-
/* @__PURE__ */
|
|
2713
|
-
/* @__PURE__ */
|
|
2804
|
+
/* @__PURE__ */ jsx19(DialogTitle2, { children: title }),
|
|
2805
|
+
/* @__PURE__ */ jsx19(DialogDescription2, { children: description })
|
|
2714
2806
|
] }),
|
|
2715
2807
|
/* @__PURE__ */ jsxs10("form", { onSubmit: (event) => void handleSubmit(event), className: "space-y-4", children: [
|
|
2716
2808
|
/* @__PURE__ */ jsxs10("div", { className: "space-y-2", children: [
|
|
2717
2809
|
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2718
|
-
/* @__PURE__ */
|
|
2810
|
+
/* @__PURE__ */ jsx19(Label8, { htmlFor: "create-workspace-name", children: "Name" }),
|
|
2719
2811
|
/* @__PURE__ */ jsxs10("span", { className: "text-xs text-muted-foreground", children: [
|
|
2720
2812
|
name.length,
|
|
2721
2813
|
"/100"
|
|
2722
2814
|
] })
|
|
2723
2815
|
] }),
|
|
2724
|
-
/* @__PURE__ */
|
|
2816
|
+
/* @__PURE__ */ jsx19(
|
|
2725
2817
|
Input8,
|
|
2726
2818
|
{
|
|
2727
2819
|
id: "create-workspace-name",
|
|
@@ -2737,12 +2829,12 @@ function CreateWorkspaceDialog({
|
|
|
2737
2829
|
autoFocus: true
|
|
2738
2830
|
}
|
|
2739
2831
|
),
|
|
2740
|
-
nameError ? /* @__PURE__ */
|
|
2741
|
-
serverError ? /* @__PURE__ */
|
|
2832
|
+
nameError ? /* @__PURE__ */ jsx19("p", { role: "alert", className: "text-sm text-destructive", children: nameError }) : null,
|
|
2833
|
+
serverError ? /* @__PURE__ */ jsx19("p", { role: "alert", className: "text-sm text-destructive", children: serverError }) : null
|
|
2742
2834
|
] }),
|
|
2743
2835
|
/* @__PURE__ */ jsxs10(DialogFooter2, { children: [
|
|
2744
|
-
/* @__PURE__ */
|
|
2745
|
-
/* @__PURE__ */
|
|
2836
|
+
/* @__PURE__ */ jsx19(Button12, { type: "button", variant: "ghost", onClick: () => handleOpenChange(false), disabled: isSubmitting, children: "Cancel" }),
|
|
2837
|
+
/* @__PURE__ */ jsx19(Button12, { type: "submit", disabled: isSubmitting || !validation.success, children: isSubmitting ? "Creating..." : title })
|
|
2746
2838
|
] })
|
|
2747
2839
|
] })
|
|
2748
2840
|
] }) });
|
|
@@ -2782,31 +2874,31 @@ function ThemeToggle() {
|
|
|
2782
2874
|
|
|
2783
2875
|
// src/front/auth/AuthErrorPage.tsx
|
|
2784
2876
|
import { Card as Card7, CardContent as CardContent7, CardDescription as CardDescription7, CardFooter as CardFooter7, CardHeader as CardHeader7, CardTitle as CardTitle7 } from "@hachej/boring-ui-kit";
|
|
2785
|
-
import { jsx as
|
|
2877
|
+
import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2786
2878
|
function readAuthErrorCode() {
|
|
2787
2879
|
if (typeof window === "undefined") return null;
|
|
2788
2880
|
return new URLSearchParams(window.location.search).get("error");
|
|
2789
2881
|
}
|
|
2790
2882
|
function AuthErrorPage() {
|
|
2791
2883
|
const errorCode = readAuthErrorCode();
|
|
2792
|
-
return /* @__PURE__ */
|
|
2884
|
+
return /* @__PURE__ */ jsx20("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsxs12(Card7, { className: "w-full max-w-sm", children: [
|
|
2793
2885
|
/* @__PURE__ */ jsxs12(CardHeader7, { children: [
|
|
2794
|
-
/* @__PURE__ */
|
|
2795
|
-
/* @__PURE__ */
|
|
2886
|
+
/* @__PURE__ */ jsx20(CardTitle7, { children: "Authentication error" }),
|
|
2887
|
+
/* @__PURE__ */ jsx20(CardDescription7, { children: "We could not complete that authentication flow. Please try again." })
|
|
2796
2888
|
] }),
|
|
2797
|
-
errorCode && /* @__PURE__ */
|
|
2889
|
+
errorCode && /* @__PURE__ */ jsx20(CardContent7, { children: /* @__PURE__ */ jsxs12("p", { className: "text-sm text-muted-foreground break-all", children: [
|
|
2798
2890
|
"Error: ",
|
|
2799
2891
|
errorCode
|
|
2800
2892
|
] }) }),
|
|
2801
2893
|
/* @__PURE__ */ jsxs12(CardFooter7, { className: "flex justify-between gap-4 text-sm", children: [
|
|
2802
|
-
/* @__PURE__ */
|
|
2803
|
-
/* @__PURE__ */
|
|
2894
|
+
/* @__PURE__ */ jsx20("a", { href: routes.signin, className: "text-muted-foreground hover:underline", children: "Back to sign in" }),
|
|
2895
|
+
/* @__PURE__ */ jsx20("a", { href: routes.signup, className: "text-muted-foreground hover:underline", children: "Create account" })
|
|
2804
2896
|
] })
|
|
2805
2897
|
] }) });
|
|
2806
2898
|
}
|
|
2807
2899
|
|
|
2808
2900
|
// src/front/workspace/InvitesPage.tsx
|
|
2809
|
-
import { useCallback as useCallback6, useState as
|
|
2901
|
+
import { useCallback as useCallback6, useState as useState19 } from "react";
|
|
2810
2902
|
import { useQuery as useQuery5, useMutation as useMutation2, useQueryClient as useQueryClient5 } from "@tanstack/react-query";
|
|
2811
2903
|
import {
|
|
2812
2904
|
Button as Button14,
|
|
@@ -2827,7 +2919,7 @@ import {
|
|
|
2827
2919
|
SelectValue,
|
|
2828
2920
|
StatusBadge
|
|
2829
2921
|
} from "@hachej/boring-ui-kit";
|
|
2830
|
-
import { jsx as
|
|
2922
|
+
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2831
2923
|
function invitesQueryKey(workspaceId) {
|
|
2832
2924
|
return ["invites", workspaceId];
|
|
2833
2925
|
}
|
|
@@ -2848,10 +2940,10 @@ function InvitesPage() {
|
|
|
2848
2940
|
const workspace = useCurrentWorkspace();
|
|
2849
2941
|
const role = useWorkspaceRole();
|
|
2850
2942
|
const queryClient = useQueryClient5();
|
|
2851
|
-
const [email, setEmail] =
|
|
2852
|
-
const [inviteRole, setInviteRole] =
|
|
2853
|
-
const [formError, setFormError] =
|
|
2854
|
-
const [successMessage, setSuccessMessage] =
|
|
2943
|
+
const [email, setEmail] = useState19("");
|
|
2944
|
+
const [inviteRole, setInviteRole] = useState19("editor");
|
|
2945
|
+
const [formError, setFormError] = useState19(null);
|
|
2946
|
+
const [successMessage, setSuccessMessage] = useState19(null);
|
|
2855
2947
|
const workspaceId = workspace?.id ?? "";
|
|
2856
2948
|
const encodedWorkspaceId = encodeURIComponent(workspaceId);
|
|
2857
2949
|
const invitesQuery = useQuery5({
|
|
@@ -2887,7 +2979,7 @@ function InvitesPage() {
|
|
|
2887
2979
|
setFormError(detail.message);
|
|
2888
2980
|
}
|
|
2889
2981
|
});
|
|
2890
|
-
const [revokeError, setRevokeError] =
|
|
2982
|
+
const [revokeError, setRevokeError] = useState19(null);
|
|
2891
2983
|
const revokeMutation = useMutation2({
|
|
2892
2984
|
mutationFn: async (inviteId) => {
|
|
2893
2985
|
await apiFetch(
|
|
@@ -2919,15 +3011,15 @@ function InvitesPage() {
|
|
|
2919
3011
|
[email, inviteRole, createMutation]
|
|
2920
3012
|
);
|
|
2921
3013
|
if (role !== "owner") {
|
|
2922
|
-
return /* @__PURE__ */
|
|
2923
|
-
/* @__PURE__ */
|
|
2924
|
-
/* @__PURE__ */
|
|
3014
|
+
return /* @__PURE__ */ jsx21("div", { className: "flex min-h-screen items-center justify-center p-4", children: /* @__PURE__ */ jsx21(Card8, { className: "w-full max-w-md", children: /* @__PURE__ */ jsxs13(CardHeader8, { children: [
|
|
3015
|
+
/* @__PURE__ */ jsx21(CardTitle8, { children: "Access denied" }),
|
|
3016
|
+
/* @__PURE__ */ jsx21(CardDescription8, { children: "Only workspace owners can manage invites." })
|
|
2925
3017
|
] }) }) });
|
|
2926
3018
|
}
|
|
2927
|
-
return /* @__PURE__ */
|
|
3019
|
+
return /* @__PURE__ */ jsx21("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
3020
|
/* @__PURE__ */ jsxs13(Card8, { children: [
|
|
2929
3021
|
/* @__PURE__ */ jsxs13(CardHeader8, { children: [
|
|
2930
|
-
/* @__PURE__ */
|
|
3022
|
+
/* @__PURE__ */ jsx21(CardTitle8, { children: "Invite a member" }),
|
|
2931
3023
|
/* @__PURE__ */ jsxs13(CardDescription8, { children: [
|
|
2932
3024
|
"Send an invite to join ",
|
|
2933
3025
|
workspace?.name ?? "this workspace",
|
|
@@ -2936,11 +3028,11 @@ function InvitesPage() {
|
|
|
2936
3028
|
] }),
|
|
2937
3029
|
/* @__PURE__ */ jsxs13("form", { onSubmit: handleSubmit, "data-testid": "invite-form", children: [
|
|
2938
3030
|
/* @__PURE__ */ jsxs13(CardContent8, { className: "space-y-4", children: [
|
|
2939
|
-
formError && /* @__PURE__ */
|
|
2940
|
-
successMessage && /* @__PURE__ */
|
|
3031
|
+
formError && /* @__PURE__ */ jsx21(Notice3, { role: "alert", tone: "error", description: formError }),
|
|
3032
|
+
successMessage && /* @__PURE__ */ jsx21(Notice3, { role: "status", tone: "success", description: successMessage }),
|
|
2941
3033
|
/* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
|
|
2942
|
-
/* @__PURE__ */
|
|
2943
|
-
/* @__PURE__ */
|
|
3034
|
+
/* @__PURE__ */ jsx21(Label9, { htmlFor: "invite-email", children: "Email address" }),
|
|
3035
|
+
/* @__PURE__ */ jsx21(
|
|
2944
3036
|
Input9,
|
|
2945
3037
|
{
|
|
2946
3038
|
id: "invite-email",
|
|
@@ -2953,18 +3045,18 @@ function InvitesPage() {
|
|
|
2953
3045
|
)
|
|
2954
3046
|
] }),
|
|
2955
3047
|
/* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
|
|
2956
|
-
/* @__PURE__ */
|
|
3048
|
+
/* @__PURE__ */ jsx21(Label9, { htmlFor: "invite-role", children: "Role" }),
|
|
2957
3049
|
/* @__PURE__ */ jsxs13(Select, { value: inviteRole, onValueChange: (value) => setInviteRole(value), children: [
|
|
2958
|
-
/* @__PURE__ */
|
|
3050
|
+
/* @__PURE__ */ jsx21(SelectTrigger, { id: "invite-role", "data-testid": "invite-role-select", children: /* @__PURE__ */ jsx21(SelectValue, { placeholder: "Select role" }) }),
|
|
2959
3051
|
/* @__PURE__ */ jsxs13(SelectContent, { children: [
|
|
2960
|
-
/* @__PURE__ */
|
|
2961
|
-
/* @__PURE__ */
|
|
2962
|
-
/* @__PURE__ */
|
|
3052
|
+
/* @__PURE__ */ jsx21(SelectItem, { value: "editor", children: "Editor" }),
|
|
3053
|
+
/* @__PURE__ */ jsx21(SelectItem, { value: "viewer", children: "Viewer" }),
|
|
3054
|
+
/* @__PURE__ */ jsx21(SelectItem, { value: "owner", children: "Owner" })
|
|
2963
3055
|
] })
|
|
2964
3056
|
] })
|
|
2965
3057
|
] })
|
|
2966
3058
|
] }),
|
|
2967
|
-
/* @__PURE__ */
|
|
3059
|
+
/* @__PURE__ */ jsx21(CardFooter8, { children: /* @__PURE__ */ jsx21(
|
|
2968
3060
|
Button14,
|
|
2969
3061
|
{
|
|
2970
3062
|
type: "submit",
|
|
@@ -2977,14 +3069,14 @@ function InvitesPage() {
|
|
|
2977
3069
|
] }),
|
|
2978
3070
|
/* @__PURE__ */ jsxs13(Card8, { children: [
|
|
2979
3071
|
/* @__PURE__ */ jsxs13(CardHeader8, { children: [
|
|
2980
|
-
/* @__PURE__ */
|
|
2981
|
-
/* @__PURE__ */
|
|
3072
|
+
/* @__PURE__ */ jsx21(CardTitle8, { children: "Pending invites" }),
|
|
3073
|
+
/* @__PURE__ */ jsx21(CardDescription8, { children: invitesQuery.data?.length ? `${invitesQuery.data.length} invite${invitesQuery.data.length === 1 ? "" : "s"}` : "No invites yet" })
|
|
2982
3074
|
] }),
|
|
2983
3075
|
/* @__PURE__ */ jsxs13(CardContent8, { children: [
|
|
2984
|
-
revokeError && /* @__PURE__ */
|
|
2985
|
-
invitesQuery.isLoading && /* @__PURE__ */
|
|
2986
|
-
invitesQuery.isError && /* @__PURE__ */
|
|
2987
|
-
invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */
|
|
3076
|
+
revokeError && /* @__PURE__ */ jsx21(Notice3, { role: "alert", tone: "error", className: "mb-4", description: revokeError }),
|
|
3077
|
+
invitesQuery.isLoading && /* @__PURE__ */ jsx21(LoadingState2, {}),
|
|
3078
|
+
invitesQuery.isError && /* @__PURE__ */ jsx21(Notice3, { tone: "error", description: "Failed to load invites." }),
|
|
3079
|
+
invitesQuery.data && invitesQuery.data.length > 0 && /* @__PURE__ */ jsx21("div", { className: "divide-y", "data-testid": "invites-list", children: invitesQuery.data.map((invite) => {
|
|
2988
3080
|
const status = getInviteStatus(invite);
|
|
2989
3081
|
return /* @__PURE__ */ jsxs13(
|
|
2990
3082
|
"div",
|
|
@@ -2993,10 +3085,10 @@ function InvitesPage() {
|
|
|
2993
3085
|
"data-testid": `invite-row-${invite.id}`,
|
|
2994
3086
|
children: [
|
|
2995
3087
|
/* @__PURE__ */ jsxs13("div", { className: "space-y-1", children: [
|
|
2996
|
-
/* @__PURE__ */
|
|
3088
|
+
/* @__PURE__ */ jsx21("p", { className: "text-sm font-medium", children: invite.email }),
|
|
2997
3089
|
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
2998
|
-
/* @__PURE__ */
|
|
2999
|
-
/* @__PURE__ */
|
|
3090
|
+
/* @__PURE__ */ jsx21("span", { children: invite.role }),
|
|
3091
|
+
/* @__PURE__ */ jsx21(StatusBadge, { "data-testid": `status-${status}`, tone: STATUS_TONES[status] ?? "neutral", children: status }),
|
|
3000
3092
|
/* @__PURE__ */ jsxs13("span", { children: [
|
|
3001
3093
|
"expires",
|
|
3002
3094
|
" ",
|
|
@@ -3004,7 +3096,7 @@ function InvitesPage() {
|
|
|
3004
3096
|
] })
|
|
3005
3097
|
] })
|
|
3006
3098
|
] }),
|
|
3007
|
-
status === "pending" && /* @__PURE__ */
|
|
3099
|
+
status === "pending" && /* @__PURE__ */ jsx21(
|
|
3008
3100
|
Button14,
|
|
3009
3101
|
{
|
|
3010
3102
|
variant: "destructive",
|
|
@@ -3026,7 +3118,7 @@ function InvitesPage() {
|
|
|
3026
3118
|
}
|
|
3027
3119
|
|
|
3028
3120
|
// src/front/workspace/MembersPage.tsx
|
|
3029
|
-
import { useCallback as useCallback7, useState as
|
|
3121
|
+
import { useCallback as useCallback7, useState as useState20 } from "react";
|
|
3030
3122
|
import { useMutation as useMutation3, useQueryClient as useQueryClient6 } from "@tanstack/react-query";
|
|
3031
3123
|
import {
|
|
3032
3124
|
AlertDialog as AlertDialog2,
|
|
@@ -3051,7 +3143,7 @@ import {
|
|
|
3051
3143
|
LoadingState as LoadingState3,
|
|
3052
3144
|
Notice as Notice4
|
|
3053
3145
|
} from "@hachej/boring-ui-kit";
|
|
3054
|
-
import { jsx as
|
|
3146
|
+
import { jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3055
3147
|
var ROLE_OPTIONS = ["owner", "editor", "viewer"];
|
|
3056
3148
|
function MembersPage() {
|
|
3057
3149
|
const workspace = useCurrentWorkspace();
|
|
@@ -3062,8 +3154,8 @@ function MembersPage() {
|
|
|
3062
3154
|
const currentUserId = session.data?.user?.id ?? "";
|
|
3063
3155
|
const encodedWorkspaceId = encodeURIComponent(workspaceId);
|
|
3064
3156
|
const membersQuery = useWorkspaceMembers(workspaceId);
|
|
3065
|
-
const [toast, setToast] =
|
|
3066
|
-
const [confirmTarget, setConfirmTarget] =
|
|
3157
|
+
const [toast, setToast] = useState20(null);
|
|
3158
|
+
const [confirmTarget, setConfirmTarget] = useState20(null);
|
|
3067
3159
|
const showToast = useCallback7((msg) => {
|
|
3068
3160
|
setToast(msg);
|
|
3069
3161
|
setTimeout(() => setToast(null), 4e3);
|
|
@@ -3124,10 +3216,10 @@ function MembersPage() {
|
|
|
3124
3216
|
removeMutation.mutate(confirmTarget.userId);
|
|
3125
3217
|
}, [confirmTarget, removeMutation]);
|
|
3126
3218
|
const isOwner = myRole === "owner";
|
|
3127
|
-
return /* @__PURE__ */
|
|
3219
|
+
return /* @__PURE__ */ jsx22("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
3220
|
/* @__PURE__ */ jsxs14(Card9, { children: [
|
|
3129
3221
|
/* @__PURE__ */ jsxs14(CardHeader9, { children: [
|
|
3130
|
-
/* @__PURE__ */
|
|
3222
|
+
/* @__PURE__ */ jsx22(CardTitle9, { children: "Members" }),
|
|
3131
3223
|
/* @__PURE__ */ jsxs14(CardDescription9, { children: [
|
|
3132
3224
|
workspace?.name ?? "Workspace",
|
|
3133
3225
|
" \xB7",
|
|
@@ -3138,10 +3230,10 @@ function MembersPage() {
|
|
|
3138
3230
|
] })
|
|
3139
3231
|
] }),
|
|
3140
3232
|
/* @__PURE__ */ jsxs14(CardContent9, { children: [
|
|
3141
|
-
toast && /* @__PURE__ */
|
|
3142
|
-
membersQuery.isLoading && /* @__PURE__ */
|
|
3143
|
-
membersQuery.isError && /* @__PURE__ */
|
|
3144
|
-
membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */
|
|
3233
|
+
toast && /* @__PURE__ */ jsx22(Notice4, { role: "alert", "data-testid": "toast", tone: "error", className: "mb-4", description: toast }),
|
|
3234
|
+
membersQuery.isLoading && /* @__PURE__ */ jsx22(LoadingState3, {}),
|
|
3235
|
+
membersQuery.isError && /* @__PURE__ */ jsx22(Notice4, { tone: "error", description: "Failed to load members." }),
|
|
3236
|
+
membersQuery.data && membersQuery.data.length > 0 && /* @__PURE__ */ jsx22("div", { className: "divide-y", "data-testid": "members-list", children: membersQuery.data.map((member) => {
|
|
3145
3237
|
const isSelf = member.userId === currentUserId;
|
|
3146
3238
|
const canChangeRole = isOwner && !isSelf;
|
|
3147
3239
|
const canRemove = isOwner || isSelf;
|
|
@@ -3152,13 +3244,13 @@ function MembersPage() {
|
|
|
3152
3244
|
"data-testid": `member-row-${member.userId}`,
|
|
3153
3245
|
children: [
|
|
3154
3246
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3", children: [
|
|
3155
|
-
/* @__PURE__ */
|
|
3247
|
+
/* @__PURE__ */ jsx22(InitialsAvatar, { initials: (member.user.name?.[0] ?? member.user.email[0]).toUpperCase() }),
|
|
3156
3248
|
/* @__PURE__ */ jsxs14("div", { children: [
|
|
3157
3249
|
/* @__PURE__ */ jsxs14("p", { className: "text-sm font-medium", children: [
|
|
3158
3250
|
member.user.name ?? member.user.email,
|
|
3159
|
-
isSelf && /* @__PURE__ */
|
|
3251
|
+
isSelf && /* @__PURE__ */ jsx22("span", { className: "ml-1 text-xs text-muted-foreground", children: "(you)" })
|
|
3160
3252
|
] }),
|
|
3161
|
-
/* @__PURE__ */
|
|
3253
|
+
/* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground", children: member.user.email })
|
|
3162
3254
|
] })
|
|
3163
3255
|
] }),
|
|
3164
3256
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
|
|
@@ -3169,12 +3261,12 @@ function MembersPage() {
|
|
|
3169
3261
|
disabled: !canChangeRole,
|
|
3170
3262
|
onValueChange: (value) => handleRoleChange(member.userId, value),
|
|
3171
3263
|
children: [
|
|
3172
|
-
/* @__PURE__ */
|
|
3173
|
-
/* @__PURE__ */
|
|
3264
|
+
/* @__PURE__ */ jsx22(SelectTrigger2, { "data-testid": `role-select-${member.userId}`, className: "h-8 w-28 text-xs", children: /* @__PURE__ */ jsx22(SelectValue2, { placeholder: "Role" }) }),
|
|
3265
|
+
/* @__PURE__ */ jsx22(SelectContent2, { children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx22(SelectItem2, { value: r, children: r }, r)) })
|
|
3174
3266
|
]
|
|
3175
3267
|
}
|
|
3176
3268
|
),
|
|
3177
|
-
canRemove && /* @__PURE__ */
|
|
3269
|
+
canRemove && /* @__PURE__ */ jsx22(
|
|
3178
3270
|
Button15,
|
|
3179
3271
|
{
|
|
3180
3272
|
variant: "destructive",
|
|
@@ -3192,7 +3284,7 @@ function MembersPage() {
|
|
|
3192
3284
|
}) })
|
|
3193
3285
|
] })
|
|
3194
3286
|
] }),
|
|
3195
|
-
/* @__PURE__ */
|
|
3287
|
+
/* @__PURE__ */ jsx22(
|
|
3196
3288
|
AlertDialog2,
|
|
3197
3289
|
{
|
|
3198
3290
|
open: confirmTarget !== null,
|
|
@@ -3201,12 +3293,12 @@ function MembersPage() {
|
|
|
3201
3293
|
},
|
|
3202
3294
|
children: /* @__PURE__ */ jsxs14(AlertDialogContent2, { children: [
|
|
3203
3295
|
/* @__PURE__ */ jsxs14(AlertDialogHeader2, { children: [
|
|
3204
|
-
/* @__PURE__ */
|
|
3205
|
-
/* @__PURE__ */
|
|
3296
|
+
/* @__PURE__ */ jsx22(AlertDialogTitle2, { children: confirmTarget?.userId === currentUserId ? "Leave workspace?" : `Remove ${confirmTarget?.user.name ?? confirmTarget?.user.email}?` }),
|
|
3297
|
+
/* @__PURE__ */ jsx22(AlertDialogDescription2, { children: confirmTarget?.userId === currentUserId ? "You will lose access to this workspace." : "This member will lose access to the workspace." })
|
|
3206
3298
|
] }),
|
|
3207
3299
|
/* @__PURE__ */ jsxs14(AlertDialogFooter2, { children: [
|
|
3208
|
-
/* @__PURE__ */
|
|
3209
|
-
/* @__PURE__ */
|
|
3300
|
+
/* @__PURE__ */ jsx22(AlertDialogCancel2, { children: "Cancel" }),
|
|
3301
|
+
/* @__PURE__ */ jsx22(
|
|
3210
3302
|
Button15,
|
|
3211
3303
|
{
|
|
3212
3304
|
variant: "destructive",
|
|
@@ -3224,7 +3316,7 @@ function MembersPage() {
|
|
|
3224
3316
|
}
|
|
3225
3317
|
|
|
3226
3318
|
// src/front/workspace/WorkspaceSettingsPage.tsx
|
|
3227
|
-
import { useCallback as useCallback8, useEffect as
|
|
3319
|
+
import { useCallback as useCallback8, useEffect as useEffect11, useState as useState21 } from "react";
|
|
3228
3320
|
import { useQuery as useQuery6, useMutation as useMutation4, useQueryClient as useQueryClient7 } from "@tanstack/react-query";
|
|
3229
3321
|
import { useNavigate as useNavigate5 } from "react-router-dom";
|
|
3230
3322
|
import {
|
|
@@ -3254,7 +3346,7 @@ import {
|
|
|
3254
3346
|
ShieldAlert as ShieldAlert2,
|
|
3255
3347
|
Trash2 as Trash22
|
|
3256
3348
|
} from "lucide-react";
|
|
3257
|
-
import { Fragment as Fragment5, jsx as
|
|
3349
|
+
import { Fragment as Fragment5, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3258
3350
|
var STATE_TONES = {
|
|
3259
3351
|
pending: "info",
|
|
3260
3352
|
ready: "success",
|
|
@@ -3266,13 +3358,13 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
|
|
|
3266
3358
|
const appInitial = (appTitle.trim().charAt(0) || "B").toUpperCase();
|
|
3267
3359
|
const navigate = useNavigate5();
|
|
3268
3360
|
const workspaceHref = workspaceId ? `/workspace/${encodeURIComponent(workspaceId)}` : "/";
|
|
3269
|
-
return /* @__PURE__ */
|
|
3361
|
+
return /* @__PURE__ */ jsx23(
|
|
3270
3362
|
"header",
|
|
3271
3363
|
{
|
|
3272
3364
|
className: "relative flex h-[52px] items-center justify-between gap-3 border-b border-border/40 bg-background px-4",
|
|
3273
3365
|
"aria-label": "App top bar",
|
|
3274
3366
|
children: /* @__PURE__ */ jsxs15("div", { className: "flex min-w-0 flex-1 items-center gap-2.5", children: [
|
|
3275
|
-
/* @__PURE__ */
|
|
3367
|
+
/* @__PURE__ */ jsx23(
|
|
3276
3368
|
IconButton,
|
|
3277
3369
|
{
|
|
3278
3370
|
type: "button",
|
|
@@ -3285,11 +3377,11 @@ function SettingsTopBar2({ workspaceId, workspaceName }) {
|
|
|
3285
3377
|
children: appInitial
|
|
3286
3378
|
}
|
|
3287
3379
|
),
|
|
3288
|
-
/* @__PURE__ */
|
|
3289
|
-
/* @__PURE__ */
|
|
3290
|
-
/* @__PURE__ */
|
|
3291
|
-
/* @__PURE__ */
|
|
3292
|
-
/* @__PURE__ */
|
|
3380
|
+
/* @__PURE__ */ jsx23("span", { className: "truncate text-[13px] font-medium tracking-tight text-foreground", children: appTitle }),
|
|
3381
|
+
/* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
3382
|
+
/* @__PURE__ */ jsx23("span", { className: "truncate text-[13px] text-muted-foreground", children: workspaceName }),
|
|
3383
|
+
/* @__PURE__ */ jsx23("span", { "aria-hidden": "true", className: "text-muted-foreground/30", children: "/" }),
|
|
3384
|
+
/* @__PURE__ */ jsx23("span", { className: "truncate text-[13px] text-muted-foreground", children: "Settings" })
|
|
3293
3385
|
] })
|
|
3294
3386
|
}
|
|
3295
3387
|
);
|
|
@@ -3302,24 +3394,24 @@ function SettingsPageHeader2({
|
|
|
3302
3394
|
}) {
|
|
3303
3395
|
return /* @__PURE__ */ jsxs15("header", { className: "boring-settings-page-header", children: [
|
|
3304
3396
|
/* @__PURE__ */ jsxs15("div", { className: "boring-settings-context", children: [
|
|
3305
|
-
/* @__PURE__ */
|
|
3397
|
+
/* @__PURE__ */ jsx23("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
3398
|
/* @__PURE__ */ jsxs15("div", { className: "min-w-0 flex-1", children: [
|
|
3307
|
-
/* @__PURE__ */
|
|
3399
|
+
/* @__PURE__ */ jsx23("p", { className: "truncate text-[13px] font-medium text-foreground", children: workspaceName }),
|
|
3308
3400
|
/* @__PURE__ */ jsxs15("div", { className: "mt-1 flex flex-wrap items-center gap-1.5", children: [
|
|
3309
|
-
/* @__PURE__ */
|
|
3310
|
-
isDefault ? /* @__PURE__ */
|
|
3401
|
+
/* @__PURE__ */ jsx23("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: roleLabel(role) }),
|
|
3402
|
+
isDefault ? /* @__PURE__ */ jsx23("span", { className: "inline-flex h-5 items-center rounded border border-border/60 px-1.5 text-[11px] text-muted-foreground", children: "Default" }) : null
|
|
3311
3403
|
] })
|
|
3312
3404
|
] })
|
|
3313
3405
|
] }),
|
|
3314
3406
|
/* @__PURE__ */ jsxs15("div", { className: "max-w-2xl", children: [
|
|
3315
|
-
/* @__PURE__ */
|
|
3316
|
-
/* @__PURE__ */
|
|
3317
|
-
/* @__PURE__ */
|
|
3407
|
+
/* @__PURE__ */ jsx23("p", { className: "text-[11px] font-medium uppercase leading-4 text-muted-foreground", children: "Workspace" }),
|
|
3408
|
+
/* @__PURE__ */ jsx23("h1", { className: "mt-1 text-[20px] font-semibold leading-7 tracking-tight text-foreground", children: "Workspace settings" }),
|
|
3409
|
+
/* @__PURE__ */ jsx23("p", { className: "mt-2 text-[13px] leading-5 text-muted-foreground", children: "Manage workspace identity, runtime recovery, and irreversible workspace actions." })
|
|
3318
3410
|
] })
|
|
3319
3411
|
] });
|
|
3320
3412
|
}
|
|
3321
3413
|
function FieldNote({ children }) {
|
|
3322
|
-
return /* @__PURE__ */
|
|
3414
|
+
return /* @__PURE__ */ jsx23("p", { className: "text-[12px] leading-5 text-muted-foreground", children });
|
|
3323
3415
|
}
|
|
3324
3416
|
function roleLabel(role) {
|
|
3325
3417
|
if (!role) return "Loading role";
|
|
@@ -3337,14 +3429,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3337
3429
|
const queryClient = useQueryClient7();
|
|
3338
3430
|
const navigate = useNavigate5();
|
|
3339
3431
|
const workspaceId = workspace?.id ?? "";
|
|
3340
|
-
const [nameValue, setNameValue] =
|
|
3341
|
-
const [nameError, setNameError] =
|
|
3342
|
-
const [retryError, setRetryError] =
|
|
3343
|
-
const [deleteConfirmName, setDeleteConfirmName] =
|
|
3344
|
-
const [deleteDialogOpen, setDeleteDialogOpen] =
|
|
3345
|
-
const [deleteError, setDeleteError] =
|
|
3346
|
-
const [imageUploadDirValue, setImageUploadDirValue] =
|
|
3347
|
-
const [fileSettingsError, setFileSettingsError] =
|
|
3432
|
+
const [nameValue, setNameValue] = useState21(null);
|
|
3433
|
+
const [nameError, setNameError] = useState21(null);
|
|
3434
|
+
const [retryError, setRetryError] = useState21(null);
|
|
3435
|
+
const [deleteConfirmName, setDeleteConfirmName] = useState21("");
|
|
3436
|
+
const [deleteDialogOpen, setDeleteDialogOpen] = useState21(false);
|
|
3437
|
+
const [deleteError, setDeleteError] = useState21(null);
|
|
3438
|
+
const [imageUploadDirValue, setImageUploadDirValue] = useState21(null);
|
|
3439
|
+
const [fileSettingsError, setFileSettingsError] = useState21(null);
|
|
3348
3440
|
const displayName = nameValue ?? workspace?.name ?? "";
|
|
3349
3441
|
const encodedWorkspaceId = encodeURIComponent(workspaceId);
|
|
3350
3442
|
const requestHeaders = workspaceId ? { "x-boring-workspace-id": workspaceId } : void 0;
|
|
@@ -3382,7 +3474,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3382
3474
|
enabled: workspaceId.length > 0,
|
|
3383
3475
|
retry: false
|
|
3384
3476
|
});
|
|
3385
|
-
|
|
3477
|
+
useEffect11(() => {
|
|
3386
3478
|
const next = fileSettingsQuery.data?.markdown?.imageUploadDir;
|
|
3387
3479
|
if (typeof next === "string") setImageUploadDirValue(next);
|
|
3388
3480
|
}, [fileSettingsQuery.data?.markdown?.imageUploadDir]);
|
|
@@ -3490,7 +3582,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3490
3582
|
const canDeleteWorkspace = role === "owner" || role === null;
|
|
3491
3583
|
const workspaceName = workspace?.name ?? "Workspace";
|
|
3492
3584
|
const workspaceInitial2 = (workspace?.name?.trim()?.[0] ?? "W").toUpperCase();
|
|
3493
|
-
const topBarNode = topBar === void 0 ? /* @__PURE__ */
|
|
3585
|
+
const topBarNode = topBar === void 0 ? /* @__PURE__ */ jsx23(SettingsTopBar2, { workspaceId, workspaceName }) : topBar;
|
|
3494
3586
|
const navItems = WORKSPACE_NAV_ITEMS.filter((item) => {
|
|
3495
3587
|
if (item.href === "#runtime") return hasRuntime;
|
|
3496
3588
|
if (item.href === "#files") return hasFileSettings;
|
|
@@ -3498,10 +3590,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3498
3590
|
});
|
|
3499
3591
|
return /* @__PURE__ */ jsxs15("main", { className: "boring-settings-shell", children: [
|
|
3500
3592
|
topBarNode,
|
|
3501
|
-
/* @__PURE__ */
|
|
3502
|
-
/* @__PURE__ */
|
|
3593
|
+
/* @__PURE__ */ jsx23("div", { className: "boring-settings-scroll", children: /* @__PURE__ */ jsxs15("div", { className: "boring-settings-layout", children: [
|
|
3594
|
+
/* @__PURE__ */ jsx23("aside", { className: "boring-settings-sidebar", children: /* @__PURE__ */ jsx23(UiSettingsNav2, { label: "Workspace settings", items: navItems }) }),
|
|
3503
3595
|
/* @__PURE__ */ jsxs15("div", { className: "boring-settings-content space-y-4", children: [
|
|
3504
|
-
/* @__PURE__ */
|
|
3596
|
+
/* @__PURE__ */ jsx23(
|
|
3505
3597
|
SettingsPageHeader2,
|
|
3506
3598
|
{
|
|
3507
3599
|
workspaceName,
|
|
@@ -3510,15 +3602,15 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3510
3602
|
isDefault: Boolean(workspace?.isDefault)
|
|
3511
3603
|
}
|
|
3512
3604
|
),
|
|
3513
|
-
/* @__PURE__ */
|
|
3605
|
+
/* @__PURE__ */ jsx23(
|
|
3514
3606
|
UiSettingsPanel2,
|
|
3515
3607
|
{
|
|
3516
3608
|
id: "general",
|
|
3517
|
-
icon: /* @__PURE__ */
|
|
3609
|
+
icon: /* @__PURE__ */ jsx23(Settings22, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3518
3610
|
title: "General",
|
|
3519
3611
|
description: "Keep the workspace name clear enough to scan in menus.",
|
|
3520
3612
|
footer: /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
3521
|
-
nameChanged ? /* @__PURE__ */
|
|
3613
|
+
nameChanged ? /* @__PURE__ */ jsx23(
|
|
3522
3614
|
Button16,
|
|
3523
3615
|
{
|
|
3524
3616
|
type: "button",
|
|
@@ -3532,7 +3624,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3532
3624
|
children: "Reset"
|
|
3533
3625
|
}
|
|
3534
3626
|
) : null,
|
|
3535
|
-
/* @__PURE__ */
|
|
3627
|
+
/* @__PURE__ */ jsx23(
|
|
3536
3628
|
Button16,
|
|
3537
3629
|
{
|
|
3538
3630
|
"data-testid": "save-name",
|
|
@@ -3544,10 +3636,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3544
3636
|
)
|
|
3545
3637
|
] }),
|
|
3546
3638
|
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
3547
|
-
nameError && /* @__PURE__ */
|
|
3639
|
+
nameError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "name-error", role: "alert", tone: "error", description: nameError }),
|
|
3548
3640
|
/* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
|
|
3549
|
-
/* @__PURE__ */
|
|
3550
|
-
/* @__PURE__ */
|
|
3641
|
+
/* @__PURE__ */ jsx23(Label10, { htmlFor: "workspace-name", className: "text-[12px]", children: "Workspace name" }),
|
|
3642
|
+
/* @__PURE__ */ jsx23(
|
|
3551
3643
|
Input10,
|
|
3552
3644
|
{
|
|
3553
3645
|
id: "workspace-name",
|
|
@@ -3559,23 +3651,23 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3559
3651
|
"aria-invalid": nameError ? "true" : "false"
|
|
3560
3652
|
}
|
|
3561
3653
|
),
|
|
3562
|
-
/* @__PURE__ */
|
|
3654
|
+
/* @__PURE__ */ jsx23(FieldNote, { children: canEditName ? "Editors and owners can rename a workspace." : "Viewers can inspect settings, but cannot rename this workspace." })
|
|
3563
3655
|
] })
|
|
3564
3656
|
] })
|
|
3565
3657
|
}
|
|
3566
3658
|
),
|
|
3567
|
-
hasRuntime && /* @__PURE__ */
|
|
3659
|
+
hasRuntime && /* @__PURE__ */ jsx23(
|
|
3568
3660
|
UiSettingsPanel2,
|
|
3569
3661
|
{
|
|
3570
3662
|
id: "runtime",
|
|
3571
3663
|
testId: "runtime-card",
|
|
3572
|
-
icon: /* @__PURE__ */
|
|
3664
|
+
icon: /* @__PURE__ */ jsx23(HardDrive, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3573
3665
|
title: "Runtime",
|
|
3574
3666
|
description: "Provisioning status for this workspace.",
|
|
3575
3667
|
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-3", children: [
|
|
3576
3668
|
/* @__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__ */
|
|
3578
|
-
/* @__PURE__ */
|
|
3669
|
+
/* @__PURE__ */ jsx23("span", { className: "text-[13px] font-medium", children: "State" }),
|
|
3670
|
+
/* @__PURE__ */ jsx23(StatusBadge2, { "data-testid": `runtime-state-${runtime.state}`, tone: STATE_TONES[runtime.state] ?? "neutral", children: runtime.state })
|
|
3579
3671
|
] }),
|
|
3580
3672
|
runtime.state === "ready" && runtime.volumePath && /* @__PURE__ */ jsxs15(
|
|
3581
3673
|
"div",
|
|
@@ -3583,8 +3675,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3583
3675
|
"data-testid": "volume-path",
|
|
3584
3676
|
className: "space-y-1 rounded-md border border-border/50 bg-muted/10 px-3 py-2",
|
|
3585
3677
|
children: [
|
|
3586
|
-
/* @__PURE__ */
|
|
3587
|
-
/* @__PURE__ */
|
|
3678
|
+
/* @__PURE__ */ jsx23("p", { className: "text-[13px] font-medium", children: "Volume" }),
|
|
3679
|
+
/* @__PURE__ */ jsx23("code", { className: "block overflow-x-auto whitespace-nowrap text-[12px] text-muted-foreground", children: runtime.volumePath })
|
|
3588
3680
|
]
|
|
3589
3681
|
}
|
|
3590
3682
|
),
|
|
@@ -3595,7 +3687,7 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3595
3687
|
role: "alert",
|
|
3596
3688
|
className: "flex gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-[13px] leading-5 text-destructive",
|
|
3597
3689
|
children: [
|
|
3598
|
-
/* @__PURE__ */
|
|
3690
|
+
/* @__PURE__ */ jsx23(AlertCircle, { className: "mt-0.5 h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
3599
3691
|
runtime.lastError
|
|
3600
3692
|
]
|
|
3601
3693
|
}
|
|
@@ -3610,14 +3702,14 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3610
3702
|
disabled: retryMutation.isPending,
|
|
3611
3703
|
onClick: () => retryMutation.mutate(),
|
|
3612
3704
|
children: [
|
|
3613
|
-
/* @__PURE__ */
|
|
3705
|
+
/* @__PURE__ */ jsx23(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
3614
3706
|
retryMutation.isPending ? "Retrying..." : "Retry provisioning"
|
|
3615
3707
|
]
|
|
3616
3708
|
}
|
|
3617
3709
|
),
|
|
3618
|
-
retryError && /* @__PURE__ */
|
|
3710
|
+
retryError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "retry-error", role: "alert", tone: "error", description: retryError })
|
|
3619
3711
|
] }),
|
|
3620
|
-
runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */
|
|
3712
|
+
runtime.state === "error" && runtime.lastErrorOp === "destroy" && /* @__PURE__ */ jsx23(
|
|
3621
3713
|
"p",
|
|
3622
3714
|
{
|
|
3623
3715
|
"data-testid": "destroy-guidance",
|
|
@@ -3628,15 +3720,15 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3628
3720
|
] })
|
|
3629
3721
|
}
|
|
3630
3722
|
),
|
|
3631
|
-
hasFileSettings && /* @__PURE__ */
|
|
3723
|
+
hasFileSettings && /* @__PURE__ */ jsx23(
|
|
3632
3724
|
UiSettingsPanel2,
|
|
3633
3725
|
{
|
|
3634
3726
|
id: "files",
|
|
3635
3727
|
testId: "file-settings-card",
|
|
3636
|
-
icon: /* @__PURE__ */
|
|
3728
|
+
icon: /* @__PURE__ */ jsx23(FileImage, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3637
3729
|
title: "Files",
|
|
3638
3730
|
description: "Configure where markdown editor image uploads are stored. Direct/local workspaces can also edit .boring/settings.",
|
|
3639
|
-
footer: /* @__PURE__ */
|
|
3731
|
+
footer: /* @__PURE__ */ jsx23(
|
|
3640
3732
|
Button16,
|
|
3641
3733
|
{
|
|
3642
3734
|
"data-testid": "save-file-settings",
|
|
@@ -3647,10 +3739,10 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3647
3739
|
}
|
|
3648
3740
|
),
|
|
3649
3741
|
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
3650
|
-
fileSettingsError && /* @__PURE__ */
|
|
3742
|
+
fileSettingsError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "file-settings-error", role: "alert", tone: "error", description: fileSettingsError }),
|
|
3651
3743
|
/* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
|
|
3652
|
-
/* @__PURE__ */
|
|
3653
|
-
/* @__PURE__ */
|
|
3744
|
+
/* @__PURE__ */ jsx23(Label10, { htmlFor: "markdown-image-upload-dir", className: "text-[12px]", children: "Markdown image upload path" }),
|
|
3745
|
+
/* @__PURE__ */ jsx23(
|
|
3654
3746
|
Input10,
|
|
3655
3747
|
{
|
|
3656
3748
|
id: "markdown-image-upload-dir",
|
|
@@ -3663,26 +3755,26 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3663
3755
|
),
|
|
3664
3756
|
/* @__PURE__ */ jsxs15(FieldNote, { children: [
|
|
3665
3757
|
"Relative workspace path used by markdown image uploads. Stored in ",
|
|
3666
|
-
/* @__PURE__ */
|
|
3758
|
+
/* @__PURE__ */ jsx23("code", { children: ".boring/settings" }),
|
|
3667
3759
|
"."
|
|
3668
3760
|
] })
|
|
3669
3761
|
] })
|
|
3670
3762
|
] })
|
|
3671
3763
|
}
|
|
3672
3764
|
),
|
|
3673
|
-
/* @__PURE__ */
|
|
3765
|
+
/* @__PURE__ */ jsx23(
|
|
3674
3766
|
UiSettingsPanel2,
|
|
3675
3767
|
{
|
|
3676
3768
|
id: "danger-zone",
|
|
3677
3769
|
testId: "danger-zone",
|
|
3678
|
-
icon: /* @__PURE__ */
|
|
3770
|
+
icon: /* @__PURE__ */ jsx23(ShieldAlert2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
3679
3771
|
title: "Danger zone",
|
|
3680
3772
|
description: "Permanently delete this workspace and all provisioned data.",
|
|
3681
3773
|
danger: true,
|
|
3682
3774
|
children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
|
|
3683
|
-
deleteError && /* @__PURE__ */
|
|
3684
|
-
!canDeleteWorkspace ? /* @__PURE__ */
|
|
3685
|
-
/* @__PURE__ */
|
|
3775
|
+
deleteError && /* @__PURE__ */ jsx23(Notice5, { "data-testid": "delete-error", role: "alert", tone: "error", description: deleteError }),
|
|
3776
|
+
!canDeleteWorkspace ? /* @__PURE__ */ jsx23("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,
|
|
3777
|
+
/* @__PURE__ */ jsx23(
|
|
3686
3778
|
UiSettingsActionRow2,
|
|
3687
3779
|
{
|
|
3688
3780
|
title: "Delete workspace",
|
|
@@ -3700,21 +3792,21 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3700
3792
|
setDeleteConfirmName("");
|
|
3701
3793
|
},
|
|
3702
3794
|
children: [
|
|
3703
|
-
/* @__PURE__ */
|
|
3795
|
+
/* @__PURE__ */ jsx23(Trash22, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
3704
3796
|
"Delete workspace"
|
|
3705
3797
|
]
|
|
3706
3798
|
}
|
|
3707
3799
|
),
|
|
3708
3800
|
/* @__PURE__ */ jsxs15(AlertDialogContent3, { children: [
|
|
3709
3801
|
/* @__PURE__ */ jsxs15(AlertDialogHeader3, { children: [
|
|
3710
|
-
/* @__PURE__ */
|
|
3802
|
+
/* @__PURE__ */ jsx23(AlertDialogTitle3, { children: "Delete workspace?" }),
|
|
3711
3803
|
/* @__PURE__ */ jsxs15(AlertDialogDescription3, { children: [
|
|
3712
3804
|
"This action cannot be undone. Type ",
|
|
3713
|
-
/* @__PURE__ */
|
|
3805
|
+
/* @__PURE__ */ jsx23("strong", { children: workspace?.name }),
|
|
3714
3806
|
" to confirm."
|
|
3715
3807
|
] })
|
|
3716
3808
|
] }),
|
|
3717
|
-
/* @__PURE__ */
|
|
3809
|
+
/* @__PURE__ */ jsx23("div", { className: "px-6 pb-2", children: /* @__PURE__ */ jsx23(
|
|
3718
3810
|
Input10,
|
|
3719
3811
|
{
|
|
3720
3812
|
"data-testid": "delete-confirm-input",
|
|
@@ -3726,8 +3818,8 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3726
3818
|
}
|
|
3727
3819
|
) }),
|
|
3728
3820
|
/* @__PURE__ */ jsxs15(AlertDialogFooter3, { children: [
|
|
3729
|
-
/* @__PURE__ */
|
|
3730
|
-
/* @__PURE__ */
|
|
3821
|
+
/* @__PURE__ */ jsx23(AlertDialogCancel3, { children: "Cancel" }),
|
|
3822
|
+
/* @__PURE__ */ jsx23(
|
|
3731
3823
|
Button16,
|
|
3732
3824
|
{
|
|
3733
3825
|
variant: "destructive",
|
|
@@ -3751,11 +3843,65 @@ function WorkspaceSettingsPage({ topBar } = {}) {
|
|
|
3751
3843
|
] });
|
|
3752
3844
|
}
|
|
3753
3845
|
|
|
3846
|
+
// src/front/workspace/CompanyAdminPage.tsx
|
|
3847
|
+
import { Navigate } from "react-router-dom";
|
|
3848
|
+
import { Button as Button17 } from "@hachej/boring-ui-kit";
|
|
3849
|
+
import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3850
|
+
var DEFAULT_PAGE_TITLE = "Admin";
|
|
3851
|
+
var DEFAULT_DENIED_MESSAGE = "You do not have access to this page.";
|
|
3852
|
+
function CompanyAdminPage() {
|
|
3853
|
+
const currentWorkspace = useCurrentWorkspace();
|
|
3854
|
+
const routeStatus = useWorkspaceRouteStatus();
|
|
3855
|
+
const companyAdmin = useCompanyAdminStatus();
|
|
3856
|
+
const pageTitle = companyAdmin.labels.pageTitle ?? DEFAULT_PAGE_TITLE;
|
|
3857
|
+
const deniedMessage = companyAdmin.labels.deniedMessage ?? DEFAULT_DENIED_MESSAGE;
|
|
3858
|
+
if (!companyAdmin.configured) return /* @__PURE__ */ jsx24(Navigate, { to: "/", replace: true });
|
|
3859
|
+
if (routeStatus.status === "loading") {
|
|
3860
|
+
return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsx24("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", "aria-busy": "true", children: /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading admin\u2026" }) }) });
|
|
3861
|
+
}
|
|
3862
|
+
if (companyAdmin.configured && companyAdmin.loading && !companyAdmin.status) {
|
|
3863
|
+
return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsx24("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", "aria-busy": "true", children: /* @__PURE__ */ jsx24("p", { className: "text-sm text-muted-foreground", children: "Loading admin status\u2026" }) }) });
|
|
3864
|
+
}
|
|
3865
|
+
if (companyAdmin.error) {
|
|
3866
|
+
const workspace2 = routeStatus.status === "matched" ? routeStatus.workspace : currentWorkspace;
|
|
3867
|
+
const workspaceId2 = routeStatus.workspaceId ?? workspace2?.id ?? null;
|
|
3868
|
+
return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsxs16("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", children: [
|
|
3869
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-destructive", children: "Admin unavailable" }),
|
|
3870
|
+
/* @__PURE__ */ jsx24("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: pageTitle }),
|
|
3871
|
+
/* @__PURE__ */ jsx24("p", { className: "mt-2 text-sm text-muted-foreground", children: companyAdmin.error }),
|
|
3872
|
+
workspaceId2 ? /* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: routeHref("workspaceSettings", { id: workspaceId2 }), children: "Back to workspace settings" }) }) : /* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: "/", children: "Back to workspace" }) })
|
|
3873
|
+
] }) });
|
|
3874
|
+
}
|
|
3875
|
+
if (!companyAdmin.status || companyAdmin.status.enabled !== true) return /* @__PURE__ */ jsx24(Navigate, { to: "/", replace: true });
|
|
3876
|
+
if (routeStatus.status === "not-found" || routeStatus.status === "switch-failed" || routeStatus.status === "mismatched") {
|
|
3877
|
+
const message = routeStatus.status === "mismatched" ? "The requested workspace could not be loaded." : routeStatus.message;
|
|
3878
|
+
return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsxs16("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", children: [
|
|
3879
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-destructive", children: "Workspace unavailable" }),
|
|
3880
|
+
/* @__PURE__ */ jsx24("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: pageTitle }),
|
|
3881
|
+
/* @__PURE__ */ jsx24("p", { className: "mt-2 text-sm text-muted-foreground", children: message }),
|
|
3882
|
+
/* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: "/", children: "Back to workspace" }) })
|
|
3883
|
+
] }) });
|
|
3884
|
+
}
|
|
3885
|
+
const workspace = routeStatus.status === "matched" ? routeStatus.workspace : currentWorkspace;
|
|
3886
|
+
const workspaceId = routeStatus.workspaceId ?? workspace?.id ?? null;
|
|
3887
|
+
if (!workspaceId) return /* @__PURE__ */ jsx24(Navigate, { to: "/", replace: true });
|
|
3888
|
+
if (routeStatus.status === "forbidden" || companyAdmin.status.admin !== true) {
|
|
3889
|
+
return /* @__PURE__ */ jsx24("main", { className: "mx-auto flex min-h-screen max-w-3xl flex-col justify-center px-6 py-12", children: /* @__PURE__ */ jsxs16("section", { className: "rounded-xl border border-border bg-card p-6 shadow-sm", children: [
|
|
3890
|
+
/* @__PURE__ */ jsx24("p", { className: "text-sm font-medium text-destructive", children: "Access required" }),
|
|
3891
|
+
/* @__PURE__ */ jsx24("h1", { className: "mt-2 text-2xl font-semibold tracking-tight text-foreground", children: pageTitle }),
|
|
3892
|
+
/* @__PURE__ */ jsx24("p", { className: "mt-2 text-sm text-muted-foreground", children: deniedMessage }),
|
|
3893
|
+
/* @__PURE__ */ jsx24(Button17, { asChild: true, className: "mt-5", children: /* @__PURE__ */ jsx24("a", { href: routeHref("workspaceSettings", { id: workspaceId }), children: "Back to workspace settings" }) })
|
|
3894
|
+
] }) });
|
|
3895
|
+
}
|
|
3896
|
+
const renderedAppContent = companyAdmin.renderContent ? companyAdmin.renderContent(companyAdmin.status) : null;
|
|
3897
|
+
return renderedAppContent ? /* @__PURE__ */ jsx24(Fragment6, { children: renderedAppContent }) : null;
|
|
3898
|
+
}
|
|
3899
|
+
|
|
3754
3900
|
// src/front/CoreFront.tsx
|
|
3755
|
-
import {
|
|
3901
|
+
import { jsx as jsx25, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3756
3902
|
var CSP_NONCE_META_NAME = "boring-csp-nonce";
|
|
3757
3903
|
function PlaceholderPage({ name }) {
|
|
3758
|
-
return /* @__PURE__ */
|
|
3904
|
+
return /* @__PURE__ */ jsxs17("div", { "data-testid": `placeholder-${name}`, children: [
|
|
3759
3905
|
name,
|
|
3760
3906
|
" (not yet implemented)"
|
|
3761
3907
|
] });
|
|
@@ -3766,6 +3912,22 @@ function readCspNonceFromDom() {
|
|
|
3766
3912
|
const value = meta?.getAttribute("content")?.trim();
|
|
3767
3913
|
return value ? value : void 0;
|
|
3768
3914
|
}
|
|
3915
|
+
function CspNonceScript({ nonce }) {
|
|
3916
|
+
useEffect12(() => {
|
|
3917
|
+
const selector = 'script[data-boring-csp-nonce="true"]';
|
|
3918
|
+
const existing = document.head.querySelector(selector);
|
|
3919
|
+
const script = existing ?? document.createElement("script");
|
|
3920
|
+
script.type = "application/json";
|
|
3921
|
+
script.setAttribute("nonce", nonce);
|
|
3922
|
+
script.dataset.boringCspNonce = "true";
|
|
3923
|
+
script.textContent = JSON.stringify({ nonce });
|
|
3924
|
+
if (!existing) document.head.appendChild(script);
|
|
3925
|
+
return () => {
|
|
3926
|
+
script.remove();
|
|
3927
|
+
};
|
|
3928
|
+
}, [nonce]);
|
|
3929
|
+
return null;
|
|
3930
|
+
}
|
|
3769
3931
|
function createDefaultQueryClient() {
|
|
3770
3932
|
return new QueryClient({
|
|
3771
3933
|
defaultOptions: {
|
|
@@ -3776,11 +3938,25 @@ function createDefaultQueryClient() {
|
|
|
3776
3938
|
}
|
|
3777
3939
|
});
|
|
3778
3940
|
}
|
|
3941
|
+
function CompanyAdminScopedProvider({ children, companyAdmin }) {
|
|
3942
|
+
const session = useSession();
|
|
3943
|
+
const identityKey = session.data?.user?.id ?? null;
|
|
3944
|
+
return /* @__PURE__ */ jsx25(
|
|
3945
|
+
CompanyAdminProvider,
|
|
3946
|
+
{
|
|
3947
|
+
loadStatus: companyAdmin?.loadStatus,
|
|
3948
|
+
renderContent: companyAdmin?.renderContent,
|
|
3949
|
+
labels: companyAdmin?.labels,
|
|
3950
|
+
identityKey,
|
|
3951
|
+
children
|
|
3952
|
+
}
|
|
3953
|
+
);
|
|
3954
|
+
}
|
|
3779
3955
|
function RouterAuthGate({ children, publicPaths }) {
|
|
3780
3956
|
const config = useConfig();
|
|
3781
3957
|
const location = useLocation2();
|
|
3782
3958
|
const navigate = useNavigate6();
|
|
3783
|
-
const authLocation =
|
|
3959
|
+
const authLocation = useMemo8(
|
|
3784
3960
|
() => ({ pathname: location.pathname, search: location.search, hash: location.hash }),
|
|
3785
3961
|
[location.hash, location.pathname, location.search]
|
|
3786
3962
|
);
|
|
@@ -3790,7 +3966,7 @@ function RouterAuthGate({ children, publicPaths }) {
|
|
|
3790
3966
|
},
|
|
3791
3967
|
[navigate]
|
|
3792
3968
|
);
|
|
3793
|
-
return /* @__PURE__ */
|
|
3969
|
+
return /* @__PURE__ */ jsx25(
|
|
3794
3970
|
AuthGate,
|
|
3795
3971
|
{
|
|
3796
3972
|
location: authLocation,
|
|
@@ -3801,9 +3977,9 @@ function RouterAuthGate({ children, publicPaths }) {
|
|
|
3801
3977
|
}
|
|
3802
3978
|
);
|
|
3803
3979
|
}
|
|
3804
|
-
function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdParam, publicPaths }) {
|
|
3805
|
-
const queryClient =
|
|
3806
|
-
const resolvedCspNonce =
|
|
3980
|
+
function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdParam, publicPaths, companyAdmin }) {
|
|
3981
|
+
const queryClient = useMemo8(createDefaultQueryClient, []);
|
|
3982
|
+
const resolvedCspNonce = useMemo8(
|
|
3807
3983
|
() => cspNonce ?? readCspNonceFromDom(),
|
|
3808
3984
|
[cspNonce]
|
|
3809
3985
|
);
|
|
@@ -3814,43 +3990,35 @@ function CoreFront({ children, authPages, cspNonce, workspaceRoute, workspaceIdP
|
|
|
3814
3990
|
const VerifyEmailPage2 = authPages?.verifyEmail ?? VerifyEmailPage;
|
|
3815
3991
|
const AuthErrorPage2 = authPages?.authError ?? AuthErrorPage;
|
|
3816
3992
|
const UserSettingsPage2 = authPages?.userSettings ?? UserSettingsPage;
|
|
3817
|
-
return /* @__PURE__ */
|
|
3818
|
-
/* @__PURE__ */
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
)
|
|
3829
|
-
|
|
3830
|
-
|
|
3831
|
-
/* @__PURE__ */
|
|
3832
|
-
/* @__PURE__ */
|
|
3833
|
-
/* @__PURE__ */
|
|
3834
|
-
/* @__PURE__ */
|
|
3835
|
-
/* @__PURE__ */
|
|
3836
|
-
/* @__PURE__ */
|
|
3837
|
-
/* @__PURE__ */
|
|
3838
|
-
/* @__PURE__ */
|
|
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, {}) }),
|
|
3993
|
+
return /* @__PURE__ */ jsx25(HelmetProvider, { children: /* @__PURE__ */ jsx25(AppErrorBoundary, { children: /* @__PURE__ */ jsx25(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx25(ConfigProvider, { children: /* @__PURE__ */ jsx25(ThemeProvider, { children: /* @__PURE__ */ jsx25(AuthProvider, { queryClient, children: /* @__PURE__ */ jsx25(UserIdentityProvider, { children: /* @__PURE__ */ jsx25(BrowserRouter, { children: /* @__PURE__ */ jsx25(CompanyAdminScopedProvider, { companyAdmin, children: /* @__PURE__ */ jsx25(WorkspaceAuthProvider, { workspaceRoute, workspaceIdParam, children: /* @__PURE__ */ jsxs17(TopBarSlotProvider, { slot: /* @__PURE__ */ jsx25(UserMenu, {}), children: [
|
|
3994
|
+
/* @__PURE__ */ jsx25(Helmet, { children: resolvedCspNonce ? /* @__PURE__ */ jsx25("meta", { name: CSP_NONCE_META_NAME, content: resolvedCspNonce }) : null }),
|
|
3995
|
+
resolvedCspNonce ? /* @__PURE__ */ jsx25(CspNonceScript, { nonce: resolvedCspNonce }) : null,
|
|
3996
|
+
/* @__PURE__ */ jsx25(RouterAuthGate, { publicPaths: ["/invites", ...publicPaths ?? []], children: /* @__PURE__ */ jsx25(Suspense, { fallback: null, children: /* @__PURE__ */ jsxs17(Routes, { children: [
|
|
3997
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.signin, element: /* @__PURE__ */ jsx25(SignInPage2, {}) }),
|
|
3998
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.signup, element: /* @__PURE__ */ jsx25(SignUpPage2, {}) }),
|
|
3999
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.forgotPassword, element: /* @__PURE__ */ jsx25(ForgotPasswordPage2, {}) }),
|
|
4000
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.resetPassword, element: /* @__PURE__ */ jsx25(ResetPasswordPage2, {}) }),
|
|
4001
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.verifyEmail, element: /* @__PURE__ */ jsx25(VerifyEmailPage2, {}) }),
|
|
4002
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.authError, element: /* @__PURE__ */ jsx25(AuthErrorPage2, {}) }),
|
|
4003
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.callbackGithub, element: /* @__PURE__ */ jsx25(PlaceholderPage, { name: "github-callback" }) }),
|
|
4004
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.callbackGoogle, element: /* @__PURE__ */ jsx25(PlaceholderPage, { name: "google-callback" }) }),
|
|
4005
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.me, element: /* @__PURE__ */ jsx25(UserSettingsPage2, {}) }),
|
|
4006
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.workspaceMembers, element: /* @__PURE__ */ jsx25(MembersPage, {}) }),
|
|
4007
|
+
/* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/members", element: /* @__PURE__ */ jsx25(MembersPage, {}) }),
|
|
4008
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.workspaceInvites, element: /* @__PURE__ */ jsx25(InvitesPage, {}) }),
|
|
4009
|
+
/* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/invites", element: /* @__PURE__ */ jsx25(InvitesPage, {}) }),
|
|
4010
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.workspaceSettings, element: /* @__PURE__ */ jsx25(WorkspaceSettingsPage, {}) }),
|
|
4011
|
+
/* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/settings", element: /* @__PURE__ */ jsx25(WorkspaceSettingsPage, {}) }),
|
|
4012
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.companyAdmin, element: /* @__PURE__ */ jsx25(CompanyAdminPage, {}) }),
|
|
4013
|
+
/* @__PURE__ */ jsx25(Route, { path: "/workspace/:id/admin", element: /* @__PURE__ */ jsx25(CompanyAdminPage, {}) }),
|
|
4014
|
+
/* @__PURE__ */ jsx25(Route, { path: routes.inviteAccept, element: /* @__PURE__ */ jsx25(InviteAcceptPage, {}) }),
|
|
3847
4015
|
children
|
|
3848
4016
|
] }) }) })
|
|
3849
|
-
] }) }) }) }) }) }) }) }) }) });
|
|
4017
|
+
] }) }) }) }) }) }) }) }) }) }) });
|
|
3850
4018
|
}
|
|
3851
4019
|
|
|
3852
4020
|
// src/front/commands/CoreCommandContributions.tsx
|
|
3853
|
-
import { useMemo as
|
|
4021
|
+
import { useMemo as useMemo9, useState as useState22 } from "react";
|
|
3854
4022
|
import { useNavigate as useNavigate7 } from "react-router-dom";
|
|
3855
4023
|
|
|
3856
4024
|
// src/front/workspace/commands.ts
|
|
@@ -3892,8 +4060,8 @@ function useCoreCommands() {
|
|
|
3892
4060
|
const navigate = useNavigate7();
|
|
3893
4061
|
const signOut = useSignOut();
|
|
3894
4062
|
const workspace = useCurrentWorkspace();
|
|
3895
|
-
const [isSigningOut, setIsSigningOut] =
|
|
3896
|
-
return
|
|
4063
|
+
const [isSigningOut, setIsSigningOut] = useState22(false);
|
|
4064
|
+
return useMemo9(() => {
|
|
3897
4065
|
const result = [
|
|
3898
4066
|
{
|
|
3899
4067
|
id: "user:settings",
|
|
@@ -4007,6 +4175,8 @@ export {
|
|
|
4007
4175
|
useConfigLoaded,
|
|
4008
4176
|
ThemeProvider,
|
|
4009
4177
|
useTheme,
|
|
4178
|
+
CompanyAdminProvider,
|
|
4179
|
+
useCompanyAdminStatus,
|
|
4010
4180
|
useKeyboardShortcuts,
|
|
4011
4181
|
useViewportBreakpoint,
|
|
4012
4182
|
useReducedMotion,
|
|
@@ -4044,6 +4214,7 @@ export {
|
|
|
4044
4214
|
InvitesPage,
|
|
4045
4215
|
MembersPage,
|
|
4046
4216
|
WorkspaceSettingsPage,
|
|
4217
|
+
CompanyAdminPage,
|
|
4047
4218
|
CoreFront,
|
|
4048
4219
|
getWorkspaceCommands,
|
|
4049
4220
|
useCoreCommands,
|