Refactor workflow trigger conditions to filters

This commit is contained in:
shamoon
2025-10-08 08:42:21 -07:00
parent e715a78b63
commit f3e749511e
4 changed files with 317 additions and 354 deletions

View File

@@ -176,58 +176,58 @@
@if (formGroup.get('type').value === WorkflowTriggerType.DocumentAdded || formGroup.get('type').value === WorkflowTriggerType.DocumentUpdated || formGroup.get('type').value === WorkflowTriggerType.Scheduled) {
<div class="row mt-3">
<div class="col">
<div class="trigger-conditions mb-3">
<div class="trigger-filters mb-3">
<div class="d-flex align-items-center">
<label class="form-label mb-0" i18n>Conditions</label>
<label class="form-label mb-0" i18n>Advanced Filters</label>
<button
type="button"
class="btn btn-sm btn-outline-primary ms-auto"
(click)="addCondition(formGroup)"
[disabled]="!canAddCondition(formGroup)"
(click)="addFilter(formGroup)"
[disabled]="!canAddFilter(formGroup)"
>
<i-bs name="plus-circle"></i-bs>&nbsp;<span i18n>Add condition</span>
<i-bs name="plus-circle"></i-bs>&nbsp;<span i18n>Add filter</span>
</button>
</div>
<ul class="mt-2 list-group conditions" formArrayName="conditions">
@if (getConditionsFormArray(formGroup).length === 0) {
<p class="text-muted small" i18n>No conditions added. Add one to define document filters.</p>
<ul class="mt-2 list-group filters" formArrayName="filters">
@if (getFiltersFormArray(formGroup).length === 0) {
<p class="text-muted small" i18n>No advanced workflow filters defined.</p>
}
@for (condition of getConditionsFormArray(formGroup).controls; track condition; let conditionIndex = $index) {
<li [formGroupName]="conditionIndex" class="list-group-item">
@for (filter of getFiltersFormArray(formGroup).controls; track filter; let filterIndex = $index) {
<li [formGroupName]="filterIndex" class="list-group-item">
<div class="d-flex align-items-center gap-2">
<div class="w-25">
<pngx-input-select
i18n-title
[items]="getConditionTypeOptions(formGroup, conditionIndex)"
[items]="getFilterTypeOptions(formGroup, filterIndex)"
formControlName="type"
[allowNull]="false"
></pngx-input-select>
</div>
<div class="flex-grow-1">
@if (isTagsCondition(condition.get('type').value)) {
@if (isTagsFilter(filter.get('type').value)) {
<pngx-input-tags
[allowCreate]="false"
[title]="null"
formControlName="values"
></pngx-input-tags>
} @else if (
isCustomFieldQueryCondition(condition.get('type').value)
isCustomFieldQueryFilter(filter.get('type').value)
) {
<pngx-custom-fields-query-dropdown
[selectionModel]="getCustomFieldQueryModel(condition)"
(selectionModelChange)="onCustomFieldQuerySelectionChange(condition, $event)"
[selectionModel]="getCustomFieldQueryModel(filter)"
(selectionModelChange)="onCustomFieldQuerySelectionChange(filter, $event)"
[useDropdown]="false"
></pngx-custom-fields-query-dropdown>
@if (!isCustomFieldQueryValid(condition)) {
@if (!isCustomFieldQueryValid(filter)) {
<div class="text-danger small" i18n>
Complete the custom field query configuration.
</div>
}
} @else {
<pngx-input-select
[items]="getConditionSelectItems(condition.get('type').value)"
[items]="getFilterSelectItems(filter.get('type').value)"
[allowNull]="true"
[multiple]="isSelectMultiple(condition.get('type').value)"
[multiple]="isSelectMultiple(filter.get('type').value)"
formControlName="values"
></pngx-input-select>
}
@@ -235,7 +235,7 @@
<button
type="button"
class="btn btn-link text-danger p-0"
(click)="removeCondition(formGroup, conditionIndex)"
(click)="removeFilter(formGroup, filterIndex)"
>
<i-bs name="trash"></i-bs><span class="ms-1" i18n>Delete</span>
</button>

View File

@@ -8,6 +8,6 @@
font-size: 1rem;
}
:host ::ng-deep .conditions .paperless-input-select.mb-3 {
:host ::ng-deep .filters .paperless-input-select.mb-3 {
margin-bottom: 0 !important;
}

View File

@@ -50,7 +50,7 @@ import { EditDialogMode } from '../edit-dialog.component'
import {
DOCUMENT_SOURCE_OPTIONS,
SCHEDULE_DATE_FIELD_OPTIONS,
TriggerConditionType,
TriggerFilterType,
WORKFLOW_ACTION_OPTIONS,
WORKFLOW_TYPE_OPTIONS,
WorkflowEditDialogComponent,
@@ -395,62 +395,50 @@ describe('WorkflowEditDialogComponent', () => {
expect(component.matchingPatternRequired(triggerGroup)).toBe(false)
})
it('should map condition builder values into trigger filters on save', () => {
it('should map filter builder values into trigger filters on save', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0)
component.addCondition(triggerGroup as FormGroup)
component.addCondition(triggerGroup as FormGroup)
component.addCondition(triggerGroup as FormGroup)
component.addFilter(triggerGroup as FormGroup)
component.addFilter(triggerGroup as FormGroup)
component.addFilter(triggerGroup as FormGroup)
const conditions = component.getConditionsFormArray(
triggerGroup as FormGroup
)
expect(conditions.length).toBe(3)
const filters = component.getFiltersFormArray(triggerGroup as FormGroup)
expect(filters.length).toBe(3)
conditions.at(0).get('values').setValue([1])
conditions.at(1).get('values').setValue([2, 3])
conditions.at(2).get('values').setValue([4])
filters.at(0).get('values').setValue([1])
filters.at(1).get('values').setValue([2, 3])
filters.at(2).get('values').setValue([4])
const addConditionOfType = (type: TriggerConditionType) => {
const newCondition = component.addCondition(triggerGroup as FormGroup)
newCondition.get('type').setValue(type)
return newCondition
const addFilterOfType = (type: TriggerFilterType) => {
const newFilter = component.addFilter(triggerGroup as FormGroup)
newFilter.get('type').setValue(type)
return newFilter
}
const correspondentIs = addConditionOfType(
TriggerConditionType.CorrespondentIs
)
const correspondentIs = addFilterOfType(TriggerFilterType.CorrespondentIs)
correspondentIs.get('values').setValue(1)
const correspondentNot = addConditionOfType(
TriggerConditionType.CorrespondentNot
)
const correspondentNot = addFilterOfType(TriggerFilterType.CorrespondentNot)
correspondentNot.get('values').setValue([1])
const documentTypeIs = addConditionOfType(
TriggerConditionType.DocumentTypeIs
)
const documentTypeIs = addFilterOfType(TriggerFilterType.DocumentTypeIs)
documentTypeIs.get('values').setValue(1)
const documentTypeNot = addConditionOfType(
TriggerConditionType.DocumentTypeNot
)
const documentTypeNot = addFilterOfType(TriggerFilterType.DocumentTypeNot)
documentTypeNot.get('values').setValue([1])
const storagePathIs = addConditionOfType(TriggerConditionType.StoragePathIs)
const storagePathIs = addFilterOfType(TriggerFilterType.StoragePathIs)
storagePathIs.get('values').setValue(1)
const storagePathNot = addConditionOfType(
TriggerConditionType.StoragePathNot
)
const storagePathNot = addFilterOfType(TriggerFilterType.StoragePathNot)
storagePathNot.get('values').setValue([1])
const customFieldCondition = addConditionOfType(
TriggerConditionType.CustomFieldQuery
const customFieldFilter = addFilterOfType(
TriggerFilterType.CustomFieldQuery
)
const customFieldQuery = JSON.stringify(['AND', [[1, 'exact', 'test']]])
customFieldCondition.get('values').setValue(customFieldQuery)
customFieldFilter.get('values').setValue(customFieldQuery)
const formValues = component['getFormValues']()
@@ -466,23 +454,21 @@ describe('WorkflowEditDialogComponent', () => {
expect(formValues.triggers[0].filter_custom_field_query).toEqual(
customFieldQuery
)
expect(formValues.triggers[0].conditions).toBeUndefined()
expect(formValues.triggers[0].filters).toBeUndefined()
})
it('should ignore empty and null condition values when mapping filters', () => {
it('should ignore empty and null filter values when mapping filters', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
const tagsCondition = component.addCondition(triggerGroup)
tagsCondition.get('type').setValue(TriggerConditionType.TagsAny)
tagsCondition.get('values').setValue([])
const tagsFilter = component.addFilter(triggerGroup)
tagsFilter.get('type').setValue(TriggerFilterType.TagsAny)
tagsFilter.get('values').setValue([])
const correspondentCondition = component.addCondition(triggerGroup)
correspondentCondition
.get('type')
.setValue(TriggerConditionType.CorrespondentIs)
correspondentCondition.get('values').setValue(null)
const correspondentFilter = component.addFilter(triggerGroup)
correspondentFilter.get('type').setValue(TriggerFilterType.CorrespondentIs)
correspondentFilter.get('values').setValue(null)
const formValues = component['getFormValues']()
@@ -495,15 +481,15 @@ describe('WorkflowEditDialogComponent', () => {
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
const addConditionOfType = (type: TriggerConditionType, value: any) => {
const condition = component.addCondition(triggerGroup)
condition.get('type').setValue(type)
condition.get('values').setValue(value)
const addFilterOfType = (type: TriggerFilterType, value: any) => {
const filter = component.addFilter(triggerGroup)
filter.get('type').setValue(type)
filter.get('values').setValue(value)
}
addConditionOfType(TriggerConditionType.CorrespondentIs, [5])
addConditionOfType(TriggerConditionType.DocumentTypeIs, [6])
addConditionOfType(TriggerConditionType.StoragePathIs, [7])
addFilterOfType(TriggerFilterType.CorrespondentIs, [5])
addFilterOfType(TriggerFilterType.DocumentTypeIs, [6])
addFilterOfType(TriggerFilterType.StoragePathIs, [7])
const formValues = component['getFormValues']()
@@ -512,22 +498,22 @@ describe('WorkflowEditDialogComponent', () => {
expect(formValues.triggers[0].filter_has_storage_path).toEqual(7)
})
it('should convert multi-value condition values when aggregating filters', () => {
it('should convert multi-value filter values when aggregating filters', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
const setCondition = (type: TriggerConditionType, value: number): void => {
const condition = component.addCondition(triggerGroup) as FormGroup
condition.get('type').setValue(type)
condition.get('values').setValue(value)
const setFilter = (type: TriggerFilterType, value: number): void => {
const filter = component.addFilter(triggerGroup) as FormGroup
filter.get('type').setValue(type)
filter.get('values').setValue(value)
}
setCondition(TriggerConditionType.TagsAll, 11)
setCondition(TriggerConditionType.TagsNone, 12)
setCondition(TriggerConditionType.CorrespondentNot, 13)
setCondition(TriggerConditionType.DocumentTypeNot, 14)
setCondition(TriggerConditionType.StoragePathNot, 15)
setFilter(TriggerFilterType.TagsAll, 11)
setFilter(TriggerFilterType.TagsNone, 12)
setFilter(TriggerFilterType.CorrespondentNot, 13)
setFilter(TriggerFilterType.DocumentTypeNot, 14)
setFilter(TriggerFilterType.StoragePathNot, 15)
const formValues = component['getFormValues']()
@@ -538,55 +524,55 @@ describe('WorkflowEditDialogComponent', () => {
expect(formValues.triggers[0].filter_has_not_storage_paths).toEqual([15])
})
it('should reuse condition type options and update disabled state', () => {
it('should reuse filter type options and update disabled state', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
component.addCondition(triggerGroup)
component.addFilter(triggerGroup)
const optionsFirst = component.getConditionTypeOptions(triggerGroup, 0)
const optionsSecond = component.getConditionTypeOptions(triggerGroup, 0)
const optionsFirst = component.getFilterTypeOptions(triggerGroup, 0)
const optionsSecond = component.getFilterTypeOptions(triggerGroup, 0)
expect(optionsFirst).toBe(optionsSecond)
// to force disabled flag
component.addCondition(triggerGroup)
const conditionArray = component.getConditionsFormArray(triggerGroup)
const firstCondition = conditionArray.at(0)
firstCondition.get('type').setValue(TriggerConditionType.CorrespondentIs)
component.addFilter(triggerGroup)
const filterArray = component.getFiltersFormArray(triggerGroup)
const firstFilter = filterArray.at(0)
firstFilter.get('type').setValue(TriggerFilterType.CorrespondentIs)
component.addCondition(triggerGroup)
const updatedConditions = component.getConditionsFormArray(triggerGroup)
const secondCondition = updatedConditions.at(1)
const options = component.getConditionTypeOptions(triggerGroup, 1)
component.addFilter(triggerGroup)
const updatedFilters = component.getFiltersFormArray(triggerGroup)
const secondFilter = updatedFilters.at(1)
const options = component.getFilterTypeOptions(triggerGroup, 1)
const correspondentIsOption = options.find(
(option) => option.id === TriggerConditionType.CorrespondentIs
(option) => option.id === TriggerFilterType.CorrespondentIs
)
expect(correspondentIsOption.disabled).toBe(true)
firstCondition.get('type').setValue(TriggerConditionType.DocumentTypeNot)
secondCondition.get('type').setValue(TriggerConditionType.TagsAll)
const postChangeOptions = component.getConditionTypeOptions(triggerGroup, 1)
firstFilter.get('type').setValue(TriggerFilterType.DocumentTypeNot)
secondFilter.get('type').setValue(TriggerFilterType.TagsAll)
const postChangeOptions = component.getFilterTypeOptions(triggerGroup, 1)
const correspondentOptionAfter = postChangeOptions.find(
(option) => option.id === TriggerConditionType.CorrespondentIs
(option) => option.id === TriggerFilterType.CorrespondentIs
)
expect(correspondentOptionAfter.disabled).toBe(false)
})
it('should keep multi-entry condition options enabled and allow duplicates', () => {
it('should keep multi-entry filter options enabled and allow duplicates', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
component.conditionDefinitions = [
component.filterDefinitions = [
{
id: TriggerConditionType.TagsAny,
id: TriggerFilterType.TagsAny,
name: 'Any tags',
inputType: 'tags',
allowMultipleEntries: true,
allowMultipleValues: true,
} as any,
{
id: TriggerConditionType.CorrespondentIs,
id: TriggerFilterType.CorrespondentIs,
name: 'Correspondent is',
inputType: 'select',
allowMultipleEntries: false,
@@ -595,36 +581,36 @@ describe('WorkflowEditDialogComponent', () => {
} as any,
]
const firstCondition = component.addCondition(triggerGroup)
firstCondition.get('type').setValue(TriggerConditionType.TagsAny)
const firstFilter = component.addFilter(triggerGroup)
firstFilter.get('type').setValue(TriggerFilterType.TagsAny)
const secondCondition = component.addCondition(triggerGroup)
expect(secondCondition).not.toBeNull()
const secondFilter = component.addFilter(triggerGroup)
expect(secondFilter).not.toBeNull()
const options = component.getConditionTypeOptions(triggerGroup, 1)
const options = component.getFilterTypeOptions(triggerGroup, 1)
const multiEntryOption = options.find(
(option) => option.id === TriggerConditionType.TagsAny
(option) => option.id === TriggerFilterType.TagsAny
)
expect(multiEntryOption.disabled).toBe(false)
expect(component.canAddCondition(triggerGroup)).toBe(true)
expect(component.canAddFilter(triggerGroup)).toBe(true)
})
it('should return null when no condition definitions remain available', () => {
it('should return null when no filter definitions remain available', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
component.conditionDefinitions = [
component.filterDefinitions = [
{
id: TriggerConditionType.TagsAny,
id: TriggerFilterType.TagsAny,
name: 'Any tags',
inputType: 'tags',
allowMultipleEntries: false,
allowMultipleValues: true,
} as any,
{
id: TriggerConditionType.CorrespondentIs,
id: TriggerFilterType.CorrespondentIs,
name: 'Correspondent is',
inputType: 'select',
allowMultipleEntries: false,
@@ -633,18 +619,18 @@ describe('WorkflowEditDialogComponent', () => {
} as any,
]
const firstCondition = component.addCondition(triggerGroup)
firstCondition.get('type').setValue(TriggerConditionType.TagsAny)
const secondCondition = component.addCondition(triggerGroup)
secondCondition.get('type').setValue(TriggerConditionType.CorrespondentIs)
const firstFilter = component.addFilter(triggerGroup)
firstFilter.get('type').setValue(TriggerFilterType.TagsAny)
const secondFilter = component.addFilter(triggerGroup)
secondFilter.get('type').setValue(TriggerFilterType.CorrespondentIs)
expect(component.canAddCondition(triggerGroup)).toBe(false)
expect(component.addCondition(triggerGroup)).toBeNull()
expect(component.canAddFilter(triggerGroup)).toBe(false)
expect(component.addFilter(triggerGroup)).toBeNull()
})
it('should skip condition definitions without handlers when building form array', () => {
const originalDefinitions = component.conditionDefinitions
component.conditionDefinitions = [
it('should skip filter definitions without handlers when building form array', () => {
const originalDefinitions = component.filterDefinitions
component.filterDefinitions = [
{
id: 999,
name: 'Unsupported',
@@ -667,52 +653,52 @@ describe('WorkflowEditDialogComponent', () => {
filter_custom_field_query: null,
} as any
const conditions = component['buildConditionFormArray'](trigger)
expect(conditions.length).toBe(0)
const filters = component['buildFiltersFormArray'](trigger)
expect(filters.length).toBe(0)
component.conditionDefinitions = originalDefinitions
component.filterDefinitions = originalDefinitions
})
it('should return null when adding condition for unknown trigger form group', () => {
expect(component.addCondition(new FormGroup({}) as any)).toBeNull()
it('should return null when adding filter for unknown trigger form group', () => {
expect(component.addFilter(new FormGroup({}) as any)).toBeNull()
})
it('should ignore remove condition calls for unknown trigger form group', () => {
it('should ignore remove filter calls for unknown trigger form group', () => {
expect(() =>
component.removeCondition(new FormGroup({}) as any, 0)
component.removeFilter(new FormGroup({}) as any, 0)
).not.toThrow()
})
it('should teardown custom field query model when removing a custom field condition', () => {
it('should teardown custom field query model when removing a custom field filter', () => {
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
component.addCondition(triggerGroup)
const conditions = component.getConditionsFormArray(triggerGroup)
const conditionGroup = conditions.at(0) as FormGroup
conditionGroup.get('type').setValue(TriggerConditionType.CustomFieldQuery)
component.addFilter(triggerGroup)
const filters = component.getFiltersFormArray(triggerGroup)
const filterGroup = filters.at(0) as FormGroup
filterGroup.get('type').setValue(TriggerFilterType.CustomFieldQuery)
const model = component.getCustomFieldQueryModel(conditionGroup)
const model = component.getCustomFieldQueryModel(filterGroup)
expect(model).toBeDefined()
expect(
component['getStoredCustomFieldQueryModel'](conditionGroup as any)
component['getStoredCustomFieldQueryModel'](filterGroup as any)
).toBe(model)
component.removeCondition(triggerGroup, 0)
component.removeFilter(triggerGroup, 0)
expect(
component['getStoredCustomFieldQueryModel'](conditionGroup as any)
component['getStoredCustomFieldQueryModel'](filterGroup as any)
).toBeNull()
})
it('should return readable condition names', () => {
expect(component.getConditionName(TriggerConditionType.TagsAny)).toBe(
it('should return readable filter names', () => {
expect(component.getFilterName(TriggerFilterType.TagsAny)).toBe(
'Has any of these tags'
)
expect(component.getConditionName(999 as any)).toBe('')
expect(component.getFilterName(999 as any)).toBe('')
})
it('should build condition form array from existing trigger filters', () => {
it('should build filter form array from existing trigger filters', () => {
const trigger = workflow.triggers[0]
trigger.filter_has_tags = [1]
trigger.filter_has_all_tags = [2, 3]
@@ -731,64 +717,62 @@ describe('WorkflowEditDialogComponent', () => {
component.object = workflow
component.ngOnInit()
const triggerGroup = component.triggerFields.at(0) as FormGroup
const conditions = component.getConditionsFormArray(triggerGroup)
expect(conditions.length).toBe(10)
const customFieldCondition = conditions.at(9) as FormGroup
expect(customFieldCondition.get('type').value).toBe(
TriggerConditionType.CustomFieldQuery
const filters = component.getFiltersFormArray(triggerGroup)
expect(filters.length).toBe(10)
const customFieldFilter = filters.at(9) as FormGroup
expect(customFieldFilter.get('type').value).toBe(
TriggerFilterType.CustomFieldQuery
)
const model = component.getCustomFieldQueryModel(customFieldCondition)
const model = component.getCustomFieldQueryModel(customFieldFilter)
expect(model.isValid()).toBe(true)
})
it('should expose select metadata helpers', () => {
expect(
component.isSelectMultiple(TriggerConditionType.CorrespondentNot)
).toBe(true)
expect(
component.isSelectMultiple(TriggerConditionType.CorrespondentIs)
).toBe(false)
expect(component.isSelectMultiple(TriggerFilterType.CorrespondentNot)).toBe(
true
)
expect(component.isSelectMultiple(TriggerFilterType.CorrespondentIs)).toBe(
false
)
component.correspondents = [{ id: 1, name: 'C1' } as any]
component.documentTypes = [{ id: 2, name: 'DT' } as any]
component.storagePaths = [{ id: 3, name: 'SP' } as any]
expect(
component.getConditionSelectItems(TriggerConditionType.CorrespondentIs)
component.getFilterSelectItems(TriggerFilterType.CorrespondentIs)
).toEqual(component.correspondents)
expect(
component.getConditionSelectItems(TriggerConditionType.DocumentTypeIs)
component.getFilterSelectItems(TriggerFilterType.DocumentTypeIs)
).toEqual(component.documentTypes)
expect(
component.getConditionSelectItems(TriggerConditionType.StoragePathIs)
component.getFilterSelectItems(TriggerFilterType.StoragePathIs)
).toEqual(component.storagePaths)
expect(
component.getConditionSelectItems(TriggerConditionType.TagsAll)
).toEqual([])
expect(component.getFilterSelectItems(TriggerFilterType.TagsAll)).toEqual(
[]
)
expect(
component.isCustomFieldQueryCondition(
TriggerConditionType.CustomFieldQuery
)
component.isCustomFieldQueryFilter(TriggerFilterType.CustomFieldQuery)
).toBe(true)
})
it('should return empty select items when definition is missing', () => {
const originalDefinitions = component.conditionDefinitions
component.conditionDefinitions = []
const originalDefinitions = component.filterDefinitions
component.filterDefinitions = []
expect(
component.getConditionSelectItems(TriggerConditionType.CorrespondentIs)
component.getFilterSelectItems(TriggerFilterType.CorrespondentIs)
).toEqual([])
component.conditionDefinitions = originalDefinitions
component.filterDefinitions = originalDefinitions
})
it('should return empty select items when definition has unknown source', () => {
const originalDefinitions = component.conditionDefinitions
component.conditionDefinitions = [
const originalDefinitions = component.filterDefinitions
component.filterDefinitions = [
{
id: TriggerConditionType.CorrespondentIs,
id: TriggerFilterType.CorrespondentIs,
name: 'Correspondent is',
inputType: 'select',
allowMultipleEntries: false,
@@ -798,10 +782,10 @@ describe('WorkflowEditDialogComponent', () => {
]
expect(
component.getConditionSelectItems(TriggerConditionType.CorrespondentIs)
component.getFilterSelectItems(TriggerFilterType.CorrespondentIs)
).toEqual([])
component.conditionDefinitions = originalDefinitions
component.filterDefinitions = originalDefinitions
})
it('should handle custom field query selection change and validation states', () => {
@@ -837,19 +821,19 @@ describe('WorkflowEditDialogComponent', () => {
})
it('should recover from invalid custom field query json and update control on changes', () => {
const conditionGroup = new FormGroup({
const filterGroup = new FormGroup({
values: new FormControl('not-json'),
})
component['ensureCustomFieldQueryModel'](conditionGroup, 'not-json')
component['ensureCustomFieldQueryModel'](filterGroup, 'not-json')
const model = component['getStoredCustomFieldQueryModel'](
conditionGroup as any
filterGroup as any
)
expect(model).toBeDefined()
expect(model.queries.length).toBeGreaterThan(0)
const valuesControl = conditionGroup.get('values')
const valuesControl = filterGroup.get('values')
expect(valuesControl.value).toBeNull()
const expression = new CustomFieldQueryExpression([
@@ -865,7 +849,7 @@ describe('WorkflowEditDialogComponent', () => {
expect(valuesControl.value).toEqual(JSON.stringify(expression.serialize()))
component['clearCustomFieldQueryModel'](conditionGroup as any)
component['clearCustomFieldQueryModel'](filterGroup as any)
})
it('should handle custom field query model change edge cases', () => {
@@ -898,71 +882,61 @@ describe('WorkflowEditDialogComponent', () => {
expect(groupWithControl.get('values').value).toBeNull()
})
it('should normalize condition values for single and multi selects', () => {
it('should normalize filter values for single and multi selects', () => {
expect(
component['normalizeConditionValue'](TriggerConditionType.TagsAny)
component['normalizeFilterValue'](TriggerFilterType.TagsAny)
).toEqual([])
expect(
component['normalizeConditionValue'](TriggerConditionType.TagsAny, 5)
component['normalizeFilterValue'](TriggerFilterType.TagsAny, 5)
).toEqual([5])
expect(
component['normalizeConditionValue'](TriggerConditionType.TagsAny, [5, 6])
component['normalizeFilterValue'](TriggerFilterType.TagsAny, [5, 6])
).toEqual([5, 6])
expect(
component['normalizeConditionValue'](
TriggerConditionType.CorrespondentIs,
[7]
)
component['normalizeFilterValue'](TriggerFilterType.CorrespondentIs, [7])
).toEqual(7)
expect(
component['normalizeConditionValue'](
TriggerConditionType.CorrespondentIs,
8
)
component['normalizeFilterValue'](TriggerFilterType.CorrespondentIs, 8)
).toEqual(8)
const customFieldJson = JSON.stringify(['AND', [[1, 'exact', 'test']]])
expect(
component['normalizeConditionValue'](
TriggerConditionType.CustomFieldQuery,
component['normalizeFilterValue'](
TriggerFilterType.CustomFieldQuery,
customFieldJson
)
).toEqual(customFieldJson)
const customFieldObject = ['AND', [[1, 'exact', 'other']]]
expect(
component['normalizeConditionValue'](
TriggerConditionType.CustomFieldQuery,
component['normalizeFilterValue'](
TriggerFilterType.CustomFieldQuery,
customFieldObject
)
).toEqual(JSON.stringify(customFieldObject))
expect(
component['normalizeConditionValue'](
TriggerConditionType.CustomFieldQuery,
component['normalizeFilterValue'](
TriggerFilterType.CustomFieldQuery,
false
)
).toBeNull()
})
it('should add and remove condition form groups', () => {
it('should add and remove filter form groups', () => {
component['changeDetector'] = { detectChanges: jest.fn() } as any
component.object = undefined
component.addTrigger()
const triggerGroup = component.triggerFields.at(0) as FormGroup
component.addCondition(triggerGroup)
component.addFilter(triggerGroup)
component.removeCondition(triggerGroup, 0)
expect(component.getConditionsFormArray(triggerGroup).length).toBe(0)
component.removeFilter(triggerGroup, 0)
expect(component.getFiltersFormArray(triggerGroup).length).toBe(0)
component.addCondition(triggerGroup)
const conditionArrayAfterAdd =
component.getConditionsFormArray(triggerGroup)
conditionArrayAfterAdd
.at(0)
.get('type')
.setValue(TriggerConditionType.TagsAll)
expect(component.getConditionsFormArray(triggerGroup).length).toBe(1)
component.addFilter(triggerGroup)
const filterArrayAfterAdd = component.getFiltersFormArray(triggerGroup)
filterArrayAfterAdd.at(0).get('type').setValue(TriggerFilterType.TagsAll)
expect(component.getFiltersFormArray(triggerGroup).length).toBe(1)
})
it('should remove selected custom field from the form group', () => {

View File

@@ -141,7 +141,7 @@ export const WORKFLOW_ACTION_OPTIONS = [
},
]
export enum TriggerConditionType {
export enum TriggerFilterType {
TagsAny = 'tags_any',
TagsAll = 'tags_all',
TagsNone = 'tags_none',
@@ -154,8 +154,8 @@ export enum TriggerConditionType {
CustomFieldQuery = 'custom_field_query',
}
interface TriggerConditionDefinition {
id: TriggerConditionType
interface TriggerFilterDefinition {
id: TriggerFilterType
name: string
inputType: 'tags' | 'select' | 'customFieldQuery'
allowMultipleEntries: boolean
@@ -164,7 +164,7 @@ interface TriggerConditionDefinition {
disabled?: boolean
}
type TriggerConditionOption = TriggerConditionDefinition & {
type TriggerFilterOption = TriggerFilterDefinition & {
disabled?: boolean
}
@@ -181,7 +181,7 @@ type TriggerFilterAggregate = {
filter_custom_field_query: string | null
}
interface ConditionFilterHandler {
interface FilterHandler {
apply: (aggregate: TriggerFilterAggregate, values: any) => void
extract: (trigger: WorkflowTrigger) => any
hasValue: (value: any) => boolean
@@ -192,35 +192,35 @@ const CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY = Symbol(
'customFieldQuerySubscription'
)
type CustomFieldConditionGroup = FormGroup & {
type CustomFieldFilterGroup = FormGroup & {
[CUSTOM_FIELD_QUERY_MODEL_KEY]?: CustomFieldQueriesModel
[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?: Subscription
}
const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
const TRIGGER_FILTER_DEFINITIONS: TriggerFilterDefinition[] = [
{
id: TriggerConditionType.TagsAny,
id: TriggerFilterType.TagsAny,
name: $localize`Has any of these tags`,
inputType: 'tags',
allowMultipleEntries: false,
allowMultipleValues: true,
},
{
id: TriggerConditionType.TagsAll,
id: TriggerFilterType.TagsAll,
name: $localize`Has all of these tags`,
inputType: 'tags',
allowMultipleEntries: false,
allowMultipleValues: true,
},
{
id: TriggerConditionType.TagsNone,
id: TriggerFilterType.TagsNone,
name: $localize`Does not have these tags`,
inputType: 'tags',
allowMultipleEntries: false,
allowMultipleValues: true,
},
{
id: TriggerConditionType.CorrespondentIs,
id: TriggerFilterType.CorrespondentIs,
name: $localize`Has correspondent`,
inputType: 'select',
allowMultipleEntries: false,
@@ -228,7 +228,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
selectItems: 'correspondents',
},
{
id: TriggerConditionType.CorrespondentNot,
id: TriggerFilterType.CorrespondentNot,
name: $localize`Does not have correspondents`,
inputType: 'select',
allowMultipleEntries: false,
@@ -236,7 +236,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
selectItems: 'correspondents',
},
{
id: TriggerConditionType.DocumentTypeIs,
id: TriggerFilterType.DocumentTypeIs,
name: $localize`Has document type`,
inputType: 'select',
allowMultipleEntries: false,
@@ -244,7 +244,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
selectItems: 'documentTypes',
},
{
id: TriggerConditionType.DocumentTypeNot,
id: TriggerFilterType.DocumentTypeNot,
name: $localize`Does not have document types`,
inputType: 'select',
allowMultipleEntries: false,
@@ -252,7 +252,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
selectItems: 'documentTypes',
},
{
id: TriggerConditionType.StoragePathIs,
id: TriggerFilterType.StoragePathIs,
name: $localize`Has storage path`,
inputType: 'select',
allowMultipleEntries: false,
@@ -260,7 +260,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
selectItems: 'storagePaths',
},
{
id: TriggerConditionType.StoragePathNot,
id: TriggerFilterType.StoragePathNot,
name: $localize`Does not have storage paths`,
inputType: 'select',
allowMultipleEntries: false,
@@ -268,7 +268,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
selectItems: 'storagePaths',
},
{
id: TriggerConditionType.CustomFieldQuery,
id: TriggerFilterType.CustomFieldQuery,
name: $localize`Matches custom field query`,
inputType: 'customFieldQuery',
allowMultipleEntries: false,
@@ -280,18 +280,15 @@ const TRIGGER_MATCHING_ALGORITHMS = MATCHING_ALGORITHMS.filter(
(a) => a.id !== MATCH_AUTO
)
const CONDITION_FILTER_HANDLERS: Record<
TriggerConditionType,
ConditionFilterHandler
> = {
[TriggerConditionType.TagsAny]: {
const FILTER_HANDLERS: Record<TriggerFilterType, FilterHandler> = {
[TriggerFilterType.TagsAny]: {
apply: (aggregate, values) => {
aggregate.filter_has_tags = Array.isArray(values) ? [...values] : [values]
},
extract: (trigger) => trigger.filter_has_tags,
hasValue: (value) => Array.isArray(value) && value.length > 0,
},
[TriggerConditionType.TagsAll]: {
[TriggerFilterType.TagsAll]: {
apply: (aggregate, values) => {
aggregate.filter_has_all_tags = Array.isArray(values)
? [...values]
@@ -300,7 +297,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_all_tags,
hasValue: (value) => Array.isArray(value) && value.length > 0,
},
[TriggerConditionType.TagsNone]: {
[TriggerFilterType.TagsNone]: {
apply: (aggregate, values) => {
aggregate.filter_has_not_tags = Array.isArray(values)
? [...values]
@@ -309,7 +306,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_not_tags,
hasValue: (value) => Array.isArray(value) && value.length > 0,
},
[TriggerConditionType.CorrespondentIs]: {
[TriggerFilterType.CorrespondentIs]: {
apply: (aggregate, values) => {
aggregate.filter_has_correspondent = Array.isArray(values)
? (values[0] ?? null)
@@ -318,7 +315,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_correspondent,
hasValue: (value) => value !== null && value !== undefined,
},
[TriggerConditionType.CorrespondentNot]: {
[TriggerFilterType.CorrespondentNot]: {
apply: (aggregate, values) => {
aggregate.filter_has_not_correspondents = Array.isArray(values)
? [...values]
@@ -327,7 +324,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_not_correspondents,
hasValue: (value) => Array.isArray(value) && value.length > 0,
},
[TriggerConditionType.DocumentTypeIs]: {
[TriggerFilterType.DocumentTypeIs]: {
apply: (aggregate, values) => {
aggregate.filter_has_document_type = Array.isArray(values)
? (values[0] ?? null)
@@ -336,7 +333,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_document_type,
hasValue: (value) => value !== null && value !== undefined,
},
[TriggerConditionType.DocumentTypeNot]: {
[TriggerFilterType.DocumentTypeNot]: {
apply: (aggregate, values) => {
aggregate.filter_has_not_document_types = Array.isArray(values)
? [...values]
@@ -345,7 +342,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_not_document_types,
hasValue: (value) => Array.isArray(value) && value.length > 0,
},
[TriggerConditionType.StoragePathIs]: {
[TriggerFilterType.StoragePathIs]: {
apply: (aggregate, values) => {
aggregate.filter_has_storage_path = Array.isArray(values)
? (values[0] ?? null)
@@ -354,7 +351,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_storage_path,
hasValue: (value) => value !== null && value !== undefined,
},
[TriggerConditionType.StoragePathNot]: {
[TriggerFilterType.StoragePathNot]: {
apply: (aggregate, values) => {
aggregate.filter_has_not_storage_paths = Array.isArray(values)
? [...values]
@@ -363,7 +360,7 @@ const CONDITION_FILTER_HANDLERS: Record<
extract: (trigger) => trigger.filter_has_not_storage_paths,
hasValue: (value) => Array.isArray(value) && value.length > 0,
},
[TriggerConditionType.CustomFieldQuery]: {
[TriggerFilterType.CustomFieldQuery]: {
apply: (aggregate, values) => {
aggregate.filter_custom_field_query = values as string
},
@@ -405,8 +402,8 @@ export class WorkflowEditDialogComponent
{
public WorkflowTriggerType = WorkflowTriggerType
public WorkflowActionType = WorkflowActionType
public TriggerConditionType = TriggerConditionType
public conditionDefinitions = TRIGGER_CONDITION_DEFINITIONS
public TriggerFilterType = TriggerFilterType
public filterDefinitions = TRIGGER_FILTER_DEFINITIONS
private correspondentService: CorrespondentService
private documentTypeService: DocumentTypeService
@@ -426,9 +423,9 @@ export class WorkflowEditDialogComponent
private allowedActionTypes = []
private readonly triggerConditionOptionsMap = new WeakMap<
private readonly triggerFilterOptionsMap = new WeakMap<
FormArray,
TriggerConditionOption[]
TriggerFilterOption[]
>()
constructor() {
@@ -639,7 +636,7 @@ export class WorkflowEditDialogComponent
formValues.triggers = formValues.triggers.map(
(trigger: any, index: number) => {
const triggerFormGroup = this.triggerFields.at(index) as FormGroup
const conditions = this.getConditionsFormArray(triggerFormGroup)
const filters = this.getFiltersFormArray(triggerFormGroup)
const aggregate: TriggerFilterAggregate = {
filter_has_tags: [],
@@ -654,8 +651,8 @@ export class WorkflowEditDialogComponent
filter_custom_field_query: null,
}
for (const control of conditions.controls) {
const type = control.get('type').value as TriggerConditionType
for (const control of filters.controls) {
const type = control.get('type').value as TriggerFilterType
const values = control.get('values').value
if (values === null || values === undefined) {
@@ -666,7 +663,7 @@ export class WorkflowEditDialogComponent
continue
}
const handler = CONDITION_FILTER_HANDLERS[type]
const handler = FILTER_HANDLERS[type]
handler?.apply(aggregate, values)
}
@@ -688,7 +685,7 @@ export class WorkflowEditDialogComponent
trigger.filter_custom_field_query =
aggregate.filter_custom_field_query ?? null
delete trigger.conditions
delete trigger.filters
return trigger
}
@@ -702,40 +699,38 @@ export class WorkflowEditDialogComponent
return formGroup.get('matching_algorithm').value !== MATCH_NONE
}
private createConditionFormGroup(
type: TriggerConditionType,
private createFilterFormGroup(
type: TriggerFilterType,
initialValue?: any
): FormGroup {
const group = new FormGroup({
type: new FormControl(type),
values: new FormControl(this.normalizeConditionValue(type, initialValue)),
values: new FormControl(this.normalizeFilterValue(type, initialValue)),
})
group
.get('type')
.valueChanges.subscribe((newType: TriggerConditionType) => {
if (newType === TriggerConditionType.CustomFieldQuery) {
this.ensureCustomFieldQueryModel(group)
} else {
this.clearCustomFieldQueryModel(group)
group.get('values').setValue(this.getDefaultConditionValue(newType), {
emitEvent: false,
})
}
})
group.get('type').valueChanges.subscribe((newType: TriggerFilterType) => {
if (newType === TriggerFilterType.CustomFieldQuery) {
this.ensureCustomFieldQueryModel(group)
} else {
this.clearCustomFieldQueryModel(group)
group.get('values').setValue(this.getDefaultFilterValue(newType), {
emitEvent: false,
})
}
})
if (type === TriggerConditionType.CustomFieldQuery) {
if (type === TriggerFilterType.CustomFieldQuery) {
this.ensureCustomFieldQueryModel(group, initialValue)
}
return group
}
private buildConditionFormArray(trigger: WorkflowTrigger): FormArray {
const conditions = new FormArray([])
private buildFiltersFormArray(trigger: WorkflowTrigger): FormArray {
const filters = new FormArray([])
for (const definition of this.conditionDefinitions) {
const handler = CONDITION_FILTER_HANDLERS[definition.id]
for (const definition of this.filterDefinitions) {
const handler = FILTER_HANDLERS[definition.id]
if (!handler) {
continue
}
@@ -745,24 +740,24 @@ export class WorkflowEditDialogComponent
continue
}
conditions.push(this.createConditionFormGroup(definition.id, value))
filters.push(this.createFilterFormGroup(definition.id, value))
}
return conditions
return filters
}
getConditionsFormArray(formGroup: FormGroup): FormArray {
return formGroup.get('conditions') as FormArray
getFiltersFormArray(formGroup: FormGroup): FormArray {
return formGroup.get('filters') as FormArray
}
getConditionTypeOptions(formGroup: FormGroup, conditionIndex: number) {
const conditions = this.getConditionsFormArray(formGroup)
const options = this.getConditionTypeOptionsForArray(conditions)
const currentType = conditions.at(conditionIndex).get('type')
.value as TriggerConditionType
getFilterTypeOptions(formGroup: FormGroup, filterIndex: number) {
const filters = this.getFiltersFormArray(formGroup)
const options = this.getFilterTypeOptionsForArray(filters)
const currentType = filters.at(filterIndex).get('type')
.value as TriggerFilterType
const usedTypes = new Set(
conditions.controls.map(
(control) => control.get('type').value as TriggerConditionType
filters.controls.map(
(control) => control.get('type').value as TriggerFilterType
)
)
@@ -778,15 +773,15 @@ export class WorkflowEditDialogComponent
return options
}
canAddCondition(formGroup: FormGroup): boolean {
const conditions = this.getConditionsFormArray(formGroup)
canAddFilter(formGroup: FormGroup): boolean {
const filters = this.getFiltersFormArray(formGroup)
const usedTypes = new Set(
conditions.controls.map(
(control) => control.get('type').value as TriggerConditionType
filters.controls.map(
(control) => control.get('type').value as TriggerFilterType
)
)
return this.conditionDefinitions.some((definition) => {
return this.filterDefinitions.some((definition) => {
if (definition.allowMultipleEntries) {
return true
}
@@ -794,19 +789,19 @@ export class WorkflowEditDialogComponent
})
}
addCondition(triggerFormGroup: FormGroup): FormGroup | null {
addFilter(triggerFormGroup: FormGroup): FormGroup | null {
const triggerIndex = this.triggerFields.controls.indexOf(triggerFormGroup)
if (triggerIndex === -1) {
return null
}
const conditions = this.getConditionsFormArray(triggerFormGroup)
const filters = this.getFiltersFormArray(triggerFormGroup)
const availableDefinition = this.conditionDefinitions.find((definition) => {
const availableDefinition = this.filterDefinitions.find((definition) => {
if (definition.allowMultipleEntries) {
return true
}
return !conditions.controls.some(
return !filters.controls.some(
(control) => control.get('type').value === definition.id
)
})
@@ -815,72 +810,67 @@ export class WorkflowEditDialogComponent
return null
}
conditions.push(this.createConditionFormGroup(availableDefinition.id))
filters.push(this.createFilterFormGroup(availableDefinition.id))
triggerFormGroup.markAsDirty()
triggerFormGroup.markAsTouched()
return conditions.at(-1) as FormGroup
return filters.at(-1) as FormGroup
}
removeCondition(triggerFormGroup: FormGroup, conditionIndex: number) {
removeFilter(triggerFormGroup: FormGroup, filterIndex: number) {
const triggerIndex = this.triggerFields.controls.indexOf(triggerFormGroup)
if (triggerIndex === -1) {
return
}
const conditions = this.getConditionsFormArray(triggerFormGroup)
const conditionGroup = conditions.at(conditionIndex) as FormGroup
if (
conditionGroup?.get('type').value ===
TriggerConditionType.CustomFieldQuery
) {
this.clearCustomFieldQueryModel(conditionGroup)
const filters = this.getFiltersFormArray(triggerFormGroup)
const filterGroup = filters.at(filterIndex) as FormGroup
if (filterGroup?.get('type').value === TriggerFilterType.CustomFieldQuery) {
this.clearCustomFieldQueryModel(filterGroup)
}
conditions.removeAt(conditionIndex)
filters.removeAt(filterIndex)
triggerFormGroup.markAsDirty()
triggerFormGroup.markAsTouched()
}
getConditionDefinition(
type: TriggerConditionType
): TriggerConditionDefinition | undefined {
return this.conditionDefinitions.find(
(definition) => definition.id === type
)
getFilterDefinition(
type: TriggerFilterType
): TriggerFilterDefinition | undefined {
return this.filterDefinitions.find((definition) => definition.id === type)
}
getConditionName(type: TriggerConditionType): string {
return this.getConditionDefinition(type)?.name ?? ''
getFilterName(type: TriggerFilterType): string {
return this.getFilterDefinition(type)?.name ?? ''
}
isTagsCondition(type: TriggerConditionType): boolean {
return this.getConditionDefinition(type)?.inputType === 'tags'
isTagsFilter(type: TriggerFilterType): boolean {
return this.getFilterDefinition(type)?.inputType === 'tags'
}
isCustomFieldQueryCondition(type: TriggerConditionType): boolean {
return this.getConditionDefinition(type)?.inputType === 'customFieldQuery'
isCustomFieldQueryFilter(type: TriggerFilterType): boolean {
return this.getFilterDefinition(type)?.inputType === 'customFieldQuery'
}
isMultiValueCondition(type: TriggerConditionType): boolean {
isMultiValueFilter(type: TriggerFilterType): boolean {
switch (type) {
case TriggerConditionType.TagsAny:
case TriggerConditionType.TagsAll:
case TriggerConditionType.TagsNone:
case TriggerConditionType.CorrespondentNot:
case TriggerConditionType.DocumentTypeNot:
case TriggerConditionType.StoragePathNot:
case TriggerFilterType.TagsAny:
case TriggerFilterType.TagsAll:
case TriggerFilterType.TagsNone:
case TriggerFilterType.CorrespondentNot:
case TriggerFilterType.DocumentTypeNot:
case TriggerFilterType.StoragePathNot:
return true
default:
return false
}
}
isSelectMultiple(type: TriggerConditionType): boolean {
return !this.isTagsCondition(type) && this.isMultiValueCondition(type)
isSelectMultiple(type: TriggerFilterType): boolean {
return !this.isTagsFilter(type) && this.isMultiValueFilter(type)
}
getConditionSelectItems(type: TriggerConditionType) {
const definition = this.getConditionDefinition(type)
getFilterSelectItems(type: TriggerFilterType) {
const definition = this.getFilterDefinition(type)
if (!definition || definition.inputType !== 'select') {
return []
}
@@ -917,36 +907,36 @@ export class WorkflowEditDialogComponent
return model.isEmpty() || model.isValid()
}
private getConditionTypeOptionsForArray(
conditions: FormArray
): TriggerConditionOption[] {
let cached = this.triggerConditionOptionsMap.get(conditions)
private getFilterTypeOptionsForArray(
filters: FormArray
): TriggerFilterOption[] {
let cached = this.triggerFilterOptionsMap.get(filters)
if (!cached) {
cached = this.conditionDefinitions.map((definition) => ({
cached = this.filterDefinitions.map((definition) => ({
...definition,
disabled: false,
}))
this.triggerConditionOptionsMap.set(conditions, cached)
this.triggerFilterOptionsMap.set(filters, cached)
}
return cached
}
private ensureCustomFieldQueryModel(
conditionGroup: FormGroup,
filterGroup: FormGroup,
initialValue?: any
): CustomFieldQueriesModel {
const existingModel = this.getStoredCustomFieldQueryModel(conditionGroup)
const existingModel = this.getStoredCustomFieldQueryModel(filterGroup)
if (existingModel) {
return existingModel
}
const model = new CustomFieldQueriesModel()
this.setCustomFieldQueryModel(conditionGroup, model)
this.setCustomFieldQueryModel(filterGroup, model)
const rawValue =
typeof initialValue === 'string'
? initialValue
: (conditionGroup.get('values').value as string)
: (filterGroup.get('values').value as string)
if (rawValue) {
try {
@@ -962,46 +952,45 @@ export class WorkflowEditDialogComponent
const subscription = model.changed
.pipe(takeUntil(this.unsubscribeNotifier))
.subscribe(() => {
this.onCustomFieldQueryModelChanged(conditionGroup, model)
this.onCustomFieldQueryModelChanged(filterGroup, model)
})
conditionGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
conditionGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY] = subscription
filterGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
filterGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY] = subscription
this.onCustomFieldQueryModelChanged(conditionGroup, model)
this.onCustomFieldQueryModelChanged(filterGroup, model)
return model
}
private clearCustomFieldQueryModel(conditionGroup: FormGroup) {
const group = conditionGroup as CustomFieldConditionGroup
private clearCustomFieldQueryModel(filterGroup: FormGroup) {
const group = filterGroup as CustomFieldFilterGroup
group[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
delete group[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]
delete group[CUSTOM_FIELD_QUERY_MODEL_KEY]
}
private getStoredCustomFieldQueryModel(
conditionGroup: FormGroup
filterGroup: FormGroup
): CustomFieldQueriesModel | null {
return (
(conditionGroup as CustomFieldConditionGroup)[
CUSTOM_FIELD_QUERY_MODEL_KEY
] ?? null
(filterGroup as CustomFieldFilterGroup)[CUSTOM_FIELD_QUERY_MODEL_KEY] ??
null
)
}
private setCustomFieldQueryModel(
conditionGroup: FormGroup,
filterGroup: FormGroup,
model: CustomFieldQueriesModel
) {
const group = conditionGroup as CustomFieldConditionGroup
const group = filterGroup as CustomFieldFilterGroup
group[CUSTOM_FIELD_QUERY_MODEL_KEY] = model
}
private onCustomFieldQueryModelChanged(
conditionGroup: FormGroup,
filterGroup: FormGroup,
model: CustomFieldQueriesModel
) {
const control = conditionGroup.get('values')
const control = filterGroup.get('values')
if (!control) {
return
}
@@ -1020,26 +1009,26 @@ export class WorkflowEditDialogComponent
control.setValue(serialized, { emitEvent: false })
}
private getDefaultConditionValue(type: TriggerConditionType) {
if (type === TriggerConditionType.CustomFieldQuery) {
private getDefaultFilterValue(type: TriggerFilterType) {
if (type === TriggerFilterType.CustomFieldQuery) {
return null
}
return this.isMultiValueCondition(type) ? [] : null
return this.isMultiValueFilter(type) ? [] : null
}
private normalizeConditionValue(type: TriggerConditionType, value?: any) {
private normalizeFilterValue(type: TriggerFilterType, value?: any) {
if (value === undefined || value === null) {
return this.getDefaultConditionValue(type)
return this.getDefaultFilterValue(type)
}
if (type === TriggerConditionType.CustomFieldQuery) {
if (type === TriggerFilterType.CustomFieldQuery) {
if (typeof value === 'string') {
return value
}
return value ? JSON.stringify(value) : null
}
if (this.isMultiValueCondition(type)) {
if (this.isMultiValueFilter(type)) {
return Array.isArray(value) ? [...value] : [value]
}
@@ -1065,7 +1054,7 @@ export class WorkflowEditDialogComponent
matching_algorithm: new FormControl(trigger.matching_algorithm),
match: new FormControl(trigger.match),
is_insensitive: new FormControl(trigger.is_insensitive),
conditions: this.buildConditionFormArray(trigger),
filters: this.buildFiltersFormArray(trigger),
schedule_offset_days: new FormControl(trigger.schedule_offset_days),
schedule_is_recurring: new FormControl(trigger.schedule_is_recurring),
schedule_recurring_interval_days: new FormControl(