diff options
author | ys9693 <ys9693@att.com> | 2020-01-19 13:50:02 +0200 |
---|---|---|
committer | Ofir Sonsino <ofir.sonsino@intl.att.com> | 2020-01-22 12:33:31 +0000 |
commit | 16a9fce0e104a38371a9e5a567ec611ae3fc7f33 (patch) | |
tree | 03a2aff3060ddb5bc26a90115805a04becbaffc9 /catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab | |
parent | aa83a2da4f911c3ac89318b8e9e8403b072942e1 (diff) |
Catalog alignment
Issue-ID: SDC-2724
Signed-off-by: ys9693 <ys9693@att.com>
Change-Id: I52b4aacb58cbd432ca0e1ff7ff1f7dd52099c6fe
Diffstat (limited to 'catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab')
4 files changed, 388 insertions, 0 deletions
diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html new file mode 100644 index 0000000000..838fd8bb51 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.html @@ -0,0 +1,48 @@ +<!-- + ~ Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<h1 class="w-sdc-designer-sidebar-section-title" titleTooltip="Targets">Targets + <svg-icon-label *ngIf="!isViewOnly" + class="add-policy-button" + name="plus-circle-o" + mode="primary" + size="medium" + label="ADD" + labelPlacement="right" + (click)="openAddTargetModal()"> + </svg-icon-label> +</h1> +<div class="expand-collapse-content"> + <ul> + <li *ngFor="let target of targets; let i = index" class="component-details-panel-large-item" + tooltip="{{target.name}}"> + <span>{{target.name}}</span> + <svg-icon-label *ngIf="!isViewOnly" + name="trash-o" + clickable="true" + size="small" + class="component-details-panel-item-delete" + data-tests-id="delete_target" + (click)="deleteTarget(target)"></svg-icon-label> + </li> + </ul> + + <div *ngIf="!targets || targets.length===0" class="component-details-panel-tab-no-data"> + <div class="component-details-panel-tab-no-data-title">No data to display yet</div> + <div class="component-details-panel-tab-no-data-content">Add targets to policy to see targets</div> + </div> +</div> + diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less new file mode 100644 index 0000000000..d16a1595df --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.less @@ -0,0 +1,61 @@ +@import './../../../../../../../assets/styles/mixins'; + + +.expand-collapse-content { + padding: 20px; +} + +.component-details-panel-tab-no-data { + margin: 0 auto; + padding-top: 30px; + text-align: center; + + .component-details-panel-tab-no-data-title { + font-family: @font-opensans-bold; + } + +} + +.component-details-panel-large-item { + font-family: OpenSans-Semibold, sans-serif; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + height: 32px; + line-height: 32px; + display: flex; + flex-direction: row; + justify-content: space-between; + + &:hover { + background-color: #f8f8f8; + margin: 0 -20px; /* to fill expand-collapse-content padding */ + padding: 0 20px; + .component-details-panel-item-delete { + visibility: visible; + } + } +} + +.component-details-panel-item-delete { + cursor: pointer; + visibility: hidden; +} + +/deep/ .w-sdc-designer-sidebar-section-title { + color: #5a5a5a; + font-family: OpenSans-Semibold, sans-serif; + font-size: 14px; + background-color: #eaeaea; + cursor: pointer; + display: flex; + justify-content: space-between; + align-items: center; + text-transform: uppercase; + line-height: 32px; + padding: 0 10px 0 20px; + margin-top: 1px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts new file mode 100644 index 0000000000..7774138cab --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.spec.ts @@ -0,0 +1,113 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular'; +import { Observable } from 'rxjs/Rx'; +import { Mock } from 'ts-mockery'; +import { ConfigureFn, configureTests } from '../../../../../../../jest/test-config.helper'; +import { ComponentMetadata } from '../../../../../../models/component-metadata'; +import { EventListenerService } from '../../../../../../services/event-listener-service'; +import { TranslateService } from '../../../../../shared/translator/translate.service'; +import { WorkspaceService } from '../../../../workspace/workspace.service'; +import { CompositionService } from '../../../composition.service'; +import { PolicyTargetsTabComponent } from "app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component"; +import { PoliciesService } from "app/services-ng2"; +import { PolicyInstance, GroupInstance } from "app/models"; +import { NgxsModule } from "@ngxs/store"; +import { GraphState } from "app/ng2/pages/composition/common/store/graph.state"; +import { WorkspaceState } from "app/ng2/store/states/workspace.state"; +import { TargetUiObject } from "app/models/ui-models/ui-target-object"; +import { TargetOrMemberType } from "app/utils"; + + + + +describe('policy targets tab component', () => { + + let fixture: ComponentFixture<PolicyTargetsTabComponent>; + let component: PolicyTargetsTabComponent; + + let policiesServiceMock = Mock.of<PoliciesService>( + { + updateTargets: jest.fn().mockImplementation((compType, uid, policyUniqueId, updatedTargets) => { + if (updatedTargets === undefined) { + return Observable.throwError('error'); + } else { + return Observable.of(updatedTargets); + } + } + )}); + + let compositionServiceMock = { + componentInstances: [{uniqueId: '1', name: 'inst1'}, + {uniqueId: '2', name: 'inst2'}, + {uniqueId: '3', name: 'inst3'}, + {uniqueId: '4', name: 'inst4'}, + {uniqueId: '5', name: 'inst5'} + ], + groupInstances : [ + Mock.of<GroupInstance>({uniqueId: "group1", name: "group1"}), + Mock.of<GroupInstance>({uniqueId: "group2", name: "group2"}), + Mock.of<GroupInstance>({uniqueId: "group3", name: "group3"}) + ] + }; + + let workspaceServiceMock = { + metadata: Mock.of<ComponentMetadata>() + }; + + let modalServiceMock = { + openInfoModal: jest.fn(), + openCustomModal: jest.fn().mockImplementation(() => { return { + innerModalContent: { instance: { existingElements: targetsToAdd }}, + closeModal: jest.fn() + }}) + }; + + let loaderServiceMock = { + activate: jest.fn(), + deactivate: jest.fn() + }; + + const targetsToAdd = [ + <TargetUiObject>{uniqueId: '1', name: 'inst1', type: TargetOrMemberType.COMPONENT_INSTANCES}, + <TargetUiObject>{uniqueId: "group1", name: "group1", type: TargetOrMemberType.GROUPS} + ]; + + const policyInstanceMock = Mock.of<PolicyInstance>( + { getTargetsAsUiObject: jest.fn().mockImplementation( () => targetsToAdd) + }); + + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [PolicyTargetsTabComponent], + imports: [NgxsModule.forRoot([WorkspaceState])], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + {provide: TranslateService, useValue: { translate: jest.fn() }}, + {provide: PoliciesService, useValue: policiesServiceMock}, + {provide: SdcUiServices.ModalService, useValue: modalServiceMock }, + {provide: EventListenerService, useValue: {} }, + {provide: CompositionService, useValue: compositionServiceMock }, + {provide: WorkspaceService, useValue: workspaceServiceMock}, + {provide: SdcUiServices.LoaderService, useValue: loaderServiceMock } + ], + }); + + fixture = TestBed.createComponent(PolicyTargetsTabComponent); + component = fixture.componentInstance; + component.policy = policyInstanceMock; + }); + + + it('if there are no existing targets, all component instances AND all groups are available for adding', () => { + component.targets = []; + const optionalTargetsToAdd = component.getOptionalsTargetsToAdd(); + expect(optionalTargetsToAdd).toHaveLength(8); + }); + + it('list of available instances to add does not include existing targets', () => { + component.targets = targetsToAdd; + const optionalMembersToAdd = component.getOptionalsTargetsToAdd(); + expect(optionalMembersToAdd).toHaveLength(6); + }); +}); diff --git a/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts new file mode 100644 index 0000000000..f117290397 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/composition/panel/panel-tabs/policy-targets-tab/policy-targets-tab.component.ts @@ -0,0 +1,166 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import * as _ from "lodash"; +import { Component, Input, Output, EventEmitter, OnChanges, HostBinding, OnDestroy, OnInit } from "@angular/core"; +import { TranslateService } from './../../../../../shared/translator/translate.service'; +import { PoliciesService } from "../../../../../services/policies.service"; +import { PolicyInstance } from './../../../../../../models/graph/zones/policy-instance'; +import { SdcUiComponents, SdcUiCommon, SdcUiServices } from "onap-ui-angular"; +import { AddElementsComponent } from "../../../../../components/ui/modal/add-elements/add-elements.component"; +import { TargetUiObject } from "../../../../../../models/ui-models/ui-target-object"; +import { ComponentInstance } from "../../../../../../models/componentsInstances/componentInstance"; +import { TargetOrMemberType } from "../../../../../../utils/constants"; +import { GRAPH_EVENTS } from 'app/utils'; +import { EventListenerService } from 'app/services/event-listener-service'; +import { CompositionService } from "app/ng2/pages/composition/composition.service"; +import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service"; +import { Store } from "@ngxs/store"; +import { Select } from "@ngxs/store"; +import { Observable } from "rxjs"; +import { tap } from "rxjs/operators"; +import {GraphState} from "../../../common/store/graph.state"; + +@Component({ + selector: 'policy-targets-tab', + templateUrl: './policy-targets-tab.component.html', + styleUrls: ['policy-targets-tab.component.less'] +}) + +export class PolicyTargetsTabComponent implements OnInit { + + @Input() input:any; + + + @Input() isViewOnly: boolean; + @HostBinding('class') classes = 'component-details-panel-tab-policy-targets'; + @Select(GraphState.getSelectedComponent) policy$: Observable<PolicyInstance>; + public policy: PolicyInstance; + private subscription; + + private addModalInstance: SdcUiComponents.ModalComponent; + public targets: Array<TargetUiObject>; // UI object to hold all targets with names. + + + constructor(private translateService: TranslateService, + private policiesService: PoliciesService, + private modalService: SdcUiServices.ModalService, + private eventListenerService: EventListenerService, + private compositionService: CompositionService, + private workspaceService: WorkspaceService, + private loaderService: SdcUiServices.LoaderService, + private store: Store + ) { } + + ngOnInit() { + this.subscription = this.policy$.pipe( + tap((policy) => { + if(policy instanceof PolicyInstance){ + this.policy = policy; + this.targets = this.policy.getTargetsAsUiObject(<ComponentInstance[]>this.compositionService.componentInstances, this.compositionService.groupInstances); + } + })).subscribe(); + } + + ngOnDestroy () { + if(this.subscription) + this.subscription.unsubscribe(); + } + + deleteTarget(target: TargetUiObject): void { + this.loaderService.activate(); + this.policiesService.deletePolicyTarget(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.policy, target.uniqueId, target.type).subscribe( + (policyInstance:PolicyInstance) => { + this.targets = this.targets.filter(item => item.uniqueId !== target.uniqueId); + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, policyInstance); + // this.store.dispatch(new UpdateSelectedComponentAction({uniqueId: policyInstance.uniqueId, type:ComponentType.})); + }, + error => { + console.log("Error deleting target!"); + this.loaderService.deactivate(); + }, + () => this.loaderService.deactivate() + ); + } + + + addTargets = ():void => { + + var targetsToAdd:Array<TargetUiObject> = this.addModalInstance.innerModalContent.instance.existingElements; //TODO refactor sdc-ui modal in order to return the data + if(targetsToAdd.length > 0) { + this.addModalInstance.closeModal(); + this.loaderService.activate(); + var updatedTargets: Array<TargetUiObject> = _.union(this.targets, targetsToAdd); + this.policiesService.updateTargets(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.policy.uniqueId, updatedTargets).subscribe( + (updatedPolicyInstance:PolicyInstance) => { + this.targets = updatedTargets; + this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, updatedPolicyInstance); + // this.store.dispatch(new UpdateSelectedComponentAction({component: updatedPolicyInstance})); + }, + error => { + console.log("Error updating targets!"); + this.loaderService.deactivate(); + }, + () => this.loaderService.deactivate() + ); + } + } + + getOptionalsTargetsToAdd():Array<TargetUiObject> { + let optionalsTargetsToAdd:Array<TargetUiObject> = []; + // adding all instances as optional targets to add if not already exist + _.forEach(this.compositionService.componentInstances, (instance:ComponentInstance) => { + if (!_.some(this.targets, (target:TargetUiObject) => { + return target.uniqueId === instance.uniqueId + })) { + optionalsTargetsToAdd.push(new TargetUiObject(instance.uniqueId, TargetOrMemberType.COMPONENT_INSTANCES, instance.name)); + } + }); + + // adding all groups as optional targets to add if not already exist + _.forEach(this.compositionService.groupInstances, (groupInstance:ComponentInstance) => { // adding all instances as optional targets to add if not already exist + if (!_.some(this.targets, (target:TargetUiObject) => { + return target.uniqueId === groupInstance.uniqueId + })) { + optionalsTargetsToAdd.push(new TargetUiObject(groupInstance.uniqueId, TargetOrMemberType.GROUPS, groupInstance.name)); + } + }); + + return optionalsTargetsToAdd; + } + + openAddTargetModal(): void { + let addTargetModalConfig = { + title: this.policy.name + " ADD TARGETS", + size: "md", + type: SdcUiCommon.ModalType.custom, + testId: "addTargetsModal", + buttons: [ + {text: "ADD TARGETS", size: 'xsm', callback: this.addTargets, closeModal: false}, + {text: 'CANCEL', size: 'sm', type: "secondary", closeModal: true} + ] + } as SdcUiCommon.IModalConfig; + var optionalTargetsToAdd = this.getOptionalsTargetsToAdd(); + this.addModalInstance = this.modalService.openCustomModal(addTargetModalConfig, AddElementsComponent, { + elementsToAdd: optionalTargetsToAdd, + elementName: "target" + }); + } +} |