@stackframe/stack 2.5.33 → 2.5.37
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 +40 -0
- package/dist/components/credential-sign-in.js +14 -12
- package/dist/components/credential-sign-in.js.map +1 -1
- package/dist/components/credential-sign-up.js +17 -15
- package/dist/components/credential-sign-up.js.map +1 -1
- package/dist/components/elements/maybe-full-page.d.mts +2 -2
- package/dist/components/elements/maybe-full-page.d.ts +2 -2
- package/dist/components/elements/sidebar-layout.d.mts +5 -5
- package/dist/components/elements/sidebar-layout.d.ts +5 -5
- package/dist/components/elements/sidebar-layout.js +15 -7
- package/dist/components/elements/sidebar-layout.js.map +1 -1
- package/dist/components/elements/user-avatar.js +1 -1
- package/dist/components/elements/user-avatar.js.map +1 -1
- package/dist/components/magic-link-sign-in.js +11 -9
- package/dist/components/magic-link-sign-in.js.map +1 -1
- package/dist/components/message-cards/message-card.d.mts +2 -2
- package/dist/components/message-cards/message-card.d.ts +2 -2
- package/dist/components/oauth-button-group.js.map +1 -1
- package/dist/components/oauth-button.js +46 -2
- package/dist/components/oauth-button.js.map +1 -1
- package/dist/components/profile-image-editor.js +7 -5
- package/dist/components/profile-image-editor.js.map +1 -1
- package/dist/components/selected-team-switcher.js +7 -4
- package/dist/components/selected-team-switcher.js.map +1 -1
- package/dist/components/team-icon.js.map +1 -1
- package/dist/components/user-button.d.mts +2 -2
- package/dist/components/user-button.d.ts +2 -2
- package/dist/components/user-button.js +11 -11
- package/dist/components/user-button.js.map +1 -1
- package/dist/components-page/account-settings.d.mts +4 -2
- package/dist/components-page/account-settings.d.ts +4 -2
- package/dist/components-page/account-settings.js +406 -221
- package/dist/components-page/account-settings.js.map +1 -1
- package/dist/components-page/auth-page.js +11 -7
- package/dist/components-page/auth-page.js.map +1 -1
- package/dist/components-page/email-verification.js +4 -2
- package/dist/components-page/email-verification.js.map +1 -1
- package/dist/components-page/error-page.js +6 -4
- package/dist/components-page/error-page.js.map +1 -1
- package/dist/components-page/forgot-password.js +12 -8
- package/dist/components-page/forgot-password.js.map +1 -1
- package/dist/components-page/magic-link-callback.js +5 -3
- package/dist/components-page/magic-link-callback.js.map +1 -1
- package/dist/components-page/oauth-callback.js +6 -5
- package/dist/components-page/oauth-callback.js.map +1 -1
- package/dist/components-page/password-reset.js +25 -22
- package/dist/components-page/password-reset.js.map +1 -1
- package/dist/components-page/stack-handler.d.mts +1 -0
- package/dist/components-page/stack-handler.d.ts +1 -0
- package/dist/components-page/team-creation.js +9 -7
- package/dist/components-page/team-creation.js.map +1 -1
- package/dist/components-page/team-invitation.js +14 -11
- package/dist/components-page/team-invitation.js.map +1 -1
- package/dist/esm/components/credential-sign-in.js +14 -12
- package/dist/esm/components/credential-sign-in.js.map +1 -1
- package/dist/esm/components/credential-sign-up.js +17 -15
- package/dist/esm/components/credential-sign-up.js.map +1 -1
- package/dist/esm/components/elements/sidebar-layout.js +15 -7
- package/dist/esm/components/elements/sidebar-layout.js.map +1 -1
- package/dist/esm/components/elements/user-avatar.js +1 -1
- package/dist/esm/components/elements/user-avatar.js.map +1 -1
- package/dist/esm/components/magic-link-sign-in.js +11 -9
- package/dist/esm/components/magic-link-sign-in.js.map +1 -1
- package/dist/esm/components/oauth-button-group.js.map +1 -1
- package/dist/esm/components/oauth-button.js +46 -2
- package/dist/esm/components/oauth-button.js.map +1 -1
- package/dist/esm/components/profile-image-editor.js +7 -5
- package/dist/esm/components/profile-image-editor.js.map +1 -1
- package/dist/esm/components/selected-team-switcher.js +7 -4
- package/dist/esm/components/selected-team-switcher.js.map +1 -1
- package/dist/esm/components/team-icon.js.map +1 -1
- package/dist/esm/components/user-button.js +12 -15
- package/dist/esm/components/user-button.js.map +1 -1
- package/dist/esm/components-page/account-settings.js +406 -222
- package/dist/esm/components-page/account-settings.js.map +1 -1
- package/dist/esm/components-page/auth-page.js +11 -7
- package/dist/esm/components-page/auth-page.js.map +1 -1
- package/dist/esm/components-page/email-verification.js +4 -2
- package/dist/esm/components-page/email-verification.js.map +1 -1
- package/dist/esm/components-page/error-page.js +6 -4
- package/dist/esm/components-page/error-page.js.map +1 -1
- package/dist/esm/components-page/forgot-password.js +12 -8
- package/dist/esm/components-page/forgot-password.js.map +1 -1
- package/dist/esm/components-page/magic-link-callback.js +5 -3
- package/dist/esm/components-page/magic-link-callback.js.map +1 -1
- package/dist/esm/components-page/oauth-callback.js +6 -5
- package/dist/esm/components-page/oauth-callback.js.map +1 -1
- package/dist/esm/components-page/password-reset.js +25 -22
- package/dist/esm/components-page/password-reset.js.map +1 -1
- package/dist/esm/components-page/team-creation.js +9 -7
- package/dist/esm/components-page/team-creation.js.map +1 -1
- package/dist/esm/components-page/team-invitation.js +14 -11
- 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 +1629 -0
- package/dist/esm/generated/quetzal-translations.js.map +1 -0
- package/dist/esm/lib/stack-app.js +8 -1
- package/dist/esm/lib/stack-app.js.map +1 -1
- package/dist/esm/lib/translations.js +20 -0
- package/dist/esm/lib/translations.js.map +1 -0
- package/dist/esm/providers/stack-provider.js +4 -2
- package/dist/esm/providers/stack-provider.js.map +1 -1
- package/dist/esm/providers/theme-provider.js.map +1 -1
- package/dist/esm/providers/translation-provider-client.js +18 -0
- package/dist/esm/providers/translation-provider-client.js.map +1 -0
- package/dist/esm/providers/translation-provider.js +12 -0
- package/dist/esm/providers/translation-provider.js.map +1 -0
- package/dist/esm/utils/browser-script.js +43 -8
- package/dist/esm/utils/browser-script.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 +4 -0
- package/dist/generated/quetzal-translations.d.ts +4 -0
- package/dist/generated/quetzal-translations.js +1655 -0
- package/dist/generated/quetzal-translations.js.map +1 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/lib/stack-app.d.mts +4 -1
- package/dist/lib/stack-app.d.ts +4 -1
- package/dist/lib/stack-app.js +8 -1
- package/dist/lib/stack-app.js.map +1 -1
- package/dist/lib/translations.d.mts +5 -0
- package/dist/lib/translations.d.ts +5 -0
- package/dist/lib/translations.js +55 -0
- package/dist/lib/translations.js.map +1 -0
- package/dist/providers/stack-provider-client.d.mts +3 -3
- package/dist/providers/stack-provider-client.d.ts +3 -3
- package/dist/providers/stack-provider.d.mts +6 -3
- package/dist/providers/stack-provider.d.ts +6 -3
- package/dist/providers/stack-provider.js +4 -2
- package/dist/providers/stack-provider.js.map +1 -1
- package/dist/providers/theme-provider.d.mts +2 -2
- package/dist/providers/theme-provider.d.ts +2 -2
- package/dist/providers/theme-provider.js.map +1 -1
- package/dist/providers/translation-provider-client.d.mts +14 -0
- package/dist/providers/translation-provider-client.d.ts +14 -0
- package/dist/providers/translation-provider-client.js +43 -0
- package/dist/providers/translation-provider-client.js.map +1 -0
- package/dist/providers/translation-provider.d.mts +9 -0
- package/dist/providers/translation-provider.d.ts +9 -0
- package/dist/providers/translation-provider.js +37 -0
- package/dist/providers/translation-provider.js.map +1 -0
- package/dist/utils/browser-script.js +43 -8
- package/dist/utils/browser-script.js.map +1 -1
- package/package.json +20 -12
|
@@ -33,7 +33,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
33
|
var account_settings_exports = {};
|
|
34
34
|
__export(account_settings_exports, {
|
|
35
35
|
AccountSettings: () => AccountSettings,
|
|
36
|
-
TeamCreation: () => TeamCreation
|
|
36
|
+
TeamCreation: () => TeamCreation,
|
|
37
|
+
useDeleteAccountSection: () => useDeleteAccountSection
|
|
37
38
|
});
|
|
38
39
|
module.exports = __toCommonJS(account_settings_exports);
|
|
39
40
|
var import_yup = require("@hookform/resolvers/yup");
|
|
@@ -47,18 +48,20 @@ var import_stack_ui = require("@stackframe/stack-ui");
|
|
|
47
48
|
var import_lucide_react = require("lucide-react");
|
|
48
49
|
var import_otp = require("oslo/otp");
|
|
49
50
|
var QRCode = __toESM(require("qrcode"));
|
|
50
|
-
var import_react = require("react");
|
|
51
|
+
var import_react = __toESM(require("react"));
|
|
51
52
|
var import_react_hook_form = require("react-hook-form");
|
|
52
53
|
var yup = __toESM(require("yup"));
|
|
53
54
|
var import__ = require("..");
|
|
54
55
|
var import_form_warning = require("../components/elements/form-warning");
|
|
56
|
+
var import_maybe_full_page = require("../components/elements/maybe-full-page");
|
|
55
57
|
var import_sidebar_layout = require("../components/elements/sidebar-layout");
|
|
56
58
|
var import_user_avatar = require("../components/elements/user-avatar");
|
|
57
59
|
var import_profile_image_editor = require("../components/profile-image-editor");
|
|
58
60
|
var import_team_icon = require("../components/team-icon");
|
|
59
|
-
var
|
|
61
|
+
var import_translations = require("../lib/translations");
|
|
60
62
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
61
63
|
function AccountSettings(props) {
|
|
64
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
62
65
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
63
66
|
const teams = user.useTeams();
|
|
64
67
|
const stackApp = (0, import__.useStackApp)();
|
|
@@ -68,29 +71,25 @@ function AccountSettings(props) {
|
|
|
68
71
|
{
|
|
69
72
|
items: [
|
|
70
73
|
{
|
|
71
|
-
title: "My Profile",
|
|
74
|
+
title: t("My Profile"),
|
|
72
75
|
type: "item",
|
|
73
76
|
subpath: "/profile",
|
|
74
77
|
icon: import_lucide_react.Contact,
|
|
75
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
78
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfilePage, {})
|
|
76
79
|
},
|
|
77
80
|
{
|
|
78
|
-
title: "Security",
|
|
81
|
+
title: t("Security"),
|
|
79
82
|
type: "item",
|
|
80
|
-
icon: import_lucide_react.ShieldCheck,
|
|
81
83
|
subpath: "/security",
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(PasswordSection, {}),
|
|
85
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MfaSection, {})
|
|
86
|
-
] })
|
|
84
|
+
icon: import_lucide_react.ShieldCheck,
|
|
85
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SecurityPage, {})
|
|
87
86
|
},
|
|
88
87
|
{
|
|
89
|
-
title: "
|
|
90
|
-
subpath: "/sign-out",
|
|
88
|
+
title: t("Settings"),
|
|
91
89
|
type: "item",
|
|
92
|
-
|
|
93
|
-
|
|
90
|
+
subpath: "/settings",
|
|
91
|
+
icon: import_lucide_react.Settings,
|
|
92
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SettingsPage, {})
|
|
94
93
|
},
|
|
95
94
|
...props.extraItems?.map((item) => ({
|
|
96
95
|
title: item.title,
|
|
@@ -100,7 +99,7 @@ function AccountSettings(props) {
|
|
|
100
99
|
content: item.content
|
|
101
100
|
})) || [],
|
|
102
101
|
...teams.length > 0 || project.config.clientTeamCreationEnabled ? [{
|
|
103
|
-
title: "Teams",
|
|
102
|
+
title: t("Teams"),
|
|
104
103
|
type: "divider"
|
|
105
104
|
}] : [],
|
|
106
105
|
...teams.map((team) => ({
|
|
@@ -110,61 +109,108 @@ function AccountSettings(props) {
|
|
|
110
109
|
] }),
|
|
111
110
|
type: "item",
|
|
112
111
|
subpath: `/teams/${team.id}`,
|
|
113
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime.
|
|
114
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ProfileSettings, { team }),
|
|
115
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ManagementSettings, { team }),
|
|
116
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MemberInvitation, { team }),
|
|
117
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(MembersSettings, { team }),
|
|
118
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(UserSettings, { team })
|
|
119
|
-
] })
|
|
112
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TeamPage, { team })
|
|
120
113
|
})),
|
|
121
114
|
...project.config.clientTeamCreationEnabled ? [{
|
|
122
|
-
title: "Create a team",
|
|
115
|
+
title: t("Create a team"),
|
|
123
116
|
icon: import_lucide_react.CirclePlus,
|
|
124
117
|
type: "item",
|
|
125
118
|
subpath: "/team-creation",
|
|
126
119
|
content: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TeamCreation, {})
|
|
127
120
|
}] : []
|
|
128
121
|
].filter((p) => p.type === "divider" || p.content),
|
|
129
|
-
title: "Account Settings",
|
|
122
|
+
title: t("Account Settings"),
|
|
130
123
|
basePath: stackApp.urls.accountSettings
|
|
131
124
|
}
|
|
132
125
|
) }) });
|
|
133
126
|
}
|
|
134
|
-
function
|
|
127
|
+
function Section(props) {
|
|
128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex", children: [
|
|
129
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex-1 flex flex-col justify-center", children: [
|
|
130
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { className: "font-medium", children: props.title }),
|
|
131
|
+
props.description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "secondary", type: "footnote", children: props.description })
|
|
132
|
+
] }),
|
|
133
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex-1 flex flex-col gap-2", children: props.children })
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
function PageLayout(props) {
|
|
137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-6", children: [
|
|
138
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Separator, {}),
|
|
139
|
+
import_react.default.Children.map(props.children, (child) => child && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
140
|
+
child,
|
|
141
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Separator, {})
|
|
142
|
+
] }))
|
|
143
|
+
] });
|
|
144
|
+
}
|
|
145
|
+
function ProfilePage() {
|
|
146
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
135
147
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
136
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
137
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
149
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
150
|
+
Section,
|
|
151
|
+
{
|
|
152
|
+
title: t("User name"),
|
|
153
|
+
description: t("This is a display name and is not used for authentication"),
|
|
154
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
155
|
+
import_stack_ui.EditableText,
|
|
156
|
+
{
|
|
157
|
+
value: user.displayName || "",
|
|
158
|
+
onSave: async (newDisplayName) => {
|
|
159
|
+
await user.update({ displayName: newDisplayName });
|
|
160
|
+
}
|
|
145
161
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
),
|
|
165
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
166
|
+
Section,
|
|
167
|
+
{
|
|
168
|
+
title: t("Profile image"),
|
|
169
|
+
description: t("Upload your own image as your avatar"),
|
|
170
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
171
|
+
import_profile_image_editor.ProfileImageEditor,
|
|
172
|
+
{
|
|
173
|
+
user,
|
|
174
|
+
onProfileImageUrlChange: async (profileImageUrl) => {
|
|
175
|
+
await user.update({ profileImageUrl });
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
)
|
|
155
181
|
] });
|
|
156
182
|
}
|
|
157
|
-
function
|
|
183
|
+
function SecurityPage() {
|
|
184
|
+
const emailVerificationSection = useEmailVerificationSection();
|
|
185
|
+
const passwordSection = usePasswordSection();
|
|
186
|
+
const mfaSection = useMfaSection();
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
188
|
+
emailVerificationSection,
|
|
189
|
+
passwordSection,
|
|
190
|
+
mfaSection
|
|
191
|
+
] });
|
|
192
|
+
}
|
|
193
|
+
function SettingsPage() {
|
|
194
|
+
const deleteAccountSection = useDeleteAccountSection();
|
|
195
|
+
const signOutSection = useSignOutSection();
|
|
196
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
197
|
+
deleteAccountSection,
|
|
198
|
+
signOutSection
|
|
199
|
+
] });
|
|
200
|
+
}
|
|
201
|
+
function useEmailVerificationSection() {
|
|
202
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
158
203
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
159
204
|
const [emailSent, setEmailSent] = (0, import_react.useState)(false);
|
|
160
205
|
if (!user.primaryEmail) {
|
|
161
206
|
return null;
|
|
162
207
|
}
|
|
163
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
208
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
209
|
+
Section,
|
|
210
|
+
{
|
|
211
|
+
title: t("Email Verification"),
|
|
212
|
+
description: t("Verify your email address to secure your account"),
|
|
213
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: user.primaryEmailVerified ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: t("Your email has been verified.") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
168
214
|
import_stack_ui.Button,
|
|
169
215
|
{
|
|
170
216
|
disabled: emailSent,
|
|
@@ -172,28 +218,29 @@ function EmailVerificationSection() {
|
|
|
172
218
|
await user.sendVerificationEmail();
|
|
173
219
|
setEmailSent(true);
|
|
174
220
|
},
|
|
175
|
-
children: emailSent ? "Email sent!" : "Send Verification Email"
|
|
221
|
+
children: emailSent ? t("Email sent!") : t("Send Verification Email")
|
|
176
222
|
}
|
|
177
|
-
) })
|
|
178
|
-
|
|
179
|
-
|
|
223
|
+
) }) })
|
|
224
|
+
}
|
|
225
|
+
);
|
|
180
226
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
227
|
+
function usePasswordSection() {
|
|
228
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
229
|
+
const passwordSchema = (0, import_schema_fields.yupObject)({
|
|
230
|
+
oldPassword: (0, import_schema_fields.yupString)().required(t("Please enter your old password")),
|
|
231
|
+
newPassword: (0, import_schema_fields.yupString)().required(t("Please enter your password")).test({
|
|
232
|
+
name: "is-valid-password",
|
|
233
|
+
test: (value, ctx) => {
|
|
234
|
+
const error = (0, import_password.getPasswordError)(value);
|
|
235
|
+
if (error) {
|
|
236
|
+
return ctx.createError({ message: error.message });
|
|
237
|
+
} else {
|
|
238
|
+
return true;
|
|
239
|
+
}
|
|
191
240
|
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
});
|
|
196
|
-
function PasswordSection() {
|
|
241
|
+
}),
|
|
242
|
+
newPasswordRepeat: (0, import_schema_fields.yupString)().nullable().oneOf([yup.ref("newPassword"), "", null], t("Passwords do not match")).required(t("Please repeat your password"))
|
|
243
|
+
});
|
|
197
244
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
198
245
|
const [changingPassword, setChangingPassword] = (0, import_react.useState)(false);
|
|
199
246
|
const { register, handleSubmit, setError, formState: { errors }, clearErrors, reset } = (0, import_react_hook_form.useForm)({
|
|
@@ -207,7 +254,7 @@ function PasswordSection() {
|
|
|
207
254
|
const { oldPassword, newPassword } = data;
|
|
208
255
|
const error = await user.updatePassword({ oldPassword, newPassword });
|
|
209
256
|
if (error) {
|
|
210
|
-
setError("oldPassword", { type: "manual", message: "Incorrect password" });
|
|
257
|
+
setError("oldPassword", { type: "manual", message: t("Incorrect password") });
|
|
211
258
|
} else {
|
|
212
259
|
reset();
|
|
213
260
|
setAlreadyReset(true);
|
|
@@ -222,15 +269,15 @@ function PasswordSection() {
|
|
|
222
269
|
return null;
|
|
223
270
|
}
|
|
224
271
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
225
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: "Change password" }),
|
|
226
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: alreadyReset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: "Password changed successfully!" }) : !changingPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
272
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { children: t("Change password") }),
|
|
273
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: alreadyReset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "success", children: t("Password changed successfully!") }) : !changingPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
227
274
|
import_stack_ui.Button,
|
|
228
275
|
{
|
|
229
276
|
variant: "secondary",
|
|
230
277
|
onClick: async () => {
|
|
231
278
|
setChangingPassword(true);
|
|
232
279
|
},
|
|
233
|
-
children: "Change Password"
|
|
280
|
+
children: t("Change Password")
|
|
234
281
|
}
|
|
235
282
|
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
236
283
|
"form",
|
|
@@ -238,7 +285,7 @@ function PasswordSection() {
|
|
|
238
285
|
onSubmit: (e) => (0, import_promises.runAsynchronouslyWithAlert)(handleSubmit(onSubmit)(e)),
|
|
239
286
|
noValidate: true,
|
|
240
287
|
children: [
|
|
241
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "old-password", className: "mb-1", children: "Old password" }),
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "old-password", className: "mb-1", children: t("Old password") }),
|
|
242
289
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
243
290
|
import_stack_ui.Input,
|
|
244
291
|
{
|
|
@@ -248,7 +295,7 @@ function PasswordSection() {
|
|
|
248
295
|
}
|
|
249
296
|
),
|
|
250
297
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.oldPassword?.message?.toString() }),
|
|
251
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "new-password", className: "mt-4 mb-1", children: "Password" }),
|
|
298
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "new-password", className: "mt-4 mb-1", children: t("Password") }),
|
|
252
299
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
253
300
|
import_stack_ui.PasswordInput,
|
|
254
301
|
{
|
|
@@ -262,7 +309,7 @@ function PasswordSection() {
|
|
|
262
309
|
}
|
|
263
310
|
),
|
|
264
311
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.newPassword?.message?.toString() }),
|
|
265
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "repeat-password", className: "mt-4 mb-1", children: "Repeat password" }),
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Label, { htmlFor: "repeat-password", className: "mt-4 mb-1", children: t("Repeat password") }),
|
|
266
313
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
267
314
|
import_stack_ui.PasswordInput,
|
|
268
315
|
{
|
|
@@ -276,13 +323,14 @@ function PasswordSection() {
|
|
|
276
323
|
}
|
|
277
324
|
),
|
|
278
325
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.newPasswordRepeat?.message?.toString() }),
|
|
279
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", className: "mt-6", loading, children: "Change Password" })
|
|
326
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", className: "mt-6", loading, children: t("Change Password") })
|
|
280
327
|
]
|
|
281
328
|
}
|
|
282
329
|
) })
|
|
283
330
|
] });
|
|
284
331
|
}
|
|
285
|
-
function
|
|
332
|
+
function useMfaSection() {
|
|
333
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
286
334
|
const project = (0, import__.useStackApp)().useProject();
|
|
287
335
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
288
336
|
const [generatedSecret, setGeneratedSecret] = (0, import_react.useState)(null);
|
|
@@ -307,100 +355,165 @@ function MfaSection() {
|
|
|
307
355
|
setIsMaybeWrong(true);
|
|
308
356
|
});
|
|
309
357
|
}, [mfaCode, generatedSecret, handleSubmit]);
|
|
310
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
/* @__PURE__ */ (0, import_jsx_runtime.
|
|
317
|
-
|
|
318
|
-
|
|
358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
359
|
+
Section,
|
|
360
|
+
{
|
|
361
|
+
title: t("Multi-factor Authentication"),
|
|
362
|
+
description: isEnabled ? t("Multi-factor authentication is currently enabled.") : t("Multi-factor authentication is currently disabled."),
|
|
363
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
364
|
+
!isEnabled && generatedSecret && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("Scan this QR code with your authenticator app:") }),
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { width: 200, height: 200, src: qrCodeUrl ?? (0, import_errors.throwErr)("TOTP QR code failed to generate"), alt: t("TOTP multi-factor authentication QR code") }),
|
|
367
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: t("Then, enter your six-digit MFA code:") }),
|
|
368
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
369
|
+
import_stack_ui.Input,
|
|
370
|
+
{
|
|
371
|
+
value: mfaCode,
|
|
372
|
+
onChange: (e) => {
|
|
373
|
+
setIsMaybeWrong(false);
|
|
374
|
+
setMfaCode(e.target.value);
|
|
375
|
+
},
|
|
376
|
+
placeholder: "123456",
|
|
377
|
+
maxLength: 6,
|
|
378
|
+
disabled: isLoading
|
|
379
|
+
}
|
|
380
|
+
),
|
|
381
|
+
isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Incorrect code. Please try again.") }),
|
|
382
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
383
|
+
import_stack_ui.Button,
|
|
384
|
+
{
|
|
385
|
+
variant: "secondary",
|
|
386
|
+
onClick: () => {
|
|
387
|
+
setGeneratedSecret(null);
|
|
388
|
+
setQrCodeUrl(null);
|
|
389
|
+
setMfaCode("");
|
|
390
|
+
},
|
|
391
|
+
children: t("Cancel")
|
|
392
|
+
}
|
|
393
|
+
) })
|
|
394
|
+
] }),
|
|
395
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex gap-2", children: isEnabled ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
396
|
+
import_stack_ui.Button,
|
|
319
397
|
{
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
setIsMaybeWrong(false);
|
|
323
|
-
setMfaCode(e.target.value);
|
|
324
|
-
},
|
|
325
|
-
placeholder: "123456",
|
|
326
|
-
maxLength: 6,
|
|
327
|
-
disabled: isLoading
|
|
328
|
-
}
|
|
329
|
-
),
|
|
330
|
-
isMaybeWrong && mfaCode.length === 6 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Incorrect code. Please try again." })
|
|
331
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Multi-factor authentication is currently disabled." }),
|
|
332
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
333
|
-
import_stack_ui.Button,
|
|
334
|
-
{
|
|
335
|
-
className: "mt-4",
|
|
336
|
-
variant: isEnabled ? "secondary" : "default",
|
|
337
|
-
onClick: async () => {
|
|
338
|
-
if (isEnabled) {
|
|
398
|
+
variant: "secondary",
|
|
399
|
+
onClick: async () => {
|
|
339
400
|
await user.update({
|
|
340
401
|
totpMultiFactorSecret: null
|
|
341
402
|
});
|
|
342
|
-
}
|
|
403
|
+
},
|
|
404
|
+
children: t("Disable")
|
|
405
|
+
}
|
|
406
|
+
) : !generatedSecret && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
407
|
+
import_stack_ui.Button,
|
|
408
|
+
{
|
|
409
|
+
variant: "default",
|
|
410
|
+
onClick: async () => {
|
|
343
411
|
const secret = (0, import_crypto.generateRandomValues)(new Uint8Array(20));
|
|
344
412
|
setQrCodeUrl(await generateTotpQrCode(project, user, secret));
|
|
345
413
|
setGeneratedSecret(secret);
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
}
|
|
354
|
-
)
|
|
355
|
-
] })
|
|
356
|
-
] }) });
|
|
414
|
+
},
|
|
415
|
+
children: t("Enable")
|
|
416
|
+
}
|
|
417
|
+
) })
|
|
418
|
+
] })
|
|
419
|
+
}
|
|
420
|
+
);
|
|
357
421
|
}
|
|
358
422
|
async function generateTotpQrCode(project, user, secret) {
|
|
359
423
|
const uri = (0, import_otp.createTOTPKeyURI)(project.displayName, user.primaryEmail ?? user.id, secret);
|
|
360
424
|
return await QRCode.toDataURL(uri);
|
|
361
425
|
}
|
|
362
|
-
function
|
|
426
|
+
function useSignOutSection() {
|
|
427
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
363
428
|
const user = (0, import__.useUser)({ or: "throw" });
|
|
364
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
365
|
-
|
|
429
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
430
|
+
Section,
|
|
366
431
|
{
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
children: "
|
|
432
|
+
title: t("Sign out"),
|
|
433
|
+
description: t("End your current session"),
|
|
434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
435
|
+
import_stack_ui.Button,
|
|
436
|
+
{
|
|
437
|
+
variant: "secondary",
|
|
438
|
+
onClick: () => user.signOut(),
|
|
439
|
+
children: t("Sign out")
|
|
440
|
+
}
|
|
441
|
+
) })
|
|
370
442
|
}
|
|
371
|
-
)
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
function TeamPage(props) {
|
|
446
|
+
const teamUserProfileSection = useTeamUserProfileSection(props);
|
|
447
|
+
const teamProfileImageSection = useTeamProfileImageSection(props);
|
|
448
|
+
const teamDisplayNameSection = useTeamDisplayNameSection(props);
|
|
449
|
+
const leaveTeamSection = useLeaveTeamSection(props);
|
|
450
|
+
const memberInvitationSection = useMemberInvitationSection(props);
|
|
451
|
+
const memberListSection = useMemberListSection(props);
|
|
452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(PageLayout, { children: [
|
|
453
|
+
teamUserProfileSection,
|
|
454
|
+
memberInvitationSection,
|
|
455
|
+
memberListSection,
|
|
456
|
+
teamProfileImageSection,
|
|
457
|
+
teamDisplayNameSection,
|
|
458
|
+
leaveTeamSection
|
|
459
|
+
] });
|
|
372
460
|
}
|
|
373
|
-
function
|
|
461
|
+
function useLeaveTeamSection(props) {
|
|
462
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
374
463
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
375
464
|
const [leaving, setLeaving] = (0, import_react.useState)(false);
|
|
376
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
377
|
-
|
|
465
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
466
|
+
Section,
|
|
378
467
|
{
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
children: "
|
|
468
|
+
title: t("Leave Team"),
|
|
469
|
+
description: t("leave this team and remove your team profile"),
|
|
470
|
+
children: !leaving ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
471
|
+
import_stack_ui.Button,
|
|
472
|
+
{
|
|
473
|
+
variant: "secondary",
|
|
474
|
+
onClick: () => setLeaving(true),
|
|
475
|
+
children: t("Leave team")
|
|
476
|
+
}
|
|
477
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
478
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Are you sure you want to leave the team?") }),
|
|
479
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
480
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
481
|
+
import_stack_ui.Button,
|
|
482
|
+
{
|
|
483
|
+
variant: "destructive",
|
|
484
|
+
onClick: async () => {
|
|
485
|
+
await user.leaveTeam(props.team);
|
|
486
|
+
window.location.reload();
|
|
487
|
+
},
|
|
488
|
+
children: t("Leave")
|
|
489
|
+
}
|
|
490
|
+
),
|
|
491
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
492
|
+
import_stack_ui.Button,
|
|
493
|
+
{
|
|
494
|
+
variant: "secondary",
|
|
495
|
+
onClick: () => setLeaving(false),
|
|
496
|
+
children: t("Cancel")
|
|
497
|
+
}
|
|
498
|
+
)
|
|
499
|
+
] })
|
|
500
|
+
] })
|
|
382
501
|
}
|
|
383
|
-
)
|
|
384
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: "Are you sure you want to leave the team?" }),
|
|
385
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
386
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "destructive", onClick: async () => {
|
|
387
|
-
await user.leaveTeam(props.team);
|
|
388
|
-
window.location.reload();
|
|
389
|
-
}, children: "Leave" }),
|
|
390
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { variant: "secondary", onClick: () => setLeaving(false), children: "Cancel" })
|
|
391
|
-
] })
|
|
392
|
-
] }) }) });
|
|
502
|
+
);
|
|
393
503
|
}
|
|
394
|
-
function
|
|
504
|
+
function useTeamProfileImageSection(props) {
|
|
505
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
395
506
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
396
507
|
const updateTeamPermission = user.usePermission(props.team, "$update_team");
|
|
397
508
|
if (!updateTeamPermission) {
|
|
398
509
|
return null;
|
|
399
510
|
}
|
|
400
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
511
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
512
|
+
Section,
|
|
513
|
+
{
|
|
514
|
+
title: t("Team profile image"),
|
|
515
|
+
description: t("Upload an image for your team"),
|
|
516
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
404
517
|
import_profile_image_editor.ProfileImageEditor,
|
|
405
518
|
{
|
|
406
519
|
user: props.team,
|
|
@@ -409,42 +522,57 @@ function ManagementSettings(props) {
|
|
|
409
522
|
}
|
|
410
523
|
}
|
|
411
524
|
)
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
function useTeamDisplayNameSection(props) {
|
|
529
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
530
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
531
|
+
const updateTeamPermission = user.usePermission(props.team, "$update_team");
|
|
532
|
+
if (!updateTeamPermission) {
|
|
533
|
+
return null;
|
|
534
|
+
}
|
|
535
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
536
|
+
Section,
|
|
537
|
+
{
|
|
538
|
+
title: t("Team display name"),
|
|
539
|
+
description: t("Change the display name of your team"),
|
|
540
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
416
541
|
import_stack_ui.EditableText,
|
|
417
542
|
{
|
|
418
543
|
value: props.team.displayName,
|
|
419
544
|
onSave: async (newDisplayName) => await props.team.update({ displayName: newDisplayName })
|
|
420
545
|
}
|
|
421
546
|
)
|
|
422
|
-
|
|
423
|
-
|
|
547
|
+
}
|
|
548
|
+
);
|
|
424
549
|
}
|
|
425
|
-
function
|
|
550
|
+
function useTeamUserProfileSection(props) {
|
|
551
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
426
552
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
427
553
|
const profile = user.useTeamProfile(props.team);
|
|
428
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
554
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
555
|
+
Section,
|
|
556
|
+
{
|
|
557
|
+
title: t("Team user name"),
|
|
558
|
+
description: t("Overwrite your user display name in this team"),
|
|
559
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
560
|
+
import_stack_ui.EditableText,
|
|
561
|
+
{
|
|
562
|
+
value: profile.displayName || "",
|
|
563
|
+
onSave: async (newDisplayName) => {
|
|
564
|
+
await profile.update({ displayName: newDisplayName });
|
|
565
|
+
}
|
|
439
566
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
567
|
+
)
|
|
568
|
+
}
|
|
569
|
+
);
|
|
443
570
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
571
|
+
function useMemberInvitationSection(props) {
|
|
572
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
573
|
+
const invitationSchema = (0, import_schema_fields.yupObject)({
|
|
574
|
+
email: (0, import_schema_fields.yupString)().email().required(t("Please enter an email address"))
|
|
575
|
+
});
|
|
448
576
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
449
577
|
const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
|
|
450
578
|
if (!inviteMemberPermission) {
|
|
@@ -467,35 +595,40 @@ function MemberInvitation(props) {
|
|
|
467
595
|
(0, import_react.useEffect)(() => {
|
|
468
596
|
setInvitedEmail(null);
|
|
469
597
|
}, [watch("email")]);
|
|
470
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
"
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
598
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
599
|
+
Section,
|
|
600
|
+
{
|
|
601
|
+
title: t("Invite member"),
|
|
602
|
+
description: t("Invite a user to your team through email"),
|
|
603
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
604
|
+
"form",
|
|
605
|
+
{
|
|
606
|
+
onSubmit: (e) => (0, import_promises.runAsynchronouslyWithAlert)(handleSubmit(onSubmit)(e)),
|
|
607
|
+
noValidate: true,
|
|
608
|
+
children: [
|
|
609
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-4 md:flex-row", children: [
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
611
|
+
import_stack_ui.Input,
|
|
612
|
+
{
|
|
613
|
+
placeholder: t("Email"),
|
|
614
|
+
...register("email")
|
|
615
|
+
}
|
|
616
|
+
),
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", loading, children: t("Invite User") })
|
|
618
|
+
] }),
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.email?.message?.toString() }),
|
|
620
|
+
invitedEmail && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Typography, { type: "label", variant: "secondary", children: [
|
|
621
|
+
"Invited ",
|
|
622
|
+
invitedEmail
|
|
623
|
+
] })
|
|
624
|
+
]
|
|
625
|
+
}
|
|
626
|
+
)
|
|
627
|
+
}
|
|
628
|
+
);
|
|
497
629
|
}
|
|
498
|
-
function
|
|
630
|
+
function useMemberListSection(props) {
|
|
631
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
499
632
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
500
633
|
const readMemberPermission = user.usePermission(props.team, "$read_members");
|
|
501
634
|
const inviteMemberPermission = user.usePermission(props.team, "$invite_members");
|
|
@@ -507,23 +640,24 @@ function MembersSettings(props) {
|
|
|
507
640
|
return null;
|
|
508
641
|
}
|
|
509
642
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
510
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.
|
|
511
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Table, { children: [
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { className: "font-medium mb-2", children: t("Members") }),
|
|
644
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "border rounded-md", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.Table, { children: [
|
|
512
645
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
513
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[100px]", children: "User" }),
|
|
514
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[200px]", children: "Name" })
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[100px]", children: t("User") }),
|
|
647
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableHead, { className: "w-[200px]", children: t("Name") })
|
|
515
648
|
] }) }),
|
|
516
649
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableBody, { children: users.map(({ id, teamProfile }, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.TableRow, { children: [
|
|
517
650
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_user_avatar.UserAvatar, { user: teamProfile }) }),
|
|
518
651
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.TableCell, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { children: teamProfile.displayName }) })
|
|
519
652
|
] }, id)) })
|
|
520
|
-
] })
|
|
653
|
+
] }) })
|
|
521
654
|
] });
|
|
522
655
|
}
|
|
523
|
-
var teamCreationSchema = (0, import_schema_fields.yupObject)({
|
|
524
|
-
displayName: (0, import_schema_fields.yupString)().required("Please enter a team name")
|
|
525
|
-
});
|
|
526
656
|
function TeamCreation() {
|
|
657
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
658
|
+
const teamCreationSchema = (0, import_schema_fields.yupObject)({
|
|
659
|
+
displayName: (0, import_schema_fields.yupString)().required(t("Please enter a team name"))
|
|
660
|
+
});
|
|
527
661
|
const { register, handleSubmit, formState: { errors } } = (0, import_react_hook_form.useForm)({
|
|
528
662
|
resolver: (0, import_yup.yupResolver)(teamCreationSchema)
|
|
529
663
|
});
|
|
@@ -532,7 +666,7 @@ function TeamCreation() {
|
|
|
532
666
|
const user = (0, import__.useUser)({ or: "redirect" });
|
|
533
667
|
const [loading, setLoading] = (0, import_react.useState)(false);
|
|
534
668
|
if (!project.config.clientTeamCreationEnabled) {
|
|
535
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.MessageCard, { title: "Team creation is not enabled" });
|
|
669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import__.MessageCard, { title: t("Team creation is not enabled") });
|
|
536
670
|
}
|
|
537
671
|
const onSubmit = async (data) => {
|
|
538
672
|
setLoading(true);
|
|
@@ -542,33 +676,84 @@ function TeamCreation() {
|
|
|
542
676
|
setLoading(false);
|
|
543
677
|
}
|
|
544
678
|
};
|
|
545
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PageLayout, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, { title: t("Create a Team"), description: t("Enter a display name for your new team"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
546
680
|
"form",
|
|
547
681
|
{
|
|
548
|
-
className: "flex flex-col items-stretch stack-scope",
|
|
549
682
|
onSubmit: (e) => (0, import_promises.runAsynchronouslyWithAlert)(handleSubmit(onSubmit)(e)),
|
|
550
683
|
noValidate: true,
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
684
|
+
className: "flex gap-2",
|
|
685
|
+
children: [
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col flex-1", children: [
|
|
554
687
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
555
688
|
import_stack_ui.Input,
|
|
556
689
|
{
|
|
557
|
-
id: "
|
|
558
|
-
type: "
|
|
690
|
+
id: "displayName",
|
|
691
|
+
type: "text",
|
|
559
692
|
...register("displayName")
|
|
560
693
|
}
|
|
561
|
-
)
|
|
694
|
+
),
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_form_warning.FormWarningText, { text: errors.displayName?.message?.toString() })
|
|
562
696
|
] }),
|
|
563
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
564
|
-
|
|
565
|
-
] })
|
|
697
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Button, { type: "submit", loading, children: t("Create") })
|
|
698
|
+
]
|
|
566
699
|
}
|
|
567
700
|
) }) });
|
|
568
701
|
}
|
|
702
|
+
function useDeleteAccountSection() {
|
|
703
|
+
const { t } = (0, import_translations.useTranslation)();
|
|
704
|
+
const user = (0, import__.useUser)({ or: "redirect" });
|
|
705
|
+
const app = (0, import__.useStackApp)();
|
|
706
|
+
const project = app.useProject();
|
|
707
|
+
const [deleting, setDeleting] = (0, import_react.useState)(false);
|
|
708
|
+
if (!project.config.clientUserDeletionEnabled) {
|
|
709
|
+
return null;
|
|
710
|
+
}
|
|
711
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
712
|
+
Section,
|
|
713
|
+
{
|
|
714
|
+
title: t("Delete Account"),
|
|
715
|
+
description: t("Permanently remove your account and all associated data"),
|
|
716
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "stack-scope flex flex-col items-stretch", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Accordion, { type: "single", collapsible: true, className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_stack_ui.AccordionItem, { value: "item-1", children: [
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.AccordionTrigger, { children: t("Danger zone") }),
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.AccordionContent, { children: !deleting ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
719
|
+
import_stack_ui.Button,
|
|
720
|
+
{
|
|
721
|
+
variant: "destructive",
|
|
722
|
+
onClick: () => setDeleting(true),
|
|
723
|
+
children: t("Delete account")
|
|
724
|
+
}
|
|
725
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
726
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_stack_ui.Typography, { variant: "destructive", children: t("Are you sure you want to delete your account? This action is IRREVERSIBLE and will delete ALL associated data.") }),
|
|
727
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex gap-2", children: [
|
|
728
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
729
|
+
import_stack_ui.Button,
|
|
730
|
+
{
|
|
731
|
+
variant: "destructive",
|
|
732
|
+
onClick: async () => {
|
|
733
|
+
await user.delete();
|
|
734
|
+
await app.redirectToHome();
|
|
735
|
+
},
|
|
736
|
+
children: t("Delete Account")
|
|
737
|
+
}
|
|
738
|
+
),
|
|
739
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
740
|
+
import_stack_ui.Button,
|
|
741
|
+
{
|
|
742
|
+
variant: "secondary",
|
|
743
|
+
onClick: () => setDeleting(false),
|
|
744
|
+
children: t("Cancel")
|
|
745
|
+
}
|
|
746
|
+
)
|
|
747
|
+
] })
|
|
748
|
+
] }) })
|
|
749
|
+
] }) }) })
|
|
750
|
+
}
|
|
751
|
+
);
|
|
752
|
+
}
|
|
569
753
|
// Annotate the CommonJS export names for ESM import in node:
|
|
570
754
|
0 && (module.exports = {
|
|
571
755
|
AccountSettings,
|
|
572
|
-
TeamCreation
|
|
756
|
+
TeamCreation,
|
|
757
|
+
useDeleteAccountSection
|
|
573
758
|
});
|
|
574
759
|
//# sourceMappingURL=account-settings.js.map
|