Compare commits

..

11 Commits

Author SHA1 Message Date
Mythie
337bdb3553 v1.8.0-rc.1 2024-11-26 21:26:12 +11:00
Catalin Pit
ab654a63d8 chore: enable typed signature by default (#1436)
Enable typed signature by default and also add the option to set a typed
signature in the profile page.
2024-11-26 21:03:44 +11:00
Mythie
dcb7c2436f fix: update prettier and tailwind 2024-11-26 11:47:28 +11:00
Catalin Pit
fa33f83696 feat: download doc without signing certificate (#1477)
## Description

I added the option of downloading a document without the signing
certificate for teams. They can disable/enable the option in the
preferences tab.

The signing certificate can still be downloaded separately from the
`logs` page.
2024-11-25 15:47:26 +11:00
Lucas Smith
b15e1d6c47 feat: support whitelabelling in the embedding (#1491)
## Description

Adds support for customising the theme and CSS for the embedding
components which is restricted to platform customers and above.

Additionally adds proper support for the platform plan which will let us
update our stripe products.

<img width="1040" alt="image"
src="https://github.com/user-attachments/assets/f694cd1e-ac93-4dc0-9f78-92fa813f6404">
<img width="1015" alt="image"
src="https://github.com/user-attachments/assets/4209972a-b2bd-40c9-9049-0367382a4de5">
<img width="1065" alt="image"
src="https://github.com/user-attachments/assets/fdbaaaa5-a028-4b1d-a58a-ea6224e21abe">


## Related Issue

N/A

## Changes Made

- Added support for using CSS Vars and CSS within the embedding route
- Added a guard for platform and enterprise plans to activate the custom
css
- Added support for the platform plan

## Testing Performed
Yes
2024-11-25 15:47:00 +11:00
Ephraim Duncan
cd5adce7df fix: hardcode delete confirmation text to avoid translation mismatch (#1487) 2024-11-22 14:22:31 +07:00
Mythie
11e483f1c4 chore: update changelog 2024-11-21 13:10:31 +11:00
Mythie
2e2bc8382f v1.8.1-rc.0 2024-11-20 23:02:32 +11:00
Lucas Smith
1f3a9b578b chore: add translations (#1485)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Release Notes

- **New Features**
- Enhanced German, Spanish, French, and Polish translations for various
document management and marketing phrases.

- **Improvements**
- Updated translations for clarity and accuracy across multiple
languages, including user notifications and document actions.
- Added new translation entries to improve user experience and
localization in the Documenso application.

- **Chores**
- Updated revision dates in translation files to reflect recent changes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2024-11-20 23:00:59 +11:00
Lucas Smith
83e7a3c222 fix: improve field sizing (#1486)
## Description

Allows for smaller field sizing in addition to improving our styling
when displaying labels on smaller fields.

This is the minimum currently supported field size until we perform a
more extensive refactor of our current drag and drop system.

## Related Issue

Reported via support channels

## Changes Made

- Updated our minimum size constraints
- Attempted to add a general autosizing component for text and failed
- Updated styling in a bunch of places to use the css `clamp()` method
for dynamic sizing.
2024-11-20 22:49:30 +11:00
Lucas Smith
9ef8b1f0c3 feat: automatically sign fields in large documents (#1484)
## Description

Adds a dialog that will display when a certain field threshold is
reached asking the user if they would like to sign non-critical fields
such as name, date, initials, and email with information that is already
available.

This has not been added to direct templates since we would often not
have all the pre-requisite knowledge since users are mostly anonymous.
Additionally, this has not been added to the embedding view since it may
detract from the experience for some.

Will not prompt the user if there is action authentication on the
document.

See the below demo:


https://github.com/user-attachments/assets/71739b5c-1323-4da9-89fd-a1145c9714d5

## Related Issue

#1281 (Older PR relating to the feature)

## Changes Made

- Added a new auto-sign dialog that will automatically trigger once
certain criteria is met.

## Testing Performed

- Tested that the dialog displays when the threshold is met
- Tested that the dialog is hidden when the threshold is not met
- Tested that the messaging during errors is correct
- Tested that the dialog does not display when 2FA or Passkeys are
required
2024-11-20 10:59:09 +11:00
101 changed files with 3295 additions and 2107 deletions

View File

@@ -27,9 +27,6 @@
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^18", "@types/react": "^18",
"@types/react-dom": "^18", "@types/react-dom": "^18",
"autoprefixer": "^10.0.1",
"postcss": "^8",
"tailwindcss": "^3.3.0",
"typescript": "^5" "typescript": "^5"
} }
} }

View File

@@ -8,6 +8,59 @@ Check out what's new in the latest version and read our thoughts on it. For more
--- ---
# Documenso v1.8.0: Team Preferences, Signature Rejection, and Document Distribution
We're excited to announce the release of Documenso v1.8.0! This update brings powerful new features to enhance your document signing process. Here's what's new:
## 🌟 Key New Features
### 1. Team Preferences
Introducing **Team Preferences**, allowing administrators to configure settings and preferences that apply to documents across the entire team. This feature ensures consistency and simplifies management by letting you set default options, permissions, and preferences that automatically apply to all team members.
![Team Preferences](/changelog/v1_8_0/team-global-settings.jpeg)
### 2. Signature Rejection
Recipients now have the option to **reject signatures**. This feature enhances communication by allowing recipients to decline signing, providing feedback or requesting changes before the document is finalized.
<video
src="/changelog/v1_8_0/reject-document.mp4"
className="aspect-video w-full"
autoPlay
loop
controls
/>
### 3. Document Distribution Settings
With the new **Document Distribution Settings**, you have greater control over how your documents are shared. Distribute communications via our automated emails and templates or take full control using our API and your own notifications infrastructure.
## 🔧 Other Improvements
- **Support for Gmail SMTP Service**: Adds support for using Gmail as your SMTP service provider.
- **Certificate and Email Translations**: Added support for multiple languages in document certificates and emails, enhancing the experience for international users.
- **Field Movement Fixes**: Resolved issues related to moving fields within documents, improving the document preparation experience.
- **Docker Environment Update**: Improved Docker setup for smoother deployments and better environment consistency.
- **Billing Access Improvements**: Users now have uninterrupted access to billing information, simplifying account management.
- **Support Time Windows for 2FA Tokens**: Enhanced two-factor authentication by supporting time windows in 2FA tokens, improving flexibility.
## 💡 Recent Features
Don't forget to take advantage of these powerful features from our recent releases:
- **Signing Order**: Define the sequence in which recipients sign your documents for a structured signing process.
- **Document Visibility Controls**: Manage who can view your documents and at what stages, offering greater privacy and control.
- **Embedded Signing Experience**: Integrate the signing process directly into your own applications for a seamless user experience.
**👏 Thank You**
As always, we're grateful for the community's contributions and feedback. Your support helps us improve Documenso and deliver a top-notch open-source document signing solution.
We hope you enjoy the new features in Documenso v1.8.0. Happy signing!
---
# Documenso v1.7.1: Signing order and document visibility # Documenso v1.7.1: Signing order and document visibility
We're excited to introduce Documenso v1.7.1, bringing you improved control over your document signing process. Here are the key updates: We're excited to introduce Documenso v1.7.1, bringing you improved control over your document signing process. Here are the key updates:

View File

@@ -1,6 +1,6 @@
{ {
"name": "@documenso/marketing", "name": "@documenso/marketing",
"version": "1.8.0-rc.4", "version": "1.8.1-rc.1",
"private": true, "private": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

View File

@@ -1,6 +1,6 @@
{ {
"name": "@documenso/web", "name": "@documenso/web",
"version": "1.8.0-rc.4", "version": "1.8.1-rc.1",
"private": true, "private": true,
"license": "AGPL-3.0", "license": "AGPL-3.0",
"scripts": { "scripts": {
@@ -28,6 +28,7 @@
"@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/browser": "^9.0.1",
"@simplewebauthn/server": "^9.0.3", "@simplewebauthn/server": "^9.0.3",
"@tanstack/react-query": "^4.29.5", "@tanstack/react-query": "^4.29.5",
"colord": "^2.9.3",
"cookie-es": "^1.0.0", "cookie-es": "^1.0.0",
"formidable": "^2.1.1", "formidable": "^2.1.1",
"framer-motion": "^10.12.8", "framer-motion": "^10.12.8",
@@ -53,7 +54,7 @@
"react-icons": "^4.11.0", "react-icons": "^4.11.0",
"react-rnd": "^10.4.1", "react-rnd": "^10.4.1",
"recharts": "^2.7.2", "recharts": "^2.7.2",
"remeda": "^2.12.1", "remeda": "^2.17.3",
"sharp": "0.32.6", "sharp": "0.32.6",
"ts-pattern": "^5.0.5", "ts-pattern": "^5.0.5",
"ua-parser-js": "^1.0.37", "ua-parser-js": "^1.0.37",

View File

@@ -47,6 +47,8 @@ export const DeleteDocumentDialog = ({
const { refreshLimits } = useLimits(); const { refreshLimits } = useLimits();
const { _ } = useLingui(); const { _ } = useLingui();
const deleteMessage = msg`delete`;
const [inputValue, setInputValue] = useState(''); const [inputValue, setInputValue] = useState('');
const [isDeleteEnabled, setIsDeleteEnabled] = useState(status === DocumentStatus.DRAFT); const [isDeleteEnabled, setIsDeleteEnabled] = useState(status === DocumentStatus.DRAFT);
@@ -87,7 +89,7 @@ export const DeleteDocumentDialog = ({
const onInputChange = (event: React.ChangeEvent<HTMLInputElement>) => { const onInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value); setInputValue(event.target.value);
setIsDeleteEnabled(event.target.value === _(msg`delete`)); setIsDeleteEnabled(event.target.value === _(deleteMessage));
}; };
return ( return (
@@ -181,7 +183,7 @@ export const DeleteDocumentDialog = ({
type="text" type="text"
value={inputValue} value={inputValue}
onChange={onInputChange} onChange={onInputChange}
placeholder={_(msg`Type 'delete' to confirm`)} placeholder={_(msg`Please type ${`'${_(deleteMessage)}'`} to confirm`)}
/> />
)} )}

View File

@@ -141,6 +141,23 @@ export const EditTemplateForm = ({
}, },
}); });
const { mutateAsync: updateTypedSignature } =
trpc.template.updateTemplateTypedSignatureSettings.useMutation({
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
onSuccess: (newData) => {
utils.template.getTemplateWithDetailsById.setData(
{
id: initialTemplate.id,
},
(oldData) => ({
...(oldData || initialTemplate),
...newData,
id: Number(newData.id),
}),
);
},
});
const onAddSettingsFormSubmit = async (data: TAddTemplateSettingsFormSchema) => { const onAddSettingsFormSubmit = async (data: TAddTemplateSettingsFormSchema) => {
try { try {
await updateTemplateSettings({ await updateTemplateSettings({
@@ -211,6 +228,12 @@ export const EditTemplateForm = ({
fields: data.fields, fields: data.fields,
}); });
await updateTypedSignature({
templateId: template.id,
teamId: team?.id,
typedSignatureEnabled: data.typedSignatureEnabled,
});
// Clear all field data from localStorage // Clear all field data from localStorage
for (let i = 0; i < localStorage.length; i++) { for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i); const key = localStorage.key(i);
@@ -225,14 +248,13 @@ export const EditTemplateForm = ({
duration: 5000, duration: 5000,
}); });
// Router refresh is here to clear the router cache for when navigating to /documents.
router.refresh();
router.push(templateRootPath); router.push(templateRootPath);
} catch (err) { } catch (err) {
console.error(err);
toast({ toast({
title: _(msg`Error`), title: _(msg`Error`),
description: _(msg`An error occurred while adding signers.`), description: _(msg`An error occurred while adding fields.`),
variant: 'destructive', variant: 'destructive',
}); });
} }
@@ -301,6 +323,7 @@ export const EditTemplateForm = ({
fields={fields} fields={fields}
onSubmit={onAddFieldsFormSubmit} onSubmit={onAddFieldsFormSubmit}
teamId={team?.id} teamId={team?.id}
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
/> />
</Stepper> </Stepper>
</DocumentFlowFormContainer> </DocumentFlowFormContainer>

View File

@@ -73,7 +73,6 @@ export const TemplatePageView = async ({ params, team }: TemplatePageViewProps)
const mockedDocumentMeta = templateMeta const mockedDocumentMeta = templateMeta
? { ? {
typedSignatureEnabled: false,
...templateMeta, ...templateMeta,
signingOrder: templateMeta.signingOrder || DocumentSigningOrder.SEQUENTIAL, signingOrder: templateMeta.signingOrder || DocumentSigningOrder.SEQUENTIAL,
documentId: 0, documentId: 0,
@@ -155,7 +154,7 @@ export const TemplatePageView = async ({ params, team }: TemplatePageViewProps)
</div> </div>
</div> </div>
<p className="text-muted-foreground mt-2 px-4 text-sm "> <p className="text-muted-foreground mt-2 px-4 text-sm">
<Trans>Manage and view template</Trans> <Trans>Manage and view template</Trans>
</p> </p>

View File

@@ -209,11 +209,19 @@ export default async function SigningCertificate({ searchParams }: SigningCertif
boxShadow: `0px 0px 0px 4.88px rgba(122, 196, 85, 0.1), 0px 0px 0px 1.22px rgba(122, 196, 85, 0.6), 0px 0px 0px 0.61px rgba(122, 196, 85, 1)`, boxShadow: `0px 0px 0px 4.88px rgba(122, 196, 85, 0.1), 0px 0px 0px 1.22px rgba(122, 196, 85, 0.6), 0px 0px 0px 0.61px rgba(122, 196, 85, 1)`,
}} }}
> >
<img {signature.Signature?.signatureImageAsBase64 && (
src={`${signature.Signature?.signatureImageAsBase64}`} <img
alt="Signature" src={`${signature.Signature?.signatureImageAsBase64}`}
className="max-h-12 max-w-full" alt="Signature"
/> className="max-h-12 max-w-full"
/>
)}
{signature.Signature?.typedSignature && (
<p className="font-signature text-center text-sm">
{signature.Signature?.typedSignature}
</p>
)}
</div> </div>
<p className="text-muted-foreground mt-2 text-sm print:text-xs"> <p className="text-muted-foreground mt-2 text-sm print:text-xs">

View File

@@ -102,9 +102,9 @@ export const SignDirectTemplateForm = ({
created: new Date(), created: new Date(),
recipientId: 1, recipientId: 1,
fieldId: 1, fieldId: 1,
signatureImageAsBase64: value.value, signatureImageAsBase64: value.value.startsWith('data:') ? value.value : null,
typedSignature: null, typedSignature: value.value.startsWith('data:') ? null : value.value,
}; } satisfies Signature;
} }
if (field.type === FieldType.DATE) { if (field.type === FieldType.DATE) {

View File

@@ -0,0 +1,237 @@
'use client';
import { useState, useTransition } from 'react';
import { useRouter } from 'next/navigation';
import { Plural, Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { useForm } from 'react-hook-form';
import { P, match } from 'ts-pattern';
import { unsafe_useEffectOnce } from '@documenso/lib/client-only/hooks/use-effect-once';
import { DocumentAuth } from '@documenso/lib/types/document-auth';
import { extractInitials } from '@documenso/lib/utils/recipient-formatter';
import type { Field, Recipient } from '@documenso/prisma/client';
import { FieldType } from '@documenso/prisma/client';
import { trpc } from '@documenso/trpc/react';
import { Button } from '@documenso/ui/primitives/button';
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from '@documenso/ui/primitives/dialog';
import { FRIENDLY_FIELD_TYPE } from '@documenso/ui/primitives/document-flow/types';
import { Form } from '@documenso/ui/primitives/form/form';
import { useToast } from '@documenso/ui/primitives/use-toast';
import { SigningDisclosure } from '~/components/general/signing-disclosure';
import { useRequiredDocumentAuthContext } from './document-auth-provider';
import { useRequiredSigningContext } from './provider';
const AUTO_SIGNABLE_FIELD_TYPES: string[] = [
FieldType.NAME,
FieldType.INITIALS,
FieldType.EMAIL,
FieldType.DATE,
];
// The action auth types that are not allowed to be auto signed
//
// Reasoning: If the action auth is a passkey or 2FA, it's likely that the owner of the document
// intends on having the user manually sign due to the additional security measures employed for
// other field types.
const NON_AUTO_SIGNABLE_ACTION_AUTH_TYPES: string[] = [
DocumentAuth.PASSKEY,
DocumentAuth.TWO_FACTOR_AUTH,
];
// The threshold for the number of fields that could be autosigned before displaying the dialog
//
// Reasoning: If there aren't that many fields, it's likely going to be easier to manually sign each one
// while for larger documents with many fields it will be beneficial to sign away the boilerplate fields.
const AUTO_SIGN_THRESHOLD = 5;
export type AutoSignProps = {
recipient: Pick<Recipient, 'id' | 'token'>;
fields: Field[];
};
export const AutoSign = ({ recipient, fields }: AutoSignProps) => {
const { _ } = useLingui();
const { toast } = useToast();
const router = useRouter();
const { email, fullName } = useRequiredSigningContext();
const { derivedRecipientActionAuth } = useRequiredDocumentAuthContext();
const [open, setOpen] = useState(false);
const [isPending, startTransition] = useTransition();
const form = useForm();
const { mutateAsync: signFieldWithToken } = trpc.field.signFieldWithToken.useMutation();
const autoSignableFields = fields.filter((field) => {
if (field.inserted) {
return false;
}
if (!AUTO_SIGNABLE_FIELD_TYPES.includes(field.type)) {
return false;
}
if (field.type === FieldType.NAME && !fullName) {
return false;
}
if (field.type === FieldType.INITIALS && !fullName) {
return false;
}
if (field.type === FieldType.EMAIL && !email) {
return false;
}
return true;
});
const actionAuthAllowsAutoSign = !NON_AUTO_SIGNABLE_ACTION_AUTH_TYPES.includes(
derivedRecipientActionAuth ?? '',
);
const onSubmit = async () => {
const results = await Promise.allSettled(
autoSignableFields.map(async (field) => {
const value = match(field.type)
.with(FieldType.NAME, () => fullName)
.with(FieldType.INITIALS, () => extractInitials(fullName))
.with(FieldType.EMAIL, () => email)
.with(FieldType.DATE, () => new Date().toISOString())
.otherwise(() => '');
const authOptions = match(derivedRecipientActionAuth)
.with(DocumentAuth.ACCOUNT, () => ({
type: DocumentAuth.ACCOUNT,
}))
.with(DocumentAuth.EXPLICIT_NONE, () => ({
type: DocumentAuth.EXPLICIT_NONE,
}))
.with(null, () => undefined)
.with(
P.union(DocumentAuth.PASSKEY, DocumentAuth.TWO_FACTOR_AUTH),
// This is a bit dirty, but the sentinel value used here is incredibly short-lived.
() => 'NOT_SUPPORTED' as const,
)
.exhaustive();
if (authOptions === 'NOT_SUPPORTED') {
throw new Error('Action auth is not supported for auto signing');
}
if (!value) {
throw new Error('No value to sign');
}
return await signFieldWithToken({
token: recipient.token,
fieldId: field.id,
value,
isBase64: false,
authOptions,
});
}),
);
if (results.some((result) => result.status === 'rejected')) {
toast({
title: _(msg`Error`),
description: _(
msg`An error occurred while auto-signing the document, some fields may not be signed. Please review and manually sign any remaining fields.`,
),
duration: 5000,
variant: 'destructive',
});
}
startTransition(() => {
router.refresh();
setOpen(false);
});
};
unsafe_useEffectOnce(() => {
if (actionAuthAllowsAutoSign && autoSignableFields.length > AUTO_SIGN_THRESHOLD) {
setOpen(true);
}
});
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogContent>
<DialogHeader>
<DialogTitle>Automatically sign fields</DialogTitle>
</DialogHeader>
<div className="text-muted-foreground max-w-[50ch]">
<p>
<Trans>
When you sign a document, we can automatically fill in and sign the following fields
using information that has already been provided. You can also manually sign or remove
any automatically signed fields afterwards if you desire.
</Trans>
</p>
<ul className="mt-4 flex list-inside list-disc flex-col gap-y-0.5">
{AUTO_SIGNABLE_FIELD_TYPES.map((fieldType) => (
<li key={fieldType}>
<Trans>{_(FRIENDLY_FIELD_TYPE[fieldType as FieldType])}</Trans>
<span className="pl-2 text-sm">
(
<Plural
value={autoSignableFields.filter((f) => f.type === fieldType).length}
one="1 matching field"
other="# matching fields"
/>
)
</span>
</li>
))}
</ul>
</div>
<SigningDisclosure className="mt-4" />
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<DialogFooter className="flex w-full flex-1 flex-nowrap gap-2">
<Button
type="button"
variant="secondary"
onClick={() => {
setOpen(false);
}}
>
<Trans>Cancel</Trans>
</Button>
<Button
type="submit"
className="min-w-[6rem]"
loading={form.formState.isSubmitting || isPending}
disabled={!autoSignableFields.length}
>
<Trans>Sign</Trans>
</Button>
</DialogFooter>
</form>
</Form>
</DialogContent>
</Dialog>
);
};

View File

@@ -144,13 +144,13 @@ export const DateField = ({
)} )}
{!field.inserted && ( {!field.inserted && (
<p className="group-hover:text-primary text-muted-foreground duration-200 group-hover:text-yellow-300"> <p className="group-hover:text-primary text-muted-foreground text-[clamp(0.425rem,25cqw,0.825rem)] duration-200 group-hover:text-yellow-300">
<Trans>Date</Trans> <Trans>Date</Trans>
</p> </p>
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 text-[clamp(0.625rem,1cqw,0.825rem)] duration-200"> <p className="text-muted-foreground dark:text-background/80 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{localDateString} {localDateString}
</p> </p>
)} )}

View File

@@ -178,7 +178,7 @@ export const DropdownField = ({
)} )}
{!field.inserted && ( {!field.inserted && (
<p className="group-hover:text-primary text-muted-foreground flex flex-col items-center justify-center duration-200"> <p className="group-hover:text-primary text-muted-foreground flex flex-col items-center justify-center duration-200 ">
<Select value={localChoice} onValueChange={handleSelectItem}> <Select value={localChoice} onValueChange={handleSelectItem}>
<SelectTrigger <SelectTrigger
className={cn( className={cn(
@@ -190,7 +190,7 @@ export const DropdownField = ({
)} )}
> >
<SelectValue <SelectValue
className="text-[clamp(0.625rem,1cqw,0.825rem)]" className="text-[clamp(0.425rem,25cqw,0.825rem)]"
placeholder={`${_(msg`Select`)}`} placeholder={`${_(msg`Select`)}`}
/> />
</SelectTrigger> </SelectTrigger>
@@ -206,7 +206,7 @@ export const DropdownField = ({
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 text-[clamp(0.625rem,1cqw,0.825rem)] duration-200"> <p className="text-muted-foreground dark:text-background/80 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{field.customText} {field.customText}
</p> </p>
)} )}

View File

@@ -122,13 +122,13 @@ export const EmailField = ({ field, recipient, onSignField, onUnsignField }: Ema
)} )}
{!field.inserted && ( {!field.inserted && (
<p className="group-hover:text-primary text-muted-foreground duration-200 group-hover:text-yellow-300"> <p className="group-hover:text-primary text-muted-foreground text-[clamp(0.425rem,25cqw,0.825rem)] duration-200 group-hover:text-yellow-300">
<Trans>Email</Trans> <Trans>Email</Trans>
</p> </p>
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 text-[clamp(0.625rem,1cqw,0.825rem)] duration-200"> <p className="text-muted-foreground dark:text-background/80 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{field.customText} {field.customText}
</p> </p>
)} )}

View File

@@ -128,13 +128,13 @@ export const InitialsField = ({
)} )}
{!field.inserted && ( {!field.inserted && (
<p className="group-hover:text-primary text-muted-foreground duration-200 group-hover:text-yellow-300"> <p className="group-hover:text-primary text-muted-foreground text-[clamp(0.425rem,25cqw,0.825rem)] duration-200 group-hover:text-yellow-300">
<Trans>Initials</Trans> <Trans>Initials</Trans>
</p> </p>
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 text-[clamp(0.625rem,1cqw,0.825rem)] duration-200"> <p className="text-muted-foreground dark:text-background/80 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{field.customText} {field.customText}
</p> </p>
)} )}

View File

@@ -172,7 +172,7 @@ export const NameField = ({ field, recipient, onSignField, onUnsignField }: Name
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 text-[clamp(0.625rem,1cqw,0.825rem)] duration-200"> <p className="text-muted-foreground dark:text-background/80 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{field.customText} {field.customText}
</p> </p>
)} )}

View File

@@ -252,14 +252,15 @@ export const NumberField = ({ field, recipient, onSignField, onUnsignField }: Nu
}, },
)} )}
> >
<span className="flex items-center justify-center gap-x-1 text-sm"> <span className="flex items-center justify-center gap-x-1">
<Hash className="h-4 w-4" /> {fieldDisplayName} <Hash className="h-[clamp(0.625rem,20cqw,0.925rem)] w-[clamp(0.625rem,20cqw,0.925rem)]" />{' '}
<span className="text-[clamp(0.425rem,25cqw,0.825rem)]">{fieldDisplayName}</span>
</span> </span>
</p> </p>
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 text-[clamp(0.625rem,1cqw,0.825rem)] duration-200"> <p className="text-muted-foreground dark:text-background/80 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{field.customText} {field.customText}
</p> </p>
)} )}

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { createContext, useContext, useState } from 'react'; import { createContext, useContext, useEffect, useState } from 'react';
export type SigningContextValue = { export type SigningContextValue = {
fullName: string; fullName: string;
@@ -44,6 +44,12 @@ export const SigningProvider = ({
const [email, setEmail] = useState(initialEmail || ''); const [email, setEmail] = useState(initialEmail || '');
const [signature, setSignature] = useState(initialSignature || null); const [signature, setSignature] = useState(initialSignature || null);
useEffect(() => {
if (initialSignature) {
setSignature(initialSignature);
}
}, [initialSignature]);
return ( return (
<SigningContext.Provider <SigningContext.Provider
value={{ value={{

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useMemo, useState, useTransition } from 'react'; import { useLayoutEffect, useMemo, useRef, useState, useTransition } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
@@ -51,6 +51,10 @@ export const SignatureField = ({
const { _ } = useLingui(); const { _ } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
const signatureRef = useRef<HTMLParagraphElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const [fontSize, setFontSize] = useState(2);
const { signature: providedSignature, setSignature: setProvidedSignature } = const { signature: providedSignature, setSignature: setProvidedSignature } =
useRequiredSigningContext(); useRequiredSigningContext();
@@ -108,6 +112,7 @@ export const SignatureField = ({
actionTarget: field.type, actionTarget: field.type,
}); });
}; };
const onSign = async (authOptions?: TRecipientActionAuth, signature?: string) => { const onSign = async (authOptions?: TRecipientActionAuth, signature?: string) => {
try { try {
const value = signature || providedSignature; const value = signature || providedSignature;
@@ -117,11 +122,23 @@ export const SignatureField = ({
return; return;
} }
const isTypedSignature = !value.startsWith('data:image');
if (isTypedSignature && !typedSignatureEnabled) {
toast({
title: _(msg`Error`),
description: _(msg`Typed signatures are not allowed. Please draw your signature.`),
variant: 'destructive',
});
return;
}
const payload: TSignFieldWithTokenMutationSchema = { const payload: TSignFieldWithTokenMutationSchema = {
token: recipient.token, token: recipient.token,
fieldId: field.id, fieldId: field.id,
value, value,
isBase64: true, isBase64: !isTypedSignature,
authOptions, authOptions,
}; };
@@ -176,6 +193,41 @@ export const SignatureField = ({
} }
}; };
useLayoutEffect(() => {
if (!signatureRef.current || !containerRef.current || !signature?.typedSignature) {
return;
}
const adjustTextSize = () => {
const container = containerRef.current;
const text = signatureRef.current;
if (!container || !text) {
return;
}
let size = 2;
text.style.fontSize = `${size}rem`;
while (
(text.scrollWidth > container.clientWidth || text.scrollHeight > container.clientHeight) &&
size > 0.8
) {
size -= 0.1;
text.style.fontSize = `${size}rem`;
}
setFontSize(size);
};
const resizeObserver = new ResizeObserver(adjustTextSize);
resizeObserver.observe(containerRef.current);
adjustTextSize();
return () => resizeObserver.disconnect();
}, [signature?.typedSignature]);
return ( return (
<SigningFieldContainer <SigningFieldContainer
field={field} field={field}
@@ -191,7 +243,7 @@ export const SignatureField = ({
)} )}
{state === 'empty' && ( {state === 'empty' && (
<p className="group-hover:text-primary font-signature text-muted-foreground text-xl duration-200 group-hover:text-yellow-300"> <p className="group-hover:text-primary font-signature text-muted-foreground text-[clamp(0.575rem,25cqw,1.2rem)] text-xl duration-200 group-hover:text-yellow-300">
<Trans>Signature</Trans> <Trans>Signature</Trans>
</p> </p>
)} )}
@@ -205,10 +257,15 @@ export const SignatureField = ({
)} )}
{state === 'signed-text' && ( {state === 'signed-text' && (
<p className="font-signature text-muted-foreground dark:text-background text-lg duration-200 sm:text-xl md:text-2xl lg:text-3xl"> <div ref={containerRef} className="flex h-full w-full items-center justify-center p-2">
{/* This optional chaining is intentional, we don't want to move the check into the condition above */} <p
{signature?.typedSignature} ref={signatureRef}
</p> className="font-signature text-muted-foreground dark:text-background w-full overflow-hidden break-all text-center leading-tight duration-200"
style={{ fontSize: `${fontSize}rem` }}
>
{signature?.typedSignature}
</p>
</div>
)} )}
<Dialog open={showSignatureModal} onOpenChange={setShowSignatureModal}> <Dialog open={showSignatureModal} onOpenChange={setShowSignatureModal}>

View File

@@ -22,6 +22,7 @@ import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer';
import { DocumentReadOnlyFields } from '~/components/document/document-read-only-fields'; import { DocumentReadOnlyFields } from '~/components/document/document-read-only-fields';
import { AutoSign } from './auto-sign';
import { CheckboxField } from './checkbox-field'; import { CheckboxField } from './checkbox-field';
import { DateField } from './date-field'; import { DateField } from './date-field';
import { DropdownField } from './dropdown-field'; import { DropdownField } from './dropdown-field';
@@ -113,6 +114,8 @@ export const SigningPageView = ({
<DocumentReadOnlyFields fields={completedFields} /> <DocumentReadOnlyFields fields={completedFields} />
<AutoSign recipient={recipient} fields={fields} />
<ElementVisible target={PDF_VIEWER_PAGE_SELECTOR}> <ElementVisible target={PDF_VIEWER_PAGE_SELECTOR}>
{fields.map((field) => {fields.map((field) =>
match(field.type) match(field.type)

View File

@@ -252,14 +252,16 @@ export const TextField = ({ field, recipient, onSignField, onUnsignField }: Text
)} )}
> >
<span className="flex items-center justify-center gap-x-1"> <span className="flex items-center justify-center gap-x-1">
<Type /> <Type className="h-[clamp(0.625rem,20cqw,0.925rem)] w-[clamp(0.625rem,20cqw,0.925rem)]" />
{fieldDisplayName || <Trans>Text</Trans>} <span className="text-[clamp(0.425rem,25cqw,0.825rem)]">
{fieldDisplayName || <Trans>Text</Trans>}
</span>
</span> </span>
</p> </p>
)} )}
{field.inserted && ( {field.inserted && (
<p className="text-muted-foreground dark:text-background/80 flex items-center justify-center gap-x-1 duration-200"> <p className="text-muted-foreground dark:text-background/80 flex items-center justify-center gap-x-1 text-[clamp(0.425rem,25cqw,0.825rem)] duration-200">
{field.customText.length < 20 {field.customText.length < 20
? field.customText ? field.customText
: field.customText.substring(0, 15) + '...'} : field.customText.substring(0, 15) + '...'}

View File

@@ -52,13 +52,7 @@ export default async function TeamsSettingsPage({ params }: TeamsSettingsPagePro
<AvatarImageForm className="mb-8" team={team} user={session.user} /> <AvatarImageForm className="mb-8" team={team} user={session.user} />
<UpdateTeamForm <UpdateTeamForm teamId={team.id} teamName={team.name} teamUrl={team.url} />
teamId={team.id}
teamName={team.name}
teamUrl={team.url}
documentVisibility={team.teamGlobalSettings?.documentVisibility}
includeSenderDetails={team.teamGlobalSettings?.includeSenderDetails}
/>
<section className="mt-6 space-y-6"> <section className="mt-6 space-y-6">
{(team.teamEmail || team.emailVerification) && ( {(team.teamEmail || team.emailVerification) && (

View File

@@ -39,6 +39,8 @@ const ZTeamDocumentPreferencesFormSchema = z.object({
documentVisibility: z.nativeEnum(DocumentVisibility), documentVisibility: z.nativeEnum(DocumentVisibility),
documentLanguage: z.enum(SUPPORTED_LANGUAGE_CODES), documentLanguage: z.enum(SUPPORTED_LANGUAGE_CODES),
includeSenderDetails: z.boolean(), includeSenderDetails: z.boolean(),
typedSignatureEnabled: z.boolean(),
includeSigningCertificate: z.boolean(),
}); });
type TTeamDocumentPreferencesFormSchema = z.infer<typeof ZTeamDocumentPreferencesFormSchema>; type TTeamDocumentPreferencesFormSchema = z.infer<typeof ZTeamDocumentPreferencesFormSchema>;
@@ -68,6 +70,8 @@ export const TeamDocumentPreferencesForm = ({
? settings?.documentLanguage ? settings?.documentLanguage
: 'en', : 'en',
includeSenderDetails: settings?.includeSenderDetails ?? false, includeSenderDetails: settings?.includeSenderDetails ?? false,
typedSignatureEnabled: settings?.typedSignatureEnabled ?? true,
includeSigningCertificate: settings?.includeSigningCertificate ?? true,
}, },
resolver: zodResolver(ZTeamDocumentPreferencesFormSchema), resolver: zodResolver(ZTeamDocumentPreferencesFormSchema),
}); });
@@ -76,7 +80,13 @@ export const TeamDocumentPreferencesForm = ({
const onSubmit = async (data: TTeamDocumentPreferencesFormSchema) => { const onSubmit = async (data: TTeamDocumentPreferencesFormSchema) => {
try { try {
const { documentVisibility, documentLanguage, includeSenderDetails } = data; const {
documentVisibility,
documentLanguage,
includeSenderDetails,
includeSigningCertificate,
typedSignatureEnabled,
} = data;
await updateTeamDocumentPreferences({ await updateTeamDocumentPreferences({
teamId: team.id, teamId: team.id,
@@ -84,6 +94,8 @@ export const TeamDocumentPreferencesForm = ({
documentVisibility, documentVisibility,
documentLanguage, documentLanguage,
includeSenderDetails, includeSenderDetails,
typedSignatureEnabled,
includeSigningCertificate,
}, },
}); });
@@ -105,7 +117,7 @@ export const TeamDocumentPreferencesForm = ({
<Form {...form}> <Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}> <form onSubmit={form.handleSubmit(onSubmit)}>
<fieldset <fieldset
className="flex h-full max-w-xl flex-col gap-y-4" className="flex h-full max-w-xl flex-col gap-y-6"
disabled={form.formState.isSubmitting} disabled={form.formState.isSubmitting}
> >
<FormField <FormField
@@ -227,6 +239,67 @@ export const TeamDocumentPreferencesForm = ({
)} )}
/> />
<FormField
control={form.control}
name="typedSignatureEnabled"
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>
<Trans>Enable Typed Signature</Trans>
</FormLabel>
<div>
<FormControl className="block">
<Switch
ref={field.ref}
name={field.name}
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</div>
<FormDescription>
<Trans>
Controls whether the recipients can sign the documents using a typed signature.
Enable or disable the typed signature globally.
</Trans>
</FormDescription>
</FormItem>
)}
/>
<FormField
control={form.control}
name="includeSigningCertificate"
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>
<Trans>Include the Signing Certificate in the Document</Trans>
</FormLabel>
<div>
<FormControl className="block">
<Switch
ref={field.ref}
name={field.name}
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</div>
<FormDescription>
<Trans>
Controls whether the signing certificate will be included in the document when
it is downloaded. The signing certificate can still be downloaded from the logs
page separately.
</Trans>
</FormDescription>
</FormItem>
)}
/>
<div className="flex flex-row justify-end space-x-4"> <div className="flex flex-row justify-end space-x-4">
<Button type="submit" loading={form.formState.isSubmitting}> <Button type="submit" loading={form.formState.isSubmitting}>
<Trans>Save</Trans> <Trans>Save</Trans>

View File

@@ -1,8 +1,12 @@
import { z } from 'zod'; import { z } from 'zod';
import { ZCssVarsSchema } from './css-vars';
export const ZBaseEmbedDataSchema = z.object({ export const ZBaseEmbedDataSchema = z.object({
darkModeDisabled: z.boolean().optional().default(false),
css: z css: z
.string() .string()
.optional() .optional()
.transform((value) => value || undefined), .transform((value) => value || undefined),
cssVars: ZCssVarsSchema.optional().default({}),
}); });

View File

@@ -10,6 +10,7 @@ export type EmbedDocumentCompletedPageProps = {
}; };
export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentCompletedPageProps) => { export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentCompletedPageProps) => {
console.log({ signature });
return ( return (
<div className="relative mx-auto flex min-h-[100dvh] max-w-screen-lg flex-col items-center justify-center p-6"> <div className="relative mx-auto flex min-h-[100dvh] max-w-screen-lg flex-col items-center justify-center p-6">
<h3 className="text-foreground text-2xl font-semibold"> <h3 className="text-foreground text-2xl font-semibold">

View File

@@ -0,0 +1,59 @@
import { colord } from 'colord';
import { toSnakeCase } from 'remeda';
import { z } from 'zod';
export const ZCssVarsSchema = z
.object({
background: z.string().optional().describe('Base background color'),
foreground: z.string().optional().describe('Base text color'),
muted: z.string().optional().describe('Muted/subtle background color'),
mutedForeground: z.string().optional().describe('Muted/subtle text color'),
popover: z.string().optional().describe('Popover/dropdown background color'),
popoverForeground: z.string().optional().describe('Popover/dropdown text color'),
card: z.string().optional().describe('Card background color'),
cardBorder: z.string().optional().describe('Card border color'),
cardBorderTint: z.string().optional().describe('Card border tint/highlight color'),
cardForeground: z.string().optional().describe('Card text color'),
fieldCard: z.string().optional().describe('Field card background color'),
fieldCardBorder: z.string().optional().describe('Field card border color'),
fieldCardForeground: z.string().optional().describe('Field card text color'),
widget: z.string().optional().describe('Widget background color'),
widgetForeground: z.string().optional().describe('Widget text color'),
border: z.string().optional().describe('Default border color'),
input: z.string().optional().describe('Input field border color'),
primary: z.string().optional().describe('Primary action/button color'),
primaryForeground: z.string().optional().describe('Primary action/button text color'),
secondary: z.string().optional().describe('Secondary action/button color'),
secondaryForeground: z.string().optional().describe('Secondary action/button text color'),
accent: z.string().optional().describe('Accent/highlight color'),
accentForeground: z.string().optional().describe('Accent/highlight text color'),
destructive: z.string().optional().describe('Destructive/danger action color'),
destructiveForeground: z.string().optional().describe('Destructive/danger text color'),
ring: z.string().optional().describe('Focus ring color'),
radius: z.string().optional().describe('Border radius size in REM units'),
warning: z.string().optional().describe('Warning/alert color'),
})
.describe('Custom CSS variables for theming');
export type TCssVarsSchema = z.infer<typeof ZCssVarsSchema>;
export const toNativeCssVars = (vars: TCssVarsSchema) => {
const cssVars: Record<string, string> = {};
const { radius, ...colorVars } = vars;
for (const [key, value] of Object.entries(colorVars)) {
if (value) {
const color = colord(value);
const { h, s, l } = color.toHsl();
cssVars[`--${toSnakeCase(key)}`] = `${h} ${s} ${l}`;
}
}
if (radius) {
cssVars[`--radius`] = `${radius}`;
}
return cssVars;
};

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useEffect, useState } from 'react'; import { useEffect, useLayoutEffect, useState } from 'react';
import { useSearchParams } from 'next/navigation'; import { useSearchParams } from 'next/navigation';
@@ -14,7 +14,7 @@ import { DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-form
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer'; import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones'; import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones';
import { validateFieldsInserted } from '@documenso/lib/utils/fields'; import { validateFieldsInserted } from '@documenso/lib/utils/fields';
import type { DocumentMeta, Recipient, TemplateMeta } from '@documenso/prisma/client'; import type { DocumentMeta, Recipient, Signature, TemplateMeta } from '@documenso/prisma/client';
import { type DocumentData, type Field, FieldType } from '@documenso/prisma/client'; import { type DocumentData, type Field, FieldType } from '@documenso/prisma/client';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import type { import type {
@@ -38,6 +38,7 @@ import { Logo } from '~/components/branding/logo';
import { EmbedClientLoading } from '../../client-loading'; import { EmbedClientLoading } from '../../client-loading';
import { EmbedDocumentCompleted } from '../../completed'; import { EmbedDocumentCompleted } from '../../completed';
import { EmbedDocumentFields } from '../../document-fields'; import { EmbedDocumentFields } from '../../document-fields';
import { injectCss } from '../../util';
import { ZDirectTemplateEmbedDataSchema } from './schema'; import { ZDirectTemplateEmbedDataSchema } from './schema';
export type EmbedDirectTemplateClientPageProps = { export type EmbedDirectTemplateClientPageProps = {
@@ -47,6 +48,8 @@ export type EmbedDirectTemplateClientPageProps = {
recipient: Recipient; recipient: Recipient;
fields: Field[]; fields: Field[];
metadata?: DocumentMeta | TemplateMeta | null; metadata?: DocumentMeta | TemplateMeta | null;
hidePoweredBy?: boolean;
isPlatformOrEnterprise?: boolean;
}; };
export const EmbedDirectTemplateClientPage = ({ export const EmbedDirectTemplateClientPage = ({
@@ -56,6 +59,8 @@ export const EmbedDirectTemplateClientPage = ({
recipient, recipient,
fields, fields,
metadata, metadata,
hidePoweredBy = false,
isPlatformOrEnterprise = false,
}: EmbedDirectTemplateClientPageProps) => { }: EmbedDirectTemplateClientPageProps) => {
const { _ } = useLingui(); const { _ } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
@@ -108,9 +113,9 @@ export const EmbedDirectTemplateClientPage = ({
created: new Date(), created: new Date(),
recipientId: 1, recipientId: 1,
fieldId: 1, fieldId: 1,
signatureImageAsBase64: payload.value, signatureImageAsBase64: payload.value.startsWith('data:') ? payload.value : null,
typedSignature: null, typedSignature: payload.value.startsWith('data:') ? null : payload.value,
}; } satisfies Signature;
} }
if (field.type === FieldType.DATE) { if (field.type === FieldType.DATE) {
@@ -249,7 +254,7 @@ export const EmbedDirectTemplateClientPage = ({
} }
}; };
useEffect(() => { useLayoutEffect(() => {
const hash = window.location.hash.slice(1); const hash = window.location.hash.slice(1);
try { try {
@@ -264,6 +269,17 @@ export const EmbedDirectTemplateClientPage = ({
setFullName(data.name); setFullName(data.name);
setIsNameLocked(!!data.lockName); setIsNameLocked(!!data.lockName);
} }
if (data.darkModeDisabled) {
document.documentElement.classList.add('dark-mode-disabled');
}
if (isPlatformOrEnterprise) {
injectCss({
css: data.css,
cssVars: data.cssVars,
});
}
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@@ -296,8 +312,8 @@ export const EmbedDirectTemplateClientPage = ({
fieldId: 1, fieldId: 1,
recipientId: 1, recipientId: 1,
created: new Date(), created: new Date(),
typedSignature: null, signatureImageAsBase64: signature?.startsWith('data:') ? signature : null,
signatureImageAsBase64: signature, typedSignature: signature?.startsWith('data:') ? null : signature,
}} }}
/> />
); );
@@ -452,10 +468,12 @@ export const EmbedDirectTemplateClientPage = ({
/> />
</div> </div>
<div className="bg-primary text-primary-foreground fixed bottom-0 left-0 z-40 rounded-tr px-2 py-1 text-xs font-medium opacity-60 hover:opacity-100"> {!hidePoweredBy && (
<span>Powered by</span> <div className="bg-primary text-primary-foreground fixed bottom-0 left-0 z-40 rounded-tr px-2 py-1 text-xs font-medium opacity-60 hover:opacity-100">
<Logo className="ml-2 inline-block h-[14px]" /> <span>Powered by</span>
</div> <Logo className="ml-2 inline-block h-[14px]" />
</div>
)}
</div> </div>
); );
}; };

View File

@@ -2,8 +2,11 @@ import { notFound } from 'next/navigation';
import { match } from 'ts-pattern'; import { match } from 'ts-pattern';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
import { isDocumentPlatform } from '@documenso/ee/server-only/util/is-document-platform';
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app'; import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
import { getServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { getServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
import { getTeamById } from '@documenso/lib/server-only/team/get-team';
import { getTemplateByDirectLinkToken } from '@documenso/lib/server-only/template/get-template-by-direct-link-token'; import { getTemplateByDirectLinkToken } from '@documenso/lib/server-only/template/get-template-by-direct-link-token';
import { DocumentAccessAuth } from '@documenso/lib/types/document-auth'; import { DocumentAccessAuth } from '@documenso/lib/types/document-auth';
import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth'; import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth';
@@ -51,6 +54,14 @@ export default async function EmbedDirectTemplatePage({ params }: EmbedDirectTem
documentAuth: template.authOptions, documentAuth: template.authOptions,
}); });
const [isPlatformDocument, isEnterpriseDocument] = await Promise.all([
isDocumentPlatform(template),
isUserEnterprise({
userId: template.userId,
teamId: template.teamId ?? undefined,
}),
]);
const isAccessAuthValid = match(derivedRecipientAccessAuth) const isAccessAuthValid = match(derivedRecipientAccessAuth)
.with(DocumentAccessAuth.ACCOUNT, () => user !== null) .with(DocumentAccessAuth.ACCOUNT, () => user !== null)
.with(null, () => true) .with(null, () => true)
@@ -72,6 +83,12 @@ export default async function EmbedDirectTemplatePage({ params }: EmbedDirectTem
const fields = template.Field.filter((field) => field.recipientId === directTemplateRecipientId); const fields = template.Field.filter((field) => field.recipientId === directTemplateRecipientId);
const team = template.teamId
? await getTeamById({ teamId: template.teamId, userId: template.userId }).catch(() => null)
: null;
const hidePoweredBy = team?.teamGlobalSettings?.brandingHidePoweredBy ?? false;
return ( return (
<SigningProvider email={user?.email} fullName={user?.name} signature={user?.signature}> <SigningProvider email={user?.email} fullName={user?.name} signature={user?.signature}>
<DocumentAuthProvider <DocumentAuthProvider
@@ -86,6 +103,8 @@ export default async function EmbedDirectTemplatePage({ params }: EmbedDirectTem
recipient={recipient} recipient={recipient}
fields={fields} fields={fields}
metadata={template.templateMeta} metadata={template.templateMeta}
hidePoweredBy={isPlatformDocument || isEnterpriseDocument || hidePoweredBy}
isPlatformOrEnterprise={isPlatformDocument || isEnterpriseDocument}
/> />
</DocumentAuthProvider> </DocumentAuthProvider>
</SigningProvider> </SigningProvider>

View File

@@ -58,6 +58,7 @@ export const EmbedDocumentFields = ({
recipient={recipient} recipient={recipient}
onSignField={onSignField} onSignField={onSignField}
onUnsignField={onUnsignField} onUnsignField={onUnsignField}
typedSignatureEnabled={metadata?.typedSignatureEnabled}
/> />
)) ))
.with(FieldType.INITIALS, () => ( .with(FieldType.INITIALS, () => (

View File

@@ -1,6 +1,6 @@
'use client'; 'use client';
import { useEffect, useState } from 'react'; import { useEffect, useLayoutEffect, useState } from 'react';
import { Trans, msg } from '@lingui/macro'; import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react'; import { useLingui } from '@lingui/react';
@@ -28,6 +28,7 @@ import { Logo } from '~/components/branding/logo';
import { EmbedClientLoading } from '../../client-loading'; import { EmbedClientLoading } from '../../client-loading';
import { EmbedDocumentCompleted } from '../../completed'; import { EmbedDocumentCompleted } from '../../completed';
import { EmbedDocumentFields } from '../../document-fields'; import { EmbedDocumentFields } from '../../document-fields';
import { injectCss } from '../../util';
import { ZSignDocumentEmbedDataSchema } from './schema'; import { ZSignDocumentEmbedDataSchema } from './schema';
export type EmbedSignDocumentClientPageProps = { export type EmbedSignDocumentClientPageProps = {
@@ -38,6 +39,8 @@ export type EmbedSignDocumentClientPageProps = {
fields: Field[]; fields: Field[];
metadata?: DocumentMeta | TemplateMeta | null; metadata?: DocumentMeta | TemplateMeta | null;
isCompleted?: boolean; isCompleted?: boolean;
hidePoweredBy?: boolean;
isPlatformOrEnterprise?: boolean;
}; };
export const EmbedSignDocumentClientPage = ({ export const EmbedSignDocumentClientPage = ({
@@ -48,6 +51,8 @@ export const EmbedSignDocumentClientPage = ({
fields, fields,
metadata, metadata,
isCompleted, isCompleted,
hidePoweredBy = false,
isPlatformOrEnterprise = false,
}: EmbedSignDocumentClientPageProps) => { }: EmbedSignDocumentClientPageProps) => {
const { _ } = useLingui(); const { _ } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
@@ -131,7 +136,7 @@ export const EmbedSignDocumentClientPage = ({
} }
}; };
useEffect(() => { useLayoutEffect(() => {
const hash = window.location.hash.slice(1); const hash = window.location.hash.slice(1);
try { try {
@@ -144,6 +149,17 @@ export const EmbedSignDocumentClientPage = ({
// Since a recipient can be provided a name we can lock it without requiring // Since a recipient can be provided a name we can lock it without requiring
// a to be provided by the parent application, unlike direct templates. // a to be provided by the parent application, unlike direct templates.
setIsNameLocked(!!data.lockName); setIsNameLocked(!!data.lockName);
if (data.darkModeDisabled) {
document.documentElement.classList.add('dark-mode-disabled');
}
if (isPlatformOrEnterprise) {
injectCss({
css: data.css,
cssVars: data.cssVars,
});
}
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@@ -176,8 +192,8 @@ export const EmbedSignDocumentClientPage = ({
fieldId: 1, fieldId: 1,
recipientId: 1, recipientId: 1,
created: new Date(), created: new Date(),
typedSignature: null, signatureImageAsBase64: signature?.startsWith('data:') ? signature : null,
signatureImageAsBase64: signature, typedSignature: signature?.startsWith('data:') ? null : signature,
}} }}
/> />
); );
@@ -202,7 +218,7 @@ export const EmbedSignDocumentClientPage = ({
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0" className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
data-expanded={isExpanded || undefined} data-expanded={isExpanded || undefined}
> >
<div className="border-border bg-widget flex w-full flex-col rounded-xl border px-4 py-4 md:py-6"> <div className="border-border bg-widget flex w-full flex-col rounded-xl border px-4 py-4 md:py-6">
{/* Header */} {/* Header */}
<div> <div>
<div className="flex items-center justify-between gap-x-2"> <div className="flex items-center justify-between gap-x-2">
@@ -325,10 +341,12 @@ export const EmbedSignDocumentClientPage = ({
<EmbedDocumentFields recipient={recipient} fields={fields} metadata={metadata} /> <EmbedDocumentFields recipient={recipient} fields={fields} metadata={metadata} />
</div> </div>
<div className="bg-primary text-primary-foreground fixed bottom-0 left-0 z-40 rounded-tr px-2 py-1 text-xs font-medium opacity-60 hover:opacity-100"> {!hidePoweredBy && (
<span>Powered by</span> <div className="bg-primary text-primary-foreground fixed bottom-0 left-0 z-40 rounded-tr px-2 py-1 text-xs font-medium opacity-60 hover:opacity-100">
<Logo className="ml-2 inline-block h-[14px]" /> <span>Powered by</span>
</div> <Logo className="ml-2 inline-block h-[14px]" />
</div>
)}
</div> </div>
); );
}; };

View File

@@ -2,11 +2,14 @@ import { notFound } from 'next/navigation';
import { match } from 'ts-pattern'; import { match } from 'ts-pattern';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
import { isDocumentPlatform } from '@documenso/ee/server-only/util/is-document-platform';
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app'; import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
import { getServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session'; import { getServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token'; import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token'; import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token';
import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token'; import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token';
import { getTeamById } from '@documenso/lib/server-only/team/get-team';
import { DocumentAccessAuth } from '@documenso/lib/types/document-auth'; import { DocumentAccessAuth } from '@documenso/lib/types/document-auth';
import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth'; import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth';
import { DocumentStatus } from '@documenso/prisma/client'; import { DocumentStatus } from '@documenso/prisma/client';
@@ -56,6 +59,14 @@ export default async function EmbedSignDocumentPage({ params }: EmbedSignDocumen
return <EmbedPaywall />; return <EmbedPaywall />;
} }
const [isPlatformDocument, isEnterpriseDocument] = await Promise.all([
isDocumentPlatform(document),
isUserEnterprise({
userId: document.userId,
teamId: document.teamId ?? undefined,
}),
]);
const { derivedRecipientAccessAuth } = extractDocumentAuthMethods({ const { derivedRecipientAccessAuth } = extractDocumentAuthMethods({
documentAuth: document.authOptions, documentAuth: document.authOptions,
}); });
@@ -74,6 +85,12 @@ export default async function EmbedSignDocumentPage({ params }: EmbedSignDocumen
); );
} }
const team = document.teamId
? await getTeamById({ teamId: document.teamId, userId: document.userId }).catch(() => null)
: null;
const hidePoweredBy = team?.teamGlobalSettings?.brandingHidePoweredBy ?? false;
return ( return (
<SigningProvider <SigningProvider
email={recipient.email} email={recipient.email}
@@ -93,6 +110,8 @@ export default async function EmbedSignDocumentPage({ params }: EmbedSignDocumen
fields={fields} fields={fields}
metadata={document.documentMeta} metadata={document.documentMeta}
isCompleted={document.status === DocumentStatus.COMPLETED} isCompleted={document.status === DocumentStatus.COMPLETED}
hidePoweredBy={isPlatformDocument || isEnterpriseDocument || hidePoweredBy}
isPlatformOrEnterprise={isPlatformDocument || isEnterpriseDocument}
/> />
</DocumentAuthProvider> </DocumentAuthProvider>
</SigningProvider> </SigningProvider>

View File

@@ -0,0 +1,20 @@
import { type TCssVarsSchema, toNativeCssVars } from './css-vars';
export const injectCss = (options: { css?: string; cssVars?: TCssVarsSchema }) => {
const { css, cssVars } = options;
if (css) {
const style = document.createElement('style');
style.innerHTML = css;
document.head.appendChild(style);
}
if (cssVars) {
const nativeVars = toNativeCssVars(cssVars);
for (const [key, value] of Object.entries(nativeVars)) {
document.documentElement.style.setProperty(key, value);
}
}
};

View File

@@ -25,8 +25,6 @@ export const StackAvatar = ({ first, zIndex, fallbackText = '', type }: StackAva
zIndexClass = ZIndexes[zIndex] ?? ''; zIndexClass = ZIndexes[zIndex] ?? '';
} }
console.log({ type, fallbackText });
switch (type) { switch (type) {
case RecipientStatusType.UNSIGNED: case RecipientStatusType.UNSIGNED:
classes = 'bg-dawn-200 text-dawn-900'; classes = 'bg-dawn-200 text-dawn-900';

View File

@@ -6,22 +6,14 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { Trans, msg } from '@lingui/macro'; import { Trans, msg } from '@lingui/macro';
import { useLingui } from '@lingui/react'; import { useLingui } from '@lingui/react';
import { AnimatePresence, motion } from 'framer-motion'; import { AnimatePresence, motion } from 'framer-motion';
import { useSession } from 'next-auth/react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import { match } from 'ts-pattern';
import type { z } from 'zod'; import type { z } from 'zod';
import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app'; import { WEBAPP_BASE_URL } from '@documenso/lib/constants/app';
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { DocumentVisibility } from '@documenso/prisma/client';
import { trpc } from '@documenso/trpc/react'; import { trpc } from '@documenso/trpc/react';
import { ZUpdateTeamMutationSchema } from '@documenso/trpc/server/team-router/schema'; import { ZUpdateTeamMutationSchema } from '@documenso/trpc/server/team-router/schema';
import {
DocumentVisibilitySelect,
DocumentVisibilityTooltip,
} from '@documenso/ui/components/document/document-visibility-select';
import { Button } from '@documenso/ui/primitives/button'; import { Button } from '@documenso/ui/primitives/button';
import { Checkbox } from '@documenso/ui/primitives/checkbox';
import { import {
Form, Form,
FormControl, FormControl,
@@ -37,29 +29,17 @@ export type UpdateTeamDialogProps = {
teamId: number; teamId: number;
teamName: string; teamName: string;
teamUrl: string; teamUrl: string;
documentVisibility?: DocumentVisibility;
includeSenderDetails?: boolean;
}; };
const ZUpdateTeamFormSchema = ZUpdateTeamMutationSchema.shape.data.pick({ const ZUpdateTeamFormSchema = ZUpdateTeamMutationSchema.shape.data.pick({
name: true, name: true,
url: true, url: true,
documentVisibility: true,
includeSenderDetails: true,
}); });
type TUpdateTeamFormSchema = z.infer<typeof ZUpdateTeamFormSchema>; type TUpdateTeamFormSchema = z.infer<typeof ZUpdateTeamFormSchema>;
export const UpdateTeamForm = ({ export const UpdateTeamForm = ({ teamId, teamName, teamUrl }: UpdateTeamDialogProps) => {
teamId,
teamName,
teamUrl,
documentVisibility,
includeSenderDetails,
}: UpdateTeamDialogProps) => {
const router = useRouter(); const router = useRouter();
const { data: session } = useSession();
const email = session?.user?.email;
const { _ } = useLingui(); const { _ } = useLingui();
const { toast } = useToast(); const { toast } = useToast();
@@ -68,36 +48,17 @@ export const UpdateTeamForm = ({
defaultValues: { defaultValues: {
name: teamName, name: teamName,
url: teamUrl, url: teamUrl,
documentVisibility,
includeSenderDetails,
}, },
}); });
const { mutateAsync: updateTeam } = trpc.team.updateTeam.useMutation(); const { mutateAsync: updateTeam } = trpc.team.updateTeam.useMutation();
const includeSenderDetailsCheck = form.watch('includeSenderDetails');
const mapVisibilityToRole = (visibility: DocumentVisibility): DocumentVisibility => const onFormSubmit = async ({ name, url }: TUpdateTeamFormSchema) => {
match(visibility)
.with(DocumentVisibility.ADMIN, () => DocumentVisibility.ADMIN)
.with(DocumentVisibility.MANAGER_AND_ABOVE, () => DocumentVisibility.MANAGER_AND_ABOVE)
.otherwise(() => DocumentVisibility.EVERYONE);
const currentVisibilityRole = mapVisibilityToRole(
documentVisibility ?? DocumentVisibility.EVERYONE,
);
const onFormSubmit = async ({
name,
url,
documentVisibility,
includeSenderDetails,
}: TUpdateTeamFormSchema) => {
try { try {
await updateTeam({ await updateTeam({
data: { data: {
name, name,
url, url,
documentVisibility,
includeSenderDetails,
}, },
teamId, teamId,
}); });
@@ -111,8 +72,6 @@ export const UpdateTeamForm = ({
form.reset({ form.reset({
name, name,
url, url,
documentVisibility,
includeSenderDetails,
}); });
if (url !== teamUrl) { if (url !== teamUrl) {
@@ -186,68 +145,6 @@ export const UpdateTeamForm = ({
)} )}
/> />
<FormField
control={form.control}
name="documentVisibility"
render={({ field }) => (
<FormItem>
<FormLabel className="mt-4 flex flex-row items-center">
<Trans>Default Document Visibility</Trans>
<DocumentVisibilityTooltip />
</FormLabel>
<FormControl>
<DocumentVisibilitySelect
currentMemberRole={currentVisibilityRole}
isTeamSettings={true}
{...field}
onValueChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="mb-4">
<FormField
control={form.control}
name="includeSenderDetails"
render={({ field }) => (
<FormItem>
<div className="mt-6 flex flex-row items-center gap-4">
<FormLabel>
<Trans>Send on Behalf of Team</Trans>
</FormLabel>
<FormControl>
<Checkbox
className="h-5 w-5"
checkClassName="text-white"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
</div>
{includeSenderDetailsCheck ? (
<blockquote className="text-foreground/50 text-xs italic">
<Trans>
"{email}" on behalf of "{teamName}" has invited you to sign "example
document".
</Trans>
</blockquote>
) : (
<blockquote className="text-foreground/50 text-xs italic">
<Trans>"{teamUrl}" has invited you to sign "example document".</Trans>
</blockquote>
)}
<FormMessage />
</FormItem>
)}
/>
</div>
<div className="flex flex-row justify-end space-x-4"> <div className="flex flex-row justify-end space-x-4">
<AnimatePresence> <AnimatePresence>
{form.formState.isDirty && ( {form.formState.isDirty && (

View File

@@ -138,6 +138,7 @@ export const ProfileForm = ({ className, user }: ProfileFormProps) => {
containerClassName={cn('rounded-lg border bg-background')} containerClassName={cn('rounded-lg border bg-background')}
defaultValue={user.signature ?? undefined} defaultValue={user.signature ?? undefined}
onChange={(v) => onChange(v ?? '')} onChange={(v) => onChange(v ?? '')}
allowTypedSignature={true}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />

796
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"private": true, "private": true,
"version": "1.8.0-rc.4", "version": "1.8.1-rc.1",
"scripts": { "scripts": {
"build": "turbo run build", "build": "turbo run build",
"build:web": "turbo run build --filter=@documenso/web", "build:web": "turbo run build --filter=@documenso/web",
@@ -52,7 +52,7 @@
"husky": "^9.0.11", "husky": "^9.0.11",
"lint-staged": "^15.2.2", "lint-staged": "^15.2.2",
"playwright": "1.43.0", "playwright": "1.43.0",
"prettier": "^2.5.1", "prettier": "^3.3.3",
"rimraf": "^5.0.1", "rimraf": "^5.0.1",
"turbo": "^1.9.3" "turbo": "^1.9.3"
}, },

View File

@@ -302,6 +302,7 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
redirectUrl: body.meta.redirectUrl, redirectUrl: body.meta.redirectUrl,
signingOrder: body.meta.signingOrder, signingOrder: body.meta.signingOrder,
language: body.meta.language, language: body.meta.language,
typedSignatureEnabled: body.meta.typedSignatureEnabled,
requestMetadata: extractNextApiRequestMetadata(args.req), requestMetadata: extractNextApiRequestMetadata(args.req),
}); });

View File

@@ -3,7 +3,6 @@ import { z } from 'zod';
import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats'; import { DATE_FORMATS, DEFAULT_DOCUMENT_DATE_FORMAT } from '@documenso/lib/constants/date-formats';
import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n'; import { SUPPORTED_LANGUAGE_CODES } from '@documenso/lib/constants/i18n';
import '@documenso/lib/constants/time-zones';
import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones'; import { DEFAULT_DOCUMENT_TIME_ZONE, TIME_ZONES } from '@documenso/lib/constants/time-zones';
import { ZUrlSchema } from '@documenso/lib/schemas/common'; import { ZUrlSchema } from '@documenso/lib/schemas/common';
import { import {
@@ -14,6 +13,7 @@ import {
import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta'; import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta';
import { import {
DocumentDataType, DocumentDataType,
DocumentDistributionMethod,
DocumentSigningOrder, DocumentSigningOrder,
FieldType, FieldType,
ReadStatus, ReadStatus,
@@ -132,6 +132,7 @@ export const ZCreateDocumentMutationSchema = z.object({
redirectUrl: z.string(), redirectUrl: z.string(),
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(), signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(), language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(),
typedSignatureEnabled: z.boolean().optional().default(true),
}) })
.partial(), .partial(),
authOptions: z authOptions: z
@@ -226,14 +227,14 @@ export type TCreateDocumentFromTemplateMutationResponseSchema = z.infer<
export const ZGenerateDocumentFromTemplateMutationSchema = z.object({ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
title: z.string().optional(), title: z.string().optional(),
externalId: z.string().nullish(), externalId: z.string().optional(),
recipients: z recipients: z
.array( .array(
z.object({ z.object({
id: z.number(), id: z.number(),
email: z.string().email(),
name: z.string().optional(), name: z.string().optional(),
email: z.string().email().min(1), signingOrder: z.number().optional(),
signingOrder: z.number().nullish(),
}), }),
) )
.refine( .refine(
@@ -252,8 +253,10 @@ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
timezone: z.string(), timezone: z.string(),
dateFormat: z.string(), dateFormat: z.string(),
redirectUrl: ZUrlSchema, redirectUrl: ZUrlSchema,
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(), signingOrder: z.nativeEnum(DocumentSigningOrder),
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(), language: z.enum(SUPPORTED_LANGUAGE_CODES),
distributionMethod: z.nativeEnum(DocumentDistributionMethod),
typedSignatureEnabled: z.boolean(),
}) })
.partial() .partial()
.optional(), .optional(),

View File

@@ -0,0 +1,271 @@
import { expect, test } from '@playwright/test';
import { PDFDocument } from 'pdf-lib';
import { getDocumentByToken } from '@documenso/lib/server-only/document/get-document-by-token';
import { getFile } from '@documenso/lib/universal/upload/get-file';
import { prisma } from '@documenso/prisma';
import { DocumentStatus, FieldType } from '@documenso/prisma/client';
import { seedPendingDocumentWithFullFields } from '@documenso/prisma/seed/documents';
import { seedTeam } from '@documenso/prisma/seed/teams';
import { seedUser } from '@documenso/prisma/seed/users';
import { apiSignin } from '../fixtures/authentication';
test.describe('Signing Certificate Tests', () => {
test('individual document should always include signing certificate', async ({ page }) => {
const user = await seedUser();
const { document, recipients } = await seedPendingDocumentWithFullFields({
owner: user,
recipients: ['signer@example.com'],
fields: [FieldType.SIGNATURE],
});
const documentData = await prisma.documentData
.findFirstOrThrow({
where: {
id: document.documentDataId,
},
})
.then(async (data) => getFile(data));
const originalPdf = await PDFDocument.load(documentData);
const recipient = recipients[0];
// Sign the document
await page.goto(`/sign/${recipient.token}`);
const canvas = page.locator('canvas');
const box = await canvas.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + box.width / 4, box.y + box.height / 4);
await page.mouse.up();
}
for (const field of recipient.Field) {
await page.locator(`#field-${field.id}`).getByRole('button').click();
await expect(page.locator(`#field-${field.id}`)).toHaveAttribute('data-inserted', 'true');
}
await page.getByRole('button', { name: 'Complete' }).click();
await page.getByRole('button', { name: 'Sign' }).click();
await page.waitForURL(`/sign/${recipient.token}/complete`);
await expect(async () => {
const { status } = await getDocumentByToken({
token: recipient.token,
});
expect(status).toBe(DocumentStatus.COMPLETED);
}).toPass();
// Get the completed document
const completedDocument = await prisma.document.findFirstOrThrow({
where: { id: document.id },
include: { documentData: true },
});
const completedDocumentData = await getFile(completedDocument.documentData);
// Load the PDF and check number of pages
const pdfDoc = await PDFDocument.load(completedDocumentData);
expect(pdfDoc.getPageCount()).toBe(originalPdf.getPageCount() + 1); // Original + Certificate
});
test('team document with signing certificate enabled should include certificate', async ({
page,
}) => {
const team = await seedTeam();
const { document, recipients } = await seedPendingDocumentWithFullFields({
owner: team.owner,
recipients: ['signer@example.com'],
fields: [FieldType.SIGNATURE],
updateDocumentOptions: {
teamId: team.id,
},
});
await prisma.teamGlobalSettings.create({
data: {
teamId: team.id,
includeSigningCertificate: true,
},
});
const documentData = await prisma.documentData
.findFirstOrThrow({
where: {
id: document.documentDataId,
},
})
.then(async (data) => getFile(data));
const originalPdf = await PDFDocument.load(documentData);
const recipient = recipients[0];
// Sign the document
await page.goto(`/sign/${recipient.token}`);
const canvas = page.locator('canvas');
const box = await canvas.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + box.width / 4, box.y + box.height / 4);
await page.mouse.up();
}
for (const field of recipient.Field) {
await page.locator(`#field-${field.id}`).getByRole('button').click();
await expect(page.locator(`#field-${field.id}`)).toHaveAttribute('data-inserted', 'true');
}
await page.getByRole('button', { name: 'Complete' }).click();
await page.getByRole('button', { name: 'Sign' }).click();
await page.waitForURL(`/sign/${recipient.token}/complete`);
await expect(async () => {
const { status } = await getDocumentByToken({
token: recipient.token,
});
expect(status).toBe(DocumentStatus.COMPLETED);
}).toPass();
// Get the completed document
const completedDocument = await prisma.document.findFirstOrThrow({
where: { id: document.id },
include: { documentData: true },
});
const completedDocumentData = await getFile(completedDocument.documentData);
// Load the PDF and check number of pages
const completedPdf = await PDFDocument.load(completedDocumentData);
expect(completedPdf.getPageCount()).toBe(originalPdf.getPageCount() + 1); // Original + Certificate
});
test('team document with signing certificate disabled should not include certificate', async ({
page,
}) => {
const team = await seedTeam();
const { document, recipients } = await seedPendingDocumentWithFullFields({
owner: team.owner,
recipients: ['signer@example.com'],
fields: [FieldType.SIGNATURE],
updateDocumentOptions: {
teamId: team.id,
},
});
await prisma.teamGlobalSettings.create({
data: {
teamId: team.id,
includeSigningCertificate: false,
},
});
const documentData = await prisma.documentData
.findFirstOrThrow({
where: {
id: document.documentDataId,
},
})
.then(async (data) => getFile(data));
const originalPdf = await PDFDocument.load(documentData);
const recipient = recipients[0];
// Sign the document
await page.goto(`/sign/${recipient.token}`);
const canvas = page.locator('canvas');
const box = await canvas.boundingBox();
if (box) {
await page.mouse.move(box.x + box.width / 2, box.y + box.height / 2);
await page.mouse.down();
await page.mouse.move(box.x + box.width / 4, box.y + box.height / 4);
await page.mouse.up();
}
for (const field of recipient.Field) {
await page.locator(`#field-${field.id}`).getByRole('button').click();
await expect(page.locator(`#field-${field.id}`)).toHaveAttribute('data-inserted', 'true');
}
await page.getByRole('button', { name: 'Complete' }).click();
await page.getByRole('button', { name: 'Sign' }).click();
await page.waitForURL(`/sign/${recipient.token}/complete`);
await expect(async () => {
const { status } = await getDocumentByToken({
token: recipient.token,
});
expect(status).toBe(DocumentStatus.COMPLETED);
}).toPass();
// Get the completed document
const completedDocument = await prisma.document.findFirstOrThrow({
where: { id: document.id },
include: { documentData: true },
});
const completedDocumentData = await getFile(completedDocument.documentData);
// Load the PDF and check number of pages
const completedPdf = await PDFDocument.load(completedDocumentData);
expect(completedPdf.getPageCount()).toBe(originalPdf.getPageCount());
});
test('team can toggle signing certificate setting', async ({ page }) => {
const team = await seedTeam();
await apiSignin({
page,
email: team.owner.email,
redirectPath: `/t/${team.url}/settings/preferences`,
});
// Toggle signing certificate setting
await page.getByLabel('Include the Signing Certificate in the Document').click();
await page.getByRole('button', { name: /Save/ }).first().click();
await page.waitForTimeout(1000);
// Verify the setting was saved
const updatedTeam = await prisma.team.findFirstOrThrow({
where: { id: team.id },
include: { teamGlobalSettings: true },
});
expect(updatedTeam.teamGlobalSettings?.includeSigningCertificate).toBe(false);
// Toggle the setting back to true
await page.getByLabel('Include the Signing Certificate in the Document').click();
await page.getByRole('button', { name: /Save/ }).first().click();
await page.waitForTimeout(1000);
// Verify the setting was saved
const updatedTeam2 = await prisma.team.findFirstOrThrow({
where: { id: team.id },
include: { teamGlobalSettings: true },
});
expect(updatedTeam2.teamGlobalSettings?.includeSigningCertificate).toBe(true);
});
});

View File

@@ -17,19 +17,17 @@ test('[TEAMS]: update the default document visibility in the team global setting
page, page,
email: team.owner.email, email: team.owner.email,
password: 'password', password: 'password',
redirectPath: `/t/${team.url}/settings`, redirectPath: `/t/${team.url}/settings/preferences`,
}); });
await page.getByRole('combobox').click(); // !: Brittle selector
await page.getByRole('combobox').first().click();
await page.getByRole('option', { name: 'Admin' }).click(); await page.getByRole('option', { name: 'Admin' }).click();
await page.getByRole('button', { name: 'Update team' }).click(); await page.getByRole('button', { name: 'Save' }).first().click();
const toast = page.locator('li[role="status"][data-state="open"]').first(); const toast = page.locator('li[role="status"][data-state="open"]').first();
await expect(toast).toBeVisible(); await expect(toast).toBeVisible();
await expect(toast.getByText('Success', { exact: true })).toBeVisible(); await expect(toast.getByText('Document preferences updated', { exact: true })).toBeVisible();
await expect(
toast.getByText('Your team has been successfully updated.', { exact: true }),
).toBeVisible();
}); });
test('[TEAMS]: update the sender details in the team global settings', async ({ page }) => { test('[TEAMS]: update the sender details in the team global settings', async ({ page }) => {
@@ -41,7 +39,7 @@ test('[TEAMS]: update the sender details in the team global settings', async ({
page, page,
email: team.owner.email, email: team.owner.email,
password: 'password', password: 'password',
redirectPath: `/t/${team.url}/settings`, redirectPath: `/t/${team.url}/settings/preferences`,
}); });
const checkbox = page.getByLabel('Send on Behalf of Team'); const checkbox = page.getByLabel('Send on Behalf of Team');
@@ -49,14 +47,11 @@ test('[TEAMS]: update the sender details in the team global settings', async ({
await expect(checkbox).toBeChecked(); await expect(checkbox).toBeChecked();
await page.getByRole('button', { name: 'Update team' }).click(); await page.getByRole('button', { name: 'Save' }).first().click();
const toast = page.locator('li[role="status"][data-state="open"]').first(); const toast = page.locator('li[role="status"][data-state="open"]').first();
await expect(toast).toBeVisible(); await expect(toast).toBeVisible();
await expect(toast.getByText('Success', { exact: true })).toBeVisible(); await expect(toast.getByText('Document preferences updated', { exact: true })).toBeVisible();
await expect(
toast.getByText('Your team has been successfully updated.', { exact: true }),
).toBeVisible();
await expect(checkbox).toBeChecked(); await expect(checkbox).toBeChecked();
}); });

View File

@@ -7,15 +7,17 @@
"scripts": { "scripts": {
"test:dev": "NODE_OPTIONS=--experimental-require-module playwright test", "test:dev": "NODE_OPTIONS=--experimental-require-module playwright test",
"test-ui:dev": "NODE_OPTIONS=--experimental-require-module playwright test --ui", "test-ui:dev": "NODE_OPTIONS=--experimental-require-module playwright test --ui",
"test:e2e": "NODE_OPTIONS=--experimental-require-module start-server-and-test \"npm run start -w @documenso/web\" http://localhost:3000 \"playwright test\"" "test:e2e": "NODE_OPTIONS=--experimental-require-module start-server-and-test \"npm run start -w @documenso/web\" http://localhost:3000 \"playwright test $E2E_TEST_PATH\""
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"devDependencies": { "devDependencies": {
"@playwright/test": "^1.18.1", "@playwright/test": "^1.18.1",
"@types/node": "^20.8.2", "@types/node": "^20.8.2",
"@documenso/lib": "*",
"@documenso/prisma": "*", "@documenso/prisma": "*",
"@documenso/web": "*" "@documenso/web": "*",
"pdf-lib": "^1.17.1"
}, },
"dependencies": { "dependencies": {
"start-server-and-test": "^2.0.1" "start-server-and-test": "^2.0.1"

View File

@@ -9,6 +9,7 @@ export const getDocumentRelatedPrices = async () => {
return await getPricesByPlan([ return await getPricesByPlan([
STRIPE_PLAN_TYPE.REGULAR, STRIPE_PLAN_TYPE.REGULAR,
STRIPE_PLAN_TYPE.COMMUNITY, STRIPE_PLAN_TYPE.COMMUNITY,
STRIPE_PLAN_TYPE.PLATFORM,
STRIPE_PLAN_TYPE.ENTERPRISE, STRIPE_PLAN_TYPE.ENTERPRISE,
]); ]);
}; };

View File

@@ -0,0 +1,13 @@
import { STRIPE_PLAN_TYPE } from '@documenso/lib/constants/billing';
import { getPricesByPlan } from './get-prices-by-plan';
export const getPlatformPlanPrices = async () => {
return await getPricesByPlan(STRIPE_PLAN_TYPE.PLATFORM);
};
export const getPlatformPlanPriceIds = async () => {
const prices = await getPlatformPlanPrices();
return prices.map((price) => price.id);
};

View File

@@ -9,6 +9,7 @@ export const getPrimaryAccountPlanPrices = async () => {
return await getPricesByPlan([ return await getPricesByPlan([
STRIPE_PLAN_TYPE.REGULAR, STRIPE_PLAN_TYPE.REGULAR,
STRIPE_PLAN_TYPE.COMMUNITY, STRIPE_PLAN_TYPE.COMMUNITY,
STRIPE_PLAN_TYPE.PLATFORM,
STRIPE_PLAN_TYPE.ENTERPRISE, STRIPE_PLAN_TYPE.ENTERPRISE,
]); ]);
}; };

View File

@@ -6,7 +6,11 @@ import { getPricesByPlan } from './get-prices-by-plan';
* Returns the Stripe prices of items that affect the amount of teams a user can create. * Returns the Stripe prices of items that affect the amount of teams a user can create.
*/ */
export const getTeamRelatedPrices = async () => { export const getTeamRelatedPrices = async () => {
return await getPricesByPlan([STRIPE_PLAN_TYPE.COMMUNITY, STRIPE_PLAN_TYPE.ENTERPRISE]); return await getPricesByPlan([
STRIPE_PLAN_TYPE.COMMUNITY,
STRIPE_PLAN_TYPE.PLATFORM,
STRIPE_PLAN_TYPE.ENTERPRISE,
]);
}; };
/** /**

View File

@@ -0,0 +1,61 @@
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
import { subscriptionsContainsActivePlan } from '@documenso/lib/utils/billing';
import { prisma } from '@documenso/prisma';
import type { Document, Subscription } from '@documenso/prisma/client';
import { getPlatformPlanPriceIds } from '../stripe/get-platform-plan-prices';
export type IsDocumentPlatformOptions = Pick<Document, 'id' | 'userId' | 'teamId'>;
/**
* Whether the user is platform, or has permission to use platform features on
* behalf of their team.
*
* It is assumed that the provided user is part of the provided team.
*/
export const isDocumentPlatform = async ({
userId,
teamId,
}: IsDocumentPlatformOptions): Promise<boolean> => {
let subscriptions: Subscription[] = [];
if (!IS_BILLING_ENABLED()) {
return true;
}
if (teamId) {
subscriptions = await prisma.team
.findFirstOrThrow({
where: {
id: teamId,
},
select: {
owner: {
include: {
Subscription: true,
},
},
},
})
.then((team) => team.owner.Subscription);
} else {
subscriptions = await prisma.user
.findFirstOrThrow({
where: {
id: userId,
},
select: {
Subscription: true,
},
})
.then((user) => user.Subscription);
}
if (subscriptions.length === 0) {
return false;
}
const platformPlanPriceIds = await getPlatformPlanPriceIds();
return subscriptionsContainsActivePlan(subscriptions, platformPlanPriceIds);
};

View File

@@ -7,5 +7,6 @@ export enum STRIPE_PLAN_TYPE {
REGULAR = 'regular', REGULAR = 'regular',
TEAM = 'team', TEAM = 'team',
COMMUNITY = 'community', COMMUNITY = 'community',
PLATFORM = 'platform',
ENTERPRISE = 'enterprise', ENTERPRISE = 'enterprise',
} }

View File

@@ -17,12 +17,14 @@ const SEND_TEAM_DELETED_EMAIL_JOB_DEFINITION_SCHEMA = z.object({
documentVisibility: z.nativeEnum(DocumentVisibility), documentVisibility: z.nativeEnum(DocumentVisibility),
documentLanguage: z.string(), documentLanguage: z.string(),
includeSenderDetails: z.boolean(), includeSenderDetails: z.boolean(),
includeSigningCertificate: z.boolean(),
brandingEnabled: z.boolean(), brandingEnabled: z.boolean(),
brandingLogo: z.string(), brandingLogo: z.string(),
brandingUrl: z.string(), brandingUrl: z.string(),
brandingCompanyDetails: z.string(), brandingCompanyDetails: z.string(),
brandingHidePoweredBy: z.boolean(), brandingHidePoweredBy: z.boolean(),
teamId: z.number(), teamId: z.number(),
typedSignatureEnabled: z.boolean(),
}) })
.nullish(), .nullish(),
}), }),

View File

@@ -57,7 +57,17 @@ export const SEAL_DOCUMENT_JOB_DEFINITION = {
}, },
}, },
include: { include: {
documentMeta: true,
Recipient: true, Recipient: true,
team: {
select: {
teamGlobalSettings: {
select: {
includeSigningCertificate: true,
},
},
},
},
}, },
}); });
@@ -117,7 +127,13 @@ export const SEAL_DOCUMENT_JOB_DEFINITION = {
} }
const pdfData = await getFile(documentData); const pdfData = await getFile(documentData);
const certificateData = await getCertificatePdf({ documentId }).catch(() => null); const certificateData =
document.team?.teamGlobalSettings?.includeSigningCertificate ?? true
? await getCertificatePdf({
documentId,
language: document.documentMeta?.language,
}).catch(() => null)
: null;
const newDataId = await io.runTask('decorate-and-sign-pdf', async () => { const newDataId = await io.runTask('decorate-and-sign-pdf', async () => {
const pdfDoc = await PDFDocument.load(pdfData); const pdfDoc = await PDFDocument.load(pdfData);

View File

@@ -51,7 +51,7 @@
"pg": "^8.11.3", "pg": "^8.11.3",
"playwright": "1.43.0", "playwright": "1.43.0",
"react": "^18", "react": "^18",
"remeda": "^2.12.1", "remeda": "^2.17.3",
"sharp": "0.32.6", "sharp": "0.32.6",
"stripe": "^12.7.0", "stripe": "^12.7.0",
"ts-pattern": "^5.0.5", "ts-pattern": "^5.0.5",

View File

@@ -112,6 +112,7 @@ export const createDocument = async ({
documentMeta: { documentMeta: {
create: { create: {
language: team?.teamGlobalSettings?.documentLanguage, language: team?.teamGlobalSettings?.documentLanguage,
typedSignatureEnabled: team?.teamGlobalSettings?.typedSignatureEnabled,
}, },
}, },
}, },

View File

@@ -10,7 +10,6 @@ import { DocumentStatus, RecipientRole, SigningStatus } from '@documenso/prisma/
import { WebhookTriggerEvents } from '@documenso/prisma/client'; import { WebhookTriggerEvents } from '@documenso/prisma/client';
import { signPdf } from '@documenso/signing'; import { signPdf } from '@documenso/signing';
import { ZSupportedLanguageCodeSchema } from '../../constants/i18n';
import type { RequestMetadata } from '../../universal/extract-request-metadata'; import type { RequestMetadata } from '../../universal/extract-request-metadata';
import { getFile } from '../../universal/upload/get-file'; import { getFile } from '../../universal/upload/get-file';
import { putPdfFile } from '../../universal/upload/put-file'; import { putPdfFile } from '../../universal/upload/put-file';
@@ -48,6 +47,15 @@ export const sealDocument = async ({
documentData: true, documentData: true,
documentMeta: true, documentMeta: true,
Recipient: true, Recipient: true,
team: {
select: {
teamGlobalSettings: {
select: {
includeSigningCertificate: true,
},
},
},
},
}, },
}); });
@@ -92,11 +100,13 @@ export const sealDocument = async ({
// !: Need to write the fields onto the document as a hard copy // !: Need to write the fields onto the document as a hard copy
const pdfData = await getFile(documentData); const pdfData = await getFile(documentData);
const documentLanguage = ZSupportedLanguageCodeSchema.parse(document.documentMeta?.language); const certificateData =
document.team?.teamGlobalSettings?.includeSigningCertificate ?? true
const certificate = await getCertificatePdf({ documentId, language: documentLanguage }) ? await getCertificatePdf({
.then(async (doc) => PDFDocument.load(doc)) documentId,
.catch(() => null); language: document.documentMeta?.language,
}).catch(() => null)
: null;
const doc = await PDFDocument.load(pdfData); const doc = await PDFDocument.load(pdfData);
@@ -105,7 +115,9 @@ export const sealDocument = async ({
flattenForm(doc); flattenForm(doc);
flattenAnnotations(doc); flattenAnnotations(doc);
if (certificate) { if (certificateData) {
const certificate = await PDFDocument.load(certificateData);
const certificatePages = await doc.copyPages(certificate, certificate.getPageIndices()); const certificatePages = await doc.copyPages(certificate, certificate.getPageIndices());
certificatePages.forEach((page) => { certificatePages.forEach((page) => {

View File

@@ -177,6 +177,10 @@ export const signFieldWithToken = async ({
throw new Error('Signature field must have a signature'); throw new Error('Signature field must have a signature');
} }
if (isSignatureField && !documentMeta?.typedSignatureEnabled && typedSignature) {
throw new Error('Typed signatures are not allowed. Please draw your signature');
}
return await prisma.$transaction(async (tx) => { return await prisma.$transaction(async (tx) => {
const updatedField = await tx.field.update({ const updatedField = await tx.field.update({
where: { where: {

View File

@@ -2,12 +2,13 @@ import { DateTime } from 'luxon';
import type { Browser } from 'playwright'; import type { Browser } from 'playwright';
import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app'; import { NEXT_PUBLIC_WEBAPP_URL } from '../../constants/app';
import type { SupportedLanguageCodes } from '../../constants/i18n'; import { type SupportedLanguageCodes, isValidLanguageCode } from '../../constants/i18n';
import { encryptSecondaryData } from '../crypto/encrypt'; import { encryptSecondaryData } from '../crypto/encrypt';
export type GetCertificatePdfOptions = { export type GetCertificatePdfOptions = {
documentId: number; documentId: number;
language?: SupportedLanguageCodes; // eslint-disable-next-line @typescript-eslint/ban-types
language?: SupportedLanguageCodes | (string & {});
}; };
export const getCertificatePdf = async ({ documentId, language }: GetCertificatePdfOptions) => { export const getCertificatePdf = async ({ documentId, language }: GetCertificatePdfOptions) => {
@@ -38,15 +39,15 @@ export const getCertificatePdf = async ({ documentId, language }: GetCertificate
const page = await browserContext.newPage(); const page = await browserContext.newPage();
if (language) { const lang = isValidLanguageCode(language) ? language : 'en';
await page.context().addCookies([
{ await page.context().addCookies([
name: 'language', {
value: language, name: 'language',
url: NEXT_PUBLIC_WEBAPP_URL(), value: lang,
}, url: NEXT_PUBLIC_WEBAPP_URL(),
]); },
} ]);
await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/__htmltopdf/certificate?d=${encryptedId}`, { await page.goto(`${NEXT_PUBLIC_WEBAPP_URL()}/__htmltopdf/certificate?d=${encryptedId}`, {
waitUntil: 'networkidle', waitUntil: 'networkidle',

View File

@@ -82,7 +82,10 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu
const fieldX = pageWidth * (Number(field.positionX) / 100); const fieldX = pageWidth * (Number(field.positionX) / 100);
const fieldY = pageHeight * (Number(field.positionY) / 100); const fieldY = pageHeight * (Number(field.positionY) / 100);
const font = await pdf.embedFont(isSignatureField ? fontCaveat : fontNoto); const font = await pdf.embedFont(
isSignatureField ? fontCaveat : fontNoto,
isSignatureField ? { features: { calt: false } } : undefined,
);
if (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) { if (field.type === FieldType.SIGNATURE || field.type === FieldType.FREE_SIGNATURE) {
await pdf.embedFont(fontCaveat); await pdf.embedFont(fontCaveat);
@@ -92,45 +95,89 @@ export const insertFieldInPDF = async (pdf: PDFDocument, field: FieldWithSignatu
.with( .with(
{ {
type: P.union(FieldType.SIGNATURE, FieldType.FREE_SIGNATURE), type: P.union(FieldType.SIGNATURE, FieldType.FREE_SIGNATURE),
Signature: { signatureImageAsBase64: P.string },
}, },
async (field) => { async (field) => {
const image = await pdf.embedPng(field.Signature?.signatureImageAsBase64 ?? ''); if (field.Signature?.signatureImageAsBase64) {
const image = await pdf.embedPng(field.Signature?.signatureImageAsBase64 ?? '');
let imageWidth = image.width; let imageWidth = image.width;
let imageHeight = image.height; let imageHeight = image.height;
const scalingFactor = Math.min(fieldWidth / imageWidth, fieldHeight / imageHeight, 1); const scalingFactor = Math.min(fieldWidth / imageWidth, fieldHeight / imageHeight, 1);
imageWidth = imageWidth * scalingFactor; imageWidth = imageWidth * scalingFactor;
imageHeight = imageHeight * scalingFactor; imageHeight = imageHeight * scalingFactor;
let imageX = fieldX + (fieldWidth - imageWidth) / 2; let imageX = fieldX + (fieldWidth - imageWidth) / 2;
let imageY = fieldY + (fieldHeight - imageHeight) / 2; let imageY = fieldY + (fieldHeight - imageHeight) / 2;
// Invert the Y axis since PDFs use a bottom-left coordinate system // Invert the Y axis since PDFs use a bottom-left coordinate system
imageY = pageHeight - imageY - imageHeight; imageY = pageHeight - imageY - imageHeight;
if (pageRotationInDegrees !== 0) { if (pageRotationInDegrees !== 0) {
const adjustedPosition = adjustPositionForRotation( const adjustedPosition = adjustPositionForRotation(
pageWidth, pageWidth,
pageHeight, pageHeight,
imageX, imageX,
imageY, imageY,
pageRotationInDegrees, pageRotationInDegrees,
); );
imageX = adjustedPosition.xPos; imageX = adjustedPosition.xPos;
imageY = adjustedPosition.yPos; imageY = adjustedPosition.yPos;
}
page.drawImage(image, {
x: imageX,
y: imageY,
width: imageWidth,
height: imageHeight,
rotate: degrees(pageRotationInDegrees),
});
} else {
const signatureText = field.Signature?.typedSignature ?? '';
const longestLineInTextForWidth = signatureText
.split('\n')
.sort((a, b) => b.length - a.length)[0];
let fontSize = maxFontSize;
let textWidth = font.widthOfTextAtSize(longestLineInTextForWidth, fontSize);
let textHeight = font.heightAtSize(fontSize);
const scalingFactor = Math.min(fieldWidth / textWidth, fieldHeight / textHeight, 1);
fontSize = Math.max(Math.min(fontSize * scalingFactor, maxFontSize), minFontSize);
textWidth = font.widthOfTextAtSize(longestLineInTextForWidth, fontSize);
textHeight = font.heightAtSize(fontSize);
let textX = fieldX + (fieldWidth - textWidth) / 2;
let textY = fieldY + (fieldHeight - textHeight) / 2;
// Invert the Y axis since PDFs use a bottom-left coordinate system
textY = pageHeight - textY - textHeight;
if (pageRotationInDegrees !== 0) {
const adjustedPosition = adjustPositionForRotation(
pageWidth,
pageHeight,
textX,
textY,
pageRotationInDegrees,
);
textX = adjustedPosition.xPos;
textY = adjustedPosition.yPos;
}
page.drawText(signatureText, {
x: textX,
y: textY,
size: fontSize,
font,
rotate: degrees(pageRotationInDegrees),
});
} }
page.drawImage(image, {
x: imageX,
y: imageY,
width: imageWidth,
height: imageHeight,
rotate: degrees(pageRotationInDegrees),
});
}, },
) )
.with({ type: FieldType.CHECKBOX }, (field) => { .with({ type: FieldType.CHECKBOX }, (field) => {

View File

@@ -12,6 +12,8 @@ export type UpdateTeamDocumentSettingsOptions = {
documentVisibility: DocumentVisibility; documentVisibility: DocumentVisibility;
documentLanguage: SupportedLanguageCodes; documentLanguage: SupportedLanguageCodes;
includeSenderDetails: boolean; includeSenderDetails: boolean;
typedSignatureEnabled: boolean;
includeSigningCertificate: boolean;
}; };
}; };
@@ -20,7 +22,13 @@ export const updateTeamDocumentSettings = async ({
teamId, teamId,
settings, settings,
}: UpdateTeamDocumentSettingsOptions) => { }: UpdateTeamDocumentSettingsOptions) => {
const { documentVisibility, documentLanguage, includeSenderDetails } = settings; const {
documentVisibility,
documentLanguage,
includeSenderDetails,
includeSigningCertificate,
typedSignatureEnabled,
} = settings;
const member = await prisma.teamMember.findFirst({ const member = await prisma.teamMember.findFirst({
where: { where: {
@@ -42,11 +50,15 @@ export const updateTeamDocumentSettings = async ({
documentVisibility, documentVisibility,
documentLanguage, documentLanguage,
includeSenderDetails, includeSenderDetails,
typedSignatureEnabled,
includeSigningCertificate,
}, },
update: { update: {
documentVisibility, documentVisibility,
documentLanguage, documentLanguage,
includeSenderDetails, includeSenderDetails,
typedSignatureEnabled,
includeSigningCertificate,
}, },
}); });
}; };

View File

@@ -4,7 +4,6 @@ import { TEAM_MEMBER_ROLE_PERMISSIONS_MAP } from '@documenso/lib/constants/teams
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import { Prisma } from '@documenso/prisma/client'; import { Prisma } from '@documenso/prisma/client';
import type { DocumentVisibility } from '@documenso/prisma/client';
export type UpdateTeamOptions = { export type UpdateTeamOptions = {
userId: number; userId: number;
@@ -12,8 +11,6 @@ export type UpdateTeamOptions = {
data: { data: {
name?: string; name?: string;
url?: string; url?: string;
documentVisibility?: DocumentVisibility;
includeSenderDetails?: boolean;
}; };
}; };
@@ -45,18 +42,6 @@ export const updateTeam = async ({ userId, teamId, data }: UpdateTeamOptions) =>
data: { data: {
url: data.url, url: data.url,
name: data.name, name: data.name,
teamGlobalSettings: {
upsert: {
create: {
documentVisibility: data.documentVisibility,
includeSenderDetails: data.includeSenderDetails,
},
update: {
documentVisibility: data.documentVisibility,
includeSenderDetails: data.includeSenderDetails,
},
},
},
}, },
}); });

View File

@@ -64,6 +64,7 @@ export type CreateDocumentFromTemplateOptions = {
signingOrder?: DocumentSigningOrder; signingOrder?: DocumentSigningOrder;
language?: SupportedLanguageCodes; language?: SupportedLanguageCodes;
distributionMethod?: DocumentDistributionMethod; distributionMethod?: DocumentDistributionMethod;
typedSignatureEnabled?: boolean;
}; };
requestMetadata?: RequestMetadata; requestMetadata?: RequestMetadata;
}; };
@@ -146,7 +147,7 @@ export const createDocumentFromTemplate = async ({
return { return {
templateRecipientId: templateRecipient.id, templateRecipientId: templateRecipient.id,
fields: templateRecipient.Field, fields: templateRecipient.Field,
name: foundRecipient ? foundRecipient.name ?? '' : templateRecipient.name, name: foundRecipient ? (foundRecipient.name ?? '') : templateRecipient.name,
email: foundRecipient ? foundRecipient.email : templateRecipient.email, email: foundRecipient ? foundRecipient.email : templateRecipient.email,
role: templateRecipient.role, role: templateRecipient.role,
signingOrder: foundRecipient?.signingOrder ?? templateRecipient.signingOrder, signingOrder: foundRecipient?.signingOrder ?? templateRecipient.signingOrder,
@@ -196,6 +197,8 @@ export const createDocumentFromTemplate = async ({
override?.language || override?.language ||
template.templateMeta?.language || template.templateMeta?.language ||
template.team?.teamGlobalSettings?.documentLanguage, template.team?.teamGlobalSettings?.documentLanguage,
typedSignatureEnabled:
override?.typedSignatureEnabled ?? template.templateMeta?.typedSignatureEnabled,
}, },
}, },
Recipient: { Recipient: {

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n" "Language: de\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: German\n" "Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -414,11 +414,11 @@ msgstr "Weiteren Wert hinzufügen"
msgid "Add myself" msgid "Add myself"
msgstr "Mich selbst hinzufügen" msgstr "Mich selbst hinzufügen"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:637 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:645
msgid "Add Myself" msgid "Add Myself"
msgstr "Mich hinzufügen" msgstr "Mich hinzufügen"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:623 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:631
msgid "Add Placeholder Recipient" msgid "Add Placeholder Recipient"
msgstr "Platzhalterempfänger hinzufügen" msgstr "Platzhalterempfänger hinzufügen"
@@ -443,8 +443,8 @@ msgstr "Admin"
msgid "Advanced Options" msgid "Advanced Options"
msgstr "Erweiterte Optionen" msgstr "Erweiterte Optionen"
#: packages/ui/primitives/document-flow/add-fields.tsx:573 #: packages/ui/primitives/document-flow/add-fields.tsx:576
#: packages/ui/primitives/template-flow/add-template-fields.tsx:406 #: packages/ui/primitives/template-flow/add-template-fields.tsx:414
msgid "Advanced settings" msgid "Advanced settings"
msgstr "Erweiterte Einstellungen" msgstr "Erweiterte Einstellungen"
@@ -500,11 +500,11 @@ msgstr "Genehmigung"
msgid "Before you get started, please confirm your email address by clicking the button below:" msgid "Before you get started, please confirm your email address by clicking the button below:"
msgstr "Bitte bestätige vor dem Start deine E-Mail-Adresse, indem du auf den Button unten klickst:" msgstr "Bitte bestätige vor dem Start deine E-Mail-Adresse, indem du auf den Button unten klickst:"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:377 #: packages/ui/primitives/signature-pad/signature-pad.tsx:383
msgid "Black" msgid "Black"
msgstr "Schwarz" msgstr "Schwarz"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:391 #: packages/ui/primitives/signature-pad/signature-pad.tsx:397
msgid "Blue" msgid "Blue"
msgstr "Blau" msgstr "Blau"
@@ -550,6 +550,10 @@ msgstr "Ccers"
msgid "Character Limit" msgid "Character Limit"
msgstr "Zeichenbeschränkung" msgstr "Zeichenbeschränkung"
#: packages/ui/primitives/document-flow/types.ts:58
msgid "Checkbox"
msgstr "Checkbox"
#: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197 #: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197
msgid "Checkbox values" msgid "Checkbox values"
msgstr "Checkbox-Werte" msgstr "Checkbox-Werte"
@@ -558,7 +562,7 @@ msgstr "Checkbox-Werte"
msgid "Clear filters" msgid "Clear filters"
msgstr "Filter löschen" msgstr "Filter löschen"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:411 #: packages/ui/primitives/signature-pad/signature-pad.tsx:417
msgid "Clear Signature" msgid "Clear Signature"
msgstr "Unterschrift löschen" msgstr "Unterschrift löschen"
@@ -585,8 +589,8 @@ msgstr "Abgeschlossenes Dokument"
msgid "Configure Direct Recipient" msgid "Configure Direct Recipient"
msgstr "Direkten Empfänger konfigurieren" msgstr "Direkten Empfänger konfigurieren"
#: packages/ui/primitives/document-flow/add-fields.tsx:574 #: packages/ui/primitives/document-flow/add-fields.tsx:577
#: packages/ui/primitives/template-flow/add-template-fields.tsx:407 #: packages/ui/primitives/template-flow/add-template-fields.tsx:415
msgid "Configure the {0} field" msgid "Configure the {0} field"
msgstr "Konfigurieren Sie das Feld {0}" msgstr "Konfigurieren Sie das Feld {0}"
@@ -647,9 +651,9 @@ msgstr "Konto erstellen"
msgid "Custom Text" msgid "Custom Text"
msgstr "Benutzerdefinierter Text" msgstr "Benutzerdefinierter Text"
#: packages/ui/primitives/document-flow/add-fields.tsx:927 #: packages/ui/primitives/document-flow/add-fields.tsx:934
#: packages/ui/primitives/document-flow/types.ts:53 #: packages/ui/primitives/document-flow/types.ts:53
#: packages/ui/primitives/template-flow/add-template-fields.tsx:690 #: packages/ui/primitives/template-flow/add-template-fields.tsx:729
msgid "Date" msgid "Date"
msgstr "Datum" msgstr "Datum"
@@ -666,7 +670,7 @@ msgstr "Ablehnen"
msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>" msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>"
msgstr "Hast du keinen Passwortwechsel angefordert? Wir helfen dir, dein Konto abzusichern, kontaktiere uns einfach <0>hier.</0>" msgstr "Hast du keinen Passwortwechsel angefordert? Wir helfen dir, dein Konto abzusichern, kontaktiere uns einfach <0>hier.</0>"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:570 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:578
msgid "Direct link receiver" msgid "Direct link receiver"
msgstr "Empfänger des direkten Links" msgstr "Empfänger des direkten Links"
@@ -788,8 +792,8 @@ msgstr "Entwurf"
msgid "Drag & drop your PDF here." msgid "Drag & drop your PDF here."
msgstr "Ziehen Sie Ihr PDF hierher." msgstr "Ziehen Sie Ihr PDF hierher."
#: packages/ui/primitives/document-flow/add-fields.tsx:1058 #: packages/ui/primitives/document-flow/add-fields.tsx:1065
#: packages/ui/primitives/template-flow/add-template-fields.tsx:820 #: packages/ui/primitives/template-flow/add-template-fields.tsx:860
msgid "Dropdown" msgid "Dropdown"
msgstr "Dropdown" msgstr "Dropdown"
@@ -798,14 +802,14 @@ msgid "Dropdown options"
msgstr "Dropdown-Optionen" msgstr "Dropdown-Optionen"
#: packages/lib/constants/document.ts:28 #: packages/lib/constants/document.ts:28
#: packages/ui/primitives/document-flow/add-fields.tsx:875 #: packages/ui/primitives/document-flow/add-fields.tsx:882
#: packages/ui/primitives/document-flow/add-signature.tsx:272 #: packages/ui/primitives/document-flow/add-signature.tsx:272
#: packages/ui/primitives/document-flow/add-signers.tsx:512 #: packages/ui/primitives/document-flow/add-signers.tsx:512
#: packages/ui/primitives/document-flow/add-signers.tsx:519 #: packages/ui/primitives/document-flow/add-signers.tsx:519
#: packages/ui/primitives/document-flow/types.ts:54 #: packages/ui/primitives/document-flow/types.ts:54
#: packages/ui/primitives/template-flow/add-template-fields.tsx:638 #: packages/ui/primitives/template-flow/add-template-fields.tsx:677
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:463 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:471
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:470 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:478
msgid "Email" msgid "Email"
msgstr "E-Mail" msgstr "E-Mail"
@@ -825,7 +829,7 @@ msgstr "E-Mail erneut gesendet"
msgid "Email sent" msgid "Email sent"
msgstr "E-Mail gesendet" msgstr "E-Mail gesendet"
#: packages/ui/primitives/document-flow/add-fields.tsx:1123 #: packages/ui/primitives/document-flow/add-fields.tsx:1130
msgid "Empty field" msgid "Empty field"
msgstr "Leeres Feld" msgstr "Leeres Feld"
@@ -834,11 +838,12 @@ msgid "Enable Direct Link Signing"
msgstr "Direktlink-Signierung aktivieren" msgstr "Direktlink-Signierung aktivieren"
#: packages/ui/primitives/document-flow/add-signers.tsx:401 #: packages/ui/primitives/document-flow/add-signers.tsx:401
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:362 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:370
msgid "Enable signing order" msgid "Enable signing order"
msgstr "Aktiviere die Signaturreihenfolge" msgstr "Aktiviere die Signaturreihenfolge"
#: packages/ui/primitives/document-flow/add-fields.tsx:795 #: packages/ui/primitives/document-flow/add-fields.tsx:802
#: packages/ui/primitives/template-flow/add-template-fields.tsx:597
msgid "Enable Typed Signatures" msgid "Enable Typed Signatures"
msgstr "Aktivieren Sie getippte Unterschriften" msgstr "Aktivieren Sie getippte Unterschriften"
@@ -926,7 +931,7 @@ msgstr "Globale Empfängerauthentifizierung"
msgid "Go Back" msgid "Go Back"
msgstr "Zurück" msgstr "Zurück"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:398 #: packages/ui/primitives/signature-pad/signature-pad.tsx:404
msgid "Green" msgid "Green"
msgstr "Grün" msgstr "Grün"
@@ -1016,14 +1021,14 @@ msgstr "Nachricht <0>(Optional)</0>"
msgid "Min" msgid "Min"
msgstr "Min" msgstr "Min"
#: packages/ui/primitives/document-flow/add-fields.tsx:901 #: packages/ui/primitives/document-flow/add-fields.tsx:908
#: packages/ui/primitives/document-flow/add-signature.tsx:298 #: packages/ui/primitives/document-flow/add-signature.tsx:298
#: packages/ui/primitives/document-flow/add-signers.tsx:550 #: packages/ui/primitives/document-flow/add-signers.tsx:550
#: packages/ui/primitives/document-flow/add-signers.tsx:556 #: packages/ui/primitives/document-flow/add-signers.tsx:556
#: packages/ui/primitives/document-flow/types.ts:55 #: packages/ui/primitives/document-flow/types.ts:55
#: packages/ui/primitives/template-flow/add-template-fields.tsx:664 #: packages/ui/primitives/template-flow/add-template-fields.tsx:703
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:498 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:506
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:504 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:512
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@@ -1039,8 +1044,8 @@ msgstr "Muss unterzeichnen"
msgid "Needs to view" msgid "Needs to view"
msgstr "Muss sehen" msgstr "Muss sehen"
#: packages/ui/primitives/document-flow/add-fields.tsx:686 #: packages/ui/primitives/document-flow/add-fields.tsx:693
#: packages/ui/primitives/template-flow/add-template-fields.tsx:504 #: packages/ui/primitives/template-flow/add-template-fields.tsx:516
msgid "No recipient matching this description was found." msgid "No recipient matching this description was found."
msgstr "Kein passender Empfänger mit dieser Beschreibung gefunden." msgstr "Kein passender Empfänger mit dieser Beschreibung gefunden."
@@ -1048,8 +1053,8 @@ msgstr "Kein passender Empfänger mit dieser Beschreibung gefunden."
msgid "No recipients" msgid "No recipients"
msgstr "Keine Empfänger" msgstr "Keine Empfänger"
#: packages/ui/primitives/document-flow/add-fields.tsx:701 #: packages/ui/primitives/document-flow/add-fields.tsx:708
#: packages/ui/primitives/template-flow/add-template-fields.tsx:519 #: packages/ui/primitives/template-flow/add-template-fields.tsx:531
msgid "No recipients with this role" msgid "No recipients with this role"
msgstr "Keine Empfänger mit dieser Rolle" msgstr "Keine Empfänger mit dieser Rolle"
@@ -1077,9 +1082,9 @@ msgstr "Kein Wert gefunden."
msgid "None" msgid "None"
msgstr "Keine" msgstr "Keine"
#: packages/ui/primitives/document-flow/add-fields.tsx:979 #: packages/ui/primitives/document-flow/add-fields.tsx:986
#: packages/ui/primitives/document-flow/types.ts:56 #: packages/ui/primitives/document-flow/types.ts:56
#: packages/ui/primitives/template-flow/add-template-fields.tsx:742 #: packages/ui/primitives/template-flow/add-template-fields.tsx:781
msgid "Number" msgid "Number"
msgstr "Nummer" msgstr "Nummer"
@@ -1170,7 +1175,7 @@ msgstr "Bitte bestätige deine E-Mail-Adresse"
msgid "Please try again or contact our support." msgid "Please try again or contact our support."
msgstr "Bitte versuchen Sie es erneut oder kontaktieren Sie unseren Support." msgstr "Bitte versuchen Sie es erneut oder kontaktieren Sie unseren Support."
#: packages/ui/primitives/template-flow/add-template-fields.tsx:768 #: packages/ui/primitives/document-flow/types.ts:57
msgid "Radio" msgid "Radio"
msgstr "Radio" msgstr "Radio"
@@ -1213,7 +1218,7 @@ msgstr "E-Mail des entfernten Empfängers"
msgid "Recipient signing request email" msgid "Recipient signing request email"
msgstr "E-Mail zur Unterzeichnungsanfrage des Empfängers" msgstr "E-Mail zur Unterzeichnungsanfrage des Empfängers"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:384 #: packages/ui/primitives/signature-pad/signature-pad.tsx:390
msgid "Red" msgid "Red"
msgstr "Rot" msgstr "Rot"
@@ -1250,7 +1255,7 @@ msgstr "Erinnerung: Bitte {recipientActionVerb} dieses Dokument"
msgid "Reminder: Please {recipientActionVerb} your document" msgid "Reminder: Please {recipientActionVerb} your document"
msgstr "Erinnerung: Bitte {recipientActionVerb} dein Dokument" msgstr "Erinnerung: Bitte {recipientActionVerb} dein Dokument"
#: packages/ui/primitives/document-flow/add-fields.tsx:1110 #: packages/ui/primitives/document-flow/add-fields.tsx:1117
msgid "Remove" msgid "Remove"
msgstr "Entfernen" msgstr "Entfernen"
@@ -1282,7 +1287,7 @@ msgstr "Zeilen pro Seite"
msgid "Save" msgid "Save"
msgstr "Speichern" msgstr "Speichern"
#: packages/ui/primitives/template-flow/add-template-fields.tsx:854 #: packages/ui/primitives/template-flow/add-template-fields.tsx:893
msgid "Save Template" msgid "Save Template"
msgstr "Vorlage speichern" msgstr "Vorlage speichern"
@@ -1291,6 +1296,7 @@ msgid "Search languages..."
msgstr "Sprachen suchen..." msgstr "Sprachen suchen..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115 #: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115
#: packages/ui/primitives/document-flow/types.ts:59
msgid "Select" msgid "Select"
msgstr "Auswählen" msgstr "Auswählen"
@@ -1354,7 +1360,7 @@ msgid "Share your signing experience!"
msgstr "Teilen Sie Ihre Unterzeichnungserfahrung!" msgstr "Teilen Sie Ihre Unterzeichnungserfahrung!"
#: packages/ui/primitives/document-flow/add-signers.tsx:709 #: packages/ui/primitives/document-flow/add-signers.tsx:709
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:655 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:663
msgid "Show advanced settings" msgid "Show advanced settings"
msgstr "Erweiterte Einstellungen anzeigen" msgstr "Erweiterte Einstellungen anzeigen"
@@ -1370,11 +1376,11 @@ msgstr "Dokument signieren"
msgid "Sign In" msgid "Sign In"
msgstr "Anmelden" msgstr "Anmelden"
#: packages/ui/primitives/document-flow/add-fields.tsx:823 #: packages/ui/primitives/document-flow/add-fields.tsx:830
#: packages/ui/primitives/document-flow/add-signature.tsx:323 #: packages/ui/primitives/document-flow/add-signature.tsx:323
#: packages/ui/primitives/document-flow/field-icon.tsx:52 #: packages/ui/primitives/document-flow/field-icon.tsx:52
#: packages/ui/primitives/document-flow/types.ts:49 #: packages/ui/primitives/document-flow/types.ts:49
#: packages/ui/primitives/template-flow/add-template-fields.tsx:586 #: packages/ui/primitives/template-flow/add-template-fields.tsx:625
msgid "Signature" msgid "Signature"
msgstr "Unterschrift" msgstr "Unterschrift"
@@ -1457,9 +1463,9 @@ msgstr "Team-E-Mail für {teamName} auf Documenso entfernt"
msgid "Template title" msgid "Template title"
msgstr "Vorlagentitel" msgstr "Vorlagentitel"
#: packages/ui/primitives/document-flow/add-fields.tsx:953 #: packages/ui/primitives/document-flow/add-fields.tsx:960
#: packages/ui/primitives/document-flow/types.ts:52 #: packages/ui/primitives/document-flow/types.ts:52
#: packages/ui/primitives/template-flow/add-template-fields.tsx:716 #: packages/ui/primitives/template-flow/add-template-fields.tsx:755
msgid "Text" msgid "Text"
msgstr "Text" msgstr "Text"
@@ -1554,7 +1560,7 @@ msgstr "Dies kann überschrieben werden, indem die Authentifizierungsanforderung
msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support."
msgstr "Dieses Dokument kann nicht wiederhergestellt werden. Wenn du den Grund für zukünftige Dokumente anfechten möchtest, kontaktiere bitte den Support." msgstr "Dieses Dokument kann nicht wiederhergestellt werden. Wenn du den Grund für zukünftige Dokumente anfechten möchtest, kontaktiere bitte den Support."
#: packages/ui/primitives/document-flow/add-fields.tsx:757 #: packages/ui/primitives/document-flow/add-fields.tsx:764
msgid "This document has already been sent to this recipient. You can no longer edit this recipient." msgid "This document has already been sent to this recipient. You can no longer edit this recipient."
msgstr "Dieses Dokument wurde bereits an diesen Empfänger gesendet. Sie können diesen Empfänger nicht mehr bearbeiten." msgstr "Dieses Dokument wurde bereits an diesen Empfänger gesendet. Sie können diesen Empfänger nicht mehr bearbeiten."
@@ -1585,7 +1591,7 @@ msgstr "Diese E-Mail wird an den Empfänger gesendet und fordert ihn auf, das Do
msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet." msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet."
msgstr "Diese E-Mail wird an den Empfänger gesendet, der das Dokument gerade unterschrieben hat, wenn es noch andere Empfänger gibt, die noch nicht unterschrieben haben." msgstr "Diese E-Mail wird an den Empfänger gesendet, der das Dokument gerade unterschrieben hat, wenn es noch andere Empfänger gibt, die noch nicht unterschrieben haben."
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:573 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:581
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
msgstr "Dieses Feld kann nicht geändert oder gelöscht werden. Wenn Sie den direkten Link dieser Vorlage teilen oder zu Ihrem öffentlichen Profil hinzufügen, kann jeder, der darauf zugreift, seinen Namen und seine E-Mail-Adresse eingeben und die ihm zugewiesenen Felder ausfüllen." msgstr "Dieses Feld kann nicht geändert oder gelöscht werden. Wenn Sie den direkten Link dieser Vorlage teilen oder zu Ihrem öffentlichen Profil hinzufügen, kann jeder, der darauf zugreift, seinen Namen und seine E-Mail-Adresse eingeben und die ihm zugewiesenen Felder ausfüllen."
@@ -1593,7 +1599,7 @@ msgstr "Dieses Feld kann nicht geändert oder gelöscht werden. Wenn Sie den dir
msgid "This is how the document will reach the recipients once the document is ready for signing." msgid "This is how the document will reach the recipients once the document is ready for signing."
msgstr "So wird das Dokument die Empfänger erreichen, sobald es zum Unterschreiben bereit ist." msgstr "So wird das Dokument die Empfänger erreichen, sobald es zum Unterschreiben bereit ist."
#: packages/ui/primitives/document-flow/add-fields.tsx:1090 #: packages/ui/primitives/document-flow/add-fields.tsx:1097
msgid "This recipient can no longer be modified as they have signed a field, or completed the document." msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr "Dieser Empfänger kann nicht mehr bearbeitet werden, da er ein Feld unterschrieben oder das Dokument abgeschlossen hat." msgstr "Dieser Empfänger kann nicht mehr bearbeitet werden, da er ein Feld unterschrieben oder das Dokument abgeschlossen hat."
@@ -1622,8 +1628,8 @@ msgstr "Zeitzone"
msgid "Title" msgid "Title"
msgstr "Titel" msgstr "Titel"
#: packages/ui/primitives/document-flow/add-fields.tsx:1073 #: packages/ui/primitives/document-flow/add-fields.tsx:1080
#: packages/ui/primitives/template-flow/add-template-fields.tsx:834 #: packages/ui/primitives/template-flow/add-template-fields.tsx:873
msgid "To proceed further, please set at least one value for the {0} field." msgid "To proceed further, please set at least one value for the {0} field."
msgstr "Um fortzufahren, legen Sie bitte mindestens einen Wert für das Feld {0} fest." msgstr "Um fortzufahren, legen Sie bitte mindestens einen Wert für das Feld {0} fest."
@@ -1808,4 +1814,3 @@ msgstr "Dein Passwort wurde aktualisiert."
#: packages/email/templates/team-delete.tsx:32 #: packages/email/templates/team-delete.tsx:32
msgid "Your team has been deleted" msgid "Your team has been deleted"
msgstr "Dein Team wurde gelöscht" msgstr "Dein Team wurde gelöscht"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n" "Language: de\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: German\n" "Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -602,4 +602,3 @@ msgstr "Sie können Documenso kostenlos selbst hosten oder unsere sofort einsatz
#: apps/marketing/src/components/(marketing)/carousel.tsx:272 #: apps/marketing/src/components/(marketing)/carousel.tsx:272
msgid "Your browser does not support the video tag." msgid "Your browser does not support the video tag."
msgstr "Ihr Browser unterstützt das Video-Tag nicht." msgstr "Ihr Browser unterstützt das Video-Tag nicht."

File diff suppressed because it is too large Load Diff

View File

@@ -409,11 +409,11 @@ msgstr "Add another value"
msgid "Add myself" msgid "Add myself"
msgstr "Add myself" msgstr "Add myself"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:637 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:645
msgid "Add Myself" msgid "Add Myself"
msgstr "Add Myself" msgstr "Add Myself"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:623 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:631
msgid "Add Placeholder Recipient" msgid "Add Placeholder Recipient"
msgstr "Add Placeholder Recipient" msgstr "Add Placeholder Recipient"
@@ -438,8 +438,8 @@ msgstr "Admin"
msgid "Advanced Options" msgid "Advanced Options"
msgstr "Advanced Options" msgstr "Advanced Options"
#: packages/ui/primitives/document-flow/add-fields.tsx:573 #: packages/ui/primitives/document-flow/add-fields.tsx:576
#: packages/ui/primitives/template-flow/add-template-fields.tsx:406 #: packages/ui/primitives/template-flow/add-template-fields.tsx:414
msgid "Advanced settings" msgid "Advanced settings"
msgstr "Advanced settings" msgstr "Advanced settings"
@@ -495,11 +495,11 @@ msgstr "Approving"
msgid "Before you get started, please confirm your email address by clicking the button below:" msgid "Before you get started, please confirm your email address by clicking the button below:"
msgstr "Before you get started, please confirm your email address by clicking the button below:" msgstr "Before you get started, please confirm your email address by clicking the button below:"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:377 #: packages/ui/primitives/signature-pad/signature-pad.tsx:383
msgid "Black" msgid "Black"
msgstr "Black" msgstr "Black"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:391 #: packages/ui/primitives/signature-pad/signature-pad.tsx:397
msgid "Blue" msgid "Blue"
msgstr "Blue" msgstr "Blue"
@@ -545,6 +545,10 @@ msgstr "Ccers"
msgid "Character Limit" msgid "Character Limit"
msgstr "Character Limit" msgstr "Character Limit"
#: packages/ui/primitives/document-flow/types.ts:58
msgid "Checkbox"
msgstr "Checkbox"
#: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197 #: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197
msgid "Checkbox values" msgid "Checkbox values"
msgstr "Checkbox values" msgstr "Checkbox values"
@@ -553,7 +557,7 @@ msgstr "Checkbox values"
msgid "Clear filters" msgid "Clear filters"
msgstr "Clear filters" msgstr "Clear filters"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:411 #: packages/ui/primitives/signature-pad/signature-pad.tsx:417
msgid "Clear Signature" msgid "Clear Signature"
msgstr "Clear Signature" msgstr "Clear Signature"
@@ -580,8 +584,8 @@ msgstr "Completed Document"
msgid "Configure Direct Recipient" msgid "Configure Direct Recipient"
msgstr "Configure Direct Recipient" msgstr "Configure Direct Recipient"
#: packages/ui/primitives/document-flow/add-fields.tsx:574 #: packages/ui/primitives/document-flow/add-fields.tsx:577
#: packages/ui/primitives/template-flow/add-template-fields.tsx:407 #: packages/ui/primitives/template-flow/add-template-fields.tsx:415
msgid "Configure the {0} field" msgid "Configure the {0} field"
msgstr "Configure the {0} field" msgstr "Configure the {0} field"
@@ -642,9 +646,9 @@ msgstr "Create account"
msgid "Custom Text" msgid "Custom Text"
msgstr "Custom Text" msgstr "Custom Text"
#: packages/ui/primitives/document-flow/add-fields.tsx:927 #: packages/ui/primitives/document-flow/add-fields.tsx:934
#: packages/ui/primitives/document-flow/types.ts:53 #: packages/ui/primitives/document-flow/types.ts:53
#: packages/ui/primitives/template-flow/add-template-fields.tsx:690 #: packages/ui/primitives/template-flow/add-template-fields.tsx:729
msgid "Date" msgid "Date"
msgstr "Date" msgstr "Date"
@@ -661,7 +665,7 @@ msgstr "Decline"
msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>" msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>"
msgstr "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>" msgstr "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:570 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:578
msgid "Direct link receiver" msgid "Direct link receiver"
msgstr "Direct link receiver" msgstr "Direct link receiver"
@@ -783,8 +787,8 @@ msgstr "Draft"
msgid "Drag & drop your PDF here." msgid "Drag & drop your PDF here."
msgstr "Drag & drop your PDF here." msgstr "Drag & drop your PDF here."
#: packages/ui/primitives/document-flow/add-fields.tsx:1058 #: packages/ui/primitives/document-flow/add-fields.tsx:1065
#: packages/ui/primitives/template-flow/add-template-fields.tsx:820 #: packages/ui/primitives/template-flow/add-template-fields.tsx:860
msgid "Dropdown" msgid "Dropdown"
msgstr "Dropdown" msgstr "Dropdown"
@@ -793,14 +797,14 @@ msgid "Dropdown options"
msgstr "Dropdown options" msgstr "Dropdown options"
#: packages/lib/constants/document.ts:28 #: packages/lib/constants/document.ts:28
#: packages/ui/primitives/document-flow/add-fields.tsx:875 #: packages/ui/primitives/document-flow/add-fields.tsx:882
#: packages/ui/primitives/document-flow/add-signature.tsx:272 #: packages/ui/primitives/document-flow/add-signature.tsx:272
#: packages/ui/primitives/document-flow/add-signers.tsx:512 #: packages/ui/primitives/document-flow/add-signers.tsx:512
#: packages/ui/primitives/document-flow/add-signers.tsx:519 #: packages/ui/primitives/document-flow/add-signers.tsx:519
#: packages/ui/primitives/document-flow/types.ts:54 #: packages/ui/primitives/document-flow/types.ts:54
#: packages/ui/primitives/template-flow/add-template-fields.tsx:638 #: packages/ui/primitives/template-flow/add-template-fields.tsx:677
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:463 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:471
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:470 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:478
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -820,7 +824,7 @@ msgstr "Email resent"
msgid "Email sent" msgid "Email sent"
msgstr "Email sent" msgstr "Email sent"
#: packages/ui/primitives/document-flow/add-fields.tsx:1123 #: packages/ui/primitives/document-flow/add-fields.tsx:1130
msgid "Empty field" msgid "Empty field"
msgstr "Empty field" msgstr "Empty field"
@@ -829,11 +833,12 @@ msgid "Enable Direct Link Signing"
msgstr "Enable Direct Link Signing" msgstr "Enable Direct Link Signing"
#: packages/ui/primitives/document-flow/add-signers.tsx:401 #: packages/ui/primitives/document-flow/add-signers.tsx:401
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:362 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:370
msgid "Enable signing order" msgid "Enable signing order"
msgstr "Enable signing order" msgstr "Enable signing order"
#: packages/ui/primitives/document-flow/add-fields.tsx:795 #: packages/ui/primitives/document-flow/add-fields.tsx:802
#: packages/ui/primitives/template-flow/add-template-fields.tsx:597
msgid "Enable Typed Signatures" msgid "Enable Typed Signatures"
msgstr "Enable Typed Signatures" msgstr "Enable Typed Signatures"
@@ -921,7 +926,7 @@ msgstr "Global recipient action authentication"
msgid "Go Back" msgid "Go Back"
msgstr "Go Back" msgstr "Go Back"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:398 #: packages/ui/primitives/signature-pad/signature-pad.tsx:404
msgid "Green" msgid "Green"
msgstr "Green" msgstr "Green"
@@ -1011,14 +1016,14 @@ msgstr "Message <0>(Optional)</0>"
msgid "Min" msgid "Min"
msgstr "Min" msgstr "Min"
#: packages/ui/primitives/document-flow/add-fields.tsx:901 #: packages/ui/primitives/document-flow/add-fields.tsx:908
#: packages/ui/primitives/document-flow/add-signature.tsx:298 #: packages/ui/primitives/document-flow/add-signature.tsx:298
#: packages/ui/primitives/document-flow/add-signers.tsx:550 #: packages/ui/primitives/document-flow/add-signers.tsx:550
#: packages/ui/primitives/document-flow/add-signers.tsx:556 #: packages/ui/primitives/document-flow/add-signers.tsx:556
#: packages/ui/primitives/document-flow/types.ts:55 #: packages/ui/primitives/document-flow/types.ts:55
#: packages/ui/primitives/template-flow/add-template-fields.tsx:664 #: packages/ui/primitives/template-flow/add-template-fields.tsx:703
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:498 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:506
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:504 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:512
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@@ -1034,8 +1039,8 @@ msgstr "Needs to sign"
msgid "Needs to view" msgid "Needs to view"
msgstr "Needs to view" msgstr "Needs to view"
#: packages/ui/primitives/document-flow/add-fields.tsx:686 #: packages/ui/primitives/document-flow/add-fields.tsx:693
#: packages/ui/primitives/template-flow/add-template-fields.tsx:504 #: packages/ui/primitives/template-flow/add-template-fields.tsx:516
msgid "No recipient matching this description was found." msgid "No recipient matching this description was found."
msgstr "No recipient matching this description was found." msgstr "No recipient matching this description was found."
@@ -1043,8 +1048,8 @@ msgstr "No recipient matching this description was found."
msgid "No recipients" msgid "No recipients"
msgstr "No recipients" msgstr "No recipients"
#: packages/ui/primitives/document-flow/add-fields.tsx:701 #: packages/ui/primitives/document-flow/add-fields.tsx:708
#: packages/ui/primitives/template-flow/add-template-fields.tsx:519 #: packages/ui/primitives/template-flow/add-template-fields.tsx:531
msgid "No recipients with this role" msgid "No recipients with this role"
msgstr "No recipients with this role" msgstr "No recipients with this role"
@@ -1072,9 +1077,9 @@ msgstr "No value found."
msgid "None" msgid "None"
msgstr "None" msgstr "None"
#: packages/ui/primitives/document-flow/add-fields.tsx:979 #: packages/ui/primitives/document-flow/add-fields.tsx:986
#: packages/ui/primitives/document-flow/types.ts:56 #: packages/ui/primitives/document-flow/types.ts:56
#: packages/ui/primitives/template-flow/add-template-fields.tsx:742 #: packages/ui/primitives/template-flow/add-template-fields.tsx:781
msgid "Number" msgid "Number"
msgstr "Number" msgstr "Number"
@@ -1165,7 +1170,7 @@ msgstr "Please confirm your email address"
msgid "Please try again or contact our support." msgid "Please try again or contact our support."
msgstr "Please try again or contact our support." msgstr "Please try again or contact our support."
#: packages/ui/primitives/template-flow/add-template-fields.tsx:768 #: packages/ui/primitives/document-flow/types.ts:57
msgid "Radio" msgid "Radio"
msgstr "Radio" msgstr "Radio"
@@ -1208,7 +1213,7 @@ msgstr "Recipient removed email"
msgid "Recipient signing request email" msgid "Recipient signing request email"
msgstr "Recipient signing request email" msgstr "Recipient signing request email"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:384 #: packages/ui/primitives/signature-pad/signature-pad.tsx:390
msgid "Red" msgid "Red"
msgstr "Red" msgstr "Red"
@@ -1245,7 +1250,7 @@ msgstr "Reminder: Please {recipientActionVerb} this document"
msgid "Reminder: Please {recipientActionVerb} your document" msgid "Reminder: Please {recipientActionVerb} your document"
msgstr "Reminder: Please {recipientActionVerb} your document" msgstr "Reminder: Please {recipientActionVerb} your document"
#: packages/ui/primitives/document-flow/add-fields.tsx:1110 #: packages/ui/primitives/document-flow/add-fields.tsx:1117
msgid "Remove" msgid "Remove"
msgstr "Remove" msgstr "Remove"
@@ -1277,7 +1282,7 @@ msgstr "Rows per page"
msgid "Save" msgid "Save"
msgstr "Save" msgstr "Save"
#: packages/ui/primitives/template-flow/add-template-fields.tsx:854 #: packages/ui/primitives/template-flow/add-template-fields.tsx:893
msgid "Save Template" msgid "Save Template"
msgstr "Save Template" msgstr "Save Template"
@@ -1286,6 +1291,7 @@ msgid "Search languages..."
msgstr "Search languages..." msgstr "Search languages..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115 #: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115
#: packages/ui/primitives/document-flow/types.ts:59
msgid "Select" msgid "Select"
msgstr "Select" msgstr "Select"
@@ -1349,7 +1355,7 @@ msgid "Share your signing experience!"
msgstr "Share your signing experience!" msgstr "Share your signing experience!"
#: packages/ui/primitives/document-flow/add-signers.tsx:709 #: packages/ui/primitives/document-flow/add-signers.tsx:709
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:655 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:663
msgid "Show advanced settings" msgid "Show advanced settings"
msgstr "Show advanced settings" msgstr "Show advanced settings"
@@ -1365,11 +1371,11 @@ msgstr "Sign Document"
msgid "Sign In" msgid "Sign In"
msgstr "Sign In" msgstr "Sign In"
#: packages/ui/primitives/document-flow/add-fields.tsx:823 #: packages/ui/primitives/document-flow/add-fields.tsx:830
#: packages/ui/primitives/document-flow/add-signature.tsx:323 #: packages/ui/primitives/document-flow/add-signature.tsx:323
#: packages/ui/primitives/document-flow/field-icon.tsx:52 #: packages/ui/primitives/document-flow/field-icon.tsx:52
#: packages/ui/primitives/document-flow/types.ts:49 #: packages/ui/primitives/document-flow/types.ts:49
#: packages/ui/primitives/template-flow/add-template-fields.tsx:586 #: packages/ui/primitives/template-flow/add-template-fields.tsx:625
msgid "Signature" msgid "Signature"
msgstr "Signature" msgstr "Signature"
@@ -1452,9 +1458,9 @@ msgstr "Team email removed for {teamName} on Documenso"
msgid "Template title" msgid "Template title"
msgstr "Template title" msgstr "Template title"
#: packages/ui/primitives/document-flow/add-fields.tsx:953 #: packages/ui/primitives/document-flow/add-fields.tsx:960
#: packages/ui/primitives/document-flow/types.ts:52 #: packages/ui/primitives/document-flow/types.ts:52
#: packages/ui/primitives/template-flow/add-template-fields.tsx:716 #: packages/ui/primitives/template-flow/add-template-fields.tsx:755
msgid "Text" msgid "Text"
msgstr "Text" msgstr "Text"
@@ -1549,7 +1555,7 @@ msgstr "This can be overriden by setting the authentication requirements directl
msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support."
msgstr "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." msgstr "This document can not be recovered, if you would like to dispute the reason for future documents please contact support."
#: packages/ui/primitives/document-flow/add-fields.tsx:757 #: packages/ui/primitives/document-flow/add-fields.tsx:764
msgid "This document has already been sent to this recipient. You can no longer edit this recipient." msgid "This document has already been sent to this recipient. You can no longer edit this recipient."
msgstr "This document has already been sent to this recipient. You can no longer edit this recipient." msgstr "This document has already been sent to this recipient. You can no longer edit this recipient."
@@ -1580,7 +1586,7 @@ msgstr "This email is sent to the recipient requesting them to sign the document
msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet." msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet."
msgstr "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet." msgstr "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet."
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:573 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:581
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
msgstr "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgstr "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
@@ -1588,7 +1594,7 @@ msgstr "This field cannot be modified or deleted. When you share this template's
msgid "This is how the document will reach the recipients once the document is ready for signing." msgid "This is how the document will reach the recipients once the document is ready for signing."
msgstr "This is how the document will reach the recipients once the document is ready for signing." msgstr "This is how the document will reach the recipients once the document is ready for signing."
#: packages/ui/primitives/document-flow/add-fields.tsx:1090 #: packages/ui/primitives/document-flow/add-fields.tsx:1097
msgid "This recipient can no longer be modified as they have signed a field, or completed the document." msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr "This recipient can no longer be modified as they have signed a field, or completed the document." msgstr "This recipient can no longer be modified as they have signed a field, or completed the document."
@@ -1617,8 +1623,8 @@ msgstr "Time Zone"
msgid "Title" msgid "Title"
msgstr "Title" msgstr "Title"
#: packages/ui/primitives/document-flow/add-fields.tsx:1073 #: packages/ui/primitives/document-flow/add-fields.tsx:1080
#: packages/ui/primitives/template-flow/add-template-fields.tsx:834 #: packages/ui/primitives/template-flow/add-template-fields.tsx:873
msgid "To proceed further, please set at least one value for the {0} field." msgid "To proceed further, please set at least one value for the {0} field."
msgstr "To proceed further, please set at least one value for the {0} field." msgstr "To proceed further, please set at least one value for the {0} field."

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: es\n" "Language: es\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -414,11 +414,11 @@ msgstr "Agregar otro valor"
msgid "Add myself" msgid "Add myself"
msgstr "Agregame" msgstr "Agregame"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:637 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:645
msgid "Add Myself" msgid "Add Myself"
msgstr "Agregame" msgstr "Agregame"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:623 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:631
msgid "Add Placeholder Recipient" msgid "Add Placeholder Recipient"
msgstr "Agregar destinatario de marcador de posición" msgstr "Agregar destinatario de marcador de posición"
@@ -443,8 +443,8 @@ msgstr "Admin"
msgid "Advanced Options" msgid "Advanced Options"
msgstr "Opciones avanzadas" msgstr "Opciones avanzadas"
#: packages/ui/primitives/document-flow/add-fields.tsx:573 #: packages/ui/primitives/document-flow/add-fields.tsx:576
#: packages/ui/primitives/template-flow/add-template-fields.tsx:406 #: packages/ui/primitives/template-flow/add-template-fields.tsx:414
msgid "Advanced settings" msgid "Advanced settings"
msgstr "Configuraciones avanzadas" msgstr "Configuraciones avanzadas"
@@ -500,11 +500,11 @@ msgstr "Aprobando"
msgid "Before you get started, please confirm your email address by clicking the button below:" msgid "Before you get started, please confirm your email address by clicking the button below:"
msgstr "Antes de comenzar, por favor confirma tu dirección de correo electrónico haciendo clic en el botón de abajo:" msgstr "Antes de comenzar, por favor confirma tu dirección de correo electrónico haciendo clic en el botón de abajo:"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:377 #: packages/ui/primitives/signature-pad/signature-pad.tsx:383
msgid "Black" msgid "Black"
msgstr "Negro" msgstr "Negro"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:391 #: packages/ui/primitives/signature-pad/signature-pad.tsx:397
msgid "Blue" msgid "Blue"
msgstr "Azul" msgstr "Azul"
@@ -550,6 +550,10 @@ msgstr "Ccers"
msgid "Character Limit" msgid "Character Limit"
msgstr "Límite de caracteres" msgstr "Límite de caracteres"
#: packages/ui/primitives/document-flow/types.ts:58
msgid "Checkbox"
msgstr "Checkbox"
#: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197 #: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197
msgid "Checkbox values" msgid "Checkbox values"
msgstr "Valores de Checkbox" msgstr "Valores de Checkbox"
@@ -558,7 +562,7 @@ msgstr "Valores de Checkbox"
msgid "Clear filters" msgid "Clear filters"
msgstr "Limpiar filtros" msgstr "Limpiar filtros"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:411 #: packages/ui/primitives/signature-pad/signature-pad.tsx:417
msgid "Clear Signature" msgid "Clear Signature"
msgstr "Limpiar firma" msgstr "Limpiar firma"
@@ -585,8 +589,8 @@ msgstr "Documento completado"
msgid "Configure Direct Recipient" msgid "Configure Direct Recipient"
msgstr "Configurar destinatario directo" msgstr "Configurar destinatario directo"
#: packages/ui/primitives/document-flow/add-fields.tsx:574 #: packages/ui/primitives/document-flow/add-fields.tsx:577
#: packages/ui/primitives/template-flow/add-template-fields.tsx:407 #: packages/ui/primitives/template-flow/add-template-fields.tsx:415
msgid "Configure the {0} field" msgid "Configure the {0} field"
msgstr "Configurar el campo {0}" msgstr "Configurar el campo {0}"
@@ -647,9 +651,9 @@ msgstr "Crear cuenta"
msgid "Custom Text" msgid "Custom Text"
msgstr "Texto personalizado" msgstr "Texto personalizado"
#: packages/ui/primitives/document-flow/add-fields.tsx:927 #: packages/ui/primitives/document-flow/add-fields.tsx:934
#: packages/ui/primitives/document-flow/types.ts:53 #: packages/ui/primitives/document-flow/types.ts:53
#: packages/ui/primitives/template-flow/add-template-fields.tsx:690 #: packages/ui/primitives/template-flow/add-template-fields.tsx:729
msgid "Date" msgid "Date"
msgstr "Fecha" msgstr "Fecha"
@@ -666,7 +670,7 @@ msgstr "Rechazar"
msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>" msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>"
msgstr "¿No solicitaste un cambio de contraseña? Estamos aquí para ayudarte a asegurar tu cuenta, solo <0>contáctanos.</0>" msgstr "¿No solicitaste un cambio de contraseña? Estamos aquí para ayudarte a asegurar tu cuenta, solo <0>contáctanos.</0>"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:570 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:578
msgid "Direct link receiver" msgid "Direct link receiver"
msgstr "Receptor de enlace directo" msgstr "Receptor de enlace directo"
@@ -788,8 +792,8 @@ msgstr "Borrador"
msgid "Drag & drop your PDF here." msgid "Drag & drop your PDF here."
msgstr "Arrastre y suelte su PDF aquí." msgstr "Arrastre y suelte su PDF aquí."
#: packages/ui/primitives/document-flow/add-fields.tsx:1058 #: packages/ui/primitives/document-flow/add-fields.tsx:1065
#: packages/ui/primitives/template-flow/add-template-fields.tsx:820 #: packages/ui/primitives/template-flow/add-template-fields.tsx:860
msgid "Dropdown" msgid "Dropdown"
msgstr "Menú desplegable" msgstr "Menú desplegable"
@@ -798,14 +802,14 @@ msgid "Dropdown options"
msgstr "Opciones de menú desplegable" msgstr "Opciones de menú desplegable"
#: packages/lib/constants/document.ts:28 #: packages/lib/constants/document.ts:28
#: packages/ui/primitives/document-flow/add-fields.tsx:875 #: packages/ui/primitives/document-flow/add-fields.tsx:882
#: packages/ui/primitives/document-flow/add-signature.tsx:272 #: packages/ui/primitives/document-flow/add-signature.tsx:272
#: packages/ui/primitives/document-flow/add-signers.tsx:512 #: packages/ui/primitives/document-flow/add-signers.tsx:512
#: packages/ui/primitives/document-flow/add-signers.tsx:519 #: packages/ui/primitives/document-flow/add-signers.tsx:519
#: packages/ui/primitives/document-flow/types.ts:54 #: packages/ui/primitives/document-flow/types.ts:54
#: packages/ui/primitives/template-flow/add-template-fields.tsx:638 #: packages/ui/primitives/template-flow/add-template-fields.tsx:677
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:463 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:471
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:470 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:478
msgid "Email" msgid "Email"
msgstr "Correo electrónico" msgstr "Correo electrónico"
@@ -825,7 +829,7 @@ msgstr "Correo electrónico reeenviado"
msgid "Email sent" msgid "Email sent"
msgstr "Correo electrónico enviado" msgstr "Correo electrónico enviado"
#: packages/ui/primitives/document-flow/add-fields.tsx:1123 #: packages/ui/primitives/document-flow/add-fields.tsx:1130
msgid "Empty field" msgid "Empty field"
msgstr "Campo vacío" msgstr "Campo vacío"
@@ -834,11 +838,12 @@ msgid "Enable Direct Link Signing"
msgstr "Habilitar firma de enlace directo" msgstr "Habilitar firma de enlace directo"
#: packages/ui/primitives/document-flow/add-signers.tsx:401 #: packages/ui/primitives/document-flow/add-signers.tsx:401
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:362 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:370
msgid "Enable signing order" msgid "Enable signing order"
msgstr "Habilitar orden de firma" msgstr "Habilitar orden de firma"
#: packages/ui/primitives/document-flow/add-fields.tsx:795 #: packages/ui/primitives/document-flow/add-fields.tsx:802
#: packages/ui/primitives/template-flow/add-template-fields.tsx:597
msgid "Enable Typed Signatures" msgid "Enable Typed Signatures"
msgstr "Habilitar firmas escritas" msgstr "Habilitar firmas escritas"
@@ -926,7 +931,7 @@ msgstr "Autenticación de acción de destinatario global"
msgid "Go Back" msgid "Go Back"
msgstr "Regresar" msgstr "Regresar"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:398 #: packages/ui/primitives/signature-pad/signature-pad.tsx:404
msgid "Green" msgid "Green"
msgstr "Verde" msgstr "Verde"
@@ -1016,14 +1021,14 @@ msgstr "Mensaje <0>(Opcional)</0>"
msgid "Min" msgid "Min"
msgstr "Mín" msgstr "Mín"
#: packages/ui/primitives/document-flow/add-fields.tsx:901 #: packages/ui/primitives/document-flow/add-fields.tsx:908
#: packages/ui/primitives/document-flow/add-signature.tsx:298 #: packages/ui/primitives/document-flow/add-signature.tsx:298
#: packages/ui/primitives/document-flow/add-signers.tsx:550 #: packages/ui/primitives/document-flow/add-signers.tsx:550
#: packages/ui/primitives/document-flow/add-signers.tsx:556 #: packages/ui/primitives/document-flow/add-signers.tsx:556
#: packages/ui/primitives/document-flow/types.ts:55 #: packages/ui/primitives/document-flow/types.ts:55
#: packages/ui/primitives/template-flow/add-template-fields.tsx:664 #: packages/ui/primitives/template-flow/add-template-fields.tsx:703
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:498 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:506
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:504 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:512
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
@@ -1039,8 +1044,8 @@ msgstr "Necesita firmar"
msgid "Needs to view" msgid "Needs to view"
msgstr "Necesita ver" msgstr "Necesita ver"
#: packages/ui/primitives/document-flow/add-fields.tsx:686 #: packages/ui/primitives/document-flow/add-fields.tsx:693
#: packages/ui/primitives/template-flow/add-template-fields.tsx:504 #: packages/ui/primitives/template-flow/add-template-fields.tsx:516
msgid "No recipient matching this description was found." msgid "No recipient matching this description was found."
msgstr "No se encontró ningún destinatario que coincidiera con esta descripción." msgstr "No se encontró ningún destinatario que coincidiera con esta descripción."
@@ -1048,8 +1053,8 @@ msgstr "No se encontró ningún destinatario que coincidiera con esta descripci
msgid "No recipients" msgid "No recipients"
msgstr "Sin destinatarios" msgstr "Sin destinatarios"
#: packages/ui/primitives/document-flow/add-fields.tsx:701 #: packages/ui/primitives/document-flow/add-fields.tsx:708
#: packages/ui/primitives/template-flow/add-template-fields.tsx:519 #: packages/ui/primitives/template-flow/add-template-fields.tsx:531
msgid "No recipients with this role" msgid "No recipients with this role"
msgstr "No hay destinatarios con este rol" msgstr "No hay destinatarios con este rol"
@@ -1077,9 +1082,9 @@ msgstr "No se encontró valor."
msgid "None" msgid "None"
msgstr "Ninguno" msgstr "Ninguno"
#: packages/ui/primitives/document-flow/add-fields.tsx:979 #: packages/ui/primitives/document-flow/add-fields.tsx:986
#: packages/ui/primitives/document-flow/types.ts:56 #: packages/ui/primitives/document-flow/types.ts:56
#: packages/ui/primitives/template-flow/add-template-fields.tsx:742 #: packages/ui/primitives/template-flow/add-template-fields.tsx:781
msgid "Number" msgid "Number"
msgstr "Número" msgstr "Número"
@@ -1170,7 +1175,7 @@ msgstr "Por favor confirma tu dirección de correo electrónico"
msgid "Please try again or contact our support." msgid "Please try again or contact our support."
msgstr "Por favor, inténtalo de nuevo o contacta a nuestro soporte." msgstr "Por favor, inténtalo de nuevo o contacta a nuestro soporte."
#: packages/ui/primitives/template-flow/add-template-fields.tsx:768 #: packages/ui/primitives/document-flow/types.ts:57
msgid "Radio" msgid "Radio"
msgstr "Radio" msgstr "Radio"
@@ -1213,7 +1218,7 @@ msgstr "Correo electrónico de destinatario eliminado"
msgid "Recipient signing request email" msgid "Recipient signing request email"
msgstr "Correo electrónico de solicitud de firma de destinatario" msgstr "Correo electrónico de solicitud de firma de destinatario"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:384 #: packages/ui/primitives/signature-pad/signature-pad.tsx:390
msgid "Red" msgid "Red"
msgstr "Rojo" msgstr "Rojo"
@@ -1250,7 +1255,7 @@ msgstr "Recordatorio: Por favor {recipientActionVerb} este documento"
msgid "Reminder: Please {recipientActionVerb} your document" msgid "Reminder: Please {recipientActionVerb} your document"
msgstr "Recordatorio: Por favor {recipientActionVerb} tu documento" msgstr "Recordatorio: Por favor {recipientActionVerb} tu documento"
#: packages/ui/primitives/document-flow/add-fields.tsx:1110 #: packages/ui/primitives/document-flow/add-fields.tsx:1117
msgid "Remove" msgid "Remove"
msgstr "Eliminar" msgstr "Eliminar"
@@ -1282,7 +1287,7 @@ msgstr "Filas por página"
msgid "Save" msgid "Save"
msgstr "Guardar" msgstr "Guardar"
#: packages/ui/primitives/template-flow/add-template-fields.tsx:854 #: packages/ui/primitives/template-flow/add-template-fields.tsx:893
msgid "Save Template" msgid "Save Template"
msgstr "Guardar plantilla" msgstr "Guardar plantilla"
@@ -1291,6 +1296,7 @@ msgid "Search languages..."
msgstr "Buscar idiomas..." msgstr "Buscar idiomas..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115 #: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115
#: packages/ui/primitives/document-flow/types.ts:59
msgid "Select" msgid "Select"
msgstr "Seleccionar" msgstr "Seleccionar"
@@ -1354,7 +1360,7 @@ msgid "Share your signing experience!"
msgstr "¡Comparte tu experiencia de firma!" msgstr "¡Comparte tu experiencia de firma!"
#: packages/ui/primitives/document-flow/add-signers.tsx:709 #: packages/ui/primitives/document-flow/add-signers.tsx:709
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:655 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:663
msgid "Show advanced settings" msgid "Show advanced settings"
msgstr "Mostrar configuraciones avanzadas" msgstr "Mostrar configuraciones avanzadas"
@@ -1370,11 +1376,11 @@ msgstr "Firmar Documento"
msgid "Sign In" msgid "Sign In"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#: packages/ui/primitives/document-flow/add-fields.tsx:823 #: packages/ui/primitives/document-flow/add-fields.tsx:830
#: packages/ui/primitives/document-flow/add-signature.tsx:323 #: packages/ui/primitives/document-flow/add-signature.tsx:323
#: packages/ui/primitives/document-flow/field-icon.tsx:52 #: packages/ui/primitives/document-flow/field-icon.tsx:52
#: packages/ui/primitives/document-flow/types.ts:49 #: packages/ui/primitives/document-flow/types.ts:49
#: packages/ui/primitives/template-flow/add-template-fields.tsx:586 #: packages/ui/primitives/template-flow/add-template-fields.tsx:625
msgid "Signature" msgid "Signature"
msgstr "Firma" msgstr "Firma"
@@ -1457,9 +1463,9 @@ msgstr "Correo electrónico del equipo eliminado para {teamName} en Documenso"
msgid "Template title" msgid "Template title"
msgstr "Título de plantilla" msgstr "Título de plantilla"
#: packages/ui/primitives/document-flow/add-fields.tsx:953 #: packages/ui/primitives/document-flow/add-fields.tsx:960
#: packages/ui/primitives/document-flow/types.ts:52 #: packages/ui/primitives/document-flow/types.ts:52
#: packages/ui/primitives/template-flow/add-template-fields.tsx:716 #: packages/ui/primitives/template-flow/add-template-fields.tsx:755
msgid "Text" msgid "Text"
msgstr "Texto" msgstr "Texto"
@@ -1554,7 +1560,7 @@ msgstr "Esto se puede anular configurando los requisitos de autenticación direc
msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support."
msgstr "Este documento no se puede recuperar, si deseas impugnar la razón para documentos futuros, por favor contacta con el soporte." msgstr "Este documento no se puede recuperar, si deseas impugnar la razón para documentos futuros, por favor contacta con el soporte."
#: packages/ui/primitives/document-flow/add-fields.tsx:757 #: packages/ui/primitives/document-flow/add-fields.tsx:764
msgid "This document has already been sent to this recipient. You can no longer edit this recipient." msgid "This document has already been sent to this recipient. You can no longer edit this recipient."
msgstr "Este documento ya ha sido enviado a este destinatario. Ya no puede editar a este destinatario." msgstr "Este documento ya ha sido enviado a este destinatario. Ya no puede editar a este destinatario."
@@ -1585,7 +1591,7 @@ msgstr "Este correo electrónico se envía al destinatario solicitando que firme
msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet." msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet."
msgstr "Este correo electrónico se enviará al destinatario que acaba de firmar el documento, si todavía hay otros destinatarios que no han firmado." msgstr "Este correo electrónico se enviará al destinatario que acaba de firmar el documento, si todavía hay otros destinatarios que no han firmado."
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:573 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:581
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
msgstr "Este campo no se puede modificar ni eliminar. Cuando comparta el enlace directo de esta plantilla o lo agregue a su perfil público, cualquiera que acceda podrá ingresar su nombre y correo electrónico, y completar los campos que se le hayan asignado." msgstr "Este campo no se puede modificar ni eliminar. Cuando comparta el enlace directo de esta plantilla o lo agregue a su perfil público, cualquiera que acceda podrá ingresar su nombre y correo electrónico, y completar los campos que se le hayan asignado."
@@ -1593,7 +1599,7 @@ msgstr "Este campo no se puede modificar ni eliminar. Cuando comparta el enlace
msgid "This is how the document will reach the recipients once the document is ready for signing." msgid "This is how the document will reach the recipients once the document is ready for signing."
msgstr "Así es como el documento llegará a los destinatarios una vez que esté listo para firmarse." msgstr "Así es como el documento llegará a los destinatarios una vez que esté listo para firmarse."
#: packages/ui/primitives/document-flow/add-fields.tsx:1090 #: packages/ui/primitives/document-flow/add-fields.tsx:1097
msgid "This recipient can no longer be modified as they have signed a field, or completed the document." msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr "Este destinatario ya no puede ser modificado ya que ha firmado un campo o completado el documento." msgstr "Este destinatario ya no puede ser modificado ya que ha firmado un campo o completado el documento."
@@ -1622,8 +1628,8 @@ msgstr "Zona horaria"
msgid "Title" msgid "Title"
msgstr "Título" msgstr "Título"
#: packages/ui/primitives/document-flow/add-fields.tsx:1073 #: packages/ui/primitives/document-flow/add-fields.tsx:1080
#: packages/ui/primitives/template-flow/add-template-fields.tsx:834 #: packages/ui/primitives/template-flow/add-template-fields.tsx:873
msgid "To proceed further, please set at least one value for the {0} field." msgid "To proceed further, please set at least one value for the {0} field."
msgstr "Para continuar, por favor establezca al menos un valor para el campo {0}." msgstr "Para continuar, por favor establezca al menos un valor para el campo {0}."
@@ -1808,4 +1814,3 @@ msgstr "Tu contraseña ha sido actualizada."
#: packages/email/templates/team-delete.tsx:32 #: packages/email/templates/team-delete.tsx:32
msgid "Your team has been deleted" msgid "Your team has been deleted"
msgstr "Tu equipo ha sido eliminado" msgstr "Tu equipo ha sido eliminado"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: es\n" "Language: es\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -602,4 +602,3 @@ msgstr "Puedes autoalojar Documenso de forma gratuita o usar nuestra versión al
#: apps/marketing/src/components/(marketing)/carousel.tsx:272 #: apps/marketing/src/components/(marketing)/carousel.tsx:272
msgid "Your browser does not support the video tag." msgid "Your browser does not support the video tag."
msgstr "Tu navegador no soporta la etiqueta de video." msgstr "Tu navegador no soporta la etiqueta de video."

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n" "Language: fr\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: French\n" "Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -414,11 +414,11 @@ msgstr "Ajouter une autre valeur"
msgid "Add myself" msgid "Add myself"
msgstr "Ajoutez-moi" msgstr "Ajoutez-moi"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:637 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:645
msgid "Add Myself" msgid "Add Myself"
msgstr "Ajoutez-moi" msgstr "Ajoutez-moi"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:623 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:631
msgid "Add Placeholder Recipient" msgid "Add Placeholder Recipient"
msgstr "Ajouter un destinataire de substitution" msgstr "Ajouter un destinataire de substitution"
@@ -443,8 +443,8 @@ msgstr "Administrateur"
msgid "Advanced Options" msgid "Advanced Options"
msgstr "Options avancées" msgstr "Options avancées"
#: packages/ui/primitives/document-flow/add-fields.tsx:573 #: packages/ui/primitives/document-flow/add-fields.tsx:576
#: packages/ui/primitives/template-flow/add-template-fields.tsx:406 #: packages/ui/primitives/template-flow/add-template-fields.tsx:414
msgid "Advanced settings" msgid "Advanced settings"
msgstr "Paramètres avancés" msgstr "Paramètres avancés"
@@ -500,11 +500,11 @@ msgstr "En attente d'approbation"
msgid "Before you get started, please confirm your email address by clicking the button below:" msgid "Before you get started, please confirm your email address by clicking the button below:"
msgstr "Avant de commencer, veuillez confirmer votre adresse email en cliquant sur le bouton ci-dessous :" msgstr "Avant de commencer, veuillez confirmer votre adresse email en cliquant sur le bouton ci-dessous :"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:377 #: packages/ui/primitives/signature-pad/signature-pad.tsx:383
msgid "Black" msgid "Black"
msgstr "Noir" msgstr "Noir"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:391 #: packages/ui/primitives/signature-pad/signature-pad.tsx:397
msgid "Blue" msgid "Blue"
msgstr "Bleu" msgstr "Bleu"
@@ -550,6 +550,10 @@ msgstr "Ccers"
msgid "Character Limit" msgid "Character Limit"
msgstr "Limite de caractères" msgstr "Limite de caractères"
#: packages/ui/primitives/document-flow/types.ts:58
msgid "Checkbox"
msgstr "Case à cocher"
#: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197 #: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197
msgid "Checkbox values" msgid "Checkbox values"
msgstr "Valeurs de case à cocher" msgstr "Valeurs de case à cocher"
@@ -558,7 +562,7 @@ msgstr "Valeurs de case à cocher"
msgid "Clear filters" msgid "Clear filters"
msgstr "Effacer les filtres" msgstr "Effacer les filtres"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:411 #: packages/ui/primitives/signature-pad/signature-pad.tsx:417
msgid "Clear Signature" msgid "Clear Signature"
msgstr "Effacer la signature" msgstr "Effacer la signature"
@@ -585,8 +589,8 @@ msgstr "Document Terminé"
msgid "Configure Direct Recipient" msgid "Configure Direct Recipient"
msgstr "Configurer le destinataire direct" msgstr "Configurer le destinataire direct"
#: packages/ui/primitives/document-flow/add-fields.tsx:574 #: packages/ui/primitives/document-flow/add-fields.tsx:577
#: packages/ui/primitives/template-flow/add-template-fields.tsx:407 #: packages/ui/primitives/template-flow/add-template-fields.tsx:415
msgid "Configure the {0} field" msgid "Configure the {0} field"
msgstr "Configurer le champ {0}" msgstr "Configurer le champ {0}"
@@ -647,9 +651,9 @@ msgstr "Créer un compte"
msgid "Custom Text" msgid "Custom Text"
msgstr "Texte personnalisé" msgstr "Texte personnalisé"
#: packages/ui/primitives/document-flow/add-fields.tsx:927 #: packages/ui/primitives/document-flow/add-fields.tsx:934
#: packages/ui/primitives/document-flow/types.ts:53 #: packages/ui/primitives/document-flow/types.ts:53
#: packages/ui/primitives/template-flow/add-template-fields.tsx:690 #: packages/ui/primitives/template-flow/add-template-fields.tsx:729
msgid "Date" msgid "Date"
msgstr "Date" msgstr "Date"
@@ -666,7 +670,7 @@ msgstr "Décliner"
msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>" msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>"
msgstr "Vous n'avez pas demandé de changement de mot de passe ? Nous sommes ici pour vous aider à sécuriser votre compte, il suffit de <0>nous contacter.</0>" msgstr "Vous n'avez pas demandé de changement de mot de passe ? Nous sommes ici pour vous aider à sécuriser votre compte, il suffit de <0>nous contacter.</0>"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:570 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:578
msgid "Direct link receiver" msgid "Direct link receiver"
msgstr "Receveur de lien direct" msgstr "Receveur de lien direct"
@@ -788,8 +792,8 @@ msgstr "Brouillon"
msgid "Drag & drop your PDF here." msgid "Drag & drop your PDF here."
msgstr "Faites glisser et déposez votre PDF ici." msgstr "Faites glisser et déposez votre PDF ici."
#: packages/ui/primitives/document-flow/add-fields.tsx:1058 #: packages/ui/primitives/document-flow/add-fields.tsx:1065
#: packages/ui/primitives/template-flow/add-template-fields.tsx:820 #: packages/ui/primitives/template-flow/add-template-fields.tsx:860
msgid "Dropdown" msgid "Dropdown"
msgstr "Liste déroulante" msgstr "Liste déroulante"
@@ -798,14 +802,14 @@ msgid "Dropdown options"
msgstr "Options de liste déroulante" msgstr "Options de liste déroulante"
#: packages/lib/constants/document.ts:28 #: packages/lib/constants/document.ts:28
#: packages/ui/primitives/document-flow/add-fields.tsx:875 #: packages/ui/primitives/document-flow/add-fields.tsx:882
#: packages/ui/primitives/document-flow/add-signature.tsx:272 #: packages/ui/primitives/document-flow/add-signature.tsx:272
#: packages/ui/primitives/document-flow/add-signers.tsx:512 #: packages/ui/primitives/document-flow/add-signers.tsx:512
#: packages/ui/primitives/document-flow/add-signers.tsx:519 #: packages/ui/primitives/document-flow/add-signers.tsx:519
#: packages/ui/primitives/document-flow/types.ts:54 #: packages/ui/primitives/document-flow/types.ts:54
#: packages/ui/primitives/template-flow/add-template-fields.tsx:638 #: packages/ui/primitives/template-flow/add-template-fields.tsx:677
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:463 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:471
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:470 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:478
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -825,7 +829,7 @@ msgstr "Email renvoyé"
msgid "Email sent" msgid "Email sent"
msgstr "Email envoyé" msgstr "Email envoyé"
#: packages/ui/primitives/document-flow/add-fields.tsx:1123 #: packages/ui/primitives/document-flow/add-fields.tsx:1130
msgid "Empty field" msgid "Empty field"
msgstr "Champ vide" msgstr "Champ vide"
@@ -834,11 +838,12 @@ msgid "Enable Direct Link Signing"
msgstr "Activer la signature de lien direct" msgstr "Activer la signature de lien direct"
#: packages/ui/primitives/document-flow/add-signers.tsx:401 #: packages/ui/primitives/document-flow/add-signers.tsx:401
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:362 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:370
msgid "Enable signing order" msgid "Enable signing order"
msgstr "Activer l'ordre de signature" msgstr "Activer l'ordre de signature"
#: packages/ui/primitives/document-flow/add-fields.tsx:795 #: packages/ui/primitives/document-flow/add-fields.tsx:802
#: packages/ui/primitives/template-flow/add-template-fields.tsx:597
msgid "Enable Typed Signatures" msgid "Enable Typed Signatures"
msgstr "Activer les signatures tapées" msgstr "Activer les signatures tapées"
@@ -926,7 +931,7 @@ msgstr "Authentification d'action de destinataire globale"
msgid "Go Back" msgid "Go Back"
msgstr "Retourner" msgstr "Retourner"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:398 #: packages/ui/primitives/signature-pad/signature-pad.tsx:404
msgid "Green" msgid "Green"
msgstr "Vert" msgstr "Vert"
@@ -1016,14 +1021,14 @@ msgstr "Message <0>(Optionnel)</0>"
msgid "Min" msgid "Min"
msgstr "Min" msgstr "Min"
#: packages/ui/primitives/document-flow/add-fields.tsx:901 #: packages/ui/primitives/document-flow/add-fields.tsx:908
#: packages/ui/primitives/document-flow/add-signature.tsx:298 #: packages/ui/primitives/document-flow/add-signature.tsx:298
#: packages/ui/primitives/document-flow/add-signers.tsx:550 #: packages/ui/primitives/document-flow/add-signers.tsx:550
#: packages/ui/primitives/document-flow/add-signers.tsx:556 #: packages/ui/primitives/document-flow/add-signers.tsx:556
#: packages/ui/primitives/document-flow/types.ts:55 #: packages/ui/primitives/document-flow/types.ts:55
#: packages/ui/primitives/template-flow/add-template-fields.tsx:664 #: packages/ui/primitives/template-flow/add-template-fields.tsx:703
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:498 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:506
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:504 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:512
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
@@ -1039,8 +1044,8 @@ msgstr "Nécessite une signature"
msgid "Needs to view" msgid "Needs to view"
msgstr "Nécessite une visualisation" msgstr "Nécessite une visualisation"
#: packages/ui/primitives/document-flow/add-fields.tsx:686 #: packages/ui/primitives/document-flow/add-fields.tsx:693
#: packages/ui/primitives/template-flow/add-template-fields.tsx:504 #: packages/ui/primitives/template-flow/add-template-fields.tsx:516
msgid "No recipient matching this description was found." msgid "No recipient matching this description was found."
msgstr "Aucun destinataire correspondant à cette description n'a été trouvé." msgstr "Aucun destinataire correspondant à cette description n'a été trouvé."
@@ -1048,8 +1053,8 @@ msgstr "Aucun destinataire correspondant à cette description n'a été trouvé.
msgid "No recipients" msgid "No recipients"
msgstr "Aucun destinataire" msgstr "Aucun destinataire"
#: packages/ui/primitives/document-flow/add-fields.tsx:701 #: packages/ui/primitives/document-flow/add-fields.tsx:708
#: packages/ui/primitives/template-flow/add-template-fields.tsx:519 #: packages/ui/primitives/template-flow/add-template-fields.tsx:531
msgid "No recipients with this role" msgid "No recipients with this role"
msgstr "Aucun destinataire avec ce rôle" msgstr "Aucun destinataire avec ce rôle"
@@ -1077,9 +1082,9 @@ msgstr "Aucune valeur trouvée."
msgid "None" msgid "None"
msgstr "Aucun" msgstr "Aucun"
#: packages/ui/primitives/document-flow/add-fields.tsx:979 #: packages/ui/primitives/document-flow/add-fields.tsx:986
#: packages/ui/primitives/document-flow/types.ts:56 #: packages/ui/primitives/document-flow/types.ts:56
#: packages/ui/primitives/template-flow/add-template-fields.tsx:742 #: packages/ui/primitives/template-flow/add-template-fields.tsx:781
msgid "Number" msgid "Number"
msgstr "Numéro" msgstr "Numéro"
@@ -1170,7 +1175,7 @@ msgstr "Veuillez confirmer votre adresse email"
msgid "Please try again or contact our support." msgid "Please try again or contact our support."
msgstr "Veuillez réessayer ou contacter notre support." msgstr "Veuillez réessayer ou contacter notre support."
#: packages/ui/primitives/template-flow/add-template-fields.tsx:768 #: packages/ui/primitives/document-flow/types.ts:57
msgid "Radio" msgid "Radio"
msgstr "Radio" msgstr "Radio"
@@ -1213,7 +1218,7 @@ msgstr "E-mail de destinataire supprimé"
msgid "Recipient signing request email" msgid "Recipient signing request email"
msgstr "E-mail de demande de signature de destinataire" msgstr "E-mail de demande de signature de destinataire"
#: packages/ui/primitives/signature-pad/signature-pad.tsx:384 #: packages/ui/primitives/signature-pad/signature-pad.tsx:390
msgid "Red" msgid "Red"
msgstr "Rouge" msgstr "Rouge"
@@ -1250,7 +1255,7 @@ msgstr "Rappel : Veuillez {recipientActionVerb} ce document"
msgid "Reminder: Please {recipientActionVerb} your document" msgid "Reminder: Please {recipientActionVerb} your document"
msgstr "Rappel : Veuillez {recipientActionVerb} votre document" msgstr "Rappel : Veuillez {recipientActionVerb} votre document"
#: packages/ui/primitives/document-flow/add-fields.tsx:1110 #: packages/ui/primitives/document-flow/add-fields.tsx:1117
msgid "Remove" msgid "Remove"
msgstr "Retirer" msgstr "Retirer"
@@ -1282,7 +1287,7 @@ msgstr "Lignes par page"
msgid "Save" msgid "Save"
msgstr "Sauvegarder" msgstr "Sauvegarder"
#: packages/ui/primitives/template-flow/add-template-fields.tsx:854 #: packages/ui/primitives/template-flow/add-template-fields.tsx:893
msgid "Save Template" msgid "Save Template"
msgstr "Sauvegarder le modèle" msgstr "Sauvegarder le modèle"
@@ -1291,6 +1296,7 @@ msgid "Search languages..."
msgstr "Rechercher des langues..." msgstr "Rechercher des langues..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115 #: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115
#: packages/ui/primitives/document-flow/types.ts:59
msgid "Select" msgid "Select"
msgstr "Sélectionner" msgstr "Sélectionner"
@@ -1354,7 +1360,7 @@ msgid "Share your signing experience!"
msgstr "Partagez votre expérience de signature !" msgstr "Partagez votre expérience de signature !"
#: packages/ui/primitives/document-flow/add-signers.tsx:709 #: packages/ui/primitives/document-flow/add-signers.tsx:709
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:655 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:663
msgid "Show advanced settings" msgid "Show advanced settings"
msgstr "Afficher les paramètres avancés" msgstr "Afficher les paramètres avancés"
@@ -1370,11 +1376,11 @@ msgstr "Signer le document"
msgid "Sign In" msgid "Sign In"
msgstr "Se connecter" msgstr "Se connecter"
#: packages/ui/primitives/document-flow/add-fields.tsx:823 #: packages/ui/primitives/document-flow/add-fields.tsx:830
#: packages/ui/primitives/document-flow/add-signature.tsx:323 #: packages/ui/primitives/document-flow/add-signature.tsx:323
#: packages/ui/primitives/document-flow/field-icon.tsx:52 #: packages/ui/primitives/document-flow/field-icon.tsx:52
#: packages/ui/primitives/document-flow/types.ts:49 #: packages/ui/primitives/document-flow/types.ts:49
#: packages/ui/primitives/template-flow/add-template-fields.tsx:586 #: packages/ui/primitives/template-flow/add-template-fields.tsx:625
msgid "Signature" msgid "Signature"
msgstr "Signature" msgstr "Signature"
@@ -1457,9 +1463,9 @@ msgstr "Email d'équipe supprimé pour {teamName} sur Documenso"
msgid "Template title" msgid "Template title"
msgstr "Titre du modèle" msgstr "Titre du modèle"
#: packages/ui/primitives/document-flow/add-fields.tsx:953 #: packages/ui/primitives/document-flow/add-fields.tsx:960
#: packages/ui/primitives/document-flow/types.ts:52 #: packages/ui/primitives/document-flow/types.ts:52
#: packages/ui/primitives/template-flow/add-template-fields.tsx:716 #: packages/ui/primitives/template-flow/add-template-fields.tsx:755
msgid "Text" msgid "Text"
msgstr "Texte" msgstr "Texte"
@@ -1554,7 +1560,7 @@ msgstr "Cela peut être remplacé par le paramétrage direct des exigences d'aut
msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support."
msgstr "Ce document ne peut pas être récupéré, si vous souhaitez contester la raison des documents futurs, veuillez contacter le support." msgstr "Ce document ne peut pas être récupéré, si vous souhaitez contester la raison des documents futurs, veuillez contacter le support."
#: packages/ui/primitives/document-flow/add-fields.tsx:757 #: packages/ui/primitives/document-flow/add-fields.tsx:764
msgid "This document has already been sent to this recipient. You can no longer edit this recipient." msgid "This document has already been sent to this recipient. You can no longer edit this recipient."
msgstr "Ce document a déjà été envoyé à ce destinataire. Vous ne pouvez plus modifier ce destinataire." msgstr "Ce document a déjà été envoyé à ce destinataire. Vous ne pouvez plus modifier ce destinataire."
@@ -1585,7 +1591,7 @@ msgstr "Cet e-mail est envoyé au destinataire lui demandant de signer le docume
msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet." msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet."
msgstr "Cet e-mail sera envoyé au destinataire qui vient de signer le document, s'il y a encore d'autres destinataires qui n'ont pas signé." msgstr "Cet e-mail sera envoyé au destinataire qui vient de signer le document, s'il y a encore d'autres destinataires qui n'ont pas signé."
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:573 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:581
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
msgstr "Ce champ ne peut pas être modifié ou supprimé. Lorsque vous partagez le lien direct de ce modèle ou l'ajoutez à votre profil public, toute personne qui y accède peut saisir son nom et son email, et remplir les champs qui lui sont attribués." msgstr "Ce champ ne peut pas être modifié ou supprimé. Lorsque vous partagez le lien direct de ce modèle ou l'ajoutez à votre profil public, toute personne qui y accède peut saisir son nom et son email, et remplir les champs qui lui sont attribués."
@@ -1593,7 +1599,7 @@ msgstr "Ce champ ne peut pas être modifié ou supprimé. Lorsque vous partagez
msgid "This is how the document will reach the recipients once the document is ready for signing." msgid "This is how the document will reach the recipients once the document is ready for signing."
msgstr "Voici comment le document atteindra les destinataires une fois qu'il sera prêt à être signé." msgstr "Voici comment le document atteindra les destinataires une fois qu'il sera prêt à être signé."
#: packages/ui/primitives/document-flow/add-fields.tsx:1090 #: packages/ui/primitives/document-flow/add-fields.tsx:1097
msgid "This recipient can no longer be modified as they have signed a field, or completed the document." msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr "Ce destinataire ne peut plus être modifié car il a signé un champ ou complété le document." msgstr "Ce destinataire ne peut plus être modifié car il a signé un champ ou complété le document."
@@ -1622,8 +1628,8 @@ msgstr "Fuseau horaire"
msgid "Title" msgid "Title"
msgstr "Titre" msgstr "Titre"
#: packages/ui/primitives/document-flow/add-fields.tsx:1073 #: packages/ui/primitives/document-flow/add-fields.tsx:1080
#: packages/ui/primitives/template-flow/add-template-fields.tsx:834 #: packages/ui/primitives/template-flow/add-template-fields.tsx:873
msgid "To proceed further, please set at least one value for the {0} field." msgid "To proceed further, please set at least one value for the {0} field."
msgstr "Pour continuer, veuillez définir au moins une valeur pour le champ {0}." msgstr "Pour continuer, veuillez définir au moins une valeur pour le champ {0}."
@@ -1808,4 +1814,3 @@ msgstr "Votre mot de passe a été mis à jour."
#: packages/email/templates/team-delete.tsx:32 #: packages/email/templates/team-delete.tsx:32
msgid "Your team has been deleted" msgid "Your team has been deleted"
msgstr "Votre équipe a été supprimée" msgstr "Votre équipe a été supprimée"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n" "Language: fr\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: French\n" "Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -602,4 +602,3 @@ msgstr "Vous pouvez auto-héberger Documenso gratuitement ou utiliser notre vers
#: apps/marketing/src/components/(marketing)/carousel.tsx:272 #: apps/marketing/src/components/(marketing)/carousel.tsx:272
msgid "Your browser does not support the video tag." msgid "Your browser does not support the video tag."
msgstr "Votre navigateur ne prend pas en charge la balise vidéo." msgstr "Votre navigateur ne prend pas en charge la balise vidéo."

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: pl\n" "Language: pl\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Polish\n" "Language-Team: Polish\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
@@ -414,11 +414,11 @@ msgstr "Dodaj kolejną wartość"
msgid "Add myself" msgid "Add myself"
msgstr "Dodaj siebie" msgstr "Dodaj siebie"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:637 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:645
msgid "Add Myself" msgid "Add Myself"
msgstr "Dodaj siebie" msgstr "Dodaj siebie"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:623 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:631
msgid "Add Placeholder Recipient" msgid "Add Placeholder Recipient"
msgstr "Dodaj odbiorcę zastępczego" msgstr "Dodaj odbiorcę zastępczego"
@@ -443,8 +443,8 @@ msgstr "Administrator"
msgid "Advanced Options" msgid "Advanced Options"
msgstr "Opcje zaawansowane" msgstr "Opcje zaawansowane"
#: packages/ui/primitives/document-flow/add-fields.tsx:573 #: packages/ui/primitives/document-flow/add-fields.tsx:576
#: packages/ui/primitives/template-flow/add-template-fields.tsx:406 #: packages/ui/primitives/template-flow/add-template-fields.tsx:409
msgid "Advanced settings" msgid "Advanced settings"
msgstr "Ustawienia zaawansowane" msgstr "Ustawienia zaawansowane"
@@ -550,6 +550,10 @@ msgstr "Kserokopie"
msgid "Character Limit" msgid "Character Limit"
msgstr "Limit znaków" msgstr "Limit znaków"
#: packages/ui/primitives/document-flow/types.ts:58
msgid "Checkbox"
msgstr "Checkbox"
#: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197 #: packages/ui/primitives/document-flow/field-items-advanced-settings/checkbox-field.tsx:197
msgid "Checkbox values" msgid "Checkbox values"
msgstr "Wartości checkboxa" msgstr "Wartości checkboxa"
@@ -585,8 +589,8 @@ msgstr "Dokument zakończony"
msgid "Configure Direct Recipient" msgid "Configure Direct Recipient"
msgstr "Skonfiguruj bezpośredniego odbiorcę" msgstr "Skonfiguruj bezpośredniego odbiorcę"
#: packages/ui/primitives/document-flow/add-fields.tsx:574 #: packages/ui/primitives/document-flow/add-fields.tsx:577
#: packages/ui/primitives/template-flow/add-template-fields.tsx:407 #: packages/ui/primitives/template-flow/add-template-fields.tsx:410
msgid "Configure the {0} field" msgid "Configure the {0} field"
msgstr "Skonfiguruj pole {0}" msgstr "Skonfiguruj pole {0}"
@@ -647,9 +651,9 @@ msgstr "Utwórz konto"
msgid "Custom Text" msgid "Custom Text"
msgstr "Tekst niestandardowy" msgstr "Tekst niestandardowy"
#: packages/ui/primitives/document-flow/add-fields.tsx:927 #: packages/ui/primitives/document-flow/add-fields.tsx:934
#: packages/ui/primitives/document-flow/types.ts:53 #: packages/ui/primitives/document-flow/types.ts:53
#: packages/ui/primitives/template-flow/add-template-fields.tsx:690 #: packages/ui/primitives/template-flow/add-template-fields.tsx:697
msgid "Date" msgid "Date"
msgstr "Data" msgstr "Data"
@@ -666,7 +670,7 @@ msgstr "Odmów"
msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>" msgid "Didn't request a password change? We are here to help you secure your account, just <0>contact us.</0>"
msgstr "Nie prosiłeś o zmianę hasła? Jesteśmy tutaj, aby pomóc Ci zabezpieczyć swoje konto, po prostu <0>skontaktuj się z nami.</0>" msgstr "Nie prosiłeś o zmianę hasła? Jesteśmy tutaj, aby pomóc Ci zabezpieczyć swoje konto, po prostu <0>skontaktuj się z nami.</0>"
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:570 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:578
msgid "Direct link receiver" msgid "Direct link receiver"
msgstr "Odbiorca linku bezpośredniego" msgstr "Odbiorca linku bezpośredniego"
@@ -788,8 +792,8 @@ msgstr "Robocza wersja"
msgid "Drag & drop your PDF here." msgid "Drag & drop your PDF here."
msgstr "Przeciągnij i upuść swój PDF tutaj." msgstr "Przeciągnij i upuść swój PDF tutaj."
#: packages/ui/primitives/document-flow/add-fields.tsx:1058 #: packages/ui/primitives/document-flow/add-fields.tsx:1065
#: packages/ui/primitives/template-flow/add-template-fields.tsx:820 #: packages/ui/primitives/template-flow/add-template-fields.tsx:827
msgid "Dropdown" msgid "Dropdown"
msgstr "Lista rozwijana" msgstr "Lista rozwijana"
@@ -798,14 +802,14 @@ msgid "Dropdown options"
msgstr "Opcje rozwijane" msgstr "Opcje rozwijane"
#: packages/lib/constants/document.ts:28 #: packages/lib/constants/document.ts:28
#: packages/ui/primitives/document-flow/add-fields.tsx:875 #: packages/ui/primitives/document-flow/add-fields.tsx:882
#: packages/ui/primitives/document-flow/add-signature.tsx:272 #: packages/ui/primitives/document-flow/add-signature.tsx:272
#: packages/ui/primitives/document-flow/add-signers.tsx:512 #: packages/ui/primitives/document-flow/add-signers.tsx:512
#: packages/ui/primitives/document-flow/add-signers.tsx:519 #: packages/ui/primitives/document-flow/add-signers.tsx:519
#: packages/ui/primitives/document-flow/types.ts:54 #: packages/ui/primitives/document-flow/types.ts:54
#: packages/ui/primitives/template-flow/add-template-fields.tsx:638 #: packages/ui/primitives/template-flow/add-template-fields.tsx:645
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:463 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:471
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:470 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:478
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -825,7 +829,7 @@ msgstr "E-mail wysłany ponownie"
msgid "Email sent" msgid "Email sent"
msgstr "E-mail wysłany" msgstr "E-mail wysłany"
#: packages/ui/primitives/document-flow/add-fields.tsx:1123 #: packages/ui/primitives/document-flow/add-fields.tsx:1130
msgid "Empty field" msgid "Empty field"
msgstr "Puste pole" msgstr "Puste pole"
@@ -834,11 +838,11 @@ msgid "Enable Direct Link Signing"
msgstr "Włącz podpisywanie linku bezpośredniego" msgstr "Włącz podpisywanie linku bezpośredniego"
#: packages/ui/primitives/document-flow/add-signers.tsx:401 #: packages/ui/primitives/document-flow/add-signers.tsx:401
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:362 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:370
msgid "Enable signing order" msgid "Enable signing order"
msgstr "Włącz kolejność podpisów" msgstr "Włącz kolejność podpisów"
#: packages/ui/primitives/document-flow/add-fields.tsx:795 #: packages/ui/primitives/document-flow/add-fields.tsx:802
msgid "Enable Typed Signatures" msgid "Enable Typed Signatures"
msgstr "Włącz podpisy typu pisanego" msgstr "Włącz podpisy typu pisanego"
@@ -1016,14 +1020,14 @@ msgstr "Wiadomość <0>(Opcjonalnie)</0>"
msgid "Min" msgid "Min"
msgstr "Min" msgstr "Min"
#: packages/ui/primitives/document-flow/add-fields.tsx:901 #: packages/ui/primitives/document-flow/add-fields.tsx:908
#: packages/ui/primitives/document-flow/add-signature.tsx:298 #: packages/ui/primitives/document-flow/add-signature.tsx:298
#: packages/ui/primitives/document-flow/add-signers.tsx:550 #: packages/ui/primitives/document-flow/add-signers.tsx:550
#: packages/ui/primitives/document-flow/add-signers.tsx:556 #: packages/ui/primitives/document-flow/add-signers.tsx:556
#: packages/ui/primitives/document-flow/types.ts:55 #: packages/ui/primitives/document-flow/types.ts:55
#: packages/ui/primitives/template-flow/add-template-fields.tsx:664 #: packages/ui/primitives/template-flow/add-template-fields.tsx:671
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:498 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:506
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:504 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:512
msgid "Name" msgid "Name"
msgstr "Nazwa" msgstr "Nazwa"
@@ -1039,8 +1043,8 @@ msgstr "Wymaga podpisania"
msgid "Needs to view" msgid "Needs to view"
msgstr "Wymaga obejrzenia" msgstr "Wymaga obejrzenia"
#: packages/ui/primitives/document-flow/add-fields.tsx:686 #: packages/ui/primitives/document-flow/add-fields.tsx:693
#: packages/ui/primitives/template-flow/add-template-fields.tsx:504 #: packages/ui/primitives/template-flow/add-template-fields.tsx:511
msgid "No recipient matching this description was found." msgid "No recipient matching this description was found."
msgstr "Nie znaleziono odbiorcy pasującego do tego opisu." msgstr "Nie znaleziono odbiorcy pasującego do tego opisu."
@@ -1048,8 +1052,8 @@ msgstr "Nie znaleziono odbiorcy pasującego do tego opisu."
msgid "No recipients" msgid "No recipients"
msgstr "Brak odbiorców" msgstr "Brak odbiorców"
#: packages/ui/primitives/document-flow/add-fields.tsx:701 #: packages/ui/primitives/document-flow/add-fields.tsx:708
#: packages/ui/primitives/template-flow/add-template-fields.tsx:519 #: packages/ui/primitives/template-flow/add-template-fields.tsx:526
msgid "No recipients with this role" msgid "No recipients with this role"
msgstr "Brak odbiorców z tą rolą" msgstr "Brak odbiorców z tą rolą"
@@ -1077,9 +1081,9 @@ msgstr "Nie znaleziono wartości."
msgid "None" msgid "None"
msgstr "Brak" msgstr "Brak"
#: packages/ui/primitives/document-flow/add-fields.tsx:979 #: packages/ui/primitives/document-flow/add-fields.tsx:986
#: packages/ui/primitives/document-flow/types.ts:56 #: packages/ui/primitives/document-flow/types.ts:56
#: packages/ui/primitives/template-flow/add-template-fields.tsx:742 #: packages/ui/primitives/template-flow/add-template-fields.tsx:749
msgid "Number" msgid "Number"
msgstr "Numer" msgstr "Numer"
@@ -1170,7 +1174,8 @@ msgstr "Proszę potwierdzić swój adres email"
msgid "Please try again or contact our support." msgid "Please try again or contact our support."
msgstr "Spróbuj ponownie lub skontaktuj się z naszym wsparciem." msgstr "Spróbuj ponownie lub skontaktuj się z naszym wsparciem."
#: packages/ui/primitives/template-flow/add-template-fields.tsx:768 #: packages/ui/primitives/document-flow/types.ts:57
#: packages/ui/primitives/template-flow/add-template-fields.tsx:775
msgid "Radio" msgid "Radio"
msgstr "Radio" msgstr "Radio"
@@ -1250,7 +1255,7 @@ msgstr "Przypomnienie: Proszę {recipientActionVerb} ten dokument"
msgid "Reminder: Please {recipientActionVerb} your document" msgid "Reminder: Please {recipientActionVerb} your document"
msgstr "Przypomnienie: Proszę {recipientActionVerb} Twój dokument" msgstr "Przypomnienie: Proszę {recipientActionVerb} Twój dokument"
#: packages/ui/primitives/document-flow/add-fields.tsx:1110 #: packages/ui/primitives/document-flow/add-fields.tsx:1117
msgid "Remove" msgid "Remove"
msgstr "Usuń" msgstr "Usuń"
@@ -1282,7 +1287,7 @@ msgstr "Wiersze na stronę"
msgid "Save" msgid "Save"
msgstr "Zapisz" msgstr "Zapisz"
#: packages/ui/primitives/template-flow/add-template-fields.tsx:854 #: packages/ui/primitives/template-flow/add-template-fields.tsx:861
msgid "Save Template" msgid "Save Template"
msgstr "Zapisz szablon" msgstr "Zapisz szablon"
@@ -1291,6 +1296,7 @@ msgid "Search languages..."
msgstr "Szukaj języków..." msgstr "Szukaj języków..."
#: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115 #: packages/ui/primitives/document-flow/field-items-advanced-settings/dropdown-field.tsx:115
#: packages/ui/primitives/document-flow/types.ts:59
msgid "Select" msgid "Select"
msgstr "Wybierz" msgstr "Wybierz"
@@ -1354,7 +1360,7 @@ msgid "Share your signing experience!"
msgstr "Podziel się swoim doświadczeniem podpisywania!" msgstr "Podziel się swoim doświadczeniem podpisywania!"
#: packages/ui/primitives/document-flow/add-signers.tsx:709 #: packages/ui/primitives/document-flow/add-signers.tsx:709
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:655 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:663
msgid "Show advanced settings" msgid "Show advanced settings"
msgstr "Pokaż ustawienia zaawansowane" msgstr "Pokaż ustawienia zaawansowane"
@@ -1370,11 +1376,11 @@ msgstr "Podpisz dokument"
msgid "Sign In" msgid "Sign In"
msgstr "Zaloguj się" msgstr "Zaloguj się"
#: packages/ui/primitives/document-flow/add-fields.tsx:823 #: packages/ui/primitives/document-flow/add-fields.tsx:830
#: packages/ui/primitives/document-flow/add-signature.tsx:323 #: packages/ui/primitives/document-flow/add-signature.tsx:323
#: packages/ui/primitives/document-flow/field-icon.tsx:52 #: packages/ui/primitives/document-flow/field-icon.tsx:52
#: packages/ui/primitives/document-flow/types.ts:49 #: packages/ui/primitives/document-flow/types.ts:49
#: packages/ui/primitives/template-flow/add-template-fields.tsx:586 #: packages/ui/primitives/template-flow/add-template-fields.tsx:593
msgid "Signature" msgid "Signature"
msgstr "Podpis" msgstr "Podpis"
@@ -1457,9 +1463,9 @@ msgstr "Email zespołowy usunięty dla {teamName} na Documenso"
msgid "Template title" msgid "Template title"
msgstr "Tytuł szablonu" msgstr "Tytuł szablonu"
#: packages/ui/primitives/document-flow/add-fields.tsx:953 #: packages/ui/primitives/document-flow/add-fields.tsx:960
#: packages/ui/primitives/document-flow/types.ts:52 #: packages/ui/primitives/document-flow/types.ts:52
#: packages/ui/primitives/template-flow/add-template-fields.tsx:716 #: packages/ui/primitives/template-flow/add-template-fields.tsx:723
msgid "Text" msgid "Text"
msgstr "Tekst" msgstr "Tekst"
@@ -1554,7 +1560,7 @@ msgstr "To można nadpisać, ustawiając wymagania dotyczące uwierzytelniania b
msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support." msgid "This document can not be recovered, if you would like to dispute the reason for future documents please contact support."
msgstr "Dokument ten nie może być odzyskany. Jeśli chcesz zakwestionować przyczynę przyszłych dokumentów, skontaktuj się z administracją." msgstr "Dokument ten nie może być odzyskany. Jeśli chcesz zakwestionować przyczynę przyszłych dokumentów, skontaktuj się z administracją."
#: packages/ui/primitives/document-flow/add-fields.tsx:757 #: packages/ui/primitives/document-flow/add-fields.tsx:764
msgid "This document has already been sent to this recipient. You can no longer edit this recipient." msgid "This document has already been sent to this recipient. You can no longer edit this recipient."
msgstr "Ten dokument został już wysłany do tego odbiorcy. Nie można już edytować tego odbiorcy." msgstr "Ten dokument został już wysłany do tego odbiorcy. Nie można już edytować tego odbiorcy."
@@ -1585,7 +1591,7 @@ msgstr "Ten e-mail jest wysyłany do odbiorcy, prosząc go o podpisanie dokument
msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet." msgid "This email will be sent to the recipient who has just signed the document, if there are still other recipients who have not signed yet."
msgstr "Ten e-mail zostanie wysłany do odbiorcy, który właśnie podpisał dokument, jeśli są jeszcze inni odbiorcy, którzy nie podpisali." msgstr "Ten e-mail zostanie wysłany do odbiorcy, który właśnie podpisał dokument, jeśli są jeszcze inni odbiorcy, którzy nie podpisali."
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:573 #: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:581
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them." msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
msgstr "To pole nie może być modyfikowane ani usuwane. Po udostępnieniu bezpośredniego linku do tego szablonu lub dodaniu go do swojego publicznego profilu, każdy, kto się w nim dostanie, może wpisać swoje imię i email oraz wypełnić przypisane mu pola." msgstr "To pole nie może być modyfikowane ani usuwane. Po udostępnieniu bezpośredniego linku do tego szablonu lub dodaniu go do swojego publicznego profilu, każdy, kto się w nim dostanie, może wpisać swoje imię i email oraz wypełnić przypisane mu pola."
@@ -1593,7 +1599,7 @@ msgstr "To pole nie może być modyfikowane ani usuwane. Po udostępnieniu bezpo
msgid "This is how the document will reach the recipients once the document is ready for signing." msgid "This is how the document will reach the recipients once the document is ready for signing."
msgstr "W ten sposób dokument dotrze do odbiorców, gdy tylko dokument będzie gotowy do podpisania." msgstr "W ten sposób dokument dotrze do odbiorców, gdy tylko dokument będzie gotowy do podpisania."
#: packages/ui/primitives/document-flow/add-fields.tsx:1090 #: packages/ui/primitives/document-flow/add-fields.tsx:1097
msgid "This recipient can no longer be modified as they have signed a field, or completed the document." msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr "Ten odbiorca nie może być już modyfikowany, ponieważ podpisał pole lub ukończył dokument." msgstr "Ten odbiorca nie może być już modyfikowany, ponieważ podpisał pole lub ukończył dokument."
@@ -1622,8 +1628,8 @@ msgstr "Strefa czasowa"
msgid "Title" msgid "Title"
msgstr "Tytuł" msgstr "Tytuł"
#: packages/ui/primitives/document-flow/add-fields.tsx:1073 #: packages/ui/primitives/document-flow/add-fields.tsx:1080
#: packages/ui/primitives/template-flow/add-template-fields.tsx:834 #: packages/ui/primitives/template-flow/add-template-fields.tsx:841
msgid "To proceed further, please set at least one value for the {0} field." msgid "To proceed further, please set at least one value for the {0} field."
msgstr "Aby kontynuować, ustaw przynajmniej jedną wartość dla pola {0}." msgstr "Aby kontynuować, ustaw przynajmniej jedną wartość dla pola {0}."

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: pl\n" "Language: pl\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Polish\n" "Language-Team: Polish\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: pl\n" "Language: pl\n"
"Project-Id-Version: documenso-app\n" "Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-11-14 12:05\n" "PO-Revision-Date: 2024-11-20 11:56\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Polish\n" "Language-Team: Polish\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
@@ -50,19 +50,19 @@ msgstr "\"{placeholderEmail}\" w imieniu \"{0}\" zaprosił Cię do podpisania \"
msgid "\"{teamUrl}\" has invited you to sign \"example document\"." msgid "\"{teamUrl}\" has invited you to sign \"example document\"."
msgstr "\"{teamUrl}\" zaprosił Cię do podpisania \"przykładowego dokumentu\"." msgstr "\"{teamUrl}\" zaprosił Cię do podpisania \"przykładowego dokumentu\"."
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:79 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80
msgid "({0}) has invited you to approve this document" msgid "({0}) has invited you to approve this document"
msgstr "({0}) zaprosił Cię do zatwierdzenia tego dokumentu" msgstr "({0}) zaprosił Cię do zatwierdzenia tego dokumentu"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:76 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77
msgid "({0}) has invited you to sign this document" msgid "({0}) has invited you to sign this document"
msgstr "({0}) zaprosił Cię do podpisania tego dokumentu" msgstr "({0}) zaprosił Cię do podpisania tego dokumentu"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:73 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:74
msgid "({0}) has invited you to view this document" msgid "({0}) has invited you to view this document"
msgstr "({0}) zaprosił Cię do przeglądania tego dokumentu" msgstr "({0}) zaprosił Cię do przeglądania tego dokumentu"
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:311 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:313
msgid "{0, plural, one {(1 character over)} other {(# characters over)}}" msgid "{0, plural, one {(1 character over)} other {(# characters over)}}"
msgstr "{0, plural, one {(1 znak przekroczony)} other {(# znaków przekroczonych)}}" msgstr "{0, plural, one {(1 znak przekroczony)} other {(# znaków przekroczonych)}}"
@@ -84,6 +84,10 @@ msgstr "{0, plural, one {# miejsce} other {# miejsc}}"
msgid "{0, plural, one {<0>You have <1>1</1> pending team invitation</0>} other {<2>You have <3>#</3> pending team invitations</2>}}" msgid "{0, plural, one {<0>You have <1>1</1> pending team invitation</0>} other {<2>You have <3>#</3> pending team invitations</2>}}"
msgstr "{0, plural, one {<0>Masz <1>1</1> oczekujące zaproszenie do zespołu</0>} other {<2>Masz <3>#</3> oczekujących zaproszeń do zespołu</2>}}" msgstr "{0, plural, one {<0>Masz <1>1</1> oczekujące zaproszenie do zespołu</0>} other {<2>Masz <3>#</3> oczekujących zaproszeń do zespołu</2>}}"
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:196
msgid "{0, plural, one {1 matching field} other {# matching fields}}"
msgstr "{0, plural, one {1 pasujące pole} other {# pasujących pól}}"
#: apps/web/src/app/(dashboard)/documents/[id]/edit/document-edit-page-view.tsx:129 #: apps/web/src/app/(dashboard)/documents/[id]/edit/document-edit-page-view.tsx:129
msgid "{0, plural, one {1 Recipient} other {# Recipients}}" msgid "{0, plural, one {1 Recipient} other {# Recipients}}"
msgstr "{0, plural, one {1 Odbiorca} other {# Odbiorców}}" msgstr "{0, plural, one {1 Odbiorca} other {# Odbiorców}}"
@@ -96,6 +100,10 @@ msgstr "{0, plural, one {Czekam na 1 odbiorcę} other {Czekam na # odbiorców}}"
msgid "{0, plural, zero {Select values} other {# selected...}}" msgid "{0, plural, zero {Select values} other {# selected...}}"
msgstr "{0, plural, zero {Wybierz wartości} other {# wybranych...}}" msgstr "{0, plural, zero {Wybierz wartości} other {# wybranych...}}"
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:193
msgid "{0}"
msgstr "{0}"
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:249 #: apps/web/src/components/templates/manage-public-template-dialog.tsx:249
msgid "{0} direct signing templates" msgid "{0} direct signing templates"
msgstr "{0} bezpośrednich szablonów podpisu" msgstr "{0} bezpośrednich szablonów podpisu"
@@ -116,7 +124,7 @@ msgstr "{0} Odbiorca (ów)"
#~ msgid "{0} the document to complete the process." #~ msgid "{0} the document to complete the process."
#~ msgstr "{0} the document to complete the process." #~ msgstr "{0} the document to complete the process."
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:292 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:294
msgid "{charactersRemaining, plural, one {1 character remaining} other {{charactersRemaining} characters remaining}}" msgid "{charactersRemaining, plural, one {1 character remaining} other {{charactersRemaining} characters remaining}}"
msgstr "{charactersRemaining, plural, one {1 znak pozostały} other {{charactersRemaining} znaki pozostałe}}" msgstr "{charactersRemaining, plural, one {1 znak pozostały} other {{charactersRemaining} znaki pozostałe}}"
@@ -254,7 +262,7 @@ msgstr "Akceptowane zaproszenie do zespołu"
#: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:128 #: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:128
msgid "Account Authentication" msgid "Account Authentication"
msgstr "Autoryzacja konta" msgstr "Uwierzytelnianie konta"
#: apps/web/src/app/(dashboard)/admin/users/[id]/delete-user-dialog.tsx:51 #: apps/web/src/app/(dashboard)/admin/users/[id]/delete-user-dialog.tsx:51
#: apps/web/src/app/(dashboard)/settings/profile/delete-account-dialog.tsx:48 #: apps/web/src/app/(dashboard)/settings/profile/delete-account-dialog.tsx:48
@@ -263,7 +271,7 @@ msgstr "Konto usunięte"
#: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:119 #: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:119
msgid "Account Re-Authentication" msgid "Account Re-Authentication"
msgstr "Ponowna autoryzacja konta" msgstr "Ponowna Autoryzacja Konta"
#: apps/web/src/app/(unauthenticated)/articles/signature-disclosure/page.tsx:139 #: apps/web/src/app/(unauthenticated)/articles/signature-disclosure/page.tsx:139
msgid "Acknowledgment" msgid "Acknowledgment"
@@ -296,7 +304,7 @@ msgstr "Aktywny"
#: apps/web/src/app/(dashboard)/admin/stats/page.tsx:68 #: apps/web/src/app/(dashboard)/admin/stats/page.tsx:68
msgid "Active Subscriptions" msgid "Active Subscriptions"
msgstr "Aktywne subskrypcje" msgstr "Aktywne Subskrypcje"
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:189 #: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:189
msgid "Add" msgid "Add"
@@ -309,7 +317,7 @@ msgstr "Dodaj wszystkie istotne pola dla każdego odbiorcy."
#: apps/web/src/app/(dashboard)/templates/[id]/edit/edit-template.tsx:83 #: apps/web/src/app/(dashboard)/templates/[id]/edit/edit-template.tsx:83
msgid "Add all relevant placeholders for each recipient." msgid "Add all relevant placeholders for each recipient."
msgstr "Dodaj wszystkie istotne znaczniki dla każdego odbiorcy." msgstr "Dodaj wszystkie odpowiednie symbole zastępcze dla każdego odbiorcy."
#: apps/web/src/app/(dashboard)/settings/security/page.tsx:62 #: apps/web/src/app/(dashboard)/settings/security/page.tsx:62
msgid "Add an authenticator to serve as a secondary authentication method for signing documents." msgid "Add an authenticator to serve as a secondary authentication method for signing documents."
@@ -335,7 +343,7 @@ msgstr "Dodaj więcej"
#: apps/web/src/app/(dashboard)/settings/security/passkeys/create-passkey-dialog.tsx:146 #: apps/web/src/app/(dashboard)/settings/security/passkeys/create-passkey-dialog.tsx:146
#: apps/web/src/app/(dashboard)/settings/security/passkeys/create-passkey-dialog.tsx:154 #: apps/web/src/app/(dashboard)/settings/security/passkeys/create-passkey-dialog.tsx:154
msgid "Add passkey" msgid "Add passkey"
msgstr "Dodaj klucz hasła" msgstr "Dodaj hasło"
#: apps/web/src/app/(dashboard)/templates/[id]/edit/edit-template.tsx:82 #: apps/web/src/app/(dashboard)/templates/[id]/edit/edit-template.tsx:82
msgid "Add Placeholders" msgid "Add Placeholders"
@@ -359,7 +367,7 @@ msgstr "Dodaj osoby, które podpiszą dokument."
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:220 #: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:220
msgid "Add the recipients to create the document with" msgid "Add the recipients to create the document with"
msgstr "Dodaj odbiorców, aby stworzyć dokument" msgstr "Dodaj odbiorców, aby utworzyć dokument"
#: apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx:181 #: apps/web/src/app/(dashboard)/documents/[id]/edit-document.tsx:181
#~ msgid "Add the subject and message you wish to send to signers." #~ msgid "Add the subject and message you wish to send to signers."
@@ -474,6 +482,10 @@ msgstr "Wystąpił błąd podczas dodawania sygnatariuszy."
msgid "An error occurred while adding the fields." msgid "An error occurred while adding the fields."
msgstr "Wystąpił błąd podczas dodawania pól." msgstr "Wystąpił błąd podczas dodawania pól."
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:154
msgid "An error occurred while auto-signing the document, some fields may not be signed. Please review and manually sign any remaining fields."
msgstr "Wystąpił błąd podczas automatycznego podpisywania dokumentu, niektóre pola mogą nie być podpisane. Proszę sprawdzić i ręcznie podpisać wszystkie pozostałe pola."
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:176 #: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:176
msgid "An error occurred while creating document from template." msgid "An error occurred while creating document from template."
msgstr "Wystąpił błąd podczas tworzenia dokumentu z szablonu." msgstr "Wystąpił błąd podczas tworzenia dokumentu z szablonu."
@@ -748,7 +760,7 @@ msgstr "Baner zaktualizowany"
msgid "Basic details" msgid "Basic details"
msgstr "Podstawowe szczegóły" msgstr "Podstawowe szczegóły"
#: apps/web/src/app/(dashboard)/settings/billing/page.tsx:72 #: apps/web/src/app/(dashboard)/settings/billing/page.tsx:74
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/billing/page.tsx:61 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/billing/page.tsx:61
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:117 #: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:117
#: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:120 #: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:120
@@ -810,6 +822,7 @@ msgstr "Korzystając z funkcji podpisu elektronicznego, wyrażasz zgodę na prze
#: apps/web/src/app/(dashboard)/templates/duplicate-template-dialog.tsx:78 #: apps/web/src/app/(dashboard)/templates/duplicate-template-dialog.tsx:78
#: apps/web/src/app/(dashboard)/templates/move-template-dialog.tsx:119 #: apps/web/src/app/(dashboard)/templates/move-template-dialog.tsx:119
#: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:472 #: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:472
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:220
#: apps/web/src/app/(signing)/sign/[token]/document-action-auth-2fa.tsx:178 #: apps/web/src/app/(signing)/sign/[token]/document-action-auth-2fa.tsx:178
#: apps/web/src/app/(signing)/sign/[token]/document-action-auth-account.tsx:71 #: apps/web/src/app/(signing)/sign/[token]/document-action-auth-account.tsx:71
#: apps/web/src/app/(signing)/sign/[token]/document-action-auth-passkey.tsx:164 #: apps/web/src/app/(signing)/sign/[token]/document-action-auth-passkey.tsx:164
@@ -817,11 +830,11 @@ msgstr "Korzystając z funkcji podpisu elektronicznego, wyrażasz zgodę na prze
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:151 #: apps/web/src/app/(signing)/sign/[token]/form.tsx:151
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:220 #: apps/web/src/app/(signing)/sign/[token]/form.tsx:220
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:215 #: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:215
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:327 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:328
#: apps/web/src/app/(signing)/sign/[token]/reject-document-dialog.tsx:153 #: apps/web/src/app/(signing)/sign/[token]/reject-document-dialog.tsx:153
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:113 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:113
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:248 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:248
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:333 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:335
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/team-transfer-status.tsx:121 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/team-transfer-status.tsx:121
#: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:176 #: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:176
#: apps/web/src/components/(dashboard)/settings/webhooks/create-webhook-dialog.tsx:242 #: apps/web/src/components/(dashboard)/settings/webhooks/create-webhook-dialog.tsx:242
@@ -1780,7 +1793,7 @@ msgstr "Wprowadź swój adres e-mail, aby otrzymać ukończony dokument."
msgid "Enter your name" msgid "Enter your name"
msgstr "Wprowadź swoje imię" msgstr "Wprowadź swoje imię"
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:278 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:280
msgid "Enter your text here" msgid "Enter your text here"
msgstr "Wprowadź swój tekst tutaj" msgstr "Wprowadź swój tekst tutaj"
@@ -1799,6 +1812,7 @@ msgstr "Wprowadź swój tekst tutaj"
#: apps/web/src/app/(dashboard)/templates/duplicate-template-dialog.tsx:51 #: apps/web/src/app/(dashboard)/templates/duplicate-template-dialog.tsx:51
#: apps/web/src/app/(dashboard)/templates/move-template-dialog.tsx:56 #: apps/web/src/app/(dashboard)/templates/move-template-dialog.tsx:56
#: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:175 #: apps/web/src/app/(dashboard)/templates/use-template-dialog.tsx:175
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:152
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:122 #: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:122
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:151 #: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:151
#: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:212 #: apps/web/src/app/(signing)/sign/[token]/checkbox-field.tsx:212
@@ -2230,6 +2244,10 @@ msgstr "Zarządzaj wszystkimi zespołami, z którymi jesteś obecnie związany."
msgid "Manage and view template" msgid "Manage and view template"
msgstr "Zarządzaj i przeglądaj szablon" msgstr "Zarządzaj i przeglądaj szablon"
#: apps/web/src/app/(dashboard)/settings/billing/page.tsx:136
msgid "Manage billing"
msgstr "Zarządzaj fakturowaniem"
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:341 #: apps/web/src/components/templates/manage-public-template-dialog.tsx:341
msgid "Manage details for this public template" msgid "Manage details for this public template"
msgstr "Zarządzaj szczegółami tego publicznego szablonu" msgstr "Zarządzaj szczegółami tego publicznego szablonu"
@@ -2250,7 +2268,7 @@ msgstr "Zarządzaj kluczami dostępu"
msgid "Manage subscription" msgid "Manage subscription"
msgstr "Zarządzaj subskrypcją" msgstr "Zarządzaj subskrypcją"
#: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:66 #: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:67
msgid "Manage Subscription" msgid "Manage Subscription"
msgstr "Zarządzaj Subskrypcją" msgstr "Zarządzaj Subskrypcją"
@@ -2463,7 +2481,7 @@ msgstr "Nieobsługiwane"
msgid "Nothing to do" msgid "Nothing to do"
msgstr "Nic do zrobienia" msgstr "Nic do zrobienia"
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:270 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:271
msgid "Number" msgid "Number"
msgstr "Numer" msgstr "Numer"
@@ -2570,7 +2588,7 @@ msgstr "Nazwa klucza dostępu"
#: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:121 #: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:121
msgid "Passkey Re-Authentication" msgid "Passkey Re-Authentication"
msgstr "Ponowna autoryzacja za pomocą klucza" msgstr "Ponowna Autoryzacja Klucza Dostępu"
#: apps/web/src/app/(dashboard)/settings/security/page.tsx:106 #: apps/web/src/app/(dashboard)/settings/security/page.tsx:106
#: apps/web/src/app/(dashboard)/settings/security/passkeys/page.tsx:32 #: apps/web/src/app/(dashboard)/settings/security/passkeys/page.tsx:32
@@ -2627,7 +2645,7 @@ msgstr "Oczekujące Dokumenty"
#: apps/web/src/app/(dashboard)/admin/stats/page.tsx:89 #: apps/web/src/app/(dashboard)/admin/stats/page.tsx:89
msgid "Pending Documents" msgid "Pending Documents"
msgstr "Oczekujące zaproszenia" msgstr "Oczekujące dokumenty"
#: apps/web/src/app/(dashboard)/settings/teams/team-invitations.tsx:62 #: apps/web/src/app/(dashboard)/settings/teams/team-invitations.tsx:62
msgid "Pending invitations" msgid "Pending invitations"
@@ -2639,71 +2657,71 @@ msgstr "Oczekujący zespół usunięty."
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:134 #: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:134
msgid "Personal" msgid "Personal"
msgstr "Konto osobiste" msgstr "Osobiste"
#: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:77 #: apps/web/src/components/(dashboard)/layout/menu-switcher.tsx:77
msgid "Personal Account" msgid "Personal Account"
msgstr "Wybierz hasło" msgstr "Konto osobiste"
#: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:152 #: apps/web/src/app/(signing)/sign/[token]/complete/claim-account.tsx:152
msgid "Pick a password" msgid "Pick a password"
msgstr "Wybierz jedną z poniższych umów i zacznij podpisywać, aby się zarejestrować" msgstr "Wybierz hasło"
#: apps/web/src/components/ui/user-profile-timur.tsx:53 #: apps/web/src/components/ui/user-profile-timur.tsx:53
msgid "Pick any of the following agreements below and start signing to get started" msgid "Pick any of the following agreements below and start signing to get started"
msgstr "Pick any of the following agreements below and start signing to get started" msgstr "Wybierz dowolną z poniższych umów i zacznij podpisywanie, aby rozpocząć"
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:212 #: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:212
msgid "Please check the CSV file and make sure it is according to our format" msgid "Please check the CSV file and make sure it is according to our format"
msgstr "Proszę wybrać nowe hasło" msgstr "Proszę sprawdzić plik CSV i upewnić się, że jest zgodny z naszym formatem"
#: apps/web/src/app/(signing)/sign/[token]/waiting/page.tsx:81 #: apps/web/src/app/(signing)/sign/[token]/waiting/page.tsx:81
msgid "Please check your email for updates." msgid "Please check your email for updates."
msgstr "Proszę sprawdź swój e-mail w celu uzyskania aktualizacji." msgstr "Proszę sprawdzić swój email w celu aktualizacji."
#: apps/web/src/app/(unauthenticated)/reset-password/[token]/page.tsx:34 #: apps/web/src/app/(unauthenticated)/reset-password/[token]/page.tsx:34
msgid "Please choose your new password" msgid "Please choose your new password"
msgstr "Please choose your new password" msgstr "Proszę wybrać nowe hasło"
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:174 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:174
msgid "Please contact support if you would like to revert this action." msgid "Please contact support if you would like to revert this action."
msgstr "Proszę podać znaczącą nazwę dla swojego tokena. To pomoże Ci zidentyfikować go później." msgstr "Proszę skontaktować się z pomocą techniczną, jeśli chcesz cofnąć tę akcję."
#: apps/web/src/components/forms/token.tsx:175 #: apps/web/src/components/forms/token.tsx:175
msgid "Please enter a meaningful name for your token. This will help you identify it later." msgid "Please enter a meaningful name for your token. This will help you identify it later."
msgstr "Please enter a meaningful name for your token. This will help you identify it later." msgstr "Proszę podać wartościową nazwę dla swojego tokena. Pomoże to później w jego identyfikacji."
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:135 #: apps/web/src/app/(signing)/sign/[token]/form.tsx:135
msgid "Please mark as viewed to complete" msgid "Please mark as viewed to complete"
msgstr "Please mark as viewed to complete" msgstr "Proszę zaznaczyć jako obejrzane, aby zakończyć"
#: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:459 #: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:459
msgid "Please note that proceeding will remove direct linking recipient and turn it into a placeholder." msgid "Please note that proceeding will remove direct linking recipient and turn it into a placeholder."
msgstr "Please note that proceeding will remove direct linking recipient and turn it into a placeholder." msgstr "Proszę zauważyć, że kontynuowanie usunie bezpośrednio łączącego odbiorcę i zamieni go w symbol zastępczy."
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:128 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:128
msgid "Please note that this action is <0>irreversible</0>." msgid "Please note that this action is <0>irreversible</0>."
msgstr "Proszę pamiętać, że ta akcja jest <0>nieodwracalna</0>. Po zatwierdzeniu ten dokument zostanie trwale usunięty." msgstr "Proszę zauważyć, że ta czynność jest <0>nieodwracalna</0>."
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:119 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:119
msgid "Please note that this action is <0>irreversible</0>. Once confirmed, this document will be permanently deleted." msgid "Please note that this action is <0>irreversible</0>. Once confirmed, this document will be permanently deleted."
msgstr "Please note that this action is <0>irreversible</0>. Once confirmed, this document will be permanently deleted." msgstr "Proszę pamiętać, że ta czynność jest <0>nieodwracalna</0>. Po potwierdzeniu, ten dokument zostanie trwale usunięty."
#: apps/web/src/app/(dashboard)/templates/delete-template-dialog.tsx:67 #: apps/web/src/app/(dashboard)/templates/delete-template-dialog.tsx:67
msgid "Please note that this action is irreversible. Once confirmed, your template will be permanently deleted." msgid "Please note that this action is irreversible. Once confirmed, your template will be permanently deleted."
msgstr "Proszę pamiętać, że ta akcja jest nieodwracalna. Po zatwierdzeniu Twój token zostanie trwale usunięty." msgstr "Proszę pamiętać, że ta czynność jest nieodwracalna. Po potwierdzeniu, Twój szablon zostanie trwale usunięty."
#: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:133 #: apps/web/src/components/(dashboard)/settings/token/delete-token-dialog.tsx:133
msgid "Please note that this action is irreversible. Once confirmed, your token will be permanently deleted." msgid "Please note that this action is irreversible. Once confirmed, your token will be permanently deleted."
msgstr "Proszę pamiętać, że ta akcja jest nieodwracalna. Po zatwierdzeniu Twój webhook zostanie trwale usunięty." msgstr "Proszę zauważyć, że ta czynność jest nieodwracalna. Po potwierdzeniu, twój token zostanie trwale usunięty."
#: apps/web/src/components/(dashboard)/settings/webhooks/delete-webhook-dialog.tsx:121 #: apps/web/src/components/(dashboard)/settings/webhooks/delete-webhook-dialog.tsx:121
msgid "Please note that this action is irreversible. Once confirmed, your webhook will be permanently deleted." msgid "Please note that this action is irreversible. Once confirmed, your webhook will be permanently deleted."
msgstr "Please note that this action is irreversible. Once confirmed, your webhook will be permanently deleted." msgstr "Proszę pamiętać, że ta czynność jest nieodwracalna. Po potwierdzeniu, Twój webhook zostanie trwale usunięty."
#: apps/web/src/components/(teams)/dialogs/delete-team-dialog.tsx:130 #: apps/web/src/components/(teams)/dialogs/delete-team-dialog.tsx:130
msgid "Please note that you will lose access to all documents associated with this team & all the members will be removed and notified" 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" msgstr "Proszę pamiętać, że stracisz dostęp do wszystkich dokumentów powiązanych z tym zespołem i wszyscy członkowie zostaną usunięci oraz powiadomieni"
#: apps/web/src/app/(signing)/sign/[token]/reject-document-dialog.tsx:37 #: apps/web/src/app/(signing)/sign/[token]/reject-document-dialog.tsx:37
msgid "Please provide a reason" msgid "Please provide a reason"
@@ -2711,11 +2729,11 @@ msgstr "Proszę podać powód"
#: apps/web/src/components/forms/2fa/disable-authenticator-app-dialog.tsx:127 #: 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." 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 "Proszę podać token z swojego autoryzatora lub kod zapasowy." msgstr "Proszę podać token z aplikacji uwierzytelniającej lub kod zapasowy. Jeśli nie masz dostępnego kodu zapasowego, skontaktuj się z pomocą techniczną."
#: apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx:120 #: apps/web/src/components/forms/2fa/view-recovery-codes-dialog.tsx:120
msgid "Please provide a token from your authenticator, or a backup code." msgid "Please provide a token from your authenticator, or a backup code."
msgstr "Proszę spróbować ponownie i upewnić się, że wprowadzasz poprawny adres e-mail." msgstr "Proszę podać token z Twojego uwierzytelniacza lub kod zapasowy."
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:169 #: apps/web/src/app/(signing)/sign/[token]/form.tsx:169
msgid "Please review the document before signing." msgid "Please review the document before signing."
@@ -2723,25 +2741,25 @@ msgstr "Proszę przejrzeć dokument przed podpisaniem."
#: apps/web/src/components/forms/send-confirmation-email.tsx:64 #: apps/web/src/components/forms/send-confirmation-email.tsx:64
msgid "Please try again and make sure you enter the correct email address." msgid "Please try again and make sure you enter the correct email address."
msgstr "Please try again and make sure you enter the correct email address." msgstr "Spróbuj ponownie i upewnij się, że wprowadzasz poprawny adres email."
#: apps/web/src/components/forms/signin.tsx:203 #: apps/web/src/components/forms/signin.tsx:203
msgid "Please try again later or login using your normal details" msgid "Please try again later or login using your normal details"
msgstr "Please try again later or login using your normal details" msgstr "Spróbuj ponownie później lub zaloguj się, używając swoich normalnych danych"
#: apps/web/src/app/(dashboard)/templates/new-template-dialog.tsx:80 #: apps/web/src/app/(dashboard)/templates/new-template-dialog.tsx:80
msgid "Please try again later." msgid "Please try again later."
msgstr "Please try again later." msgstr "Proszę spróbować ponownie później."
#: apps/web/src/app/(dashboard)/settings/profile/delete-account-dialog.tsx:134 #: apps/web/src/app/(dashboard)/settings/profile/delete-account-dialog.tsx:134
msgid "Please type <0>{0}</0> to confirm." msgid "Please type <0>{0}</0> to confirm."
msgstr "Please type <0>{0}</0> to confirm." msgstr "Proszę wpisać <0>{0}</0> aby potwierdzić."
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:214 #: apps/web/src/components/(dashboard)/common/command-menu.tsx:214
#: apps/web/src/components/(teams)/settings/layout/desktop-nav.tsx:58 #: apps/web/src/components/(teams)/settings/layout/desktop-nav.tsx:58
#: apps/web/src/components/(teams)/settings/layout/mobile-nav.tsx:67 #: apps/web/src/components/(teams)/settings/layout/mobile-nav.tsx:67
msgid "Preferences" msgid "Preferences"
msgstr "Preferences" msgstr "Preferencje"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:204 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:204
msgid "Preview" msgid "Preview"
@@ -2749,7 +2767,7 @@ msgstr "Podgląd"
#: apps/web/src/app/(recipient)/d/[token]/direct-template.tsx:63 #: apps/web/src/app/(recipient)/d/[token]/direct-template.tsx:63
msgid "Preview and configure template." msgid "Preview and configure template."
msgstr "Preview and configure template." msgstr "Podgląd i konfiguracja szablonu."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:130 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:130
#~ msgid "Preview: {0}" #~ msgid "Preview: {0}"
@@ -2758,36 +2776,36 @@ msgstr "Preview and configure template."
#: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:105 #: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:105
#: apps/web/src/components/formatter/template-type.tsx:22 #: apps/web/src/components/formatter/template-type.tsx:22
msgid "Private" msgid "Private"
msgstr "Private" msgstr "Prywatne"
#: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:115 #: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:115
msgid "Private templates can only be modified and viewed by you." msgid "Private templates can only be modified and viewed by you."
msgstr "Private templates can only be modified and viewed by you." msgstr "Prywatne szablony mogą być modyfikowane i przeglądane tylko przez Ciebie."
#: apps/web/src/app/(dashboard)/settings/profile/page.tsx:28 #: apps/web/src/app/(dashboard)/settings/profile/page.tsx:28
#: apps/web/src/components/(dashboard)/common/command-menu.tsx:69 #: apps/web/src/components/(dashboard)/common/command-menu.tsx:69
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:36 #: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:36
#: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:39 #: apps/web/src/components/(dashboard)/settings/layout/mobile-nav.tsx:39
msgid "Profile" msgid "Profile"
msgstr "Profile" msgstr "Profil"
#: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:184 #: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:184
msgid "Profile is currently <0>hidden</0>." msgid "Profile is currently <0>hidden</0>."
msgstr "Profil jest obecnie <0>widoczny</0>." msgstr "Profil jest obecnie <0>ukryty</0>."
#: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:172 #: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:172
msgid "Profile is currently <0>visible</0>." msgid "Profile is currently <0>visible</0>."
msgstr "Profile is currently <0>visible</0>." msgstr "Profil jest obecnie <0>widoczny</0>."
#: apps/web/src/app/(dashboard)/admin/users/[id]/page.tsx:72 #: apps/web/src/app/(dashboard)/admin/users/[id]/page.tsx:72
#: apps/web/src/components/forms/profile.tsx:72 #: apps/web/src/components/forms/profile.tsx:72
msgid "Profile updated" msgid "Profile updated"
msgstr "Publiczny" msgstr "Profil zaktualizowano"
#: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:78 #: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:78
#: apps/web/src/components/formatter/template-type.tsx:27 #: apps/web/src/components/formatter/template-type.tsx:27
msgid "Public" msgid "Public"
msgstr "Publiczny profil" msgstr "Publiczny"
#: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:42 #: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:42
#: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:50 #: apps/web/src/components/(dashboard)/settings/layout/desktop-nav.tsx:50
@@ -2795,23 +2813,23 @@ msgstr "Publiczny profil"
#: apps/web/src/components/(teams)/settings/layout/desktop-nav.tsx:72 #: apps/web/src/components/(teams)/settings/layout/desktop-nav.tsx:72
#: apps/web/src/components/(teams)/settings/layout/mobile-nav.tsx:81 #: apps/web/src/components/(teams)/settings/layout/mobile-nav.tsx:81
msgid "Public Profile" msgid "Public Profile"
msgstr "Public Profile" msgstr "Profil publiczny"
#: apps/web/src/components/forms/public-profile-form.tsx:146 #: apps/web/src/components/forms/public-profile-form.tsx:146
msgid "Public profile URL" msgid "Public profile URL"
msgstr "Nazwa użytkownika publicznego profilu" msgstr "URL publicznego profilu"
#: apps/web/src/components/forms/v2/signup.tsx:450 #: apps/web/src/components/forms/v2/signup.tsx:450
msgid "Public profile username" msgid "Public profile username"
msgstr "Public profile username" msgstr "Nazwa użytkownika profilu publicznego"
#: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:82 #: apps/web/src/app/(dashboard)/templates/data-table-templates.tsx:82
msgid "Public templates are connected to your public profile. Any modifications to public templates will also appear in your public profile." msgid "Public templates are connected to your public profile. Any modifications to public templates will also appear in your public profile."
msgstr "Public templates are connected to your public profile. Any modifications to public templates will also appear in your public profile." msgstr "Szablony publiczne są powiązane z Twoim publicznym profilem. Wszelkie modyfikacje szablonów publicznych również pojawią się w Twoim publicznym profilu."
#: apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx:144 #: apps/web/src/app/(signing)/sign/[token]/signing-field-container.tsx:144
msgid "Read only field" msgid "Read only field"
msgstr "Gotowe" msgstr "Pole tylko do odczytu"
#: apps/web/src/components/general/signing-disclosure.tsx:21 #: apps/web/src/components/general/signing-disclosure.tsx:21
msgid "Read the full <0>signature disclosure</0>." msgid "Read the full <0>signature disclosure</0>."
@@ -2819,7 +2837,7 @@ msgstr "Przeczytaj pełne <0>ujawnienie podpisu</0>."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-recipients.tsx:106 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-recipients.tsx:106
msgid "Ready" msgid "Ready"
msgstr "Wymagana ponowna autoryzacja, aby podpisać to pole" msgstr "Gotowy"
#: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:281 #: apps/web/src/app/(internal)/%5F%5Fhtmltopdf/certificate/page.tsx:281
msgid "Reason" msgid "Reason"
@@ -2835,12 +2853,12 @@ msgstr "Powód musi mieć mniej niż 500 znaków"
#: apps/web/src/app/(signing)/sign/[token]/document-action-auth-dialog.tsx:62 #: apps/web/src/app/(signing)/sign/[token]/document-action-auth-dialog.tsx:62
msgid "Reauthentication is required to sign this field" msgid "Reauthentication is required to sign this field"
msgstr "Ostatnia aktywność" msgstr "Wymagana jest ponowna autoryzacja, aby podpisać to pole"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-recent-activity.tsx:57 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-recent-activity.tsx:57
#: apps/web/src/app/(dashboard)/settings/security/page.tsx:130 #: apps/web/src/app/(dashboard)/settings/security/page.tsx:130
msgid "Recent activity" msgid "Recent activity"
msgstr "Odbiorca" msgstr "Ostatnia aktywność"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-recent-activity.tsx:47 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-recent-activity.tsx:47
msgid "Recent documents" msgid "Recent documents"
@@ -2898,7 +2916,7 @@ msgstr "Odrzucony"
#: apps/web/src/app/(unauthenticated)/forgot-password/page.tsx:34 #: apps/web/src/app/(unauthenticated)/forgot-password/page.tsx:34
msgid "Remembered your password? <0>Sign In</0>" msgid "Remembered your password? <0>Sign In</0>"
msgstr "Pamiętasz swoje hasło? <0>Zaloguj się</0>" msgstr "Zapamiętałeś hasło? <0>Zaloguj się</0>"
#: apps/web/src/app/(dashboard)/settings/public-profile/public-templates-data-table.tsx:193 #: apps/web/src/app/(dashboard)/settings/public-profile/public-templates-data-table.tsx:193
#: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:431 #: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:431
@@ -2929,11 +2947,11 @@ msgstr "Powtórz hasło"
#: apps/web/src/components/(teams)/dialogs/transfer-team-dialog.tsx:282 #: apps/web/src/components/(teams)/dialogs/transfer-team-dialog.tsx:282
msgid "Request transfer" msgid "Request transfer"
msgstr "Poproś o transfer" msgstr "Zleć przeniesienie"
#: apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx:61 #: apps/web/src/app/(dashboard)/admin/documents/[id]/admin-actions.tsx:61
msgid "Reseal document" msgid "Reseal document"
msgstr "Zamknij dokument" msgstr "Zapieczętuj ponownie dokument"
#: apps/web/src/app/(dashboard)/documents/_action-items/resend-document.tsx:118 #: apps/web/src/app/(dashboard)/documents/_action-items/resend-document.tsx:118
#: apps/web/src/components/(teams)/tables/team-member-invites-data-table.tsx:154 #: apps/web/src/components/(teams)/tables/team-member-invites-data-table.tsx:154
@@ -2992,7 +3010,7 @@ msgstr "Zwróć"
#: apps/web/src/app/(unauthenticated)/team/decline/[token]/page.tsx:130 #: apps/web/src/app/(unauthenticated)/team/decline/[token]/page.tsx:130
msgid "Return to Dashboard" msgid "Return to Dashboard"
msgstr "Powrót do pulpitu nawigacyjnego" msgstr "Powrót do pulpitu"
#: apps/web/src/app/(unauthenticated)/team/decline/[token]/page.tsx:136 #: apps/web/src/app/(unauthenticated)/team/decline/[token]/page.tsx:136
msgid "Return to Home" msgid "Return to Home"
@@ -3026,8 +3044,8 @@ msgid "Roles"
msgstr "Role" msgstr "Role"
#: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:446 #: apps/web/src/app/(dashboard)/templates/template-direct-link-dialog.tsx:446
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:336 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:342 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:344
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/branding-preferences.tsx:312 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/branding-preferences.tsx:312
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:232 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:232
msgid "Save" msgid "Save"
@@ -3175,6 +3193,7 @@ msgstr "Pokaż szablony w profilu publicznym zespołu dla swojej publiczności,
#: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:114 #: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:114
#: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:139 #: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:139
#: apps/web/src/app/(profile)/p/[url]/page.tsx:192 #: apps/web/src/app/(profile)/p/[url]/page.tsx:192
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:229
#: apps/web/src/app/(signing)/sign/[token]/document-action-auth-2fa.tsx:182 #: apps/web/src/app/(signing)/sign/[token]/document-action-auth-2fa.tsx:182
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:224 #: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:224
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:124 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:124
@@ -3331,7 +3350,7 @@ msgstr "Ustawienia strony"
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:80 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:80
#: apps/web/src/app/(dashboard)/documents/duplicate-document-dialog.tsx:72 #: apps/web/src/app/(dashboard)/documents/duplicate-document-dialog.tsx:72
#: apps/web/src/app/(dashboard)/settings/billing/billing-plans.tsx:62 #: apps/web/src/app/(dashboard)/settings/billing/billing-plans.tsx:62
#: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:50 #: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:51
#: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:124 #: apps/web/src/app/(dashboard)/settings/public-profile/public-profile-page-view.tsx:124
#: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:73 #: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:73
#: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:93 #: apps/web/src/app/(dashboard)/settings/security/passkeys/user-passkeys-data-table-actions.tsx:93
@@ -3646,8 +3665,8 @@ msgstr "Szablony"
msgid "Templates allow you to quickly generate documents with pre-filled recipients and fields." msgid "Templates allow you to quickly generate documents with pre-filled recipients and fields."
msgstr "Szablony pozwalają na szybkie generowanie dokumentów z wypełnionymi odbiorcami i polami." msgstr "Szablony pozwalają na szybkie generowanie dokumentów z wypełnionymi odbiorcami i polami."
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:256 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:257
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:272 #: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:274
msgid "Text" msgid "Text"
msgstr "Tekst" msgstr "Tekst"
@@ -4451,7 +4470,7 @@ msgstr "Chcesz wysłać eleganckie linki do podpisywania, takie jak ten? <0>Spra
msgid "Want your own public profile?" msgid "Want your own public profile?"
msgstr "Chcesz swój własny profil publiczny?" msgstr "Chcesz swój własny profil publiczny?"
#: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:40 #: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:41
#: apps/web/src/app/(teams)/t/[teamUrl]/layout-billing-banner.tsx:55 #: apps/web/src/app/(teams)/t/[teamUrl]/layout-billing-banner.tsx:55
#: apps/web/src/components/(teams)/team-billing-portal-button.tsx:31 #: apps/web/src/components/(teams)/team-billing-portal-button.tsx:31
msgid "We are unable to proceed to the billing portal at this time. Please try again, or contact support." msgid "We are unable to proceed to the billing portal at this time. Please try again, or contact support."
@@ -4715,6 +4734,10 @@ msgstr "Czy próbowałeś raczej edytować ten dokument?"
msgid "When you click continue, you will be prompted to add the first available authenticator on your system." msgid "When you click continue, you will be prompted to add the first available authenticator on your system."
msgstr "Kiedy klikniesz kontynuuj, zostaniesz poproszony o dodanie pierwszego dostępnego autoryzatora w swoim systemie." msgstr "Kiedy klikniesz kontynuuj, zostaniesz poproszony o dodanie pierwszego dostępnego autoryzatora w swoim systemie."
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:183
msgid "When you sign a document, we can automatically fill in and sign the following fields using information that has already been provided. You can also manually sign or remove any automatically signed fields afterwards if you desire."
msgstr "Podczas podpisywania dokumentu możemy automatycznie wypełnić i podpisać następujące pola, używając informacji, które zostały już podane. Możesz również ręcznie podpisać lub usunąć każde automatycznie podpisane pole później, jeśli chcesz."
#: apps/web/src/app/(unauthenticated)/articles/signature-disclosure/page.tsx:36 #: apps/web/src/app/(unauthenticated)/articles/signature-disclosure/page.tsx:36
msgid "When you use our platform to affix your electronic signature to documents, you are consenting to do so under the Electronic Signatures in Global and National Commerce Act (E-Sign Act) and other applicable laws. This action indicates your agreement to use electronic means to sign documents and receive notifications." msgid "When you use our platform to affix your electronic signature to documents, you are consenting to do so under the Electronic Signatures in Global and National Commerce Act (E-Sign Act) and other applicable laws. This action indicates your agreement to use electronic means to sign documents and receive notifications."
msgstr "Kiedy korzystasz z naszej platformy, aby przyczepić swój podpis elektroniczny do dokumentów, wyrażasz zgodę na dokonanie tego zgodnie z Ustawą o podpisach elektronicznych w handlu globalnym i krajowym (Ustawa E-Sign) oraz innymi obowiązującymi przepisami. Ta czynność wskazuje na twoją zgodę na korzystanie z elektronicznych środków do podpisywania dokumentów i otrzymywania powiadomień." msgstr "Kiedy korzystasz z naszej platformy, aby przyczepić swój podpis elektroniczny do dokumentów, wyrażasz zgodę na dokonanie tego zgodnie z Ustawą o podpisach elektronicznych w handlu globalnym i krajowym (Ustawa E-Sign) oraz innymi obowiązującymi przepisami. Ta czynność wskazuje na twoją zgodę na korzystanie z elektronicznych środków do podpisywania dokumentów i otrzymywania powiadomień."
@@ -4784,7 +4807,7 @@ msgstr "Zaraz usuniesz następującego użytkownika z <0>{teamName}</0>."
msgid "You are about to revoke access for team <0>{0}</0> ({1}) to use your email." msgid "You are about to revoke access for team <0>{0}</0> ({1}) to use your email."
msgstr "Zaraz cofniesz dostęp dla zespołu <0>{0}</0> ({1}) do korzystania z twojego e-maila." msgstr "Zaraz cofniesz dostęp dla zespołu <0>{0}</0> ({1}) do korzystania z twojego e-maila."
#: apps/web/src/app/(dashboard)/settings/billing/page.tsx:78 #: apps/web/src/app/(dashboard)/settings/billing/page.tsx:80
msgid "You are currently on the <0>Free Plan</0>." msgid "You are currently on the <0>Free Plan</0>."
msgstr "Obecnie jesteś na <0>Planie darmowym</0>." msgstr "Obecnie jesteś na <0>Planie darmowym</0>."
@@ -4836,7 +4859,7 @@ msgstr "Nie możesz modyfikować członka zespołu, który ma wyższą rolę ni
msgid "You cannot upload encrypted PDFs" msgid "You cannot upload encrypted PDFs"
msgstr "Nie możesz przesyłać zaszyfrowanych plików PDF" msgstr "Nie możesz przesyłać zaszyfrowanych plików PDF"
#: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:45 #: apps/web/src/app/(dashboard)/settings/billing/billing-portal-button.tsx:46
msgid "You do not currently have a customer record, this should not happen. Please contact support for assistance." msgid "You do not currently have a customer record, this should not happen. Please contact support for assistance."
msgstr "Obecnie nie masz rekordu klienta, nie powinno tak się dziać. Proszę skontaktuj się z pomocą techniczną." msgstr "Obecnie nie masz rekordu klienta, nie powinno tak się dziać. Proszę skontaktuj się z pomocą techniczną."
@@ -4982,7 +5005,7 @@ msgstr "Adres URL witryny Twojej marki"
msgid "Your branding preferences have been updated" msgid "Your branding preferences have been updated"
msgstr "Preferencje dotyczące marki zostały zaktualizowane" msgstr "Preferencje dotyczące marki zostały zaktualizowane"
#: apps/web/src/app/(dashboard)/settings/billing/page.tsx:119 #: apps/web/src/app/(dashboard)/settings/billing/page.tsx:125
msgid "Your current plan is past due. Please update your payment information." msgid "Your current plan is past due. Please update your payment information."
msgstr "Twój obecny plan jest przeterminowany. Zaktualizuj swoje informacje płatnicze." msgstr "Twój obecny plan jest przeterminowany. Zaktualizuj swoje informacje płatnicze."

View File

@@ -24,7 +24,8 @@ module.exports = {
plugins: [ plugins: [
'@trivago/prettier-plugin-sort-imports', '@trivago/prettier-plugin-sort-imports',
'prettier-plugin-sql', // !: Disabled until Prettier 3.x is supported.
// 'prettier-plugin-sql',
'prettier-plugin-tailwindcss', 'prettier-plugin-tailwindcss',
], ],

View File

@@ -7,10 +7,9 @@
"clean": "rimraf node_modules" "clean": "rimraf node_modules"
}, },
"dependencies": { "dependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.1.1", "@trivago/prettier-plugin-sort-imports": "^4.3.0",
"prettier": "^2.8.8", "prettier": "^3.3.3",
"prettier-plugin-sql": "^0.14.0", "prettier-plugin-tailwindcss": "^0.6.9"
"prettier-plugin-tailwindcss": "^0.2.8"
}, },
"devDependencies": {} "devDependencies": {}
} }

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "DocumentMeta" ALTER COLUMN "typedSignatureEnabled" SET DEFAULT true;

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "TeamGlobalSettings" ADD COLUMN "typedSignatureEnabled" BOOLEAN NOT NULL DEFAULT true;

View File

@@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "TeamGlobalSettings" ADD COLUMN "includeSigningCertificate" BOOLEAN NOT NULL DEFAULT true;

View File

@@ -0,0 +1,7 @@
-- Existing templates should not have this enabled by default.
-- AlterTable
ALTER TABLE "TemplateMeta" ADD COLUMN "typedSignatureEnabled" BOOLEAN NOT NULL DEFAULT false;
-- New templates should have this enabled by default.
-- AlterTable
ALTER TABLE "TemplateMeta" ALTER COLUMN "typedSignatureEnabled" SET DEFAULT true;

View File

@@ -374,7 +374,7 @@ model DocumentMeta {
document Document @relation(fields: [documentId], references: [id], onDelete: Cascade) document Document @relation(fields: [documentId], references: [id], onDelete: Cascade)
redirectUrl String? redirectUrl String?
signingOrder DocumentSigningOrder @default(PARALLEL) signingOrder DocumentSigningOrder @default(PARALLEL)
typedSignatureEnabled Boolean @default(false) typedSignatureEnabled Boolean @default(true)
language String @default("en") language String @default("en")
distributionMethod DocumentDistributionMethod @default(EMAIL) distributionMethod DocumentDistributionMethod @default(EMAIL)
emailSettings Json? emailSettings Json?
@@ -511,10 +511,12 @@ enum TeamMemberInviteStatus {
} }
model TeamGlobalSettings { model TeamGlobalSettings {
teamId Int @unique teamId Int @unique
documentVisibility DocumentVisibility @default(EVERYONE) documentVisibility DocumentVisibility @default(EVERYONE)
documentLanguage String @default("en") documentLanguage String @default("en")
includeSenderDetails Boolean @default(true) includeSenderDetails Boolean @default(true)
typedSignatureEnabled Boolean @default(true)
includeSigningCertificate Boolean @default(true)
brandingEnabled Boolean @default(false) brandingEnabled Boolean @default(false)
brandingLogo String @default("") brandingLogo String @default("")
@@ -628,19 +630,21 @@ enum TemplateType {
} }
model TemplateMeta { model TemplateMeta {
id String @id @default(cuid()) id String @id @default(cuid())
subject String? subject String?
message String? message String?
timezone String? @default("Etc/UTC") @db.Text timezone String? @default("Etc/UTC") @db.Text
password String? password String?
dateFormat String? @default("yyyy-MM-dd hh:mm a") @db.Text dateFormat String? @default("yyyy-MM-dd hh:mm a") @db.Text
signingOrder DocumentSigningOrder? @default(PARALLEL) signingOrder DocumentSigningOrder? @default(PARALLEL)
templateId Int @unique typedSignatureEnabled Boolean @default(true)
template Template @relation(fields: [templateId], references: [id], onDelete: Cascade) distributionMethod DocumentDistributionMethod @default(EMAIL)
redirectUrl String?
language String @default("en") templateId Int @unique
distributionMethod DocumentDistributionMethod @default(EMAIL) template Template @relation(fields: [templateId], references: [id], onDelete: Cascade)
emailSettings Json? redirectUrl String?
language String @default("en")
emailSettings Json?
} }
model Template { model Template {

View File

@@ -3,7 +3,7 @@ const { fontFamily } = require('tailwindcss/defaultTheme');
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
darkMode: ['class'], darkMode: ['variant', '&:is(.dark:not(.dark-mode-disabled) *)'],
content: ['src/**/*.{ts,tsx}'], content: ['src/**/*.{ts,tsx}'],
theme: { theme: {
extend: { extend: {
@@ -108,6 +108,9 @@ module.exports = {
'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
}, },
borderRadius: { borderRadius: {
DEFAULT: 'calc(var(--radius) - 3px)',
'2xl': 'calc(var(--radius) + 4px)',
xl: 'calc(var(--radius) + 2px)',
lg: 'var(--radius)', lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)', md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)', sm: 'calc(var(--radius) - 4px)',
@@ -139,5 +142,9 @@ module.exports = {
}, },
}, },
}, },
plugins: [require('tailwindcss-animate'), require('@tailwindcss/typography')], plugins: [
require('tailwindcss-animate'),
require('@tailwindcss/typography'),
require('@tailwindcss/container-queries'),
],
}; };

View File

@@ -7,14 +7,14 @@
"clean": "rimraf node_modules" "clean": "rimraf node_modules"
}, },
"dependencies": { "dependencies": {
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/typography": "^0.5.9",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"postcss": "^8.4.32", "postcss": "^8.4.32",
"tailwindcss": "3.3.2", "tailwindcss": "3.4.15",
"tailwindcss-animate": "^1.0.5" "tailwindcss-animate": "^1.0.5"
}, },
"devDependencies": { "devDependencies": {},
"@tailwindcss/typography": "^0.5.9"
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }

View File

@@ -151,8 +151,6 @@ export const ZUpdateTeamMutationSchema = z.object({
data: z.object({ data: z.object({
name: ZTeamNameSchema, name: ZTeamNameSchema,
url: ZTeamUrlSchema, url: ZTeamUrlSchema,
documentVisibility: z.nativeEnum(DocumentVisibility).optional(),
includeSenderDetails: z.boolean().optional(),
}), }),
}); });
@@ -212,6 +210,8 @@ export const ZUpdateTeamDocumentSettingsMutationSchema = z.object({
.default(DocumentVisibility.EVERYONE), .default(DocumentVisibility.EVERYONE),
documentLanguage: z.enum(SUPPORTED_LANGUAGE_CODES).optional().default('en'), documentLanguage: z.enum(SUPPORTED_LANGUAGE_CODES).optional().default('en'),
includeSenderDetails: z.boolean().optional().default(false), includeSenderDetails: z.boolean().optional().default(false),
typedSignatureEnabled: z.boolean().optional().default(true),
includeSigningCertificate: z.boolean().optional().default(true),
}), }),
}); });

View File

@@ -35,6 +35,7 @@ import {
ZSetSigningOrderForTemplateMutationSchema, ZSetSigningOrderForTemplateMutationSchema,
ZToggleTemplateDirectLinkMutationSchema, ZToggleTemplateDirectLinkMutationSchema,
ZUpdateTemplateSettingsMutationSchema, ZUpdateTemplateSettingsMutationSchema,
ZUpdateTemplateTypedSignatureSettingsMutationSchema,
} from './schema'; } from './schema';
export const templateRouter = router({ export const templateRouter = router({
@@ -359,4 +360,48 @@ export const templateRouter = router({
}); });
} }
}), }),
updateTemplateTypedSignatureSettings: authenticatedProcedure
.input(ZUpdateTemplateTypedSignatureSettingsMutationSchema)
.mutation(async ({ input, ctx }) => {
try {
const { templateId, teamId, typedSignatureEnabled } = input;
const template = await getTemplateById({
id: templateId,
teamId,
userId: ctx.user.id,
}).catch(() => null);
if (!template) {
throw new TRPCError({
code: 'NOT_FOUND',
message: 'Template not found',
});
}
return await updateTemplateSettings({
templateId,
teamId,
userId: ctx.user.id,
data: {},
meta: {
typedSignatureEnabled,
},
requestMetadata: extractNextApiRequestMetadata(ctx.req),
});
} catch (err) {
console.error(err);
if (err instanceof TRPCError) {
throw err;
}
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update the settings for this template. Please try again later.',
});
}
}),
}); });

View File

@@ -114,6 +114,7 @@ export const ZUpdateTemplateSettingsMutationSchema = z.object({
'Please enter a valid URL, make sure you include http:// or https:// part of the url.', 'Please enter a valid URL, make sure you include http:// or https:// part of the url.',
}), }),
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(), language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(),
typedSignatureEnabled: z.boolean().optional(),
}) })
.optional(), .optional(),
}); });
@@ -138,6 +139,12 @@ export const ZMoveTemplatesToTeamSchema = z.object({
teamId: z.number(), teamId: z.number(),
}); });
export const ZUpdateTemplateTypedSignatureSettingsMutationSchema = z.object({
templateId: z.number(),
teamId: z.number().optional(),
typedSignatureEnabled: z.boolean(),
});
export type TCreateTemplateMutationSchema = z.infer<typeof ZCreateTemplateMutationSchema>; export type TCreateTemplateMutationSchema = z.infer<typeof ZCreateTemplateMutationSchema>;
export type TCreateDocumentFromTemplateMutationSchema = z.infer< export type TCreateDocumentFromTemplateMutationSchema = z.infer<
typeof ZCreateDocumentFromTemplateMutationSchema typeof ZCreateDocumentFromTemplateMutationSchema

View File

@@ -34,7 +34,7 @@ const getCardClassNames = (
const baseClasses = 'field-card-container relative z-20 h-full w-full transition-all'; const baseClasses = 'field-card-container relative z-20 h-full w-full transition-all';
const insertedClasses = const insertedClasses =
'bg-documenso/20 border-documenso ring-documenso-200 ring-offset-documenso-200 ring-2 ring-offset-2 dark:shadow-none'; 'bg-primary/20 border-primary ring-primary/20 ring-offset-primary/20 ring-2 ring-offset-2 dark:shadow-none';
const nonRequiredClasses = const nonRequiredClasses =
'border-yellow-300 shadow-none ring-2 ring-yellow-100 ring-offset-2 ring-offset-yellow-100 dark:border-2'; 'border-yellow-300 shadow-none ring-2 ring-yellow-100 ring-offset-2 ring-offset-yellow-100 dark:border-2';
const validatingClasses = 'border-orange-300 ring-1 ring-orange-300'; const validatingClasses = 'border-orange-300 ring-1 ring-orange-300';

View File

@@ -74,7 +74,7 @@
"react-hook-form": "^7.45.4", "react-hook-form": "^7.45.4",
"react-pdf": "7.7.3", "react-pdf": "7.7.3",
"react-rnd": "^10.4.1", "react-rnd": "^10.4.1",
"remeda": "^1.27.1", "remeda": "^2.17.3",
"tailwind-merge": "^1.12.0", "tailwind-merge": "^1.12.0",
"tailwindcss-animate": "^1.0.5", "tailwindcss-animate": "^1.0.5",
"ts-pattern": "^5.0.5", "ts-pattern": "^5.0.5",

View File

@@ -0,0 +1,157 @@
'use client';
import { useLayoutEffect, useRef } from 'react';
import { cn } from '../lib/utils';
export type Dimensions = {
height: number;
width: number;
};
export type AutoSizedTextProps = {
children: React.ReactNode;
className?: string;
maxHeight?: number;
useRem?: boolean;
};
const ITERATION_LIMIT = 20;
const MAXIMUM_DIFFERENCE = 1; // px
function getElementDimensions(element: HTMLElement): Dimensions {
const bbox = element.getBoundingClientRect();
return {
width: bbox.width,
height: bbox.height,
};
}
function getBaseFontSize(): number {
try {
const fontSize = getComputedStyle(document.documentElement).fontSize;
const parsed = parseFloat(fontSize);
// Check if we got a valid number
if (!Number.isFinite(parsed)) {
return 16;
}
return parsed;
} catch (error) {
// Fallback to browser default if anything goes wrong
return 16;
}
}
function pxToRem(px: number): number {
return px / getBaseFontSize();
}
export function AutoSizedText({
children,
className,
maxHeight,
useRem = false,
}: AutoSizedTextProps) {
const childRef = useRef<HTMLDivElement>(null);
const fontSize = useRef<number>(0);
const fontSizeLowerBound = useRef<number>(0);
const fontSizeUpperBound = useRef<number>(0);
const adjustFontSize = (childDimensions: Dimensions, parentDimensions: Dimensions) => {
const childElement = childRef.current;
if (!childElement) {
return;
}
let newFontSize: number;
const targetHeight =
maxHeight && maxHeight < parentDimensions.height ? maxHeight : parentDimensions.height;
const isElementTooBig =
childDimensions.width > parentDimensions.width || childDimensions.height > targetHeight;
if (isElementTooBig) {
// Scale down if element is bigger than target
newFontSize = (fontSizeLowerBound.current + fontSize.current) / 2;
fontSizeUpperBound.current = fontSize.current;
} else if (
childDimensions.width < parentDimensions.width ||
childDimensions.height < parentDimensions.height
) {
// Scale up if element is smaller than target
newFontSize = (fontSizeUpperBound.current + fontSize.current) / 2;
fontSizeLowerBound.current = fontSize.current;
}
fontSize.current = newFontSize;
// Convert to rem if useRem is true
const displayFontSize = useRem ? `${pxToRem(newFontSize)}rem` : `${newFontSize}px`;
childElement.style.fontSize = displayFontSize;
};
useLayoutEffect(() => {
const childElement = childRef.current;
const parentElement = childRef.current?.parentElement;
if (!childElement || !parentElement) {
return;
}
const observer = new ResizeObserver((entries) => {
const entry = entries[0];
if (!entry) {
return;
}
const parentDimensions = entry.contentRect;
// Reset iteration parameters
fontSizeLowerBound.current = 0;
fontSizeUpperBound.current = parentDimensions.height;
let iterationCount = 0;
while (iterationCount <= ITERATION_LIMIT) {
const childDimensions = getElementDimensions(childElement);
const targetHeight =
maxHeight && maxHeight < parentDimensions.height ? maxHeight : parentDimensions.height;
const widthDifference = parentDimensions.width - childDimensions.width;
const heightDifference = targetHeight - childDimensions.height;
const childFitsIntoParent = heightDifference >= 0 && widthDifference >= 0;
const isWithinTolerance =
Math.abs(widthDifference) <= MAXIMUM_DIFFERENCE ||
Math.abs(heightDifference) <= MAXIMUM_DIFFERENCE;
if (childFitsIntoParent && isWithinTolerance) {
break;
}
adjustFontSize(childDimensions, parentDimensions);
iterationCount += 1;
}
});
observer.observe(parentElement);
return () => {
observer.disconnect();
};
}, [maxHeight, useRem]);
return (
<div ref={childRef} className={cn('inline-block leading-none', className)}>
{children}
</div>
);
}

View File

@@ -36,11 +36,11 @@ const Card = React.forwardRef<HTMLDivElement, CardProps>(
className={cn( className={cn(
'bg-background text-foreground group relative rounded-lg border-2 backdrop-blur-[2px]', 'bg-background text-foreground group relative rounded-lg border-2 backdrop-blur-[2px]',
{ {
'gradient-border-mask before:pointer-events-none before:absolute before:-inset-[2px] before:rounded-lg before:p-[2px] before:[background:linear-gradient(var(--card-gradient-degrees),theme(colors.documenso.DEFAULT/50%)_5%,theme(colors.border/80%)_30%)]': 'gradient-border-mask before:pointer-events-none before:absolute before:-inset-[2px] before:rounded-lg before:p-[2px] before:[background:linear-gradient(var(--card-gradient-degrees),theme(colors.primary.DEFAULT/50%)_5%,theme(colors.border/80%)_30%)]':
gradient, gradient,
'dark:gradient-border-mask before:pointer-events-none before:absolute before:-inset-[2px] before:rounded-lg before:p-[2px] before:[background:linear-gradient(var(--card-gradient-degrees),theme(colors.documenso.DEFAULT/70%)_5%,theme(colors.border/80%)_30%)]': 'dark:gradient-border-mask before:pointer-events-none before:absolute before:-inset-[2px] before:rounded-lg before:p-[2px] before:[background:linear-gradient(var(--card-gradient-degrees),theme(colors.primary.DEFAULT/70%)_5%,theme(colors.border/80%)_30%)]':
gradient, gradient,
'shadow-[0_0_0_4px_theme(colors.gray.100/70%),0_0_0_1px_theme(colors.gray.100/70%),0_0_0_0.5px_theme(colors.primary.DEFAULT/70%)]': 'shadow-[0_0_0_4px_theme(colors.gray.100/70%),0_0_0_1px_theme(colors.gray.100/70%),0_0_0_0.5px_var(colors.primary.DEFAULT/70%)]':
true, true,
'dark:shadow-[0]': true, 'dark:shadow-[0]': true,
}, },

View File

@@ -113,7 +113,7 @@ const DialogTitle = React.forwardRef<
>(({ className, ...props }, ref) => ( >(({ className, ...props }, ref) => (
<DialogPrimitive.Title <DialogPrimitive.Title
ref={ref} ref={ref}
className={cn('truncate text-lg font-semibold leading-none tracking-tight', className)} className={cn('truncate text-lg font-semibold tracking-tight', className)}
{...props} {...props}
/> />
)); ));

View File

@@ -76,8 +76,11 @@ const fontCaveat = Caveat({
variable: '--font-caveat', variable: '--font-caveat',
}); });
const MIN_HEIGHT_PX = 20; const MIN_HEIGHT_PX = 12;
const MIN_WIDTH_PX = 80; const MIN_WIDTH_PX = 36;
const DEFAULT_HEIGHT_PX = MIN_HEIGHT_PX * 2.5;
const DEFAULT_WIDTH_PX = MIN_WIDTH_PX * 2.5;
export type FieldFormType = { export type FieldFormType = {
nativeId?: number; nativeId?: number;
@@ -480,8 +483,8 @@ export const AddFieldsFormPartial = ({
} }
fieldBounds.current = { fieldBounds.current = {
height: Math.max(MIN_HEIGHT_PX), height: Math.max(DEFAULT_HEIGHT_PX),
width: Math.max(MIN_WIDTH_PX), width: Math.max(DEFAULT_WIDTH_PX),
}; };
}); });
@@ -594,7 +597,7 @@ export const AddFieldsFormPartial = ({
{selectedField && ( {selectedField && (
<div <div
className={cn( className={cn(
'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center bg-white transition duration-200', 'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center bg-white transition duration-200 [container-type:size]',
selectedSignerStyles.default.base, selectedSignerStyles.default.base,
{ {
'-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds, '-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds,
@@ -609,7 +612,9 @@ export const AddFieldsFormPartial = ({
width: fieldBounds.current.width, width: fieldBounds.current.width,
}} }}
> >
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[selectedField])} <span className="text-[clamp(0.425rem,25cqw,0.825rem)]">
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[selectedField])}
</span>
</div> </div>
)} )}
@@ -630,8 +635,10 @@ export const AddFieldsFormPartial = ({
selectedSigner?.email !== field.signerEmail || selectedSigner?.email !== field.signerEmail ||
!canRecipientBeModified(selectedSigner, fields) !canRecipientBeModified(selectedSigner, fields)
} }
minHeight={fieldBounds.current.height} minHeight={MIN_HEIGHT_PX}
minWidth={fieldBounds.current.width} minWidth={MIN_WIDTH_PX}
defaultHeight={DEFAULT_HEIGHT_PX}
defaultWidth={DEFAULT_WIDTH_PX}
passive={isFieldWithinBounds && !!selectedField} passive={isFieldWithinBounds && !!selectedField}
onFocus={() => setLastActiveField(field)} onFocus={() => setLastActiveField(field)}
onBlur={() => setLastActiveField(null)} onBlur={() => setLastActiveField(null)}

View File

@@ -45,7 +45,7 @@ export const FieldIcon = ({
return ( return (
<div <div
className={cn( className={cn(
'text-field-card-foreground flex items-center justify-center gap-x-1 text-[clamp(0.875rem,1.8cqw,1.2rem)]', 'text-field-card-foreground flex items-center justify-center gap-x-1 text-[clamp(0.575rem,25cqw,1.2rem)]',
fontCaveatClassName, fontCaveatClassName,
)} )}
> >
@@ -71,8 +71,9 @@ export const FieldIcon = ({
} }
return ( return (
<div className="text-field-card-foreground flex items-center justify-center gap-x-1.5 text-[clamp(0.625rem,1cqw,0.825rem)]"> <div className="text-field-card-foreground flex items-center justify-center gap-x-1.5 text-[clamp(0.425rem,25cqw,0.825rem)]">
<Icon className="h-4 w-4" /> {label} <Icon className="h-[clamp(0.625rem,20cqw,0.925rem)] w-[clamp(0.625rem,20cqw,0.925rem)]" />{' '}
{label}
</div> </div>
); );
} }

View File

@@ -35,6 +35,8 @@ export type FieldItemProps = {
disabled?: boolean; disabled?: boolean;
minHeight?: number; minHeight?: number;
minWidth?: number; minWidth?: number;
defaultHeight?: number;
defaultWidth?: number;
onResize?: (_node: HTMLElement) => void; onResize?: (_node: HTMLElement) => void;
onMove?: (_node: HTMLElement) => void; onMove?: (_node: HTMLElement) => void;
onRemove?: () => void; onRemove?: () => void;
@@ -53,6 +55,8 @@ export const FieldItem = ({
disabled, disabled,
minHeight, minHeight,
minWidth, minWidth,
defaultHeight,
defaultWidth,
onResize, onResize,
onMove, onMove,
onRemove, onRemove,
@@ -68,8 +72,8 @@ export const FieldItem = ({
const [coords, setCoords] = useState({ const [coords, setCoords] = useState({
pageX: 0, pageX: 0,
pageY: 0, pageY: 0,
pageHeight: 0, pageHeight: defaultHeight || 0,
pageWidth: 0, pageWidth: defaultWidth || 0,
}); });
const [settingsActive, setSettingsActive] = useState(false); const [settingsActive, setSettingsActive] = useState(false);
const $el = useRef(null); const $el = useRef(null);

View File

@@ -141,7 +141,7 @@ export const RadioFieldAdvancedSettings = ({
{values.map((value) => ( {values.map((value) => (
<div key={value.id} className="mt-2 flex items-center gap-4"> <div key={value.id} className="mt-2 flex items-center gap-4">
<Checkbox <Checkbox
className="data-[state=checked]:bg-documenso border-foreground/30 data-[state=checked]:ring-documenso dark:data-[state=checked]:ring-offset-background h-5 w-5 rounded-full data-[state=checked]:ring-1 data-[state=checked]:ring-offset-2 data-[state=checked]:ring-offset-white" className="data-[state=checked]:bg-documenso border-foreground/30 data-[state=checked]:ring-primary dark:data-[state=checked]:ring-offset-background h-5 w-5 rounded-full data-[state=checked]:ring-1 data-[state=checked]:ring-offset-2 data-[state=checked]:ring-offset-white"
checked={value.checked} checked={value.checked}
onCheckedChange={(checked) => handleCheckedChange(Boolean(checked), value.id)} onCheckedChange={(checked) => handleCheckedChange(Boolean(checked), value.id)}
/> />

View File

@@ -44,18 +44,18 @@ export const ShowFieldItem = ({ field, recipients }: ShowFieldItemProps) => {
width: `${coords.width}px`, width: `${coords.width}px`,
}} }}
> >
<Card className={cn('bg-background h-full w-full')}> <Card className={cn('bg-background h-full w-full [container-type:size]')}>
<CardContent <CardContent
className={cn( className={cn(
'text-muted-foreground/50 flex h-full w-full flex-col items-center justify-center p-2 text-xl', 'text-muted-foreground/50 flex h-full w-full flex-col items-center justify-center p-0 text-[clamp(0.575rem,1.8cqw,1.2rem)] leading-none',
field.type === FieldType.SIGNATURE && fontCaveat.className, field.type === FieldType.SIGNATURE && fontCaveat.className,
)} )}
> >
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type])} {parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[field.type])}
<p className="text-muted-foreground/50 w-full truncate text-center text-xs"> {/* <p className="text-muted-foreground/50 w-full truncate text-center text-xs">
{signerEmail} {signerEmail}
</p> </p> */}
</CardContent> </CardContent>
</Card> </Card>
</div>, </div>,

View File

@@ -45,7 +45,7 @@ export const ZDocumentFlowFormSchema = z.object({
export type TDocumentFlowFormSchema = z.infer<typeof ZDocumentFlowFormSchema>; export type TDocumentFlowFormSchema = z.infer<typeof ZDocumentFlowFormSchema>;
export const FRIENDLY_FIELD_TYPE: Record<FieldType, MessageDescriptor | string> = { export const FRIENDLY_FIELD_TYPE: Record<FieldType, MessageDescriptor> = {
[FieldType.SIGNATURE]: msg`Signature`, [FieldType.SIGNATURE]: msg`Signature`,
[FieldType.FREE_SIGNATURE]: msg`Free Signature`, [FieldType.FREE_SIGNATURE]: msg`Free Signature`,
[FieldType.INITIALS]: msg`Initials`, [FieldType.INITIALS]: msg`Initials`,
@@ -54,9 +54,9 @@ export const FRIENDLY_FIELD_TYPE: Record<FieldType, MessageDescriptor | string>
[FieldType.EMAIL]: msg`Email`, [FieldType.EMAIL]: msg`Email`,
[FieldType.NAME]: msg`Name`, [FieldType.NAME]: msg`Name`,
[FieldType.NUMBER]: msg`Number`, [FieldType.NUMBER]: msg`Number`,
[FieldType.RADIO]: `Radio`, [FieldType.RADIO]: msg`Radio`,
[FieldType.CHECKBOX]: `Checkbox`, [FieldType.CHECKBOX]: msg`Checkbox`,
[FieldType.DROPDOWN]: `Select`, [FieldType.DROPDOWN]: msg`Select`,
}; };
export interface DocumentFlowStep { export interface DocumentFlowStep {

View File

@@ -38,6 +38,7 @@ export type SignaturePadProps = Omit<HTMLAttributes<HTMLCanvasElement>, 'onChang
containerClassName?: string; containerClassName?: string;
disabled?: boolean; disabled?: boolean;
allowTypedSignature?: boolean; allowTypedSignature?: boolean;
defaultValue?: string;
}; };
export const SignaturePad = ({ export const SignaturePad = ({
@@ -56,7 +57,7 @@ export const SignaturePad = ({
const [lines, setLines] = useState<Point[][]>([]); const [lines, setLines] = useState<Point[][]>([]);
const [currentLine, setCurrentLine] = useState<Point[]>([]); const [currentLine, setCurrentLine] = useState<Point[]>([]);
const [selectedColor, setSelectedColor] = useState('black'); const [selectedColor, setSelectedColor] = useState('black');
const [typedSignature, setTypedSignature] = useState(''); const [typedSignature, setTypedSignature] = useState(defaultValue ?? '');
const perfectFreehandOptions = useMemo(() => { const perfectFreehandOptions = useMemo(() => {
const size = $el.current ? Math.min($el.current.height, $el.current.width) * 0.03 : 10; const size = $el.current ? Math.min($el.current.height, $el.current.width) * 0.03 : 10;
@@ -206,6 +207,7 @@ export const SignaturePad = ({
if (ctx) { if (ctx) {
const canvasWidth = $el.current.width; const canvasWidth = $el.current.width;
const canvasHeight = $el.current.height; const canvasHeight = $el.current.height;
const fontFamily = String(fontCaveat.style.fontFamily);
ctx.clearRect(0, 0, canvasWidth, canvasHeight); ctx.clearRect(0, 0, canvasWidth, canvasHeight);
ctx.textAlign = 'center'; ctx.textAlign = 'center';
@@ -217,7 +219,7 @@ export const SignaturePad = ({
// Start with a base font size // Start with a base font size
let fontSize = 18; let fontSize = 18;
ctx.font = `${fontSize}px ${fontCaveat.style.fontFamily}`; ctx.font = `${fontSize}px ${fontFamily}`;
// Measure 10 characters and calculate scale factor // Measure 10 characters and calculate scale factor
const characterWidth = ctx.measureText('m'.repeat(10)).width; const characterWidth = ctx.measureText('m'.repeat(10)).width;
@@ -227,7 +229,7 @@ export const SignaturePad = ({
fontSize = fontSize * scaleFactor; fontSize = fontSize * scaleFactor;
// Adjust font size if it exceeds canvas width // Adjust font size if it exceeds canvas width
ctx.font = `${fontSize}px ${fontCaveat.style.fontFamily}`; ctx.font = `${fontSize}px ${fontFamily}`;
const textWidth = ctx.measureText(typedSignature).width; const textWidth = ctx.measureText(typedSignature).width;
@@ -236,7 +238,7 @@ export const SignaturePad = ({
} }
// Set final font and render text // Set final font and render text
ctx.font = `${fontSize}px ${fontCaveat.style.fontFamily}`; ctx.font = `${fontSize}px ${fontFamily}`;
ctx.fillText(typedSignature, canvasWidth / 2, canvasHeight / 2); ctx.fillText(typedSignature, canvasWidth / 2, canvasHeight / 2);
} }
} }
@@ -247,7 +249,7 @@ export const SignaturePad = ({
setTypedSignature(newValue); setTypedSignature(newValue);
if (newValue.trim() !== '') { if (newValue.trim() !== '') {
onChange?.($el.current?.toDataURL() || null); onChange?.(newValue);
} else { } else {
onChange?.(null); onChange?.(null);
} }
@@ -256,7 +258,7 @@ export const SignaturePad = ({
useEffect(() => { useEffect(() => {
if (typedSignature.trim() !== '') { if (typedSignature.trim() !== '') {
renderTypedSignature(); renderTypedSignature();
onChange?.($el.current?.toDataURL() || null); onChange?.(typedSignature);
} else { } else {
onClearClick(); onClearClick();
} }
@@ -303,6 +305,10 @@ export const SignaturePad = ({
$el.current.width = $el.current.clientWidth * DPI; $el.current.width = $el.current.clientWidth * DPI;
$el.current.height = $el.current.clientHeight * DPI; $el.current.height = $el.current.clientHeight * DPI;
} }
if (defaultValue && typedSignature) {
renderTypedSignature();
}
}, []); }, []);
unsafe_useEffectOnce(() => { unsafe_useEffectOnce(() => {

View File

@@ -55,8 +55,10 @@ import { FRIENDLY_FIELD_TYPE } from '@documenso/ui/primitives/document-flow/type
import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitives/popover'; import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitives/popover';
import { getSignerColorStyles, useSignerColors } from '../../lib/signer-colors'; import { getSignerColorStyles, useSignerColors } from '../../lib/signer-colors';
import { Checkbox } from '../checkbox';
import type { FieldFormType } from '../document-flow/add-fields'; import type { FieldFormType } from '../document-flow/add-fields';
import { FieldAdvancedSettings } from '../document-flow/field-item-advanced-settings'; import { FieldAdvancedSettings } from '../document-flow/field-item-advanced-settings';
import { Form, FormControl, FormField, FormItem, FormLabel } from '../form/form';
import { useStep } from '../stepper'; import { useStep } from '../stepper';
import type { TAddTemplateFieldsFormSchema } from './add-template-fields.types'; import type { TAddTemplateFieldsFormSchema } from './add-template-fields.types';
@@ -67,8 +69,11 @@ const fontCaveat = Caveat({
variable: '--font-caveat', variable: '--font-caveat',
}); });
const MIN_HEIGHT_PX = 20; const MIN_HEIGHT_PX = 12;
const MIN_WIDTH_PX = 80; const MIN_WIDTH_PX = 36;
const DEFAULT_HEIGHT_PX = MIN_HEIGHT_PX * 2.5;
const DEFAULT_WIDTH_PX = MIN_WIDTH_PX * 2.5;
export type AddTemplateFieldsFormProps = { export type AddTemplateFieldsFormProps = {
documentFlow: DocumentFlowStep; documentFlow: DocumentFlowStep;
@@ -77,6 +82,7 @@ export type AddTemplateFieldsFormProps = {
fields: Field[]; fields: Field[];
onSubmit: (_data: TAddTemplateFieldsFormSchema) => void; onSubmit: (_data: TAddTemplateFieldsFormSchema) => void;
teamId?: number; teamId?: number;
typedSignatureEnabled?: boolean;
}; };
export const AddTemplateFieldsFormPartial = ({ export const AddTemplateFieldsFormPartial = ({
@@ -86,6 +92,7 @@ export const AddTemplateFieldsFormPartial = ({
fields, fields,
onSubmit, onSubmit,
teamId, teamId,
typedSignatureEnabled,
}: AddTemplateFieldsFormProps) => { }: AddTemplateFieldsFormProps) => {
const { _ } = useLingui(); const { _ } = useLingui();
@@ -94,13 +101,7 @@ export const AddTemplateFieldsFormPartial = ({
const [showAdvancedSettings, setShowAdvancedSettings] = useState(false); const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
const [currentField, setCurrentField] = useState<FieldFormType>(); const [currentField, setCurrentField] = useState<FieldFormType>();
const { const form = useForm<TAddTemplateFieldsFormSchema>({
control,
handleSubmit,
formState: { isSubmitting },
setValue,
getValues,
} = useForm<TAddTemplateFieldsFormSchema>({
defaultValues: { defaultValues: {
fields: fields.map((field) => ({ fields: fields.map((field) => ({
nativeId: field.id, nativeId: field.id,
@@ -118,13 +119,14 @@ export const AddTemplateFieldsFormPartial = ({
recipients.find((recipient) => recipient.id === field.recipientId)?.token ?? '', recipients.find((recipient) => recipient.id === field.recipientId)?.token ?? '',
fieldMeta: field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined, fieldMeta: field.fieldMeta ? ZFieldMetaSchema.parse(field.fieldMeta) : undefined,
})), })),
typedSignatureEnabled: typedSignatureEnabled ?? false,
}, },
}); });
const onFormSubmit = handleSubmit(onSubmit); const onFormSubmit = form.handleSubmit(onSubmit);
const handleSavedFieldSettings = (fieldState: FieldMeta) => { const handleSavedFieldSettings = (fieldState: FieldMeta) => {
const initialValues = getValues(); const initialValues = form.getValues();
const updatedFields = initialValues.fields.map((field) => { const updatedFields = initialValues.fields.map((field) => {
if (field.formId === currentField?.formId) { if (field.formId === currentField?.formId) {
@@ -139,7 +141,7 @@ export const AddTemplateFieldsFormPartial = ({
return field; return field;
}); });
setValue('fields', updatedFields); form.setValue('fields', updatedFields);
}; };
const { const {
@@ -148,7 +150,7 @@ export const AddTemplateFieldsFormPartial = ({
update, update,
fields: localFields, fields: localFields,
} = useFieldArray({ } = useFieldArray({
control, control: form.control,
name: 'fields', name: 'fields',
}); });
@@ -354,8 +356,8 @@ export const AddTemplateFieldsFormPartial = ({
} }
fieldBounds.current = { fieldBounds.current = {
height: Math.max(MIN_HEIGHT_PX), height: Math.max(DEFAULT_HEIGHT_PX),
width: Math.max(MIN_WIDTH_PX), width: Math.max(DEFAULT_WIDTH_PX),
}; };
}); });
@@ -399,6 +401,12 @@ export const AddTemplateFieldsFormPartial = ({
setShowAdvancedSettings((prev) => !prev); setShowAdvancedSettings((prev) => !prev);
}; };
const isTypedSignatureEnabled = form.watch('typedSignatureEnabled');
const handleTypedSignatureChange = (value: boolean) => {
form.setValue('typedSignatureEnabled', value, { shouldDirty: true });
};
return ( return (
<> <>
{showAdvancedSettings && currentField ? ( {showAdvancedSettings && currentField ? (
@@ -425,7 +433,7 @@ export const AddTemplateFieldsFormPartial = ({
{selectedField && ( {selectedField && (
<div <div
className={cn( className={cn(
'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center bg-white transition duration-200', 'text-muted-foreground dark:text-muted-background pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center bg-white transition duration-200 [container-type:size]',
selectedSignerStyles.default.base, selectedSignerStyles.default.base,
{ {
'-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds, '-rotate-6 scale-90 opacity-50 dark:bg-black/20': !isFieldWithinBounds,
@@ -439,7 +447,9 @@ export const AddTemplateFieldsFormPartial = ({
width: fieldBounds.current.width, width: fieldBounds.current.width,
}} }}
> >
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[selectedField])} <span className="text-[clamp(0.425rem,25cqw,0.825rem)]">
{parseMessageDescriptor(_, FRIENDLY_FIELD_TYPE[selectedField])}
</span>
</div> </div>
)} )}
@@ -452,8 +462,10 @@ export const AddTemplateFieldsFormPartial = ({
recipientIndex={recipientIndex === -1 ? 0 : recipientIndex} recipientIndex={recipientIndex === -1 ? 0 : recipientIndex}
field={field} field={field}
disabled={selectedSigner?.email !== field.signerEmail} disabled={selectedSigner?.email !== field.signerEmail}
minHeight={fieldBounds.current.height} minHeight={MIN_HEIGHT_PX}
minWidth={fieldBounds.current.width} minWidth={MIN_WIDTH_PX}
defaultHeight={DEFAULT_HEIGHT_PX}
defaultWidth={DEFAULT_WIDTH_PX}
passive={isFieldWithinBounds && !!selectedField} passive={isFieldWithinBounds && !!selectedField}
onResize={(options) => onFieldResize(options, index)} onResize={(options) => onFieldResize(options, index)}
onMove={(options) => onFieldMove(options, index)} onMove={(options) => onFieldMove(options, index)}
@@ -561,305 +573,334 @@ export const AddTemplateFieldsFormPartial = ({
</Popover> </Popover>
)} )}
<div className="-mx-2 flex-1 overflow-y-auto px-2"> <Form {...form}>
<fieldset className="my-2 grid grid-cols-3 gap-4"> <FormField
<button control={form.control}
type="button" name="typedSignatureEnabled"
className="group h-full w-full" render={({ field: { value, ...field } }) => (
onClick={() => setSelectedField(FieldType.SIGNATURE)} <FormItem className="mb-6 flex flex-row items-center space-x-2 space-y-0">
onMouseDown={() => setSelectedField(FieldType.SIGNATURE)} <FormControl>
data-selected={selectedField === FieldType.SIGNATURE ? true : undefined} <Checkbox
> {...field}
<Card id="typedSignatureEnabled"
className={cn( checkClassName="text-white"
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50', checked={value}
// selectedSignerStyles.borderClass, onCheckedChange={(checked) => field.onChange(checked)}
)} disabled={form.formState.isSubmitting}
> />
<CardContent className="flex flex-col items-center justify-center px-6 py-4"> </FormControl>
<p
className={cn(
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-lg font-normal',
fontCaveat.className,
)}
>
<Trans>Signature</Trans>
</p>
</CardContent>
</Card>
</button>
<button <FormLabel
type="button" htmlFor="typedSignatureEnabled"
className="group h-full w-full" className="text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
onClick={() => setSelectedField(FieldType.INITIALS)} >
onMouseDown={() => setSelectedField(FieldType.INITIALS)} <Trans>Enable Typed Signatures</Trans>
data-selected={selectedField === FieldType.INITIALS ? true : undefined} </FormLabel>
> </FormItem>
<Card )}
className={cn( />
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
>
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
<p
className={cn(
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
)}
>
<Contact className="h-4 w-4" />
Initials
</p>
</CardContent>
</Card>
</button>
<button <div className="-mx-2 flex-1 overflow-y-auto px-2">
type="button" <fieldset className="my-2 grid grid-cols-3 gap-4">
className="group h-full w-full" <button
onClick={() => setSelectedField(FieldType.EMAIL)} type="button"
onMouseDown={() => setSelectedField(FieldType.EMAIL)} className="group h-full w-full"
data-selected={selectedField === FieldType.EMAIL ? true : undefined} onClick={() => setSelectedField(FieldType.SIGNATURE)}
> onMouseDown={() => setSelectedField(FieldType.SIGNATURE)}
<Card data-selected={selectedField === FieldType.SIGNATURE ? true : undefined}
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<Mail className="h-4 w-4" /> <CardContent className="flex flex-col items-center justify-center px-6 py-4">
<Trans>Email</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-lg font-normal',
</Card> fontCaveat.className,
</button> )}
>
<Trans>Signature</Trans>
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.NAME)} onClick={() => setSelectedField(FieldType.INITIALS)}
onMouseDown={() => setSelectedField(FieldType.NAME)} onMouseDown={() => setSelectedField(FieldType.INITIALS)}
data-selected={selectedField === FieldType.NAME ? true : undefined} data-selected={selectedField === FieldType.INITIALS ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<User className="h-4 w-4" /> <CardContent className="flex flex-col items-center justify-center px-6 py-4">
<Trans>Name</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
<Contact className="h-4 w-4" />
Initials
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.DATE)} onClick={() => setSelectedField(FieldType.EMAIL)}
onMouseDown={() => setSelectedField(FieldType.DATE)} onMouseDown={() => setSelectedField(FieldType.EMAIL)}
data-selected={selectedField === FieldType.DATE ? true : undefined} data-selected={selectedField === FieldType.EMAIL ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<CalendarDays className="h-4 w-4" /> <CardContent className="p-4">
<Trans>Date</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
<Mail className="h-4 w-4" />
<Trans>Email</Trans>
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.TEXT)} onClick={() => setSelectedField(FieldType.NAME)}
onMouseDown={() => setSelectedField(FieldType.TEXT)} onMouseDown={() => setSelectedField(FieldType.NAME)}
data-selected={selectedField === FieldType.TEXT ? true : undefined} data-selected={selectedField === FieldType.NAME ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<Type className="h-4 w-4" /> <CardContent className="p-4">
<Trans>Text</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
<User className="h-4 w-4" />
<Trans>Name</Trans>
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.NUMBER)} onClick={() => setSelectedField(FieldType.DATE)}
onMouseDown={() => setSelectedField(FieldType.NUMBER)} onMouseDown={() => setSelectedField(FieldType.DATE)}
data-selected={selectedField === FieldType.NUMBER ? true : undefined} data-selected={selectedField === FieldType.DATE ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<Hash className="h-4 w-4" /> <CardContent className="p-4">
<Trans>Number</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
<CalendarDays className="h-4 w-4" />
<Trans>Date</Trans>
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.RADIO)} onClick={() => setSelectedField(FieldType.TEXT)}
onMouseDown={() => setSelectedField(FieldType.RADIO)} onMouseDown={() => setSelectedField(FieldType.TEXT)}
data-selected={selectedField === FieldType.RADIO ? true : undefined} data-selected={selectedField === FieldType.TEXT ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<Disc className="h-4 w-4" /> <CardContent className="p-4">
<Trans>Radio</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
<Type className="h-4 w-4" />
<Trans>Text</Trans>
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.CHECKBOX)} onClick={() => setSelectedField(FieldType.NUMBER)}
onMouseDown={() => setSelectedField(FieldType.CHECKBOX)} onMouseDown={() => setSelectedField(FieldType.NUMBER)}
data-selected={selectedField === FieldType.CHECKBOX ? true : undefined} data-selected={selectedField === FieldType.NUMBER ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<CheckSquare className="h-4 w-4" /> <CardContent className="p-4">
Checkbox <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
<Hash className="h-4 w-4" />
<Trans>Number</Trans>
</p>
</CardContent>
</Card>
</button>
<button <button
type="button" type="button"
className="group h-full w-full" className="group h-full w-full"
onClick={() => setSelectedField(FieldType.DROPDOWN)} onClick={() => setSelectedField(FieldType.RADIO)}
onMouseDown={() => setSelectedField(FieldType.DROPDOWN)} onMouseDown={() => setSelectedField(FieldType.RADIO)}
data-selected={selectedField === FieldType.DROPDOWN ? true : undefined} data-selected={selectedField === FieldType.RADIO ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
> >
<CardContent className="p-4"> <Card
<p className={cn(
className={cn( 'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal', // selectedSignerStyles.borderClass,
)} )}
> >
<ChevronDown className="h-4 w-4" /> <CardContent className="p-4">
<Trans>Dropdown</Trans> <p
</p> className={cn(
</CardContent> 'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
</Card> )}
</button> >
</fieldset> <Disc className="h-4 w-4" />
</div> Radio
</p>
</CardContent>
</Card>
</button>
<button
type="button"
className="group h-full w-full"
onClick={() => setSelectedField(FieldType.CHECKBOX)}
onMouseDown={() => setSelectedField(FieldType.CHECKBOX)}
data-selected={selectedField === FieldType.CHECKBOX ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
>
<CardContent className="p-4">
<p
className={cn(
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
)}
>
<CheckSquare className="h-4 w-4" />
{/* Not translated on purpose. */}
Checkbox
</p>
</CardContent>
</Card>
</button>
<button
type="button"
className="group h-full w-full"
onClick={() => setSelectedField(FieldType.DROPDOWN)}
onMouseDown={() => setSelectedField(FieldType.DROPDOWN)}
data-selected={selectedField === FieldType.DROPDOWN ? true : undefined}
>
<Card
className={cn(
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
// selectedSignerStyles.borderClass,
)}
>
<CardContent className="p-4">
<p
className={cn(
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
)}
>
<ChevronDown className="h-4 w-4" />
<Trans>Dropdown</Trans>
</p>
</CardContent>
</Card>
</button>
</fieldset>
</div>
</Form>
{hasErrors && (
<div className="mt-4">
<ul>
<li className="text-sm text-red-500">
<Trans>
To proceed further, please set at least one value for the{' '}
{emptyCheckboxFields.length > 0
? 'Checkbox'
: emptyRadioFields.length > 0
? 'Radio'
: 'Select'}{' '}
field.
</Trans>
</li>
</ul>
</div>
)}
<DocumentFlowFormContainerFooter>
<DocumentFlowFormContainerStep step={currentStep} maxStep={totalSteps} />
<DocumentFlowFormContainerActions
loading={form.formState.isSubmitting}
disabled={form.formState.isSubmitting}
goNextLabel={msg`Save Template`}
disableNextStep={hasErrors}
onGoBackClick={() => {
previousStep();
remove();
}}
onGoNextClick={() => void onFormSubmit()}
/>
</DocumentFlowFormContainerFooter>
</div> </div>
</DocumentFlowFormContainerContent> </DocumentFlowFormContainerContent>
{hasErrors && (
<div className="mt-4">
<ul>
<li className="text-sm text-red-500">
<Trans>
To proceed further, please set at least one value for the{' '}
{emptyCheckboxFields.length > 0
? 'Checkbox'
: emptyRadioFields.length > 0
? 'Radio'
: 'Select'}{' '}
field.
</Trans>
</li>
</ul>
</div>
)}
<DocumentFlowFormContainerFooter>
<DocumentFlowFormContainerStep step={currentStep} maxStep={totalSteps} />
<DocumentFlowFormContainerActions
loading={isSubmitting}
disabled={isSubmitting}
goNextLabel={msg`Save Template`}
disableNextStep={hasErrors}
onGoBackClick={() => {
previousStep();
remove();
}}
onGoNextClick={() => void onFormSubmit()}
/>
</DocumentFlowFormContainerFooter>
</> </>
)} )}
</> </>

View File

@@ -20,6 +20,7 @@ export const ZAddTemplateFieldsFormSchema = z.object({
fieldMeta: ZFieldMetaSchema, fieldMeta: ZFieldMetaSchema,
}), }),
), ),
typedSignatureEnabled: z.boolean(),
}); });
export type TAddTemplateFieldsFormSchema = z.infer<typeof ZAddTemplateFieldsFormSchema>; export type TAddTemplateFieldsFormSchema = z.infer<typeof ZAddTemplateFieldsFormSchema>;

Some files were not shown because too many files have changed in this diff Show More