mirror of
https://github.com/documenso/documenso.git
synced 2026-08-24 15:22:26 +10:00
fix: reviewed
This commit is contained in:
@@ -463,6 +463,7 @@ const response = await fetch(`${BASE_URL}/template/use`, {
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: false,
|
uploadSignatureEnabled: false,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
},
|
},
|
||||||
distributeDocument: true,
|
distributeDocument: true,
|
||||||
}),
|
}),
|
||||||
@@ -483,6 +484,7 @@ const response = await fetch(`${BASE_URL}/template/use`, {
|
|||||||
| `typedSignatureEnabled` | boolean | Allow typed signatures |
|
| `typedSignatureEnabled` | boolean | Allow typed signatures |
|
||||||
| `uploadSignatureEnabled` | boolean | Allow uploaded signature images |
|
| `uploadSignatureEnabled` | boolean | Allow uploaded signature images |
|
||||||
| `drawSignatureEnabled` | boolean | Allow drawn signatures |
|
| `drawSignatureEnabled` | boolean | Allow drawn signatures |
|
||||||
|
| `qrSignatureEnabled` | boolean | Allow QR code handoff to a mobile device |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -390,6 +390,7 @@ const response = await fetch(`${BASE_URL}/template/update`, {
|
|||||||
typedSignatureEnabled: true, // Allow typed signatures
|
typedSignatureEnabled: true, // Allow typed signatures
|
||||||
drawSignatureEnabled: true, // Allow drawn signatures
|
drawSignatureEnabled: true, // Allow drawn signatures
|
||||||
uploadSignatureEnabled: false, // Disable uploaded signatures
|
uploadSignatureEnabled: false, // Disable uploaded signatures
|
||||||
|
qrSignatureEnabled: true, // Allow QR code handoff to a mobile device
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ All webhook events share a common structure:
|
|||||||
| `typedSignatureEnabled` | boolean | Whether typed signatures are allowed |
|
| `typedSignatureEnabled` | boolean | Whether typed signatures are allowed |
|
||||||
| `uploadSignatureEnabled` | boolean | Whether uploaded signatures are allowed |
|
| `uploadSignatureEnabled` | boolean | Whether uploaded signatures are allowed |
|
||||||
| `drawSignatureEnabled` | boolean | Whether drawn signatures are allowed |
|
| `drawSignatureEnabled` | boolean | Whether drawn signatures are allowed |
|
||||||
|
| `qrSignatureEnabled` | boolean | Whether QR code handoff to a mobile device is allowed |
|
||||||
| `language` | string | Document language code |
|
| `language` | string | Document language code |
|
||||||
| `distributionMethod` | string | How document is distributed |
|
| `distributionMethod` | string | How document is distributed |
|
||||||
| `emailSettings` | object? | Custom email settings for this document |
|
| `emailSettings` | object? | Custom email settings for this document |
|
||||||
@@ -138,6 +139,7 @@ Triggered when a new document is created.
|
|||||||
"typedSignatureEnabled": true,
|
"typedSignatureEnabled": true,
|
||||||
"uploadSignatureEnabled": true,
|
"uploadSignatureEnabled": true,
|
||||||
"drawSignatureEnabled": true,
|
"drawSignatureEnabled": true,
|
||||||
|
"qrSignatureEnabled": true,
|
||||||
"language": "en",
|
"language": "en",
|
||||||
"distributionMethod": "EMAIL",
|
"distributionMethod": "EMAIL",
|
||||||
"emailSettings": null
|
"emailSettings": null
|
||||||
@@ -230,6 +232,7 @@ The document status changes to `PENDING` and recipients have `sendStatus: "SENT"
|
|||||||
"typedSignatureEnabled": true,
|
"typedSignatureEnabled": true,
|
||||||
"uploadSignatureEnabled": true,
|
"uploadSignatureEnabled": true,
|
||||||
"drawSignatureEnabled": true,
|
"drawSignatureEnabled": true,
|
||||||
|
"qrSignatureEnabled": true,
|
||||||
"language": "en",
|
"language": "en",
|
||||||
"distributionMethod": "EMAIL",
|
"distributionMethod": "EMAIL",
|
||||||
"emailSettings": null
|
"emailSettings": null
|
||||||
@@ -422,6 +425,7 @@ The document status changes to `COMPLETED` and `completedAt` is set.
|
|||||||
"typedSignatureEnabled": true,
|
"typedSignatureEnabled": true,
|
||||||
"uploadSignatureEnabled": true,
|
"uploadSignatureEnabled": true,
|
||||||
"drawSignatureEnabled": true,
|
"drawSignatureEnabled": true,
|
||||||
|
"qrSignatureEnabled": true,
|
||||||
"language": "en",
|
"language": "en",
|
||||||
"distributionMethod": "EMAIL",
|
"distributionMethod": "EMAIL",
|
||||||
"emailSettings": null
|
"emailSettings": null
|
||||||
@@ -599,6 +603,7 @@ This event is **not** triggered when a recipient hides a document from their inb
|
|||||||
"typedSignatureEnabled": true,
|
"typedSignatureEnabled": true,
|
||||||
"uploadSignatureEnabled": true,
|
"uploadSignatureEnabled": true,
|
||||||
"drawSignatureEnabled": true,
|
"drawSignatureEnabled": true,
|
||||||
|
"qrSignatureEnabled": true,
|
||||||
"language": "en",
|
"language": "en",
|
||||||
"distributionMethod": "EMAIL",
|
"distributionMethod": "EMAIL",
|
||||||
"emailSettings": null
|
"emailSettings": null
|
||||||
|
|||||||
@@ -13,10 +13,19 @@ export type SignFieldSignatureDialogProps = {
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SignFieldSignatureDialog = createCallable<SignFieldSignatureDialogProps, string | null>(
|
export const SignFieldSignatureDialog = createCallable<SignFieldSignatureDialogProps, string | null>(
|
||||||
({ call, fullName, typedSignatureEnabled, uploadSignatureEnabled, drawSignatureEnabled, initialSignature }) => {
|
({
|
||||||
|
call,
|
||||||
|
fullName,
|
||||||
|
typedSignatureEnabled,
|
||||||
|
uploadSignatureEnabled,
|
||||||
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
|
initialSignature,
|
||||||
|
}) => {
|
||||||
const [localSignature, setLocalSignature] = useState(initialSignature);
|
const [localSignature, setLocalSignature] = useState(initialSignature);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -36,6 +45,7 @@ export const SignFieldSignatureDialog = createCallable<SignFieldSignatureDialogP
|
|||||||
typedSignatureEnabled={typedSignatureEnabled}
|
typedSignatureEnabled={typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={uploadSignatureEnabled}
|
uploadSignatureEnabled={uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={drawSignatureEnabled}
|
drawSignatureEnabled={drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -470,6 +470,7 @@ export const EmbedDirectTemplateClientPage = ({
|
|||||||
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={metadata?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -33,7 +33,12 @@ export type EmbedDocumentFieldsProps = {
|
|||||||
fields: Field[];
|
fields: Field[];
|
||||||
metadata?: Pick<
|
metadata?: Pick<
|
||||||
DocumentMeta,
|
DocumentMeta,
|
||||||
'timezone' | 'dateFormat' | 'typedSignatureEnabled' | 'uploadSignatureEnabled' | 'drawSignatureEnabled'
|
| 'timezone'
|
||||||
|
| 'dateFormat'
|
||||||
|
| 'typedSignatureEnabled'
|
||||||
|
| 'uploadSignatureEnabled'
|
||||||
|
| 'drawSignatureEnabled'
|
||||||
|
| 'qrSignatureEnabled'
|
||||||
> | null;
|
> | null;
|
||||||
onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise<void> | void;
|
onSignField?: (value: TSignFieldWithTokenMutationSchema) => Promise<void> | void;
|
||||||
onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise<void> | void;
|
onUnsignField?: (value: TRemovedSignedFieldWithTokenMutationSchema) => Promise<void> | void;
|
||||||
@@ -53,6 +58,7 @@ export const EmbedDocumentFields = ({ fields, metadata, onSignField, onUnsignFie
|
|||||||
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={metadata?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
.with(FieldType.INITIALS, () => (
|
.with(FieldType.INITIALS, () => (
|
||||||
|
|||||||
@@ -461,6 +461,7 @@ export const EmbedSignDocumentV1ClientPage = ({
|
|||||||
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
typedSignatureEnabled={metadata?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
uploadSignatureEnabled={metadata?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
drawSignatureEnabled={metadata?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={metadata?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ export const MultiSignDocumentSigningView = ({
|
|||||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={document.documentMeta?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ type SettingsSubset = Pick<
|
|||||||
| 'typedSignatureEnabled'
|
| 'typedSignatureEnabled'
|
||||||
| 'uploadSignatureEnabled'
|
| 'uploadSignatureEnabled'
|
||||||
| 'drawSignatureEnabled'
|
| 'drawSignatureEnabled'
|
||||||
|
| 'qrSignatureEnabled'
|
||||||
| 'defaultRecipients'
|
| 'defaultRecipients'
|
||||||
| 'delegateDocumentOwnership'
|
| 'delegateDocumentOwnership'
|
||||||
| 'aiFeaturesEnabled'
|
| 'aiFeaturesEnabled'
|
||||||
|
|||||||
@@ -156,6 +156,10 @@ export const AdminGlobalSettingsSection = ({
|
|||||||
</DetailsValue>
|
</DetailsValue>
|
||||||
</DetailsCard>
|
</DetailsCard>
|
||||||
|
|
||||||
|
<DetailsCard label={<Trans>QR signature</Trans>}>
|
||||||
|
<DetailsValue>{booleanValue(settings.qrSignatureEnabled, inheritedSettings?.qrSignatureEnabled)}</DetailsValue>
|
||||||
|
</DetailsCard>
|
||||||
|
|
||||||
<DetailsCard label={<Trans>Branding</Trans>}>
|
<DetailsCard label={<Trans>Branding</Trans>}>
|
||||||
<DetailsValue>{booleanValue(settings.brandingEnabled, inheritedSettings?.brandingEnabled)}</DetailsValue>
|
<DetailsValue>{booleanValue(settings.brandingEnabled, inheritedSettings?.brandingEnabled)}</DetailsValue>
|
||||||
</DetailsCard>
|
</DetailsCard>
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ export const DirectTemplateSigningForm = ({
|
|||||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={template.templateMeta?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
.with(FieldType.INITIALS, () => (
|
.with(FieldType.INITIALS, () => (
|
||||||
@@ -408,6 +409,7 @@ export const DirectTemplateSigningForm = ({
|
|||||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={template.templateMeta?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ export const DocumentSigningForm = ({
|
|||||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={document.documentMeta?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -408,6 +408,7 @@ export const DocumentSigningPageViewV1 = ({
|
|||||||
typedSignatureEnabled={documentMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={documentMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={documentMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={documentMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={documentMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={documentMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={documentMeta?.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
.with(FieldType.INITIALS, () => <DocumentSigningInitialsField key={field.id} field={field} />)
|
.with(FieldType.INITIALS, () => <DocumentSigningInitialsField key={field.id} field={field} />)
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export interface DocumentSigningProviderProps {
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ export const DocumentSigningProvider = ({
|
|||||||
typedSignatureEnabled = true,
|
typedSignatureEnabled = true,
|
||||||
uploadSignatureEnabled = true,
|
uploadSignatureEnabled = true,
|
||||||
drawSignatureEnabled = true,
|
drawSignatureEnabled = true,
|
||||||
|
qrSignatureEnabled = true,
|
||||||
children,
|
children,
|
||||||
}: DocumentSigningProviderProps) => {
|
}: DocumentSigningProviderProps) => {
|
||||||
const [fullName, setFullName] = useState(initialFullName || '');
|
const [fullName, setFullName] = useState(initialFullName || '');
|
||||||
@@ -54,7 +56,7 @@ export const DocumentSigningProvider = ({
|
|||||||
const sig = initialSignature || '';
|
const sig = initialSignature || '';
|
||||||
const isBase64 = isBase64Image(sig);
|
const isBase64 = isBase64Image(sig);
|
||||||
|
|
||||||
if (isBase64 && (uploadSignatureEnabled || drawSignatureEnabled)) {
|
if (isBase64 && (uploadSignatureEnabled || drawSignatureEnabled || qrSignatureEnabled)) {
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
@@ -34,6 +34,7 @@ export type DocumentSigningSignatureFieldProps = {
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DocumentSigningSignatureField = ({
|
export const DocumentSigningSignatureField = ({
|
||||||
@@ -43,6 +44,7 @@ export const DocumentSigningSignatureField = ({
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
}: DocumentSigningSignatureFieldProps) => {
|
}: DocumentSigningSignatureFieldProps) => {
|
||||||
const { _ } = useLingui();
|
const { _ } = useLingui();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -279,6 +281,7 @@ export const DocumentSigningSignatureField = ({
|
|||||||
typedSignatureEnabled={typedSignatureEnabled}
|
typedSignatureEnabled={typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={uploadSignatureEnabled}
|
uploadSignatureEnabled={uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={drawSignatureEnabled}
|
drawSignatureEnabled={drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DocumentSigningDisclosure />
|
<DocumentSigningDisclosure />
|
||||||
|
|||||||
@@ -172,7 +172,9 @@ export const EnvelopeSigningProvider = ({
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
!sig &&
|
!sig &&
|
||||||
(envelope.documentMeta.uploadSignatureEnabled || envelope.documentMeta.drawSignatureEnabled) &&
|
(envelope.documentMeta.uploadSignatureEnabled ||
|
||||||
|
envelope.documentMeta.drawSignatureEnabled ||
|
||||||
|
envelope.documentMeta.qrSignatureEnabled) &&
|
||||||
envelopeData.recipientSignature?.signatureImageAsBase64
|
envelopeData.recipientSignature?.signatureImageAsBase64
|
||||||
) {
|
) {
|
||||||
return envelopeData.recipientSignature.signatureImageAsBase64;
|
return envelopeData.recipientSignature.signatureImageAsBase64;
|
||||||
@@ -182,7 +184,12 @@ export const EnvelopeSigningProvider = ({
|
|||||||
return envelopeData.recipientSignature.typedSignature;
|
return envelopeData.recipientSignature.typedSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBase64 && (envelope.documentMeta.uploadSignatureEnabled || envelope.documentMeta.drawSignatureEnabled)) {
|
if (
|
||||||
|
isBase64 &&
|
||||||
|
(envelope.documentMeta.uploadSignatureEnabled ||
|
||||||
|
envelope.documentMeta.drawSignatureEnabled ||
|
||||||
|
envelope.documentMeta.qrSignatureEnabled)
|
||||||
|
) {
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ export const DocumentEditForm = ({ className, initialDocument, documentRootPath
|
|||||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||||
|
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -278,6 +278,7 @@ export const EnvelopeEditorSettingsDialog = ({ trigger, ...props }: EnvelopeEdit
|
|||||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||||
|
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
|
||||||
envelopeExpirationPeriod,
|
envelopeExpirationPeriod,
|
||||||
reminderSettings,
|
reminderSettings,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ export default function EnvelopeSignerForm() {
|
|||||||
typedSignatureEnabled={envelope.documentMeta.typedSignatureEnabled}
|
typedSignatureEnabled={envelope.documentMeta.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={envelope.documentMeta.uploadSignatureEnabled}
|
uploadSignatureEnabled={envelope.documentMeta.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={envelope.documentMeta.drawSignatureEnabled}
|
drawSignatureEnabled={envelope.documentMeta.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={envelope.documentMeta.qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ export const EnvelopeSignerPageRenderer = ({ pageData }: { pageData: PageRenderD
|
|||||||
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled,
|
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled,
|
||||||
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled,
|
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled,
|
||||||
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled,
|
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled: envelope.documentMeta.qrSignatureEnabled,
|
||||||
})
|
})
|
||||||
.then(async (payload) => {
|
.then(async (payload) => {
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ export const TemplateEditForm = ({ initialTemplate, className, templateRootPath
|
|||||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||||
|
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
|
||||||
language: isValidLanguageCode(data.meta.language) ? data.meta.language : undefined,
|
language: isValidLanguageCode(data.meta.language) ? data.meta.language : undefined,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ export default function OrganisationSettingsDocumentPage() {
|
|||||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||||
|
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
|
||||||
delegateDocumentOwnership,
|
delegateDocumentOwnership,
|
||||||
aiFeaturesEnabled,
|
aiFeaturesEnabled,
|
||||||
envelopeExpirationPeriod: envelopeExpirationPeriod ?? undefined,
|
envelopeExpirationPeriod: envelopeExpirationPeriod ?? undefined,
|
||||||
|
|||||||
@@ -76,11 +76,13 @@ export default function TeamsSettingsPage() {
|
|||||||
typedSignatureEnabled: null,
|
typedSignatureEnabled: null,
|
||||||
uploadSignatureEnabled: null,
|
uploadSignatureEnabled: null,
|
||||||
drawSignatureEnabled: null,
|
drawSignatureEnabled: null,
|
||||||
|
qrSignatureEnabled: null,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||||
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||||
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||||
|
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
|
||||||
}),
|
}),
|
||||||
delegateDocumentOwnership,
|
delegateDocumentOwnership,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ const DirectSigningPageV1 = ({ data }: { data: Awaited<ReturnType<typeof handleV
|
|||||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={template.templateMeta?.qrSignatureEnabled}
|
||||||
>
|
>
|
||||||
<DocumentSigningAuthProvider
|
<DocumentSigningAuthProvider
|
||||||
documentAuthOptions={template.authOptions}
|
documentAuthOptions={template.authOptions}
|
||||||
|
|||||||
@@ -474,6 +474,7 @@ const SigningPageV1 = ({ data }: { data: Awaited<ReturnType<typeof handleV1Loade
|
|||||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={document.documentMeta?.qrSignatureEnabled}
|
||||||
>
|
>
|
||||||
<DocumentSigningAuthProvider documentAuthOptions={document.authOptions} recipient={recipient} user={user}>
|
<DocumentSigningAuthProvider documentAuthOptions={document.authOptions} recipient={recipient} user={user}>
|
||||||
{sessionData?.user && <AuthenticatedHeader />}
|
{sessionData?.user && <AuthenticatedHeader />}
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ const EmbedDirectTemplatePageV1 = ({ data }: { data: Awaited<ReturnType<typeof h
|
|||||||
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={template.templateMeta?.qrSignatureEnabled}
|
||||||
>
|
>
|
||||||
<DocumentSigningAuthProvider documentAuthOptions={template.authOptions} recipient={recipient} user={user}>
|
<DocumentSigningAuthProvider documentAuthOptions={template.authOptions} recipient={recipient} user={user}>
|
||||||
<DocumentSigningRecipientProvider recipient={recipient}>
|
<DocumentSigningRecipientProvider recipient={recipient}>
|
||||||
|
|||||||
@@ -354,6 +354,7 @@ const EmbedSignDocumentPageV1 = ({ data }: { data: Awaited<ReturnType<typeof han
|
|||||||
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={document.documentMeta?.qrSignatureEnabled}
|
||||||
>
|
>
|
||||||
<DocumentSigningAuthProvider documentAuthOptions={document.authOptions} recipient={recipient} user={user}>
|
<DocumentSigningAuthProvider documentAuthOptions={document.authOptions} recipient={recipient} user={user}>
|
||||||
<EmbedSignDocumentV1ClientPage
|
<EmbedSignDocumentV1ClientPage
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export default function EmbeddingAuthoringDocumentCreatePage() {
|
|||||||
drawSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.DRAW),
|
drawSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.DRAW),
|
||||||
typedSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.TYPE),
|
typedSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.TYPE),
|
||||||
uploadSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
uploadSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.UPLOAD),
|
||||||
|
qrSignatureEnabled: signatureTypes.length === 0 || signatureTypes.includes(DocumentSignatureType.QR),
|
||||||
},
|
},
|
||||||
recipients: configuration.signers.map((signer) => ({
|
recipients: configuration.signers.map((signer) => ({
|
||||||
name: signer.name,
|
name: signer.name,
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ export default function EmbeddingAuthoringDocumentEditPage() {
|
|||||||
types.push(DocumentSignatureType.UPLOAD);
|
types.push(DocumentSignatureType.UPLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (document.documentMeta?.qrSignatureEnabled) {
|
||||||
|
types.push(DocumentSignatureType.QR);
|
||||||
|
}
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}, [document.documentMeta]);
|
}, [document.documentMeta]);
|
||||||
|
|
||||||
@@ -216,6 +220,10 @@ export default function EmbeddingAuthoringDocumentEditPage() {
|
|||||||
? configuration.meta.signatureTypes.length === 0 ||
|
? configuration.meta.signatureTypes.length === 0 ||
|
||||||
configuration.meta.signatureTypes.includes(DocumentSignatureType.UPLOAD)
|
configuration.meta.signatureTypes.includes(DocumentSignatureType.UPLOAD)
|
||||||
: undefined,
|
: undefined,
|
||||||
|
qrSignatureEnabled: configuration.meta.signatureTypes
|
||||||
|
? configuration.meta.signatureTypes.length === 0 ||
|
||||||
|
configuration.meta.signatureTypes.includes(DocumentSignatureType.QR)
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
recipients: configuration.signers.map((signer) => ({
|
recipients: configuration.signers.map((signer) => ({
|
||||||
id: signer.nativeId,
|
id: signer.nativeId,
|
||||||
|
|||||||
@@ -101,6 +101,10 @@ export default function EmbeddingAuthoringTemplateEditPage() {
|
|||||||
types.push(DocumentSignatureType.UPLOAD);
|
types.push(DocumentSignatureType.UPLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (template.templateMeta?.qrSignatureEnabled) {
|
||||||
|
types.push(DocumentSignatureType.QR);
|
||||||
|
}
|
||||||
|
|
||||||
return types;
|
return types;
|
||||||
}, [template.templateMeta]);
|
}, [template.templateMeta]);
|
||||||
|
|
||||||
@@ -215,6 +219,10 @@ export default function EmbeddingAuthoringTemplateEditPage() {
|
|||||||
? configuration.meta.signatureTypes.length === 0 ||
|
? configuration.meta.signatureTypes.length === 0 ||
|
||||||
configuration.meta.signatureTypes.includes(DocumentSignatureType.UPLOAD)
|
configuration.meta.signatureTypes.includes(DocumentSignatureType.UPLOAD)
|
||||||
: undefined,
|
: undefined,
|
||||||
|
qrSignatureEnabled: configuration.meta.signatureTypes
|
||||||
|
? configuration.meta.signatureTypes.length === 0 ||
|
||||||
|
configuration.meta.signatureTypes.includes(DocumentSignatureType.QR)
|
||||||
|
: undefined,
|
||||||
},
|
},
|
||||||
recipients: configuration.signers.map((signer) => ({
|
recipients: configuration.signers.map((signer) => ({
|
||||||
id: signer.nativeId,
|
id: signer.nativeId,
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ export default function MultisignPage() {
|
|||||||
typedSignatureEnabled={selectedDocument.documentMeta?.typedSignatureEnabled}
|
typedSignatureEnabled={selectedDocument.documentMeta?.typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={selectedDocument.documentMeta?.uploadSignatureEnabled}
|
uploadSignatureEnabled={selectedDocument.documentMeta?.uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={selectedDocument.documentMeta?.drawSignatureEnabled}
|
drawSignatureEnabled={selectedDocument.documentMeta?.drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={selectedDocument.documentMeta?.qrSignatureEnabled}
|
||||||
>
|
>
|
||||||
<DocumentSigningAuthProvider
|
<DocumentSigningAuthProvider
|
||||||
documentAuthOptions={selectedDocument.authOptions}
|
documentAuthOptions={selectedDocument.authOptions}
|
||||||
|
|||||||
@@ -224,6 +224,7 @@ const EnvelopeCreatePage = ({ embedAuthoringOptions }: EnvelopeCreatePageProps)
|
|||||||
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled ?? undefined,
|
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled ?? undefined,
|
||||||
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled ?? undefined,
|
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled ?? undefined,
|
||||||
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled ?? undefined,
|
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled ?? undefined,
|
||||||
|
qrSignatureEnabled: envelope.documentMeta.qrSignatureEnabled ?? undefined,
|
||||||
dateFormat: (envelope.documentMeta.dateFormat as TDocumentMetaDateFormat) ?? undefined,
|
dateFormat: (envelope.documentMeta.dateFormat as TDocumentMetaDateFormat) ?? undefined,
|
||||||
language: envelope.documentMeta.language as SupportedLanguageCodes,
|
language: envelope.documentMeta.language as SupportedLanguageCodes,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -239,6 +239,7 @@ const EnvelopeEditPage = ({ embedAuthoringOptions }: EnvelopeEditPageProps) => {
|
|||||||
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled, //
|
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled, //
|
||||||
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled, //
|
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled, //
|
||||||
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled, //
|
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled, //
|
||||||
|
qrSignatureEnabled: envelope.documentMeta.qrSignatureEnabled, //
|
||||||
dateFormat: (envelope.documentMeta.dateFormat as TDocumentMetaDateFormat) ?? undefined,
|
dateFormat: (envelope.documentMeta.dateFormat as TDocumentMetaDateFormat) ?? undefined,
|
||||||
language: envelope.documentMeta.language as SupportedLanguageCodes,
|
language: envelope.documentMeta.language as SupportedLanguageCodes,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -12,12 +12,21 @@ type HandleSignatureFieldClickOptions = {
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const handleSignatureFieldClick = async (
|
export const handleSignatureFieldClick = async (
|
||||||
options: HandleSignatureFieldClickOptions,
|
options: HandleSignatureFieldClickOptions,
|
||||||
): Promise<Extract<TSignEnvelopeFieldValue, { type: typeof FieldType.SIGNATURE }> | null> => {
|
): Promise<Extract<TSignEnvelopeFieldValue, { type: typeof FieldType.SIGNATURE }> | null> => {
|
||||||
const { field, fullName, signature, typedSignatureEnabled, uploadSignatureEnabled, drawSignatureEnabled } = options;
|
const {
|
||||||
|
field,
|
||||||
|
fullName,
|
||||||
|
signature,
|
||||||
|
typedSignatureEnabled,
|
||||||
|
uploadSignatureEnabled,
|
||||||
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
|
} = options;
|
||||||
|
|
||||||
if (field.type !== FieldType.SIGNATURE) {
|
if (field.type !== FieldType.SIGNATURE) {
|
||||||
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
throw new AppError(AppErrorCode.INVALID_REQUEST, {
|
||||||
@@ -40,6 +49,7 @@ export const handleSignatureFieldClick = async (
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Generated
+1
@@ -33965,6 +33965,7 @@
|
|||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"ts-pattern": "^5.9.0",
|
"ts-pattern": "^5.9.0",
|
||||||
|
"uqr": "^0.1.2",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -438,6 +438,7 @@ export const ApiContractV1Implementation = tsr.router(ApiContractV1, {
|
|||||||
typedSignatureEnabled: body.meta.typedSignatureEnabled,
|
typedSignatureEnabled: body.meta.typedSignatureEnabled,
|
||||||
uploadSignatureEnabled: body.meta.uploadSignatureEnabled,
|
uploadSignatureEnabled: body.meta.uploadSignatureEnabled,
|
||||||
drawSignatureEnabled: body.meta.drawSignatureEnabled,
|
drawSignatureEnabled: body.meta.drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled: body.meta.qrSignatureEnabled,
|
||||||
distributionMethod: body.meta.distributionMethod,
|
distributionMethod: body.meta.distributionMethod,
|
||||||
emailSettings: body.meta.emailSettings,
|
emailSettings: body.meta.emailSettings,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ test.describe('API V2 Envelopes', () => {
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: false,
|
uploadSignatureEnabled: false,
|
||||||
drawSignatureEnabled: false,
|
drawSignatureEnabled: false,
|
||||||
|
qrSignatureEnabled: false,
|
||||||
emailReplyTo: userA.email,
|
emailReplyTo: userA.email,
|
||||||
emailSettings: {
|
emailSettings: {
|
||||||
recipientSigningRequest: false,
|
recipientSigningRequest: false,
|
||||||
@@ -295,6 +296,7 @@ test.describe('API V2 Envelopes', () => {
|
|||||||
expect(envelope.documentMeta.typedSignatureEnabled).toBe(payload.meta.typedSignatureEnabled);
|
expect(envelope.documentMeta.typedSignatureEnabled).toBe(payload.meta.typedSignatureEnabled);
|
||||||
expect(envelope.documentMeta.uploadSignatureEnabled).toBe(payload.meta.uploadSignatureEnabled);
|
expect(envelope.documentMeta.uploadSignatureEnabled).toBe(payload.meta.uploadSignatureEnabled);
|
||||||
expect(envelope.documentMeta.drawSignatureEnabled).toBe(payload.meta.drawSignatureEnabled);
|
expect(envelope.documentMeta.drawSignatureEnabled).toBe(payload.meta.drawSignatureEnabled);
|
||||||
|
expect(envelope.documentMeta.qrSignatureEnabled).toBe(payload.meta.qrSignatureEnabled);
|
||||||
expect(envelope.documentMeta.emailReplyTo).toBe(payload.meta.emailReplyTo);
|
expect(envelope.documentMeta.emailReplyTo).toBe(payload.meta.emailReplyTo);
|
||||||
expect(envelope.documentMeta.emailSettings).toEqual(payload.meta.emailSettings);
|
expect(envelope.documentMeta.emailSettings).toEqual(payload.meta.emailSettings);
|
||||||
|
|
||||||
|
|||||||
@@ -158,6 +158,7 @@ test.describe('AutoSave Settings Step', () => {
|
|||||||
expect(retrieved.documentMeta?.drawSignatureEnabled).toBe(false);
|
expect(retrieved.documentMeta?.drawSignatureEnabled).toBe(false);
|
||||||
expect(retrieved.documentMeta?.typedSignatureEnabled).toBe(false);
|
expect(retrieved.documentMeta?.typedSignatureEnabled).toBe(false);
|
||||||
expect(retrieved.documentMeta?.uploadSignatureEnabled).toBe(true);
|
expect(retrieved.documentMeta?.uploadSignatureEnabled).toBe(true);
|
||||||
|
expect(retrieved.documentMeta?.qrSignatureEnabled).toBe(true);
|
||||||
}).toPass();
|
}).toPass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ const assertEnvelopeSettingsPersistedInDatabase = async ({
|
|||||||
expect(envelope.documentMeta.drawSignatureEnabled).toBe(true);
|
expect(envelope.documentMeta.drawSignatureEnabled).toBe(true);
|
||||||
expect(envelope.documentMeta.typedSignatureEnabled).toBe(true);
|
expect(envelope.documentMeta.typedSignatureEnabled).toBe(true);
|
||||||
expect(envelope.documentMeta.uploadSignatureEnabled).toBe(false);
|
expect(envelope.documentMeta.uploadSignatureEnabled).toBe(false);
|
||||||
|
expect(envelope.documentMeta.qrSignatureEnabled).toBe(true);
|
||||||
expect(envelope.documentMeta.emailSettings).toMatchObject(DB_EXPECTED_VALUES.emailSettings);
|
expect(envelope.documentMeta.emailSettings).toMatchObject(DB_EXPECTED_VALUES.emailSettings);
|
||||||
|
|
||||||
const authOptions = parseAuthOptions(envelope.authOptions);
|
const authOptions = parseAuthOptions(envelope.authOptions);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ test('[ORGANISATIONS]: manage document preferences', async ({ page }) => {
|
|||||||
expect(teamSettings.typedSignatureEnabled).toEqual(true);
|
expect(teamSettings.typedSignatureEnabled).toEqual(true);
|
||||||
expect(teamSettings.uploadSignatureEnabled).toEqual(false);
|
expect(teamSettings.uploadSignatureEnabled).toEqual(false);
|
||||||
expect(teamSettings.drawSignatureEnabled).toEqual(false);
|
expect(teamSettings.drawSignatureEnabled).toEqual(false);
|
||||||
|
expect(teamSettings.qrSignatureEnabled).toEqual(true);
|
||||||
|
|
||||||
// Edit the team settings
|
// Edit the team settings
|
||||||
await page.goto(`/t/${team.url}/settings/document`);
|
await page.goto(`/t/${team.url}/settings/document`);
|
||||||
@@ -90,6 +91,7 @@ test('[ORGANISATIONS]: manage document preferences', async ({ page }) => {
|
|||||||
expect(updatedTeamSettings.typedSignatureEnabled).toEqual(true);
|
expect(updatedTeamSettings.typedSignatureEnabled).toEqual(true);
|
||||||
expect(updatedTeamSettings.uploadSignatureEnabled).toEqual(false);
|
expect(updatedTeamSettings.uploadSignatureEnabled).toEqual(false);
|
||||||
expect(updatedTeamSettings.drawSignatureEnabled).toEqual(false);
|
expect(updatedTeamSettings.drawSignatureEnabled).toEqual(false);
|
||||||
|
expect(updatedTeamSettings.qrSignatureEnabled).toEqual(true);
|
||||||
|
|
||||||
const document = await seedTeamDocumentWithMeta(team);
|
const document = await seedTeamDocumentWithMeta(team);
|
||||||
|
|
||||||
@@ -105,6 +107,7 @@ test('[ORGANISATIONS]: manage document preferences', async ({ page }) => {
|
|||||||
expect(documentMeta.typedSignatureEnabled).toEqual(true);
|
expect(documentMeta.typedSignatureEnabled).toEqual(true);
|
||||||
expect(documentMeta.uploadSignatureEnabled).toEqual(false);
|
expect(documentMeta.uploadSignatureEnabled).toEqual(false);
|
||||||
expect(documentMeta.drawSignatureEnabled).toEqual(false);
|
expect(documentMeta.drawSignatureEnabled).toEqual(false);
|
||||||
|
expect(documentMeta.qrSignatureEnabled).toEqual(true);
|
||||||
expect(documentMeta.language).toEqual('pl');
|
expect(documentMeta.language).toEqual('pl');
|
||||||
expect(documentMeta.timezone).toEqual('Europe/London');
|
expect(documentMeta.timezone).toEqual('Europe/London');
|
||||||
expect(documentMeta.dateFormat).toEqual('MM/dd/yyyy');
|
expect(documentMeta.dateFormat).toEqual('MM/dd/yyyy');
|
||||||
|
|||||||
@@ -0,0 +1,213 @@
|
|||||||
|
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||||
|
import { prisma } from '@documenso/prisma';
|
||||||
|
import { AnonymousVerificationTokenType, FieldType } from '@documenso/prisma/client';
|
||||||
|
import { seedPendingDocumentWithFullFields } from '@documenso/prisma/seed/documents';
|
||||||
|
import { seedUser } from '@documenso/prisma/seed/users';
|
||||||
|
import type { Page } from '@playwright/test';
|
||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
test.describe.configure({ mode: 'parallel' });
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a zig-zag onto the drawing canvas so that it passes the minimum
|
||||||
|
* signature coverage threshold.
|
||||||
|
*/
|
||||||
|
const drawOnSignaturePad = async (page: Page) => {
|
||||||
|
const canvas = page.getByTestId('signature-pad-draw');
|
||||||
|
|
||||||
|
await canvas.waitFor({ state: 'visible' });
|
||||||
|
|
||||||
|
let capturedBox: { x: number; y: number; width: number; height: number } | null = null;
|
||||||
|
|
||||||
|
// `boundingBox()` can return null if the canvas is replaced mid-hydration,
|
||||||
|
// so poll until a measurable element is attached, capturing the box inside
|
||||||
|
// the retry closure so it is never re-fetched (and re-raced) afterwards.
|
||||||
|
await expect(async () => {
|
||||||
|
capturedBox = await canvas.boundingBox();
|
||||||
|
|
||||||
|
expect(capturedBox).not.toBeNull();
|
||||||
|
expect(capturedBox?.width ?? 0).toBeGreaterThan(0);
|
||||||
|
}).toPass({ timeout: 5_000 });
|
||||||
|
|
||||||
|
// TS cannot see the closure assignment above, so widen the type back out.
|
||||||
|
const box = capturedBox as { x: number; y: number; width: number; height: number } | null;
|
||||||
|
|
||||||
|
if (!box) {
|
||||||
|
throw new Error('Signature pad canvas not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.mouse.move(box.x + box.width * 0.15, box.y + box.height * 0.5);
|
||||||
|
await page.mouse.down();
|
||||||
|
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
await page.mouse.move(box.x + box.width * (0.15 + i * 0.09), box.y + box.height * (i % 2 === 0 ? 0.25 : 0.75), {
|
||||||
|
steps: 10,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await page.mouse.up();
|
||||||
|
};
|
||||||
|
|
||||||
|
test('[QR_SIGNATURE]: complete signing via mobile qr handoff', async ({ page, browser }) => {
|
||||||
|
const { user, team } = await seedUser();
|
||||||
|
|
||||||
|
const { recipients } = await seedPendingDocumentWithFullFields({
|
||||||
|
owner: user,
|
||||||
|
recipients: ['qr-signer@test.documenso.com'],
|
||||||
|
teamId: team.id,
|
||||||
|
fields: [FieldType.SIGNATURE],
|
||||||
|
});
|
||||||
|
|
||||||
|
const recipient = recipients[0];
|
||||||
|
|
||||||
|
await page.goto(`/sign/${recipient.token}`);
|
||||||
|
|
||||||
|
// Wait for the client-side PDF render so we know the page has hydrated
|
||||||
|
// before interacting with the signature pad.
|
||||||
|
await page.waitForSelector(PDF_VIEWER_PAGE_SELECTOR);
|
||||||
|
|
||||||
|
// Open the signature dialog and switch to the Mobile tab.
|
||||||
|
await page.getByTestId('signature-pad-dialog-button').click();
|
||||||
|
await page.getByRole('tab', { name: 'Mobile' }).click();
|
||||||
|
|
||||||
|
// Read the handoff URL rendered beneath the QR code.
|
||||||
|
await expect(page.getByTestId('signature-pad-qr-url')).toBeVisible();
|
||||||
|
const handoffUrl = await page.getByTestId('signature-pad-qr-url').textContent();
|
||||||
|
|
||||||
|
expect(handoffUrl).toContain('/mobile-signature/');
|
||||||
|
|
||||||
|
// Open the mobile page in a fully isolated browser context (no shared
|
||||||
|
// cookies or session) to prove the handoff requires no authentication.
|
||||||
|
const mobileContext = await browser.newContext();
|
||||||
|
const mobilePage = await mobileContext.newPage();
|
||||||
|
|
||||||
|
await mobilePage.goto(handoffUrl ?? '');
|
||||||
|
|
||||||
|
await expect(mobilePage.getByRole('heading', { name: 'Draw your signature' })).toBeVisible();
|
||||||
|
|
||||||
|
await drawOnSignaturePad(mobilePage);
|
||||||
|
|
||||||
|
await mobilePage.getByRole('button', { name: 'Submit' }).click();
|
||||||
|
|
||||||
|
await expect(mobilePage.getByText('Signature sent')).toBeVisible();
|
||||||
|
|
||||||
|
await mobileContext.close();
|
||||||
|
|
||||||
|
// The desktop pad should receive the signature within a poll interval.
|
||||||
|
await expect(page.getByTestId('signature-pad-qr-preview')).toBeVisible({ timeout: 10_000 });
|
||||||
|
|
||||||
|
// The session is single-use: the desktop pickup deletes the row on read, and
|
||||||
|
// a missing row is indistinguishable from an expired one by design. So a
|
||||||
|
// revisit must show the expired page (not "Signature already sent"), which
|
||||||
|
// proves the deletion happened.
|
||||||
|
const revisitContext = await browser.newContext();
|
||||||
|
const revisitPage = await revisitContext.newPage();
|
||||||
|
|
||||||
|
await revisitPage.goto(handoffUrl ?? '');
|
||||||
|
|
||||||
|
await expect(revisitPage.getByRole('heading', { name: 'This link has expired' })).toBeVisible();
|
||||||
|
|
||||||
|
await revisitContext.close();
|
||||||
|
|
||||||
|
// Direct proof of consumption: the token row must be gone from the database.
|
||||||
|
const consumedToken = (handoffUrl ?? '').split('/mobile-signature/')[1];
|
||||||
|
|
||||||
|
const consumedRow = await prisma.anonymousVerificationToken.findFirst({
|
||||||
|
where: { token: consumedToken },
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(consumedRow).toBeNull();
|
||||||
|
|
||||||
|
// Confirm and finish signing the document.
|
||||||
|
await page.getByRole('button', { name: 'Next' }).click();
|
||||||
|
|
||||||
|
await page.locator('[data-field-type="SIGNATURE"]:not([data-readonly="true"])').first().click();
|
||||||
|
|
||||||
|
await page.getByRole('button', { name: 'Complete' }).click();
|
||||||
|
await page.getByRole('button', { name: 'Sign' }).click();
|
||||||
|
|
||||||
|
await page.waitForURL(`/sign/${recipient.token}/complete`);
|
||||||
|
await expect(page.getByText('Document Signed')).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[QR_SIGNATURE]: mobile tab hidden when qr disabled', async ({ page }) => {
|
||||||
|
const { user, team } = await seedUser();
|
||||||
|
|
||||||
|
const { document, recipients } = await seedPendingDocumentWithFullFields({
|
||||||
|
owner: user,
|
||||||
|
recipients: ['qr-disabled-signer@test.documenso.com'],
|
||||||
|
teamId: team.id,
|
||||||
|
fields: [FieldType.SIGNATURE],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Seeded documents create their meta row with bare column defaults, which
|
||||||
|
// leave qrSignatureEnabled true, so disable it directly on the meta row.
|
||||||
|
await prisma.documentMeta.update({
|
||||||
|
where: { id: document.documentMetaId },
|
||||||
|
data: { qrSignatureEnabled: false },
|
||||||
|
});
|
||||||
|
|
||||||
|
const recipient = recipients[0];
|
||||||
|
|
||||||
|
await page.goto(`/sign/${recipient.token}`);
|
||||||
|
|
||||||
|
await page.waitForSelector(PDF_VIEWER_PAGE_SELECTOR);
|
||||||
|
|
||||||
|
await page.getByTestId('signature-pad-dialog-button').click();
|
||||||
|
|
||||||
|
// Waiting on the Draw tab first guarantees the tab list has rendered before
|
||||||
|
// asserting the Mobile tab is absent.
|
||||||
|
await expect(page.getByRole('tab', { name: 'Draw' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('tab', { name: 'Mobile' })).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[QR_SIGNATURE]: mobile tab shown when draw disabled but qr enabled', async ({ page }) => {
|
||||||
|
const { user, team } = await seedUser();
|
||||||
|
|
||||||
|
const { document, recipients } = await seedPendingDocumentWithFullFields({
|
||||||
|
owner: user,
|
||||||
|
recipients: ['qr-only-signer@test.documenso.com'],
|
||||||
|
teamId: team.id,
|
||||||
|
fields: [FieldType.SIGNATURE],
|
||||||
|
});
|
||||||
|
|
||||||
|
// qrSignatureEnabled already defaults to true on seeded metas, but set it
|
||||||
|
// explicitly so the test still documents the required state if defaults change.
|
||||||
|
await prisma.documentMeta.update({
|
||||||
|
where: { id: document.documentMetaId },
|
||||||
|
data: { drawSignatureEnabled: false, qrSignatureEnabled: true },
|
||||||
|
});
|
||||||
|
|
||||||
|
const recipient = recipients[0];
|
||||||
|
|
||||||
|
await page.goto(`/sign/${recipient.token}`);
|
||||||
|
|
||||||
|
await page.waitForSelector(PDF_VIEWER_PAGE_SELECTOR);
|
||||||
|
|
||||||
|
await page.getByTestId('signature-pad-dialog-button').click();
|
||||||
|
|
||||||
|
await expect(page.getByRole('tab', { name: 'Mobile' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('tab', { name: 'Draw' })).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[QR_SIGNATURE]: unknown token shows expired page', async ({ page }) => {
|
||||||
|
await page.goto('/mobile-signature/this-token-does-not-exist');
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: 'This link has expired' })).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('[QR_SIGNATURE]: expired token shows expired page', async ({ page }) => {
|
||||||
|
const expiredToken = `qr-e2e-expired-${Date.now()}-${Math.floor(Math.random() * 100000)}`;
|
||||||
|
|
||||||
|
await prisma.anonymousVerificationToken.create({
|
||||||
|
data: {
|
||||||
|
type: AnonymousVerificationTokenType.QR_SIGNATURE,
|
||||||
|
token: expiredToken,
|
||||||
|
expiresAt: new Date(Date.now() - 60_000),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await page.goto(`/mobile-signature/${expiredToken}`);
|
||||||
|
|
||||||
|
await expect(page.getByRole('heading', { name: 'This link has expired' })).toBeVisible();
|
||||||
|
});
|
||||||
@@ -25,6 +25,7 @@ test('[TEAMS]: check that default team signature settings are all enabled', asyn
|
|||||||
await expect(page.getByRole('combobox').filter({ hasText: 'Type' })).toBeVisible();
|
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: 'Upload' })).toBeVisible();
|
||||||
await expect(page.getByRole('combobox').filter({ hasText: 'Draw' })).toBeVisible();
|
await expect(page.getByRole('combobox').filter({ hasText: 'Draw' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('combobox').filter({ hasText: 'QR code' })).toBeVisible();
|
||||||
|
|
||||||
// Go to document and check that the signatured tabs are correct.
|
// Go to document and check that the signatured tabs are correct.
|
||||||
await page.goto(`/sign/${document.recipients[0].token}`);
|
await page.goto(`/sign/${document.recipients[0].token}`);
|
||||||
@@ -34,6 +35,7 @@ test('[TEAMS]: check that default team signature settings are all enabled', asyn
|
|||||||
await expect(page.getByRole('tab', { name: 'Type' })).toBeVisible();
|
await expect(page.getByRole('tab', { name: 'Type' })).toBeVisible();
|
||||||
await expect(page.getByRole('tab', { name: 'Upload' })).toBeVisible();
|
await expect(page.getByRole('tab', { name: 'Upload' })).toBeVisible();
|
||||||
await expect(page.getByRole('tab', { name: 'Draw' })).toBeVisible();
|
await expect(page.getByRole('tab', { name: 'Draw' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('tab', { name: 'Mobile' })).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
||||||
@@ -45,8 +47,11 @@ test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
|||||||
redirectPath: `/t/${team.url}/settings/document`,
|
redirectPath: `/t/${team.url}/settings/document`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const allTabs = ['Type', 'Upload', 'Draw'];
|
// The 'QR code' signature type is surfaced as the 'Mobile' tab on the signing dialog.
|
||||||
const tabTest = [['Type', 'Upload', 'Draw'], ['Type', 'Upload'], ['Type']];
|
const allSignatureOptions = ['Type', 'Upload', 'Draw', 'QR code'];
|
||||||
|
const tabNameForOption = (option: string) => (option === 'QR code' ? 'Mobile' : option);
|
||||||
|
|
||||||
|
const tabTest = [['Type', 'Upload', 'Draw', 'QR code'], ['Type', 'Upload'], ['Type']];
|
||||||
|
|
||||||
for (const tabs of tabTest) {
|
for (const tabs of tabTest) {
|
||||||
await page.goto(`/t/${team.url}/settings/document`);
|
await page.goto(`/t/${team.url}/settings/document`);
|
||||||
@@ -57,9 +62,10 @@ test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
|||||||
await expect(page.getByRole('option', { name: 'Type' })).toBeVisible();
|
await expect(page.getByRole('option', { name: 'Type' })).toBeVisible();
|
||||||
await expect(page.getByRole('option', { name: 'Upload' })).toBeVisible();
|
await expect(page.getByRole('option', { name: 'Upload' })).toBeVisible();
|
||||||
await expect(page.getByRole('option', { name: 'Draw' })).toBeVisible();
|
await expect(page.getByRole('option', { name: 'Draw' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'QR code' })).toBeVisible();
|
||||||
|
|
||||||
// Clear all selected items.
|
// Clear all selected items.
|
||||||
for (const tab of allTabs) {
|
for (const tab of allSignatureOptions) {
|
||||||
const item = page.getByRole('option', { name: tab });
|
const item = page.getByRole('option', { name: tab });
|
||||||
|
|
||||||
const isSelected = (await item.innerHTML()).includes('opacity-100');
|
const isSelected = (await item.innerHTML()).includes('opacity-100');
|
||||||
@@ -90,12 +96,13 @@ test('[TEAMS]: check signature modes can be disabled', async ({ page }) => {
|
|||||||
await page.waitForSelector('[role="dialog"]');
|
await page.waitForSelector('[role="dialog"]');
|
||||||
|
|
||||||
// Check the tab values
|
// Check the tab values
|
||||||
for (const tab of allTabs) {
|
for (const option of allSignatureOptions) {
|
||||||
if (tabs.includes(tab)) {
|
const tabName = tabNameForOption(option);
|
||||||
await expect(page.getByRole('tab', { name: tab })).toBeVisible();
|
|
||||||
|
if (tabs.includes(option)) {
|
||||||
|
await expect(page.getByRole('tab', { name: tabName })).toBeVisible();
|
||||||
} else {
|
} else {
|
||||||
// await expect(page.getByRole('tab', { name: tab })).not.toBeVisible();
|
await expect(page.getByRole('tab', { name: tabName })).toHaveCount(0);
|
||||||
await expect(page.getByRole('tab', { name: tab })).toHaveCount(0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,8 +117,8 @@ test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
|
|||||||
redirectPath: `/t/${team.url}/settings/document`,
|
redirectPath: `/t/${team.url}/settings/document`,
|
||||||
});
|
});
|
||||||
|
|
||||||
const allTabs = ['Type', 'Upload', 'Draw'];
|
const allSignatureOptions = ['Type', 'Upload', 'Draw', 'QR code'];
|
||||||
const tabTest = [['Type', 'Upload', 'Draw'], ['Type', 'Upload'], ['Type']];
|
const tabTest = [['Type', 'Upload', 'Draw', 'QR code'], ['Type', 'Upload'], ['Type']];
|
||||||
|
|
||||||
for (const tabs of tabTest) {
|
for (const tabs of tabTest) {
|
||||||
await page.goto(`/t/${team.url}/settings/document`);
|
await page.goto(`/t/${team.url}/settings/document`);
|
||||||
@@ -122,9 +129,10 @@ test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
|
|||||||
await expect(page.getByRole('option', { name: 'Type' })).toBeVisible();
|
await expect(page.getByRole('option', { name: 'Type' })).toBeVisible();
|
||||||
await expect(page.getByRole('option', { name: 'Upload' })).toBeVisible();
|
await expect(page.getByRole('option', { name: 'Upload' })).toBeVisible();
|
||||||
await expect(page.getByRole('option', { name: 'Draw' })).toBeVisible();
|
await expect(page.getByRole('option', { name: 'Draw' })).toBeVisible();
|
||||||
|
await expect(page.getByRole('option', { name: 'QR code' })).toBeVisible();
|
||||||
|
|
||||||
// Clear all selected items.
|
// Clear all selected items.
|
||||||
for (const tab of allTabs) {
|
for (const tab of allSignatureOptions) {
|
||||||
const item = page.getByRole('option', { name: tab });
|
const item = page.getByRole('option', { name: tab });
|
||||||
|
|
||||||
const isSelected = (await item.innerHTML()).includes('opacity-100');
|
const isSelected = (await item.innerHTML()).includes('opacity-100');
|
||||||
@@ -176,5 +184,6 @@ test('[TEAMS]: check signature modes work for templates', async ({ page }) => {
|
|||||||
expect(document?.documentMeta?.typedSignatureEnabled).toEqual(tabs.includes('Type'));
|
expect(document?.documentMeta?.typedSignatureEnabled).toEqual(tabs.includes('Type'));
|
||||||
expect(document?.documentMeta?.uploadSignatureEnabled).toEqual(tabs.includes('Upload'));
|
expect(document?.documentMeta?.uploadSignatureEnabled).toEqual(tabs.includes('Upload'));
|
||||||
expect(document?.documentMeta?.drawSignatureEnabled).toEqual(tabs.includes('Draw'));
|
expect(document?.documentMeta?.drawSignatureEnabled).toEqual(tabs.includes('Draw'));
|
||||||
|
expect(document?.documentMeta?.qrSignatureEnabled).toEqual(tabs.includes('QR code'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ test.describe('AutoSave Settings Step - Templates', () => {
|
|||||||
expect(retrievedTemplate.templateMeta?.drawSignatureEnabled).toBe(false);
|
expect(retrievedTemplate.templateMeta?.drawSignatureEnabled).toBe(false);
|
||||||
expect(retrievedTemplate.templateMeta?.typedSignatureEnabled).toBe(false);
|
expect(retrievedTemplate.templateMeta?.typedSignatureEnabled).toBe(false);
|
||||||
expect(retrievedTemplate.templateMeta?.uploadSignatureEnabled).toBe(true);
|
expect(retrievedTemplate.templateMeta?.uploadSignatureEnabled).toBe(true);
|
||||||
|
expect(retrievedTemplate.templateMeta?.qrSignatureEnabled).toBe(true);
|
||||||
}).toPass();
|
}).toPass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -77,4 +77,11 @@ export const DOCUMENT_SIGNATURE_TYPES = {
|
|||||||
}),
|
}),
|
||||||
value: DocumentSignatureType.UPLOAD,
|
value: DocumentSignatureType.UPLOAD,
|
||||||
},
|
},
|
||||||
|
[DocumentSignatureType.QR]: {
|
||||||
|
label: msg({
|
||||||
|
message: `QR code`,
|
||||||
|
context: `Sign using a mobile phone via QR code`,
|
||||||
|
}),
|
||||||
|
value: DocumentSignatureType.QR,
|
||||||
|
},
|
||||||
} satisfies Record<DocumentSignatureType, DocumentSignatureTypeData>;
|
} satisfies Record<DocumentSignatureType, DocumentSignatureTypeData>;
|
||||||
|
|||||||
@@ -2,3 +2,5 @@ export const SIGNATURE_CANVAS_DPI = 2;
|
|||||||
export const SIGNATURE_MIN_COVERAGE_THRESHOLD = 0.01;
|
export const SIGNATURE_MIN_COVERAGE_THRESHOLD = 0.01;
|
||||||
|
|
||||||
export const isBase64Image = (value: string) => value.startsWith('data:image/png;base64,');
|
export const isBase64Image = (value: string) => value.startsWith('data:image/png;base64,');
|
||||||
|
|
||||||
|
export const QR_SIGNATURE_TOKEN_EXPIRY_MINUTES = 10;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import { ADMIN_DELETE_ORGANISATION_JOB_DEFINITION } from './definitions/internal
|
|||||||
import { BACKPORT_SUBSCRIPTION_CLAIM_JOB_DEFINITION } from './definitions/internal/backport-subscription-claims';
|
import { BACKPORT_SUBSCRIPTION_CLAIM_JOB_DEFINITION } from './definitions/internal/backport-subscription-claims';
|
||||||
import { BULK_SEND_TEMPLATE_JOB_DEFINITION } from './definitions/internal/bulk-send-template';
|
import { BULK_SEND_TEMPLATE_JOB_DEFINITION } from './definitions/internal/bulk-send-template';
|
||||||
import { CANCEL_ORGANISATION_SUBSCRIPTION_JOB_DEFINITION } from './definitions/internal/cancel-organisation-subscription';
|
import { CANCEL_ORGANISATION_SUBSCRIPTION_JOB_DEFINITION } from './definitions/internal/cancel-organisation-subscription';
|
||||||
|
import { CLEANUP_ANONYMOUS_TOKENS_JOB_DEFINITION } from './definitions/internal/cleanup-anonymous-tokens';
|
||||||
import { CLEANUP_RATE_LIMITS_JOB_DEFINITION } from './definitions/internal/cleanup-rate-limits';
|
import { CLEANUP_RATE_LIMITS_JOB_DEFINITION } from './definitions/internal/cleanup-rate-limits';
|
||||||
import { EXECUTE_WEBHOOK_JOB_DEFINITION } from './definitions/internal/execute-webhook';
|
import { EXECUTE_WEBHOOK_JOB_DEFINITION } from './definitions/internal/execute-webhook';
|
||||||
import { EXPIRE_RECIPIENTS_SWEEP_JOB_DEFINITION } from './definitions/internal/expire-recipients-sweep';
|
import { EXPIRE_RECIPIENTS_SWEEP_JOB_DEFINITION } from './definitions/internal/expire-recipients-sweep';
|
||||||
@@ -62,6 +63,7 @@ export const jobsClient = new JobClient([
|
|||||||
SEND_SIGNING_REMINDERS_SWEEP_JOB_DEFINITION,
|
SEND_SIGNING_REMINDERS_SWEEP_JOB_DEFINITION,
|
||||||
PROCESS_SIGNING_REMINDER_JOB_DEFINITION,
|
PROCESS_SIGNING_REMINDER_JOB_DEFINITION,
|
||||||
CLEANUP_RATE_LIMITS_JOB_DEFINITION,
|
CLEANUP_RATE_LIMITS_JOB_DEFINITION,
|
||||||
|
CLEANUP_ANONYMOUS_TOKENS_JOB_DEFINITION,
|
||||||
SYNC_EMAIL_DOMAINS_JOB_DEFINITION,
|
SYNC_EMAIL_DOMAINS_JOB_DEFINITION,
|
||||||
ADMIN_DELETE_ORGANISATION_JOB_DEFINITION,
|
ADMIN_DELETE_ORGANISATION_JOB_DEFINITION,
|
||||||
CANCEL_ORGANISATION_SUBSCRIPTION_JOB_DEFINITION,
|
CANCEL_ORGANISATION_SUBSCRIPTION_JOB_DEFINITION,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { prisma } from '@documenso/prisma';
|
import { prisma } from '@documenso/prisma';
|
||||||
|
import { AnonymousVerificationTokenType } from '@prisma/client';
|
||||||
import { generateAuthenticationOptions } from '@simplewebauthn/server';
|
import { generateAuthenticationOptions } from '@simplewebauthn/server';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
|
|
||||||
@@ -24,12 +25,14 @@ export const createPasskeySigninOptions = async ({ sessionId }: CreatePasskeySig
|
|||||||
id: sessionId,
|
id: sessionId,
|
||||||
},
|
},
|
||||||
update: {
|
update: {
|
||||||
|
type: AnonymousVerificationTokenType.PASSKEY,
|
||||||
token: challenge,
|
token: challenge,
|
||||||
expiresAt: DateTime.now().plus({ minutes: 2 }).toJSDate(),
|
expiresAt: DateTime.now().plus({ minutes: 2 }).toJSDate(),
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
},
|
},
|
||||||
create: {
|
create: {
|
||||||
id: sessionId,
|
id: sessionId,
|
||||||
|
type: AnonymousVerificationTokenType.PASSKEY,
|
||||||
token: challenge,
|
token: challenge,
|
||||||
expiresAt: DateTime.now().plus({ minutes: 2 }).toJSDate(),
|
expiresAt: DateTime.now().plus({ minutes: 2 }).toJSDate(),
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ export type CreateDocumentMetaOptions = {
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
language?: SupportedLanguageCodes;
|
language?: SupportedLanguageCodes;
|
||||||
requestMetadata: ApiRequestMetadata;
|
requestMetadata: ApiRequestMetadata;
|
||||||
};
|
};
|
||||||
@@ -53,6 +54,7 @@ export const updateDocumentMeta = async ({
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
language,
|
language,
|
||||||
requestMetadata,
|
requestMetadata,
|
||||||
}: CreateDocumentMetaOptions) => {
|
}: CreateDocumentMetaOptions) => {
|
||||||
@@ -132,6 +134,7 @@ export const updateDocumentMeta = async ({
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
language,
|
language,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ export const ZEnvelopeForSigningResponse = z.object({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
allowDictateNextSigner: true,
|
allowDictateNextSigner: true,
|
||||||
language: true,
|
language: true,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ export type CreateDocumentFromTemplateOptions = {
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
envelopeExpirationPeriod?: TEnvelopeExpirationPeriod | null;
|
envelopeExpirationPeriod?: TEnvelopeExpirationPeriod | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -540,6 +541,7 @@ export const createDocumentFromTemplate = async ({
|
|||||||
typedSignatureEnabled: override?.typedSignatureEnabled ?? template.documentMeta?.typedSignatureEnabled,
|
typedSignatureEnabled: override?.typedSignatureEnabled ?? template.documentMeta?.typedSignatureEnabled,
|
||||||
uploadSignatureEnabled: override?.uploadSignatureEnabled ?? template.documentMeta?.uploadSignatureEnabled,
|
uploadSignatureEnabled: override?.uploadSignatureEnabled ?? template.documentMeta?.uploadSignatureEnabled,
|
||||||
drawSignatureEnabled: override?.drawSignatureEnabled ?? template.documentMeta?.drawSignatureEnabled,
|
drawSignatureEnabled: override?.drawSignatureEnabled ?? template.documentMeta?.drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled: override?.qrSignatureEnabled ?? template.documentMeta?.qrSignatureEnabled,
|
||||||
allowDictateNextSigner: override?.allowDictateNextSigner ?? template.documentMeta?.allowDictateNextSigner,
|
allowDictateNextSigner: override?.allowDictateNextSigner ?? template.documentMeta?.allowDictateNextSigner,
|
||||||
envelopeExpirationPeriod: override?.envelopeExpirationPeriod ?? template.documentMeta?.envelopeExpirationPeriod,
|
envelopeExpirationPeriod: override?.envelopeExpirationPeriod ?? template.documentMeta?.envelopeExpirationPeriod,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ export const generateSampleWebhookPayload = (event: WebhookTriggerEvents, webhoo
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
distributionMethod: DocumentDistributionMethod.EMAIL,
|
distributionMethod: DocumentDistributionMethod.EMAIL,
|
||||||
emailSettings: null,
|
emailSettings: null,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export const ZDocumentMetaSchema = DocumentMetaSchema.pick({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
language: true,
|
language: true,
|
||||||
emailSettings: true,
|
emailSettings: true,
|
||||||
});
|
});
|
||||||
@@ -105,6 +106,10 @@ export const ZDocumentMetaUploadSignatureEnabledSchema = z
|
|||||||
.boolean()
|
.boolean()
|
||||||
.describe('Whether to allow recipients to sign using an uploaded signature.');
|
.describe('Whether to allow recipients to sign using an uploaded signature.');
|
||||||
|
|
||||||
|
export const ZDocumentMetaQrSignatureEnabledSchema = z
|
||||||
|
.boolean()
|
||||||
|
.describe('Whether to allow recipients to sign using a QR code handoff to a mobile device.');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Any updates to this will cause public API changes. You will need to update
|
* Note: Any updates to this will cause public API changes. You will need to update
|
||||||
* all corresponding areas where this is used (some places that use this needs to pass
|
* all corresponding areas where this is used (some places that use this needs to pass
|
||||||
@@ -123,6 +128,7 @@ export const ZDocumentMetaCreateSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
emailId: z.string().nullish(),
|
emailId: z.string().nullish(),
|
||||||
emailReplyTo: zEmail().nullish(),
|
emailReplyTo: zEmail().nullish(),
|
||||||
emailSettings: ZDocumentEmailSettingsSchema.nullish(),
|
emailSettings: ZDocumentEmailSettingsSchema.nullish(),
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ export const ZDocumentSchema = LegacyDocumentSchema.pick({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
allowDictateNextSigner: true,
|
allowDictateNextSigner: true,
|
||||||
language: true,
|
language: true,
|
||||||
emailSettings: true,
|
emailSettings: true,
|
||||||
|
|||||||
@@ -279,6 +279,7 @@ export const ZEditorEnvelopeSchema = EnvelopeSchema.pick({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
allowDictateNextSigner: true,
|
allowDictateNextSigner: true,
|
||||||
language: true,
|
language: true,
|
||||||
emailSettings: true,
|
emailSettings: true,
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export const ZEnvelopeSchema = EnvelopeSchema.pick({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
allowDictateNextSigner: true,
|
allowDictateNextSigner: true,
|
||||||
language: true,
|
language: true,
|
||||||
emailSettings: true,
|
emailSettings: true,
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export const ZTemplateSchema = TemplateSchema.pick({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
allowDictateNextSigner: true,
|
allowDictateNextSigner: true,
|
||||||
distributionMethod: true,
|
distributionMethod: true,
|
||||||
redirectUrl: true,
|
redirectUrl: true,
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ export const ZWebhookDocumentMetaSchema = z.object({
|
|||||||
typedSignatureEnabled: z.boolean(),
|
typedSignatureEnabled: z.boolean(),
|
||||||
uploadSignatureEnabled: z.boolean(),
|
uploadSignatureEnabled: z.boolean(),
|
||||||
drawSignatureEnabled: z.boolean(),
|
drawSignatureEnabled: z.boolean(),
|
||||||
|
qrSignatureEnabled: z.boolean(),
|
||||||
language: z.string(),
|
language: z.string(),
|
||||||
distributionMethod: z.nativeEnum(DocumentDistributionMethod),
|
distributionMethod: z.nativeEnum(DocumentDistributionMethod),
|
||||||
emailSettings: z.any().nullable(),
|
emailSettings: z.any().nullable(),
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ export const extractDerivedDocumentMeta = (
|
|||||||
typedSignatureEnabled: meta.typedSignatureEnabled ?? settings.typedSignatureEnabled,
|
typedSignatureEnabled: meta.typedSignatureEnabled ?? settings.typedSignatureEnabled,
|
||||||
uploadSignatureEnabled: meta.uploadSignatureEnabled ?? settings.uploadSignatureEnabled,
|
uploadSignatureEnabled: meta.uploadSignatureEnabled ?? settings.uploadSignatureEnabled,
|
||||||
drawSignatureEnabled: meta.drawSignatureEnabled ?? settings.drawSignatureEnabled,
|
drawSignatureEnabled: meta.drawSignatureEnabled ?? settings.drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled: meta.qrSignatureEnabled ?? settings.qrSignatureEnabled,
|
||||||
|
|
||||||
// Email settings.
|
// Email settings.
|
||||||
emailId: meta.emailId ?? settings.emailId,
|
emailId: meta.emailId ?? settings.emailId,
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ export const generateDefaultOrganisationSettings = (): Omit<OrganisationGlobalSe
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
|
|
||||||
brandingEnabled: false,
|
brandingEnabled: false,
|
||||||
brandingLogo: '',
|
brandingLogo: '',
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export enum DocumentSignatureType {
|
|||||||
DRAW = 'draw',
|
DRAW = 'draw',
|
||||||
TYPE = 'type',
|
TYPE = 'type',
|
||||||
UPLOAD = 'upload',
|
UPLOAD = 'upload',
|
||||||
|
QR = 'qr',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const formatTeamUrl = (teamUrl: string, baseUrl?: string) => {
|
export const formatTeamUrl = (teamUrl: string, baseUrl?: string) => {
|
||||||
@@ -93,10 +94,16 @@ export const extractTeamSignatureSettings = (
|
|||||||
typedSignatureEnabled: boolean | null;
|
typedSignatureEnabled: boolean | null;
|
||||||
drawSignatureEnabled: boolean | null;
|
drawSignatureEnabled: boolean | null;
|
||||||
uploadSignatureEnabled: boolean | null;
|
uploadSignatureEnabled: boolean | null;
|
||||||
|
qrSignatureEnabled: boolean | null;
|
||||||
} | null,
|
} | null,
|
||||||
) => {
|
) => {
|
||||||
if (!settings) {
|
if (!settings) {
|
||||||
return [DocumentSignatureType.TYPE, DocumentSignatureType.UPLOAD, DocumentSignatureType.DRAW];
|
return [
|
||||||
|
DocumentSignatureType.TYPE,
|
||||||
|
DocumentSignatureType.UPLOAD,
|
||||||
|
DocumentSignatureType.DRAW,
|
||||||
|
DocumentSignatureType.QR,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
const signatureTypes: DocumentSignatureType[] = [];
|
const signatureTypes: DocumentSignatureType[] = [];
|
||||||
@@ -113,6 +120,10 @@ export const extractTeamSignatureSettings = (
|
|||||||
signatureTypes.push(DocumentSignatureType.UPLOAD);
|
signatureTypes.push(DocumentSignatureType.UPLOAD);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.qrSignatureEnabled) {
|
||||||
|
signatureTypes.push(DocumentSignatureType.QR);
|
||||||
|
}
|
||||||
|
|
||||||
return signatureTypes;
|
return signatureTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -186,6 +197,7 @@ export const generateDefaultTeamSettings = (): Omit<TeamGlobalSettings, 'id' | '
|
|||||||
typedSignatureEnabled: null,
|
typedSignatureEnabled: null,
|
||||||
uploadSignatureEnabled: null,
|
uploadSignatureEnabled: null,
|
||||||
drawSignatureEnabled: null,
|
drawSignatureEnabled: null,
|
||||||
|
qrSignatureEnabled: null,
|
||||||
|
|
||||||
brandingEnabled: null,
|
brandingEnabled: null,
|
||||||
brandingLogo: null,
|
brandingLogo: null,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||||
ZDocumentMetaLanguageSchema,
|
ZDocumentMetaLanguageSchema,
|
||||||
ZDocumentMetaMessageSchema,
|
ZDocumentMetaMessageSchema,
|
||||||
|
ZDocumentMetaQrSignatureEnabledSchema,
|
||||||
ZDocumentMetaRedirectUrlSchema,
|
ZDocumentMetaRedirectUrlSchema,
|
||||||
ZDocumentMetaSubjectSchema,
|
ZDocumentMetaSubjectSchema,
|
||||||
ZDocumentMetaTimezoneSchema,
|
ZDocumentMetaTimezoneSchema,
|
||||||
@@ -65,6 +66,7 @@ export const ZCreateEmbeddingDocumentRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||||
ZDocumentMetaLanguageSchema,
|
ZDocumentMetaLanguageSchema,
|
||||||
ZDocumentMetaMessageSchema,
|
ZDocumentMetaMessageSchema,
|
||||||
|
ZDocumentMetaQrSignatureEnabledSchema,
|
||||||
ZDocumentMetaRedirectUrlSchema,
|
ZDocumentMetaRedirectUrlSchema,
|
||||||
ZDocumentMetaSubjectSchema,
|
ZDocumentMetaSubjectSchema,
|
||||||
ZDocumentMetaTimezoneSchema,
|
ZDocumentMetaTimezoneSchema,
|
||||||
@@ -62,6 +63,7 @@ export const ZCreateEmbeddingTemplateRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export const ZGetMultiSignDocumentResponseSchema = ZDocumentLiteSchema.extend({
|
|||||||
typedSignatureEnabled: true,
|
typedSignatureEnabled: true,
|
||||||
uploadSignatureEnabled: true,
|
uploadSignatureEnabled: true,
|
||||||
drawSignatureEnabled: true,
|
drawSignatureEnabled: true,
|
||||||
|
qrSignatureEnabled: true,
|
||||||
allowDictateNextSigner: true,
|
allowDictateNextSigner: true,
|
||||||
language: true,
|
language: true,
|
||||||
emailSettings: true,
|
emailSettings: true,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||||
ZDocumentMetaLanguageSchema,
|
ZDocumentMetaLanguageSchema,
|
||||||
ZDocumentMetaMessageSchema,
|
ZDocumentMetaMessageSchema,
|
||||||
|
ZDocumentMetaQrSignatureEnabledSchema,
|
||||||
ZDocumentMetaRedirectUrlSchema,
|
ZDocumentMetaRedirectUrlSchema,
|
||||||
ZDocumentMetaSubjectSchema,
|
ZDocumentMetaSubjectSchema,
|
||||||
ZDocumentMetaTimezoneSchema,
|
ZDocumentMetaTimezoneSchema,
|
||||||
@@ -66,6 +67,7 @@ export const ZUpdateEmbeddingDocumentRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||||
ZDocumentMetaLanguageSchema,
|
ZDocumentMetaLanguageSchema,
|
||||||
ZDocumentMetaMessageSchema,
|
ZDocumentMetaMessageSchema,
|
||||||
|
ZDocumentMetaQrSignatureEnabledSchema,
|
||||||
ZDocumentMetaRedirectUrlSchema,
|
ZDocumentMetaRedirectUrlSchema,
|
||||||
ZDocumentMetaSubjectSchema,
|
ZDocumentMetaSubjectSchema,
|
||||||
ZDocumentMetaTimezoneSchema,
|
ZDocumentMetaTimezoneSchema,
|
||||||
@@ -66,6 +67,7 @@ export const ZUpdateEmbeddingTemplateRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
emailSettings: ZDocumentEmailSettingsSchema.optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||||
ZDocumentMetaLanguageSchema,
|
ZDocumentMetaLanguageSchema,
|
||||||
ZDocumentMetaMessageSchema,
|
ZDocumentMetaMessageSchema,
|
||||||
|
ZDocumentMetaQrSignatureEnabledSchema,
|
||||||
ZDocumentMetaRedirectUrlSchema,
|
ZDocumentMetaRedirectUrlSchema,
|
||||||
ZDocumentMetaSubjectSchema,
|
ZDocumentMetaSubjectSchema,
|
||||||
ZDocumentMetaTimezoneSchema,
|
ZDocumentMetaTimezoneSchema,
|
||||||
@@ -94,6 +95,7 @@ export const ZUseEnvelopePayloadSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
allowDictateNextSigner: z.boolean().optional(),
|
allowDictateNextSigner: z.boolean().optional(),
|
||||||
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
|
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ export const updateOrganisationSettingsRoute = authenticatedProcedure
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
defaultRecipients,
|
defaultRecipients,
|
||||||
delegateDocumentOwnership,
|
delegateDocumentOwnership,
|
||||||
envelopeExpirationPeriod,
|
envelopeExpirationPeriod,
|
||||||
@@ -104,6 +105,7 @@ export const updateOrganisationSettingsRoute = authenticatedProcedure
|
|||||||
uploadSignatureEnabled ?? organisation.organisationGlobalSettings.uploadSignatureEnabled;
|
uploadSignatureEnabled ?? organisation.organisationGlobalSettings.uploadSignatureEnabled;
|
||||||
const derivedDrawSignatureEnabled =
|
const derivedDrawSignatureEnabled =
|
||||||
drawSignatureEnabled ?? organisation.organisationGlobalSettings.drawSignatureEnabled;
|
drawSignatureEnabled ?? organisation.organisationGlobalSettings.drawSignatureEnabled;
|
||||||
|
const derivedQrSignatureEnabled = qrSignatureEnabled ?? organisation.organisationGlobalSettings.qrSignatureEnabled;
|
||||||
|
|
||||||
const derivedDelegateDocumentOwnership =
|
const derivedDelegateDocumentOwnership =
|
||||||
delegateDocumentOwnership ?? organisation.organisationGlobalSettings.delegateDocumentOwnership;
|
delegateDocumentOwnership ?? organisation.organisationGlobalSettings.delegateDocumentOwnership;
|
||||||
@@ -111,7 +113,8 @@ export const updateOrganisationSettingsRoute = authenticatedProcedure
|
|||||||
if (
|
if (
|
||||||
derivedTypedSignatureEnabled === false &&
|
derivedTypedSignatureEnabled === false &&
|
||||||
derivedUploadSignatureEnabled === false &&
|
derivedUploadSignatureEnabled === false &&
|
||||||
derivedDrawSignatureEnabled === false
|
derivedDrawSignatureEnabled === false &&
|
||||||
|
derivedQrSignatureEnabled === false
|
||||||
) {
|
) {
|
||||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||||
message: 'At least one signature type must be enabled',
|
message: 'At least one signature type must be enabled',
|
||||||
@@ -166,6 +169,7 @@ export const updateOrganisationSettingsRoute = authenticatedProcedure
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
defaultRecipients: defaultRecipients === null ? Prisma.DbNull : defaultRecipients,
|
defaultRecipients: defaultRecipients === null ? Prisma.DbNull : defaultRecipients,
|
||||||
delegateDocumentOwnership: derivedDelegateDocumentOwnership,
|
delegateDocumentOwnership: derivedDelegateDocumentOwnership,
|
||||||
envelopeExpirationPeriod: envelopeExpirationPeriod === null ? Prisma.DbNull : envelopeExpirationPeriod,
|
envelopeExpirationPeriod: envelopeExpirationPeriod === null ? Prisma.DbNull : envelopeExpirationPeriod,
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const ZUpdateOrganisationSettingsRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: z.boolean().optional(),
|
typedSignatureEnabled: z.boolean().optional(),
|
||||||
uploadSignatureEnabled: z.boolean().optional(),
|
uploadSignatureEnabled: z.boolean().optional(),
|
||||||
drawSignatureEnabled: z.boolean().optional(),
|
drawSignatureEnabled: z.boolean().optional(),
|
||||||
|
qrSignatureEnabled: z.boolean().optional(),
|
||||||
defaultRecipients: ZDefaultRecipientsSchema.nullish(),
|
defaultRecipients: ZDefaultRecipientsSchema.nullish(),
|
||||||
delegateDocumentOwnership: z.boolean().nullish(),
|
delegateDocumentOwnership: z.boolean().nullish(),
|
||||||
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.optional(),
|
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.optional(),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { folderRouter } from './folder-router/router';
|
|||||||
import { organisationRouter } from './organisation-router/router';
|
import { organisationRouter } from './organisation-router/router';
|
||||||
import { profileRouter } from './profile-router/router';
|
import { profileRouter } from './profile-router/router';
|
||||||
import { recipientRouter } from './recipient-router/router';
|
import { recipientRouter } from './recipient-router/router';
|
||||||
|
import { signatureRouter } from './signature-router/router';
|
||||||
import { teamRouter } from './team-router/router';
|
import { teamRouter } from './team-router/router';
|
||||||
import { templateRouter } from './template-router/router';
|
import { templateRouter } from './template-router/router';
|
||||||
import { router } from './trpc';
|
import { router } from './trpc';
|
||||||
@@ -24,6 +25,7 @@ export const appRouter = router({
|
|||||||
field: fieldRouter,
|
field: fieldRouter,
|
||||||
folder: folderRouter,
|
folder: folderRouter,
|
||||||
recipient: recipientRouter,
|
recipient: recipientRouter,
|
||||||
|
signature: signatureRouter,
|
||||||
admin: adminRouter,
|
admin: adminRouter,
|
||||||
organisation: organisationRouter,
|
organisation: organisationRouter,
|
||||||
apiToken: apiTokenRouter,
|
apiToken: apiTokenRouter,
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ export const updateTeamSettingsRoute = authenticatedProcedure
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
delegateDocumentOwnership,
|
delegateDocumentOwnership,
|
||||||
envelopeExpirationPeriod,
|
envelopeExpirationPeriod,
|
||||||
reminderSettings,
|
reminderSettings,
|
||||||
@@ -66,7 +67,12 @@ export const updateTeamSettingsRoute = authenticatedProcedure
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Signatures will only be inherited if all are NULL.
|
// Signatures will only be inherited if all are NULL.
|
||||||
if (typedSignatureEnabled === false && uploadSignatureEnabled === false && drawSignatureEnabled === false) {
|
if (
|
||||||
|
typedSignatureEnabled === false &&
|
||||||
|
uploadSignatureEnabled === false &&
|
||||||
|
drawSignatureEnabled === false &&
|
||||||
|
qrSignatureEnabled === false
|
||||||
|
) {
|
||||||
throw new AppError(AppErrorCode.INVALID_BODY, {
|
throw new AppError(AppErrorCode.INVALID_BODY, {
|
||||||
message: 'At least one signature type must be enabled',
|
message: 'At least one signature type must be enabled',
|
||||||
});
|
});
|
||||||
@@ -169,6 +175,7 @@ export const updateTeamSettingsRoute = authenticatedProcedure
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
delegateDocumentOwnership,
|
delegateDocumentOwnership,
|
||||||
envelopeExpirationPeriod: envelopeExpirationPeriod === null ? Prisma.DbNull : envelopeExpirationPeriod,
|
envelopeExpirationPeriod: envelopeExpirationPeriod === null ? Prisma.DbNull : envelopeExpirationPeriod,
|
||||||
reminderSettings: reminderSettings === null ? Prisma.DbNull : reminderSettings,
|
reminderSettings: reminderSettings === null ? Prisma.DbNull : reminderSettings,
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const ZUpdateTeamSettingsRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: z.boolean().nullish(),
|
typedSignatureEnabled: z.boolean().nullish(),
|
||||||
uploadSignatureEnabled: z.boolean().nullish(),
|
uploadSignatureEnabled: z.boolean().nullish(),
|
||||||
drawSignatureEnabled: z.boolean().nullish(),
|
drawSignatureEnabled: z.boolean().nullish(),
|
||||||
|
qrSignatureEnabled: z.boolean().nullish(),
|
||||||
delegateDocumentOwnership: z.boolean().nullish(),
|
delegateDocumentOwnership: z.boolean().nullish(),
|
||||||
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
|
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
|
||||||
reminderSettings: ZEnvelopeReminderSettings.nullish(),
|
reminderSettings: ZEnvelopeReminderSettings.nullish(),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
ZDocumentMetaDrawSignatureEnabledSchema,
|
ZDocumentMetaDrawSignatureEnabledSchema,
|
||||||
ZDocumentMetaLanguageSchema,
|
ZDocumentMetaLanguageSchema,
|
||||||
ZDocumentMetaMessageSchema,
|
ZDocumentMetaMessageSchema,
|
||||||
|
ZDocumentMetaQrSignatureEnabledSchema,
|
||||||
ZDocumentMetaRedirectUrlSchema,
|
ZDocumentMetaRedirectUrlSchema,
|
||||||
ZDocumentMetaSubjectSchema,
|
ZDocumentMetaSubjectSchema,
|
||||||
ZDocumentMetaTimezoneSchema,
|
ZDocumentMetaTimezoneSchema,
|
||||||
@@ -66,6 +67,7 @@ export const ZTemplateMetaUpsertSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
signingOrder: z.nativeEnum(DocumentSigningOrder).optional(),
|
||||||
allowDictateNextSigner: z.boolean().optional(),
|
allowDictateNextSigner: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
@@ -147,6 +149,7 @@ export const ZCreateDocumentFromTemplateRequestSchema = z.object({
|
|||||||
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
typedSignatureEnabled: ZDocumentMetaTypedSignatureEnabledSchema.optional(),
|
||||||
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
uploadSignatureEnabled: ZDocumentMetaUploadSignatureEnabledSchema.optional(),
|
||||||
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
drawSignatureEnabled: ZDocumentMetaDrawSignatureEnabledSchema.optional(),
|
||||||
|
qrSignatureEnabled: ZDocumentMetaQrSignatureEnabledSchema.optional(),
|
||||||
allowDictateNextSigner: z.boolean().optional(),
|
allowDictateNextSigner: z.boolean().optional(),
|
||||||
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
|
envelopeExpirationPeriod: ZEnvelopeExpirationPeriod.nullish(),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"tailwind-merge": "^1.14.0",
|
"tailwind-merge": "^1.14.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"ts-pattern": "^5.9.0",
|
"ts-pattern": "^5.9.0",
|
||||||
|
"uqr": "^0.1.2",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ export type SignaturePadDialogProps = Omit<HTMLAttributes<HTMLCanvasElement>, 'o
|
|||||||
typedSignatureEnabled?: boolean;
|
typedSignatureEnabled?: boolean;
|
||||||
uploadSignatureEnabled?: boolean;
|
uploadSignatureEnabled?: boolean;
|
||||||
drawSignatureEnabled?: boolean;
|
drawSignatureEnabled?: boolean;
|
||||||
|
qrSignatureEnabled?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SignaturePadDialog = ({
|
export const SignaturePadDialog = ({
|
||||||
@@ -34,6 +35,7 @@ export const SignaturePadDialog = ({
|
|||||||
typedSignatureEnabled,
|
typedSignatureEnabled,
|
||||||
uploadSignatureEnabled,
|
uploadSignatureEnabled,
|
||||||
drawSignatureEnabled,
|
drawSignatureEnabled,
|
||||||
|
qrSignatureEnabled,
|
||||||
dialogConfirmText,
|
dialogConfirmText,
|
||||||
}: SignaturePadDialogProps) => {
|
}: SignaturePadDialogProps) => {
|
||||||
const { i18n } = useLingui();
|
const { i18n } = useLingui();
|
||||||
@@ -121,6 +123,7 @@ export const SignaturePadDialog = ({
|
|||||||
typedSignatureEnabled={typedSignatureEnabled}
|
typedSignatureEnabled={typedSignatureEnabled}
|
||||||
uploadSignatureEnabled={uploadSignatureEnabled}
|
uploadSignatureEnabled={uploadSignatureEnabled}
|
||||||
drawSignatureEnabled={drawSignatureEnabled}
|
drawSignatureEnabled={drawSignatureEnabled}
|
||||||
|
qrSignatureEnabled={qrSignatureEnabled}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
|
|||||||
Reference in New Issue
Block a user