Compare commits
20 Commits
v1.7.0-rc.
...
feat/signa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a730acc76a | ||
|
|
51afe95780 | ||
|
|
80d2d0703a | ||
|
|
a301dd345f | ||
|
|
69bf404b32 | ||
|
|
f4e98ae03a | ||
|
|
0298e79e8c | ||
|
|
8ab7464b84 | ||
|
|
ad4cff937d | ||
|
|
921617b905 | ||
|
|
a1a8a174bf | ||
|
|
3657050b02 | ||
|
|
210081c520 | ||
|
|
fd7c1fea1c | ||
|
|
5f4972d63b | ||
|
|
4c13176c52 | ||
|
|
d599ab0630 | ||
|
|
9e714d607e | ||
|
|
81479b5b55 | ||
|
|
15efc6c36d |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@documenso/marketing",
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@documenso/web",
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"private": true,
|
||||
"license": "AGPL-3.0",
|
||||
"scripts": {
|
||||
|
||||
@@ -65,17 +65,13 @@ export default async function ApiTokensPage() {
|
||||
<h5 className="text-base">{token.name}</h5>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">
|
||||
<Trans>
|
||||
Created on{' '}
|
||||
<LocaleDate date={token.createdAt} format={DateTime.DATETIME_FULL} />
|
||||
</Trans>
|
||||
<Trans>Created on</Trans>{' '}
|
||||
<LocaleDate date={token.createdAt} format={DateTime.DATETIME_FULL} />
|
||||
</p>
|
||||
{token.expires ? (
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
<Trans>
|
||||
Expires on{' '}
|
||||
<LocaleDate date={token.expires} format={DateTime.DATETIME_FULL} />
|
||||
</Trans>
|
||||
<Trans>Expires on</Trans>{' '}
|
||||
<LocaleDate date={token.expires} format={DateTime.DATETIME_FULL} />
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
|
||||
@@ -98,17 +98,13 @@ export default async function ApiTokensPage({ params }: ApiTokensPageProps) {
|
||||
<h5 className="text-base">{token.name}</h5>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">
|
||||
<Trans>
|
||||
Created on{' '}
|
||||
<LocaleDate date={token.createdAt} format={DateTime.DATETIME_FULL} />
|
||||
</Trans>
|
||||
<Trans>Created on</Trans>{' '}
|
||||
<LocaleDate date={token.createdAt} format={DateTime.DATETIME_FULL} />
|
||||
</p>
|
||||
{token.expires ? (
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
<Trans>
|
||||
Expires on{' '}
|
||||
<LocaleDate date={token.expires} format={DateTime.DATETIME_FULL} />
|
||||
</Trans>
|
||||
<Trans>Expires on</Trans>{' '}
|
||||
<LocaleDate date={token.expires} format={DateTime.DATETIME_FULL} />
|
||||
</p>
|
||||
) : (
|
||||
<p className="text-muted-foreground mt-1 text-xs">
|
||||
|
||||
@@ -15,7 +15,6 @@ import { trpc } from '@documenso/trpc/react';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
@@ -28,13 +27,16 @@ import {
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@documenso/ui/primitives/form/form';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { PinInput, PinInputGroup, PinInputSlot } from '@documenso/ui/primitives/pin-input';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
export const ZDisable2FAForm = z.object({
|
||||
token: z.string(),
|
||||
totpCode: z.string().trim().optional(),
|
||||
backupCode: z.string().trim().optional(),
|
||||
});
|
||||
|
||||
export type TDisable2FAForm = z.infer<typeof ZDisable2FAForm>;
|
||||
@@ -46,21 +48,43 @@ export const DisableAuthenticatorAppDialog = () => {
|
||||
const { toast } = useToast();
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [twoFactorDisableMethod, setTwoFactorDisableMethod] = useState<'totp' | 'backup'>('totp');
|
||||
|
||||
const { mutateAsync: disable2FA } = trpc.twoFactorAuthentication.disable.useMutation();
|
||||
|
||||
const disable2FAForm = useForm<TDisable2FAForm>({
|
||||
defaultValues: {
|
||||
token: '',
|
||||
totpCode: '',
|
||||
backupCode: '',
|
||||
},
|
||||
resolver: zodResolver(ZDisable2FAForm),
|
||||
});
|
||||
|
||||
const onCloseTwoFactorDisableDialog = () => {
|
||||
disable2FAForm.reset();
|
||||
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
const onToggleTwoFactorDisableMethodClick = () => {
|
||||
const method = twoFactorDisableMethod === 'totp' ? 'backup' : 'totp';
|
||||
|
||||
if (method === 'totp') {
|
||||
disable2FAForm.setValue('backupCode', '');
|
||||
}
|
||||
|
||||
if (method === 'backup') {
|
||||
disable2FAForm.setValue('totpCode', '');
|
||||
}
|
||||
|
||||
setTwoFactorDisableMethod(method);
|
||||
};
|
||||
|
||||
const { isSubmitting: isDisable2FASubmitting } = disable2FAForm.formState;
|
||||
|
||||
const onDisable2FAFormSubmit = async ({ token }: TDisable2FAForm) => {
|
||||
const onDisable2FAFormSubmit = async ({ totpCode, backupCode }: TDisable2FAForm) => {
|
||||
try {
|
||||
await disable2FA({ token });
|
||||
await disable2FA({ totpCode, backupCode });
|
||||
|
||||
toast({
|
||||
title: _(msg`Two-factor authentication disabled`),
|
||||
@@ -70,7 +94,7 @@ export const DisableAuthenticatorAppDialog = () => {
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
setIsOpen(false);
|
||||
onCloseTwoFactorDisableDialog();
|
||||
});
|
||||
|
||||
router.refresh();
|
||||
@@ -86,7 +110,7 @@ export const DisableAuthenticatorAppDialog = () => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||
<Dialog open={isOpen} onOpenChange={onCloseTwoFactorDisableDialog}>
|
||||
<DialogTrigger asChild={true}>
|
||||
<Button className="flex-shrink-0" variant="destructive">
|
||||
<Trans>Disable 2FA</Trans>
|
||||
@@ -110,33 +134,59 @@ export const DisableAuthenticatorAppDialog = () => {
|
||||
<Form {...disable2FAForm}>
|
||||
<form onSubmit={disable2FAForm.handleSubmit(onDisable2FAFormSubmit)}>
|
||||
<fieldset className="flex flex-col gap-y-4" disabled={isDisable2FASubmitting}>
|
||||
<FormField
|
||||
name="token"
|
||||
control={disable2FAForm.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<PinInput {...field} value={field.value ?? ''} maxLength={6}>
|
||||
{Array(6)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<PinInputGroup key={i}>
|
||||
<PinInputSlot index={i} />
|
||||
</PinInputGroup>
|
||||
))}
|
||||
</PinInput>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
{twoFactorDisableMethod === 'totp' && (
|
||||
<FormField
|
||||
name="totpCode"
|
||||
control={disable2FAForm.control}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<PinInput {...field} value={field.value ?? ''} maxLength={6}>
|
||||
{Array(6)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<PinInputGroup key={i}>
|
||||
<PinInputSlot index={i} />
|
||||
</PinInputGroup>
|
||||
))}
|
||||
</PinInput>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{twoFactorDisableMethod === 'backup' && (
|
||||
<FormField
|
||||
control={disable2FAForm.control}
|
||||
name="backupCode"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans>Backup Code</Trans>
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="text" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<DialogFooter>
|
||||
<DialogClose asChild>
|
||||
<Button type="button" variant="secondary">
|
||||
<Trans>Cancel</Trans>
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
onClick={onToggleTwoFactorDisableMethodClick}
|
||||
>
|
||||
{twoFactorDisableMethod === 'totp' ? (
|
||||
<Trans>Use Backup Code</Trans>
|
||||
) : (
|
||||
<Trans>Use Authenticator</Trans>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button type="submit" variant="destructive" loading={isDisable2FASubmitting}>
|
||||
<Trans>Disable 2FA</Trans>
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@documenso/root",
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@documenso/root",
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
"packages/*"
|
||||
@@ -81,7 +81,7 @@
|
||||
},
|
||||
"apps/marketing": {
|
||||
"name": "@documenso/marketing",
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@documenso/assets": "*",
|
||||
@@ -424,7 +424,7 @@
|
||||
},
|
||||
"apps/web": {
|
||||
"name": "@documenso/web",
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"license": "AGPL-3.0",
|
||||
"dependencies": {
|
||||
"@documenso/api": "*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "1.7.0-rc.0",
|
||||
"version": "1.7.0-rc.2",
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
"build:web": "turbo run build --filter=@documenso/web",
|
||||
|
||||
@@ -2,25 +2,33 @@ import { prisma } from '@documenso/prisma';
|
||||
import type { User } from '@documenso/prisma/client';
|
||||
import { UserSecurityAuditLogType } from '@documenso/prisma/client';
|
||||
|
||||
import { AppError } from '../../errors/app-error';
|
||||
import { AppError, AppErrorCode } from '../../errors/app-error';
|
||||
import type { RequestMetadata } from '../../universal/extract-request-metadata';
|
||||
import { validateTwoFactorAuthentication } from './validate-2fa';
|
||||
|
||||
type DisableTwoFactorAuthenticationOptions = {
|
||||
user: User;
|
||||
token: string;
|
||||
totpCode?: string;
|
||||
backupCode?: string;
|
||||
requestMetadata?: RequestMetadata;
|
||||
};
|
||||
|
||||
export const disableTwoFactorAuthentication = async ({
|
||||
token,
|
||||
totpCode,
|
||||
backupCode,
|
||||
user,
|
||||
requestMetadata,
|
||||
}: DisableTwoFactorAuthenticationOptions) => {
|
||||
let isValid = await validateTwoFactorAuthentication({ totpCode: token, user });
|
||||
let isValid = false;
|
||||
|
||||
if (!isValid) {
|
||||
isValid = await validateTwoFactorAuthentication({ backupCode: token, user });
|
||||
if (!totpCode && !backupCode) {
|
||||
throw new AppError(AppErrorCode.INVALID_REQUEST);
|
||||
}
|
||||
|
||||
if (totpCode) {
|
||||
isValid = await validateTwoFactorAuthentication({ totpCode, user });
|
||||
} else if (backupCode) {
|
||||
isValid = await validateTwoFactorAuthentication({ backupCode, user });
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
|
||||
@@ -140,6 +140,14 @@ msgstr "Genehmiger"
|
||||
msgid "Approving"
|
||||
msgstr "Genehmigung"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:271
|
||||
msgid "Black"
|
||||
msgstr ""
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:298
|
||||
msgid "Blue"
|
||||
msgstr ""
|
||||
|
||||
#: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx:297
|
||||
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:58
|
||||
msgid "Cancel"
|
||||
@@ -179,7 +187,7 @@ msgstr "Checkbox-Werte"
|
||||
msgid "Clear filters"
|
||||
msgstr "Filter löschen"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:256
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:321
|
||||
msgid "Clear Signature"
|
||||
msgstr "Unterschrift löschen"
|
||||
|
||||
@@ -312,6 +320,10 @@ msgstr "Globale Empfängerauthentifizierung"
|
||||
msgid "Go Back"
|
||||
msgstr "Zurück"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:307
|
||||
msgid "Green"
|
||||
msgstr ""
|
||||
|
||||
#: packages/lib/constants/recipient-roles.ts:72
|
||||
msgid "I am a signer of this document"
|
||||
msgstr "Ich bin ein Unterzeichner dieses Dokuments"
|
||||
@@ -477,6 +489,10 @@ msgstr "Erhält Kopie"
|
||||
msgid "Recipient action authentication"
|
||||
msgstr "Empfängeraktion Authentifizierung"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:289
|
||||
msgid "Red"
|
||||
msgstr ""
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-settings.tsx:298
|
||||
#: packages/ui/primitives/template-flow/add-template-settings.tsx:332
|
||||
msgid "Redirect URL"
|
||||
@@ -733,6 +749,10 @@ msgstr "Viewer"
|
||||
msgid "Viewing"
|
||||
msgstr "Viewing"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:280
|
||||
msgid "White"
|
||||
msgstr ""
|
||||
|
||||
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:44
|
||||
msgid "You are about to send this document to the recipients. Are you sure you want to continue?"
|
||||
msgstr "Sie sind dabei, dieses Dokument an die Empfänger zu senden. Sind Sie sicher, dass Sie fortfahren möchten?"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -607,6 +607,7 @@ msgstr ""
|
||||
msgid "Background Color"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:167
|
||||
#: apps/web/src/components/forms/signin.tsx:451
|
||||
msgid "Backup Code"
|
||||
msgstr ""
|
||||
@@ -632,6 +633,14 @@ msgstr ""
|
||||
msgid "Billing"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:207
|
||||
#~ msgid "Black"
|
||||
#~ msgstr ""
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:223
|
||||
#~ msgid "Blue"
|
||||
#~ msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/security/activity/user-security-activity-data-table.tsx:101
|
||||
msgid "Browser"
|
||||
msgstr ""
|
||||
@@ -684,7 +693,6 @@ msgstr ""
|
||||
#: apps/web/src/components/(teams)/dialogs/transfer-team-dialog.tsx:278
|
||||
#: apps/web/src/components/(teams)/dialogs/update-team-email-dialog.tsx:162
|
||||
#: apps/web/src/components/(teams)/dialogs/update-team-member-dialog.tsx:187
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:137
|
||||
#: apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx:257
|
||||
#: apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx:163
|
||||
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:452
|
||||
@@ -973,13 +981,13 @@ msgid "Created by"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/admin/documents/[id]/page.tsx:49
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:68
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:101
|
||||
#: apps/web/src/components/(teams)/tables/pending-user-teams-data-table.tsx:80
|
||||
msgid "Created on"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:68
|
||||
#: apps/web/src/app/(dashboard)/settings/webhooks/page.tsx:89
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:101
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/webhooks/page.tsx:94
|
||||
msgid "Created on <0/>"
|
||||
msgstr ""
|
||||
@@ -1022,11 +1030,11 @@ msgstr ""
|
||||
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:200
|
||||
#: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:177
|
||||
#: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:211
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:90
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:86
|
||||
#: apps/web/src/app/(dashboard)/settings/webhooks/page.tsx:104
|
||||
#: apps/web/src/app/(dashboard)/templates/data-table-action-dropdown.tsx:91
|
||||
#: apps/web/src/app/(dashboard)/templates/delete-template-dialog.tsx:90
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:123
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:119
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/webhooks/page.tsx:109
|
||||
#: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:121
|
||||
#: apps/web/src/components/(dashboard)/settings/webhooks/delete-webhook-dialog.tsx:109
|
||||
@@ -1143,9 +1151,9 @@ msgstr ""
|
||||
msgid "Disable"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:92
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:99
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:142
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:116
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:123
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:192
|
||||
msgid "Disable 2FA"
|
||||
msgstr ""
|
||||
|
||||
@@ -1525,10 +1533,15 @@ msgstr ""
|
||||
msgid "Expired"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:73
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:106
|
||||
msgid "Expires on"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:75
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:108
|
||||
msgid "Expires on <0/>"
|
||||
msgstr ""
|
||||
#~ msgid "Expires on <0/>"
|
||||
#~ msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx:42
|
||||
msgid "Failed to reseal document"
|
||||
@@ -1599,6 +1612,10 @@ msgstr ""
|
||||
msgid "Go to your <0>public profile settings</0> to add documents."
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:231
|
||||
#~ msgid "Green"
|
||||
#~ msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/profile/page.tsx:29
|
||||
msgid "Here you can edit your personal details."
|
||||
msgstr ""
|
||||
@@ -2274,7 +2291,7 @@ msgstr ""
|
||||
msgid "Please note that you will lose access to all documents associated with this team & all the members will be removed and notified"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:103
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:127
|
||||
msgid "Please provide a token from the authenticator, or a backup code. If you do not have a backup code available, please contact support."
|
||||
msgstr ""
|
||||
|
||||
@@ -2407,6 +2424,10 @@ msgstr ""
|
||||
msgid "Recovery codes"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:215
|
||||
#~ msgid "Red"
|
||||
#~ msgstr ""
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:78
|
||||
#: apps/web/src/components/forms/signup.tsx:93
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:127
|
||||
@@ -3387,8 +3408,8 @@ msgstr ""
|
||||
msgid "Token deleted"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:82
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:115
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:78
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:111
|
||||
msgid "Token doesn't have an expiration date"
|
||||
msgstr ""
|
||||
|
||||
@@ -3448,7 +3469,7 @@ msgstr ""
|
||||
msgid "Two-Factor Authentication"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:66
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:90
|
||||
msgid "Two-factor authentication disabled"
|
||||
msgstr ""
|
||||
|
||||
@@ -3456,7 +3477,7 @@ msgstr ""
|
||||
msgid "Two-factor authentication enabled"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:68
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:92
|
||||
msgid "Two-factor authentication has been disabled for your account. You will no longer be required to enter a code from your authenticator app when signing in."
|
||||
msgstr ""
|
||||
|
||||
@@ -3501,7 +3522,7 @@ msgstr ""
|
||||
msgid "Unable to delete team"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:79
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:103
|
||||
msgid "Unable to disable two-factor authentication"
|
||||
msgstr ""
|
||||
|
||||
@@ -3649,10 +3670,12 @@ msgstr ""
|
||||
msgid "Uploaded file not an allowed file type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:187
|
||||
#: apps/web/src/components/forms/signin.tsx:471
|
||||
msgid "Use Authenticator"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:185
|
||||
#: apps/web/src/components/forms/signin.tsx:469
|
||||
msgid "Use Backup Code"
|
||||
msgstr ""
|
||||
@@ -3939,7 +3962,7 @@ msgstr ""
|
||||
msgid "We were unable to create a checkout session. Please try again, or contact support"
|
||||
msgstr ""
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:81
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:105
|
||||
msgid "We were unable to disable two-factor authentication for your account. Please ensure that you have entered your password and backup code correctly and try again."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -135,6 +135,14 @@ msgstr "Approver"
|
||||
msgid "Approving"
|
||||
msgstr "Approving"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:271
|
||||
msgid "Black"
|
||||
msgstr "Black"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:298
|
||||
msgid "Blue"
|
||||
msgstr "Blue"
|
||||
|
||||
#: packages/ui/primitives/document-flow/field-item-advanced-settings.tsx:297
|
||||
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:58
|
||||
msgid "Cancel"
|
||||
@@ -174,7 +182,7 @@ msgstr "Checkbox values"
|
||||
msgid "Clear filters"
|
||||
msgstr "Clear filters"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:256
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:321
|
||||
msgid "Clear Signature"
|
||||
msgstr "Clear Signature"
|
||||
|
||||
@@ -307,6 +315,10 @@ msgstr "Global recipient action authentication"
|
||||
msgid "Go Back"
|
||||
msgstr "Go Back"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:307
|
||||
msgid "Green"
|
||||
msgstr "Green"
|
||||
|
||||
#: packages/lib/constants/recipient-roles.ts:72
|
||||
msgid "I am a signer of this document"
|
||||
msgstr "I am a signer of this document"
|
||||
@@ -472,6 +484,10 @@ msgstr "Receives copy"
|
||||
msgid "Recipient action authentication"
|
||||
msgstr "Recipient action authentication"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:289
|
||||
msgid "Red"
|
||||
msgstr "Red"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-settings.tsx:298
|
||||
#: packages/ui/primitives/template-flow/add-template-settings.tsx:332
|
||||
msgid "Redirect URL"
|
||||
@@ -728,6 +744,10 @@ msgstr "Viewer"
|
||||
msgid "Viewing"
|
||||
msgstr "Viewing"
|
||||
|
||||
#: packages/ui/primitives/signature-pad/signature-pad.tsx:280
|
||||
msgid "White"
|
||||
msgstr "White"
|
||||
|
||||
#: packages/ui/primitives/document-flow/send-document-action-dialog.tsx:44
|
||||
msgid "You are about to send this document to the recipients. Are you sure you want to continue?"
|
||||
msgstr "You are about to send this document to the recipients. Are you sure you want to continue?"
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -602,6 +602,7 @@ msgstr "Back to Documents"
|
||||
msgid "Background Color"
|
||||
msgstr "Background Color"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:167
|
||||
#: apps/web/src/components/forms/signin.tsx:451
|
||||
msgid "Backup Code"
|
||||
msgstr "Backup Code"
|
||||
@@ -627,6 +628,14 @@ msgstr "Basic details"
|
||||
msgid "Billing"
|
||||
msgstr "Billing"
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:207
|
||||
#~ msgid "Black"
|
||||
#~ msgstr "Black"
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:223
|
||||
#~ msgid "Blue"
|
||||
#~ msgstr "Blue"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/security/activity/user-security-activity-data-table.tsx:101
|
||||
msgid "Browser"
|
||||
msgstr "Browser"
|
||||
@@ -679,7 +688,6 @@ msgstr "By enabling 2FA, you will be required to enter a code from your authenti
|
||||
#: apps/web/src/components/(teams)/dialogs/transfer-team-dialog.tsx:278
|
||||
#: apps/web/src/components/(teams)/dialogs/update-team-email-dialog.tsx:162
|
||||
#: apps/web/src/components/(teams)/dialogs/update-team-member-dialog.tsx:187
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:137
|
||||
#: apps/web/src/components/forms/2fa/enable-authenticator-app-dialog.tsx:257
|
||||
#: apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx:163
|
||||
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:452
|
||||
@@ -968,13 +976,13 @@ msgid "Created by"
|
||||
msgstr "Created by"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/admin/documents/[id]/page.tsx:49
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:68
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:101
|
||||
#: apps/web/src/components/(teams)/tables/pending-user-teams-data-table.tsx:80
|
||||
msgid "Created on"
|
||||
msgstr "Created on"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:68
|
||||
#: apps/web/src/app/(dashboard)/settings/webhooks/page.tsx:89
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:101
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/webhooks/page.tsx:94
|
||||
msgid "Created on <0/>"
|
||||
msgstr "Created on <0/>"
|
||||
@@ -1017,11 +1025,11 @@ msgstr "Declined team invitation"
|
||||
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:200
|
||||
#: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:177
|
||||
#: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:211
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:90
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:86
|
||||
#: apps/web/src/app/(dashboard)/settings/webhooks/page.tsx:104
|
||||
#: apps/web/src/app/(dashboard)/templates/data-table-action-dropdown.tsx:91
|
||||
#: apps/web/src/app/(dashboard)/templates/delete-template-dialog.tsx:90
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:123
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:119
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/webhooks/page.tsx:109
|
||||
#: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:121
|
||||
#: apps/web/src/components/(dashboard)/settings/webhooks/delete-webhook-dialog.tsx:109
|
||||
@@ -1138,9 +1146,9 @@ msgstr "Direct template link usage exceeded ({0}/{1})"
|
||||
msgid "Disable"
|
||||
msgstr "Disable"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:92
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:99
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:142
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:116
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:123
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:192
|
||||
msgid "Disable 2FA"
|
||||
msgstr "Disable 2FA"
|
||||
|
||||
@@ -1520,10 +1528,15 @@ msgstr "Exceeded timeout"
|
||||
msgid "Expired"
|
||||
msgstr "Expired"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:73
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:106
|
||||
msgid "Expires on"
|
||||
msgstr "Expires on"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:75
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:108
|
||||
msgid "Expires on <0/>"
|
||||
msgstr "Expires on <0/>"
|
||||
#~ msgid "Expires on <0/>"
|
||||
#~ msgstr "Expires on <0/>"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx:42
|
||||
msgid "Failed to reseal document"
|
||||
@@ -1594,6 +1607,10 @@ msgstr "Go to owner"
|
||||
msgid "Go to your <0>public profile settings</0> to add documents."
|
||||
msgstr "Go to your <0>public profile settings</0> to add documents."
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:231
|
||||
#~ msgid "Green"
|
||||
#~ msgstr "Green"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/profile/page.tsx:29
|
||||
msgid "Here you can edit your personal details."
|
||||
msgstr "Here you can edit your personal details."
|
||||
@@ -2269,7 +2286,7 @@ msgstr "Please note that this action is irreversible. Once confirmed, your webho
|
||||
msgid "Please note that you will lose access to all documents associated with this team & all the members will be removed and notified"
|
||||
msgstr "Please note that you will lose access to all documents associated with this team & all the members will be removed and notified"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:103
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:127
|
||||
msgid "Please provide a token from the authenticator, or a backup code. If you do not have a backup code available, please contact support."
|
||||
msgstr "Please provide a token from the authenticator, or a backup code. If you do not have a backup code available, please contact support."
|
||||
|
||||
@@ -2402,6 +2419,10 @@ msgstr "Recovery code copied"
|
||||
msgid "Recovery codes"
|
||||
msgstr "Recovery codes"
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:215
|
||||
#~ msgid "Red"
|
||||
#~ msgstr "Red"
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:78
|
||||
#: apps/web/src/components/forms/signup.tsx:93
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:127
|
||||
@@ -3382,8 +3403,8 @@ msgstr "Token created"
|
||||
msgid "Token deleted"
|
||||
msgstr "Token deleted"
|
||||
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:82
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:115
|
||||
#: apps/web/src/app/(dashboard)/settings/tokens/page.tsx:78
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/tokens/page.tsx:111
|
||||
msgid "Token doesn't have an expiration date"
|
||||
msgstr "Token doesn't have an expiration date"
|
||||
|
||||
@@ -3443,7 +3464,7 @@ msgstr "Two factor authentication recovery codes are used to access your account
|
||||
msgid "Two-Factor Authentication"
|
||||
msgstr "Two-Factor Authentication"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:66
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:90
|
||||
msgid "Two-factor authentication disabled"
|
||||
msgstr "Two-factor authentication disabled"
|
||||
|
||||
@@ -3451,7 +3472,7 @@ msgstr "Two-factor authentication disabled"
|
||||
msgid "Two-factor authentication enabled"
|
||||
msgstr "Two-factor authentication enabled"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:68
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:92
|
||||
msgid "Two-factor authentication has been disabled for your account. You will no longer be required to enter a code from your authenticator app when signing in."
|
||||
msgstr "Two-factor authentication has been disabled for your account. You will no longer be required to enter a code from your authenticator app when signing in."
|
||||
|
||||
@@ -3496,7 +3517,7 @@ msgstr "Unable to delete invitation. Please try again."
|
||||
msgid "Unable to delete team"
|
||||
msgstr "Unable to delete team"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:79
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:103
|
||||
msgid "Unable to disable two-factor authentication"
|
||||
msgstr "Unable to disable two-factor authentication"
|
||||
|
||||
@@ -3644,10 +3665,12 @@ msgstr "Uploaded file is too small"
|
||||
msgid "Uploaded file not an allowed file type"
|
||||
msgstr "Uploaded file not an allowed file type"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:187
|
||||
#: apps/web/src/components/forms/signin.tsx:471
|
||||
msgid "Use Authenticator"
|
||||
msgstr "Use Authenticator"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:185
|
||||
#: apps/web/src/components/forms/signin.tsx:469
|
||||
msgid "Use Backup Code"
|
||||
msgstr "Use Backup Code"
|
||||
@@ -3934,7 +3957,7 @@ msgstr "We were unable to copy your recovery code to your clipboard. Please try
|
||||
msgid "We were unable to create a checkout session. Please try again, or contact support"
|
||||
msgstr "We were unable to create a checkout session. Please try again, or contact support"
|
||||
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:81
|
||||
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:105
|
||||
msgid "We were unable to disable two-factor authentication for your account. Please ensure that you have entered your password and backup code correctly and try again."
|
||||
msgstr "We were unable to disable two-factor authentication for your account. Please ensure that you have entered your password and backup code correctly and try again."
|
||||
|
||||
|
||||
@@ -65,7 +65,8 @@ export const twoFactorAuthenticationRouter = router({
|
||||
|
||||
return await disableTwoFactorAuthentication({
|
||||
user,
|
||||
token: input.token,
|
||||
totpCode: input.totpCode,
|
||||
backupCode: input.backupCode,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -9,7 +9,8 @@ export type TEnableTwoFactorAuthenticationMutationSchema = z.infer<
|
||||
>;
|
||||
|
||||
export const ZDisableTwoFactorAuthenticationMutationSchema = z.object({
|
||||
token: z.string().trim().min(1),
|
||||
totpCode: z.string().trim().optional(),
|
||||
backupCode: z.string().trim().optional(),
|
||||
});
|
||||
|
||||
export type TDisableTwoFactorAuthenticationMutationSchema = z.infer<
|
||||
|
||||
@@ -9,6 +9,13 @@ import type { StrokeOptions } from 'perfect-freehand';
|
||||
import { getStroke } from 'perfect-freehand';
|
||||
|
||||
import { unsafe_useEffectOnce } from '@documenso/lib/client-only/hooks/use-effect-once';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@documenso/ui/primitives/select';
|
||||
|
||||
import { cn } from '../../lib/utils';
|
||||
import { getSvgPathFromStroke } from './helper';
|
||||
@@ -36,6 +43,7 @@ export const SignaturePad = ({
|
||||
const [isPressed, setIsPressed] = useState(false);
|
||||
const [lines, setLines] = useState<Point[][]>([]);
|
||||
const [currentLine, setCurrentLine] = useState<Point[]>([]);
|
||||
const [selectedColor, setSelectedColor] = useState('black');
|
||||
|
||||
const perfectFreehandOptions = useMemo(() => {
|
||||
const size = $el.current ? Math.min($el.current.height, $el.current.width) * 0.03 : 10;
|
||||
@@ -85,6 +93,7 @@ export const SignaturePad = ({
|
||||
ctx.restore();
|
||||
ctx.imageSmoothingEnabled = true;
|
||||
ctx.imageSmoothingQuality = 'high';
|
||||
ctx.fillStyle = selectedColor;
|
||||
|
||||
lines.forEach((line) => {
|
||||
const pathData = new Path2D(
|
||||
@@ -129,6 +138,7 @@ export const SignaturePad = ({
|
||||
|
||||
ctx.imageSmoothingEnabled = true;
|
||||
ctx.imageSmoothingQuality = 'high';
|
||||
ctx.fillStyle = selectedColor;
|
||||
|
||||
newLines.forEach((line) => {
|
||||
const pathData = new Path2D(
|
||||
@@ -237,7 +247,7 @@ export const SignaturePad = ({
|
||||
>
|
||||
<canvas
|
||||
ref={$el}
|
||||
className={cn('relative block dark:invert', className)}
|
||||
className={cn('relative block', className)}
|
||||
style={{ touchAction: 'none' }}
|
||||
onPointerMove={(event) => onMouseMove(event)}
|
||||
onPointerDown={(event) => onMouseDown(event)}
|
||||
@@ -247,6 +257,61 @@ export const SignaturePad = ({
|
||||
{...props}
|
||||
/>
|
||||
|
||||
<div className="absolute right-2 top-2">
|
||||
<Select onValueChange={(value) => setSelectedColor(value)}>
|
||||
<SelectTrigger className="bg-background w-[90px]">
|
||||
<SelectValue placeholder="Color" />
|
||||
</SelectTrigger>
|
||||
|
||||
<SelectContent align="end">
|
||||
<SelectItem value="black">
|
||||
<div className="flex items-center">
|
||||
<div className="flex w-[150px] items-center">
|
||||
<div className="mr-2 h-5 w-5 rounded-full border-2 bg-black shadow-sm"></div>
|
||||
<Trans>Black</Trans>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
<SelectItem value="white">
|
||||
<div className="flex items-center">
|
||||
<div className="flex w-[150px] items-center">
|
||||
<div className="mr-2 h-5 w-5 rounded-full border-2 shadow-sm"></div>
|
||||
<Trans>White</Trans>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
<SelectItem value="red">
|
||||
<div className="flex items-center">
|
||||
<div className="flex w-[150px] items-center">
|
||||
<div className="mr-2 h-5 w-5 rounded-full border-2 bg-red-500 shadow-sm"></div>
|
||||
<Trans>Red</Trans>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
<SelectItem value="blue">
|
||||
<div className="flex items-center">
|
||||
<div className="flex w-[150px] items-center">
|
||||
<div className="mr-2 h-5 w-5 rounded-full border-2 bg-blue-500 shadow-sm"></div>
|
||||
<Trans>Blue</Trans>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
|
||||
<SelectItem value="green">
|
||||
<div className="flex items-center">
|
||||
<div className="flex w-[150px] items-center">
|
||||
<div className="mr-2 h-5 w-5 rounded-full border-2 bg-green-500 shadow-sm"></div>
|
||||
<Trans>Green</Trans>
|
||||
</div>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-4 right-4 flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
|
||||
Reference in New Issue
Block a user