verben-workflow-ui 0.5.72 → 0.5.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/src/lib/components/workflow-designer/designer-canvas/designer-canvas.component.mjs +26 -2
- package/esm2022/src/lib/components/workflow-designer/swimlane-dialog/swimlane-dialog.component.mjs +14 -4
- package/esm2022/src/lib/components/workflow-designer/workflow-data.service.mjs +5 -1
- package/esm2022/src/lib/components/workflow-designer/workflow-designer.component.mjs +45 -3
- package/esm2022/src/lib/components/workflow-designer/workflow-designer.state.mjs +38 -1
- package/fesm2022/verben-workflow-ui-src-lib-components-workflow-designer.mjs +121 -5
- package/fesm2022/verben-workflow-ui-src-lib-components-workflow-designer.mjs.map +1 -1
- package/package.json +55 -55
- package/src/lib/components/workflow-designer/swimlane-dialog/swimlane-dialog.component.d.ts +4 -1
- package/src/lib/components/workflow-designer/workflow-data.service.d.ts +2 -1
- package/src/lib/components/workflow-designer/workflow-designer.component.d.ts +2 -0
- package/src/lib/components/workflow-designer/workflow-designer.state.d.ts +16 -0
|
@@ -365,6 +365,43 @@ class WorkflowDesignerState {
|
|
|
365
365
|
const sourceNodeType = sourceNodeInfo.node.type;
|
|
366
366
|
return this.connectionRules[sourceNodeType] || [];
|
|
367
367
|
}
|
|
368
|
+
/**
|
|
369
|
+
* Deletes a swimlane. Only succeeds when the lane has no nodes — stages must
|
|
370
|
+
* be moved to another lane first. Returns false when the lane still has nodes
|
|
371
|
+
* or the index is out of range.
|
|
372
|
+
*
|
|
373
|
+
* Keeps everything aligned after removal:
|
|
374
|
+
* - Re-sequences `order` on the remaining lanes (immutable reassignment so
|
|
375
|
+
* Angular's @for blocks re-render).
|
|
376
|
+
* - Decrements the swimlane indices stored on connections whose endpoints
|
|
377
|
+
* live below the removed lane, since those lanes shift up by one.
|
|
378
|
+
*
|
|
379
|
+
* The lane's original record is left in `swimlaneRecord`, so a previously
|
|
380
|
+
* loaded lane is emitted with `ObjectState.Removed` by
|
|
381
|
+
* `transformToWorkflowModel`; a never-saved lane simply disappears.
|
|
382
|
+
*/
|
|
383
|
+
deleteSwimlane(index) {
|
|
384
|
+
if (index < 0 || index >= this.swimlanes.length) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
if (this.swimlanes[index].nodes?.length) {
|
|
388
|
+
console.warn('Cannot delete a swimlane that still has stages; move them out first.');
|
|
389
|
+
return false;
|
|
390
|
+
}
|
|
391
|
+
this.swimlanes = this.swimlanes
|
|
392
|
+
.filter((_, i) => i !== index)
|
|
393
|
+
.map((lane, i) => ({ ...lane, order: i }));
|
|
394
|
+
this.connections = this.connections.map((conn) => ({
|
|
395
|
+
...conn,
|
|
396
|
+
sourceSwimlaneIndex: conn.sourceSwimlaneIndex > index
|
|
397
|
+
? conn.sourceSwimlaneIndex - 1
|
|
398
|
+
: conn.sourceSwimlaneIndex,
|
|
399
|
+
targetSwimlaneIndex: conn.targetSwimlaneIndex > index
|
|
400
|
+
? conn.targetSwimlaneIndex - 1
|
|
401
|
+
: conn.targetSwimlaneIndex,
|
|
402
|
+
}));
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
368
405
|
updateSwimlane(index, name, tags) {
|
|
369
406
|
console.log('State: Updating swimlane at index', index, 'with name', name, 'and tags', tags);
|
|
370
407
|
if (index >= 0 && index < this.swimlanes.length) {
|
|
@@ -770,6 +807,10 @@ class WorkflowDataService {
|
|
|
770
807
|
const url = `DeleteWorkflowAction`;
|
|
771
808
|
return this.httpService.post(url, requests, this.envSvc.environment.WorkFlowAPI);
|
|
772
809
|
}
|
|
810
|
+
deleteSwimLanes(requests) {
|
|
811
|
+
const url = `DeleteSwimLane`;
|
|
812
|
+
return this.httpService.post(url, requests, this.envSvc.environment.WorkFlowAPI);
|
|
813
|
+
}
|
|
773
814
|
saveEscalations(requests) {
|
|
774
815
|
const url = `SaveEscalations`;
|
|
775
816
|
// console.log('Saving workflows', requests);
|
|
@@ -2531,7 +2572,14 @@ class DesignerCanvasComponent {
|
|
|
2531
2572
|
const nodeInfo = this.state.findNodeById(stageId);
|
|
2532
2573
|
if (nodeInfo) {
|
|
2533
2574
|
this.activeStageId = stageId;
|
|
2534
|
-
|
|
2575
|
+
// Seed the entry-point toggle from the node's actual start state, which is
|
|
2576
|
+
// the source of truth for the start circle and API serialization. The
|
|
2577
|
+
// auto-assigned entry node has isStartNode=true without stageData.IsEntryPoint.
|
|
2578
|
+
this.activeStageData = {
|
|
2579
|
+
...nodeInfo.node.stageData,
|
|
2580
|
+
IsEntryPoint: nodeInfo.node.isStartNode,
|
|
2581
|
+
id: stageId,
|
|
2582
|
+
};
|
|
2535
2583
|
console.log(this.activeStageData, "ACTIVE STAGE DATA");
|
|
2536
2584
|
this.showStageDialogLocal = true;
|
|
2537
2585
|
}
|
|
@@ -2599,6 +2647,23 @@ class DesignerCanvasComponent {
|
|
|
2599
2647
|
...stageData,
|
|
2600
2648
|
};
|
|
2601
2649
|
console.log('Updated stage data:', nodeInfo.node.stageData);
|
|
2650
|
+
// Sync the entry-point flag onto node.isStartNode, which drives both the
|
|
2651
|
+
// start circle and the IsEntryPoint value serialized to the API.
|
|
2652
|
+
if (stageData.IsEntryPoint) {
|
|
2653
|
+
// Enforce a single entry point: this node becomes the sole start node.
|
|
2654
|
+
this.state.swimlanes.forEach((swimlane) => {
|
|
2655
|
+
swimlane.nodes?.forEach((node) => {
|
|
2656
|
+
node.isStartNode = node.id === this.activeStageId;
|
|
2657
|
+
});
|
|
2658
|
+
});
|
|
2659
|
+
this.state.startNodeId = this.activeStageId;
|
|
2660
|
+
}
|
|
2661
|
+
else {
|
|
2662
|
+
nodeInfo.node.isStartNode = false;
|
|
2663
|
+
if (this.state.startNodeId === this.activeStageId) {
|
|
2664
|
+
this.state.startNodeId = null;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2602
2667
|
// Emit event for parent component to know about the update
|
|
2603
2668
|
this.stagePropertiesUpdated.emit({
|
|
2604
2669
|
nodeId: this.activeStageId,
|
|
@@ -3622,9 +3687,11 @@ class SwimlaneDialogComponent {
|
|
|
3622
3687
|
dataService;
|
|
3623
3688
|
swimlaneService;
|
|
3624
3689
|
visible = false;
|
|
3690
|
+
isEditing = false;
|
|
3625
3691
|
swimlaneData = input(null);
|
|
3626
3692
|
closed = new EventEmitter();
|
|
3627
3693
|
created = new EventEmitter();
|
|
3694
|
+
deleted = new EventEmitter();
|
|
3628
3695
|
searchQuery = '';
|
|
3629
3696
|
workflowName = '';
|
|
3630
3697
|
// Track selected tags in a separate array
|
|
@@ -3692,6 +3759,9 @@ class SwimlaneDialogComponent {
|
|
|
3692
3759
|
this.selectedTagNames.push(tagName);
|
|
3693
3760
|
}
|
|
3694
3761
|
}
|
|
3762
|
+
onDeleteSwimlane() {
|
|
3763
|
+
this.deleted.emit();
|
|
3764
|
+
}
|
|
3695
3765
|
onDialogClose(eventData) {
|
|
3696
3766
|
console.log('Dialog closed, received data:', eventData);
|
|
3697
3767
|
this.searchQuery = '';
|
|
@@ -3719,17 +3789,21 @@ class SwimlaneDialogComponent {
|
|
|
3719
3789
|
this.searchQuery = '';
|
|
3720
3790
|
}
|
|
3721
3791
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SwimlaneDialogComponent, deps: [{ token: i1$1.FormBuilder }, { token: WorkflowDataService }, { token: SwimlaneService }], target: i0.ɵɵFactoryTarget.Component });
|
|
3722
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: SwimlaneDialogComponent, selector: "lib-swimlane-dialog", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: false, isRequired: false, transformFunction: null }, swimlaneData: { classPropertyName: "swimlaneData", publicName: "swimlaneData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", created: "created" }, ngImport: i0, template: "<verben-dialogue\n [showCloseIcon]=\"true\"\n [dismissOutsideClick]=\"true\"\n [closeOnEscape]=\"true\"\n [size]=\"'medium'\"\n [mode]=\"'drawer'\"\n [disableFooter]=\"false\"\n [isVisible]=\"visible\"\n [headerTemplate]=\"headerTemplate\"\n [bodyTemplate]=\"bodyTemplate\"\n [footerTemplate]=\"footerTemplate\"\n (openModal)=\"onDialogOpen($event)\"\n (closeModal)=\"onDialogClose($event)\"\n>\n</verben-dialogue>\n\n<ng-template #headerTemplate>\n <div\n class=\"flex items-center justify-between p-3 text-xs border-b-4 border-[#FFE681]\"\n >\n <button class=\"mr-4\" type=\"button\" (click)=\"onDialogClose($event)\">\n <span\n class=\"block w-2.5 h-2.5 border-t border-l border-[#3E3E3E]/70 transform -rotate-45\"\n ></span>\n </button>\n <div class=\"text-center\">\n <h2 class=\"text-sm font-medium\">Select Tags</h2>\n <span class=\"text-xs text-[#3E3E3E]/70\"\n >{{ this.selectedTags.length }}/{{ tags.length }}</span\n >\n </div>\n <span\n class=\"font-medium cursor-pointer text-[#3E3E3E]/70\"\n (click)=\"applySelection()\"\n >Create</span\n >\n </div>\n</ng-template>\n\n<ng-template #bodyTemplate>\n <div class=\"p-3\">\n <div class=\"mb-4 grid gap-4\">\n <!-- <input\n type=\"text\"\n placeholder=\"Enter Name\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"workflowName\"\n />\n\n <input\n type=\"search\"\n placeholder=\"Filter Tags\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"searchQuery\"\n />\n </div>\n\n <div class=\"\">\n <div class=\"py-3\">\n <label class=\"flex items-center\">\n <input type=\"checkbox\" class=\"mr-3\" [(ngModel)]=\"allSelected\" />\n <span class=\"text-sm\">Select All</span>\n </label>\n </div>\n\n <div *ngFor=\"let tag of filteredTags\" class=\"py-3\">\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n class=\"mr-3\"\n [checked]=\"isTagSelected(tag.Name)\"\n (change)=\"toggleTagSelection(tag.Name)\"\n />\n <span class=\"text-sm\">{{ tag.Name }}</span>\n <span *ngIf=\"!tag.IsOptional\" class=\"ml-2 text-xs text-red-500\"\n >(Required)</span\n >\n </label>\n </div> -->\n\n <verbena-input\n [(ngModel)]=\"workflowName\"\n [border]=\"'1px solid #9A9FBF66'\"\n placeHolder=\"Enter Swimlane Label\"\n [bgColor]=\"'white'\"\n ></verbena-input>\n\n <verben-drop-down\n selectKey=\"Code\"\n label=\"Tags\"\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"true\"\n placeholder=\"Select\"\n [options]=\"tags\"\n optionLabel=\"Name\"\n id=\"tags\"\n [(ngModel)]=\"selectedTags\"\n class=\"form-control\"\n [filter]=\"true\"\n [filterBy]=\"'Name'\"\n [showClear]=\"true\"\n >\n </verben-drop-down>\n </div>\n </div>\n</ng-template>\n\n<ng-template #footerTemplate>\n <div\n class=\"flex justify-between w-full items-center p-4 border-t border-gray-200\"\n >\n <!-- <button\n class=\"px-4 py-2 mr-2 bg-white border border-gray-200 rounded text-sm font-medium\"\n (click)=\"onDialogClose($event)\"\n >\n Cancel\n </button> -->\n\n <verbena-button\n (click)=\"onDialogClose($event)\"\n text=\"Cancel\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n\n <verbena-button\n type=\"submit\"\n text=\"Save\"\n bgColor=\"#FFE681\"\n textColor=\"#404040\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n width=\"114px\"\n height=\"39px\"\n [disable]=\"selectedTags.length < 1\"\n (click)=\"applySelection()\"\n ></verbena-button>\n\n
|
|
3792
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: SwimlaneDialogComponent, selector: "lib-swimlane-dialog", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: false, isRequired: false, transformFunction: null }, isEditing: { classPropertyName: "isEditing", publicName: "isEditing", isSignal: false, isRequired: false, transformFunction: null }, swimlaneData: { classPropertyName: "swimlaneData", publicName: "swimlaneData", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { closed: "closed", created: "created", deleted: "deleted" }, ngImport: i0, template: "<verben-dialogue\n [showCloseIcon]=\"true\"\n [dismissOutsideClick]=\"true\"\n [closeOnEscape]=\"true\"\n [size]=\"'medium'\"\n [mode]=\"'drawer'\"\n [disableFooter]=\"false\"\n [isVisible]=\"visible\"\n [headerTemplate]=\"headerTemplate\"\n [bodyTemplate]=\"bodyTemplate\"\n [footerTemplate]=\"footerTemplate\"\n (openModal)=\"onDialogOpen($event)\"\n (closeModal)=\"onDialogClose($event)\"\n>\n</verben-dialogue>\n\n<ng-template #headerTemplate>\n <div\n class=\"flex items-center justify-between p-3 text-xs border-b-4 border-[#FFE681]\"\n >\n <button class=\"mr-4\" type=\"button\" (click)=\"onDialogClose($event)\">\n <span\n class=\"block w-2.5 h-2.5 border-t border-l border-[#3E3E3E]/70 transform -rotate-45\"\n ></span>\n </button>\n <div class=\"text-center\">\n <h2 class=\"text-sm font-medium\">Select Tags</h2>\n <span class=\"text-xs text-[#3E3E3E]/70\"\n >{{ this.selectedTags.length }}/{{ tags.length }}</span\n >\n </div>\n <span\n class=\"font-medium cursor-pointer text-[#3E3E3E]/70\"\n (click)=\"applySelection()\"\n >Create</span\n >\n </div>\n</ng-template>\n\n<ng-template #bodyTemplate>\n <div class=\"p-3\">\n <div class=\"mb-4 grid gap-4\">\n <!-- <input\n type=\"text\"\n placeholder=\"Enter Name\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"workflowName\"\n />\n\n <input\n type=\"search\"\n placeholder=\"Filter Tags\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"searchQuery\"\n />\n </div>\n\n <div class=\"\">\n <div class=\"py-3\">\n <label class=\"flex items-center\">\n <input type=\"checkbox\" class=\"mr-3\" [(ngModel)]=\"allSelected\" />\n <span class=\"text-sm\">Select All</span>\n </label>\n </div>\n\n <div *ngFor=\"let tag of filteredTags\" class=\"py-3\">\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n class=\"mr-3\"\n [checked]=\"isTagSelected(tag.Name)\"\n (change)=\"toggleTagSelection(tag.Name)\"\n />\n <span class=\"text-sm\">{{ tag.Name }}</span>\n <span *ngIf=\"!tag.IsOptional\" class=\"ml-2 text-xs text-red-500\"\n >(Required)</span\n >\n </label>\n </div> -->\n\n <verbena-input\n [(ngModel)]=\"workflowName\"\n [border]=\"'1px solid #9A9FBF66'\"\n placeHolder=\"Enter Swimlane Label\"\n [bgColor]=\"'white'\"\n ></verbena-input>\n\n <verben-drop-down\n selectKey=\"Code\"\n label=\"Tags\"\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"true\"\n placeholder=\"Select\"\n [options]=\"tags\"\n optionLabel=\"Name\"\n id=\"tags\"\n [(ngModel)]=\"selectedTags\"\n class=\"form-control\"\n [filter]=\"true\"\n [filterBy]=\"'Name'\"\n [showClear]=\"true\"\n >\n </verben-drop-down>\n </div>\n </div>\n</ng-template>\n\n<ng-template #footerTemplate>\n <div\n class=\"flex justify-between w-full items-center p-4 border-t border-gray-200\"\n >\n <!-- <button\n class=\"px-4 py-2 mr-2 bg-white border border-gray-200 rounded text-sm font-medium\"\n (click)=\"onDialogClose($event)\"\n >\n Cancel\n </button> -->\n\n <verbena-button\n (click)=\"onDialogClose($event)\"\n text=\"Cancel\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n\n <verbena-button\n type=\"submit\"\n text=\"Save\"\n bgColor=\"#FFE681\"\n textColor=\"#404040\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n width=\"114px\"\n height=\"39px\"\n [disable]=\"selectedTags.length < 1\"\n (click)=\"applySelection()\"\n ></verbena-button>\n\n <verbena-button\n *ngIf=\"isEditing\"\n width=\"114px\"\n height=\"39px\"\n text=\"Delete\"\n bgColor=\"#999999\"\n textColor=\"#404040\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n (click)=\"onDeleteSwimlane()\"\n ></verbena-button>\n </div>\n</ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i5.VerbenDialogueComponent, selector: "verben-dialogue", inputs: ["dialogueWidth", "headerTemplate", "bodyTemplate", "footerTemplate", "showCloseIcon", "dismissOutsideClick", "closeOnEscape", "isVisible", "size", "backdropColor", "customClass", "disableFooter", "margin", "padding", "borderRadius", "dialogueBgColor", "width", "closeIconClass", "boxShadow", "enableTransition", "modalData", "mode", "position", "drawerWidth"], outputs: ["openModal", "closeModal"] }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i5.VerbenaButtonComponent, selector: "verbena-button", inputs: ["text", "icon", "useIcon", "svgPosition", "iconPosition", "bgColor", "textColor", "border", "borderRadius", "pd", "width", "height", "fontSize", "fontWeight", "disable", "svgSize", "weight", "variant", "styleType", "svg", "svgWidth", "svgHeight", "iconColor", "svgColor", "buttonClass", "buttonTextClass", "isLoading", "spinnerSize", "spinnerColor"] }, { kind: "component", type: i5.DropDownComponent, selector: "verben-drop-down", inputs: ["options", "width", "showHorizontalLine", "horizontalLineColor", "optionLabel", "optionSubLabel", "optionValue", "placeholder", "invalidMessage", "errorPosition", "loadMoreCaption", "display", "showClear", "lazyLoad", "selectKey", "styleClass", "group", "multiselect", "filter", "avoidDuplication", "filterBy", "debounceTime", "minChar", "disabled", "required", "load", "asyncLabel", "search"], outputs: ["optionsChange", "onChange", "onClick", "onClear"] }, { kind: "component", type: i5.VerbenaInputComponent, selector: "verbena-input", inputs: ["label", "placeHolder", "required", "svgPosition", "minLength", "maxLength", "type", "bgColor", "border", "borderRadius", "textColor", "value", "labelPosition", "labelColor", "disable", "readOnly", "min", "max", "showBorder", "showErrorMessage", "errorMessageColor", "errorBorderColor", "errorPosition", "svg", "fontSize", "svgWidth", "svgHeight", "svgColor", "capitalization", "inputContainerClass", "inputFieldClass", "passLength", "inputWrapperClass", "passwordToggle", "customErrorMessages", "icon", "textPass"], outputs: ["valueChange"] }] });
|
|
3723
3793
|
}
|
|
3724
3794
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SwimlaneDialogComponent, decorators: [{
|
|
3725
3795
|
type: Component,
|
|
3726
|
-
args: [{ selector: 'lib-swimlane-dialog', template: "<verben-dialogue\n [showCloseIcon]=\"true\"\n [dismissOutsideClick]=\"true\"\n [closeOnEscape]=\"true\"\n [size]=\"'medium'\"\n [mode]=\"'drawer'\"\n [disableFooter]=\"false\"\n [isVisible]=\"visible\"\n [headerTemplate]=\"headerTemplate\"\n [bodyTemplate]=\"bodyTemplate\"\n [footerTemplate]=\"footerTemplate\"\n (openModal)=\"onDialogOpen($event)\"\n (closeModal)=\"onDialogClose($event)\"\n>\n</verben-dialogue>\n\n<ng-template #headerTemplate>\n <div\n class=\"flex items-center justify-between p-3 text-xs border-b-4 border-[#FFE681]\"\n >\n <button class=\"mr-4\" type=\"button\" (click)=\"onDialogClose($event)\">\n <span\n class=\"block w-2.5 h-2.5 border-t border-l border-[#3E3E3E]/70 transform -rotate-45\"\n ></span>\n </button>\n <div class=\"text-center\">\n <h2 class=\"text-sm font-medium\">Select Tags</h2>\n <span class=\"text-xs text-[#3E3E3E]/70\"\n >{{ this.selectedTags.length }}/{{ tags.length }}</span\n >\n </div>\n <span\n class=\"font-medium cursor-pointer text-[#3E3E3E]/70\"\n (click)=\"applySelection()\"\n >Create</span\n >\n </div>\n</ng-template>\n\n<ng-template #bodyTemplate>\n <div class=\"p-3\">\n <div class=\"mb-4 grid gap-4\">\n <!-- <input\n type=\"text\"\n placeholder=\"Enter Name\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"workflowName\"\n />\n\n <input\n type=\"search\"\n placeholder=\"Filter Tags\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"searchQuery\"\n />\n </div>\n\n <div class=\"\">\n <div class=\"py-3\">\n <label class=\"flex items-center\">\n <input type=\"checkbox\" class=\"mr-3\" [(ngModel)]=\"allSelected\" />\n <span class=\"text-sm\">Select All</span>\n </label>\n </div>\n\n <div *ngFor=\"let tag of filteredTags\" class=\"py-3\">\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n class=\"mr-3\"\n [checked]=\"isTagSelected(tag.Name)\"\n (change)=\"toggleTagSelection(tag.Name)\"\n />\n <span class=\"text-sm\">{{ tag.Name }}</span>\n <span *ngIf=\"!tag.IsOptional\" class=\"ml-2 text-xs text-red-500\"\n >(Required)</span\n >\n </label>\n </div> -->\n\n <verbena-input\n [(ngModel)]=\"workflowName\"\n [border]=\"'1px solid #9A9FBF66'\"\n placeHolder=\"Enter Swimlane Label\"\n [bgColor]=\"'white'\"\n ></verbena-input>\n\n <verben-drop-down\n selectKey=\"Code\"\n label=\"Tags\"\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"true\"\n placeholder=\"Select\"\n [options]=\"tags\"\n optionLabel=\"Name\"\n id=\"tags\"\n [(ngModel)]=\"selectedTags\"\n class=\"form-control\"\n [filter]=\"true\"\n [filterBy]=\"'Name'\"\n [showClear]=\"true\"\n >\n </verben-drop-down>\n </div>\n </div>\n</ng-template>\n\n<ng-template #footerTemplate>\n <div\n class=\"flex justify-between w-full items-center p-4 border-t border-gray-200\"\n >\n <!-- <button\n class=\"px-4 py-2 mr-2 bg-white border border-gray-200 rounded text-sm font-medium\"\n (click)=\"onDialogClose($event)\"\n >\n Cancel\n </button> -->\n\n <verbena-button\n (click)=\"onDialogClose($event)\"\n text=\"Cancel\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n\n <verbena-button\n type=\"submit\"\n text=\"Save\"\n bgColor=\"#FFE681\"\n textColor=\"#404040\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n width=\"114px\"\n height=\"39px\"\n [disable]=\"selectedTags.length < 1\"\n (click)=\"applySelection()\"\n ></verbena-button>\n\n
|
|
3796
|
+
args: [{ selector: 'lib-swimlane-dialog', template: "<verben-dialogue\n [showCloseIcon]=\"true\"\n [dismissOutsideClick]=\"true\"\n [closeOnEscape]=\"true\"\n [size]=\"'medium'\"\n [mode]=\"'drawer'\"\n [disableFooter]=\"false\"\n [isVisible]=\"visible\"\n [headerTemplate]=\"headerTemplate\"\n [bodyTemplate]=\"bodyTemplate\"\n [footerTemplate]=\"footerTemplate\"\n (openModal)=\"onDialogOpen($event)\"\n (closeModal)=\"onDialogClose($event)\"\n>\n</verben-dialogue>\n\n<ng-template #headerTemplate>\n <div\n class=\"flex items-center justify-between p-3 text-xs border-b-4 border-[#FFE681]\"\n >\n <button class=\"mr-4\" type=\"button\" (click)=\"onDialogClose($event)\">\n <span\n class=\"block w-2.5 h-2.5 border-t border-l border-[#3E3E3E]/70 transform -rotate-45\"\n ></span>\n </button>\n <div class=\"text-center\">\n <h2 class=\"text-sm font-medium\">Select Tags</h2>\n <span class=\"text-xs text-[#3E3E3E]/70\"\n >{{ this.selectedTags.length }}/{{ tags.length }}</span\n >\n </div>\n <span\n class=\"font-medium cursor-pointer text-[#3E3E3E]/70\"\n (click)=\"applySelection()\"\n >Create</span\n >\n </div>\n</ng-template>\n\n<ng-template #bodyTemplate>\n <div class=\"p-3\">\n <div class=\"mb-4 grid gap-4\">\n <!-- <input\n type=\"text\"\n placeholder=\"Enter Name\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"workflowName\"\n />\n\n <input\n type=\"search\"\n placeholder=\"Filter Tags\"\n class=\"w-full px-4 py-2 rounded-lg border border-[#E7C10B] outline-none\"\n [(ngModel)]=\"searchQuery\"\n />\n </div>\n\n <div class=\"\">\n <div class=\"py-3\">\n <label class=\"flex items-center\">\n <input type=\"checkbox\" class=\"mr-3\" [(ngModel)]=\"allSelected\" />\n <span class=\"text-sm\">Select All</span>\n </label>\n </div>\n\n <div *ngFor=\"let tag of filteredTags\" class=\"py-3\">\n <label class=\"flex items-center\">\n <input\n type=\"checkbox\"\n class=\"mr-3\"\n [checked]=\"isTagSelected(tag.Name)\"\n (change)=\"toggleTagSelection(tag.Name)\"\n />\n <span class=\"text-sm\">{{ tag.Name }}</span>\n <span *ngIf=\"!tag.IsOptional\" class=\"ml-2 text-xs text-red-500\"\n >(Required)</span\n >\n </label>\n </div> -->\n\n <verbena-input\n [(ngModel)]=\"workflowName\"\n [border]=\"'1px solid #9A9FBF66'\"\n placeHolder=\"Enter Swimlane Label\"\n [bgColor]=\"'white'\"\n ></verbena-input>\n\n <verben-drop-down\n selectKey=\"Code\"\n label=\"Tags\"\n styleClass=\"w-full\"\n width=\"100%\"\n [multiselect]=\"true\"\n placeholder=\"Select\"\n [options]=\"tags\"\n optionLabel=\"Name\"\n id=\"tags\"\n [(ngModel)]=\"selectedTags\"\n class=\"form-control\"\n [filter]=\"true\"\n [filterBy]=\"'Name'\"\n [showClear]=\"true\"\n >\n </verben-drop-down>\n </div>\n </div>\n</ng-template>\n\n<ng-template #footerTemplate>\n <div\n class=\"flex justify-between w-full items-center p-4 border-t border-gray-200\"\n >\n <!-- <button\n class=\"px-4 py-2 mr-2 bg-white border border-gray-200 rounded text-sm font-medium\"\n (click)=\"onDialogClose($event)\"\n >\n Cancel\n </button> -->\n\n <verbena-button\n (click)=\"onDialogClose($event)\"\n text=\"Cancel\"\n styleType=\"ylw-outline\"\n ></verbena-button>\n\n <verbena-button\n type=\"submit\"\n text=\"Save\"\n bgColor=\"#FFE681\"\n textColor=\"#404040\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n width=\"114px\"\n height=\"39px\"\n [disable]=\"selectedTags.length < 1\"\n (click)=\"applySelection()\"\n ></verbena-button>\n\n <verbena-button\n *ngIf=\"isEditing\"\n width=\"114px\"\n height=\"39px\"\n text=\"Delete\"\n bgColor=\"#999999\"\n textColor=\"#404040\"\n borderRadius=\"10px\"\n pd=\"10px 20px\"\n (click)=\"onDeleteSwimlane()\"\n ></verbena-button>\n </div>\n</ng-template>\n" }]
|
|
3727
3797
|
}], ctorParameters: () => [{ type: i1$1.FormBuilder }, { type: WorkflowDataService }, { type: SwimlaneService }], propDecorators: { visible: [{
|
|
3728
3798
|
type: Input
|
|
3799
|
+
}], isEditing: [{
|
|
3800
|
+
type: Input
|
|
3729
3801
|
}], closed: [{
|
|
3730
3802
|
type: Output
|
|
3731
3803
|
}], created: [{
|
|
3732
3804
|
type: Output
|
|
3805
|
+
}], deleted: [{
|
|
3806
|
+
type: Output
|
|
3733
3807
|
}] } });
|
|
3734
3808
|
|
|
3735
3809
|
class ActorTagsDialogComponent {
|
|
@@ -4131,6 +4205,48 @@ class WorkflowDesignerComponent {
|
|
|
4131
4205
|
this.showSwimlaneDialog = false;
|
|
4132
4206
|
this.editingSwimlaneIndex = null;
|
|
4133
4207
|
}
|
|
4208
|
+
onSwimlaneDialogDeleted() {
|
|
4209
|
+
if (this.editingSwimlaneIndex === null) {
|
|
4210
|
+
return;
|
|
4211
|
+
}
|
|
4212
|
+
const index = this.editingSwimlaneIndex;
|
|
4213
|
+
const swimlane = this.state.swimlanes[index];
|
|
4214
|
+
// Guard: stages must be moved out first (also enforced in state.deleteSwimlane).
|
|
4215
|
+
if (swimlane?.nodes?.length) {
|
|
4216
|
+
this.utilService.showError('Move all stages out of this swimlane before deleting it.');
|
|
4217
|
+
return;
|
|
4218
|
+
}
|
|
4219
|
+
// A loaded lane keeps its backend Code in swimlaneRecord (keyed by id/Code).
|
|
4220
|
+
const backendRecord = swimlane?.id
|
|
4221
|
+
? this.state.swimlaneRecord[swimlane.id]
|
|
4222
|
+
: undefined;
|
|
4223
|
+
if (backendRecord?.Code) {
|
|
4224
|
+
// Path A: backend-persisted lane — delete on the server first.
|
|
4225
|
+
this.dataService
|
|
4226
|
+
.deleteSwimLanes([backendRecord.Code])
|
|
4227
|
+
.then(() => {
|
|
4228
|
+
this.finishSwimlaneDelete(index);
|
|
4229
|
+
})
|
|
4230
|
+
.catch((error) => {
|
|
4231
|
+
console.error('Error deleting swimlane:', error);
|
|
4232
|
+
this.utilService.showError('Failed to delete swimlane');
|
|
4233
|
+
});
|
|
4234
|
+
}
|
|
4235
|
+
else {
|
|
4236
|
+
// Path B: never-saved lane — remove from state directly, no API call.
|
|
4237
|
+
this.finishSwimlaneDelete(index);
|
|
4238
|
+
}
|
|
4239
|
+
}
|
|
4240
|
+
finishSwimlaneDelete(index) {
|
|
4241
|
+
const deleted = this.state.deleteSwimlane(index);
|
|
4242
|
+
if (!deleted) {
|
|
4243
|
+
this.utilService.showError('Move all stages out of this swimlane before deleting it.');
|
|
4244
|
+
return;
|
|
4245
|
+
}
|
|
4246
|
+
this.showSwimlaneDialog = false;
|
|
4247
|
+
this.editingSwimlaneIndex = null;
|
|
4248
|
+
this.canvasRef?.updateCanvasSize();
|
|
4249
|
+
}
|
|
4134
4250
|
onSubflowSelected() {
|
|
4135
4251
|
// Reset the selected tool after placing a subflow node
|
|
4136
4252
|
this.selectedTool = null;
|
|
@@ -4139,11 +4255,11 @@ class WorkflowDesignerComponent {
|
|
|
4139
4255
|
this.showActorTagsDialog = true;
|
|
4140
4256
|
}
|
|
4141
4257
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WorkflowDesignerComponent, deps: [{ token: WorkflowDesignerState }, { token: WorkflowDataService }, { token: i1.UtilService }], target: i0.ɵɵFactoryTarget.Component });
|
|
4142
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: WorkflowDesignerComponent, selector: "lib-workflow-designer", inputs: { workflowCode: "workflowCode" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvasRef"], descendants: true }], ngImport: i0, template: "<div class=\"workflow-designer\">\n <div class=\"workflow-header\">\n <h1>{{ state.workflow?.Name }}</h1>\n </div>\n\n <!-- Toolbar Component -->\n <lib-designer-toolbar [selectedTool]=\"selectedTool\" [isSaving]=\"isSaving\"\n [workflowCode]=\"state.workflow?.Code || null\" (toolSelected)=\"onToolSelected($event)\"\n (saveWorkflow)=\"saveWorkflow()\" (openActorTags)=\"openActorTagsDialog()\">\n </lib-designer-toolbar>\n\n <!-- Show loading indicator if needed -->\n <div *ngIf=\"isLoading\" class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">Loading workflow...</div>\n </div>\n\n <!-- Canvas Component -->\n <lib-designer-canvas [selectedTool]=\"selectedTool\" (clickedPosition)=\"handleCanvasPositionClick($event)\"\n (subflowSelected)=\"onSubflowSelected()\" #canvasRef>\n </lib-designer-canvas>\n\n <lib-swimlane-dialog [visible]=\"showSwimlaneDialog\" [swimlaneData]=\"editingSwimlane()\"\n (created)=\"onSwimlaneDialogFilled($event)\" (closed)=\"showSwimlaneDialog = false\"></lib-swimlane-dialog>\n\n <lib-actor-tags-dialog [visible]=\"showActorTagsDialog\" [workflowCode]=\"state.workflow?.Code || null\"\n (closed)=\"showActorTagsDialog = false\"></lib-actor-tags-dialog>\n</div>\n", styles: [".workflow-designer{display:flex;flex-direction:column;height:100vh;background-color:#f8fafc}.workflow-header{padding:1rem;background-color:#fff;border-bottom:1px solid #e2e8f0;text-align:center}.workflow-header h1{font-size:1.25rem;font-weight:600;color:#334155;margin:0}.loading-overlay{position:absolute;inset:0;background-color:#ffffffb3;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:1000}.loading-spinner{border:4px solid #f3f3f3;border-top:4px solid #d8b4fe;border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite}.loading-text{margin-top:1rem;font-size:1rem;color:#7e22ce}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: DesignerToolbarComponent, selector: "lib-designer-toolbar", inputs: ["selectedTool", "isSaving", "workflowCode"], outputs: ["openActorTags", "toolSelected", "saveWorkflow"] }, { kind: "component", type: DesignerCanvasComponent, selector: "lib-designer-canvas", inputs: ["selectedTool"], outputs: ["clickedPosition", "subflowSelected", "stagePropertiesUpdated", "actionPropertiesUpdated"] }, { kind: "component", type: SwimlaneDialogComponent, selector: "lib-swimlane-dialog", inputs: ["visible", "swimlaneData"], outputs: ["closed", "created"] }, { kind: "component", type: ActorTagsDialogComponent, selector: "lib-actor-tags-dialog", inputs: ["visible", "workflowCode"], outputs: ["closed"] }] });
|
|
4258
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: WorkflowDesignerComponent, selector: "lib-workflow-designer", inputs: { workflowCode: "workflowCode" }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvasRef"], descendants: true }], ngImport: i0, template: "<div class=\"workflow-designer\">\n <div class=\"workflow-header\">\n <h1>{{ state.workflow?.Name }}</h1>\n </div>\n\n <!-- Toolbar Component -->\n <lib-designer-toolbar [selectedTool]=\"selectedTool\" [isSaving]=\"isSaving\"\n [workflowCode]=\"state.workflow?.Code || null\" (toolSelected)=\"onToolSelected($event)\"\n (saveWorkflow)=\"saveWorkflow()\" (openActorTags)=\"openActorTagsDialog()\">\n </lib-designer-toolbar>\n\n <!-- Show loading indicator if needed -->\n <div *ngIf=\"isLoading\" class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">Loading workflow...</div>\n </div>\n\n <!-- Canvas Component -->\n <lib-designer-canvas [selectedTool]=\"selectedTool\" (clickedPosition)=\"handleCanvasPositionClick($event)\"\n (subflowSelected)=\"onSubflowSelected()\" #canvasRef>\n </lib-designer-canvas>\n\n <lib-swimlane-dialog [visible]=\"showSwimlaneDialog\" [swimlaneData]=\"editingSwimlane()\"\n [isEditing]=\"editingSwimlaneIndex !== null\" (created)=\"onSwimlaneDialogFilled($event)\"\n (deleted)=\"onSwimlaneDialogDeleted()\" (closed)=\"showSwimlaneDialog = false\"></lib-swimlane-dialog>\n\n <lib-actor-tags-dialog [visible]=\"showActorTagsDialog\" [workflowCode]=\"state.workflow?.Code || null\"\n (closed)=\"showActorTagsDialog = false\"></lib-actor-tags-dialog>\n</div>\n", styles: [".workflow-designer{display:flex;flex-direction:column;height:100vh;background-color:#f8fafc}.workflow-header{padding:1rem;background-color:#fff;border-bottom:1px solid #e2e8f0;text-align:center}.workflow-header h1{font-size:1.25rem;font-weight:600;color:#334155;margin:0}.loading-overlay{position:absolute;inset:0;background-color:#ffffffb3;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:1000}.loading-spinner{border:4px solid #f3f3f3;border-top:4px solid #d8b4fe;border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite}.loading-text{margin-top:1rem;font-size:1rem;color:#7e22ce}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"], dependencies: [{ kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: DesignerToolbarComponent, selector: "lib-designer-toolbar", inputs: ["selectedTool", "isSaving", "workflowCode"], outputs: ["openActorTags", "toolSelected", "saveWorkflow"] }, { kind: "component", type: DesignerCanvasComponent, selector: "lib-designer-canvas", inputs: ["selectedTool"], outputs: ["clickedPosition", "subflowSelected", "stagePropertiesUpdated", "actionPropertiesUpdated"] }, { kind: "component", type: SwimlaneDialogComponent, selector: "lib-swimlane-dialog", inputs: ["visible", "isEditing", "swimlaneData"], outputs: ["closed", "created", "deleted"] }, { kind: "component", type: ActorTagsDialogComponent, selector: "lib-actor-tags-dialog", inputs: ["visible", "workflowCode"], outputs: ["closed"] }] });
|
|
4143
4259
|
}
|
|
4144
4260
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: WorkflowDesignerComponent, decorators: [{
|
|
4145
4261
|
type: Component,
|
|
4146
|
-
args: [{ selector: 'lib-workflow-designer', template: "<div class=\"workflow-designer\">\n <div class=\"workflow-header\">\n <h1>{{ state.workflow?.Name }}</h1>\n </div>\n\n <!-- Toolbar Component -->\n <lib-designer-toolbar [selectedTool]=\"selectedTool\" [isSaving]=\"isSaving\"\n [workflowCode]=\"state.workflow?.Code || null\" (toolSelected)=\"onToolSelected($event)\"\n (saveWorkflow)=\"saveWorkflow()\" (openActorTags)=\"openActorTagsDialog()\">\n </lib-designer-toolbar>\n\n <!-- Show loading indicator if needed -->\n <div *ngIf=\"isLoading\" class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">Loading workflow...</div>\n </div>\n\n <!-- Canvas Component -->\n <lib-designer-canvas [selectedTool]=\"selectedTool\" (clickedPosition)=\"handleCanvasPositionClick($event)\"\n (subflowSelected)=\"onSubflowSelected()\" #canvasRef>\n </lib-designer-canvas>\n\n <lib-swimlane-dialog [visible]=\"showSwimlaneDialog\" [swimlaneData]=\"editingSwimlane()\"\n (created)=\"onSwimlaneDialogFilled($event)\" (closed)=\"showSwimlaneDialog = false\"></lib-swimlane-dialog>\n\n <lib-actor-tags-dialog [visible]=\"showActorTagsDialog\" [workflowCode]=\"state.workflow?.Code || null\"\n (closed)=\"showActorTagsDialog = false\"></lib-actor-tags-dialog>\n</div>\n", styles: [".workflow-designer{display:flex;flex-direction:column;height:100vh;background-color:#f8fafc}.workflow-header{padding:1rem;background-color:#fff;border-bottom:1px solid #e2e8f0;text-align:center}.workflow-header h1{font-size:1.25rem;font-weight:600;color:#334155;margin:0}.loading-overlay{position:absolute;inset:0;background-color:#ffffffb3;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:1000}.loading-spinner{border:4px solid #f3f3f3;border-top:4px solid #d8b4fe;border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite}.loading-text{margin-top:1rem;font-size:1rem;color:#7e22ce}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
|
|
4262
|
+
args: [{ selector: 'lib-workflow-designer', template: "<div class=\"workflow-designer\">\n <div class=\"workflow-header\">\n <h1>{{ state.workflow?.Name }}</h1>\n </div>\n\n <!-- Toolbar Component -->\n <lib-designer-toolbar [selectedTool]=\"selectedTool\" [isSaving]=\"isSaving\"\n [workflowCode]=\"state.workflow?.Code || null\" (toolSelected)=\"onToolSelected($event)\"\n (saveWorkflow)=\"saveWorkflow()\" (openActorTags)=\"openActorTagsDialog()\">\n </lib-designer-toolbar>\n\n <!-- Show loading indicator if needed -->\n <div *ngIf=\"isLoading\" class=\"loading-overlay\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">Loading workflow...</div>\n </div>\n\n <!-- Canvas Component -->\n <lib-designer-canvas [selectedTool]=\"selectedTool\" (clickedPosition)=\"handleCanvasPositionClick($event)\"\n (subflowSelected)=\"onSubflowSelected()\" #canvasRef>\n </lib-designer-canvas>\n\n <lib-swimlane-dialog [visible]=\"showSwimlaneDialog\" [swimlaneData]=\"editingSwimlane()\"\n [isEditing]=\"editingSwimlaneIndex !== null\" (created)=\"onSwimlaneDialogFilled($event)\"\n (deleted)=\"onSwimlaneDialogDeleted()\" (closed)=\"showSwimlaneDialog = false\"></lib-swimlane-dialog>\n\n <lib-actor-tags-dialog [visible]=\"showActorTagsDialog\" [workflowCode]=\"state.workflow?.Code || null\"\n (closed)=\"showActorTagsDialog = false\"></lib-actor-tags-dialog>\n</div>\n", styles: [".workflow-designer{display:flex;flex-direction:column;height:100vh;background-color:#f8fafc}.workflow-header{padding:1rem;background-color:#fff;border-bottom:1px solid #e2e8f0;text-align:center}.workflow-header h1{font-size:1.25rem;font-weight:600;color:#334155;margin:0}.loading-overlay{position:absolute;inset:0;background-color:#ffffffb3;display:flex;flex-direction:column;justify-content:center;align-items:center;z-index:1000}.loading-spinner{border:4px solid #f3f3f3;border-top:4px solid #d8b4fe;border-radius:50%;width:40px;height:40px;animation:spin 1s linear infinite}.loading-text{margin-top:1rem;font-size:1rem;color:#7e22ce}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\n"] }]
|
|
4147
4263
|
}], ctorParameters: () => [{ type: WorkflowDesignerState }, { type: WorkflowDataService }, { type: i1.UtilService }], propDecorators: { canvasRef: [{
|
|
4148
4264
|
type: ViewChild,
|
|
4149
4265
|
args: ['canvasRef']
|