@stackframe/stack 2.6.28 → 2.6.30
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/CHANGELOG.md +20 -0
- package/dist/components/elements/sidebar-layout.d.mts +1 -2
- package/dist/components/elements/sidebar-layout.d.ts +1 -2
- package/dist/components/elements/sidebar-layout.js +1 -1
- package/dist/components/elements/sidebar-layout.js.map +1 -1
- package/dist/components/message-cards/known-error-message-card.js +2 -2
- package/dist/components/message-cards/known-error-message-card.js.map +1 -1
- package/dist/components/message-cards/predefined-message-card.js +5 -5
- package/dist/components/message-cards/predefined-message-card.js.map +1 -1
- package/dist/components-page/account-settings.d.mts +7 -4
- package/dist/components-page/account-settings.d.ts +7 -4
- package/dist/components-page/account-settings.js +73 -41
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/email-verification.js +3 -3
- package/dist/components-page/email-verification.js.map +1 -1
- package/dist/components-page/error-page.js +6 -6
- package/dist/components-page/error-page.js.map +1 -1
- package/dist/components-page/magic-link-callback.js +4 -4
- package/dist/components-page/magic-link-callback.js.map +1 -1
- package/dist/components-page/team-invitation.js +2 -2
- package/dist/components-page/team-invitation.js.map +1 -1
- package/dist/esm/components/elements/sidebar-layout.js +1 -1
- package/dist/esm/components/elements/sidebar-layout.js.map +1 -1
- package/dist/esm/components/message-cards/known-error-message-card.js +2 -2
- package/dist/esm/components/message-cards/known-error-message-card.js.map +1 -1
- package/dist/esm/components/message-cards/predefined-message-card.js +5 -5
- package/dist/esm/components/message-cards/predefined-message-card.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +75 -43
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/email-verification.js +3 -3
- package/dist/esm/components-page/email-verification.js.map +1 -1
- package/dist/esm/components-page/error-page.js +6 -6
- package/dist/esm/components-page/error-page.js.map +1 -1
- package/dist/esm/components-page/magic-link-callback.js +4 -4
- package/dist/esm/components-page/magic-link-callback.js.map +1 -1
- package/dist/esm/components-page/team-invitation.js +2 -2
- package/dist/esm/components-page/team-invitation.js.map +1 -1
- package/dist/esm/generated/global-css.js +1 -1
- package/dist/esm/generated/global-css.js.map +1 -1
- package/dist/esm/generated/quetzal-translations.js +1233 -1221
- package/dist/esm/generated/quetzal-translations.js.map +1 -1
- package/dist/esm/lib/stack-app.js +50 -1
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/esm/providers/theme-provider.js +1 -0
- package/dist/esm/providers/theme-provider.js.map +1 -1
- package/dist/generated/global-css.d.mts +1 -1
- package/dist/generated/global-css.d.ts +1 -1
- package/dist/generated/global-css.js +1 -1
- package/dist/generated/global-css.js.map +1 -1
- package/dist/generated/quetzal-translations.d.mts +2 -2
- package/dist/generated/quetzal-translations.d.ts +2 -2
- package/dist/generated/quetzal-translations.js +1233 -1221
- package/dist/generated/quetzal-translations.js.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lib/stack-app.d.mts +9 -1
- package/dist/lib/stack-app.d.ts +9 -1
- package/dist/lib/stack-app.js +50 -1
- package/dist/lib/stack-app.js.map +1 -1
- package/dist/providers/theme-provider.js +1 -0
- package/dist/providers/theme-provider.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/elements/sidebar-layout.tsx"],"sourcesContent":["'use client';\n\nimport { useHash } from '@stackframe/stack-shared/dist/hooks/use-hash';\nimport { Button, Typography, cn } from '@stackframe/stack-ui';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/elements/sidebar-layout.tsx"],"sourcesContent":["'use client';\n\nimport { useHash } from '@stackframe/stack-shared/dist/hooks/use-hash';\nimport { Button, Typography, cn } from '@stackframe/stack-ui';\nimport { XIcon } from 'lucide-react';\nimport { useRouter } from 'next/navigation';\nimport React, { ReactNode, useEffect } from 'react';\n\nexport type SidebarItem = {\n title: React.ReactNode,\n type: 'item' | 'divider',\n description?: React.ReactNode,\n id?: string,\n icon?: React.ReactNode,\n content?: React.ReactNode,\n contentTitle?: React.ReactNode,\n}\n\nexport function SidebarLayout(props: { items: SidebarItem[], title?: ReactNode, className?: string }) {\n const router = useRouter();\n const hash = useHash();\n const selectedIndex = props.items.findIndex(item => item.id && (item.id === hash));\n\n useEffect(() => {\n if (selectedIndex === -1) {\n router.push('#' + props.items[0].id);\n }\n }, [hash]);\n\n return (\n <>\n <div className={cn(\"hidden sm:flex stack-scope h-full\", props.className)}>\n <DesktopLayout items={props.items} title={props.title} selectedIndex={selectedIndex} />\n </div>\n <div className={cn(\"sm:hidden stack-scope h-full\", props.className)}>\n <MobileLayout items={props.items} title={props.title} selectedIndex={selectedIndex} />\n </div>\n </>\n );\n}\n\nfunction Items(props: { items: SidebarItem[], selectedIndex: number }) {\n const router = useRouter();\n\n return props.items.map((item, index) => (\n item.type === 'item' ?\n <Button\n key={index}\n variant='ghost'\n size='sm'\n className={cn(\n props.selectedIndex === index && \"bg-muted\",\n \"justify-start text-md text-zinc-800 dark:text-zinc-300 px-2 text-left\",\n )}\n onClick={() => {\n if (item.id) {\n router.push('#' + item.id);\n }\n }}\n >\n {item.icon}\n {item.title}\n </Button> :\n <Typography key={index}>\n {item.title}\n </Typography>\n ));\n\n}\n\nfunction DesktopLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {\n const selectedItem = props.items[props.selectedIndex === -1 ? 0 : props.selectedIndex];\n\n return (\n <div className=\"stack-scope flex w-full h-full max-w-full relative\">\n <div className=\"flex max-w-[200px] min-w-[200px] border-r flex-col items-stretch gap-2 p-2 overflow-y-auto\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n <Items items={props.items} selectedIndex={props.selectedIndex} />\n </div>\n <div className=\"flex-1 w-0 flex justify-center gap-4 py-2 px-4\">\n <div className='flex flex-col max-w-[800px] w-[800px]'>\n <div className='mt-4 mb-6'>\n <Typography type='h4' className='font-semibold'>{selectedItem.title}</Typography>\n {selectedItem.description && <Typography variant='secondary' type='label'>{selectedItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {selectedItem.content}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction MobileLayout(props: { items: SidebarItem[], title?: ReactNode, selectedIndex: number }) {\n const selectedItem = props.items[props.selectedIndex];\n const router = useRouter();\n\n if (props.selectedIndex === -1) {\n return (\n <div className=\"flex flex-col gap-2 p-2\">\n {props.title && <div className='mb-2 ml-2'>\n <Typography type='h2' className=\"text-lg font-semibold text-zinc-800 dark:text-zinc-300\">{props.title}</Typography>\n </div>}\n\n <Items items={props.items} selectedIndex={props.selectedIndex} />\n </div>\n );\n } else {\n return (\n <div className=\"flex-1 flex flex-col gap-4 py-2 px-4\">\n <div className='flex flex-col'>\n <div className='flex justify-between'>\n <Typography type='h4' className='font-semibold'>{selectedItem.title}</Typography>\n <Button\n variant='ghost'\n size='icon'\n onClick={() => { router.push('#'); }}\n >\n <XIcon className='h-5 w-5' />\n </Button>\n </div>\n {selectedItem.description && <Typography variant='secondary' type='label'>{selectedItem.description}</Typography>}\n </div>\n <div className='flex-1'>\n {selectedItem.content}\n </div>\n </div>\n );\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
4
|
// src/components/message-cards/known-error-message-card.tsx
|
|
5
|
-
import { useStackApp } from "../..";
|
|
6
5
|
import { Typography } from "@stackframe/stack-ui";
|
|
6
|
+
import { useStackApp } from "../..";
|
|
7
7
|
import { MessageCard } from "./message-card";
|
|
8
8
|
import { jsxs } from "react/jsx-runtime";
|
|
9
9
|
function KnownErrorMessageCard({
|
|
@@ -16,7 +16,7 @@ function KnownErrorMessageCard({
|
|
|
16
16
|
{
|
|
17
17
|
title: "An error occurred",
|
|
18
18
|
fullPage,
|
|
19
|
-
primaryButtonText: "Go
|
|
19
|
+
primaryButtonText: "Go Home",
|
|
20
20
|
primaryAction: () => stackApp.redirectToHome(),
|
|
21
21
|
children: [
|
|
22
22
|
/* @__PURE__ */ jsxs(Typography, { children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/message-cards/known-error-message-card.tsx"],"sourcesContent":["\"use client\";\n\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/message-cards/known-error-message-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { KnownError } from \"@stackframe/stack-shared\";\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { MessageCard } from \"./message-card\";\n\nexport function KnownErrorMessageCard({\n error,\n fullPage=false,\n}: {\n error: KnownError,\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n\n return (\n <MessageCard\n title={\"An error occurred\"}\n fullPage={fullPage}\n primaryButtonText={\"Go Home\"}\n primaryAction={() => stackApp.redirectToHome()}\n >\n {<Typography>Error Code: {error.errorCode}</Typography>}\n {<Typography>Error Message: {error.message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;AAGA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAkBrB;AAhBA,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,WAAW,YAAY;AAE7B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,MACP;AAAA,MACA,mBAAmB;AAAA,MACnB,eAAe,MAAM,SAAS,eAAe;AAAA,MAE5C;AAAA,6BAAC,cAAW;AAAA;AAAA,UAAa,MAAM;AAAA,WAAU;AAAA,QACzC,qBAAC,cAAW;AAAA;AAAA,UAAgB,MAAM;AAAA,WAAQ;AAAA;AAAA;AAAA,EAC7C;AAEJ;","names":[]}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
// src/components/message-cards/predefined-message-card.tsx
|
|
5
5
|
import { Typography } from "@stackframe/stack-ui";
|
|
6
6
|
import { useStackApp } from "../..";
|
|
7
|
-
import { MessageCard } from "./message-card";
|
|
8
7
|
import { useTranslation } from "../../lib/translations";
|
|
8
|
+
import { MessageCard } from "./message-card";
|
|
9
9
|
import { jsx } from "react/jsx-runtime";
|
|
10
10
|
function PredefinedMessageCard({
|
|
11
11
|
type,
|
|
@@ -24,7 +24,7 @@ function PredefinedMessageCard({
|
|
|
24
24
|
title = t("You are already signed in");
|
|
25
25
|
primaryAction = () => stackApp.redirectToHome();
|
|
26
26
|
secondaryAction = () => stackApp.redirectToSignOut();
|
|
27
|
-
primaryButton = t("Go
|
|
27
|
+
primaryButton = t("Go home");
|
|
28
28
|
secondaryButton = t("Sign out");
|
|
29
29
|
break;
|
|
30
30
|
}
|
|
@@ -38,7 +38,7 @@ function PredefinedMessageCard({
|
|
|
38
38
|
title = t("Sign up for new users is not enabled at the moment.");
|
|
39
39
|
primaryAction = () => stackApp.redirectToHome();
|
|
40
40
|
secondaryAction = () => stackApp.redirectToSignIn();
|
|
41
|
-
primaryButton = t("Go
|
|
41
|
+
primaryButton = t("Go home");
|
|
42
42
|
secondaryButton = t("Sign in");
|
|
43
43
|
break;
|
|
44
44
|
}
|
|
@@ -46,7 +46,7 @@ function PredefinedMessageCard({
|
|
|
46
46
|
title = t("Email sent!");
|
|
47
47
|
message = t("If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.");
|
|
48
48
|
primaryAction = () => stackApp.redirectToHome();
|
|
49
|
-
primaryButton = t("Go
|
|
49
|
+
primaryButton = t("Go home");
|
|
50
50
|
break;
|
|
51
51
|
}
|
|
52
52
|
case "passwordReset": {
|
|
@@ -60,7 +60,7 @@ function PredefinedMessageCard({
|
|
|
60
60
|
title = t("An unknown error occurred");
|
|
61
61
|
message = t("Please try again and if the problem persists, contact support.");
|
|
62
62
|
primaryAction = () => stackApp.redirectToHome();
|
|
63
|
-
primaryButton = t("Go
|
|
63
|
+
primaryButton = t("Go home");
|
|
64
64
|
break;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/message-cards/predefined-message-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/message-cards/predefined-message-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Typography } from \"@stackframe/stack-ui\";\nimport { useStackApp } from \"../..\";\nimport { useTranslation } from \"../../lib/translations\";\nimport { MessageCard } from \"./message-card\";\n\nexport function PredefinedMessageCard({\n type,\n fullPage=false,\n}: {\n type: 'signedIn' | 'signedOut' | 'emailSent' | 'passwordReset' | 'unknownError' | 'signUpDisabled',\n fullPage?: boolean,\n}) {\n const stackApp = useStackApp();\n const { t } = useTranslation();\n\n let title: string;\n let message: string | null = null;\n let primaryButton: string | null = null;\n let secondaryButton: string | null = null;\n let primaryAction: (() => Promise<void> | void) | null = null;\n let secondaryAction: (() => Promise<void> | void) | null = null;\n\n switch (type) {\n case 'signedIn': {\n title = t(\"You are already signed in\");\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignOut();\n primaryButton = t(\"Go home\");\n secondaryButton = t(\"Sign out\");\n break;\n }\n case 'signedOut': {\n title = t(\"You are not currently signed in.\");\n primaryAction = () => stackApp.redirectToSignIn();\n primaryButton = t(\"Sign in\");\n break;\n }\n case 'signUpDisabled': {\n title = t(\"Sign up for new users is not enabled at the moment.\");\n primaryAction = () => stackApp.redirectToHome();\n secondaryAction = () => stackApp.redirectToSignIn();\n primaryButton = t(\"Go home\");\n secondaryButton = t(\"Sign in\");\n break;\n }\n case 'emailSent': {\n title = t(\"Email sent!\");\n message = t(\"If the user with this e-mail address exists, an e-mail was sent to your inbox. Make sure to check your spam folder.\");\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = t(\"Go home\");\n break;\n }\n case 'passwordReset': {\n title = t(\"Password reset successfully!\");\n message = t(\"Your password has been reset. You can now sign in with your new password.\");\n primaryAction = () => stackApp.redirectToSignIn({ noRedirectBack: true });\n primaryButton = t(\"Sign in\");\n break;\n }\n case 'unknownError': {\n title = t(\"An unknown error occurred\");\n message = t(\"Please try again and if the problem persists, contact support.\");\n primaryAction = () => stackApp.redirectToHome();\n primaryButton = t(\"Go home\");\n break;\n }\n }\n\n return (\n <MessageCard\n title={title}\n fullPage={fullPage}\n primaryButtonText={primaryButton}\n primaryAction={primaryAction}\n secondaryButtonText={secondaryButton || undefined}\n secondaryAction={secondaryAction || undefined}\n >\n {message && <Typography>{message}</Typography>}\n </MessageCard>\n );\n}\n"],"mappings":";;;AAEA,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AA0EV;AAxEX,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,WAAS;AACX,GAGG;AACD,QAAM,WAAW,YAAY;AAC7B,QAAM,EAAE,EAAE,IAAI,eAAe;AAE7B,MAAI;AACJ,MAAI,UAAyB;AAC7B,MAAI,gBAA+B;AACnC,MAAI,kBAAiC;AACrC,MAAI,gBAAqD;AACzD,MAAI,kBAAuD;AAE3D,UAAQ,MAAM;AAAA,IACZ,KAAK,YAAY;AACf,cAAQ,EAAE,2BAA2B;AACrC,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,kBAAkB;AACnD,sBAAgB,EAAE,SAAS;AAC3B,wBAAkB,EAAE,UAAU;AAC9B;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ,EAAE,kCAAkC;AAC5C,sBAAgB,MAAM,SAAS,iBAAiB;AAChD,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,kBAAkB;AACrB,cAAQ,EAAE,qDAAqD;AAC/D,sBAAgB,MAAM,SAAS,eAAe;AAC9C,wBAAkB,MAAM,SAAS,iBAAiB;AAClD,sBAAgB,EAAE,SAAS;AAC3B,wBAAkB,EAAE,SAAS;AAC7B;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,cAAQ,EAAE,aAAa;AACvB,gBAAU,EAAE,qHAAqH;AACjI,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,iBAAiB;AACpB,cAAQ,EAAE,8BAA8B;AACxC,gBAAU,EAAE,2EAA2E;AACvF,sBAAgB,MAAM,SAAS,iBAAiB,EAAE,gBAAgB,KAAK,CAAC;AACxE,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,IACA,KAAK,gBAAgB;AACnB,cAAQ,EAAE,2BAA2B;AACrC,gBAAU,EAAE,gEAAgE;AAC5E,sBAAgB,MAAM,SAAS,eAAe;AAC9C,sBAAgB,EAAE,SAAS;AAC3B;AAAA,IACF;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB;AAAA,MACA,qBAAqB,mBAAmB;AAAA,MACxC,iBAAiB,mBAAmB;AAAA,MAEnC,qBAAW,oBAAC,cAAY,mBAAQ;AAAA;AAAA,EACnC;AAEJ;","names":[]}
|
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
import { yupResolver } from "@hookform/resolvers/yup";
|
|
6
6
|
import { getPasswordError } from "@stackframe/stack-shared/dist/helpers/password";
|
|
7
7
|
import { useAsyncCallback } from "@stackframe/stack-shared/dist/hooks/use-async-callback";
|
|
8
|
-
import {
|
|
8
|
+
import { passwordSchema as schemaFieldsPasswordSchema, strictEmailSchema, yupObject, yupString } from "@stackframe/stack-shared/dist/schema-fields";
|
|
9
9
|
import { generateRandomValues } from "@stackframe/stack-shared/dist/utils/crypto";
|
|
10
10
|
import { throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
|
11
11
|
import { runAsynchronously, runAsynchronouslyWithAlert } from "@stackframe/stack-shared/dist/utils/promises";
|
|
12
12
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActionCell, Badge, Button, Input, Label, PasswordInput, Separator, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Typography } from "@stackframe/stack-ui";
|
|
13
|
-
import {
|
|
13
|
+
import { Edit, Trash, icons } from "lucide-react";
|
|
14
14
|
import { useRouter } from "next/navigation";
|
|
15
15
|
import { TOTPController, createTOTPKeyURI } from "oslo/otp";
|
|
16
16
|
import * as QRCode from "qrcode";
|
|
@@ -26,6 +26,10 @@ import { ProfileImageEditor } from "../components/profile-image-editor";
|
|
|
26
26
|
import { TeamIcon } from "../components/team-icon";
|
|
27
27
|
import { useTranslation } from "../lib/translations";
|
|
28
28
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
29
|
+
var Icon = ({ name }) => {
|
|
30
|
+
const LucideIcon = icons[name];
|
|
31
|
+
return /* @__PURE__ */ jsx(LucideIcon, { className: "mr-2 h-4 w-4" });
|
|
32
|
+
};
|
|
29
33
|
function AccountSettings(props) {
|
|
30
34
|
const { t } = useTranslation();
|
|
31
35
|
const user = useUser({ or: "redirect" });
|
|
@@ -40,28 +44,36 @@ function AccountSettings(props) {
|
|
|
40
44
|
title: t("My Profile"),
|
|
41
45
|
type: "item",
|
|
42
46
|
id: "profile",
|
|
43
|
-
icon: Contact,
|
|
47
|
+
icon: /* @__PURE__ */ jsx(Icon, { name: "Contact" }),
|
|
44
48
|
content: /* @__PURE__ */ jsx(ProfilePage, {})
|
|
45
49
|
},
|
|
46
50
|
{
|
|
47
51
|
title: t("Emails & Auth"),
|
|
48
52
|
type: "item",
|
|
49
53
|
id: "auth",
|
|
50
|
-
icon: ShieldCheck,
|
|
54
|
+
icon: /* @__PURE__ */ jsx(Icon, { name: "ShieldCheck" }),
|
|
51
55
|
content: /* @__PURE__ */ jsx(EmailsAndAuthPage, {})
|
|
52
56
|
},
|
|
53
57
|
{
|
|
54
58
|
title: t("Settings"),
|
|
55
59
|
type: "item",
|
|
56
60
|
id: "settings",
|
|
57
|
-
icon: Settings,
|
|
61
|
+
icon: /* @__PURE__ */ jsx(Icon, { name: "Settings" }),
|
|
58
62
|
content: /* @__PURE__ */ jsx(SettingsPage, {})
|
|
59
63
|
},
|
|
60
64
|
...props.extraItems?.map((item) => ({
|
|
61
65
|
title: item.title,
|
|
62
66
|
type: "item",
|
|
63
67
|
id: item.id,
|
|
64
|
-
icon:
|
|
68
|
+
icon: (() => {
|
|
69
|
+
const iconName = item.iconName;
|
|
70
|
+
if (iconName) {
|
|
71
|
+
return /* @__PURE__ */ jsx(Icon, { name: iconName });
|
|
72
|
+
} else if (item.icon) {
|
|
73
|
+
return item.icon;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
})(),
|
|
65
77
|
content: item.content
|
|
66
78
|
})) || [],
|
|
67
79
|
...teams.length > 0 || project.config.clientTeamCreationEnabled ? [{
|
|
@@ -79,7 +91,7 @@ function AccountSettings(props) {
|
|
|
79
91
|
})),
|
|
80
92
|
...project.config.clientTeamCreationEnabled ? [{
|
|
81
93
|
title: t("Create a team"),
|
|
82
|
-
icon: CirclePlus,
|
|
94
|
+
icon: /* @__PURE__ */ jsx(Icon, { name: "CirclePlus" }),
|
|
83
95
|
type: "item",
|
|
84
96
|
id: "team-creation",
|
|
85
97
|
content: /* @__PURE__ */ jsx(TeamCreation, {})
|
|
@@ -164,11 +176,11 @@ function EmailsSection() {
|
|
|
164
176
|
});
|
|
165
177
|
}
|
|
166
178
|
}, [contactChannels, addedEmail]);
|
|
167
|
-
const
|
|
179
|
+
const emailSchema = yupObject({
|
|
168
180
|
email: strictEmailSchema(t("Please enter a valid email address")).notOneOf(contactChannels.map((x) => x.value), t("Email already exists")).defined().nonEmpty(t("Email is required"))
|
|
169
181
|
});
|
|
170
182
|
const { register, handleSubmit, formState: { errors }, reset } = useForm({
|
|
171
|
-
resolver: yupResolver(
|
|
183
|
+
resolver: yupResolver(emailSchema)
|
|
172
184
|
});
|
|
173
185
|
const onSubmit = async (data) => {
|
|
174
186
|
setAddingEmailLoading(true);
|
|
@@ -660,8 +672,8 @@ function TeamPage(props) {
|
|
|
660
672
|
const memberListSection = useMemberListSection(props);
|
|
661
673
|
return /* @__PURE__ */ jsxs(PageLayout, { children: [
|
|
662
674
|
teamUserProfileSection,
|
|
663
|
-
memberInvitationSection,
|
|
664
675
|
memberListSection,
|
|
676
|
+
memberInvitationSection,
|
|
665
677
|
teamProfileImageSection,
|
|
666
678
|
teamDisplayNameSection,
|
|
667
679
|
leaveTeamSection
|
|
@@ -780,13 +792,19 @@ function useTeamUserProfileSection(props) {
|
|
|
780
792
|
function useMemberInvitationSection(props) {
|
|
781
793
|
const { t } = useTranslation();
|
|
782
794
|
const invitationSchema = yupObject({
|
|
783
|
-
email:
|
|
795
|
+
email: strictEmailSchema(t("Please enter a valid email address")).defined().nonEmpty(t("Please enter an email address"))
|
|
784
796
|
});
|
|
785
797
|
const user = useUser({ or: "redirect" });
|
|
786
798
|
const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
|
|
799
|
+
const readMemberPermission = user.usePermission(props.team, "$read_members");
|
|
800
|
+
const removeMemberPermission = user.usePermission(props.team, "$remove_members");
|
|
787
801
|
if (!inviteMemberPermission) {
|
|
788
802
|
return null;
|
|
789
803
|
}
|
|
804
|
+
let invitationsToShow = [];
|
|
805
|
+
if (readMemberPermission) {
|
|
806
|
+
invitationsToShow = props.team.useInvitations();
|
|
807
|
+
}
|
|
790
808
|
const { register, handleSubmit, formState: { errors }, watch } = useForm({
|
|
791
809
|
resolver: yupResolver(invitationSchema)
|
|
792
810
|
});
|
|
@@ -804,38 +822,52 @@ function useMemberInvitationSection(props) {
|
|
|
804
822
|
useEffect(() => {
|
|
805
823
|
setInvitedEmail(null);
|
|
806
824
|
}, [watch("email")]);
|
|
807
|
-
return /* @__PURE__ */
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
/* @__PURE__ */
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
"
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
825
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
826
|
+
/* @__PURE__ */ jsx(
|
|
827
|
+
Section,
|
|
828
|
+
{
|
|
829
|
+
title: t("Invite member"),
|
|
830
|
+
description: t("Invite a user to your team through email"),
|
|
831
|
+
children: /* @__PURE__ */ jsxs(
|
|
832
|
+
"form",
|
|
833
|
+
{
|
|
834
|
+
onSubmit: (e) => runAsynchronouslyWithAlert(handleSubmit(onSubmit)(e)),
|
|
835
|
+
noValidate: true,
|
|
836
|
+
className: "w-full",
|
|
837
|
+
children: [
|
|
838
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row w-full", children: [
|
|
839
|
+
/* @__PURE__ */ jsx(
|
|
840
|
+
Input,
|
|
841
|
+
{
|
|
842
|
+
placeholder: t("Email"),
|
|
843
|
+
...register("email")
|
|
844
|
+
}
|
|
845
|
+
),
|
|
846
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", loading, children: t("Invite User") })
|
|
847
|
+
] }),
|
|
848
|
+
/* @__PURE__ */ jsx(FormWarningText, { text: errors.email?.message?.toString() }),
|
|
849
|
+
invitedEmail && /* @__PURE__ */ jsxs(Typography, { type: "label", variant: "secondary", children: [
|
|
850
|
+
"Invited ",
|
|
851
|
+
invitedEmail
|
|
852
|
+
] })
|
|
853
|
+
]
|
|
854
|
+
}
|
|
855
|
+
)
|
|
856
|
+
}
|
|
857
|
+
),
|
|
858
|
+
invitationsToShow.length > 0 && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Table, { className: "mt-6", children: [
|
|
859
|
+
/* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
860
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[200px]", children: t("Outstanding invitations") }),
|
|
861
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[60px]", children: t("Expires") }),
|
|
862
|
+
/* @__PURE__ */ jsx(TableHead, { className: "w-[36px] max-w-[36px]" })
|
|
863
|
+
] }) }),
|
|
864
|
+
/* @__PURE__ */ jsx(TableBody, { children: invitationsToShow.map((invitation, i) => /* @__PURE__ */ jsxs(TableRow, { children: [
|
|
865
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { children: invitation.recipientEmail }) }),
|
|
866
|
+
/* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Typography, { variant: "secondary", children: invitation.expiresAt.toLocaleString() }) }),
|
|
867
|
+
/* @__PURE__ */ jsx(TableCell, { align: "right", className: "max-w-[36px]", children: removeMemberPermission && /* @__PURE__ */ jsx(Button, { onClick: async () => await invitation.revoke(), size: "icon", variant: "ghost", children: /* @__PURE__ */ jsx(Trash, { className: "w-4 h-4" }) }) })
|
|
868
|
+
] }, invitation.id)) })
|
|
869
|
+
] }) })
|
|
870
|
+
] });
|
|
839
871
|
}
|
|
840
872
|
function useMemberListSection(props) {
|
|
841
873
|
const { t } = useTranslation();
|