mirror of
https://github.com/documenso/documenso.git
synced 2025-11-10 04:22:32 +10:00
Compare commits
9 Commits
d2a009d52e
...
feat/save-
| Author | SHA1 | Date | |
|---|---|---|---|
| bb7732a203 | |||
| 7ea7740b88 | |||
| ced583a525 | |||
| ca0e96d4c0 | |||
| 1d73a0f9e6 | |||
| 479131822e | |||
| b885aae511 | |||
| da9287440b | |||
| bed8cbd651 |
4
apps/marketing/process-env.d.ts
vendored
4
apps/marketing/process-env.d.ts
vendored
@ -2,8 +2,8 @@ declare namespace NodeJS {
|
||||
export interface ProcessEnv {
|
||||
NEXT_PUBLIC_WEBAPP_URL?: string;
|
||||
NEXT_PUBLIC_MARKETING_URL?: string;
|
||||
NEXT_PRIVATE_INTERNAL_WEBAPP_URL?:string;
|
||||
|
||||
NEXT_PRIVATE_INTERNAL_WEBAPP_URL?: string;
|
||||
|
||||
NEXT_PRIVATE_DATABASE_URL: string;
|
||||
|
||||
NEXT_PUBLIC_STRIPE_COMMUNITY_PLAN_MONTHLY_PRICE_ID: string;
|
||||
|
||||
2
apps/web/process-env.d.ts
vendored
2
apps/web/process-env.d.ts
vendored
@ -2,7 +2,7 @@ declare namespace NodeJS {
|
||||
export interface ProcessEnv {
|
||||
NEXT_PUBLIC_WEBAPP_URL?: string;
|
||||
NEXT_PUBLIC_MARKETING_URL?: string;
|
||||
NEXT_PRIVATE_INTERNAL_WEBAPP_URL?:string;
|
||||
NEXT_PRIVATE_INTERNAL_WEBAPP_URL?: string;
|
||||
|
||||
NEXT_PRIVATE_DATABASE_URL: string;
|
||||
|
||||
|
||||
@ -349,11 +349,13 @@ export const EditDocumentForm = ({
|
||||
<AddSignersFormPartial
|
||||
key={recipients.length}
|
||||
documentFlow={documentFlow.signers}
|
||||
document={document}
|
||||
recipients={recipients}
|
||||
fields={fields}
|
||||
isDocumentEnterprise={isDocumentEnterprise}
|
||||
onSubmit={onAddSignersFormSubmit}
|
||||
isDocumentPdfLoaded={isDocumentPdfLoaded}
|
||||
teamId={team?.id}
|
||||
/>
|
||||
|
||||
<AddFieldsFormPartial
|
||||
|
||||
@ -266,6 +266,7 @@ export const EditTemplateForm = ({
|
||||
onSubmit={onAddTemplatePlaceholderFormSubmit}
|
||||
isEnterprise={isEnterprise}
|
||||
isDocumentPdfLoaded={isDocumentPdfLoaded}
|
||||
template={template}
|
||||
/>
|
||||
|
||||
<AddTemplateFieldsFormPartial
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const ZBaseEmbedDataSchema = z.object({
|
||||
css: z.string().optional().transform(value => value || undefined),
|
||||
css: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((value) => value || undefined),
|
||||
});
|
||||
|
||||
@ -18,15 +18,18 @@ export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentComplet
|
||||
|
||||
<div className="mt-8 w-full max-w-md">
|
||||
<SigningCard3D
|
||||
className='w-full mx-auto'
|
||||
className="mx-auto w-full"
|
||||
name={name || 'Documenso'}
|
||||
signature={signature}
|
||||
signingCelebrationImage={signingCelebration}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<p className="mt-8 max-w-[50ch] text-center text-muted-foreground text-sm">
|
||||
<Trans>The document is now completed, please follow any instructions provided within the parent application.</Trans>
|
||||
<p className="text-muted-foreground mt-8 max-w-[50ch] text-center text-sm">
|
||||
<Trans>
|
||||
The document is now completed, please follow any instructions provided within the parent
|
||||
application.
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -6,6 +6,7 @@ import { useSearchParams } from 'next/navigation';
|
||||
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { LucideChevronDown, LucideChevronUp } from 'lucide-react';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { useThrottleFn } from '@documenso/lib/client-only/hooks/use-throttle-fn';
|
||||
@ -14,7 +15,7 @@ import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { DEFAULT_DOCUMENT_TIME_ZONE } from '@documenso/lib/constants/time-zones';
|
||||
import { validateFieldsInserted } from '@documenso/lib/utils/fields';
|
||||
import type { DocumentMeta, Recipient, TemplateMeta } from '@documenso/prisma/client';
|
||||
import { FieldType, type DocumentData, type Field } from '@documenso/prisma/client';
|
||||
import { type DocumentData, type Field, FieldType } from '@documenso/prisma/client';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import type {
|
||||
TRemovedSignedFieldWithTokenMutationSchema,
|
||||
@ -34,7 +35,6 @@ import type { DirectTemplateLocalField } from '~/app/(recipient)/d/[token]/sign-
|
||||
import { useRequiredSigningContext } from '~/app/(signing)/sign/[token]/provider';
|
||||
import { Logo } from '~/components/branding/logo';
|
||||
|
||||
import { LucideChevronDown, LucideChevronUp } from 'lucide-react';
|
||||
import { EmbedClientLoading } from '../../client-loading';
|
||||
import { EmbedDocumentCompleted } from '../../completed';
|
||||
import { EmbedDocumentFields } from '../../document-fields';
|
||||
@ -307,7 +307,7 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
<div className="relative mx-auto flex min-h-[100dvh] max-w-screen-lg flex-col items-center justify-center p-6">
|
||||
{(!hasFinishedInit || !hasDocumentLoaded) && <EmbedClientLoading />}
|
||||
|
||||
<div className="relative flex flex-col md:flex-row w-full gap-x-6 gap-y-12">
|
||||
<div className="relative flex w-full flex-col gap-x-6 gap-y-12 md:flex-row">
|
||||
{/* Viewer */}
|
||||
<div className="flex-1">
|
||||
<LazyPDFViewer
|
||||
@ -318,26 +318,26 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
|
||||
{/* Widget */}
|
||||
<div
|
||||
className="group/document-widget fixed md:sticky md:top-4 left-0 w-full bottom-8 px-6 md:px-0 z-50 md:z-auto md:w-[350px] flex-shrink-0 h-fit"
|
||||
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
|
||||
data-expanded={isExpanded || undefined}
|
||||
>
|
||||
<div className="w-full border-border bg-widget flex md:min-h-[min(calc(100dvh-2rem),48rem)] h-fit flex-col rounded-xl border px-4 py-4 md:py-6">
|
||||
<div className="border-border bg-widget flex h-fit w-full flex-col rounded-xl border px-4 py-4 md:min-h-[min(calc(100dvh-2rem),48rem)] md:py-6">
|
||||
{/* Header */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between gap-x-2">
|
||||
<h3 className="text-foreground text-xl md:text-2xl font-semibold">
|
||||
<h3 className="text-foreground text-xl font-semibold md:text-2xl">
|
||||
<Trans>Sign document</Trans>
|
||||
</h3>
|
||||
|
||||
<Button variant="outline" className="h-8 w-8 p-0 md:hidden">
|
||||
{isExpanded ? (
|
||||
<LucideChevronDown
|
||||
className="h-5 w-5 text-muted-foreground"
|
||||
className="text-muted-foreground h-5 w-5"
|
||||
onClick={() => setIsExpanded(false)}
|
||||
/>
|
||||
) : (
|
||||
<LucideChevronUp
|
||||
className="h-5 w-5 text-muted-foreground"
|
||||
className="text-muted-foreground h-5 w-5"
|
||||
onClick={() => setIsExpanded(true)}
|
||||
/>
|
||||
)}
|
||||
@ -354,7 +354,7 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<div className="-mx-2 px-2 hidden group-data-[expanded]/document-widget:block md:block">
|
||||
<div className="-mx-2 hidden px-2 group-data-[expanded]/document-widget:block md:block">
|
||||
<div className="flex flex-1 flex-col gap-y-4">
|
||||
<div>
|
||||
<Label htmlFor="full-name">
|
||||
@ -408,9 +408,9 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 hidden group-data-[expanded]/document-widget:block md:block" />
|
||||
<div className="hidden flex-1 group-data-[expanded]/document-widget:block md:block" />
|
||||
|
||||
<div className="w-full grid-cols-2 items-center mt-4 hidden group-data-[expanded]/document-widget:grid md:grid">
|
||||
<div className="mt-4 hidden w-full grid-cols-2 items-center group-data-[expanded]/document-widget:grid md:grid">
|
||||
{pendingFields.length > 0 ? (
|
||||
<Button className="col-start-2" onClick={() => onNextFieldClick()}>
|
||||
<Trans>Next</Trans>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
export default function EmbedDirectTemplateNotFound() {
|
||||
return <div>Not Found</div>
|
||||
return <div>Not Found</div>;
|
||||
}
|
||||
|
||||
@ -73,11 +73,7 @@ export default async function EmbedDirectTemplatePage({ params }: EmbedDirectTem
|
||||
const fields = template.Field.filter((field) => field.recipientId === directTemplateRecipientId);
|
||||
|
||||
return (
|
||||
<SigningProvider
|
||||
email={user?.email}
|
||||
fullName={user?.name}
|
||||
signature={user?.signature}
|
||||
>
|
||||
<SigningProvider email={user?.email} fullName={user?.name} signature={user?.signature}>
|
||||
<DocumentAuthProvider
|
||||
documentAuthOptions={template.authOptions}
|
||||
recipient={recipient}
|
||||
|
||||
@ -13,7 +13,7 @@ import {
|
||||
ZTextFieldMeta,
|
||||
} from '@documenso/lib/types/field-meta';
|
||||
import type { DocumentMeta, Recipient, TemplateMeta } from '@documenso/prisma/client';
|
||||
import { FieldType, type Field } from '@documenso/prisma/client';
|
||||
import { type Field, FieldType } from '@documenso/prisma/client';
|
||||
import type { FieldWithSignatureAndFieldMeta } from '@documenso/prisma/types/field-with-signature-and-fieldmeta';
|
||||
import type {
|
||||
TRemovedSignedFieldWithTokenMutationSchema,
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
export const EmbedPaywall = () => {
|
||||
return <div>
|
||||
<h1>Paywall</h1>
|
||||
</div>
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<h1>Paywall</h1>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { LucideChevronDown, LucideChevronUp } from 'lucide-react';
|
||||
|
||||
import { useThrottleFn } from '@documenso/lib/client-only/hooks/use-throttle-fn';
|
||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { validateFieldsInserted } from '@documenso/lib/utils/fields';
|
||||
import type { DocumentMeta, Recipient, TemplateMeta } from '@documenso/prisma/client';
|
||||
import { type DocumentData, type Field } from '@documenso/prisma/client';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||
@ -20,9 +22,9 @@ import { LazyPDFViewer } from '@documenso/ui/primitives/lazy-pdf-viewer';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { LucideChevronDown, LucideChevronUp } from 'lucide-react';
|
||||
import { useRequiredSigningContext } from '~/app/(signing)/sign/[token]/provider';
|
||||
import { Logo } from '~/components/branding/logo';
|
||||
|
||||
import { EmbedClientLoading } from '../../client-loading';
|
||||
import { EmbedDocumentCompleted } from '../../completed';
|
||||
import { EmbedDocumentFields } from '../../document-fields';
|
||||
@ -185,7 +187,7 @@ export const EmbedSignDocumentClientPage = ({
|
||||
<div className="relative mx-auto flex min-h-[100dvh] max-w-screen-lg flex-col items-center justify-center p-6">
|
||||
{(!hasFinishedInit || !hasDocumentLoaded) && <EmbedClientLoading />}
|
||||
|
||||
<div className="relative flex flex-col md:flex-row w-full gap-x-6 gap-y-12">
|
||||
<div className="relative flex w-full flex-col gap-x-6 gap-y-12 md:flex-row">
|
||||
{/* Viewer */}
|
||||
<div className="flex-1">
|
||||
<LazyPDFViewer
|
||||
@ -196,26 +198,26 @@ export const EmbedSignDocumentClientPage = ({
|
||||
|
||||
{/* Widget */}
|
||||
<div
|
||||
className="group/document-widget fixed md:sticky md:top-4 left-0 w-full bottom-8 px-6 md:px-0 z-50 md:z-auto md:w-[350px] flex-shrink-0 h-fit"
|
||||
className="group/document-widget fixed bottom-8 left-0 z-50 h-fit w-full flex-shrink-0 px-6 md:sticky md:top-4 md:z-auto md:w-[350px] md:px-0"
|
||||
data-expanded={isExpanded || undefined}
|
||||
>
|
||||
<div className="w-full border-border bg-widget flex flex-col rounded-xl border px-4 py-4 md:py-6">
|
||||
<div className="border-border bg-widget flex w-full flex-col rounded-xl border px-4 py-4 md:py-6">
|
||||
{/* Header */}
|
||||
<div>
|
||||
<div className="flex items-center justify-between gap-x-2">
|
||||
<h3 className="text-foreground text-xl md:text-2xl font-semibold">
|
||||
<h3 className="text-foreground text-xl font-semibold md:text-2xl">
|
||||
<Trans>Sign document</Trans>
|
||||
</h3>
|
||||
|
||||
<Button variant="outline" className="h-8 w-8 p-0 md:hidden">
|
||||
{isExpanded ? (
|
||||
<LucideChevronDown
|
||||
className="h-5 w-5 text-muted-foreground"
|
||||
className="text-muted-foreground h-5 w-5"
|
||||
onClick={() => setIsExpanded(false)}
|
||||
/>
|
||||
) : (
|
||||
<LucideChevronUp
|
||||
className="h-5 w-5 text-muted-foreground"
|
||||
className="text-muted-foreground h-5 w-5"
|
||||
onClick={() => setIsExpanded(true)}
|
||||
/>
|
||||
)}
|
||||
@ -232,7 +234,7 @@ export const EmbedSignDocumentClientPage = ({
|
||||
</div>
|
||||
|
||||
{/* Form */}
|
||||
<div className="-mx-2 px-2 hidden group-data-[expanded]/document-widget:block md:block">
|
||||
<div className="-mx-2 hidden px-2 group-data-[expanded]/document-widget:block md:block">
|
||||
<div className="flex flex-1 flex-col gap-y-4">
|
||||
<div>
|
||||
<Label htmlFor="full-name">
|
||||
@ -285,9 +287,9 @@ export const EmbedSignDocumentClientPage = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 hidden group-data-[expanded]/document-widget:block md:block" />
|
||||
<div className="hidden flex-1 group-data-[expanded]/document-widget:block md:block" />
|
||||
|
||||
<div className="w-full grid-cols-2 items-center mt-4 hidden group-data-[expanded]/document-widget:grid md:grid">
|
||||
<div className="mt-4 hidden w-full grid-cols-2 items-center group-data-[expanded]/document-widget:grid md:grid">
|
||||
{pendingFields.length > 0 ? (
|
||||
<Button className="col-start-2" onClick={() => onNextFieldClick()}>
|
||||
<Trans>Next</Trans>
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
export default function EmbedDirectTemplateNotFound() {
|
||||
return <div>Not Found</div>
|
||||
return <div>Not Found</div>;
|
||||
}
|
||||
|
||||
@ -4,8 +4,12 @@ import { match } from 'ts-pattern';
|
||||
|
||||
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
|
||||
import { getServerComponentSession } from '@documenso/lib/next-auth/get-server-component-session';
|
||||
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
|
||||
import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token';
|
||||
import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token';
|
||||
import { DocumentAccessAuth } from '@documenso/lib/types/document-auth';
|
||||
import { extractDocumentAuthMethods } from '@documenso/lib/utils/document-auth';
|
||||
import { DocumentStatus } from '@documenso/prisma/client';
|
||||
|
||||
import { DocumentAuthProvider } from '~/app/(signing)/sign/[token]/document-auth-provider';
|
||||
import { SigningProvider } from '~/app/(signing)/sign/[token]/provider';
|
||||
@ -13,10 +17,6 @@ import { SigningProvider } from '~/app/(signing)/sign/[token]/provider';
|
||||
import { EmbedAuthenticateView } from '../../authenticate';
|
||||
import { EmbedPaywall } from '../../paywall';
|
||||
import { EmbedSignDocumentClientPage } from './client';
|
||||
import { getFieldsForToken } from '@documenso/lib/server-only/field/get-fields-for-token';
|
||||
import { getRecipientByToken } from '@documenso/lib/server-only/recipient/get-recipient-by-token';
|
||||
import { getDocumentAndSenderByToken } from '@documenso/lib/server-only/document/get-document-by-token';
|
||||
import { DocumentStatus } from '@documenso/prisma/client';
|
||||
|
||||
export type EmbedSignDocumentPageProps = {
|
||||
params: {
|
||||
@ -66,7 +66,12 @@ export default async function EmbedSignDocumentPage({ params }: EmbedSignDocumen
|
||||
.exhaustive();
|
||||
|
||||
if (!isAccessAuthValid) {
|
||||
return <EmbedAuthenticateView email={user?.email || recipient.email} returnTo={`/embed/direct/${token}`} />;
|
||||
return (
|
||||
<EmbedAuthenticateView
|
||||
email={user?.email || recipient.email}
|
||||
returnTo={`/embed/direct/${token}`}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@ -81,7 +81,7 @@ async function middleware(req: NextRequest): Promise<NextResponse> {
|
||||
// Allow third parties to iframe the document.
|
||||
res.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||
res.headers.set('Access-Control-Allow-Origin', '*');
|
||||
res.headers.set('Content-Security-Policy', "frame-ancestors *");
|
||||
res.headers.set('Content-Security-Policy', 'frame-ancestors *');
|
||||
res.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||
res.headers.set('X-Content-Type-Options', 'nosniff');
|
||||
res.headers.set('X-Frame-Options', 'ALLOW-ALL');
|
||||
|
||||
@ -3,19 +3,19 @@ import { useCallback, useRef, useState } from 'react';
|
||||
type ThrottleOptions = {
|
||||
leading?: boolean;
|
||||
trailing?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export function useThrottleFn<T extends (...args: unknown[]) => unknown>(
|
||||
fn: T,
|
||||
ms = 500,
|
||||
options: ThrottleOptions = {}
|
||||
options: ThrottleOptions = {},
|
||||
): [(...args: Parameters<T>) => void, boolean, () => void] {
|
||||
const [isThrottling, setIsThrottling] = useState(false);
|
||||
const $isThrottling = useRef(false);
|
||||
|
||||
const $timeout = useRef<NodeJS.Timeout | null>(null);
|
||||
const $lastArgs = useRef<Parameters<T> | null>(null);
|
||||
|
||||
|
||||
const { leading = true, trailing = true } = options;
|
||||
|
||||
const $setIsThrottling = useCallback((value: boolean) => {
|
||||
@ -44,7 +44,7 @@ export function useThrottleFn<T extends (...args: unknown[]) => unknown>(
|
||||
$lastArgs.current = args;
|
||||
}
|
||||
},
|
||||
[fn, ms, leading, trailing, $setIsThrottling]
|
||||
[fn, ms, leading, trailing, $setIsThrottling],
|
||||
);
|
||||
|
||||
const cancel = useCallback(() => {
|
||||
|
||||
@ -5,7 +5,8 @@ export const APP_DOCUMENT_UPLOAD_SIZE_LIMIT =
|
||||
|
||||
export const NEXT_PUBLIC_WEBAPP_URL = () => env('NEXT_PUBLIC_WEBAPP_URL');
|
||||
export const NEXT_PUBLIC_MARKETING_URL = () => env('NEXT_PUBLIC_MARKETING_URL');
|
||||
export const NEXT_PRIVATE_INTERNAL_WEBAPP_URL = process.env.NEXT_PRIVATE_INTERNAL_WEBAPP_URL ?? NEXT_PUBLIC_WEBAPP_URL();
|
||||
export const NEXT_PRIVATE_INTERNAL_WEBAPP_URL =
|
||||
process.env.NEXT_PRIVATE_INTERNAL_WEBAPP_URL ?? NEXT_PUBLIC_WEBAPP_URL();
|
||||
|
||||
export const IS_APP_MARKETING = process.env.NEXT_PUBLIC_PROJECT === 'marketing';
|
||||
export const IS_APP_WEB = process.env.NEXT_PUBLIC_PROJECT === 'web';
|
||||
|
||||
@ -5,7 +5,11 @@ import { getToken } from 'next-auth/jwt';
|
||||
import { LOCAL_FEATURE_FLAGS } from '@documenso/lib/constants/feature-flags';
|
||||
import PostHogServerClient from '@documenso/lib/server-only/feature-flags/get-post-hog-server-client';
|
||||
|
||||
import { NEXT_PUBLIC_MARKETING_URL, NEXT_PUBLIC_WEBAPP_URL, NEXT_PRIVATE_INTERNAL_WEBAPP_URL } from '../../constants/app';
|
||||
import {
|
||||
NEXT_PRIVATE_INTERNAL_WEBAPP_URL,
|
||||
NEXT_PUBLIC_MARKETING_URL,
|
||||
NEXT_PUBLIC_WEBAPP_URL,
|
||||
} from '../../constants/app';
|
||||
import { extractDistinctUserId, mapJwtToFlagProperties } from './get';
|
||||
|
||||
/**
|
||||
|
||||
@ -7,7 +7,11 @@ import { getToken } from 'next-auth/jwt';
|
||||
import { LOCAL_FEATURE_FLAGS, extractPostHogConfig } from '@documenso/lib/constants/feature-flags';
|
||||
import PostHogServerClient from '@documenso/lib/server-only/feature-flags/get-post-hog-server-client';
|
||||
|
||||
import { NEXT_PUBLIC_MARKETING_URL, NEXT_PUBLIC_WEBAPP_URL, NEXT_PRIVATE_INTERNAL_WEBAPP_URL } from '../../constants/app';
|
||||
import {
|
||||
NEXT_PRIVATE_INTERNAL_WEBAPP_URL,
|
||||
NEXT_PUBLIC_MARKETING_URL,
|
||||
NEXT_PUBLIC_WEBAPP_URL,
|
||||
} from '../../constants/app';
|
||||
|
||||
/**
|
||||
* Evaluate a single feature flag based on the current user if possible.
|
||||
@ -67,7 +71,7 @@ export default async function handleFeatureFlagGet(req: Request) {
|
||||
if (origin.startsWith(NEXT_PUBLIC_MARKETING_URL() ?? 'http://localhost:3001')) {
|
||||
res.headers.set('Access-Control-Allow-Origin', origin);
|
||||
}
|
||||
|
||||
|
||||
if (origin.startsWith(NEXT_PRIVATE_INTERNAL_WEBAPP_URL ?? 'http://localhost:3000')) {
|
||||
res.headers.set('Access-Control-Allow-Origin', origin);
|
||||
}
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import { SendStatus } from '@documenso/prisma/client';
|
||||
|
||||
export type DeleteRecipientForTemplateOptions = {
|
||||
templateId: number;
|
||||
recipientId: number;
|
||||
userId: number;
|
||||
teamId?: number;
|
||||
};
|
||||
|
||||
export const deleteRecipientFromTemplate = async ({
|
||||
templateId,
|
||||
recipientId,
|
||||
userId,
|
||||
teamId,
|
||||
}: DeleteRecipientForTemplateOptions) => {
|
||||
const recipient = await prisma.recipient.findFirst({
|
||||
where: {
|
||||
id: recipientId,
|
||||
Template: {
|
||||
id: templateId,
|
||||
...(teamId
|
||||
? {
|
||||
team: {
|
||||
id: teamId,
|
||||
members: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
: {
|
||||
userId,
|
||||
teamId: null,
|
||||
}),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!recipient) {
|
||||
throw new Error('Recipient not found');
|
||||
}
|
||||
|
||||
if (recipient.sendStatus !== SendStatus.NOT_SENT) {
|
||||
throw new Error('Can not delete a recipient that has already been sent a document');
|
||||
}
|
||||
|
||||
return await prisma.recipient.delete({
|
||||
where: {
|
||||
id: recipient.id,
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -1,12 +1,12 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2024-07-24 13:01+1000\n"
|
||||
"POT-Creation-Date: 2024-08-22 05:16+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: @lingui/cli\n"
|
||||
"Language: de\n"
|
||||
"Project-Id-Version: documenso-app\n"
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2024-09-05 06:04\n"
|
||||
"Last-Translator: \n"
|
||||
@ -82,19 +82,19 @@ msgstr "Weitere Option hinzufügen"
|
||||
msgid "Add another value"
|
||||
msgstr "Weiteren Wert hinzufügen"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:359
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:459
|
||||
msgid "Add myself"
|
||||
msgstr "Mich selbst hinzufügen"
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:369
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:450
|
||||
msgid "Add Myself"
|
||||
msgstr "Mich hinzufügen"
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:355
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:436
|
||||
msgid "Add Placeholder Recipient"
|
||||
msgstr "Platzhalterempfänger hinzufügen"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:348
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:448
|
||||
msgid "Add Signer"
|
||||
msgstr "Unterzeichner hinzufügen"
|
||||
|
||||
@ -154,8 +154,8 @@ msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:164
|
||||
msgid "Cannot remove signer"
|
||||
msgstr "Unterzeichner kann nicht entfernt werden"
|
||||
#~ msgid "Cannot remove signer"
|
||||
#~ msgstr "Unterzeichner kann nicht entfernt werden"
|
||||
|
||||
#: packages/lib/constants/recipient-roles.ts:17
|
||||
msgid "Cc"
|
||||
@ -230,7 +230,7 @@ msgstr "Datum"
|
||||
msgid "Date Format"
|
||||
msgstr "Datumsformat"
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:312
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:393
|
||||
msgid "Direct link receiver"
|
||||
msgstr "Empfänger des direkten Links"
|
||||
|
||||
@ -263,11 +263,11 @@ msgstr "Dropdown-Optionen"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-fields.tsx:776
|
||||
#: packages/ui/primitives/document-flow/add-signature.tsx:272
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:232
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:239
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:330
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:337
|
||||
#: packages/ui/primitives/template-flow/add-template-fields.tsx:632
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:210
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:217
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:296
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:303
|
||||
msgid "Email"
|
||||
msgstr "E-Mail"
|
||||
|
||||
@ -378,10 +378,10 @@ msgstr "Min"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-fields.tsx:802
|
||||
#: packages/ui/primitives/document-flow/add-signature.tsx:298
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:265
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:364
|
||||
#: packages/ui/primitives/template-flow/add-template-fields.tsx:658
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:245
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:251
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:327
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:333
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
@ -560,8 +560,8 @@ msgstr "Unterschriftenkarte teilen"
|
||||
msgid "Share the Link"
|
||||
msgstr "Link teilen"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:377
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:387
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:477
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:468
|
||||
msgid "Show advanced settings"
|
||||
msgstr "Erweiterte Einstellungen anzeigen"
|
||||
|
||||
@ -686,13 +686,13 @@ msgstr "Dieses Dokument wurde bereits an diesen Empfänger gesendet. Sie können
|
||||
msgid "This document is password protected. Please enter the password to view the document."
|
||||
msgstr "Dieses Dokument ist durch ein Passwort geschützt. Bitte geben Sie das Passwort ein, um das Dokument anzusehen."
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:315
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:396
|
||||
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
|
||||
msgstr "Dieses Feld kann nicht geändert oder gelöscht werden. Wenn Sie den direkten Link dieser Vorlage teilen oder zu Ihrem öffentlichen Profil hinzufügen, kann jeder, der darauf zugreift, seinen Namen und seine E-Mail-Adresse eingeben und die ihm zugewiesenen Felder ausfüllen."
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:165
|
||||
msgid "This signer has already received the document."
|
||||
msgstr "Dieser Unterzeichner hat das Dokument bereits erhalten."
|
||||
#~ msgid "This signer has already received the document."
|
||||
#~ msgstr "Dieser Unterzeichner hat das Dokument bereits erhalten."
|
||||
|
||||
#: packages/ui/components/recipient/recipient-action-auth-select.tsx:48
|
||||
msgid "This will override any global settings."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,38 +1,33 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2024-07-24 13:01+1000\n"
|
||||
"POT-Creation-Date: 2024-08-22 05:16+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: @lingui/cli\n"
|
||||
"Language: de\n"
|
||||
"Project-Id-Version: documenso-app\n"
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2024-09-05 06:04\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Crowdin-Project: documenso-app\n"
|
||||
"X-Crowdin-Project-ID: 694691\n"
|
||||
"X-Crowdin-Language: de\n"
|
||||
"X-Crowdin-File: marketing.po\n"
|
||||
"X-Crowdin-File-ID: 6\n"
|
||||
"Language-Team: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/blog/page.tsx:45
|
||||
msgid "{0}"
|
||||
msgstr "{0}"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:100
|
||||
msgid "5 standard documents per month"
|
||||
msgstr "5 Standarddokumente pro Monat"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:198
|
||||
msgid "5 Users Included"
|
||||
msgstr "5 Benutzer inbegriffen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:34
|
||||
msgid "A 10x better signing experience."
|
||||
msgstr "Eine 10x bessere Signaturerfahrung."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:51
|
||||
msgid "Add document"
|
||||
@ -40,142 +35,138 @@ msgstr "Dokument hinzufügen"
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:201
|
||||
msgid "Add More Users for {0}"
|
||||
msgstr "Mehr Benutzer hinzufügen für {0}"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:165
|
||||
msgid "All our metrics, finances, and learnings are public. We believe in transparency and want to share our journey with you. You can read more about why here: <0>Announcing Open Metrics</0>"
|
||||
msgstr "Alle unsere Kennzahlen, Finanzen und Erkenntnisse sind öffentlich. Wir glauben an Transparenz und möchten unsere Reise mit Ihnen teilen. Mehr erfahren Sie hier: <0>Ankündigung Offene Kennzahlen</0>"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/funding-raised.tsx:58
|
||||
#: apps/marketing/src/app/(marketing)/open/funding-raised.tsx:65
|
||||
msgid "Amount Raised"
|
||||
msgstr "Erhobener Betrag"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:145
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:189
|
||||
msgid "API Access"
|
||||
msgstr "API-Zugriff"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:67
|
||||
msgid "Beautiful."
|
||||
msgstr "Schön."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:69
|
||||
msgid "Because signing should be celebrated. That’s why we care about the smallest detail in our product."
|
||||
msgstr "Weil Unterschriften gefeiert werden sollten. Deshalb kümmern wir uns um jedes kleinste Detail in unserem Produkt."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:35
|
||||
#: apps/marketing/src/components/(marketing)/header.tsx:57
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:36
|
||||
msgid "Blog"
|
||||
msgstr "Blog"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:64
|
||||
msgid "Build on top."
|
||||
msgstr "Aufbauen oben drauf."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:163
|
||||
msgid "Can I use Documenso commercially?"
|
||||
msgstr "Kann ich Documenso kommerziell nutzen?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:42
|
||||
msgid "Careers"
|
||||
msgstr "Karrieren"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:36
|
||||
msgid "Changelog"
|
||||
msgstr "Änderungsprotokoll"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:85
|
||||
msgid "Choose a template from the community app store. Or submit your own template for others to use."
|
||||
msgstr "Wählen Sie eine Vorlage aus dem Community-App-Store. Oder reichen Sie Ihre eigene Vorlage ein, damit andere sie benutzen können."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:219
|
||||
msgid "Community"
|
||||
msgstr "Gemeinschaft"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx:55
|
||||
msgid "Completed Documents"
|
||||
msgstr "Fertige Dokumente"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-completed-documents-chart.tsx:33
|
||||
msgid "Completed Documents per Month"
|
||||
msgstr "Fertige Dokumente pro Monat"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:65
|
||||
msgid "Connections"
|
||||
msgstr "Verbindungen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/enterprise.tsx:35
|
||||
msgid "Contact Us"
|
||||
msgstr "Kontaktiere uns"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:67
|
||||
msgid "Create connections and automations with Zapier and more to integrate with your favorite tools."
|
||||
msgstr "Erstellen Sie Verbindungen und Automatisierungen mit Zapier und mehr, um sich mit Ihren Lieblingstools zu integrieren."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/call-to-action.tsx:23
|
||||
msgid "Create your account and start using state-of-the-art document signing. Open and beautiful signing is within your grasp."
|
||||
msgstr "Erstellen Sie Ihr Konto und beginnen Sie mit der Nutzung modernster Dokumentensignaturen. Offene und schöne Signaturen sind zum Greifen nah."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/tooltip.tsx:35
|
||||
msgid "Customers with an Active Subscriptions."
|
||||
msgstr "Kunden mit einer aktiven Abonnements."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:33
|
||||
msgid "Customise and expand."
|
||||
msgstr "Anpassen und erweitern."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:38
|
||||
msgid "Design"
|
||||
msgstr "Design"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:44
|
||||
msgid "Designed for every stage of your journey."
|
||||
msgstr "Entwickelt für jede Phase Ihrer Reise."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/carousel.tsx:40
|
||||
msgid "Direct Link"
|
||||
msgstr "Direktlink"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:181
|
||||
msgid "Documenso is a community effort to create an open and vibrant ecosystem around a tool, everybody is free to use and adapt. By being truly open we want to create trusted infrastructure for the future of the internet."
|
||||
msgstr "Documenso ist eine Gemeinschaftsanstrengung, um ein offenes und lebendiges Ökosystem um ein Werkzeug zu schaffen, das jeder frei nutzen und anpassen kann. Indem wir wirklich offen sind, wollen wir vertrauenswürdige Infrastruktur für die Zukunft des Internets schaffen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:28
|
||||
msgid "Documenso on X"
|
||||
msgstr "Documenso auf X"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/hero.tsx:104
|
||||
msgid "Document signing,<0/>finally open source."
|
||||
msgstr "Unterschriften,<0/>endlich Open Source."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:33
|
||||
#: apps/marketing/src/components/(marketing)/header.tsx:50
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:28
|
||||
msgid "Documentation"
|
||||
msgstr "Dokumentation"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:110
|
||||
msgid "Easily embed Documenso into your product. Simply copy and paste our react widget into your application."
|
||||
msgstr "Betten Sie Documenso ganz einfach in Ihr Produkt ein. Kopieren und fügen Sie einfach unser React-Widget in Ihre Anwendung ein."
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:42
|
||||
#~ msgid "Easy Sharing (Soon)."
|
||||
#~ msgstr "Easy Sharing (Soon)."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:46
|
||||
msgid "Easy Sharing."
|
||||
msgstr "Einfaches Teilen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:148
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:192
|
||||
msgid "Email and Discord Support"
|
||||
msgstr "E-Mail- und Discord-Support"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:43
|
||||
msgid "Engagement"
|
||||
msgstr "Beteiligung"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:64
|
||||
msgid "Enter your details."
|
||||
@ -183,43 +174,43 @@ msgstr "Geben Sie Ihre Details ein."
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/enterprise.tsx:16
|
||||
msgid "Enterprise Compliance, License or Technical Needs?"
|
||||
msgstr "Enterprise-Konformität, Lizenz- oder technische Bedürfnisse?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:128
|
||||
msgid "Everything you need for a great signing experience."
|
||||
msgstr "Alles, was Sie für ein großartiges Signaturerlebnis benötigen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:45
|
||||
msgid "Fast."
|
||||
msgstr "Schnell."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:36
|
||||
msgid "Faster, smarter and more beautiful."
|
||||
msgstr "Schneller, intelligenter und schöner."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:210
|
||||
msgid "Finances"
|
||||
msgstr "Finanzen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:38
|
||||
msgid "Follow us on X"
|
||||
msgstr "Folgen Sie uns auf X"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:172
|
||||
msgid "For companies looking to scale across multiple teams."
|
||||
msgstr "Für Unternehmen, die über mehrere Teams skalieren möchten."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:85
|
||||
msgid "For small teams and individuals with basic needs."
|
||||
msgstr "Für kleine Teams und Einzelpersonen mit grundlegenden Bedürfnissen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:80
|
||||
msgid "Free"
|
||||
msgstr "Kostenlos"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/blog/page.tsx:26
|
||||
msgid "From the blog"
|
||||
msgstr "Aus dem Blog"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/data.ts:9
|
||||
#: apps/marketing/src/app/(marketing)/open/data.ts:17
|
||||
@ -227,227 +218,222 @@ msgstr "Aus dem Blog"
|
||||
#: apps/marketing/src/app/(marketing)/open/data.ts:41
|
||||
#: apps/marketing/src/app/(marketing)/open/data.ts:49
|
||||
msgid "Full-Time"
|
||||
msgstr "Vollzeit"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:87
|
||||
msgid "Get paid (Soon)."
|
||||
msgstr "Lassen Sie sich bezahlen (Bald)."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/call-to-action.tsx:31
|
||||
msgid "Get started"
|
||||
msgstr "Loslegen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:75
|
||||
msgid "Get Started"
|
||||
msgstr "Loslegen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:47
|
||||
msgid "Get started today."
|
||||
msgstr "Fangen Sie heute an."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/blog/page.tsx:30
|
||||
msgid "Get the latest news from Documenso, including product updates, team announcements and more!"
|
||||
msgstr "Erhalten Sie die neuesten Nachrichten von Documenso, einschließlich Produkt-Updates, Team-Ankündigungen und mehr!"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:233
|
||||
msgid "GitHub: Total Merged PRs"
|
||||
msgstr "GitHub: Gesamte PRs zusammengeführt"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:251
|
||||
msgid "GitHub: Total Open Issues"
|
||||
msgstr "GitHub: Gesamte offene Issues"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:225
|
||||
msgid "GitHub: Total Stars"
|
||||
msgstr "GitHub: Gesamtanzahl Sterne"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:23
|
||||
msgid "Global Salary Bands"
|
||||
msgstr "Globale Gehaltsbänder"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:261
|
||||
msgid "Growth"
|
||||
msgstr "Wachstum"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:134
|
||||
msgid "How can I contribute?"
|
||||
msgstr "Wie kann ich beitragen?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:105
|
||||
msgid "How do you handle my data?"
|
||||
msgstr "Wie gehen Sie mit meinen Daten um?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:118
|
||||
msgid "Individual"
|
||||
msgstr "Einzelperson"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:89
|
||||
msgid "Integrated payments with Stripe so you don’t have to worry about getting paid."
|
||||
msgstr "Integrierte Zahlungen mit Stripe, sodass Sie sich keine Sorgen ums Bezahlen machen müssen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:35
|
||||
msgid "Integrates with all your favourite tools."
|
||||
msgstr "Integriert sich mit all Ihren Lieblingstools."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:289
|
||||
msgid "Is there more?"
|
||||
msgstr "Gibt es mehr?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:44
|
||||
msgid "It’s up to you. Either clone our repository or rely on our easy to use hosting solution."
|
||||
msgstr "Es liegt an Ihnen. Entweder klonen Sie unser Repository oder nutzen unsere einfach zu bedienende Hosting-Lösung."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:49
|
||||
msgid "Join Date"
|
||||
msgstr "Eintrittsdatum"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/call-to-action.tsx:19
|
||||
msgid "Join the Open Signing Movement"
|
||||
msgstr "Treten Sie der Open Signing-Bewegung bei"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:46
|
||||
msgid "Location"
|
||||
msgstr "Standort"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:66
|
||||
msgid "Make it your own through advanced customization and adjustability."
|
||||
msgstr "Machen Sie es zu Ihrem eigenen durch erweiterte Anpassung und Einstellbarkeit."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:199
|
||||
msgid "Merged PR's"
|
||||
msgstr "Zusammengeführte PRs"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:234
|
||||
msgid "Merged PRs"
|
||||
msgstr "Zusammengeführte PRs"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:40
|
||||
msgid "Monthly"
|
||||
msgstr "Monatlich"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:34
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx:30
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx:43
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-new-users-chart.tsx:52
|
||||
msgid "New Users"
|
||||
msgstr "Neue Benutzer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:106
|
||||
msgid "No credit card required"
|
||||
msgstr "Keine Kreditkarte erforderlich"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/callout.tsx:29
|
||||
#: apps/marketing/src/components/(marketing)/hero.tsx:125
|
||||
msgid "No Credit Card required"
|
||||
msgstr "Keine Kreditkarte erforderlich"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:61
|
||||
msgid "None of these work for you? Try self-hosting!"
|
||||
msgstr "Keines dieser Angebote passt zu Ihnen? Versuchen Sie das Selbst-Hosting!"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:194
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:252
|
||||
msgid "Open Issues"
|
||||
msgstr "Offene Issues"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:42
|
||||
msgid "Open Source or Hosted."
|
||||
msgstr "Open Source oder Hosted."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:161
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:37
|
||||
#: apps/marketing/src/components/(marketing)/header.tsx:64
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:40
|
||||
msgid "Open Startup"
|
||||
msgstr "Offenes Startup"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:41
|
||||
msgid "OSS Friends"
|
||||
msgstr "OSS-Freunde"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:91
|
||||
msgid "Our custom templates come with smart rules that can help you save time and energy."
|
||||
msgstr "Unsere benutzerdefinierten Vorlagen verfügen über intelligente Regeln, die Ihnen Zeit und Energie sparen können."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/enterprise.tsx:20
|
||||
msgid "Our Enterprise License is great for large organizations looking to switch to Documenso for all their signing needs. It's available for our cloud offering as well as self-hosted setups and offers a wide range of compliance and Adminstration Features."
|
||||
msgstr "Unsere Enterprise-Lizenz ist ideal für große Organisationen, die auf Documenso für all ihre Signaturanforderungen umsteigen möchten. Sie ist sowohl für unser Cloud-Angebot als auch für selbstgehostete Setups verfügbar und bietet eine breite Palette an Compliance- und Verwaltungsfunktionen."
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/enterprise.tsx:20
|
||||
#~ msgid "Our Enterprise License is great large organizations looking to switch to Documenso for all their signing needs. It's availible for our cloud offering as well as self-hosted setups and offer a wide range of compliance and Adminstration Features."
|
||||
#~ msgstr "Our Enterprise License is great large organizations looking to switch to Documenso for all their signing needs. It's availible for our cloud offering as well as self-hosted setups and offer a wide range of compliance and Adminstration Features."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:65
|
||||
msgid "Our self-hosted option is great for small teams and individuals who need a simple solution. You can use our docker based setup to get started in minutes. Take control with full customizability and data ownership."
|
||||
msgstr "Unsere selbstgehostete Option ist ideal für kleine Teams und Einzelpersonen, die eine einfache Lösung benötigen. Sie können unser docker-basiertes Setup verwenden, um in wenigen Minuten loszulegen. Übernehmen Sie die Kontrolle mit vollständiger Anpassbarkeit und Datenhoheit."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/data.ts:25
|
||||
msgid "Part-Time"
|
||||
msgstr "Teilzeit"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:151
|
||||
msgid "Premium Profile Name"
|
||||
msgstr "Premium Profilname"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:40
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:31
|
||||
#: apps/marketing/src/components/(marketing)/header.tsx:42
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:24
|
||||
msgid "Pricing"
|
||||
msgstr "Preise"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:43
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:53
|
||||
msgid "Privacy"
|
||||
msgstr "Datenschutz"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/carousel.tsx:58
|
||||
msgid "Profile"
|
||||
msgstr "Profil"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:108
|
||||
msgid "React Widget (Soon)."
|
||||
msgstr "React Widget (Demnächst)."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:48
|
||||
msgid "Receive your personal link to share with everyone you care about."
|
||||
msgstr "Erhalten Sie Ihren persönlichen Link zum Teilen mit allen, die Ihnen wichtig sind."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:37
|
||||
msgid "Role"
|
||||
msgstr "Rolle"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:37
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:40
|
||||
msgid "Salary"
|
||||
msgstr "Gehalt"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:62
|
||||
msgid "Save $60 or $120"
|
||||
msgstr "Sparen Sie $60 oder $120"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/i18n-switcher.tsx:47
|
||||
#~ msgid "Search languages..."
|
||||
#~ msgstr "Sprachen suchen..."
|
||||
#~ msgstr "Sprachen suchen...>>>>>>> main"
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:109
|
||||
msgid "Securely. Our data centers are located in Frankfurt (Germany), giving us the best local privacy laws. We are very aware of the sensitive nature of our data and follow best practices to ensure the security and integrity of the data entrusted to us."
|
||||
msgstr "Sicher. Unsere Rechenzentren befinden sich in Frankfurt (Deutschland) und bieten uns die besten lokalen Datenschutzgesetze. Uns ist die sensible Natur unserer Daten sehr bewusst und wir folgen bewährten Praktiken, um die Sicherheit und Integrität der uns anvertrauten Daten zu gewährleisten."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/share-connect-paid-widget-bento.tsx:37
|
||||
msgid "Send, connect, receive and embed everywhere."
|
||||
msgstr "Überall senden, verbinden, empfangen und einbetten."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:34
|
||||
msgid "Seniority"
|
||||
msgstr "Dienstalter"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:39
|
||||
msgid "Shop"
|
||||
msgstr "Shop"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:63
|
||||
msgid "Sign"
|
||||
@ -456,115 +442,115 @@ msgstr "Signieren"
|
||||
#: apps/marketing/src/components/(marketing)/header.tsx:72
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:61
|
||||
msgid "Sign in"
|
||||
msgstr "Anmelden"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/header.tsx:77
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:57
|
||||
msgid "Sign up"
|
||||
msgstr "Registrieren"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/carousel.tsx:22
|
||||
msgid "Signing Process"
|
||||
msgstr "Signaturprozess"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:94
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:136
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:180
|
||||
msgid "Signup Now"
|
||||
msgstr "Jetzt registrieren"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:89
|
||||
msgid "Smart."
|
||||
msgstr "Intelligent."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/hero.tsx:132
|
||||
msgid "Star on GitHub"
|
||||
msgstr "Auf GitHub favorisieren"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:226
|
||||
msgid "Stars"
|
||||
msgstr "Favoriten"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:40
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:44
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/footer.tsx:34
|
||||
#: apps/marketing/src/components/(marketing)/mobile-navigation.tsx:48
|
||||
msgid "Support"
|
||||
msgstr "Support"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/team-members.tsx:26
|
||||
msgid "Team"
|
||||
msgstr "Team"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:195
|
||||
msgid "Team Inbox"
|
||||
msgstr "Team-Posteingang"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/carousel.tsx:28
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:162
|
||||
msgid "Teams"
|
||||
msgstr "Teams"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:83
|
||||
msgid "Template Store (Soon)."
|
||||
msgstr "Vorlagen-Shop (Demnächst)."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:138
|
||||
msgid "That's awesome. You can take a look at the current <0>Issues</0> and join our <1>Discord Community</1> to keep up to date, on what the current priorities are. In any case, we are an open community and welcome all input, technical and non-technical ❤️"
|
||||
msgstr "Das ist großartig. Sie können sich die aktuellen <0>Issues</0> ansehen und unserer <1>Discord-Community</1> beitreten, um auf dem neuesten Stand zu bleiben, was die aktuellen Prioritäten sind. In jedem Fall sind wir eine offene Gemeinschaft und begrüßen jegliche Beiträge, technische und nicht-technische ❤️"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:293
|
||||
msgid "This page is evolving as we learn what makes a great signing company. We'll update it when we have more to share."
|
||||
msgstr "Diese Seite entwickelt sich weiter, während wir lernen, was ein großartiges Signing-Unternehmen ausmacht. Wir werden sie aktualisieren, wenn wir mehr zu teilen haben."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/salary-bands.tsx:31
|
||||
msgid "Title"
|
||||
msgstr "Titel"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx:30
|
||||
#: apps/marketing/src/app/(marketing)/open/total-signed-documents-chart.tsx:55
|
||||
msgid "Total Completed Documents"
|
||||
msgstr "Insgesamt Abgeschlossene Dokumente"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:267
|
||||
#: apps/marketing/src/app/(marketing)/open/page.tsx:268
|
||||
msgid "Total Customers"
|
||||
msgstr "Insgesamt Kunden"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/funding-raised.tsx:29
|
||||
msgid "Total Funding Raised"
|
||||
msgstr "Insgesamt Finanzierungsvolumen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx:30
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx:43
|
||||
#: apps/marketing/src/app/(marketing)/open/monthly-total-users-chart.tsx:52
|
||||
msgid "Total Users"
|
||||
msgstr "Gesamtanzahl der Benutzer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/open-build-template-bento.tsx:31
|
||||
msgid "Truly your own."
|
||||
msgstr "Wirklich Ihr Eigenes."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/callout.tsx:27
|
||||
#: apps/marketing/src/components/(marketing)/hero.tsx:123
|
||||
msgid "Try our Free Plan"
|
||||
msgstr "Probieren Sie unseren Gratisplan aus"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:20
|
||||
msgid "Twitter Stats"
|
||||
msgstr "Twitter-Statistiken"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:142
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:186
|
||||
msgid "Unlimited Documents per Month"
|
||||
msgstr "Unbegrenzte Dokumente pro Monat"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:103
|
||||
msgid "Up to 10 recipients per document"
|
||||
msgstr "Bis zu 10 Empfänger pro Dokument"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/singleplayer/client.tsx:52
|
||||
msgid "Upload a document and add fields."
|
||||
@ -572,48 +558,52 @@ msgstr "Laden Sie ein Dokument hoch und fügen Sie Felder hinzu."
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:123
|
||||
msgid "Using our hosted version is the easiest way to get started, you can simply subscribe and start signing your documents. We take care of the infrastructure, so you can focus on your business. Additionally, when using our hosted version you benefit from our trusted signing certificates which helps you to build trust with your customers."
|
||||
msgstr "Die Nutzung unserer gehosteten Version ist der einfachste Weg, um zu starten. Sie können einfach abonnieren und mit der Unterzeichnung Ihrer Dokumente beginnen. Wir kümmern uns um die Infrastruktur, damit Sie sich auf Ihr Geschäft konzentrieren können. Zudem profitieren Sie bei der Nutzung unserer gehosteten Version von unseren vertrauenswürdigen Signaturzertifikaten, die Ihnen helfen, Vertrauen bei Ihren Kunden aufzubauen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/open/typefully.tsx:33
|
||||
msgid "View all stats"
|
||||
msgstr "Alle Statistiken anzeigen"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:195
|
||||
msgid "We are happy to assist you at <0>support@documenso.com</0> or <1>in our Discord-Support-Channel</1> please message either Lucas or Timur to get added to the channel if you are not already a member."
|
||||
msgstr "Wir helfen Ihnen gerne unter <0>support@documenso.com</0> oder <1>in unserem Discord-Support-Kanal</1>. Bitte senden Sie Lucas oder Timur eine Nachricht, um dem Kanal beizutreten, falls Sie noch kein Mitglied sind."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:89
|
||||
msgid "What is the difference between the plans?"
|
||||
msgstr "Was ist der Unterschied zwischen den Plänen?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/faster-smarter-beautiful-bento.tsx:47
|
||||
msgid "When it comes to sending or receiving a contract, you can count on lightning-fast speeds."
|
||||
msgstr "Wenn es um das Senden oder Empfangen eines Vertrags geht, können Sie auf blitzschnelle Geschwindigkeiten zählen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:191
|
||||
msgid "Where can I get support?"
|
||||
msgstr "Wo kann ich Unterstützung bekommen?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:177
|
||||
msgid "Why should I prefer Documenso over DocuSign or some other signing tool?"
|
||||
msgstr "Warum sollte ich Documenso gegenüber DocuSign oder einem anderen Signatur-Tool bevorzugen?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:119
|
||||
msgid "Why should I use your hosting service?"
|
||||
msgstr "Warum sollte ich Ihren Hosting-Service nutzen?"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/pricing-table.tsx:60
|
||||
msgid "Yearly"
|
||||
msgstr "Jährlich"
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:167
|
||||
msgid "Yes! Documenso is offered under the GNU AGPL V3 open source license. This means you can use it for free and even modify it to fit your needs, as long as you publish your changes under the same license."
|
||||
msgstr "Ja! Documenso wird unter der GNU AGPL V3 Open-Source-Lizenz angeboten. Das bedeutet, dass Sie es kostenlos nutzen und sogar an Ihre Bedürfnisse anpassen können, solange Sie Ihre Änderungen unter derselben Lizenz veröffentlichen."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/app/(marketing)/pricing/page.tsx:93
|
||||
msgid "You can self-host Documenso for free or use our ready-to-use hosted version. The hosted version comes with additional support, painless scalability and more. Early adopters will get access to all features we build this year, for no additional cost! Forever! Yes, that includes multiple users per account later. If you want Documenso for your enterprise, we are happy to talk about your needs."
|
||||
msgstr "Sie können Documenso kostenlos selbst hosten oder unsere sofort einsatzbereite gehostete Version nutzen. Die gehostete Version bietet zusätzlichen Support, schmerzfreie Skalierbarkeit und mehr. Frühzeitige Anwender erhalten in diesem Jahr Zugriff auf alle Funktionen, die wir entwickeln, ohne zusätzliche Kosten! Für immer! Ja, das beinhaltet später mehrere Benutzer pro Konto. Wenn Sie Documenso für Ihr Unternehmen möchten, sprechen wir gerne über Ihre Bedürfnisse."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/carousel.tsx:265
|
||||
msgid "Your browser does not support the video tag."
|
||||
msgstr "Ihr Browser unterstützt das Video-Tag nicht."
|
||||
msgstr ""
|
||||
|
||||
#: apps/marketing/src/components/(marketing)/carousel.tsx:265
|
||||
#~ msgid "Your browser does not support the video tag.<<<<<<< HEAD"
|
||||
#~ msgstr "Ihr Browser unterstützt das Video-Tag nicht.>>>>>>> main"
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"POT-Creation-Date: 2024-07-24 13:01+1000\n"
|
||||
"POT-Creation-Date: 2024-08-22 05:16+0000\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: @lingui/cli\n"
|
||||
"Language: de\n"
|
||||
"Project-Id-Version: documenso-app\n"
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2024-09-05 06:04\n"
|
||||
"Last-Translator: \n"
|
||||
@ -754,7 +754,7 @@ msgstr "Klicken Sie, um den Signatur-Link zu kopieren, um ihn an den Empfänger
|
||||
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:175
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:107
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:435
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:312
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:314
|
||||
msgid "Click to insert field"
|
||||
msgstr "Klicken Sie, um das Feld einzufügen"
|
||||
|
||||
@ -772,7 +772,7 @@ msgstr "Schließen"
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:58
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:425
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:302
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:304
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:522
|
||||
msgid "Complete"
|
||||
msgstr "Vollständig"
|
||||
@ -1405,7 +1405,7 @@ msgstr "Webhook bearbeiten"
|
||||
#: apps/web/src/app/(recipient)/d/[token]/configure-direct-template.tsx:118
|
||||
#: apps/web/src/app/(signing)/sign/[token]/email-field.tsx:126
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:376
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:254
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:256
|
||||
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:169
|
||||
#: apps/web/src/components/(teams)/dialogs/update-team-email-dialog.tsx:153
|
||||
#: apps/web/src/components/forms/forgot-password.tsx:81
|
||||
@ -1587,7 +1587,7 @@ msgstr "Haben Sie Ihr Passwort vergessen?"
|
||||
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:326
|
||||
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:193
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:361
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:239
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:241
|
||||
#: apps/web/src/components/forms/profile.tsx:110
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:300
|
||||
msgid "Full Name"
|
||||
@ -2030,7 +2030,7 @@ msgid "New Template"
|
||||
msgstr "Neue Vorlage"
|
||||
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:416
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:293
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:295
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:509
|
||||
msgid "Next"
|
||||
msgstr "Nächster"
|
||||
@ -2733,7 +2733,7 @@ msgid "Sign as<0>{0} <1>({1})</1></0>"
|
||||
msgstr "Unterzeichnen als<0>{0} <1>({1})</1></0>"
|
||||
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:329
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:207
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:209
|
||||
msgid "Sign document"
|
||||
msgstr "Dokument unterschreiben"
|
||||
|
||||
@ -2762,7 +2762,7 @@ msgid "Sign Out"
|
||||
msgstr "Ausloggen"
|
||||
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:350
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:228
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:230
|
||||
msgid "Sign the document to complete the process."
|
||||
msgstr "Unterschreiben Sie das Dokument, um den Vorgang abzuschließen."
|
||||
|
||||
@ -2789,7 +2789,7 @@ msgstr "Registrieren mit OIDC"
|
||||
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:197
|
||||
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:227
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:391
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:268
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:270
|
||||
#: apps/web/src/components/forms/profile.tsx:132
|
||||
msgid "Signature"
|
||||
msgstr "Unterschrift"
|
||||
@ -2857,7 +2857,7 @@ msgstr "Website Einstellungen"
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/team-email-dropdown.tsx:39
|
||||
#: apps/web/src/app/(unauthenticated)/verify-email/[token]/page.tsx:61
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:243
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:123
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:125
|
||||
#: apps/web/src/components/(teams)/dialogs/create-team-checkout-dialog.tsx:50
|
||||
#: apps/web/src/components/(teams)/dialogs/create-team-checkout-dialog.tsx:99
|
||||
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:210
|
||||
@ -4023,7 +4023,7 @@ msgstr "Wir konnten die Zwei-Faktor-Authentifizierung für Ihr Konto nicht einri
|
||||
|
||||
#: apps/web/src/app/(recipient)/d/[token]/direct-template.tsx:119
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:245
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:125
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:127
|
||||
msgid "We were unable to submit this document at this time. Please try again later."
|
||||
msgstr "Wir konnten dieses Dokument zurzeit nicht einreichen. Bitte versuchen Sie es später erneut."
|
||||
|
||||
|
||||
@ -77,19 +77,19 @@ msgstr "Add another option"
|
||||
msgid "Add another value"
|
||||
msgstr "Add another value"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:359
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:459
|
||||
msgid "Add myself"
|
||||
msgstr "Add myself"
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:369
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:450
|
||||
msgid "Add Myself"
|
||||
msgstr "Add Myself"
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:355
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:436
|
||||
msgid "Add Placeholder Recipient"
|
||||
msgstr "Add Placeholder Recipient"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:348
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:448
|
||||
msgid "Add Signer"
|
||||
msgstr "Add Signer"
|
||||
|
||||
@ -149,8 +149,8 @@ msgid "Cancel"
|
||||
msgstr "Cancel"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:164
|
||||
msgid "Cannot remove signer"
|
||||
msgstr "Cannot remove signer"
|
||||
#~ msgid "Cannot remove signer"
|
||||
#~ msgstr "Cannot remove signer"
|
||||
|
||||
#: packages/lib/constants/recipient-roles.ts:17
|
||||
msgid "Cc"
|
||||
@ -225,7 +225,7 @@ msgstr "Date"
|
||||
msgid "Date Format"
|
||||
msgstr "Date Format"
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:312
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:393
|
||||
msgid "Direct link receiver"
|
||||
msgstr "Direct link receiver"
|
||||
|
||||
@ -258,11 +258,11 @@ msgstr "Dropdown options"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-fields.tsx:776
|
||||
#: packages/ui/primitives/document-flow/add-signature.tsx:272
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:232
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:239
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:330
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:337
|
||||
#: packages/ui/primitives/template-flow/add-template-fields.tsx:632
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:210
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:217
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:296
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:303
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
|
||||
@ -373,10 +373,10 @@ msgstr "Min"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-fields.tsx:802
|
||||
#: packages/ui/primitives/document-flow/add-signature.tsx:298
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:265
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:364
|
||||
#: packages/ui/primitives/template-flow/add-template-fields.tsx:658
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:245
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:251
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:327
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:333
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
@ -555,8 +555,8 @@ msgstr "Share Signature Card"
|
||||
msgid "Share the Link"
|
||||
msgstr "Share the Link"
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:377
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:387
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:477
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:468
|
||||
msgid "Show advanced settings"
|
||||
msgstr "Show advanced settings"
|
||||
|
||||
@ -681,13 +681,13 @@ msgstr "This document has already been sent to this recipient. You can no longer
|
||||
msgid "This document is password protected. Please enter the password to view the document."
|
||||
msgstr "This document is password protected. Please enter the password to view the document."
|
||||
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:315
|
||||
#: packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx:396
|
||||
msgid "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
|
||||
msgstr "This field cannot be modified or deleted. When you share this template's direct link or add it to your public profile, anyone who accesses it can input their name and email, and fill in the fields assigned to them."
|
||||
|
||||
#: packages/ui/primitives/document-flow/add-signers.tsx:165
|
||||
msgid "This signer has already received the document."
|
||||
msgstr "This signer has already received the document."
|
||||
#~ msgid "This signer has already received the document."
|
||||
#~ msgstr "This signer has already received the document."
|
||||
|
||||
#: packages/ui/components/recipient/recipient-action-auth-select.tsx:48
|
||||
msgid "This will override any global settings."
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -749,7 +749,7 @@ msgstr "Click to copy signing link for sending to recipient"
|
||||
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:175
|
||||
#: apps/web/src/app/(signing)/sign/[token]/form.tsx:107
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:435
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:312
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:314
|
||||
msgid "Click to insert field"
|
||||
msgstr "Click to insert field"
|
||||
|
||||
@ -767,7 +767,7 @@ msgstr "Close"
|
||||
|
||||
#: apps/web/src/app/(signing)/sign/[token]/sign-dialog.tsx:58
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:425
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:302
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:304
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:522
|
||||
msgid "Complete"
|
||||
msgstr "Complete"
|
||||
@ -1402,7 +1402,7 @@ msgstr "Edit webhook"
|
||||
#: apps/web/src/app/(recipient)/d/[token]/configure-direct-template.tsx:118
|
||||
#: apps/web/src/app/(signing)/sign/[token]/email-field.tsx:126
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:376
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:254
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:256
|
||||
#: apps/web/src/components/(teams)/dialogs/add-team-email-dialog.tsx:169
|
||||
#: apps/web/src/components/(teams)/dialogs/update-team-email-dialog.tsx:153
|
||||
#: apps/web/src/components/forms/forgot-password.tsx:81
|
||||
@ -1586,7 +1586,7 @@ msgstr "Forgot your password?"
|
||||
#: apps/web/src/app/(recipient)/d/[token]/sign-direct-template.tsx:326
|
||||
#: apps/web/src/app/(signing)/sign/[token]/name-field.tsx:193
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:361
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:239
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:241
|
||||
#: apps/web/src/components/forms/profile.tsx:110
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:300
|
||||
msgid "Full Name"
|
||||
@ -2029,7 +2029,7 @@ msgid "New Template"
|
||||
msgstr "New Template"
|
||||
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:416
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:293
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:295
|
||||
#: apps/web/src/components/forms/v2/signup.tsx:509
|
||||
msgid "Next"
|
||||
msgstr "Next"
|
||||
@ -2732,7 +2732,7 @@ msgid "Sign as<0>{0} <1>({1})</1></0>"
|
||||
msgstr "Sign as<0>{0} <1>({1})</1></0>"
|
||||
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:329
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:207
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:209
|
||||
msgid "Sign document"
|
||||
msgstr "Sign document"
|
||||
|
||||
@ -2761,7 +2761,7 @@ msgid "Sign Out"
|
||||
msgstr "Sign Out"
|
||||
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:350
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:228
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:230
|
||||
msgid "Sign the document to complete the process."
|
||||
msgstr "Sign the document to complete the process."
|
||||
|
||||
@ -2788,7 +2788,7 @@ msgstr "Sign Up with OIDC"
|
||||
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:197
|
||||
#: apps/web/src/app/(signing)/sign/[token]/signature-field.tsx:227
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:391
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:268
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:270
|
||||
#: apps/web/src/components/forms/profile.tsx:132
|
||||
msgid "Signature"
|
||||
msgstr "Signature"
|
||||
@ -2856,7 +2856,7 @@ msgstr "Site Settings"
|
||||
#: apps/web/src/app/(teams)/t/[teamUrl]/settings/team-email-dropdown.tsx:39
|
||||
#: apps/web/src/app/(unauthenticated)/verify-email/[token]/page.tsx:61
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:243
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:123
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:125
|
||||
#: apps/web/src/components/(teams)/dialogs/create-team-checkout-dialog.tsx:50
|
||||
#: apps/web/src/components/(teams)/dialogs/create-team-checkout-dialog.tsx:99
|
||||
#: apps/web/src/components/(teams)/dialogs/invite-team-member-dialog.tsx:210
|
||||
@ -4022,7 +4022,7 @@ msgstr "We were unable to setup two-factor authentication for your account. Plea
|
||||
|
||||
#: apps/web/src/app/(recipient)/d/[token]/direct-template.tsx:119
|
||||
#: apps/web/src/app/embed/direct/[[...url]]/client.tsx:245
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:125
|
||||
#: apps/web/src/app/embed/sign/[[...url]]/client.tsx:127
|
||||
msgid "We were unable to submit this document at this time. Please try again later."
|
||||
msgstr "We were unable to submit this document at this time. Please try again later."
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { TRPCError } from '@trpc/server';
|
||||
|
||||
import { completeDocumentWithToken } from '@documenso/lib/server-only/document/complete-document-with-token';
|
||||
import { deleteRecipient } from '@documenso/lib/server-only/recipient/delete-recipient';
|
||||
import { deleteRecipientFromTemplate } from '@documenso/lib/server-only/recipient/delete-recipient-from-template';
|
||||
import { setRecipientsForDocument } from '@documenso/lib/server-only/recipient/set-recipients-for-document';
|
||||
import { setRecipientsForTemplate } from '@documenso/lib/server-only/recipient/set-recipients-for-template';
|
||||
import { extractNextApiRequestMetadata } from '@documenso/lib/universal/extract-request-metadata';
|
||||
@ -10,6 +12,8 @@ import {
|
||||
ZAddSignersMutationSchema,
|
||||
ZAddTemplateSignersMutationSchema,
|
||||
ZCompleteDocumentWithTokenMutationSchema,
|
||||
ZRemoveSignerMutationSchema,
|
||||
ZRemoveTemplateSignerMutationSchema,
|
||||
} from './schema';
|
||||
|
||||
export const recipientRouter = router({
|
||||
@ -70,6 +74,51 @@ export const recipientRouter = router({
|
||||
}
|
||||
}),
|
||||
|
||||
removeTemplateSigner: authenticatedProcedure
|
||||
.input(ZRemoveTemplateSignerMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { templateId, recipientId, teamId } = input;
|
||||
const userId = ctx.user.id;
|
||||
|
||||
return await deleteRecipientFromTemplate({
|
||||
userId,
|
||||
templateId,
|
||||
teamId,
|
||||
recipientId,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to remove the recipient. Please try again later.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
removeSigner: authenticatedProcedure
|
||||
.input(ZRemoveSignerMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
try {
|
||||
const { documentId, teamId, recipientId } = input;
|
||||
|
||||
return await deleteRecipient({
|
||||
userId: ctx.user.id,
|
||||
documentId,
|
||||
teamId,
|
||||
recipientId,
|
||||
requestMetadata: extractNextApiRequestMetadata(ctx.req),
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'We were unable to set this field. Please try again later.',
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
completeDocumentWithToken: procedure
|
||||
.input(ZCompleteDocumentWithTokenMutationSchema)
|
||||
.mutation(async ({ input, ctx }) => {
|
||||
|
||||
@ -58,6 +58,14 @@ export const ZAddTemplateSignersMutationSchema = z
|
||||
|
||||
export type TAddTemplateSignersMutationSchema = z.infer<typeof ZAddTemplateSignersMutationSchema>;
|
||||
|
||||
export const ZRemoveSignerMutationSchema = z.object({
|
||||
documentId: z.number(),
|
||||
teamId: z.number().optional(),
|
||||
recipientId: z.number(),
|
||||
});
|
||||
|
||||
export type TRemoveSignerMutationSchema = z.infer<typeof ZRemoveSignerMutationSchema>;
|
||||
|
||||
export const ZCompleteDocumentWithTokenMutationSchema = z.object({
|
||||
token: z.string(),
|
||||
documentId: z.number(),
|
||||
@ -67,3 +75,13 @@ export const ZCompleteDocumentWithTokenMutationSchema = z.object({
|
||||
export type TCompleteDocumentWithTokenMutationSchema = z.infer<
|
||||
typeof ZCompleteDocumentWithTokenMutationSchema
|
||||
>;
|
||||
|
||||
export const ZRemoveTemplateSignerMutationSchema = z.object({
|
||||
templateId: z.number(),
|
||||
teamId: z.number().optional(),
|
||||
recipientId: z.number(),
|
||||
});
|
||||
|
||||
export type TRemoveTemplateSignerMutationSchema = z.infer<
|
||||
typeof ZRemoveTemplateSignerMutationSchema
|
||||
>;
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
import React, { useId, useMemo, useState } from 'react';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
@ -11,10 +13,13 @@ import { useSession } from 'next-auth/react';
|
||||
import { useFieldArray, useForm } from 'react-hook-form';
|
||||
|
||||
import { useLimits } from '@documenso/ee/server-only/limits/provider/client';
|
||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||
import { ZRecipientAuthOptionsSchema } from '@documenso/lib/types/document-auth';
|
||||
import { nanoid } from '@documenso/lib/universal/id';
|
||||
import type { Field, Recipient } from '@documenso/prisma/client';
|
||||
import { RecipientRole, SendStatus } from '@documenso/prisma/client';
|
||||
import type { DocumentWithDetails } from '@documenso/prisma/types/document';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { AnimateGenericFadeInOut } from '@documenso/ui/components/animate/animate-generic-fade-in-out';
|
||||
import { RecipientActionAuthSelect } from '@documenso/ui/components/recipient/recipient-action-auth-select';
|
||||
import { RecipientRoleSelect } from '@documenso/ui/components/recipient/recipient-role-select';
|
||||
@ -41,32 +46,70 @@ import type { DocumentFlowStep } from './types';
|
||||
|
||||
export type AddSignersFormProps = {
|
||||
documentFlow: DocumentFlowStep;
|
||||
document: DocumentWithDetails;
|
||||
recipients: Recipient[];
|
||||
fields: Field[];
|
||||
isDocumentEnterprise: boolean;
|
||||
onSubmit: (_data: TAddSignersFormSchema) => void;
|
||||
isDocumentPdfLoaded: boolean;
|
||||
teamId?: number;
|
||||
};
|
||||
|
||||
export const AddSignersFormPartial = ({
|
||||
documentFlow,
|
||||
document,
|
||||
recipients,
|
||||
fields,
|
||||
isDocumentEnterprise,
|
||||
onSubmit,
|
||||
isDocumentPdfLoaded,
|
||||
teamId,
|
||||
}: AddSignersFormProps) => {
|
||||
const { _ } = useLingui();
|
||||
const { toast } = useToast();
|
||||
const { remaining } = useLimits();
|
||||
const { data: session } = useSession();
|
||||
const router = useRouter();
|
||||
|
||||
const user = session?.user;
|
||||
|
||||
const initialId = useId();
|
||||
const utils = trpc.useUtils();
|
||||
|
||||
const { currentStep, totalSteps, previousStep } = useStep();
|
||||
|
||||
const { mutateAsync: addSigners } = trpc.recipient.addSigners.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (newRecipients) => {
|
||||
utils.document.getDocumentWithDetailsById.setData(
|
||||
{
|
||||
id: document.id,
|
||||
teamId,
|
||||
},
|
||||
(oldData) => ({ ...(oldData || document), Recipient: newRecipients }),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: deleteSigner } = trpc.recipient.removeSigner.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (deletedRecipient) => {
|
||||
utils.document.getDocumentWithDetailsById.setData(
|
||||
{
|
||||
id: document.id,
|
||||
teamId,
|
||||
},
|
||||
(oldData) => {
|
||||
if (!oldData) return document;
|
||||
return {
|
||||
...oldData,
|
||||
Recipient: oldData.Recipient.filter((r) => r.id !== deletedRecipient.id),
|
||||
};
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const form = useForm<TAddSignersFormSchema>({
|
||||
resolver: zodResolver(ZAddSignersFormSchema),
|
||||
defaultValues: {
|
||||
@ -156,22 +199,11 @@ export const AddSignersFormPartial = ({
|
||||
});
|
||||
};
|
||||
|
||||
const onRemoveSigner = (index: number) => {
|
||||
const signer = signers[index];
|
||||
|
||||
if (hasBeenSentToRecipientId(signer.nativeId)) {
|
||||
toast({
|
||||
title: _(msg`Cannot remove signer`),
|
||||
description: _(msg`This signer has already received the document.`),
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
removeSigner(index);
|
||||
};
|
||||
|
||||
/*
|
||||
The self-signer is automatically saved on blur
|
||||
since the email input is focused after adding the self-signer.
|
||||
When the user clicks outside the input, the self-signer is saved in the db.
|
||||
*/
|
||||
const onAddSelfSigner = () => {
|
||||
if (emptySignerIndex !== -1) {
|
||||
setValue(`signers.${emptySignerIndex}.name`, user?.name ?? '');
|
||||
@ -193,6 +225,72 @@ export const AddSignersFormPartial = ({
|
||||
}
|
||||
};
|
||||
|
||||
const handleOnBlur = async (index: number) => {
|
||||
try {
|
||||
const currentSigner = form.getValues(`signers.${index}`);
|
||||
|
||||
if (!currentSigner.email) {
|
||||
return;
|
||||
}
|
||||
|
||||
await addSigners({
|
||||
documentId: document.id,
|
||||
teamId: teamId,
|
||||
signers: form.getValues('signers').map((signer) => ({
|
||||
...signer,
|
||||
actionAuth: signer.actionAuth || null,
|
||||
})),
|
||||
});
|
||||
|
||||
const isNewSigner = !currentSigner.nativeId;
|
||||
|
||||
toast({
|
||||
title: isNewSigner ? 'Signer added' : 'Signer updated',
|
||||
description: isNewSigner
|
||||
? 'The signer has been added to the document.'
|
||||
: 'The signer information has been updated.',
|
||||
});
|
||||
|
||||
router.refresh();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'An error occurred while updating the document recipient.',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveSigner = async (index: number) => {
|
||||
const signer = signers[index];
|
||||
|
||||
if (hasBeenSentToRecipientId(signer.nativeId)) {
|
||||
toast({
|
||||
title: 'Cannot remove signer',
|
||||
description: 'This signer has already received the document.',
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
removeSigner(index);
|
||||
|
||||
if (signer.nativeId) {
|
||||
await deleteSigner({
|
||||
documentId: document.id,
|
||||
teamId: teamId,
|
||||
recipientId: signer.nativeId,
|
||||
});
|
||||
|
||||
toast({
|
||||
title: 'Signer removed',
|
||||
description: 'The signer has been removed from the document.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DocumentFlowFormContainerHeader
|
||||
@ -240,6 +338,7 @@ export const AddSignersFormPartial = ({
|
||||
{...field}
|
||||
disabled={isSubmitting || hasBeenSentToRecipientId(signer.nativeId)}
|
||||
onKeyDown={onKeyDown}
|
||||
onBlur={() => void handleOnBlur(index)}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@ -266,6 +365,7 @@ export const AddSignersFormPartial = ({
|
||||
{...field}
|
||||
disabled={isSubmitting || hasBeenSentToRecipientId(signer.nativeId)}
|
||||
onKeyDown={onKeyDown}
|
||||
onBlur={() => void handleOnBlur(index)}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@ -319,7 +419,7 @@ export const AddSignersFormPartial = ({
|
||||
hasBeenSentToRecipientId(signer.nativeId) ||
|
||||
signers.length === 1
|
||||
}
|
||||
onClick={() => onRemoveSigner(index)}
|
||||
onClick={() => void handleRemoveSigner(index)}
|
||||
>
|
||||
<Trash className="h-5 w-5" />
|
||||
</button>
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
|
||||
import React, { useEffect, useId, useMemo, useState } from 'react';
|
||||
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { Trans, msg } from '@lingui/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
@ -10,11 +12,14 @@ import { Link2Icon, Plus, Trash } from 'lucide-react';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import { useFieldArray, useForm } from 'react-hook-form';
|
||||
|
||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||
import { ZRecipientAuthOptionsSchema } from '@documenso/lib/types/document-auth';
|
||||
import { nanoid } from '@documenso/lib/universal/id';
|
||||
import { generateRecipientPlaceholder } from '@documenso/lib/utils/templates';
|
||||
import type { TemplateDirectLink } from '@documenso/prisma/client';
|
||||
import { type Field, type Recipient, RecipientRole } from '@documenso/prisma/client';
|
||||
import type { TemplateWithDetails } from '@documenso/prisma/types/template';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { AnimateGenericFadeInOut } from '@documenso/ui/components/animate/animate-generic-fade-in-out';
|
||||
import { RecipientActionAuthSelect } from '@documenso/ui/components/recipient/recipient-action-auth-select';
|
||||
import { RecipientRoleSelect } from '@documenso/ui/components/recipient/recipient-role-select';
|
||||
@ -22,6 +27,7 @@ import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { FormErrorMessage } from '@documenso/ui/primitives/form/form-error-message';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { Checkbox } from '../checkbox';
|
||||
import {
|
||||
@ -46,6 +52,7 @@ export type AddTemplatePlaceholderRecipientsFormProps = {
|
||||
templateDirectLink: TemplateDirectLink | null;
|
||||
isEnterprise: boolean;
|
||||
isDocumentPdfLoaded: boolean;
|
||||
template: TemplateWithDetails;
|
||||
onSubmit: (_data: TAddTemplatePlacholderRecipientsFormSchema) => void;
|
||||
};
|
||||
|
||||
@ -57,7 +64,10 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
fields,
|
||||
isDocumentPdfLoaded,
|
||||
onSubmit,
|
||||
template,
|
||||
}: AddTemplatePlaceholderRecipientsFormProps) => {
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const initialId = useId();
|
||||
|
||||
const { _ } = useLingui();
|
||||
@ -71,6 +81,38 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
|
||||
const { currentStep, totalSteps, previousStep } = useStep();
|
||||
|
||||
const utils = trpc.useUtils();
|
||||
|
||||
const { mutateAsync: addTemplateSigners } = trpc.recipient.addTemplateSigners.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (newData) => {
|
||||
utils.template.getTemplateWithDetailsById.setData(
|
||||
{
|
||||
id: template.id,
|
||||
},
|
||||
(oldData) => ({ ...(oldData || template), ...newData }),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const { mutateAsync: removeTemplateSigner } = trpc.recipient.removeTemplateSigner.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (deletedRecipient) => {
|
||||
utils.template.getTemplateWithDetailsById.setData(
|
||||
{
|
||||
id: template.id,
|
||||
},
|
||||
(oldData) => {
|
||||
if (!oldData) return template;
|
||||
return {
|
||||
...oldData,
|
||||
recipients: oldData.Recipient.filter((r) => r.id !== deletedRecipient.id),
|
||||
};
|
||||
},
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const generateDefaultFormSigners = () => {
|
||||
if (recipients.length === 0) {
|
||||
return [
|
||||
@ -158,10 +200,6 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
setPlaceholderRecipientCount((count) => count + 1);
|
||||
};
|
||||
|
||||
const onRemoveSigner = (index: number) => {
|
||||
removeSigner(index);
|
||||
};
|
||||
|
||||
const isSignerDirectRecipient = (
|
||||
signer: TAddTemplatePlacholderRecipientsFormSchema['signers'][number],
|
||||
): boolean => {
|
||||
@ -171,6 +209,54 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
);
|
||||
};
|
||||
|
||||
const handleOnBlur = async (index: number) => {
|
||||
try {
|
||||
const currentSigner = form.getValues(`signers.${index}`);
|
||||
|
||||
if (!currentSigner.email) {
|
||||
return;
|
||||
}
|
||||
|
||||
await addTemplateSigners({
|
||||
templateId: template.id,
|
||||
teamId: template.teamId ?? undefined,
|
||||
signers: form.getValues('signers'),
|
||||
});
|
||||
|
||||
router.refresh();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
toast({
|
||||
title: 'Error',
|
||||
description: 'An error occurred while updating the template recipient.',
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveSigner = async (index: number) => {
|
||||
const signer = signers[index];
|
||||
|
||||
if (!signer) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeSigner(index);
|
||||
|
||||
if (signer.nativeId) {
|
||||
await removeTemplateSigner({
|
||||
templateId: template.id,
|
||||
teamId: template.teamId ?? undefined,
|
||||
recipientId: signer.nativeId,
|
||||
});
|
||||
|
||||
toast({
|
||||
title: 'Signer removed',
|
||||
description: 'The signer has been removed from the document.',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DocumentFlowFormContainerHeader
|
||||
@ -216,12 +302,8 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
type="email"
|
||||
placeholder={_(msg`Email`)}
|
||||
{...field}
|
||||
disabled={
|
||||
field.disabled ||
|
||||
isSubmitting ||
|
||||
signers[index].email === user?.email ||
|
||||
isSignerDirectRecipient(signer)
|
||||
}
|
||||
disabled={field.disabled || isSubmitting}
|
||||
onBlur={() => void handleOnBlur(index)}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@ -250,12 +332,8 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
<Input
|
||||
placeholder={_(msg`Name`)}
|
||||
{...field}
|
||||
disabled={
|
||||
field.disabled ||
|
||||
isSubmitting ||
|
||||
signers[index].email === user?.email ||
|
||||
isSignerDirectRecipient(signer)
|
||||
}
|
||||
disabled={field.disabled || isSubmitting}
|
||||
onBlur={() => void handleOnBlur(index)}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@ -291,7 +369,10 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
<FormControl>
|
||||
<RecipientRoleSelect
|
||||
{...field}
|
||||
onValueChange={field.onChange}
|
||||
onValueChange={(value) => {
|
||||
field.onChange(value);
|
||||
void handleOnBlur(index);
|
||||
}}
|
||||
disabled={isSubmitting}
|
||||
hideCCRecipients={isSignerDirectRecipient(signer)}
|
||||
/>
|
||||
@ -325,7 +406,7 @@ export const AddTemplatePlaceholderRecipientsFormPartial = ({
|
||||
type="button"
|
||||
className="col-span-1 mt-auto inline-flex h-10 w-10 items-center justify-center text-slate-500 hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={isSubmitting || signers.length === 1}
|
||||
onClick={() => onRemoveSigner(index)}
|
||||
onClick={() => void handleRemoveSigner(index)}
|
||||
>
|
||||
<Trash className="h-5 w-5" />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user