mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-10-12 02:26:09 -05:00
Refactor workflow trigger conditions to filters
This commit is contained in:
@@ -176,58 +176,58 @@
|
|||||||
@if (formGroup.get('type').value === WorkflowTriggerType.DocumentAdded || formGroup.get('type').value === WorkflowTriggerType.DocumentUpdated || formGroup.get('type').value === WorkflowTriggerType.Scheduled) {
|
@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="row mt-3">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="trigger-conditions mb-3">
|
<div class="trigger-filters mb-3">
|
||||||
<div class="d-flex align-items-center">
|
<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
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-sm btn-outline-primary ms-auto"
|
class="btn btn-sm btn-outline-primary ms-auto"
|
||||||
(click)="addCondition(formGroup)"
|
(click)="addFilter(formGroup)"
|
||||||
[disabled]="!canAddCondition(formGroup)"
|
[disabled]="!canAddFilter(formGroup)"
|
||||||
>
|
>
|
||||||
<i-bs name="plus-circle"></i-bs> <span i18n>Add condition</span>
|
<i-bs name="plus-circle"></i-bs> <span i18n>Add filter</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ul class="mt-2 list-group conditions" formArrayName="conditions">
|
<ul class="mt-2 list-group filters" formArrayName="filters">
|
||||||
@if (getConditionsFormArray(formGroup).length === 0) {
|
@if (getFiltersFormArray(formGroup).length === 0) {
|
||||||
<p class="text-muted small" i18n>No conditions added. Add one to define document filters.</p>
|
<p class="text-muted small" i18n>No advanced workflow filters defined.</p>
|
||||||
}
|
}
|
||||||
@for (condition of getConditionsFormArray(formGroup).controls; track condition; let conditionIndex = $index) {
|
@for (filter of getFiltersFormArray(formGroup).controls; track filter; let filterIndex = $index) {
|
||||||
<li [formGroupName]="conditionIndex" class="list-group-item">
|
<li [formGroupName]="filterIndex" class="list-group-item">
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<div class="w-25">
|
<div class="w-25">
|
||||||
<pngx-input-select
|
<pngx-input-select
|
||||||
i18n-title
|
i18n-title
|
||||||
[items]="getConditionTypeOptions(formGroup, conditionIndex)"
|
[items]="getFilterTypeOptions(formGroup, filterIndex)"
|
||||||
formControlName="type"
|
formControlName="type"
|
||||||
[allowNull]="false"
|
[allowNull]="false"
|
||||||
></pngx-input-select>
|
></pngx-input-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
@if (isTagsCondition(condition.get('type').value)) {
|
@if (isTagsFilter(filter.get('type').value)) {
|
||||||
<pngx-input-tags
|
<pngx-input-tags
|
||||||
[allowCreate]="false"
|
[allowCreate]="false"
|
||||||
[title]="null"
|
[title]="null"
|
||||||
formControlName="values"
|
formControlName="values"
|
||||||
></pngx-input-tags>
|
></pngx-input-tags>
|
||||||
} @else if (
|
} @else if (
|
||||||
isCustomFieldQueryCondition(condition.get('type').value)
|
isCustomFieldQueryFilter(filter.get('type').value)
|
||||||
) {
|
) {
|
||||||
<pngx-custom-fields-query-dropdown
|
<pngx-custom-fields-query-dropdown
|
||||||
[selectionModel]="getCustomFieldQueryModel(condition)"
|
[selectionModel]="getCustomFieldQueryModel(filter)"
|
||||||
(selectionModelChange)="onCustomFieldQuerySelectionChange(condition, $event)"
|
(selectionModelChange)="onCustomFieldQuerySelectionChange(filter, $event)"
|
||||||
[useDropdown]="false"
|
[useDropdown]="false"
|
||||||
></pngx-custom-fields-query-dropdown>
|
></pngx-custom-fields-query-dropdown>
|
||||||
@if (!isCustomFieldQueryValid(condition)) {
|
@if (!isCustomFieldQueryValid(filter)) {
|
||||||
<div class="text-danger small" i18n>
|
<div class="text-danger small" i18n>
|
||||||
Complete the custom field query configuration.
|
Complete the custom field query configuration.
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
} @else {
|
} @else {
|
||||||
<pngx-input-select
|
<pngx-input-select
|
||||||
[items]="getConditionSelectItems(condition.get('type').value)"
|
[items]="getFilterSelectItems(filter.get('type').value)"
|
||||||
[allowNull]="true"
|
[allowNull]="true"
|
||||||
[multiple]="isSelectMultiple(condition.get('type').value)"
|
[multiple]="isSelectMultiple(filter.get('type').value)"
|
||||||
formControlName="values"
|
formControlName="values"
|
||||||
></pngx-input-select>
|
></pngx-input-select>
|
||||||
}
|
}
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-link text-danger p-0"
|
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>
|
<i-bs name="trash"></i-bs><span class="ms-1" i18n>Delete</span>
|
||||||
</button>
|
</button>
|
||||||
|
@@ -8,6 +8,6 @@
|
|||||||
font-size: 1rem;
|
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;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
@@ -50,7 +50,7 @@ import { EditDialogMode } from '../edit-dialog.component'
|
|||||||
import {
|
import {
|
||||||
DOCUMENT_SOURCE_OPTIONS,
|
DOCUMENT_SOURCE_OPTIONS,
|
||||||
SCHEDULE_DATE_FIELD_OPTIONS,
|
SCHEDULE_DATE_FIELD_OPTIONS,
|
||||||
TriggerConditionType,
|
TriggerFilterType,
|
||||||
WORKFLOW_ACTION_OPTIONS,
|
WORKFLOW_ACTION_OPTIONS,
|
||||||
WORKFLOW_TYPE_OPTIONS,
|
WORKFLOW_TYPE_OPTIONS,
|
||||||
WorkflowEditDialogComponent,
|
WorkflowEditDialogComponent,
|
||||||
@@ -395,62 +395,50 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
expect(component.matchingPatternRequired(triggerGroup)).toBe(false)
|
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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0)
|
const triggerGroup = component.triggerFields.at(0)
|
||||||
component.addCondition(triggerGroup as FormGroup)
|
component.addFilter(triggerGroup as FormGroup)
|
||||||
component.addCondition(triggerGroup as FormGroup)
|
component.addFilter(triggerGroup as FormGroup)
|
||||||
component.addCondition(triggerGroup as FormGroup)
|
component.addFilter(triggerGroup as FormGroup)
|
||||||
|
|
||||||
const conditions = component.getConditionsFormArray(
|
const filters = component.getFiltersFormArray(triggerGroup as FormGroup)
|
||||||
triggerGroup as FormGroup
|
expect(filters.length).toBe(3)
|
||||||
)
|
|
||||||
expect(conditions.length).toBe(3)
|
|
||||||
|
|
||||||
conditions.at(0).get('values').setValue([1])
|
filters.at(0).get('values').setValue([1])
|
||||||
conditions.at(1).get('values').setValue([2, 3])
|
filters.at(1).get('values').setValue([2, 3])
|
||||||
conditions.at(2).get('values').setValue([4])
|
filters.at(2).get('values').setValue([4])
|
||||||
|
|
||||||
const addConditionOfType = (type: TriggerConditionType) => {
|
const addFilterOfType = (type: TriggerFilterType) => {
|
||||||
const newCondition = component.addCondition(triggerGroup as FormGroup)
|
const newFilter = component.addFilter(triggerGroup as FormGroup)
|
||||||
newCondition.get('type').setValue(type)
|
newFilter.get('type').setValue(type)
|
||||||
return newCondition
|
return newFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
const correspondentIs = addConditionOfType(
|
const correspondentIs = addFilterOfType(TriggerFilterType.CorrespondentIs)
|
||||||
TriggerConditionType.CorrespondentIs
|
|
||||||
)
|
|
||||||
correspondentIs.get('values').setValue(1)
|
correspondentIs.get('values').setValue(1)
|
||||||
|
|
||||||
const correspondentNot = addConditionOfType(
|
const correspondentNot = addFilterOfType(TriggerFilterType.CorrespondentNot)
|
||||||
TriggerConditionType.CorrespondentNot
|
|
||||||
)
|
|
||||||
correspondentNot.get('values').setValue([1])
|
correspondentNot.get('values').setValue([1])
|
||||||
|
|
||||||
const documentTypeIs = addConditionOfType(
|
const documentTypeIs = addFilterOfType(TriggerFilterType.DocumentTypeIs)
|
||||||
TriggerConditionType.DocumentTypeIs
|
|
||||||
)
|
|
||||||
documentTypeIs.get('values').setValue(1)
|
documentTypeIs.get('values').setValue(1)
|
||||||
|
|
||||||
const documentTypeNot = addConditionOfType(
|
const documentTypeNot = addFilterOfType(TriggerFilterType.DocumentTypeNot)
|
||||||
TriggerConditionType.DocumentTypeNot
|
|
||||||
)
|
|
||||||
documentTypeNot.get('values').setValue([1])
|
documentTypeNot.get('values').setValue([1])
|
||||||
|
|
||||||
const storagePathIs = addConditionOfType(TriggerConditionType.StoragePathIs)
|
const storagePathIs = addFilterOfType(TriggerFilterType.StoragePathIs)
|
||||||
storagePathIs.get('values').setValue(1)
|
storagePathIs.get('values').setValue(1)
|
||||||
|
|
||||||
const storagePathNot = addConditionOfType(
|
const storagePathNot = addFilterOfType(TriggerFilterType.StoragePathNot)
|
||||||
TriggerConditionType.StoragePathNot
|
|
||||||
)
|
|
||||||
storagePathNot.get('values').setValue([1])
|
storagePathNot.get('values').setValue([1])
|
||||||
|
|
||||||
const customFieldCondition = addConditionOfType(
|
const customFieldFilter = addFilterOfType(
|
||||||
TriggerConditionType.CustomFieldQuery
|
TriggerFilterType.CustomFieldQuery
|
||||||
)
|
)
|
||||||
const customFieldQuery = JSON.stringify(['AND', [[1, 'exact', 'test']]])
|
const customFieldQuery = JSON.stringify(['AND', [[1, 'exact', 'test']]])
|
||||||
customFieldCondition.get('values').setValue(customFieldQuery)
|
customFieldFilter.get('values').setValue(customFieldQuery)
|
||||||
|
|
||||||
const formValues = component['getFormValues']()
|
const formValues = component['getFormValues']()
|
||||||
|
|
||||||
@@ -466,23 +454,21 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
expect(formValues.triggers[0].filter_custom_field_query).toEqual(
|
expect(formValues.triggers[0].filter_custom_field_query).toEqual(
|
||||||
customFieldQuery
|
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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
const tagsCondition = component.addCondition(triggerGroup)
|
const tagsFilter = component.addFilter(triggerGroup)
|
||||||
tagsCondition.get('type').setValue(TriggerConditionType.TagsAny)
|
tagsFilter.get('type').setValue(TriggerFilterType.TagsAny)
|
||||||
tagsCondition.get('values').setValue([])
|
tagsFilter.get('values').setValue([])
|
||||||
|
|
||||||
const correspondentCondition = component.addCondition(triggerGroup)
|
const correspondentFilter = component.addFilter(triggerGroup)
|
||||||
correspondentCondition
|
correspondentFilter.get('type').setValue(TriggerFilterType.CorrespondentIs)
|
||||||
.get('type')
|
correspondentFilter.get('values').setValue(null)
|
||||||
.setValue(TriggerConditionType.CorrespondentIs)
|
|
||||||
correspondentCondition.get('values').setValue(null)
|
|
||||||
|
|
||||||
const formValues = component['getFormValues']()
|
const formValues = component['getFormValues']()
|
||||||
|
|
||||||
@@ -495,15 +481,15 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
const addConditionOfType = (type: TriggerConditionType, value: any) => {
|
const addFilterOfType = (type: TriggerFilterType, value: any) => {
|
||||||
const condition = component.addCondition(triggerGroup)
|
const filter = component.addFilter(triggerGroup)
|
||||||
condition.get('type').setValue(type)
|
filter.get('type').setValue(type)
|
||||||
condition.get('values').setValue(value)
|
filter.get('values').setValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
addConditionOfType(TriggerConditionType.CorrespondentIs, [5])
|
addFilterOfType(TriggerFilterType.CorrespondentIs, [5])
|
||||||
addConditionOfType(TriggerConditionType.DocumentTypeIs, [6])
|
addFilterOfType(TriggerFilterType.DocumentTypeIs, [6])
|
||||||
addConditionOfType(TriggerConditionType.StoragePathIs, [7])
|
addFilterOfType(TriggerFilterType.StoragePathIs, [7])
|
||||||
|
|
||||||
const formValues = component['getFormValues']()
|
const formValues = component['getFormValues']()
|
||||||
|
|
||||||
@@ -512,22 +498,22 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
expect(formValues.triggers[0].filter_has_storage_path).toEqual(7)
|
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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
const setCondition = (type: TriggerConditionType, value: number): void => {
|
const setFilter = (type: TriggerFilterType, value: number): void => {
|
||||||
const condition = component.addCondition(triggerGroup) as FormGroup
|
const filter = component.addFilter(triggerGroup) as FormGroup
|
||||||
condition.get('type').setValue(type)
|
filter.get('type').setValue(type)
|
||||||
condition.get('values').setValue(value)
|
filter.get('values').setValue(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
setCondition(TriggerConditionType.TagsAll, 11)
|
setFilter(TriggerFilterType.TagsAll, 11)
|
||||||
setCondition(TriggerConditionType.TagsNone, 12)
|
setFilter(TriggerFilterType.TagsNone, 12)
|
||||||
setCondition(TriggerConditionType.CorrespondentNot, 13)
|
setFilter(TriggerFilterType.CorrespondentNot, 13)
|
||||||
setCondition(TriggerConditionType.DocumentTypeNot, 14)
|
setFilter(TriggerFilterType.DocumentTypeNot, 14)
|
||||||
setCondition(TriggerConditionType.StoragePathNot, 15)
|
setFilter(TriggerFilterType.StoragePathNot, 15)
|
||||||
|
|
||||||
const formValues = component['getFormValues']()
|
const formValues = component['getFormValues']()
|
||||||
|
|
||||||
@@ -538,55 +524,55 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
expect(formValues.triggers[0].filter_has_not_storage_paths).toEqual([15])
|
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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
component.addCondition(triggerGroup)
|
component.addFilter(triggerGroup)
|
||||||
|
|
||||||
const optionsFirst = component.getConditionTypeOptions(triggerGroup, 0)
|
const optionsFirst = component.getFilterTypeOptions(triggerGroup, 0)
|
||||||
const optionsSecond = component.getConditionTypeOptions(triggerGroup, 0)
|
const optionsSecond = component.getFilterTypeOptions(triggerGroup, 0)
|
||||||
expect(optionsFirst).toBe(optionsSecond)
|
expect(optionsFirst).toBe(optionsSecond)
|
||||||
|
|
||||||
// to force disabled flag
|
// to force disabled flag
|
||||||
component.addCondition(triggerGroup)
|
component.addFilter(triggerGroup)
|
||||||
const conditionArray = component.getConditionsFormArray(triggerGroup)
|
const filterArray = component.getFiltersFormArray(triggerGroup)
|
||||||
const firstCondition = conditionArray.at(0)
|
const firstFilter = filterArray.at(0)
|
||||||
firstCondition.get('type').setValue(TriggerConditionType.CorrespondentIs)
|
firstFilter.get('type').setValue(TriggerFilterType.CorrespondentIs)
|
||||||
|
|
||||||
component.addCondition(triggerGroup)
|
component.addFilter(triggerGroup)
|
||||||
const updatedConditions = component.getConditionsFormArray(triggerGroup)
|
const updatedFilters = component.getFiltersFormArray(triggerGroup)
|
||||||
const secondCondition = updatedConditions.at(1)
|
const secondFilter = updatedFilters.at(1)
|
||||||
const options = component.getConditionTypeOptions(triggerGroup, 1)
|
const options = component.getFilterTypeOptions(triggerGroup, 1)
|
||||||
const correspondentIsOption = options.find(
|
const correspondentIsOption = options.find(
|
||||||
(option) => option.id === TriggerConditionType.CorrespondentIs
|
(option) => option.id === TriggerFilterType.CorrespondentIs
|
||||||
)
|
)
|
||||||
expect(correspondentIsOption.disabled).toBe(true)
|
expect(correspondentIsOption.disabled).toBe(true)
|
||||||
|
|
||||||
firstCondition.get('type').setValue(TriggerConditionType.DocumentTypeNot)
|
firstFilter.get('type').setValue(TriggerFilterType.DocumentTypeNot)
|
||||||
secondCondition.get('type').setValue(TriggerConditionType.TagsAll)
|
secondFilter.get('type').setValue(TriggerFilterType.TagsAll)
|
||||||
const postChangeOptions = component.getConditionTypeOptions(triggerGroup, 1)
|
const postChangeOptions = component.getFilterTypeOptions(triggerGroup, 1)
|
||||||
const correspondentOptionAfter = postChangeOptions.find(
|
const correspondentOptionAfter = postChangeOptions.find(
|
||||||
(option) => option.id === TriggerConditionType.CorrespondentIs
|
(option) => option.id === TriggerFilterType.CorrespondentIs
|
||||||
)
|
)
|
||||||
expect(correspondentOptionAfter.disabled).toBe(false)
|
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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
component.conditionDefinitions = [
|
component.filterDefinitions = [
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.TagsAny,
|
id: TriggerFilterType.TagsAny,
|
||||||
name: 'Any tags',
|
name: 'Any tags',
|
||||||
inputType: 'tags',
|
inputType: 'tags',
|
||||||
allowMultipleEntries: true,
|
allowMultipleEntries: true,
|
||||||
allowMultipleValues: true,
|
allowMultipleValues: true,
|
||||||
} as any,
|
} as any,
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.CorrespondentIs,
|
id: TriggerFilterType.CorrespondentIs,
|
||||||
name: 'Correspondent is',
|
name: 'Correspondent is',
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -595,36 +581,36 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
} as any,
|
} as any,
|
||||||
]
|
]
|
||||||
|
|
||||||
const firstCondition = component.addCondition(triggerGroup)
|
const firstFilter = component.addFilter(triggerGroup)
|
||||||
firstCondition.get('type').setValue(TriggerConditionType.TagsAny)
|
firstFilter.get('type').setValue(TriggerFilterType.TagsAny)
|
||||||
|
|
||||||
const secondCondition = component.addCondition(triggerGroup)
|
const secondFilter = component.addFilter(triggerGroup)
|
||||||
expect(secondCondition).not.toBeNull()
|
expect(secondFilter).not.toBeNull()
|
||||||
|
|
||||||
const options = component.getConditionTypeOptions(triggerGroup, 1)
|
const options = component.getFilterTypeOptions(triggerGroup, 1)
|
||||||
const multiEntryOption = options.find(
|
const multiEntryOption = options.find(
|
||||||
(option) => option.id === TriggerConditionType.TagsAny
|
(option) => option.id === TriggerFilterType.TagsAny
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(multiEntryOption.disabled).toBe(false)
|
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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
component.conditionDefinitions = [
|
component.filterDefinitions = [
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.TagsAny,
|
id: TriggerFilterType.TagsAny,
|
||||||
name: 'Any tags',
|
name: 'Any tags',
|
||||||
inputType: 'tags',
|
inputType: 'tags',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
allowMultipleValues: true,
|
allowMultipleValues: true,
|
||||||
} as any,
|
} as any,
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.CorrespondentIs,
|
id: TriggerFilterType.CorrespondentIs,
|
||||||
name: 'Correspondent is',
|
name: 'Correspondent is',
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -633,18 +619,18 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
} as any,
|
} as any,
|
||||||
]
|
]
|
||||||
|
|
||||||
const firstCondition = component.addCondition(triggerGroup)
|
const firstFilter = component.addFilter(triggerGroup)
|
||||||
firstCondition.get('type').setValue(TriggerConditionType.TagsAny)
|
firstFilter.get('type').setValue(TriggerFilterType.TagsAny)
|
||||||
const secondCondition = component.addCondition(triggerGroup)
|
const secondFilter = component.addFilter(triggerGroup)
|
||||||
secondCondition.get('type').setValue(TriggerConditionType.CorrespondentIs)
|
secondFilter.get('type').setValue(TriggerFilterType.CorrespondentIs)
|
||||||
|
|
||||||
expect(component.canAddCondition(triggerGroup)).toBe(false)
|
expect(component.canAddFilter(triggerGroup)).toBe(false)
|
||||||
expect(component.addCondition(triggerGroup)).toBeNull()
|
expect(component.addFilter(triggerGroup)).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should skip condition definitions without handlers when building form array', () => {
|
it('should skip filter definitions without handlers when building form array', () => {
|
||||||
const originalDefinitions = component.conditionDefinitions
|
const originalDefinitions = component.filterDefinitions
|
||||||
component.conditionDefinitions = [
|
component.filterDefinitions = [
|
||||||
{
|
{
|
||||||
id: 999,
|
id: 999,
|
||||||
name: 'Unsupported',
|
name: 'Unsupported',
|
||||||
@@ -667,52 +653,52 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
filter_custom_field_query: null,
|
filter_custom_field_query: null,
|
||||||
} as any
|
} as any
|
||||||
|
|
||||||
const conditions = component['buildConditionFormArray'](trigger)
|
const filters = component['buildFiltersFormArray'](trigger)
|
||||||
expect(conditions.length).toBe(0)
|
expect(filters.length).toBe(0)
|
||||||
|
|
||||||
component.conditionDefinitions = originalDefinitions
|
component.filterDefinitions = originalDefinitions
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return null when adding condition for unknown trigger form group', () => {
|
it('should return null when adding filter for unknown trigger form group', () => {
|
||||||
expect(component.addCondition(new FormGroup({}) as any)).toBeNull()
|
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(() =>
|
expect(() =>
|
||||||
component.removeCondition(new FormGroup({}) as any, 0)
|
component.removeFilter(new FormGroup({}) as any, 0)
|
||||||
).not.toThrow()
|
).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.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
component.addCondition(triggerGroup)
|
component.addFilter(triggerGroup)
|
||||||
const conditions = component.getConditionsFormArray(triggerGroup)
|
const filters = component.getFiltersFormArray(triggerGroup)
|
||||||
const conditionGroup = conditions.at(0) as FormGroup
|
const filterGroup = filters.at(0) as FormGroup
|
||||||
conditionGroup.get('type').setValue(TriggerConditionType.CustomFieldQuery)
|
filterGroup.get('type').setValue(TriggerFilterType.CustomFieldQuery)
|
||||||
|
|
||||||
const model = component.getCustomFieldQueryModel(conditionGroup)
|
const model = component.getCustomFieldQueryModel(filterGroup)
|
||||||
expect(model).toBeDefined()
|
expect(model).toBeDefined()
|
||||||
expect(
|
expect(
|
||||||
component['getStoredCustomFieldQueryModel'](conditionGroup as any)
|
component['getStoredCustomFieldQueryModel'](filterGroup as any)
|
||||||
).toBe(model)
|
).toBe(model)
|
||||||
|
|
||||||
component.removeCondition(triggerGroup, 0)
|
component.removeFilter(triggerGroup, 0)
|
||||||
expect(
|
expect(
|
||||||
component['getStoredCustomFieldQueryModel'](conditionGroup as any)
|
component['getStoredCustomFieldQueryModel'](filterGroup as any)
|
||||||
).toBeNull()
|
).toBeNull()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return readable condition names', () => {
|
it('should return readable filter names', () => {
|
||||||
expect(component.getConditionName(TriggerConditionType.TagsAny)).toBe(
|
expect(component.getFilterName(TriggerFilterType.TagsAny)).toBe(
|
||||||
'Has any of these tags'
|
'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]
|
const trigger = workflow.triggers[0]
|
||||||
trigger.filter_has_tags = [1]
|
trigger.filter_has_tags = [1]
|
||||||
trigger.filter_has_all_tags = [2, 3]
|
trigger.filter_has_all_tags = [2, 3]
|
||||||
@@ -731,64 +717,62 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
component.object = workflow
|
component.object = workflow
|
||||||
component.ngOnInit()
|
component.ngOnInit()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
const conditions = component.getConditionsFormArray(triggerGroup)
|
const filters = component.getFiltersFormArray(triggerGroup)
|
||||||
expect(conditions.length).toBe(10)
|
expect(filters.length).toBe(10)
|
||||||
const customFieldCondition = conditions.at(9) as FormGroup
|
const customFieldFilter = filters.at(9) as FormGroup
|
||||||
expect(customFieldCondition.get('type').value).toBe(
|
expect(customFieldFilter.get('type').value).toBe(
|
||||||
TriggerConditionType.CustomFieldQuery
|
TriggerFilterType.CustomFieldQuery
|
||||||
)
|
)
|
||||||
const model = component.getCustomFieldQueryModel(customFieldCondition)
|
const model = component.getCustomFieldQueryModel(customFieldFilter)
|
||||||
expect(model.isValid()).toBe(true)
|
expect(model.isValid()).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should expose select metadata helpers', () => {
|
it('should expose select metadata helpers', () => {
|
||||||
expect(
|
expect(component.isSelectMultiple(TriggerFilterType.CorrespondentNot)).toBe(
|
||||||
component.isSelectMultiple(TriggerConditionType.CorrespondentNot)
|
true
|
||||||
).toBe(true)
|
)
|
||||||
expect(
|
expect(component.isSelectMultiple(TriggerFilterType.CorrespondentIs)).toBe(
|
||||||
component.isSelectMultiple(TriggerConditionType.CorrespondentIs)
|
false
|
||||||
).toBe(false)
|
)
|
||||||
|
|
||||||
component.correspondents = [{ id: 1, name: 'C1' } as any]
|
component.correspondents = [{ id: 1, name: 'C1' } as any]
|
||||||
component.documentTypes = [{ id: 2, name: 'DT' } as any]
|
component.documentTypes = [{ id: 2, name: 'DT' } as any]
|
||||||
component.storagePaths = [{ id: 3, name: 'SP' } as any]
|
component.storagePaths = [{ id: 3, name: 'SP' } as any]
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
component.getConditionSelectItems(TriggerConditionType.CorrespondentIs)
|
component.getFilterSelectItems(TriggerFilterType.CorrespondentIs)
|
||||||
).toEqual(component.correspondents)
|
).toEqual(component.correspondents)
|
||||||
expect(
|
expect(
|
||||||
component.getConditionSelectItems(TriggerConditionType.DocumentTypeIs)
|
component.getFilterSelectItems(TriggerFilterType.DocumentTypeIs)
|
||||||
).toEqual(component.documentTypes)
|
).toEqual(component.documentTypes)
|
||||||
expect(
|
expect(
|
||||||
component.getConditionSelectItems(TriggerConditionType.StoragePathIs)
|
component.getFilterSelectItems(TriggerFilterType.StoragePathIs)
|
||||||
).toEqual(component.storagePaths)
|
).toEqual(component.storagePaths)
|
||||||
expect(
|
expect(component.getFilterSelectItems(TriggerFilterType.TagsAll)).toEqual(
|
||||||
component.getConditionSelectItems(TriggerConditionType.TagsAll)
|
[]
|
||||||
).toEqual([])
|
)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
component.isCustomFieldQueryCondition(
|
component.isCustomFieldQueryFilter(TriggerFilterType.CustomFieldQuery)
|
||||||
TriggerConditionType.CustomFieldQuery
|
|
||||||
)
|
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return empty select items when definition is missing', () => {
|
it('should return empty select items when definition is missing', () => {
|
||||||
const originalDefinitions = component.conditionDefinitions
|
const originalDefinitions = component.filterDefinitions
|
||||||
component.conditionDefinitions = []
|
component.filterDefinitions = []
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
component.getConditionSelectItems(TriggerConditionType.CorrespondentIs)
|
component.getFilterSelectItems(TriggerFilterType.CorrespondentIs)
|
||||||
).toEqual([])
|
).toEqual([])
|
||||||
|
|
||||||
component.conditionDefinitions = originalDefinitions
|
component.filterDefinitions = originalDefinitions
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should return empty select items when definition has unknown source', () => {
|
it('should return empty select items when definition has unknown source', () => {
|
||||||
const originalDefinitions = component.conditionDefinitions
|
const originalDefinitions = component.filterDefinitions
|
||||||
component.conditionDefinitions = [
|
component.filterDefinitions = [
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.CorrespondentIs,
|
id: TriggerFilterType.CorrespondentIs,
|
||||||
name: 'Correspondent is',
|
name: 'Correspondent is',
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -798,10 +782,10 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
component.getConditionSelectItems(TriggerConditionType.CorrespondentIs)
|
component.getFilterSelectItems(TriggerFilterType.CorrespondentIs)
|
||||||
).toEqual([])
|
).toEqual([])
|
||||||
|
|
||||||
component.conditionDefinitions = originalDefinitions
|
component.filterDefinitions = originalDefinitions
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should handle custom field query selection change and validation states', () => {
|
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', () => {
|
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'),
|
values: new FormControl('not-json'),
|
||||||
})
|
})
|
||||||
|
|
||||||
component['ensureCustomFieldQueryModel'](conditionGroup, 'not-json')
|
component['ensureCustomFieldQueryModel'](filterGroup, 'not-json')
|
||||||
|
|
||||||
const model = component['getStoredCustomFieldQueryModel'](
|
const model = component['getStoredCustomFieldQueryModel'](
|
||||||
conditionGroup as any
|
filterGroup as any
|
||||||
)
|
)
|
||||||
expect(model).toBeDefined()
|
expect(model).toBeDefined()
|
||||||
expect(model.queries.length).toBeGreaterThan(0)
|
expect(model.queries.length).toBeGreaterThan(0)
|
||||||
|
|
||||||
const valuesControl = conditionGroup.get('values')
|
const valuesControl = filterGroup.get('values')
|
||||||
expect(valuesControl.value).toBeNull()
|
expect(valuesControl.value).toBeNull()
|
||||||
|
|
||||||
const expression = new CustomFieldQueryExpression([
|
const expression = new CustomFieldQueryExpression([
|
||||||
@@ -865,7 +849,7 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
|
|
||||||
expect(valuesControl.value).toEqual(JSON.stringify(expression.serialize()))
|
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', () => {
|
it('should handle custom field query model change edge cases', () => {
|
||||||
@@ -898,71 +882,61 @@ describe('WorkflowEditDialogComponent', () => {
|
|||||||
expect(groupWithControl.get('values').value).toBeNull()
|
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(
|
expect(
|
||||||
component['normalizeConditionValue'](TriggerConditionType.TagsAny)
|
component['normalizeFilterValue'](TriggerFilterType.TagsAny)
|
||||||
).toEqual([])
|
).toEqual([])
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](TriggerConditionType.TagsAny, 5)
|
component['normalizeFilterValue'](TriggerFilterType.TagsAny, 5)
|
||||||
).toEqual([5])
|
).toEqual([5])
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](TriggerConditionType.TagsAny, [5, 6])
|
component['normalizeFilterValue'](TriggerFilterType.TagsAny, [5, 6])
|
||||||
).toEqual([5, 6])
|
).toEqual([5, 6])
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](
|
component['normalizeFilterValue'](TriggerFilterType.CorrespondentIs, [7])
|
||||||
TriggerConditionType.CorrespondentIs,
|
|
||||||
[7]
|
|
||||||
)
|
|
||||||
).toEqual(7)
|
).toEqual(7)
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](
|
component['normalizeFilterValue'](TriggerFilterType.CorrespondentIs, 8)
|
||||||
TriggerConditionType.CorrespondentIs,
|
|
||||||
8
|
|
||||||
)
|
|
||||||
).toEqual(8)
|
).toEqual(8)
|
||||||
const customFieldJson = JSON.stringify(['AND', [[1, 'exact', 'test']]])
|
const customFieldJson = JSON.stringify(['AND', [[1, 'exact', 'test']]])
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](
|
component['normalizeFilterValue'](
|
||||||
TriggerConditionType.CustomFieldQuery,
|
TriggerFilterType.CustomFieldQuery,
|
||||||
customFieldJson
|
customFieldJson
|
||||||
)
|
)
|
||||||
).toEqual(customFieldJson)
|
).toEqual(customFieldJson)
|
||||||
|
|
||||||
const customFieldObject = ['AND', [[1, 'exact', 'other']]]
|
const customFieldObject = ['AND', [[1, 'exact', 'other']]]
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](
|
component['normalizeFilterValue'](
|
||||||
TriggerConditionType.CustomFieldQuery,
|
TriggerFilterType.CustomFieldQuery,
|
||||||
customFieldObject
|
customFieldObject
|
||||||
)
|
)
|
||||||
).toEqual(JSON.stringify(customFieldObject))
|
).toEqual(JSON.stringify(customFieldObject))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
component['normalizeConditionValue'](
|
component['normalizeFilterValue'](
|
||||||
TriggerConditionType.CustomFieldQuery,
|
TriggerFilterType.CustomFieldQuery,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
).toBeNull()
|
).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['changeDetector'] = { detectChanges: jest.fn() } as any
|
||||||
component.object = undefined
|
component.object = undefined
|
||||||
component.addTrigger()
|
component.addTrigger()
|
||||||
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
const triggerGroup = component.triggerFields.at(0) as FormGroup
|
||||||
|
|
||||||
component.addCondition(triggerGroup)
|
component.addFilter(triggerGroup)
|
||||||
|
|
||||||
component.removeCondition(triggerGroup, 0)
|
component.removeFilter(triggerGroup, 0)
|
||||||
expect(component.getConditionsFormArray(triggerGroup).length).toBe(0)
|
expect(component.getFiltersFormArray(triggerGroup).length).toBe(0)
|
||||||
|
|
||||||
component.addCondition(triggerGroup)
|
component.addFilter(triggerGroup)
|
||||||
const conditionArrayAfterAdd =
|
const filterArrayAfterAdd = component.getFiltersFormArray(triggerGroup)
|
||||||
component.getConditionsFormArray(triggerGroup)
|
filterArrayAfterAdd.at(0).get('type').setValue(TriggerFilterType.TagsAll)
|
||||||
conditionArrayAfterAdd
|
expect(component.getFiltersFormArray(triggerGroup).length).toBe(1)
|
||||||
.at(0)
|
|
||||||
.get('type')
|
|
||||||
.setValue(TriggerConditionType.TagsAll)
|
|
||||||
expect(component.getConditionsFormArray(triggerGroup).length).toBe(1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should remove selected custom field from the form group', () => {
|
it('should remove selected custom field from the form group', () => {
|
||||||
|
@@ -141,7 +141,7 @@ export const WORKFLOW_ACTION_OPTIONS = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
export enum TriggerConditionType {
|
export enum TriggerFilterType {
|
||||||
TagsAny = 'tags_any',
|
TagsAny = 'tags_any',
|
||||||
TagsAll = 'tags_all',
|
TagsAll = 'tags_all',
|
||||||
TagsNone = 'tags_none',
|
TagsNone = 'tags_none',
|
||||||
@@ -154,8 +154,8 @@ export enum TriggerConditionType {
|
|||||||
CustomFieldQuery = 'custom_field_query',
|
CustomFieldQuery = 'custom_field_query',
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TriggerConditionDefinition {
|
interface TriggerFilterDefinition {
|
||||||
id: TriggerConditionType
|
id: TriggerFilterType
|
||||||
name: string
|
name: string
|
||||||
inputType: 'tags' | 'select' | 'customFieldQuery'
|
inputType: 'tags' | 'select' | 'customFieldQuery'
|
||||||
allowMultipleEntries: boolean
|
allowMultipleEntries: boolean
|
||||||
@@ -164,7 +164,7 @@ interface TriggerConditionDefinition {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type TriggerConditionOption = TriggerConditionDefinition & {
|
type TriggerFilterOption = TriggerFilterDefinition & {
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +181,7 @@ type TriggerFilterAggregate = {
|
|||||||
filter_custom_field_query: string | null
|
filter_custom_field_query: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ConditionFilterHandler {
|
interface FilterHandler {
|
||||||
apply: (aggregate: TriggerFilterAggregate, values: any) => void
|
apply: (aggregate: TriggerFilterAggregate, values: any) => void
|
||||||
extract: (trigger: WorkflowTrigger) => any
|
extract: (trigger: WorkflowTrigger) => any
|
||||||
hasValue: (value: any) => boolean
|
hasValue: (value: any) => boolean
|
||||||
@@ -192,35 +192,35 @@ const CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY = Symbol(
|
|||||||
'customFieldQuerySubscription'
|
'customFieldQuerySubscription'
|
||||||
)
|
)
|
||||||
|
|
||||||
type CustomFieldConditionGroup = FormGroup & {
|
type CustomFieldFilterGroup = FormGroup & {
|
||||||
[CUSTOM_FIELD_QUERY_MODEL_KEY]?: CustomFieldQueriesModel
|
[CUSTOM_FIELD_QUERY_MODEL_KEY]?: CustomFieldQueriesModel
|
||||||
[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?: Subscription
|
[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`,
|
name: $localize`Has any of these tags`,
|
||||||
inputType: 'tags',
|
inputType: 'tags',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
allowMultipleValues: true,
|
allowMultipleValues: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.TagsAll,
|
id: TriggerFilterType.TagsAll,
|
||||||
name: $localize`Has all of these tags`,
|
name: $localize`Has all of these tags`,
|
||||||
inputType: 'tags',
|
inputType: 'tags',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
allowMultipleValues: true,
|
allowMultipleValues: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.TagsNone,
|
id: TriggerFilterType.TagsNone,
|
||||||
name: $localize`Does not have these tags`,
|
name: $localize`Does not have these tags`,
|
||||||
inputType: 'tags',
|
inputType: 'tags',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
allowMultipleValues: true,
|
allowMultipleValues: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.CorrespondentIs,
|
id: TriggerFilterType.CorrespondentIs,
|
||||||
name: $localize`Has correspondent`,
|
name: $localize`Has correspondent`,
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -228,7 +228,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
|
|||||||
selectItems: 'correspondents',
|
selectItems: 'correspondents',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.CorrespondentNot,
|
id: TriggerFilterType.CorrespondentNot,
|
||||||
name: $localize`Does not have correspondents`,
|
name: $localize`Does not have correspondents`,
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -236,7 +236,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
|
|||||||
selectItems: 'correspondents',
|
selectItems: 'correspondents',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.DocumentTypeIs,
|
id: TriggerFilterType.DocumentTypeIs,
|
||||||
name: $localize`Has document type`,
|
name: $localize`Has document type`,
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -244,7 +244,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
|
|||||||
selectItems: 'documentTypes',
|
selectItems: 'documentTypes',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.DocumentTypeNot,
|
id: TriggerFilterType.DocumentTypeNot,
|
||||||
name: $localize`Does not have document types`,
|
name: $localize`Does not have document types`,
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -252,7 +252,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
|
|||||||
selectItems: 'documentTypes',
|
selectItems: 'documentTypes',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.StoragePathIs,
|
id: TriggerFilterType.StoragePathIs,
|
||||||
name: $localize`Has storage path`,
|
name: $localize`Has storage path`,
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -260,7 +260,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
|
|||||||
selectItems: 'storagePaths',
|
selectItems: 'storagePaths',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.StoragePathNot,
|
id: TriggerFilterType.StoragePathNot,
|
||||||
name: $localize`Does not have storage paths`,
|
name: $localize`Does not have storage paths`,
|
||||||
inputType: 'select',
|
inputType: 'select',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -268,7 +268,7 @@ const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
|
|||||||
selectItems: 'storagePaths',
|
selectItems: 'storagePaths',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: TriggerConditionType.CustomFieldQuery,
|
id: TriggerFilterType.CustomFieldQuery,
|
||||||
name: $localize`Matches custom field query`,
|
name: $localize`Matches custom field query`,
|
||||||
inputType: 'customFieldQuery',
|
inputType: 'customFieldQuery',
|
||||||
allowMultipleEntries: false,
|
allowMultipleEntries: false,
|
||||||
@@ -280,18 +280,15 @@ const TRIGGER_MATCHING_ALGORITHMS = MATCHING_ALGORITHMS.filter(
|
|||||||
(a) => a.id !== MATCH_AUTO
|
(a) => a.id !== MATCH_AUTO
|
||||||
)
|
)
|
||||||
|
|
||||||
const CONDITION_FILTER_HANDLERS: Record<
|
const FILTER_HANDLERS: Record<TriggerFilterType, FilterHandler> = {
|
||||||
TriggerConditionType,
|
[TriggerFilterType.TagsAny]: {
|
||||||
ConditionFilterHandler
|
|
||||||
> = {
|
|
||||||
[TriggerConditionType.TagsAny]: {
|
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_tags = Array.isArray(values) ? [...values] : [values]
|
aggregate.filter_has_tags = Array.isArray(values) ? [...values] : [values]
|
||||||
},
|
},
|
||||||
extract: (trigger) => trigger.filter_has_tags,
|
extract: (trigger) => trigger.filter_has_tags,
|
||||||
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.TagsAll]: {
|
[TriggerFilterType.TagsAll]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_all_tags = Array.isArray(values)
|
aggregate.filter_has_all_tags = Array.isArray(values)
|
||||||
? [...values]
|
? [...values]
|
||||||
@@ -300,7 +297,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_all_tags,
|
extract: (trigger) => trigger.filter_has_all_tags,
|
||||||
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.TagsNone]: {
|
[TriggerFilterType.TagsNone]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_not_tags = Array.isArray(values)
|
aggregate.filter_has_not_tags = Array.isArray(values)
|
||||||
? [...values]
|
? [...values]
|
||||||
@@ -309,7 +306,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_not_tags,
|
extract: (trigger) => trigger.filter_has_not_tags,
|
||||||
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.CorrespondentIs]: {
|
[TriggerFilterType.CorrespondentIs]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_correspondent = Array.isArray(values)
|
aggregate.filter_has_correspondent = Array.isArray(values)
|
||||||
? (values[0] ?? null)
|
? (values[0] ?? null)
|
||||||
@@ -318,7 +315,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_correspondent,
|
extract: (trigger) => trigger.filter_has_correspondent,
|
||||||
hasValue: (value) => value !== null && value !== undefined,
|
hasValue: (value) => value !== null && value !== undefined,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.CorrespondentNot]: {
|
[TriggerFilterType.CorrespondentNot]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_not_correspondents = Array.isArray(values)
|
aggregate.filter_has_not_correspondents = Array.isArray(values)
|
||||||
? [...values]
|
? [...values]
|
||||||
@@ -327,7 +324,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_not_correspondents,
|
extract: (trigger) => trigger.filter_has_not_correspondents,
|
||||||
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.DocumentTypeIs]: {
|
[TriggerFilterType.DocumentTypeIs]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_document_type = Array.isArray(values)
|
aggregate.filter_has_document_type = Array.isArray(values)
|
||||||
? (values[0] ?? null)
|
? (values[0] ?? null)
|
||||||
@@ -336,7 +333,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_document_type,
|
extract: (trigger) => trigger.filter_has_document_type,
|
||||||
hasValue: (value) => value !== null && value !== undefined,
|
hasValue: (value) => value !== null && value !== undefined,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.DocumentTypeNot]: {
|
[TriggerFilterType.DocumentTypeNot]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_not_document_types = Array.isArray(values)
|
aggregate.filter_has_not_document_types = Array.isArray(values)
|
||||||
? [...values]
|
? [...values]
|
||||||
@@ -345,7 +342,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_not_document_types,
|
extract: (trigger) => trigger.filter_has_not_document_types,
|
||||||
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.StoragePathIs]: {
|
[TriggerFilterType.StoragePathIs]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_storage_path = Array.isArray(values)
|
aggregate.filter_has_storage_path = Array.isArray(values)
|
||||||
? (values[0] ?? null)
|
? (values[0] ?? null)
|
||||||
@@ -354,7 +351,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_storage_path,
|
extract: (trigger) => trigger.filter_has_storage_path,
|
||||||
hasValue: (value) => value !== null && value !== undefined,
|
hasValue: (value) => value !== null && value !== undefined,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.StoragePathNot]: {
|
[TriggerFilterType.StoragePathNot]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_has_not_storage_paths = Array.isArray(values)
|
aggregate.filter_has_not_storage_paths = Array.isArray(values)
|
||||||
? [...values]
|
? [...values]
|
||||||
@@ -363,7 +360,7 @@ const CONDITION_FILTER_HANDLERS: Record<
|
|||||||
extract: (trigger) => trigger.filter_has_not_storage_paths,
|
extract: (trigger) => trigger.filter_has_not_storage_paths,
|
||||||
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
hasValue: (value) => Array.isArray(value) && value.length > 0,
|
||||||
},
|
},
|
||||||
[TriggerConditionType.CustomFieldQuery]: {
|
[TriggerFilterType.CustomFieldQuery]: {
|
||||||
apply: (aggregate, values) => {
|
apply: (aggregate, values) => {
|
||||||
aggregate.filter_custom_field_query = values as string
|
aggregate.filter_custom_field_query = values as string
|
||||||
},
|
},
|
||||||
@@ -405,8 +402,8 @@ export class WorkflowEditDialogComponent
|
|||||||
{
|
{
|
||||||
public WorkflowTriggerType = WorkflowTriggerType
|
public WorkflowTriggerType = WorkflowTriggerType
|
||||||
public WorkflowActionType = WorkflowActionType
|
public WorkflowActionType = WorkflowActionType
|
||||||
public TriggerConditionType = TriggerConditionType
|
public TriggerFilterType = TriggerFilterType
|
||||||
public conditionDefinitions = TRIGGER_CONDITION_DEFINITIONS
|
public filterDefinitions = TRIGGER_FILTER_DEFINITIONS
|
||||||
|
|
||||||
private correspondentService: CorrespondentService
|
private correspondentService: CorrespondentService
|
||||||
private documentTypeService: DocumentTypeService
|
private documentTypeService: DocumentTypeService
|
||||||
@@ -426,9 +423,9 @@ export class WorkflowEditDialogComponent
|
|||||||
|
|
||||||
private allowedActionTypes = []
|
private allowedActionTypes = []
|
||||||
|
|
||||||
private readonly triggerConditionOptionsMap = new WeakMap<
|
private readonly triggerFilterOptionsMap = new WeakMap<
|
||||||
FormArray,
|
FormArray,
|
||||||
TriggerConditionOption[]
|
TriggerFilterOption[]
|
||||||
>()
|
>()
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -639,7 +636,7 @@ export class WorkflowEditDialogComponent
|
|||||||
formValues.triggers = formValues.triggers.map(
|
formValues.triggers = formValues.triggers.map(
|
||||||
(trigger: any, index: number) => {
|
(trigger: any, index: number) => {
|
||||||
const triggerFormGroup = this.triggerFields.at(index) as FormGroup
|
const triggerFormGroup = this.triggerFields.at(index) as FormGroup
|
||||||
const conditions = this.getConditionsFormArray(triggerFormGroup)
|
const filters = this.getFiltersFormArray(triggerFormGroup)
|
||||||
|
|
||||||
const aggregate: TriggerFilterAggregate = {
|
const aggregate: TriggerFilterAggregate = {
|
||||||
filter_has_tags: [],
|
filter_has_tags: [],
|
||||||
@@ -654,8 +651,8 @@ export class WorkflowEditDialogComponent
|
|||||||
filter_custom_field_query: null,
|
filter_custom_field_query: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const control of conditions.controls) {
|
for (const control of filters.controls) {
|
||||||
const type = control.get('type').value as TriggerConditionType
|
const type = control.get('type').value as TriggerFilterType
|
||||||
const values = control.get('values').value
|
const values = control.get('values').value
|
||||||
|
|
||||||
if (values === null || values === undefined) {
|
if (values === null || values === undefined) {
|
||||||
@@ -666,7 +663,7 @@ export class WorkflowEditDialogComponent
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const handler = CONDITION_FILTER_HANDLERS[type]
|
const handler = FILTER_HANDLERS[type]
|
||||||
handler?.apply(aggregate, values)
|
handler?.apply(aggregate, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -688,7 +685,7 @@ export class WorkflowEditDialogComponent
|
|||||||
trigger.filter_custom_field_query =
|
trigger.filter_custom_field_query =
|
||||||
aggregate.filter_custom_field_query ?? null
|
aggregate.filter_custom_field_query ?? null
|
||||||
|
|
||||||
delete trigger.conditions
|
delete trigger.filters
|
||||||
|
|
||||||
return trigger
|
return trigger
|
||||||
}
|
}
|
||||||
@@ -702,40 +699,38 @@ export class WorkflowEditDialogComponent
|
|||||||
return formGroup.get('matching_algorithm').value !== MATCH_NONE
|
return formGroup.get('matching_algorithm').value !== MATCH_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
private createConditionFormGroup(
|
private createFilterFormGroup(
|
||||||
type: TriggerConditionType,
|
type: TriggerFilterType,
|
||||||
initialValue?: any
|
initialValue?: any
|
||||||
): FormGroup {
|
): FormGroup {
|
||||||
const group = new FormGroup({
|
const group = new FormGroup({
|
||||||
type: new FormControl(type),
|
type: new FormControl(type),
|
||||||
values: new FormControl(this.normalizeConditionValue(type, initialValue)),
|
values: new FormControl(this.normalizeFilterValue(type, initialValue)),
|
||||||
})
|
})
|
||||||
|
|
||||||
group
|
group.get('type').valueChanges.subscribe((newType: TriggerFilterType) => {
|
||||||
.get('type')
|
if (newType === TriggerFilterType.CustomFieldQuery) {
|
||||||
.valueChanges.subscribe((newType: TriggerConditionType) => {
|
this.ensureCustomFieldQueryModel(group)
|
||||||
if (newType === TriggerConditionType.CustomFieldQuery) {
|
} else {
|
||||||
this.ensureCustomFieldQueryModel(group)
|
this.clearCustomFieldQueryModel(group)
|
||||||
} else {
|
group.get('values').setValue(this.getDefaultFilterValue(newType), {
|
||||||
this.clearCustomFieldQueryModel(group)
|
emitEvent: false,
|
||||||
group.get('values').setValue(this.getDefaultConditionValue(newType), {
|
})
|
||||||
emitEvent: false,
|
}
|
||||||
})
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (type === TriggerConditionType.CustomFieldQuery) {
|
if (type === TriggerFilterType.CustomFieldQuery) {
|
||||||
this.ensureCustomFieldQueryModel(group, initialValue)
|
this.ensureCustomFieldQueryModel(group, initialValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
return group
|
return group
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildConditionFormArray(trigger: WorkflowTrigger): FormArray {
|
private buildFiltersFormArray(trigger: WorkflowTrigger): FormArray {
|
||||||
const conditions = new FormArray([])
|
const filters = new FormArray([])
|
||||||
|
|
||||||
for (const definition of this.conditionDefinitions) {
|
for (const definition of this.filterDefinitions) {
|
||||||
const handler = CONDITION_FILTER_HANDLERS[definition.id]
|
const handler = FILTER_HANDLERS[definition.id]
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -745,24 +740,24 @@ export class WorkflowEditDialogComponent
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions.push(this.createConditionFormGroup(definition.id, value))
|
filters.push(this.createFilterFormGroup(definition.id, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
return conditions
|
return filters
|
||||||
}
|
}
|
||||||
|
|
||||||
getConditionsFormArray(formGroup: FormGroup): FormArray {
|
getFiltersFormArray(formGroup: FormGroup): FormArray {
|
||||||
return formGroup.get('conditions') as FormArray
|
return formGroup.get('filters') as FormArray
|
||||||
}
|
}
|
||||||
|
|
||||||
getConditionTypeOptions(formGroup: FormGroup, conditionIndex: number) {
|
getFilterTypeOptions(formGroup: FormGroup, filterIndex: number) {
|
||||||
const conditions = this.getConditionsFormArray(formGroup)
|
const filters = this.getFiltersFormArray(formGroup)
|
||||||
const options = this.getConditionTypeOptionsForArray(conditions)
|
const options = this.getFilterTypeOptionsForArray(filters)
|
||||||
const currentType = conditions.at(conditionIndex).get('type')
|
const currentType = filters.at(filterIndex).get('type')
|
||||||
.value as TriggerConditionType
|
.value as TriggerFilterType
|
||||||
const usedTypes = new Set(
|
const usedTypes = new Set(
|
||||||
conditions.controls.map(
|
filters.controls.map(
|
||||||
(control) => control.get('type').value as TriggerConditionType
|
(control) => control.get('type').value as TriggerFilterType
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -778,15 +773,15 @@ export class WorkflowEditDialogComponent
|
|||||||
return options
|
return options
|
||||||
}
|
}
|
||||||
|
|
||||||
canAddCondition(formGroup: FormGroup): boolean {
|
canAddFilter(formGroup: FormGroup): boolean {
|
||||||
const conditions = this.getConditionsFormArray(formGroup)
|
const filters = this.getFiltersFormArray(formGroup)
|
||||||
const usedTypes = new Set(
|
const usedTypes = new Set(
|
||||||
conditions.controls.map(
|
filters.controls.map(
|
||||||
(control) => control.get('type').value as TriggerConditionType
|
(control) => control.get('type').value as TriggerFilterType
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
return this.conditionDefinitions.some((definition) => {
|
return this.filterDefinitions.some((definition) => {
|
||||||
if (definition.allowMultipleEntries) {
|
if (definition.allowMultipleEntries) {
|
||||||
return true
|
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)
|
const triggerIndex = this.triggerFields.controls.indexOf(triggerFormGroup)
|
||||||
if (triggerIndex === -1) {
|
if (triggerIndex === -1) {
|
||||||
return null
|
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) {
|
if (definition.allowMultipleEntries) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return !conditions.controls.some(
|
return !filters.controls.some(
|
||||||
(control) => control.get('type').value === definition.id
|
(control) => control.get('type').value === definition.id
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -815,72 +810,67 @@ export class WorkflowEditDialogComponent
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
conditions.push(this.createConditionFormGroup(availableDefinition.id))
|
filters.push(this.createFilterFormGroup(availableDefinition.id))
|
||||||
triggerFormGroup.markAsDirty()
|
triggerFormGroup.markAsDirty()
|
||||||
triggerFormGroup.markAsTouched()
|
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)
|
const triggerIndex = this.triggerFields.controls.indexOf(triggerFormGroup)
|
||||||
if (triggerIndex === -1) {
|
if (triggerIndex === -1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditions = this.getConditionsFormArray(triggerFormGroup)
|
const filters = this.getFiltersFormArray(triggerFormGroup)
|
||||||
const conditionGroup = conditions.at(conditionIndex) as FormGroup
|
const filterGroup = filters.at(filterIndex) as FormGroup
|
||||||
if (
|
if (filterGroup?.get('type').value === TriggerFilterType.CustomFieldQuery) {
|
||||||
conditionGroup?.get('type').value ===
|
this.clearCustomFieldQueryModel(filterGroup)
|
||||||
TriggerConditionType.CustomFieldQuery
|
|
||||||
) {
|
|
||||||
this.clearCustomFieldQueryModel(conditionGroup)
|
|
||||||
}
|
}
|
||||||
conditions.removeAt(conditionIndex)
|
filters.removeAt(filterIndex)
|
||||||
triggerFormGroup.markAsDirty()
|
triggerFormGroup.markAsDirty()
|
||||||
triggerFormGroup.markAsTouched()
|
triggerFormGroup.markAsTouched()
|
||||||
}
|
}
|
||||||
|
|
||||||
getConditionDefinition(
|
getFilterDefinition(
|
||||||
type: TriggerConditionType
|
type: TriggerFilterType
|
||||||
): TriggerConditionDefinition | undefined {
|
): TriggerFilterDefinition | undefined {
|
||||||
return this.conditionDefinitions.find(
|
return this.filterDefinitions.find((definition) => definition.id === type)
|
||||||
(definition) => definition.id === type
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getConditionName(type: TriggerConditionType): string {
|
getFilterName(type: TriggerFilterType): string {
|
||||||
return this.getConditionDefinition(type)?.name ?? ''
|
return this.getFilterDefinition(type)?.name ?? ''
|
||||||
}
|
}
|
||||||
|
|
||||||
isTagsCondition(type: TriggerConditionType): boolean {
|
isTagsFilter(type: TriggerFilterType): boolean {
|
||||||
return this.getConditionDefinition(type)?.inputType === 'tags'
|
return this.getFilterDefinition(type)?.inputType === 'tags'
|
||||||
}
|
}
|
||||||
|
|
||||||
isCustomFieldQueryCondition(type: TriggerConditionType): boolean {
|
isCustomFieldQueryFilter(type: TriggerFilterType): boolean {
|
||||||
return this.getConditionDefinition(type)?.inputType === 'customFieldQuery'
|
return this.getFilterDefinition(type)?.inputType === 'customFieldQuery'
|
||||||
}
|
}
|
||||||
|
|
||||||
isMultiValueCondition(type: TriggerConditionType): boolean {
|
isMultiValueFilter(type: TriggerFilterType): boolean {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TriggerConditionType.TagsAny:
|
case TriggerFilterType.TagsAny:
|
||||||
case TriggerConditionType.TagsAll:
|
case TriggerFilterType.TagsAll:
|
||||||
case TriggerConditionType.TagsNone:
|
case TriggerFilterType.TagsNone:
|
||||||
case TriggerConditionType.CorrespondentNot:
|
case TriggerFilterType.CorrespondentNot:
|
||||||
case TriggerConditionType.DocumentTypeNot:
|
case TriggerFilterType.DocumentTypeNot:
|
||||||
case TriggerConditionType.StoragePathNot:
|
case TriggerFilterType.StoragePathNot:
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isSelectMultiple(type: TriggerConditionType): boolean {
|
isSelectMultiple(type: TriggerFilterType): boolean {
|
||||||
return !this.isTagsCondition(type) && this.isMultiValueCondition(type)
|
return !this.isTagsFilter(type) && this.isMultiValueFilter(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
getConditionSelectItems(type: TriggerConditionType) {
|
getFilterSelectItems(type: TriggerFilterType) {
|
||||||
const definition = this.getConditionDefinition(type)
|
const definition = this.getFilterDefinition(type)
|
||||||
if (!definition || definition.inputType !== 'select') {
|
if (!definition || definition.inputType !== 'select') {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@@ -917,36 +907,36 @@ export class WorkflowEditDialogComponent
|
|||||||
return model.isEmpty() || model.isValid()
|
return model.isEmpty() || model.isValid()
|
||||||
}
|
}
|
||||||
|
|
||||||
private getConditionTypeOptionsForArray(
|
private getFilterTypeOptionsForArray(
|
||||||
conditions: FormArray
|
filters: FormArray
|
||||||
): TriggerConditionOption[] {
|
): TriggerFilterOption[] {
|
||||||
let cached = this.triggerConditionOptionsMap.get(conditions)
|
let cached = this.triggerFilterOptionsMap.get(filters)
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
cached = this.conditionDefinitions.map((definition) => ({
|
cached = this.filterDefinitions.map((definition) => ({
|
||||||
...definition,
|
...definition,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
}))
|
}))
|
||||||
this.triggerConditionOptionsMap.set(conditions, cached)
|
this.triggerFilterOptionsMap.set(filters, cached)
|
||||||
}
|
}
|
||||||
return cached
|
return cached
|
||||||
}
|
}
|
||||||
|
|
||||||
private ensureCustomFieldQueryModel(
|
private ensureCustomFieldQueryModel(
|
||||||
conditionGroup: FormGroup,
|
filterGroup: FormGroup,
|
||||||
initialValue?: any
|
initialValue?: any
|
||||||
): CustomFieldQueriesModel {
|
): CustomFieldQueriesModel {
|
||||||
const existingModel = this.getStoredCustomFieldQueryModel(conditionGroup)
|
const existingModel = this.getStoredCustomFieldQueryModel(filterGroup)
|
||||||
if (existingModel) {
|
if (existingModel) {
|
||||||
return existingModel
|
return existingModel
|
||||||
}
|
}
|
||||||
|
|
||||||
const model = new CustomFieldQueriesModel()
|
const model = new CustomFieldQueriesModel()
|
||||||
this.setCustomFieldQueryModel(conditionGroup, model)
|
this.setCustomFieldQueryModel(filterGroup, model)
|
||||||
|
|
||||||
const rawValue =
|
const rawValue =
|
||||||
typeof initialValue === 'string'
|
typeof initialValue === 'string'
|
||||||
? initialValue
|
? initialValue
|
||||||
: (conditionGroup.get('values').value as string)
|
: (filterGroup.get('values').value as string)
|
||||||
|
|
||||||
if (rawValue) {
|
if (rawValue) {
|
||||||
try {
|
try {
|
||||||
@@ -962,46 +952,45 @@ export class WorkflowEditDialogComponent
|
|||||||
const subscription = model.changed
|
const subscription = model.changed
|
||||||
.pipe(takeUntil(this.unsubscribeNotifier))
|
.pipe(takeUntil(this.unsubscribeNotifier))
|
||||||
.subscribe(() => {
|
.subscribe(() => {
|
||||||
this.onCustomFieldQueryModelChanged(conditionGroup, model)
|
this.onCustomFieldQueryModelChanged(filterGroup, model)
|
||||||
})
|
})
|
||||||
conditionGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
|
filterGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
|
||||||
conditionGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY] = subscription
|
filterGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY] = subscription
|
||||||
|
|
||||||
this.onCustomFieldQueryModelChanged(conditionGroup, model)
|
this.onCustomFieldQueryModelChanged(filterGroup, model)
|
||||||
|
|
||||||
return model
|
return model
|
||||||
}
|
}
|
||||||
|
|
||||||
private clearCustomFieldQueryModel(conditionGroup: FormGroup) {
|
private clearCustomFieldQueryModel(filterGroup: FormGroup) {
|
||||||
const group = conditionGroup as CustomFieldConditionGroup
|
const group = filterGroup as CustomFieldFilterGroup
|
||||||
group[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
|
group[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
|
||||||
delete group[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]
|
delete group[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]
|
||||||
delete group[CUSTOM_FIELD_QUERY_MODEL_KEY]
|
delete group[CUSTOM_FIELD_QUERY_MODEL_KEY]
|
||||||
}
|
}
|
||||||
|
|
||||||
private getStoredCustomFieldQueryModel(
|
private getStoredCustomFieldQueryModel(
|
||||||
conditionGroup: FormGroup
|
filterGroup: FormGroup
|
||||||
): CustomFieldQueriesModel | null {
|
): CustomFieldQueriesModel | null {
|
||||||
return (
|
return (
|
||||||
(conditionGroup as CustomFieldConditionGroup)[
|
(filterGroup as CustomFieldFilterGroup)[CUSTOM_FIELD_QUERY_MODEL_KEY] ??
|
||||||
CUSTOM_FIELD_QUERY_MODEL_KEY
|
null
|
||||||
] ?? null
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private setCustomFieldQueryModel(
|
private setCustomFieldQueryModel(
|
||||||
conditionGroup: FormGroup,
|
filterGroup: FormGroup,
|
||||||
model: CustomFieldQueriesModel
|
model: CustomFieldQueriesModel
|
||||||
) {
|
) {
|
||||||
const group = conditionGroup as CustomFieldConditionGroup
|
const group = filterGroup as CustomFieldFilterGroup
|
||||||
group[CUSTOM_FIELD_QUERY_MODEL_KEY] = model
|
group[CUSTOM_FIELD_QUERY_MODEL_KEY] = model
|
||||||
}
|
}
|
||||||
|
|
||||||
private onCustomFieldQueryModelChanged(
|
private onCustomFieldQueryModelChanged(
|
||||||
conditionGroup: FormGroup,
|
filterGroup: FormGroup,
|
||||||
model: CustomFieldQueriesModel
|
model: CustomFieldQueriesModel
|
||||||
) {
|
) {
|
||||||
const control = conditionGroup.get('values')
|
const control = filterGroup.get('values')
|
||||||
if (!control) {
|
if (!control) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1020,26 +1009,26 @@ export class WorkflowEditDialogComponent
|
|||||||
control.setValue(serialized, { emitEvent: false })
|
control.setValue(serialized, { emitEvent: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
private getDefaultConditionValue(type: TriggerConditionType) {
|
private getDefaultFilterValue(type: TriggerFilterType) {
|
||||||
if (type === TriggerConditionType.CustomFieldQuery) {
|
if (type === TriggerFilterType.CustomFieldQuery) {
|
||||||
return null
|
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) {
|
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') {
|
if (typeof value === 'string') {
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
return value ? JSON.stringify(value) : null
|
return value ? JSON.stringify(value) : null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isMultiValueCondition(type)) {
|
if (this.isMultiValueFilter(type)) {
|
||||||
return Array.isArray(value) ? [...value] : [value]
|
return Array.isArray(value) ? [...value] : [value]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,7 +1054,7 @@ export class WorkflowEditDialogComponent
|
|||||||
matching_algorithm: new FormControl(trigger.matching_algorithm),
|
matching_algorithm: new FormControl(trigger.matching_algorithm),
|
||||||
match: new FormControl(trigger.match),
|
match: new FormControl(trigger.match),
|
||||||
is_insensitive: new FormControl(trigger.is_insensitive),
|
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_offset_days: new FormControl(trigger.schedule_offset_days),
|
||||||
schedule_is_recurring: new FormControl(trigger.schedule_is_recurring),
|
schedule_is_recurring: new FormControl(trigger.schedule_is_recurring),
|
||||||
schedule_recurring_interval_days: new FormControl(
|
schedule_recurring_interval_days: new FormControl(
|
||||||
|
Reference in New Issue
Block a user