diff --git a/packages/bbui/src/Form/Core/Signature.svelte b/packages/bbui/src/Form/Core/Signature.svelte index b59436016f..3fb411534e 100644 --- a/packages/bbui/src/Form/Core/Signature.svelte +++ b/packages/bbui/src/Form/Core/Signature.svelte @@ -66,8 +66,7 @@ let urlFailed $: if (value) { - const [attachment] = value || [] - signatureFile = attachment + signatureFile = value } $: if (signatureFile?.url) { diff --git a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte index 0cf0f6c740..3bcbed5dcf 100644 --- a/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte +++ b/packages/builder/src/components/automation/SetupPanel/AutomationBlockSetup.svelte @@ -358,6 +358,7 @@ value.customType !== "cron" && value.customType !== "triggerSchema" && value.customType !== "automationFields" && + value.type !== "signature" && value.type !== "attachment" && value.type !== "attachment_single" ) @@ -449,7 +450,7 @@ value={inputData[key]} options={Object.keys(table?.schema || {})} /> - {:else if value.type === "attachment"} + {:else if value.type === "attachment" || value.type === "signature"}
diff --git a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte index ab020aad08..fd7f5de459 100644 --- a/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte +++ b/packages/builder/src/components/automation/SetupPanel/RowSelector.svelte @@ -24,6 +24,11 @@ let table let schemaFields + let attachmentTypes = [ + FieldType.ATTACHMENTS, + FieldType.ATTACHMENT_SINGLE, + FieldType.SIGNATURE, + ] $: { table = $tables.list.find(table => table._id === value?.tableId) @@ -120,15 +125,9 @@ {#if schemaFields.length} {#each schemaFields as [field, schema]} {#if !schema.autocolumn} -
+
-
+
{#if isTestModal} onChange(e, field)} useLabel={false} /> -{:else if schema.type === FieldType.ATTACHMENTS || schema.type === FieldType.ATTACHMENT_SINGLE} +{:else if schema.type === FieldType.ATTACHMENTS || schema.type === FieldType.ATTACHMENT_SINGLE || schema.type === FieldType.SIGNATURE}
onChange( { detail: - schema.type === FieldType.ATTACHMENT_SINGLE + schema.type === FieldType.ATTACHMENT_SINGLE || + schema.type === FieldType.SIGNATURE ? e.detail.length > 0 - ? { url: e.detail[0].name, filename: e.detail[0].value } + ? { + url: e.detail[0].name, + filename: e.detail[0].value, + } : {} : e.detail.map(({ name, value }) => ({ url: name, @@ -125,7 +130,8 @@ customButtonText={"Add attachment"} keyPlaceholder={"URL"} valuePlaceholder={"Filename"} - actionButtonDisabled={schema.type === FieldType.ATTACHMENT_SINGLE && + actionButtonDisabled={(schema.type === FieldType.ATTACHMENT_SINGLE || + schema.type === FieldType.SIGNATURE) && Object.keys(value[field]).length >= 1} />
diff --git a/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte b/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte index c3bae3e079..7ba2fc5bcd 100644 --- a/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte +++ b/packages/builder/src/components/backend/DataTable/RowFieldControl.svelte @@ -62,7 +62,8 @@ try { const uploadReq = await API.uploadBuilderAttachment(attachRequest) - value = uploadReq + const [signatureAttachment] = uploadReq + value = signatureAttachment } catch (error) { $notifications.error(error.message || "Failed to save signature") value = [] @@ -114,14 +115,14 @@ {:else if type === "signature"}
-
- {#if value?.length} +
+ {#if value} { - value = [] + value = null }} /> {:else} diff --git a/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte b/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte index b7fa243c07..b2ef25d7f3 100644 --- a/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte +++ b/packages/builder/src/components/backend/TableNavigator/ExistingTableDataImport.svelte @@ -54,6 +54,10 @@ label: "Attachment", value: FieldType.ATTACHMENT_SINGLE, }, + { + label: "Signature", + value: FieldType.SIGNATURE, + }, { label: "Attachment list", value: FieldType.ATTACHMENTS, diff --git a/packages/builder/src/components/common/bindings/DrawerBindableSlot.svelte b/packages/builder/src/components/common/bindings/DrawerBindableSlot.svelte index fb448cca8d..4a0664363c 100644 --- a/packages/builder/src/components/common/bindings/DrawerBindableSlot.svelte +++ b/packages/builder/src/components/common/bindings/DrawerBindableSlot.svelte @@ -28,6 +28,12 @@ let bindingDrawer let currentVal = value + let attachmentTypes = [ + FieldType.ATTACHMENT_SINGLE, + FieldType.ATTACHMENTS, + FieldType.SIGNATURE, + ] + $: readableValue = runtimeToReadableBinding(bindings, value) $: tempValue = readableValue $: isJS = isJSBinding(value) @@ -105,6 +111,7 @@ boolean: isValidBoolean, attachment: false, attachment_single: false, + signature: false, } const isValid = value => { @@ -126,6 +133,7 @@ "bigint", "barcodeqr", "attachment", + "signature", "attachment_single", ].includes(type) ) { @@ -169,7 +177,7 @@ {updateOnChange} /> {/if} - {#if !disabled && type !== "formula" && !disabled && type !== FieldType.ATTACHMENTS && !disabled && type !== FieldType.ATTACHMENT_SINGLE} + {#if !disabled && type !== "formula" && !disabled && !attachmentTypes.includes(type)}
{ diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 5283c2a101..b3a1cc6099 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -132,7 +132,6 @@ export const FIELDS = { type: FieldType.SIGNATURE, icon: "AnnotatePen", constraints: { - type: "array", presence: false, }, }, diff --git a/packages/client/src/components/app/forms/SignatureField.svelte b/packages/client/src/components/app/forms/SignatureField.svelte index 72d4ebe94f..39cda69cb8 100644 --- a/packages/client/src/components/app/forms/SignatureField.svelte +++ b/packages/client/src/components/app/forms/SignatureField.svelte @@ -35,10 +35,10 @@ data: attachRequest, tableId: formContext?.dataSource?.tableId, }) - - updateValue = resp + const [signatureAttachment] = resp + updateValue = signatureAttachment } else { - updateValue = [] + updateValue = null } const changed = fieldApi.setValue(updateValue) @@ -54,9 +54,9 @@ } const deleteSignature = async () => { - const changed = fieldApi.setValue([]) + const changed = fieldApi.setValue(null) if (onChange && changed) { - onChange({ value: [] }) + onChange({ value: null }) } } diff --git a/packages/client/src/components/app/forms/validation.js b/packages/client/src/components/app/forms/validation.js index 22f02c7544..57471e68d3 100644 --- a/packages/client/src/components/app/forms/validation.js +++ b/packages/client/src/components/app/forms/validation.js @@ -192,16 +192,16 @@ const parseType = (value, type) => { return value === true } - // Parse attachments/signatures, treating no elements as null - if (type === FieldTypes.ATTACHMENTS || type === FieldTypes.SIGNATURE) { + // Parse attachments, treating no elements as null + if (type === FieldTypes.ATTACHMENTS) { if (!Array.isArray(value) || !value.length) { return null } return value } - // Parse attachment single, treating no key as null - if (type === FieldTypes.ATTACHMENT_SINGLE) { + // Parse attachment/signature single, treating no key as null + if (type === FieldTypes.ATTACHMENT_SINGLE || type === FieldTypes.SIGNATURE) { if (!value?.key) { return null } diff --git a/packages/frontend-core/src/components/grid/cells/SignatureCell.svelte b/packages/frontend-core/src/components/grid/cells/SignatureCell.svelte index 9ef1765f2b..eb14c8bfc6 100644 --- a/packages/frontend-core/src/components/grid/cells/SignatureCell.svelte +++ b/packages/frontend-core/src/components/grid/cells/SignatureCell.svelte @@ -15,14 +15,8 @@ const { API, notifications, props } = getContext("grid") let isOpen = false - let signature let modal - $: if (value) { - const [attachment] = value - signature = attachment - } - $: editable = focused && !readonly $: { if (!focused) { @@ -43,7 +37,7 @@ } const deleteSignature = async () => { - onChange([]) + onChange(null) } const saveSignature = async sigCanvas => { @@ -54,7 +48,8 @@ try { const uploadReq = await API.uploadBuilderAttachment(attachRequest) - onChange(uploadReq) + const [signatureAttachment] = uploadReq + onChange(signatureAttachment) } catch (error) { $notifications.error(error.message || "Failed to save signature") return [] @@ -79,9 +74,9 @@ class:editable on:click={editable ? open : null} > - {#if signature?.url} + {#if value?.url} - + {/if}
@@ -94,8 +89,8 @@ /> {#if isOpen} -
- {#if signature?.key} +
+ {#if value?.key}
rewriteAttachmentUrl(prodAppId, attachment) ) } else if ( - columnType === FieldType.ATTACHMENT_SINGLE && + (columnType === FieldType.ATTACHMENT_SINGLE || + columnType === FieldType.SIGNATURE) && row[column] ) { row[column] = rewriteAttachmentUrl(prodAppId, row[column]) diff --git a/packages/server/src/sdk/app/rows/utils.ts b/packages/server/src/sdk/app/rows/utils.ts index dc9821aba3..a9df4f89cd 100644 --- a/packages/server/src/sdk/app/rows/utils.ts +++ b/packages/server/src/sdk/app/rows/utils.ts @@ -181,15 +181,13 @@ export async function validate({ errors[fieldName] = [`${fieldName} is required`] } } else if ( - (type === FieldType.ATTACHMENTS || - type === FieldType.JSON || - type === FieldType.SIGNATURE) && + (type === FieldType.ATTACHMENTS || type === FieldType.JSON) && typeof row[fieldName] === "string" ) { // this should only happen if there is an error try { const json = JSON.parse(row[fieldName]) - if (type === FieldType.ATTACHMENTS || type === FieldType.SIGNATURE) { + if (type === FieldType.ATTACHMENTS) { if (Array.isArray(json)) { row[fieldName] = json } else { diff --git a/packages/server/src/sdk/tests/attachments.spec.ts b/packages/server/src/sdk/tests/attachments.spec.ts index 823e1a575d..d8673b02e6 100644 --- a/packages/server/src/sdk/tests/attachments.spec.ts +++ b/packages/server/src/sdk/tests/attachments.spec.ts @@ -94,14 +94,14 @@ describe("should be able to re-write attachment URLs", () => { }, }, { - signature: [{ ...attachment }], + signature: { ...attachment }, otherCol: "string", } ) for (const row of rows) { expect(row.otherCol).toBe("string") - expect(row.signature[0].url).toBe("") - expect(row.signature[0].key).toBe(`${db.name}/attachments/a.png`) + expect(row.signature.url).toBe("") + expect(row.signature.key).toBe(`${db.name}/attachments/a.png`) } }) }) diff --git a/packages/server/src/utilities/rowProcessor/attachments.ts b/packages/server/src/utilities/rowProcessor/attachments.ts index 762ab6cb07..1d788e5a62 100644 --- a/packages/server/src/utilities/rowProcessor/attachments.ts +++ b/packages/server/src/utilities/rowProcessor/attachments.ts @@ -35,7 +35,7 @@ export class AttachmentCleanup { return [] } - if (type === FieldType.ATTACHMENTS || type === FieldType.SIGNATURE) { + if (type === FieldType.ATTACHMENTS) { return rowData.map((attachment: any) => attachment.key) } return [rowData.key] diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index ae5ae7992c..11f5e033e6 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -148,17 +148,17 @@ export async function inputProcessing( } // remove any attachment urls, they are generated on read - if ( - field.type === FieldType.ATTACHMENTS || - field.type === FieldType.SIGNATURE - ) { + if (field.type === FieldType.ATTACHMENTS) { const attachments = clonedRow[key] if (attachments?.length) { attachments.forEach((attachment: RowAttachment) => { delete attachment.url }) } - } else if (field.type === FieldType.ATTACHMENT_SINGLE) { + } else if ( + field.type === FieldType.ATTACHMENT_SINGLE || + field.type === FieldType.SIGNATURE + ) { const attachment = clonedRow[key] if (attachment?.url) { delete clonedRow[key].url @@ -224,10 +224,7 @@ export async function outputProcessing( // process complex types: attachements, bb references... for (let [property, column] of Object.entries(table.schema)) { - if ( - column.type === FieldType.ATTACHMENTS || - column.type === FieldType.SIGNATURE - ) { + if (column.type === FieldType.ATTACHMENTS) { for (let row of enriched) { if (row[property] == null || !Array.isArray(row[property])) { continue @@ -238,7 +235,10 @@ export async function outputProcessing( } }) } - } else if (column.type === FieldType.ATTACHMENT_SINGLE) { + } else if ( + column.type === FieldType.ATTACHMENT_SINGLE || + column.type === FieldType.SIGNATURE + ) { for (let row of enriched) { if (!row[property] || Object.keys(row[property]).length === 0) { continue diff --git a/packages/server/src/utilities/rowProcessor/map.ts b/packages/server/src/utilities/rowProcessor/map.ts index 956efc9a4f..2e0ac9efe1 100644 --- a/packages/server/src/utilities/rowProcessor/map.ts +++ b/packages/server/src/utilities/rowProcessor/map.ts @@ -113,14 +113,6 @@ export const TYPE_TRANSFORM_MAP: any = { [undefined]: undefined, parse: parseArrayString, }, - //Review this - [FieldType.SIGNATURE]: { - //@ts-ignore - [null]: [], - //@ts-ignore - [undefined]: undefined, - parse: parseArrayString, - }, [FieldType.BOOLEAN]: { "": null, //@ts-ignore diff --git a/packages/server/src/utilities/schema.ts b/packages/server/src/utilities/schema.ts index 40bde42a5d..2bdc5653af 100644 --- a/packages/server/src/utilities/schema.ts +++ b/packages/server/src/utilities/schema.ts @@ -149,7 +149,8 @@ export function parse(rows: Rows, schema: TableSchema): Rows { } } else if ( (columnType === FieldType.ATTACHMENTS || - columnType === FieldType.ATTACHMENT_SINGLE) && + columnType === FieldType.ATTACHMENT_SINGLE || + columnType === FieldType.SIGNATURE) && typeof columnData === "string" ) { parsedRow[columnName] = parseCsvExport(columnData)