@micha.bigler/ui-core-micha 2.2.2 → 2.2.3
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/components/QrSignupManager.js +1 -1
- package/dist/components/RegistrationMethodsManager.js +12 -2
- package/dist/i18n/authTranslations.js +6 -0
- package/dist/pages/SignUpPage.js +1 -1
- package/package.json +1 -1
- package/src/components/QrSignupManager.jsx +8 -0
- package/src/components/RegistrationMethodsManager.jsx +24 -1
- package/src/i18n/authTranslations.ts +6 -0
- package/src/pages/SignUpPage.jsx +0 -11
|
@@ -77,5 +77,5 @@ export function QrSignupManager({ enabled = false }) {
|
|
|
77
77
|
active = false;
|
|
78
78
|
};
|
|
79
79
|
}, [enabled, label, t]);
|
|
80
|
-
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.SIGNUP_QR_MANAGER_TITLE', 'QR Signup') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Auth.SIGNUP_QR_MANAGER_HINT', 'When QR signup is enabled, a signup QR code is shown here immediately.') }), error && _jsx(Alert, { severity: "error", sx: { mb: 2 }, children: error }), success && _jsx(Alert, { severity: "success", sx: { mb: 2 }, children: success }), !enabled && (_jsx(Alert, { severity: "info", sx: { mb: 2 }, children: t('Auth.SIGNUP_QR_DISABLED_HINT', 'Enable self-signup by QR above to show a QR code here.') })), _jsx(TextField, { label: t('Common.LABEL', 'Label'), value: label, onChange: (event) => setLabel(event.target.value), fullWidth: true, disabled: !enabled || busy }), _jsx(Button, { variant: "contained", sx: { mt: 2 }, onClick: generate, disabled: !enabled || busy, children: t('Common.SAVE', 'Save') }), (result === null || result === void 0 ? void 0 : result.signup_url) && (_jsxs(Box, { sx: { mt: 3 }, children: [_jsx(QRCodeSVG, { value: result.signup_url, size: 180, includeMargin: true }), _jsx(TextField, { label: t('Auth.SIGNUP_QR_LINK_LABEL', 'Signup link'), value: result.signup_url, fullWidth: true, multiline: true, minRows: 2, sx: { mt: 2 }, InputProps: { readOnly: true } })] }))] }));
|
|
80
|
+
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.SIGNUP_QR_MANAGER_TITLE', 'QR Signup') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Auth.SIGNUP_QR_MANAGER_HINT', 'When QR signup is enabled, a signup QR code is shown here immediately.') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Auth.SIGNUP_QR_POLICY_HINT', 'The default QR validity is configured in the authentication policy above.') }), error && _jsx(Alert, { severity: "error", sx: { mb: 2 }, children: error }), success && _jsx(Alert, { severity: "success", sx: { mb: 2 }, children: success }), !enabled && (_jsx(Alert, { severity: "info", sx: { mb: 2 }, children: t('Auth.SIGNUP_QR_DISABLED_HINT', 'Enable self-signup by QR above to show a QR code here.') })), _jsx(TextField, { label: t('Common.LABEL', 'Label'), value: label, onChange: (event) => setLabel(event.target.value), fullWidth: true, disabled: !enabled || busy }), _jsx(Button, { variant: "contained", sx: { mt: 2 }, onClick: generate, disabled: !enabled || busy, children: t('Common.SAVE', 'Save') }), (result === null || result === void 0 ? void 0 : result.signup_url) && (_jsxs(Box, { sx: { mt: 3 }, children: [_jsx(QRCodeSVG, { value: result.signup_url, size: 180, includeMargin: true }), _jsx(TextField, { label: t('Auth.SIGNUP_QR_LINK_LABEL', 'Signup link'), value: result.signup_url, fullWidth: true, multiline: true, minRows: 2, sx: { mt: 2 }, InputProps: { readOnly: true } }), (result === null || result === void 0 ? void 0 : result.expires_at) && (_jsxs(Typography, { variant: "body2", sx: { mt: 1.5, color: 'text.secondary' }, children: [t('Auth.SIGNUP_QR_VALID_UNTIL', 'Valid until'), ": ", result.expires_at] }))] }))] }));
|
|
81
81
|
}
|
|
@@ -11,11 +11,13 @@ const EMPTY_POLICY = {
|
|
|
11
11
|
allow_self_signup_qr: false,
|
|
12
12
|
allowed_email_domains: [],
|
|
13
13
|
required_auth_factor_count: 1,
|
|
14
|
+
signup_qr_expiry_days: 90,
|
|
14
15
|
};
|
|
15
16
|
export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
16
17
|
const { t } = useTranslation();
|
|
17
18
|
const [policy, setPolicy] = useState(EMPTY_POLICY);
|
|
18
19
|
const [domainsText, setDomainsText] = useState('');
|
|
20
|
+
const [signupQrExpiryDays, setSignupQrExpiryDays] = useState(String(EMPTY_POLICY.signup_qr_expiry_days));
|
|
19
21
|
const [busy, setBusy] = useState(false);
|
|
20
22
|
const [busyField, setBusyField] = useState('');
|
|
21
23
|
const [error, setError] = useState('');
|
|
@@ -29,6 +31,7 @@ export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
|
29
31
|
return;
|
|
30
32
|
setPolicy((prev) => (Object.assign(Object.assign({}, prev), data)));
|
|
31
33
|
setDomainsText(((data === null || data === void 0 ? void 0 : data.allowed_email_domains) || []).join('\n'));
|
|
34
|
+
setSignupQrExpiryDays(String((data === null || data === void 0 ? void 0 : data.signup_qr_expiry_days) || EMPTY_POLICY.signup_qr_expiry_days));
|
|
32
35
|
if (onPolicyChange)
|
|
33
36
|
onPolicyChange(data);
|
|
34
37
|
}
|
|
@@ -73,9 +76,16 @@ export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
|
73
76
|
.split(/\r?\n/)
|
|
74
77
|
.map((value) => value.trim())
|
|
75
78
|
.filter(Boolean);
|
|
76
|
-
const
|
|
79
|
+
const parsedExpiryDays = parseInt(signupQrExpiryDays, 10);
|
|
80
|
+
const next = await updateAuthPolicy({
|
|
81
|
+
allowed_email_domains,
|
|
82
|
+
signup_qr_expiry_days: Number.isFinite(parsedExpiryDays) && parsedExpiryDays > 0
|
|
83
|
+
? parsedExpiryDays
|
|
84
|
+
: EMPTY_POLICY.signup_qr_expiry_days,
|
|
85
|
+
});
|
|
77
86
|
setPolicy((prev) => (Object.assign(Object.assign({}, prev), next)));
|
|
78
87
|
setDomainsText(((next === null || next === void 0 ? void 0 : next.allowed_email_domains) || allowed_email_domains).join('\n'));
|
|
88
|
+
setSignupQrExpiryDays(String((next === null || next === void 0 ? void 0 : next.signup_qr_expiry_days) || EMPTY_POLICY.signup_qr_expiry_days));
|
|
79
89
|
setSuccess(t('Auth.AUTH_POLICY_SAVE_SUCCESS', 'Authentication settings saved.'));
|
|
80
90
|
if (onPolicyChange)
|
|
81
91
|
onPolicyChange(next);
|
|
@@ -87,5 +97,5 @@ export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
|
87
97
|
setBusy(false);
|
|
88
98
|
}
|
|
89
99
|
};
|
|
90
|
-
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.REGISTRATION_METHODS_TITLE', 'Registration Methods') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Auth.REGISTRATION_METHODS_HINT', 'Choose which signup and invite flows are active for this app.') }), error && _jsx(Alert, { severity: "error", sx: { mb: 2 }, children: error }), success && _jsx(Alert, { severity: "success", sx: { mb: 2 }, children: success }), _jsxs(Stack, { spacing: 1, children: [_jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_admin_invite), onChange: toggle('allow_admin_invite'), disabled: Boolean(busyField) })), label: t('Auth.ADMIN_INVITE_LABEL', 'Admin invite') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_access_code), onChange: toggle('allow_self_signup_access_code'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_ACCESS_CODE_LABEL', 'Self-signup with access code') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_open), onChange: toggle('allow_self_signup_open'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_OPEN_LABEL', 'Open self-signup') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_email_domain), onChange: toggle('allow_self_signup_email_domain'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_EMAIL_DOMAIN_LABEL', 'Self-signup by email domain') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_qr), onChange: toggle('allow_self_signup_qr'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_QR_LABEL', 'Self-signup by QR') })] }), policy.allow_self_signup_email_domain && !(policy.allowed_email_domains || []).length && (_jsx(Alert, { severity: "info", sx: { mt: 2 }, children: t('Auth.EMAIL_DOMAIN_CURRENTLY_BLOCKED_HINT', 'Email-domain signup is enabled, but it stays blocked until at least one allowed domain is saved.') })), _jsx(TextField, { label: t('Auth.ALLOWED_EMAIL_DOMAINS_LABEL', 'Allowed email domains'), helperText: t('Auth.ALLOWED_EMAIL_DOMAINS_HINT', 'One domain per line, e.g. example.org. You can leave this empty temporarily.'), multiline: true, minRows: 3, fullWidth: true, sx: { mt: 2 }, value: domainsText, onChange: (event) => setDomainsText(event.target.value) }), _jsx(Button, { variant: "contained", sx: { mt: 2 }, onClick: save, disabled: busy, children: t('Common.SAVE', 'Save') })] }));
|
|
100
|
+
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t('Auth.REGISTRATION_METHODS_TITLE', 'Registration Methods') }), _jsx(Typography, { variant: "body2", sx: { mb: 2, color: 'text.secondary' }, children: t('Auth.REGISTRATION_METHODS_HINT', 'Choose which signup and invite flows are active for this app.') }), error && _jsx(Alert, { severity: "error", sx: { mb: 2 }, children: error }), success && _jsx(Alert, { severity: "success", sx: { mb: 2 }, children: success }), _jsxs(Stack, { spacing: 1, children: [_jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_admin_invite), onChange: toggle('allow_admin_invite'), disabled: Boolean(busyField) })), label: t('Auth.ADMIN_INVITE_LABEL', 'Admin invite') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_access_code), onChange: toggle('allow_self_signup_access_code'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_ACCESS_CODE_LABEL', 'Self-signup with access code') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_open), onChange: toggle('allow_self_signup_open'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_OPEN_LABEL', 'Open self-signup') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_email_domain), onChange: toggle('allow_self_signup_email_domain'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_EMAIL_DOMAIN_LABEL', 'Self-signup by email domain') }), _jsx(FormControlLabel, { control: (_jsx(Switch, { checked: Boolean(policy.allow_self_signup_qr), onChange: toggle('allow_self_signup_qr'), disabled: Boolean(busyField) })), label: t('Auth.SIGNUP_QR_LABEL', 'Self-signup by QR') })] }), policy.allow_self_signup_email_domain && !(policy.allowed_email_domains || []).length && (_jsx(Alert, { severity: "info", sx: { mt: 2 }, children: t('Auth.EMAIL_DOMAIN_CURRENTLY_BLOCKED_HINT', 'Email-domain signup is enabled, but it stays blocked until at least one allowed domain is saved.') })), _jsx(TextField, { label: t('Auth.ALLOWED_EMAIL_DOMAINS_LABEL', 'Allowed email domains'), helperText: t('Auth.ALLOWED_EMAIL_DOMAINS_HINT', 'One domain per line, e.g. example.org. You can leave this empty temporarily.'), multiline: true, minRows: 3, fullWidth: true, sx: { mt: 2 }, value: domainsText, onChange: (event) => setDomainsText(event.target.value) }), _jsx(TextField, { label: t('Auth.SIGNUP_QR_EXPIRY_DAYS_LABEL', 'QR signup validity (days)'), helperText: t('Auth.SIGNUP_QR_EXPIRY_DAYS_HINT', 'Default validity for newly generated QR signup links.'), type: "number", fullWidth: true, sx: { mt: 2 }, value: signupQrExpiryDays, onChange: (event) => setSignupQrExpiryDays(event.target.value) }), _jsx(Button, { variant: "contained", sx: { mt: 2 }, onClick: save, disabled: busy, children: t('Common.SAVE', 'Save') })] }));
|
|
91
101
|
}
|
|
@@ -840,6 +840,12 @@ export const authTranslations = {
|
|
|
840
840
|
"en": "Profile updated successfully.",
|
|
841
841
|
"sw": "Wasifu umesasishwa kwa mafanikio."
|
|
842
842
|
},
|
|
843
|
+
"Profile.NAME_LABEL": {
|
|
844
|
+
"de": "Name",
|
|
845
|
+
"fr": "Nom",
|
|
846
|
+
"en": "Name",
|
|
847
|
+
"sw": "Jina"
|
|
848
|
+
},
|
|
843
849
|
"Profile.USERNAME_LABEL": {
|
|
844
850
|
"de": "Benutzername",
|
|
845
851
|
"fr": "Nom d’utilisateur",
|
package/dist/pages/SignUpPage.js
CHANGED
|
@@ -92,7 +92,7 @@ export function SignUpPage() {
|
|
|
92
92
|
const handleGoToLogin = () => {
|
|
93
93
|
navigate('/login');
|
|
94
94
|
};
|
|
95
|
-
return (_jsxs(NarrowPage, { title: t('Auth.LOGIN_SIGNUP_BUTTON'), subtitle: pageSubtitle, children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('App.NAME'), " \u2013 ", t('Auth.LOGIN_SIGNUP_BUTTON')] }) }), successKey && (_jsx(Alert, { severity: "success", sx: { mb: 2 }, children: t(successKey, { email }) })), errorKey && (_jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(errorKey, t('Auth.INVITE_FAILED', 'Could not complete signup.')) })), signupModes.length > 1 && (_jsx(Stack, { spacing: 1, sx: { mb: 2 }, children: _jsx(Stack, { spacing: 1, children: signupModes.map((entry) => (_jsx(Button, { variant: mode === entry ? 'contained' : 'outlined', onClick: () => setMode(entry), disabled: submitting, fullWidth: true, children: t(MODE_LABELS[entry] || entry, entry) }, entry))) }) })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: email, onChange: (e) => setEmail(e.target.value), disabled: submitting }), mode === 'self_signup_access_code' && (_jsx(TextField, { label: t('Auth.ACCESS_CODE_LABEL'), type: "text", required: true, fullWidth: true, value: accessCode, onChange: (e) => setAccessCode(e.target.value), disabled: submitting })),
|
|
95
|
+
return (_jsxs(NarrowPage, { title: t('Auth.LOGIN_SIGNUP_BUTTON'), subtitle: pageSubtitle, children: [_jsx(Helmet, { children: _jsxs("title", { children: [t('App.NAME'), " \u2013 ", t('Auth.LOGIN_SIGNUP_BUTTON')] }) }), successKey && (_jsx(Alert, { severity: "success", sx: { mb: 2 }, children: t(successKey, { email }) })), errorKey && (_jsx(Alert, { severity: "error", sx: { mb: 2 }, children: t(errorKey, t('Auth.INVITE_FAILED', 'Could not complete signup.')) })), signupModes.length > 1 && (_jsx(Stack, { spacing: 1, sx: { mb: 2 }, children: _jsx(Stack, { spacing: 1, children: signupModes.map((entry) => (_jsx(Button, { variant: mode === entry ? 'contained' : 'outlined', onClick: () => setMode(entry), disabled: submitting, fullWidth: true, children: t(MODE_LABELS[entry] || entry, entry) }, entry))) }) })), _jsxs(Box, { component: "form", onSubmit: handleSubmit, sx: { display: 'flex', flexDirection: 'column', gap: 2 }, children: [_jsx(TextField, { label: t('Auth.EMAIL_LABEL'), type: "email", required: true, fullWidth: true, value: email, onChange: (e) => setEmail(e.target.value), disabled: submitting }), mode === 'self_signup_access_code' && (_jsx(TextField, { label: t('Auth.ACCESS_CODE_LABEL'), type: "text", required: true, fullWidth: true, value: accessCode, onChange: (e) => setAccessCode(e.target.value), disabled: submitting })), _jsx(Button, { type: "submit", variant: "contained", disabled: submitting || signupModes.length === 0, children: submitting
|
|
96
96
|
? t('Auth.SIGNUP_SUBMITTING')
|
|
97
97
|
: t('Auth.SIGNUP_SUBMIT') })] }), _jsx(Box, { sx: { mt: 3 }, children: _jsxs(Typography, { variant: "body2", children: [t('Auth.SIGNUP_ALREADY_HAVE_ACCOUNT'), ' ', _jsx(Button, { onClick: handleGoToLogin, variant: "text", size: "small", children: t('Auth.SIGNUP_GO_TO_LOGIN') })] }) })] }));
|
|
98
98
|
}
|
package/package.json
CHANGED
|
@@ -88,6 +88,9 @@ export function QrSignupManager({ enabled = false }) {
|
|
|
88
88
|
<Typography variant="body2" sx={{ mb: 2, color: 'text.secondary' }}>
|
|
89
89
|
{t('Auth.SIGNUP_QR_MANAGER_HINT', 'When QR signup is enabled, a signup QR code is shown here immediately.')}
|
|
90
90
|
</Typography>
|
|
91
|
+
<Typography variant="body2" sx={{ mb: 2, color: 'text.secondary' }}>
|
|
92
|
+
{t('Auth.SIGNUP_QR_POLICY_HINT', 'The default QR validity is configured in the authentication policy above.')}
|
|
93
|
+
</Typography>
|
|
91
94
|
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
|
|
92
95
|
{success && <Alert severity="success" sx={{ mb: 2 }}>{success}</Alert>}
|
|
93
96
|
|
|
@@ -121,6 +124,11 @@ export function QrSignupManager({ enabled = false }) {
|
|
|
121
124
|
sx={{ mt: 2 }}
|
|
122
125
|
InputProps={{ readOnly: true }}
|
|
123
126
|
/>
|
|
127
|
+
{result?.expires_at && (
|
|
128
|
+
<Typography variant="body2" sx={{ mt: 1.5, color: 'text.secondary' }}>
|
|
129
|
+
{t('Auth.SIGNUP_QR_VALID_UNTIL', 'Valid until')}: {result.expires_at}
|
|
130
|
+
</Typography>
|
|
131
|
+
)}
|
|
124
132
|
</Box>
|
|
125
133
|
)}
|
|
126
134
|
</Box>
|
|
@@ -20,12 +20,14 @@ const EMPTY_POLICY = {
|
|
|
20
20
|
allow_self_signup_qr: false,
|
|
21
21
|
allowed_email_domains: [],
|
|
22
22
|
required_auth_factor_count: 1,
|
|
23
|
+
signup_qr_expiry_days: 90,
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
26
27
|
const { t } = useTranslation();
|
|
27
28
|
const [policy, setPolicy] = useState(EMPTY_POLICY);
|
|
28
29
|
const [domainsText, setDomainsText] = useState('');
|
|
30
|
+
const [signupQrExpiryDays, setSignupQrExpiryDays] = useState(String(EMPTY_POLICY.signup_qr_expiry_days));
|
|
29
31
|
const [busy, setBusy] = useState(false);
|
|
30
32
|
const [busyField, setBusyField] = useState('');
|
|
31
33
|
const [error, setError] = useState('');
|
|
@@ -39,6 +41,7 @@ export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
|
39
41
|
if (!active) return;
|
|
40
42
|
setPolicy((prev) => ({ ...prev, ...data }));
|
|
41
43
|
setDomainsText((data?.allowed_email_domains || []).join('\n'));
|
|
44
|
+
setSignupQrExpiryDays(String(data?.signup_qr_expiry_days || EMPTY_POLICY.signup_qr_expiry_days));
|
|
42
45
|
if (onPolicyChange) onPolicyChange(data);
|
|
43
46
|
} catch (err) {
|
|
44
47
|
if (active) {
|
|
@@ -80,9 +83,16 @@ export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
|
80
83
|
.split(/\r?\n/)
|
|
81
84
|
.map((value) => value.trim())
|
|
82
85
|
.filter(Boolean);
|
|
83
|
-
const
|
|
86
|
+
const parsedExpiryDays = parseInt(signupQrExpiryDays, 10);
|
|
87
|
+
const next = await updateAuthPolicy({
|
|
88
|
+
allowed_email_domains,
|
|
89
|
+
signup_qr_expiry_days: Number.isFinite(parsedExpiryDays) && parsedExpiryDays > 0
|
|
90
|
+
? parsedExpiryDays
|
|
91
|
+
: EMPTY_POLICY.signup_qr_expiry_days,
|
|
92
|
+
});
|
|
84
93
|
setPolicy((prev) => ({ ...prev, ...next }));
|
|
85
94
|
setDomainsText((next?.allowed_email_domains || allowed_email_domains).join('\n'));
|
|
95
|
+
setSignupQrExpiryDays(String(next?.signup_qr_expiry_days || EMPTY_POLICY.signup_qr_expiry_days));
|
|
86
96
|
setSuccess(t('Auth.AUTH_POLICY_SAVE_SUCCESS', 'Authentication settings saved.'));
|
|
87
97
|
if (onPolicyChange) onPolicyChange(next);
|
|
88
98
|
} catch (err) {
|
|
@@ -176,6 +186,19 @@ export function RegistrationMethodsManager({ onPolicyChange }) {
|
|
|
176
186
|
onChange={(event) => setDomainsText(event.target.value)}
|
|
177
187
|
/>
|
|
178
188
|
|
|
189
|
+
<TextField
|
|
190
|
+
label={t('Auth.SIGNUP_QR_EXPIRY_DAYS_LABEL', 'QR signup validity (days)')}
|
|
191
|
+
helperText={t(
|
|
192
|
+
'Auth.SIGNUP_QR_EXPIRY_DAYS_HINT',
|
|
193
|
+
'Default validity for newly generated QR signup links.',
|
|
194
|
+
)}
|
|
195
|
+
type="number"
|
|
196
|
+
fullWidth
|
|
197
|
+
sx={{ mt: 2 }}
|
|
198
|
+
value={signupQrExpiryDays}
|
|
199
|
+
onChange={(event) => setSignupQrExpiryDays(event.target.value)}
|
|
200
|
+
/>
|
|
201
|
+
|
|
179
202
|
<Button variant="contained" sx={{ mt: 2 }} onClick={save} disabled={busy}>
|
|
180
203
|
{t('Common.SAVE', 'Save')}
|
|
181
204
|
</Button>
|
|
@@ -885,6 +885,12 @@ export const authTranslations = {
|
|
|
885
885
|
"en": "Profile updated successfully.",
|
|
886
886
|
"sw": "Wasifu umesasishwa kwa mafanikio."
|
|
887
887
|
},
|
|
888
|
+
"Profile.NAME_LABEL": {
|
|
889
|
+
"de": "Name",
|
|
890
|
+
"fr": "Nom",
|
|
891
|
+
"en": "Name",
|
|
892
|
+
"sw": "Jina"
|
|
893
|
+
},
|
|
888
894
|
"Profile.USERNAME_LABEL": {
|
|
889
895
|
"de": "Benutzername",
|
|
890
896
|
"fr": "Nom d’utilisateur",
|
package/src/pages/SignUpPage.jsx
CHANGED
|
@@ -186,17 +186,6 @@ export function SignUpPage() {
|
|
|
186
186
|
/>
|
|
187
187
|
)}
|
|
188
188
|
|
|
189
|
-
{mode === 'self_signup_qr' && (
|
|
190
|
-
<Stack spacing={1}>
|
|
191
|
-
<TextField
|
|
192
|
-
label={t('Auth.SIGNUP_QR_TOKEN_LABEL', 'QR token')}
|
|
193
|
-
value={tokenFromUrl}
|
|
194
|
-
fullWidth
|
|
195
|
-
InputProps={{ readOnly: true }}
|
|
196
|
-
/>
|
|
197
|
-
</Stack>
|
|
198
|
-
)}
|
|
199
|
-
|
|
200
189
|
<Button
|
|
201
190
|
type="submit"
|
|
202
191
|
variant="contained"
|