1 import { Component, Input, OnInit } from '@angular/core';
2 import { Store } from '@ngxs/store';
6 Component as TopologyTemplate,
15 import {ToscaGetFunctionType} from "app/models/tosca-get-function-type";
16 import { CompositionService } from 'app/ng2/pages/composition/composition.service';
17 import { WorkspaceService } from 'app/ng2/pages/workspace/workspace.service';
18 import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe';
19 import { ResourceNamePipe } from 'app/ng2/pipes/resource-name.pipe';
20 import { TopologyTemplateService } from 'app/ng2/services/component-services/topology-template.service';
21 import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service";
22 import { DropdownValue } from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component';
23 import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response';
24 import { TranslateService } from 'app/ng2/shared/translator/translate.service';
25 import { ModalsHandler } from 'app/utils';
26 import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
27 import {SelectedComponentType, TogglePanelLoadingAction} from "../../../common/store/graph.actions";
30 selector: 'properties-tab',
31 templateUrl: './properties-tab.component.html',
32 styleUrls: ['./properties-tab.component.less']
34 export class PropertiesTabComponent implements OnInit {
35 attributes: AttributesGroup;
36 isComponentInstanceSelected: boolean;
37 properties: PropertiesGroup;
38 groupPropertiesByInstance: boolean;
39 propertiesMessage: string;
40 metadata: ComponentMetadata;
41 objectKeys = Object.keys;
42 isUnboundedChecked: boolean;
43 isOccurrencesEnabled: boolean = false;
45 selectInputs: DropdownValue[] = [];
48 @Input() isViewOnly: boolean;
49 @Input() componentType: SelectedComponentType;
50 @Input() component: FullComponentInstance | TopologyTemplate;
51 @Input() input: {title: string};
53 constructor(private store: Store,
54 private workspaceService: WorkspaceService,
55 private compositionService: CompositionService,
56 private modalsHandler: ModalsHandler,
57 private topologyTemplateService: TopologyTemplateService,
58 private componentInstanceService: ComponentInstanceServiceNg2,
59 private modalService: SdcUiServices.ModalService,
60 private translateService: TranslateService,
61 private groupByPipe: GroupByPipe) {
65 this.metadata = this.workspaceService.metadata;
66 this.isComponentInstanceSelected = this.componentType === SelectedComponentType.COMPONENT_INSTANCE;
67 this.getComponentInstancesPropertiesAndAttributes();
70 public isPropertyOwner = (): boolean => {
71 return this.component instanceof TopologyTemplate && this.component.isResource();
74 public updateProperty = (property: PropertyModel): void => {
75 this.openEditPropertyModal(property);
78 public deleteProperty = (property: PropertyModel): void => {
80 const onOk: Function = (): void => {
81 this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
82 this.topologyTemplateService.deleteProperty(this.component.componentType, this.component.uniqueId, property.uniqueId)
83 .subscribe((response) => {
84 this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
85 this.component.properties = this.component.properties.filter((prop) => prop.uniqueId !== property.uniqueId);
86 this.initComponentProperties();
88 this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
92 const title: string = this.translateService.translate('PROPERTY_VIEW_DELETE_MODAL_TITLE');
93 const message: string = this.translateService.translate('PROPERTY_VIEW_DELETE_MODAL_TEXT', {name: property.name});
97 type: SdcUiCommon.ButtonType.info,
99 closeModal: true} as SdcUiComponents.ModalButtonComponent;
100 this.modalService.openInfoModal(title, message, 'delete-modal', [okButton]);
103 public groupNameByKey = (key: string): string => {
108 case this.metadata.uniqueId:
109 return ResourceNamePipe.getDisplayName(this.metadata.name);
112 return this.getComponentInstanceNameFromInstanceByKey(key);
116 public getComponentInstanceNameFromInstanceByKey = (key: string): string => {
117 let instanceName: string = '';
118 const componentInstance = this.compositionService.getComponentInstances().find((item) => item.uniqueId === key);
119 if (key !== undefined && componentInstance) {
121 instanceName = ResourceNamePipe.getDisplayName(componentInstance.name);
126 private getComponentInstancesPropertiesAndAttributes = () => {
127 this.topologyTemplateService.getComponentInstanceAttributesAndPropertiesAndInputs(
128 this.workspaceService.metadata.uniqueId,
129 this.workspaceService.metadata.componentType)
130 .subscribe((genericResponse: ComponentGenericResponse) => {
131 this.compositionService.componentInstancesAttributes = genericResponse.componentInstancesAttributes || new AttributesGroup();
132 this.compositionService.componentInstancesProperties = genericResponse.componentInstancesProperties;
133 this.inputs = genericResponse.inputs;
134 this.initPropertiesAndAttributes();
138 private initComponentProperties = (): void => {
139 let result: PropertiesGroup = {};
141 this.propertiesMessage = undefined;
142 this.groupPropertiesByInstance = false;
143 if (this.component instanceof FullComponentInstance) {
144 result[this.component.uniqueId] = _.orderBy(this.compositionService.componentInstancesProperties[this.component.uniqueId], ['name']);
145 if (this.component.originType === 'VF') {
146 this.groupPropertiesByInstance = true;
147 result[this.component.uniqueId] = Array.from(this.groupByPipe.transform(result[this.component.uniqueId], 'path'));
149 } else if (this.metadata.isService()) {
150 // Temporally fix to hide properties for service (UI stack when there are many properties)
151 result = this.compositionService.componentInstancesProperties;
152 this.propertiesMessage = 'Note: properties for service are disabled';
154 const componentUid = this.component.uniqueId;
155 result[componentUid] = Array<PropertyModel>();
156 const derived = Array<PropertyModel>();
157 _.forEach(this.component.properties, (property: PropertyModel) => {
158 if (componentUid === property.parentUniqueId) {
159 result[componentUid].push(property);
161 property.readonly = true;
162 derived.push(property);
165 if (derived.length) {
166 result['derived'] = derived;
168 this.objectKeys(result).forEach((key) => { result[key] = _.orderBy(result[key], ['name']); });
170 this.properties = result;
173 private initComponentAttributes = (): void => {
174 let result: AttributesGroup = {};
176 if (this.component) {
177 if (this.component instanceof FullComponentInstance) {
178 result[this.component.uniqueId] = this.compositionService.componentInstancesAttributes[this.component.uniqueId] || [];
179 } else if (this.metadata.isService()) {
180 result = this.compositionService.componentInstancesAttributes;
182 result[this.component.uniqueId] = (this.component as TopologyTemplate).attributes;
184 this.attributes = result;
185 this.objectKeys(this.attributes).forEach((key) => {
186 this.attributes[key] = _.orderBy(this.attributes[key], ['name']);
192 private initComponentOccurrences = (): void => {
193 if (this.component instanceof FullComponentInstance) {
194 if(this.component.minOccurrences != null && this.component.maxOccurrences != null){
195 this.isOccurrencesEnabled = true;
197 this.isUnboundedChecked = this.component.maxOccurrences == "UNBOUNDED" ? true: false;
199 if(!this.component.instanceCount){
200 this.component.instanceCount = "";
203 _.forEach(this.inputs, (input: InputModel) => {
204 if(input.type === "integer"){
205 this.selectInputs.push(new DropdownValue('{' + ToscaGetFunctionType.GET_INPUT.toLowerCase() + ":" + input.name + '}', input.name));
209 this.selectInputs.unshift(new DropdownValue('', 'Select Input...'));
214 * This function is checking if the component is the value owner of the current property
215 * in order to notify the edit property modal which fields to disable
217 private isPropertyValueOwner = (): boolean => {
218 return this.metadata.isService() || !!this.component;
222 * The function opens the edit property modal.
223 * It checks if the property is from the VF or from one of it's resource instances and sends the needed property list.
224 * For create property reasons an empty array is transferd
226 * @param property the wanted property to edit/create
228 private openEditPropertyModal = (property: PropertyModel): void => {
229 this.modalsHandler.newOpenEditPropertyModal(property,
230 (this.isPropertyOwner() ?
231 this.properties[property.parentUniqueId] :
232 this.properties[property.resourceInstanceUniqueId]) || [],
233 this.isPropertyValueOwner(), 'component', property.resourceInstanceUniqueId).then((updatedProperty: PropertyModel) => {
234 if (updatedProperty) {
235 const oldProp = _.find(this.properties[updatedProperty.resourceInstanceUniqueId],
236 (prop: PropertyModel) => prop.uniqueId === updatedProperty.uniqueId);
237 oldProp.value = updatedProperty.value;
242 private initPropertiesAndAttributes = (): void => {
243 this.initComponentProperties();
244 this.initComponentAttributes();
245 this.initComponentOccurrences();
248 onUnboundedChanged(component: ComponentInstance) {
249 this.isUnboundedChecked = !this.isUnboundedChecked;
250 component.maxOccurrences = this.isUnboundedChecked ? "UNBOUNDED" : "1";
253 private updateComponentInstance(component: ComponentInstance) {
254 this.store.dispatch(new TogglePanelLoadingAction({isLoading: true}));
256 this.componentInstanceService.updateComponentInstance(this.workspaceService.metadata.componentType,
257 this.workspaceService.metadata.uniqueId, component)
258 .subscribe((updatedComponentInstance: ComponentInstance) => {
259 component = new ComponentInstance(updatedComponentInstance);
260 this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).maxOccurrences = component.maxOccurrences;
261 this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).minOccurrences = component.minOccurrences;
262 this.compositionService.getComponentInstances().find((item) => item.uniqueId === component.uniqueId).instanceCount = component.instanceCount;
263 this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
265 this.store.dispatch(new TogglePanelLoadingAction({isLoading: false}));
271 private enableOccurrences = () => {
272 if(this.component instanceof FullComponentInstance){
273 if(!this.isOccurrencesEnabled){
274 this.component.minOccurrences = null;
275 this.component.maxOccurrences = null;
276 this.component.instanceCount = null;
278 this.component.minOccurrences = "1";
279 this.component.maxOccurrences = "1";
280 this.component.instanceCount = "";
285 private isOccurrencesFormValid(component: FullComponentInstance) {
287 (component.minOccurrences === null && component.maxOccurrences === null && !component.instanceCount) ||
288 (component.minOccurrences && parseInt(component.minOccurrences) >= 0 && component.maxOccurrences &&
289 (parseInt(component.maxOccurrences) >= parseInt(component.minOccurrences) || component.maxOccurrences === "UNBOUNDED"))
297 private saveOccurrences = () => {
298 if(this.component instanceof FullComponentInstance && this.isOccurrencesFormValid(this.component)) {
299 this.updateComponentInstance(this.component);