2 * ============LICENSE_START=======================================================
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
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
21 import * as _ from "lodash";
22 import {Component, Inject, Input} from '@angular/core';
23 import {Component as IComponent} from 'app/models/components/component';
25 import {ISdcConfig, SdcConfigToken} from "app/ng2/config/sdc-config.config";
26 import {TranslateService} from "app/ng2/shared/translator/translate.service";
28 import {Observable} from "rxjs/Observable";
30 import {ModalComponent} from 'onap-ui-angular/dist/modals/modal.component';
31 import {ModalService} from 'app/ng2/services/modal.service';
38 WORKFLOW_ASSOCIATION_OPTIONS
41 import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service';
42 import {PluginsService} from 'app/ng2/services/plugins.service';
43 import {WorkflowServiceNg2} from 'app/ng2/services/workflow.service';
46 OperationCreatorComponent,
48 } from 'app/ng2/pages/interface-operation/operation-creator/operation-creator.component';
49 import {IModalButtonComponent, IModalConfig, SdcUiServices} from 'onap-ui-angular';
51 export class UIOperationModel extends OperationModel {
52 isCollapsed: boolean = true;
57 constructor(operation: OperationModel) {
60 if (!operation.description) {
61 this.description = '';
64 if (this.description.length > this.MAX_LENGTH) {
65 this.isEllipsis = true;
67 this.isEllipsis = false;
71 getDescriptionEllipsis(): string {
72 if (this.isCollapsed && this.description.length > this.MAX_LENGTH) {
73 return this.description.substr(0, this.MAX_LENGTH - 3) + '...';
75 return this.description;
80 this.isCollapsed = !this.isCollapsed;
84 // tslint:disable-next-line:max-classes-per-file
85 class ModalTranslation {
89 CANCEL_BUTTON: string;
91 CREATE_BUTTON: string;
92 DELETE_BUTTON: string;
95 constructor(private TranslateService: TranslateService) {
96 this.TranslateService.languageChangedObservable.subscribe(lang => {
97 this.CREATE_TITLE = this.TranslateService.translate("INTERFACE_CREATE_TITLE");
98 this.EDIT_TITLE = this.TranslateService.translate('INTERFACE_EDIT_TITLE');
99 this.DELETE_TITLE = this.TranslateService.translate("INTERFACE_DELETE_TITLE");
100 this.CANCEL_BUTTON = this.TranslateService.translate("INTERFACE_CANCEL_BUTTON");
101 this.SAVE_BUTTON = this.TranslateService.translate("INTERFACE_SAVE_BUTTON");
102 this.CREATE_BUTTON = this.TranslateService.translate("INTERFACE_CREATE_BUTTON");
103 this.DELETE_BUTTON = this.TranslateService.translate("INTERFACE_DELETE_BUTTON");
104 this.deleteText = (operationName) => this.TranslateService.translate("INTERFACE_DELETE_TEXT", {operationName});
109 // tslint:disable-next-line:max-classes-per-file
110 export class UIInterfaceModel extends InterfaceModel {
111 isCollapsed: boolean = false;
113 constructor(interf?: any) {
115 this.operations = _.map(
117 (operation) => new UIOperationModel(operation)
122 this.isCollapsed = !this.isCollapsed;
126 // tslint:disable-next-line:max-classes-per-file
128 selector: 'interface-operation',
129 templateUrl: './interface-operation.page.component.html',
130 styleUrls: ['interface-operation.page.component.less'],
131 providers: [ModalService, TranslateService]
134 export class InterfaceOperationComponent {
136 interfaces: UIInterfaceModel[];
137 modalInstance: ModalComponent;
138 openOperation: OperationModel;
139 enableWorkflowAssociation: boolean;
140 inputs: InputBEModel[];
142 interfaceTypes: { [interfaceType: string]: string[] };
143 modalTranslation: ModalTranslation;
144 workflowIsOnline: boolean;
146 capabilities: CapabilitiesGroup;
148 @Input() component: IComponent;
149 @Input() readonly: boolean;
150 @Input() enableMenuItems: Function;
151 @Input() disableMenuItems: Function;
154 @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
155 @Inject("$state") private $state: ng.ui.IStateService,
156 private TranslateService: TranslateService,
157 private PluginsService: PluginsService,
158 private ComponentServiceNg2: ComponentServiceNg2,
159 private WorkflowServiceNg2: WorkflowServiceNg2,
160 private ModalServiceNg2: ModalService,
161 private ModalServiceSdcUI: SdcUiServices.ModalService
163 this.enableWorkflowAssociation = sdcConfig.enableWorkflowAssociation;
164 this.modalTranslation = new ModalTranslation(TranslateService);
168 this.isLoading = true;
169 this.workflowIsOnline = !_.isUndefined(this.PluginsService.getPluginByStateUrl('workflowDesigner'));
171 this.ComponentServiceNg2.getInterfaceOperations(this.component),
172 this.ComponentServiceNg2.getComponentInputs(this.component),
173 this.ComponentServiceNg2.getInterfaceTypes(this.component),
174 this.ComponentServiceNg2.getCapabilitiesAndRequirements(this.component.componentType, this.component.uniqueId)
175 ).subscribe((response: any[]) => {
176 const callback = (workflows) => {
177 this.isLoading = false;
178 this.initInterfaces(response[0].interfaces);
179 this.sortInterfaces();
180 this.inputs = response[1].inputs;
181 this.interfaceTypes = response[2];
182 this.workflows = (workflows.items) ? workflows.items : workflows;
183 this.capabilities = response[3].capabilities;
185 if (this.enableWorkflowAssociation && this.workflowIsOnline) {
186 this.WorkflowServiceNg2.getWorkflows().subscribe(
189 this.workflowIsOnline = false;
199 initInterfaces(interfaces: InterfaceModel[]): void {
200 this.interfaces = _.map(interfaces, (interf) => new UIInterfaceModel(interf));
203 sortInterfaces(): void {
204 this.interfaces = _.filter(this.interfaces, (interf) => interf.operations && interf.operations.length > 0); // remove empty interfaces
205 this.interfaces.sort((a, b) => a.type.localeCompare(b.type)); // sort interfaces alphabetically
206 _.forEach(this.interfaces, (interf) => {
207 interf.operations.sort((a, b) => a.name.localeCompare(b.name)); // sort operations alphabetically
211 collapseAll(value: boolean = true): void {
212 _.forEach(this.interfaces, (interf) => {
213 interf.isCollapsed = value;
217 isAllCollapsed(): boolean {
218 return _.every(this.interfaces, (interf) => interf.isCollapsed);
221 isAllExpanded(): boolean {
222 return _.every(this.interfaces, (interf) => !interf.isCollapsed);
225 isListEmpty(): boolean {
228 (interf) => interf.operations && interf.operations.length > 0
232 getDisabled = (): boolean => {
233 return !this.modalInstance.innerModalContent.instance.checkFormValidForSubmit();
236 onEditOperation = (operation?: OperationModel): void => {
240 modalTitle: this.modalTranslation.CREATE_TITLE,
241 saveBtnText: this.modalTranslation.CREATE_BUTTON,
242 submitCallback: this.createOperation,
245 modalTitle: this.modalTranslation.EDIT_TITLE,
246 saveBtnText: this.modalTranslation.SAVE_BUTTON,
247 submitCallback: this.updateOperation,
251 const modalData = operation ? modalMap.edit : modalMap.create;
253 if (this.openOperation) {
254 if (operation ? operation.uniqueId === this.openOperation.uniqueId : !this.openOperation.uniqueId) {
255 operation = this.openOperation;
259 const cancelButton: IModalButtonComponent = {
261 text: this.modalTranslation.CANCEL_BUTTON,
266 this.openOperation = null;
270 const saveButton: IModalButtonComponent = {
272 text: modalData.saveBtnText,
277 const modalInstance = this.modalInstance.innerModalContent.instance;
279 const {operation, isUsingExistingWF, createParamLists} = modalInstance;
281 this.openOperation = {...operation};
283 if (this.enableWorkflowAssociation && !isUsingExistingWF()) {
284 operation.workflowId = null;
285 operation.workflowVersionId = null;
288 modalData.submitCallback(operation);
292 const input: OperationCreatorInput = {
293 allWorkflows: this.workflows,
294 inputOperation: operation,
295 interfaces: this.interfaces,
296 inputProperties: this.inputs,
297 enableWorkflowAssociation: this.enableWorkflowAssociation,
298 readonly: this.readonly,
299 interfaceTypes: this.interfaceTypes,
300 validityChangedCallback: this.enableOrDisableSaveButton,
301 workflowIsOnline: this.workflowIsOnline,
302 capabilities: _.filter(CapabilitiesGroup.getFlattenedCapabilities(this.capabilities), (capability: Capability) => capability.ownerId === this.component.uniqueId)
305 const modalConfig: IModalConfig = {
306 title: modalData.modalTitle,
309 buttons: [saveButton, cancelButton] as IModalButtonComponent[]
312 this.modalInstance = this.ModalServiceSdcUI.openCustomModal(modalConfig, OperationCreatorComponent, input);
315 onRemoveOperation = (event: Event, operation: OperationModel): void => {
316 event.stopPropagation();
318 const deleteButton: IModalButtonComponent = {
320 text: this.modalTranslation.DELETE_BUTTON,
325 this.ComponentServiceNg2
326 .deleteInterfaceOperation(this.component, operation)
328 const curInterf = _.find(this.interfaces, (interf) => interf.type === operation.interfaceType);
329 const index = _.findIndex(curInterf.operations, (el) => el.uniqueId === operation.uniqueId);
330 curInterf.operations.splice(index, 1);
331 if (!curInterf.operations.length) {
332 const interfIndex = _.findIndex(this.interfaces, (interf) => interf.type === operation.interfaceType);
333 this.interfaces.splice(interfIndex, 1);
339 const cancelButton: IModalButtonComponent = {
341 text: this.modalTranslation.CANCEL_BUTTON,
346 this.openOperation = null;
350 this.ModalServiceSdcUI.openWarningModal(
351 this.modalTranslation.DELETE_TITLE,
352 this.modalTranslation.deleteText(operation.name),
353 'deleteOperationModal',
354 [deleteButton, cancelButton],
358 private enableOrDisableSaveButton = (shouldEnable: boolean): void => {
359 const saveButton = this.modalInstance.getButtonById('saveButton');
360 saveButton.disabled = !shouldEnable;
363 private createOperation = (operation: OperationModel): void => {
364 this.ComponentServiceNg2.createInterfaceOperation(this.component, operation).subscribe((response: OperationModel) => {
365 this.openOperation = null;
367 let curInterf = _.find(
369 (interf) => interf.type === operation.interfaceType
373 curInterf = new UIInterfaceModel({
374 type: response.interfaceType,
375 uniqueId: response.uniqueId,
378 this.interfaces.push(curInterf);
381 const newOpModel = new UIOperationModel(response);
382 curInterf.operations.push(newOpModel);
383 this.sortInterfaces();
385 if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL && operation.artifactData) {
386 this.ComponentServiceNg2.uploadInterfaceOperationArtifact(this.component, newOpModel, operation).subscribe();
387 } else if (response.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) {
388 this.WorkflowServiceNg2.associateWorkflowArtifact(this.component, response).subscribe();
389 } else if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.NEW) {
390 this.$state.go('workspace.plugins', {path: 'workflowDesigner'});
395 private updateOperation = (operation: OperationModel): void => {
396 this.ComponentServiceNg2.updateInterfaceOperation(this.component, operation).subscribe((newOperation: OperationModel) => {
397 this.openOperation = null;
401 _.forEach(this.interfaces, (interf) => {
402 _.forEach(interf.operations, (op) => {
403 if (op.uniqueId === newOperation.uniqueId) {
405 oldOpIndex = _.findIndex(interf.operations, (el) => el.uniqueId === op.uniqueId);
409 oldInterf.operations.splice(oldOpIndex, 1);
411 const newInterf = _.find(this.interfaces, (interf) => interf.type === operation.interfaceType);
412 const newOpModel = new UIOperationModel(newOperation);
413 newInterf.operations.push(newOpModel);
414 this.sortInterfaces();
416 if (operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXTERNAL && operation.artifactData) {
417 this.ComponentServiceNg2.uploadInterfaceOperationArtifact(this.component, newOpModel, operation).subscribe();
418 } else if (newOperation.workflowId && operation.workflowAssociationType === WORKFLOW_ASSOCIATION_OPTIONS.EXISTING) {
419 this.WorkflowServiceNg2.associateWorkflowArtifact(this.component, newOperation).subscribe();