Compare commits

...

6 Commits

Author SHA1 Message Date
Mythie
4326e27a2a v1.8.1-rc.3 2024-12-02 07:48:03 +11:00
Catalin Pit
62806298cf fix: wrong signing invitation message (#1497) 2024-12-02 07:47:11 +11:00
Mythie
87186e08b1 v1.8.1-rc.2 2024-11-29 15:09:03 +11:00
Mythie
b27fd800ed fix: add distribution settings to external api 2024-11-29 14:10:48 +11:00
David Nguyen
98d85b086d feat: add initial api logging (#1494)
Improve API logging and error handling between client and server side.
2024-11-28 16:05:37 +07:00
Mythie
04293968c6 chore: update embedding docs 2024-11-28 15:55:17 +11:00
79 changed files with 1668 additions and 1085 deletions

View File

@@ -139,3 +139,6 @@ E2E_TEST_AUTHENTICATE_USER_PASSWORD="test_Password123"
# [[REDIS]] # [[REDIS]]
NEXT_PRIVATE_REDIS_URL= NEXT_PRIVATE_REDIS_URL=
NEXT_PRIVATE_REDIS_TOKEN= NEXT_PRIVATE_REDIS_TOKEN=
# [[LOGGER]]
NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY=

View File

@@ -0,0 +1,9 @@
{
"index": "Get Started",
"react": "React Integration",
"vue": "Vue Integration",
"svelte": "Svelte Integration",
"solid": "Solid Integration",
"preact": "Preact Integration",
"css-variables": "CSS Variables"
}

View File

@@ -0,0 +1,120 @@
---
title: CSS Variables
description: Learn about all available CSS variables for customizing your embedded signing experience
---
# CSS Variables
Platform customers have access to a comprehensive set of CSS variables that can be used to customize the appearance of the embedded signing experience. These variables control everything from colors to spacing and can be used to match your application's design system.
## Available Variables
### Colors
| Variable | Description | Default |
| ----------------------- | ---------------------------------- | -------------- |
| `background` | Base background color | System default |
| `foreground` | Base text color | System default |
| `muted` | Muted/subtle background color | System default |
| `mutedForeground` | Muted/subtle text color | System default |
| `popover` | Popover/dropdown background color | System default |
| `popoverForeground` | Popover/dropdown text color | System default |
| `card` | Card background color | System default |
| `cardBorder` | Card border color | System default |
| `cardBorderTint` | Card border tint/highlight color | System default |
| `cardForeground` | Card text color | System default |
| `fieldCard` | Field card background color | System default |
| `fieldCardBorder` | Field card border color | System default |
| `fieldCardForeground` | Field card text color | System default |
| `widget` | Widget background color | System default |
| `widgetForeground` | Widget text color | System default |
| `border` | Default border color | System default |
| `input` | Input field border color | System default |
| `primary` | Primary action/button color | System default |
| `primaryForeground` | Primary action/button text color | System default |
| `secondary` | Secondary action/button color | System default |
| `secondaryForeground` | Secondary action/button text color | System default |
| `accent` | Accent/highlight color | System default |
| `accentForeground` | Accent/highlight text color | System default |
| `destructive` | Destructive/danger action color | System default |
| `destructiveForeground` | Destructive/danger text color | System default |
| `ring` | Focus ring color | System default |
| `warning` | Warning/alert color | System default |
### Spacing and Layout
| Variable | Description | Default |
| -------- | ------------------------------- | -------------- |
| `radius` | Border radius size in REM units | System default |
## Usage Example
Here's how to use these variables in your embedding implementation:
```jsx
const cssVars = {
// Colors
background: '#ffffff',
foreground: '#000000',
primary: '#0000ff',
primaryForeground: '#ffffff',
accent: '#4f46e5',
destructive: '#ef4444',
// Spacing
radius: '0.5rem'
};
// React/Preact
<EmbedDirectTemplate
token={token}
cssVars={cssVars}
/>
// Vue
<EmbedDirectTemplate
:token="token"
:cssVars="cssVars"
/>
// Svelte
<EmbedDirectTemplate
{token}
cssVars={cssVars}
/>
// Solid
<EmbedDirectTemplate
token={token}
cssVars={cssVars}
/>
```
## Color Format
Colors can be specified in any valid CSS color format:
- Hexadecimal: `#ff0000`
- RGB: `rgb(255, 0, 0)`
- HSL: `hsl(0, 100%, 50%)`
- Named colors: `red`
The colors will be automatically converted to the appropriate format internally.
## Best Practices
1. **Maintain Contrast**: When customizing colors, ensure there's sufficient contrast between background and foreground colors for accessibility.
2. **Test Dark Mode**: If you haven't disabled dark mode, test your color variables in both light and dark modes.
3. **Use Your Brand Colors**: Align the primary and accent colors with your brand's color scheme for a cohesive look.
4. **Consistent Radius**: Use a consistent border radius value that matches your application's design system.
## Related
- [React Integration](/developers/embedding/react)
- [Vue Integration](/developers/embedding/vue)
- [Svelte Integration](/developers/embedding/svelte)
- [Solid Integration](/developers/embedding/solid)
- [Preact Integration](/developers/embedding/preact)

View File

@@ -11,7 +11,11 @@ Our embedding feature lets you integrate our document signing experience into yo
Embedding is currently available for all users on a **Teams Plan** and above, as well as **Early Adopter's** within a team (Early Adopters can create a team for free). Embedding is currently available for all users on a **Teams Plan** and above, as well as **Early Adopter's** within a team (Early Adopters can create a team for free).
In the future, we will roll out a **Platform Plan** that will offer additional enhancements for embedding, including the option to remove Documenso branding for a more customized experience. Our **Platform Plan** offers enhanced customization features including:
- Custom CSS and styling variables
- Dark mode controls
- The removal of Documenso branding from the embedding experience
## How Embedding Works ## How Embedding Works
@@ -22,6 +26,49 @@ Embedding with Documenso allows you to handle document signing in two main ways:
_For most use-cases we recommend using direct templates, however if you have a need for a more advanced integration, we are happy to help you get started._ _For most use-cases we recommend using direct templates, however if you have a need for a more advanced integration, we are happy to help you get started._
## Customization Options
### Styling and Theming
Platform customers have access to advanced styling options to customize the embedding experience:
1. **Custom CSS**: You can provide custom CSS to style the embedded component:
```jsx
<EmbedDirectTemplate
token={token}
css={`
.documenso-embed {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
`}
/>
```
2. **CSS Variables**: Fine-tune the appearance using CSS variables for colors, spacing, and more:
```jsx
<EmbedDirectTemplate
token={token}
cssVars={{
colorPrimary: '#0000FF',
colorBackground: '#F5F5F5',
borderRadius: '8px',
}}
/>
```
For a complete list of available CSS variables and their usage, see our [CSS Variables](/developers/embedding/css-variables) documentation.
3. **Dark Mode Control**: Disable dark mode if it doesn't match your application's theme:
```jsx
<EmbedDirectTemplate token={token} darkModeDisabled={true} />
```
These customization options are available for both Direct Templates and Signing Token embeds.
## Supported Frameworks ## Supported Frameworks
We support embedding across a range of popular JavaScript frameworks, including: We support embedding across a range of popular JavaScript frameworks, including:
@@ -120,12 +167,11 @@ Once you've obtained the appropriate tokens, you can integrate the signing exper
If you're using **web components**, the integration process is slightly different. Keep in mind that web components are currently less tested but can still provide flexibility for general use cases. If you're using **web components**, the integration process is slightly different. Keep in mind that web components are currently less tested but can still provide flexibility for general use cases.
## Stay Tuned for the Platform Plan ## Related
While embedding is already a powerful tool, we're working on a **Platform Plan** that will introduce even more functionality. This plan will offer: - [React Integration](/developers/embedding/react)
- [Vue Integration](/developers/embedding/vue)
- Additional customization options - [Svelte Integration](/developers/embedding/svelte)
- The ability to remove Documenso branding - [Solid Integration](/developers/embedding/solid)
- Additional controls for the signing experience - [Preact Integration](/developers/embedding/preact)
- [CSS Variables](/developers/embedding/css-variables)
More details will be shared as we approach the release.

View File

@@ -44,6 +44,9 @@ const MyEmbeddingComponent = () => {
| email | string (optional) | The email the signer that will be used by default for signing | | email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications | | lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion | | externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| css | string (optional) | Custom CSS to style the embedded component (Platform Plan only) |
| cssVars | object (optional) | CSS variables for customizing colors, spacing, etc. (Platform Plan only) |
| darkModeDisabled | boolean (optional) | Disable dark mode functionality (Platform Plan only) |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
@@ -75,3 +78,30 @@ const MyEmbeddingComponent = () => {
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
### Styling and Theming (Platform Plan)
Platform customers have access to advanced styling options:
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-preact';
const MyEmbeddingComponent = () => {
const token = 'your-token';
const customCss = `
.documenso-embed {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
`;
const cssVars = {
colorPrimary: '#0000FF',
colorBackground: '#F5F5F5',
borderRadius: '8px',
};
return (
<EmbedDirectTemplate token={token} css={customCss} cssVars={cssVars} darkModeDisabled={true} />
);
};
```

View File

@@ -44,6 +44,9 @@ const MyEmbeddingComponent = () => {
| email | string (optional) | The email the signer that will be used by default for signing | | email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications | | lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion | | externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| css | string (optional) | Custom CSS to style the embedded component (Platform Plan only) |
| cssVars | object (optional) | CSS variables for customizing colors, spacing, etc. (Platform Plan only) |
| darkModeDisabled | boolean (optional) | Disable dark mode functionality (Platform Plan only) |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
@@ -75,3 +78,34 @@ const MyEmbeddingComponent = () => {
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
### Styling and Theming (Platform Plan)
Platform customers have access to advanced styling options:
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-react';
const MyEmbeddingComponent = () => {
return (
<EmbedDirectTemplate
token="your-token"
// Custom CSS
css={`
.documenso-embed {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
`}
// CSS Variables
cssVars={{
colorPrimary: '#0000FF',
colorBackground: '#F5F5F5',
borderRadius: '8px',
}}
// Dark Mode Control
darkModeDisabled={true}
/>
);
};
```

View File

@@ -44,6 +44,9 @@ const MyEmbeddingComponent = () => {
| email | string (optional) | The email the signer that will be used by default for signing | | email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications | | lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion | | externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| css | string (optional) | Custom CSS to style the embedded component (Platform Plan only) |
| cssVars | object (optional) | CSS variables for customizing colors, spacing, etc. (Platform Plan only) |
| darkModeDisabled | boolean (optional) | Disable dark mode functionality (Platform Plan only) |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
@@ -75,3 +78,30 @@ const MyEmbeddingComponent = () => {
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
### Styling and Theming (Platform Plan)
Platform customers have access to advanced styling options:
```jsx
import { EmbedDirectTemplate } from '@documenso/embed-solid';
const MyEmbeddingComponent = () => {
const token = 'your-token';
const customCss = `
.documenso-embed {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
`;
const cssVars = {
colorPrimary: '#0000FF',
colorBackground: '#F5F5F5',
borderRadius: '8px',
};
return (
<EmbedDirectTemplate token={token} css={customCss} cssVars={cssVars} darkModeDisabled={true} />
);
};
```

View File

@@ -46,6 +46,9 @@ If you have a direct link template, you can simply provide the token for the tem
| email | string (optional) | The email the signer that will be used by default for signing | | email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications | | lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion | | externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| css | string (optional) | Custom CSS to style the embedded component (Platform Plan only) |
| cssVars | object (optional) | CSS variables for customizing colors, spacing, etc. (Platform Plan only) |
| darkModeDisabled | boolean (optional) | Disable dark mode functionality (Platform Plan only) |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
@@ -77,3 +80,28 @@ const MyEmbeddingComponent = () => {
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
### Styling and Theming (Platform Plan)
Platform customers have access to advanced styling options:
```html
<script lang="ts">
import { EmbedDirectTemplate } from '@documenso/embed-svelte';
const token = 'your-token';
const customCss = `
.documenso-embed {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
`;
const cssVars = {
colorPrimary: '#0000FF',
colorBackground: '#F5F5F5',
borderRadius: '8px',
};
</script>
<EmbedDirectTemplate {token} css="{customCss}" cssVars="{cssVars}" darkModeDisabled="{true}" />
```

View File

@@ -46,6 +46,9 @@ If you have a direct link template, you can simply provide the token for the tem
| email | string (optional) | The email the signer that will be used by default for signing | | email | string (optional) | The email the signer that will be used by default for signing |
| lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications | | lockEmail | boolean (optional) | Whether or not the email field should be locked disallowing modifications |
| externalId | string (optional) | The external ID to be used for the document that will be created upon completion | | externalId | string (optional) | The external ID to be used for the document that will be created upon completion |
| css | string (optional) | Custom CSS to style the embedded component (Platform Plan only) |
| cssVars | object (optional) | CSS variables for customizing colors, spacing, etc. (Platform Plan only) |
| darkModeDisabled | boolean (optional) | Disable dark mode functionality (Platform Plan only) |
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
@@ -77,3 +80,35 @@ const MyEmbeddingComponent = () => {
| onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed | | onDocumentReady | function (optional) | A callback function that will be called when the document is loaded and ready to be signed |
| onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed | | onDocumentCompleted | function (optional) | A callback function that will be called when the document has been completed |
| onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document | | onDocumentError | function (optional) | A callback function that will be called when an error occurs with the document |
### Styling and Theming (Platform Plan)
Platform customers have access to advanced styling options:
```html
<script setup lang="ts">
import { EmbedDirectTemplate } from '@documenso/embed-vue';
const token = ref('your-token');
const customCss = `
.documenso-embed {
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
`;
const cssVars = {
colorPrimary: '#0000FF',
colorBackground: '#F5F5F5',
borderRadius: '8px',
};
</script>
<template>
<EmbedDirectTemplate
:token="token"
:css="customCss"
:cssVars="cssVars"
:darkModeDisabled="true"
/>
</template>
```

View File

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

View File

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

View File

@@ -53,6 +53,17 @@ export const SigningPageView = ({
}: SigningPageViewProps) => { }: SigningPageViewProps) => {
const { documentData, documentMeta } = document; const { documentData, documentMeta } = document;
const shouldUseTeamDetails =
document.teamId && document.team?.teamGlobalSettings?.includeSenderDetails === false;
let senderName = document.User.name ?? '';
let senderEmail = `(${document.User.email})`;
if (shouldUseTeamDetails) {
senderName = document.team?.name ?? '';
senderEmail = document.team?.teamEmail?.email ? `(${document.team.teamEmail.email})` : '';
}
return ( return (
<div className="mx-auto w-full max-w-screen-xl"> <div className="mx-auto w-full max-w-screen-xl">
<h1 <h1
@@ -63,27 +74,41 @@ export const SigningPageView = ({
</h1> </h1>
<div className="mt-2.5 flex flex-wrap items-center justify-between gap-x-6"> <div className="mt-2.5 flex flex-wrap items-center justify-between gap-x-6">
<div> <div className="max-w-[50ch]">
<p <span className="text-muted-foreground truncate" title={senderName}>
className="text-muted-foreground truncate" {senderName} {senderEmail}
title={document.User.name ? document.User.name : ''} </span>{' '}
> <span className="text-muted-foreground">
{document.User.name}
</p>
<p className="text-muted-foreground">
{match(recipient.role) {match(recipient.role)
.with(RecipientRole.VIEWER, () => ( .with(RecipientRole.VIEWER, () =>
<Trans>({document.User.email}) has invited you to view this document</Trans> document.teamId && !shouldUseTeamDetails ? (
)) <Trans>
.with(RecipientRole.SIGNER, () => ( on behalf of "{document.team?.name}" has invited you to view this document
<Trans>({document.User.email}) has invited you to sign this document</Trans> </Trans>
)) ) : (
.with(RecipientRole.APPROVER, () => ( <Trans>has invited you to view this document</Trans>
<Trans>({document.User.email}) has invited you to approve this document</Trans> ),
)) )
.with(RecipientRole.SIGNER, () =>
document.teamId && !shouldUseTeamDetails ? (
<Trans>
on behalf of "{document.team?.name}" has invited you to sign this document
</Trans>
) : (
<Trans>has invited you to sign this document</Trans>
),
)
.with(RecipientRole.APPROVER, () =>
document.teamId && !shouldUseTeamDetails ? (
<Trans>
on behalf of "{document.team?.name}" has invited you to approve this document
</Trans>
) : (
<Trans>has invited you to approve this document</Trans>
),
)
.otherwise(() => null)} .otherwise(() => null)}
</p> </span>
</div> </div>
<RejectDocumentDialog document={document} token={recipient.token} /> <RejectDocumentDialog document={document} token={recipient.token} />

View File

@@ -1,3 +1,5 @@
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
import { buildLogger } from '@documenso/lib/utils/logger';
import * as trpcNext from '@documenso/trpc/server/adapters/next'; import * as trpcNext from '@documenso/trpc/server/adapters/next';
import { createTrpcContext } from '@documenso/trpc/server/context'; import { createTrpcContext } from '@documenso/trpc/server/context';
import { appRouter } from '@documenso/trpc/server/router'; import { appRouter } from '@documenso/trpc/server/router';
@@ -11,7 +13,44 @@ export const config = {
}, },
}; };
const logger = buildLogger();
export default trpcNext.createNextApiHandler({ export default trpcNext.createNextApiHandler({
router: appRouter, router: appRouter,
createContext: async ({ req, res }) => createTrpcContext({ req, res }), createContext: async ({ req, res }) => createTrpcContext({ req, res }),
onError(opts) {
const { error, path } = opts;
// Currently trialing changes with template and team router only.
if (!path || (!path.startsWith('template') && !path.startsWith('team'))) {
return;
}
// Always log the error for now.
console.error(error);
const appError = AppError.parseError(error.cause || error);
const isAppError = error.cause instanceof AppError;
// Only log AppErrors that are explicitly set to 500 or the error code
// is in the errorCodesToAlertOn list.
const isLoggableAppError =
isAppError && (appError.statusCode === 500 || errorCodesToAlertOn.includes(appError.code));
// Only log TRPC errors that are in the `errorCodesToAlertOn` list and is
// not an AppError.
const isLoggableTrpcError = !isAppError && errorCodesToAlertOn.includes(error.code);
if (isLoggableAppError || isLoggableTrpcError) {
logger.error(error, {
method: path,
context: {
appError: AppError.toJSON(appError),
},
});
}
},
}); });
const errorCodesToAlertOn = [AppErrorCode.UNKNOWN_ERROR, 'INTERNAL_SERVER_ERROR'];

144
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "@documenso/root", "name": "@documenso/root",
"version": "1.8.1-rc.1", "version": "1.8.1-rc.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@documenso/root", "name": "@documenso/root",
"version": "1.8.1-rc.1", "version": "1.8.1-rc.3",
"workspaces": [ "workspaces": [
"apps/*", "apps/*",
"packages/*" "packages/*"
@@ -77,7 +77,7 @@
}, },
"apps/marketing": { "apps/marketing": {
"name": "@documenso/marketing", "name": "@documenso/marketing",
"version": "1.8.1-rc.1", "version": "1.8.1-rc.3",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"@documenso/assets": "*", "@documenso/assets": "*",
@@ -438,7 +438,7 @@
}, },
"apps/web": { "apps/web": {
"name": "@documenso/web", "name": "@documenso/web",
"version": "1.8.1-rc.1", "version": "1.8.1-rc.3",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"@documenso/api": "*", "@documenso/api": "*",
@@ -3498,6 +3498,34 @@
"resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz", "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz",
"integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==" "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw=="
}, },
"node_modules/@honeybadger-io/core": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@honeybadger-io/core/-/core-6.6.0.tgz",
"integrity": "sha512-B5X05huAsDs7NJOYm4bwHf2v0tMuTjBWLfumHH9DCblq8E1XrujlbbNkIdEHlzc01K9oAXuvsaBwVkE7G5+aLQ==",
"dependencies": {
"json-nd": "^1.0.0",
"stacktrace-parser": "^0.1.10"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@honeybadger-io/js": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/@honeybadger-io/js/-/js-6.10.1.tgz",
"integrity": "sha512-T5WAhYHWHXFMxjY4NSawSY945i8ISIL5/gsjN3m0xO+oXrBAFaul3wY5p/FGH6r6RfCrjHoHl9Iu7Ed9aO9Ehg==",
"dependencies": {
"@honeybadger-io/core": "^6.6.0",
"@types/aws-lambda": "^8.10.89",
"@types/express": "^4.17.13"
},
"bin": {
"honeybadger-checkins-sync": "scripts/check-ins-sync-bin.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@hookform/resolvers": { "node_modules/@hookform/resolvers": {
"version": "3.3.2", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.2.tgz", "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.3.2.tgz",
@@ -10956,6 +10984,20 @@
"@types/estree": "*" "@types/estree": "*"
} }
}, },
"node_modules/@types/aws-lambda": {
"version": "8.10.146",
"resolved": "https://registry.npmjs.org/@types/aws-lambda/-/aws-lambda-8.10.146.tgz",
"integrity": "sha512-3BaDXYTh0e6UCJYL/jwV/3+GRslSc08toAiZSmleYtkAUyV5rtvdPYxrG/88uqvTuT6sb27WE9OS90ZNTIuQ0g=="
},
"node_modules/@types/body-parser": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
"integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
"node_modules/@types/cacheable-request": { "node_modules/@types/cacheable-request": {
"version": "6.0.3", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz",
@@ -10968,6 +11010,14 @@
"@types/responselike": "^1.0.0" "@types/responselike": "^1.0.0"
} }
}, },
"node_modules/@types/connect": {
"version": "3.4.38",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/cookie": { "node_modules/@types/cookie": {
"version": "0.6.0", "version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
@@ -11090,6 +11140,28 @@
"@types/estree": "*" "@types/estree": "*"
} }
}, },
"node_modules/@types/express": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz",
"integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^4.17.33",
"@types/qs": "*",
"@types/serve-static": "*"
}
},
"node_modules/@types/express-serve-static-core": {
"version": "4.19.6",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
"integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*",
"@types/send": "*"
}
},
"node_modules/@types/formidable": { "node_modules/@types/formidable": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-2.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-2.0.6.tgz",
@@ -11132,6 +11204,11 @@
"integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==",
"dev": true "dev": true
}, },
"node_modules/@types/http-errors": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
"integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA=="
},
"node_modules/@types/istanbul-lib-coverage": { "node_modules/@types/istanbul-lib-coverage": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
@@ -11201,6 +11278,11 @@
"resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.10.tgz",
"integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==" "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg=="
}, },
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
},
"node_modules/@types/minimatch": { "node_modules/@types/minimatch": {
"version": "5.1.2", "version": "5.1.2",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz",
@@ -11338,6 +11420,11 @@
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
"integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==" "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng=="
}, },
"node_modules/@types/qs": {
"version": "6.9.17",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz",
"integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ=="
},
"node_modules/@types/ramda": { "node_modules/@types/ramda": {
"version": "0.29.9", "version": "0.29.9",
"resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.9.tgz", "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.29.9.tgz",
@@ -11346,6 +11433,11 @@
"types-ramda": "^0.29.6" "types-ramda": "^0.29.6"
} }
}, },
"node_modules/@types/range-parser": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
},
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "18.2.18", "version": "18.2.18",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.18.tgz",
@@ -11401,6 +11493,25 @@
"integrity": "sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==", "integrity": "sha512-T+YwkslhsM+CeuhYUxyAjWm7mJ5am/K10UX40RuA6k6Lc7eGtq8iY2xOzy7Vq0GOqhl/xZl5l2FwURZMTPTUww==",
"dev": true "dev": true
}, },
"node_modules/@types/send": {
"version": "0.17.4",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
"integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
"dependencies": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"node_modules/@types/serve-static": {
"version": "1.15.7",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
"integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
"dependencies": {
"@types/http-errors": "*",
"@types/node": "*",
"@types/send": "*"
}
},
"node_modules/@types/swagger-ui-react": { "node_modules/@types/swagger-ui-react": {
"version": "4.18.3", "version": "4.18.3",
"resolved": "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.18.3.tgz", "resolved": "https://registry.npmjs.org/@types/swagger-ui-react/-/swagger-ui-react-4.18.3.tgz",
@@ -21011,6 +21122,11 @@
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
}, },
"node_modules/json-nd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-nd/-/json-nd-1.0.0.tgz",
"integrity": "sha512-8TIp0HZAY0VVrwRQJJPb4+nOTSPoOWZeEKBTLizUfQO4oym5Fc/MKqN8vEbLCxcyxDf2vwNxOQ1q84O49GWPyQ=="
},
"node_modules/json-parse-even-better-errors": { "node_modules/json-parse-even-better-errors": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
@@ -31249,6 +31365,25 @@
"integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
"dev": true "dev": true
}, },
"node_modules/stacktrace-parser": {
"version": "0.1.10",
"resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz",
"integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==",
"dependencies": {
"type-fest": "^0.7.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/stacktrace-parser/node_modules/type-fest": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz",
"integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==",
"engines": {
"node": ">=8"
}
},
"node_modules/stampit": { "node_modules/stampit": {
"version": "4.3.2", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/stampit/-/stampit-4.3.2.tgz", "resolved": "https://registry.npmjs.org/stampit/-/stampit-4.3.2.tgz",
@@ -36484,6 +36619,7 @@
"@documenso/email": "*", "@documenso/email": "*",
"@documenso/prisma": "*", "@documenso/prisma": "*",
"@documenso/signing": "*", "@documenso/signing": "*",
"@honeybadger-io/js": "^6.10.1",
"@lingui/core": "^4.11.3", "@lingui/core": "^4.11.3",
"@lingui/macro": "^4.11.3", "@lingui/macro": "^4.11.3",
"@lingui/react": "^4.11.3", "@lingui/react": "^4.11.3",

View File

@@ -1,6 +1,6 @@
{ {
"private": true, "private": true,
"version": "1.8.1-rc.1", "version": "1.8.1-rc.3",
"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",

View File

@@ -303,6 +303,8 @@ export const ApiContractV1Implementation = createNextRoute(ApiContractV1, {
signingOrder: body.meta.signingOrder, signingOrder: body.meta.signingOrder,
language: body.meta.language, language: body.meta.language,
typedSignatureEnabled: body.meta.typedSignatureEnabled, typedSignatureEnabled: body.meta.typedSignatureEnabled,
distributionMethod: body.meta.distributionMethod,
emailSettings: body.meta.emailSettings,
requestMetadata: extractNextApiRequestMetadata(args.req), requestMetadata: extractNextApiRequestMetadata(args.req),
}); });

View File

@@ -10,6 +10,7 @@ import {
ZDocumentActionAuthTypesSchema, ZDocumentActionAuthTypesSchema,
ZRecipientActionAuthTypesSchema, ZRecipientActionAuthTypesSchema,
} from '@documenso/lib/types/document-auth'; } from '@documenso/lib/types/document-auth';
import { ZDocumentEmailSettingsSchema } from '@documenso/lib/types/document-email';
import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta'; import { ZFieldMetaSchema } from '@documenso/lib/types/field-meta';
import { import {
DocumentDataType, DocumentDataType,
@@ -133,8 +134,12 @@ export const ZCreateDocumentMutationSchema = z.object({
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), typedSignatureEnabled: z.boolean().optional().default(true),
distributionMethod: z.nativeEnum(DocumentDistributionMethod).optional(),
emailSettings: ZDocumentEmailSettingsSchema.optional(),
}) })
.partial(), .partial()
.optional()
.default({}),
authOptions: z authOptions: z
.object({ .object({
globalAccessAuth: ZDocumentAccessAuthTypesSchema.optional(), globalAccessAuth: ZDocumentAccessAuthTypesSchema.optional(),
@@ -257,6 +262,7 @@ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
language: z.enum(SUPPORTED_LANGUAGE_CODES), language: z.enum(SUPPORTED_LANGUAGE_CODES),
distributionMethod: z.nativeEnum(DocumentDistributionMethod), distributionMethod: z.nativeEnum(DocumentDistributionMethod),
typedSignatureEnabled: z.boolean(), typedSignatureEnabled: z.boolean(),
emailSettings: ZDocumentEmailSettingsSchema,
}) })
.partial() .partial()
.optional(), .optional(),

View File

@@ -13,7 +13,9 @@ export const getTeamPrices = async () => {
const priceIds = prices.map((price) => price.id); const priceIds = prices.map((price) => price.id);
if (!monthlyPrice || !yearlyPrice) { if (!monthlyPrice || !yearlyPrice) {
throw new AppError('INVALID_CONFIG', 'Missing monthly or yearly price'); throw new AppError('INVALID_CONFIG', {
message: 'Missing monthly or yearly price',
});
} }
return { return {

View File

@@ -43,7 +43,9 @@ export const transferTeamSubscription = async ({
const teamCustomerId = team.customerId; const teamCustomerId = team.customerId;
if (!teamCustomerId) { if (!teamCustomerId) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Missing customer ID.'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Missing customer ID.',
});
} }
const [teamRelatedPlanPriceIds, teamSeatPrices] = await Promise.all([ const [teamRelatedPlanPriceIds, teamSeatPrices] = await Promise.all([

View File

@@ -61,7 +61,7 @@ export const TemplateDocumentInvite = ({
<> <>
{includeSenderDetails ? ( {includeSenderDetails ? (
<Trans> <Trans>
{inviterName} on behalf of {teamName} has invited you to{' '} {inviterName} on behalf of "{teamName}" has invited you to{' '}
{_(actionVerb).toLowerCase()} {_(actionVerb).toLowerCase()}
</Trans> </Trans>
) : ( ) : (

View File

@@ -42,7 +42,7 @@ export const DocumentInviteEmailTemplate = ({
if (isTeamInvite) { if (isTeamInvite) {
previewText = includeSenderDetails previewText = includeSenderDetails
? msg`${inviterName} on behalf of ${teamName} has invited you to ${action} ${documentName}` ? msg`${inviterName} on behalf of "${teamName}" has invited you to ${action} ${documentName}`
: msg`${teamName} has invited you to ${action} ${documentName}`; : msg`${teamName} has invited you to ${action} ${documentName}`;
} }
@@ -90,14 +90,16 @@ export const DocumentInviteEmailTemplate = ({
<Container className="mx-auto mt-12 max-w-xl"> <Container className="mx-auto mt-12 max-w-xl">
<Section> <Section>
<Text className="my-4 text-base font-semibold"> {!isTeamInvite && (
<Trans> <Text className="my-4 text-base font-semibold">
{inviterName}{' '} <Trans>
<Link className="font-normal text-slate-400" href="mailto:{inviterEmail}"> {inviterName}{' '}
({inviterEmail}) <Link className="font-normal text-slate-400" href="mailto:{inviterEmail}">
</Link> ({inviterEmail})
</Trans> </Link>
</Text> </Trans>
</Text>
)}
<Text className="mt-2 text-base text-slate-400"> <Text className="mt-2 text-base text-slate-400">
{customBody ? ( {customBody ? (

View File

@@ -1,4 +1,4 @@
import { TRPCError } from '@trpc/server'; import type { TRPCError } from '@trpc/server';
import { match } from 'ts-pattern'; import { match } from 'ts-pattern';
import { z } from 'zod'; import { z } from 'zod';
@@ -8,46 +8,69 @@ import { TRPCClientError } from '@documenso/trpc/client';
* Generic application error codes. * Generic application error codes.
*/ */
export enum AppErrorCode { export enum AppErrorCode {
'ALREADY_EXISTS' = 'AlreadyExists', 'ALREADY_EXISTS' = 'ALREADY_EXISTS',
'EXPIRED_CODE' = 'ExpiredCode', 'EXPIRED_CODE' = 'EXPIRED_CODE',
'INVALID_BODY' = 'InvalidBody', 'INVALID_BODY' = 'INVALID_BODY',
'INVALID_REQUEST' = 'InvalidRequest', 'INVALID_REQUEST' = 'INVALID_REQUEST',
'LIMIT_EXCEEDED' = 'LimitExceeded', 'LIMIT_EXCEEDED' = 'LIMIT_EXCEEDED',
'NOT_FOUND' = 'NotFound', 'NOT_FOUND' = 'NOT_FOUND',
'NOT_SETUP' = 'NotSetup', 'NOT_SETUP' = 'NOT_SETUP',
'UNAUTHORIZED' = 'Unauthorized', 'UNAUTHORIZED' = 'UNAUTHORIZED',
'UNKNOWN_ERROR' = 'UnknownError', 'UNKNOWN_ERROR' = 'UNKNOWN_ERROR',
'RETRY_EXCEPTION' = 'RetryException', 'RETRY_EXCEPTION' = 'RETRY_EXCEPTION',
'SCHEMA_FAILED' = 'SchemaFailed', 'SCHEMA_FAILED' = 'SCHEMA_FAILED',
'TOO_MANY_REQUESTS' = 'TooManyRequests', 'TOO_MANY_REQUESTS' = 'TOO_MANY_REQUESTS',
'PROFILE_URL_TAKEN' = 'ProfileUrlTaken', 'PROFILE_URL_TAKEN' = 'PROFILE_URL_TAKEN',
'PREMIUM_PROFILE_URL' = 'PremiumProfileUrl', 'PREMIUM_PROFILE_URL' = 'PREMIUM_PROFILE_URL',
} }
const genericErrorCodeToTrpcErrorCodeMap: Record<string, TRPCError['code']> = { export const genericErrorCodeToTrpcErrorCodeMap: Record<
[AppErrorCode.ALREADY_EXISTS]: 'BAD_REQUEST', string,
[AppErrorCode.EXPIRED_CODE]: 'BAD_REQUEST', { code: TRPCError['code']; status: number }
[AppErrorCode.INVALID_BODY]: 'BAD_REQUEST', > = {
[AppErrorCode.INVALID_REQUEST]: 'BAD_REQUEST', [AppErrorCode.ALREADY_EXISTS]: { code: 'BAD_REQUEST', status: 400 },
[AppErrorCode.NOT_FOUND]: 'NOT_FOUND', [AppErrorCode.EXPIRED_CODE]: { code: 'BAD_REQUEST', status: 400 },
[AppErrorCode.NOT_SETUP]: 'BAD_REQUEST', [AppErrorCode.INVALID_BODY]: { code: 'BAD_REQUEST', status: 400 },
[AppErrorCode.UNAUTHORIZED]: 'UNAUTHORIZED', [AppErrorCode.INVALID_REQUEST]: { code: 'BAD_REQUEST', status: 400 },
[AppErrorCode.UNKNOWN_ERROR]: 'INTERNAL_SERVER_ERROR', [AppErrorCode.NOT_FOUND]: { code: 'NOT_FOUND', status: 404 },
[AppErrorCode.RETRY_EXCEPTION]: 'INTERNAL_SERVER_ERROR', [AppErrorCode.NOT_SETUP]: { code: 'BAD_REQUEST', status: 400 },
[AppErrorCode.SCHEMA_FAILED]: 'INTERNAL_SERVER_ERROR', [AppErrorCode.UNAUTHORIZED]: { code: 'UNAUTHORIZED', status: 401 },
[AppErrorCode.TOO_MANY_REQUESTS]: 'TOO_MANY_REQUESTS', [AppErrorCode.UNKNOWN_ERROR]: { code: 'INTERNAL_SERVER_ERROR', status: 500 },
[AppErrorCode.PROFILE_URL_TAKEN]: 'BAD_REQUEST', [AppErrorCode.RETRY_EXCEPTION]: { code: 'INTERNAL_SERVER_ERROR', status: 500 },
[AppErrorCode.PREMIUM_PROFILE_URL]: 'BAD_REQUEST', [AppErrorCode.SCHEMA_FAILED]: { code: 'INTERNAL_SERVER_ERROR', status: 500 },
[AppErrorCode.TOO_MANY_REQUESTS]: { code: 'TOO_MANY_REQUESTS', status: 429 },
[AppErrorCode.PROFILE_URL_TAKEN]: { code: 'BAD_REQUEST', status: 400 },
[AppErrorCode.PREMIUM_PROFILE_URL]: { code: 'BAD_REQUEST', status: 400 },
}; };
export const ZAppErrorJsonSchema = z.object({ export const ZAppErrorJsonSchema = z.object({
code: z.string(), code: z.string(),
message: z.string().optional(), message: z.string().optional(),
userMessage: z.string().optional(), userMessage: z.string().optional(),
statusCode: z.number().optional(),
}); });
export type TAppErrorJsonSchema = z.infer<typeof ZAppErrorJsonSchema>; export type TAppErrorJsonSchema = z.infer<typeof ZAppErrorJsonSchema>;
type AppErrorOptions = {
/**
* An internal message for logging.
*/
message?: string;
/**
* A message which can be potientially displayed to the user.
*/
userMessage?: string;
/**
* The status code to be associated with the error.
*
* Mainly used for API -> Frontend communication and logging filtering.
*/
statusCode?: number;
};
export class AppError extends Error { export class AppError extends Error {
/** /**
* The error code. * The error code.
@@ -59,6 +82,11 @@ export class AppError extends Error {
*/ */
userMessage?: string; userMessage?: string;
/**
* The status code to be associated with the error.
*/
statusCode?: number;
/** /**
* Create a new AppError. * Create a new AppError.
* *
@@ -66,10 +94,12 @@ export class AppError extends Error {
* @param message An internal error message. * @param message An internal error message.
* @param userMessage A error message which can be displayed to the user. * @param userMessage A error message which can be displayed to the user.
*/ */
public constructor(errorCode: string, message?: string, userMessage?: string) { public constructor(errorCode: string, options?: AppErrorOptions) {
super(message || errorCode); super(options?.message || errorCode);
this.code = errorCode; this.code = errorCode;
this.userMessage = userMessage; this.userMessage = options?.userMessage;
this.statusCode = options?.statusCode;
} }
/** /**
@@ -84,16 +114,21 @@ export class AppError extends Error {
// Handle TRPC errors. // Handle TRPC errors.
if (error instanceof TRPCClientError) { if (error instanceof TRPCClientError) {
const parsedJsonError = AppError.parseFromJSONString(error.message); const parsedJsonError = AppError.parseFromJSON(error.data?.appError);
return parsedJsonError || new AppError('UnknownError', error.message);
const fallbackError = new AppError(AppErrorCode.UNKNOWN_ERROR, {
message: error.message,
});
return parsedJsonError || fallbackError;
} }
// Handle completely unknown errors. // Handle completely unknown errors.
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const { code, message, userMessage } = error as { const { code, message, userMessage, statusCode } = error as {
code: unknown; code: unknown;
message: unknown; message: unknown;
status: unknown; statusCode: unknown;
userMessage: unknown; userMessage: unknown;
}; };
@@ -102,16 +137,15 @@ export class AppError extends Error {
const validUserMessage: string | undefined = const validUserMessage: string | undefined =
typeof userMessage === 'string' ? userMessage : undefined; typeof userMessage === 'string' ? userMessage : undefined;
return new AppError(validCode, validMessage, validUserMessage); const validStatusCode = typeof statusCode === 'number' ? statusCode : undefined;
}
static parseErrorToTRPCError(error: unknown): TRPCError { const options: AppErrorOptions = {
const appError = AppError.parseError(error); message: validMessage,
userMessage: validUserMessage,
statusCode: validStatusCode,
};
return new TRPCError({ return new AppError(validCode, options);
code: genericErrorCodeToTrpcErrorCodeMap[appError.code] || 'BAD_REQUEST',
message: AppError.toJSONString(appError),
});
} }
/** /**
@@ -120,12 +154,26 @@ export class AppError extends Error {
* @param appError The AppError to convert to JSON. * @param appError The AppError to convert to JSON.
* @returns A JSON object representing the AppError. * @returns A JSON object representing the AppError.
*/ */
static toJSON({ code, message, userMessage }: AppError): TAppErrorJsonSchema { static toJSON({ code, message, userMessage, statusCode }: AppError): TAppErrorJsonSchema {
return { const data: TAppErrorJsonSchema = {
code, code,
message,
userMessage,
}; };
// Explicity only set values if it exists, since TRPC will add meta for undefined
// values which clutters up API responses.
if (message) {
data.message = message;
}
if (userMessage) {
data.userMessage = userMessage;
}
if (statusCode) {
data.statusCode = statusCode;
}
return data;
} }
/** /**
@@ -138,15 +186,21 @@ export class AppError extends Error {
return JSON.stringify(AppError.toJSON(appError)); return JSON.stringify(AppError.toJSON(appError));
} }
static parseFromJSONString(jsonString: string): AppError | null { static parseFromJSON(value: unknown): AppError | null {
try { try {
const parsed = ZAppErrorJsonSchema.safeParse(JSON.parse(jsonString)); const parsed = ZAppErrorJsonSchema.safeParse(value);
if (!parsed.success) { if (!parsed.success) {
return null; return null;
} }
return new AppError(parsed.data.code, parsed.data.message, parsed.data.userMessage); const { message, userMessage, statusCode } = parsed.data;
return new AppError(parsed.data.code, {
message,
userMessage,
statusCode,
});
} catch { } catch {
return null; return null;
} }

View File

@@ -133,7 +133,7 @@ export const SEND_SIGNING_EMAIL_JOB_DEFINITION = {
if (!emailMessage) { if (!emailMessage) {
emailMessage = i18n._( emailMessage = i18n._(
team.teamGlobalSettings?.includeSenderDetails team.teamGlobalSettings?.includeSenderDetails
? msg`${user.name} on behalf of ${team.name} has invited you to ${recipientActionVerb} the document "${document.title}".` ? msg`${user.name} on behalf of "${team.name}" has invited you to ${recipientActionVerb} the document "${document.title}".`
: msg`${team.name} has invited you to ${recipientActionVerb} the document "${document.title}".`, : msg`${team.name} has invited you to ${recipientActionVerb} the document "${document.title}".`,
); );
} }

View File

@@ -25,6 +25,7 @@
"@documenso/email": "*", "@documenso/email": "*",
"@documenso/prisma": "*", "@documenso/prisma": "*",
"@documenso/signing": "*", "@documenso/signing": "*",
"@honeybadger-io/js": "^6.10.1",
"@lingui/core": "^4.11.3", "@lingui/core": "^4.11.3",
"@lingui/macro": "^4.11.3", "@lingui/macro": "^4.11.3",
"@lingui/react": "^4.11.3", "@lingui/react": "^4.11.3",
@@ -62,4 +63,4 @@
"@types/luxon": "^3.3.1", "@types/luxon": "^3.3.1",
"@types/pg": "^8.11.4" "@types/pg": "^8.11.4"
} }
} }

View File

@@ -40,7 +40,9 @@ export const createPasskeyAuthenticationOptions = async ({
}); });
if (!preferredPasskey) { if (!preferredPasskey) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Requested passkey not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Requested passkey not found',
});
} }
} }

View File

@@ -50,7 +50,9 @@ export const createPasskey = async ({
}); });
if (!verificationToken) { if (!verificationToken) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Challenge token not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Challenge token not found',
});
} }
await prisma.verificationToken.deleteMany({ await prisma.verificationToken.deleteMany({
@@ -61,7 +63,9 @@ export const createPasskey = async ({
}); });
if (verificationToken.expires < new Date()) { if (verificationToken.expires < new Date()) {
throw new AppError(AppErrorCode.EXPIRED_CODE, 'Challenge token expired'); throw new AppError(AppErrorCode.EXPIRED_CODE, {
message: 'Challenge token expired',
});
} }
const { rpId: expectedRPID, origin: expectedOrigin } = getAuthenticatorOptions(); const { rpId: expectedRPID, origin: expectedOrigin } = getAuthenticatorOptions();
@@ -74,7 +78,9 @@ export const createPasskey = async ({
}); });
if (!verification.verified || !verification.registrationInfo) { if (!verification.verified || !verification.registrationInfo) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Verification failed'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Verification failed',
});
} }
const { credentialPublicKey, credentialID, counter, credentialDeviceType, credentialBackedUp } = const { credentialPublicKey, credentialID, counter, credentialDeviceType, credentialBackedUp } =

View File

@@ -47,7 +47,9 @@ export const createDocument = async ({
teamId !== undefined && teamId !== undefined &&
!user.teamMembers.some((teamMember) => teamMember.teamId === teamId) !user.teamMembers.some((teamMember) => teamMember.teamId === teamId)
) { ) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Team not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Team not found',
});
} }
let team: (Team & { teamGlobalSettings: TeamGlobalSettings | null }) | null = null; let team: (Team & { teamGlobalSettings: TeamGlobalSettings | null }) | null = null;

View File

@@ -4,6 +4,7 @@ import { prisma } from '@documenso/prisma';
import type { Prisma } from '@documenso/prisma/client'; import type { Prisma } from '@documenso/prisma/client';
import { TeamMemberRole } from '@documenso/prisma/client'; import { TeamMemberRole } from '@documenso/prisma/client';
import { AppError, AppErrorCode } from '../../errors/app-error';
import { DocumentVisibility } from '../../types/document-visibility'; import { DocumentVisibility } from '../../types/document-visibility';
import { getTeamById } from '../team/get-team'; import { getTeamById } from '../team/get-team';
@@ -20,7 +21,7 @@ export const getDocumentById = async ({ id, userId, teamId }: GetDocumentByIdOpt
teamId, teamId,
}); });
return await prisma.document.findFirstOrThrow({ const document = await prisma.document.findFirst({
where: documentWhereInput, where: documentWhereInput,
include: { include: {
documentData: true, documentData: true,
@@ -45,6 +46,14 @@ export const getDocumentById = async ({ id, userId, teamId }: GetDocumentByIdOpt
}, },
}, },
}); });
if (!document) {
throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Document could not be found',
});
}
return document;
}; };
export type GetDocumentWhereInputOptions = { export type GetDocumentWhereInputOptions = {

View File

@@ -81,6 +81,17 @@ export const getDocumentAndSenderByToken = async ({
token, token,
}, },
}, },
team: {
select: {
name: true,
teamEmail: true,
teamGlobalSettings: {
select: {
includeSenderDetails: true,
},
},
},
},
}, },
}); });
@@ -107,7 +118,9 @@ export const getDocumentAndSenderByToken = async ({
} }
if (!documentAccessValid) { if (!documentAccessValid) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Invalid access values'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Invalid access values',
});
} }
return { return {
@@ -167,7 +180,9 @@ export const getDocumentAndRecipientByToken = async ({
} }
if (!documentAccessValid) { if (!documentAccessValid) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Invalid access values'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Invalid access values',
});
} }
return { return {

View File

@@ -106,7 +106,9 @@ export const isRecipientAuthorized = async ({
// Should not be possible. // Should not be possible.
if (!user) { if (!user) {
throw new AppError(AppErrorCode.NOT_FOUND, 'User not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'User not found',
});
} }
return await verifyTwoFactorAuthenticationToken({ return await verifyTwoFactorAuthenticationToken({
@@ -164,7 +166,9 @@ const verifyPasskey = async ({
}); });
if (!passkey) { if (!passkey) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Passkey not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Passkey not found',
});
} }
const verificationToken = await prisma.verificationToken const verificationToken = await prisma.verificationToken
@@ -177,11 +181,15 @@ const verifyPasskey = async ({
.catch(() => null); .catch(() => null);
if (!verificationToken) { if (!verificationToken) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Token not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Token not found',
});
} }
if (verificationToken.expires < new Date()) { if (verificationToken.expires < new Date()) {
throw new AppError(AppErrorCode.EXPIRED_CODE, 'Token expired'); throw new AppError(AppErrorCode.EXPIRED_CODE, {
message: 'Token expired',
});
} }
const { rpId, origin } = getAuthenticatorOptions(); const { rpId, origin } = getAuthenticatorOptions();
@@ -199,7 +207,9 @@ const verifyPasskey = async ({
}).catch(() => null); // May want to log this for insights. }).catch(() => null); // May want to log this for insights.
if (verification?.verified !== true) { if (verification?.verified !== true) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'User is not authorized'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'User is not authorized',
});
} }
await prisma.passkey.update({ await prisma.passkey.update({

View File

@@ -134,7 +134,7 @@ export const resendDocument = async ({
emailMessage = emailMessage =
customEmail?.message || customEmail?.message ||
i18n._( i18n._(
msg`${user.name} on behalf of ${document.team.name} has invited you to ${recipientActionVerb} the document "${document.title}".`, msg`${user.name} on behalf of "${document.team.name}" has invited you to ${recipientActionVerb} the document "${document.title}".`,
); );
} }

View File

@@ -37,7 +37,9 @@ export const updateDocumentSettings = async ({
requestMetadata, requestMetadata,
}: UpdateDocumentSettingsOptions) => { }: UpdateDocumentSettingsOptions) => {
if (!data.title && !data.globalAccessAuth && !data.globalActionAuth) { if (!data.title && !data.globalAccessAuth && !data.globalActionAuth) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Missing data to update'); throw new AppError(AppErrorCode.INVALID_BODY, {
message: 'Missing data to update',
});
} }
const user = await prisma.user.findFirstOrThrow({ const user = await prisma.user.findFirstOrThrow({
@@ -96,10 +98,9 @@ export const updateDocumentSettings = async ({
!allowedVisibilities.includes(document.visibility) || !allowedVisibilities.includes(document.visibility) ||
(data.visibility && !allowedVisibilities.includes(data.visibility)) (data.visibility && !allowedVisibilities.includes(data.visibility))
) { ) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to update the document visibility',
'You do not have permission to update the document visibility', });
);
} }
}) })
.with(TeamMemberRole.MEMBER, () => { .with(TeamMemberRole.MEMBER, () => {
@@ -107,17 +108,15 @@ export const updateDocumentSettings = async ({
document.visibility !== DocumentVisibility.EVERYONE || document.visibility !== DocumentVisibility.EVERYONE ||
(data.visibility && data.visibility !== DocumentVisibility.EVERYONE) (data.visibility && data.visibility !== DocumentVisibility.EVERYONE)
) { ) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to update the document visibility',
'You do not have permission to update the document visibility', });
);
} }
}) })
.otherwise(() => { .otherwise(() => {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to update the document',
'You do not have permission to update the document', });
);
}); });
} }
@@ -142,10 +141,9 @@ export const updateDocumentSettings = async ({
}); });
if (!isDocumentEnterprise) { if (!isDocumentEnterprise) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to set the action auth',
'You do not have permission to set the action auth', });
);
} }
} }
@@ -161,10 +159,9 @@ export const updateDocumentSettings = async ({
const auditLogs: CreateDocumentAuditLogDataResponse[] = []; const auditLogs: CreateDocumentAuditLogDataResponse[] = [];
if (!isTitleSame && document.status !== DocumentStatus.DRAFT) { if (!isTitleSame && document.status !== DocumentStatus.DRAFT) {
throw new AppError( throw new AppError(AppErrorCode.INVALID_BODY, {
AppErrorCode.INVALID_BODY, message: 'You cannot update the title if the document has been sent',
'You cannot update the title if the document has been sent', });
);
} }
if (!isTitleSame) { if (!isTitleSame) {

View File

@@ -45,7 +45,9 @@ export const validateFieldAuth = async ({
}); });
if (!isValid) { if (!isValid) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Invalid authentication values'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Invalid authentication values',
});
} }
return derivedRecipientActionAuth; return derivedRecipientActionAuth;

View File

@@ -104,7 +104,9 @@ export const setFieldsForDocument = async ({
// Each field MUST have a recipient associated with it. // Each field MUST have a recipient associated with it.
if (!recipient) { if (!recipient) {
throw new AppError(AppErrorCode.INVALID_REQUEST, `Recipient not found for field ${field.id}`); throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: `Recipient not found for field ${field.id}`,
});
} }
// Check whether the existing field can be modified. // Check whether the existing field can be modified.
@@ -113,10 +115,10 @@ export const setFieldsForDocument = async ({
hasFieldBeenChanged(existing, field) && hasFieldBeenChanged(existing, field) &&
!canRecipientFieldsBeModified(recipient, existingFields) !canRecipientFieldsBeModified(recipient, existingFields)
) { ) {
throw new AppError( throw new AppError(AppErrorCode.INVALID_REQUEST, {
AppErrorCode.INVALID_REQUEST, message:
'Cannot modify a field where the recipient has already interacted with the document', 'Cannot modify a field where the recipient has already interacted with the document',
); });
} }
return { return {

View File

@@ -115,7 +115,9 @@ export const getPublicProfileByUrl = async ({
// Log as critical error. // Log as critical error.
if (user?.profile && team?.profile) { if (user?.profile && team?.profile) {
console.error('Profile URL is ambiguous', { profileUrl, userId: user.id, teamId: team.id }); console.error('Profile URL is ambiguous', { profileUrl, userId: user.id, teamId: team.id });
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Profile URL is ambiguous'); throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: 'Profile URL is ambiguous',
});
} }
if (user?.profile?.enabled) { if (user?.profile?.enabled) {
@@ -177,5 +179,7 @@ export const getPublicProfileByUrl = async ({
}; };
} }
throw new AppError(AppErrorCode.NOT_FOUND, 'Profile not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Profile not found',
});
}; };

View File

@@ -18,10 +18,9 @@ export const getTeamTokens = async ({ userId, teamId }: GetUserTokensOptions) =>
}); });
if (teamMember?.role !== TeamMemberRole.ADMIN) { if (teamMember?.role !== TeamMemberRole.ADMIN) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have the required permissions to view this page.',
'You do not have the required permissions to view this page.', });
);
} }
return await prisma.apiToken.findMany({ return await prisma.apiToken.findMany({

View File

@@ -105,10 +105,9 @@ export const setRecipientsForDocument = async ({
}); });
if (!isDocumentEnterprise) { if (!isDocumentEnterprise) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to set the action auth',
'You do not have permission to set the action auth', });
);
} }
} }
@@ -142,10 +141,9 @@ export const setRecipientsForDocument = async ({
hasRecipientBeenChanged(existing, recipient) && hasRecipientBeenChanged(existing, recipient) &&
!canRecipientBeModified(existing, document.Field) !canRecipientBeModified(existing, document.Field)
) { ) {
throw new AppError( throw new AppError(AppErrorCode.INVALID_REQUEST, {
AppErrorCode.INVALID_REQUEST, message: 'Cannot modify a recipient who has already interacted with the document',
'Cannot modify a recipient who has already interacted with the document', });
);
} }
return { return {

View File

@@ -72,10 +72,9 @@ export const setRecipientsForTemplate = async ({
}); });
if (!isDocumentEnterprise) { if (!isDocumentEnterprise) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to set the action auth',
'You do not have permission to set the action auth', });
);
} }
} }
@@ -119,14 +118,15 @@ export const setRecipientsForTemplate = async ({
); );
if (updatedDirectRecipient?.role === RecipientRole.CC) { if (updatedDirectRecipient?.role === RecipientRole.CC) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Cannot set direct recipient as CC'); throw new AppError(AppErrorCode.INVALID_BODY, {
message: 'Cannot set direct recipient as CC',
});
} }
if (deletedDirectRecipient) { if (deletedDirectRecipient) {
throw new AppError( throw new AppError(AppErrorCode.INVALID_BODY, {
AppErrorCode.INVALID_BODY, message: 'Cannot delete direct recipient while direct template exists',
'Cannot delete direct recipient while direct template exists', });
);
} }
} }

View File

@@ -96,10 +96,9 @@ export const updateRecipient = async ({
}); });
if (!isDocumentEnterprise) { if (!isDocumentEnterprise) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to set the action auth',
'You do not have permission to set the action auth', });
);
} }
} }

View File

@@ -47,6 +47,8 @@ export const createTeamPendingCheckoutSession = async ({
console.error(e); console.error(e);
// Absorb all the errors incase Stripe throws something sensitive. // Absorb all the errors incase Stripe throws something sensitive.
throw new AppError(AppErrorCode.UNKNOWN_ERROR, 'Something went wrong.'); throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
message: 'Something went wrong.',
});
} }
}; };

View File

@@ -55,10 +55,9 @@ export const createTeamEmailVerification = async ({
}); });
if (team.teamEmail || team.emailVerification) { if (team.teamEmail || team.emailVerification) {
throw new AppError( throw new AppError(AppErrorCode.INVALID_REQUEST, {
AppErrorCode.INVALID_REQUEST, message: 'Team already has an email or existing email verification.',
'Team already has an email or existing email verification.', });
);
} }
const existingTeamEmail = await tx.teamEmail.findFirst({ const existingTeamEmail = await tx.teamEmail.findFirst({
@@ -68,7 +67,9 @@ export const createTeamEmailVerification = async ({
}); });
if (existingTeamEmail) { if (existingTeamEmail) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Email already taken by another team.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'Email already taken by another team.',
});
} }
const { token, expiresAt } = createTokenVerification({ hours: 1 }); const { token, expiresAt } = createTokenVerification({ hours: 1 });
@@ -97,7 +98,9 @@ export const createTeamEmailVerification = async ({
const target = z.array(z.string()).safeParse(err.meta?.target); const target = z.array(z.string()).safeParse(err.meta?.target);
if (err.code === 'P2002' && target.success && target.data.includes('email')) { if (err.code === 'P2002' && target.success && target.data.includes('email')) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Email already taken by another team.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'Email already taken by another team.',
});
} }
throw err; throw err;

View File

@@ -69,7 +69,9 @@ export const createTeamMemberInvites = async ({
const currentTeamMember = team.members.find((member) => member.user.id === userId); const currentTeamMember = team.members.find((member) => member.user.id === userId);
if (!currentTeamMember) { if (!currentTeamMember) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'User not part of team.'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'User not part of team.',
});
} }
const usersToInvite = invitations.filter((invitation) => { const usersToInvite = invitations.filter((invitation) => {
@@ -91,10 +93,9 @@ export const createTeamMemberInvites = async ({
); );
if (unauthorizedRoleAccess) { if (unauthorizedRoleAccess) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'User does not have permission to set high level roles',
'User does not have permission to set high level roles', });
);
} }
const teamMemberInvites = usersToInvite.map(({ email, role }) => ({ const teamMemberInvites = usersToInvite.map(({ email, role }) => ({
@@ -127,11 +128,10 @@ export const createTeamMemberInvites = async ({
if (sendEmailResultErrorList.length > 0) { if (sendEmailResultErrorList.length > 0) {
console.error(JSON.stringify(sendEmailResultErrorList)); console.error(JSON.stringify(sendEmailResultErrorList));
throw new AppError( throw new AppError('EmailDeliveryFailed', {
'EmailDeliveryFailed', message: 'Failed to send invite emails to one or more users.',
'Failed to send invite emails to one or more users.', userMessage: `Failed to send invites to ${sendEmailResultErrorList.length}/${teamMemberInvites.length} users.`,
`Failed to send invites to ${sendEmailResultErrorList.length}/${teamMemberInvites.length} users.`, });
);
} }
}; };

View File

@@ -87,7 +87,9 @@ export const createTeam = async ({
}); });
if (existingUserProfileWithUrl) { if (existingUserProfileWithUrl) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'URL already taken.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'URL already taken.',
});
} }
await tx.team.create({ await tx.team.create({
@@ -131,15 +133,21 @@ export const createTeam = async ({
}); });
if (existingUserProfileWithUrl) { if (existingUserProfileWithUrl) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'URL already taken.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'URL already taken.',
});
} }
if (existingTeamWithUrl) { if (existingTeamWithUrl) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Team URL already exists.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'Team URL already exists.',
});
} }
if (!customerId) { if (!customerId) {
throw new AppError(AppErrorCode.UNKNOWN_ERROR, 'Missing customer ID for pending teams.'); throw new AppError(AppErrorCode.UNKNOWN_ERROR, {
message: 'Missing customer ID for pending teams.',
});
} }
return await tx.teamPending.create({ return await tx.teamPending.create({
@@ -166,7 +174,9 @@ export const createTeam = async ({
const target = z.array(z.string()).safeParse(err.meta?.target); const target = z.array(z.string()).safeParse(err.meta?.target);
if (err.code === 'P2002' && target.success && target.data.includes('url')) { if (err.code === 'P2002' && target.success && target.data.includes('url')) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Team URL already exists.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'Team URL already exists.',
});
} }
throw err; throw err;

View File

@@ -60,11 +60,13 @@ export const deleteTeamMembers = async ({
); );
if (!currentTeamMember) { if (!currentTeamMember) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Team member record does not exist'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Team member record does not exist',
});
} }
if (teamMembersToRemove.find((member) => member.userId === team.ownerUserId)) { if (teamMembersToRemove.find((member) => member.userId === team.ownerUserId)) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Cannot remove the team owner'); throw new AppError(AppErrorCode.UNAUTHORIZED, { message: 'Cannot remove the team owner' });
} }
const isMemberToRemoveHigherRole = teamMembersToRemove.some( const isMemberToRemoveHigherRole = teamMembersToRemove.some(
@@ -72,7 +74,9 @@ export const deleteTeamMembers = async ({
); );
if (isMemberToRemoveHigherRole) { if (isMemberToRemoveHigherRole) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Cannot remove a member with a higher role'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Cannot remove a member with a higher role',
});
} }
// Remove the team members. // Remove the team members.

View File

@@ -24,7 +24,9 @@ export const findTeamInvoices = async ({ userId, teamId }: FindTeamInvoicesOptio
}); });
if (!team.customerId) { if (!team.customerId) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Team has no customer ID.'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Team has no customer ID.',
});
} }
const results = await getInvoices({ customerId: team.customerId }); const results = await getInvoices({ customerId: team.customerId });

View File

@@ -33,7 +33,9 @@ export const getTeamPublicProfile = async ({
}); });
if (!team) { if (!team) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Team not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Team not found',
});
} }
// Create and return the public profile. // Create and return the public profile.
@@ -47,7 +49,9 @@ export const getTeamPublicProfile = async ({
}); });
if (!profile) { if (!profile) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Failed to create public profile'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Failed to create public profile',
});
} }
return { return {

View File

@@ -38,16 +38,17 @@ export const resendTeamEmailVerification = async ({
}); });
if (!team) { if (!team) {
throw new AppError('TeamNotFound', 'User is not a member of the team.'); throw new AppError('TeamNotFound', {
message: 'User is not a member of the team.',
});
} }
const { emailVerification } = team; const { emailVerification } = team;
if (!emailVerification) { if (!emailVerification) {
throw new AppError( throw new AppError('VerificationNotFound', {
'VerificationNotFound', message: 'No team email verification exists for this team.',
'No team email verification exists for this team.', });
);
} }
const { token, expiresAt } = createTokenVerification({ hours: 1 }); const { token, expiresAt } = createTokenVerification({ hours: 1 });

View File

@@ -55,7 +55,7 @@ export const resendTeamMemberInvitation = async ({
}); });
if (!team) { if (!team) {
throw new AppError('TeamNotFound', 'User is not a valid member of the team.'); throw new AppError('TeamNotFound', { message: 'User is not a valid member of the team.' });
} }
const teamMemberInvite = await tx.teamMemberInvite.findUniqueOrThrow({ const teamMemberInvite = await tx.teamMemberInvite.findUniqueOrThrow({
@@ -66,7 +66,7 @@ export const resendTeamMemberInvitation = async ({
}); });
if (!teamMemberInvite) { if (!teamMemberInvite) {
throw new AppError('InviteNotFound', 'No invite exists for this user.'); throw new AppError('InviteNotFound', { message: 'No invite exists for this user.' });
} }
await sendTeamMemberInviteEmail({ await sendTeamMemberInviteEmail({

View File

@@ -48,11 +48,11 @@ export const updateTeamMember = async ({
const teamMemberToUpdate = team.members.find((member) => member.id === teamMemberId); const teamMemberToUpdate = team.members.find((member) => member.id === teamMemberId);
if (!teamMemberToUpdate || !currentTeamMember) { if (!teamMemberToUpdate || !currentTeamMember) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Team member does not exist'); throw new AppError(AppErrorCode.NOT_FOUND, { message: 'Team member does not exist' });
} }
if (teamMemberToUpdate.userId === team.ownerUserId) { if (teamMemberToUpdate.userId === team.ownerUserId) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Cannot update the owner'); throw new AppError(AppErrorCode.UNAUTHORIZED, { message: 'Cannot update the owner' });
} }
const isMemberToUpdateHigherRole = !isTeamRoleWithinUserHierarchy( const isMemberToUpdateHigherRole = !isTeamRoleWithinUserHierarchy(
@@ -61,7 +61,9 @@ export const updateTeamMember = async ({
); );
if (isMemberToUpdateHigherRole) { if (isMemberToUpdateHigherRole) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'Cannot update a member with a higher role'); throw new AppError(AppErrorCode.UNAUTHORIZED, {
message: 'Cannot update a member with a higher role',
});
} }
const isNewMemberRoleHigherThanCurrentRole = !isTeamRoleWithinUserHierarchy( const isNewMemberRoleHigherThanCurrentRole = !isTeamRoleWithinUserHierarchy(
@@ -70,10 +72,9 @@ export const updateTeamMember = async ({
); );
if (isNewMemberRoleHigherThanCurrentRole) { if (isNewMemberRoleHigherThanCurrentRole) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'Cannot give a member a role higher than the user initating the update',
'Cannot give a member a role higher than the user initating the update', });
);
} }
return await tx.teamMember.update({ return await tx.teamMember.update({

View File

@@ -24,7 +24,9 @@ export const updateTeam = async ({ userId, teamId, data }: UpdateTeamOptions) =>
}); });
if (foundPendingTeamWithUrl) { if (foundPendingTeamWithUrl) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Team URL already exists.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'Team URL already exists.',
});
} }
const team = await tx.team.update({ const team = await tx.team.update({
@@ -57,7 +59,9 @@ export const updateTeam = async ({ userId, teamId, data }: UpdateTeamOptions) =>
const target = z.array(z.string()).safeParse(err.meta?.target); const target = z.array(z.string()).safeParse(err.meta?.target);
if (err.code === 'P2002' && target.success && target.data.includes('url')) { if (err.code === 'P2002' && target.success && target.data.includes('url')) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Team URL already exists.'); throw new AppError(AppErrorCode.ALREADY_EXISTS, {
message: 'Team URL already exists.',
});
} }
throw err; throw err;

View File

@@ -101,7 +101,7 @@ export const createDocumentFromDirectTemplate = async ({
}); });
if (!template?.directLink?.enabled) { if (!template?.directLink?.enabled) {
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Invalid or missing template'); throw new AppError(AppErrorCode.INVALID_REQUEST, { message: 'Invalid or missing template' });
} }
const { Recipient: recipients, directLink, User: templateOwner } = template; const { Recipient: recipients, directLink, User: templateOwner } = template;
@@ -111,15 +111,19 @@ export const createDocumentFromDirectTemplate = async ({
); );
if (!directTemplateRecipient || directTemplateRecipient.role === RecipientRole.CC) { if (!directTemplateRecipient || directTemplateRecipient.role === RecipientRole.CC) {
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Invalid or missing direct recipient'); throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: 'Invalid or missing direct recipient',
});
} }
if (template.updatedAt.getTime() !== templateUpdatedAt.getTime()) { if (template.updatedAt.getTime() !== templateUpdatedAt.getTime()) {
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Template no longer matches'); throw new AppError(AppErrorCode.INVALID_REQUEST, { message: 'Template no longer matches' });
} }
if (user && user.email !== directRecipientEmail) { if (user && user.email !== directRecipientEmail) {
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Email must match if you are logged in'); throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: 'Email must match if you are logged in',
});
} }
const { derivedRecipientAccessAuth, documentAuthOption: templateAuthOptions } = const { derivedRecipientAccessAuth, documentAuthOption: templateAuthOptions } =
@@ -136,7 +140,7 @@ export const createDocumentFromDirectTemplate = async ({
.exhaustive(); .exhaustive();
if (!isAccessAuthValid) { if (!isAccessAuthValid) {
throw new AppError(AppErrorCode.UNAUTHORIZED, 'You must be logged in'); throw new AppError(AppErrorCode.UNAUTHORIZED, { message: 'You must be logged in' });
} }
const directTemplateRecipientAuthOptions = ZRecipientAuthOptionsSchema.parse( const directTemplateRecipientAuthOptions = ZRecipientAuthOptionsSchema.parse(
@@ -163,7 +167,9 @@ export const createDocumentFromDirectTemplate = async ({
); );
if (!signedFieldValue) { if (!signedFieldValue) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Invalid, missing or changed fields'); throw new AppError(AppErrorCode.INVALID_BODY, {
message: 'Invalid, missing or changed fields',
});
} }
if (templateField.type === FieldType.NAME && directRecipientName === undefined) { if (templateField.type === FieldType.NAME && directRecipientName === undefined) {

View File

@@ -16,6 +16,7 @@ import type { SupportedLanguageCodes } from '../../constants/i18n';
import { AppError, AppErrorCode } from '../../errors/app-error'; import { AppError, AppErrorCode } from '../../errors/app-error';
import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs'; import { DOCUMENT_AUDIT_LOG_TYPE } from '../../types/document-audit-logs';
import { ZRecipientAuthOptionsSchema } from '../../types/document-auth'; import { ZRecipientAuthOptionsSchema } from '../../types/document-auth';
import type { TDocumentEmailSettings } from '../../types/document-email';
import { ZFieldMetaSchema } from '../../types/field-meta'; import { ZFieldMetaSchema } from '../../types/field-meta';
import type { RequestMetadata } from '../../universal/extract-request-metadata'; import type { RequestMetadata } from '../../universal/extract-request-metadata';
import { createDocumentAuditLogData } from '../../utils/document-audit-logs'; import { createDocumentAuditLogData } from '../../utils/document-audit-logs';
@@ -65,6 +66,7 @@ export type CreateDocumentFromTemplateOptions = {
language?: SupportedLanguageCodes; language?: SupportedLanguageCodes;
distributionMethod?: DocumentDistributionMethod; distributionMethod?: DocumentDistributionMethod;
typedSignatureEnabled?: boolean; typedSignatureEnabled?: boolean;
emailSettings?: TDocumentEmailSettings;
}; };
requestMetadata?: RequestMetadata; requestMetadata?: RequestMetadata;
}; };
@@ -120,7 +122,9 @@ export const createDocumentFromTemplate = async ({
}); });
if (!template) { if (!template) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Template not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Template not found',
});
} }
// Check that all the passed in recipient IDs can be associated with a template recipient. // Check that all the passed in recipient IDs can be associated with a template recipient.
@@ -130,10 +134,9 @@ export const createDocumentFromTemplate = async ({
); );
if (!foundRecipient) { if (!foundRecipient) {
throw new AppError( throw new AppError(AppErrorCode.INVALID_BODY, {
AppErrorCode.INVALID_BODY, message: `Recipient with ID ${recipient.id} not found in the template.`,
`Recipient with ID ${recipient.id} not found in the template.`, });
);
} }
}); });
@@ -188,7 +191,9 @@ export const createDocumentFromTemplate = async ({
redirectUrl: override?.redirectUrl || template.templateMeta?.redirectUrl, redirectUrl: override?.redirectUrl || template.templateMeta?.redirectUrl,
distributionMethod: distributionMethod:
override?.distributionMethod || template.templateMeta?.distributionMethod, override?.distributionMethod || template.templateMeta?.distributionMethod,
emailSettings: template.templateMeta?.emailSettings || undefined, // last `undefined` is due to JsonValue's
emailSettings:
override?.emailSettings || template.templateMeta?.emailSettings || undefined,
signingOrder: signingOrder:
override?.signingOrder || override?.signingOrder ||
template.templateMeta?.signingOrder || template.templateMeta?.signingOrder ||

View File

@@ -47,18 +47,18 @@ export const createTemplateDirectLink = async ({
}); });
if (!template) { if (!template) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Template not found'); throw new AppError(AppErrorCode.NOT_FOUND, { message: 'Template not found' });
} }
if (template.directLink) { if (template.directLink) {
throw new AppError(AppErrorCode.ALREADY_EXISTS, 'Direct template already exists'); throw new AppError(AppErrorCode.ALREADY_EXISTS, { message: 'Direct template already exists' });
} }
if ( if (
directRecipientId && directRecipientId &&
!template.Recipient.find((recipient) => recipient.id === directRecipientId) !template.Recipient.find((recipient) => recipient.id === directRecipientId)
) { ) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Recipient not found'); throw new AppError(AppErrorCode.NOT_FOUND, { message: 'Recipient not found' });
} }
if ( if (
@@ -67,7 +67,9 @@ export const createTemplateDirectLink = async ({
(recipient) => recipient.email.toLowerCase() === DIRECT_TEMPLATE_RECIPIENT_EMAIL, (recipient) => recipient.email.toLowerCase() === DIRECT_TEMPLATE_RECIPIENT_EMAIL,
) )
) { ) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Cannot generate placeholder direct recipient'); throw new AppError(AppErrorCode.INVALID_BODY, {
message: 'Cannot generate placeholder direct recipient',
});
} }
return await prisma.$transaction(async (tx) => { return await prisma.$transaction(async (tx) => {

View File

@@ -39,7 +39,9 @@ export const deleteTemplateDirectLink = async ({
}); });
if (!template) { if (!template) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Template not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Template not found',
});
} }
const { directLink } = template; const { directLink } = template;

View File

@@ -53,7 +53,9 @@ export const getTemplateById = async ({ id, userId, teamId }: GetTemplateByIdOpt
}); });
if (!template) { if (!template) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Template not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Template not found',
});
} }
return template; return template;

View File

@@ -1,6 +1,8 @@
import { prisma } from '@documenso/prisma'; import { prisma } from '@documenso/prisma';
import type { TemplateWithDetails } from '@documenso/prisma/types/template'; import type { TemplateWithDetails } from '@documenso/prisma/types/template';
import { AppError, AppErrorCode } from '../../errors/app-error';
export type GetTemplateWithDetailsByIdOptions = { export type GetTemplateWithDetailsByIdOptions = {
id: number; id: number;
userId: number; userId: number;
@@ -10,7 +12,7 @@ export const getTemplateWithDetailsById = async ({
id, id,
userId, userId,
}: GetTemplateWithDetailsByIdOptions): Promise<TemplateWithDetails> => { }: GetTemplateWithDetailsByIdOptions): Promise<TemplateWithDetails> => {
return await prisma.template.findFirstOrThrow({ const template = await prisma.template.findFirst({
where: { where: {
id, id,
OR: [ OR: [
@@ -36,4 +38,12 @@ export const getTemplateWithDetailsById = async ({
Field: true, Field: true,
}, },
}); });
if (!template) {
throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Template not found',
});
}
return template;
}; };

View File

@@ -40,13 +40,17 @@ export const toggleTemplateDirectLink = async ({
}); });
if (!template) { if (!template) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Template not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Template not found',
});
} }
const { directLink } = template; const { directLink } = template;
if (!directLink) { if (!directLink) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Direct template link not found'); throw new AppError(AppErrorCode.NOT_FOUND, {
message: 'Direct template link not found',
});
} }
return await prisma.templateDirectLink.update({ return await prisma.templateDirectLink.update({

View File

@@ -34,7 +34,9 @@ export const updateTemplateSettings = async ({
data, data,
}: UpdateTemplateSettingsOptions) => { }: UpdateTemplateSettingsOptions) => {
if (Object.values(data).length === 0 && Object.keys(meta ?? {}).length === 0) { if (Object.values(data).length === 0 && Object.keys(meta ?? {}).length === 0) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Missing data to update'); throw new AppError(AppErrorCode.INVALID_BODY, {
message: 'Missing data to update',
});
} }
const template = await prisma.template.findFirstOrThrow({ const template = await prisma.template.findFirstOrThrow({
@@ -82,10 +84,9 @@ export const updateTemplateSettings = async ({
}); });
if (!isDocumentEnterprise) { if (!isDocumentEnterprise) {
throw new AppError( throw new AppError(AppErrorCode.UNAUTHORIZED, {
AppErrorCode.UNAUTHORIZED, message: 'You do not have permission to set the action auth',
'You do not have permission to set the action auth', });
);
} }
} }

View File

@@ -38,11 +38,10 @@ export const createUser = async ({ name, email, password, signature, url }: Crea
}); });
if (urlExists) { if (urlExists) {
throw new AppError( throw new AppError(AppErrorCode.PROFILE_URL_TAKEN, {
AppErrorCode.PROFILE_URL_TAKEN, message: 'Profile username is taken',
'Profile username is taken', userMessage: 'The profile username is already taken',
'The profile username is already taken', });
);
} }
} }

View File

@@ -26,7 +26,7 @@ export const getUserPublicProfile = async ({
}); });
if (!user) { if (!user) {
throw new AppError(AppErrorCode.NOT_FOUND, 'User not found'); throw new AppError(AppErrorCode.NOT_FOUND, { message: 'User not found' });
} }
// Create and return the public profile. // Create and return the public profile.
@@ -39,7 +39,7 @@ export const getUserPublicProfile = async ({
}); });
if (!profile) { if (!profile) {
throw new AppError(AppErrorCode.NOT_FOUND, 'Failed to create public profile'); throw new AppError(AppErrorCode.NOT_FOUND, { message: 'Failed to create public profile' });
} }
return { return {

View File

@@ -13,7 +13,7 @@ export type UpdatePublicProfileOptions = {
export const updatePublicProfile = async ({ userId, data }: UpdatePublicProfileOptions) => { export const updatePublicProfile = async ({ userId, data }: UpdatePublicProfileOptions) => {
if (Object.values(data).length === 0) { if (Object.values(data).length === 0) {
throw new AppError(AppErrorCode.INVALID_BODY, 'Missing data to update'); throw new AppError(AppErrorCode.INVALID_BODY, { message: 'Missing data to update' });
} }
const { url, bio, enabled } = data; const { url, bio, enabled } = data;
@@ -25,13 +25,15 @@ export const updatePublicProfile = async ({ userId, data }: UpdatePublicProfileO
}); });
if (!user) { if (!user) {
throw new AppError(AppErrorCode.NOT_FOUND, 'User not found'); throw new AppError(AppErrorCode.NOT_FOUND, { message: 'User not found' });
} }
const finalUrl = url ?? user.url; const finalUrl = url ?? user.url;
if (!finalUrl && enabled) { if (!finalUrl && enabled) {
throw new AppError(AppErrorCode.INVALID_REQUEST, 'Cannot enable a profile without a URL'); throw new AppError(AppErrorCode.INVALID_REQUEST, {
message: 'Cannot enable a profile without a URL',
});
} }
if (url) { if (url) {
@@ -57,7 +59,9 @@ export const updatePublicProfile = async ({ userId, data }: UpdatePublicProfileO
}); });
if (isUrlTakenByAnotherUser || isUrlTakenByAnotherTeam) { if (isUrlTakenByAnotherUser || isUrlTakenByAnotherTeam) {
throw new AppError(AppErrorCode.PROFILE_URL_TAKEN, 'The profile username is already taken'); throw new AppError(AppErrorCode.PROFILE_URL_TAKEN, {
message: 'The profile username is already taken',
});
} }
} }

View File

@@ -341,7 +341,7 @@ msgstr "Ein Empfänger wurde entfernt"
msgid "A recipient was updated" msgid "A recipient was updated"
msgstr "Ein Empfänger wurde aktualisiert" msgstr "Ein Empfänger wurde aktualisiert"
#: packages/lib/server-only/team/create-team-email-verification.ts:156 #: packages/lib/server-only/team/create-team-email-verification.ts:159
msgid "A request to use your email has been initiated by {0} on Documenso" msgid "A request to use your email has been initiated by {0} on Documenso"
msgstr "Eine Anfrage zur Verwendung Ihrer E-Mail wurde von {0} auf Documenso initiiert" msgstr "Eine Anfrage zur Verwendung Ihrer E-Mail wurde von {0} auf Documenso initiiert"
@@ -711,7 +711,7 @@ msgid "Document created"
msgstr "Dokument erstellt" msgstr "Dokument erstellt"
#: packages/email/templates/document-created-from-direct-template.tsx:32 #: packages/email/templates/document-created-from-direct-template.tsx:32
#: packages/lib/server-only/template/create-document-from-direct-template.ts:567 #: packages/lib/server-only/template/create-document-from-direct-template.ts:573
msgid "Document created from direct template" msgid "Document created from direct template"
msgstr "Dokument erstellt aus direkter Vorlage" msgstr "Dokument erstellt aus direkter Vorlage"
@@ -1774,7 +1774,7 @@ msgstr "Du wurdest eingeladen, {0} auf Documenso beizutreten"
msgid "You have been invited to join the following team" msgid "You have been invited to join the following team"
msgstr "Du wurdest eingeladen, dem folgenden Team beizutreten" msgstr "Du wurdest eingeladen, dem folgenden Team beizutreten"
#: packages/lib/server-only/recipient/set-recipients-for-document.ts:329 #: packages/lib/server-only/recipient/set-recipients-for-document.ts:327
msgid "You have been removed from a document" msgid "You have been removed from a document"
msgstr "Du wurdest von einem Dokument entfernt" msgstr "Du wurdest von einem Dokument entfernt"

View File

@@ -18,7 +18,7 @@ msgstr ""
"X-Crowdin-File: web.po\n" "X-Crowdin-File: web.po\n"
"X-Crowdin-File-ID: 8\n" "X-Crowdin-File-ID: 8\n"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:231 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226
msgid "\"{0}\" has invited you to sign \"example document\"." msgid "\"{0}\" has invited you to sign \"example document\"."
msgstr "\"{0}\" hat Sie eingeladen, \"Beispieldokument\" zu unterschreiben." msgstr "\"{0}\" hat Sie eingeladen, \"Beispieldokument\" zu unterschreiben."
@@ -42,7 +42,7 @@ msgstr "\"{documentTitle}\" wurde erfolgreich gelöscht"
#~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n" #~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n"
#~ "document\"." #~ "document\"."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221
msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"." msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"."
msgstr "\"{placeholderEmail}\" im Namen von \"{0}\" hat Sie eingeladen, \"Beispieldokument\" zu unterzeichnen." msgstr "\"{placeholderEmail}\" im Namen von \"{0}\" hat Sie eingeladen, \"Beispieldokument\" zu unterzeichnen."
@@ -50,15 +50,15 @@ msgstr "\"{placeholderEmail}\" im Namen von \"{0}\" hat Sie eingeladen, \"Beispi
#~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"." #~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"."
#~ msgstr "\"{teamUrl}\" hat Sie eingeladen, \"Beispieldokument\" zu unterschreiben." #~ msgstr "\"{teamUrl}\" hat Sie eingeladen, \"Beispieldokument\" zu unterschreiben."
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:83
msgid "({0}) has invited you to approve this document" msgid "({0}) has invited you to approve this document"
msgstr "({0}) hat dich eingeladen, dieses Dokument zu genehmigen" msgstr "({0}) hat dich eingeladen, dieses Dokument zu genehmigen"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80
msgid "({0}) has invited you to sign this document" msgid "({0}) has invited you to sign this document"
msgstr "({0}) hat dich eingeladen, dieses Dokument zu unterzeichnen" msgstr "({0}) hat dich eingeladen, dieses Dokument zu unterzeichnen"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:74 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77
msgid "({0}) has invited you to view this document" msgid "({0}) has invited you to view this document"
msgstr "({0}) hat dich eingeladen, dieses Dokument zu betrachten" msgstr "({0}) hat dich eingeladen, dieses Dokument zu betrachten"
@@ -71,7 +71,7 @@ msgstr "{0, plural, one {(1 Zeichen über dem Limit)} other {(# Zeichen über de
msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}"
msgstr "{0, plural, one {# Zeichen über dem Limit} other {# Zeichen über dem Limit}}" msgstr "{0, plural, one {# Zeichen über dem Limit} other {# Zeichen über dem Limit}}"
#: apps/web/src/app/(recipient)/d/[token]/page.tsx:82 #: apps/web/src/app/(recipient)/d/[token]/page.tsx:84
msgid "{0, plural, one {# recipient} other {# recipients}}" msgid "{0, plural, one {# recipient} other {# recipients}}"
msgstr "{0, plural, one {# Empfänger} other {# Empfänger}}" msgstr "{0, plural, one {# Empfänger} other {# Empfänger}}"
@@ -88,11 +88,11 @@ msgstr "{0, plural, one {<0>Du hast <1>1</1> ausstehende Team-Einladung</0>} oth
msgid "{0, plural, one {1 matching field} other {# matching fields}}" msgid "{0, plural, one {1 matching field} other {# matching fields}}"
msgstr "{0, plural, one {1 passendes Feld} other {# passende Felder}}" msgstr "{0, plural, one {1 passendes Feld} other {# passende Felder}}"
#: 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:132
msgid "{0, plural, one {1 Recipient} other {# Recipients}}" msgid "{0, plural, one {1 Recipient} other {# Recipients}}"
msgstr "{0, plural, one {1 Empfänger} other {# Empfänger}}" msgstr "{0, plural, one {1 Empfänger} other {# Empfänger}}"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:235 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:238
msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}" msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}"
msgstr "{0, plural, one {Warte auf 1 Empfänger} other {Warte auf # Empfänger}}" msgstr "{0, plural, one {Warte auf 1 Empfänger} other {Warte auf # Empfänger}}"
@@ -116,7 +116,7 @@ msgstr "{0} direkte Signaturvorlagen"
msgid "{0} of {1} documents remaining this month." msgid "{0} of {1} documents remaining this month."
msgstr "{0} von {1} Dokumenten verbleibend in diesem Monat." msgstr "{0} von {1} Dokumenten verbleibend in diesem Monat."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:170 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:173
msgid "{0} Recipient(s)" msgid "{0} Recipient(s)"
msgstr "{0} Empfänger(in)" msgstr "{0} Empfänger(in)"
@@ -157,6 +157,18 @@ msgstr "<0>\"{0}\"</0> steht nicht mehr zur Unterschrift zur Verfügung"
msgid "<0>Sender:</0> All" msgid "<0>Sender:</0> All"
msgstr "<0>Absender:</0> Alle" msgstr "<0>Absender:</0> Alle"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:104
msgid "<0>You are about to complete approving <1>\"{documentTitle}\"</1>.</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:90
msgid "<0>You are about to complete signing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:76
msgid "<0>You are about to complete viewing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/components/(dashboard)/settings/token/contants.ts:5 #: apps/web/src/components/(dashboard)/settings/token/contants.ts:5
msgid "1 month" msgid "1 month"
msgstr "1 Monat" msgstr "1 Monat"
@@ -665,7 +677,7 @@ msgstr "App-Version"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89
#: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120 #: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120
#: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146 #: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:125 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:142
msgid "Approve" msgid "Approve"
msgstr "Genehmigen" msgstr "Genehmigen"
@@ -835,7 +847,7 @@ msgstr "Durch die Verwendung der elektronischen Unterschriftsfunktion stimmen Si
#: 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:328 #: 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:130
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:335 #: 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
@@ -947,22 +959,22 @@ msgstr "Klicken Sie, um das Feld einzufügen"
msgid "Close" msgid "Close"
msgstr "Schließen" msgstr "Schließen"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446 #: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325 #: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325
#: apps/web/src/components/forms/v2/signup.tsx:534 #: apps/web/src/components/forms/v2/signup.tsx:534
msgid "Complete" msgid "Complete"
msgstr "Vollständig" msgstr "Vollständig"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:70 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69
msgid "Complete Approval" msgid "Complete Approval"
msgstr "Genehmigung abschließen" msgstr "Genehmigung abschließen"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68
msgid "Complete Signing" msgid "Complete Signing"
msgstr "Unterzeichnung abschließen" msgstr "Unterzeichnung abschließen"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:67
msgid "Complete Viewing" msgid "Complete Viewing"
msgstr "Betrachten abschließen" msgstr "Betrachten abschließen"
@@ -1048,23 +1060,23 @@ msgstr "Fortfahren"
msgid "Continue to login" msgid "Continue to login"
msgstr "Weiter zum Login" msgstr "Weiter zum Login"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:188 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:185
msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients." msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients."
msgstr "Steuert die Standardsprache eines hochgeladenen Dokuments. Diese wird als Sprache in der E-Mail-Kommunikation mit den Empfängern verwendet." msgstr "Steuert die Standardsprache eines hochgeladenen Dokuments. Diese wird als Sprache in der E-Mail-Kommunikation mit den Empfängern verwendet."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:154 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:153
msgid "Controls the default visibility of an uploaded document." msgid "Controls the default visibility of an uploaded document."
msgstr "Steuert die Standard-sichtbarkeit eines hochgeladenen Dokuments." msgstr "Steuert die Standard-sichtbarkeit eines hochgeladenen Dokuments."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:237 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:232
msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead." msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead."
msgstr "Steuert das Format der Nachricht, die gesendet wird, wenn ein Empfänger eingeladen wird, ein Dokument zu unterschreiben. Wenn eine benutzerdefinierte Nachricht beim Konfigurieren des Dokuments bereitgestellt wurde, wird diese stattdessen verwendet." msgstr "Steuert das Format der Nachricht, die gesendet wird, wenn ein Empfänger eingeladen wird, ein Dokument zu unterschreiben. Wenn eine benutzerdefinierte Nachricht beim Konfigurieren des Dokuments bereitgestellt wurde, wird diese stattdessen verwendet."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:270 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:263
msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally." msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally."
msgstr "" msgstr ""
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:301 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:293
msgid "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." msgid "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."
msgstr "" msgstr ""
@@ -1185,7 +1197,7 @@ msgstr "Webhook erstellen"
msgid "Create Webhook" msgid "Create Webhook"
msgstr "Webhook erstellen" msgstr "Webhook erstellen"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:215 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:213
msgid "Create your account and start using state-of-the-art document signing." msgid "Create your account and start using state-of-the-art document signing."
msgstr "Erstellen Sie Ihr Konto und beginnen Sie mit dem modernen Dokumentensignieren." msgstr "Erstellen Sie Ihr Konto und beginnen Sie mit dem modernen Dokumentensignieren."
@@ -1258,11 +1270,11 @@ msgstr "Ablehnen"
msgid "Declined team invitation" msgid "Declined team invitation"
msgstr "Team-Einladung abgelehnt" msgstr "Team-Einladung abgelehnt"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:168 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:165
msgid "Default Document Language" msgid "Default Document Language"
msgstr "Standardsprache des Dokuments" msgstr "Standardsprache des Dokuments"
#: 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:129
msgid "Default Document Visibility" msgid "Default Document Visibility"
msgstr "Standard Sichtbarkeit des Dokuments" msgstr "Standard Sichtbarkeit des Dokuments"
@@ -1461,7 +1473,7 @@ msgstr "Dokument"
msgid "Document All" msgid "Document All"
msgstr "Dokument Alle" msgstr "Dokument Alle"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:134 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132
msgid "Document Approved" msgid "Document Approved"
msgstr "Dokument genehmigt" msgstr "Dokument genehmigt"
@@ -1490,7 +1502,7 @@ msgid "Document created using a <0>direct link</0>"
msgstr "Dokument erstellt mit einem <0>direkten Link</0>" msgstr "Dokument erstellt mit einem <0>direkten Link</0>"
#: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51 #: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:178 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:181
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61
msgid "Document deleted" msgid "Document deleted"
msgstr "Dokument gelöscht" msgstr "Dokument gelöscht"
@@ -1503,7 +1515,7 @@ msgstr "Dokument-Entwurf"
msgid "Document Duplicated" msgid "Document Duplicated"
msgstr "Dokument dupliziert" msgstr "Dokument dupliziert"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:189 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:192
#: apps/web/src/components/document/document-history-sheet.tsx:104 #: apps/web/src/components/document/document-history-sheet.tsx:104
msgid "Document history" msgid "Document history"
msgstr "Dokumentverlauf" msgstr "Dokumentverlauf"
@@ -1529,7 +1541,7 @@ msgstr "Dokumentmetrik"
msgid "Document moved" msgid "Document moved"
msgstr "Dokument verschoben" msgstr "Dokument verschoben"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:158 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:156
msgid "Document no longer available to sign" msgid "Document no longer available to sign"
msgstr "Dokument steht nicht mehr zur Unterschrift zur Verfügung" msgstr "Dokument steht nicht mehr zur Unterschrift zur Verfügung"
@@ -1561,7 +1573,7 @@ msgstr "Dokument gesendet"
#~ msgid "Document Settings" #~ msgid "Document Settings"
#~ msgstr "Document Settings" #~ msgstr "Document Settings"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:130
msgid "Document Signed" msgid "Document Signed"
msgstr "Dokument signiert" msgstr "Dokument signiert"
@@ -1585,7 +1597,7 @@ msgstr "Dokumenten-Upload deaktiviert aufgrund unbezahlter Rechnungen"
msgid "Document uploaded" msgid "Document uploaded"
msgstr "Dokument hochgeladen" msgstr "Dokument hochgeladen"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:133 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:131
msgid "Document Viewed" msgid "Document Viewed"
msgstr "Dokument angesehen" msgstr "Dokument angesehen"
@@ -1609,7 +1621,7 @@ msgstr "Dokument wird dauerhaft gelöscht"
msgid "Documents" msgid "Documents"
msgstr "Dokumente" msgstr "Dokumente"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:194 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:197
msgid "Documents created from template" msgid "Documents created from template"
msgstr "Dokumente erstellt aus Vorlage" msgstr "Dokumente erstellt aus Vorlage"
@@ -1690,7 +1702,7 @@ msgstr "Duplizieren"
msgid "Edit" msgid "Edit"
msgstr "Bearbeiten" msgstr "Bearbeiten"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:114 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:117
msgid "Edit Template" msgid "Edit Template"
msgstr "Vorlage bearbeiten" msgstr "Vorlage bearbeiten"
@@ -1778,7 +1790,7 @@ msgstr "Direktlinksignierung aktivieren"
msgid "Enable Direct Link Signing" msgid "Enable Direct Link Signing"
msgstr "Direktlinksignierung aktivieren" msgstr "Direktlinksignierung aktivieren"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:255 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:248
msgid "Enable Typed Signature" msgid "Enable Typed Signature"
msgstr "" msgstr ""
@@ -1866,15 +1878,15 @@ msgstr "Fehler"
#~ msgid "Error updating global team settings" #~ msgid "Error updating global team settings"
#~ msgstr "Error updating global team settings" #~ msgstr "Error updating global team settings"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:141 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:140
msgid "Everyone can access and view the document" msgid "Everyone can access and view the document"
msgstr "Jeder kann auf das Dokument zugreifen und es anzeigen" msgstr "Jeder kann auf das Dokument zugreifen und es anzeigen"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:142 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:140
msgid "Everyone has signed" msgid "Everyone has signed"
msgstr "Alle haben unterschrieben" msgstr "Alle haben unterschrieben"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:166 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:164
msgid "Everyone has signed! You will receive an Email copy of the signed document." msgid "Everyone has signed! You will receive an Email copy of the signed document."
msgstr "Alle haben unterschrieben! Sie werden eine E-Mail-Kopie des unterzeichneten Dokuments erhalten." msgstr "Alle haben unterschrieben! Sie werden eine E-Mail-Kopie des unterzeichneten Dokuments erhalten."
@@ -1963,7 +1975,7 @@ msgstr "Zurück"
msgid "Go back home" msgid "Go back home"
msgstr "Zurück nach Hause" msgstr "Zurück nach Hause"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:226 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:224
#: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57 #: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57
msgid "Go Back Home" msgid "Go Back Home"
msgstr "Zurück nach Hause" msgstr "Zurück nach Hause"
@@ -2047,7 +2059,7 @@ msgstr "Posteingang Dokumente"
#~ msgid "Include Sender Details" #~ msgid "Include Sender Details"
#~ msgstr "Include Sender Details" #~ msgstr "Include Sender Details"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:286 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:278
msgid "Include the Signing Certificate in the Document" msgid "Include the Signing Certificate in the Document"
msgstr "" msgstr ""
@@ -2267,7 +2279,7 @@ msgstr "Verwalten Sie das Profil von {0}"
msgid "Manage all teams you are currently associated with." msgid "Manage all teams you are currently associated with."
msgstr "Verwalten Sie alle Teams, mit denen Sie derzeit verbunden sind." msgstr "Verwalten Sie alle Teams, mit denen Sie derzeit verbunden sind."
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:158 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:161
msgid "Manage and view template" msgid "Manage and view template"
msgstr "Vorlage verwalten und anzeigen" msgstr "Vorlage verwalten und anzeigen"
@@ -2331,7 +2343,7 @@ msgstr "Verwalten Sie Ihre Passkeys."
msgid "Manage your site settings here" msgid "Manage your site settings here"
msgstr "Verwalten Sie hier Ihre Seiteneinstellungen" msgstr "Verwalten Sie hier Ihre Seiteneinstellungen"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:123 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:140
msgid "Mark as Viewed" msgid "Mark as Viewed"
msgstr "Als angesehen markieren" msgstr "Als angesehen markieren"
@@ -2413,7 +2425,7 @@ msgstr "Meine Vorlagen"
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:211 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:209
msgid "Need to sign documents?" msgid "Need to sign documents?"
msgstr "Müssen Dokumente signieren?" msgstr "Müssen Dokumente signieren?"
@@ -2440,7 +2452,7 @@ msgstr "Neue Vorlage"
msgid "Next" msgid "Next"
msgstr "Nächster" msgstr "Nächster"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
msgid "Next field" msgid "Next field"
msgstr "Nächstes Feld" msgstr "Nächstes Feld"
@@ -2542,11 +2554,11 @@ msgstr "Sobald dies bestätigt ist, wird Folgendes geschehen:"
msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below." msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below."
msgstr "Sobald Sie den QR-Code gescannt oder den Code manuell eingegeben haben, geben Sie den von Ihrer Authentifizierungs-App bereitgestellten Code unten ein." msgstr "Sobald Sie den QR-Code gescannt oder den Code manuell eingegeben haben, geben Sie den von Ihrer Authentifizierungs-App bereitgestellten Code unten ein."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:147 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:146
msgid "Only admins can access and view the document" msgid "Only admins can access and view the document"
msgstr "Nur Administratoren können auf das Dokument zugreifen und es anzeigen" msgstr "Nur Administratoren können auf das Dokument zugreifen und es anzeigen"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:144 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:143
msgid "Only managers and above can access and view the document" msgid "Only managers and above can access and view the document"
msgstr "Nur Manager und darüber können auf das Dokument zugreifen und es anzeigen" msgstr "Nur Manager und darüber können auf das Dokument zugreifen und es anzeigen"
@@ -2792,7 +2804,7 @@ msgstr "Bitte geben Sie <0>{0}</0> ein, um zu bestätigen."
msgid "Preferences" msgid "Preferences"
msgstr "Einstellungen" msgstr "Einstellungen"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:216
msgid "Preview" msgid "Preview"
msgstr "Vorschau" msgstr "Vorschau"
@@ -3078,7 +3090,7 @@ msgstr "Rollen"
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:344 #: 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:313 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:305
msgid "Save" msgid "Save"
msgstr "Speichern" msgstr "Speichern"
@@ -3153,7 +3165,7 @@ msgstr "Bestätigungs-E-Mail senden"
msgid "Send document" msgid "Send document"
msgstr "Dokument senden" msgstr "Dokument senden"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:205 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:200
msgid "Send on Behalf of Team" msgid "Send on Behalf of Team"
msgstr "Im Namen des Teams senden" msgstr "Im Namen des Teams senden"
@@ -3226,7 +3238,7 @@ msgstr "Vorlagen in Ihrem Team-Öffentliches Profil anzeigen, damit Ihre Zielgru
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:229 #: 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:141
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313
#: apps/web/src/components/ui/user-profile-skeleton.tsx:75 #: apps/web/src/components/ui/user-profile-skeleton.tsx:75
#: apps/web/src/components/ui/user-profile-timur.tsx:81 #: apps/web/src/components/ui/user-profile-timur.tsx:81
@@ -3317,7 +3329,7 @@ msgstr "Signatur-ID"
msgid "Signatures Collected" msgid "Signatures Collected"
msgstr "Gesammelte Unterschriften" msgstr "Gesammelte Unterschriften"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:200 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:198
msgid "Signatures will appear once the document has been completed" msgid "Signatures will appear once the document has been completed"
msgstr "Unterschriften erscheinen, sobald das Dokument abgeschlossen ist" msgstr "Unterschriften erscheinen, sobald das Dokument abgeschlossen ist"
@@ -3649,7 +3661,7 @@ msgstr "Teams beschränkt"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:145 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:148
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408 #: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:271 #: apps/web/src/components/templates/manage-public-template-dialog.tsx:271
msgid "Template" msgid "Template"
@@ -3883,7 +3895,7 @@ msgstr "Dieses Dokument konnte derzeit nicht dupliziert werden. Bitte versuche e
msgid "This document could not be re-sent at this time. Please try again." msgid "This document could not be re-sent at this time. Please try again."
msgstr "Dieses Dokument konnte zu diesem Zeitpunkt nicht erneut gesendet werden. Bitte versuchen Sie es erneut." msgstr "Dieses Dokument konnte zu diesem Zeitpunkt nicht erneut gesendet werden. Bitte versuchen Sie es erneut."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:180 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:178
msgid "This document has been cancelled by the owner and is no longer available for others to sign." msgid "This document has been cancelled by the owner and is no longer available for others to sign."
msgstr "Dieses Dokument wurde vom Eigentümer storniert und steht anderen nicht mehr zur Unterzeichnung zur Verfügung." msgstr "Dieses Dokument wurde vom Eigentümer storniert und steht anderen nicht mehr zur Unterzeichnung zur Verfügung."
@@ -3891,11 +3903,11 @@ msgstr "Dieses Dokument wurde vom Eigentümer storniert und steht anderen nicht
msgid "This document has been cancelled by the owner." msgid "This document has been cancelled by the owner."
msgstr "Dieses Dokument wurde vom Eigentümer storniert." msgstr "Dieses Dokument wurde vom Eigentümer storniert."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:224 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227
msgid "This document has been signed by all recipients" msgid "This document has been signed by all recipients"
msgstr "Dieses Dokument wurde von allen Empfängern unterschrieben" msgstr "Dieses Dokument wurde von allen Empfängern unterschrieben"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:230
msgid "This document is currently a draft and has not been sent" msgid "This document is currently a draft and has not been sent"
msgstr "Dieses Dokument ist momentan ein Entwurf und wurde nicht gesendet" msgstr "Dieses Dokument ist momentan ein Entwurf und wurde nicht gesendet"
@@ -4346,7 +4358,7 @@ msgstr "Die hochgeladene Datei ist zu klein"
msgid "Uploaded file not an allowed file type" msgid "Uploaded file not an allowed file type"
msgstr "Die hochgeladene Datei ist kein zulässiger Dateityp" msgstr "Die hochgeladene Datei ist kein zulässiger Dateityp"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:169 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:172
msgid "Use" msgid "Use"
msgstr "Verwenden" msgstr "Verwenden"
@@ -4488,7 +4500,7 @@ msgstr "Angesehen"
msgid "Waiting" msgid "Waiting"
msgstr "Warten" msgstr "Warten"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:150 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:148
msgid "Waiting for others to sign" msgid "Waiting for others to sign"
msgstr "Warten auf andere, um zu unterschreiben" msgstr "Warten auf andere, um zu unterschreiben"
@@ -4806,16 +4818,16 @@ msgid "You"
msgstr "Sie" msgstr "Sie"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93
msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Sie stehen kurz davor, die Genehmigung für \"{truncatedTitle}\" abzuschließen.<0/> Sind Sie sicher?" #~ msgstr "Sie stehen kurz davor, die Genehmigung für \"{truncatedTitle}\" abzuschließen.<0/> Sind Sie sicher?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85
msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Sie stehen kurz davor, \"{truncatedTitle}\" zu unterzeichnen.<0/> Sind Sie sicher?" #~ msgstr "Sie stehen kurz davor, \"{truncatedTitle}\" zu unterzeichnen.<0/> Sind Sie sicher?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77
msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Sie stehen kurz davor, \"{truncatedTitle}\" anzusehen.<0/> Sind Sie sicher?" #~ msgstr "Sie stehen kurz davor, \"{truncatedTitle}\" anzusehen.<0/> Sind Sie sicher?"
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105
msgid "You are about to delete <0>\"{documentTitle}\"</0>" msgid "You are about to delete <0>\"{documentTitle}\"</0>"
@@ -5015,7 +5027,7 @@ msgstr "Sie werden benachrichtigt und können Ihr Documenso öffentliches Profil
msgid "You will now be required to enter a code from your authenticator app when signing in." msgid "You will now be required to enter a code from your authenticator app when signing in."
msgstr "Sie müssen bei der Anmeldung jetzt einen Code von Ihrer Authenticator-App eingeben." msgstr "Sie müssen bei der Anmeldung jetzt einen Code von Ihrer Authenticator-App eingeben."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:173 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:171
msgid "You will receive an Email copy of the signed document once everyone has signed." msgid "You will receive an Email copy of the signed document once everyone has signed."
msgstr "Sie erhalten eine E-Mail-Kopie des unterzeichneten Dokuments, sobald alle unterschrieben haben." msgstr "Sie erhalten eine E-Mail-Kopie des unterzeichneten Dokuments, sobald alle unterschrieben haben."

View File

@@ -336,7 +336,7 @@ msgstr "A recipient was removed"
msgid "A recipient was updated" msgid "A recipient was updated"
msgstr "A recipient was updated" msgstr "A recipient was updated"
#: packages/lib/server-only/team/create-team-email-verification.ts:156 #: packages/lib/server-only/team/create-team-email-verification.ts:159
msgid "A request to use your email has been initiated by {0} on Documenso" msgid "A request to use your email has been initiated by {0} on Documenso"
msgstr "A request to use your email has been initiated by {0} on Documenso" msgstr "A request to use your email has been initiated by {0} on Documenso"
@@ -706,7 +706,7 @@ msgid "Document created"
msgstr "Document created" msgstr "Document created"
#: packages/email/templates/document-created-from-direct-template.tsx:32 #: packages/email/templates/document-created-from-direct-template.tsx:32
#: packages/lib/server-only/template/create-document-from-direct-template.ts:567 #: packages/lib/server-only/template/create-document-from-direct-template.ts:573
msgid "Document created from direct template" msgid "Document created from direct template"
msgstr "Document created from direct template" msgstr "Document created from direct template"
@@ -1769,7 +1769,7 @@ msgstr "You have been invited to join {0} on Documenso"
msgid "You have been invited to join the following team" msgid "You have been invited to join the following team"
msgstr "You have been invited to join the following team" msgstr "You have been invited to join the following team"
#: packages/lib/server-only/recipient/set-recipients-for-document.ts:329 #: packages/lib/server-only/recipient/set-recipients-for-document.ts:327
msgid "You have been removed from a document" msgid "You have been removed from a document"
msgstr "You have been removed from a document" msgstr "You have been removed from a document"

View File

@@ -13,7 +13,7 @@ msgstr ""
"Language-Team: \n" "Language-Team: \n"
"Plural-Forms: \n" "Plural-Forms: \n"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:231 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226
msgid "\"{0}\" has invited you to sign \"example document\"." msgid "\"{0}\" has invited you to sign \"example document\"."
msgstr "\"{0}\" has invited you to sign \"example document\"." msgstr "\"{0}\" has invited you to sign \"example document\"."
@@ -37,7 +37,7 @@ msgstr "\"{documentTitle}\" has been successfully deleted"
#~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n" #~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n"
#~ "document\"." #~ "document\"."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221
msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"." msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"."
msgstr "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"." msgstr "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"."
@@ -45,15 +45,15 @@ msgstr "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"ex
#~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"." #~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"."
#~ msgstr "\"{teamUrl}\" has invited you to sign \"example document\"." #~ msgstr "\"{teamUrl}\" has invited you to sign \"example document\"."
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:83
msgid "({0}) has invited you to approve this document" msgid "({0}) has invited you to approve this document"
msgstr "({0}) has invited you to approve this document" msgstr "({0}) has invited you to approve this document"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80
msgid "({0}) has invited you to sign this document" msgid "({0}) has invited you to sign this document"
msgstr "({0}) has invited you to sign this document" msgstr "({0}) has invited you to sign this document"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:74 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77
msgid "({0}) has invited you to view this document" msgid "({0}) has invited you to view this document"
msgstr "({0}) has invited you to view this document" msgstr "({0}) has invited you to view this document"
@@ -66,7 +66,7 @@ msgstr "{0, plural, one {(1 character over)} other {(# characters over)}}"
msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}"
msgstr "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgstr "{0, plural, one {# character over the limit} other {# characters over the limit}}"
#: apps/web/src/app/(recipient)/d/[token]/page.tsx:82 #: apps/web/src/app/(recipient)/d/[token]/page.tsx:84
msgid "{0, plural, one {# recipient} other {# recipients}}" msgid "{0, plural, one {# recipient} other {# recipients}}"
msgstr "{0, plural, one {# recipient} other {# recipients}}" msgstr "{0, plural, one {# recipient} other {# recipients}}"
@@ -83,11 +83,11 @@ msgstr "{0, plural, one {<0>You have <1>1</1> pending team invitation</0>} other
msgid "{0, plural, one {1 matching field} other {# matching fields}}" msgid "{0, plural, one {1 matching field} other {# matching fields}}"
msgstr "{0, plural, one {1 matching field} other {# matching fields}}" msgstr "{0, plural, one {1 matching field} other {# matching fields}}"
#: 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:132
msgid "{0, plural, one {1 Recipient} other {# Recipients}}" msgid "{0, plural, one {1 Recipient} other {# Recipients}}"
msgstr "{0, plural, one {1 Recipient} other {# Recipients}}" msgstr "{0, plural, one {1 Recipient} other {# Recipients}}"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:235 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:238
msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}" msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}"
msgstr "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}" msgstr "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}"
@@ -111,7 +111,7 @@ msgstr "{0} direct signing templates"
msgid "{0} of {1} documents remaining this month." msgid "{0} of {1} documents remaining this month."
msgstr "{0} of {1} documents remaining this month." msgstr "{0} of {1} documents remaining this month."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:170 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:173
msgid "{0} Recipient(s)" msgid "{0} Recipient(s)"
msgstr "{0} Recipient(s)" msgstr "{0} Recipient(s)"
@@ -152,6 +152,18 @@ msgstr "<0>\"{0}\"</0>is no longer available to sign"
msgid "<0>Sender:</0> All" msgid "<0>Sender:</0> All"
msgstr "<0>Sender:</0> All" msgstr "<0>Sender:</0> All"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:104
msgid "<0>You are about to complete approving <1>\"{documentTitle}\"</1>.</0><2/> Are you sure?"
msgstr "<0>You are about to complete approving <1>\"{documentTitle}\"</1>.</0><2/> Are you sure?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:90
msgid "<0>You are about to complete signing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr "<0>You are about to complete signing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:76
msgid "<0>You are about to complete viewing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr "<0>You are about to complete viewing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
#: apps/web/src/components/(dashboard)/settings/token/contants.ts:5 #: apps/web/src/components/(dashboard)/settings/token/contants.ts:5
msgid "1 month" msgid "1 month"
msgstr "1 month" msgstr "1 month"
@@ -660,7 +672,7 @@ msgstr "App Version"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89
#: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120 #: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120
#: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146 #: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:125 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:142
msgid "Approve" msgid "Approve"
msgstr "Approve" msgstr "Approve"
@@ -830,7 +842,7 @@ msgstr "By using the electronic signature feature, you are consenting to conduct
#: 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:328 #: 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:130
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:335 #: 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
@@ -942,22 +954,22 @@ msgstr "Click to insert field"
msgid "Close" msgid "Close"
msgstr "Close" msgstr "Close"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446 #: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325 #: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325
#: apps/web/src/components/forms/v2/signup.tsx:534 #: apps/web/src/components/forms/v2/signup.tsx:534
msgid "Complete" msgid "Complete"
msgstr "Complete" msgstr "Complete"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:70 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69
msgid "Complete Approval" msgid "Complete Approval"
msgstr "Complete Approval" msgstr "Complete Approval"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68
msgid "Complete Signing" msgid "Complete Signing"
msgstr "Complete Signing" msgstr "Complete Signing"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:67
msgid "Complete Viewing" msgid "Complete Viewing"
msgstr "Complete Viewing" msgstr "Complete Viewing"
@@ -1043,23 +1055,23 @@ msgstr "Continue"
msgid "Continue to login" msgid "Continue to login"
msgstr "Continue to login" msgstr "Continue to login"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:188 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:185
msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients." msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients."
msgstr "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients." msgstr "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:154 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:153
msgid "Controls the default visibility of an uploaded document." msgid "Controls the default visibility of an uploaded document."
msgstr "Controls the default visibility of an uploaded document." msgstr "Controls the default visibility of an uploaded document."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:237 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:232
msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead." msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead."
msgstr "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead." msgstr "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:270 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:263
msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally." msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally."
msgstr "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally." msgstr "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:301 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:293
msgid "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." msgid "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."
msgstr "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." msgstr "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."
@@ -1180,7 +1192,7 @@ msgstr "Create webhook"
msgid "Create Webhook" msgid "Create Webhook"
msgstr "Create Webhook" msgstr "Create Webhook"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:215 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:213
msgid "Create your account and start using state-of-the-art document signing." msgid "Create your account and start using state-of-the-art document signing."
msgstr "Create your account and start using state-of-the-art document signing." msgstr "Create your account and start using state-of-the-art document signing."
@@ -1253,11 +1265,11 @@ msgstr "Decline"
msgid "Declined team invitation" msgid "Declined team invitation"
msgstr "Declined team invitation" msgstr "Declined team invitation"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:168 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:165
msgid "Default Document Language" msgid "Default Document Language"
msgstr "Default Document Language" msgstr "Default Document Language"
#: 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:129
msgid "Default Document Visibility" msgid "Default Document Visibility"
msgstr "Default Document Visibility" msgstr "Default Document Visibility"
@@ -1456,7 +1468,7 @@ msgstr "Document"
msgid "Document All" msgid "Document All"
msgstr "Document All" msgstr "Document All"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:134 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132
msgid "Document Approved" msgid "Document Approved"
msgstr "Document Approved" msgstr "Document Approved"
@@ -1485,7 +1497,7 @@ msgid "Document created using a <0>direct link</0>"
msgstr "Document created using a <0>direct link</0>" msgstr "Document created using a <0>direct link</0>"
#: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51 #: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:178 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:181
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61
msgid "Document deleted" msgid "Document deleted"
msgstr "Document deleted" msgstr "Document deleted"
@@ -1498,7 +1510,7 @@ msgstr "Document draft"
msgid "Document Duplicated" msgid "Document Duplicated"
msgstr "Document Duplicated" msgstr "Document Duplicated"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:189 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:192
#: apps/web/src/components/document/document-history-sheet.tsx:104 #: apps/web/src/components/document/document-history-sheet.tsx:104
msgid "Document history" msgid "Document history"
msgstr "Document history" msgstr "Document history"
@@ -1524,7 +1536,7 @@ msgstr "Document metrics"
msgid "Document moved" msgid "Document moved"
msgstr "Document moved" msgstr "Document moved"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:158 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:156
msgid "Document no longer available to sign" msgid "Document no longer available to sign"
msgstr "Document no longer available to sign" msgstr "Document no longer available to sign"
@@ -1556,7 +1568,7 @@ msgstr "Document sent"
#~ msgid "Document Settings" #~ msgid "Document Settings"
#~ msgstr "Document Settings" #~ msgstr "Document Settings"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:130
msgid "Document Signed" msgid "Document Signed"
msgstr "Document Signed" msgstr "Document Signed"
@@ -1580,7 +1592,7 @@ msgstr "Document upload disabled due to unpaid invoices"
msgid "Document uploaded" msgid "Document uploaded"
msgstr "Document uploaded" msgstr "Document uploaded"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:133 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:131
msgid "Document Viewed" msgid "Document Viewed"
msgstr "Document Viewed" msgstr "Document Viewed"
@@ -1604,7 +1616,7 @@ msgstr "Document will be permanently deleted"
msgid "Documents" msgid "Documents"
msgstr "Documents" msgstr "Documents"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:194 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:197
msgid "Documents created from template" msgid "Documents created from template"
msgstr "Documents created from template" msgstr "Documents created from template"
@@ -1685,7 +1697,7 @@ msgstr "Duplicate"
msgid "Edit" msgid "Edit"
msgstr "Edit" msgstr "Edit"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:114 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:117
msgid "Edit Template" msgid "Edit Template"
msgstr "Edit Template" msgstr "Edit Template"
@@ -1773,7 +1785,7 @@ msgstr "Enable direct link signing"
msgid "Enable Direct Link Signing" msgid "Enable Direct Link Signing"
msgstr "Enable Direct Link Signing" msgstr "Enable Direct Link Signing"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:255 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:248
msgid "Enable Typed Signature" msgid "Enable Typed Signature"
msgstr "Enable Typed Signature" msgstr "Enable Typed Signature"
@@ -1861,15 +1873,15 @@ msgstr "Error"
#~ msgid "Error updating global team settings" #~ msgid "Error updating global team settings"
#~ msgstr "Error updating global team settings" #~ msgstr "Error updating global team settings"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:141 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:140
msgid "Everyone can access and view the document" msgid "Everyone can access and view the document"
msgstr "Everyone can access and view the document" msgstr "Everyone can access and view the document"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:142 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:140
msgid "Everyone has signed" msgid "Everyone has signed"
msgstr "Everyone has signed" msgstr "Everyone has signed"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:166 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:164
msgid "Everyone has signed! You will receive an Email copy of the signed document." msgid "Everyone has signed! You will receive an Email copy of the signed document."
msgstr "Everyone has signed! You will receive an Email copy of the signed document." msgstr "Everyone has signed! You will receive an Email copy of the signed document."
@@ -1958,7 +1970,7 @@ msgstr "Go Back"
msgid "Go back home" msgid "Go back home"
msgstr "Go back home" msgstr "Go back home"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:226 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:224
#: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57 #: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57
msgid "Go Back Home" msgid "Go Back Home"
msgstr "Go Back Home" msgstr "Go Back Home"
@@ -2042,7 +2054,7 @@ msgstr "Inbox documents"
#~ msgid "Include Sender Details" #~ msgid "Include Sender Details"
#~ msgstr "Include Sender Details" #~ msgstr "Include Sender Details"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:286 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:278
msgid "Include the Signing Certificate in the Document" msgid "Include the Signing Certificate in the Document"
msgstr "Include the Signing Certificate in the Document" msgstr "Include the Signing Certificate in the Document"
@@ -2262,7 +2274,7 @@ msgstr "Manage {0}'s profile"
msgid "Manage all teams you are currently associated with." msgid "Manage all teams you are currently associated with."
msgstr "Manage all teams you are currently associated with." msgstr "Manage all teams you are currently associated with."
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:158 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:161
msgid "Manage and view template" msgid "Manage and view template"
msgstr "Manage and view template" msgstr "Manage and view template"
@@ -2326,7 +2338,7 @@ msgstr "Manage your passkeys."
msgid "Manage your site settings here" msgid "Manage your site settings here"
msgstr "Manage your site settings here" msgstr "Manage your site settings here"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:123 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:140
msgid "Mark as Viewed" msgid "Mark as Viewed"
msgstr "Mark as Viewed" msgstr "Mark as Viewed"
@@ -2408,7 +2420,7 @@ msgstr "My templates"
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:211 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:209
msgid "Need to sign documents?" msgid "Need to sign documents?"
msgstr "Need to sign documents?" msgstr "Need to sign documents?"
@@ -2435,7 +2447,7 @@ msgstr "New Template"
msgid "Next" msgid "Next"
msgstr "Next" msgstr "Next"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
msgid "Next field" msgid "Next field"
msgstr "Next field" msgstr "Next field"
@@ -2537,11 +2549,11 @@ msgstr "Once confirmed, the following will occur:"
msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below." msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below."
msgstr "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below." msgstr "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:147 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:146
msgid "Only admins can access and view the document" msgid "Only admins can access and view the document"
msgstr "Only admins can access and view the document" msgstr "Only admins can access and view the document"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:144 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:143
msgid "Only managers and above can access and view the document" msgid "Only managers and above can access and view the document"
msgstr "Only managers and above can access and view the document" msgstr "Only managers and above can access and view the document"
@@ -2787,7 +2799,7 @@ msgstr "Please type <0>{0}</0> to confirm."
msgid "Preferences" msgid "Preferences"
msgstr "Preferences" msgstr "Preferences"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:216
msgid "Preview" msgid "Preview"
msgstr "Preview" msgstr "Preview"
@@ -3073,7 +3085,7 @@ msgstr "Roles"
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:344 #: 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:313 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:305
msgid "Save" msgid "Save"
msgstr "Save" msgstr "Save"
@@ -3148,7 +3160,7 @@ msgstr "Send confirmation email"
msgid "Send document" msgid "Send document"
msgstr "Send document" msgstr "Send document"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:205 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:200
msgid "Send on Behalf of Team" msgid "Send on Behalf of Team"
msgstr "Send on Behalf of Team" msgstr "Send on Behalf of Team"
@@ -3221,7 +3233,7 @@ msgstr "Show templates in your team public profile for your audience to sign and
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:229 #: 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:141
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313
#: apps/web/src/components/ui/user-profile-skeleton.tsx:75 #: apps/web/src/components/ui/user-profile-skeleton.tsx:75
#: apps/web/src/components/ui/user-profile-timur.tsx:81 #: apps/web/src/components/ui/user-profile-timur.tsx:81
@@ -3312,7 +3324,7 @@ msgstr "Signature ID"
msgid "Signatures Collected" msgid "Signatures Collected"
msgstr "Signatures Collected" msgstr "Signatures Collected"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:200 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:198
msgid "Signatures will appear once the document has been completed" msgid "Signatures will appear once the document has been completed"
msgstr "Signatures will appear once the document has been completed" msgstr "Signatures will appear once the document has been completed"
@@ -3644,7 +3656,7 @@ msgstr "Teams restricted"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:145 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:148
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408 #: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:271 #: apps/web/src/components/templates/manage-public-template-dialog.tsx:271
msgid "Template" msgid "Template"
@@ -3878,7 +3890,7 @@ msgstr "This document could not be duplicated at this time. Please try again."
msgid "This document could not be re-sent at this time. Please try again." msgid "This document could not be re-sent at this time. Please try again."
msgstr "This document could not be re-sent at this time. Please try again." msgstr "This document could not be re-sent at this time. Please try again."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:180 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:178
msgid "This document has been cancelled by the owner and is no longer available for others to sign." msgid "This document has been cancelled by the owner and is no longer available for others to sign."
msgstr "This document has been cancelled by the owner and is no longer available for others to sign." msgstr "This document has been cancelled by the owner and is no longer available for others to sign."
@@ -3886,11 +3898,11 @@ msgstr "This document has been cancelled by the owner and is no longer available
msgid "This document has been cancelled by the owner." msgid "This document has been cancelled by the owner."
msgstr "This document has been cancelled by the owner." msgstr "This document has been cancelled by the owner."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:224 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227
msgid "This document has been signed by all recipients" msgid "This document has been signed by all recipients"
msgstr "This document has been signed by all recipients" msgstr "This document has been signed by all recipients"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:230
msgid "This document is currently a draft and has not been sent" msgid "This document is currently a draft and has not been sent"
msgstr "This document is currently a draft and has not been sent" msgstr "This document is currently a draft and has not been sent"
@@ -4341,7 +4353,7 @@ msgstr "Uploaded file is too small"
msgid "Uploaded file not an allowed file type" msgid "Uploaded file not an allowed file type"
msgstr "Uploaded file not an allowed file type" msgstr "Uploaded file not an allowed file type"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:169 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:172
msgid "Use" msgid "Use"
msgstr "Use" msgstr "Use"
@@ -4483,7 +4495,7 @@ msgstr "Viewed"
msgid "Waiting" msgid "Waiting"
msgstr "Waiting" msgstr "Waiting"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:150 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:148
msgid "Waiting for others to sign" msgid "Waiting for others to sign"
msgstr "Waiting for others to sign" msgstr "Waiting for others to sign"
@@ -4801,16 +4813,16 @@ msgid "You"
msgstr "You" msgstr "You"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93
msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?" #~ msgstr "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85
msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgstr "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77
msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgstr "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?"
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105
msgid "You are about to delete <0>\"{documentTitle}\"</0>" msgid "You are about to delete <0>\"{documentTitle}\"</0>"
@@ -5010,7 +5022,7 @@ msgstr "You will get notified & be able to set up your documenso public profile
msgid "You will now be required to enter a code from your authenticator app when signing in." msgid "You will now be required to enter a code from your authenticator app when signing in."
msgstr "You will now be required to enter a code from your authenticator app when signing in." msgstr "You will now be required to enter a code from your authenticator app when signing in."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:173 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:171
msgid "You will receive an Email copy of the signed document once everyone has signed." msgid "You will receive an Email copy of the signed document once everyone has signed."
msgstr "You will receive an Email copy of the signed document once everyone has signed." msgstr "You will receive an Email copy of the signed document once everyone has signed."

View File

@@ -341,7 +341,7 @@ msgstr "Se eliminó un destinatario"
msgid "A recipient was updated" msgid "A recipient was updated"
msgstr "Se actualizó un destinatario" msgstr "Se actualizó un destinatario"
#: packages/lib/server-only/team/create-team-email-verification.ts:156 #: packages/lib/server-only/team/create-team-email-verification.ts:159
msgid "A request to use your email has been initiated by {0} on Documenso" msgid "A request to use your email has been initiated by {0} on Documenso"
msgstr "Se ha iniciado una solicitud para usar tu correo electrónico por {0} en Documenso" msgstr "Se ha iniciado una solicitud para usar tu correo electrónico por {0} en Documenso"
@@ -711,7 +711,7 @@ msgid "Document created"
msgstr "Documento creado" msgstr "Documento creado"
#: packages/email/templates/document-created-from-direct-template.tsx:32 #: packages/email/templates/document-created-from-direct-template.tsx:32
#: packages/lib/server-only/template/create-document-from-direct-template.ts:567 #: packages/lib/server-only/template/create-document-from-direct-template.ts:573
msgid "Document created from direct template" msgid "Document created from direct template"
msgstr "Documento creado a partir de plantilla directa" msgstr "Documento creado a partir de plantilla directa"
@@ -1774,7 +1774,7 @@ msgstr "Te han invitado a unirte a {0} en Documenso"
msgid "You have been invited to join the following team" msgid "You have been invited to join the following team"
msgstr "Te han invitado a unirte al siguiente equipo" msgstr "Te han invitado a unirte al siguiente equipo"
#: packages/lib/server-only/recipient/set-recipients-for-document.ts:329 #: packages/lib/server-only/recipient/set-recipients-for-document.ts:327
msgid "You have been removed from a document" msgid "You have been removed from a document"
msgstr "Te han eliminado de un documento" msgstr "Te han eliminado de un documento"

View File

@@ -18,7 +18,7 @@ msgstr ""
"X-Crowdin-File: web.po\n" "X-Crowdin-File: web.po\n"
"X-Crowdin-File-ID: 8\n" "X-Crowdin-File-ID: 8\n"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:231 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226
msgid "\"{0}\" has invited you to sign \"example document\"." msgid "\"{0}\" has invited you to sign \"example document\"."
msgstr "\"{0}\" te ha invitado a firmar \"ejemplo de documento\"." msgstr "\"{0}\" te ha invitado a firmar \"ejemplo de documento\"."
@@ -42,7 +42,7 @@ msgstr "\"{documentTitle}\" ha sido eliminado con éxito"
#~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n" #~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n"
#~ "document\"." #~ "document\"."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221
msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"." msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"."
msgstr "\"{placeholderEmail}\" en nombre de \"{0}\" te ha invitado a firmar \"documento de ejemplo\"." msgstr "\"{placeholderEmail}\" en nombre de \"{0}\" te ha invitado a firmar \"documento de ejemplo\"."
@@ -50,15 +50,15 @@ msgstr "\"{placeholderEmail}\" en nombre de \"{0}\" te ha invitado a firmar \"do
#~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"." #~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"."
#~ msgstr "\"{teamUrl}\" te ha invitado a firmar \"ejemplo de documento\"." #~ msgstr "\"{teamUrl}\" te ha invitado a firmar \"ejemplo de documento\"."
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:83
msgid "({0}) has invited you to approve this document" msgid "({0}) has invited you to approve this document"
msgstr "({0}) te ha invitado a aprobar este documento" msgstr "({0}) te ha invitado a aprobar este documento"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80
msgid "({0}) has invited you to sign this document" msgid "({0}) has invited you to sign this document"
msgstr "({0}) te ha invitado a firmar este documento" msgstr "({0}) te ha invitado a firmar este documento"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:74 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77
msgid "({0}) has invited you to view this document" msgid "({0}) has invited you to view this document"
msgstr "({0}) te ha invitado a ver este documento" msgstr "({0}) te ha invitado a ver este documento"
@@ -71,7 +71,7 @@ msgstr "{0, plural, one {(1 carácter excedido)} other {(# caracteres excedidos)
msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}"
msgstr "{0, plural, one {# carácter sobre el límite} other {# caracteres sobre el límite}}" msgstr "{0, plural, one {# carácter sobre el límite} other {# caracteres sobre el límite}}"
#: apps/web/src/app/(recipient)/d/[token]/page.tsx:82 #: apps/web/src/app/(recipient)/d/[token]/page.tsx:84
msgid "{0, plural, one {# recipient} other {# recipients}}" msgid "{0, plural, one {# recipient} other {# recipients}}"
msgstr "{0, plural, one {# destinatario} other {# destinatarios}}" msgstr "{0, plural, one {# destinatario} other {# destinatarios}}"
@@ -88,11 +88,11 @@ msgstr "{0, plural, one {<0>Tienes <1>1</1> invitación de equipo pendiente</0>}
msgid "{0, plural, one {1 matching field} other {# matching fields}}" msgid "{0, plural, one {1 matching field} other {# matching fields}}"
msgstr "{0, plural, one {1 campo que coincide} other {# campos que coinciden}}" msgstr "{0, plural, one {1 campo que coincide} other {# campos que coinciden}}"
#: 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:132
msgid "{0, plural, one {1 Recipient} other {# Recipients}}" msgid "{0, plural, one {1 Recipient} other {# Recipients}}"
msgstr "{0, plural, one {1 Destinatario} other {# Destinatarios}}" msgstr "{0, plural, one {1 Destinatario} other {# Destinatarios}}"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:235 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:238
msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}" msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}"
msgstr "{0, plural, one {Esperando 1 destinatario} other {Esperando # destinatarios}}" msgstr "{0, plural, one {Esperando 1 destinatario} other {Esperando # destinatarios}}"
@@ -116,7 +116,7 @@ msgstr "{0} plantillas de firma directa"
msgid "{0} of {1} documents remaining this month." msgid "{0} of {1} documents remaining this month."
msgstr "{0} de {1} documentos restantes este mes." msgstr "{0} de {1} documentos restantes este mes."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:170 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:173
msgid "{0} Recipient(s)" msgid "{0} Recipient(s)"
msgstr "{0} Destinatario(s)" msgstr "{0} Destinatario(s)"
@@ -157,6 +157,18 @@ msgstr "<0>\"{0}\"</0> ya no está disponible para firmar"
msgid "<0>Sender:</0> All" msgid "<0>Sender:</0> All"
msgstr "<0>Remitente:</0> Todos" msgstr "<0>Remitente:</0> Todos"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:104
msgid "<0>You are about to complete approving <1>\"{documentTitle}\"</1>.</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:90
msgid "<0>You are about to complete signing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:76
msgid "<0>You are about to complete viewing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/components/(dashboard)/settings/token/contants.ts:5 #: apps/web/src/components/(dashboard)/settings/token/contants.ts:5
msgid "1 month" msgid "1 month"
msgstr "1 mes" msgstr "1 mes"
@@ -665,7 +677,7 @@ msgstr "Versión de la Aplicación"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89
#: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120 #: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120
#: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146 #: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:125 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:142
msgid "Approve" msgid "Approve"
msgstr "Aprobar" msgstr "Aprobar"
@@ -835,7 +847,7 @@ msgstr "Al utilizar la función de firma electrónica, usted está consintiendo
#: 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:328 #: 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:130
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:335 #: 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
@@ -947,22 +959,22 @@ msgstr "Haga clic para insertar campo"
msgid "Close" msgid "Close"
msgstr "Cerrar" msgstr "Cerrar"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446 #: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325 #: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325
#: apps/web/src/components/forms/v2/signup.tsx:534 #: apps/web/src/components/forms/v2/signup.tsx:534
msgid "Complete" msgid "Complete"
msgstr "Completo" msgstr "Completo"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:70 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69
msgid "Complete Approval" msgid "Complete Approval"
msgstr "Completar Aprobación" msgstr "Completar Aprobación"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68
msgid "Complete Signing" msgid "Complete Signing"
msgstr "Completar Firmado" msgstr "Completar Firmado"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:67
msgid "Complete Viewing" msgid "Complete Viewing"
msgstr "Completar Visualización" msgstr "Completar Visualización"
@@ -1048,23 +1060,23 @@ msgstr "Continuar"
msgid "Continue to login" msgid "Continue to login"
msgstr "Continuar con el inicio de sesión" msgstr "Continuar con el inicio de sesión"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:188 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:185
msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients." msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients."
msgstr "Controla el idioma predeterminado de un documento cargado. Este se utilizará como el idioma en las comunicaciones por correo electrónico con los destinatarios." msgstr "Controla el idioma predeterminado de un documento cargado. Este se utilizará como el idioma en las comunicaciones por correo electrónico con los destinatarios."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:154 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:153
msgid "Controls the default visibility of an uploaded document." msgid "Controls the default visibility of an uploaded document."
msgstr "Controla la visibilidad predeterminada de un documento cargado." msgstr "Controla la visibilidad predeterminada de un documento cargado."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:237 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:232
msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead." msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead."
msgstr "Controla el formato del mensaje que se enviará al invitar a un destinatario a firmar un documento. Si se ha proporcionado un mensaje personalizado al configurar el documento, se usará en su lugar." msgstr "Controla el formato del mensaje que se enviará al invitar a un destinatario a firmar un documento. Si se ha proporcionado un mensaje personalizado al configurar el documento, se usará en su lugar."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:270 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:263
msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally." msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally."
msgstr "" msgstr ""
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:301 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:293
msgid "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." msgid "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."
msgstr "" msgstr ""
@@ -1185,7 +1197,7 @@ msgstr "Crear webhook"
msgid "Create Webhook" msgid "Create Webhook"
msgstr "Crear Webhook" msgstr "Crear Webhook"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:215 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:213
msgid "Create your account and start using state-of-the-art document signing." msgid "Create your account and start using state-of-the-art document signing."
msgstr "Crea tu cuenta y comienza a utilizar la firma de documentos de última generación." msgstr "Crea tu cuenta y comienza a utilizar la firma de documentos de última generación."
@@ -1258,11 +1270,11 @@ msgstr "Rechazar"
msgid "Declined team invitation" msgid "Declined team invitation"
msgstr "Invitación de equipo rechazada" msgstr "Invitación de equipo rechazada"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:168 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:165
msgid "Default Document Language" msgid "Default Document Language"
msgstr "Idioma predeterminado del documento" msgstr "Idioma predeterminado del documento"
#: 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:129
msgid "Default Document Visibility" msgid "Default Document Visibility"
msgstr "Visibilidad predeterminada del documento" msgstr "Visibilidad predeterminada del documento"
@@ -1461,7 +1473,7 @@ msgstr "Documento"
msgid "Document All" msgid "Document All"
msgstr "Documentar Todo" msgstr "Documentar Todo"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:134 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132
msgid "Document Approved" msgid "Document Approved"
msgstr "Documento Aprobado" msgstr "Documento Aprobado"
@@ -1490,7 +1502,7 @@ msgid "Document created using a <0>direct link</0>"
msgstr "Documento creado usando un <0>enlace directo</0>" msgstr "Documento creado usando un <0>enlace directo</0>"
#: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51 #: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:178 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:181
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61
msgid "Document deleted" msgid "Document deleted"
msgstr "Documento eliminado" msgstr "Documento eliminado"
@@ -1503,7 +1515,7 @@ msgstr "Borrador de documento"
msgid "Document Duplicated" msgid "Document Duplicated"
msgstr "Documento duplicado" msgstr "Documento duplicado"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:189 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:192
#: apps/web/src/components/document/document-history-sheet.tsx:104 #: apps/web/src/components/document/document-history-sheet.tsx:104
msgid "Document history" msgid "Document history"
msgstr "Historial de documentos" msgstr "Historial de documentos"
@@ -1529,7 +1541,7 @@ msgstr "Métricas de documento"
msgid "Document moved" msgid "Document moved"
msgstr "Documento movido" msgstr "Documento movido"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:158 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:156
msgid "Document no longer available to sign" msgid "Document no longer available to sign"
msgstr "El documento ya no está disponible para firmar" msgstr "El documento ya no está disponible para firmar"
@@ -1561,7 +1573,7 @@ msgstr "Documento enviado"
#~ msgid "Document Settings" #~ msgid "Document Settings"
#~ msgstr "Document Settings" #~ msgstr "Document Settings"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:130
msgid "Document Signed" msgid "Document Signed"
msgstr "Documento firmado" msgstr "Documento firmado"
@@ -1585,7 +1597,7 @@ msgstr "La carga de documentos está deshabilitada debido a facturas impagadas"
msgid "Document uploaded" msgid "Document uploaded"
msgstr "Documento subido" msgstr "Documento subido"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:133 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:131
msgid "Document Viewed" msgid "Document Viewed"
msgstr "Documento visto" msgstr "Documento visto"
@@ -1609,7 +1621,7 @@ msgstr "El documento será eliminado permanentemente"
msgid "Documents" msgid "Documents"
msgstr "Documentos" msgstr "Documentos"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:194 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:197
msgid "Documents created from template" msgid "Documents created from template"
msgstr "Documentos creados a partir de la plantilla" msgstr "Documentos creados a partir de la plantilla"
@@ -1690,7 +1702,7 @@ msgstr "Duplicar"
msgid "Edit" msgid "Edit"
msgstr "Editar" msgstr "Editar"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:114 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:117
msgid "Edit Template" msgid "Edit Template"
msgstr "Editar plantilla" msgstr "Editar plantilla"
@@ -1778,7 +1790,7 @@ msgstr "Habilitar firma de enlace directo"
msgid "Enable Direct Link Signing" msgid "Enable Direct Link Signing"
msgstr "Habilitar firma de enlace directo" msgstr "Habilitar firma de enlace directo"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:255 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:248
msgid "Enable Typed Signature" msgid "Enable Typed Signature"
msgstr "" msgstr ""
@@ -1866,15 +1878,15 @@ msgstr "Error"
#~ msgid "Error updating global team settings" #~ msgid "Error updating global team settings"
#~ msgstr "Error updating global team settings" #~ msgstr "Error updating global team settings"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:141 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:140
msgid "Everyone can access and view the document" msgid "Everyone can access and view the document"
msgstr "Todos pueden acceder y ver el documento" msgstr "Todos pueden acceder y ver el documento"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:142 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:140
msgid "Everyone has signed" msgid "Everyone has signed"
msgstr "Todos han firmado" msgstr "Todos han firmado"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:166 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:164
msgid "Everyone has signed! You will receive an Email copy of the signed document." msgid "Everyone has signed! You will receive an Email copy of the signed document."
msgstr "¡Todos han firmado! Recibirás una copia por correo electrónico del documento firmado." msgstr "¡Todos han firmado! Recibirás una copia por correo electrónico del documento firmado."
@@ -1963,7 +1975,7 @@ msgstr "Regresar"
msgid "Go back home" msgid "Go back home"
msgstr "Regresar a casa" msgstr "Regresar a casa"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:226 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:224
#: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57 #: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57
msgid "Go Back Home" msgid "Go Back Home"
msgstr "Regresar a casa" msgstr "Regresar a casa"
@@ -2047,7 +2059,7 @@ msgstr "Documentos en bandeja de entrada"
#~ msgid "Include Sender Details" #~ msgid "Include Sender Details"
#~ msgstr "Include Sender Details" #~ msgstr "Include Sender Details"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:286 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:278
msgid "Include the Signing Certificate in the Document" msgid "Include the Signing Certificate in the Document"
msgstr "" msgstr ""
@@ -2267,7 +2279,7 @@ msgstr "Gestionar el perfil de {0}"
msgid "Manage all teams you are currently associated with." msgid "Manage all teams you are currently associated with."
msgstr "Gestionar todos los equipos con los que estás asociado actualmente." msgstr "Gestionar todos los equipos con los que estás asociado actualmente."
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:158 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:161
msgid "Manage and view template" msgid "Manage and view template"
msgstr "Gestionar y ver plantilla" msgstr "Gestionar y ver plantilla"
@@ -2331,7 +2343,7 @@ msgstr "Gestionar tus claves de acceso."
msgid "Manage your site settings here" msgid "Manage your site settings here"
msgstr "Gestionar la configuración de tu sitio aquí" msgstr "Gestionar la configuración de tu sitio aquí"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:123 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:140
msgid "Mark as Viewed" msgid "Mark as Viewed"
msgstr "Marcar como visto" msgstr "Marcar como visto"
@@ -2413,7 +2425,7 @@ msgstr "Mis plantillas"
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:211 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:209
msgid "Need to sign documents?" msgid "Need to sign documents?"
msgstr "¿Necesitas firmar documentos?" msgstr "¿Necesitas firmar documentos?"
@@ -2440,7 +2452,7 @@ msgstr "Nueva plantilla"
msgid "Next" msgid "Next"
msgstr "Siguiente" msgstr "Siguiente"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
msgid "Next field" msgid "Next field"
msgstr "Siguiente campo" msgstr "Siguiente campo"
@@ -2542,11 +2554,11 @@ msgstr "Una vez confirmado, ocurrirá lo siguiente:"
msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below." msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below."
msgstr "Una vez que hayas escaneado el código QR o ingresado el código manualmente, ingresa el código proporcionado por tu aplicación de autenticación a continuación." msgstr "Una vez que hayas escaneado el código QR o ingresado el código manualmente, ingresa el código proporcionado por tu aplicación de autenticación a continuación."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:147 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:146
msgid "Only admins can access and view the document" msgid "Only admins can access and view the document"
msgstr "Solo los administradores pueden acceder y ver el documento" msgstr "Solo los administradores pueden acceder y ver el documento"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:144 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:143
msgid "Only managers and above can access and view the document" msgid "Only managers and above can access and view the document"
msgstr "Solo los gerentes y superiores pueden acceder y ver el documento" msgstr "Solo los gerentes y superiores pueden acceder y ver el documento"
@@ -2792,7 +2804,7 @@ msgstr "Por favor, escribe <0>{0}</0> para confirmar."
msgid "Preferences" msgid "Preferences"
msgstr "Preferencias" msgstr "Preferencias"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:216
msgid "Preview" msgid "Preview"
msgstr "Vista previa" msgstr "Vista previa"
@@ -3078,7 +3090,7 @@ msgstr "Roles"
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:344 #: 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:313 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:305
msgid "Save" msgid "Save"
msgstr "Guardar" msgstr "Guardar"
@@ -3153,7 +3165,7 @@ msgstr "Enviar correo de confirmación"
msgid "Send document" msgid "Send document"
msgstr "Enviar documento" msgstr "Enviar documento"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:205 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:200
msgid "Send on Behalf of Team" msgid "Send on Behalf of Team"
msgstr "Enviar en nombre del equipo" msgstr "Enviar en nombre del equipo"
@@ -3226,7 +3238,7 @@ msgstr "Mostrar plantillas en el perfil público de tu equipo para que tu audien
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:229 #: 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:141
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313
#: apps/web/src/components/ui/user-profile-skeleton.tsx:75 #: apps/web/src/components/ui/user-profile-skeleton.tsx:75
#: apps/web/src/components/ui/user-profile-timur.tsx:81 #: apps/web/src/components/ui/user-profile-timur.tsx:81
@@ -3317,7 +3329,7 @@ msgstr "ID de Firma"
msgid "Signatures Collected" msgid "Signatures Collected"
msgstr "Firmas recolectadas" msgstr "Firmas recolectadas"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:200 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:198
msgid "Signatures will appear once the document has been completed" msgid "Signatures will appear once the document has been completed"
msgstr "Las firmas aparecerán una vez que el documento se haya completado" msgstr "Las firmas aparecerán una vez que el documento se haya completado"
@@ -3649,7 +3661,7 @@ msgstr "Equipos restringidos"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:145 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:148
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408 #: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:271 #: apps/web/src/components/templates/manage-public-template-dialog.tsx:271
msgid "Template" msgid "Template"
@@ -3883,7 +3895,7 @@ msgstr "Este documento no se pudo duplicar en este momento. Por favor, inténtal
msgid "This document could not be re-sent at this time. Please try again." msgid "This document could not be re-sent at this time. Please try again."
msgstr "Este documento no se pudo reenviar en este momento. Por favor, inténtalo de nuevo." msgstr "Este documento no se pudo reenviar en este momento. Por favor, inténtalo de nuevo."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:180 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:178
msgid "This document has been cancelled by the owner and is no longer available for others to sign." msgid "This document has been cancelled by the owner and is no longer available for others to sign."
msgstr "Este documento ha sido cancelado por el propietario y ya no está disponible para que otros lo firmen." msgstr "Este documento ha sido cancelado por el propietario y ya no está disponible para que otros lo firmen."
@@ -3891,11 +3903,11 @@ msgstr "Este documento ha sido cancelado por el propietario y ya no está dispon
msgid "This document has been cancelled by the owner." msgid "This document has been cancelled by the owner."
msgstr "Este documento ha sido cancelado por el propietario." msgstr "Este documento ha sido cancelado por el propietario."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:224 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227
msgid "This document has been signed by all recipients" msgid "This document has been signed by all recipients"
msgstr "Este documento ha sido firmado por todos los destinatarios" msgstr "Este documento ha sido firmado por todos los destinatarios"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:230
msgid "This document is currently a draft and has not been sent" msgid "This document is currently a draft and has not been sent"
msgstr "Este documento es actualmente un borrador y no ha sido enviado" msgstr "Este documento es actualmente un borrador y no ha sido enviado"
@@ -4346,7 +4358,7 @@ msgstr "El archivo subido es demasiado pequeño"
msgid "Uploaded file not an allowed file type" msgid "Uploaded file not an allowed file type"
msgstr "El archivo subido no es un tipo de archivo permitido" msgstr "El archivo subido no es un tipo de archivo permitido"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:169 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:172
msgid "Use" msgid "Use"
msgstr "Usar" msgstr "Usar"
@@ -4488,7 +4500,7 @@ msgstr "Visto"
msgid "Waiting" msgid "Waiting"
msgstr "Esperando" msgstr "Esperando"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:150 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:148
msgid "Waiting for others to sign" msgid "Waiting for others to sign"
msgstr "Esperando a que otros firmen" msgstr "Esperando a que otros firmen"
@@ -4806,16 +4818,16 @@ msgid "You"
msgstr "Tú" msgstr "Tú"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93
msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Estás a punto de completar la aprobación de \"{truncatedTitle}\".<0/> ¿Estás seguro?" #~ msgstr "Estás a punto de completar la aprobación de \"{truncatedTitle}\".<0/> ¿Estás seguro?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85
msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Estás a punto de completar la firma de \"{truncatedTitle}\".<0/> ¿Estás seguro?" #~ msgstr "Estás a punto de completar la firma de \"{truncatedTitle}\".<0/> ¿Estás seguro?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77
msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Estás a punto de completar la visualización de \"{truncatedTitle}\".<0/> ¿Estás seguro?" #~ msgstr "Estás a punto de completar la visualización de \"{truncatedTitle}\".<0/> ¿Estás seguro?"
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105
msgid "You are about to delete <0>\"{documentTitle}\"</0>" msgid "You are about to delete <0>\"{documentTitle}\"</0>"
@@ -5015,7 +5027,7 @@ msgstr "Recibirás una notificación y podrás configurar tu perfil público de
msgid "You will now be required to enter a code from your authenticator app when signing in." msgid "You will now be required to enter a code from your authenticator app when signing in."
msgstr "Ahora se te pedirá que ingreses un código de tu aplicación de autenticador al iniciar sesión." msgstr "Ahora se te pedirá que ingreses un código de tu aplicación de autenticador al iniciar sesión."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:173 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:171
msgid "You will receive an Email copy of the signed document once everyone has signed." msgid "You will receive an Email copy of the signed document once everyone has signed."
msgstr "Recibirás una copia por correo electrónico del documento firmado una vez que todos hayan firmado." msgstr "Recibirás una copia por correo electrónico del documento firmado una vez que todos hayan firmado."

View File

@@ -341,7 +341,7 @@ msgstr "Un destinataire a été supprimé"
msgid "A recipient was updated" msgid "A recipient was updated"
msgstr "Un destinataire a été mis à jour" msgstr "Un destinataire a été mis à jour"
#: packages/lib/server-only/team/create-team-email-verification.ts:156 #: packages/lib/server-only/team/create-team-email-verification.ts:159
msgid "A request to use your email has been initiated by {0} on Documenso" msgid "A request to use your email has been initiated by {0} on Documenso"
msgstr "Une demande d'utilisation de votre e-mail a été initiée par {0} sur Documenso" msgstr "Une demande d'utilisation de votre e-mail a été initiée par {0} sur Documenso"
@@ -711,7 +711,7 @@ msgid "Document created"
msgstr "Document créé" msgstr "Document créé"
#: packages/email/templates/document-created-from-direct-template.tsx:32 #: packages/email/templates/document-created-from-direct-template.tsx:32
#: packages/lib/server-only/template/create-document-from-direct-template.ts:567 #: packages/lib/server-only/template/create-document-from-direct-template.ts:573
msgid "Document created from direct template" msgid "Document created from direct template"
msgstr "Document créé à partir d'un modèle direct" msgstr "Document créé à partir d'un modèle direct"
@@ -1774,7 +1774,7 @@ msgstr "Vous avez été invité à rejoindre {0} sur Documenso"
msgid "You have been invited to join the following team" msgid "You have been invited to join the following team"
msgstr "Vous avez été invité à rejoindre l'équipe suivante" msgstr "Vous avez été invité à rejoindre l'équipe suivante"
#: packages/lib/server-only/recipient/set-recipients-for-document.ts:329 #: packages/lib/server-only/recipient/set-recipients-for-document.ts:327
msgid "You have been removed from a document" msgid "You have been removed from a document"
msgstr "Vous avez été supprimé d'un document" msgstr "Vous avez été supprimé d'un document"

View File

@@ -18,7 +18,7 @@ msgstr ""
"X-Crowdin-File: web.po\n" "X-Crowdin-File: web.po\n"
"X-Crowdin-File-ID: 8\n" "X-Crowdin-File-ID: 8\n"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:231 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226
msgid "\"{0}\" has invited you to sign \"example document\"." msgid "\"{0}\" has invited you to sign \"example document\"."
msgstr "\"{0}\" vous a invité à signer \"example document\"." msgstr "\"{0}\" vous a invité à signer \"example document\"."
@@ -42,7 +42,7 @@ msgstr "\"{documentTitle}\" a été supprimé avec succès"
#~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n" #~ "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example\n"
#~ "document\"." #~ "document\"."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:226 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221
msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"." msgid "\"{placeholderEmail}\" on behalf of \"{0}\" has invited you to sign \"example document\"."
msgstr "\"{placeholderEmail}\" au nom de \"{0}\" vous a invité à signer \"exemple de document\"." msgstr "\"{placeholderEmail}\" au nom de \"{0}\" vous a invité à signer \"exemple de document\"."
@@ -50,15 +50,15 @@ msgstr "\"{placeholderEmail}\" au nom de \"{0}\" vous a invité à signer \"exem
#~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"." #~ msgid "\"{teamUrl}\" has invited you to sign \"example document\"."
#~ msgstr "\"{teamUrl}\" vous a invité à signer \"example document\"." #~ msgstr "\"{teamUrl}\" vous a invité à signer \"example document\"."
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:83
msgid "({0}) has invited you to approve this document" msgid "({0}) has invited you to approve this document"
msgstr "({0}) vous a invité à approuver ce document" msgstr "({0}) vous a invité à approuver ce document"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:80
msgid "({0}) has invited you to sign this document" msgid "({0}) has invited you to sign this document"
msgstr "({0}) vous a invité à signer ce document" msgstr "({0}) vous a invité à signer ce document"
#: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:74 #: apps/web/src/app/(signing)/sign/[token]/signing-page-view.tsx:77
msgid "({0}) has invited you to view this document" msgid "({0}) has invited you to view this document"
msgstr "({0}) vous a invité à consulter ce document" msgstr "({0}) vous a invité à consulter ce document"
@@ -71,7 +71,7 @@ msgstr "{0, plural, one {(1 caractère de trop)} other {(# caractères de trop)}
msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}" msgid "{0, plural, one {# character over the limit} other {# characters over the limit}}"
msgstr "{0, plural, one {# caractère au-dessus de la limite} other {# caractères au-dessus de la limite}}" msgstr "{0, plural, one {# caractère au-dessus de la limite} other {# caractères au-dessus de la limite}}"
#: apps/web/src/app/(recipient)/d/[token]/page.tsx:82 #: apps/web/src/app/(recipient)/d/[token]/page.tsx:84
msgid "{0, plural, one {# recipient} other {# recipients}}" msgid "{0, plural, one {# recipient} other {# recipients}}"
msgstr "{0, plural, one {# destinataire} other {# destinataires}}" msgstr "{0, plural, one {# destinataire} other {# destinataires}}"
@@ -88,11 +88,11 @@ msgstr "{0, plural, one {<0>Vous avez <1>1</1> invitation d'équipe en attente</
msgid "{0, plural, one {1 matching field} other {# matching fields}}" msgid "{0, plural, one {1 matching field} other {# matching fields}}"
msgstr "{0, plural, one {1 champ correspondant} other {# champs correspondants}}" msgstr "{0, plural, one {1 champ correspondant} other {# champs correspondants}}"
#: 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:132
msgid "{0, plural, one {1 Recipient} other {# Recipients}}" msgid "{0, plural, one {1 Recipient} other {# Recipients}}"
msgstr "{0, plural, one {1 Destinataire} other {# Destinataires}}" msgstr "{0, plural, one {1 Destinataire} other {# Destinataires}}"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:235 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:238
msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}" msgid "{0, plural, one {Waiting on 1 recipient} other {Waiting on # recipients}}"
msgstr "{0, plural, one {En attente d'1 destinataire} other {En attente de # destinataires}}" msgstr "{0, plural, one {En attente d'1 destinataire} other {En attente de # destinataires}}"
@@ -116,7 +116,7 @@ msgstr "{0} modèles de signature directe"
msgid "{0} of {1} documents remaining this month." msgid "{0} of {1} documents remaining this month."
msgstr "{0} des {1} documents restants ce mois-ci." msgstr "{0} des {1} documents restants ce mois-ci."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:170 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:173
msgid "{0} Recipient(s)" msgid "{0} Recipient(s)"
msgstr "{0} Destinataire(s)" msgstr "{0} Destinataire(s)"
@@ -157,6 +157,18 @@ msgstr "<0>\"{0}\"</0> n'est plus disponible pour signer"
msgid "<0>Sender:</0> All" msgid "<0>Sender:</0> All"
msgstr "<0>Expéditeur :</0> Tous" msgstr "<0>Expéditeur :</0> Tous"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:104
msgid "<0>You are about to complete approving <1>\"{documentTitle}\"</1>.</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:90
msgid "<0>You are about to complete signing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:76
msgid "<0>You are about to complete viewing \"<1>{documentTitle}</1>\".</0><2/> Are you sure?"
msgstr ""
#: apps/web/src/components/(dashboard)/settings/token/contants.ts:5 #: apps/web/src/components/(dashboard)/settings/token/contants.ts:5
msgid "1 month" msgid "1 month"
msgstr "1 mois" msgstr "1 mois"
@@ -665,7 +677,7 @@ msgstr "Version de l'application"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view-button.tsx:89
#: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120 #: apps/web/src/app/(dashboard)/documents/data-table-action-button.tsx:120
#: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146 #: apps/web/src/app/(dashboard)/documents/data-table-action-dropdown.tsx:146
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:125 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:142
msgid "Approve" msgid "Approve"
msgstr "Approuver" msgstr "Approuver"
@@ -835,7 +847,7 @@ msgstr "En utilisant la fonctionnalité de signature électronique, vous consent
#: 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:328 #: 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:130
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:305
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:335 #: 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
@@ -947,22 +959,22 @@ msgstr "Cliquez pour insérer le champ"
msgid "Close" msgid "Close"
msgstr "Fermer" msgstr "Fermer"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446 #: apps/web/src/app/embed/direct/[[...url]]/client.tsx:446
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325 #: apps/web/src/app/embed/sign/[[...url]]/client.tsx:325
#: apps/web/src/components/forms/v2/signup.tsx:534 #: apps/web/src/components/forms/v2/signup.tsx:534
msgid "Complete" msgid "Complete"
msgstr "Compléter" msgstr "Compléter"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:70 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69
msgid "Complete Approval" msgid "Complete Approval"
msgstr "Compléter l'approbation" msgstr "Compléter l'approbation"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:69 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68
msgid "Complete Signing" msgid "Complete Signing"
msgstr "Compléter la signature" msgstr "Compléter la signature"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:68 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:67
msgid "Complete Viewing" msgid "Complete Viewing"
msgstr "Compléter la visualisation" msgstr "Compléter la visualisation"
@@ -1048,23 +1060,23 @@ msgstr "Continuer"
msgid "Continue to login" msgid "Continue to login"
msgstr "Continuer vers la connexion" msgstr "Continuer vers la connexion"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:188 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:185
msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients." msgid "Controls the default language of an uploaded document. This will be used as the language in email communications with the recipients."
msgstr "Contrôle la langue par défaut d'un document téléchargé. Cela sera utilisé comme langue dans les communications par e-mail avec les destinataires." msgstr "Contrôle la langue par défaut d'un document téléchargé. Cela sera utilisé comme langue dans les communications par e-mail avec les destinataires."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:154 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:153
msgid "Controls the default visibility of an uploaded document." msgid "Controls the default visibility of an uploaded document."
msgstr "Contrôle la visibilité par défaut d'un document téléchargé." msgstr "Contrôle la visibilité par défaut d'un document téléchargé."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:237 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:232
msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead." msgid "Controls the formatting of the message that will be sent when inviting a recipient to sign a document. If a custom message has been provided while configuring the document, it will be used instead."
msgstr "Contrôle le formatage du message qui sera envoyé lors de l'invitation d'un destinataire à signer un document. Si un message personnalisé a été fourni lors de la configuration du document, il sera utilisé à la place." msgstr "Contrôle le formatage du message qui sera envoyé lors de l'invitation d'un destinataire à signer un document. Si un message personnalisé a été fourni lors de la configuration du document, il sera utilisé à la place."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:270 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:263
msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally." msgid "Controls whether the recipients can sign the documents using a typed signature. Enable or disable the typed signature globally."
msgstr "" msgstr ""
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:301 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:293
msgid "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." msgid "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."
msgstr "" msgstr ""
@@ -1185,7 +1197,7 @@ msgstr "Créer un webhook"
msgid "Create Webhook" msgid "Create Webhook"
msgstr "Créer un Webhook" msgstr "Créer un Webhook"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:215 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:213
msgid "Create your account and start using state-of-the-art document signing." msgid "Create your account and start using state-of-the-art document signing."
msgstr "Créez votre compte et commencez à utiliser la signature de documents à la pointe de la technologie." msgstr "Créez votre compte et commencez à utiliser la signature de documents à la pointe de la technologie."
@@ -1258,11 +1270,11 @@ msgstr "Décliner"
msgid "Declined team invitation" msgid "Declined team invitation"
msgstr "Invitation d'équipe refusée" msgstr "Invitation d'équipe refusée"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:168 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:165
msgid "Default Document Language" msgid "Default Document Language"
msgstr "Langue par défaut du document" msgstr "Langue par défaut du document"
#: 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:129
msgid "Default Document Visibility" msgid "Default Document Visibility"
msgstr "Visibilité par défaut du document" msgstr "Visibilité par défaut du document"
@@ -1461,7 +1473,7 @@ msgstr "Document"
msgid "Document All" msgid "Document All"
msgstr "Document Tout" msgstr "Document Tout"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:134 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132
msgid "Document Approved" msgid "Document Approved"
msgstr "Document Approuvé" msgstr "Document Approuvé"
@@ -1490,7 +1502,7 @@ msgid "Document created using a <0>direct link</0>"
msgstr "Document créé en utilisant un <0>lien direct</0>" msgstr "Document créé en utilisant un <0>lien direct</0>"
#: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51 #: apps/web/src/app/(dashboard)/admin/documents/[id]/super-delete-document-dialog.tsx:51
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:178 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:181
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:61
msgid "Document deleted" msgid "Document deleted"
msgstr "Document supprimé" msgstr "Document supprimé"
@@ -1503,7 +1515,7 @@ msgstr "Brouillon de document"
msgid "Document Duplicated" msgid "Document Duplicated"
msgstr "Document dupliqué" msgstr "Document dupliqué"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:189 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:192
#: apps/web/src/components/document/document-history-sheet.tsx:104 #: apps/web/src/components/document/document-history-sheet.tsx:104
msgid "Document history" msgid "Document history"
msgstr "Historique du document" msgstr "Historique du document"
@@ -1529,7 +1541,7 @@ msgstr "Métriques du document"
msgid "Document moved" msgid "Document moved"
msgstr "Document déplacé" msgstr "Document déplacé"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:158 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:156
msgid "Document no longer available to sign" msgid "Document no longer available to sign"
msgstr "Document non disponible pour signature" msgstr "Document non disponible pour signature"
@@ -1561,7 +1573,7 @@ msgstr "Document envoyé"
#~ msgid "Document Settings" #~ msgid "Document Settings"
#~ msgstr "Document Settings" #~ msgstr "Document Settings"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:132 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:130
msgid "Document Signed" msgid "Document Signed"
msgstr "Document signé" msgstr "Document signé"
@@ -1585,7 +1597,7 @@ msgstr "Téléchargement du document désactivé en raison de factures impayées
msgid "Document uploaded" msgid "Document uploaded"
msgstr "Document téléchargé" msgstr "Document téléchargé"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:133 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:131
msgid "Document Viewed" msgid "Document Viewed"
msgstr "Document consulté" msgstr "Document consulté"
@@ -1609,7 +1621,7 @@ msgstr "Le document sera supprimé de manière permanente"
msgid "Documents" msgid "Documents"
msgstr "Documents" msgstr "Documents"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:194 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:197
msgid "Documents created from template" msgid "Documents created from template"
msgstr "Documents créés à partir du modèle" msgstr "Documents créés à partir du modèle"
@@ -1690,7 +1702,7 @@ msgstr "Dupliquer"
msgid "Edit" msgid "Edit"
msgstr "Modifier" msgstr "Modifier"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:114 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:117
msgid "Edit Template" msgid "Edit Template"
msgstr "Modifier le modèle" msgstr "Modifier le modèle"
@@ -1778,7 +1790,7 @@ msgstr "Activer la signature par lien direct"
msgid "Enable Direct Link Signing" msgid "Enable Direct Link Signing"
msgstr "Activer la signature par lien direct" msgstr "Activer la signature par lien direct"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:255 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:248
msgid "Enable Typed Signature" msgid "Enable Typed Signature"
msgstr "" msgstr ""
@@ -1866,15 +1878,15 @@ msgstr "Erreur"
#~ msgid "Error updating global team settings" #~ msgid "Error updating global team settings"
#~ msgstr "Error updating global team settings" #~ msgstr "Error updating global team settings"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:141 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:140
msgid "Everyone can access and view the document" msgid "Everyone can access and view the document"
msgstr "Tout le monde peut accéder et voir le document" msgstr "Tout le monde peut accéder et voir le document"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:142 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:140
msgid "Everyone has signed" msgid "Everyone has signed"
msgstr "Tout le monde a signé" msgstr "Tout le monde a signé"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:166 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:164
msgid "Everyone has signed! You will receive an Email copy of the signed document." msgid "Everyone has signed! You will receive an Email copy of the signed document."
msgstr "Tout le monde a signé ! Vous recevrez une copie par email du document signé." msgstr "Tout le monde a signé ! Vous recevrez une copie par email du document signé."
@@ -1963,7 +1975,7 @@ msgstr "Retourner"
msgid "Go back home" msgid "Go back home"
msgstr "Retourner à la maison" msgstr "Retourner à la maison"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:226 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:224
#: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57 #: apps/web/src/app/(signing)/sign/[token]/no-longer-available.tsx:57
msgid "Go Back Home" msgid "Go Back Home"
msgstr "Retourner à la maison" msgstr "Retourner à la maison"
@@ -2047,7 +2059,7 @@ msgstr "Documents de la boîte de réception"
#~ msgid "Include Sender Details" #~ msgid "Include Sender Details"
#~ msgstr "Include Sender Details" #~ msgstr "Include Sender Details"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:286 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:278
msgid "Include the Signing Certificate in the Document" msgid "Include the Signing Certificate in the Document"
msgstr "" msgstr ""
@@ -2267,7 +2279,7 @@ msgstr "Gérer le profil de {0}"
msgid "Manage all teams you are currently associated with." msgid "Manage all teams you are currently associated with."
msgstr "Gérer toutes les équipes avec lesquelles vous êtes actuellement associé." msgstr "Gérer toutes les équipes avec lesquelles vous êtes actuellement associé."
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:158 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:161
msgid "Manage and view template" msgid "Manage and view template"
msgstr "Gérer et afficher le modèle" msgstr "Gérer et afficher le modèle"
@@ -2331,7 +2343,7 @@ msgstr "Gérer vos clés d'accès."
msgid "Manage your site settings here" msgid "Manage your site settings here"
msgstr "Gérer les paramètres de votre site ici" msgstr "Gérer les paramètres de votre site ici"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:123 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:140
msgid "Mark as Viewed" msgid "Mark as Viewed"
msgstr "Marquer comme vu" msgstr "Marquer comme vu"
@@ -2413,7 +2425,7 @@ msgstr "Mes modèles"
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:211 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:209
msgid "Need to sign documents?" msgid "Need to sign documents?"
msgstr "Besoin de signer des documents ?" msgstr "Besoin de signer des documents ?"
@@ -2440,7 +2452,7 @@ msgstr "Nouveau modèle"
msgid "Next" msgid "Next"
msgstr "Suivant" msgstr "Suivant"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:61 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:60
msgid "Next field" msgid "Next field"
msgstr "Champ suivant" msgstr "Champ suivant"
@@ -2542,11 +2554,11 @@ msgstr "Une fois confirmé, les éléments suivants se produiront :"
msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below." msgid "Once you have scanned the QR code or entered the code manually, enter the code provided by your authenticator app below."
msgstr "Une fois que vous avez scanné le code QR ou saisi le code manuellement, entrez le code fourni par votre application d'authentification ci-dessous." msgstr "Une fois que vous avez scanné le code QR ou saisi le code manuellement, entrez le code fourni par votre application d'authentification ci-dessous."
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:147 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:146
msgid "Only admins can access and view the document" msgid "Only admins can access and view the document"
msgstr "Seules les administrateurs peuvent accéder et voir le document" msgstr "Seules les administrateurs peuvent accéder et voir le document"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:144 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:143
msgid "Only managers and above can access and view the document" msgid "Only managers and above can access and view the document"
msgstr "Seuls les responsables et au-dessus peuvent accéder et voir le document" msgstr "Seuls les responsables et au-dessus peuvent accéder et voir le document"
@@ -2792,7 +2804,7 @@ msgstr "Veuillez taper <0>{0}</0> pour confirmer."
msgid "Preferences" msgid "Preferences"
msgstr "Préférences" msgstr "Préférences"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:221 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:216
msgid "Preview" msgid "Preview"
msgstr "Aperçu" msgstr "Aperçu"
@@ -3078,7 +3090,7 @@ msgstr "Rôles"
#: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337 #: apps/web/src/app/(signing)/sign/[token]/number-field.tsx:337
#: apps/web/src/app/(signing)/sign/[token]/text-field.tsx:344 #: 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:313 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:305
msgid "Save" msgid "Save"
msgstr "Sauvegarder" msgstr "Sauvegarder"
@@ -3153,7 +3165,7 @@ msgstr "Envoyer l'e-mail de confirmation"
msgid "Send document" msgid "Send document"
msgstr "Envoyer le document" msgstr "Envoyer le document"
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:205 #: apps/web/src/app/(teams)/t/[teamUrl]/settings/preferences/document-preferences.tsx:200
msgid "Send on Behalf of Team" msgid "Send on Behalf of Team"
msgstr "Envoyer au nom de l'équipe" msgstr "Envoyer au nom de l'équipe"
@@ -3226,7 +3238,7 @@ msgstr "Afficher des modèles dans le profil public de votre équipe pour que vo
#: apps/web/src/app/(signing)/sign/[token]/auto-sign.tsx:229 #: 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:141
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313 #: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:313
#: apps/web/src/components/ui/user-profile-skeleton.tsx:75 #: apps/web/src/components/ui/user-profile-skeleton.tsx:75
#: apps/web/src/components/ui/user-profile-timur.tsx:81 #: apps/web/src/components/ui/user-profile-timur.tsx:81
@@ -3317,7 +3329,7 @@ msgstr "ID de signature"
msgid "Signatures Collected" msgid "Signatures Collected"
msgstr "Signatures collectées" msgstr "Signatures collectées"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:200 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:198
msgid "Signatures will appear once the document has been completed" msgid "Signatures will appear once the document has been completed"
msgstr "Les signatures apparaîtront une fois le document complété" msgstr "Les signatures apparaîtront une fois le document complété"
@@ -3649,7 +3661,7 @@ msgstr "Équipes restreintes"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:39
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:148
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view-documents-table.tsx:228
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:145 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:148
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408 #: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:408
#: apps/web/src/components/templates/manage-public-template-dialog.tsx:271 #: apps/web/src/components/templates/manage-public-template-dialog.tsx:271
msgid "Template" msgid "Template"
@@ -3883,7 +3895,7 @@ msgstr "Ce document n'a pas pu être dupliqué pour le moment. Veuillez réessay
msgid "This document could not be re-sent at this time. Please try again." msgid "This document could not be re-sent at this time. Please try again."
msgstr "Ce document n'a pas pu être renvoyé pour le moment. Veuillez réessayer." msgstr "Ce document n'a pas pu être renvoyé pour le moment. Veuillez réessayer."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:180 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:178
msgid "This document has been cancelled by the owner and is no longer available for others to sign." msgid "This document has been cancelled by the owner and is no longer available for others to sign."
msgstr "Ce document a été annulé par le propriétaire et n'est plus disponible pour d'autres à signer." msgstr "Ce document a été annulé par le propriétaire et n'est plus disponible pour d'autres à signer."
@@ -3891,11 +3903,11 @@ msgstr "Ce document a été annulé par le propriétaire et n'est plus disponibl
msgid "This document has been cancelled by the owner." msgid "This document has been cancelled by the owner."
msgstr "Ce document a été annulé par le propriétaire." msgstr "Ce document a été annulé par le propriétaire."
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:224 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227
msgid "This document has been signed by all recipients" msgid "This document has been signed by all recipients"
msgstr "Ce document a été signé par tous les destinataires" msgstr "Ce document a été signé par tous les destinataires"
#: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:227 #: apps/web/src/app/(dashboard)/documents/[id]/document-page-view.tsx:230
msgid "This document is currently a draft and has not been sent" msgid "This document is currently a draft and has not been sent"
msgstr "Ce document est actuellement un brouillon et n'a pas été envoyé" msgstr "Ce document est actuellement un brouillon et n'a pas été envoyé"
@@ -4346,7 +4358,7 @@ msgstr "Le fichier téléchargé est trop petit"
msgid "Uploaded file not an allowed file type" msgid "Uploaded file not an allowed file type"
msgstr "Le fichier téléchargé n'est pas un type de fichier autorisé" msgstr "Le fichier téléchargé n'est pas un type de fichier autorisé"
#: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:169 #: apps/web/src/app/(dashboard)/templates/[id]/template-page-view.tsx:172
msgid "Use" msgid "Use"
msgstr "Utiliser" msgstr "Utiliser"
@@ -4488,7 +4500,7 @@ msgstr "Vu"
msgid "Waiting" msgid "Waiting"
msgstr "En attente" msgstr "En attente"
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:150 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:148
msgid "Waiting for others to sign" msgid "Waiting for others to sign"
msgstr "En attente que d'autres signent" msgstr "En attente que d'autres signent"
@@ -4806,16 +4818,16 @@ msgid "You"
msgstr "Vous" msgstr "Vous"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:93
msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete approving \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Vous êtes sur le point de terminer l'approbation de \"{truncatedTitle}\".<0/> Êtes-vous sûr?" #~ msgstr "Vous êtes sur le point de terminer l'approbation de \"{truncatedTitle}\".<0/> Êtes-vous sûr?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:85
msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete signing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Vous êtes sur le point de terminer la signature de \"{truncatedTitle}\".<0/> Êtes-vous sûr?" #~ msgstr "Vous êtes sur le point de terminer la signature de \"{truncatedTitle}\".<0/> Êtes-vous sûr?"
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77 #: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:77
msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?" #~ msgid "You are about to complete viewing \"{truncatedTitle}\".<0/> Are you sure?"
msgstr "Vous êtes sur le point de terminer la visualisation de \"{truncatedTitle}\".<0/> Êtes-vous sûr?" #~ msgstr "Vous êtes sur le point de terminer la visualisation de \"{truncatedTitle}\".<0/> Êtes-vous sûr?"
#: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105 #: apps/web/src/app/(dashboard)/documents/delete-document-dialog.tsx:105
msgid "You are about to delete <0>\"{documentTitle}\"</0>" msgid "You are about to delete <0>\"{documentTitle}\"</0>"
@@ -5015,7 +5027,7 @@ msgstr "Vous serez notifié et pourrez configurer votre profil public Documenso
msgid "You will now be required to enter a code from your authenticator app when signing in." msgid "You will now be required to enter a code from your authenticator app when signing in."
msgstr "Vous devrez maintenant entrer un code de votre application d'authentification lors de la connexion." msgstr "Vous devrez maintenant entrer un code de votre application d'authentification lors de la connexion."
#: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:173 #: apps/web/src/app/(signing)/sign/[token]/complete/page.tsx:171
msgid "You will receive an Email copy of the signed document once everyone has signed." msgid "You will receive an Email copy of the signed document once everyone has signed."
msgstr "Vous recevrez une copie par e-mail du document signé une fois que tout le monde aura signé." msgstr "Vous recevrez une copie par e-mail du document signé une fois que tout le monde aura signé."

View File

@@ -0,0 +1,108 @@
import Honeybadger from '@honeybadger-io/js';
export const buildLogger = () => {
if (process.env.NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY) {
return new HoneybadgerLogger();
}
return new DefaultLogger();
};
interface LoggerDescriptionOptions {
method?: string;
path?: string;
context?: Record<string, unknown>;
/**
* The type of log to be captured.
*
* Defaults to `info`.
*/
level?: 'info' | 'error' | 'critical';
}
/**
* Basic logger implementation intended to be used in the server side for capturing
* explicit errors and other logs.
*
* Not intended to capture the request and responses.
*/
interface Logger {
log(message: string, options?: LoggerDescriptionOptions): void;
error(error: Error, options?: LoggerDescriptionOptions): void;
}
class DefaultLogger implements Logger {
log(_message: string, _options?: LoggerDescriptionOptions) {
// Do nothing.
}
error(_error: Error, _options?: LoggerDescriptionOptions): void {
// Do nothing.
}
}
class HoneybadgerLogger implements Logger {
constructor() {
if (!process.env.NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY) {
throw new Error('NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY is not set');
}
Honeybadger.configure({
apiKey: process.env.NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY,
});
}
/**
* Honeybadger doesn't really have a non-error logging system.
*/
log(message: string, options?: LoggerDescriptionOptions) {
const { context = {}, level = 'info' } = options || {};
try {
Honeybadger.event({
message,
context: {
level,
...context,
},
});
} catch (err) {
console.error(err);
// Do nothing.
}
}
error(error: Error, options?: LoggerDescriptionOptions): void {
const { context = {}, level = 'error', method, path } = options || {};
const tags = [`level:${level}`];
let errorMessage = error.message;
if (method) {
tags.push(`method:${method}`);
errorMessage = `[${method}]: ${error.message}`;
}
if (path) {
tags.push(`path:${path}`);
}
try {
Honeybadger.notify(errorMessage, {
context: {
level,
...context,
},
tags,
});
} catch (err) {
console.error(err);
// Do nothing.
}
}
}

View File

@@ -44,10 +44,9 @@ export const authRouter = router({
const { name, email, password, signature, url } = input; const { name, email, password, signature, url } = input;
if (IS_BILLING_ENABLED() && url && url.length < 6) { if (IS_BILLING_ENABLED() && url && url.length < 6) {
throw new AppError( throw new AppError(AppErrorCode.PREMIUM_PROFILE_URL, {
AppErrorCode.PREMIUM_PROFILE_URL, message: 'Only subscribers can have a username shorter than 6 characters',
'Only subscribers can have a username shorter than 6 characters', });
);
} }
const user = await createUser({ name, email, password, signature, url }); const user = await createUser({ name, email, password, signature, url });
@@ -66,7 +65,7 @@ export const authRouter = router({
const error = AppError.parseError(err); const error = AppError.parseError(err);
if (error.code !== AppErrorCode.UNKNOWN_ERROR) { if (error.code !== AppErrorCode.UNKNOWN_ERROR) {
throw AppError.parseErrorToTRPCError(error); throw error;
} }
let message = let message =
@@ -118,7 +117,7 @@ export const authRouter = router({
} catch (err) { } catch (err) {
console.error(err); console.error(err);
throw AppError.parseErrorToTRPCError(err); throw err;
} }
}), }),

View File

@@ -1,6 +1,5 @@
import { TRPCError } from '@trpc/server'; import { TRPCError } from '@trpc/server';
import { AppError } from '@documenso/lib/errors/app-error';
import { getFieldById } from '@documenso/lib/server-only/field/get-field-by-id'; import { getFieldById } from '@documenso/lib/server-only/field/get-field-by-id';
import { removeSignedFieldWithToken } from '@documenso/lib/server-only/field/remove-signed-field-with-token'; import { removeSignedFieldWithToken } from '@documenso/lib/server-only/field/remove-signed-field-with-token';
import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document'; import { setFieldsForDocument } from '@documenso/lib/server-only/field/set-fields-for-document';
@@ -96,7 +95,7 @@ export const fieldRouter = router({
} catch (err) { } catch (err) {
console.error(err); console.error(err);
throw AppError.parseErrorToTRPCError(err); throw err;
} }
}), }),

View File

@@ -100,10 +100,9 @@ export const profileRouter = router({
); );
if (subscriptions.length === 0) { if (subscriptions.length === 0) {
throw new AppError( throw new AppError(AppErrorCode.PREMIUM_PROFILE_URL, {
AppErrorCode.PREMIUM_PROFILE_URL, message: 'Only subscribers can have a username shorter than 6 characters',
'Only subscribers can have a username shorter than 6 characters', });
);
} }
} }
@@ -123,7 +122,7 @@ export const profileRouter = router({
const error = AppError.parseError(err); const error = AppError.parseError(err);
if (error.code !== AppErrorCode.UNKNOWN_ERROR) { if (error.code !== AppErrorCode.UNKNOWN_ERROR) {
throw AppError.parseErrorToTRPCError(error); throw error;
} }
throw new TRPCError({ throw new TRPCError({

View File

@@ -76,412 +76,238 @@ export const teamRouter = router({
acceptTeamInvitation: authenticatedProcedure acceptTeamInvitation: authenticatedProcedure
.input(ZAcceptTeamInvitationMutationSchema) .input(ZAcceptTeamInvitationMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await acceptTeamInvitation({
return await acceptTeamInvitation({ teamId: input.teamId,
teamId: input.teamId, userId: ctx.user.id,
userId: ctx.user.id, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
declineTeamInvitation: authenticatedProcedure declineTeamInvitation: authenticatedProcedure
.input(ZDeclineTeamInvitationMutationSchema) .input(ZDeclineTeamInvitationMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await declineTeamInvitation({
return await declineTeamInvitation({ teamId: input.teamId,
teamId: input.teamId, userId: ctx.user.id,
userId: ctx.user.id, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createBillingPortal: authenticatedProcedure createBillingPortal: authenticatedProcedure
.input(ZCreateTeamBillingPortalMutationSchema) .input(ZCreateTeamBillingPortalMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await createTeamBillingPortal({
return await createTeamBillingPortal({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createTeam: authenticatedProcedure createTeam: authenticatedProcedure
.input(ZCreateTeamMutationSchema) .input(ZCreateTeamMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await createTeam({
return await createTeam({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createTeamEmailVerification: authenticatedProcedure createTeamEmailVerification: authenticatedProcedure
.input(ZCreateTeamEmailVerificationMutationSchema) .input(ZCreateTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await createTeamEmailVerification({
return await createTeamEmailVerification({ teamId: input.teamId,
teamId: input.teamId, userId: ctx.user.id,
userId: ctx.user.id, data: {
data: { email: input.email,
email: input.email, name: input.name,
name: input.name, },
}, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createTeamMemberInvites: authenticatedProcedure createTeamMemberInvites: authenticatedProcedure
.input(ZCreateTeamMemberInvitesMutationSchema) .input(ZCreateTeamMemberInvitesMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await createTeamMemberInvites({
return await createTeamMemberInvites({ userId: ctx.user.id,
userId: ctx.user.id, userName: ctx.user.name ?? '',
userName: ctx.user.name ?? '', ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createTeamPendingCheckout: authenticatedProcedure createTeamPendingCheckout: authenticatedProcedure
.input(ZCreateTeamPendingCheckoutMutationSchema) .input(ZCreateTeamPendingCheckoutMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await createTeamPendingCheckoutSession({
return await createTeamPendingCheckoutSession({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeam: authenticatedProcedure deleteTeam: authenticatedProcedure
.input(ZDeleteTeamMutationSchema) .input(ZDeleteTeamMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeam({
return await deleteTeam({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeamEmail: authenticatedProcedure deleteTeamEmail: authenticatedProcedure
.input(ZDeleteTeamEmailMutationSchema) .input(ZDeleteTeamEmailMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeamEmail({
return await deleteTeamEmail({ userId: ctx.user.id,
userId: ctx.user.id, userEmail: ctx.user.email,
userEmail: ctx.user.email, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeamEmailVerification: authenticatedProcedure deleteTeamEmailVerification: authenticatedProcedure
.input(ZDeleteTeamEmailVerificationMutationSchema) .input(ZDeleteTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeamEmailVerification({
return await deleteTeamEmailVerification({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeamMemberInvitations: authenticatedProcedure deleteTeamMemberInvitations: authenticatedProcedure
.input(ZDeleteTeamMemberInvitationsMutationSchema) .input(ZDeleteTeamMemberInvitationsMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeamMemberInvitations({
return await deleteTeamMemberInvitations({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeamMembers: authenticatedProcedure deleteTeamMembers: authenticatedProcedure
.input(ZDeleteTeamMembersMutationSchema) .input(ZDeleteTeamMembersMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeamMembers({
return await deleteTeamMembers({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeamPending: authenticatedProcedure deleteTeamPending: authenticatedProcedure
.input(ZDeleteTeamPendingMutationSchema) .input(ZDeleteTeamPendingMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeamPending({
return await deleteTeamPending({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
deleteTeamTransferRequest: authenticatedProcedure deleteTeamTransferRequest: authenticatedProcedure
.input(ZDeleteTeamTransferRequestMutationSchema) .input(ZDeleteTeamTransferRequestMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await deleteTeamTransferRequest({
return await deleteTeamTransferRequest({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
findTeamInvoices: authenticatedProcedure findTeamInvoices: authenticatedProcedure
.input(ZFindTeamInvoicesQuerySchema) .input(ZFindTeamInvoicesQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await findTeamInvoices({
return await findTeamInvoices({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
findTeamMemberInvites: authenticatedProcedure findTeamMemberInvites: authenticatedProcedure
.input(ZFindTeamMemberInvitesQuerySchema) .input(ZFindTeamMemberInvitesQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await findTeamMemberInvites({
return await findTeamMemberInvites({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
findTeamMembers: authenticatedProcedure findTeamMembers: authenticatedProcedure
.input(ZFindTeamMembersQuerySchema) .input(ZFindTeamMembersQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await findTeamMembers({
return await findTeamMembers({
userId: ctx.user.id,
...input,
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}),
findTeams: authenticatedProcedure.input(ZFindTeamsQuerySchema).query(async ({ input, ctx }) => {
try {
return await findTeams({
userId: ctx.user.id, userId: ctx.user.id,
...input, ...input,
}); });
} catch (err) { }),
console.error(err);
throw AppError.parseErrorToTRPCError(err); findTeams: authenticatedProcedure.input(ZFindTeamsQuerySchema).query(async ({ input, ctx }) => {
} return await findTeams({
userId: ctx.user.id,
...input,
});
}), }),
findTeamsPending: authenticatedProcedure findTeamsPending: authenticatedProcedure
.input(ZFindTeamsPendingQuerySchema) .input(ZFindTeamsPendingQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await findTeamsPending({
return await findTeamsPending({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
getTeam: authenticatedProcedure.input(ZGetTeamQuerySchema).query(async ({ input, ctx }) => { getTeam: authenticatedProcedure.input(ZGetTeamQuerySchema).query(async ({ input, ctx }) => {
try { return await getTeamById({ teamId: input.teamId, userId: ctx.user.id });
return await getTeamById({ teamId: input.teamId, userId: ctx.user.id });
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
getTeamEmailByEmail: authenticatedProcedure.query(async ({ ctx }) => { getTeamEmailByEmail: authenticatedProcedure.query(async ({ ctx }) => {
try { return await getTeamEmailByEmail({ email: ctx.user.email });
return await getTeamEmailByEmail({ email: ctx.user.email });
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
getTeamInvitations: authenticatedProcedure.query(async ({ ctx }) => { getTeamInvitations: authenticatedProcedure.query(async ({ ctx }) => {
try { return await getTeamInvitations({ email: ctx.user.email });
return await getTeamInvitations({ email: ctx.user.email });
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
getTeamMembers: authenticatedProcedure getTeamMembers: authenticatedProcedure
.input(ZGetTeamMembersQuerySchema) .input(ZGetTeamMembersQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await getTeamMembers({ teamId: input.teamId, userId: ctx.user.id });
return await getTeamMembers({ teamId: input.teamId, userId: ctx.user.id });
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
getTeamPrices: authenticatedProcedure.query(async () => { getTeamPrices: authenticatedProcedure.query(async () => {
try { return await getTeamPrices();
return await getTeamPrices();
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
getTeams: authenticatedProcedure.query(async ({ ctx }) => { getTeams: authenticatedProcedure.query(async ({ ctx }) => {
try { return await getTeams({ userId: ctx.user.id });
return await getTeams({ userId: ctx.user.id });
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
leaveTeam: authenticatedProcedure leaveTeam: authenticatedProcedure
.input(ZLeaveTeamMutationSchema) .input(ZLeaveTeamMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await leaveTeam({
return await leaveTeam({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
updateTeam: authenticatedProcedure updateTeam: authenticatedProcedure
.input(ZUpdateTeamMutationSchema) .input(ZUpdateTeamMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await updateTeam({
return await updateTeam({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
updateTeamEmail: authenticatedProcedure updateTeamEmail: authenticatedProcedure
.input(ZUpdateTeamEmailMutationSchema) .input(ZUpdateTeamEmailMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await updateTeamEmail({
return await updateTeamEmail({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
updateTeamMember: authenticatedProcedure updateTeamMember: authenticatedProcedure
.input(ZUpdateTeamMemberMutationSchema) .input(ZUpdateTeamMemberMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await updateTeamMember({
return await updateTeamMember({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
updateTeamPublicProfile: authenticatedProcedure updateTeamPublicProfile: authenticatedProcedure
@@ -506,7 +332,7 @@ export const teamRouter = router({
const error = AppError.parseError(err); const error = AppError.parseError(err);
if (error.code !== AppErrorCode.UNKNOWN_ERROR) { if (error.code !== AppErrorCode.UNKNOWN_ERROR) {
throw AppError.parseErrorToTRPCError(error); throw error;
} }
throw new TRPCError({ throw new TRPCError({
@@ -520,48 +346,30 @@ export const teamRouter = router({
requestTeamOwnershipTransfer: authenticatedProcedure requestTeamOwnershipTransfer: authenticatedProcedure
.input(ZRequestTeamOwnerhsipTransferMutationSchema) .input(ZRequestTeamOwnerhsipTransferMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { return await requestTeamOwnershipTransfer({
return await requestTeamOwnershipTransfer({ userId: ctx.user.id,
userId: ctx.user.id, userName: ctx.user.name ?? '',
userName: ctx.user.name ?? '', ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
resendTeamEmailVerification: authenticatedProcedure resendTeamEmailVerification: authenticatedProcedure
.input(ZResendTeamEmailVerificationMutationSchema) .input(ZResendTeamEmailVerificationMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { await resendTeamEmailVerification({
await resendTeamEmailVerification({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
resendTeamMemberInvitation: authenticatedProcedure resendTeamMemberInvitation: authenticatedProcedure
.input(ZResendTeamMemberInvitationMutationSchema) .input(ZResendTeamMemberInvitationMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { await resendTeamMemberInvitation({
await resendTeamMemberInvitation({ userId: ctx.user.id,
userId: ctx.user.id, userName: ctx.user.name ?? '',
userName: ctx.user.name ?? '', ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
updateTeamBrandingSettings: authenticatedProcedure updateTeamBrandingSettings: authenticatedProcedure
@@ -569,17 +377,11 @@ export const teamRouter = router({
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
const { teamId, settings } = input; const { teamId, settings } = input;
try { return await updateTeamBrandingSettings({
return await updateTeamBrandingSettings({ userId: ctx.user.id,
userId: ctx.user.id, teamId,
teamId, settings,
settings, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
updateTeamDocumentSettings: authenticatedProcedure updateTeamDocumentSettings: authenticatedProcedure
@@ -587,16 +389,10 @@ export const teamRouter = router({
.mutation(async ({ ctx, input }) => { .mutation(async ({ ctx, input }) => {
const { teamId, settings } = input; const { teamId, settings } = input;
try { return await updateTeamDocumentSettings({
return await updateTeamDocumentSettings({ userId: ctx.user.id,
userId: ctx.user.id, teamId,
teamId, settings,
settings, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
}); });

View File

@@ -42,323 +42,214 @@ export const templateRouter = router({
createTemplate: authenticatedProcedure createTemplate: authenticatedProcedure
.input(ZCreateTemplateMutationSchema) .input(ZCreateTemplateMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { teamId, title, templateDocumentDataId } = input;
const { teamId, title, templateDocumentDataId } = input;
return await createTemplate({ return await createTemplate({
userId: ctx.user.id, userId: ctx.user.id,
teamId, teamId,
title, title,
templateDocumentDataId, templateDocumentDataId,
}); });
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to create this template. Please try again later.',
});
}
}), }),
createDocumentFromDirectTemplate: maybeAuthenticatedProcedure createDocumentFromDirectTemplate: maybeAuthenticatedProcedure
.input(ZCreateDocumentFromDirectTemplateMutationSchema) .input(ZCreateDocumentFromDirectTemplateMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const {
const { directRecipientName,
directRecipientName, directRecipientEmail,
directRecipientEmail, directTemplateToken,
directTemplateToken, directTemplateExternalId,
directTemplateExternalId, signedFieldValues,
signedFieldValues, templateUpdatedAt,
templateUpdatedAt, } = input;
} = input;
const requestMetadata = extractNextApiRequestMetadata(ctx.req); const requestMetadata = extractNextApiRequestMetadata(ctx.req);
return await createDocumentFromDirectTemplate({ return await createDocumentFromDirectTemplate({
directRecipientName, directRecipientName,
directRecipientEmail, directRecipientEmail,
directTemplateToken, directTemplateToken,
directTemplateExternalId, directTemplateExternalId,
signedFieldValues, signedFieldValues,
templateUpdatedAt, templateUpdatedAt,
user: ctx.user user: ctx.user
? { ? {
id: ctx.user.id, id: ctx.user.id,
name: ctx.user.name || undefined, name: ctx.user.name || undefined,
email: ctx.user.email, email: ctx.user.email,
} }
: undefined, : undefined,
requestMetadata, requestMetadata,
}); });
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createDocumentFromTemplate: authenticatedProcedure createDocumentFromTemplate: authenticatedProcedure
.input(ZCreateDocumentFromTemplateMutationSchema) .input(ZCreateDocumentFromTemplateMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId, teamId, recipients } = input;
const { templateId, teamId, recipients } = input;
const limits = await getServerLimits({ email: ctx.user.email, teamId }); const limits = await getServerLimits({ email: ctx.user.email, teamId });
if (limits.remaining.documents === 0) { if (limits.remaining.documents === 0) {
throw new Error('You have reached your document limit.'); throw new Error('You have reached your document limit.');
}
const requestMetadata = extractNextApiRequestMetadata(ctx.req);
let document: Document = await createDocumentFromTemplate({
templateId,
teamId,
userId: ctx.user.id,
recipients,
requestMetadata,
});
if (input.distributeDocument) {
document = await sendDocument({
documentId: document.id,
userId: ctx.user.id,
teamId,
requestMetadata,
}).catch((err) => {
console.error(err);
throw new AppError('DOCUMENT_SEND_FAILED');
});
}
return document;
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
} }
const requestMetadata = extractNextApiRequestMetadata(ctx.req);
let document: Document = await createDocumentFromTemplate({
templateId,
teamId,
userId: ctx.user.id,
recipients,
requestMetadata,
});
if (input.distributeDocument) {
document = await sendDocument({
documentId: document.id,
userId: ctx.user.id,
teamId,
requestMetadata,
}).catch((err) => {
console.error(err);
throw new AppError('DOCUMENT_SEND_FAILED');
});
}
return document;
}), }),
duplicateTemplate: authenticatedProcedure duplicateTemplate: authenticatedProcedure
.input(ZDuplicateTemplateMutationSchema) .input(ZDuplicateTemplateMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { teamId, templateId } = input;
const { teamId, templateId } = input;
return await duplicateTemplate({ return await duplicateTemplate({
userId: ctx.user.id, userId: ctx.user.id,
teamId, teamId,
templateId, templateId,
}); });
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to duplicate the template. Please try again later.',
});
}
}), }),
deleteTemplate: authenticatedProcedure deleteTemplate: authenticatedProcedure
.input(ZDeleteTemplateMutationSchema) .input(ZDeleteTemplateMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { id, teamId } = input;
const { id, teamId } = input;
const userId = ctx.user.id; const userId = ctx.user.id;
return await deleteTemplate({ userId, id, teamId }); return await deleteTemplate({ userId, id, teamId });
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to delete this template. Please try again later.',
});
}
}), }),
getTemplateWithDetailsById: authenticatedProcedure getTemplateWithDetailsById: authenticatedProcedure
.input(ZGetTemplateWithDetailsByIdQuerySchema) .input(ZGetTemplateWithDetailsByIdQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await getTemplateWithDetailsById({
return await getTemplateWithDetailsById({ id: input.id,
id: input.id, userId: ctx.user.id,
userId: ctx.user.id, });
});
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to find this template. Please try again later.',
});
}
}), }),
// Todo: Add API // Todo: Add API
updateTemplateSettings: authenticatedProcedure updateTemplateSettings: authenticatedProcedure
.input(ZUpdateTemplateSettingsMutationSchema) .input(ZUpdateTemplateSettingsMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId, teamId, data, meta } = input;
const { templateId, teamId, data, meta } = input;
const userId = ctx.user.id; const userId = ctx.user.id;
const requestMetadata = extractNextApiRequestMetadata(ctx.req); const requestMetadata = extractNextApiRequestMetadata(ctx.req);
return await updateTemplateSettings({ return await updateTemplateSettings({
userId, userId,
teamId, teamId,
templateId, templateId,
data, data,
meta: { meta: {
...meta, ...meta,
language: isValidLanguageCode(meta?.language) ? meta?.language : undefined, language: isValidLanguageCode(meta?.language) ? meta?.language : undefined,
}, },
requestMetadata, requestMetadata,
}); });
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update the settings for this template. Please try again later.',
});
}
}), }),
setSigningOrderForTemplate: authenticatedProcedure setSigningOrderForTemplate: authenticatedProcedure
.input(ZSetSigningOrderForTemplateMutationSchema) .input(ZSetSigningOrderForTemplateMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId, teamId, signingOrder } = input;
const { templateId, teamId, signingOrder } = input;
return await updateTemplateSettings({ return await updateTemplateSettings({
templateId, templateId,
teamId, teamId,
data: {}, data: {},
meta: { signingOrder }, meta: { signingOrder },
userId: ctx.user.id, userId: ctx.user.id,
requestMetadata: extractNextApiRequestMetadata(ctx.req), requestMetadata: extractNextApiRequestMetadata(ctx.req),
}); });
} catch (err) {
console.error(err);
throw new TRPCError({
code: 'BAD_REQUEST',
message:
'We were unable to update the settings for this document. Please try again later.',
});
}
}), }),
findTemplates: authenticatedProcedure findTemplates: authenticatedProcedure
.input(ZFindTemplatesQuerySchema) .input(ZFindTemplatesQuerySchema)
.query(async ({ input, ctx }) => { .query(async ({ input, ctx }) => {
try { return await findTemplates({
return await findTemplates({ userId: ctx.user.id,
userId: ctx.user.id, ...input,
...input, });
});
} catch (err) {
console.error(err);
throw AppError.parseErrorToTRPCError(err);
}
}), }),
createTemplateDirectLink: authenticatedProcedure createTemplateDirectLink: authenticatedProcedure
.input(ZCreateTemplateDirectLinkMutationSchema) .input(ZCreateTemplateDirectLinkMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId, teamId, directRecipientId } = input;
const { templateId, teamId, directRecipientId } = input;
const userId = ctx.user.id; const userId = ctx.user.id;
const template = await getTemplateById({ id: templateId, teamId, userId: ctx.user.id }); const template = await getTemplateById({ id: templateId, teamId, userId: ctx.user.id });
const limits = await getServerLimits({ email: ctx.user.email, teamId: template.teamId }); const limits = await getServerLimits({ email: ctx.user.email, teamId: template.teamId });
if (limits.remaining.directTemplates === 0) { if (limits.remaining.directTemplates === 0) {
throw new AppError( throw new AppError(AppErrorCode.LIMIT_EXCEEDED, {
AppErrorCode.LIMIT_EXCEEDED, message: 'You have reached your direct templates limit.',
'You have reached your direct templates limit.', });
);
}
return await createTemplateDirectLink({ userId, templateId, directRecipientId });
} catch (err) {
console.error(err);
const error = AppError.parseError(err);
throw AppError.parseErrorToTRPCError(error);
} }
return await createTemplateDirectLink({ userId, templateId, directRecipientId });
}), }),
deleteTemplateDirectLink: authenticatedProcedure deleteTemplateDirectLink: authenticatedProcedure
.input(ZDeleteTemplateDirectLinkMutationSchema) .input(ZDeleteTemplateDirectLinkMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId } = input;
const { templateId } = input;
const userId = ctx.user.id; const userId = ctx.user.id;
return await deleteTemplateDirectLink({ userId, templateId }); return await deleteTemplateDirectLink({ userId, templateId });
} catch (err) {
console.error(err);
const error = AppError.parseError(err);
throw AppError.parseErrorToTRPCError(error);
}
}), }),
toggleTemplateDirectLink: authenticatedProcedure toggleTemplateDirectLink: authenticatedProcedure
.input(ZToggleTemplateDirectLinkMutationSchema) .input(ZToggleTemplateDirectLinkMutationSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId, enabled } = input;
const { templateId, enabled } = input;
const userId = ctx.user.id; const userId = ctx.user.id;
return await toggleTemplateDirectLink({ userId, templateId, enabled }); return await toggleTemplateDirectLink({ userId, templateId, enabled });
} catch (err) {
console.error(err);
const error = AppError.parseError(err);
throw AppError.parseErrorToTRPCError(error);
}
}), }),
moveTemplateToTeam: authenticatedProcedure moveTemplateToTeam: authenticatedProcedure
.input(ZMoveTemplatesToTeamSchema) .input(ZMoveTemplatesToTeamSchema)
.mutation(async ({ input, ctx }) => { .mutation(async ({ input, ctx }) => {
try { const { templateId, teamId } = input;
const { templateId, teamId } = input; const userId = ctx.user.id;
const userId = ctx.user.id;
return await moveTemplateToTeam({ return await moveTemplateToTeam({
templateId, templateId,
teamId, teamId,
userId, userId,
}); });
} catch (err) {
console.error(err);
if (err instanceof TRPCError) {
throw err;
}
throw new TRPCError({
code: 'BAD_REQUEST',
message: 'We were unable to move this template. Please try again later.',
});
}
}), }),
updateTemplateTypedSignatureSettings: authenticatedProcedure updateTemplateTypedSignatureSettings: authenticatedProcedure

View File

@@ -1,12 +1,37 @@
import { TRPCError, initTRPC } from '@trpc/server'; import { TRPCError, initTRPC } from '@trpc/server';
import SuperJSON from 'superjson'; import SuperJSON from 'superjson';
import { AppError, genericErrorCodeToTrpcErrorCodeMap } from '@documenso/lib/errors/app-error';
import { isAdmin } from '@documenso/lib/next-auth/guards/is-admin'; import { isAdmin } from '@documenso/lib/next-auth/guards/is-admin';
import type { TrpcContext } from './context'; import type { TrpcContext } from './context';
const t = initTRPC.context<TrpcContext>().create({ const t = initTRPC.context<TrpcContext>().create({
transformer: SuperJSON, transformer: SuperJSON,
errorFormatter(opts) {
const { shape, error } = opts;
const originalError = error.cause;
let data: Record<string, unknown> = shape.data;
if (originalError instanceof AppError) {
data = {
...data,
appError: AppError.toJSON(originalError),
code: originalError.code,
httpStatus:
originalError.statusCode ??
genericErrorCodeToTrpcErrorCodeMap[originalError.code]?.status ??
500,
};
}
return {
...shape,
data,
};
},
}); });
/** /**

View File

@@ -98,7 +98,7 @@ export const twoFactorAuthenticationRouter = router({
console.error(err); console.error(err);
} }
throw AppError.parseErrorToTRPCError(err); throw error;
} }
}), }),
}); });

View File

@@ -88,6 +88,8 @@ declare namespace NodeJS {
NEXT_PRIVATE_INNGEST_APP_ID?: string; NEXT_PRIVATE_INNGEST_APP_ID?: string;
NEXT_PRIVATE_INNGEST_EVENT_KEY?: string; NEXT_PRIVATE_INNGEST_EVENT_KEY?: string;
NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY?: string;
/** /**
* Vercel environment variables * Vercel environment variables
*/ */

View File

@@ -114,6 +114,7 @@
"NEXT_PRIVATE_TRIGGER_API_KEY", "NEXT_PRIVATE_TRIGGER_API_KEY",
"NEXT_PRIVATE_TRIGGER_API_URL", "NEXT_PRIVATE_TRIGGER_API_URL",
"NEXT_PRIVATE_INNGEST_APP_ID", "NEXT_PRIVATE_INNGEST_APP_ID",
"NEXT_PRIVATE_LOGGER_HONEY_BADGER_API_KEY",
"INNGEST_EVENT_KEY", "INNGEST_EVENT_KEY",
"NEXT_PRIVATE_INNGEST_EVENT_KEY", "NEXT_PRIVATE_INNGEST_EVENT_KEY",
"CI", "CI",