Compare commits
30 Commits
v1.10.0-rc
...
BLS
| Author | SHA1 | Date | |
|---|---|---|---|
| 69ab5eedd5 | |||
| 9007acd265 | |||
| fcf906db36 | |||
| 0e196a68cf | |||
| 643e37a0aa | |||
| f6a1b0bd2d | |||
| 28b28f7363 | |||
| f1b989bb78 | |||
| 63182f9587 | |||
| a9d7c3315d | |||
| de4197fba1 | |||
| 1b304b4f44 | |||
| 5c1a0c683f | |||
| 3af68e9e49 | |||
| ff712de07c | |||
| ce9bd6bb80 | |||
| 1447f03456 | |||
| 335e833170 | |||
| e20153c9c5 | |||
| 23c6c7935e | |||
| 01232624cc | |||
| 3045bcefc2 | |||
| cde5a43410 | |||
| bdf4db2c30 | |||
| 5747a0d52d | |||
| d2b83af9ea | |||
|
|
063fd32f18 | ||
|
|
231f51bd1f | ||
|
|
a8de8368a2 | ||
|
|
7dd331addf |
@@ -1,7 +1,4 @@
|
||||
# General Issues
|
||||
Contact: https://github.com/documenso/documenso/issues/new?assignees=&labels=bug&projects=&template=bug-report.yml
|
||||
|
||||
# Report critical issues privately to let us take appropriate action before publishing.
|
||||
Contact: mailto:security@documenso.com
|
||||
Preferred-Languages: en
|
||||
Canonical: https://documenso.com/.well-known/security.txt
|
||||
Contact: mailto:hello@bls-media.de
|
||||
Preferred-Languages: de
|
||||
Canonical: https://bls.media/.well-known/security.txt
|
||||
@@ -150,7 +150,7 @@ Example payload for the `document.created` event:
|
||||
"id": 52,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@documenso.com",
|
||||
"email": "signer@sign.bls.media",
|
||||
"name": "John Doe",
|
||||
"token": "vbT8hi3jKQmrFP_LN1WcS",
|
||||
"documentDeletedAt": null,
|
||||
@@ -212,7 +212,7 @@ Example payload for the `document.sent` event:
|
||||
"id": 52,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer2@documenso.com",
|
||||
"email": "signer2@sign.bls.media",
|
||||
"name": "Signer 2",
|
||||
"token": "vbT8hi3jKQmrFP_LN1WcS",
|
||||
"documentDeletedAt": null,
|
||||
@@ -230,7 +230,7 @@ Example payload for the `document.sent` event:
|
||||
"id": 53,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer1@documenso.com",
|
||||
"email": "signer1@sign.bls.media",
|
||||
"name": "Signer 1",
|
||||
"token": "HkrptwS42ZBXdRKj1TyUo",
|
||||
"documentDeletedAt": null,
|
||||
@@ -292,7 +292,7 @@ Example payload for the `document.opened` event:
|
||||
"id": 52,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer2@documenso.com",
|
||||
"email": "signer2@sign.bls.media",
|
||||
"name": "Signer 2",
|
||||
"token": "vbT8hi3jKQmrFP_LN1WcS",
|
||||
"documentDeletedAt": null,
|
||||
@@ -354,7 +354,7 @@ Example payload for the `document.signed` event:
|
||||
"id": 51,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer1@documenso.com",
|
||||
"email": "signer1@sign.bls.media",
|
||||
"name": "Signer 1",
|
||||
"token": "HkrptwS42ZBXdRKj1TyUo",
|
||||
"documentDeletedAt": null,
|
||||
@@ -419,7 +419,7 @@ Example payload for the `document.completed` event:
|
||||
"id": 50,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer2@documenso.com",
|
||||
"email": "signer2@sign.bls.media",
|
||||
"name": "Signer 2",
|
||||
"token": "vbT8hi3jKQmrFP_LN1WcS",
|
||||
"documentDeletedAt": null,
|
||||
@@ -440,7 +440,7 @@ Example payload for the `document.completed` event:
|
||||
"id": 51,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer1@documenso.com",
|
||||
"email": "signer1@sign.bls.media",
|
||||
"name": "Signer 1",
|
||||
"token": "HkrptwS42ZBXdRKj1TyUo",
|
||||
"documentDeletedAt": null,
|
||||
@@ -505,7 +505,7 @@ Example payload for the `document.rejected` event:
|
||||
"id": 52,
|
||||
"documentId": 10,
|
||||
"templateId": null,
|
||||
"email": "signer@documenso.com",
|
||||
"email": "signer@sign.bls.media",
|
||||
"name": "Signer",
|
||||
"token": "vbT8hi3jKQmrFP_LN1WcS",
|
||||
"documentDeletedAt": null,
|
||||
@@ -598,7 +598,7 @@ Example payload for the `document.rejected` event:
|
||||
"id": 7,
|
||||
"documentId": 7,
|
||||
"templateId": null,
|
||||
"email": "signer@documenso.com",
|
||||
"email": "signer@sign.bls.media",
|
||||
"name": "Signer",
|
||||
"token": "XkKx1HCs6Znm2UBJA2j6o",
|
||||
"documentDeletedAt": null,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { DocsThemeConfig } from 'nextra-theme-docs';
|
||||
import { useConfig } from 'nextra-theme-docs';
|
||||
|
||||
const themeConfig: DocsThemeConfig = {
|
||||
logo: <span>Documenso</span>,
|
||||
logo: <span>BLS sign</span>,
|
||||
head: function useHead() {
|
||||
const config = useConfig<{ title?: string; description?: string }>();
|
||||
|
||||
|
||||
@@ -216,9 +216,9 @@ export const TeamMemberInviteDialog = ({ trigger, ...props }: TeamMemberInviteDi
|
||||
|
||||
const downloadTemplate = () => {
|
||||
const data = [
|
||||
{ email: 'admin@documenso.com', role: 'Admin' },
|
||||
{ email: 'manager@documenso.com', role: 'Manager' },
|
||||
{ email: 'member@documenso.com', role: 'Member' },
|
||||
{ email: 'admin@sign.bls.media', role: 'Admin' },
|
||||
{ email: 'manager@sign.bls.media', role: 'Manager' },
|
||||
{ email: 'member@sign.bls.media', role: 'Member' },
|
||||
];
|
||||
|
||||
const csvContent =
|
||||
|
||||
@@ -3,8 +3,8 @@ import { useEffect, useLayoutEffect, useState } from 'react';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { type DocumentData, type Field, FieldType } from '@prisma/client';
|
||||
import type { DocumentMeta, Recipient, Signature, TemplateMeta } from '@prisma/client';
|
||||
import { type DocumentData, type Field, FieldType } from '@prisma/client';
|
||||
import { LucideChevronDown, LucideChevronUp } from 'lucide-react';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useSearchParams } from 'react-router';
|
||||
@@ -25,12 +25,11 @@ import type {
|
||||
} from '@documenso/trpc/server/field-router/schema';
|
||||
import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||
import { ElementVisible } from '@documenso/ui/primitives/element-visible';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { SignaturePadDialog } from '@documenso/ui/primitives/signature-pad/signature-pad-dialog';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { BrandingLogo } from '~/components/general/branding-logo';
|
||||
@@ -69,16 +68,8 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const {
|
||||
fullName,
|
||||
email,
|
||||
signature,
|
||||
signatureValid,
|
||||
setFullName,
|
||||
setEmail,
|
||||
setSignature,
|
||||
setSignatureValid,
|
||||
} = useRequiredDocumentSigningContext();
|
||||
const { fullName, email, signature, setFullName, setEmail, setSignature } =
|
||||
useRequiredDocumentSigningContext();
|
||||
|
||||
const [hasFinishedInit, setHasFinishedInit] = useState(false);
|
||||
const [hasDocumentLoaded, setHasDocumentLoaded] = useState(false);
|
||||
@@ -194,10 +185,6 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
|
||||
const onCompleteClick = async () => {
|
||||
try {
|
||||
if (hasSignatureField && !signatureValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const valid = validateFieldsInserted(pendingFields);
|
||||
|
||||
if (!valid) {
|
||||
@@ -419,34 +406,16 @@ export const EmbedDirectTemplateClientPage = ({
|
||||
<Trans>Signature</Trans>
|
||||
</Label>
|
||||
|
||||
<Card className="mt-2" gradient degrees={-120}>
|
||||
<CardContent className="p-0">
|
||||
<SignaturePad
|
||||
className="h-44 w-full"
|
||||
disabled={isThrottled || isSubmitting}
|
||||
defaultValue={signature ?? undefined}
|
||||
onChange={(value) => {
|
||||
setSignature(value);
|
||||
}}
|
||||
onValidityChange={(isValid) => {
|
||||
setSignatureValid(isValid);
|
||||
}}
|
||||
allowTypedSignature={Boolean(
|
||||
metadata &&
|
||||
'typedSignatureEnabled' in metadata &&
|
||||
metadata.typedSignatureEnabled,
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{hasSignatureField && !signatureValid && (
|
||||
<div className="text-destructive mt-2 text-sm">
|
||||
<Trans>
|
||||
Signature is too small. Please provide a more complete signature.
|
||||
</Trans>
|
||||
</div>
|
||||
)}
|
||||
<SignaturePadDialog
|
||||
className="mt-2"
|
||||
disabled={isThrottled || isSubmitting}
|
||||
disableAnimation
|
||||
value={signature ?? ''}
|
||||
onChange={(v) => setSignature(v ?? '')}
|
||||
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -20,7 +20,7 @@ export const EmbedDocumentCompleted = ({ name, signature }: EmbedDocumentComplet
|
||||
<div className="mt-8 w-full max-w-md">
|
||||
<SigningCard3D
|
||||
className="mx-auto w-full"
|
||||
name={name || 'Documenso'}
|
||||
name={name || 'BLS sign'}
|
||||
signature={signature}
|
||||
signingCelebrationImage={signingCelebration}
|
||||
/>
|
||||
|
||||
@@ -54,6 +54,8 @@ export const EmbedDocumentFields = ({
|
||||
onSignField={onSignField}
|
||||
onUnsignField={onUnsignField}
|
||||
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
||||
/>
|
||||
))
|
||||
.with(FieldType.INITIALS, () => (
|
||||
|
||||
@@ -21,13 +21,12 @@ import type { RecipientWithFields } from '@documenso/prisma/types/recipient-with
|
||||
import { trpc } from '@documenso/trpc/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';
|
||||
import { ElementVisible } from '@documenso/ui/primitives/element-visible';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import { PDFViewer } from '@documenso/ui/primitives/pdf-viewer';
|
||||
import { RadioGroup, RadioGroupItem } from '@documenso/ui/primitives/radio-group';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { SignaturePadDialog } from '@documenso/ui/primitives/signature-pad/signature-pad-dialog';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { BrandingLogo } from '~/components/general/branding-logo';
|
||||
@@ -70,15 +69,8 @@ export const EmbedSignDocumentClientPage = ({
|
||||
const { _ } = useLingui();
|
||||
const { toast } = useToast();
|
||||
|
||||
const {
|
||||
fullName,
|
||||
email,
|
||||
signature,
|
||||
signatureValid,
|
||||
setFullName,
|
||||
setSignature,
|
||||
setSignatureValid,
|
||||
} = useRequiredDocumentSigningContext();
|
||||
const { fullName, email, signature, setFullName, setSignature } =
|
||||
useRequiredDocumentSigningContext();
|
||||
|
||||
const [hasFinishedInit, setHasFinishedInit] = useState(false);
|
||||
const [hasDocumentLoaded, setHasDocumentLoaded] = useState(false);
|
||||
@@ -129,10 +121,6 @@ export const EmbedSignDocumentClientPage = ({
|
||||
|
||||
const onCompleteClick = async () => {
|
||||
try {
|
||||
if (hasSignatureField && !signatureValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const valid = validateFieldsInserted(fieldsRequiringValidation);
|
||||
|
||||
if (!valid) {
|
||||
@@ -432,34 +420,16 @@ export const EmbedSignDocumentClientPage = ({
|
||||
<Trans>Signature</Trans>
|
||||
</Label>
|
||||
|
||||
<Card className="mt-2" gradient degrees={-120}>
|
||||
<CardContent className="p-0">
|
||||
<SignaturePad
|
||||
className="h-44 w-full"
|
||||
disabled={isThrottled || isSubmitting}
|
||||
defaultValue={signature ?? undefined}
|
||||
onChange={(value) => {
|
||||
setSignature(value);
|
||||
}}
|
||||
onValidityChange={(isValid) => {
|
||||
setSignatureValid(isValid);
|
||||
}}
|
||||
allowTypedSignature={Boolean(
|
||||
metadata &&
|
||||
'typedSignatureEnabled' in metadata &&
|
||||
metadata.typedSignatureEnabled,
|
||||
)}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{hasSignatureField && !signatureValid && (
|
||||
<div className="text-destructive mt-2 text-sm">
|
||||
<Trans>
|
||||
Signature is too small. Please provide a more complete signature.
|
||||
</Trans>
|
||||
</div>
|
||||
)}
|
||||
<SignaturePadDialog
|
||||
className="mt-2"
|
||||
disabled={isThrottled || isSubmitting}
|
||||
disableAnimation
|
||||
value={signature ?? ''}
|
||||
onChange={(v) => setSignature(v ?? '')}
|
||||
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
@@ -477,9 +447,7 @@ export const EmbedSignDocumentClientPage = ({
|
||||
) : (
|
||||
<Button
|
||||
className={allowDocumentRejection ? 'col-start-2' : 'col-span-2'}
|
||||
disabled={
|
||||
isThrottled || (!isAssistantMode && hasSignatureField && !signatureValid)
|
||||
}
|
||||
disabled={isThrottled}
|
||||
loading={isSubmitting}
|
||||
onClick={() => throttledOnCompleteClick()}
|
||||
>
|
||||
|
||||
@@ -19,12 +19,15 @@ import {
|
||||
} from '@documenso/ui/primitives/form/form';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { SignaturePadDialog } from '@documenso/ui/primitives/signature-pad/signature-pad-dialog';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
export const ZProfileFormSchema = z.object({
|
||||
name: z.string().trim().min(1, { message: 'Please enter a valid name.' }),
|
||||
signature: z.string().min(1, 'Signature Pad cannot be empty'),
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1, { message: msg`Please enter a valid name.`.id }),
|
||||
signature: z.string().min(1, { message: msg`Signature Pad cannot be empty.`.id }),
|
||||
});
|
||||
|
||||
export const ZTwoFactorAuthTokenSchema = z.object({
|
||||
@@ -109,22 +112,20 @@ export const ProfileForm = ({ className }: ProfileFormProps) => {
|
||||
</Label>
|
||||
<Input id="email" type="email" className="bg-muted mt-2" value={user.email} disabled />
|
||||
</div>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="signature"
|
||||
render={({ field: { onChange } }) => (
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans>Signature</Trans>
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<SignaturePad
|
||||
className="h-44 w-full"
|
||||
<SignaturePadDialog
|
||||
disabled={isSubmitting}
|
||||
containerClassName={cn('rounded-lg border bg-background')}
|
||||
defaultValue={user.signature ?? undefined}
|
||||
value={value}
|
||||
onChange={(v) => onChange(v ?? '')}
|
||||
allowTypedSignature={true}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
@@ -134,7 +135,7 @@ export const ProfileForm = ({ className }: ProfileFormProps) => {
|
||||
</fieldset>
|
||||
|
||||
<Button type="submit" loading={isSubmitting} className="self-end">
|
||||
{isSubmitting ? <Trans>Updating profile...</Trans> : <Trans>Update profile</Trans>}
|
||||
<Trans>Update profile</Trans>
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
} from '@documenso/ui/primitives/form/form';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { PasswordInput } from '@documenso/ui/primitives/password-input';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { SignaturePadDialog } from '@documenso/ui/primitives/signature-pad/signature-pad-dialog';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import { UserProfileSkeleton } from '~/components/general/user-profile-skeleton';
|
||||
@@ -353,16 +353,15 @@ export const SignUpForm = ({
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="signature"
|
||||
render={({ field: { onChange } }) => (
|
||||
render={({ field: { onChange, value } }) => (
|
||||
<FormItem>
|
||||
<FormLabel>
|
||||
<Trans>Sign Here</Trans>
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<SignaturePad
|
||||
className="h-36 w-full"
|
||||
<SignaturePadDialog
|
||||
disabled={isSubmitting}
|
||||
containerClassName="mt-2 rounded-lg border bg-background"
|
||||
value={value}
|
||||
onChange={(v) => onChange(v ?? '')}
|
||||
/>
|
||||
</FormControl>
|
||||
@@ -535,7 +534,7 @@ export const SignUpForm = ({
|
||||
<Trans>
|
||||
By proceeding, you agree to our{' '}
|
||||
<Link
|
||||
to="https://documen.so/terms"
|
||||
to="https://bls.media/agb/"
|
||||
target="_blank"
|
||||
className="text-documenso-700 duration-200 hover:opacity-70"
|
||||
>
|
||||
@@ -543,7 +542,7 @@ export const SignUpForm = ({
|
||||
</Link>{' '}
|
||||
and{' '}
|
||||
<Link
|
||||
to="https://documen.so/privacy"
|
||||
to="https://bls.media/datenschutz/"
|
||||
target="_blank"
|
||||
className="text-documenso-700 duration-200 hover:opacity-70"
|
||||
>
|
||||
|
||||
@@ -308,7 +308,7 @@ export function TeamBrandingPreferencesForm({ team, settings }: TeamBrandingPref
|
||||
|
||||
<div className="flex flex-row justify-end space-x-4">
|
||||
<Button type="submit" loading={form.formState.isSubmitting}>
|
||||
<Trans>Save</Trans>
|
||||
<Trans>Update</Trans>
|
||||
</Button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -8,12 +8,15 @@ import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { useSession } from '@documenso/lib/client-only/providers/session';
|
||||
import { DOCUMENT_SIGNATURE_TYPES, DocumentSignatureType } from '@documenso/lib/constants/document';
|
||||
import {
|
||||
SUPPORTED_LANGUAGES,
|
||||
SUPPORTED_LANGUAGE_CODES,
|
||||
isValidLanguageCode,
|
||||
} from '@documenso/lib/constants/i18n';
|
||||
import { extractTeamSignatureSettings } from '@documenso/lib/utils/teams';
|
||||
import { trpc } from '@documenso/trpc/react';
|
||||
import { DocumentSignatureSettingsTooltip } from '@documenso/ui/components/document/document-signature-settings-tooltip';
|
||||
import { Alert } from '@documenso/ui/primitives/alert';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import {
|
||||
@@ -23,7 +26,9 @@ import {
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@documenso/ui/primitives/form/form';
|
||||
import { MultiSelectCombobox } from '@documenso/ui/primitives/multi-select-combobox';
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -38,8 +43,10 @@ const ZTeamDocumentPreferencesFormSchema = z.object({
|
||||
documentVisibility: z.nativeEnum(DocumentVisibility),
|
||||
documentLanguage: z.enum(SUPPORTED_LANGUAGE_CODES),
|
||||
includeSenderDetails: z.boolean(),
|
||||
typedSignatureEnabled: z.boolean(),
|
||||
includeSigningCertificate: z.boolean(),
|
||||
signatureTypes: z.array(z.nativeEnum(DocumentSignatureType)).min(1, {
|
||||
message: msg`At least one signature type must be enabled`.id,
|
||||
}),
|
||||
});
|
||||
|
||||
type TTeamDocumentPreferencesFormSchema = z.infer<typeof ZTeamDocumentPreferencesFormSchema>;
|
||||
@@ -67,10 +74,10 @@ export const TeamDocumentPreferencesForm = ({
|
||||
documentVisibility: settings?.documentVisibility ?? 'EVERYONE',
|
||||
documentLanguage: isValidLanguageCode(settings?.documentLanguage)
|
||||
? settings?.documentLanguage
|
||||
: 'en',
|
||||
: 'de',
|
||||
includeSenderDetails: settings?.includeSenderDetails ?? false,
|
||||
typedSignatureEnabled: settings?.typedSignatureEnabled ?? true,
|
||||
includeSigningCertificate: settings?.includeSigningCertificate ?? true,
|
||||
signatureTypes: extractTeamSignatureSettings(settings),
|
||||
},
|
||||
resolver: zodResolver(ZTeamDocumentPreferencesFormSchema),
|
||||
});
|
||||
@@ -84,7 +91,7 @@ export const TeamDocumentPreferencesForm = ({
|
||||
documentLanguage,
|
||||
includeSenderDetails,
|
||||
includeSigningCertificate,
|
||||
typedSignatureEnabled,
|
||||
signatureTypes,
|
||||
} = data;
|
||||
|
||||
await updateTeamDocumentPreferences({
|
||||
@@ -93,8 +100,10 @@ export const TeamDocumentPreferencesForm = ({
|
||||
documentVisibility,
|
||||
documentLanguage,
|
||||
includeSenderDetails,
|
||||
typedSignatureEnabled,
|
||||
includeSigningCertificate,
|
||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -190,6 +199,44 @@ export const TeamDocumentPreferencesForm = ({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="signatureTypes"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel className="flex flex-row items-center">
|
||||
<Trans>Default Signature Settings</Trans>
|
||||
<DocumentSignatureSettingsTooltip />
|
||||
</FormLabel>
|
||||
|
||||
<FormControl>
|
||||
<MultiSelectCombobox
|
||||
options={Object.values(DOCUMENT_SIGNATURE_TYPES).map((option) => ({
|
||||
label: _(option.label),
|
||||
value: option.value,
|
||||
}))}
|
||||
selectedValues={field.value}
|
||||
onChange={field.onChange}
|
||||
className="bg-background w-full"
|
||||
enableSearch={false}
|
||||
emptySelectionPlaceholder="Select signature types"
|
||||
testId="signature-types-combobox"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
{form.formState.errors.signatureTypes ? (
|
||||
<FormMessage />
|
||||
) : (
|
||||
<FormDescription>
|
||||
<Trans>
|
||||
Controls which signatures are allowed to be used when signing a document.
|
||||
</Trans>
|
||||
</FormDescription>
|
||||
)}
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="includeSenderDetails"
|
||||
@@ -238,36 +285,6 @@ export const TeamDocumentPreferencesForm = ({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="typedSignatureEnabled"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex-1">
|
||||
<FormLabel>
|
||||
<Trans>Enable Typed Signature</Trans>
|
||||
</FormLabel>
|
||||
|
||||
<div>
|
||||
<FormControl className="block">
|
||||
<Switch
|
||||
ref={field.ref}
|
||||
name={field.name}
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
</div>
|
||||
|
||||
<FormDescription>
|
||||
<Trans>
|
||||
Controls whether the recipients can sign the documents using a typed signature.
|
||||
Enable or disable the typed signature globally.
|
||||
</Trans>
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="includeSigningCertificate"
|
||||
@@ -301,7 +318,7 @@ export const TeamDocumentPreferencesForm = ({
|
||||
|
||||
<div className="flex flex-row justify-end space-x-4">
|
||||
<Button type="submit" loading={form.formState.isSubmitting}>
|
||||
<Trans>Save</Trans>
|
||||
<Trans>Update</Trans>
|
||||
</Button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -205,14 +205,12 @@ export function AppCommandMenu({ open, onOpenChange }: AppCommandMenuProps) {
|
||||
</CommandGroup>
|
||||
<CommandGroup className="mx-2 p-0 pb-2" heading={_(msg`Settings`)}>
|
||||
<Commands push={push} pages={SETTINGS_PAGES} />
|
||||
</CommandGroup>
|
||||
<CommandGroup className="mx-2 p-0 pb-2" heading={_(msg`Preferences`)}>
|
||||
<CommandItem className="-mx-2 -my-1 rounded-lg" onSelect={() => addPage('language')}>
|
||||
Change language
|
||||
</CommandItem>
|
||||
<CommandItem className="-mx-2 -my-1 rounded-lg" onSelect={() => addPage('theme')}>
|
||||
Change theme
|
||||
</CommandItem>
|
||||
<CommandItem className="-mx-2 -my-1 rounded-lg" onSelect={() => addPage('language')}>
|
||||
Sprache
|
||||
</CommandItem>
|
||||
<CommandItem className="-mx-2 -my-1 rounded-lg" onSelect={() => addPage('theme')}>
|
||||
Aussehen
|
||||
</CommandItem>
|
||||
</CommandGroup>
|
||||
{searchResults.length > 0 && (
|
||||
<CommandGroup className="mx-2 p-0 pb-2" heading={_(msg`Your documents`)}>
|
||||
|
||||
@@ -50,7 +50,7 @@ export const AppNavMobile = ({ isMenuOpen, onMenuOpenChange }: AppNavMobileProps
|
||||
<Link to="/" onClick={handleMenuItemClick}>
|
||||
<img
|
||||
src={LogoImage}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="dark:invert"
|
||||
width={170}
|
||||
height={25}
|
||||
@@ -83,7 +83,7 @@ export const AppNavMobile = ({ isMenuOpen, onMenuOpenChange }: AppNavMobileProps
|
||||
</div>
|
||||
|
||||
<p className="text-muted-foreground text-sm">
|
||||
© {new Date().getFullYear()} Documenso, Inc. <br /> All rights reserved.
|
||||
© {new Date().getFullYear()} Made by BLS media
|
||||
</p>
|
||||
</div>
|
||||
</SheetContent>
|
||||
|
||||
@@ -128,7 +128,7 @@ export const DirectTemplateConfigureForm = ({
|
||||
derivedRecipientAccessAuth !== null ||
|
||||
user?.email !== undefined
|
||||
}
|
||||
placeholder="recipient@documenso.com"
|
||||
placeholder="recipient@sign.bls.media"
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ import type {
|
||||
} from '@documenso/trpc/server/field-router/schema';
|
||||
import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||
import {
|
||||
DocumentFlowFormContainerContent,
|
||||
DocumentFlowFormContainerFooter,
|
||||
@@ -35,7 +34,7 @@ import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/ty
|
||||
import { ElementVisible } from '@documenso/ui/primitives/element-visible';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { SignaturePadDialog } from '@documenso/ui/primitives/signature-pad/signature-pad-dialog';
|
||||
import { useStep } from '@documenso/ui/primitives/stepper';
|
||||
|
||||
import { DocumentSigningCheckboxField } from '~/components/general/document-signing/document-signing-checkbox-field';
|
||||
@@ -73,8 +72,7 @@ export const DirectTemplateSigningForm = ({
|
||||
template,
|
||||
onSubmit,
|
||||
}: DirectTemplateSigningFormProps) => {
|
||||
const { fullName, signature, signatureValid, setFullName, setSignature } =
|
||||
useRequiredDocumentSigningContext();
|
||||
const { fullName, signature, setFullName, setSignature } = useRequiredDocumentSigningContext();
|
||||
|
||||
const [localFields, setLocalFields] = useState<DirectTemplateLocalField[]>(directRecipientFields);
|
||||
const [validateUninsertedFields, setValidateUninsertedFields] = useState(false);
|
||||
@@ -135,8 +133,6 @@ export const DirectTemplateSigningForm = ({
|
||||
);
|
||||
};
|
||||
|
||||
const hasSignatureField = localFields.some((field) => field.type === FieldType.SIGNATURE);
|
||||
|
||||
const uninsertedFields = useMemo(() => {
|
||||
return sortFieldsByPosition(localFields.filter((field) => !field.inserted));
|
||||
}, [localFields]);
|
||||
@@ -149,10 +145,6 @@ export const DirectTemplateSigningForm = ({
|
||||
const handleSubmit = async () => {
|
||||
setValidateUninsertedFields(true);
|
||||
|
||||
if (hasSignatureField && !signatureValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isFieldsValid = validateFieldsInserted(localFields);
|
||||
|
||||
if (!isFieldsValid) {
|
||||
@@ -240,6 +232,8 @@ export const DirectTemplateSigningForm = ({
|
||||
onSignField={onSignField}
|
||||
onUnsignField={onUnsignField}
|
||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||
/>
|
||||
))
|
||||
.with(FieldType.INITIALS, () => (
|
||||
@@ -384,19 +378,15 @@ export const DirectTemplateSigningForm = ({
|
||||
<Trans>Signature</Trans>
|
||||
</Label>
|
||||
|
||||
<Card className="mt-2" gradient degrees={-120}>
|
||||
<CardContent className="p-0">
|
||||
<SignaturePad
|
||||
className="h-44 w-full"
|
||||
disabled={isSubmitting}
|
||||
defaultValue={signature ?? undefined}
|
||||
onChange={(value) => {
|
||||
setSignature(value);
|
||||
}}
|
||||
allowTypedSignature={template.templateMeta?.typedSignatureEnabled}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<SignaturePadDialog
|
||||
className="mt-2"
|
||||
disabled={isSubmitting}
|
||||
value={signature ?? ''}
|
||||
onChange={(value) => setSignature(value)}
|
||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,11 +20,10 @@ import { trpc } from '@documenso/trpc/react';
|
||||
import { FieldToolTip } from '@documenso/ui/components/field/field-tooltip';
|
||||
import { cn } from '@documenso/ui/lib/utils';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Card, CardContent } from '@documenso/ui/primitives/card';
|
||||
import { Input } from '@documenso/ui/primitives/input';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import { RadioGroup, RadioGroupItem } from '@documenso/ui/primitives/radio-group';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { SignaturePadDialog } from '@documenso/ui/primitives/signature-pad/signature-pad-dialog';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
import {
|
||||
@@ -71,8 +70,7 @@ export const DocumentSigningForm = ({
|
||||
|
||||
const assistantSignersId = useId();
|
||||
|
||||
const { fullName, signature, setFullName, setSignature, signatureValid, setSignatureValid } =
|
||||
useRequiredDocumentSigningContext();
|
||||
const { fullName, signature, setFullName, setSignature } = useRequiredDocumentSigningContext();
|
||||
|
||||
const [validateUninsertedFields, setValidateUninsertedFields] = useState(false);
|
||||
const [isConfirmationDialogOpen, setIsConfirmationDialogOpen] = useState(false);
|
||||
@@ -120,10 +118,6 @@ export const DocumentSigningForm = ({
|
||||
|
||||
const isFieldsValid = validateFieldsInserted(fieldsRequiringValidation);
|
||||
|
||||
if (hasSignatureField && !signatureValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isFieldsValid) {
|
||||
return;
|
||||
}
|
||||
@@ -423,32 +417,15 @@ export const DocumentSigningForm = ({
|
||||
<Trans>Signature</Trans>
|
||||
</Label>
|
||||
|
||||
<Card className="mt-2" gradient degrees={-120}>
|
||||
<CardContent className="p-0">
|
||||
<SignaturePad
|
||||
className="h-44 w-full"
|
||||
disabled={isSubmitting}
|
||||
defaultValue={signature ?? undefined}
|
||||
onValidityChange={(isValid) => {
|
||||
setSignatureValid(isValid);
|
||||
}}
|
||||
onChange={(value) => {
|
||||
if (signatureValid) {
|
||||
setSignature(value);
|
||||
}
|
||||
}}
|
||||
allowTypedSignature={document.documentMeta?.typedSignatureEnabled}
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{!signatureValid && (
|
||||
<div className="text-destructive mt-2 text-sm">
|
||||
<Trans>
|
||||
Signature is too small. Please provide a more complete signature.
|
||||
</Trans>
|
||||
</div>
|
||||
)}
|
||||
<SignaturePadDialog
|
||||
className="mt-2"
|
||||
disabled={isSubmitting}
|
||||
value={signature ?? ''}
|
||||
onChange={(v) => setSignature(v ?? '')}
|
||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -177,6 +177,8 @@ export const DocumentSigningPageView = ({
|
||||
key={field.id}
|
||||
field={field}
|
||||
typedSignatureEnabled={documentMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={documentMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={documentMeta?.drawSignatureEnabled}
|
||||
/>
|
||||
))
|
||||
.with(FieldType.INITIALS, () => (
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { createContext, useContext, useState } from 'react';
|
||||
|
||||
import { isBase64Image } from '@documenso/lib/constants/signatures';
|
||||
|
||||
export type DocumentSigningContextValue = {
|
||||
fullName: string;
|
||||
@@ -7,8 +9,6 @@ export type DocumentSigningContextValue = {
|
||||
setEmail: (_value: string) => void;
|
||||
signature: string | null;
|
||||
setSignature: (_value: string | null) => void;
|
||||
signatureValid: boolean;
|
||||
setSignatureValid: (_valid: boolean) => void;
|
||||
};
|
||||
|
||||
const DocumentSigningContext = createContext<DocumentSigningContextValue | null>(null);
|
||||
@@ -31,6 +31,9 @@ export interface DocumentSigningProviderProps {
|
||||
fullName?: string | null;
|
||||
email?: string | null;
|
||||
signature?: string | null;
|
||||
typedSignatureEnabled?: boolean;
|
||||
uploadSignatureEnabled?: boolean;
|
||||
drawSignatureEnabled?: boolean;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
@@ -38,18 +41,31 @@ export const DocumentSigningProvider = ({
|
||||
fullName: initialFullName,
|
||||
email: initialEmail,
|
||||
signature: initialSignature,
|
||||
typedSignatureEnabled = true,
|
||||
uploadSignatureEnabled = true,
|
||||
drawSignatureEnabled = true,
|
||||
children,
|
||||
}: DocumentSigningProviderProps) => {
|
||||
const [fullName, setFullName] = useState(initialFullName || '');
|
||||
const [email, setEmail] = useState(initialEmail || '');
|
||||
const [signature, setSignature] = useState(initialSignature || null);
|
||||
const [signatureValid, setSignatureValid] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (initialSignature) {
|
||||
setSignature(initialSignature);
|
||||
}
|
||||
}, [initialSignature]);
|
||||
// Ensure the user signature doesn't show up if it's not allowed.
|
||||
const [signature, setSignature] = useState(
|
||||
(() => {
|
||||
const sig = initialSignature || '';
|
||||
const isBase64 = isBase64Image(sig);
|
||||
|
||||
if (isBase64 && (uploadSignatureEnabled || drawSignatureEnabled)) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
if (!isBase64 && typedSignatureEnabled) {
|
||||
return sig;
|
||||
}
|
||||
|
||||
return null;
|
||||
})(),
|
||||
);
|
||||
|
||||
return (
|
||||
<DocumentSigningContext.Provider
|
||||
@@ -60,8 +76,6 @@ export const DocumentSigningProvider = ({
|
||||
setEmail,
|
||||
signature,
|
||||
setSignature,
|
||||
signatureValid,
|
||||
setSignatureValid,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -31,10 +31,7 @@ import { Textarea } from '@documenso/ui/primitives/textarea';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
const ZRejectDocumentFormSchema = z.object({
|
||||
reason: z
|
||||
.string()
|
||||
.min(5, msg`Please provide a reason`)
|
||||
.max(500, msg`Reason must be less than 500 characters`),
|
||||
reason: z.string().max(500, msg`Reason must be less than 500 characters`),
|
||||
});
|
||||
|
||||
type TRejectDocumentFormSchema = z.infer<typeof ZRejectDocumentFormSchema>;
|
||||
@@ -141,7 +138,7 @@ export function DocumentSigningRejectDialog({
|
||||
<Textarea
|
||||
{...field}
|
||||
rows={4}
|
||||
placeholder="Please provide a reason for rejecting this document"
|
||||
placeholder="Bitte gib' einen Grund für die Ablehnung an."
|
||||
disabled={form.formState.isSubmitting}
|
||||
/>
|
||||
</FormControl>
|
||||
|
||||
@@ -17,7 +17,6 @@ import type {
|
||||
} from '@documenso/trpc/server/field-router/schema';
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
import { Dialog, DialogContent, DialogFooter, DialogTitle } from '@documenso/ui/primitives/dialog';
|
||||
import { Label } from '@documenso/ui/primitives/label';
|
||||
import { SignaturePad } from '@documenso/ui/primitives/signature-pad';
|
||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||
|
||||
@@ -29,11 +28,14 @@ import { useRequiredDocumentSigningContext } from './document-signing-provider';
|
||||
import { useDocumentSigningRecipientContext } from './document-signing-recipient-provider';
|
||||
|
||||
type SignatureFieldState = 'empty' | 'signed-image' | 'signed-text';
|
||||
|
||||
export type DocumentSigningSignatureFieldProps = {
|
||||
field: FieldWithSignature;
|
||||
onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise<void> | void;
|
||||
onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise<void> | void;
|
||||
typedSignatureEnabled?: boolean;
|
||||
uploadSignatureEnabled?: boolean;
|
||||
drawSignatureEnabled?: boolean;
|
||||
};
|
||||
|
||||
export const DocumentSigningSignatureField = ({
|
||||
@@ -41,6 +43,8 @@ export const DocumentSigningSignatureField = ({
|
||||
onSignField,
|
||||
onUnsignField,
|
||||
typedSignatureEnabled,
|
||||
uploadSignatureEnabled,
|
||||
drawSignatureEnabled,
|
||||
}: DocumentSigningSignatureFieldProps) => {
|
||||
const { _ } = useLingui();
|
||||
const { toast } = useToast();
|
||||
@@ -52,12 +56,8 @@ export const DocumentSigningSignatureField = ({
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [fontSize, setFontSize] = useState(2);
|
||||
|
||||
const {
|
||||
signature: providedSignature,
|
||||
setSignature: setProvidedSignature,
|
||||
signatureValid,
|
||||
setSignatureValid,
|
||||
} = useRequiredDocumentSigningContext();
|
||||
const { signature: providedSignature, setSignature: setProvidedSignature } =
|
||||
useRequiredDocumentSigningContext();
|
||||
|
||||
const { executeActionAuthProcedure } = useRequiredDocumentSigningAuthContext();
|
||||
|
||||
@@ -89,7 +89,7 @@ export const DocumentSigningSignatureField = ({
|
||||
}, [field.inserted, signature?.signatureImageAsBase64]);
|
||||
|
||||
const onPreSign = () => {
|
||||
if (!providedSignature || !signatureValid) {
|
||||
if (!providedSignature) {
|
||||
setShowSignatureModal(true);
|
||||
return false;
|
||||
}
|
||||
@@ -102,6 +102,7 @@ export const DocumentSigningSignatureField = ({
|
||||
const onDialogSignClick = () => {
|
||||
setShowSignatureModal(false);
|
||||
setProvidedSignature(localSignature);
|
||||
|
||||
if (!localSignature) {
|
||||
return;
|
||||
}
|
||||
@@ -116,14 +117,14 @@ export const DocumentSigningSignatureField = ({
|
||||
try {
|
||||
const value = signature || providedSignature;
|
||||
|
||||
if (!value || (signature && !signatureValid)) {
|
||||
if (!value) {
|
||||
setShowSignatureModal(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const isTypedSignature = !value.startsWith('data:image');
|
||||
|
||||
if (isTypedSignature && !typedSignatureEnabled) {
|
||||
if (isTypedSignature && typedSignatureEnabled === false) {
|
||||
toast({
|
||||
title: _(msg`Error`),
|
||||
description: _(msg`Typed signatures are not allowed. Please draw your signature.`),
|
||||
@@ -275,29 +276,14 @@ export const DocumentSigningSignatureField = ({
|
||||
</Trans>
|
||||
</DialogTitle>
|
||||
|
||||
<div className="">
|
||||
<Label htmlFor="signature">
|
||||
<Trans>Signature</Trans>
|
||||
</Label>
|
||||
|
||||
<div className="border-border mt-2 rounded-md border">
|
||||
<SignaturePad
|
||||
id="signature"
|
||||
className="h-44 w-full"
|
||||
onChange={(value) => setLocalSignature(value)}
|
||||
allowTypedSignature={typedSignatureEnabled}
|
||||
onValidityChange={(isValid) => {
|
||||
setSignatureValid(isValid);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{!signatureValid && (
|
||||
<div className="text-destructive mt-2 text-sm">
|
||||
<Trans>Signature is too small. Please provide a more complete signature.</Trans>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<SignaturePad
|
||||
className="mt-2"
|
||||
value={localSignature ?? ''}
|
||||
onChange={({ value }) => setLocalSignature(value)}
|
||||
typedSignatureEnabled={typedSignatureEnabled}
|
||||
uploadSignatureEnabled={uploadSignatureEnabled}
|
||||
drawSignatureEnabled={drawSignatureEnabled}
|
||||
/>
|
||||
|
||||
<DocumentSigningDisclosure />
|
||||
|
||||
@@ -317,7 +303,7 @@ export const DocumentSigningSignatureField = ({
|
||||
<Button
|
||||
type="button"
|
||||
className="flex-1"
|
||||
disabled={!localSignature || !signatureValid}
|
||||
disabled={!localSignature}
|
||||
onClick={() => onDialogSignClick()}
|
||||
>
|
||||
<Trans>Sign</Trans>
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useLingui } from '@lingui/react';
|
||||
import { DocumentDistributionMethod, DocumentStatus } from '@prisma/client';
|
||||
import { useNavigate, useSearchParams } from 'react-router';
|
||||
|
||||
import { DocumentSignatureType } from '@documenso/lib/constants/document';
|
||||
import { isValidLanguageCode } from '@documenso/lib/constants/i18n';
|
||||
import {
|
||||
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
@@ -71,7 +72,7 @@ export const DocumentEditForm = ({
|
||||
|
||||
const { recipients, fields } = document;
|
||||
|
||||
const { mutateAsync: updateDocumentSettings } = trpc.document.setSettingsForDocument.useMutation({
|
||||
const { mutateAsync: updateDocument } = trpc.document.updateDocument.useMutation({
|
||||
...DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
onSuccess: (newData) => {
|
||||
utils.document.getDocumentWithDetailsById.setData(
|
||||
@@ -174,9 +175,9 @@ export const DocumentEditForm = ({
|
||||
|
||||
const onAddSettingsFormSubmit = async (data: TAddSettingsFormSchema) => {
|
||||
try {
|
||||
const { timezone, dateFormat, redirectUrl, language } = data.meta;
|
||||
const { timezone, dateFormat, redirectUrl, language, signatureTypes } = data.meta;
|
||||
|
||||
await updateDocumentSettings({
|
||||
await updateDocument({
|
||||
documentId: document.id,
|
||||
data: {
|
||||
title: data.title,
|
||||
@@ -190,6 +191,9 @@ export const DocumentEditForm = ({
|
||||
dateFormat,
|
||||
redirectUrl,
|
||||
language: isValidLanguageCode(language) ? language : undefined,
|
||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -213,7 +217,7 @@ export const DocumentEditForm = ({
|
||||
signingOrder: data.signingOrder,
|
||||
}),
|
||||
|
||||
updateDocumentSettings({
|
||||
updateDocument({
|
||||
documentId: document.id,
|
||||
meta: {
|
||||
allowDictateNextSigner: data.allowDictateNextSigner,
|
||||
@@ -249,14 +253,6 @@ export const DocumentEditForm = ({
|
||||
fields: data.fields,
|
||||
});
|
||||
|
||||
await updateDocumentSettings({
|
||||
documentId: document.id,
|
||||
|
||||
meta: {
|
||||
typedSignatureEnabled: data.typedSignatureEnabled,
|
||||
},
|
||||
});
|
||||
|
||||
// Clear all field data from localStorage
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
@@ -386,7 +382,6 @@ export const DocumentEditForm = ({
|
||||
fields={fields}
|
||||
onSubmit={onAddFieldsFormSubmit}
|
||||
isDocumentPdfLoaded={isDocumentPdfLoaded}
|
||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||
teamId={team?.id}
|
||||
/>
|
||||
|
||||
|
||||
@@ -166,6 +166,7 @@ export const DocumentPageViewDropdown = ({ document }: DocumentPageViewDropdownP
|
||||
|
||||
<DocumentResendDialog document={document} recipients={nonSignedRecipients} />
|
||||
|
||||
{/* DOKUMENT SHARING KARTE DEAKTIVIERT
|
||||
<DocumentShareButton
|
||||
documentId={document.id}
|
||||
token={isOwner ? undefined : recipient?.token}
|
||||
@@ -177,7 +178,8 @@ export const DocumentPageViewDropdown = ({ document }: DocumentPageViewDropdownP
|
||||
</div>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
/>
|
||||
/>
|
||||
*/}
|
||||
</DropdownMenuContent>
|
||||
|
||||
<DocumentDeleteDialog
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { HTMLAttributes } from 'react';
|
||||
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Braces, CreditCard, Globe2Icon, Lock, User, Users, Webhook } from 'lucide-react';
|
||||
import { Braces, CreditCard, Globe2Icon, Lock, User, Users, Webhook, Bot } from 'lucide-react';
|
||||
import { useLocation } from 'react-router';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
@@ -96,6 +96,13 @@ export const SettingsDesktopNav = ({ className, ...props }: SettingsDesktopNavPr
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
<Link to="https://bot.bls.media/medi">
|
||||
<Button variant="ghost">
|
||||
<Bot className="mr-2 h-5 w-5" />
|
||||
Hilfe
|
||||
</Button>
|
||||
</Link>
|
||||
|
||||
{isBillingEnabled && (
|
||||
<Link to="/settings/billing">
|
||||
<Button
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Skeleton } from '@documenso/ui/primitives/skeleton';
|
||||
export default function DocumentEditSkeleton() {
|
||||
return (
|
||||
<div className="mx-auto -mt-4 flex w-full max-w-screen-xl flex-col px-4 md:px-8">
|
||||
<Link to="/documents" className="flex grow-0 items-center text-[#7AC455] hover:opacity-80">
|
||||
<Link to="/documents" className="flex grow-0 items-center text-[#FF6B3D] hover:opacity-80">
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Documents</Trans>
|
||||
</Link>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import { DocumentSignatureType } from '@documenso/lib/constants/document';
|
||||
import { isValidLanguageCode } from '@documenso/lib/constants/i18n';
|
||||
import {
|
||||
DO_NOT_INVALIDATE_QUERY_ON_MUTATION,
|
||||
@@ -124,6 +125,8 @@ export const TemplateEditForm = ({
|
||||
});
|
||||
|
||||
const onAddSettingsFormSubmit = async (data: TAddTemplateSettingsFormSchema) => {
|
||||
const { signatureTypes } = data.meta;
|
||||
|
||||
try {
|
||||
await updateTemplateSettings({
|
||||
templateId: template.id,
|
||||
@@ -136,6 +139,9 @@ export const TemplateEditForm = ({
|
||||
},
|
||||
meta: {
|
||||
...data.meta,
|
||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||
language: isValidLanguageCode(data.meta.language) ? data.meta.language : undefined,
|
||||
},
|
||||
});
|
||||
@@ -188,13 +194,6 @@ export const TemplateEditForm = ({
|
||||
fields: data.fields,
|
||||
});
|
||||
|
||||
await updateTemplateSettings({
|
||||
templateId: template.id,
|
||||
meta: {
|
||||
typedSignatureEnabled: data.typedSignatureEnabled,
|
||||
},
|
||||
});
|
||||
|
||||
// Clear all field data from localStorage
|
||||
for (let i = 0; i < localStorage.length; i++) {
|
||||
const key = localStorage.key(i);
|
||||
@@ -286,7 +285,6 @@ export const TemplateEditForm = ({
|
||||
fields={fields}
|
||||
onSubmit={onAddFieldsFormSubmit}
|
||||
teamId={team?.id}
|
||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||
/>
|
||||
</Stepper>
|
||||
</DocumentFlowFormContainer>
|
||||
|
||||
@@ -196,6 +196,7 @@ export const DocumentsTableActionDropdown = ({ row }: DocumentsTableActionDropdo
|
||||
|
||||
<DocumentResendDialog document={row} recipients={nonSignedRecipients} />
|
||||
|
||||
{/* DOKUMENT SHARING KARTE DEAKTIVIERT
|
||||
<DocumentShareButton
|
||||
documentId={row.id}
|
||||
token={isOwner ? undefined : recipient?.token}
|
||||
@@ -208,6 +209,8 @@ export const DocumentsTableActionDropdown = ({ row }: DocumentsTableActionDropdo
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
/>
|
||||
*/}
|
||||
|
||||
</DropdownMenuContent>
|
||||
|
||||
<DocumentDeleteDialog
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { useLingui } from '@lingui/react';
|
||||
import { Bird, CheckCircle2 } from 'lucide-react';
|
||||
import { FileSearch2, FileCheck } from 'lucide-react';
|
||||
import { match } from 'ts-pattern';
|
||||
|
||||
import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status';
|
||||
@@ -18,22 +18,22 @@ export const DocumentsTableEmptyState = ({ status }: DocumentsTableEmptyStatePro
|
||||
.with(ExtendedDocumentStatus.COMPLETED, () => ({
|
||||
title: msg`Nothing to do`,
|
||||
message: msg`There are no completed documents yet. Documents that you have created or received will appear here once completed.`,
|
||||
icon: CheckCircle2,
|
||||
icon: FileCheck,
|
||||
}))
|
||||
.with(ExtendedDocumentStatus.DRAFT, () => ({
|
||||
title: msg`No active drafts`,
|
||||
message: msg`There are no active drafts at the current moment. You can upload a document to start drafting.`,
|
||||
icon: CheckCircle2,
|
||||
icon: FileCheck,
|
||||
}))
|
||||
.with(ExtendedDocumentStatus.ALL, () => ({
|
||||
title: msg`We're all empty`,
|
||||
message: msg`You have not yet created or received any documents. To create a document please upload one.`,
|
||||
icon: Bird,
|
||||
icon: FileSearch2,
|
||||
}))
|
||||
.otherwise(() => ({
|
||||
title: msg`Nothing to do`,
|
||||
message: msg`All documents have been processed. Any new documents that are sent or received will show here.`,
|
||||
icon: CheckCircle2,
|
||||
icon: FileCheck,
|
||||
}));
|
||||
|
||||
return (
|
||||
|
||||
@@ -26,7 +26,7 @@ function PosthogInit() {
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const locale = detect(fromHtmlTag('lang')) || 'en';
|
||||
const locale = detect(fromHtmlTag('lang')) || 'de';
|
||||
|
||||
await dynamicActivate(locale);
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ export default function DocumentPage() {
|
||||
<DocumentRecipientLinkCopyDialog recipients={recipients} />
|
||||
)}
|
||||
|
||||
<Link to={documentRootPath} className="flex items-center text-[#7AC455] hover:opacity-80">
|
||||
<Link to={documentRootPath} className="flex items-center text-[#FF6B3D] hover:opacity-80">
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Documents</Trans>
|
||||
</Link>
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function DocumentEditPage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto -mt-4 w-full max-w-screen-xl px-4 md:px-8">
|
||||
<Link to={documentRootPath} className="flex items-center text-[#7AC455] hover:opacity-80">
|
||||
<Link to={documentRootPath} className="flex items-center text-[#FF6B3D] hover:opacity-80">
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Documents</Trans>
|
||||
</Link>
|
||||
|
||||
@@ -123,7 +123,7 @@ export default function DocumentsLogsPage({ loaderData }: Route.ComponentProps)
|
||||
<div className="mx-auto -mt-4 w-full max-w-screen-xl px-4 md:px-8">
|
||||
<Link
|
||||
to={`${documentRootPath}/${document.id}`}
|
||||
className="flex items-center text-[#7AC455] hover:opacity-80"
|
||||
className="flex items-center text-[#FF6B3D] hover:opacity-80"
|
||||
>
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Document</Trans>
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function TemplatePage() {
|
||||
|
||||
return (
|
||||
<div className="mx-auto -mt-4 w-full max-w-screen-xl px-4 md:px-8">
|
||||
<Link to={templateRootPath} className="flex items-center text-[#7AC455] hover:opacity-80">
|
||||
<Link to={templateRootPath} className="flex items-center text-[#FF6B3D] hover:opacity-80">
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Templates</Trans>
|
||||
</Link>
|
||||
|
||||
@@ -65,7 +65,7 @@ export default function TemplateEditPage() {
|
||||
<div>
|
||||
<Link
|
||||
to={`${templateRootPath}/${template.id}`}
|
||||
className="flex items-center text-[#7AC455] hover:opacity-80"
|
||||
className="flex items-center text-[#FF6B3D] hover:opacity-80"
|
||||
>
|
||||
<ChevronLeft className="mr-2 inline-block h-5 w-5" />
|
||||
<Trans>Template</Trans>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { Trans } from '@lingui/react/macro';
|
||||
import { Bird } from 'lucide-react';
|
||||
import { FileSearch2 } from 'lucide-react';
|
||||
import { useSearchParams } from 'react-router';
|
||||
|
||||
import { formatAvatarUrl } from '@documenso/lib/utils/avatars';
|
||||
@@ -65,7 +65,7 @@ export default function TemplatesPage() {
|
||||
<div className="relative mt-5">
|
||||
{data && data.count === 0 ? (
|
||||
<div className="text-muted-foreground/60 flex h-96 flex-col items-center justify-center gap-y-4">
|
||||
<Bird className="h-12 w-12" strokeWidth={1.5} />
|
||||
<FileSearch2 className="h-12 w-12" strokeWidth={1.5} />
|
||||
|
||||
<div className="text-center">
|
||||
<h3 className="text-lg font-semibold">
|
||||
|
||||
@@ -6,6 +6,7 @@ import { redirect } from 'react-router';
|
||||
import { match } from 'ts-pattern';
|
||||
import { UAParser } from 'ua-parser-js';
|
||||
|
||||
import { isDocumentPlatform } from '@documenso/ee/server-only/util/is-document-platform';
|
||||
import { APP_I18N_OPTIONS, ZSupportedLanguageCodeSchema } from '@documenso/lib/constants/i18n';
|
||||
import {
|
||||
RECIPIENT_ROLES_DESCRIPTION,
|
||||
@@ -59,6 +60,8 @@ export async function loader({ request }: Route.LoaderArgs) {
|
||||
throw redirect('/');
|
||||
}
|
||||
|
||||
const isPlatformDocument = await isDocumentPlatform(document);
|
||||
|
||||
const documentLanguage = ZSupportedLanguageCodeSchema.parse(document.documentMeta?.language);
|
||||
|
||||
const auditLogs = await getDocumentCertificateAuditLogs({
|
||||
@@ -70,6 +73,7 @@ export async function loader({ request }: Route.LoaderArgs) {
|
||||
return {
|
||||
document,
|
||||
documentLanguage,
|
||||
isPlatformDocument,
|
||||
auditLogs,
|
||||
messages,
|
||||
};
|
||||
@@ -85,7 +89,7 @@ export async function loader({ request }: Route.LoaderArgs) {
|
||||
* Update: Maybe <Trans> tags work now after RR7 migration.
|
||||
*/
|
||||
export default function SigningCertificate({ loaderData }: Route.ComponentProps) {
|
||||
const { document, documentLanguage, auditLogs, messages } = loaderData;
|
||||
const { document, documentLanguage, isPlatformDocument, auditLogs, messages } = loaderData;
|
||||
|
||||
const { i18n, _ } = useLingui();
|
||||
|
||||
@@ -337,15 +341,17 @@ export default function SigningCertificate({ loaderData }: Route.ComponentProps)
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="my-8 flex-row-reverse">
|
||||
<div className="flex items-end justify-end gap-x-4">
|
||||
<p className="flex-shrink-0 text-sm font-medium print:text-xs">
|
||||
{_(msg`Signing certificate provided by`)}:
|
||||
</p>
|
||||
{isPlatformDocument && (
|
||||
<div className="my-8 flex-row-reverse">
|
||||
<div className="flex items-end justify-end gap-x-4">
|
||||
<p className="flex-shrink-0 text-sm font-medium print:text-xs">
|
||||
{_(msg`Signing certificate provided by`)}:
|
||||
</p>
|
||||
|
||||
<BrandingLogo className="max-h-6 print:max-h-4" />
|
||||
<BrandingLogo className="max-h-6 print:max-h-4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ export default function PublicProfileLayout() {
|
||||
</p>
|
||||
|
||||
<Button asChild variant="secondary">
|
||||
<Link to="/signup">
|
||||
<Link to="https://bls.media/sign/">
|
||||
<div className="hidden flex-row items-center sm:flex">
|
||||
<PlusIcon className="mr-1 h-5 w-5" />
|
||||
<Trans>Create now</Trans>
|
||||
|
||||
@@ -79,7 +79,14 @@ export default function DirectTemplatePage() {
|
||||
const { template, directTemplateRecipient } = data;
|
||||
|
||||
return (
|
||||
<DocumentSigningProvider email={user?.email} fullName={user?.name} signature={user?.signature}>
|
||||
<DocumentSigningProvider
|
||||
email={user?.email}
|
||||
fullName={user?.name}
|
||||
signature={user?.signature}
|
||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||
>
|
||||
<DocumentSigningAuthProvider
|
||||
documentAuthOptions={template.authOptions}
|
||||
recipient={directTemplateRecipient}
|
||||
|
||||
@@ -233,6 +233,9 @@ export default function SigningPage() {
|
||||
email={recipient.email}
|
||||
fullName={user?.email === recipient.email ? user?.name : recipient.name}
|
||||
signature={user?.email === recipient.email ? user?.signature : undefined}
|
||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||
>
|
||||
<DocumentSigningAuthProvider
|
||||
documentAuthOptions={document.authOptions}
|
||||
|
||||
@@ -204,7 +204,7 @@ export default function CompletedSigningPage({ loaderData }: Route.ComponentProp
|
||||
))}
|
||||
|
||||
<div className="mt-8 flex w-full max-w-sm items-center justify-center gap-4">
|
||||
<DocumentShareButton documentId={document.id} token={recipient.token} />
|
||||
{/* <DocumentShareButton documentId={document.id} token={recipient.token} /> Share Button ausgeblendet */}
|
||||
|
||||
{isDocumentCompleted(document.status) ? (
|
||||
<DocumentDownloadButton
|
||||
|
||||
@@ -115,7 +115,7 @@ export default function RejectedSigningPage({ loaderData }: Route.ComponentProps
|
||||
|
||||
{user && (
|
||||
<Button className="mt-6" asChild>
|
||||
<Link to={`/`}>Return Home</Link>
|
||||
<Link to={`/`}>Zurück</Link>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function WaitingForTurnToSignPage({ loaderData }: Route.Component
|
||||
</Button>
|
||||
) : (
|
||||
<Button variant="link" asChild>
|
||||
<Link to="/documents">Return Home</Link>
|
||||
<Link to="/documents">Zurück</Link>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Link } from 'react-router';
|
||||
|
||||
import { Button } from '@documenso/ui/primitives/button';
|
||||
|
||||
const SUPPORT_EMAIL = 'support@documenso.com';
|
||||
const SUPPORT_EMAIL = 'hello@bls-media.de';
|
||||
|
||||
export default function SignatureDisclosure() {
|
||||
return (
|
||||
|
||||
@@ -6,15 +6,15 @@ import type { Route } from './+types/share.$slug';
|
||||
|
||||
export function meta({ params: { slug } }: Route.MetaArgs) {
|
||||
return [
|
||||
{ title: 'Documenso - Share' },
|
||||
{ description: 'I just signed a document in style with Documenso!' },
|
||||
{ title: 'BLS sign - Share' },
|
||||
{ description: 'I just signed a document in style with BLS sign!' },
|
||||
{
|
||||
property: 'og:title',
|
||||
content: 'Documenso - Join the open source signing revolution',
|
||||
content: 'BLS sign - Join the open source signing revolution',
|
||||
},
|
||||
{
|
||||
property: 'og:description',
|
||||
content: 'I just signed with Documenso!',
|
||||
content: 'I just signed with BLS sign!',
|
||||
},
|
||||
{
|
||||
property: 'og:type',
|
||||
@@ -38,7 +38,7 @@ export function meta({ params: { slug } }: Route.MetaArgs) {
|
||||
},
|
||||
{
|
||||
name: 'twitter:description',
|
||||
content: 'I just signed with Documenso!',
|
||||
content: 'I just signed with BLS sign!',
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -50,8 +50,8 @@ export const loader = ({ request }: Route.LoaderArgs) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Is hardcoded because this whole meta is hardcoded anyway for Documenso.
|
||||
throw redirect('https://documenso.com');
|
||||
// Is hardcoded because this whole meta is hardcoded anyway for BLS sign.
|
||||
throw redirect('https://bls.media/');
|
||||
};
|
||||
|
||||
export default function SharePage() {
|
||||
|
||||
@@ -131,7 +131,14 @@ export default function EmbedDirectTemplatePage() {
|
||||
} = useSuperLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<DocumentSigningProvider email={user?.email} fullName={user?.name} signature={user?.signature}>
|
||||
<DocumentSigningProvider
|
||||
email={user?.email}
|
||||
fullName={user?.name}
|
||||
signature={user?.signature}
|
||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||
>
|
||||
<DocumentSigningAuthProvider
|
||||
documentAuthOptions={template.authOptions}
|
||||
recipient={recipient}
|
||||
|
||||
@@ -156,6 +156,9 @@ export default function EmbedSignDocumentPage() {
|
||||
email={recipient.email}
|
||||
fullName={user?.email === recipient.email ? user?.name : recipient.name}
|
||||
signature={user?.email === recipient.email ? user?.signature : undefined}
|
||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||
>
|
||||
<DocumentSigningAuthProvider
|
||||
documentAuthOptions={document.authOptions}
|
||||
|
||||
@@ -2,11 +2,11 @@ import { NEXT_PUBLIC_WEBAPP_URL } from '@documenso/lib/constants/app';
|
||||
|
||||
export const appMetaTags = (title?: string) => {
|
||||
const description =
|
||||
'Join Documenso, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.';
|
||||
'Join BLS sign, the open signing infrastructure, and get a 10x better signing experience. Pricing starts at $30/mo. forever! Sign in now and enjoy a faster, smarter, and more beautiful document signing process. Integrates with your favorite tools, customizable, and expandable. Support our mission and become a part of our open-source community.';
|
||||
|
||||
return [
|
||||
{
|
||||
title: title ? `${title} - Documenso` : 'Documenso',
|
||||
title: title ? `${title} - BLS sign` : 'BLS sign',
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
@@ -15,7 +15,7 @@ export const appMetaTags = (title?: string) => {
|
||||
{
|
||||
name: 'keywords',
|
||||
content:
|
||||
'Documenso, open source, DocuSign alternative, document signing, open signing infrastructure, open-source community, fast signing, beautiful signing, smart templates',
|
||||
'BLS sign, open source, DocuSign alternative, document signing, open signing infrastructure, open-source community, fast signing, beautiful signing, smart templates',
|
||||
},
|
||||
{
|
||||
name: 'author',
|
||||
@@ -27,7 +27,7 @@ export const appMetaTags = (title?: string) => {
|
||||
},
|
||||
{
|
||||
property: 'og:title',
|
||||
content: 'Documenso - The Open Source DocuSign Alternative',
|
||||
content: 'BLS sign',
|
||||
},
|
||||
{
|
||||
property: 'og:description',
|
||||
|
||||
@@ -100,5 +100,5 @@
|
||||
"vite-plugin-babel-macros": "^1.0.6",
|
||||
"vite-tsconfig-paths": "^5.1.4"
|
||||
},
|
||||
"version": "1.10.0-rc.0"
|
||||
"version": "1.10.0-rc.1"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
Contact: https://github.com/documenso/documenso/issues/new?assignees=&labels=bug&projects=&template=bug-report.yml
|
||||
|
||||
# Report critical issues privately to let us take appropriate action before publishing.
|
||||
Contact: mailto:security@documenso.com
|
||||
Contact: mailto:security@sign.bls.media
|
||||
Preferred-Languages: en
|
||||
Canonical: https://documenso.com/.well-known/security.txt
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Documenso",
|
||||
"short_name": "Documenso",
|
||||
"name": "BLS sign",
|
||||
"short_name": "BLS sign",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
@@ -13,7 +13,7 @@
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#A2E771",
|
||||
"background_color": "#FFFFFF",
|
||||
//"theme_color": "#A2E771",
|
||||
"background_color": "#F8F8F8",
|
||||
"display": "standalone"
|
||||
}
|
||||
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@documenso/root",
|
||||
"version": "1.10.0-rc.0",
|
||||
"version": "1.10.0-rc.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@documenso/root",
|
||||
"version": "1.10.0-rc.0",
|
||||
"version": "1.10.0-rc.1",
|
||||
"workspaces": [
|
||||
"apps/*",
|
||||
"packages/*"
|
||||
@@ -95,7 +95,7 @@
|
||||
},
|
||||
"apps/remix": {
|
||||
"name": "@documenso/remix",
|
||||
"version": "1.10.0-rc.0",
|
||||
"version": "1.10.0-rc.1",
|
||||
"dependencies": {
|
||||
"@documenso/api": "*",
|
||||
"@documenso/assets": "*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"private": true,
|
||||
"version": "1.10.0-rc.0",
|
||||
"version": "1.10.0-rc.1",
|
||||
"scripts": {
|
||||
"build": "turbo run build",
|
||||
"dev": "turbo run dev --filter=@documenso/remix",
|
||||
|
||||
@@ -326,6 +326,8 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
|
||||
allowDictateNextSigner: body.meta.allowDictateNextSigner,
|
||||
language: body.meta.language,
|
||||
typedSignatureEnabled: body.meta.typedSignatureEnabled,
|
||||
uploadSignatureEnabled: body.meta.uploadSignatureEnabled,
|
||||
drawSignatureEnabled: body.meta.drawSignatureEnabled,
|
||||
distributionMethod: body.meta.distributionMethod,
|
||||
emailSettings: body.meta.emailSettings,
|
||||
requestMetadata: metadata,
|
||||
|
||||
@@ -9,9 +9,9 @@ export const OpenAPIV1 = Object.assign(
|
||||
ApiContractV1,
|
||||
{
|
||||
info: {
|
||||
title: 'Documenso API',
|
||||
title: 'BLS sign API',
|
||||
version: '1.0.0',
|
||||
description: 'The Documenso API for retrieving, creating, updating and deleting documents.',
|
||||
description: 'The BLS sign API for retrieving, creating, updating and deleting documents.',
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
|
||||
@@ -158,6 +158,8 @@ export const ZCreateDocumentMutationSchema = z.object({
|
||||
allowDictateNextSigner: z.boolean().optional(),
|
||||
language: z.enum(SUPPORTED_LANGUAGE_CODES).optional(),
|
||||
typedSignatureEnabled: z.boolean().optional().default(true),
|
||||
uploadSignatureEnabled: z.boolean().optional().default(true),
|
||||
drawSignatureEnabled: z.boolean().optional().default(true),
|
||||
distributionMethod: z.nativeEnum(DocumentDistributionMethod).optional(),
|
||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||
})
|
||||
@@ -291,6 +293,8 @@ export const ZGenerateDocumentFromTemplateMutationSchema = z.object({
|
||||
language: z.enum(SUPPORTED_LANGUAGE_CODES),
|
||||
distributionMethod: z.nativeEnum(DocumentDistributionMethod),
|
||||
typedSignatureEnabled: z.boolean(),
|
||||
uploadSignatureEnabled: z.boolean(),
|
||||
drawSignatureEnabled: z.boolean(),
|
||||
emailSettings: ZDocumentEmailSettingsSchema,
|
||||
})
|
||||
.partial()
|
||||
|
||||
@@ -16,7 +16,7 @@ test('[DOCUMENT_AUTH]: should grant access when not required', async ({ page })
|
||||
|
||||
const document = await seedPendingDocument(user, [
|
||||
recipientWithAccount,
|
||||
'recipientwithoutaccount@documenso.com',
|
||||
'recipientwithoutaccount@sign.bls.media',
|
||||
]);
|
||||
|
||||
const recipients = await prisma.recipient.findMany({
|
||||
@@ -40,7 +40,7 @@ test('[DOCUMENT_AUTH]: should allow or deny access when required', async ({ page
|
||||
|
||||
const document = await seedPendingDocument(
|
||||
user,
|
||||
[recipientWithAccount, 'recipientwithoutaccount@documenso.com'],
|
||||
[recipientWithAccount, 'recipientwithoutaccount@sign.bls.media'],
|
||||
{
|
||||
createDocumentOptions: {
|
||||
authOptions: createDocumentAuthOptions({
|
||||
|
||||
@@ -246,7 +246,9 @@ test('[DOCUMENT_AUTH]: should allow field signing when required for recipient au
|
||||
});
|
||||
}
|
||||
|
||||
await signSignaturePad(page);
|
||||
if (fields.some((field) => field.type === FieldType.SIGNATURE)) {
|
||||
await signSignaturePad(page);
|
||||
}
|
||||
|
||||
for (const field of fields) {
|
||||
await page.locator(`#field-${field.id}`).getByRole('button').click();
|
||||
@@ -349,7 +351,9 @@ test('[DOCUMENT_AUTH]: should allow field signing when required for recipient an
|
||||
});
|
||||
}
|
||||
|
||||
await signSignaturePad(page);
|
||||
if (fields.some((field) => field.type === FieldType.SIGNATURE)) {
|
||||
await signSignaturePad(page);
|
||||
}
|
||||
|
||||
for (const field of fields) {
|
||||
await page.locator(`#field-${field.id}`).getByRole('button').click();
|
||||
|
||||
@@ -11,7 +11,7 @@ import { prisma } from '@documenso/prisma';
|
||||
import { seedPendingDocumentWithFullFields } from '@documenso/prisma/seed/documents';
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
|
||||
import { signSignaturePad } from '../fixtures/signature';
|
||||
import { signDirectSignaturePad, signSignaturePad } from '../fixtures/signature';
|
||||
|
||||
test('[NEXT_RECIPIENT_DICTATION]: should allow updating next recipient when dictation is enabled', async ({
|
||||
page,
|
||||
@@ -322,7 +322,7 @@ test('[NEXT_RECIPIENT_DICTATION]: should allow assistant to dictate next signer'
|
||||
await page.locator(`#field-${field.id}`).getByRole('button').click();
|
||||
|
||||
if (field.type === FieldType.SIGNATURE) {
|
||||
await signSignaturePad(page);
|
||||
await signDirectSignaturePad(page);
|
||||
await page.getByRole('button', { name: 'Sign', exact: true }).click();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,11 +39,11 @@ test.describe('[EE_ONLY]', () => {
|
||||
await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible();
|
||||
|
||||
// Add 2 signers.
|
||||
await page.getByPlaceholder('Email').fill('recipient1@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient1@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient 1');
|
||||
|
||||
await page.getByRole('button', { name: 'Add Signer' }).click();
|
||||
await page.getByLabel('Email').nth(1).fill('recipient2@documenso.com');
|
||||
await page.getByLabel('Email').nth(1).fill('recipient2@sign.bls.media');
|
||||
await page.getByLabel('Name').nth(1).fill('Recipient 2');
|
||||
|
||||
// Display advanced settings.
|
||||
@@ -74,12 +74,12 @@ test('[DOCUMENT_FLOW]: add signers', async ({ page }) => {
|
||||
await expect(page.getByRole('heading', { name: 'Add Signers' })).toBeVisible();
|
||||
|
||||
// Add 2 signers.
|
||||
await page.getByPlaceholder('Email').fill('recipient1@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient1@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient 1');
|
||||
|
||||
await page.getByRole('button', { name: 'Add Signer' }).click();
|
||||
|
||||
await page.getByLabel('Email').nth(1).fill('recipient2@documenso.com');
|
||||
await page.getByLabel('Email').nth(1).fill('recipient2@sign.bls.media');
|
||||
await page.getByLabel('Name').nth(1).fill('Recipient 2');
|
||||
|
||||
// Advanced settings should not be visible for non EE users.
|
||||
|
||||
@@ -343,14 +343,14 @@ test('[DOCUMENT_FLOW]: should be able to approve a document', async ({ page }) =
|
||||
|
||||
const { recipients } = await seedPendingDocumentWithFullFields({
|
||||
owner: user,
|
||||
recipients: ['user@documenso.com', 'approver@documenso.com'],
|
||||
recipients: ['user@sign.bls.media', 'approver@sign.bls.media'],
|
||||
recipientsCreateOptions: [
|
||||
{
|
||||
email: 'user@documenso.com',
|
||||
email: 'user@sign.bls.media',
|
||||
role: RecipientRole.SIGNER,
|
||||
},
|
||||
{
|
||||
email: 'approver@documenso.com',
|
||||
email: 'approver@sign.bls.media',
|
||||
role: RecipientRole.APPROVER,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -222,7 +222,10 @@ test.describe('Signing Certificate Tests', () => {
|
||||
|
||||
// Toggle signing certificate setting
|
||||
await page.getByLabel('Include the Signing Certificate in the Document').click();
|
||||
await page.getByRole('button', { name: /Save/ }).first().click();
|
||||
await page
|
||||
.getByRole('button', { name: /Update/ })
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
@@ -236,7 +239,10 @@ test.describe('Signing Certificate Tests', () => {
|
||||
|
||||
// Toggle the setting back to true
|
||||
await page.getByLabel('Include the Signing Certificate in the Document').click();
|
||||
await page.getByRole('button', { name: /Save/ }).first().click();
|
||||
await page
|
||||
.getByRole('button', { name: /Update/ })
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ type LoginOptions = {
|
||||
|
||||
export const apiSignin = async ({
|
||||
page,
|
||||
email = 'example@documenso.com',
|
||||
email = 'example@sign.bls.media',
|
||||
password = 'password',
|
||||
redirectPath = '/documents',
|
||||
}: LoginOptions) => {
|
||||
|
||||
@@ -1,40 +1,28 @@
|
||||
import type { Page } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* Will open the signature pad dialog and sign it.
|
||||
*/
|
||||
export const signSignaturePad = async (page: Page) => {
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
const canvas = page.getByTestId('signature-pad');
|
||||
await page.getByTestId('signature-pad-dialog-button').click();
|
||||
|
||||
const box = await canvas.boundingBox();
|
||||
// Click type tab
|
||||
await page.getByRole('tab', { name: 'Type' }).click();
|
||||
await page.getByTestId('signature-pad-type-input').fill('Signature');
|
||||
|
||||
if (!box) {
|
||||
throw new Error('Signature pad not found');
|
||||
}
|
||||
|
||||
// Calculate center point
|
||||
const centerX = box.x + box.width / 2;
|
||||
const centerY = box.y + box.height / 2;
|
||||
|
||||
// Calculate square size (making it slightly smaller than the canvas)
|
||||
const squareSize = Math.min(box.width, box.height) * 0.4; // 40% of the smallest dimension
|
||||
|
||||
// Move to center
|
||||
await page.mouse.move(centerX, centerY);
|
||||
await page.mouse.down();
|
||||
|
||||
// Draw square clockwise from center
|
||||
// Move right
|
||||
await page.mouse.move(centerX + squareSize, centerY, { steps: 10 });
|
||||
// Move down
|
||||
await page.mouse.move(centerX + squareSize, centerY + squareSize, { steps: 10 });
|
||||
// Move left
|
||||
await page.mouse.move(centerX - squareSize, centerY + squareSize, { steps: 10 });
|
||||
// Move up
|
||||
await page.mouse.move(centerX - squareSize, centerY - squareSize, { steps: 10 });
|
||||
// Move right
|
||||
await page.mouse.move(centerX + squareSize, centerY - squareSize, { steps: 10 });
|
||||
// Move down to close the square
|
||||
await page.mouse.move(centerX + squareSize, centerY, { steps: 10 });
|
||||
|
||||
await page.mouse.up();
|
||||
// Click Next button
|
||||
await page.getByRole('button', { name: 'Next' }).click();
|
||||
};
|
||||
|
||||
/**
|
||||
* For when the signature pad is already open.
|
||||
*/
|
||||
export const signDirectSignaturePad = async (page: Page) => {
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Click type tab
|
||||
await page.getByRole('tab', { name: 'Type' }).click();
|
||||
await page.getByTestId('signature-pad-type-input').fill('Signature');
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@ test('[TEAMS]: update the default document visibility in the team global setting
|
||||
// !: Brittle selector
|
||||
await page.getByRole('combobox').first().click();
|
||||
await page.getByRole('option', { name: 'Admin' }).click();
|
||||
await page.getByRole('button', { name: 'Save' }).first().click();
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
|
||||
const toast = page.locator('li[role="status"][data-state="open"]').first();
|
||||
await expect(toast).toBeVisible();
|
||||
@@ -47,7 +47,7 @@ test('[TEAMS]: update the sender details in the team global settings', async ({
|
||||
|
||||
await expect(checkbox).toBeChecked();
|
||||
|
||||
await page.getByRole('button', { name: 'Save' }).first().click();
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
|
||||
const toast = page.locator('li[role="status"][data-state="open"]').first();
|
||||
await expect(toast).toBeVisible();
|
||||
|
||||
182
packages/app-tests/e2e/teams/team-signature-settings.spec.ts
Normal file
182
packages/app-tests/e2e/teams/team-signature-settings.spec.ts
Normal file
@@ -0,0 +1,182 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { prisma } from '@documenso/prisma';
|
||||
import {
|
||||
seedTeamDocumentWithMeta,
|
||||
seedTeamDocuments,
|
||||
seedTeamTemplateWithMeta,
|
||||
} from '@documenso/prisma/seed/documents';
|
||||
|
||||
import { apiSignin } from '../fixtures/authentication';
|
||||
|
||||
test.describe.configure({ mode: 'parallel' });
|
||||
|
||||
test('[TEAMS]: check that default team signature settings are all enabled', async ({ page }) => {
|
||||
const { team } = await seedTeamDocuments();
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: team.owner.email,
|
||||
password: 'password',
|
||||
redirectPath: `/t/${team.url}/settings/preferences`,
|
||||
});
|
||||
|
||||
// Verify that the default created team settings has all signatures enabled
|
||||
await expect(page.getByRole('combobox').filter({ hasText: 'Type' })).toBeVisible();
|
||||
await expect(page.getByRole('combobox').filter({ hasText: 'Upload' })).toBeVisible();
|
||||
await expect(page.getByRole('combobox').filter({ hasText: 'Draw' })).toBeVisible();
|
||||
|
||||
const document = await seedTeamDocumentWithMeta(team);
|
||||
|
||||
// Create a document and check the settings
|
||||
await page.goto(`/t/${team.url}/documents/${document.id}/edit`);
|
||||
|
||||
// Verify that the settings match
|
||||
await page.getByRole('button', { name: 'Advanced Options' }).click();
|
||||
await expect(page.getByRole('combobox').filter({ hasText: 'Type' })).toBeVisible();
|
||||
await expect(page.getByRole('combobox').filter({ hasText: 'Upload' })).toBeVisible();
|
||||
await expect(page.getByRole('combobox').filter({ hasText: 'Draw' })).toBeVisible();
|
||||
|
||||
// Go to document and check that the signatured tabs are correct.
|
||||
await page.goto(`/sign/${document.recipients[0].token}`);
|
||||
await page.getByTestId('signature-pad-dialog-button').click();
|
||||
|
||||
// Check the tab values
|
||||
await expect(page.getByRole('tab', { name: 'Type' })).toBeVisible();
|
||||
await expect(page.getByRole('tab', { name: 'Upload' })).toBeVisible();
|
||||
await expect(page.getByRole('tab', { name: 'Draw' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
||||
const { team } = await seedTeamDocuments();
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: team.owner.email,
|
||||
password: 'password',
|
||||
redirectPath: `/t/${team.url}/settings/preferences`,
|
||||
});
|
||||
|
||||
const allTabs = ['Type', 'Upload', 'Draw'];
|
||||
const tabTest = [['Type', 'Upload', 'Draw'], ['Type', 'Upload'], ['Type']];
|
||||
|
||||
for (const tabs of tabTest) {
|
||||
await page.goto(`/t/${team.url}/settings/preferences`);
|
||||
|
||||
// Update combobox to have the correct tabs
|
||||
await page.getByTestId('signature-types-combobox').click();
|
||||
|
||||
await expect(page.getByRole('option', { name: 'Type' })).toBeVisible();
|
||||
await expect(page.getByRole('option', { name: 'Upload' })).toBeVisible();
|
||||
await expect(page.getByRole('option', { name: 'Draw' })).toBeVisible();
|
||||
|
||||
// Clear all selected items.
|
||||
for (const tab of allTabs) {
|
||||
const item = page.getByRole('option', { name: tab });
|
||||
|
||||
const isSelected = (await item.innerHTML()).includes('opacity-100');
|
||||
|
||||
if (isSelected) {
|
||||
await item.click();
|
||||
}
|
||||
}
|
||||
|
||||
// Selected wanted items.
|
||||
for (const tab of tabs) {
|
||||
const item = page.getByRole('option', { name: tab });
|
||||
await item.click();
|
||||
}
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
|
||||
const document = await seedTeamDocumentWithMeta(team);
|
||||
|
||||
// Go to document and check that the signatured tabs are correct.
|
||||
await page.goto(`/sign/${document.recipients[0].token}`);
|
||||
await page.getByTestId('signature-pad-dialog-button').click();
|
||||
|
||||
// Check the tab values
|
||||
for (const tab of allTabs) {
|
||||
if (tabs.includes(tab)) {
|
||||
await expect(page.getByRole('tab', { name: tab })).toBeVisible();
|
||||
} else {
|
||||
await expect(page.getByRole('tab', { name: tab })).not.toBeVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
|
||||
const { team } = await seedTeamDocuments();
|
||||
|
||||
await apiSignin({
|
||||
page,
|
||||
email: team.owner.email,
|
||||
password: 'password',
|
||||
redirectPath: `/t/${team.url}/settings/preferences`,
|
||||
});
|
||||
|
||||
const allTabs = ['Type', 'Upload', 'Draw'];
|
||||
const tabTest = [['Type', 'Upload', 'Draw'], ['Type', 'Upload'], ['Type']];
|
||||
|
||||
for (const tabs of tabTest) {
|
||||
await page.goto(`/t/${team.url}/settings/preferences`);
|
||||
|
||||
// Update combobox to have the correct tabs
|
||||
await page.getByTestId('signature-types-combobox').click();
|
||||
|
||||
await expect(page.getByRole('option', { name: 'Type' })).toBeVisible();
|
||||
await expect(page.getByRole('option', { name: 'Upload' })).toBeVisible();
|
||||
await expect(page.getByRole('option', { name: 'Draw' })).toBeVisible();
|
||||
|
||||
// Clear all selected items.
|
||||
for (const tab of allTabs) {
|
||||
const item = page.getByRole('option', { name: tab });
|
||||
|
||||
const isSelected = (await item.innerHTML()).includes('opacity-100');
|
||||
|
||||
if (isSelected) {
|
||||
await item.click();
|
||||
}
|
||||
}
|
||||
|
||||
// Selected wanted items.
|
||||
for (const tab of tabs) {
|
||||
const item = page.getByRole('option', { name: tab });
|
||||
await item.click();
|
||||
}
|
||||
|
||||
await page.getByRole('button', { name: 'Update' }).first().click();
|
||||
|
||||
const template = await seedTeamTemplateWithMeta(team);
|
||||
|
||||
await page.goto(`/t/${team.url}/templates/${template.id}`);
|
||||
await page.getByRole('button', { name: 'Use' }).click();
|
||||
|
||||
// Check the send document checkbox to true
|
||||
await page.getByLabel('Send document').click();
|
||||
await page.getByRole('button', { name: 'Create and send' }).click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
const document = await prisma.document.findFirst({
|
||||
where: {
|
||||
templateId: template.id,
|
||||
},
|
||||
include: {
|
||||
documentMeta: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Test kinda flaky, debug here.
|
||||
// console.log({
|
||||
// tabs,
|
||||
// typedSignatureEnabled: document?.documentMeta?.typedSignatureEnabled,
|
||||
// uploadSignatureEnabled: document?.documentMeta?.uploadSignatureEnabled,
|
||||
// drawSignatureEnabled: document?.documentMeta?.drawSignatureEnabled,
|
||||
// });
|
||||
|
||||
expect(document?.documentMeta?.typedSignatureEnabled).toEqual(tabs.includes('Type'));
|
||||
expect(document?.documentMeta?.uploadSignatureEnabled).toEqual(tabs.includes('Upload'));
|
||||
expect(document?.documentMeta?.drawSignatureEnabled).toEqual(tabs.includes('Draw'));
|
||||
}
|
||||
});
|
||||
@@ -39,10 +39,10 @@ test.describe('[EE_ONLY]', () => {
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add 2 signers.
|
||||
await page.getByPlaceholder('Email').fill('recipient1@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient1@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient 1');
|
||||
await page.getByRole('button', { name: 'Add Placeholder Recipient' }).click();
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@documenso.com');
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').nth(1).fill('Recipient 2');
|
||||
|
||||
// Display advanced settings.
|
||||
@@ -89,10 +89,10 @@ test('[TEMPLATE_FLOW]: add placeholder', async ({ page }) => {
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add 2 signers.
|
||||
await page.getByPlaceholder('Email').fill('recipient1@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient1@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient 1');
|
||||
await page.getByRole('button', { name: 'Add Placeholder Recipient' }).click();
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@documenso.com');
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').nth(1).fill('Recipient 2');
|
||||
|
||||
// Advanced settings should not be visible for non EE users.
|
||||
|
||||
@@ -91,10 +91,10 @@ test('[TEMPLATE]: should create a document from a template', async ({ page }) =>
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add 2 signers.
|
||||
await page.getByPlaceholder('Email').fill('recipient1@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient1@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient 1');
|
||||
await page.getByRole('button', { name: 'Add Placeholder Recipient' }).click();
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@documenso.com');
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').nth(1).fill('Recipient 2');
|
||||
|
||||
// Apply require passkey for Recipient 1.
|
||||
@@ -226,10 +226,10 @@ test('[TEMPLATE]: should create a team document from a team template', async ({
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add 2 signers.
|
||||
await page.getByPlaceholder('Email').fill('recipient1@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient1@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient 1');
|
||||
await page.getByRole('button', { name: 'Add Placeholder Recipient' }).click();
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@documenso.com');
|
||||
await page.getByPlaceholder('Email').nth(1).fill('recipient2@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').nth(1).fill('Recipient 2');
|
||||
|
||||
// Apply require passkey for Recipient 1.
|
||||
@@ -330,7 +330,7 @@ test('[TEMPLATE]: should create a document from a template with custom document'
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add a signer
|
||||
await page.getByPlaceholder('Email').fill('recipient@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient');
|
||||
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
@@ -411,7 +411,7 @@ test('[TEMPLATE]: should create a team document from a template with custom docu
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add a signer
|
||||
await page.getByPlaceholder('Email').fill('recipient@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient');
|
||||
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
@@ -481,7 +481,7 @@ test('[TEMPLATE]: should create a document from a template using template docume
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add a signer
|
||||
await page.getByPlaceholder('Email').fill('recipient@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient');
|
||||
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
@@ -561,7 +561,7 @@ test('[TEMPLATE]: should persist document visibility when creating from template
|
||||
await expect(page.getByRole('heading', { name: 'Add Placeholder' })).toBeVisible();
|
||||
|
||||
// Add a signer
|
||||
await page.getByPlaceholder('Email').fill('recipient@documenso.com');
|
||||
await page.getByPlaceholder('Email').fill('recipient@sign.bls.media');
|
||||
await page.getByPlaceholder('Name').fill('Recipient');
|
||||
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
|
||||
@@ -225,7 +225,7 @@ test('[DIRECT_TEMPLATES]: use direct template link with 1 recipient', async ({ p
|
||||
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
|
||||
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder('recipient@documenso.com').fill(seedTestEmail());
|
||||
await page.getByPlaceholder('recipient@sign.bls.media').fill(seedTestEmail());
|
||||
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
await page.getByRole('button', { name: 'Complete' }).click();
|
||||
@@ -298,7 +298,8 @@ test('[DIRECT_TEMPLATES]: use direct template link with 2 recipients', async ({
|
||||
await page.goto(formatDirectTemplatePath(template.directLink?.token || ''));
|
||||
await expect(page.getByRole('heading', { name: 'General' })).toBeVisible();
|
||||
|
||||
await page.getByPlaceholder('recipient@documenso.com').fill(seedTestEmail());
|
||||
await page.waitForTimeout(1000);
|
||||
await page.getByPlaceholder('recipient@sign.bls.media').fill(seedTestEmail());
|
||||
|
||||
await page.getByRole('button', { name: 'Continue' }).click();
|
||||
await page.getByRole('button', { name: 'Complete' }).click();
|
||||
|
||||
@@ -184,8 +184,8 @@ test('[TEMPLATES]: use template', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Use Template' }).click();
|
||||
|
||||
// Enter template values.
|
||||
await page.getByPlaceholder('recipient.1@documenso.com').click();
|
||||
await page.getByPlaceholder('recipient.1@documenso.com').fill(teamMemberUser.email);
|
||||
await page.getByPlaceholder('recipient.1@sign.bls.media').click();
|
||||
await page.getByPlaceholder('recipient.1@sign.bls.media').fill(teamMemberUser.email);
|
||||
await page.getByPlaceholder('Recipient 1').click();
|
||||
await page.getByPlaceholder('Recipient 1').fill('name');
|
||||
|
||||
@@ -202,8 +202,8 @@ test('[TEMPLATES]: use template', async ({ page }) => {
|
||||
await page.getByRole('button', { name: 'Use Template' }).click();
|
||||
|
||||
// Enter template values.
|
||||
await page.getByPlaceholder('recipient.1@documenso.com').click();
|
||||
await page.getByPlaceholder('recipient.1@documenso.com').fill(teamMemberUser.email);
|
||||
await page.getByPlaceholder('recipient.1@sign.bls.media').click();
|
||||
await page.getByPlaceholder('recipient.1@sign.bls.media').fill(teamMemberUser.email);
|
||||
await page.getByPlaceholder('Recipient 1').click();
|
||||
await page.getByPlaceholder('Recipient 1').fill('name');
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import { getUserByEmail } from '@documenso/lib/server-only/user/get-user-by-emai
|
||||
import { seedUser } from '@documenso/prisma/seed/users';
|
||||
|
||||
import { apiSignin } from '../fixtures/authentication';
|
||||
import { signSignaturePad } from '../fixtures/signature';
|
||||
|
||||
test('[USER] update full name', async ({ page }) => {
|
||||
const user = await seedUser();
|
||||
@@ -12,7 +13,7 @@ test('[USER] update full name', async ({ page }) => {
|
||||
|
||||
await page.getByLabel('Full Name').fill('John Doe');
|
||||
|
||||
await page.getByPlaceholder('Type your signature').fill('John Doe');
|
||||
await signSignaturePad(page);
|
||||
|
||||
await page.getByRole('button', { name: 'Update profile' }).click();
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Documenso",
|
||||
"short_name": "Documenso",
|
||||
"name": "BLS sign",
|
||||
"short_name": "BLS sign",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/android-chrome-192x192.png",
|
||||
@@ -13,7 +13,7 @@
|
||||
"type": "image/png"
|
||||
}
|
||||
],
|
||||
"theme_color": "#A2E771",
|
||||
"background_color": "#FFFFFF",
|
||||
//"theme_color": "#A2E771",
|
||||
"background_color": "#F8F8F8",
|
||||
"display": "standalone"
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export const TemplateDocumentCompleted = ({
|
||||
<Section>
|
||||
<Section className="mb-4">
|
||||
<Column align="center">
|
||||
<Text className="text-base font-semibold text-[#7AC455]">
|
||||
<Text className="text-base font-semibold text-[#FF6B3D]">
|
||||
<Img
|
||||
src={getAssetUrl('/static/completed.png')}
|
||||
className="-mt-0.5 mr-2 inline h-7 w-7 align-middle"
|
||||
|
||||
@@ -16,7 +16,7 @@ export const TemplateDocumentImage = ({ assetBaseUrl, className }: TemplateDocum
|
||||
<Column />
|
||||
|
||||
<Column>
|
||||
<Img className="h-42 mx-auto" src={getAssetUrl('/static/document.png')} alt="Documenso" />
|
||||
<Img className="h-42 mx-auto" src={getAssetUrl('/static/document.png')} alt="BLS sign" />
|
||||
</Column>
|
||||
|
||||
<Column />
|
||||
|
||||
@@ -29,7 +29,7 @@ export const TemplateDocumentRecipientSigned = ({
|
||||
<Section>
|
||||
<Section className="mb-4">
|
||||
<Column align="center">
|
||||
<Text className="text-base font-semibold text-[#7AC455]">
|
||||
<Text className="text-base font-semibold text-[#FF6B3D]">
|
||||
<Img
|
||||
src={getAssetUrl('/static/completed.png')}
|
||||
className="-mt-0.5 mr-2 inline h-7 w-7 align-middle"
|
||||
|
||||
@@ -29,7 +29,7 @@ export const TemplateDocumentSelfSigned = ({
|
||||
<Section className="flex-row items-center justify-center">
|
||||
<Section>
|
||||
<Column align="center">
|
||||
<Text className="text-base font-semibold text-[#7AC455]">
|
||||
<Text className="text-base font-semibold text-[#FF6B3D]">
|
||||
<Img
|
||||
src={getAssetUrl('/static/completed.png')}
|
||||
className="-mt-0.5 mr-2 inline h-7 w-7 align-middle"
|
||||
|
||||
@@ -16,8 +16,8 @@ export const TemplateFooter = ({ isDocument = true }: TemplateFooterProps) => {
|
||||
<Text className="my-4 text-base text-slate-400">
|
||||
<Trans>
|
||||
This document was sent using{' '}
|
||||
<Link className="text-[#7AC455]" href="https://documen.so/mail-footer">
|
||||
Documenso.
|
||||
<Link className="text-[#FF6B3D]" href="https://bls.media/sign/">
|
||||
BLS sign.
|
||||
</Link>
|
||||
</Trans>
|
||||
</Text>
|
||||
@@ -36,9 +36,7 @@ export const TemplateFooter = ({ isDocument = true }: TemplateFooterProps) => {
|
||||
</Text>
|
||||
) : (
|
||||
<Text className="my-8 text-sm text-slate-400">
|
||||
Documenso, Inc.
|
||||
<br />
|
||||
2261 Market Street, #5211, San Francisco, CA 94114, USA
|
||||
Made by BLS media
|
||||
</Text>
|
||||
)}
|
||||
</Section>
|
||||
|
||||
@@ -33,7 +33,7 @@ export const ConfirmEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -11,7 +11,7 @@ export type DocumentCancelEmailTemplateProps = Partial<TemplateDocumentCancelPro
|
||||
|
||||
export const DocumentCancelTemplate = ({
|
||||
inviterName = 'Lucas Smith',
|
||||
inviterEmail = 'lucas@documenso.com',
|
||||
inviterEmail = 'lucas@sign.bls.media',
|
||||
documentName = 'Open Source Pledge.pdf',
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
cancellationReason,
|
||||
@@ -39,7 +39,7 @@ export const DocumentCancelTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -40,7 +40,7 @@ export const DocumentCompletedEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -50,7 +50,7 @@ export const DocumentCreatedFromDirectTemplateEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -23,7 +23,7 @@ export type DocumentInviteEmailTemplateProps = Partial<TemplateDocumentInvitePro
|
||||
|
||||
export const DocumentInviteEmailTemplate = ({
|
||||
inviterName = 'Lucas Smith',
|
||||
inviterEmail = 'lucas@documenso.com',
|
||||
inviterEmail = 'lucas@sign.bls.media',
|
||||
documentName = 'Open Source Pledge.pdf',
|
||||
signDocumentLink = 'https://documenso.com',
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
@@ -69,7 +69,7 @@ export const DocumentInviteEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -36,7 +36,7 @@ export const DocumentPendingEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -16,7 +16,7 @@ export interface DocumentRecipientSignedEmailTemplateProps {
|
||||
export const DocumentRecipientSignedEmailTemplate = ({
|
||||
documentName = 'Open Source Pledge.pdf',
|
||||
recipientName = 'John Doe',
|
||||
recipientEmail = 'lucas@documenso.com',
|
||||
recipientEmail = 'lucas@sign.bls.media',
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
}: DocumentRecipientSignedEmailTemplateProps) => {
|
||||
const { _ } = useLingui();
|
||||
@@ -44,7 +44,7 @@ export const DocumentRecipientSignedEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -44,7 +44,7 @@ export function DocumentRejectedEmail({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -44,7 +44,7 @@ export function DocumentRejectionConfirmedEmail({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -36,7 +36,7 @@ export const DocumentSelfSignedEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const DocumentSuperDeleteEmailTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -36,7 +36,7 @@ export const ForgotPasswordTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -38,7 +38,7 @@ export const RecipientRemovedFromDocumentTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -12,7 +12,7 @@ export type ResetPasswordTemplateProps = Partial<TemplateResetPasswordProps>;
|
||||
|
||||
export const ResetPasswordTemplate = ({
|
||||
userName = 'Lucas Smith',
|
||||
userEmail = 'lucas@documenso.com',
|
||||
userEmail = 'lucas@sign.bls.media',
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
}: ResetPasswordTemplateProps) => {
|
||||
const { _ } = useLingui();
|
||||
@@ -38,7 +38,7 @@ export const ResetPasswordTemplate = ({
|
||||
) : (
|
||||
<Img
|
||||
src={getAssetUrl('/static/logo.png')}
|
||||
alt="Documenso Logo"
|
||||
alt="BLS sign Logo"
|
||||
className="mb-4 h-6"
|
||||
/>
|
||||
)}
|
||||
@@ -72,7 +72,7 @@ export const ResetPasswordTemplate = ({
|
||||
<Trans>
|
||||
Didn't request a password change? We are here to help you secure your account,
|
||||
just{' '}
|
||||
<Link className="text-documenso-700 font-normal" href="mailto:hi@documenso.com">
|
||||
<Link className="text-documenso-700 font-normal" href="mailto:hi@sign.bls.media">
|
||||
contact us.
|
||||
</Link>
|
||||
</Trans>
|
||||
|
||||
@@ -20,7 +20,7 @@ export type TeamEmailRemovedTemplateProps = {
|
||||
export const TeamEmailRemovedTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
teamEmail = 'example@documenso.com',
|
||||
teamEmail = 'example@sign.bls.media',
|
||||
teamName = 'Team Name',
|
||||
teamUrl = 'demo',
|
||||
}: TeamEmailRemovedTemplateProps) => {
|
||||
|
||||
@@ -22,7 +22,7 @@ export const TeamJoinEmailTemplate = ({
|
||||
assetBaseUrl = 'http://localhost:3002',
|
||||
baseUrl = 'https://documenso.com',
|
||||
memberName = 'John Doe',
|
||||
memberEmail = 'johndoe@documenso.com',
|
||||
memberEmail = 'johndoe@sign.bls.media',
|
||||
teamName = 'Team Name',
|
||||
teamUrl = 'demo',
|
||||
}: TeamJoinEmailProps) => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user