2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2021 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=========================================================
22 import {Component, ComponentRef, Inject, Input} from '@angular/core';
24 TopologyTemplateService
25 } from '../../../services/component-services/topology-template.service';
26 import {TranslateService} from "../../../shared/translator/translate.service";
27 import {ModalService} from 'app/ng2/services/modal.service';
28 import {CompositionService} from "app/ng2/pages/composition/composition.service";
29 import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component';
30 import {Component as TopologyTemplate} from "../../../../models/components/component";
31 import {PluginsService} from "app/ng2/services/plugins.service";
32 import {SelectedComponentType} from "../common/store/graph.actions";
33 import {InstanceFeDetails} from "../../../../models/instance-fe-details";
34 import {WorkspaceService} from "../../workspace/workspace.service";
36 ComponentInterfaceDefinitionModel,
37 InterfaceOperationModel
38 } from "../../../../models/interfaceOperation";
40 InterfaceOperationHandlerComponent
41 } from "./operation-creator/interface-operation-handler.component";
52 import {ArtifactGroupType} from "../../../../utils/constants";
55 } from "../../../components/ui/form-components/dropdown/ui-element-dropdown.component";
56 import {ToscaArtifactService} from "../../../services/tosca-artifact.service";
57 import {ToscaArtifactModel} from "../../../../models/toscaArtifact";
59 export class UIInterfaceOperationModel extends InterfaceOperationModel {
60 isCollapsed: boolean = true;
64 constructor(operation: InterfaceOperationModel) {
67 if (!operation.description) {
68 this.description = '';
71 if (this.description.length > this.MAX_LENGTH) {
72 this.isEllipsis = true;
74 this.isEllipsis = false;
78 getDescriptionEllipsis(): string {
79 if (this.isCollapsed && this.description.length > this.MAX_LENGTH) {
80 return this.description.substr(0, this.MAX_LENGTH - 3) + '...';
82 return this.description;
87 this.isCollapsed = !this.isCollapsed;
91 class ModalTranslation {
93 CANCEL_BUTTON: string;
97 constructor(private translateService: TranslateService) {
98 this.translateService.languageChangedObservable.subscribe(lang => {
99 this.EDIT_TITLE = this.translateService.translate('INTERFACE_EDIT_TITLE');
100 this.CANCEL_BUTTON = this.translateService.translate("INTERFACE_CANCEL_BUTTON");
101 this.CLOSE_BUTTON = this.translateService.translate("INTERFACE_CLOSE_BUTTON");
102 this.SAVE_BUTTON = this.translateService.translate("INTERFACE_SAVE_BUTTON");
107 export class UIInterfaceModel extends ComponentInterfaceDefinitionModel {
108 isCollapsed: boolean = false;
110 constructor(interf?: any) {
112 this.operations = _.map(
114 (operation) => new UIInterfaceOperationModel(operation)
119 this.isCollapsed = !this.isCollapsed;
124 selector: 'app-interface-operations',
125 templateUrl: './interface-operations.component.html',
126 styleUrls: ['./interface-operations.component.less'],
127 providers: [ModalService, TranslateService]
129 export class InterfaceOperationsComponent {
130 interfaces: UIInterfaceModel[];
131 inputs: Array<InputBEModel>;
133 interfaceTypes: { [interfaceType: string]: string[] };
134 topologyTemplate: TopologyTemplate;
135 componentMetaData: ComponentMetadata;
136 componentInstanceSelected: ComponentInstance;
137 modalInstance: ComponentRef<ModalComponent>;
138 modalTranslation: ModalTranslation;
139 componentInstancesInterfaces: Map<string, InterfaceModel[]>;
141 deploymentArtifactsFilePath: Array<DropdownValue> = [];
142 toscaArtifactTypes: Array<DropdownValue> = [];
143 componentInstanceMap: Map<string, InstanceFeDetails> = new Map<string, InstanceFeDetails>();
144 validImplementationProps: boolean = true;
145 validMilestoneActivities: boolean = true;
146 validMilestoneFilters: boolean = true;
148 @Input() component: ComponentInstance;
149 @Input() isViewOnly: boolean;
150 @Input() enableMenuItems: Function;
151 @Input() disableMenuItems: Function;
152 @Input() componentType: SelectedComponentType;
156 private translateService: TranslateService,
157 private pluginsService: PluginsService,
158 private topologyTemplateService: TopologyTemplateService,
159 private toscaArtifactService: ToscaArtifactService,
160 private modalServiceNg2: ModalService,
161 private compositionService: CompositionService,
162 private workspaceService: WorkspaceService,
163 @Inject("Notification") private Notification: any,
165 this.modalTranslation = new ModalTranslation(translateService);
169 this.componentMetaData = this.workspaceService.metadata;
170 this.loadComponentInstances();
171 this.loadDeployedArtifacts();
172 this.loadToscaArtifacts()
175 private loadComponentInstances() {
176 this.isLoading = true;
177 this.topologyTemplateService.getComponentInstances(this.componentMetaData.componentType, this.componentMetaData.uniqueId)
178 .subscribe((response) => {
179 this.componentInstanceSelected = response.componentInstances.find(ci => ci.uniqueId === this.component.uniqueId);
180 this.initComponentInstanceInterfaceOperations();
181 this.isLoading = false;
185 private initComponentInstanceInterfaceOperations() {
186 this.initInterfaces(this.componentInstanceSelected.interfaces);
187 this.sortInterfaces();
190 private initInterfaces(interfaces: ComponentInterfaceDefinitionModel[]): void {
191 this.interfaces = _.map(interfaces, (interfaceModel) => new UIInterfaceModel(interfaceModel));
194 private sortInterfaces(): void {
195 this.interfaces = _.filter(this.interfaces, (interf) => interf.operations && interf.operations.length > 0); // remove empty interfaces
196 this.interfaces.sort((a, b) => a.type.localeCompare(b.type)); // sort interfaces alphabetically
197 _.forEach(this.interfaces, (interf) => {
198 interf.operations.sort((a, b) => a.name.localeCompare(b.name)); // sort operations alphabetically
202 collapseAll(value: boolean = true): void {
203 _.forEach(this.interfaces, (interf) => {
204 interf.isCollapsed = value;
208 isAllCollapsed(): boolean {
209 return _.every(this.interfaces, (interf) => interf.isCollapsed);
212 isAllExpanded(): boolean {
213 return _.every(this.interfaces, (interf) => !interf.isCollapsed);
216 isListEmpty(): boolean {
219 (interf) => interf.operations && interf.operations.length > 0
223 private disableSaveButton = (): boolean => {
224 let disable:boolean = true;
225 if(this.isViewOnly) {
229 const validMilestoneFilters = this.modalInstance.instance.dynamicContent.instance.validMilestoneFilters;
230 const validMilestoneActivities = this.modalInstance.instance.dynamicContent.instance.validMilestoneActivities;
231 if (!validMilestoneActivities || !validMilestoneFilters) {
234 let enableAddArtifactImplementation = this.modalInstance.instance.dynamicContent.instance.enableAddArtifactImplementation;
235 if(enableAddArtifactImplementation) {
236 const validImplementationProps = this.modalInstance.instance.dynamicContent.instance.validImplementationProps;
237 const toscaArtifactTypeSelected = this.modalInstance.instance.dynamicContent.instance.toscaArtifactTypeSelected;
238 const isToscaArtifactType:boolean = !(typeof toscaArtifactTypeSelected == 'undefined' || _.isEmpty(toscaArtifactTypeSelected));
239 disable = !isToscaArtifactType || !validImplementationProps;
246 onSelectInterfaceOperation(interfaceModel: UIInterfaceModel, operation: InterfaceOperationModel) {
248 const buttonList = [];
249 if (this.isViewOnly) {
250 const closeButton: ButtonModel = new ButtonModel(this.modalTranslation.CLOSE_BUTTON, 'outline white', this.cancelAndCloseModal);
251 buttonList.push(closeButton);
253 const saveButton: ButtonModel = new ButtonModel(this.modalTranslation.SAVE_BUTTON, 'blue', () =>
254 this.updateInterfaceOperation(), this.disableSaveButton);
255 const cancelButton: ButtonModel = new ButtonModel(this.modalTranslation.CANCEL_BUTTON, 'outline white', this.cancelAndCloseModal);
256 buttonList.push(saveButton);
257 buttonList.push(cancelButton);
259 const modalModel: ModalModel = new ModalModel('l', this.modalTranslation.EDIT_TITLE, '', buttonList, 'custom');
260 this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel);
262 const componentInstances = this.compositionService.getComponentInstances()
263 if (componentInstances) {
264 componentInstances.forEach(value => {
265 this.componentInstanceMap.set(value.uniqueId, <InstanceFeDetails>{
271 this.modalServiceNg2.addDynamicContentToModal(
273 InterfaceOperationHandlerComponent,
275 deploymentArtifactsFilePath: this.deploymentArtifactsFilePath,
276 componentInstanceMap: this.componentInstanceMap,
277 toscaArtifactTypes: this.toscaArtifactTypes,
278 selectedInterface: interfaceModel ? interfaceModel : new UIInterfaceModel(),
279 selectedInterfaceOperation: operation ? operation : new InterfaceOperationModel(),
280 validityChangedCallback: this.disableSaveButton,
281 isViewOnly: this.isViewOnly,
282 validImplementationProps: this.validImplementationProps,
283 validMilestoneActivities: this.validMilestoneActivities,
284 validMilestoneFilters: this.validMilestoneFilters,
286 modelName: this.componentMetaData.model
289 this.modalInstance.instance.open();
292 private cancelAndCloseModal = () => {
293 this.loadComponentInstances();
294 return this.modalServiceNg2.closeCurrentModal();
297 private updateInterfaceOperation() {
298 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = true;
299 const interfaceOperationHandlerComponentInstance: InterfaceOperationHandlerComponent = this.modalInstance.instance.dynamicContent.instance;
300 const operationUpdated: InterfaceOperationModel = interfaceOperationHandlerComponentInstance.operationToUpdate;
302 if (operationUpdated.implementation && operationUpdated.implementation.timeout != null) {
303 timeout = operationUpdated.implementation.timeout;
305 const isArtifactChecked = interfaceOperationHandlerComponentInstance.enableAddArtifactImplementation;
306 if (!isArtifactChecked) {
307 let artifactName = interfaceOperationHandlerComponentInstance.artifactName;
308 artifactName = artifactName === undefined ? '' : artifactName;
309 operationUpdated.implementation = new ArtifactModel({'artifactName': artifactName, 'artifactVersion': ''} as ArtifactModel);
311 if (timeout != null) {
312 operationUpdated.implementation.timeout = timeout;
314 this.topologyTemplateService.updateComponentInstanceInterfaceOperation(
315 this.componentMetaData.uniqueId,
316 this.componentMetaData.componentType,
317 this.componentInstanceSelected.uniqueId,
319 .subscribe((updatedComponentInstance: ComponentInstance) => {
320 this.componentInstanceSelected = new ComponentInstance(updatedComponentInstance);
321 this.initComponentInstanceInterfaceOperations();
322 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
323 this.modalServiceNg2.closeCurrentModal();
325 this.modalServiceNg2.currentModal.instance.dynamicContent.instance.isLoading = false;
326 this.modalServiceNg2.closeCurrentModal();
330 loadDeployedArtifacts() {
331 this.topologyTemplateService.getArtifactsByType(this.componentMetaData.componentType, this.componentMetaData.uniqueId, ArtifactGroupType.DEPLOYMENT)
332 .subscribe(response => {
333 let artifactsDeployment = response.deploymentArtifacts;
334 if (artifactsDeployment) {
335 let deploymentArtifactsFound = <ArtifactModel[]>_.values(artifactsDeployment)
336 deploymentArtifactsFound.forEach(value => {
337 this.deploymentArtifactsFilePath.push(new DropdownValue(value, value.artifactType.concat('->').concat(value.artifactName)));
341 this.Notification.error({
342 message: 'Failed to Load the Deployed Artifacts:' + error,
348 loadToscaArtifacts() {
349 this.toscaArtifactService.getToscaArtifacts(this.componentMetaData.model).subscribe(response => {
351 let toscaArtifactsFound = <ToscaArtifactModel[]>_.values(response);
352 toscaArtifactsFound.forEach(value => this.toscaArtifactTypes.push(new DropdownValue(value, value.type)));
355 this.Notification.error({
356 message: 'Failed to Load Tosca Artifacts:' + error,