diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ce8fc6d..c8a1ed65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `hideApprovalDenyButton` to `approvalStepNodeProps` +- `EXCEL_ADD_ROW` form workflow event to validation ## [12.3.1] - 2025-11-07 diff --git a/package-lock.json b/package-lock.json index 93b9f5c4..15b8eb03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2800,7 +2800,7 @@ }, "node_modules/@oneblink/types": { "version": "1.0.0", - "resolved": "git+ssh://git@github.com/oneblink/types.git#96f900d05b9b4f4a0555ce5da695f333c408e0e6", + "resolved": "git+ssh://git@github.com/oneblink/types.git#88ab16ae5e889c100971e9cae519731e0b7a97aa", "dev": true, "license": "GPL-3.0-only", "dependencies": { diff --git a/src/lib/forms-schema/index.ts b/src/lib/forms-schema/index.ts index df033218..857dd7fd 100644 --- a/src/lib/forms-schema/index.ts +++ b/src/lib/forms-schema/index.ts @@ -299,8 +299,38 @@ export const formWorkflowEventTypes: SubmissionEventTypes.FormWorkflowEventType[ 'SHAREPOINT_STORE_FILES', 'CIVIC_REC_COMPLETE_CHECKOUT', 'GOOD_TO_GO_UPDATE_ASSET', + 'EXCEL_ADD_ROW', ] +const entraApplicationKeys = { + integrationEntraApplicationId: Joi.string().required(), +} + +const entraApplicationEntitySchema = Joi.object().keys({ + id: Joi.string().required(), + displayName: Joi.string().required(), +}) + +const entraApplicationFolderPathSchema = Joi.string() + .custom((value, helpers) => { + if (typeof value === 'string') { + if (!value.startsWith('/')) { + return helpers.error('string.startsWithSlash') + } + if (value.endsWith('/')) { + return helpers.error('string.endsWithSlash') + } + } + + return value + }) + .messages({ + 'string.startsWithSlash': + '{{#label}} must start with a forward slash ("/")', + 'string.endsWithSlash': + '{{#label}} must not end with a forward slash ("/")', + }) + export const WorkflowEventSchema = Joi.object().keys({ type: Joi.string() .required() @@ -469,19 +499,9 @@ export const WorkflowEventSchema = Joi.object().keys({ .when('type', { is: 'SHAREPOINT_CREATE_LIST_ITEM', then: Joi.object().keys({ - integrationEntraApplicationId: Joi.string().required(), - sharepointSite: Joi.object() - .keys({ - id: Joi.string().required(), - displayName: Joi.string().required(), - }) - .required(), - sharepointList: Joi.object() - .keys({ - id: Joi.string().required(), - displayName: Joi.string().required(), - }) - .required(), + ...entraApplicationKeys, + sharepointSite: entraApplicationEntitySchema.required(), + sharepointList: entraApplicationEntitySchema.required(), mapping: Joi.array() .items( Joi.object({ @@ -498,42 +518,37 @@ export const WorkflowEventSchema = Joi.object().keys({ .when('type', { is: 'SHAREPOINT_STORE_FILES', then: Joi.object().keys({ - integrationEntraApplicationId: Joi.string().required(), - sharepointSite: Joi.object() - .keys({ - id: Joi.string().required(), - displayName: Joi.string().required(), - }) - .required(), - sharepointDrive: Joi.object() - .keys({ - id: Joi.string().required(), - displayName: Joi.string().required(), - }) - .required(), - folderPath: Joi.string() - .custom((value, helpers) => { - if (typeof value === 'string') { - if (!value.startsWith('/')) { - return helpers.error('string.startsWithSlash') - } - if (value.endsWith('/')) { - return helpers.error('string.endsWithSlash') - } - } - - return value - }) - .messages({ - 'string.startsWithSlash': - '{{#label}} must start with a forward slash ("/")', - 'string.endsWithSlash': - '{{#label}} must not end with a forward slash ("/")', - }), + ...entraApplicationKeys, + sharepointSite: entraApplicationEntitySchema.required(), + sharepointDrive: entraApplicationEntitySchema.required(), + folderPath: entraApplicationFolderPathSchema, excludeAttachments: Joi.boolean().default(false), ...pdfSubmissionEventConfiguration, }), }) + .when('type', { + is: 'EXCEL_ADD_ROW', + then: Joi.object().keys({ + ...entraApplicationKeys, + site: entraApplicationFolderPathSchema.required(), + drive: entraApplicationFolderPathSchema.required(), + folderPath: entraApplicationFolderPathSchema.required(), + excelFile: entraApplicationEntitySchema.required(), + table: entraApplicationEntitySchema.required(), + mapping: Joi.array() + .items( + Joi.object({ + columnName: Joi.string().required(), + ...generateFormWorkflowEventElementMappingKeys( + 'ExcelAddRowMapping', + [], + ), + }).id('ExcelAddRowMapping'), + ) + .min(1) + .required(), + }), + }) .when('type', { is: 'CIVIC_REC_COMPLETE_CHECKOUT', then: Joi.object().keys({ diff --git a/tests/forms-schema/forms-schema-form-events.test.ts b/tests/forms-schema/forms-schema-form-events.test.ts index 264c5a67..c17bcdad 100644 --- a/tests/forms-schema/forms-schema-form-events.test.ts +++ b/tests/forms-schema/forms-schema-form-events.test.ts @@ -64,7 +64,7 @@ describe('Scheduling events should throw errors when not passed to "schedulingEv submissionEvents: [schedulingEvent], }), ).toThrow( - '"submissionEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET]', + '"submissionEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET, EXCEL_ADD_ROW]', ) }) test('SCHEDULING form event should error when being passed to "paymentEvents"', () => { @@ -116,7 +116,7 @@ describe('Payment events should throw errors when not passed to "paymentEvents" submissionEvents: [paymentEvent], }), ).toThrow( - '"submissionEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET]', + '"submissionEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET, EXCEL_ADD_ROW]', ) }) test('Payment form event should error when being passed to "schedulingEvents"', () => { @@ -343,7 +343,7 @@ describe('"draftEvents" and "approvalEvents" should allow only submission events draftEvents: [paymentEvent], }), ).toThrow( - '"draftEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET]', + '"draftEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET, EXCEL_ADD_ROW]', ) }) test('SCHEDULING form event should error when being passed to "draftEvents"', () => { @@ -353,7 +353,7 @@ describe('"draftEvents" and "approvalEvents" should allow only submission events draftEvents: [schedulingEvent], }), ).toThrow( - '"draftEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET]', + '"draftEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET, EXCEL_ADD_ROW]', ) }) test('Should not error when passing submissionEvents to "draftEvents"', () => { @@ -372,7 +372,7 @@ describe('"draftEvents" and "approvalEvents" should allow only submission events approvalEvents: [paymentEvent], }), ).toThrow( - '"approvalEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET]', + '"approvalEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET, EXCEL_ADD_ROW]', ) }) test('SCHEDULING form event should error when being passed to "approvalEvents"', () => { @@ -382,7 +382,7 @@ describe('"draftEvents" and "approvalEvents" should allow only submission events approvalEvents: [schedulingEvent], }), ).toThrow( - '"approvalEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET]', + '"approvalEvents[0].type" must be one of [CALLBACK, POWER_AUTOMATE_FLOW, CP_INTEGRATION_HUB_WEBHOOK, PDF, EMAIL, ONEBLINK_API, TRIM, CP_HCMS, CIVICA_CRM, FRESHDESK_CREATE_TICKET, FRESHDESK_ADD_NOTE_TO_TICKET, SHAREPOINT_CREATE_LIST_ITEM, SHAREPOINT_STORE_FILES, CIVIC_REC_COMPLETE_CHECKOUT, GOOD_TO_GO_UPDATE_ASSET, EXCEL_ADD_ROW]', ) }) test('Should not error when passing submissionEvents to "approvalEvents"', () => {