diff options
author | talio <tali.orenbach@amdocs.com> | 2019-04-14 15:37:20 +0300 |
---|---|---|
committer | Avi Gaffa <avi.gaffa@amdocs.com> | 2019-04-14 16:07:26 +0000 |
commit | fe4afd47955705bb377583649cb53e2cf4508493 (patch) | |
tree | 335f4555155fbeb1085e7ab554ad8406a3ad68be /catalog-ui/src | |
parent | b08309847c24bd3c060839a335a20cb3f750ed30 (diff) |
Declare properties as policies
Change-Id: I54dc7b444e08117097c314cf5f51bd356ac5287d
Issue-ID: SDC-2240
Signed-off-by: talio <tali.orenbach@amdocs.com>
Diffstat (limited to 'catalog-ui/src')
13 files changed, 502 insertions, 15 deletions
diff --git a/catalog-ui/src/app/models/graph/zones/policy-instance.ts b/catalog-ui/src/app/models/graph/zones/policy-instance.ts index c0a6678b21..cef1705a41 100644 --- a/catalog-ui/src/app/models/graph/zones/policy-instance.ts +++ b/catalog-ui/src/app/models/graph/zones/policy-instance.ts @@ -62,6 +62,7 @@ export class PolicyInstance implements IZoneInstanceMethod { iconSprite:string; icon:string; originArchived:boolean; + instanceUniqueId: string; constructor(policy?:PolicyInstance) { @@ -81,6 +82,7 @@ export class PolicyInstance implements IZoneInstanceMethod { this.targets = policy.targets; this.uniqueId = policy.uniqueId; this.version = policy.version; + this.instanceUniqueId = policy.instanceUniqueId; this.iconSprite = ''; this.icon = 'icon-policy'; diff --git a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts index a1a85aa73d..15b9534b99 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts @@ -26,14 +26,26 @@ export enum DerivedPropertyType { MAP, COMPLEX } +export class PropertyPolicyDetail { + policyId: string; + propertyName: string; + constructor(propertyPolicy?:PropertyPolicyDetail) { + if(propertyPolicy) { + this.policyId = propertyPolicy.policyId; + this.propertyName = propertyPolicy.propertyName; + } + } +} export class PropertyBEModel { + constraints: Array<any>; defaultValue: string; definition: boolean; description: string; fromDerived: boolean; getInputValues: Array<PropertyInputDetail>; + getPolicyValues: Array<PropertyPolicyDetail>; name: string; parentUniqueId: string; password: boolean; @@ -45,6 +57,7 @@ export class PropertyBEModel { value: string; parentPropertyType: string; subPropertyInputPath: string; + inputPath: string; constructor(property?: PropertyBEModel) { if (property) { @@ -65,6 +78,8 @@ export class PropertyBEModel { this.getInputValues = property.getInputValues; this.parentPropertyType = property.parentPropertyType; this.subPropertyInputPath = property.subPropertyInputPath; + this.getPolicyValues = property.getPolicyValues; + this.inputPath = property.inputPath; } if (!this.schema || !this.schema.property) { diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.html b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.html new file mode 100644 index 0000000000..6106e13924 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.html @@ -0,0 +1,48 @@ + +<div class="properties-table"> + <loader [display]="isLoading" [size]="'large'" [relative]="true"></loader> + <div class="table-header"> + <div class="table-cell col1" (click)="sort('name')">Property Name + <span *ngIf="sortBy === 'name'" class="table-header-sort-arrow" [ngClass]="{'down': reverse, 'up':!reverse}"> + </span> + </div> + <div class="table-cell col3" (click)="sort('instanceUniqueId')">From Instance + <span *ngIf="sortBy === 'instanceUniqueId'" class="table-header-sort-arrow" [ngClass]="{'down': reverse, 'up':!reverse}"> + </span> + </div> + <div class="table-cell col2" (click)="sort('type')">Type + <span *ngIf="sortBy === 'type'" class="table-header-sort-arrow" [ngClass]="{'down': reverse, 'up':!reverse}"> + </span> + </div> + </div> + <div class="table-body"> + <div class="no-data" *ngIf="!policies || !policies.length">No data to display</div> + <div> + <div class="table-row" *ngFor="let policy of policies"> + <div class="table-cell col1"> + <div class="inner-cell-div" tooltips tooltip="{{policy.name}}"> + <span class="property-name">{{policy.name}}</span> + </div> + </div> + <div class="table-cell col3"> + <div class="inner-cell-div" tooltips tooltip="{{instanceNamesMap[policy.instanceUniqueId]?.name}}"> + <span>{{instanceNamesMap[policy.instanceUniqueId]?.name}}</span> + </div> + </div> + <div class="table-cell col2"> + <div class="inner-cell-div" tooltips tooltip="{{policy.type | contentAfterLastDot}}"> + <span>{{policy.type | contentAfterLastDot}}</span> + </div> + </div> + <div class="table-cell valueCol policy-value-col"> + <div class="delete-button-container"> + <span *ngIf="policy.uniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(policy)" data-tests-id="delete-policy-button"></span> + </div> + </div> + + </div> + </div> + </div> +</div> + + diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.less b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.less new file mode 100644 index 0000000000..57a69a3aa1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.less @@ -0,0 +1,169 @@ + +@import './../../../../../assets/styles/variables.less'; + +:host /deep/ input { width:100%;} + +.properties-table { + display:flex; + flex-direction:column; + flex: 1; + height:100%; + text-align:left; + + .inner-cell-div{ + max-width: 100%; + text-overflow: ellipsis; + overflow: hidden; + height: 20px; + } + + + .table-header { + font-weight:bold; + border-top: @main_color_o solid 1px; + background-color: @tlv_color_u; + color:@func_color_s; + + .table-cell { + font-size: 13px; + .table-header-sort-arrow { + display: inline-block; + background-color: transparent; + border: none; + color: #AAA; + margin: 8px 0 0 5px; + &.up { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-bottom: 5px solid; + } + &.down { + border-left: 5px solid transparent; + border-right: 5px solid transparent; + border-top: 5px solid; + } + } + } + } + .table-header, .table-row { + display: flex; + flex-direction:row; + flex: 0 0 auto; + } + + .table-body { + display:flex; + flex-direction: column; + overflow-y:auto; + flex: 1; + + .no-data { + border: @main_color_o solid 1px; + border-top:none; + text-align: center; + height: 100%; + padding: 20px; + } + /deep/.selected{ + background-color: @tlv_color_v; + color: @main_color_a; + } + } + + .table-row { + &:hover { + background-color:@tlv_color_t; cursor:pointer; + } + + &:last-child { + flex: 1 0 auto; + } + .selected-row { + background-color:@tlv_color_v; + } + } + + .table-cell { + font-size:13px; + flex:1; + border: @main_color_o solid 1px; + border-right:none; + border-top:none; + padding: 10px; + text-overflow: ellipsis; + white-space: nowrap; + + + &:last-child { + border-right:@main_color_o solid 1px; + } + &.col1 { + flex: 1 0 130px; + max-width:130px; + + justify-content: space-between; + + .policy-name { + flex: 1; + } + + //.policy-description-icon { + // float: right; + // margin-top: 4px; + // margin-left: 5px; + // flex: 0 0 auto; + //} + } + &.col2 { + flex: 0 0 140px; + max-width:140px; + } + + &.col3 { + flex:0 0 120px; + max-width:120px; + } + + &.valueCol { + .value-input { + flex: 1; + border: none; + background-color: inherit; + + &:focus, &:active { + border:none; + outline:none; + } + } + + .delete-btn { + flex: 0 0 auto; + } + + .delete-button-container { + max-height: 24px; + } + + &.inner-table-container { + padding: 0px; + + .delete-button-container { + padding: 0 8px 0 0 ; + } + } + } + + &.input-value-col { + padding: 8px; + } + + + } + + .filtered { + /deep/ .checkbox-label-content{ + background-color: yellow; + } + } + +} diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts new file mode 100644 index 0000000000..aa5f2420b3 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.component.ts @@ -0,0 +1,100 @@ +/*! + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + + +import { Component, Input, Output, EventEmitter } from "@angular/core"; +import { PolicyInstance } from "app/models"; +import { ModalService } from "../../../services/modal.service"; +import { InstanceFeDetails } from "app/models/instance-fe-details"; +import {TranslateService} from 'app/ng2/shared/translator/translate.service'; + +@Component({ + selector: 'policies-table', + templateUrl: 'policies-table.component.html', + styleUrls: ['policies-table.component.less'], +}) +export class PoliciesTableComponent { + + @Input() policies: Array<PolicyInstance>; + @Input() instanceNamesMap: Map<string, InstanceFeDetails>; + @Input() readonly: boolean; + @Input() isLoading: boolean; + @Output() deletePolicy: EventEmitter<any> = new EventEmitter<any>(); + + sortBy: String; + reverse: boolean; + selectedPolicyToDelete: PolicyInstance; + deleteMsgTitle: string; + deleteMsgBodyTxt: string; + modalDeleteBtn: string; + modalCancelBtn: string; + + sort = (sortBy) => { + this.reverse = (this.sortBy === sortBy) ? !this.reverse : true; + let reverse = this.reverse ? 1 : -1; + this.sortBy = sortBy; + let instanceNameMapTemp = this.instanceNamesMap; + let itemIdx1Val = ""; + let itemIdx2Val = ""; + this.policies.sort(function (itemIdx1, itemIdx2) { + if (sortBy == 'instanceUniqueId') { + itemIdx1Val = (itemIdx1[sortBy] && instanceNameMapTemp[itemIdx1[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx1[sortBy]].name : ""; + itemIdx2Val = (itemIdx2[sortBy] && instanceNameMapTemp[itemIdx2[sortBy]] !== undefined) ? instanceNameMapTemp[itemIdx2[sortBy]].name : ""; + } + else { + itemIdx1Val = itemIdx1[sortBy]; + itemIdx2Val = itemIdx2[sortBy]; + } + if (itemIdx1Val < itemIdx2Val) { + return -1 * reverse; + } + else if (itemIdx1Val > itemIdx2Val) { + return 1 * reverse; + } + else { + return 0; + } + }); + }; + + + constructor(private modalService: ModalService, private translateService: TranslateService) { + } + + ngOnInit() { + this.translateService.languageChangedObservable.subscribe(lang => { + this.deleteMsgTitle = this.translateService.translate("DELETE_POLICY_TITLE"); + this.modalDeleteBtn = this.translateService.translate("MODAL_DELETE"); + this.modalCancelBtn = this.translateService.translate("MODAL_CANCEL"); + + }); + } + + onDeletePolicy = () => { + this.deletePolicy.emit(this.selectedPolicyToDelete); + this.modalService.closeCurrentModal(); + }; + + openDeleteModal = (policy: PolicyInstance) => { + this.selectedPolicyToDelete = policy; + this.translateService.languageChangedObservable.subscribe(lang => { + this.deleteMsgBodyTxt = this.translateService.translate("DELETE_POLICY_MSG", {policyName: policy.name}); + this.modalService.createActionModal(this.deleteMsgTitle, this.deleteMsgBodyTxt, this.modalDeleteBtn, this.onDeletePolicy, this.modalCancelBtn).instance.open(); + }); + } +} + + diff --git a/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts new file mode 100644 index 0000000000..f780c62c0b --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/policies-table/policies-table.module.ts @@ -0,0 +1,41 @@ +/*! + * Copyright © 2016-2018 European Support Limited + * + * 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. + */ + +import { NgModule } from "@angular/core"; +import {CommonModule} from "@angular/common"; +import {PoliciesTableComponent} from "./policies-table.component"; +import {TranslateModule} from 'app/ng2/shared/translator/translate.module'; +import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; +import {GlobalPipesModule} from "../../../pipes/global-pipes.module"; + +@NgModule({ + declarations: [ + PoliciesTableComponent + ], + imports: [ + CommonModule, + GlobalPipesModule, + UiElementsModule, + TranslateModule + ], + exports: [PoliciesTableComponent], + entryComponents: [ + PoliciesTableComponent + ], + providers: [] +}) +export class PoliciesTableModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts index 907f7638bb..c46d617b86 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts @@ -27,6 +27,7 @@ import {GlobalPipesModule} from "../../pipes/global-pipes.module"; import {BrowserModule} from "@angular/platform-browser"; import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component"; import {InputsTableComponent} from "../../components/logic/inputs-table/inputs-table.component"; +import {PoliciesTableModule} from "../../components/logic/policies-table/policies-table.module"; import {PropertiesService} from "../../services/properties.service"; import {DataTypeService} from "../../services/data-type.service"; import {PropertiesAssignmentComponent} from "./properties-assignment.page.component"; @@ -48,6 +49,7 @@ import {ComponentModeService} from "../../services/component-services/component- HttpModule, GlobalPipesModule, PropertyTableModule, + PoliciesTableModule, UiElementsModule], entryComponents: [PropertiesAssignmentComponent], 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 8a3e8d23ee..1ec6df9bc1 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 @@ -49,6 +49,15 @@ (inputChanged)="dataChanged($event)"> </inputs-table> </tab> + <tab tabTitle="Policies"> + <policies-table class="properties-table" + [readonly]="isReadonly" + [policies]="policies | searchFilter:'name':searchQuery" + [instanceNamesMap]="componentInstanceNamesMap" + [isLoading]="loadingPolicies" + (deletePolicy)="deletePolicy($event)"> + </policies-table> + </tab> </tabs> <div class="main-tabs-section-buttons"> <button class="tlv-btn outline blue" [disabled]="!hasChangedData || savingChangedData" (click)="reverseChangedData()" data-tests-id="properties-reverse-button">Discard</button> @@ -56,13 +65,14 @@ </div> </div> <div class="header"> - <div class="search-filter-container" [class.without-filter]="isInputsTabSelected"> + <div class="search-filter-container" [class.without-filter]="isInputsTabSelected || isPoliciesTabSelected"> <span *ngIf="displayClearSearch && isPropertiesTabSelected" (click)="clickOnClearSearch()" class="clear-filter" data-tests-id="clear-filter-button">Clear All</span> <input type="text" class="search-box" placeholder="Search" [(ngModel)]="searchQuery" data-tests-id="search-box"/> <span class="sprite search-icon" data-tests-id="search-button"></span> <filter-properties-assignment *ngIf="isPropertiesTabSelected" #advanceSearch class="advance-search" [componentType]="component.componentType" (searchProperties)="searchPropertiesInstances($event)"></filter-properties-assignment> </div> - <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button">Declare</button> + <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData" (click)="declareProperties()" data-tests-id="declare-button declare-input">Declare Input</button> + <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly || hasChangedData || isSelf()" (click)="declarePropertiesToPolicies()" data-tests-id="declare-button declare-policy">Declare Policy</button> </div> </div> <div class="right-column"> @@ -75,10 +85,10 @@ <div class="hierarchy-header white-sub-header"> <span tooltip="{{component.name}}">{{component.name}}</span> </div> - <div *ngIf="!instancesNavigationData || instancesNavigationData.length === 0 || isInputsTabSelected">No data to display</div> + <div *ngIf="!instancesNavigationData || instancesNavigationData.length === 0 || isInputsTabSelected || isPoliciesTabSelected">No data to display</div> <hierarchy-navigation class="hierarchy-nav" (updateSelected)="onInstanceSelectedUpdate($event)" - [displayData]="isInputsTabSelected ? []: instancesNavigationData" + [displayData]="isInputsTabSelected || isPoliciesTabSelected ? []: instancesNavigationData" [selectedItem]="selectedInstanceData?.uniqueId" [displayOptions]="hierarchyInstancesDisplayOptions"></hierarchy-navigation> </div> @@ -88,10 +98,10 @@ <div class="hierarchy-header white-sub-header" [class.selected]="selectedFlatProperty.path == propertyStructureHeader"> <span tooltip="{{isPropertiesTabSelected ? propertyStructureHeader : ''}}">{{isPropertiesTabSelected ? (propertyStructureHeader || "No Property Selected") : "No Property Selected"}}</span> </div> - <div *ngIf="!propertiesNavigationData || propertiesNavigationData.length === 0 || isInputsTabSelected">No data to display</div> + <div *ngIf="!propertiesNavigationData || propertiesNavigationData.length === 0 || isInputsTabSelected || isPoliciesTabSelected">No data to display</div> <hierarchy-navigation class="hierarchy-nav" (updateSelected)="onPropertySelectedUpdate($event)" - [displayData]="isInputsTabSelected ? [] : propertiesNavigationData" + [displayData]="isInputsTabSelected || isPoliciesTabSelected ? [] : propertiesNavigationData" [selectedItem]="selectedFlatProperty.path" [displayOptions]="hierarchyPropertiesDisplayOptions"></hierarchy-navigation> </div> 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 95ff94317c..523eda2e9f 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 @@ -59,11 +59,10 @@ position:absolute; top:0; right:0; + display: flex; } .search-filter-container{ - position: absolute; - right: 100px; display:flex; flex-direction:row; @@ -87,7 +86,7 @@ width: 14px; height: 14px; position: absolute; - right:42px; + left:170px; top: 8px; } @@ -110,9 +109,9 @@ } .declare-button{ - position: absolute; - top: 0; - right: 0; + &:first-of-type { + margin-right: 10px; + } } .main-tabs-section { 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 615325559e..037b7f4963 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 @@ -61,6 +61,7 @@ export class PropertiesAssignmentComponent { instanceFePropertiesMap:InstanceFePropertiesMap; inputs: Array<InputFEModel> = []; + policies: Array<PolicyInstance> = []; instances: Array<ComponentInstance|GroupInstance|PolicyInstance> = []; searchQuery: string; propertyStructureHeader: string; @@ -76,10 +77,12 @@ export class PropertiesAssignmentComponent { currentMainTab:Tab; isInputsTabSelected:boolean; isPropertiesTabSelected:boolean; + isPoliciesTabSelected:boolean; isReadonly:boolean; resourceIsReadonly:boolean; loadingInstances:boolean = false; loadingInputs:boolean = false; + loadingPolicies:boolean = false; loadingProperties:boolean = false; changedData:Array<PropertyFEModel|InputFEModel>; hasChangedData:boolean; @@ -123,6 +126,7 @@ export class PropertiesAssignmentComponent { ngOnInit() { console.log("==>" + this.constructor.name + ": ngOnInit"); this.loadingInputs = true; + this.loadingPolicies = true; this.loadingInstances = true; this.loadingProperties = true; this.componentServiceNg2 @@ -139,10 +143,16 @@ export class PropertiesAssignmentComponent { this.componentServiceNg2 .getComponentResourcePropertiesData(this.component) .subscribe(response => { + this.loadingPolicies = false; this.instances = []; this.instances.push(...response.componentInstances); this.instances.push(...response.groupInstances); - this.instances.push(...response.policies); + + _.forEach(response.policies, (policy: any) => { + const newPolicy: InputFEModel = new InputFEModel(policy); + this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue); + this.policies.push(policy); + }); // add the service self instance to the top of the list. const serviceInstance = new ComponentInstance(); @@ -296,6 +306,8 @@ export class PropertiesAssignmentComponent { itemHasChanged = item.hasValueObjChanged(); } else if (this.isInputsTabSelected && item instanceof InputFEModel) { itemHasChanged = item.hasDefaultValueChanged(); + } else if (this.isPoliciesTabSelected && item instanceof InputFEModel) { + itemHasChanged = item.hasDefaultValueChanged(); } const dataChangedIdx = this.changedData.findIndex((changedItem) => changedItem === item); @@ -311,7 +323,7 @@ export class PropertiesAssignmentComponent { if (this.isPropertiesTabSelected) { this.isValidChangedData = this.changedData.every((changedItem) => (<PropertyFEModel>changedItem).valueObjIsValid); - } else if (this.isInputsTabSelected) { + } else if (this.isInputsTabSelected || this.isPoliciesTabSelected) { this.isValidChangedData = this.changedData.every((changedItem) => (<InputFEModel>changedItem).defaultValueObjIsValid); } this.updateHasChangedData(); @@ -385,6 +397,7 @@ export class PropertiesAssignmentComponent { this.currentMainTab = this.propertyInputTabs.tabs.find((tab) => tab.title === event.title); this.isPropertiesTabSelected = this.currentMainTab.title === "Properties"; this.isInputsTabSelected = this.currentMainTab.title === "Inputs"; + this.isPoliciesTabSelected = this.currentMainTab.title === "Policies"; this.propertyStructureHeader = null; this.searchQuery = ''; }; @@ -432,6 +445,46 @@ export class PropertiesAssignmentComponent { }, error => {}); //ignore error }; + /*** DECLARE PROPERTIES/POLICIES ***/ + declarePropertiesToPolicies = (): void => { + let selectedComponentInstancesProperties: InstanceBePropertiesMap = new InstanceBePropertiesMap(); + let instancesIds = new KeysPipe().transform(this.instanceFePropertiesMap, []); + + angular.forEach(instancesIds, (instanceId: string): void => { + let selectedInstanceData: any = this.instances.find(instance => instance.uniqueId == instanceId); + if (selectedInstanceData instanceof ComponentInstance) { + if (!this.isInput(selectedInstanceData.originType)) { + selectedComponentInstancesProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); + } + } + }); + + let policiesToCreate: InstancePropertiesAPIMap = new InstancePropertiesAPIMap(null, selectedComponentInstancesProperties, null, null); + this.loadingPolicies = true; + + this.componentServiceNg2 + .createPolicy(this.component, policiesToCreate, this.isSelf()) + .subscribe(response => { + this.setPolicyTabIndication(response.length); + this.checkedPropertiesCount = 0; + this.displayPoliciesAsDeclared(response); + this.loadingPolicies = false; + }); //ignore error + + }; + + displayPoliciesAsDeclared = (policies) => { + _.forEach(policies, (policy: any) => { + let newPolicy: InputFEModel = new InputFEModel(policy); + this.inputsUtils.resetInputDefaultValue(newPolicy, policy.defaultValue); + newPolicy.relatedPropertyName = policy.name; + newPolicy.relatedPropertyValue = policy.value; + this.updatePropertyValueAfterDeclare(newPolicy); + this.policies.push(policy); + }); + }; + + saveChangedData = ():Promise<(PropertyBEModel|InputBEModel)[]> => { return new Promise((resolve, reject) => { if (!this.isValidChangedData) { @@ -648,6 +701,10 @@ export class PropertiesAssignmentComponent { this.propertyInputTabs.setTabIndication('Inputs', numInputs); }; + setPolicyTabIndication = (numPolicies: number): void => { + this.propertyInputTabs.setTabIndication('Policies', numPolicies); + }; + resetUnsavedChangesForInput = (input:InputFEModel) => { this.inputsUtils.resetInputDefaultValue(input, input.defaultValue); this.changedData = this.changedData.filter((changedItem) => changedItem.uniqueId !== input.uniqueId); @@ -685,6 +742,18 @@ export class PropertiesAssignmentComponent { }, error => {}); //ignore error }; + deletePolicy = (policy: PolicyInstance) => { + this.loadingPolicies = true; + this.componentServiceNg2 + .deletePolicy(this.component, policy) + .subscribe(response => { + this.policies = this.policies.filter(policy => policy.uniqueId !== response.uniqueId); + //Reload the whole instance for now - TODO: CHANGE THIS after the BE starts returning properties within the response, use commented code below instead! + this.changeSelectedInstance(this.selectedInstanceData); + this.loadingPolicies = false; + }); + }; + deleteProperty = (property: PropertyFEModel) => { let propertyToDelete = new PropertyFEModel(property); this.loadingProperties = true; 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 3ed535d6a0..011be41611 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 @@ -67,6 +67,10 @@ export class PropertiesUtils { this.propertiesService.disableRelatedProperties(newFEProp, inputPath); }); } + if (newFEProp.getPolicyValues && newFEProp.getPolicyValues.length) { + newFEProp.setAsDeclared(newFEProp.inputPath); //if a path is sent, its a child prop. this param is optional + this.propertiesService.disableRelatedProperties(newFEProp, newFEProp.inputPath); + } } }); instanceFePropertiesMap[instanceId] = propertyFeArray; 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 3243291483..fd746516b7 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 @@ -25,7 +25,7 @@ import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; import {Response, URLSearchParams} from '@angular/http'; import { Component, ComponentInstance, InputBEModel, InstancePropertiesAPIMap, FilterPropertiesAssignmentData, - PropertyBEModel, OperationModel, BEOperationModel, Capability, Requirement} from "app/models"; + PropertyBEModel, OperationModel, BEOperationModel, Capability, Requirement, PolicyInstance} from "app/models"; import {COMPONENT_FIELDS, CommonUtils, SERVICE_FIELDS} from "app/utils"; import {downgradeInjectable} from '@angular/upgrade/static'; import {ComponentGenericResponse} from "../responses/component-generic-response"; @@ -285,6 +285,30 @@ export class ComponentServiceNg2 { }) } + createPolicy(component:Component, policiesToCreate:InstancePropertiesAPIMap, isSelf:boolean):Observable<any> { + const policiesList = + isSelf ? + {'componentPropertiesToPolicies': { + ...policiesToCreate.componentInstanceProperties + } + } : + {'componentInstancePropertiesToPolicies': { + ...policiesToCreate.componentInstanceProperties + } + }; + return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/create/policies', policiesList) + .map(res => { + return res.json(); + }); + } + + deletePolicy(component:Component, policy: PolicyInstance) { + return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/policies/' + policy.uniqueId + '/undeclare', policy) + .map(res => { + return res.json(); + }); + } + restoreComponent(componentType:string, componentId:string){ return this.http.post(this.baseUrl + this.getServerTypeUrl(componentType) + componentId + '/restore', {}) } diff --git a/catalog-ui/src/assets/languages/en_US.json b/catalog-ui/src/assets/languages/en_US.json index b81dadffd9..c2a81dd82e 100644 --- a/catalog-ui/src/assets/languages/en_US.json +++ b/catalog-ui/src/assets/languages/en_US.json @@ -531,6 +531,10 @@ "=========== POLICY AND GROUPS ===========": "", "ADD_TARGETS" : "Add Targets", "ADD_MEMBERS" : "Add Members", + "=========== PROPERTIES ASSIGNMENT DECLARE AS POLICY ===========": "", + "DELETE_POLICY_TITLE": "Delete Policy", + "DELETE_POLICY_MSG": "Are you sure you want to delete policy '{{policyName}}'?", + "=========== AUTOMATED UPGRADE ===========": "", "RESOURCE_UPGRADE_TITLE" : "Upgrade Services", "SERVICE_UPGRADE_TITLE" : "Update Service References", |