feat: add qr signatures

This commit is contained in:
David Nguyen
2026-08-18 11:49:15 +10:00
parent 779de01fe8
commit 9825ea88b1
99 changed files with 1686 additions and 48 deletions
@@ -156,6 +156,10 @@ export const AdminGlobalSettingsSection = ({
</DetailsValue>
</DetailsCard>
<DetailsCard label={<Trans>QR signature</Trans>}>
<DetailsValue>{booleanValue(settings.qrSignatureEnabled, inheritedSettings?.qrSignatureEnabled)}</DetailsValue>
</DetailsCard>
<DetailsCard label={<Trans>Branding</Trans>}>
<DetailsValue>{booleanValue(settings.brandingEnabled, inheritedSettings?.brandingEnabled)}</DetailsValue>
</DetailsCard>
@@ -269,6 +269,7 @@ export const DirectTemplateSigningForm = ({
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
qrSignatureEnabled={template.templateMeta?.qrSignatureEnabled}
/>
))
.with(FieldType.INITIALS, () => (
@@ -408,6 +409,7 @@ export const DirectTemplateSigningForm = ({
typedSignatureEnabled={template.templateMeta?.typedSignatureEnabled}
uploadSignatureEnabled={template.templateMeta?.uploadSignatureEnabled}
drawSignatureEnabled={template.templateMeta?.drawSignatureEnabled}
qrSignatureEnabled={template.templateMeta?.qrSignatureEnabled}
/>
</div>
</div>
@@ -254,6 +254,8 @@ export const DocumentSigningForm = ({
typedSignatureEnabled={document.documentMeta?.typedSignatureEnabled}
uploadSignatureEnabled={document.documentMeta?.uploadSignatureEnabled}
drawSignatureEnabled={document.documentMeta?.drawSignatureEnabled}
qrSignatureEnabled={document.documentMeta?.qrSignatureEnabled}
qrSignatureContext={{ type: 'DOCUMENT_SIGNATURE', recipientToken: recipient.token }}
/>
</div>
)}
@@ -408,6 +408,7 @@ export const DocumentSigningPageViewV1 = ({
typedSignatureEnabled={documentMeta?.typedSignatureEnabled}
uploadSignatureEnabled={documentMeta?.uploadSignatureEnabled}
drawSignatureEnabled={documentMeta?.drawSignatureEnabled}
qrSignatureEnabled={documentMeta?.qrSignatureEnabled}
/>
))
.with(FieldType.INITIALS, () => <DocumentSigningInitialsField key={field.id} field={field} />)
@@ -33,6 +33,7 @@ export interface DocumentSigningProviderProps {
typedSignatureEnabled?: boolean;
uploadSignatureEnabled?: boolean;
drawSignatureEnabled?: boolean;
qrSignatureEnabled?: boolean;
children: React.ReactNode;
}
@@ -43,6 +44,7 @@ export const DocumentSigningProvider = ({
typedSignatureEnabled = true,
uploadSignatureEnabled = true,
drawSignatureEnabled = true,
qrSignatureEnabled = true,
children,
}: DocumentSigningProviderProps) => {
const [fullName, setFullName] = useState(initialFullName || '');
@@ -54,7 +56,7 @@ export const DocumentSigningProvider = ({
const sig = initialSignature || '';
const isBase64 = isBase64Image(sig);
if (isBase64 && (uploadSignatureEnabled || drawSignatureEnabled)) {
if (isBase64 && (uploadSignatureEnabled || drawSignatureEnabled || qrSignatureEnabled)) {
return sig;
}
@@ -34,6 +34,7 @@ export type DocumentSigningSignatureFieldProps = {
typedSignatureEnabled?: boolean;
uploadSignatureEnabled?: boolean;
drawSignatureEnabled?: boolean;
qrSignatureEnabled?: boolean;
};
export const DocumentSigningSignatureField = ({
@@ -43,6 +44,7 @@ export const DocumentSigningSignatureField = ({
typedSignatureEnabled,
uploadSignatureEnabled,
drawSignatureEnabled,
qrSignatureEnabled,
}: DocumentSigningSignatureFieldProps) => {
const { _ } = useLingui();
const { toast } = useToast();
@@ -279,6 +281,8 @@ export const DocumentSigningSignatureField = ({
typedSignatureEnabled={typedSignatureEnabled}
uploadSignatureEnabled={uploadSignatureEnabled}
drawSignatureEnabled={drawSignatureEnabled}
qrSignatureEnabled={qrSignatureEnabled}
qrSignatureContext={{ type: 'DOCUMENT_SIGNATURE', recipientToken: recipient.token }}
/>
<DocumentSigningDisclosure />
@@ -172,7 +172,9 @@ export const EnvelopeSigningProvider = ({
if (
!sig &&
(envelope.documentMeta.uploadSignatureEnabled || envelope.documentMeta.drawSignatureEnabled) &&
(envelope.documentMeta.uploadSignatureEnabled ||
envelope.documentMeta.drawSignatureEnabled ||
envelope.documentMeta.qrSignatureEnabled) &&
envelopeData.recipientSignature?.signatureImageAsBase64
) {
return envelopeData.recipientSignature.signatureImageAsBase64;
@@ -182,7 +184,12 @@ export const EnvelopeSigningProvider = ({
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;
}
@@ -174,6 +174,7 @@ export const DocumentEditForm = ({ className, initialDocument, documentRootPath
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
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),
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
envelopeExpirationPeriod,
reminderSettings,
},
@@ -121,6 +121,8 @@ export default function EnvelopeSignerForm() {
typedSignatureEnabled={envelope.documentMeta.typedSignatureEnabled}
uploadSignatureEnabled={envelope.documentMeta.uploadSignatureEnabled}
drawSignatureEnabled={envelope.documentMeta.drawSignatureEnabled}
qrSignatureEnabled={envelope.documentMeta.qrSignatureEnabled}
qrSignatureContext={{ type: 'DOCUMENT_SIGNATURE', recipientToken: recipient.token }}
/>
</div>
)}
@@ -384,6 +384,8 @@ export const EnvelopeSignerPageRenderer = ({ pageData }: { pageData: PageRenderD
typedSignatureEnabled: envelope.documentMeta.typedSignatureEnabled,
uploadSignatureEnabled: envelope.documentMeta.uploadSignatureEnabled,
drawSignatureEnabled: envelope.documentMeta.drawSignatureEnabled,
qrSignatureEnabled: envelope.documentMeta.qrSignatureEnabled,
recipientToken: envelopeData.recipient.token,
})
.then(async (payload) => {
if (!payload) {
@@ -137,6 +137,7 @@ export const TemplateEditForm = ({ initialTemplate, className, templateRootPath
typedSignatureEnabled: signatureTypes.includes(DocumentSignatureType.TYPE),
uploadSignatureEnabled: signatureTypes.includes(DocumentSignatureType.UPLOAD),
drawSignatureEnabled: signatureTypes.includes(DocumentSignatureType.DRAW),
qrSignatureEnabled: signatureTypes.includes(DocumentSignatureType.QR),
language: isValidLanguageCode(data.meta.language) ? data.meta.language : undefined,
},
});