diff options
9 files changed, 508 insertions, 1 deletions
diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index 70ceb0fed3..e339b5d471 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -96,6 +96,7 @@ import {DistributionComponent} from '../ng2/pages/workspace/disribution/distribu import {AttributesOutputsComponent} from "../ng2/pages/attributes-outputs/attributes-outputs.page.component"; import {InterfaceDefinitionComponent} from "../ng2/pages/interface-definition/interface-definition.page.component"; import {ToscaFunctionComponent} from '../ng2/pages/properties-assignment/tosca-function/tosca-function.component'; +import {ConstraintsComponent} from '../ng2/pages/properties-assignment/constraints/constraints.component'; import {TypeWorkspaceComponent} from "../ng2/pages/type-workspace/type-workspace.component"; import {TypeWorkspaceGeneralComponent} from "../ng2/pages/type-workspace/type-workspace-general/type-workspace-general.component"; @@ -324,6 +325,12 @@ directiveModule.directive('toscaFunction', downgradeComponent({ outputs: [] }) as angular.IDirectiveFactory); +directiveModule.directive('appConstraints', downgradeComponent({ + component: ConstraintsComponent, + inputs: ['property', 'isViewOnly'], + outputs: ['onConstraintChange'] +}) as angular.IDirectiveFactory); + directiveModule.directive('appTypeWorkspace', downgradeComponent({ component: TypeWorkspaceComponent, inputs: [], diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 801b663d69..1e23bb6c4e 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -100,6 +100,7 @@ import {ServiceDependenciesEditorModule} from './pages/service-dependencies-edit import {PropertyCreatorModule} from './pages/properties-assignment/property-creator/property-creator.module'; import {DeclareListModule} from './pages/properties-assignment/declare-list/declare-list.module'; import {ToscaFunctionModule} from "./pages/properties-assignment/tosca-function/tosca-function.module"; +import {ConstraintsModule} from "./pages/properties-assignment/constraints/constraints.module"; import {WorkflowServiceNg2} from './services/workflow.service'; import {ToscaTypesServiceNg2} from "./services/tosca-types.service"; import {InterfaceOperationHandlerModule} from "./pages/composition/interface-operatons/operation-creator/interface-operation-handler.module"; @@ -159,6 +160,7 @@ export function configServiceFactory(config: ConfigService, authService: Authent PropertyCreatorModule, DeclareListModule, ToscaFunctionModule, + ConstraintsModule, PluginFrameModule, PluginsModule, InterfaceOperationModule, diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html new file mode 100644 index 0000000000..301d196d41 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html @@ -0,0 +1,97 @@ +<!-- + ~ - + ~ ============LICENSE_START======================================================= + ~ Copyright (C) 2022 Nordix Foundation. + ~ ================================================================================ + ~ 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========================================================= + --> + +<div class="app-constraints"> + <form novalidate class="w-sdc-form two-columns"> + <div class="w-sdc-form-columns-wrapper" *ngFor="let constraint of constraints; let constraintIndex = index"> + <div class="w-sdc-form-column-small"> + <select class="i-sdc-form-select" + data-tests-id="constraints" + [disabled]="isViewOnly" + (change)="onChangeConstraintType(constraintIndex, $event.target.value)"> + <option *ngIf="constraint" [value]="constraint.type" + hidden selected> + {{ConstraintTypesMapping[constraint.type]}} + </option> + <option *ngFor="let constraintType of constraintTypes" [value]="constraintType"> + {{ConstraintTypesMapping[constraintType]}} + </option> + </select> + </div> + + + <div class="w-sdc-form-columns-wrapper"> + + <div class="w-sdc-form-column"> + <div class="w-sdc-form-columns-wrapper" *ngIf="constraint.type == 'inRange'"> + <div class="w-sdc-form-column"> + <input type="text" class="i-sdc-form-input myClass" + (change)="onChangeConstrainValueIndex(constraintIndex, $event.target.value, 0)" + [disabled]="isViewOnly" + [value]="getInRangeValue(constraintIndex, 0)"/> + </div> + <div class="w-sdc-form-column"> + <input type="text" class="i-sdc-form-input myClass" + (change)="onChangeConstrainValueIndex(constraintIndex, $event.target.value, 1)" + [disabled]="isViewOnly" + [value]="getInRangeValue(constraintIndex, 1)"/> + </div> + </div> + + <div *ngIf="constraint.type == 'validValues'"> + <div class="w-sdc-form-columns-wrapper-block"> + <div class="add-btn add-list-item w-sdc-form-column-block" + [ngClass]="{'disabled': isViewOnly}" + (click)="addToList(constraintIndex)">Add to List</div> + </div> + <div class="w-sdc-form-columns-wrapper" *ngFor="let value of constraint.value; let valueIndex = index"> + <div class="w-sdc-form-column"> + <input type="text" class="i-sdc-form-input" [value]="value" + [disabled]="isViewOnly" + (change)="onChangeConstrainValueIndex(constraintIndex, $event.target.value, valueIndex)"/> + </div> + <div class="w-sdc-form-column"> + <span class="sprite-new delete-btn" [ngClass]="{'disabled': isViewOnly}" (click)="removeFromList(constraintIndex, valueIndex)"></span> + </div> + </div> + </div> + + <div *ngIf="constraint.type != 'inRange' && constraint.type != 'validValues'"> + <input type="text" class="i-sdc-form-input myClass" + (change)="onChangeConstraintValue(constraintIndex, $event.target.value)" + [value]="constraint.value"/> + </div> + </div> + + <div class="w-sdc-form-column-vsmall"> + <span class="sprite-new delete-btn" [ngClass]="{'disabled': isViewOnly}" (click)="removeConstraint(constraintIndex)"></span> + </div> + </div> + + + </div> + <div class="w-sdc-form-columns-wrapper-small" *ngIf="!isViewOnly"> + <div class="add-btn add-list-item w-sdc-form-column-small" *ngIf="!isViewOnly" [ngClass]="{'disabled': isViewOnly}" + (click)="addConstraint()"> Add Constraint </div> + </div> + + </form> +</div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.less new file mode 100644 index 0000000000..40dc956934 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.less @@ -0,0 +1,72 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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========================================================= + */ + +@import '../../../../../assets/styles/variables.less'; + +.w-sdc-form-column-small { + width: 30%; + margin: 0; + padding: 0 6% 0 0; + text-align: left; + + &:last-child { + padding: 0; + } +} + +.w-sdc-form-columns-wrapper { + padding-bottom: 10px; + width: 100%; +} + +.w-sdc-form-columns-wrapper-block { + + display: block; + height: 30px; + + .w-sdc-form-column-block { + display: block; + width: 100%; + margin: 0; + padding: 0 6% 0 0; + text-align: left; + } + +} + +.w-sdc-form-columns-wrapper-small { + + display: flex; + justify-content: space-between; + width: 55%; + +} + +.w-sdc-form-columns-wrapper-vsmall { + + display: flex; + justify-content: space-between; + width: 15%; + +} + +.disabled { + pointer-events: none; + opacity: 50%; +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.spec.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.spec.ts new file mode 100644 index 0000000000..bfee76910e --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.spec.ts @@ -0,0 +1,44 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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========================================================= + */ + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ConstraintsComponent } from './constraints.component'; + +describe('ConstraintsComponent', () => { + let component: ConstraintsComponent; + let fixture: ComponentFixture<ConstraintsComponent>; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ConstraintsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ConstraintsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts new file mode 100644 index 0000000000..ef4d6fd954 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts @@ -0,0 +1,240 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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========================================================= + */ + +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { PropertyBEModel } from "app/models"; + +@Component({ + selector: 'app-constraints', + templateUrl: './constraints.component.html', + styleUrls: ['./constraints.component.less'] +}) +export class ConstraintsComponent implements OnInit { + + @Input() set property(property: PropertyBEModel) { + this.constraints = new Array(); + if(property.constraints) { + this._property = property; + property.constraints.forEach((constraint: any) => { + this.constraints.push(this.getConstraintFromPropertyBEModel(constraint)); + }); + } + } + @Input() isViewOnly: boolean = false; + @Output() onConstraintChange: EventEmitter<any[]> = new EventEmitter<any[]>(); + + constraints: Constraint[]; + constraintTypes: string[]; + ConstraintTypesMapping = ConstraintTypesMapping; + newConstraintType: any = ConstraintTypes.equal; + newConstraintValue: any = null; + _property: PropertyBEModel; + + ngOnInit() { + this.constraintTypes = Object.keys(ConstraintTypes).map(key => ConstraintTypes[key]); + } + + private getConstraintFromPropertyBEModel(constraint: any):Constraint { + let constraintType: ConstraintTypes; + let constraintValue: any; + if(constraint.validValues){ + constraintType = ConstraintTypes.valid_values; + constraintValue = constraint.validValues; + } else if(constraint.equal) { + constraintType = ConstraintTypes.equal; + constraintValue = constraint.equal; + } else if(constraint.greaterThan) { + constraintType = ConstraintTypes.greater_than; + constraintValue = constraint.greaterThan; + } else if(constraint.greaterOrEqual) { + constraintType = ConstraintTypes.greater_or_equal; + constraintValue = constraint.greaterOrEqual; + } else if(constraint.lessThan) { + constraintType = ConstraintTypes.less_than; + constraintValue = constraint.lessThan; + } else if(constraint.lessOrEqual) { + constraintType = ConstraintTypes.less_or_equal; + constraintValue = constraint.lessOrEqual; + } else if(constraint.rangeMinValue && constraint.rangeMaxValue) { + constraintType = ConstraintTypes.in_range; + constraintValue = new Array(constraint.rangeMinValue, constraint.rangeMaxValue); + } else if(constraint.length) { + constraintType = ConstraintTypes.length; + constraintValue = constraint.length; + } else if(constraint.minLength) { + constraintType = ConstraintTypes.min_length; + constraintValue = constraint.minLength; + } else if(constraint.maxLength) { + constraintType = ConstraintTypes.max_length; + constraintValue = constraint.maxLength; + } else if(constraint.pattern) { + constraintType = ConstraintTypes.pattern; + constraintValue = constraint.pattern; + } + return { + type:constraintType, + value:constraintValue + } + } + + private getConstraintsFormat(): any[] { + let constraintArray = new Array(); + this.constraints.forEach((constraint: Constraint) => { + constraintArray.push(this.getConstraintFormat(constraint)) + }); + return constraintArray; + } + + private getConstraintFormat(constraint: Constraint) { + switch (constraint.type) { + case ConstraintTypes.equal: + return { + [ConstraintTypes.equal]: constraint.value + } + case ConstraintTypes.less_or_equal: + return { + [ConstraintTypes.less_or_equal]: constraint.value + } + case ConstraintTypes.less_than: + return { + [ConstraintTypes.less_than]: constraint.value + } + case ConstraintTypes.greater_or_equal: + return { + [ConstraintTypes.greater_or_equal]: constraint.value + } + case ConstraintTypes.greater_than: + return { + [ConstraintTypes.greater_than]: constraint.value + } + case ConstraintTypes.in_range: + return { + [ConstraintTypes.in_range]: constraint.value + } + case ConstraintTypes.length: + return { + [ConstraintTypes.length]: constraint.value + } + case ConstraintTypes.max_length: + return { + [ConstraintTypes.max_length]: constraint.value + } + case ConstraintTypes.min_length: + return { + [ConstraintTypes.min_length]: constraint.value + } + case ConstraintTypes.pattern: + return { + [ConstraintTypes.pattern]: constraint.value + } + case ConstraintTypes.valid_values: + return { + [ConstraintTypes.valid_values]: constraint.value + } + default: + return; + } + } + + removeFromList(constraintIndex: number, valueIndex: number){ + this.constraints[constraintIndex].value.splice(valueIndex, 1); + } + + addToList(constraintIndex: number){ + if (!this.constraints[constraintIndex].value) { + this.constraints[constraintIndex].value = new Array(); + } + this.constraints[constraintIndex].value.push(""); + } + + onChangeConstraintType(constraintIndex: number, newType: ConstraintTypes) { + this.constraints[constraintIndex].type = newType; + if ((newType == ConstraintTypes.in_range || newType == ConstraintTypes.valid_values) && !Array.isArray(this.constraints[constraintIndex].value)) { + this.constraints[constraintIndex].value = new Array() + } + } + + onChangeConstraintValue(constraintIndex: number, newValue: any) { + this.constraints[constraintIndex].value = newValue; + } + + onChangeConstrainValueIndex(constraintIndex: number, newValue: any, valueIndex: number) { + if(!this.constraints[constraintIndex].value) { + this.constraints[constraintIndex].value = new Array(); + } + this.constraints[constraintIndex].value[valueIndex] = newValue; + } + + removeConstraint(constraintIndex: number) { + this.constraints.splice(constraintIndex, 1); + this.onConstraintChange.emit(this.getConstraintsFormat()); +} + + addConstraint() { + let newConstraint: Constraint = { + type:this.newConstraintType, + value: this.newConstraintValue + } + this.constraints.push(newConstraint); + this.newConstraintValue = null; + this.onConstraintChange.emit(this.getConstraintsFormat()); + } + + getInRangeValue(constraintIndex: number, valueIndex: number): string { + if(!this.constraints[constraintIndex].value || !this.constraints[constraintIndex].value[valueIndex]) { + return ""; + } + return this.constraints[constraintIndex].value[valueIndex]; + } + +} + +export enum ConstraintTypes { + equal= "equal", + greater_than = "greaterThan", + greater_or_equal = "greaterOrEqual", + less_than = "lessThan", + less_or_equal = "lessOrEqual", + in_range = "inRange", + valid_values = "validValues", + length = "length", + min_length = "minLength", + max_length = "maxLength", + pattern = "pattern" +} + +export const ConstraintTypesMapping = { + [ConstraintTypes.equal]: "equal", + [ConstraintTypes.greater_than]: "greater_than", + [ConstraintTypes.greater_or_equal]: "greater_or_equal", + [ConstraintTypes.less_than]: "less_than", + [ConstraintTypes.less_or_equal]: "less_or_equal", + [ConstraintTypes.in_range]: "in_range", + [ConstraintTypes.valid_values]: "valid_values", + [ConstraintTypes.length]: "length", + [ConstraintTypes.min_length]: "min_length", + [ConstraintTypes.max_length]: "max_length", + [ConstraintTypes.pattern]: "pattern" +}; + +export interface Constraint { + type:ConstraintTypes, + value:any + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.module.ts new file mode 100644 index 0000000000..4f14e1f855 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.module.ts @@ -0,0 +1,36 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 Nordix Foundation + * ================================================================================ + * 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========================================================= + */ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ConstraintsComponent } from './constraints.component'; +import { FormsModule } from '@angular/forms'; + +@NgModule({ + imports: [ + CommonModule, + FormsModule + ], + declarations: [ConstraintsComponent], + exports: [ConstraintsComponent], + entryComponents: [ + ConstraintsComponent + ], +}) + +export class ConstraintsModule { } diff --git a/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base.less b/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base.less index 15e30af4ee..8682dd79fe 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base.less +++ b/catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base.less @@ -55,7 +55,7 @@ top: 13px; } - .default-value-section{ + .default-value-section, .constraints-section { border-top: solid 1px @main_color_a; padding-top: 15px; margin-top: 15px; diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html index 105bef3ea9..35e3932586 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html @@ -261,6 +261,15 @@ </div> </div> </div> + <div class="constraints-section i-sdc-form-item" data-ng-if="editPropertyModel.property.constraints || !(isViewOnly || componentMetadata.isService)"> + <label class="i-sdc-form-label">Constraints</label> + <ng-container> + <app-constraints [property]="editPropertyModel.property" + [is-view-only]="isViewOnly || componentMetadata.isService" + (on-constraint-change)="onConstraintChange($event)"> + </app-constraints> + </ng-container> + </div> <span class="w-sdc-form-note" data-ng-show="forms.editForm.$invalid && false" translate="LABEL_ALL_FIELDS_ARE_MANDATORY"></span> </form> </perfect-scrollbar> |