Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

105 changes: 60 additions & 45 deletions src/lib/forms-schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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({
Expand All @@ -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({
Expand Down
12 changes: 6 additions & 6 deletions tests/forms-schema/forms-schema-form-events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"', () => {
Expand Down Expand Up @@ -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"', () => {
Expand Down Expand Up @@ -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"', () => {
Expand All @@ -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"', () => {
Expand All @@ -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"', () => {
Expand All @@ -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"', () => {
Expand Down