Create UI Component for viewing property constraints 95/131495/13
authorJvD_Ericsson <jeff.van.dam@est.tech>
Thu, 13 Oct 2022 18:13:37 +0000 (19:13 +0100)
committerAndr� Schmid <andre.schmid@est.tech>
Thu, 17 Nov 2022 11:38:37 +0000 (11:38 +0000)
Issue-ID: SDC-4219
Signed-off-by: JvD_Ericsson <jeff.van.dam@est.tech>
Change-Id: Ia0e40e2ed2fd954749a74ce307f1474380f9ad71

catalog-ui/src/app/modules/directive-module.ts
catalog-ui/src/app/ng2/app.module.ts
catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.html [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.less [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.spec.ts [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.component.ts [new file with mode: 0644]
catalog-ui/src/app/ng2/pages/properties-assignment/constraints/constraints.module.ts [new file with mode: 0644]
catalog-ui/src/app/view-models/forms/property-forms/base-property-form/property-form-base.less
catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html

index 70ceb0f..e339b5d 100644 (file)
@@ -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: [],
index 801b663..1e23bb6 100644 (file)
@@ -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 (file)
index 0000000..301d196
--- /dev/null
@@ -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 (file)
index 0000000..40dc956
--- /dev/null
@@ -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 (file)
index 0000000..bfee769
--- /dev/null
@@ -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 (file)
index 0000000..ef4d6fd
--- /dev/null
@@ -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 (file)
index 0000000..4f14e1f
--- /dev/null
@@ -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 { }
index 15e30af..8682dd7 100644 (file)
@@ -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;
index 105bef3..35e3932 100644 (file)
                         </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>