mirror of
				https://github.com/paperless-ngx/paperless-ngx.git
				synced 2025-11-03 03:16:10 -06:00 
			
		
		
		
	Ok big refactor, also some subscription handling
This commit is contained in:
		@@ -512,7 +512,7 @@ describe('WorkflowEditDialogComponent', () => {
 | 
			
		||||
    expect(formValues.triggers[0].filter_has_storage_path).toEqual(7)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should reuse cached condition type options and update disabled state', () => {
 | 
			
		||||
  it('should reuse condition type options and update disabled state', () => {
 | 
			
		||||
    component.object = undefined
 | 
			
		||||
    component.addTrigger()
 | 
			
		||||
    const triggerGroup = component.triggerFields.at(0) as FormGroup
 | 
			
		||||
@@ -638,10 +638,14 @@ describe('WorkflowEditDialogComponent', () => {
 | 
			
		||||
 | 
			
		||||
    const model = component.getCustomFieldQueryModel(conditionGroup)
 | 
			
		||||
    expect(model).toBeDefined()
 | 
			
		||||
    expect(component['customFieldQueryModels'].has(conditionGroup)).toBe(true)
 | 
			
		||||
    expect(
 | 
			
		||||
      component['getStoredCustomFieldQueryModel'](conditionGroup as any)
 | 
			
		||||
    ).toBe(model)
 | 
			
		||||
 | 
			
		||||
    component.removeCondition(triggerGroup, 0)
 | 
			
		||||
    expect(component['customFieldQueryModels'].has(conditionGroup)).toBe(false)
 | 
			
		||||
    expect(
 | 
			
		||||
      component['getStoredCustomFieldQueryModel'](conditionGroup as any)
 | 
			
		||||
    ).toBeNull()
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should return readable condition names', () => {
 | 
			
		||||
@@ -726,10 +730,8 @@ describe('WorkflowEditDialogComponent', () => {
 | 
			
		||||
    component.onCustomFieldQuerySelectionChange(formGroup, model)
 | 
			
		||||
    expect(changeSpy).toHaveBeenCalledWith(formGroup, model)
 | 
			
		||||
 | 
			
		||||
    const map = component['customFieldQueryModels']
 | 
			
		||||
 | 
			
		||||
    expect(component.isCustomFieldQueryValid(formGroup)).toBe(true)
 | 
			
		||||
    map.set(formGroup, model)
 | 
			
		||||
    component['setCustomFieldQueryModel'](formGroup as any, model as any)
 | 
			
		||||
 | 
			
		||||
    const validSpy = jest.spyOn(model, 'isValid').mockReturnValue(false)
 | 
			
		||||
    const emptySpy = jest.spyOn(model, 'isEmpty').mockReturnValue(false)
 | 
			
		||||
@@ -743,7 +745,7 @@ describe('WorkflowEditDialogComponent', () => {
 | 
			
		||||
    emptySpy.mockReturnValue(false)
 | 
			
		||||
    expect(component.isCustomFieldQueryValid(formGroup)).toBe(true)
 | 
			
		||||
 | 
			
		||||
    map.delete(formGroup)
 | 
			
		||||
    component['clearCustomFieldQueryModel'](formGroup as any)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should recover from invalid custom field query json and update control on changes', () => {
 | 
			
		||||
@@ -753,7 +755,9 @@ describe('WorkflowEditDialogComponent', () => {
 | 
			
		||||
 | 
			
		||||
    component['ensureCustomFieldQueryModel'](conditionGroup, 'not-json')
 | 
			
		||||
 | 
			
		||||
    const model = component['customFieldQueryModels'].get(conditionGroup)
 | 
			
		||||
    const model = component['getStoredCustomFieldQueryModel'](
 | 
			
		||||
      conditionGroup as any
 | 
			
		||||
    )
 | 
			
		||||
    expect(model).toBeDefined()
 | 
			
		||||
    expect(model.queries.length).toBeGreaterThan(0)
 | 
			
		||||
 | 
			
		||||
@@ -773,7 +777,7 @@ describe('WorkflowEditDialogComponent', () => {
 | 
			
		||||
 | 
			
		||||
    expect(valuesControl.value).toEqual(JSON.stringify(expression.serialize()))
 | 
			
		||||
 | 
			
		||||
    component['teardownCustomFieldQueryModel'](conditionGroup)
 | 
			
		||||
    component['clearCustomFieldQueryModel'](conditionGroup as any)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  it('should handle custom field query model change edge cases', () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ import {
 | 
			
		||||
} from '@angular/forms'
 | 
			
		||||
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'
 | 
			
		||||
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
 | 
			
		||||
import { first } from 'rxjs'
 | 
			
		||||
import { Subscription, first, takeUntil } from 'rxjs'
 | 
			
		||||
import { Correspondent } from 'src/app/data/correspondent'
 | 
			
		||||
import { CustomField, CustomFieldDataType } from 'src/app/data/custom-field'
 | 
			
		||||
import { DocumentType } from 'src/app/data/document-type'
 | 
			
		||||
@@ -168,6 +168,35 @@ type TriggerConditionOption = TriggerConditionDefinition & {
 | 
			
		||||
  disabled?: boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type TriggerFilterAggregate = {
 | 
			
		||||
  filter_has_tags: number[]
 | 
			
		||||
  filter_has_all_tags: number[]
 | 
			
		||||
  filter_has_not_tags: number[]
 | 
			
		||||
  filter_has_not_correspondents: number[]
 | 
			
		||||
  filter_has_not_document_types: number[]
 | 
			
		||||
  filter_has_not_storage_paths: number[]
 | 
			
		||||
  filter_has_correspondent: number | null
 | 
			
		||||
  filter_has_document_type: number | null
 | 
			
		||||
  filter_has_storage_path: number | null
 | 
			
		||||
  filter_custom_field_query: string | null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface ConditionFilterHandler {
 | 
			
		||||
  apply: (aggregate: TriggerFilterAggregate, values: any) => void
 | 
			
		||||
  extract: (trigger: WorkflowTrigger) => any
 | 
			
		||||
  hasValue: (value: any) => boolean
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const CUSTOM_FIELD_QUERY_MODEL_KEY = Symbol('customFieldQueryModel')
 | 
			
		||||
const CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY = Symbol(
 | 
			
		||||
  'customFieldQuerySubscription'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type CustomFieldConditionGroup = FormGroup & {
 | 
			
		||||
  [CUSTOM_FIELD_QUERY_MODEL_KEY]?: CustomFieldQueriesModel
 | 
			
		||||
  [CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?: Subscription
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const TRIGGER_CONDITION_DEFINITIONS: TriggerConditionDefinition[] = [
 | 
			
		||||
  {
 | 
			
		||||
    id: TriggerConditionType.TagsAny,
 | 
			
		||||
@@ -251,6 +280,99 @@ const TRIGGER_MATCHING_ALGORITHMS = MATCHING_ALGORITHMS.filter(
 | 
			
		||||
  (a) => a.id !== MATCH_AUTO
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const CONDITION_FILTER_HANDLERS: Record<
 | 
			
		||||
  TriggerConditionType,
 | 
			
		||||
  ConditionFilterHandler
 | 
			
		||||
> = {
 | 
			
		||||
  [TriggerConditionType.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]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_all_tags = Array.isArray(values)
 | 
			
		||||
        ? [...values]
 | 
			
		||||
        : [values]
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_all_tags,
 | 
			
		||||
    hasValue: (value) => Array.isArray(value) && value.length > 0,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.TagsNone]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_not_tags = Array.isArray(values)
 | 
			
		||||
        ? [...values]
 | 
			
		||||
        : [values]
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_not_tags,
 | 
			
		||||
    hasValue: (value) => Array.isArray(value) && value.length > 0,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.CorrespondentIs]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_correspondent = Array.isArray(values)
 | 
			
		||||
        ? (values[0] ?? null)
 | 
			
		||||
        : values
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_correspondent,
 | 
			
		||||
    hasValue: (value) => value !== null && value !== undefined,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.CorrespondentNot]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_not_correspondents = Array.isArray(values)
 | 
			
		||||
        ? [...values]
 | 
			
		||||
        : [values]
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_not_correspondents,
 | 
			
		||||
    hasValue: (value) => Array.isArray(value) && value.length > 0,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.DocumentTypeIs]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_document_type = Array.isArray(values)
 | 
			
		||||
        ? (values[0] ?? null)
 | 
			
		||||
        : values
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_document_type,
 | 
			
		||||
    hasValue: (value) => value !== null && value !== undefined,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.DocumentTypeNot]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_not_document_types = Array.isArray(values)
 | 
			
		||||
        ? [...values]
 | 
			
		||||
        : [values]
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_not_document_types,
 | 
			
		||||
    hasValue: (value) => Array.isArray(value) && value.length > 0,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.StoragePathIs]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_storage_path = Array.isArray(values)
 | 
			
		||||
        ? (values[0] ?? null)
 | 
			
		||||
        : values
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_storage_path,
 | 
			
		||||
    hasValue: (value) => value !== null && value !== undefined,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.StoragePathNot]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_has_not_storage_paths = Array.isArray(values)
 | 
			
		||||
        ? [...values]
 | 
			
		||||
        : [values]
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_has_not_storage_paths,
 | 
			
		||||
    hasValue: (value) => Array.isArray(value) && value.length > 0,
 | 
			
		||||
  },
 | 
			
		||||
  [TriggerConditionType.CustomFieldQuery]: {
 | 
			
		||||
    apply: (aggregate, values) => {
 | 
			
		||||
      aggregate.filter_custom_field_query = values as string
 | 
			
		||||
    },
 | 
			
		||||
    extract: (trigger) => trigger.filter_custom_field_query,
 | 
			
		||||
    hasValue: (value) =>
 | 
			
		||||
      typeof value === 'string' && value !== null && value.trim().length > 0,
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'pngx-workflow-edit-dialog',
 | 
			
		||||
  templateUrl: './workflow-edit-dialog.component.html',
 | 
			
		||||
@@ -304,16 +426,11 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
 | 
			
		||||
  private allowedActionTypes = []
 | 
			
		||||
 | 
			
		||||
  private conditionTypeOptionCache = new WeakMap<
 | 
			
		||||
  private triggerConditionOptionsMap = new WeakMap<
 | 
			
		||||
    FormArray,
 | 
			
		||||
    TriggerConditionOption[]
 | 
			
		||||
  >()
 | 
			
		||||
 | 
			
		||||
  private customFieldQueryModels = new WeakMap<
 | 
			
		||||
    FormGroup,
 | 
			
		||||
    CustomFieldQueriesModel
 | 
			
		||||
  >()
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
    super()
 | 
			
		||||
    this.service = inject(WorkflowService)
 | 
			
		||||
@@ -524,17 +641,17 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
          const triggerFormGroup = this.triggerFields.at(index) as FormGroup
 | 
			
		||||
          const conditions = this.getConditionsFormArray(triggerFormGroup)
 | 
			
		||||
 | 
			
		||||
          const aggregate = {
 | 
			
		||||
            filter_has_tags: [] as number[],
 | 
			
		||||
            filter_has_all_tags: [] as number[],
 | 
			
		||||
            filter_has_not_tags: [] as number[],
 | 
			
		||||
            filter_has_not_correspondents: [] as number[],
 | 
			
		||||
            filter_has_not_document_types: [] as number[],
 | 
			
		||||
            filter_has_not_storage_paths: [] as number[],
 | 
			
		||||
            filter_has_correspondent: null as number | null,
 | 
			
		||||
            filter_has_document_type: null as number | null,
 | 
			
		||||
            filter_has_storage_path: null as number | null,
 | 
			
		||||
            filter_custom_field_query: null as string | null,
 | 
			
		||||
          const aggregate: TriggerFilterAggregate = {
 | 
			
		||||
            filter_has_tags: [],
 | 
			
		||||
            filter_has_all_tags: [],
 | 
			
		||||
            filter_has_not_tags: [],
 | 
			
		||||
            filter_has_not_correspondents: [],
 | 
			
		||||
            filter_has_not_document_types: [],
 | 
			
		||||
            filter_has_not_storage_paths: [],
 | 
			
		||||
            filter_has_correspondent: null,
 | 
			
		||||
            filter_has_document_type: null,
 | 
			
		||||
            filter_has_storage_path: null,
 | 
			
		||||
            filter_custom_field_query: null,
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          conditions.controls.forEach((control) => {
 | 
			
		||||
@@ -549,44 +666,8 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
              return
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switch (type) {
 | 
			
		||||
              case TriggerConditionType.TagsAny:
 | 
			
		||||
                aggregate.filter_has_tags = [...values]
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.TagsAll:
 | 
			
		||||
                aggregate.filter_has_all_tags = [...values]
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.TagsNone:
 | 
			
		||||
                aggregate.filter_has_not_tags = [...values]
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.CorrespondentIs:
 | 
			
		||||
                aggregate.filter_has_correspondent = Array.isArray(values)
 | 
			
		||||
                  ? values[0]
 | 
			
		||||
                  : values
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.CorrespondentNot:
 | 
			
		||||
                aggregate.filter_has_not_correspondents = [...values]
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.DocumentTypeIs:
 | 
			
		||||
                aggregate.filter_has_document_type = Array.isArray(values)
 | 
			
		||||
                  ? values[0]
 | 
			
		||||
                  : values
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.DocumentTypeNot:
 | 
			
		||||
                aggregate.filter_has_not_document_types = [...values]
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.StoragePathIs:
 | 
			
		||||
                aggregate.filter_has_storage_path = Array.isArray(values)
 | 
			
		||||
                  ? values[0]
 | 
			
		||||
                  : values
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.StoragePathNot:
 | 
			
		||||
                aggregate.filter_has_not_storage_paths = [...values]
 | 
			
		||||
                break
 | 
			
		||||
              case TriggerConditionType.CustomFieldQuery:
 | 
			
		||||
                aggregate.filter_custom_field_query = values as string
 | 
			
		||||
                break
 | 
			
		||||
            }
 | 
			
		||||
            const handler = CONDITION_FILTER_HANDLERS[type]
 | 
			
		||||
            handler?.apply(aggregate, values)
 | 
			
		||||
          })
 | 
			
		||||
 | 
			
		||||
          trigger.filter_has_tags = aggregate.filter_has_tags
 | 
			
		||||
@@ -636,7 +717,7 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
        if (newType === TriggerConditionType.CustomFieldQuery) {
 | 
			
		||||
          this.ensureCustomFieldQueryModel(group)
 | 
			
		||||
        } else {
 | 
			
		||||
          this.teardownCustomFieldQueryModel(group)
 | 
			
		||||
          this.clearCustomFieldQueryModel(group)
 | 
			
		||||
          group.get('values').setValue(this.getDefaultConditionValue(newType), {
 | 
			
		||||
            emitEvent: false,
 | 
			
		||||
          })
 | 
			
		||||
@@ -653,104 +734,19 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
  private buildConditionFormArray(trigger: WorkflowTrigger): FormArray {
 | 
			
		||||
    const conditions = new FormArray([])
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_has_tags && trigger.filter_has_tags.length > 0) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.TagsAny,
 | 
			
		||||
          trigger.filter_has_tags
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
    this.conditionDefinitions.forEach((definition) => {
 | 
			
		||||
      const handler = CONDITION_FILTER_HANDLERS[definition.id]
 | 
			
		||||
      if (!handler) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_has_all_tags && trigger.filter_has_all_tags.length > 0) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.TagsAll,
 | 
			
		||||
          trigger.filter_has_all_tags
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
      const value = handler.extract(trigger)
 | 
			
		||||
      if (!handler.hasValue(value)) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_has_not_tags && trigger.filter_has_not_tags.length > 0) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.TagsNone,
 | 
			
		||||
          trigger.filter_has_not_tags
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_has_correspondent) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.CorrespondentIs,
 | 
			
		||||
          trigger.filter_has_correspondent
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      trigger.filter_has_not_correspondents &&
 | 
			
		||||
      trigger.filter_has_not_correspondents.length > 0
 | 
			
		||||
    ) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.CorrespondentNot,
 | 
			
		||||
          trigger.filter_has_not_correspondents
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_has_document_type) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.DocumentTypeIs,
 | 
			
		||||
          trigger.filter_has_document_type
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      trigger.filter_has_not_document_types &&
 | 
			
		||||
      trigger.filter_has_not_document_types.length > 0
 | 
			
		||||
    ) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.DocumentTypeNot,
 | 
			
		||||
          trigger.filter_has_not_document_types
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_has_storage_path) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.StoragePathIs,
 | 
			
		||||
          trigger.filter_has_storage_path
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (
 | 
			
		||||
      trigger.filter_has_not_storage_paths &&
 | 
			
		||||
      trigger.filter_has_not_storage_paths.length > 0
 | 
			
		||||
    ) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.StoragePathNot,
 | 
			
		||||
          trigger.filter_has_not_storage_paths
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (trigger.filter_custom_field_query) {
 | 
			
		||||
      conditions.push(
 | 
			
		||||
        this.createConditionFormGroup(
 | 
			
		||||
          TriggerConditionType.CustomFieldQuery,
 | 
			
		||||
          trigger.filter_custom_field_query
 | 
			
		||||
        )
 | 
			
		||||
      )
 | 
			
		||||
    }
 | 
			
		||||
      conditions.push(this.createConditionFormGroup(definition.id, value))
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    return conditions
 | 
			
		||||
  }
 | 
			
		||||
@@ -841,7 +837,7 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
      conditionGroup?.get('type').value ===
 | 
			
		||||
      TriggerConditionType.CustomFieldQuery
 | 
			
		||||
    ) {
 | 
			
		||||
      this.teardownCustomFieldQueryModel(conditionGroup)
 | 
			
		||||
      this.clearCustomFieldQueryModel(conditionGroup)
 | 
			
		||||
    }
 | 
			
		||||
    conditions.removeAt(conditionIndex)
 | 
			
		||||
    triggerFormGroup.markAsDirty()
 | 
			
		||||
@@ -905,9 +901,7 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getCustomFieldQueryModel(control: AbstractControl): CustomFieldQueriesModel {
 | 
			
		||||
    const conditionGroup = control as FormGroup
 | 
			
		||||
    this.ensureCustomFieldQueryModel(conditionGroup)
 | 
			
		||||
    return this.customFieldQueryModels.get(conditionGroup)
 | 
			
		||||
    return this.ensureCustomFieldQueryModel(control as FormGroup)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onCustomFieldQuerySelectionChange(
 | 
			
		||||
@@ -918,7 +912,7 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isCustomFieldQueryValid(control: AbstractControl): boolean {
 | 
			
		||||
    const model = this.customFieldQueryModels.get(control as FormGroup)
 | 
			
		||||
    const model = this.getStoredCustomFieldQueryModel(control as FormGroup)
 | 
			
		||||
    if (!model) {
 | 
			
		||||
      return true
 | 
			
		||||
    }
 | 
			
		||||
@@ -929,13 +923,13 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
  private getConditionTypeOptionsForArray(
 | 
			
		||||
    conditions: FormArray
 | 
			
		||||
  ): TriggerConditionOption[] {
 | 
			
		||||
    let cached = this.conditionTypeOptionCache.get(conditions)
 | 
			
		||||
    let cached = this.triggerConditionOptionsMap.get(conditions)
 | 
			
		||||
    if (!cached) {
 | 
			
		||||
      cached = this.conditionDefinitions.map((definition) => ({
 | 
			
		||||
        ...definition,
 | 
			
		||||
        disabled: false,
 | 
			
		||||
      }))
 | 
			
		||||
      this.conditionTypeOptionCache.set(conditions, cached)
 | 
			
		||||
      this.triggerConditionOptionsMap.set(conditions, cached)
 | 
			
		||||
    }
 | 
			
		||||
    return cached
 | 
			
		||||
  }
 | 
			
		||||
@@ -943,13 +937,14 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
  private ensureCustomFieldQueryModel(
 | 
			
		||||
    conditionGroup: FormGroup,
 | 
			
		||||
    initialValue?: any
 | 
			
		||||
  ) {
 | 
			
		||||
    if (this.customFieldQueryModels.has(conditionGroup)) {
 | 
			
		||||
      return
 | 
			
		||||
  ): CustomFieldQueriesModel {
 | 
			
		||||
    const existingModel = this.getStoredCustomFieldQueryModel(conditionGroup)
 | 
			
		||||
    if (existingModel) {
 | 
			
		||||
      return existingModel
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const model = new CustomFieldQueriesModel()
 | 
			
		||||
    this.customFieldQueryModels.set(conditionGroup, model)
 | 
			
		||||
    this.setCustomFieldQueryModel(conditionGroup, model)
 | 
			
		||||
 | 
			
		||||
    const rawValue =
 | 
			
		||||
      typeof initialValue === 'string'
 | 
			
		||||
@@ -967,18 +962,42 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    model.changed.subscribe(() => {
 | 
			
		||||
      this.onCustomFieldQueryModelChanged(conditionGroup, model)
 | 
			
		||||
    })
 | 
			
		||||
    const subscription = model.changed
 | 
			
		||||
      .pipe(takeUntil(this.unsubscribeNotifier))
 | 
			
		||||
      .subscribe(() => {
 | 
			
		||||
        this.onCustomFieldQueryModelChanged(conditionGroup, model)
 | 
			
		||||
      })
 | 
			
		||||
    conditionGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY]?.unsubscribe()
 | 
			
		||||
    conditionGroup[CUSTOM_FIELD_QUERY_SUBSCRIPTION_KEY] = subscription
 | 
			
		||||
 | 
			
		||||
    this.onCustomFieldQueryModelChanged(conditionGroup, model)
 | 
			
		||||
 | 
			
		||||
    return model
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private teardownCustomFieldQueryModel(conditionGroup: FormGroup) {
 | 
			
		||||
    if (!this.customFieldQueryModels.has(conditionGroup)) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    this.customFieldQueryModels.delete(conditionGroup)
 | 
			
		||||
  private clearCustomFieldQueryModel(conditionGroup: FormGroup) {
 | 
			
		||||
    const group = conditionGroup as CustomFieldConditionGroup
 | 
			
		||||
    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
 | 
			
		||||
  ): CustomFieldQueriesModel | null {
 | 
			
		||||
    return (
 | 
			
		||||
      (conditionGroup as CustomFieldConditionGroup)[
 | 
			
		||||
        CUSTOM_FIELD_QUERY_MODEL_KEY
 | 
			
		||||
      ] ?? null
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private setCustomFieldQueryModel(
 | 
			
		||||
    conditionGroup: FormGroup,
 | 
			
		||||
    model: CustomFieldQueriesModel
 | 
			
		||||
  ) {
 | 
			
		||||
    const group = conditionGroup as CustomFieldConditionGroup
 | 
			
		||||
    group[CUSTOM_FIELD_QUERY_MODEL_KEY] = model
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private onCustomFieldQueryModelChanged(
 | 
			
		||||
@@ -1049,15 +1068,6 @@ export class WorkflowEditDialogComponent
 | 
			
		||||
        matching_algorithm: new FormControl(trigger.matching_algorithm),
 | 
			
		||||
        match: new FormControl(trigger.match),
 | 
			
		||||
        is_insensitive: new FormControl(trigger.is_insensitive),
 | 
			
		||||
        filter_has_correspondent: new FormControl(
 | 
			
		||||
          trigger.filter_has_correspondent
 | 
			
		||||
        ),
 | 
			
		||||
        filter_has_document_type: new FormControl(
 | 
			
		||||
          trigger.filter_has_document_type
 | 
			
		||||
        ),
 | 
			
		||||
        filter_has_storage_path: new FormControl(
 | 
			
		||||
          trigger.filter_has_storage_path
 | 
			
		||||
        ),
 | 
			
		||||
        conditions: this.buildConditionFormArray(trigger),
 | 
			
		||||
        schedule_offset_days: new FormControl(trigger.schedule_offset_days),
 | 
			
		||||
        schedule_is_recurring: new FormControl(trigger.schedule_is_recurring),
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user