From 92b18f188105d5ba4b2c469cdfaedc7d2953d593 Mon Sep 17 00:00:00 2001 From: "andre.schmid" Date: Wed, 10 Aug 2022 14:50:08 +0100 Subject: Support TOSCA functions in Node Filters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds support to use tosca functions as value in the node property filters and substitution filters Change-Id: Id242691cc9ddd233245b58f052b9f0e2c7bbd66b Issue-ID: SDC-4128 Signed-off-by: André Schmid --- .../src/app/models/capability-filter-constraint.ts | 61 ++++ catalog-ui/src/app/models/filter-constraint.ts | 17 ++ .../models/properties-inputs/property-fe-model.ts | 5 +- catalog-ui/src/app/models/tosca-concat-function.ts | 36 +++ .../src/app/models/tosca-function-parameter.ts | 1 + catalog-ui/src/app/models/tosca-function.ts | 2 + catalog-ui/src/app/models/tosca-get-function.ts | 39 ++- .../src/app/models/tosca-string-parameter.ts | 11 + .../app/models/ui-models/constraint-object-ui.ts | 26 ++ catalog-ui/src/app/models/yaml-function.ts | 9 + .../capabilities-constraint.component.ts | 61 ---- .../service-dependencies.component.html | 13 +- .../service-dependencies.component.ts | 220 ++++++--------- .../substitution-filter.component.html | 7 +- .../substitution-filter.component.ts | 142 ++++------ ...abilities-filter-properties-editor.component.ts | 12 +- .../service-dependencies-tab.component.ts | 10 +- .../substitution-filter-tab.component.ts | 35 +-- .../services/properties.utils.ts | 21 +- .../tosca-concat-function.component.ts | 29 +- .../tosca-function/tosca-function.component.html | 2 +- .../tosca-function/tosca-function.component.ts | 58 +++- .../tosca-function/tosca-function.module.ts | 4 +- .../tosca-get-function.component.ts | 1 + .../service-dependencies-editor.component.html | 79 +++--- .../service-dependencies-editor.component.less | 5 +- .../service-dependencies-editor.component.ts | 312 +++++++++------------ .../service-dependencies-editor.module.ts | 6 +- .../component-services/component.service.ts | 8 +- .../topology-template.service.ts | 22 +- .../src/app/utils/filter-constraint-helper.ts | 64 +++++ 31 files changed, 724 insertions(+), 594 deletions(-) create mode 100644 catalog-ui/src/app/models/capability-filter-constraint.ts create mode 100644 catalog-ui/src/app/models/filter-constraint.ts create mode 100644 catalog-ui/src/app/models/ui-models/constraint-object-ui.ts delete mode 100644 catalog-ui/src/app/ng2/components/logic/capabilities-constraint/capabilities-constraint.component.ts create mode 100644 catalog-ui/src/app/utils/filter-constraint-helper.ts (limited to 'catalog-ui/src/app') diff --git a/catalog-ui/src/app/models/capability-filter-constraint.ts b/catalog-ui/src/app/models/capability-filter-constraint.ts new file mode 100644 index 0000000000..64d9913a54 --- /dev/null +++ b/catalog-ui/src/app/models/capability-filter-constraint.ts @@ -0,0 +1,61 @@ +/* +* ============LICENSE_START======================================================= +* SDC +* ================================================================================ +* Copyright (C) 2020 Nordix Foundation. All rights reserved. +* ================================================================================ +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* SPDX-License-Identifier: Apache-2.0 +* ============LICENSE_END========================================================= +*/ + +export class CapabilityFilterConstraint { + capabilityName: string; + servicePropertyName: string; + constraintOperator: string; + sourceType: string; + sourceName: string; + value: string; + + constructor(input?: any) { + if (input) { + this.capabilityName = input.capabilityName; + this.servicePropertyName = input.servicePropertyName; + this.constraintOperator = input.constraintOperator; + this.sourceType = input.sourceType; + this.sourceName = input.sourceName; + this.value = input.value; + } + } +} + +export class CapabilityFilterConstraintUI extends CapabilityFilterConstraint { + isValidValue: boolean; + + constructor(input?: any) { + super(input); + if (input) { + this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== ''; + } + } + + public updateValidity(isValidValue: boolean) { + this.isValidValue = isValidValue; + } + + public isValidRule(isStatic) { + const isValidValue = isStatic ? this.isValidValue : true; + return this.servicePropertyName != null && this.servicePropertyName !== '' + && this.value != null && this.value !== '' && isValidValue; + } +} diff --git a/catalog-ui/src/app/models/filter-constraint.ts b/catalog-ui/src/app/models/filter-constraint.ts new file mode 100644 index 0000000000..a118c97d7b --- /dev/null +++ b/catalog-ui/src/app/models/filter-constraint.ts @@ -0,0 +1,17 @@ +export class FilterConstraint { + servicePropertyName: string; + constraintOperator: string; + sourceType: string; + sourceName: string; + value: any; + + constructor(input?: any) { + if (input) { + this.servicePropertyName = input.servicePropertyName; + this.constraintOperator = input.constraintOperator; + this.sourceType = input.sourceType; + this.sourceName = input.sourceName; + this.value = input.value; + } + } +} diff --git a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts index eb18c4e4f9..49baefd4e0 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts @@ -46,6 +46,9 @@ export class PropertyFEModel extends PropertyBEModel { constructor(property: PropertyBEModel){ super(property); + if (!property) { + return; + } this.value = property.value ? property.value : property.defaultValue;//In FE if a property doesn't have value - display the default value this.isSimpleType = PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type) > -1; this.setNonDeclared(); @@ -290,7 +293,7 @@ export class PropertyFEModel extends PropertyBEModel { propertyType !== PROPERTY_TYPES.TIMESTAMP && propertyType !== PROPERTY_TYPES.JSON && PROPERTY_DATA.SCALAR_TYPES.indexOf(propertyType) == -1) { - return JSON.parse(value); // the value object contains the real value ans not the value as string + return JSON.parse(valueObj); // the value object contains the real value ans not the value as string } return valueObj; } diff --git a/catalog-ui/src/app/models/tosca-concat-function.ts b/catalog-ui/src/app/models/tosca-concat-function.ts index 9656d8ddb9..74fe7f6793 100644 --- a/catalog-ui/src/app/models/tosca-concat-function.ts +++ b/catalog-ui/src/app/models/tosca-concat-function.ts @@ -22,6 +22,9 @@ import {ToscaFunction} from "./tosca-function"; import {ToscaFunctionType} from "./tosca-function-type.enum"; import {ToscaFunctionParameter} from "./tosca-function-parameter"; +import {ToscaGetFunction} from "./tosca-get-function"; +import {YamlFunction} from "./yaml-function"; +import {ToscaStringParameter} from "./tosca-string-parameter"; export class ToscaConcatFunction implements ToscaFunction, ToscaFunctionParameter { type = ToscaFunctionType.CONCAT; @@ -33,6 +36,39 @@ export class ToscaConcatFunction implements ToscaFunction, ToscaFunctionParamete return; } this.value = toscaConcatFunction.value; + if (toscaConcatFunction.parameters) { + toscaConcatFunction.parameters.forEach(parameter => { + switch (parameter.type) { + case ToscaFunctionType.GET_INPUT: + case ToscaFunctionType.GET_ATTRIBUTE: + case ToscaFunctionType.GET_PROPERTY: + this.parameters.push(new ToscaGetFunction(parameter)); + break; + case ToscaFunctionType.CONCAT: + this.parameters.push(new ToscaConcatFunction(parameter)); + break; + case ToscaFunctionType.YAML: + this.parameters.push(new YamlFunction(parameter)); + break; + case ToscaFunctionType.STRING: + this.parameters.push(new ToscaStringParameter(parameter)); + break; + default: + console.error(`Unsupported parameter type "${parameter.type}"`); + this.parameters.push(parameter); + } + }); + } + } + + public buildValueString(): string { + return JSON.stringify(this.buildValueObject()); + } + + public buildValueObject(): Object { + return { + [this.type.toLowerCase()]: this.parameters.map(parameter => parameter.buildValueObject()) + } } } \ No newline at end of file diff --git a/catalog-ui/src/app/models/tosca-function-parameter.ts b/catalog-ui/src/app/models/tosca-function-parameter.ts index 84c4f0b014..a667543f74 100644 --- a/catalog-ui/src/app/models/tosca-function-parameter.ts +++ b/catalog-ui/src/app/models/tosca-function-parameter.ts @@ -24,4 +24,5 @@ import {ToscaFunctionType} from "./tosca-function-type.enum"; export interface ToscaFunctionParameter { type: ToscaFunctionType; value: any; + buildValueObject(): Object; } \ No newline at end of file diff --git a/catalog-ui/src/app/models/tosca-function.ts b/catalog-ui/src/app/models/tosca-function.ts index ebb024ee7c..8ea2a829a8 100644 --- a/catalog-ui/src/app/models/tosca-function.ts +++ b/catalog-ui/src/app/models/tosca-function.ts @@ -24,4 +24,6 @@ import {ToscaFunctionType} from "./tosca-function-type.enum"; export interface ToscaFunction { type: ToscaFunctionType; value: any; + buildValueString(): string + buildValueObject(): Object } \ No newline at end of file diff --git a/catalog-ui/src/app/models/tosca-get-function.ts b/catalog-ui/src/app/models/tosca-get-function.ts index 2386338c98..7e6c5ad739 100644 --- a/catalog-ui/src/app/models/tosca-get-function.ts +++ b/catalog-ui/src/app/models/tosca-get-function.ts @@ -23,8 +23,9 @@ import {PropertySource} from "./property-source"; import {ToscaGetFunctionType} from "./tosca-get-function-type"; import {ToscaFunction} from "./tosca-function"; import {ToscaFunctionType} from "./tosca-function-type.enum"; +import {ToscaFunctionParameter} from "./tosca-function-parameter"; -export class ToscaGetFunction implements ToscaFunction { +export class ToscaGetFunction implements ToscaFunction, ToscaFunctionParameter { type: ToscaFunctionType; propertyUniqueId: string; propertyName: string; @@ -39,6 +40,8 @@ export class ToscaGetFunction implements ToscaFunction { if (!toscaGetFunction) { return; } + this.type = toscaGetFunction.type; + this.value = toscaGetFunction.value; this.propertyUniqueId = toscaGetFunction.propertyUniqueId; this.propertyName = toscaGetFunction.propertyName; this.propertySource = toscaGetFunction.propertySource; @@ -50,4 +53,38 @@ export class ToscaGetFunction implements ToscaFunction { } } + public buildValueString(): string { + return JSON.stringify(this.buildValueObject()); + } + + public buildValueObject(): Object { + if (this.functionType == ToscaGetFunctionType.GET_PROPERTY || this.functionType == ToscaGetFunctionType.GET_ATTRIBUTE) { + return this.buildFunctionValueWithPropertySource(); + } + if (this.functionType == ToscaGetFunctionType.GET_INPUT) { + return this.buildGetInputFunctionValue(); + } + return undefined; + } + + private buildGetInputFunctionValue(): Object { + if (this.propertyPathFromSource.length === 1) { + return {[this.functionType.toLowerCase()]: this.propertyPathFromSource[0]}; + } + return {[this.functionType.toLowerCase()]: this.propertyPathFromSource}; + } + + private buildFunctionValueWithPropertySource(): Object { + if (this.propertySource == PropertySource.SELF) { + return { + [this.functionType.toLowerCase()]: [PropertySource.SELF, ...this.propertyPathFromSource] + }; + } + if (this.propertySource == PropertySource.INSTANCE) { + return { + [this.functionType.toLowerCase()]: [this.sourceName, ...this.propertyPathFromSource] + }; + } + } + } \ No newline at end of file diff --git a/catalog-ui/src/app/models/tosca-string-parameter.ts b/catalog-ui/src/app/models/tosca-string-parameter.ts index 0f7423582c..64f6676624 100644 --- a/catalog-ui/src/app/models/tosca-string-parameter.ts +++ b/catalog-ui/src/app/models/tosca-string-parameter.ts @@ -25,4 +25,15 @@ import {ToscaFunctionType} from "./tosca-function-type.enum"; export class ToscaStringParameter implements ToscaFunctionParameter { type: ToscaFunctionType = ToscaFunctionType.STRING; value: string; + + + constructor(toscaStringParameter?: ToscaStringParameter) { + if (toscaStringParameter) { + this.value = toscaStringParameter.value; + } + } + + buildValueObject(): Object { + return this.value; + } } \ No newline at end of file diff --git a/catalog-ui/src/app/models/ui-models/constraint-object-ui.ts b/catalog-ui/src/app/models/ui-models/constraint-object-ui.ts new file mode 100644 index 0000000000..48cf2abdc6 --- /dev/null +++ b/catalog-ui/src/app/models/ui-models/constraint-object-ui.ts @@ -0,0 +1,26 @@ +import {FilterConstraint} from "../filter-constraint"; + +export class ConstraintObjectUI extends FilterConstraint { + isValidValue: boolean; + + constructor(input?: any) { + super(input); + if (input) { + this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== ''; + } + } + + public updateValidity(isValidValue: boolean) { + this.isValidValue = isValidValue; + } + + public isValidRule() { + const isValidValue = this.isStatic() ? this.isValidValue : true; + return this.servicePropertyName != null && this.servicePropertyName !== '' + && this.value != null && this.value !== '' && isValidValue; + } + + private isStatic() { + return this.sourceName === 'static'; + } +} \ No newline at end of file diff --git a/catalog-ui/src/app/models/yaml-function.ts b/catalog-ui/src/app/models/yaml-function.ts index e80d783424..e992d6bf47 100644 --- a/catalog-ui/src/app/models/yaml-function.ts +++ b/catalog-ui/src/app/models/yaml-function.ts @@ -22,6 +22,7 @@ import {ToscaFunction} from "./tosca-function"; import {ToscaFunctionType} from "./tosca-function-type.enum"; import {ToscaFunctionParameter} from "./tosca-function-parameter"; +import * as jsYaml from 'js-yaml'; export class YamlFunction implements ToscaFunction, ToscaFunctionParameter { type = ToscaFunctionType.YAML; @@ -34,4 +35,12 @@ export class YamlFunction implements ToscaFunction, ToscaFunctionParameter { this.value = yamlFunction.value; } + public buildValueObject(): Object { + return jsYaml.load(this.value); + } + + public buildValueString(): string { + return this.value; + } + } \ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/capabilities-constraint/capabilities-constraint.component.ts b/catalog-ui/src/app/ng2/components/logic/capabilities-constraint/capabilities-constraint.component.ts deleted file mode 100644 index 853106c806..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/capabilities-constraint/capabilities-constraint.component.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* -* ============LICENSE_START======================================================= -* SDC -* ================================================================================ -* Copyright (C) 2020 Nordix Foundation. All rights reserved. -* ================================================================================ -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -* -* SPDX-License-Identifier: Apache-2.0 -* ============LICENSE_END========================================================= -*/ - -export class CapabilitiesConstraintObject { - capabilityName: string; - servicePropertyName: string; - constraintOperator: string; - sourceType: string; - sourceName: string; - value: string; - - constructor(input?: any) { - if (input) { - this.capabilityName = input.capabilityName; - this.servicePropertyName = input.servicePropertyName; - this.constraintOperator = input.constraintOperator; - this.sourceType = input.sourceType; - this.sourceName = input.sourceName; - this.value = input.value; - } - } -} - -export class CapabilitiesConstraintObjectUI extends CapabilitiesConstraintObject{ - isValidValue: boolean; - - constructor(input?: any) { - super(input); - if (input) { - this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== ''; - } - } - - public updateValidity(isValidValue: boolean) { - this.isValidValue = isValidValue; - } - - public isValidRule(isStatic) { - const isValidValue = isStatic ? this.isValidValue : true; - return this.servicePropertyName != null && this.servicePropertyName !== '' - && this.value != null && this.value !== '' && isValidValue; - } -} diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.html b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.html index 213210cc7d..f0430ff1cd 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.html +++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.html @@ -23,11 +23,8 @@
- {{capability.capabilityName + ' : ' + capability.servicePropertyName + ' ' + getSymbol(capability.constraintOperator) - + ' ' + (capability.value | json)}} + tooltip="{{constraintCapabilityLabels[i]}}"> + {{constraintCapabilityLabels[i]}}
- {{property.servicePropertyName + ' ' + getSymbol(property.constraintOperator) - + ' ' + (property.value | json)}} + tooltip="{{constraintPropertyLabels[i]}}"> + {{constraintPropertyLabels[i]}}
; isDependent: boolean; isLoading: boolean; parentServiceInputs: InputBEModel[] = []; parentServiceProperties: PropertyBEModel[] = []; - constraintProperties: ConstraintObject[] = []; - constraintCapabilities: CapabilitiesConstraintObjectUI[] = []; + constraintProperties: FilterConstraint[] = []; + constraintPropertyLabels: string[] = []; + constraintCapabilities: CapabilityFilterConstraintUI[] = []; + constraintCapabilityLabels: string[] = []; operatorTypes: any[]; capabilities: string = ToscaFilterConstraintType.CAPABILITIES; properties: string = ToscaFilterConstraintType.PROPERTIES; - private componentInstancesConstraints: ConstraintObject[] = []; + private componentInstancesConstraints: FilterConstraint[] = []; isEditable: boolean; @Input() readonly: boolean; @Input() compositeService: ComponentMetadata; @Input() currentServiceInstance: ComponentInstance; @Input() selectedInstanceSiblings: ServiceInstanceObject[]; - @Input() selectedInstanceConstraints: ConstraintObject[] = []; + @Input() selectedInstanceConstraints: FilterConstraint[] = []; @Input() selectedInstanceProperties: PropertyBEModel[] = []; - @Output() updateRulesListEvent: EventEmitter = new EventEmitter(); - @Output() updateNodeFilterProperties: EventEmitter = new EventEmitter(); - @Output() updateNodeFilterCapabilities: EventEmitter = new EventEmitter(); + @Input() componentInstanceCapabilitiesMap: Map; + @Output() updateRulesListEvent: EventEmitter = new EventEmitter(); + @Output() updateNodeFilterProperties: EventEmitter = new EventEmitter(); + @Output() updateNodeFilterCapabilities: EventEmitter = new EventEmitter(); @Output() loadRulesListEvent:EventEmitter = new EventEmitter(); @Output() dependencyStatus = new EventEmitter(); - @Input() componentInstanceCapabilitiesMap: Map; - constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService, private compositionService: CompositionService) { } - ngOnInit() { + ngOnInit(): void { this.isLoading = false; this.operatorTypes = [ - {label: '>', value: OPERATOR_TYPES.GREATER_THAN}, - {label: '<', value: OPERATOR_TYPES.LESS_THAN}, - {label: '=', value: OPERATOR_TYPES.EQUAL}, - {label: '>=', value: OPERATOR_TYPES.GREATER_OR_EQUAL}, - {label: '<=', value: OPERATOR_TYPES.LESS_OR_EQUAL} + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.GREATER_THAN), value: OPERATOR_TYPES.GREATER_THAN}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.LESS_THAN), value: OPERATOR_TYPES.LESS_THAN}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.EQUAL), value: OPERATOR_TYPES.EQUAL}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.GREATER_OR_EQUAL), value: OPERATOR_TYPES.GREATER_OR_EQUAL}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.LESS_OR_EQUAL), value: OPERATOR_TYPES.LESS_OR_EQUAL} ]; this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId) .subscribe((result: ComponentGenericResponse) => { @@ -186,7 +140,7 @@ export class ServiceDependenciesComponent { }); } - ngOnChanges(changes) { + ngOnChanges(changes): void { if (changes.currentServiceInstance) { this.currentServiceInstance = changes.currentServiceInstance.currentValue; this.isDependent = this.currentServiceInstance.isDependent(); @@ -210,27 +164,19 @@ export class ServiceDependenciesComponent { return this.modalServiceNg2.createCustomModal(modalModel); } - public openUpdateDependencyModal = (): ComponentRef => { - const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency); - const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal); - const modalModel: ModalModel = new ModalModel('sm', I18nTexts.updateDirectiveModalTitle, - I18nTexts.updateDirectiveModalText, [actionButton, cancelButton]); - return this.modalServiceNg2.createCustomModal(modalModel); - } - private loadNodeFilter = (): void => { this.topologyTemplateService.getServiceFilterConstraints(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((response) => { if (response.nodeFilterforNode && response.nodeFilterforNode[this.currentServiceInstance.uniqueId]) { this.componentInstancesConstraints = response.nodeFilterforNode; - const nodeFilterPropertiesResponse: ConstraintObject[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].properties; - this.constraintProperties = nodeFilterPropertiesResponse; - const nodeFilterCapabilitiesResponse: CapabilitiesConstraintObjectUI[] = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].capabilities; - this.constraintCapabilities = nodeFilterCapabilitiesResponse; + this.constraintProperties = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].properties; + this.buildConstraintPropertyLabels(); + this.constraintCapabilities = response.nodeFilterforNode[this.currentServiceInstance.uniqueId].capabilities; + this.buildCapabilityFilterConstraintLabels(); } }); } - onUncheckDependency = () => { + onUncheckDependency = (): void => { this.modalServiceNg2.closeCurrentModal(); this.isLoading = true; const isDepOrig = this.isDependent; @@ -239,36 +185,40 @@ export class ServiceDependenciesComponent { this.updateComponentInstance(isDepOrig, rulesListOrig); } - onCloseRemoveDependencyModal = () => { + onCloseRemoveDependencyModal = (): void => { this.isDependent = true; this.modalServiceNg2.closeCurrentModal(); } - onAddDirectives(directives: string[]) { + onAddDirectives(directives: string[]): void { this.isEditable = false; this.setDirectiveValue(directives); const rulesListOrig = this.componentInstancesConstraints; this.constraintProperties = []; + this.constraintPropertyLabels = []; this.constraintCapabilities = []; + this.constraintCapabilityLabels = []; this.loadNodeFilter(); this.updateComponentInstance(this.isDependent, rulesListOrig); } - private onRemoveDirective() { + private onRemoveDirective(): void { this.openRemoveDependencyModal().instance.open(); this.constraintProperties = []; + this.constraintPropertyLabels = []; this.constraintCapabilities = []; + this.constraintCapabilityLabels = []; } - private onEditDirectives() { + private onEditDirectives(): void { this.isEditable = true; } - private setDirectiveValue(newDirectiveValues: string[]) { + private setDirectiveValue(newDirectiveValues: string[]): void { this.currentServiceInstance.setDirectiveValue(newDirectiveValues); } - updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) { + updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: FilterConstraint[]): void { this.isLoading = true; this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId, this.compositeService.componentType, @@ -288,11 +238,11 @@ export class ServiceDependenciesComponent { this.isDependent = isDependentOrigVal; this.componentInstancesConstraints = rulesListOrig; this.isLoading = false; - console.log('An error has occurred.'); + console.error('An error has occurred.', err); }); } - onAddNodeFilter = () => { + onAddNodeFilter = (): void => { if (!this.selectedInstanceProperties) { this.modalServiceNg2.openAlertModal(I18nTexts.validateNodePropertiesTxt, I18nTexts.validateNodePropertiesMsg); } else { @@ -317,7 +267,7 @@ export class ServiceDependenciesComponent { } } - onAddNodeFilterCapabilities = () => { + onAddNodeFilterCapabilities = (): void => { if (this.componentInstanceCapabilitiesMap.size == 0) { this.modalServiceNg2.openAlertModal(I18nTexts.validateCapabilitiesTxt, I18nTexts.validateCapabilitiesMsg); } else { @@ -342,12 +292,12 @@ export class ServiceDependenciesComponent { } } - createNodeFilter = (constraintType: string) => { + createNodeFilter = (constraintType: string): void => { this.isLoading = true; this.topologyTemplateService.createServiceFilterConstraints( this.compositeService.uniqueId, this.currentServiceInstance.uniqueId, - new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule), + new FilterConstraint(this.modalInstance.instance.dynamicContent.instance.currentRule), this.compositeService.componentType, constraintType ).subscribe( (response) => { @@ -359,12 +309,12 @@ export class ServiceDependenciesComponent { this.modalServiceNg2.closeCurrentModal(); } - createNodeFilterCapabilities = (constraintType: string) => { + createNodeFilterCapabilities = (constraintType: string): void => { this.isLoading = true; this.topologyTemplateService.createServiceFilterCapabilitiesConstraints( this.compositeService.uniqueId, this.currentServiceInstance.uniqueId, - new CapabilitiesConstraintObjectUI(this.modalInstance.instance.dynamicContent.instance.currentRule), + new CapabilityFilterConstraintUI(this.modalInstance.instance.dynamicContent.instance.currentRule), this.compositeService.componentType, constraintType ).subscribe( (response) => { @@ -376,7 +326,7 @@ export class ServiceDependenciesComponent { this.modalServiceNg2.closeCurrentModal(); } - onSelectNodeFilterCapability(constraintType: string, index: number) { + onSelectNodeFilterCapability(constraintType: string, index: number): void { const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal); const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilterCapability(constraintType, index), this.getDisabled); const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard'); @@ -387,7 +337,7 @@ export class ServiceDependenciesComponent { CapabilitiesFilterPropertiesEditorComponent, { serviceRuleIndex: index, - serviceRules: _.map(this.constraintCapabilities, (rule) => new CapabilitiesConstraintObjectUI(rule)), + serviceRules: _.map(this.constraintCapabilities, (rule) => new CapabilityFilterConstraintUI(rule)), currentServiceName: this.currentServiceInstance.name, operatorTypes: this.operatorTypes, compositeServiceName: this.compositeService.name, @@ -400,7 +350,7 @@ export class ServiceDependenciesComponent { this.modalInstance.instance.open(); } - onSelectNodeFilter(constraintType: string, index: number) { + onSelectNodeFilter(constraintType: string, index: number): void { const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal); const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateNodeFilter(constraintType, index), this.getDisabled); const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateNodeFilterTxt, '', [saveButton, cancelButton], 'standard'); @@ -410,7 +360,7 @@ export class ServiceDependenciesComponent { ServiceDependenciesEditorComponent, { serviceRuleIndex: index, - serviceRules: _.map(this.constraintProperties, (rule) => new ConstraintObjectUI(rule)), + serviceRules: this.constraintProperties.map(rule => new ConstraintObjectUI(rule)), currentServiceName: this.currentServiceInstance.name, operatorTypes: this.operatorTypes, compositeServiceName: this.compositeService.name, @@ -427,12 +377,12 @@ export class ServiceDependenciesComponent { return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit(); } - updateNodeFilter = (constraintType: string, index: number) => { + updateNodeFilter = (constraintType: string, index: number): void => { this.isLoading = true; this.topologyTemplateService.updateServiceFilterConstraints( this.compositeService.uniqueId, this.currentServiceInstance.uniqueId, - new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule), + new FilterConstraint(this.modalInstance.instance.dynamicContent.instance.currentRule), this.compositeService.componentType, constraintType, index @@ -445,12 +395,12 @@ export class ServiceDependenciesComponent { this.modalServiceNg2.closeCurrentModal(); } - updateNodeFilterCapability= (constraintType: string, index: number) => { + updateNodeFilterCapability = (constraintType: string, index: number): void => { this.isLoading = true; this.topologyTemplateService.updateServiceFilterCapabilitiesConstraint( this.compositeService.uniqueId, this.currentServiceInstance.uniqueId, - new CapabilitiesConstraintObjectUI(this.modalInstance.instance.dynamicContent.instance.currentRule), + new CapabilityFilterConstraintUI(this.modalInstance.instance.dynamicContent.instance.currentRule), this.compositeService.componentType, constraintType, index @@ -463,17 +413,7 @@ export class ServiceDependenciesComponent { this.modalServiceNg2.closeCurrentModal(); } - getSymbol(constraintOperator) { - switch (constraintOperator) { - case OPERATOR_TYPES.LESS_THAN: return '<'; - case OPERATOR_TYPES.EQUAL: return '='; - case OPERATOR_TYPES.GREATER_THAN: return '>'; - case OPERATOR_TYPES.GREATER_OR_EQUAL: return '>='; - case OPERATOR_TYPES.LESS_OR_EQUAL: return '<='; - } - } - - onDeleteNodeFilter = (constraintType: string, index: number) => { + onDeleteNodeFilter = (constraintType: string, index: number): void => { this.isLoading = true; this.topologyTemplateService.deleteServiceFilterConstraints( this.compositeService.uniqueId, @@ -494,15 +434,37 @@ export class ServiceDependenciesComponent { if (this.properties === constraintType) { this.updateNodeFilterProperties.emit(response.properties); this.constraintProperties = response.properties; + this.buildConstraintPropertyLabels(); } else { this.updateNodeFilterCapabilities.emit(response.capabilities); this.constraintCapabilities = response.capabilities; + this.buildCapabilityFilterConstraintLabels(); } } - openDeleteModal = (constraintType: string, index: number) => { + openDeleteModal = (constraintType: string, index: number): void => { this.modalServiceNg2.createActionModal(I18nTexts.deleteNodeFilterTxt, I18nTexts.deleteNodeFilterMsg, I18nTexts.modalDelete, () => this.onDeleteNodeFilter(constraintType, index), I18nTexts.modalCancel).instance.open(); } + private buildConstraintPropertyLabels(): void { + this.constraintPropertyLabels = []; + if (!this.constraintProperties) { + return; + } + this.constraintProperties.forEach( + constraint => this.constraintPropertyLabels.push(FilterConstraintHelper.buildFilterConstraintLabel(constraint)) + ) + } + + private buildCapabilityFilterConstraintLabels(): void { + this.constraintCapabilityLabels = []; + if (!this.constraintCapabilities) { + return; + } + this.constraintCapabilities.forEach( + constraint => this.constraintCapabilityLabels.push(FilterConstraintHelper.buildFilterConstraintLabel(constraint)) + ) + } + } diff --git a/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html b/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html index 81fc5b48ee..6e57de50ea 100644 --- a/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html +++ b/catalog-ui/src/app/ng2/components/logic/substitution-filter/substitution-filter.component.html @@ -30,11 +30,8 @@
- {{property.servicePropertyName + ' ' + getSymbol(property.constraintOperator) - + ' ' - + (property.sourceName ? property.sourceName + ':' : '') + property.value}} + tooltip="{{constraintPropertyLabels[i]}}"> + {{constraintPropertyLabels[i]}}
; isLoading: boolean; operatorTypes: any[]; - constraintProperties: ConstraintObject[] = []; + constraintProperties: FilterConstraint[] = []; + constraintPropertyLabels: string[] = []; PROPERTIES: string = ToscaFilterConstraintType.PROPERTIES; @Input() readonly: boolean; @Input() compositeService: ComponentMetadata; @Input() currentServiceInstance: ComponentInstance; - @Input() selectedInstanceConstraints: ConstraintObject[] = []; + @Input() selectedInstanceConstraints: FilterConstraint[] = []; @Input() selectedInstanceProperties: PropertyBEModel[] = []; @Input() parentServiceProperties: PropertyBEModel[] = []; @Input() parentServiceInputs: InputBEModel[] = []; - @Output() updateSubstitutionFilterProperties: EventEmitter = new EventEmitter(); - @Output() updateConstraintListEvent: EventEmitter = new EventEmitter(); + @Output() updateSubstitutionFilterProperties: EventEmitter = new EventEmitter(); + @Output() updateConstraintListEvent: EventEmitter = new EventEmitter(); @Output() loadConstraintListEvent: EventEmitter = new EventEmitter(); @Output() hasSubstitutionFilter = new EventEmitter(); constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) { } - ngOnInit() { + ngOnInit(): void { this.isLoading = false; this.operatorTypes = [ - {label: '>', value: OPERATOR_TYPES.GREATER_THAN}, - {label: '<', value: OPERATOR_TYPES.LESS_THAN}, - {label: '=', value: OPERATOR_TYPES.EQUAL} + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.GREATER_THAN), value: OPERATOR_TYPES.GREATER_THAN}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.LESS_THAN), value: OPERATOR_TYPES.LESS_THAN}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.EQUAL), value: OPERATOR_TYPES.EQUAL}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.GREATER_OR_EQUAL), value: OPERATOR_TYPES.GREATER_OR_EQUAL}, + {label: FilterConstraintHelper.convertToSymbol(OPERATOR_TYPES.LESS_OR_EQUAL), value: OPERATOR_TYPES.LESS_OR_EQUAL} ]; this.loadSubstitutionFilter(); this.translateService.languageChangedObservable.subscribe((lang) => { @@ -143,7 +98,7 @@ export class SubstitutionFilterComponent { }); } - ngOnChanges(changes) { + ngOnChanges(changes): void { if (changes.compositeService) { this.compositeService = changes.compositeService.currentValue; } @@ -158,11 +113,12 @@ export class SubstitutionFilterComponent { .subscribe((response) => { if(response.substitutionFilters) { this.constraintProperties = response.substitutionFilters.properties; + this.buildConstraintPropertyLabels(); } }); } - onAddSubstitutionFilter = (constraintType: string) => { + onAddSubstitutionFilter = (constraintType: string): void => { const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal); const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', () => this.createSubstitutionFilter(constraintType), this.getDisabled); const modalModel: ModalModel = new ModalModel('l', I18nTexts.addSubstitutionFilterTxt, '', [saveButton, cancelButton], 'standard'); @@ -182,8 +138,8 @@ export class SubstitutionFilterComponent { this.modalInstance.instance.open(); } - createSubstitutionFilter = (constraintType: string) => { - const newSubstitutionFilter: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule); + createSubstitutionFilter = (constraintType: string): void => { + const newSubstitutionFilter: FilterConstraint = new FilterConstraint(this.modalInstance.instance.dynamicContent.instance.currentRule); this.isLoading = true; this.topologyTemplateService.createSubstitutionFilterConstraints( this.compositeService.uniqueId, @@ -194,7 +150,7 @@ export class SubstitutionFilterComponent { this.emitEventOnChanges(constraintType, response); this.isLoading = false; }, (err) => { - console.error("Failed to Create Substitution Filter on the component with id: ", this.compositeService.uniqueId); + console.error(`Failed to Create Substitution Filter on the component with id: ${this.compositeService.uniqueId}`, err); this.isLoading = false; }); this.modalServiceNg2.closeCurrentModal(); @@ -202,7 +158,7 @@ export class SubstitutionFilterComponent { onSelectSubstitutionFilter(constraintType: string, index: number) { const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal); - const updateButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateSubstitutionFilter(constraintType), this.getDisabled); + const updateButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateSubstitutionFilter(constraintType, index), this.getDisabled); const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateSubstitutionFilterTxt, '', [updateButton, cancelButton], 'standard'); this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel); this.modalServiceNg2.addDynamicContentToModal( @@ -222,25 +178,26 @@ export class SubstitutionFilterComponent { this.modalInstance.instance.open(); } - updateSubstitutionFilter = (constraintType: string): void => { - const constraintToUpdate: ConstraintObject[] = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map((rule) => new ConstraintObject(rule)); + updateSubstitutionFilter(constraintType: string, index: number): void { + const constraintToUpdate: FilterConstraint = this.modalInstance.instance.dynamicContent.instance.currentRule; this.isLoading = true; - this.topologyTemplateService.updateSubstitutionFilterConstraints( + this.topologyTemplateService.updateSubstitutionFilterConstraint( this.compositeService.uniqueId, constraintToUpdate, this.compositeService.componentType, - constraintType + constraintType, + index ).subscribe((response) => { this.emitEventOnChanges(constraintType, response); this.isLoading = false; - }, () => { - console.error("Failed to Update Substitution Filter on the component with id: ", this.compositeService.uniqueId); + }, (error) => { + console.error("Failed to Update Substitution Filter on the component with id: ", this.compositeService.uniqueId, error); this.isLoading = false; }); this.modalServiceNg2.closeCurrentModal(); } - onDeleteSubstitutionFilter = (constraintType: string, index: number) => { + onDeleteSubstitutionFilter = (constraintType: string, index: number): void => { this.isLoading = true; this.topologyTemplateService.deleteSubstitutionFilterConstraints( this.compositeService.uniqueId, @@ -262,26 +219,27 @@ export class SubstitutionFilterComponent { return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit(); } - getSymbol(constraintOperator) { - switch (constraintOperator) { - case OPERATOR_TYPES.LESS_THAN: - return '<'; - case OPERATOR_TYPES.EQUAL: - return '='; - case OPERATOR_TYPES.GREATER_THAN: - return '>'; - } - } - - openDeleteModal = (constraintType: string, index: number) => { + openDeleteModal = (constraintType: string, index: number): void => { this.modalServiceNg2.createActionModal(I18nTexts.deleteSubstitutionFilterTxt, I18nTexts.deleteSubstitutionFilterMsg, I18nTexts.modalDelete, () => this.onDeleteSubstitutionFilter(constraintType, index), I18nTexts.modalCancel).instance.open(); } - private emitEventOnChanges(constraintType: string, response) { - if (ToscaFilterConstraintType.PROPERTIES === constraintType) { - this.updateSubstitutionFilterProperties.emit(response.properties); - this.constraintProperties = response.properties; - } + private emitEventOnChanges(constraintType: string, response): void { + if (ToscaFilterConstraintType.PROPERTIES === constraintType) { + this.updateSubstitutionFilterProperties.emit(response.properties); + this.constraintProperties = response.properties; + this.buildConstraintPropertyLabels(); + } + } + + private buildConstraintPropertyLabels(): void { + this.constraintPropertyLabels = []; + if (!this.constraintProperties) { + return; + } + this.constraintProperties.forEach( + constraint => this.constraintPropertyLabels.push(FilterConstraintHelper.buildFilterConstraintLabel(constraint)) + ) } + } diff --git a/catalog-ui/src/app/ng2/pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.component.ts b/catalog-ui/src/app/ng2/pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.component.ts index 7e3bc69835..b59591bd06 100644 --- a/catalog-ui/src/app/ng2/pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/capabilities-filter-properties-editor/capabilities-filter-properties-editor.component.ts @@ -21,12 +21,12 @@ import {Component} from '@angular/core'; import {InputBEModel, PropertyBEModel, PropertyModel} from 'app/models'; -import {OPERATOR_TYPES} from 'app/ng2/components/logic/service-dependencies/service-dependencies.component'; import {DropdownValue} from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component'; import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service'; import {PROPERTY_DATA} from 'app/utils'; import {ServiceInstanceObject} from '../../../../models/service-instance-properties-and-interfaces'; -import {CapabilitiesConstraintObjectUI} from "../../../components/logic/capabilities-constraint/capabilities-constraint.component"; +import {CapabilityFilterConstraintUI} from "../../../../models/capability-filter-constraint"; +import {OPERATOR_TYPES} from "../../../../utils/filter-constraint-helper"; export class UIDropDownSourceTypesElement extends DropdownValue { options: any[]; @@ -53,7 +53,7 @@ export class CapabilitiesFilterPropertiesEditorComponent { input: { serviceRuleIndex: number, - serviceRules: CapabilitiesConstraintObjectUI[], + serviceRules: CapabilityFilterConstraintUI[], compositeServiceName: string, currentServiceName: string, parentServiceInputs: InputBEModel[], @@ -66,12 +66,12 @@ export class CapabilitiesFilterPropertiesEditorComponent { selectedServiceProperties: PropertyBEModel[]; operatorTypes: DropdownValue[]; sourceTypes: UIDropDownSourceTypesElement[] = []; - currentRule: CapabilitiesConstraintObjectUI; + currentRule: CapabilityFilterConstraintUI; currentIndex: number; listOfValuesToAssign: DropdownValue[]; listOfSourceOptions: PropertyBEModel[]; assignedValueLabel: string; - serviceRulesList: CapabilitiesConstraintObjectUI[]; + serviceRulesList: CapabilityFilterConstraintUI[]; capabilitiesNames: string[]; selectedPropertiesByCapabilityName: Array; @@ -92,7 +92,7 @@ export class CapabilitiesFilterPropertiesEditorComponent { this.serviceRulesList = this.input.serviceRules; this.currentRule = this.serviceRulesList && this.input.serviceRuleIndex >= 0 ? this.serviceRulesList[this.input.serviceRuleIndex] : - new CapabilitiesConstraintObjectUI({ + new CapabilityFilterConstraintUI({ capabilityName: this.SOURCE_TYPES.CAPABILITY_NAME.value, sourceName: this.SOURCE_TYPES.STATIC.value, sourceType: this.SOURCE_TYPES.STATIC.value, value: '', diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts index f844dfae4c..ce1a43dd3b 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/service-dependencies-tab/service-dependencies-tab.component.ts @@ -11,13 +11,13 @@ import {DEPENDENCY_EVENTS} from 'app/utils/constants'; import {ComponentMetadata} from '../../../../../../models/component-metadata'; import {ServiceInstanceObject} from '../../../../../../models/service-instance-properties-and-interfaces'; import {EventListenerService} from '../../../../../../services/event-listener-service'; -import {ConstraintObject} from '../../../../../components/logic/service-dependencies/service-dependencies.component'; import {TopologyTemplateService} from '../../../../../services/component-services/topology-template.service'; import {ComponentGenericResponse} from '../../../../../services/responses/component-generic-response'; import {WorkspaceService} from '../../../../workspace/workspace.service'; import {SelectedComponentType} from '../../../common/store/graph.actions'; import {CompositionService} from '../../../composition.service'; -import {CapabilitiesConstraintObject} from "../../../../../components/logic/capabilities-constraint/capabilities-constraint.component"; +import {CapabilityFilterConstraint} from "../../../../../../models/capability-filter-constraint"; +import {FilterConstraint} from "../../../../../../models/filter-constraint"; @Component({ selector: 'service-dependencies-tab', @@ -29,7 +29,7 @@ export class ServiceDependenciesTabComponent { selectedInstanceSiblings: ServiceInstanceObject[]; componentInstancesConstraints: any[]; - selectedInstanceConstraints: ConstraintObject[]; + selectedInstanceConstraints: FilterConstraint[]; selectedInstanceProperties: PropertyBEModel[]; componentInstanceProperties: PropertiesGroup; componentInstanceCapabilityProperties: CapabilitiesGroup; @@ -68,12 +68,12 @@ export class ServiceDependenciesTabComponent { this.eventListenerService.notifyObservers(DEPENDENCY_EVENTS.ON_DEPENDENCY_CHANGE, isChecked); } - public updateSelectedInstanceConstraints = (constraintsList:Array):void => { + public updateSelectedInstanceConstraints = (constraintsList:Array):void => { this.componentInstancesConstraints[this.component.uniqueId].properties = constraintsList; this.selectedInstanceConstraints = this.componentInstancesConstraints[this.component.uniqueId].properties; } - public updateSelectedInstanceCapabilitiesConstraints = (constraintsList:Array):void => { + public updateSelectedInstanceCapabilitiesConstraints = (constraintsList:Array):void => { this.componentInstancesConstraints[this.component.uniqueId].capabilities = constraintsList; this.selectedInstanceConstraints = this.componentInstancesConstraints[this.component.uniqueId].capabilities; } diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/substitution-filter-tab/substitution-filter-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/substitution-filter-tab/substitution-filter-tab.component.ts index bf8d1e43b1..ac497ee98e 100644 --- a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/substitution-filter-tab/substitution-filter-tab.component.ts +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/substitution-filter-tab/substitution-filter-tab.component.ts @@ -17,24 +17,19 @@ * ============LICENSE_END========================================================= */ -import { Component, Input } from '@angular/core'; -import { Store } from '@ngxs/store'; -import { - Component as TopologyTemplate, - FullComponentInstance, InputBEModel, - PropertiesGroup, - PropertyBEModel, -} from 'app/models'; -import { SUBSTITUTION_FILTER_EVENTS } from 'app/utils/constants'; -import { ComponentMetadata } from '../../../../../../models/component-metadata'; -import { ServiceInstanceObject } from '../../../../../../models/service-instance-properties-and-interfaces'; -import { EventListenerService } from '../../../../../../services/event-listener-service'; -import { ConstraintObject } from '../../../../../components/logic/service-dependencies/service-dependencies.component'; -import { TopologyTemplateService } from '../../../../../services/component-services/topology-template.service'; -import { ComponentGenericResponse } from '../../../../../services/responses/component-generic-response'; -import { WorkspaceService } from '../../../../workspace/workspace.service'; -import { SelectedComponentType } from '../../../common/store/graph.actions'; -import { CompositionService } from '../../../composition.service'; +import {Component, Input} from '@angular/core'; +import {Store} from '@ngxs/store'; +import {Component as TopologyTemplate, FullComponentInstance, InputBEModel, PropertiesGroup, PropertyBEModel,} from 'app/models'; +import {SUBSTITUTION_FILTER_EVENTS} from 'app/utils/constants'; +import {ComponentMetadata} from '../../../../../../models/component-metadata'; +import {ServiceInstanceObject} from '../../../../../../models/service-instance-properties-and-interfaces'; +import {EventListenerService} from '../../../../../../services/event-listener-service'; +import {TopologyTemplateService} from '../../../../../services/component-services/topology-template.service'; +import {ComponentGenericResponse} from '../../../../../services/responses/component-generic-response'; +import {WorkspaceService} from '../../../../workspace/workspace.service'; +import {SelectedComponentType} from '../../../common/store/graph.actions'; +import {CompositionService} from '../../../composition.service'; +import {FilterConstraint} from "../../../../../../models/filter-constraint"; @Component({ selector: 'substitution-filter-tab', @@ -46,7 +41,7 @@ export class SubstitutionFilterTabComponent { selectedInstanceSiblings: ServiceInstanceObject[]; componentInstancesConstraints: any[]; - selectedInstanceConstraints: ConstraintObject[]; + selectedInstanceConstraints: FilterConstraint[]; parentServiceProperties: PropertyBEModel[]; parentServiceInputs: InputBEModel[]; componentInstanceProperties: PropertiesGroup; @@ -80,7 +75,7 @@ export class SubstitutionFilterTabComponent { this.eventListenerService.notifyObservers(SUBSTITUTION_FILTER_EVENTS.ON_SUBSTITUTION_FILTER_CHANGE, isChecked); } - public updateSelectedInstanceConstraints = (constraintsList:Array):void => { + public updateSelectedInstanceConstraints = (constraintsList:Array):void => { this.componentInstancesConstraints[this.component.uniqueId].properties = constraintsList; this.selectedInstanceConstraints = this.componentInstancesConstraints[this.component.uniqueId].properties; } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts index 753cb6afe0..747de7c00f 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts @@ -19,11 +19,20 @@ */ import * as _ from "lodash"; -import { Injectable } from '@angular/core'; -import { DataTypeModel, PropertyFEModel, PropertyBEModel, InstanceBePropertiesMap, InstanceFePropertiesMap, DerivedFEProperty, DerivedPropertyType, InputFEModel} from "app/models"; -import { DataTypeService } from "app/ng2/services/data-type.service"; -import { PropertiesService } from "app/ng2/services/properties.service"; -import { PROPERTY_TYPES, PROPERTY_DATA } from "app/utils"; +import {Injectable} from '@angular/core'; +import { + DataTypeModel, + DerivedFEProperty, + DerivedPropertyType, + InputFEModel, + InstanceBePropertiesMap, + InstanceFePropertiesMap, + PropertyBEModel, + PropertyFEModel +} from "app/models"; +import {DataTypeService} from "app/ng2/services/data-type.service"; +import {PropertiesService} from "app/ng2/services/properties.service"; +import {PROPERTY_TYPES} from "app/utils"; import { SubPropertyToscaFunction } from "app/models/sub-property-tosca-function"; @Injectable() @@ -139,7 +148,7 @@ export class PropertiesUtils { Object.keys(nestedValue).forEach((keyNested) => { property.flattenedChildren.push(...this.createListOrMapChildren(lastCreatedChild, keyNested, nestedValue[keyNested])); }); - }; + } }); } else if (property.derivedDataType === DerivedPropertyType.COMPLEX) { property.flattenedChildren = this.createFlattenedChildren(property.type, property.name); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts index d808c284a8..ef45211ea0 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-concat-function/tosca-concat-function.component.ts @@ -8,6 +8,7 @@ import {PropertyBEModel} from "../../../../../models/properties-inputs/property- import {PROPERTY_TYPES} from "../../../../../utils/constants"; import {InstanceFeDetails} from "../../../../../models/instance-fe-details"; import {ToscaFunctionValidationEvent} from "../tosca-function.component"; +import {ToscaFunction} from "../../../../../models/tosca-function"; @Component({ selector: 'app-tosca-concat-function', @@ -30,7 +31,6 @@ export class ToscaConcatFunctionComponent implements OnInit { parameters: ToscaFunctionParameter[] = []; propertyInputList: Array = []; - stringProperty: PropertyBEModel STRING_FUNCTION_TYPE = ToscaFunctionType.STRING @@ -44,7 +44,7 @@ export class ToscaConcatFunctionComponent implements OnInit { this.initForm(); } - private initForm() { + private initForm(): void { this.formGroup.valueChanges.subscribe(() => { this.onValidityChange.emit({ isValid: this.formGroup.valid, @@ -57,12 +57,13 @@ export class ToscaConcatFunctionComponent implements OnInit { if (!this.toscaConcatFunction) { return; } - if (this.toscaConcatFunction.parameters) { this.parameters = Array.from(this.toscaConcatFunction.parameters); for (const parameter of this.parameters) { if (parameter.type !== PROPERTY_TYPES.STRING) { - this.propertyInputList.push(this.createStringProperty(parameter)); + const propertyBEModel = this.createStringProperty(parameter.value); + propertyBEModel.toscaFunction = parameter; + this.propertyInputList.push(propertyBEModel); this.concatParameterFormArray.push( new FormControl(parameter, [Validators.required, Validators.minLength(1)]) ); @@ -92,7 +93,7 @@ export class ToscaConcatFunctionComponent implements OnInit { return toscaConcatFunction1; } - addFunction() { + addFunction(): void { this.propertyInputList.push(this.createStringProperty()); this.parameters.push({} as ToscaFunctionParameter); this.concatParameterFormArray.push( @@ -100,32 +101,30 @@ export class ToscaConcatFunctionComponent implements OnInit { ); } - addStringParameter() { - this.parameters.push({ - type: ToscaFunctionType.STRING, - value: '' - }); + addStringParameter(): void { + const toscaStringParameter = new ToscaStringParameter(); + toscaStringParameter.value = '' + this.parameters.push(toscaStringParameter); this.propertyInputList.push(undefined); this.concatParameterFormArray.push( new FormControl('', [Validators.required, Validators.minLength(1)]) ); } - removeParameter(position) { + removeParameter(position): void { this.propertyInputList.splice(position, 1); this.parameters.splice(position, 1); this.concatParameterFormArray.removeAt(position); } - createStringProperty(toscaFunctionParameter?: ToscaFunctionParameter) { + createStringProperty(value?: any): PropertyBEModel { const property = new PropertyBEModel(); property.type = PROPERTY_TYPES.STRING; - property.toscaFunction = toscaFunctionParameter ? toscaFunctionParameter : undefined; - property.value = toscaFunctionParameter ? toscaFunctionParameter.value : undefined; + property.value = value ? value : undefined; return property; } - onFunctionValidityChange(event: ToscaFunctionValidationEvent, index: number) { + onFunctionValidityChange(event: ToscaFunctionValidationEvent, index: number): void { if (event.isValid && event.toscaFunction) { this.concatParameterFormArray.controls[index].setValue(event.toscaFunction) } else { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html index f93973cb16..8ee253e5dc 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.html @@ -21,7 +21,7 @@
- diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts index 70df4eaced..e40a4d6e1e 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.component.ts @@ -17,7 +17,7 @@ * ============LICENSE_END========================================================= */ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges} from '@angular/core'; import {ComponentMetadata, PropertyBEModel, PropertyDeclareAPIModel} from 'app/models'; import {TopologyTemplateService} from "../../../services/component-services/topology-template.service"; import {WorkspaceService} from "../../workspace/workspace.service"; @@ -31,13 +31,15 @@ import {ToscaFunction} from "../../../../models/tosca-function"; import {ToscaConcatFunctionValidationEvent} from "./tosca-concat-function/tosca-concat-function.component"; import {PROPERTY_TYPES} from "../../../../utils/constants"; import {YamlFunctionValidationEvent} from "./yaml-function/yaml-function.component"; +import {ToscaConcatFunction} from "../../../../models/tosca-concat-function"; +import {YamlFunction} from "../../../../models/yaml-function"; @Component({ selector: 'tosca-function', templateUrl: './tosca-function.component.html', styleUrls: ['./tosca-function.component.less'], }) -export class ToscaFunctionComponent implements OnInit { +export class ToscaFunctionComponent implements OnInit, OnChanges { @Input() property: PropertyBEModel; @Input() componentInstanceMap: Map = new Map(); @@ -81,11 +83,21 @@ export class ToscaFunctionComponent implements OnInit { this.isInitialized = true; } - private validate() { + ngOnChanges(changes: SimpleChanges): void { + if (changes.property) { + this.resetForm(); + this.toscaFunction = this.property.toscaFunction ? this.property.toscaFunction : undefined; + this.initToscaFunction(); + this.loadToscaFunctions(); + this.emitValidityChange(); + } + } + + private validate(): boolean { return (!this.toscaFunctionForm.value && !this.toscaFunctionTypeForm.value) || this.formGroup.valid; } - private initToscaFunction() { + private initToscaFunction(): void { if (this.property instanceof PropertyDeclareAPIModel && this.property.subPropertyToscaFunctions && ( this.property).propertiesName){ let propertiesPath = ( this.property).propertiesName.split("#"); if (propertiesPath.length > 1){ @@ -100,7 +112,7 @@ export class ToscaFunctionComponent implements OnInit { return; } } - + if (!this.property.isToscaFunction()) { return; } @@ -113,6 +125,7 @@ export class ToscaFunctionComponent implements OnInit { } private loadToscaFunctions(): void { + this.toscaFunctions = []; this.toscaFunctions.push(ToscaFunctionType.GET_ATTRIBUTE); this.toscaFunctions.push(ToscaFunctionType.GET_INPUT); this.toscaFunctions.push(ToscaFunctionType.GET_PROPERTY); @@ -151,7 +164,7 @@ export class ToscaFunctionComponent implements OnInit { return this.formGroup.get('toscaFunctionType').value === ToscaFunctionType.YAML; } - onClearValues() { + onClearValues(): void { this.resetForm(); } @@ -159,7 +172,7 @@ export class ToscaFunctionComponent implements OnInit { return this.allowClear && this.toscaFunctionTypeForm.value; } - onConcatFunctionValidityChange(validationEvent: ToscaConcatFunctionValidationEvent) { + onConcatFunctionValidityChange(validationEvent: ToscaConcatFunctionValidationEvent): void { if (validationEvent.isValid) { this.toscaFunctionForm.setValue(validationEvent.toscaConcatFunction); } else { @@ -167,7 +180,7 @@ export class ToscaFunctionComponent implements OnInit { } } - onGetFunctionValidityChange(validationEvent: ToscaGetFunctionValidationEvent) { + onGetFunctionValidityChange(validationEvent: ToscaGetFunctionValidationEvent): void { if (validationEvent.isValid) { this.toscaFunctionForm.setValue(validationEvent.toscaGetFunction); } else { @@ -175,7 +188,7 @@ export class ToscaFunctionComponent implements OnInit { } } - onYamlFunctionValidityChange(validationEvent: YamlFunctionValidationEvent) { + onYamlFunctionValidityChange(validationEvent: YamlFunctionValidationEvent): void { if (validationEvent.isValid) { this.toscaFunctionForm.setValue(validationEvent.value); } else { @@ -183,14 +196,35 @@ export class ToscaFunctionComponent implements OnInit { } } - private emitValidityChange() { - const isValid = this.validate(); + onFunctionTypeChange(): void { + this.toscaFunction = undefined; + this.toscaFunctionForm.reset(); + } + + private emitValidityChange(): void { + const isValid: boolean = this.validate(); this.onValidityChange.emit({ isValid: isValid, - toscaFunction: isValid ? this.toscaFunctionForm.value : undefined + toscaFunction: isValid ? this.buildFunctionFromForm() : undefined }); } + private buildFunctionFromForm(): ToscaFunction { + if (!this.toscaFunctionTypeForm.value) { + return undefined; + } + if (this.isConcatSelected()) { + return new ToscaConcatFunction(this.toscaFunctionForm.value); + } + if (this.isGetFunctionSelected()) { + return new ToscaGetFunction(this.toscaFunctionForm.value); + } + if (this.isYamlFunctionSelected()) { + return new YamlFunction(this.toscaFunctionForm.value); + } + + console.error(`Function ${this.toscaFunctionTypeForm.value} not supported`); + } } export class ToscaFunctionValidationEvent { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts index 19cf2fb260..bcf10728f8 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-function.module.ts @@ -45,7 +45,9 @@ import { YamlFunctionComponent } from './yaml-function/yaml-function.component'; TranslateModule, SdcUiComponentsModule ], - exports: [], + exports: [ + ToscaFunctionComponent + ], entryComponents: [ ToscaFunctionComponent ], diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts index 1f658f968a..a32a4d0e45 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/tosca-function/tosca-get-function/tosca-get-function.component.ts @@ -426,6 +426,7 @@ export class ToscaGetFunctionComponent implements OnInit, OnChanges { } onPropertySourceChange(): void { + this.selectedProperty.reset(); if (!this.functionType || !this.propertySource.valid) { return; } diff --git a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.html b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.html index 2765fcce25..4e6993a1e4 100644 --- a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.html +++ b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.html @@ -5,8 +5,8 @@
-
- +
+
+
- -
- - +
+
+
+ + {{"VALUE_LABEL" | translate}} + {{"VALUE_EXPRESSION_LABEL" | translate}}
- -
- - +
+
+
+ +
- -
- +
+
+ {{"NODE_FILTER_SELECT_PROPERTY" | translate}} +
+
+
+ [rootProperty]="selectedProperty" + (expandChild)="selectedProperty.updateExpandedChildPropertyId($event)"> + *ngIf="!isComplexListMapType()" + [(value)]="currentRule.value" + class="rule-assigned-value" + data-tests-id="ruleAssignedValue" + (elementChanged)="onValueChange($event.isValid)" + [type]="selectedProperty ? selectedProperty.type : 'string'"> - -
-
diff --git a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.less b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.less index b475ed2847..36772a2f96 100644 --- a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.less +++ b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.less @@ -29,7 +29,10 @@ } &.operator{ width: 55px; - flex: 0 1 auto; + flex: 1 0 auto; + } + &.property { + flex: 2; } &.assigned-value-field { margin-bottom: 10px; diff --git a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts index eddebc999d..ba7a4946ca 100644 --- a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts +++ b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component.ts @@ -13,42 +13,30 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {Component} from '@angular/core'; +import {Component, OnInit} from '@angular/core'; import {InputBEModel, PropertyBEModel, PropertyFEModel} from 'app/models'; -import { - ConstraintObjectUI, - OPERATOR_TYPES -} from 'app/ng2/components/logic/service-dependencies/service-dependencies.component'; +import {SourceType} from 'app/ng2/components/logic/service-dependencies/service-dependencies.component'; import {DropdownValue} from 'app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component'; import {ServiceServiceNg2} from 'app/ng2/services/component-services/service.service'; import {PROPERTY_DATA} from 'app/utils'; import {ServiceInstanceObject} from '../../../models/service-instance-properties-and-interfaces'; -import { PropertiesUtils } from '../properties-assignment/services/properties.utils'; +import {PropertiesUtils} from '../properties-assignment/services/properties.utils'; +import {ToscaFunctionValidationEvent} from "../properties-assignment/tosca-function/tosca-function.component"; +import {InstanceFeDetails} from "../../../models/instance-fe-details"; +import {CompositionService} from "../composition/composition.service"; +import {ToscaGetFunction} from "../../../models/tosca-get-function"; +import {ToscaFunction} from "../../../models/tosca-function"; +import {ToscaFunctionType} from "../../../models/tosca-function-type.enum"; +import {ConstraintObjectUI} from "../../../models/ui-models/constraint-object-ui"; +import {OPERATOR_TYPES} from "../../../utils/filter-constraint-helper"; -export class UIDropDownSourceTypesElement extends DropdownValue { - options: any[]; - assignedLabel: string; - type: string; - - constructor(input?: any) { - super(input ? input.value || '' : "", input ? input.label || '' : ""); - if (input) { - this.options = input.options; - this.assignedLabel = input.assignedLabel; - this.type = input.type; - } - } -} - -// tslint:disable-next-line:max-classes-per-file @Component({ selector: 'service-dependencies-editor', templateUrl: './service-dependencies-editor.component.html', styleUrls: ['./service-dependencies-editor.component.less'], providers: [ServiceServiceNg2] }) - -export class ServiceDependenciesEditorComponent { +export class ServiceDependenciesEditorComponent implements OnInit { input: { serviceRuleIndex: number, @@ -61,139 +49,94 @@ export class ServiceDependenciesEditorComponent { operatorTypes: DropdownValue[], selectedInstanceSiblings: ServiceInstanceObject[] }; + //output + currentRule: ConstraintObjectUI; + currentServiceName: string; - selectedServiceProperties: PropertyBEModel[]; - selectedPropertyObj: PropertyFEModel; + selectedServiceProperties: PropertyBEModel[] = []; ddValueSelectedServicePropertiesNames: DropdownValue[]; operatorTypes: DropdownValue[]; - functionTypes: DropdownValue[]; - sourceTypes: UIDropDownSourceTypesElement[] = []; - currentRule: ConstraintObjectUI; currentIndex: number; - listOfValuesToAssign: DropdownValue[]; - listOfSourceOptions: PropertyBEModel[]; - assignedValueLabel: string; serviceRulesList: ConstraintObjectUI[]; + isLoading: false; + selectedProperty: PropertyFEModel; + selectedSourceType: string; + componentInstanceMap: Map = new Map(); SOURCE_TYPES = { - STATIC: {label: 'Static', value: 'static'}, - SERVICE_PROPERTY: {label: 'Service Property', value: 'property'}, - SERVICE_INPUT: {label: 'Service Input', value: 'service_input'} + STATIC: {label: 'Static', value: SourceType.STATIC}, + TOSCA_FUNCTION: {label: 'Tosca Function', value: SourceType.TOSCA_FUNCTION} }; - constructor(private propertiesUtils: PropertiesUtils) {} + constructor(private propertiesUtils: PropertiesUtils, private compositionService: CompositionService) {} - ngOnInit() { + ngOnInit(): void { this.currentIndex = this.input.serviceRuleIndex; this.serviceRulesList = this.input.serviceRules; - this.initFunctionTypes(); - this.initCurrentRule(); + if (this.input.selectedInstanceProperties) { + this.selectedServiceProperties = this.input.selectedInstanceProperties; + } this.currentServiceName = this.input.currentServiceName; this.operatorTypes = this.input.operatorTypes; - this.selectedServiceProperties = this.input.selectedInstanceProperties; - this.ddValueSelectedServicePropertiesNames = _.map(this.input.selectedInstanceProperties, (prop) => new DropdownValue(prop.name, prop.name)); - if (this.SOURCE_TYPES.STATIC.value !== this.currentRule.sourceType) { - this.loadSourceTypesData(); + if (this.compositionService.componentInstances) { + this.compositionService.componentInstances.forEach(value => { + this.componentInstanceMap.set(value.uniqueId, { + name: value.name + }); + }); } + this.initCurrentRule(); + this.initSelectedSourceType(); + this.selectedProperty = new PropertyFEModel(this.selectedServiceProperties.find(property => property.name === this.currentRule.servicePropertyName)); + this.selectedProperty.toscaFunction = undefined; + this.selectedProperty.value = undefined; + this.ddValueSelectedServicePropertiesNames = _.map(this.input.selectedInstanceProperties, (prop) => new DropdownValue(prop.name, prop.name)); this.syncRuleData(); - } - - private initCurrentRule() { - this.currentRule = this.serviceRulesList && this.input.serviceRuleIndex >= 0 ? - this.serviceRulesList[this.input.serviceRuleIndex] : - new ConstraintObjectUI({ - sourceName: this.SOURCE_TYPES.STATIC.value, - sourceType: this.SOURCE_TYPES.STATIC.value, - value: '', - constraintOperator: OPERATOR_TYPES.EQUAL - }); - if (this.currentRule && this.currentRule.sourceType === this.SOURCE_TYPES.STATIC.value){ - this.sourceTypes.push({ - label: this.SOURCE_TYPES.STATIC.label, - value: this.SOURCE_TYPES.STATIC.value, - assignedLabel: this.SOURCE_TYPES.STATIC.value, - type: this.SOURCE_TYPES.STATIC.value, - options: []}); + if (this.isValueToscaFunction(this.currentRule.value)) { + this.selectedProperty.toscaFunction = this.currentRule.value; } } - private initFunctionTypes() { - this.functionTypes = [ - {label: this.SOURCE_TYPES.STATIC.label, value: this.SOURCE_TYPES.STATIC.value}, - {label: this.SOURCE_TYPES.SERVICE_PROPERTY.label, value: this.SOURCE_TYPES.SERVICE_PROPERTY.value}, - {label: this.SOURCE_TYPES.SERVICE_INPUT.label, value: this.SOURCE_TYPES.SERVICE_INPUT.value}]; - } - - onServicePropertyChanged() { - if(this.SOURCE_TYPES.SERVICE_INPUT.value === this.currentRule.sourceType || this.SOURCE_TYPES.SERVICE_PROPERTY.value === this.currentRule.sourceType){ - this.currentRule.sourceName = "SELF"; + private initSelectedSourceType(): void { + if (!this.currentRule.sourceType || this.currentRule.sourceType === SourceType.STATIC) { + this.selectedSourceType = SourceType.STATIC; } else { - this.currentRule.sourceName = ""; + this.selectedSourceType = SourceType.TOSCA_FUNCTION; } - this.updateSelectedPropertyObj(); - this.updateOperatorTypesList(); - this.updateSourceTypesRelatedValues(); - this.currentRule.value = ""; - } - - onSelectFunctionType(value: any) { - this.currentRule.sourceName = ""; - this.listOfValuesToAssign = []; - this.currentRule.sourceType = value; - this.loadSourceTypesData(); - this.updateSourceTypesRelatedValues(); } - private loadSourceTypesData() { - const SELF = "SELF"; - if (this.SOURCE_TYPES.SERVICE_INPUT.value === this.currentRule.sourceType || this.SOURCE_TYPES.SERVICE_PROPERTY.value === this.currentRule.sourceType) { - this.currentRule.sourceName = SELF; - } - this.sourceTypes = []; - this.sourceTypes.push({ - label: SELF, - value: SELF, - assignedLabel: this.currentRule.sourceType == this.SOURCE_TYPES.SERVICE_PROPERTY.value - ? this.SOURCE_TYPES.SERVICE_PROPERTY.label : this.SOURCE_TYPES.SERVICE_INPUT.label, - type: this.currentRule.sourceType == this.SOURCE_TYPES.SERVICE_PROPERTY.value - ? this.SOURCE_TYPES.SERVICE_PROPERTY.value : this.SOURCE_TYPES.SERVICE_INPUT.value, - options: this.loadSourceTypeBySelectedFunction().get(this.currentRule.sourceType) - }); - - if (this.currentRule.sourceType !== this.SOURCE_TYPES.SERVICE_INPUT.value) { - if (this.input.selectedInstanceSiblings && this.isPropertyFunctionSelected) { - _.forEach(this.input.selectedInstanceSiblings, (sib) => - this.sourceTypes.push({ - label: sib.name, - value: sib.name, - options: sib.properties || [], - assignedLabel: this.SOURCE_TYPES.SERVICE_PROPERTY.label, - type: this.SOURCE_TYPES.SERVICE_PROPERTY.value - }) - ); - } + private initCurrentRule(): void { + if (this.serviceRulesList && this.input.serviceRuleIndex >= 0) { + this.currentRule = new ConstraintObjectUI(this.serviceRulesList[this.input.serviceRuleIndex]); + } else { + this.currentRule = new ConstraintObjectUI({ + sourceName: SourceType.STATIC, + sourceType: SourceType.STATIC, + value: '', + constraintOperator: OPERATOR_TYPES.EQUAL + }); } } - loadSourceTypeBySelectedFunction = (): any => { - let parentDataMap = new Map(); - parentDataMap.set(this.SOURCE_TYPES.SERVICE_PROPERTY.value, this.input.parentServiceProperties); - parentDataMap.set(this.SOURCE_TYPES.SERVICE_INPUT.value , this.input.parentServiceInputs); - return parentDataMap; + onServicePropertyChanged(): void { + this.currentRule.sourceName = undefined; + this.currentRule.value = undefined; + this.selectedProperty = undefined; + this.updateSelectedProperty(); + this.updateOperatorTypesList(); } - syncRuleData() { - if (!this.currentRule.sourceName || this.currentRule.sourceType === this.SOURCE_TYPES.STATIC.value) { - this.currentRule.sourceName = this.SOURCE_TYPES.STATIC.value; - this.currentRule.sourceType = this.SOURCE_TYPES.STATIC.value; + syncRuleData(): void { + if (!this.currentRule.sourceName || this.currentRule.sourceType === SourceType.STATIC) { + this.currentRule.sourceName = SourceType.STATIC; + this.currentRule.sourceType = SourceType.STATIC; } - this.updateSelectedPropertyObj(); + this.initSelectedProperty(); this.updateOperatorTypesList(); - this.updateSourceTypesRelatedValues(); } - updateOperatorTypesList() { - if (this.selectedPropertyObj && PROPERTY_DATA.SIMPLE_TYPES_COMPARABLE.indexOf(this.selectedPropertyObj.type) === -1) { + updateOperatorTypesList(): void { + if (this.selectedProperty && PROPERTY_DATA.SIMPLE_TYPES_COMPARABLE.indexOf(this.selectedProperty.type) === -1) { this.operatorTypes = [{label: '=', value: OPERATOR_TYPES.EQUAL}]; this.currentRule.constraintOperator = OPERATOR_TYPES.EQUAL; } else { @@ -201,84 +144,95 @@ export class ServiceDependenciesEditorComponent { } } - updateSourceTypesRelatedValues() { - if (this.currentRule.sourceName) { - const selectedSourceType: UIDropDownSourceTypesElement = this.sourceTypes.find( - (t) => t.value === this.currentRule.sourceName && t.type === this.currentRule.sourceType - ); - if (selectedSourceType) { - this.listOfSourceOptions = []; - this.listOfSourceOptions = selectedSourceType.options || []; - this.assignedValueLabel = selectedSourceType.assignedLabel || this.SOURCE_TYPES.STATIC.label; - this.filterOptionsByType(); - } - } + onValueChange(isValidValue:any): void { + this.currentRule.updateValidity(isValidValue); } - onChangePage(newIndex:any) { - if (newIndex >= 0 && newIndex < this.input.serviceRules.length) { - this.currentIndex = newIndex; - this.currentRule = this.serviceRulesList[newIndex]; - this.syncRuleData(); - } + checkFormValidForSubmit(): boolean { + return this.currentRule.isValidRule(); } - filterOptionsByType() { - if (!this.selectedPropertyObj) { - this.listOfValuesToAssign = []; + initSelectedProperty(): void { + if (!this.currentRule.servicePropertyName) { + this.selectedProperty = undefined; return; } - this.listOfValuesToAssign = this.listOfSourceOptions.reduce((result, op: PropertyBEModel) => { - if (op.type === this.selectedPropertyObj.type && (!op.schemaType || op.schemaType === this.selectedPropertyObj.schemaType)) { - result.push(new DropdownValue(op.name, op.name)); - } - return result; - }, []); - } - onValueChange(isValidValue:any) { - this.currentRule.updateValidity(isValidValue); + const newProperty = new PropertyFEModel(this.selectedServiceProperties.find(property => property.name === this.currentRule.servicePropertyName)); + newProperty.value = undefined; + newProperty.toscaFunction = undefined; + if (typeof this.currentRule.value === 'string') { + newProperty.value = this.currentRule.value; + } else if (this.isValueToscaFunction(newProperty.value)) { + newProperty.toscaFunction = this.currentRule.value; + newProperty.value = (this.currentRule.value).buildValueString(); + } else { + newProperty.value = JSON.stringify(this.currentRule.value); + } + this.propertiesUtils.initValueObjectRef(newProperty); + this.selectedProperty = newProperty; } - checkFormValidForSubmit() { - if (!this.serviceRulesList) { // for create modal - const isStatic = this.currentRule.sourceName === this.SOURCE_TYPES.STATIC.value; - return this.currentRule.isValidRule(isStatic); + updateSelectedProperty(): void { + this.selectedProperty = undefined; + if (!this.currentRule.servicePropertyName) { + return; + } + + const newProperty = new PropertyFEModel(this.selectedServiceProperties.find(property => property.name === this.currentRule.servicePropertyName)); + newProperty.value = undefined; + newProperty.toscaFunction = undefined; + if (this.isValueToscaFunction(newProperty.value)) { + newProperty.toscaFunction = this.currentRule.value; } - // for update all rules - return this.serviceRulesList.every((rule) => rule.isValidRule(rule.sourceName === this.SOURCE_TYPES.STATIC.value)); + this.propertiesUtils.initValueObjectRef(newProperty); + this.selectedProperty = newProperty; } - updateSelectedPropertyObj(): void { - this.selectedPropertyObj = null; - if (this.currentRule.servicePropertyName) { - let newProp = new PropertyFEModel(_.find(this.selectedServiceProperties, (prop) => prop.name === this.currentRule.servicePropertyName)); - newProp.value = JSON.stringify(this.currentRule.value); - this.propertiesUtils.initValueObjectRef(newProp); - console.log("TEST" + newProp.value); - setTimeout(() => { - this.selectedPropertyObj = newProp}) - this.selectedPropertyObj = newProp; - } + isValueToscaFunction(value: any): boolean { + return value instanceof Object && 'type' in value && (Object).values(ToscaFunctionType).includes(value.type); } isStaticSource(): boolean { - return this.currentRule.sourceType === this.SOURCE_TYPES.STATIC.value + return this.selectedSourceType === SourceType.STATIC } - isPropertyFunctionSelected(): boolean { - return this.currentRule.sourceType === this.SOURCE_TYPES.SERVICE_PROPERTY.value; + isToscaFunctionSource(): boolean { + return this.selectedSourceType === SourceType.TOSCA_FUNCTION } isComplexListMapType(): boolean { - return this.selectedPropertyObj && this.selectedPropertyObj.derivedDataType > 0; + return this.selectedProperty && this.selectedProperty.derivedDataType > 0; } updateComplexListMapTypeRuleValue(): void { - let value = PropertyFEModel.cleanValueObj(this.selectedPropertyObj.valueObj); - this.currentRule.value = JSON.stringify(value); - this.onValueChange(this.selectedPropertyObj.valueObjIsValid); + this.currentRule.value = PropertyFEModel.cleanValueObj(this.selectedProperty.valueObj); + this.onValueChange(this.selectedProperty.valueObjIsValid); + } + + onToscaFunctionValidityChange(validationEvent: ToscaFunctionValidationEvent): void { + if (validationEvent.isValid && validationEvent.toscaFunction) { + this.currentRule.value = validationEvent.toscaFunction; + this.currentRule.sourceType = validationEvent.toscaFunction.type + if (validationEvent.toscaFunction instanceof ToscaGetFunction) { + this.currentRule.sourceName = validationEvent.toscaFunction.sourceName; + } + } else { + this.currentRule.updateValidity(false); + this.currentRule.value = undefined; + this.currentRule.sourceType = undefined; + this.currentRule.sourceName = undefined; + } + } + + onSourceTypeChange(): void { + this.currentRule.value = undefined; + this.currentRule.sourceType = this.selectedSourceType; + if (this.isStaticSource()) { + this.currentRule.sourceName = SourceType.STATIC; + } + this.updateSelectedProperty(); } } diff --git a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts index cfa466ffa3..d5104c803f 100644 --- a/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts +++ b/catalog-ui/src/app/ng2/pages/service-dependencies-editor/service-dependencies-editor.module.ts @@ -5,6 +5,8 @@ import { FormElementsModule } from 'app/ng2/components/ui/form-components/form-e import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module'; import { ServiceDependenciesEditorComponent } from './service-dependencies-editor.component'; import { PropertyTableModule } from 'app/ng2/components/logic/properties-table/property-table.module'; +import {TranslateModule} from "../../shared/translator/translate.module"; +import {ToscaFunctionModule} from "../properties-assignment/tosca-function/tosca-function.module"; @NgModule({ declarations: [ @@ -15,7 +17,9 @@ import { PropertyTableModule } from 'app/ng2/components/logic/properties-table/p FormsModule, FormElementsModule, UiElementsModule, - PropertyTableModule + PropertyTableModule, + TranslateModule, + ToscaFunctionModule ], exports: [], entryComponents: [ diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts index c9bb4d59f5..450e66ead2 100644 --- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts @@ -44,15 +44,13 @@ import {HttpClient, HttpHeaders, HttpParams} from "@angular/common/http"; import {BEOperationModel, InterfaceModel} from "../../../models/operation"; import {PropertyBEModel} from "../../../models/properties-inputs/property-be-model"; import {PolicyInstance} from "../../../models/graph/zones/policy-instance"; -import { - ConstraintObject -} from "../../components/logic/service-dependencies/service-dependencies.component"; import {OutputBEModel} from "app/models/attributes-outputs/output-be-model"; import {HttpHelperService} from '../http-hepler.service'; import { BEInterfaceOperationModel, InterfaceOperationModel } from "../../../models/interfaceOperation"; +import {FilterConstraint} from "../../../models/filter-constraint"; /* PLEASE DO NOT USE THIS SERVICE IN ANGULAR2! Use the topology-template.service instead @@ -474,11 +472,11 @@ export class ComponentServiceNg2 { return this.getComponentDataByFieldsName(component.componentType, component.uniqueId, [SERVICE_FIELDS.NODE_FILTER]); } - createServiceFilterConstraints(component: Component, componentInstance: ComponentInstance, constraint: ConstraintObject): Observable { + createServiceFilterConstraints(component: Component, componentInstance: ComponentInstance, constraint: FilterConstraint): Observable { return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter', constraint); } - updateServiceFilterConstraints(component: Component, componentInstance: ComponentInstance, constraints: ConstraintObject[]): Observable { + updateServiceFilterConstraints(component: Component, componentInstance: ComponentInstance, constraints: FilterConstraint[]): Observable { return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstances/' + componentInstance.uniqueId + '/nodeFilter/', constraints); } diff --git a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts index c497e013b4..5f6f074f5e 100644 --- a/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/topology-template.service.ts @@ -54,14 +54,14 @@ import {ServiceGenericResponse} from "../responses/service-generic-response"; import {HttpClient, HttpHeaders, HttpParams} from "@angular/common/http"; import {HttpHelperService} from "../http-hepler.service"; import {ConsumptionInput} from "../../components/logic/service-consumption/service-consumption.component"; -import {ConstraintObject} from "../../components/logic/service-dependencies/service-dependencies.component"; import {PolicyInstance} from "../../../models/graph/zones/policy-instance"; import {PropertyBEModel} from "../../../models/properties-inputs/property-be-model"; import {map} from "rxjs/operators"; -import {CapabilitiesConstraintObject} from "../../components/logic/capabilities-constraint/capabilities-constraint.component"; +import {CapabilityFilterConstraint} from "../../../models/capability-filter-constraint"; import {BEInterfaceOperationModel, InterfaceOperationModel} from "../../../models/interfaceOperation"; import {AttributeBEModel} from "../../../models/attributes-outputs/attribute-be-model"; import {InstanceAttributesAPIMap} from "../../../models/attributes-outputs/attribute-fe-map"; +import {FilterConstraint} from "../../../models/filter-constraint"; /* we need to use this service from now, we will remove component.service when we finish remove the angular1. The service is duplicated since we can not use downgrades service with NGXS*/ @@ -477,19 +477,19 @@ export class TopologyTemplateService { [COMPONENT_FIELDS.COMPONENT_CAPABILITIES, COMPONENT_FIELDS.COMPONENT_CAPABILITIES_PROPERTIES]); } - createServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraint: ConstraintObject, componentType: string, constraintType: string): Observable { + createServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraint: FilterConstraint, componentType: string, constraintType: string): Observable { return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/componentInstance/' + componentInstanceId + '/' + constraintType + '/nodeFilter', constraint); } - createServiceFilterCapabilitiesConstraints(componentMetaDataId: string, componentInstanceId: string, constraint: CapabilitiesConstraintObject, componentType: string, constraintType: string): Observable { + createServiceFilterCapabilitiesConstraints(componentMetaDataId: string, componentInstanceId: string, constraint: CapabilityFilterConstraint, componentType: string, constraintType: string): Observable { return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/componentInstance/' + componentInstanceId + '/' + constraintType + '/nodeFilter', constraint); } - updateServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraints: ConstraintObject, componentType: string, constraintType: string, constraintIndex: number):Observable{ - return this.http.put(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/componentInstance/' + componentInstanceId + '/' + constraintType + '/' + constraintIndex + '/nodeFilter', constraints) + updateServiceFilterConstraints(componentMetaDataId: string, componentInstanceId: string, constraint: FilterConstraint, componentType: string, constraintType: string, constraintIndex: number):Observable{ + return this.http.put(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/componentInstance/' + componentInstanceId + '/' + constraintType + '/' + constraintIndex + '/nodeFilter', constraint) } - updateServiceFilterCapabilitiesConstraint(componentMetaDataId: string, componentInstanceId: string, constraints: CapabilitiesConstraintObject, componentType: string, constraintType: string, constraintIndex: number):Observable{ + updateServiceFilterCapabilitiesConstraint(componentMetaDataId: string, componentInstanceId: string, constraints: CapabilityFilterConstraint, componentType: string, constraintType: string, constraintIndex: number):Observable{ return this.http.put(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/componentInstance/' + componentInstanceId + '/' + constraintType + '/' + constraintIndex + '/nodeFilter', constraints) } @@ -501,12 +501,14 @@ export class TopologyTemplateService { return this.getComponentDataByFieldsName(componentType, componentId, [COMPONENT_FIELDS.COMPONENT_PROPERTIES, COMPONENT_FIELDS.COMPONENT_INPUTS]); } - createSubstitutionFilterConstraints(componentMetaDataId: string, constraint: ConstraintObject, componentType: string, constraintType: string): Observable { + createSubstitutionFilterConstraints(componentMetaDataId: string, constraint: FilterConstraint, componentType: string, constraintType: string): Observable { return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/substitutionFilter/' + constraintType, constraint); } - updateSubstitutionFilterConstraints(componentMetaDataId: string, constraint: ConstraintObject[], componentType: string, constraintType: string): Observable{ - return this.http.put(this.baseUrl + this.getServerTypeUrl(componentType) + componentMetaDataId + '/substitutionFilter/' + constraintType, constraint); + updateSubstitutionFilterConstraint(componentId: string, constraint: FilterConstraint, componentType: string, constraintType: string, + index: number): Observable { + const url = `${this.baseUrl}${this.getServerTypeUrl(componentType)}${componentId}/substitutionFilter/${constraintType}/${index}`; + return this.http.put(url, constraint); } deleteSubstitutionFilterConstraints(componentMetaDataId: string, constraintIndex: number, componentType: string, constraintType: string): Observable{ diff --git a/catalog-ui/src/app/utils/filter-constraint-helper.ts b/catalog-ui/src/app/utils/filter-constraint-helper.ts new file mode 100644 index 0000000000..bdb3f9ec7a --- /dev/null +++ b/catalog-ui/src/app/utils/filter-constraint-helper.ts @@ -0,0 +1,64 @@ +import {FilterConstraint} from "../models/filter-constraint"; +import {ToscaFunctionType} from "../models/tosca-function-type.enum"; +import {ToscaConcatFunction} from "../models/tosca-concat-function"; +import {ToscaGetFunction} from "../models/tosca-get-function"; +import {YamlFunction} from "../models/yaml-function"; +import {CapabilityFilterConstraint} from "../models/capability-filter-constraint"; + +export class FilterConstraintHelper { + + public static buildFilterConstraintLabel(constraint: FilterConstraint | CapabilityFilterConstraint): string { + let value; + if (this.isValueToscaFunction(constraint.value)) { + switch (constraint.value.type) { + case ToscaFunctionType.CONCAT: + value = new ToscaConcatFunction(constraint.value).buildValueString(); + break; + case ToscaFunctionType.GET_PROPERTY: + case ToscaFunctionType.GET_INPUT: + case ToscaFunctionType.GET_ATTRIBUTE: + value = new ToscaGetFunction(constraint.value).buildValueString(); + break; + case ToscaFunctionType.YAML: + value = new YamlFunction(constraint.value).buildValueString(); + break; + case ToscaFunctionType.STRING: + value = constraint.value.value; + break; + default: + value = JSON.stringify(constraint.value, null, 4); + } + } else { + value = JSON.stringify(constraint.value, null, 4); + } + if (constraint instanceof CapabilityFilterConstraint) { + return `${constraint.capabilityName}: ${constraint.servicePropertyName} ${this.convertToSymbol(constraint.constraintOperator)} ${value}`; + } + + return `${constraint.servicePropertyName} ${this.convertToSymbol(constraint.constraintOperator)} ${value}`; + } + + public static convertToSymbol(constraintOperator: string) { + switch (constraintOperator) { + case OPERATOR_TYPES.LESS_THAN: return '<'; + case OPERATOR_TYPES.EQUAL: return '='; + case OPERATOR_TYPES.GREATER_THAN: return '>'; + case OPERATOR_TYPES.GREATER_OR_EQUAL: return '>='; + case OPERATOR_TYPES.LESS_OR_EQUAL: return '<='; + } + } + + private static isValueToscaFunction(value: any): boolean { + return value instanceof Object && 'type' in value && (Object).values(ToscaFunctionType).includes(value.type); + } + +} + +export const OPERATOR_TYPES = { + EQUAL: 'equal', + GREATER_THAN: 'greater_than', + LESS_THAN: 'less_than', + GREATER_OR_EQUAL: 'greater_or_equal', + LESS_OR_EQUAL: 'less_or_equal' +}; + -- cgit 1.2.3-korg