Support setting interfaces on instances
[sdc.git] / catalog-ui / src / app / ng2 / pages / interface-definition / interface-definition.page.component.ts
1 /*
2 * ============LICENSE_START=======================================================
3 * SDC
4 * ================================================================================
5 *  Copyright (C) 2022 Nordix Foundation. All rights reserved.
6 *  ================================================================================
7 *  Licensed under the Apache License, Version 2.0 (the "License");
8 *  you may not use this file except in compliance with the License.
9 *  You may obtain a copy of the License at
10 *
11 *        http://www.apache.org/licenses/LICENSE-2.0
12 *  Unless required by applicable law or agreed to in writing, software
13 *  distributed under the License is distributed on an "AS IS" BASIS,
14 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 *  See the License for the specific language governing permissions and
16 *  limitations under the License.
17 *
18 *  SPDX-License-Identifier: Apache-2.0
19 *  ============LICENSE_END=========================================================
20 */
21 import {Component, ComponentRef, Inject, Input} from '@angular/core';
22 import {Component as IComponent} from 'app/models/components/component';
23 import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service';
24 import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options";
25 import {ISdcConfig, SdcConfigToken} from "app/ng2/config/sdc-config.config";
26 import {TranslateService} from "app/ng2/shared/translator/translate.service";
27 import {IModalButtonComponent, SdcUiServices} from 'onap-ui-angular';
28 import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
29 import {ResourceType, ComponentType} from "app/utils";
30 import {ModalService} from 'app/ng2/services/modal.service';
31 import {
32     ArtifactModel,
33     ButtonModel,
34     CapabilitiesGroup,
35     InputBEModel,
36     InterfaceModel,
37     ComponentInstance,
38     ModalModel,
39     OperationModel,
40     WORKFLOW_ASSOCIATION_OPTIONS
41 } from 'app/models';
42
43 import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service';
44 import {TopologyTemplateService} from "../../services/component-services/topology-template.service";
45 import {InterfaceOperationModel} from "../../../models/interfaceOperation";
46 import {InterfaceOperationHandlerComponent} from "../composition/interface-operatons/operation-creator/interface-operation-handler.component";
47 import {DropdownValue} from "../../components/ui/form-components/dropdown/ui-element-dropdown.component";
48 import {ToscaArtifactModel} from "../../../models/toscaArtifact";
49 import {ToscaArtifactService} from "../../services/tosca-artifact.service";
50 import {InterfaceOperationComponent} from "../interface-operation/interface-operation.page.component";
51 import {Observable} from "rxjs/Observable";
52 import {PluginsService} from 'app/ng2/services/plugins.service';
53 import { InstanceFeDetails } from 'app/models/instance-fe-details';
54
55 export class UIOperationModel extends OperationModel {
56     isCollapsed: boolean = true;
57     isEllipsis: boolean;
58     MAX_LENGTH = 75;
59
60     constructor(operation: OperationModel) {
61         super(operation);
62         if (!operation.description) {
63             this.description = '';
64         }
65
66         if (this.description.length > this.MAX_LENGTH) {
67             this.isEllipsis = true;
68         } else {
69             this.isEllipsis = false;
70         }
71     }
72
73     getDescriptionEllipsis(): string {
74         if (this.isCollapsed && this.description.length > this.MAX_LENGTH) {
75             return this.description.substr(0, this.MAX_LENGTH - 3) + '...';
76         }
77         return this.description;
78     }
79
80     toggleCollapsed(e) {
81         e.stopPropagation();
82         this.isCollapsed = !this.isCollapsed;
83     }
84 }
85
86 class ModalTranslation {
87     CREATE_TITLE: string;
88     EDIT_TITLE: string;
89     DELETE_TITLE: string;
90     CANCEL_BUTTON: string;
91     SAVE_BUTTON: string;
92     CREATE_BUTTON: string;
93     DELETE_BUTTON: string;
94     deleteText: Function;
95
96     constructor(private TranslateService: TranslateService) {
97         this.TranslateService.languageChangedObservable.subscribe(lang => {
98             this.CREATE_TITLE = this.TranslateService.translate("INTERFACE_CREATE_TITLE");
99             this.EDIT_TITLE = this.TranslateService.translate('INTERFACE_EDIT_TITLE');
100             this.DELETE_TITLE = this.TranslateService.translate("INTERFACE_DELETE_TITLE");
101             this.CANCEL_BUTTON = this.TranslateService.translate("INTERFACE_CANCEL_BUTTON");
102             this.SAVE_BUTTON = this.TranslateService.translate("INTERFACE_SAVE_BUTTON");
103             this.CREATE_BUTTON = this.TranslateService.translate("INTERFACE_CREATE_BUTTON");
104             this.DELETE_BUTTON = this.TranslateService.translate("INTERFACE_DELETE_BUTTON");
105             this.deleteText = (operationName) => this.TranslateService.translate("INTERFACE_DELETE_TEXT", {operationName});
106         });
107     }
108 }
109
110 export class UIInterfaceModel extends InterfaceModel {
111     isCollapsed: boolean = false;
112
113     constructor(interf?: any) {
114         super(interf);
115         if (this.operations) {
116             this.operations = this.operations.map((operation) => new UIOperationModel(operation));
117         }
118     }
119
120     toggleCollapse() {
121         this.isCollapsed = !this.isCollapsed;
122     }
123 }
124
125 @Component({
126     selector: 'interface-definition',
127     templateUrl: './interface-definition.page.component.html',
128     styleUrls: ['interface-definition.page.component.less'],
129     providers: [ModalService, TranslateService, InterfaceOperationComponent]
130 })
131 export class InterfaceDefinitionComponent {
132
133     modalInstance: ComponentRef<ModalComponent>;
134     interfaces: UIInterfaceModel[];
135     inputs: InputBEModel[];
136
137     instancesNavigationData = [];
138     instances: any = [];
139     loadingInstances: boolean = false;
140     selectedInstanceData: any = null;
141     hierarchyInstancesDisplayOptions: HierarchyDisplayOptions = new HierarchyDisplayOptions('uniqueId', 'name', 'archived', null, 'iconClass');
142     disableFlag : boolean = true;
143
144     deploymentArtifactsFilePath: Array<DropdownValue> = [];
145
146     toscaArtifactTypes: Array<DropdownValue> = [];
147     interfaceTypesTest: Array<DropdownValue> = [];
148     interfaceTypesMap: Map<string, string[]>;
149
150     isLoading: boolean;
151     interfaceTypes: { [interfaceType: string]: string[] };
152     modalTranslation: ModalTranslation;
153     workflows: any[];
154     capabilities: CapabilitiesGroup;
155
156     openOperation: OperationModel;
157     enableWorkflowAssociation: boolean;
158     workflowIsOnline: boolean;
159     validImplementationProps: boolean = true;
160     validMilestoneActivities: boolean = true;
161     validMilestoneFilters: boolean = true;
162     serviceInterfaces: InterfaceModel[];
163
164     @Input() component: IComponent;
165     @Input() readonly: boolean;
166     @Input() enableMenuItems: Function;
167     @Input() disableMenuItems: Function;
168
169     constructor(
170         @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
171         @Inject("$state") private $state: ng.ui.IStateService,
172         @Inject("Notification") private notification: any,
173         private translateService: TranslateService,
174         private componentServiceNg2: ComponentServiceNg2,
175         private modalServiceNg2: ModalService,
176         private modalServiceSdcUI: SdcUiServices.ModalService,
177         private topologyTemplateService: TopologyTemplateService,
178         private toscaArtifactService: ToscaArtifactService,
179         private ComponentServiceNg2: ComponentServiceNg2,
180         private WorkflowServiceNg2: WorkflowServiceNg2,
181         private ModalServiceSdcUI: SdcUiServices.ModalService,
182         private PluginsService: PluginsService
183     ) {
184         this.modalTranslation = new ModalTranslation(translateService);
185         this.interfaceTypesMap = new Map<string, string[]>();
186     }
187
188     ngOnInit(): void {
189         this.isLoading = true;
190         this.interfaces = [];
191         this.workflowIsOnline = !_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner'));
192         Observable.forkJoin(
193             this.ComponentServiceNg2.getInterfaceOperations(this.component),
194             this.ComponentServiceNg2.getComponentInputs(this.component),
195             this.ComponentServiceNg2.getInterfaceTypes(this.component),
196             this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.component.componentType, this.component.uniqueId),
197             this.componentServiceNg2.getComponentResourcePropertiesData(this.component)
198         ).subscribe((response: any[]) => {
199             const callback = (workflows) => {
200                 this.isLoading = false;
201                 this.serviceInterfaces = response[0].interfaces;
202                 this.initInterfaces(response[0].interfaces);
203                 this.sortInterfaces();
204                 this.inputs = response[1].inputs;
205                 this.interfaceTypes = response[2];
206                 this.workflows = (workflows.items) ? workflows.items : workflows;
207                 this.capabilities = response[3].capabilities;
208                 this.instances = response[4].componentInstances;
209                 const serviceInstance = new ComponentInstance();
210                 serviceInstance.name = "SELF";
211                 serviceInstance.uniqueId = this.component.uniqueId;
212                 if (this.instances != null) {
213                     this.instances.unshift(serviceInstance);
214                 } else {
215                     this.instances = [serviceInstance];
216                 }
217                 _.forEach(this.instances, (instance) => {
218                     this.instancesNavigationData.push(instance);
219                 });
220                 this.onInstanceSelectedUpdate(this.instancesNavigationData[0]);
221                 this.loadingInstances = false;
222
223             };
224             if (this.enableWorkflowAssociation && this.workflowIsOnline) {
225                 this.WorkflowServiceNg2.getWorkflows().subscribe(
226                     callback,
227                     (err) => {
228                         this.workflowIsOnline = false;
229                         callback([]);
230                     }
231                 );
232             } else {
233                 callback([]);
234             }
235         });
236
237         this.loadToscaArtifacts();
238     }
239
240     onInstanceSelectedUpdate = (instance: any) => {
241         this.interfaces = [];
242         this.selectedInstanceData = instance;
243         if (instance.name != "SELF") {
244             this.disableFlag = !this.isAllowAddOperation(instance.originType);
245             if (!instance.interfaces) {
246                 return;
247             }
248             let newInterfaces : InterfaceModel[] = [];
249             if (instance.interfaces instanceof Array) {
250                 instance.interfaces.forEach(result => {
251                     let interfaceObj = new InterfaceModel();
252                     interfaceObj.type = result.type;
253                     interfaceObj.uniqueId = result.uniqueId;
254                     if (result.operations instanceof Array) {
255                         interfaceObj.operations = result.operations;
256                     } else if (!_.isEmpty(result.operations)) {
257                         interfaceObj.operations = [];
258                         Object.keys(result.operations).forEach(name => {
259                             result.operations[name].interfaceId = result.type;
260                             result.operations[name].interfaceType = result.type;
261                             interfaceObj.operations.push(result.operations[name]);
262                         });
263                     }
264                     newInterfaces.push(interfaceObj);
265                 });
266             } else {
267                 Object.keys(instance.interfaces).forEach(key => {
268                     let obj = instance.interfaces[key];
269                     let interfaceObj = new InterfaceModel();
270                     interfaceObj.type = obj.type;
271                     interfaceObj.uniqueId = obj.uniqueId;
272                     if (obj.operations instanceof Array) {
273                         interfaceObj.operations = obj.operations;
274                     } else if (!_.isEmpty(obj.operations)) {
275                         interfaceObj.operations = [];
276                         Object.keys(obj.operations).forEach(name => {
277                             obj.operations[name].interfaceId = key;
278                             obj.operations[name].interfaceType = key;
279                             interfaceObj.operations.push(obj.operations[name]);
280                         });
281                     }
282                     newInterfaces.push(interfaceObj);
283                 });
284             }
285             this.interfaces = newInterfaces.map((interf) => new UIInterfaceModel(interf));
286         } else {
287             this.disableFlag = true;
288             this.interfaces = this.serviceInterfaces.map((interf) => new UIInterfaceModel(interf));
289         }
290         this.sortInterfaces();
291     }
292
293     isAllowAddOperation(originType: string): boolean {
294         if (originType && (originType === ResourceType.VFC || originType === ResourceType.CP || originType === ResourceType.VL)){
295             return true;
296         }
297         return false;
298     }
299
300     initInterfaces(interfaces: InterfaceModel[]): void {
301         if (interfaces) {
302             this.interfaces = interfaces.map((interf) => new UIInterfaceModel(interf));
303         }
304     }
305
306     private cancelAndCloseModal = () => {
307         return this.modalServiceNg2.closeCurrentModal();
308     }
309
310     private disableSaveButton = (): boolean => {
311         let disable:boolean = true;
312         if(this.readonly) {
313             return disable;
314         }
315         const validMilestoneActivities = this.modalInstance.instance.dynamicContent.instance.validMilestoneActivities;
316         const validMilestoneFilters = this.modalInstance.instance.dynamicContent.instance.validMilestoneFilters;
317         if (!validMilestoneActivities || !validMilestoneFilters) {
318             return disable;
319         }
320
321         let selectedInterfaceOperation = this.modalInstance.instance.dynamicContent.instance.selectedInterfaceOperation;
322         let isInterfaceOperation:boolean = !(typeof selectedInterfaceOperation == 'undefined' || _.isEmpty(selectedInterfaceOperation));
323         let selectedInterfaceType = this.modalInstance.instance.dynamicContent.instance.selectedInterfaceType;
324         let isInterfaceType:boolean = !(typeof selectedInterfaceType == 'undefined' || _.isEmpty(selectedInterfaceType));
325         let bothSet: boolean = isInterfaceOperation && isInterfaceType;
326     
327         let enableAddArtifactImplementation = this.modalInstance.instance.dynamicContent.instance.enableAddArtifactImplementation;
328         if(enableAddArtifactImplementation) {
329             let validImplementationProps = this.modalInstance.instance.dynamicContent.instance.validImplementationProps;
330             let toscaArtifactTypeSelected = this.modalInstance.instance.dynamicContent.instance.toscaArtifactTypeSelected;
331             let isToscaArtifactType:boolean = !(typeof toscaArtifactTypeSelected == 'undefined' || _.isEmpty(toscaArtifactTypeSelected));
332             disable = !bothSet || !isToscaArtifactType || !validImplementationProps;
333             return disable;
334         }
335         disable = !bothSet;
336         return disable;
337     }
338
339     onSelectInterfaceOperation(interfaceModel: UIInterfaceModel, operation: InterfaceOperationModel) {
340         const isEdit = operation !== undefined;
341         const modalButtons = [];
342         if (!this.readonly) {
343             const saveButton: ButtonModel = new ButtonModel(this.modalTranslation.SAVE_BUTTON, 'blue',
344                 () => isEdit ? this.updateOperation() : this.createOperationCallback(),
345                 this.disableSaveButton
346             );
347             modalButtons.push(saveButton);
348         }
349         modalButtons.push(new ButtonModel(this.modalTranslation.CANCEL_BUTTON, 'outline white', this.cancelAndCloseModal));
350         const interfaceDataModal: ModalModel =
351             new ModalModel('l', this.modalTranslation.EDIT_TITLE, '', modalButtons, 'custom');
352         this.modalInstance = this.modalServiceNg2.createCustomModal(interfaceDataModal);
353
354         this.modalServiceNg2.addDynamicContentToModal(
355             this.modalInstance,
356             InterfaceOperationHandlerComponent,
357             {
358                 deploymentArtifactsFilePath: this.deploymentArtifactsFilePath,
359                 toscaArtifactTypes: this.toscaArtifactTypes,
360                 selectedInterface: interfaceModel ? interfaceModel : new UIInterfaceModel(),
361                 selectedInterfaceOperation: operation ? operation : new InterfaceOperationModel(),
362                 validityChangedCallback: this.disableSaveButton,
363                 isViewOnly: this.readonly,
364                 validImplementationProps: this.validImplementationProps,
365                 validMilestoneActivities: this.validMilestoneActivities,
366                 validMilestoneFilters: this.validMilestoneFilters,
367                 'isEdit': isEdit,
368                 interfaceTypesMap: this.interfaceTypesMap,
369                 modelName: this.component.model
370             }
371         );
372         this.modalInstance.instance.open();
373     }
374
375     private updateOperation = (): void => {
376         this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = true;
377         const interfaceOperationHandlerComponentInstance: InterfaceOperationHandlerComponent = this.modalInstance.instance.dynamicContent.instance;
378         const operationToUpdate = this.modalInstance.instance.dynamicContent.instance.operationToUpdate;
379         let timeout = null;
380         if (operationToUpdate.implementation && operationToUpdate.implementation.timeout != null) {
381             timeout = operationToUpdate.implementation.timeout;
382         }
383         const isArtifactChecked = interfaceOperationHandlerComponentInstance.enableAddArtifactImplementation;
384         if (!isArtifactChecked) {
385             const artifactName = interfaceOperationHandlerComponentInstance.artifactName ?
386                 interfaceOperationHandlerComponentInstance.artifactName : '';
387             operationToUpdate.implementation = new ArtifactModel({'artifactName': artifactName, 'artifactVersion': ''} as ArtifactModel);
388         }
389         if (timeout != null) {
390             operationToUpdate.implementation.timeout = timeout;
391         }
392         if (this.component.componentType === ComponentType.SERVICE) {
393             this.topologyTemplateService.updateComponentInstanceInterfaceOperation(this.component.uniqueId, this.component.componentType, this.selectedInstanceData.uniqueId, operationToUpdate)
394             .subscribe((res) => {
395                 const interf: InterfaceModel = _.find(res.interfaces, interf => interf.type === operationToUpdate.interfaceType);
396                 const newOp: OperationModel = _.find(interf.operations, op => op.name === operationToUpdate.name);
397                 let newOperation = new InterfaceOperationModel({
398                     ...newOp,
399                     interfaceType: interf.type,
400                     interfaceId: interf.uniqueId,
401                 })
402                 let oldOpIndex;
403                 let oldInterf;
404                 this.interfaces.forEach(interf => {
405                     interf.operations.forEach(op => {
406                         if (op.uniqueId === newOperation.uniqueId) {
407                             oldInterf = interf;
408                             oldOpIndex = interf.operations.findIndex((el) => el.uniqueId === op.uniqueId);
409                         }
410                     });
411                 });
412                 oldInterf.operations.splice(oldOpIndex, 1);
413                 oldInterf.operations.push(new InterfaceOperationModel(newOperation));
414             }, () => {
415                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
416             }, () => {
417                 this.sortInterfaces();
418                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
419                 this.modalServiceNg2.closeCurrentModal();
420             });
421         } else {
422             this.componentServiceNg2.updateComponentInterfaceOperation(this.component.uniqueId, operationToUpdate)
423             .subscribe((newOperation: InterfaceOperationModel) => {
424                 let oldOpIndex;
425                 let oldInterf;
426                 this.interfaces.forEach(interf => {
427                     interf.operations.forEach(op => {
428                         if (op.uniqueId === newOperation.uniqueId) {
429                             oldInterf = interf;
430                             oldOpIndex = interf.operations.findIndex((el) => el.uniqueId === op.uniqueId);
431                         }
432                     });
433                 });
434                 oldInterf.operations.splice(oldOpIndex, 1);
435                 oldInterf.operations.push(new InterfaceOperationModel(newOperation));
436             }, () => {
437                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
438             }, () => {
439                 this.sortInterfaces();
440                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
441                 this.modalServiceNg2.closeCurrentModal();
442             });
443         }
444     }
445
446     private createOperationCallback(): void {
447         this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = true;
448         const operationToUpdate = this.modalInstance.instance.dynamicContent.instance.operationToUpdate;
449         if (this.component.componentType === ComponentType.SERVICE) {
450             this.topologyTemplateService.createComponentInstanceInterfaceOperation(this.component.uniqueId, this.selectedInstanceData.uniqueId, operationToUpdate)
451             .subscribe((newOperation: InterfaceOperationModel) => {
452                 const foundInterface = this.interfaces.find(value => value.type === newOperation.interfaceType);
453                 if (foundInterface) {
454                     foundInterface.operations.push(new UIOperationModel(new OperationModel(newOperation)));
455                 } else {
456                     const uiInterfaceModel = new UIInterfaceModel();
457                     uiInterfaceModel.type = newOperation.interfaceType;
458                     uiInterfaceModel.uniqueId = newOperation.interfaceType;
459                     uiInterfaceModel.operations = [];
460                     uiInterfaceModel.operations.push(new UIOperationModel(new OperationModel(newOperation)));
461                     this.interfaces.push(uiInterfaceModel);
462                 }
463             }, () => {
464                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
465                 this.modalServiceNg2.closeCurrentModal();
466             }, () => {
467                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
468                 this.modalServiceNg2.closeCurrentModal();
469             });
470         } else {
471             this.componentServiceNg2.createComponentInterfaceOperation(this.component.uniqueId, this.component.getTypeUrl(), operationToUpdate)
472             .subscribe((newOperation: InterfaceOperationModel) => {
473                 const foundInterface = this.interfaces.find(value => value.type === newOperation.interfaceType);
474                 if (foundInterface) {
475                     foundInterface.operations.push(new UIOperationModel(new OperationModel(newOperation)));
476                 } else {
477                     const uiInterfaceModel = new UIInterfaceModel();
478                     uiInterfaceModel.type = newOperation.interfaceType;
479                     uiInterfaceModel.uniqueId = newOperation.interfaceType;
480                     uiInterfaceModel.operations = [];
481                     uiInterfaceModel.operations.push(new UIOperationModel(new OperationModel(newOperation)));
482                     this.interfaces.push(uiInterfaceModel);
483                 }
484             }, () => {
485                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
486                 this.modalServiceNg2.closeCurrentModal();
487             }, () => {
488                 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
489                 this.modalServiceNg2.closeCurrentModal();
490             });
491         }
492     }
493
494     private handleEnableAddArtifactImplementation = (newOperation: InterfaceOperationModel): InterfaceOperationModel => {
495         if (!this.isEnableAddArtifactImplementation()) {
496             newOperation.implementation.artifactType = null;
497             newOperation.implementation.artifactVersion = null;
498         }
499         return newOperation;
500     }
501
502     private isEnableAddArtifactImplementation = (): boolean => {
503         return this.modalInstance.instance.dynamicContent.enableAddArtifactImplementation;
504     }
505
506     private initInterfaceDefinition() {
507         this.isLoading = true;
508         this.interfaces = [];
509         this.topologyTemplateService.getComponentInterfaceOperations(this.component.componentType, this.component.uniqueId)
510         .subscribe((response) => {
511             if (response.interfaces) {
512                 this.interfaces = response.interfaces.map((interfaceModel) => new UIInterfaceModel(interfaceModel));
513             }
514             this.isLoading = false;
515         });
516     }
517
518     private loadToscaArtifacts() {
519         this.toscaArtifactService.getToscaArtifacts(this.component.model).subscribe(response => {
520             if (response) {
521                 let toscaArtifactsFound = <ToscaArtifactModel[]>_.values(response);
522                 toscaArtifactsFound.forEach(value => this.toscaArtifactTypes.push(new DropdownValue(value, value.type)));
523             }
524         }, error => {
525             this.notification.error({
526                 message: 'Failed to Load Tosca Artifacts:' + error,
527                 title: 'Failure'
528             });
529         });
530     }
531
532     private loadInterfaceTypes() {
533         this.componentServiceNg2.getInterfaceTypes(this.component).subscribe(response => {
534             if (response) {
535                 console.info("loadInterfaceTypes ", response);
536                 for (const interfaceType in response) {
537                     this.interfaceTypesMap.set(interfaceType, response[interfaceType]);
538                     this.interfaceTypesTest.push(new DropdownValue(interfaceType, interfaceType));
539                 }
540             }
541         }, error => {
542             this.notification.error({
543                 message: 'Failed to Load Interface Types:' + error,
544                 title: 'Failure'
545             });
546         });
547     }
548
549     collapseAll(value: boolean = true): void {
550         this.interfaces.forEach(interfaceData => {
551             interfaceData.isCollapsed = value;
552         });
553     }
554
555     isAllCollapsed(): boolean {
556         return this.interfaces.every((interfaceData) => interfaceData.isCollapsed);
557     }
558
559     isAllExpanded(): boolean {
560         return this.interfaces.every((interfaceData) => !interfaceData.isCollapsed);
561     }
562
563     isInterfaceListEmpty(): boolean {
564         return this.interfaces.length === 0;
565     }
566
567     isOperationListEmpty(): boolean {
568         return this.interfaces.filter((interfaceData) => interfaceData.operations && interfaceData.operations.length > 0).length > 0;
569     }
570
571     onRemoveOperation(operation: OperationModel): void {
572         if (this.readonly) {
573             return;
574         }
575
576         const deleteButton: IModalButtonComponent = {
577             id: 'deleteButton',
578             text: this.modalTranslation.DELETE_BUTTON,
579             type: 'primary',
580             size: 'small',
581             closeModal: true,
582             callback: () => {
583                 this.ComponentServiceNg2
584                 .deleteInterfaceOperation(this.component, operation)
585                 .subscribe(() => {
586                     const curInterf = this.interfaces.find((interf) => interf.type === operation.interfaceType);
587                     const index = curInterf.operations.findIndex((el) => el.uniqueId === operation.uniqueId);
588                     curInterf.operations.splice(index, 1);
589                     if (!curInterf.operations.length) {
590                         const interfIndex = this.interfaces.findIndex((interf) => interf.type === operation.interfaceType);
591                         this.interfaces.splice(interfIndex, 1);
592                     }
593                 });
594             }
595         };
596
597         const cancelButton: IModalButtonComponent = {
598             id: 'cancelButton',
599             text: this.modalTranslation.CANCEL_BUTTON,
600             type: 'secondary',
601             size: 'small',
602             closeModal: true,
603             callback: () => {
604                 this.openOperation = null;
605             },
606         };
607
608         this.ModalServiceSdcUI.openWarningModal(
609             this.modalTranslation.DELETE_TITLE,
610             this.modalTranslation.deleteText(operation.name),
611             'deleteOperationModal',
612             [deleteButton, cancelButton],
613         );
614     }
615
616     private createOperation = (operation: OperationModel): void => {
617         this.ComponentServiceNg2.createInterfaceOperation(this.component, operation).subscribe((response: OperationModel) => {
618             this.openOperation = null;
619
620             let curInterf = this.interfaces.find((interf) => interf.type === operation.interfaceType);
621
622             if (!curInterf) {
623                 curInterf = new UIInterfaceModel({
624                     type: response.interfaceType,
625                     uniqueId: response.uniqueId,
626                     operations: []
627                 });
628                 this.interfaces.push(curInterf);
629             }
630
631             const newOpModel = new UIOperationModel(response);
632             curInterf.operations.push(newOpModel);
633             this.sortInterfaces();
634
635             if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL && operation.artifactData) {
636                 this.ComponentServiceNg2.uploadInterfaceOperationArtifact(this.component, newOpModel, operation).subscribe();
637             } else if (response.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) {
638                 this.WorkflowServiceNg2.associateWorkflowArtifact(this.component, response).subscribe();
639             } else if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW) {
640                 this.$state.go('workspace.plugins', {path: 'workflowDesigner'});
641             }
642         });
643     }
644
645     private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
646         const saveButton = this.modalInstance.instance.dynamicContent.getButtonById('saveButton');
647         saveButton.disabled = !shouldEnable;
648     }
649
650     private sortInterfaces(): void {
651         this.interfaces = this.interfaces.filter((interf) => interf.operations && interf.operations.length > 0); // remove empty interfaces
652         this.interfaces.sort((a, b) => a.type.localeCompare(b.type)); // sort interfaces alphabetically
653         this.interfaces.forEach((interf) => {
654             interf.operations.sort((a, b) => a.name.localeCompare(b.name)); // sort operations alphabetically
655         });
656     }
657
658 }