mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 08:13:56 +10:00
This change allows API users to pre-fill fields with values by
passing the data in the request body. Example body for V2 API endpoint
`/api/v2-beta/template/use`:
```json
{
"templateId": 1,
"recipients": [
{
"id": 1,
"email": "signer1@mail.com",
"name": "Signer 1"
},
{
"id": 2,
"email": "signer2@mail.com",
"name": "Signer 2"
}
],
"prefillValues": [
{
"id": 14,
"fieldMeta": {
"type": "text",
"label": "my label",
"placeholder": "text placeholder test",
"text": "auto-sign value",
"characterLimit": 25,
"textAlign": "right",
"fontSize": 94,
"required": true
}
},
{
"id": 15,
"fieldMeta": {
"type": "radio",
"label": "radio label",
"placeholder": "new radio placeholder",
"required": false,
"readOnly": true,
"values": [
{
"id": 2,
"checked": true,
"value": "radio val 1"
},
{
"id": 3,
"checked": false,
"value": "radio val 2"
}
]
}
},
{
"id": 16,
"fieldMeta": {
"type": "dropdown",
"label": "dropdown label",
"placeholder": "DD placeholder",
"required": false,
"readOnly": false,
"values": [
{
"value": "option 1"
},
{
"value": "option 2"
},
{
"value": "option 3"
}
],
"defaultValue": "option 2"
}
}
],
"distributeDocument": false,
"customDocumentDataId": ""
}
```
175 lines
5.1 KiB
TypeScript
175 lines
5.1 KiB
TypeScript
import { msg } from '@lingui/core/macro';
|
|
import { useLingui } from '@lingui/react';
|
|
import { Trans } from '@lingui/react/macro';
|
|
|
|
import { validateTextField } from '@documenso/lib/advanced-fields-validation/validate-text';
|
|
import { type TTextFieldMeta as TextFieldMeta } from '@documenso/lib/types/field-meta';
|
|
import { Input } from '@documenso/ui/primitives/input';
|
|
import { Label } from '@documenso/ui/primitives/label';
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from '@documenso/ui/primitives/select';
|
|
import { Switch } from '@documenso/ui/primitives/switch';
|
|
import { Textarea } from '@documenso/ui/primitives/textarea';
|
|
|
|
type TextFieldAdvancedSettingsProps = {
|
|
fieldState: TextFieldMeta;
|
|
handleFieldChange: (key: keyof TextFieldMeta, value: string | boolean) => void;
|
|
handleErrors: (errors: string[]) => void;
|
|
};
|
|
|
|
export const TextFieldAdvancedSettings = ({
|
|
fieldState,
|
|
handleFieldChange,
|
|
handleErrors,
|
|
}: TextFieldAdvancedSettingsProps) => {
|
|
const { _ } = useLingui();
|
|
|
|
const handleInput = (field: keyof TextFieldMeta, value: string | boolean) => {
|
|
const text = field === 'text' ? String(value) : (fieldState.text ?? '');
|
|
const limit =
|
|
field === 'characterLimit' ? Number(value) : Number(fieldState.characterLimit ?? 0);
|
|
const fontSize = field === 'fontSize' ? Number(value) : Number(fieldState.fontSize ?? 14);
|
|
const readOnly = field === 'readOnly' ? Boolean(value) : Boolean(fieldState.readOnly);
|
|
const required = field === 'required' ? Boolean(value) : Boolean(fieldState.required);
|
|
|
|
const textErrors = validateTextField(text, {
|
|
characterLimit: Number(limit),
|
|
readOnly,
|
|
required,
|
|
fontSize,
|
|
type: 'text',
|
|
});
|
|
|
|
handleErrors(textErrors);
|
|
handleFieldChange(field, value);
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col gap-4">
|
|
<div>
|
|
<Label>
|
|
<Trans>Label</Trans>
|
|
</Label>
|
|
<Input
|
|
id="label"
|
|
className="bg-background mt-2"
|
|
placeholder={_(msg`Field label`)}
|
|
value={fieldState.label}
|
|
onChange={(e) => handleFieldChange('label', e.target.value)}
|
|
/>
|
|
</div>
|
|
<div>
|
|
<Label className="mt-4">
|
|
<Trans>Placeholder</Trans>
|
|
</Label>
|
|
<Input
|
|
id="placeholder"
|
|
className="bg-background mt-2"
|
|
placeholder={_(msg`Field placeholder`)}
|
|
value={fieldState.placeholder}
|
|
onChange={(e) => handleFieldChange('placeholder', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label className="mt-4">
|
|
<Trans>Add text</Trans>
|
|
</Label>
|
|
<Textarea
|
|
id="text"
|
|
className="bg-background mt-2"
|
|
placeholder={_(msg`Add text to the field`)}
|
|
value={fieldState.text}
|
|
onChange={(e) => handleInput('text', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label>
|
|
<Trans>Character Limit</Trans>
|
|
</Label>
|
|
<Input
|
|
id="characterLimit"
|
|
type="number"
|
|
min={0}
|
|
className="bg-background mt-2"
|
|
placeholder={_(msg`Field character limit`)}
|
|
value={fieldState.characterLimit}
|
|
onChange={(e) => handleInput('characterLimit', e.target.value)}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label>
|
|
<Trans>Font Size</Trans>
|
|
</Label>
|
|
<Input
|
|
id="fontSize"
|
|
type="number"
|
|
className="bg-background mt-2"
|
|
placeholder={_(msg`Field font size`)}
|
|
value={fieldState.fontSize}
|
|
onChange={(e) => handleInput('fontSize', e.target.value)}
|
|
min={8}
|
|
max={96}
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label>
|
|
<Trans>Text Align</Trans>
|
|
</Label>
|
|
|
|
<Select
|
|
value={fieldState.textAlign}
|
|
onValueChange={(value) => {
|
|
if (!value) {
|
|
return;
|
|
}
|
|
|
|
handleInput('textAlign', value);
|
|
}}
|
|
>
|
|
<SelectTrigger className="bg-background mt-2">
|
|
<SelectValue placeholder="Select text align" />
|
|
</SelectTrigger>
|
|
|
|
<SelectContent>
|
|
<SelectItem value="left">Left</SelectItem>
|
|
<SelectItem value="center">Center</SelectItem>
|
|
<SelectItem value="right">Right</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div className="mt-4 flex flex-col gap-4">
|
|
<div className="flex flex-row items-center gap-2">
|
|
<Switch
|
|
className="bg-background"
|
|
checked={fieldState.required}
|
|
onCheckedChange={(checked) => handleInput('required', checked)}
|
|
/>
|
|
<Label>
|
|
<Trans>Required field</Trans>
|
|
</Label>
|
|
</div>
|
|
<div className="flex flex-row items-center gap-2">
|
|
<Switch
|
|
className="bg-background"
|
|
checked={fieldState.readOnly}
|
|
onCheckedChange={(checked) => handleInput('readOnly', checked)}
|
|
/>
|
|
<Label>
|
|
<Trans>Read only</Trans>
|
|
</Label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|