diff --git a/src-ui/src/app/components/app-frame/app-frame.component.html b/src-ui/src/app/components/app-frame/app-frame.component.html index 9aa8f84aa..78097a8aa 100644 --- a/src-ui/src/app/components/app-frame/app-frame.component.html +++ b/src-ui/src/app/components/app-frame/app-frame.component.html @@ -241,7 +241,7 @@ ngbPopover="Workflows" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim"> - +  Workflows diff --git a/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html b/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html index 5a88e81fb..908a0638f 100644 --- a/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html +++ b/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.html @@ -21,13 +21,29 @@
-

Trigger Workflow On:

+
+

Trigger Workflow On:

+ +
@for (trigger of object.triggers; track trigger; let i = $index){
-

- -

+
+ + +
@@ -64,13 +80,29 @@
-

Apply Actions:

+
+

Apply Actions:

+ +
@for (action of object.actions; track action; let i = $index){
-

- -

+
+ + +
diff --git a/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.scss b/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.scss index e69de29bb..ad12f4a97 100644 --- a/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.scss +++ b/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.scss @@ -0,0 +1,5 @@ +.btn.text-danger { + &:hover, &:focus { + color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important; + } +} diff --git a/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts index 6e2391c52..23fa9f2ca 100644 --- a/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts +++ b/src-ui/src/app/components/common/edit-dialog/workflow-edit-dialog/workflow-edit-dialog.component.ts @@ -195,4 +195,47 @@ export class WorkflowEditDialogComponent getTypeOptionName(type: WorkflowTriggerType): string { return this.typeOptions.find((t) => t.id === type).name ?? '' } + + addTrigger() { + this.object.triggers.push({ + type: WorkflowTriggerType.Consumption, + sources: [], + filter_filename: null, + filter_path: null, + filter_mailrule: null, + filter_has_tags: [], + filter_has_correspondent: null, + filter_has_document_type: null, + }) + + this.updateTriggerActionFields() + } + + addAction() { + this.object.actions.push({ + assign_title: null, + assign_tags: [], + assign_document_type: null, + assign_correspondent: null, + assign_storage_path: null, + assign_owner: null, + assign_view_users: [], + assign_view_groups: [], + assign_change_users: [], + assign_change_groups: [], + assign_custom_fields: [], + }) + + this.updateTriggerActionFields() + } + + removeTrigger(index: number) { + this.object.triggers.splice(index, 1) + this.updateTriggerActionFields() + } + + removeAction(index: number) { + this.object.actions.splice(index, 1) + this.updateTriggerActionFields() + } } diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 123699135..cdd342925 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -1262,10 +1262,10 @@ class BulkEditObjectPermissionsSerializer(serializers.Serializer, SetPermissions class WorkflowTriggerSerializer(serializers.ModelSerializer): - id = serializers.IntegerField(required=False) + id = serializers.IntegerField(required=False, allow_null=True) sources = fields.MultipleChoiceField( choices=WorkflowTrigger.DocumentSourceChoices.choices, - allow_empty=False, + allow_empty=True, default={ DocumentSource.ConsumeFolder, DocumentSource.ApiUpload, @@ -1324,7 +1324,7 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer): class WorkflowActionSerializer(serializers.ModelSerializer): - id = serializers.IntegerField(required=False) + id = serializers.IntegerField(required=False, allow_null=True) assign_correspondent = CorrespondentField(allow_null=True, required=False) assign_tags = TagsField(many=True, allow_null=True, required=False) assign_document_type = DocumentTypeField(allow_null=True, required=False) @@ -1381,10 +1381,13 @@ class WorkflowSerializer(serializers.ModelSerializer): if triggers is not None: for trigger in triggers: + filter_has_tags = trigger.pop("filter_has_tags", None) trigger_instance, _ = WorkflowTrigger.objects.update_or_create( id=trigger["id"], defaults=trigger, ) + if filter_has_tags is not None: + trigger_instance.filter_has_tags.set(filter_has_tags) set_triggers.append(trigger_instance) if actions is not None: @@ -1396,7 +1399,7 @@ class WorkflowSerializer(serializers.ModelSerializer): assign_change_groups = action.pop("assign_change_groups", None) assign_custom_fields = action.pop("assign_custom_fields", None) action_instance, _ = WorkflowAction.objects.update_or_create( - id=trigger["id"], + id=action["id"], defaults=action, ) if assign_tags is not None: @@ -1417,6 +1420,19 @@ class WorkflowSerializer(serializers.ModelSerializer): instance.actions.set(set_actions) instance.save() + def prune_triggers_and_actions(self): + """ + ManyToMany fields dont support e.g. on_delete so we need to discard unattached + triggers and actionas manually + """ + for trigger in WorkflowTrigger.objects.all(): + if trigger.workflows.all().count() == 0: + trigger.delete() + + for action in WorkflowAction.objects.all(): + if action.workflows.all().count() == 0: + action.delete() + def create(self, validated_data: Any) -> Workflow: if "triggers" in validated_data: triggers = validated_data.pop("triggers") @@ -1441,4 +1457,6 @@ class WorkflowSerializer(serializers.ModelSerializer): self.update_triggers_and_actions(instance, triggers, actions) + self.prune_triggers_and_actions() + return instance