Compare commits

...

4 Commits

Author SHA1 Message Date
Mythie 1aeb6325b0 wip: wip 2024-10-16 15:45:46 +11:00
Ephraim Duncan 2c1a18bafc fix: stacked avatar colors (#1361) 2024-10-09 12:25:56 +11:00
Mythie a2db5e9642 chore: update changelog 2024-10-09 12:23:38 +11:00
Lucas Smith 4ec9dc78c1 chore: add translations (#1359) 2024-10-09 10:55:21 +11:00
27 changed files with 6710 additions and 192 deletions
+55
View File
@@ -8,6 +8,61 @@ Check out what's new in the latest version and read our thoughts on it. For more
---
# 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:
## 🌟 Key New Features
### 1. Signing Order
Specify the sequence in which recipients sign your documents. This ensures a structured signing process, particularly useful for complex agreements or hierarchical approvals.
<video
src="/changelog/signing-order-demo.mp4"
className="aspect-video w-full"
autoPlay
loop
controls
/>
### 2. Document Visibility
Manage who can view your documents and when. This feature offers greater privacy and flexibility in your document sharing workflows.
<video
src="/changelog/document-visibility-demo.mp4"
className="aspect-video w-full"
autoPlay
loop
controls
/>
## 🔧 Other Improvements
- Added language switcher for easier language selection
- Support for smaller field bounds in documents
- Improved select field UX
- Enhanced template functionality for advanced fields
- Added authOptions to the API
- Various UI refinements and bug fixes
## 💡 Recent Features
Don't forget about these powerful features from our recent v1.7.0 release:
- Embedded Signing Experience
- Copy and Paste Fields
- Customizable Signature Colors
## 👏 Thank You
As always, we're grateful for our community's contributions and feedback. Your input continues to shape Documenso into the leading open-source document signing solution.
We're eager to see how these new features enhance your document workflows. Enjoy exploring Documenso v1.7.1!
---
# Documenso v1.7.0: Embedded Signing, Copy and Paste, and More
We're thrilled to announce the release of Documenso v1.7.0, packed with exciting new features and improvements that enhance document signing flexibility, user experience, and global accessibility.
@@ -1,9 +1,11 @@
'use client';
import { useMemo } from 'react';
import { Trans } from '@lingui/macro';
import { useLingui } from '@lingui/react';
import { getRecipientType } from '@documenso/lib/client-only/recipient-type';
import { RecipientStatusType, getRecipientType } from '@documenso/lib/client-only/recipient-type';
import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles';
import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter';
import type { DocumentStatus, Recipient } from '@documenso/prisma/client';
@@ -29,24 +31,26 @@ export const StackAvatarsWithTooltip = ({
const { _ } = useLingui();
const waitingRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'waiting',
(recipient) => getRecipientType(recipient) === RecipientStatusType.WAITING,
);
const openedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'opened',
(recipient) => getRecipientType(recipient) === RecipientStatusType.OPENED,
);
const completedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'completed',
(recipient) => getRecipientType(recipient) === RecipientStatusType.COMPLETED,
);
const uncompletedRecipients = recipients.filter(
(recipient) => getRecipientType(recipient) === 'unsigned',
(recipient) => getRecipientType(recipient) === RecipientStatusType.UNSIGNED,
);
const sortedRecipients = useMemo(() => recipients.sort((a, b) => a.id - b.id), [recipients]);
return (
<PopoverHover
trigger={children || <StackAvatars recipients={recipients} />}
trigger={children || <StackAvatars recipients={sortedRecipients} />}
contentProps={{
className: 'flex flex-col gap-y-5 py-2',
side: position,
@@ -65,7 +69,7 @@ export const StackAvatarsWithTooltip = ({
type={getRecipientType(recipient)}
fallbackText={recipientAbbreviation(recipient)}
/>
<div className="">
<div>
<p className="text-muted-foreground text-sm">{recipient.email}</p>
<p className="text-muted-foreground/70 text-xs">
{_(RECIPIENT_ROLES_DESCRIPTION[recipient.role].roleName)}
@@ -1,6 +1,9 @@
import React from 'react';
import { getRecipientType } from '@documenso/lib/client-only/recipient-type';
import {
getExtraRecipientsType,
getRecipientType,
} from '@documenso/lib/client-only/recipient-type';
import { recipientAbbreviation } from '@documenso/lib/utils/recipient-formatter';
import type { Recipient } from '@documenso/prisma/client';
@@ -13,20 +16,27 @@ export function StackAvatars({ recipients }: { recipients: Recipient[] }) {
const remainingItems = recipients.length - itemsToRender.length;
return itemsToRender.map((recipient: Recipient, index: number) => {
const first = index === 0 ? true : false;
const first = index === 0;
const lastItemText =
index === itemsToRender.length - 1 && remainingItems > 0
? `+${remainingItems + 1}`
: undefined;
if (index === 4 && remainingItems > 0) {
return (
<StackAvatar
key="extra-recipient"
first={first}
zIndex={String(zIndex - index * 10)}
type={getExtraRecipientsType(recipients.slice(4))}
fallbackText={`+${remainingItems + 1}`}
/>
);
}
return (
<StackAvatar
key={recipient.id}
first={first}
zIndex={String(zIndex - index * 10)}
type={lastItemText && index === 4 ? 'unsigned' : getRecipientType(recipient)}
fallbackText={lastItemText ? lastItemText : recipientAbbreviation(recipient)}
type={getRecipientType(recipient)}
fallbackText={recipientAbbreviation(recipient)}
/>
);
});
+3
View File
@@ -0,0 +1,3 @@
/bin/
/node_modules/
+2
View File
@@ -0,0 +1,2 @@
config:
gcp:project: scratchpad-438301
+10
View File
@@ -0,0 +1,10 @@
name: gcloud
runtime:
name: nodejs
options:
packagemanager: npm
description: documenso on google cloud
config:
app--url: 'https://app.documenso.com'
app--smtp-from-name: 'Documenso'
app--smtp-from-address: 'noreply@documenso.com'
+418
View File
@@ -0,0 +1,418 @@
import * as gcp from '@pulumi/gcp';
import * as pulumi from '@pulumi/pulumi';
import * as random from '@pulumi/random';
const config = new pulumi.Config();
// Storage Config
const storageLocation = config.get('storage--location') || 'EU';
const serviceLocation = config.get('service--location') || 'europe-west3';
// KMS Config
const algorithm = config.get('kms--algorithm') || 'RSA_SIGN_PKCS1_4096_SHA256';
// Database Config
const databasePassword = config.get('db--password') || 'password';
// App Config
// App Config
const appUrl = config.require('app--url');
const nextAuthSecret =
config.getSecret('app--nextauth-secret') ||
new random.RandomString('next-auth-secret', {
length: 32,
}).result;
const encryptionKey =
config.getSecret('app--encryption-key') ||
new random.RandomString('encryption-key', {
length: 32,
}).result;
const encryptionSecondaryKey =
config.getSecret('app--encryption-secondary-key') ||
new random.RandomString('encryption-secondary-key', {
length: 32,
}).result;
const googleClientId = config.get('app--google-client-id') || '';
const googleClientSecret = config.get('app--google-client-secret') || '';
const oidcWellKnown = config.get('app--oidc-well-known') || '';
const oidcClientId = config.get('app--oidc-client-id') || '';
const oidcClientSecret = config.get('app--oidc-client-secret') || '';
const oidcProviderLabel = config.get('app--oidc-provider-label') || 'OIDC';
const oidcAllowSignup = config.get('app--oidc-allow-signup') || '';
const oidcSkipVerify = config.get('app--oidc-skip-verify') || '';
const internalWebappUrl = config.get('app--internal-webapp-url') || '';
const smtpTransport = config.get('app--smtp-transport') || 'smtp-auth';
const smtpHost = config.get('app--smtp-host') || '';
const smtpPort = config.get('app--smtp-port') || '';
const smtpUsername = config.get('app--smtp-username') || '';
const smtpPassword = config.getSecret('app--smtp-password') || '';
const smtpApikeyUser = config.get('app--smtp-apikey-user') || '';
const smtpApikey = config.getSecret('app--smtp-apikey') || '';
const smtpSecure = config.get('app--smtp-secure') || '';
const smtpUnsafeIgnoreTls = config.get('app--smtp-unsafe-ignore-tls') || '';
const smtpFromName = config.require('app--smtp-from-name');
const smtpFromAddress = config.require('app--smtp-from-address');
const resendApiKey = config.getSecret('app--resend-api-key') || '';
const documentSizeUploadLimit = config.get('app--document-size-upload-limit') || '50';
const stripeApiKey = config.getSecret('app--stripe-api-key') || '';
const stripeWebhookSecret = config.getSecret('app--stripe-webhook-secret') || '';
const stripeEnterprisePlanMonthlyPriceId =
config.get('app--stripe-enterprise-plan-monthly-price-id') || '';
const jobsProvider = config.get('app--jobs-provider') || 'local';
const triggerApiKey = config.get('app--trigger-api-key') || '';
const triggerApiUrl = config.get('app--trigger-api-url') || '';
const inngestEventKey = config.get('app--inngest-event-key') || '';
const posthogKey = config.get('app--posthog-key') || '';
const billingEnabled = config.get('app--billing-enabled') || 'false';
new gcp.projects.Service('cloud-kms-api', {
project: gcp.config.project,
service: 'cloudkms.googleapis.com',
disableOnDestroy: false,
});
new gcp.projects.Service('cloud-run-api', {
project: gcp.config.project,
service: 'run.googleapis.com',
disableOnDestroy: false,
});
new gcp.projects.Service('compute-api', {
project: gcp.config.project,
service: 'compute.googleapis.com',
disableOnDestroy: false,
});
const signupDisabled = config.get('app--signup-disabled') || 'false';
// Create a GCS bucket for storage
const storageBucket = new gcp.storage.Bucket('documenso-storage', {
name: 'documenso-storage',
location: storageLocation,
});
// Create a service account so we can create a HMAC key to use the S3-compatible storage
// API
const storageServiceAccount = new gcp.serviceaccount.Account('documenso-storage-sa', {
accountId: 'documenso-storage-sa',
displayName: 'Storage Service Account',
});
const appServiceAccount = new gcp.serviceaccount.Account('documenso-app-sa', {
accountId: 'documenso-app-sa',
displayName: 'App Service Account',
});
// Create the HMAC key for the storage service account
const hmacKey = new gcp.storage.HmacKey('documenso-storage-key', {
serviceAccountEmail: storageServiceAccount.email,
});
// Create a Cloud HSM cluster
const hsmCluster = new gcp.kms.KeyRing('hsm-keyring', {
name: 'documenso-hsm-keyring',
location: serviceLocation,
});
const hsmKey = new gcp.kms.CryptoKey('hsm-key', {
name: 'documenso-hsm-key',
keyRing: hsmCluster.id,
purpose: 'ASYMMETRIC_SIGN',
versionTemplate: {
algorithm,
protectionLevel: 'HSM',
},
});
// Create the database
const database = new gcp.sql.DatabaseInstance('documenso-db', {
name: 'documenso-db',
databaseVersion: 'POSTGRES_15',
region: serviceLocation,
settings: {
tier: 'db-custom-2-4096',
diskSize: 50,
diskType: 'PD_SSD',
diskAutoresize: true,
ipConfiguration: {
ipv4Enabled: true,
},
backupConfiguration: {
enabled: true,
startTime: '02:00',
backupRetentionSettings: {
retainedBackups: 30,
},
pointInTimeRecoveryEnabled: true,
transactionLogRetentionDays: 7,
},
databaseFlags: [
{ name: 'max_connections', value: '100' },
{ name: 'log_min_duration_statement', value: '300' },
],
maintenanceWindow: {
day: 7,
hour: 3,
},
insightsConfig: {
queryInsightsEnabled: true,
queryStringLength: 1024,
recordApplicationTags: true,
recordClientAddress: true,
},
},
deletionProtection: true,
});
const user = new gcp.sql.User('documenso-db-user', {
name: 'documenso',
instance: database.name,
password: databasePassword,
});
// Build and deploy the containerized application using Cloud Run
const appService = new gcp.cloudrun.Service('documenso-app', {
name: 'documenso-app',
location: serviceLocation,
template: {
metadata: {
annotations: {
'run.googleapis.com/cloudsql-instances': database.connectionName,
},
},
spec: {
containers: [
{
image: 'documenso/documenso:latest',
resources: {
limits: {
memory: '4Gi',
cpu: '4',
},
},
ports: [{ containerPort: 3000 }],
envs: [
{
name: 'NEXTAUTH_URL',
value: appUrl,
},
{
name: 'NEXTAUTH_SECRET',
value: nextAuthSecret,
},
{
name: 'NEXT_PRIVATE_ENCRYPTION_KEY',
value: encryptionKey,
},
{
name: 'NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY',
value: encryptionSecondaryKey,
},
{
name: 'NEXT_PRIVATE_GOOGLE_CLIENT_ID',
value: googleClientId,
},
{
name: 'NEXT_PRIVATE_GOOGLE_CLIENT_SECRET',
value: googleClientSecret,
},
{
name: 'NEXT_PRIVATE_OIDC_WELL_KNOWN',
value: oidcWellKnown,
},
{
name: 'NEXT_PRIVATE_OIDC_CLIENT_ID',
value: oidcClientId,
},
{
name: 'NEXT_PRIVATE_OIDC_CLIENT_SECRET',
value: oidcClientSecret,
},
{
name: 'NEXT_PRIVATE_OIDC_PROVIDER_LABEL',
value: oidcProviderLabel,
},
{
name: 'NEXT_PRIVATE_OIDC_ALLOW_SIGNUP',
value: oidcAllowSignup,
},
{
name: 'NEXT_PRIVATE_OIDC_SKIP_VERIFY',
value: oidcSkipVerify,
},
{
name: 'NEXT_PUBLIC_WEBAPP_URL',
value: appUrl,
},
{
name: 'NEXT_PRIVATE_INTERNAL_WEBAPP_URL',
value: internalWebappUrl,
},
{
name: 'NEXT_PRIVATE_DATABASE_URL',
value: pulumi.interpolate`postgres://${user.name}:${user.password}@localhost:5432/documenso?host=/cloudsql/${database.connectionName}/`,
},
{
name: 'NEXT_PRIVATE_DIRECT_DATABASE_URL',
value: pulumi.interpolate`postgres://${user.name}:${user.password}@localhost:5432/documenso?host=/cloudsql/${database.connectionName}/`,
},
{
name: 'NEXT_PRIVATE_SIGNING_TRANSPORT',
value: 'gcloud-hsm',
},
{
name: 'NEXT_PRIVATE_SIGNING_GCLOUD_HSM_KEY_PATH',
value: hsmKey.id,
},
{
name: 'NEXT_PUBLIC_UPLOAD_TRANSPORT',
value: 's3',
},
{
name: 'NEXT_PRIVATE_UPLOAD_ENDPOINT',
value: 'https://storage.googleapis.com',
},
{
name: 'NEXT_PRIVATE_UPLOAD_FORCE_PATH_STYLE',
value: 'true',
},
{
name: 'NEXT_PRIVATE_UPLOAD_REGION',
value: 'auto',
},
{
name: 'NEXT_PRIVATE_UPLOAD_BUCKET',
value: storageBucket.name,
},
{
name: 'NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID',
value: hmacKey.accessId,
},
{
name: 'NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY',
value: hmacKey.secret,
},
{
name: 'NEXT_PRIVATE_SMTP_TRANSPORT',
value: smtpTransport,
},
{
name: 'NEXT_PRIVATE_SMTP_HOST',
value: smtpHost,
},
{
name: 'NEXT_PRIVATE_SMTP_PORT',
value: smtpPort,
},
{
name: 'NEXT_PRIVATE_SMTP_USERNAME',
value: smtpUsername,
},
{
name: 'NEXT_PRIVATE_SMTP_PASSWORD',
value: smtpPassword,
},
{
name: 'NEXT_PRIVATE_SMTP_APIKEY_USER',
value: smtpApikeyUser,
},
{
name: 'NEXT_PRIVATE_SMTP_APIKEY',
value: smtpApikey,
},
{
name: 'NEXT_PRIVATE_SMTP_SECURE',
value: smtpSecure,
},
{
name: 'NEXT_PRIVATE_SMTP_UNSAFE_IGNORE_TLS',
value: smtpUnsafeIgnoreTls,
},
{
name: 'NEXT_PRIVATE_SMTP_FROM_NAME',
value: smtpFromName,
},
{
name: 'NEXT_PRIVATE_SMTP_FROM_ADDRESS',
value: smtpFromAddress,
},
{
name: 'NEXT_PRIVATE_RESEND_API_KEY',
value: resendApiKey,
},
{
name: 'NEXT_PUBLIC_DOCUMENT_SIZE_UPLOAD_LIMIT',
value: documentSizeUploadLimit,
},
{
name: 'NEXT_PRIVATE_STRIPE_API_KEY',
value: stripeApiKey,
},
{
name: 'NEXT_PRIVATE_STRIPE_WEBHOOK_SECRET',
value: stripeWebhookSecret,
},
{
name: 'NEXT_PUBLIC_STRIPE_ENTERPRISE_PLAN_MONTHLY_PRICE_ID',
value: stripeEnterprisePlanMonthlyPriceId,
},
{
name: 'NEXT_PRIVATE_JOBS_PROVIDER',
value: jobsProvider,
},
{
name: 'NEXT_PRIVATE_TRIGGER_API_KEY',
value: triggerApiKey,
},
{
name: 'NEXT_PRIVATE_TRIGGER_API_URL',
value: triggerApiUrl,
},
{
name: 'NEXT_PRIVATE_INNGEST_EVENT_KEY',
value: inngestEventKey,
},
{
name: 'NEXT_PUBLIC_POSTHOG_KEY',
value: posthogKey,
},
{
name: 'NEXT_PUBLIC_FEATURE_BILLING_ENABLED',
value: billingEnabled,
},
{
name: 'NEXT_PUBLIC_DISABLE_SIGNUP',
value: signupDisabled,
},
],
},
],
timeoutSeconds: 3600,
serviceAccountName: appServiceAccount.email,
},
},
});
// Allow unauthenticated invocations
const iam = new gcp.cloudrun.IamMember('documenso-app-invoker', {
service: appService.name,
location: appService.location,
role: 'roles/run.invoker',
member: 'allUsers',
});
// Allow the Cloud Run service to use the HSM for signing
const _cryptoKeyIAMBinding = new gcp.kms.CryptoKeyIAMBinding('cryptoKeyIAMBinding', {
cryptoKeyId: hsmKey.id,
role: 'roles/cloudkms.signerVerifier',
members: [appServiceAccount.email.apply((email) => `serviceAccount:${email}`)],
});
// Allow the Cloud Run service to access the GCS Bucket
const _bucketIAMBinding = new gcp.storage.BucketIAMBinding('bucketIAMBinding', {
bucket: storageBucket.name,
role: 'roles/storage.objectAdmin',
members: [appServiceAccount.email.apply((email) => `serviceAccount:${email}`)],
});
export const serviceUrl = appService.statuses[0].url;
+3631
View File
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
{
"name": "gcloud",
"description": "documenso on google cloud",
"main": "index.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"dependencies": {
"@pulumi/pulumi": "*",
"@pulumi/gcp": "7.8.0",
"@pulumi/google-native": "0.31.1",
"@pulumi/random": "^4.16.6"
}
}
+21
View File
@@ -0,0 +1,21 @@
{
"compilerOptions": {
"strict": true,
"outDir": "bin",
"target": "es2016",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"experimentalDecorators": true,
"pretty": true,
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"."
],
"exclude": [
"node_modules"
]
}
+2445 -133
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -59,7 +59,8 @@
"name": "@documenso/root",
"workspaces": [
"apps/*",
"packages/*"
"packages/*",
"infra/*"
],
"dependencies": {
"@documenso/pdf-sign": "^0.1.0",
@@ -74,4 +75,4 @@
"trigger.dev": {
"endpointId": "documenso-app"
}
}
}
+33 -5
View File
@@ -1,12 +1,19 @@
import type { Recipient } from '@documenso/prisma/client';
import { ReadStatus, RecipientRole, SendStatus, SigningStatus } from '@documenso/prisma/client';
export enum RecipientStatusType {
COMPLETED = 'completed',
OPENED = 'opened',
WAITING = 'waiting',
UNSIGNED = 'unsigned',
}
export const getRecipientType = (recipient: Recipient) => {
if (
recipient.role === RecipientRole.CC ||
(recipient.sendStatus === SendStatus.SENT && recipient.signingStatus === SigningStatus.SIGNED)
) {
return 'completed';
return RecipientStatusType.COMPLETED;
}
if (
@@ -14,12 +21,33 @@ export const getRecipientType = (recipient: Recipient) => {
recipient.readStatus === ReadStatus.OPENED &&
recipient.signingStatus === SigningStatus.NOT_SIGNED
) {
return 'opened';
return RecipientStatusType.OPENED;
}
if (recipient.sendStatus === 'SENT' && recipient.signingStatus === 'NOT_SIGNED') {
return 'waiting';
if (
recipient.sendStatus === SendStatus.SENT &&
recipient.signingStatus === SigningStatus.NOT_SIGNED
) {
return RecipientStatusType.WAITING;
}
return 'unsigned';
return RecipientStatusType.UNSIGNED;
};
export const getExtraRecipientsType = (extraRecipients: Recipient[]) => {
const types = extraRecipients.map((r) => getRecipientType(r));
if (types.includes(RecipientStatusType.UNSIGNED)) {
return RecipientStatusType.UNSIGNED;
}
if (types.includes(RecipientStatusType.OPENED)) {
return RecipientStatusType.OPENED;
}
if (types.includes(RecipientStatusType.WAITING)) {
return RecipientStatusType.WAITING;
}
return RecipientStatusType.COMPLETED;
};
+7 -7
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n"
"Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-16 16:03\n"
"PO-Revision-Date: 2024-10-08 12:05\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -159,7 +159,7 @@ msgstr "Unterzeichner kann nicht entfernt werden"
#: packages/ui/primitives/document-flow/add-signers.tsx:221
#~ msgid "Cannot update signer because they have already signed a field"
#~ msgstr ""
#~ msgstr "Cannot update signer because they have already signed a field"
#: packages/lib/constants/recipient-roles.ts:17
msgid "Cc"
@@ -280,7 +280,7 @@ msgstr "E-Mail-Optionen"
#: packages/ui/primitives/document-flow/add-fields.tsx:1082
msgid "Empty field"
msgstr ""
msgstr "Leeres Feld"
#: packages/lib/constants/template.ts:8
msgid "Enable Direct Link Signing"
@@ -705,15 +705,15 @@ msgstr "Dieses Feld kann nicht geändert oder gelöscht werden. Wenn Sie den dir
#: packages/ui/primitives/document-flow/add-fields.tsx:1050
msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr ""
msgstr "Dieser Empfänger kann nicht mehr bearbeitet werden, da er ein Feld unterschrieben oder das Dokument abgeschlossen hat."
#: packages/ui/primitives/document-flow/add-signers.tsx:195
#: packages/ui/primitives/document-flow/add-signers.tsx:165
#~ msgid "This signer has already received the document."
#~ msgstr "Dieser Unterzeichner hat das Dokument bereits erhalten."
#~ msgstr "This signer has already received the document."
#: packages/ui/primitives/document-flow/add-signers.tsx:194
msgid "This signer has already signed the document."
msgstr ""
msgstr "Dieser Unterzeichner hat das Dokument bereits unterschrieben."
#: packages/ui/components/recipient/recipient-action-auth-select.tsx:48
msgid "This will override any global settings."
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n"
"Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-16 14:04\n"
"PO-Revision-Date: 2024-10-08 12:05\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -387,7 +387,7 @@ msgstr "Unsere selbstgehostete Option ist ideal für kleine Teams und Einzelpers
#: apps/marketing/src/app/(marketing)/open/data.ts:25
#~ msgid "Part-Time"
#~ msgstr "Teilzeit"
#~ msgstr "Part-Time"
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:151
msgid "Premium Profile Name"
File diff suppressed because one or more lines are too long
+5 -5
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n"
"Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-16 16:03\n"
"PO-Revision-Date: 2024-10-08 12:05\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -789,7 +789,7 @@ msgstr "Unterzeichnung abschließen"
msgid "Complete Viewing"
msgstr "Betrachten abschließen"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:58
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:62
#: apps/web/src/components/formatter/document-status.tsx:28
msgid "Completed"
msgstr "Abgeschlossen"
@@ -2143,7 +2143,7 @@ msgstr "Sobald Sie den QR-Code gescannt oder den Code manuell eingegeben haben,
msgid "Oops! Something went wrong."
msgstr "Hoppla! Etwas ist schief gelaufen."
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:97
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:101
msgid "Opened"
msgstr "Geöffnet"
@@ -3636,7 +3636,7 @@ msgstr "Unable to sign in"
msgid "Unauthorized"
msgstr "Unauthorized"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:112
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:116
msgid "Uncompleted"
msgstr "Uncompleted"
@@ -3848,7 +3848,7 @@ msgstr "Teams ansehen"
msgid "Viewed"
msgstr "Angesehen"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:82
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:86
msgid "Waiting"
msgstr "Warten"
+4 -4
View File
@@ -784,7 +784,7 @@ msgstr "Complete Signing"
msgid "Complete Viewing"
msgstr "Complete Viewing"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:58
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:62
#: apps/web/src/components/formatter/document-status.tsx:28
msgid "Completed"
msgstr "Completed"
@@ -2138,7 +2138,7 @@ msgstr "Once you have scanned the QR code or entered the code manually, enter th
msgid "Oops! Something went wrong."
msgstr "Oops! Something went wrong."
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:97
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:101
msgid "Opened"
msgstr "Opened"
@@ -3631,7 +3631,7 @@ msgstr "Unable to sign in"
msgid "Unauthorized"
msgstr "Unauthorized"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:112
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:116
msgid "Uncompleted"
msgstr "Uncompleted"
@@ -3843,7 +3843,7 @@ msgstr "View teams"
msgid "Viewed"
msgstr "Viewed"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:82
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:86
msgid "Waiting"
msgstr "Waiting"
+10 -6
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n"
"Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-19 09:18\n"
"PO-Revision-Date: 2024-10-08 12:05\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -157,6 +157,10 @@ msgstr "Annuler"
msgid "Cannot remove signer"
msgstr "Impossible de retirer le signataire"
#: packages/ui/primitives/document-flow/add-signers.tsx:221
#~ msgid "Cannot update signer because they have already signed a field"
#~ msgstr "Cannot update signer because they have already signed a field"
#: packages/lib/constants/recipient-roles.ts:17
msgid "Cc"
msgstr "Cc"
@@ -276,7 +280,7 @@ msgstr "Options d'email"
#: packages/ui/primitives/document-flow/add-fields.tsx:1082
msgid "Empty field"
msgstr ""
msgstr "Champ vide"
#: packages/lib/constants/template.ts:8
msgid "Enable Direct Link Signing"
@@ -701,15 +705,15 @@ msgstr "Ce champ ne peut pas être modifié ou supprimé. Lorsque vous partagez
#: packages/ui/primitives/document-flow/add-fields.tsx:1050
msgid "This recipient can no longer be modified as they have signed a field, or completed the document."
msgstr ""
msgstr "Ce destinataire ne peut plus être modifié car il a signé un champ ou complété le document."
#: packages/ui/primitives/document-flow/add-signers.tsx:195
#: packages/ui/primitives/document-flow/add-signers.tsx:165
#~ msgid "This signer has already received the document."
#~ msgstr "Ce signataire a déjà reçu le document."
#~ msgstr "This signer has already received the document."
#: packages/ui/primitives/document-flow/add-signers.tsx:194
msgid "This signer has already signed the document."
msgstr ""
msgstr "Ce signataire a déjà signé le document."
#: packages/ui/components/recipient/recipient-action-auth-select.tsx:48
msgid "This will override any global settings."
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n"
"Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-19 09:18\n"
"PO-Revision-Date: 2024-10-08 12:05\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -387,7 +387,7 @@ msgstr "Notre option auto-hébergée est idéale pour les petites équipes et le
#: apps/marketing/src/app/(marketing)/open/data.ts:25
#~ msgid "Part-Time"
#~ msgstr "Temps partiel"
#~ msgstr "Part-Time"
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:151
msgid "Premium Profile Name"
File diff suppressed because one or more lines are too long
+5 -5
View File
@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n"
"Project-Id-Version: documenso-app\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2024-09-19 09:18\n"
"PO-Revision-Date: 2024-10-08 12:05\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -789,7 +789,7 @@ msgstr "Compléter la signature"
msgid "Complete Viewing"
msgstr "Compléter la visualisation"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:58
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:62
#: apps/web/src/components/formatter/document-status.tsx:28
msgid "Completed"
msgstr "Complété"
@@ -2143,7 +2143,7 @@ msgstr "Une fois que vous avez scanné le code QR ou saisi le code manuellement,
msgid "Oops! Something went wrong."
msgstr "Oups ! Quelque chose a mal tourné."
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:97
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:101
msgid "Opened"
msgstr "Ouvert"
@@ -3636,7 +3636,7 @@ msgstr "Impossible de se connecter"
msgid "Unauthorized"
msgstr "Non autorisé"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:112
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:116
msgid "Uncompleted"
msgstr "Non complet"
@@ -3848,7 +3848,7 @@ msgstr "Voir les équipes"
msgid "Viewed"
msgstr "Vu"
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:82
#: apps/web/src/components/(dashboard)/avatar/stack-avatars-with-tooltip.tsx:86
msgid "Waiting"
msgstr "En attente"
+6 -2
View File
@@ -1,4 +1,8 @@
{
"extends": "./packages/tsconfig/base.json",
"include": ["packages/**/*", "apps/**/*"]
}
"include": [
"packages/**/*",
"apps/**/*",
"infra/**/*"
],
}