Skip to content

Commit

Permalink
Feature(402686):Api integration for edit and delete
Browse files Browse the repository at this point in the history
  • Loading branch information
GowthamKumarMVS committed Dec 24, 2024
1 parent 017c669 commit 2d9dd3d
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 47 deletions.
11 changes: 11 additions & 0 deletions src/app/api/workflowDesignerAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export interface WorkflowListPathsType {
readonly updateWorkflowRules: string;
readonly deleteWorkflowRules: string;
}

const apiPaths: WorkflowListPathsType = {
updateWorkflowRules: `{baseUrl}/{workflowId}/rules/{ruleId}/update`,
deleteWorkflowRules: `{baseUrl}/rules/{ruleId}/delete`,
}

export const WorkflowApiPaths: WorkflowListPathsType = apiPaths;
63 changes: 38 additions & 25 deletions src/app/components/workflow-diagram/workflow-diagram.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ComplexHierarchicalTree, ConnectionPointOrigin, ConnectorConstraints, C
HierarchicalTree, HierarchicalTreeService, HtmlModel, IClickEventArgs, IExportOptions, LayoutModel, LineDistribution, Node, NodeModel, PrintAndExport,
SelectorConstraints, SelectorModel, SnapSettingsModel, TextModel, UserHandleEventsArgs, UserHandleModel, DataSourceModel,
DataBindingService} from '@syncfusion/ej2-angular-diagrams';
import { ChatWorkflowRulesData, FieldDetails, FieldOptionDetail, FieldValidation, MessageDetails, RuleData2 } from '../../models/appModel';
import { ChatWorkflowRulesData, ChatWorkflowRulesData2, FieldDetails, FieldOptionDetail, FieldValidation, MessageDetails, RuleData2 } from '../../models/appModel';
import { RULE_DATA, RULE_DATA2, RULE_DATA3 } from '../../data/rule-data';
import { DialogModule } from '@syncfusion/ej2-angular-popups';
import { BeforeOpenCloseMenuEventArgs, DropDownButtonComponent, DropDownButtonModule, ItemModel, OpenCloseMenuEventArgs } from '@syncfusion/ej2-angular-splitbuttons';
Expand All @@ -22,14 +22,16 @@ import sampleWorkflowData from '../../data/sample-workflow-data.json'; // Adjust
import { AsyncSettingsModel, FileInfo, Uploader } from '@syncfusion/ej2-inputs';
import { WorkflowSidebarComponent } from '../workflow-sidebar/workflow-sidebar.component'; // Import child component
import { Adaptor, DataManager, WebApiAdaptor } from '@syncfusion/ej2-data';
import { WorkflowService } from '../../services/workflow.service';
import { HttpErrorResponse } from '@angular/common/http';


Diagram.Inject(HierarchicalTree, LineDistribution, PrintAndExport);

@Component({
selector: 'app-workflow-diagram',
standalone: true,
providers: [HierarchicalTreeService, DataBindingService],
providers: [HierarchicalTreeService, DataBindingService, WorkflowService],
imports: [DiagramModule, DialogModule, DropDownButtonModule, ButtonModule, CommonModule, ListViewModule, DropDownListModule, MultiSelectModule, NumericTextBoxModule, TextBoxModule, TextAreaModule, DatePickerModule, DateTimePickerModule, SwitchModule, ToolbarModule, UploaderModule, WorkflowSidebarComponent],
templateUrl: './workflow-diagram.component.html',
styleUrl: './workflow-diagram.component.scss'
Expand Down Expand Up @@ -99,7 +101,7 @@ export class WorkflowDiagramComponent implements AfterViewInit {

public dataSourceSettings!: DataSourceModel;

constructor() {
constructor(private workflowService: WorkflowService) {
}

ngOnInit() {
Expand Down Expand Up @@ -196,6 +198,7 @@ export class WorkflowDiagramComponent implements AfterViewInit {
this.diagram.selectedItems.userHandles[2].visible = false;
}
this.selectedBlockId = clickedBlock.id;
this.selectedWorkFlowId = this.workflowID;
}
}

Expand All @@ -205,31 +208,44 @@ export class WorkflowDiagramComponent implements AfterViewInit {

// Method to add a new node and connect it
public onaddNodeAndConnect([sourceNodeId, newNode]: [string, NodeModel]): void {
// Add the new node to the diagram
this.diagram.addNode(newNode);
const index = this.diagram.nodes.findIndex(node => node.id === sourceNodeId);
(this.diagram.nodes[index].data as RuleData2).successRuleId = (newNode.data as RuleData2).id;
// Create a new connector to link the new node to the source node
const newConnectorId = `connector${++this.connectorIdCounter}`;
const newConnector: ConnectorModel = {
id: newConnectorId,
sourceID: sourceNodeId,
targetID: newNode.id,
type: 'Orthogonal',
style: { strokeColor: '#6BA5D7', strokeWidth: 1 }
};
// Add the connector to the diagram
this.diagram.addConnector(newConnector);
this.diagram.doLayout();
this.diagram.setProperties({ nodes: [], connectors: [] }, true);
this.diagram.refresh();
}

// Update the Node and reload
public onUpdateNode([sourceNodeId, newNode]: [string, RuleData2]) : void {
const index = this.diagram.nodes.findIndex(node => node.id === sourceNodeId);
newNode.id = (this.diagram.nodes[index].data as RuleData2).id;
this.diagram.nodes[index].data = newNode;
this.diagram.refresh();
var workBody : ChatWorkflowRulesData2 = {
chatWorkflowEditorTypeId : newNode.chatWorkflowEditorTypeId,
fieldDetails: newNode.fieldDetails,
fieldOptionDetails : newNode.fieldOptionDetails
};
this.workflowService.updateDiagramData(newNode.chatWorkflowId, newNode.id, workBody).then((result) => {
console.log(result.message);
this.diagram.setProperties({ nodes: [], connectors: [] }, true);
this.diagram.refresh();
}).catch((e : HttpErrorResponse) => {
if(e && e.error?.Message){
console.log("Update failed");
}
});
}

// on node delete
public onDeleteNode(nodeObject) : void{
let ruleData : RuleData2 = nodeObject.data as RuleData2;
const index = this.diagram.nodes.findIndex(node => (node.data as RuleData2).successRuleId === ruleData.id);
this.workflowService.deleteDiagramData(ruleData.id).then((result) => {
console.log(result.message);
this.diagram.setProperties({ nodes: [], connectors: [] }, true);
this.diagram.refresh();
}).catch((e : HttpErrorResponse) =>{
if(e&& e.error?.Message){
console.log("Delete failed");
}
});
}
public onUserHandleMouseDown(event: UserHandleEventsArgs) {
if(event.element.name === 'addBlock') {
if(this.diagram.selectedItems.userHandles){
Expand All @@ -254,10 +270,7 @@ export class WorkflowDiagramComponent implements AfterViewInit {
this.diagram.selectedItems.userHandles[2].visible = false;
}
let nodeObject = this.diagram.getNodeObject(this.selectedBlockId);
let id = (nodeObject.data as RuleData2).id;
const index = this.diagram.nodes.findIndex(node => (node.data as RuleData2).successRuleId === id);
(this.diagram.nodes[index].data as RuleData2).successRuleId = null;
this.diagram.remove(nodeObject);
this.onDeleteNode(nodeObject);
}
}

Expand Down
23 changes: 12 additions & 11 deletions src/app/components/workflow-sidebar/workflow-sidebar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export class WorkflowSidebarComponent {
onUpdateCloseSideBarClick(): void {
this.addOrUpdateBlock(this.soureId)
this.sidebar?.hide();
this.removeSetBlockValues();
}
// Cancel the add or update
onCancelSideBarClick(): void {
Expand All @@ -100,7 +101,7 @@ export class WorkflowSidebarComponent {
// Add and Save option
addOrUpdateSaveOption(label: string, value: string, description: string | null, labelInput: HTMLInputElement, valueInput: HTMLInputElement, descriptionInput: HTMLInputElement | null): void {
const option = { label: label.trim(), value: value.trim(), description };
if(this.isEdit){
if(this.isEditButton){
this.options[this.editIndex] = option;
}
else {
Expand Down Expand Up @@ -215,7 +216,7 @@ export class WorkflowSidebarComponent {
break;
}
case (this.chatWorkflowEditorTypeEnum.MultiSelect): {
let fieldValidationInfo = this.createFieldValidationInfo(this.fieldOptionMinValue.toString(), this.fieldOptionMaxValue.toString(), null);
let fieldValidationInfo = this.createFieldValidationInfo(this.fieldOptionMinValue.toString(), this.fieldOptionMaxValue.toString(), "");
let fieldOptionInfo = this.mapOptionsToFieldOptions();
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, fieldOptionInfo, null);
Expand All @@ -235,13 +236,13 @@ export class WorkflowSidebarComponent {
case (this.chatWorkflowBlockTypeEnum.GetTextInput): {
switch (this.nodeEditType) {
case (this.chatWorkflowEditorTypeEnum.Text): {
let fieldValidationInfo = this.createFieldValidationInfo(null, this.fieldOptionMaxValue.toString(), null);
let fieldValidationInfo = this.createFieldValidationInfo("", this.fieldOptionMaxValue.toString(), "");
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
}
case (this.chatWorkflowEditorTypeEnum.TextArea): {
let fieldValidationInfo = this.createFieldValidationInfo(null, this.fieldOptionMaxValue.toString(), null);
let fieldValidationInfo = this.createFieldValidationInfo("", this.fieldOptionMaxValue.toString(), "");
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
Expand All @@ -252,7 +253,7 @@ export class WorkflowSidebarComponent {
today.getDate() + 30; // Calculate 30 days from today
const maxDate = today.toISOString().split('T')[0]; // Max date in YYYY-MM-DD format

let fieldValidationInfo = this.createFieldValidationInfo(minDate, maxDate, null);
let fieldValidationInfo = this.createFieldValidationInfo(minDate, maxDate, "");
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
Expand All @@ -262,25 +263,25 @@ export class WorkflowSidebarComponent {
const minDateTime = now.toISOString(); // Current datetime in ISO format
const maxDateTime = new Date(now.setDate(now.getDate() + 30)).toISOString(); // Max datetime, 30 days from now

let fieldValidationInfo = this.createFieldValidationInfo(minDateTime, maxDateTime, null);
let fieldValidationInfo = this.createFieldValidationInfo(minDateTime, maxDateTime, "");
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
}
case (this.chatWorkflowEditorTypeEnum.Number): {
let fieldValidationInfo = this.createFieldValidationInfo(this.fieldOptionMinValue.toString(), this.fieldOptionMaxValue.toString(), null);
let fieldValidationInfo = this.createFieldValidationInfo(this.fieldOptionMinValue.toString(), this.fieldOptionMaxValue.toString(), "");
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
}
case (this.chatWorkflowEditorTypeEnum.Decimal): {
let fieldValidationInfo = this.createFieldValidationInfo(this.fieldOptionMinValue.toString(), this.fieldOptionMaxValue.toString(), null);
let fieldValidationInfo = this.createFieldValidationInfo(this.fieldOptionMinValue.toString(), this.fieldOptionMaxValue.toString(), "");
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
}
case (this.chatWorkflowEditorTypeEnum.Regex): {
let fieldValidationInfo = this.createFieldValidationInfo(null, null, this.fieldOptionRegexValue);
let fieldValidationInfo = this.createFieldValidationInfo("", "", this.fieldOptionRegexValue);
let fieldInfo = this.createFieldInfo(fieldValidationInfo);
this.newNodeInfo = this.createNodeInfo(this.nodeEditType, this.nodeBlockType, this.selectedWorkFlowId, fieldInfo, null, null);
break;
Expand Down Expand Up @@ -319,11 +320,11 @@ export class WorkflowSidebarComponent {
return this.options.map(button => ({
label: button.label,
value: button.value,
description: button.description ?? null
description: button.description ?? ""
}));
}

public createFieldValidationInfo(minValue: string | null, maxValue: string | null, regexValue: string | null): FieldValidation {
public createFieldValidationInfo(minValue: string | "", maxValue: string | "", regexValue: string | ""): FieldValidation {
return {
min: minValue,
max: maxValue,
Expand Down
14 changes: 10 additions & 4 deletions src/app/models/appModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ export interface RuleData {
export interface FieldOptionDetail {
label: string;
value: string;
description?: string | null;
description?: string | "";
}

// Define FieldValidation interface
export interface FieldValidation {
max?: string | null;
min?: string | null;
regex?: string | null;
max?: string | "";
min?: string | "";
regex?: string | "";
}

// Define FieldDetails interface
Expand Down Expand Up @@ -94,4 +94,10 @@ export interface ChatWorkflowRulesData {
messageDetails?: MessageDetails | null;
fieldOptionDetails?: FieldOptionDetail[] | null;
parentId?: number | null;
}

export interface ChatWorkflowRulesData2 {
chatWorkflowEditorTypeId?: number | null;
fieldDetails?: FieldDetails | null;
fieldOptionDetails?: FieldOptionDetail[] | null;
}
34 changes: 34 additions & 0 deletions src/app/services/workflow.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { WorkflowApiPaths } from '../api/workflowDesignerAPI';
import { ChatWorkflowRulesData2 } from '../models/appModel';

@Injectable({
providedIn: 'root'
})
export class WorkflowService {
private baseUrl = 'https://localhost:44303/chatwidget-api/v1/workflow-designer';

constructor(private http: HttpClient) {}

httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};

updateDiagramData(workflowId :number , ruleId: number, body : ChatWorkflowRulesData2) : Promise<{ message: string }> {
const url = WorkflowApiPaths.updateWorkflowRules
.replace('{baseUrl}', this.baseUrl)
.replace('{workflowId}', workflowId.toString())
.replace('{ruleId}', ruleId.toString());

return this.http.put<{ message: string }>(url, body, this.httpOptions).toPromise();
}

deleteDiagramData(ruleId: number): Promise<{ message: string }> {
const url = WorkflowApiPaths.updateWorkflowRules
.replace('{baseUrl}', this.baseUrl)
.replace('{ruleId}', ruleId.toString());

return this.http.put<{ message: string }>(url, this.httpOptions).toPromise();
}
}
9 changes: 7 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
import { provideHttpClient } from '@angular/common/http';

bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
bootstrapApplication(AppComponent, {
...appConfig,
providers: [
provideHttpClient() // Add HttpClientModule to providers
]
}).catch((err) => console.error(err));
6 changes: 1 addition & 5 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
Expand All @@ -25,9 +24,6 @@
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
"enableI18nLegacyMessageIdFormat": false
}
}

0 comments on commit 2d9dd3d

Please sign in to comment.