Dynamic adding / removing workflow triggers + actions
This commit is contained in:
parent
220e9993a1
commit
2f61968e2e
@ -241,7 +241,7 @@
|
|||||||
ngbPopover="Workflows" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end"
|
ngbPopover="Workflows" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end"
|
||||||
container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
||||||
<svg class="sidebaricon" fill="currentColor">
|
<svg class="sidebaricon" fill="currentColor">
|
||||||
<use xlink:href="assets/bootstrap-icons.svg#boxes" />
|
<use xlink:href="assets/bootstrap-icons.svg#arrow-left-right" />
|
||||||
</svg><span> <ng-container i18n>Workflows</ng-container></span>
|
</svg><span> <ng-container i18n>Workflows</ng-container></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -21,13 +21,29 @@
|
|||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
<ng-template>
|
<ng-template>
|
||||||
<p class="small" i18n>Trigger Workflow On:</p>
|
<div class="d-flex">
|
||||||
|
<p class="p-2" i18n>Trigger Workflow On:</p>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-primary ms-auto mb-3" (click)="addTrigger()">
|
||||||
|
<svg class="sidebaricon me-1" fill="currentColor">
|
||||||
|
<use xlink:href="assets/bootstrap-icons.svg#plus-circle" />
|
||||||
|
</svg>
|
||||||
|
<ng-container i18n>Add Trigger</ng-container>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div ngbAccordion [closeOthers]="true">
|
<div ngbAccordion [closeOthers]="true">
|
||||||
@for (trigger of object.triggers; track trigger; let i = $index){
|
@for (trigger of object.triggers; track trigger; let i = $index){
|
||||||
<div ngbAccordionItem [formGroup]="triggerFields.controls[i]">
|
<div ngbAccordionItem [formGroup]="triggerFields.controls[i]">
|
||||||
<h2 ngbAccordionHeader>
|
<div ngbAccordionHeader>
|
||||||
<button ngbAccordionButton>{{getTypeOptionName(triggerFields.controls[i].value.type)}} ({{i + 1}})</button>
|
<button ngbAccordionButton>{{i + 1}}. {{getTypeOptionName(triggerFields.controls[i].value.type)}}
|
||||||
</h2>
|
|
||||||
|
<button type="button" class="btn btn-link text-danger ms-3" (click)="removeTrigger(i)">
|
||||||
|
<svg class="sidebaricon me-1" fill="currentColor">
|
||||||
|
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
||||||
|
</svg>
|
||||||
|
<ng-container i18n>Delete</ng-container>
|
||||||
|
</button>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
|
|
||||||
@ -64,13 +80,29 @@
|
|||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
<ng-template>
|
<ng-template>
|
||||||
<p class="small" i18n>Apply Actions:</p>
|
<div class="d-flex">
|
||||||
|
<p class="p-2" i18n>Apply Actions:</p>
|
||||||
|
<button type="button" class="btn btn-sm btn-outline-primary ms-auto mb-3" (click)="addAction()">
|
||||||
|
<svg class="sidebaricon me-1" fill="currentColor">
|
||||||
|
<use xlink:href="assets/bootstrap-icons.svg#plus-circle" />
|
||||||
|
</svg>
|
||||||
|
<ng-container i18n>Add Action</ng-container>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div ngbAccordion [closeOthers]="true">
|
<div ngbAccordion [closeOthers]="true">
|
||||||
@for (action of object.actions; track action; let i = $index){
|
@for (action of object.actions; track action; let i = $index){
|
||||||
<div ngbAccordionItem [formGroup]="actionFields.controls[i]">
|
<div ngbAccordionItem [formGroup]="actionFields.controls[i]">
|
||||||
<h2 ngbAccordionHeader>
|
<div ngbAccordionHeader>
|
||||||
<button ngbAccordionButton>{{i + 1}}</button>
|
<button ngbAccordionButton><ng-container i18n>Action</ng-container> {{i + 1}}
|
||||||
</h2>
|
|
||||||
|
<button type="button" class="btn btn-link text-danger ms-3" (click)="removeAction(i)">
|
||||||
|
<svg class="sidebaricon me-1" fill="currentColor">
|
||||||
|
<use xlink:href="assets/bootstrap-icons.svg#trash" />
|
||||||
|
</svg>
|
||||||
|
<ng-container i18n>Delete</ng-container>
|
||||||
|
</button>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<div ngbAccordionCollapse>
|
<div ngbAccordionCollapse>
|
||||||
<div ngbAccordionBody>
|
<div ngbAccordionBody>
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
.btn.text-danger {
|
||||||
|
&:hover, &:focus {
|
||||||
|
color: rgba(var(--bs-danger-rgb), var(--bs-text-opacity)) !important;
|
||||||
|
}
|
||||||
|
}
|
@ -195,4 +195,47 @@ export class WorkflowEditDialogComponent
|
|||||||
getTypeOptionName(type: WorkflowTriggerType): string {
|
getTypeOptionName(type: WorkflowTriggerType): string {
|
||||||
return this.typeOptions.find((t) => t.id === type).name ?? ''
|
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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1262,10 +1262,10 @@ class BulkEditObjectPermissionsSerializer(serializers.Serializer, SetPermissions
|
|||||||
|
|
||||||
|
|
||||||
class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
||||||
id = serializers.IntegerField(required=False)
|
id = serializers.IntegerField(required=False, allow_null=True)
|
||||||
sources = fields.MultipleChoiceField(
|
sources = fields.MultipleChoiceField(
|
||||||
choices=WorkflowTrigger.DocumentSourceChoices.choices,
|
choices=WorkflowTrigger.DocumentSourceChoices.choices,
|
||||||
allow_empty=False,
|
allow_empty=True,
|
||||||
default={
|
default={
|
||||||
DocumentSource.ConsumeFolder,
|
DocumentSource.ConsumeFolder,
|
||||||
DocumentSource.ApiUpload,
|
DocumentSource.ApiUpload,
|
||||||
@ -1324,7 +1324,7 @@ class WorkflowTriggerSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class WorkflowActionSerializer(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_correspondent = CorrespondentField(allow_null=True, required=False)
|
||||||
assign_tags = TagsField(many=True, allow_null=True, required=False)
|
assign_tags = TagsField(many=True, allow_null=True, required=False)
|
||||||
assign_document_type = DocumentTypeField(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:
|
if triggers is not None:
|
||||||
for trigger in triggers:
|
for trigger in triggers:
|
||||||
|
filter_has_tags = trigger.pop("filter_has_tags", None)
|
||||||
trigger_instance, _ = WorkflowTrigger.objects.update_or_create(
|
trigger_instance, _ = WorkflowTrigger.objects.update_or_create(
|
||||||
id=trigger["id"],
|
id=trigger["id"],
|
||||||
defaults=trigger,
|
defaults=trigger,
|
||||||
)
|
)
|
||||||
|
if filter_has_tags is not None:
|
||||||
|
trigger_instance.filter_has_tags.set(filter_has_tags)
|
||||||
set_triggers.append(trigger_instance)
|
set_triggers.append(trigger_instance)
|
||||||
|
|
||||||
if actions is not None:
|
if actions is not None:
|
||||||
@ -1396,7 +1399,7 @@ class WorkflowSerializer(serializers.ModelSerializer):
|
|||||||
assign_change_groups = action.pop("assign_change_groups", None)
|
assign_change_groups = action.pop("assign_change_groups", None)
|
||||||
assign_custom_fields = action.pop("assign_custom_fields", None)
|
assign_custom_fields = action.pop("assign_custom_fields", None)
|
||||||
action_instance, _ = WorkflowAction.objects.update_or_create(
|
action_instance, _ = WorkflowAction.objects.update_or_create(
|
||||||
id=trigger["id"],
|
id=action["id"],
|
||||||
defaults=action,
|
defaults=action,
|
||||||
)
|
)
|
||||||
if assign_tags is not None:
|
if assign_tags is not None:
|
||||||
@ -1417,6 +1420,19 @@ class WorkflowSerializer(serializers.ModelSerializer):
|
|||||||
instance.actions.set(set_actions)
|
instance.actions.set(set_actions)
|
||||||
instance.save()
|
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:
|
def create(self, validated_data: Any) -> Workflow:
|
||||||
if "triggers" in validated_data:
|
if "triggers" in validated_data:
|
||||||
triggers = validated_data.pop("triggers")
|
triggers = validated_data.pop("triggers")
|
||||||
@ -1441,4 +1457,6 @@ class WorkflowSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
self.update_triggers_and_actions(instance, triggers, actions)
|
self.update_triggers_and_actions(instance, triggers, actions)
|
||||||
|
|
||||||
|
self.prune_triggers_and_actions()
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
Loading…
x
Reference in New Issue
Block a user