Refactored signature from previous array implementation to the new single approach. Added support for automations
This commit is contained in:
parent
f696299ceb
commit
0589a6a730
|
@ -66,8 +66,7 @@
|
|||
let urlFailed
|
||||
|
||||
$: if (value) {
|
||||
const [attachment] = value || []
|
||||
signatureFile = attachment
|
||||
signatureFile = value
|
||||
}
|
||||
|
||||
$: if (signatureFile?.url) {
|
||||
|
|
|
@ -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"}
|
||||
<div class="attachment-field-wrapper">
|
||||
<div class="label-wrapper">
|
||||
<Label>{label}</Label>
|
||||
|
|
|
@ -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}
|
||||
<div
|
||||
class:schema-fields={schema.type !== FieldType.ATTACHMENTS &&
|
||||
schema.type !== FieldType.ATTACHMENT_SINGLE}
|
||||
>
|
||||
<div class:schema-fields={!attachmentTypes.includes(schema.type)}>
|
||||
<Label>{field}</Label>
|
||||
<div
|
||||
class:field-width={schema.type !== FieldType.ATTACHMENTS &&
|
||||
schema.type !== FieldType.ATTACHMENT_SINGLE}
|
||||
>
|
||||
<div class:field-width={!attachmentTypes.includes(schema.type)}>
|
||||
{#if isTestModal}
|
||||
<RowSelectorTypes
|
||||
{isTestModal}
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
let params = {}
|
||||
|
||||
if (
|
||||
schema.type === FieldType.ATTACHMENT_SINGLE &&
|
||||
(schema.type === FieldType.ATTACHMENT_SINGLE ||
|
||||
schema.type === FieldType.SIGNATURE) &&
|
||||
Object.keys(keyValuObj).length === 0
|
||||
) {
|
||||
return []
|
||||
|
@ -100,16 +101,20 @@
|
|||
on:change={e => 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}
|
||||
<div class="attachment-field-spacinng">
|
||||
<KeyValueBuilder
|
||||
on:change={e =>
|
||||
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}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -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"}
|
||||
<div class="signature">
|
||||
<Label>{label}</Label>
|
||||
<div class="sig-wrap" class:display={value?.length}>
|
||||
{#if value?.length}
|
||||
<div class="sig-wrap" class:display={value}>
|
||||
{#if value}
|
||||
<CoreSignature
|
||||
{darkMode}
|
||||
{value}
|
||||
editable={false}
|
||||
on:clear={() => {
|
||||
value = []
|
||||
value = null
|
||||
}}
|
||||
/>
|
||||
{:else}
|
||||
|
|
|
@ -54,6 +54,10 @@
|
|||
label: "Attachment",
|
||||
value: FieldType.ATTACHMENT_SINGLE,
|
||||
},
|
||||
{
|
||||
label: "Signature",
|
||||
value: FieldType.SIGNATURE,
|
||||
},
|
||||
{
|
||||
label: "Attachment list",
|
||||
value: FieldType.ATTACHMENTS,
|
||||
|
|
|
@ -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)}
|
||||
<div
|
||||
class={`icon ${getIconClass(value, type)}`}
|
||||
on:click={() => {
|
||||
|
|
|
@ -132,7 +132,6 @@ export const FIELDS = {
|
|||
type: FieldType.SIGNATURE,
|
||||
icon: "AnnotatePen",
|
||||
constraints: {
|
||||
type: "array",
|
||||
presence: false,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
<!-- svelte-ignore a11y-missing-attribute -->
|
||||
<img src={signature?.url} />
|
||||
<img src={value?.url} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
|
@ -94,8 +89,8 @@
|
|||
/>
|
||||
|
||||
{#if isOpen}
|
||||
<div class="signature" class:invertX class:invertY class:empty={!signature}>
|
||||
{#if signature?.key}
|
||||
<div class="signature" class:invertX class:invertY class:empty={!value}>
|
||||
{#if value?.key}
|
||||
<div class="signature-wrap">
|
||||
<CoreSignature
|
||||
darkMode={$props.darkMode}
|
||||
|
|
|
@ -312,7 +312,7 @@ describe.each([
|
|||
const signature: FieldSchema = {
|
||||
type: FieldType.SIGNATURE,
|
||||
name: "signature",
|
||||
constraints: { type: "array", presence: false },
|
||||
constraints: { presence: false },
|
||||
}
|
||||
const bool: FieldSchema = {
|
||||
type: FieldType.BOOLEAN,
|
||||
|
@ -382,8 +382,6 @@ describe.each([
|
|||
attachmentListEmptyArrayStr: attachmentList,
|
||||
signatureNull: signature,
|
||||
signatureUndefined: signature,
|
||||
signatureEmpty: signature,
|
||||
signatureEmptyArrayStr: signature,
|
||||
arrayFieldEmptyArrayStr: arrayField,
|
||||
arrayFieldArrayStrKnown: arrayField,
|
||||
arrayFieldNull: arrayField,
|
||||
|
@ -427,8 +425,6 @@ describe.each([
|
|||
attachmentListEmptyArrayStr: "[]",
|
||||
signatureNull: null,
|
||||
signatureUndefined: undefined,
|
||||
signatureEmpty: "",
|
||||
signatureEmptyArrayStr: "[]",
|
||||
arrayFieldEmptyArrayStr: "[]",
|
||||
arrayFieldUndefined: undefined,
|
||||
arrayFieldNull: null,
|
||||
|
@ -463,10 +459,8 @@ describe.each([
|
|||
expect(row.attachmentListUndefined).toBe(undefined)
|
||||
expect(row.attachmentListEmpty).toEqual([])
|
||||
expect(row.attachmentListEmptyArrayStr).toEqual([])
|
||||
expect(row.signatureNull).toEqual([])
|
||||
expect(row.signatureNull).toEqual(null)
|
||||
expect(row.signatureUndefined).toBe(undefined)
|
||||
expect(row.signatureEmpty).toEqual([])
|
||||
expect(row.signatureEmptyArrayStr).toEqual([])
|
||||
expect(row.arrayFieldEmptyArrayStr).toEqual([])
|
||||
expect(row.arrayFieldNull).toEqual([])
|
||||
expect(row.arrayFieldUndefined).toEqual(undefined)
|
||||
|
@ -990,11 +984,11 @@ describe.each([
|
|||
signature: {
|
||||
type: FieldType.SIGNATURE,
|
||||
name: "signature",
|
||||
constraints: { type: "array", presence: false },
|
||||
constraints: { presence: false },
|
||||
},
|
||||
},
|
||||
"signature",
|
||||
[`${uuid.v4()}.png`]
|
||||
`${uuid.v4()}.png`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -113,7 +113,8 @@ export async function sendAutomationAttachmentsToStorage(
|
|||
const schema = table.schema[prop]
|
||||
if (
|
||||
schema?.type === FieldType.ATTACHMENTS ||
|
||||
schema?.type === FieldType.ATTACHMENT_SINGLE
|
||||
schema?.type === FieldType.ATTACHMENT_SINGLE ||
|
||||
schema?.type === FieldType.SIGNATURE
|
||||
) {
|
||||
attachmentRows[prop] = value
|
||||
}
|
||||
|
|
|
@ -61,15 +61,15 @@ export async function updateAttachmentColumns(prodAppId: string, db: Database) {
|
|||
for (let column of columns) {
|
||||
const columnType = table.schema[column].type
|
||||
if (
|
||||
(columnType === FieldType.ATTACHMENTS ||
|
||||
columnType === FieldType.SIGNATURE) &&
|
||||
columnType === FieldType.ATTACHMENTS &&
|
||||
Array.isArray(row[column])
|
||||
) {
|
||||
row[column] = row[column].map((attachment: RowAttachment) =>
|
||||
rewriteAttachmentUrl(prodAppId, attachment)
|
||||
)
|
||||
} else if (
|
||||
columnType === FieldType.ATTACHMENT_SINGLE &&
|
||||
(columnType === FieldType.ATTACHMENT_SINGLE ||
|
||||
columnType === FieldType.SIGNATURE) &&
|
||||
row[column]
|
||||
) {
|
||||
row[column] = rewriteAttachmentUrl(prodAppId, row[column])
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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`)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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<T extends Row[] | Row>(
|
|||
|
||||
// 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<T extends Row[] | Row>(
|
|||
}
|
||||
})
|
||||
}
|
||||
} 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue