diff options
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/properties-assignment')
8 files changed, 295 insertions, 9 deletions
diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html index ca3e90fbc2..8a3e8d23ee 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html @@ -29,12 +29,14 @@ [readonly]="isReadonly || resourceIsReadonly" [isLoading]="loadingProperties || savingChangedData" [hasDeclareOption]="true" + [showDelete]="!isReadOnly && isSelf()" (propertyChanged)="dataChanged($event)" (propertySelected)="propertySelected($event)" (selectPropertyRow)="selectPropertyRow($event)" (selectChildProperty)="selectChildProperty($event)" (updateCheckedPropertyCount)="updateCheckedPropertyCount($event)" - (selectInstanceRow)="selectInstanceRow($event)"> + (selectInstanceRow)="selectInstanceRow($event)" + (deleteProperty)="deleteProperty($event)"> </properties-table> </tab> <tab tabTitle="Inputs"> @@ -63,8 +65,10 @@ <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button">Declare</button> </div> </div> - <div class="right-column gray-border"> - <tabs #hierarchyNavTabs tabStyle="simple-tabs"> + <div class="right-column"> + <div *ngIf="!isReadonly" class="add-btn" + (click)="addProperty()" [ngClass]="{'disabled': !isSelf()}">Add Property</div> + <tabs #hierarchyNavTabs tabStyle="simple-tabs" class="gray-border"> <tab tabTitle="Composition"> <div class="hierarchy-nav-container"> <loader [display]="loadingInstances" [size]="'medium'" [relative]="true" [loaderDelay]="500"></loader> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less index 6de6dda7bb..95ff94317c 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less @@ -131,8 +131,14 @@ display:flex; flex:0 0 350px; flex-direction:column; - margin: 45px 0 0 1em; + margin: 0px 0 0 1em; overflow-x:auto; + .add-btn{ + + align-self: flex-end; + margin-top: 10px; + margin-bottom: 19px; + } /deep/ .tabs { border-bottom: solid 1px #d0d0d0; diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 5a21e86879..953c973d1a 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -38,12 +38,14 @@ import {ComponentModeService} from "../../services/component-services/component- import {ModalService} from "../../services/modal.service"; import {Tabs, Tab} from "../../components/ui/tabs/tabs.component"; import {InputsUtils} from "./services/inputs.utils"; +import {PropertyCreatorComponent} from "./property-creator/property-creator.component"; import { InstanceFeDetails } from "../../../models/instance-fe-details"; import { SdcUiComponents } from "sdc-ui/lib/angular"; //import { ModalService as ModalServiceSdcUI} from "sdc-ui/lib/angular/modals/modal.service"; import { IModalButtonComponent } from "sdc-ui/lib/angular/modals/models/modal-config"; import { UnsavedChangesComponent } from "app/ng2/components/ui/forms/unsaved-changes/unsaved-changes.component"; +const SERVICE_SELF_TITLE = "SELF"; @Component({ templateUrl: './properties-assignment.page.component.html', styleUrls: ['./properties-assignment.page.component.less'] @@ -84,6 +86,7 @@ export class PropertiesAssignmentComponent { isValidChangedData:boolean; savingChangedData:boolean; stateChangeStartUnregister:Function; + serviceBePropertiesMap: InstanceBePropertiesMap; @ViewChild('hierarchyNavTabs') hierarchyNavTabs: Tabs; @ViewChild('propertyInputTabs') propertyInputTabs: Tabs; @@ -132,7 +135,7 @@ export class PropertiesAssignmentComponent { }); this.loadingInputs = false; - }, error => {}); //ignore error + }); this.componentServiceNg2 .getComponentResourcePropertiesData(this.component) .subscribe(response => { @@ -141,6 +144,12 @@ export class PropertiesAssignmentComponent { this.instances.push(...response.groupInstances); this.instances.push(...response.policies); + // add the service self instance to the top of the list. + const serviceInstance = new ComponentInstance(); + serviceInstance.name = SERVICE_SELF_TITLE; + serviceInstance.uniqueId = this.component.uniqueId; + this.instances.unshift(serviceInstance); + _.forEach(this.instances, (instance) => { this.instancesNavigationData.push(instance); this.componentInstanceNamesMap[instance.uniqueId] = <InstanceFeDetails>{name: instance.name, iconClass:instance.iconClass, originArchived:instance.originArchived}; @@ -150,7 +159,7 @@ export class PropertiesAssignmentComponent { this.loadingProperties = false; } this.selectFirstInstanceByDefault(); - }, error => {}); //ignore error + }); this.stateChangeStartUnregister = this.$scope.$on('$stateChangeStart', (event, toState, toParams) => { // stop if has changed properties @@ -183,6 +192,23 @@ export class PropertiesAssignmentComponent { this.updateViewMode(); } + isSelf = ():boolean => { + return this.selectedInstanceData && this.selectedInstanceData.uniqueId == this.component.uniqueId; + } + + getServiceProperties(){ + this.loadingProperties = false; + this.componentServiceNg2 + .getServiceProperties(this.component) + .subscribe(response => { + this.serviceBePropertiesMap = new InstanceBePropertiesMap(); + this.serviceBePropertiesMap[this.component.uniqueId] = response; + this.processInstancePropertiesResponse(this.serviceBePropertiesMap, false); + this.loadingProperties = false; + }, error => { + this.loadingProperties = false; + }); + } onInstanceSelectedUpdate = (instance: ComponentInstance|GroupInstance|PolicyInstance) => { // stop if has changed properties @@ -210,6 +236,8 @@ export class PropertiesAssignmentComponent { this.loadingProperties = false; }, error => { }); //ignore error + } else if (this.isSelf()) { + this.getServiceProperties(); } else { this.componentInstanceServiceNg2 .getComponentInstanceProperties(this.component, instance.uniqueId) @@ -391,7 +419,7 @@ export class PropertiesAssignmentComponent { let inputsToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(selectedComponentInstancesInputs, selectedComponentInstancesProperties, selectedGroupInstancesProperties, selectedPolicyInstancesProperties); this.componentServiceNg2 - .createInput(this.component, inputsToCreate) + .createInput(this.component, inputsToCreate, this.isSelf()) .subscribe(response => { this.setInputTabIndication(response.length); this.checkedPropertiesCount = 0; @@ -439,8 +467,12 @@ export class PropertiesAssignmentComponent { console.log('updated instance inputs:', response); }; } else { - request = this.componentInstanceServiceNg2 - .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties) + if (this.isSelf()) { + request = this.componentServiceNg2.updateServiceProperties(this.component, changedProperties); + } else { + request = this.componentInstanceServiceNg2 + .updateInstanceProperties(this.component, this.selectedInstanceData.uniqueId, changedProperties); + } handleSuccess = (response) => { // reset each changed property with new value and remove it from changed properties list response.forEach((resProp) => { @@ -650,7 +682,57 @@ export class PropertiesAssignmentComponent { }, error => {}); //ignore error }; + deleteProperty = (property: PropertyFEModel) => { + let propertyToDelete = new PropertyFEModel(property); + this.loadingProperties = true; + let feMap = this.instanceFePropertiesMap; + this.componentServiceNg2 + .deleteServiceProperty(this.component, propertyToDelete) + .subscribe(response => { + const props = feMap[this.component.uniqueId]; + props.splice(props.findIndex(p => p.uniqueId === response),1); + this.loadingProperties = false; + }, error => { + this.loadingProperties = false; + console.error(error); + }); + }; + + /*** addProperty ***/ + addProperty = () => { + let modalTitle = 'Add Property'; + const modal = this.ModalService.createCustomModal(new ModalModel( + 'sm', + modalTitle, + null, + [ + new ButtonModel('Save', 'blue', () => { + modal.instance.dynamicContent.instance.isLoading = true; + const newProperty: PropertyBEModel = modal.instance.dynamicContent.instance.propertyModel; + this.componentServiceNg2.createServiceProperty(this.component, newProperty) + .subscribe(response => { + modal.instance.dynamicContent.instance.isLoading = false; + let newProp: PropertyFEModel = this.propertiesUtils.convertAddPropertyBAToPropertyFE(response); + this.instanceFePropertiesMap[this.component.uniqueId].push(newProp); + modal.instance.close(); + }, (error) => { + modal.instance.dynamicContent.instance.isLoading = false; + this.Notification.error({ + message: 'Failed to add property:' + error, + title: 'Failure' + }); + }); + }, () => !modal.instance.dynamicContent.instance.checkFormValidForSubmit()), + new ButtonModel('Cancel', 'outline grey', () => { + modal.instance.close(); + }), + ], + null + )); + this.ModalService.addDynamicContentToModal(modal, PropertyCreatorComponent, {}); + modal.instance.open(); + }; /*** SEARCH RELATED FUNCTIONS ***/ searchPropertiesInstances = (filterData:FilterPropertiesAssignmentData) => { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html new file mode 100644 index 0000000000..e97ec79c04 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.html @@ -0,0 +1,46 @@ +<div class="property-creator"> + <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader> + <form class="w-sdc-form"> + + <div class="side-by-side"> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label required">Name</label> + <input class="i-sdc-form-input" + type="text" + name="propertyName" + data-tests-id="property-name" + [(ngModel)]="propertyModel.name" + [ngModelOptions]="{ debounce: 200 }" + autofocus/> + </div> + <!-- Type --> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label required">Type</label> + <ui-element-dropdown [testId]="'property-type'" + class="cell link-selector" + [values]="typesProperties" + [(value)]="propertyModel.type"></ui-element-dropdown> + </div> + <div class="i-sdc-form-item propertySchemaType" *ngIf="showSchema()"> + <label class="i-sdc-form-label required">Schema Type</label> + <ui-element-dropdown [testId]="'property-type'" + class="cell link-selector" + [values]="typesSchemaProperties" + [(value)]="propertyModel.schema.property.type"></ui-element-dropdown> + </div> + </div> + + <!-- Description --> + <div class="i-sdc-form-item"> + <label class="i-sdc-form-label">Description</label> + <textarea class="i-sdc-form-textarea" + [pattern]="commentValidationPattern" + name="propertyDescription" + [(ngModel)]="propertyModel.description" + [ngModelOptions]="{ debounce: 200 }" + data-tests-id="property-description" + ></textarea> + </div> + + </form> +</div> diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less new file mode 100644 index 0000000000..d17a45e2c9 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.less @@ -0,0 +1,35 @@ +@import '../../../../../assets/styles/variables.less'; + +.property-creator { + font-family: @font-opensans-regular; + user-select: none; + padding-top: 12px; + padding-bottom: 20px; + + .i-sdc-form-label { + font-size: 12px; + } + + .w-sdc-form .i-sdc-form-item { + margin-bottom: 15px; + } + + .side-by-side { + display: flex; + + .i-sdc-form-item { + flex-basis: 100%; + + &:first-child { + flex-basis: 50%; + margin-right: 10px; + } + + } + .propertySchemaType{ + margin-left: 10px; + } + } + + +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts new file mode 100644 index 0000000000..d5946d2e4a --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.component.ts @@ -0,0 +1,78 @@ +import * as _ from "lodash"; +import {Component} from '@angular/core'; +import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component"; +import { DataTypeService } from "app/ng2/services/data-type.service"; +import {PropertyBEModel, DataTypesMap} from "app/models"; +import {PROPERTY_DATA} from "app/utils"; +import {PROPERTY_TYPES} from "../../../../utils"; + + + +@Component({ + selector: 'property-creator', + templateUrl: './property-creator.component.html', + styleUrls:['./property-creator.component.less'], +}) + +export class PropertyCreatorComponent { + + typesProperties: Array<DropdownValue>; + typesSchemaProperties: Array<DropdownValue>; + propertyModel: PropertyBEModel; + //propertyNameValidationPattern:RegExp = /^[a-zA-Z0-9_:-]{1,50}$/; + //commentValidationPattern:RegExp = /^[\u0000-\u00BF]*$/; + //types:Array<string>; + dataTypes:DataTypesMap; + isLoading:boolean; + + constructor(protected dataTypeService:DataTypeService) {} + + ngOnInit() { + this.propertyModel = new PropertyBEModel(); + this.propertyModel.type = ''; + this.propertyModel.schema.property.type = ''; + const types: Array<string> = PROPERTY_DATA.TYPES; //All types - simple type + map + list + this.dataTypes = this.dataTypeService.getAllDataTypes(); //Get all data types in service + const nonPrimitiveTypes :Array<string> = _.filter(Object.keys(this.dataTypes), (type:string)=> { + return types.indexOf(type) == -1; + }); + + this.typesProperties = _.map(PROPERTY_DATA.TYPES, + (type: string) => new DropdownValue(type, type) + ); + let typesSimpleProperties = _.map(PROPERTY_DATA.SIMPLE_TYPES, + (type: string) => new DropdownValue(type, type) + ); + let nonPrimitiveTypesValues = _.map(nonPrimitiveTypes, + (type: string) => new DropdownValue(type, + type.replace("org.openecomp.datatypes.heat.","")) + ); + this.typesProperties = _.concat(this.typesProperties,nonPrimitiveTypesValues); + this.typesSchemaProperties = _.concat(typesSimpleProperties,nonPrimitiveTypesValues); + this.typesProperties.unshift(new DropdownValue('','Select Type...')); + this.typesSchemaProperties.unshift(new DropdownValue('','Select Schema Type...')); + + } + + checkFormValidForSubmit(){ + const showSchema:boolean = this.showSchema(); + let isSchemaValid: boolean = (showSchema && !this.propertyModel.schema.property.type)? false : true; + if (!showSchema){ + this.propertyModel.schema.property.type = ''; + } + return this.propertyModel.name && this.propertyModel.type && isSchemaValid; + } + + showSchema():boolean { + return [PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP].indexOf(this.propertyModel.type) > -1; + }; + + onSchemaTypeChange():void { + if (this.propertyModel.type == PROPERTY_TYPES.MAP) { + this.propertyModel.value = JSON.stringify({'': null}); + } else if (this.propertyModel.type == PROPERTY_TYPES.LIST) { + this.propertyModel.value = JSON.stringify([]); + } + }; + +} diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts new file mode 100644 index 0000000000..92accb26b5 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/property-creator/property-creator.module.ts @@ -0,0 +1,27 @@ +import {NgModule} from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {PropertyCreatorComponent} from "./property-creator.component"; +import {FormsModule} from "@angular/forms"; +import {FormElementsModule} from "app/ng2/components/ui/form-components/form-elements.module"; +import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; +import {TranslateModule} from "../../../shared/translator/translate.module"; + +@NgModule({ + declarations: [ + PropertyCreatorComponent, + ], + imports: [ + CommonModule, + FormsModule, + FormElementsModule, + UiElementsModule, + TranslateModule + ], + exports: [], + entryComponents: [ + PropertyCreatorComponent + ], + providers: [] +}) + +export class PropertyCreatorModule {} 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 e7b59b96ba..3ed535d6a0 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 @@ -75,6 +75,14 @@ export class PropertiesUtils { return instanceFePropertiesMap; } + public convertAddPropertyBAToPropertyFE = (property: PropertyBEModel):PropertyFEModel => { + let newFEProp: PropertyFEModel = new PropertyFEModel(property); //Convert property to FE + this.initValueObjectRef(newFEProp); + newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children + this.dataTypeService.checkForCustomBehavior(newFEProp); + return newFEProp; + } + public createListOrMapChildren = (property:PropertyFEModel | DerivedFEProperty, key: string, valueObj: any): Array<DerivedFEProperty> => { let newProps: Array<DerivedFEProperty> = []; let parentProp = new DerivedFEProperty(property, property.propertiesName, true, key, valueObj); |