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/components | |
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/components')
122 files changed, 3664 insertions, 1775 deletions
diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts index 85d1899d96..269a8708fe 100644 --- a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts @@ -1,21 +1,19 @@ /*- - * ============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========================================================= + <!-- + ~ 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. + --> */ import { Component, Input } from '@angular/core'; diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/__snapshots__/artifact-form.component.spec.ts.snap b/catalog-ui/src/app/ng2/components/forms/artifacts-form/__snapshots__/artifact-form.component.spec.ts.snap new file mode 100644 index 0000000000..8cd085e248 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/__snapshots__/artifact-form.component.spec.ts.snap @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`artifact form component should match current snapshot of artifact form component 1`] = ` +<artifact-form + artifactTypesOptions={[Function Array]} + cacheService={[Function Object]} + initArtifactTypes={[Function Function]} + onDescriptionChange={[Function Function]} + onLabelChange={[Function Function]} + onTypeChange={[Function Function]} + onUploadFile={[Function Function]} + onValidationChange={[Function Subject]} + verifyTypeAndFileWereFilled={[Function Function]} +> + <form + class="artifact-form" + name="artifactForm" + novalidate="" + > + <onap-file-upload /> + <div + class="artifact-form-container" + > + + <div + class="right-form-container" + > + <sdc-textarea + label="Description" + testid="description" + /> + <sdc-validation> + <sdc-required-validator /> + <sdc-regex-validator /> + </sdc-validation> + </div> + </div> + </form> +</artifact-form> +`; diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.html b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.html new file mode 100644 index 0000000000..c84d6de512 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.html @@ -0,0 +1,55 @@ +<form class="artifact-form" novalidate name="artifactForm"> + + <onap-file-upload [disabled]="isViewOnly || showTypeFields && !artifact.artifactType" [convertToBase64]="true" [(value)]="artifact.artifactName" (fileUpload)="onUploadFile($event)" [placeHolder]="'Select File'" [label]="'Upload File'" [testId]="'fileUploadElement'" [required]="true"> + + </onap-file-upload> + <div class="artifact-form-container"> + <div class="left-form-container" *ngIf="showTypeFields"> + <sdc-input #artifactLabel + required="true" + [(value)]="artifact.artifactLabel" + [maxLength]="25" + [label]="'Artifact Label'" + [disabled]="isViewOnly || artifact && artifact.uniqueId" + [testId]="'artifactLabel'" + (keyup)="verifyTypeAndFileWereFilled()"> + </sdc-input> + <sdc-validation [validateElement]="artifactLabel" (validityChanged)="onLabelChange($event)"> + <sdc-required-validator [message]="'ADD_ARTIFACT_ERROR_LABEL_REQUIRED' | translate"></sdc-required-validator> + <sdc-regex-validator [message]="'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate" + [pattern]="validationPatterns['label']"></sdc-regex-validator> + </sdc-validation> + + <sdc-dropdown #artifactType [disabled]="isViewOnly || artifact && artifact.uniqueId" label="Type" [required]="true" + [selectedOption]="selectedFileType" placeHolder="Please choose type" (changed)="onTypeChange($event)" + [options]="artifactTypesOptions" [testId]="'artifacttype'"></sdc-dropdown> + <sdc-validation [validateElement]="artifactType"> + <sdc-required-validator + [message]="'ADD_ARTIFACT_ERROR_TYPE_REQUIRED' | translate"></sdc-required-validator> + </sdc-validation> + </div> + + <div class="right-form-container"> + <sdc-textarea #artifactDescription + [(value)]="artifact.description" + [required]="true" + testId="description" + [maxLength]="256" + label="Description" + [disabled]="isViewOnly" + (keyup)="verifyTypeAndFileWereFilled()"> + </sdc-textarea> + <sdc-validation [validateElement]="artifactDescription" (validityChanged)="onDescriptionChange($event)"> + <sdc-required-validator + [message]="'ADD_ARTIFACT_ERROR_DESCRIPTION_REQUIRED' | translate:{'field': 'Message' }"></sdc-required-validator> + <sdc-regex-validator [message]="'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate" + [pattern]="validationPatterns['comment']"></sdc-regex-validator> + </sdc-validation> + </div> + </div> +</form> + +<div *ngIf="artifact && artifact.esId"> + <div>UUID: {{artifact.artifactUUID}}</div> + <div>Version: {{artifact.artifactVersion}}</div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.less b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.less new file mode 100644 index 0000000000..3b04122085 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.less @@ -0,0 +1,23 @@ +.artifact-form { + display: flex; + justify-content: space-between; + flex-direction: column; + + .artifact-form-container { + margin-top: 10px; + display: flex; + flex-direction: row; + .left-form-container { + flex: 1; + padding-right: 10px; + } + + .right-form-container { + flex: 1; + + /deep/.sdc-textarea .sdc-textarea__textarea{ + min-height: 110px; + } + } + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.spec.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.spec.ts new file mode 100644 index 0000000000..fc69509ee9 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.spec.ts @@ -0,0 +1,242 @@ +import {ArtifactFormComponent} from "./artifact-form.component"; +import {async, ComponentFixture} from "@angular/core/testing"; +import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper"; +import {NO_ERRORS_SCHEMA} from "@angular/core"; +import {TranslateModule} from "../../../shared/translator/translate.module"; +import {CacheService} from "../../../services/cache.service"; +import {TranslateService} from "../../../shared/translator/translate.service"; +import {ArtifactModel} from "../../../../models/artifacts"; +import {IDropDownOption} from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models"; +import {Observable, Subject} from "rxjs"; +import {getValue} from "@ngxs/store"; + + +describe('artifact form component', () => { + + let fixture: ComponentFixture<ArtifactFormComponent>; + let cacheServiceMock: Partial<CacheService>; + let onValidationChangeMock: Partial<Subject<boolean>>; + + let artifactModel = new ArtifactModel(); + + + beforeEach( + async(() => { + + onValidationChangeMock = { + next: jest.fn() + } + + cacheServiceMock = { + contains: jest.fn(), + remove: jest.fn(), + set: jest.fn(), + get: jest.fn() + } + + const configure: ConfigureFn = testBed => { + testBed.configureTestingModule({ + declarations: [ArtifactFormComponent], + imports: [TranslateModule], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + {provide: CacheService, useValue: cacheServiceMock}, + {provide: TranslateService, useValue: {}} + ], + }); + }; + + configureTests(configure).then(testBed => { + fixture = testBed.createComponent(ArtifactFormComponent); + }); + }) + ); + + + it('should verify initArtifactTypes for DEPLOYMENT and ArtifactType = HEAT_ENV', () =>{ + + cacheServiceMock.get.mockImplementation(() =>{ + return { + artifacts: { + deployment:{ + resourceInstanceDeploymentArtifacts: [{name: "Dummy Value Returned from ui api"}], + } + } + } + }); + + fixture.componentInstance.artifactType = 'DEPLOYMENT'; + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.artifactType = 'HEAT_ENV'; + + fixture.componentInstance.initArtifactTypes(); + + expect(fixture.componentInstance.selectedFileType).toEqual(undefined); + + }); + + it('should verify initArtifactTypes for DEPLOYMENT and ComponentType = RESOURCE', () =>{ + + cacheServiceMock.get.mockImplementation(() =>{ + return { + artifacts: { + deployment:{ + resourceDeploymentArtifacts: [{name: "Dummy Value Returned from ui api"}], + } + } + } + }); + + fixture.componentInstance.artifactType = 'DEPLOYMENT'; + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.componentType = 'RESOURCE'; + + fixture.componentInstance.initArtifactTypes(); + + expect(fixture.componentInstance.selectedFileType).toEqual(undefined); + + }); + + it('should verify initArtifactTypes for DEPLOYMENT and NOT ComponentType = RESOURCE OR NOT ArtifactType = HEAT_ENV', () =>{ + + cacheServiceMock.get.mockImplementation(() =>{ + return { + artifacts: { + deployment:{ + serviceDeploymentArtifacts: [{name: "Dummy Value Returned from ui api"}], + } + } + } + }); + + fixture.componentInstance.artifactType = 'DEPLOYMENT'; + fixture.componentInstance.artifact = artifactModel; + // fixture.componentInstance.componentType = 'RESOURCE'; + + fixture.componentInstance.initArtifactTypes(); + + expect(fixture.componentInstance.selectedFileType).toEqual(undefined); + + }); + + it('should verify initArtifactTypes for INFORMATION', () =>{ + + cacheServiceMock.get.mockImplementation(() =>{ + return { + artifacts: { + other: [{name: "Val1"}, {name: "ExpectedValToBeSelected"}, {name: "Val3"}] + } + } + }); + + fixture.componentInstance.artifactType = 'INFORMATIONAL'; + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.artifactType = 'ExpectedValToBeSelected'; + + fixture.componentInstance.initArtifactTypes(); + + expect(fixture.componentInstance.selectedFileType).toEqual({"label": "ExpectedValToBeSelected", "value": "ExpectedValToBeSelected"}); + + }); + + + it('should match current snapshot of artifact form component', () => { + expect(fixture).toMatchSnapshot(); + }); + + it('should verify onUploadFile -> file gets file name', () => { + let file = { + filename:'dummyFileName' + } + + fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn(); + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.onUploadFile(file); + + expect(fixture.componentInstance.artifact.artifactName).toBe('dummyFileName'); + + const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled'); + expect(spy1).toHaveBeenCalled(); + }); + + it('should verify onUploadFile -> file is null', () => { + let file = null; + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.onUploadFile(file); + + expect(fixture.componentInstance.artifact.artifactName).toBe(null); + }); + + it('should verify onTypeChange -> verifyTypeAndFileWereFilled is being called', () => { + let selectedFileType:IDropDownOption; + selectedFileType = {"label": "dummyLabel", "value": "dummyValue"}; + fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn(); + + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.onTypeChange(selectedFileType); + + const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled'); + expect(spy1).toHaveBeenCalled(); + }); + + it('should verify onDescriptionChange -> verifyTypeAndFileWereFilled is being called', () => { + fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn(); + fixture.componentInstance.onValidationChange.next = jest.fn(() => true); + + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.onDescriptionChange(); + + const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled'); + expect(spy1).toHaveBeenCalled(); + }); + + it('should verify onLabelChange -> verifyTypeAndFileWereFilled is being called', () => { + fixture.componentInstance.verifyTypeAndFileWereFilled = jest.fn(); + fixture.componentInstance.onValidationChange.next = jest.fn(() => true); + + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.onLabelChange(true); + + const spy1 = jest.spyOn(fixture.componentInstance,'verifyTypeAndFileWereFilled'); + expect(spy1).toHaveBeenCalled(); + }); + + it('should verify verifyTypeAndFileWereFilled -> verify branch this.artifact.artifactType !== \'DEPLOYMENT\' ==>> onValidationChange.next(false)', () => { + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.artifactType = 'NOT_DEPLOYMENT'; + fixture.componentInstance.artifact.mandatory = true; + fixture.componentInstance.descriptionIsValid = false; + + let onValidationChangeResult; + + fixture.componentInstance.onValidationChange.subscribe((data) => { + onValidationChangeResult = data; + // console.log("Subscriber got data >>>>> "+ data); + }); + + fixture.componentInstance.verifyTypeAndFileWereFilled(); + + expect(onValidationChangeResult).toBe(false); + }); + + it('should verify verifyTypeAndFileWereFilled -> verify branch this.artifact.artifactType !== \'DEPLOYMENT\' ==>> onValidationChange.next(true)', () => { + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.artifactType = 'NOT_DEPLOYMENT'; + fixture.componentInstance.artifact.mandatory = true; + fixture.componentInstance.artifact.artifactName = 'Something'; + fixture.componentInstance.descriptionIsValid = true; + + let onValidationChangeResult; + + fixture.componentInstance.onValidationChange.subscribe((data) => { + onValidationChangeResult = data; + // console.log("Subscriber got data >>>>> "+ data); + }); + + fixture.componentInstance.verifyTypeAndFileWereFilled(); + + expect(onValidationChangeResult).toBe(true); + }); + + +});
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.ts new file mode 100644 index 0000000000..905d1a25ad --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.component.ts @@ -0,0 +1,132 @@ +/** + * Created by rc2122 on 5/31/2018. + */ +import { Component, Input } from '@angular/core'; +import * as _ from 'lodash'; +import { IDropDownOption } from 'onap-ui-angular/dist/form-elements/dropdown/dropdown-models'; +import { Subject } from 'rxjs/Subject'; +import { ArtifactModel } from '../../../../models'; +import { ArtifactType, ComponentType } from '../../../../utils'; +import { Dictionary } from '../../../../utils/dictionary/dictionary'; +import { CacheService } from '../../../services/cache.service'; + +@Component({ + selector: 'artifact-form', + templateUrl: './artifact-form.component.html', + styleUrls: ['./artifact-form.component.less'] +}) +export class ArtifactFormComponent { + + @Input() artifact: ArtifactModel; + @Input() artifactType: ArtifactType; + @Input() componentType: string; + @Input() instanceId: string; + @Input() isViewOnly: boolean; + + public artifactTypesOptions: IDropDownOption[] = []; + public validationPatterns: Dictionary<string, RegExp>; + public selectedFileType: IDropDownOption; + public showTypeFields: boolean; + private onValidationChange: Subject<boolean> = new Subject(); + private descriptionIsValid: boolean; + private labelIsValid: boolean; + + constructor(private cacheService: CacheService) { + } + + ngOnInit(): void { + this.validationPatterns = this.cacheService.get('validation').validationPatterns; + this.initArtifactTypes(); + this.artifact.artifactGroupType = this.artifact.artifactGroupType || this.artifactType.toString(); + this.showTypeFields = (this.artifact.artifactGroupType === 'DEPLOYMENT' || !this.artifact.mandatory) && this.artifact.artifactGroupType !== 'SERVICE_API'; + } + + public onTypeChange = (selectedFileType: IDropDownOption) => { + this.artifact.artifactType = selectedFileType.value; + this.verifyTypeAndFileWereFilled(); + } + + public onUploadFile = (file) => { + if (file) { + this.artifact.artifactName = file.filename; + this.artifact.payloadData = file.base64; + console.log('FILE UPLOADED', file); + } else { + this.artifact.artifactName = null; + } + this.verifyTypeAndFileWereFilled(); + } + + private initArtifactTypes = (): void => { + const artifactTypes: any = this.cacheService.get('UIConfiguration'); + let validExtensions: string[]; + let artifactTypesList: string[]; + + switch (this.artifactType) { + case ArtifactType.DEPLOYMENT: + if (this.artifact.artifactType === ArtifactType.HEAT_ENV || this.instanceId) { + validExtensions = artifactTypes.artifacts.deployment.resourceInstanceDeploymentArtifacts; + } else if (this.componentType === ComponentType.RESOURCE) { + validExtensions = artifactTypes.artifacts.deployment.resourceDeploymentArtifacts; + } else { + validExtensions = artifactTypes.artifacts.deployment.serviceDeploymentArtifacts; + } + if (validExtensions) { + artifactTypesList = Object.keys(validExtensions); + } + break; + case ArtifactType.INFORMATION: + artifactTypesList = artifactTypes.artifacts.other.map((element: any) => { + return element.name; + }); + _.remove(artifactTypesList, (item: string) => { + return _.has(ArtifactType.THIRD_PARTY_RESERVED_TYPES, item) || + _.has(ArtifactType.TOSCA, item); + }); + break; + } + + _.forEach(artifactTypesList, (artifactType: string) => { + this.artifactTypesOptions.push({ label: artifactType, value: artifactType }); + }); + + this.selectedFileType = _.find(this.artifactTypesOptions, (artifactType) => { + return artifactType.value === this.artifact.artifactType; + }); + + } + + // Verify that the Type and the Name (file) are filled in the Modal + // For Description and Label - I used this.descriptionIsValid:boolean & this.labelIsValid:boolean as part of the sdc-validation Element + private verifyTypeAndFileWereFilled = () => { + if (this.artifact.artifactType === 'DEPLOYMENT' || !this.artifact.mandatory && this.artifact.artifactGroupType !== 'SERVICE_API') { + // In case of all fields are required: + // File, Description, Type and Label + if (this.artifact.artifactType && this.artifact.artifactName && this.descriptionIsValid && this.labelIsValid) { + this.onValidationChange.next(true); + } else { + this.onValidationChange.next(false); + } + } else { + // In case of like Information Artifact + // Only file and description are required + if (this.descriptionIsValid && this.artifact.artifactName) { + this.onValidationChange.next(true); + } else { + this.onValidationChange.next(false); + } + } + } + + // sdc-validation for Description + private onDescriptionChange = (isValid: boolean): void => { + this.descriptionIsValid = isValid; + this.onValidationChange.next(isValid) && this.verifyTypeAndFileWereFilled(); + } + + // sdc-validation for Label + private onLabelChange = (isValid: boolean): void => { + this.labelIsValid = isValid; + this.onValidationChange.next(isValid) && this.verifyTypeAndFileWereFilled(); + } +} diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.module.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.module.ts new file mode 100644 index 0000000000..dba801212e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifact-form.module.ts @@ -0,0 +1,21 @@ +/** + * Created by rc2122 on 5/24/2018. + */ +import { NgModule } from "@angular/core"; +import { TranslateModule } from "app/ng2/shared/translator/translate.module"; +import { SdcUiComponentsModule } from "onap-ui-angular"; +import { CommonModule } from '@angular/common'; +import {ArtifactFormComponent} from "./artifact-form.component"; + +@NgModule({ + declarations: [ArtifactFormComponent], + imports: [TranslateModule, + SdcUiComponentsModule, + CommonModule], + exports: [ArtifactFormComponent], + entryComponents: [ArtifactFormComponent] +}) + + +export class ArtifactFormModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifacts.service.ts b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifacts.service.ts new file mode 100644 index 0000000000..f9400e9d18 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/artifacts-form/artifacts.service.ts @@ -0,0 +1,175 @@ +import { Injectable } from '@angular/core'; +import { Store } from '@ngxs/store'; +import { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular'; +import { ArtifactModel } from '../../../../models'; +import { ArtifactGroupType, ArtifactType } from '../../../../utils/constants'; +import { TopologyTemplateService } from '../../../services/component-services/topology-template.service'; +import { TranslateService } from '../../../shared/translator/translate.service'; +import { CreateOrUpdateArtifactAction, DeleteArtifactAction } from '../../../store/actions/artifacts.action'; +import { EnvParamsComponent } from '../env-params/env-params.component'; +import { ArtifactFormComponent } from './artifact-form.component'; + +import { + CreateInstanceArtifactAction, + DeleteInstanceArtifactAction, + UpdateInstanceArtifactAction +} from '../../../store/actions/instance-artifacts.actions'; + +@Injectable() +export class ArtifactsService { + + constructor(private serviceLoader: SdcUiServices.LoaderService, + private modalService: SdcUiServices.ModalService, + private topologyTemplateService: TopologyTemplateService, + private translateService: TranslateService, + private store: Store) { + } + + public dispatchArtifactAction = (componentId: string, componentType: string, artifact: ArtifactModel, artifactType: ArtifactGroupType, instanceId: string) => { + const artifactObj = { + componentType, + componentId, + instanceId, + artifact + }; + + // Create or update instance artifact + if (instanceId) { + if (!artifact.uniqueId) { + // create instance artifact + return this.store.dispatch(new CreateInstanceArtifactAction(artifactObj)); + } else { + // update instance artifact + return this.store.dispatch(new UpdateInstanceArtifactAction(artifactObj)); + } + } else { + // Create or update artifact + return this.store.dispatch(new CreateOrUpdateArtifactAction(artifactObj)); + } + } + + public openArtifactModal = (componentId: string, componentType: string, artifact: ArtifactModel, artifactType: ArtifactGroupType, isViewOnly?: boolean, instanceId?: string) => { + + let modalInstance; + + const onOkPressed = () => { + const updatedArtifact = modalInstance.innerModalContent.instance.artifact; + this.serviceLoader.activate(); + this.dispatchArtifactAction(componentId, componentType, updatedArtifact, artifactType, instanceId) + .subscribe().add(() => this.serviceLoader.deactivate()); + }; + + const addOrUpdateArtifactModalConfig = { + title: (artifact && artifact.uniqueId) ? 'Update Artifact' : 'Create Artifact', + size: 'md', + type: SdcUiCommon.ModalType.custom, + testId: 'upgradeVspModal', + buttons: [ + { + id: 'done', + text: 'DONE', + disabled: isViewOnly, + size: 'Add Another', + closeModal: true, + callback: onOkPressed + }, + {text: 'CANCEL', size: 'sm', closeModal: true, type: 'secondary'} + ] as SdcUiCommon.IModalButtonComponent[] + } as SdcUiCommon.IModalConfig; + + modalInstance = this.modalService.openCustomModal(addOrUpdateArtifactModalConfig, ArtifactFormComponent, { + artifact: new ArtifactModel(artifact), + artifactType, + instanceId, + componentType, + isViewOnly + }); + + if (!isViewOnly) { + modalInstance.innerModalContent.instance.onValidationChange.subscribe((isValid) => { + modalInstance.getButtonById('done').disabled = !isValid; + }); + } + } + + public openViewEnvParams(componentType: string, componentId: string, artifact: ArtifactModel, instanceId?: string) { + const envParamsModal = { + title: artifact.artifactDisplayName, + size: 'xl', + type: SdcUiCommon.ModalType.custom, + testId: 'viewEnvParams', + isDisabled: false, + } as SdcUiCommon.IModalConfig; + + this.modalService.openCustomModal(envParamsModal, EnvParamsComponent, { + isInstanceSelected: !!instanceId, // equals to instanceId ? true : false + artifact: new ArtifactModel(artifact), + isViewOnly: true + }); + } + + public openUpdateEnvParams(componentType: string, componentId: string, artifact: ArtifactModel, instanceId?: string) { + let modalInstance; + const onOkPressed = () => { + const updatedArtifact = modalInstance.innerModalContent.instance.artifact; + this.serviceLoader.activate(); + this.dispatchArtifactAction(componentId, componentType, updatedArtifact, ArtifactType.DEPLOYMENT, instanceId) + .subscribe().add(() => this.serviceLoader.deactivate()); + }; + + const envParamsModal = { + title: artifact.artifactDisplayName, + size: 'xl', + type: SdcUiCommon.ModalType.custom, + testId: 'envParams', + isDisabled: false, + buttons: [ + { + id: 'save', + text: 'Save', + spinner_position: 'left', + size: 'sm', + callback: onOkPressed, + closeModal: true + }, + {text: 'Cancel', size: 'sm', closeModal: true, type: 'secondary'} + ] as SdcUiCommon.IModalButtonComponent[] + } as SdcUiCommon.IModalConfig; + + modalInstance = this.modalService.openCustomModal(envParamsModal, EnvParamsComponent, { + isInstanceSelected: !!instanceId, // equals to instanceId ? true : false + artifact: new ArtifactModel(artifact) + }); + + modalInstance.innerModalContent.instance.onValidationChange.subscribe((isValid) => { + modalInstance.getButtonById('save').disabled = !isValid; + }); + } + + public deleteArtifact = (componentType: string, componentId: string, artifact: ArtifactModel, instanceId?: string) => { + + const artifactObject = { + componentType, + componentId, + artifact, + instanceId + }; + + const onOkPressed: Function = () => { + this.serviceLoader.activate(); + this.store.dispatch((instanceId) ? new DeleteInstanceArtifactAction(artifactObject) : new DeleteArtifactAction(artifactObject)) + .subscribe().add(() => this.serviceLoader.deactivate()); + }; + + const title = this.translateService.translate('ARTIFACT_VIEW_DELETE_MODAL_TITLE'); + const text = this.translateService.translate('ARTIFACT_VIEW_DELETE_MODAL_TEXT', {name: artifact.artifactDisplayName}); + const okButton = { + testId: 'OK', + text: 'OK', + type: SdcUiCommon.ButtonType.warning, + callback: onOkPressed, + closeModal: true + } as SdcUiComponents.ModalButtonComponent; + this.modalService.openWarningModal(title, text, 'delete-information-artifact-modal', [okButton]); + } +} diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/__snapshots__/env-params.component.spec.ts.snap b/catalog-ui/src/app/ng2/components/forms/env-params/__snapshots__/env-params.component.spec.ts.snap new file mode 100644 index 0000000000..aa567bbef2 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/env-params/__snapshots__/env-params.component.spec.ts.snap @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`environment parameters component should match current snapshot of env-params component 1`] = ` +<env-params + cacheService={[Function Object]} + clearCurrentValue={[Function Function]} + copiedWorkingArtifactHeatParameters={[Function Array]} + defaultDeploymentTimeout={[Function Number]} + displayRegexValid={[Function String]} + maxDeploymentTimeout={[Function Number]} + minDeploymentTimeout={[Function Number]} + onValidationChange={[Function Subject]} + onValidityChange={[Function Function]} + openPopOver={[Function Function]} + popoverService={[Function Object]} + textArea="undefined" +> + <div + class="filter-bar" + > + <sdc-filter-bar /> + </div><ngx-datatable + class="material ngx-datatable" + > + <div + visibilityobserver="" + > + + <datatable-body + class="datatable-body" + > + <datatable-selection> + + + + </datatable-selection> + </datatable-body> + + </div> + </ngx-datatable> +</env-params> +`; diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.html b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.html new file mode 100644 index 0000000000..f55aff5132 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.html @@ -0,0 +1,71 @@ +<div class="filter-bar"> + <sdc-filter-bar + [placeHolder]="'Search...'" + [testId]="'search-env-param-name'" + (keyup)="updateFilter($event)"> + </sdc-filter-bar> +</div> + +<ngx-datatable + class='material' + [rows]='artifact.heatParameters' + [columnMode]="'flex'" + [headerHeight]="40" + [rowHeight]="'auto'" + [scrollbarV]="false"> + + <ngx-datatable-column name="Parameter" [flexGrow]="2"> + <ng-template let-row="row" ngx-datatable-cell-template prop="name"> + {{row.name}} + <span *ngIf="row.description.length > 0" class="info"> + <svg-icon [name]="'comment'" (click)="openPopOver('',row.description,{x:$event.pageX , y:$event.pageY },'bottom')"></svg-icon> + </span> + </ng-template> + </ngx-datatable-column> + + <ngx-datatable-column name="DefaultValue"[flexGrow]="1"> + <ng-template let-row="row" let-value="value" ngx-datatable-cell-template> + {{row.defaultValue}} + </ng-template> + </ngx-datatable-column> + + <ngx-datatable-column name="CurrentValue" [flexGrow]="2"> + <ng-template let-row="row" let-value="value" ngx-datatable-cell-template> + <sdc-input class="sdc-input-wrapper" #numberValidator + [placeHolder]="'Enter text'" + [isViewMode]="isViewOnly" + [size]="'medium'" + [(value)]=row.currentValue + [isIconClickable]="true" + (onRighIconClicked)="clearCurrentValue(row.name)" + [righIconName]="'trash-o'" + [testId] = "'value-field-of-' + row.name"> + </sdc-input> + + <sdc-validation [validateElement]="numberValidator" (validityChanged)="onValidityChange($event)" [disabled]="false" [testId]="_testId"> + <sdc-regex-validator *ngIf="displayRegexValid && row.type == 'number' && row.currentValue !== null" [message]="'Value should be of type number.'" [pattern]="displayRegexValid" [disabled]="false"></sdc-regex-validator> + </sdc-validation> + </ng-template> + </ngx-datatable-column> + +</ngx-datatable> + +<div *ngIf="isInstanceSelected" class="artifactTimeout"> + + <sdc-number-input + label="Deployment Timeout ({{minDeploymentTimeout}}-{{maxDeploymentTimeout}} minutes)" + [required]="true" + [disabled]="false" + name="artifactTimeout" + testId="deploymentTimeout" + value="{{artifact.timeout}}" + [maxValue]="maxDeploymentTimeout" + [minValue]="minDeploymentTimeout" + (valueChange)="timeoutChanged($event)" + [isViewMode]="isViewOnly" + [step]="1" + > + + </sdc-number-input> + +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.less b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.less new file mode 100644 index 0000000000..48b4cba184 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.less @@ -0,0 +1,21 @@ +.filter-bar { + padding-bottom: 25px; +} + +:host ::ng-deep { + + .ngx-datatable { + //border: 1px solid red; + .datatable-body-cell { + .info { + float: right; + } + } + } +} + +.artifactTimeout{ + padding-top: 25px; + justify-content: start; + width: 230px; +} diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.spec.ts b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.spec.ts new file mode 100644 index 0000000000..f6b0eb4a21 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.spec.ts @@ -0,0 +1,98 @@ +import {async, ComponentFixture} from "@angular/core/testing"; +import {EnvParamsComponent} from "./env-params.component"; +import {SdcUiServices, SdcUiCommon} from "onap-ui-angular"; +import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper"; +import {NgxDatatableModule} from "@swimlane/ngx-datatable"; +import {NO_ERRORS_SCHEMA} from "@angular/core"; +import {ArtifactModel} from "../../../../models/artifacts"; +import { CacheService } from '../../../services/cache.service'; + +describe('environment parameters component', () => { + + let fixture: ComponentFixture<EnvParamsComponent>; + let popoverServiceMock: Partial<SdcUiServices.PopoverService>; + let regexPatterns: any; + + let artifactModel = new ArtifactModel(); + + let mockHeatParameters = [ + {currentValue: "1", defaultValue: null, description: "Description 1", empty:false, name: "Param1", ownerId: null, type: "string", uniqueId: null, envDisplayName:null, version: null, filterTerm:null}, + {currentValue: "2", defaultValue: null, description: "Description 2", empty:false, name: "Param2", ownerId: null, type: "string", uniqueId: null, envDisplayName:null, version: null, filterTerm:null}, + {currentValue: "3", defaultValue: null, description: "Description 3", empty:false, name: "Param3", ownerId: null, type: "string", uniqueId: null, envDisplayName:null, version: null, filterTerm:null} + ]; + + let keyboardEvent = new KeyboardEvent("keyup"); + + beforeEach( + async(() => { + + popoverServiceMock = { + createPopOver : jest.fn() + } + + const configure: ConfigureFn = testBed => { + testBed.configureTestingModule({ + declarations: [EnvParamsComponent], + imports: [NgxDatatableModule], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + { provide: SdcUiServices.PopoverService, useValue: popoverServiceMock }, + { provide: CacheService, useValue: { get: jest.fn() } } + ], + }); + }; + + configureTests(configure).then(testBed => { + fixture = testBed.createComponent(EnvParamsComponent); + }); + }) + ); + + it('should match current snapshot of env-params component', () => { + expect(fixture).toMatchSnapshot(); + }); + + it('should clear CurrentValue for a given name in the heat parameter', () => { + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.heatParameters = mockHeatParameters; + expect(fixture.componentInstance.artifact.heatParameters.length).toBe(3); + expect(fixture.componentInstance.artifact.heatParameters[0].currentValue).toBe("1"); + fixture.componentInstance.clearCurrentValue("Param1"); + expect(fixture.componentInstance.artifact.heatParameters[0].currentValue).toBe(""); + }); + + it("should update filter heatParameters so there won''t be any value to be displayed", () => { + + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.heatParameters = mockHeatParameters; + fixture.componentInstance.ngOnInit(); + + let event = { + target : { + value: 'paramNotExist' + } + } + + expect(fixture.componentInstance.artifact.heatParameters.length).toBe(3); + fixture.componentInstance.updateFilter(event); + expect(fixture.componentInstance.artifact.heatParameters.length).toBe(0); + }); + + it("should update filter heatParameters so there will be only 1 value to be displayed", () => { + + fixture.componentInstance.artifact = artifactModel; + fixture.componentInstance.artifact.heatParameters = mockHeatParameters; + fixture.componentInstance.ngOnInit(); + + let event = { + target : { + value: 'param1' + } + } + + expect(fixture.componentInstance.artifact.heatParameters.length).toBe(3); + fixture.componentInstance.updateFilter(event); + expect(fixture.componentInstance.artifact.heatParameters.length).toBe(1); + }); + +});
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.ts b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.ts new file mode 100644 index 0000000000..58d266a01d --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.component.ts @@ -0,0 +1,91 @@ +/*- + * ============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 { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; +import { SdcUiCommon, SdcUiServices } from 'onap-ui-angular'; +import { Subject } from 'rxjs/Rx'; +import { ArtifactModel } from '../../../../models/artifacts'; +import { CacheService } from '../../../services/cache.service'; + +export interface IPoint { + x: number; + y: number; +} + +@Component({ + selector: 'env-params', + templateUrl: './env-params.component.html', + styleUrls: ['../../../../../assets/styles/table-style.less', './env-params.component.less'] +}) +export class EnvParamsComponent implements OnInit { + + @Input() public artifact: ArtifactModel; + @Input() public isInstanceSelected: boolean; + @Input() public isViewOnly: boolean; + + @ViewChild('textArea') textArea: ElementRef; + private copiedWorkingArtifactHeatParameters = []; + private onValidationChange: Subject<boolean> = new Subject(); + private displayRegexValid = SdcUiCommon.RegexPatterns.numberOrEmpty; + + // Deployment timeout in minutes + private maxDeploymentTimeout: number = 120; + private minDeploymentTimeout: number = 1; + private defaultDeploymentTimeout: number = 60; + + constructor(private cacheService: CacheService, private popoverService: SdcUiServices.PopoverService) { + const configuration = cacheService.get('UIConfiguration'); + if (configuration && configuration.heatDeploymentTimeout) { + this.maxDeploymentTimeout = configuration.heatDeploymentTimeout.maxMinutes; + this.minDeploymentTimeout = configuration.heatDeploymentTimeout.minMinutes; + this.defaultDeploymentTimeout = configuration.heatDeploymentTimeout.defaultMinutes; + } + } + + ngOnInit(): void { + this.copiedWorkingArtifactHeatParameters = [...this.artifact.heatParameters]; + } + + public clearCurrentValue = (name: string) => { + this.artifact.heatParameters.filter((param) => param.name === name)[0].currentValue = ''; + } + + public timeoutChanged(timeout) { + this.artifact.timeout = timeout; + } + + updateFilter(event) { + const val = event.target.value.toLowerCase(); + // filter our data + const temp = this.copiedWorkingArtifactHeatParameters.filter((param) => { + return !val || param.name ? param.name.toLowerCase().indexOf(val) !== -1 : -1 || param.currentValue ? param.currentValue.toLowerCase().indexOf(val) !== -1 : -1; + }); + // update the rows + this.artifact.heatParameters = temp; + } + + private openPopOver = (title: string, content: string, positionOnPage: IPoint, location: string) => { + this.popoverService.createPopOver(title, content, positionOnPage, location); + } + + private onValidityChange = (isValid: boolean): void => { + this.onValidationChange.next(isValid); + } +} diff --git a/catalog-ui/src/app/ng2/components/forms/env-params/env-params.module.ts b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.module.ts new file mode 100644 index 0000000000..85797bd45f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/forms/env-params/env-params.module.ts @@ -0,0 +1,28 @@ +import { NgModule } from "@angular/core"; +import { EnvParamsComponent } from "./env-params.component"; +import { NgxDatatableModule } from "@swimlane/ngx-datatable"; +import { SdcUiComponentsModule, SdcUiServices } from "onap-ui-angular"; + + +@NgModule({ + declarations: [ + EnvParamsComponent + ], + imports: [ + NgxDatatableModule, + SdcUiComponentsModule + ], + exports: [ + EnvParamsComponent + ], + entryComponents: [ //need to add anything that will be dynamically created + EnvParamsComponent + ], + providers: [ + SdcUiServices.ModalService + ] +}) + +export class EnvParamsModule { + +} diff --git a/catalog-ui/src/app/ng2/components/layout/layout.module.ts b/catalog-ui/src/app/ng2/components/layout/layout.module.ts index 827209326c..f6d2cf487e 100644 --- a/catalog-ui/src/app/ng2/components/layout/layout.module.ts +++ b/catalog-ui/src/app/ng2/components/layout/layout.module.ts @@ -13,7 +13,9 @@ import { TopNavComponent } from "./top-nav/top-nav.component"; FormsModule, TranslateModule ], - exports: [], + exports: [ + TopNavComponent + ], entryComponents: [ //need to add anything that will be dynamically created TopNavComponent ], diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/__snapshots__/top-nav.comonent.spec.ts.snap b/catalog-ui/src/app/ng2/components/layout/top-nav/__snapshots__/top-nav.comonent.spec.ts.snap new file mode 100644 index 0000000000..c650a9ca56 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/__snapshots__/top-nav.comonent.spec.ts.snap @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`artifact form component should match current snapshot of top-nav component 1`] = ` +<top-nav + $state={[Function Object]} + _getTopLvlSelectedIndexByState={[Function Function]} + authService={[Function Object]} + sdcConfig={[Function Object]} + searchTermChange={[Function EventEmitter]} + translateService={[Function Object]} +> + <nav + class="top-nav" + > + <div + class="asdc-app-title-wrapper" + > + <a + class="asdc-app-title" + > + + </a> + <div + class="asdc-version" + > + v. + </div> + </div> + + + <div + class="top-search" + > + <input + class="search-text" + data-tests-id="main-menu-input-search" + placeholder="Search" + type="text" + /> + <span + class="w-sdc-search-icon magnification" + /> + </div> + + </nav> +</top-nav> +`; diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.comonent.spec.ts b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.comonent.spec.ts new file mode 100644 index 0000000000..54fbb36dcf --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.comonent.spec.ts @@ -0,0 +1,161 @@ +import { NO_ERRORS_SCHEMA } from '@angular/core'; +import { async, ComponentFixture } from '@angular/core/testing'; +import { PluginsConfiguration } from 'app/models'; +import { Observable } from 'rxjs'; +import { Mock } from 'ts-mockery'; +import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper'; +import { MenuItem, MenuItemGroup } from '../../../../utils/menu-handler'; +import { SdcConfigToken } from '../../../config/sdc-config.config'; +import { AuthenticationService } from '../../../services/authentication.service'; +import { TranslateModule } from '../../../shared/translator/translate.module'; +import { TranslateService } from '../../../shared/translator/translate.service'; +import { TopNavComponent } from './top-nav.component'; + +describe('artifact form component', () => { + + let fixture: ComponentFixture<TopNavComponent>; + let translateServiceMock: Partial<TranslateService>; + let mockStateService; + let authServiceMock; + + const designerUser = { + email: 'designer@sdc.com', + firstName: 'Carlos', + fullName: 'Carlos Santana', + lastLoginTime: 1555587266566, + lastName: 'Santana', + role: 'DESIGNER', + status: 'ACTIVE', + userId: 'cs0008' + }; + + const pluginDisplayOptions = { + displayName : '', + displayContext : new Array<string>(), + displayRoles : new Array<string>() + }; + + let roleToReturn = designerUser; + + const map1 = new Map(); + map1.otherValue = pluginDisplayOptions; + + const map2 = new Map(); + pluginDisplayOptions.displayRoles = ['DESIGNER']; + pluginDisplayOptions.displayName = 'DCAE-DS'; + map2.tab = pluginDisplayOptions; + + PluginsConfiguration.plugins = + [ + {pluginId: 'DCAED', pluginDiscoveryUrl: 'DCAED_discoveryURL', pluginSourceUrl: 'DCAED_sourceURL', pluginStateUrl: 'DCAED_stateURL', pluginDisplayOptions: map1, isOnline: true}, + {pluginId: 'DCAE-DS', pluginDiscoveryUrl: 'DCAE-DS_discoveryURL', pluginSourceUrl: 'DCAE-DS_sourceURL', pluginStateUrl: 'DCAE-DS_stateURL', pluginDisplayOptions: map2, isOnline: true} + ]; + + beforeEach( + async(() => { + authServiceMock = { + getLoggedinUser: jest.fn().mockImplementation(() => { + return roleToReturn; + }) + }; + + mockStateService = { + go: jest.fn(), + includes: jest.fn(() => true), + current : { + name : 'plugins' + }, + params : {} + }; + + translateServiceMock = { + languageChangedObservable: Mock.of<Observable<string>>( { + subscribe : jest.fn().mockImplementation((cb) => { + cb(); + }) + }), + translate: jest.fn((str: string) => { + if (str === 'TOP_MENU_HOME_BUTTON') { + return 'HOME'; + } else if (str === 'TOP_MENU_CATALOG_BUTTON') { + return 'CATALOG'; + } else if (str === 'TOP_MENU_ON_BOARD_BUTTON') { + return 'ONBOARD'; + } else { + return 'TBD...'; + } + }) + }; + + const configure: ConfigureFn = (testBed) => { + testBed.configureTestingModule({ + declarations: [TopNavComponent], + imports: [TranslateModule], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + {provide: TranslateService, useValue: translateServiceMock}, + {provide: '$state', useValue: mockStateService}, + {provide: AuthenticationService, useValue: authServiceMock}, + {provide: SdcConfigToken, useValue: {csarFileExtension: 'csar', toscaFileExtension: 'yaml,yml'}}, + ], + }); + }; + + configureTests(configure).then((testBed) => { + fixture = testBed.createComponent(TopNavComponent); + }); + }) + ); + + it('should match current snapshot of top-nav component', () => { + expect(fixture).toMatchSnapshot(); + }); + + it('Once a Designer logged in, Menu Items will contain HOME, CATALOG, ONBOARD & DCAE-DS; HOME will be selected', () => { + + // topLvlSelectedIndex = 1 => Ignore the inner call to _getTopLvlSelectedIndexByState. + fixture.componentInstance.topLvlSelectedIndex = 0; + fixture.componentInstance.ngOnInit(); + + expect(fixture.componentInstance.topLvlMenu.itemClick).toBe(true); + + expect(fixture.componentInstance.topLvlMenu.menuItems.length).toBe(4); + + expect(fixture.componentInstance.topLvlMenu.menuItems[0]).toEqual({ + action: 'goToState', + blockedForTypes: null, + callback: null, + params: null, + state: 'dashboard', + text: 'HOME' + }); + expect(fixture.componentInstance.topLvlMenu.menuItems[1]).toEqual({ + action: 'goToState', + blockedForTypes: null, + callback: null, + params: null, + state: 'catalog', + text: 'CATALOG' + }); + expect(fixture.componentInstance.topLvlMenu.menuItems[2]).toEqual({ + action: 'goToState', + blockedForTypes: null, + callback: null, + params: null, + state: 'onboardVendor', + text: 'ONBOARD' + }); + expect(fixture.componentInstance.topLvlMenu.menuItems[3]).toEqual({ + action: 'goToState', + blockedForTypes: null, + callback: null, + params: + {path: 'DCAE-DS_stateURL'}, + state: 'plugins', + text: 'DCAE-DS' + }); + + expect(fixture.componentInstance.topLvlMenu.selectedIndex).toBe(0); + }); + +}); diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html index f82e110f1f..2636dd96bb 100644 --- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html @@ -65,6 +65,6 @@ <span class="w-sdc-search-icon magnification"></span> </div> - <div class="notification-icon" [ngClass]="{'disabled' : progress > 0}" *ngIf="user.role === 'DESIGNER' && notificationIconCallback" (click)="notificationIconCallback()" tooltip="Vendor Software Product Repository" tooltipPlacement="left" data-tests-id="repository-icon"></div> + <div class="notification-icon" [ngClass]="{'disabled' : progress > 0}" *ngIf="user && user.role === 'DESIGNER' && notificationIconCallback" (click)="notificationIconCallback()" tooltip="Vendor Software Product Repository" tooltipPlacement="left" data-tests-id="repository-icon"></div> </nav> diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less index 5c99015e7d..2bcdfc28d5 100644 --- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less @@ -120,7 +120,7 @@ height: 35px; background-color: white; font-size: 13px; - width: 150px; + width: auto; line-height: 35px; padding: 0 10px; diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts index a253b3a933..3bd2255488 100644 --- a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts @@ -19,14 +19,17 @@ */ import * as _ from "lodash"; -import {Component, Inject, Input, Output, EventEmitter} from "@angular/core"; +import {Component, Inject, Input, Output, EventEmitter, OnInit, OnDestroy, OnChanges} from "@angular/core"; import {IHostedApplication, IUserProperties} from "app/models"; import {MenuItemGroup, MenuItem} from "app/utils"; -import {UserService} from "../../../services/user.service"; +import {AuthenticationService} from "../../../services/authentication.service"; import {SdcConfigToken, ISdcConfig} from "../../../config/sdc-config.config"; import {TranslateService} from "../../../shared/translator/translate.service"; import {PluginsConfiguration, Plugin} from "app/models"; - +import { Subscription } from "rxjs"; +// import { Store } from "@ngrx/store"; +// import { AppState } from "app/ng2/store/app.state"; +// import * as unsavedChangesReducer from 'app/ng2/store/reducers/unsaved-changes.reducer'; declare const window:any; @Component({ @@ -34,7 +37,7 @@ declare const window:any; templateUrl: './top-nav.component.html', styleUrls:['./top-nav.component.less'] }) -export class TopNavComponent { +export class TopNavComponent implements OnInit, OnChanges { @Input() public version:string; @Input() public menuModel:Array<MenuItemGroup>; @Input() public topLvlSelectedIndex:number; @@ -48,15 +51,18 @@ export class TopNavComponent { this.searchTermChange.emit(event); } + private subscription: Subscription; + private hasUnsavedChanges: boolean; public topLvlMenu:MenuItemGroup; public user:IUserProperties; private topNavPlugins: Array<Plugin>; constructor(private translateService:TranslateService, @Inject('$state') private $state:ng.ui.IStateService, - private userService:UserService, + private authService:AuthenticationService, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { window.nav = this; + } private _getTopLvlSelectedIndexByState = ():number => { @@ -112,7 +118,7 @@ export class TopNavComponent { ngOnInit() { console.log('Nav is init!', this.menuModel); - this.user = this.userService.getLoggedinUser(); + this.user = this.authService.getLoggedinUser(); this.topNavPlugins = _.filter(PluginsConfiguration.plugins, (plugin: Plugin) => { return plugin.pluginDisplayOptions["tab"] !== undefined; }); @@ -142,7 +148,6 @@ export class TopNavComponent { this.topLvlMenu = new MenuItemGroup(0, tmpArray, true); this.topLvlMenu.selectedIndex = isNaN(this.topLvlSelectedIndex) ? this._getTopLvlSelectedIndexByState() : this.topLvlSelectedIndex; - this.generateMenu(); }); } @@ -160,6 +165,7 @@ export class TopNavComponent { }); } + menuItemClick(itemGroup:MenuItemGroup, item:MenuItem) { let onSuccessFunction = () => { diff --git a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/__snapshots__/filter-properties-assignment.component.spec.ts.snap b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/__snapshots__/filter-properties-assignment.component.spec.ts.snap new file mode 100644 index 0000000000..02e98e2219 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/__snapshots__/filter-properties-assignment.component.spec.ts.snap @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`filter-properties-assignemnt component should match current snapshot of artifact-tab component 1`] = ` +<filter-properties-assignment + allSelected="false" + clearAll={[Function Function]} + close={[Function Function]} + filterData={[Function FilterPropertiesAssignmentData]} + filterPopover={[Function ElementRef]} + footerButtons={[Function Object]} + onTypeSelected={[Function Function]} + search={[Function Function]} + searchProperties={[Function EventEmitter]} + selectAll={[Function Function]} + selectedTypes={[Function Object]} + someTypesSelectedAndThereIsPropertyName={[Function Function]} +> + <popover-content + placement="bottom-right" + > + <form> + <div + class="field" + > + <label> + Resource Type + </label> + <div> + <checkbox + data-tests-id="filter-checkbox-all" + /> + </div> + + </div> + <div + class="field" + > + <label> + Property Name + </label> + <input + class="i-sdc-form-input" + data-tests-id="filter-box" + name="propertyName" + placeholder="Type here" + required="" + /> + </div> + </form> + </popover-content><div + class="open-filter-button" + > + <div + class="sprite-new filter-icon" + data-tests-id="filter-button" + /> + </div> +</filter-properties-assignment> +`; diff --git a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html index 9593ade48b..1c2d77a728 100644 --- a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html @@ -38,6 +38,6 @@ </div> </form> </popover-content> -<div class="open-filter-button" [popover]="filterPopover" [ngClass]="{'open':showPopover}" (onShown)="showPopover = true" (onHidden)="showPopover = false"> +<div class="open-filter-button" [popover]="filterPopover" > <div class="sprite-new filter-icon" data-tests-id="filter-button"></div> </div> diff --git a/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.spec.ts new file mode 100644 index 0000000000..bcc5535b32 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.spec.ts @@ -0,0 +1,141 @@ +import {async, ComponentFixture} from "@angular/core/testing"; +import {FilterPropertiesAssignmentComponent} from "./filter-properties-assignment.component"; +import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper"; +import {NO_ERRORS_SCHEMA} from "@angular/core"; +import {FilterPropertiesAssignmentData} from "../../../../models/filter-properties-assignment-data"; +import {PopoverComponent} from "../../ui/popover/popover.component"; + + + +describe('filter-properties-assignemnt component', () => { + + let fixture: ComponentFixture<FilterPropertiesAssignmentComponent>; + + beforeEach( + async(() => { + + const configure: ConfigureFn = testBed => { + testBed.configureTestingModule({ + declarations: [FilterPropertiesAssignmentComponent], + imports: [], + schemas: [NO_ERRORS_SCHEMA], + providers: [], + }); + }; + + configureTests(configure).then(testBed => { + fixture = testBed.createComponent(FilterPropertiesAssignmentComponent); + + }); + }) + ); + + + it('should match current snapshot of artifact-tab component', () => { + expect(fixture).toMatchSnapshot(); + }); + + it('on selectAll', () => { + let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData(); + filterData.propertyName = 'testVal'; + let typesOptions:Array<string> = ['option1', 'option2', 'option3']; + let selectedTypes:Object = {}; + + fixture.componentInstance.filterData = filterData; + fixture.componentInstance.typesOptions = typesOptions; + fixture.componentInstance.selectedTypes = selectedTypes; + + fixture.componentInstance.selectAll(); + + let expectedRes = {"option1": false,"option2": false,"option3": false}; + expect(fixture.componentInstance.selectedTypes).toEqual(expectedRes); + }); + + + it ('on onTypeSelected allSelected set to False', () => { + let selectedTypes:Object = {"option1": true,"option2": false,"option3": true}; + fixture.componentInstance.selectedTypes = selectedTypes; + fixture.componentInstance.allSelected = true; + fixture.componentInstance.onTypeSelected('option2'); + + expect(fixture.componentInstance.allSelected).toBe(false); + }); + + it ('on onTypeSelected allSelected remains True', () => { + let selectedTypes:Object = {"option1": true,"option2": true,"option3": true}; + fixture.componentInstance.selectedTypes = selectedTypes; + fixture.componentInstance.allSelected = true; + fixture.componentInstance.onTypeSelected('option2'); + + expect(fixture.componentInstance.allSelected).toBe(true); + }); + + it ('on clearAll', () => { + let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData(); + filterData.propertyName = 'testVal'; + let selectedTypes:Object = {"option1": true,"option2": false,"option3": true}; + + fixture.componentInstance.filterData = filterData; + fixture.componentInstance.selectedTypes = selectedTypes; + fixture.componentInstance.allSelected = true; + + fixture.componentInstance.clearAll(); + + expect(fixture.componentInstance.filterData.propertyName).toBe(''); + expect(fixture.componentInstance.allSelected).toBe(false); + }); + + it ('someTypesSelectedAndThereIsPropertyName return True', ()=> { + let res = fixture.componentInstance.someTypesSelectedAndThereIsPropertyName(); + + expect(res).toBe(true) + }); + + it ('someTypesSelectedAndThereIsPropertyName return Null', ()=> { + let selectedTypes:Object = {"option1": true,"option2": false,"option3": true}; + let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData(); + filterData.propertyName = 'testVal'; + + fixture.componentInstance.selectedTypes = selectedTypes; + fixture.componentInstance.filterData = filterData; + + let res = fixture.componentInstance.someTypesSelectedAndThereIsPropertyName(); + + expect(res).toBe(null) + }); + + it ('search', ()=> { + + let filterData:FilterPropertiesAssignmentData = new FilterPropertiesAssignmentData(); + filterData.selectedTypes = ["CP"]; + fixture.componentInstance.filterData = filterData; + + let componentType: string = 'resource'; + fixture.componentInstance.componentType = componentType; + + let selectedTypes:Object = {"option1": true,"CP": true,"option3": true}; + fixture.componentInstance.selectedTypes = selectedTypes; + + let temp:any; + let filterPopover: PopoverComponent = new PopoverComponent(temp , temp ); + fixture.componentInstance.filterPopover = filterPopover; + fixture.componentInstance.filterPopover.hide = jest.fn(); + + fixture.componentInstance.search(); + + expect(fixture.componentInstance.filterData.selectedTypes).toEqual(["CP"]); + expect(fixture.componentInstance.filterPopover.hide).toHaveBeenCalled(); + }); + + it('close', () => { + let temp:any; + let filterPopover: PopoverComponent = new PopoverComponent(temp , temp ); + fixture.componentInstance.filterPopover = filterPopover; + fixture.componentInstance.filterPopover.hide = jest.fn(); + + fixture.componentInstance.close(); + + expect(fixture.componentInstance.filterPopover.hide).toHaveBeenCalled(); + }); + +});
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html index 41ecaa899e..9d1a2fa734 100644 --- a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html +++ b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.html @@ -29,8 +29,8 @@ [rowHeight]="200" [reorderable]="false" > - <ngx-datatable-column prop="{{col.prop}}" [minWidth]="100" *ngFor="let col of columns"> - <template let-column="column" height="100" ngx-datatable-header-template> + <ngx-datatable-column *ngFor="let col of columns" prop="{{col.prop}}" [minWidth]="100" > + <ng-template let-column="column" height="100" ngx-datatable-header-template> <span class="datatable-column-span"> <b>{{col.name}}</b> <div *ngIf="canBeDeleted(col.name)" style="width: 45px !important; color: red; " @@ -44,23 +44,23 @@ placeholder='Filter column...' (keyup)='updateColumnFilter($event, col.prop)' /> - </template> + </ng-template> </ngx-datatable-column> <ngx-datatable-column *ngIf="addNewColumn" class="datatable-white-body-cell" [minWidth]="220" [maxWidth]="220" [width]="220" > - <template ngx-datatable-header-template> + <ng-template ngx-datatable-header-template> <gab-column-provider [pathsAndNames]="pathsandnames" (onCancel)="hideAddNewColumn()" (onSave)="refresh()"></gab-column-provider> - </template> - <template class="datatable-white-body-cell" ngx-datatable-cell-template> - </template> + </ng-template> + <ng-template class="datatable-white-body-cell" ngx-datatable-cell-template> + </ng-template> </ngx-datatable-column> <ngx-datatable-column class="datatable-white-body-cell" [minWidth]="50" [maxWidth]="50" [width]="50" > - <template ngx-datatable-header-template> + <ng-template ngx-datatable-header-template> <div data-tests-id="gab-add-btn" class="add-btn add-btn-div" (click)="showAddNewColumn()">Add</div> - </template> - <template class="datatable-white-body-cell" ngx-datatable-cell-template> - </template> + </ng-template> + <ng-template class="datatable-white-body-cell" ngx-datatable-cell-template> + </ng-template> </ngx-datatable-column> </ngx-datatable> -</div>
\ No newline at end of file +</div> diff --git a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts index 4de7ff07d9..ea8039e1b4 100644 --- a/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/generic-artifact-browser/generic-artifact-browser.component.ts @@ -64,8 +64,8 @@ export class GenericArtifactBrowserComponent { this.gabService.getArtifact(this.artifactid, this.resourceid, paths) .subscribe( response => { - let typedServerResponse: IServerResponse = response.json() as IServerResponse; - this.normalizeDataForNgxDatatable(typedServerResponse.data); + // let typedServerResponse: IServerResponse = response.json() as IServerResponse; + this.normalizeDataForNgxDatatable(response['data']); }, () => { this.ready = false; diff --git a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.spec.ts new file mode 100644 index 0000000000..fc76463970 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.spec.ts @@ -0,0 +1,52 @@ +import { async, ComponentFixture } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper'; +import 'jest-dom/extend-expect'; +import {HierarchyNavigationComponent} from "./hierarchy-navigation.component"; +import {HierarchyDisplayOptions} from "./hierarchy-display-options"; + + +describe('hierarchyNavigationComponent', () => { + let fixture: ComponentFixture<HierarchyNavigationComponent>; + let hierarchyDisplayOptions: HierarchyDisplayOptions; + beforeEach( + async(() => { + const configure: ConfigureFn = testBed => { + testBed.configureTestingModule({ + declarations: [HierarchyNavigationComponent] + }); + }; + + configureTests(configure).then(testBed => { + fixture = testBed.createComponent(HierarchyNavigationComponent); + hierarchyDisplayOptions = new HierarchyDisplayOptions("id", "name", "children"); + fixture.componentInstance.displayOptions = hierarchyDisplayOptions; + fixture.detectChanges(); + fixture.componentInstance.displayData = [{name: "aaa", id: "1", children: [{name: "bbb", id: "1.1"}, {name: "ccc", id: "1.2", children: [{name: "aaa", id: "1.2.1"}]}]}, {name: "bbb", id: "2"}]; + fixture.detectChanges(); + }); + }) + ); + + it('should have a selected class after user click on a tree node', + () => { + let firstNodeElement = fixture.debugElement.query(By.css('.node-item')); + fixture.componentInstance.updateSelected.subscribe((item) => { + fixture.componentInstance.selectedItem = item.id; + fixture.detectChanges(); + }); + firstNodeElement.nativeElement.click(); + fixture.whenStable().then(() => { + expect(firstNodeElement.children[0].nativeElement).toHaveClass('selected'); + }); + }); + + it('should call onClick function when user click on a tree node', + () => { + spyOn(fixture.componentInstance, 'onClick'); + let firstNodeElement = fixture.debugElement.query(By.css('.node-item')).nativeElement; + firstNodeElement.click(); + expect(fixture.componentInstance.onClick).toHaveBeenCalled(); + }); + +});
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts index 1698157e90..8b20aa28f8 100644 --- a/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts @@ -21,7 +21,6 @@ import {Component, Input, Output, EventEmitter} from '@angular/core'; import {HierarchyDisplayOptions} from './hierarchy-display-options'; - @Component({ selector: 'hierarchy-navigation', templateUrl: './hierarchy-navigation.component.html', @@ -32,7 +31,6 @@ export class HierarchyNavigationComponent { @Input() displayData: Array<any>; @Input() selectedItem: any; @Input() displayOptions: HierarchyDisplayOptions; - @Output() updateSelected:EventEmitter<any> = new EventEmitter(); onClick = ($event, item) => { diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html index 3ef1f57bf2..eeba590046 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html @@ -35,33 +35,37 @@ <div class="no-data" *ngIf="!inputs || !inputs.length">No data to display</div> <div> <div class="table-row" *ngFor="let input of inputs" (click)="selectedInputId = input.path" [ngClass]="{'selected': selectedInputId && selectedInputId === input.path}"> + <!-- Property Name --> <div class="table-cell col1"> <div class="inner-cell-div" tooltip="{{input.name}}"><span class="property-name">{{input.name}}</span></div> <span *ngIf="input.description" class="property-description-icon sprite-new show-desc" tooltip="{{input.description}}" tooltipDelay="0"></span> </div> + <!-- From Instance --> <div class="table-cell col3"> <div class="inner-cell-div" tooltip="{{instanceNamesMap[input.instanceUniqueId]?.name}}"> <span>{{instanceNamesMap[input.instanceUniqueId]?.name}}</span> </div> </div> + <!-- Type --> <div class="table-cell col2"> <div class="inner-cell-div" tooltip="{{input.type | contentAfterLastDot}}"> <span>{{input.type | contentAfterLastDot}}</span> </div> </div> + <!-- Value --> <div class="table-cell valueCol input-value-col" [class.inner-table-container]="input.childrenProperties || !input.isSimpleType"> <dynamic-element class="value-input" - *ngIf="input.isSimpleType" + *ngIf="checkInstanceFePropertiesMapIsFilled() && input.isSimpleType" pattern="validationUtils.getValidationPattern(input.type)" [value]="input.defaultValueObj" [type]="input.type" - [constraints]="input.constraints" [name]="input.name" (elementChanged)="onInputChanged(input, $event)" [readonly]="readonly" - [testId]="'input-' + input.name"> + [testId]="'input-' + input.name" + [constraints] = "getConstraints(input)"> </dynamic-element> <div class="delete-button-container"> <span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)" data-tests-id="delete-input-button"></span> diff --git a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts index d95198f162..f45d5a85c7 100644 --- a/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts @@ -26,6 +26,8 @@ import { Component, Input, Output, EventEmitter } from "@angular/core"; import { InputFEModel } from "app/models"; import { ModalService } from "../../../services/modal.service"; import { InstanceFeDetails } from "app/models/instance-fe-details"; +import { InstanceFePropertiesMap } from "../../../../models/properties-inputs/property-fe-map"; +import { DataTypeService } from "../../../services/data-type.service"; @Component({ selector: 'inputs-table', @@ -41,6 +43,8 @@ export class InputsTableComponent { @Output() inputChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() deleteInput: EventEmitter<any> = new EventEmitter<any>(); + @Input() fePropertiesMap: InstanceFePropertiesMap; + sortBy: String; reverse: boolean; selectedInputToDelete: InputFEModel; @@ -74,7 +78,8 @@ export class InputsTableComponent { }; - constructor(private modalService: ModalService) { + constructor(private modalService: ModalService, private dataTypeService: DataTypeService){ + var x = 5 } @@ -89,9 +94,40 @@ export class InputsTableComponent { }; openDeleteModal = (input: InputFEModel) => { + console.log('exist inputs: ' + this.inputs) + + this.selectedInputToDelete = input; this.modalService.createActionModal("Delete Input", "Are you sure you want to delete this input?", "Delete", this.onDeleteInput, "Close").instance.open(); } + + getConstraints(input:InputFEModel): string[]{ + + if (input.inputPath){ + const pathValuesName = input.inputPath.split('#'); + const rootPropertyName = pathValuesName[0]; + const propertyName = pathValuesName[1]; + let filterredRootPropertyType = _.values(this.fePropertiesMap)[0].filter(property => + property.name == rootPropertyName); + if (filterredRootPropertyType.length > 0){ + let rootPropertyType = filterredRootPropertyType[0].type; + return this.dataTypeService.getConstraintsByParentTypeAndUniqueID(rootPropertyType, propertyName); + }else{ + return null; + } + + } + // else if(input.constraints.length > 0){ + // return input.constraints[0].validValues + // } + else{ + return null; + } + } + + checkInstanceFePropertiesMapIsFilled(){ + return _.keys(this.fePropertiesMap).length > 0 + } } 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 index aa5f2420b3..9613439859 100644 --- 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 @@ -14,12 +14,11 @@ * 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'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { PolicyInstance } from 'app/models'; +import { InstanceFeDetails } from 'app/models/instance-fe-details'; +import { TranslateService } from 'app/ng2/shared/translator/translate.service'; +import { ModalService } from '../../../services/modal.service'; @Component({ selector: 'policies-table', @@ -28,13 +27,13 @@ import {TranslateService} from 'app/ng2/shared/translator/translate.service'; }) export class PoliciesTableComponent { - @Input() policies: Array<PolicyInstance>; + @Input() policies: PolicyInstance[]; @Input() instanceNamesMap: Map<string, InstanceFeDetails>; @Input() readonly: boolean; @Input() isLoading: boolean; @Output() deletePolicy: EventEmitter<any> = new EventEmitter<any>(); - sortBy: String; + sortBy: string; reverse: boolean; selectedPolicyToDelete: PolicyInstance; deleteMsgTitle: string; @@ -42,43 +41,39 @@ export class PoliciesTableComponent { modalDeleteBtn: string; modalCancelBtn: string; + constructor(private modalService: ModalService, private translateService: TranslateService) { + } + sort = (sortBy) => { this.reverse = (this.sortBy === sortBy) ? !this.reverse : true; - let reverse = this.reverse ? 1 : -1; + const 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 { + const instanceNameMapTemp = this.instanceNamesMap; + let itemIdx1Val = ''; + let itemIdx2Val = ''; + this.policies.sort((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) { + } else if (itemIdx1Val > itemIdx2Val) { return 1 * reverse; - } - else { + } 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"); + 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'); }); } @@ -86,15 +81,13 @@ export class PoliciesTableComponent { 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.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 index f780c62c0b..57cb13c281 100644 --- 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 @@ -14,12 +14,12 @@ * 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"; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module'; +import { TranslateModule } from 'app/ng2/shared/translator/translate.module'; +import { GlobalPipesModule } from '../../../pipes/global-pipes.module'; +import { PoliciesTableComponent } from './policies-table.component'; @NgModule({ declarations: [ @@ -38,4 +38,4 @@ import {GlobalPipesModule} from "../../../pipes/global-pipes.module"; providers: [] }) export class PoliciesTableModule { -}
\ No newline at end of file +} diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html index c4639aeda0..f6396e6f2c 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html @@ -12,8 +12,8 @@ * See the License for the specific language governing permissions and * limitations under the License. --> - - + + <div *ngIf="!property.hidden" class="dynamic-property-row nested-level-{{nestedLevel}}" [@fadeIn] [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName, 'readonly': property.isDisabled ||property.isDeclared}" [class.with-top-border]="property.isChildOfListOrMap" @@ -48,13 +48,13 @@ pattern="validationUtils.getValidationPattern(property.type)" [value]="property.isDeclared ? property.value : property.valueObj" [type]="property.isDeclared ? 'string' : property.type" - [childType]="property.schema.property.type" [name]="property.name" [path]="property.propertiesName" - [constraints]="property.constraints" (elementChanged)="onElementChanged($event)" [readonly]="readonly || property.isDeclared || property.isDisabled" [testId]="'prop-' + propertyTestsId" + [declared] = "property.isDeclared" + [constraints] = "constraints" ></dynamic-element> </div> </ng-container> @@ -69,7 +69,7 @@ <ng-container *ngIf="!property.isDeclared"> <a *ngIf="(propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && !property.isChildOfListOrMap" class="property-icon add-item" (click)="createNewChildProperty();" [ngClass]="{'disabled':readonly || preventInsertItem(property)}" [attr.data-tests-id]="'add-to-list-' + propertyTestsId">Add value to list</a> <span *ngIf="property.isChildOfListOrMap" (click)="deleteItem.emit(property);" class="property-icon sprite-new delete-item-icon" [ngClass]="{'disabled':readonly}" [attr.data-tests-id]="'delete-from-list-' + propertyTestsId"></span> - <span *ngIf="!isPropertyFEModel && (propType == derivedPropertyTypes.COMPLEX || ((propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && hasChildren))" (click)="expandChildById(propPath)" class="property-icon sprite-new round-expand-icon" [class.open]="expandedChildId.indexOf(propPath) == 0" [attr.data-tests-id]="'expand-' + propertyTestsId"></span> + <span *ngIf="!isPropertyFEModel && (propType == derivedPropertyTypes.COMPLEX || ((propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && hasChildren))" (click)="expandChildById(propPath)" class="property-icon sprite-new round-expand-icon" [class.open]="expandedChildId.indexOf(propPath) == 0" [attr.data-tests-id]="'expand-' + propertyTestsId" ></span> </ng-container> </div> diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less index 0adce2c99d..1007292854 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less @@ -60,7 +60,7 @@ align-self:center; cursor:pointer; } - + } .filtered { diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts index 6e19c95003..715426f212 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts @@ -23,7 +23,7 @@ import {Component, Input, Output, EventEmitter, ViewChild, ComponentRef} from "@ import { PropertyFEModel, DerivedFEProperty, DerivedPropertyType } from "app/models"; import { PROPERTY_TYPES } from 'app/utils'; import { DataTypeService } from "../../../../services/data-type.service"; -import { trigger, state, style, transition, animate } from '@angular/core'; +import { trigger, state, style, transition, animate } from '@angular/animations'; import {PropertiesUtils} from "../../../../pages/properties-assignment/services/properties.utils"; import {IUiElementChangeEvent} from "../../../ui/form-components/ui-element-base.component"; import {DynamicElementComponent} from "../../../ui/dynamic-element/dynamic-element.component"; @@ -42,6 +42,7 @@ export class DynamicPropertyComponent { isPropertyFEModel: boolean; nestedLevel: number; propertyTestsId: string; + constraints:string[]; @Input() canBeDeclared: boolean; @Input() property: PropertyFEModel | DerivedFEProperty; @@ -72,7 +73,30 @@ export class DynamicPropertyComponent { this.propPath = (this.property instanceof PropertyFEModel) ? this.property.name : this.property.propertiesName; this.nestedLevel = (this.property.propertiesName.match(/#/g) || []).length; this.rootProperty = (this.rootProperty) ? this.rootProperty : <PropertyFEModel>this.property; - this.propertyTestsId = this.getPropertyTestsId(); + this.propertyTestsId = this.getPropertyTestsId(); + + this.initConsraintsValues(); + + + } + + initConsraintsValues(){ + let primitiveProperties = ['string', 'integer', 'float', 'boolean']; + + //Property has constraints + if(this.property.constraints){ + this.constraints = this.property.constraints[0].validValues + } + + //Complex Type + else if (primitiveProperties.indexOf(this.rootProperty.type) == -1 && primitiveProperties.indexOf(this.property.type) >= 0 ){ + this.constraints = this.dataTypeService.getConstraintsByParentTypeAndUniqueID(this.rootProperty.type, this.property.name); + } + + else{ + this.constraints = null; + } + } ngDoCheck() { diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html index 2068b170b3..89b85d3578 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html @@ -37,18 +37,18 @@ <div class="no-data" *ngIf="!fePropertiesMap || !(fePropertiesMap | keys).length">No data to display</div> <ng-container *ngFor="let instanceId of fePropertiesMap | keys; trackBy:vspId"> + <!-- Icon & Instance Name --> <div class="table-rows-header white-sub-header" *ngIf="feInstanceNamesMap"> - - <span [ngClass]="['prop-instance-icon', feInstanceNamesMap[instanceId].iconClass, 'small']"></span> - {{feInstanceNamesMap[instanceId].name}} + {{feInstanceNamesMap[instanceId].name}} <div class="sprite-new archive-label" *ngIf="feInstanceNamesMap[instanceId].originArchived == true"></div> </div> - - <div class="table-row" *ngFor="let property of fePropertiesMap[instanceId] | searchFilter:'name':searchTerm | orderBy:{path: path, direction: direction}; trackBy:property?.name " + + <div class="table-row" *ngFor="let property of fePropertiesMap[instanceId] | searchFilter:'name':searchTerm | propertiesOrderBy:{path: path, direction: direction}; trackBy:property?.name " (click)="onClickPropertyRow(property, instanceId, $event)" [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name, 'readonly': property.isDisabled || property.isDeclared}"> <div class="table-cell col1" [ngClass]="{'filtered':property.name === propertyNameSearchText}" [class.round-checkbox]="property.isDeclared"> + <!-- Property Name --> <div class="property-name"> <checkbox *ngIf="hasDeclareOption" [(checked)]="property.isSelected" [disabled]="property.isDisabled || property.isDeclared || readonly" (checkedChange)="propertyChecked(property)" [attr.data-tests-id]="property.name"></checkbox> @@ -62,16 +62,19 @@ <span *ngIf="showDelete" class="sprite-new delete-btn" [ngClass]="{'disabled' : property.isDisabled || property.isDeclared}" (click)="openDeleteModal(property)" data-tests-id="delete-input-button"></span> </div> </div> + <!-- Property Type --> <div class="table-cell col2" *ngIf="!hidePropertyType"> <div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}"> <span>{{property.type | contentAfterLastDot}}</span> </div> </div> + <!-- Property ES (Entry Schema) --> <div class="table-cell col3" *ngIf="!hidePropertyType"> <div *ngIf="property.schema && property.schema.property && property.schema.property.type" class="inner-cell-div" tooltip="{{property.schema.property.type | contentAfterLastDot}}"> <span>{{property.schema.property.type | contentAfterLastDot}}</span> </div> </div> + <!-- Property Value --> <div class="table-cell valueCol"> <!-- [ngClass]="{'filtered':property.name === propertyNameSearchText}" (selectProperty)="propertySelected(property, $event, flatProperty.propertiesName)" [propType]="property.type" [propSchema]="property.schema" [propKey]="" [propValue]="property.value"--> <dynamic-property @@ -86,9 +89,10 @@ (expandChild)="property.updateExpandedChildPropertyId($event)" (clickOnPropertyRow)="onClickPropertyInnerRow($event, instanceId)" (checkProperty)="propertyChecked(property, $event)" + > + </dynamic-property> - </div> </div> </ng-container> diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.spec.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.spec.ts new file mode 100644 index 0000000000..ea524e54b1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.spec.ts @@ -0,0 +1,175 @@ +import { NO_ERRORS_SCHEMA, SimpleChange } from '@angular/core'; +import { ComponentFixture } from '@angular/core/testing'; +import { ConfigureFn, configureTests } from '../../../../../jest/test-config.helper'; +import { DerivedFEProperty } from '../../../../models/properties-inputs/derived-fe-property'; +import { PropertyBEModel } from '../../../../models/properties-inputs/property-be-model'; +import { PropertyFEModel } from '../../../../models/properties-inputs/property-fe-model'; +import { ContentAfterLastDotPipe } from '../../../pipes/contentAfterLastDot.pipe'; +import { KeysPipe } from '../../../pipes/keys.pipe'; +import { PropertiesOrderByPipe } from '../../../pipes/properties-order-by.pipe'; +import { SearchFilterPipe } from '../../../pipes/searchFilter.pipe'; +import { ModalService } from '../../../services/modal.service'; +import { PropertiesService } from '../../../services/properties.service'; +import { PropertiesTableComponent, PropertyRowSelectedEvent } from './properties-table.component'; + +describe('properties-table component', () => { + + let fixture: ComponentFixture<PropertiesTableComponent>; + let propertiesServiceMock: Partial<PropertiesService>; + let modalServiceMock: Partial<ModalService>; + + beforeEach( + () => { + propertiesServiceMock = { + undoDisableRelatedProperties: jest.fn(), + disableRelatedProperties: jest.fn() + }; + modalServiceMock = { + + }; + + const configure: ConfigureFn = (testBed) => { + testBed.configureTestingModule({ + declarations: [ + PropertiesTableComponent, + KeysPipe, + PropertiesOrderByPipe, + SearchFilterPipe, + ContentAfterLastDotPipe + ], + imports: [], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + {provide: PropertiesService, useValue: propertiesServiceMock}, + {provide: ModalService, useValue: modalServiceMock} + ], + }); + }; + + configureTests(configure).then((testBed) => { + fixture = testBed.createComponent(PropertiesTableComponent); + }); + } + ); + + it('When Properties assignment page is loaded, it is sorted by property name (acsending)', () => { + const fePropertiesMapValues = new SimpleChange('previousValue', 'currentValue', true); + const changes = { + fePropertiesMap: fePropertiesMapValues + }; + + // init values before ngOnChanges was called + fixture.componentInstance.sortBy = 'existingValue'; + + fixture.componentInstance.ngOnChanges(changes); + + expect (fixture.componentInstance.reverse).toEqual(true); + // expect (fixture.componentInstance.direction).toEqual(1); + expect (fixture.componentInstance.direction).toEqual(fixture.componentInstance.ascUpperLettersFirst); + expect (fixture.componentInstance.sortBy).toEqual('name'); + expect (fixture.componentInstance.path.length).toEqual(1); + expect (fixture.componentInstance.path[0]).toEqual('name'); + }); + + it('When ngOnChanges is called without fePropertiesMap,' + + ' sortBy will remain as it was', () => { + const fePropertiesMapValues = new SimpleChange('previousValue', 'currentValue', true); + const changes = { + dummyKey: fePropertiesMapValues + }; + + // init values before ngOnChanges was called + fixture.componentInstance.sortBy = 'existingValue'; + fixture.componentInstance.sort = jest.fn(); + + fixture.componentInstance.ngOnChanges(changes); + + expect (fixture.componentInstance.sortBy).toEqual('existingValue'); + }); + + it ('When sort is called init this.direction to 1', () => { + // init values + fixture.componentInstance.reverse = false; + fixture.componentInstance.direction = 0; + fixture.componentInstance.sortBy = 'initialize.Value'; + fixture.componentInstance.path = []; + + // call sore function + fixture.componentInstance.sort('initialize.Value'); + + // expect that + expect (fixture.componentInstance.reverse).toBe(true); + expect (fixture.componentInstance.direction).toBe(fixture.componentInstance.ascUpperLettersFirst); + expect (fixture.componentInstance.sortBy).toBe('initialize.Value'); + expect (fixture.componentInstance.path.length).toBe(2); + expect (fixture.componentInstance.path[0]).toBe('initialize'); + expect (fixture.componentInstance.path[1]).toBe('Value'); + }); + + it ('When sort is called init this.direction to -1', () => { + // init values + fixture.componentInstance.reverse = true; + fixture.componentInstance.direction = 0; + fixture.componentInstance.sortBy = 'initialize.Value'; + fixture.componentInstance.path = []; + + // call sore function + fixture.componentInstance.sort('initialize.Value'); + + // expect that + expect (fixture.componentInstance.reverse).toBe(false); + expect (fixture.componentInstance.direction).toBe(fixture.componentInstance.descLowerLettersFirst); + }); + + it ('When onPropertyChanged is called, event is emitted' , () => { + spyOn(fixture.componentInstance.emitter, 'emit'); + fixture.componentInstance.onPropertyChanged('testProperty'); + expect(fixture.componentInstance.emitter.emit).toHaveBeenCalledWith('testProperty'); + }); + + it ('When onClickPropertyRow is called, selectedPropertyId is updated and event is emitted.' , () => { + const propertyFEModel = new PropertyFEModel(new PropertyBEModel()); + propertyFEModel.name = 'propertyName'; + const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(propertyFEModel, 'instanceName'); + + spyOn(fixture.componentInstance.selectPropertyRow, 'emit'); + fixture.componentInstance.onClickPropertyRow(propertyFEModel, 'instanceName'); + + expect (fixture.componentInstance.selectedPropertyId).toBe('propertyName'); + expect (fixture.componentInstance.selectPropertyRow.emit).toHaveBeenCalledWith(propertyRowSelectedEvent); + }); + + it ('When onClickPropertyInnerRow is called, event is emitted.' , () => { + const derivedFEProperty = new DerivedFEProperty(new PropertyBEModel()); + const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(derivedFEProperty, 'instanceName'); + spyOn(fixture.componentInstance.selectPropertyRow, 'emit'); + fixture.componentInstance.onClickPropertyInnerRow(derivedFEProperty, 'instanceName'); + + expect (fixture.componentInstance.selectPropertyRow.emit).toHaveBeenCalledWith(propertyRowSelectedEvent); + }); + + it ('When propertyChecked is called, propertiesService.undoDisableRelatedProperties is called and event is emitted.' , () => { + + const propertyFEModel = new PropertyFEModel(new PropertyBEModel()); + propertyFEModel.isSelected = false; + const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(propertyFEModel, 'instanceName1'); + + spyOn(fixture.componentInstance.updateCheckedPropertyCount, 'emit'); + fixture.componentInstance.propertyChecked(propertyFEModel); + expect (propertiesServiceMock.undoDisableRelatedProperties).toHaveBeenCalledWith(propertyFEModel, undefined); + expect (fixture.componentInstance.updateCheckedPropertyCount.emit).toHaveBeenCalledWith(false); + }); + + it ('When propertyChecked is called, propertiesService.disableRelatedProperties is called and event is emitted.' , () => { + + const propertyFEModel = new PropertyFEModel(new PropertyBEModel()); + propertyFEModel.isSelected = true; + const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(propertyFEModel, 'instanceName1'); + + spyOn(fixture.componentInstance.updateCheckedPropertyCount, 'emit'); + fixture.componentInstance.propertyChecked(propertyFEModel); + expect (propertiesServiceMock.disableRelatedProperties).toHaveBeenCalledWith(propertyFEModel, undefined); + expect (fixture.componentInstance.updateCheckedPropertyCount.emit).toHaveBeenCalledWith(true); + }); + +}); diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts index 0cc188134f..e499b3786b 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts @@ -8,9 +8,9 @@ * 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. @@ -19,33 +19,33 @@ * ============LICENSE_END========================================================= */ -import { Component, Input, Output, EventEmitter} from "@angular/core"; -import {PropertyFEModel, DerivedFEProperty, InstanceFePropertiesMap} from "app/models"; -import {PropertiesService} from "../../../services/properties.service"; -import {ModalService} from "../../../services/modal.service"; -import { InstanceFeDetails } from "../../../../models/instance-fe-details"; +import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; +import { DerivedFEProperty, InstanceFePropertiesMap, PropertyFEModel } from 'app/models'; +import { InstanceFeDetails } from '../../../../models/instance-fe-details'; +import { PropertiesService } from '../../../services/properties.service'; +import { ModalService } from '../../../services/modal.service'; @Component({ selector: 'properties-table', templateUrl: './properties-table.component.html', styleUrls: ['./properties-table.component.less'] }) -export class PropertiesTableComponent { +export class PropertiesTableComponent implements OnChanges { @Input() fePropertiesMap: InstanceFePropertiesMap; @Input() feInstanceNamesMap: Map<string, InstanceFeDetails>; @Input() selectedPropertyId: string; - @Input() propertyNameSearchText:string; - @Input() searchTerm:string; - @Input() readonly:boolean; - @Input() isLoading:boolean; - @Input() hasDeclareOption:boolean; - @Input() hidePropertyType:boolean; + @Input() propertyNameSearchText: string; + @Input() searchTerm: string; + @Input() readonly: boolean; + @Input() isLoading: boolean; + @Input() hasDeclareOption: boolean; + @Input() hidePropertyType: boolean; @Input() showDelete:boolean; - + @Output('propertyChanged') emitter: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>(); @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>(); - @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption and hasDeclareListOption + @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>(); // only for hasDeclareOption @Output() updateCheckedChildPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareListOption @Output() deleteProperty: EventEmitter<PropertyFEModel> = new EventEmitter<PropertyFEModel>(); private selectedPropertyToDelete: PropertyFEModel; @@ -53,41 +53,48 @@ export class PropertiesTableComponent { sortBy: String; reverse: boolean; direction: number; - path:string[]; + path: string[]; - sort(sortBy){ - this.reverse = (this.sortBy === sortBy) ? !this.reverse : true; - this.direction = this.reverse ? 1 : -1; - this.sortBy = sortBy; - this.path = sortBy.split('.'); + readonly ascUpperLettersFirst = 1; + readonly descLowerLettersFirst = -1; + + constructor(private propertiesService: PropertiesService, private modalService: ModalService ) { } - constructor (private propertiesService:PropertiesService, private modalService: ModalService){ + ngOnChanges(changes: SimpleChanges): void { + if (changes.fePropertiesMap) { + this.sortBy = ''; + this.sort('name'); + } } - - ngOnInit() { + + sort(sortBy) { + this.reverse = (this.sortBy === sortBy) ? !this.reverse : true; + this.direction = this.reverse ? this.ascUpperLettersFirst : this.descLowerLettersFirst; + this.sortBy = sortBy; + this.path = sortBy.split('.'); } onPropertyChanged = (property) => { this.emitter.emit(property); - }; + } // Click on main row (row of propertyFEModel) - onClickPropertyRow = (property:PropertyFEModel, instanceName:string, event?) => { - //event && event.stopPropagation(); + onClickPropertyRow = (property: PropertyFEModel, instanceName: string, event?) => { + // event && event.stopPropagation(); this.selectedPropertyId = property.name; - let propertyRowSelectedEvent:PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName); + const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName); this.selectPropertyRow.emit(propertyRowSelectedEvent); - }; + } // Click on inner row (row of DerivedFEProperty) - onClickPropertyInnerRow = (property:DerivedFEProperty, instanceName:string) => { - let propertyRowSelectedEvent:PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName); + onClickPropertyInnerRow = (property: DerivedFEProperty, instanceName: string) => { + const propertyRowSelectedEvent: PropertyRowSelectedEvent = new PropertyRowSelectedEvent(property, instanceName); this.selectPropertyRow.emit(propertyRowSelectedEvent); } propertyChecked = (prop: PropertyFEModel, childPropName?: string) => { - let isChecked: boolean = (!childPropName)? prop.isSelected : prop.flattenedChildren.find(prop => prop.propertiesName == childPropName).isSelected; + const isChecked: boolean = (!childPropName) ? prop.isSelected : prop.flattenedChildren.find((prop) => prop.propertiesName == childPropName).isSelected; if (!isChecked) { this.propertiesService.undoDisableRelatedProperties(prop, childPropName); @@ -116,11 +123,10 @@ export class PropertiesTableComponent { } export class PropertyRowSelectedEvent { - propertyModel:PropertyFEModel | DerivedFEProperty; - instanceName:string; - constructor ( propertyModel:PropertyFEModel | DerivedFEProperty, instanceName:string ){ + propertyModel: PropertyFEModel | DerivedFEProperty; + instanceName: string; + constructor( propertyModel: PropertyFEModel | DerivedFEProperty, instanceName: string ) { this.propertyModel = propertyModel; this.instanceName = instanceName; } } - diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts index cb8c9a694b..4d968a088c 100644 --- a/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts @@ -4,7 +4,6 @@ import {DynamicPropertyComponent} from "./dynamic-property/dynamic-property.comp import {FormsModule} from "@angular/forms"; import {UiElementsModule} from "../../ui/ui-elements.module"; import {CommonModule} from "@angular/common"; -import {HttpModule} from "@angular/http"; import {FilterChildPropertiesPipe} from "./pipes/filterChildProperties.pipe"; import {GlobalPipesModule} from "../../../pipes/global-pipes.module"; import {PropertiesService} from "../../../services/properties.service"; @@ -13,7 +12,6 @@ import {MultilineEllipsisModule} from "../../../shared/multiline-ellipsis/multil @NgModule({ imports: [ FormsModule, - HttpModule, CommonModule, GlobalPipesModule, UiElementsModule, diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts index 2e3c21c210..d41b580514 100644 --- a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts @@ -9,6 +9,7 @@ import {ComponentInstanceServiceNg2} from "../../../services/component-instance- import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils"; import {Requirement} from "../../../../models/requirement"; import {Capability, RequirementCapabilityModel} from "../../../../models/capability"; +import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service"; const REQUIREMENT = 'Requirement'; const CAPABILITY = 'Capability'; @@ -24,14 +25,9 @@ export class SelectRequirementOrCapabilityComponent implements OnInit { @Input() optionalRequirementsMap:Dictionary<Requirement[]>; //optional requirement map - key is type, value is array of requirements @Input() optionalCapabilitiesMap:Dictionary<Capability[]>; //optional capabilities map - key is type, value is array of capabilities - @Input() selectedReqOrCapOption:string; // the selection value chosen by the user (options: requirement / capability ) - - @Input() currentComponent:ComponentModel; @Input() componentInstanceId:string; - @Input() selectedReqOrCapModel:RequirementCapabilityModel; - @Output() updateSelectedReqOrCap:EventEmitter<RequirementCapabilityModel> = new EventEmitter<RequirementCapabilityModel>(); types:Array<string> = []; @@ -51,7 +47,8 @@ export class SelectRequirementOrCapabilityComponent implements OnInit { private _loadingCapabilityProperties: Array<Capability>; constructor(private componentInstanceServiceNg2:ComponentInstanceServiceNg2, - private propertiesUtils:PropertiesUtils) { + private propertiesUtils:PropertiesUtils, + private workspaceService: WorkspaceService) { this.selectOptions = [new RadioButtonModel(REQUIREMENT, REQUIREMENT), new RadioButtonModel(CAPABILITY, CAPABILITY)]; this._loadingCapabilityProperties = []; } @@ -171,14 +168,13 @@ export class SelectRequirementOrCapabilityComponent implements OnInit { } } - private setCapabilityProperties = ():void => { let selectedCapability = <Capability>this.selectedReqOrCapModel; if (!selectedCapability.properties) { this.loadingCapabilityProperties = true; if (this._loadingCapabilityProperties.indexOf(selectedCapability) == -1) { this._loadingCapabilityProperties.push(selectedCapability); - this.componentInstanceServiceNg2.getInstanceCapabilityProperties(this.currentComponent, this.componentInstanceId, selectedCapability) + this.componentInstanceServiceNg2.getInstanceCapabilityProperties(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.componentInstanceId, selectedCapability) .subscribe((response: Array<PropertyModel>) => { if (this.selectedReqOrCapModel === selectedCapability) { delete this.loadingCapabilityProperties; diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less index 5830c06972..f4d673d695 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less +++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.less @@ -50,7 +50,7 @@ } .operation-name { - .s_1; + // .s_1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts index ebcf9eba22..08e6c36db1 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.component.ts @@ -14,34 +14,38 @@ * permissions and limitations under the License. */ -import {Component, Input, ComponentRef} from '@angular/core'; -import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service'; -import {ComponentInstanceServiceNg2} from 'app/ng2/services/component-instance-services/component-instance.service'; -import {ServiceServiceNg2} from "app/ng2/services/component-services/service.service"; -import {ModalService} from 'app/ng2/services/modal.service'; -import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; +import { Component, ComponentRef, Input } from '@angular/core'; import { - ModalModel, ButtonModel, - OperationModel, - Service, - ServiceInstanceObject, - PropertyFEModel, - PropertyBEModel, + CapabilitiesGroup, + Capability, + Component as TopologyTemplate, InputBEModel, InterfaceModel, - CapabilitiesGroup, - Capability + ModalModel, + OperationModel, + PropertyBEModel, + PropertyFEModel } from 'app/models'; -import {ServiceConsumptionCreatorComponent} from 'app/ng2/pages/service-consumption-editor/service-consumption-editor.component'; - +import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component'; +import { ServiceConsumptionCreatorComponent } from 'app/ng2/pages/service-consumption-editor/service-consumption-editor.component'; +import { ComponentInstanceServiceNg2 } from 'app/ng2/services/component-instance-services/component-instance.service'; +import { ComponentServiceNg2 } from 'app/ng2/services/component-services/component.service'; +import { ModalService } from 'app/ng2/services/modal.service'; +import { ComponentMetadata } from '../../../../models/component-metadata'; +import { Resource } from '../../../../models/components/resource'; +import { FullComponentInstance } from '../../../../models/componentsInstances/fullComponentInstance'; +import { ServiceInstanceObject } from '../../../../models/service-instance-properties-and-interfaces'; +import { ComponentFactory } from '../../../../utils/component-factory'; +import { ComponentType } from '../../../../utils/constants'; +import { TopologyTemplateService } from '../../../services/component-services/topology-template.service'; export class ConsumptionInput extends PropertyFEModel{ inputId: string; type: string; source: string; value: any; - constraints: Array<any>; + constraints: any[]; constructor(input?: any) { super(input); @@ -49,19 +53,20 @@ export class ConsumptionInput extends PropertyFEModel{ this.inputId = input.inputId; this.type = input.type; this.source = input.source; - this.value = input.value || ""; + this.value = input.value || ''; this.constraints = input.constraints; } } } +// tslint:disable-next-line:max-classes-per-file export class ConsumptionInputDetails extends ConsumptionInput { name: string; expanded: boolean; assignValueLabel: string; - associatedProps: Array<string>; - associatedInterfaces: Array<any>; - associatedCapabilities: Array<Capability>; + associatedProps: string[]; + associatedInterfaces: any[]; + associatedCapabilities: Capability[]; origVal: string; isValid: boolean; @@ -74,7 +79,7 @@ export class ConsumptionInputDetails extends ConsumptionInput { this.associatedProps = input.associatedProps; this.associatedInterfaces = input.associatedInterfaces; this.associatedCapabilities = input.associatedCapabilities; - this.origVal = input.value || ""; + this.origVal = input.value || ''; this.isValid = input.isValid; } } @@ -84,9 +89,10 @@ export class ConsumptionInputDetails extends ConsumptionInput { } } +// tslint:disable-next-line:max-classes-per-file export class ServiceOperation { operation: OperationModel; - consumptionInputs: Array<ConsumptionInputDetails>; + consumptionInputs: ConsumptionInputDetails[]; constructor(input?: any) { if (input) { @@ -96,24 +102,24 @@ export class ServiceOperation { } } +// tslint:disable-next-line:max-classes-per-file export class InterfaceWithServiceOperation { interfaceId: string; displayName: string; - operationsList: Array<ServiceOperation>; + operationsList: ServiceOperation[]; isExpanded: boolean; constructor(input?: InterfaceModel) { if (input) { this.interfaceId = input.uniqueId; this.displayName = input.displayType(); - this.operationsList = _.map(input.operations, operation => new ServiceOperation({operation: operation})); + this.operationsList = _.map(input.operations, (operation) => new ServiceOperation({operation: operation})); this.isExpanded = true; } } } - - +// tslint:disable-next-line:max-classes-per-file @Component({ selector: 'service-consumption', templateUrl: './service-consumption.component.html', @@ -125,21 +131,23 @@ export class ServiceConsumptionComponent { modalInstance: ComponentRef<ModalComponent>; isLoading: boolean = false; - interfacesList: Array<InterfaceWithServiceOperation>; - operationsGroup: Array<ServiceOperation>; - @Input() parentServiceInputs: Array<InputBEModel> = []; - @Input() parentService: Service; - @Input() selectedService: Service; + interfacesList: InterfaceWithServiceOperation[]; + operationsGroup: ServiceOperation[]; + @Input() parentServiceInputs: InputBEModel[] = []; + @Input() parentService: ComponentMetadata; + @Input() selectedService: TopologyTemplate | FullComponentInstance; @Input() selectedServiceInstanceId: string; - @Input() instancesMappedList: Array<ServiceInstanceObject>; - @Input() instancesCapabilitiesMap: Map<string, Array<Capability>>; + @Input() instancesMappedList: ServiceInstanceObject[]; + @Input() instancesCapabilitiesMap: Map<string, Capability[]>; @Input() readonly: boolean; - selectedInstanceSiblings: Array<ServiceInstanceObject>; - selectedInstancePropertiesList: Array<PropertyBEModel> = []; - selectedInstanceCapabilitisList: Array<Capability> = []; + selectedInstanceSiblings: ServiceInstanceObject[]; + selectedInstancePropertiesList: PropertyBEModel[] = []; + selectedInstanceCapabilitisList: Capability[] = []; - constructor(private ModalServiceNg2: ModalService, private serviceServiceNg2: ServiceServiceNg2, private componentServiceNg2: ComponentServiceNg2, private componentInstanceServiceNg2:ComponentInstanceServiceNg2) {} + constructor(private modalServiceNg2: ModalService, private topologyTemplateService: TopologyTemplateService, + private componentServiceNg2: ComponentServiceNg2, private componentInstanceServiceNg2: ComponentInstanceServiceNg2, + private componentFactory: ComponentFactory) {} ngOnInit() { this.updateSelectedInstancePropertiesAndSiblings(); @@ -147,15 +155,15 @@ export class ServiceConsumptionComponent { } ngOnChanges(changes) { - if(changes.selectedServiceInstanceId && changes.selectedServiceInstanceId.currentValue !== changes.selectedServiceInstanceId.previousValue) { + if (changes.selectedServiceInstanceId && changes.selectedServiceInstanceId.currentValue !== changes.selectedServiceInstanceId.previousValue) { this.selectedServiceInstanceId = changes.selectedServiceInstanceId.currentValue; - if(changes.selectedService && changes.selectedService.currentValue !== changes.selectedService.previousValue) { + if (changes.selectedService && changes.selectedService.currentValue !== changes.selectedService.previousValue) { this.selectedService = changes.selectedService.currentValue; } this.updateSelectedInstancePropertiesAndSiblings(); this.updateSelectedServiceCapabilities(); } - if(changes.instancesMappedList && !_.isEqual(changes.instancesMappedList.currentValue, changes.instancesMappedList.previousValue)) { + if (changes.instancesMappedList && !_.isEqual(changes.instancesMappedList.currentValue, changes.instancesMappedList.previousValue)) { this.updateSelectedInstancePropertiesAndSiblings(); this.updateSelectedServiceCapabilities(); } @@ -163,22 +171,22 @@ export class ServiceConsumptionComponent { updateSelectedInstancePropertiesAndSiblings() { this.interfacesList = []; - let selectedInstanceMetadata: ServiceInstanceObject = _.find(this.instancesMappedList, coInstance => coInstance.id === this.selectedServiceInstanceId); + const selectedInstanceMetadata: ServiceInstanceObject = _.find(this.instancesMappedList, (coInstance) => coInstance.id === this.selectedServiceInstanceId); if (selectedInstanceMetadata) { - _.forEach(selectedInstanceMetadata.interfaces, (interfaceData:InterfaceModel) => { + _.forEach(selectedInstanceMetadata.interfaces, (interfaceData: InterfaceModel) => { this.interfacesList.push(new InterfaceWithServiceOperation(interfaceData)); }); } - this.interfacesList.sort((interf1:InterfaceWithServiceOperation, interf2:InterfaceWithServiceOperation) => interf1.displayName.localeCompare(interf2.displayName)); + this.interfacesList.sort((interf1: InterfaceWithServiceOperation, interf2: InterfaceWithServiceOperation) => interf1.displayName.localeCompare(interf2.displayName)); this.selectedInstancePropertiesList = selectedInstanceMetadata && selectedInstanceMetadata.properties; - this.selectedInstanceSiblings = _.filter(this.instancesMappedList, coInstance => coInstance.id !== this.selectedServiceInstanceId); + this.selectedInstanceSiblings = _.filter(this.instancesMappedList, (coInstance) => coInstance.id !== this.selectedServiceInstanceId); } updateSelectedServiceCapabilities() { this.selectedInstanceCapabilitisList = _.filter( CapabilitiesGroup.getFlattenedCapabilities(this.selectedService.capabilities), - cap => cap.properties && cap.ownerId === this.selectedService.uniqueId + (cap) => cap.properties && cap.ownerId === this.selectedService.uniqueId ); } @@ -186,15 +194,15 @@ export class ServiceConsumptionComponent { currInterface.isExpanded = !currInterface.isExpanded; } - onSelectOperation(event, currInterface:InterfaceWithServiceOperation, opIndex: number) { + onSelectOperation(event, currInterface: InterfaceWithServiceOperation, opIndex: number) { event.stopPropagation(); - if(!this.readonly) { + if (!this.readonly) { this.operationsGroup = currInterface.operationsList; - let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.ModalServiceNg2.closeCurrentModal); - let saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createOrUpdateOperationInput, this.getDisabled); - let modalModel: ModalModel = new ModalModel('l', 'Modify Operation Consumption', '', [saveButton, cancelButton], 'standard'); - this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel); - this.ModalServiceNg2.addDynamicContentToModal( + const cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.modalServiceNg2.closeCurrentModal); + const saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createOrUpdateOperationInput, this.getDisabled); + const modalModel: ModalModel = new ModalModel('l', 'Modify Operation Consumption', '', [saveButton, cancelButton], 'standard'); + this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel); + this.modalServiceNg2.addDynamicContentToModal( this.modalInstance, ServiceConsumptionCreatorComponent, { @@ -215,11 +223,11 @@ export class ServiceConsumptionComponent { } } - createOrUpdateOperationInput = ():void => { + createOrUpdateOperationInput = (): void => { this.isLoading = true; - let consumptionInputsList:Array<{[id: string]: Array<ConsumptionInput>}> = _.map(this.operationsGroup, (serviceOp) => { - let consumptionInputsArr: Array<any> = []; - if(serviceOp.consumptionInputs) { + const consumptionInputsList: Array<{[id: string]: ConsumptionInput[]}> = _.map(this.operationsGroup, (serviceOp) => { + let consumptionInputsArr: any[] = []; + if (serviceOp.consumptionInputs) { consumptionInputsArr = _.map(serviceOp.consumptionInputs, (input: ConsumptionInputDetails) => { return { inputId: input.inputId, @@ -233,16 +241,24 @@ export class ServiceConsumptionComponent { [serviceOp.operation.uniqueId]: consumptionInputsArr }; }); - this.serviceServiceNg2.createOrUpdateServiceConsumptionInputs(this.parentService,this.selectedServiceInstanceId, consumptionInputsList).subscribe(() => { + this.topologyTemplateService.createOrUpdateServiceConsumptionInputs(this.convertMetaDataToComponent(this.parentService).uniqueId, this.selectedServiceInstanceId, consumptionInputsList) + .subscribe(() => { this.isLoading = false; - }, err=> { + }, (err) => { this.isLoading = false; }); - this.ModalServiceNg2.closeCurrentModal(); - }; + this.modalServiceNg2.closeCurrentModal(); + } - getDisabled = ():boolean => { + getDisabled = (): boolean => { return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit(); - }; + } + + //TODO remove when workspace page convert to angular5 + convertMetaDataToComponent(componentMetadata: ComponentMetadata) { + const newResource: Resource = this.componentFactory.createEmptyComponent(ComponentType.RESOURCE) as Resource; + newResource.setComponentMetadata(componentMetadata); + return newResource; + } }
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts index 8593bef3eb..70b5911779 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-consumption/service-consumption.module.ts @@ -14,11 +14,11 @@ * permissions and limitations under the License. */ -import { NgModule } from "@angular/core"; -import {CommonModule} from "@angular/common"; -import {ServiceConsumptionComponent} from "./service-consumption.component"; -import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; -import {TranslateModule} from 'app/ng2/shared/translator/translate.module'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module'; +import { TranslateModule } from 'app/ng2/shared/translator/translate.module'; +import { ServiceConsumptionComponent } from './service-consumption.component'; @NgModule({ declarations: [ @@ -29,11 +29,13 @@ import {TranslateModule} from 'app/ng2/shared/translator/translate.module'; UiElementsModule, TranslateModule ], - exports: [], + exports: [ + ServiceConsumptionComponent + ], entryComponents: [ ServiceConsumptionComponent ], providers: [] }) export class ServiceConsumptionModule { -}
\ No newline at end of file +} diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less index ae990dc85f..2fccfb414b 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less +++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.less @@ -38,7 +38,7 @@ justify-content: space-between; .rule-details { - .s_1; + // .s_1; display: flex; flex: 1; align-items: center; @@ -67,4 +67,13 @@ } } + .w-sdc-designer-sidebar-section-footer { + margin-top: 10px; + text-align: center; + width: 100%; + } + .w-sdc-designer-sidebar-section-footer-action { + width: 180px; + margin-top: 10px; + } }
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts index bc3531dc58..fa75a275aa 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.component.ts @@ -13,22 +13,22 @@ * or implied. See the License for the specific language governing * permissions and limitations under the License. */ -import {Component, Input, Output, EventEmitter, ComponentRef} from '@angular/core'; -import {ModalService} from 'app/ng2/services/modal.service'; +import { Component, ComponentRef, EventEmitter, Input, Output } from '@angular/core'; import { - Service, + ButtonModel, ComponentInstance, + InputBEModel, ModalModel, - ButtonModel, PropertyBEModel, - InputBEModel, - ServiceInstanceObject } from 'app/models'; -import {ServiceDependenciesEditorComponent} from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component'; -import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; -import {ComponentServiceNg2} from 'app/ng2/services/component-services/component.service'; -import {TranslateService} from 'app/ng2/shared/translator/translate.service'; -import {ComponentGenericResponse} from 'app/ng2/services/responses/component-generic-response'; +import { ModalComponent } from 'app/ng2/components/ui/modal/modal.component'; +import { ServiceDependenciesEditorComponent } from 'app/ng2/pages/service-dependencies-editor/service-dependencies-editor.component'; +import { ModalService } from 'app/ng2/services/modal.service'; +import { ComponentGenericResponse } from 'app/ng2/services/responses/component-generic-response'; +import { TranslateService } from 'app/ng2/shared/translator/translate.service'; +import { ComponentMetadata } from '../../../../models/component-metadata'; +import { ServiceInstanceObject } from '../../../../models/service-instance-properties-and-interfaces'; +import { TopologyTemplateService } from '../../../services/component-services/topology-template.service'; export class ConstraintObject { servicePropertyName: string; @@ -48,12 +48,13 @@ export class ConstraintObject { } } +// tslint:disable-next-line:max-classes-per-file export class ConstraintObjectUI extends ConstraintObject{ isValidValue: boolean; constructor(input?: any) { super(input); - if(input) { + if (input) { this.isValidValue = input.isValidValue ? input.isValidValue : input.value !== ''; } } @@ -63,7 +64,7 @@ export class ConstraintObjectUI extends ConstraintObject{ } public isValidRule(isStatic) { - let isValidValue = isStatic ? this.isValidValue : true; + const isValidValue = isStatic ? this.isValidValue : true; return this.servicePropertyName != null && this.servicePropertyName !== '' && this.value != null && this.value !== '' && isValidValue; } @@ -75,6 +76,7 @@ export const OPERATOR_TYPES = { LESS_THAN: 'less_than' }; +// tslint:disable-next-line:max-classes-per-file class I18nTexts { static uncheckModalTitle: string; static uncheckModalText: string; @@ -89,21 +91,21 @@ class I18nTexts { static deleteRuleMsg: string; public static translateTexts(translateService) { - I18nTexts.uncheckModalTitle = translateService.translate("SERVICE_DEPENDENCY_UNCHECK_TITLE"); - I18nTexts.uncheckModalText = translateService.translate("SERVICE_DEPENDENCY_UNCHECK_TEXT"); - I18nTexts.modalApprove = translateService.translate("MODAL_APPROVE"); - I18nTexts.modalCancel = translateService.translate("MODAL_CANCEL"); - I18nTexts.modalCreate = translateService.translate("MODAL_CREATE"); - I18nTexts.modalSave = translateService.translate("MODAL_SAVE"); - I18nTexts.modalDelete = translateService.translate("MODAL_DELETE"); - I18nTexts.addRuleTxt = translateService.translate("SERVICE_DEPENDENCY_ADD_RULE"); - I18nTexts.updateRuleTxt = translateService.translate("SERVICE_DEPENDENCY_UPDATE_RULE"); - I18nTexts.deleteRuleTxt = translateService.translate("SERVICE_DEPENDENCY_DELETE_RULE"); - I18nTexts.deleteRuleMsg = translateService.translate("SERVICE_DEPENDENCY_DELETE_RULE_MSG"); + I18nTexts.uncheckModalTitle = translateService.translate('SERVICE_DEPENDENCY_UNCHECK_TITLE'); + I18nTexts.uncheckModalText = translateService.translate('SERVICE_DEPENDENCY_UNCHECK_TEXT'); + I18nTexts.modalApprove = translateService.translate('MODAL_APPROVE'); + I18nTexts.modalCancel = translateService.translate('MODAL_CANCEL'); + I18nTexts.modalCreate = translateService.translate('MODAL_CREATE'); + I18nTexts.modalSave = translateService.translate('MODAL_SAVE'); + I18nTexts.modalDelete = translateService.translate('MODAL_DELETE'); + I18nTexts.addRuleTxt = translateService.translate('SERVICE_DEPENDENCY_ADD_RULE'); + I18nTexts.updateRuleTxt = translateService.translate('SERVICE_DEPENDENCY_UPDATE_RULE'); + I18nTexts.deleteRuleTxt = translateService.translate('SERVICE_DEPENDENCY_DELETE_RULE'); + I18nTexts.deleteRuleMsg = translateService.translate('SERVICE_DEPENDENCY_DELETE_RULE_MSG'); } } - +// tslint:disable-next-line:max-classes-per-file @Component({ selector: 'service-dependencies', templateUrl: './service-dependencies.component.html', @@ -115,56 +117,55 @@ export class ServiceDependenciesComponent { modalInstance: ComponentRef<ModalComponent>; isDependent: boolean; isLoading: boolean; - parentServiceInputs: Array<InputBEModel> = []; - rulesList: Array<ConstraintObject> = []; - operatorTypes: Array<any>; + parentServiceInputs: InputBEModel[] = []; + rulesList: ConstraintObject[] = []; + operatorTypes: any[]; @Input() readonly: boolean; - @Input() compositeService: Service; + @Input() compositeService: ComponentMetadata; @Input() currentServiceInstance: ComponentInstance; - @Input() selectedInstanceSiblings: Array<ServiceInstanceObject>; - @Input() selectedInstanceConstraints: Array<ConstraintObject> = []; - @Input() selectedInstanceProperties: Array<PropertyBEModel> = []; - @Output() updateRulesListEvent:EventEmitter<Array<ConstraintObject>> = new EventEmitter<Array<ConstraintObject>>(); + @Input() selectedInstanceSiblings: ServiceInstanceObject[]; + @Input() selectedInstanceConstraints: ConstraintObject[] = []; + @Input() selectedInstanceProperties: PropertyBEModel[] = []; + @Output() updateRulesListEvent: EventEmitter<ConstraintObject[]> = new EventEmitter<ConstraintObject[]>(); @Output() loadRulesListEvent:EventEmitter<any> = new EventEmitter(); @Output() dependencyStatus = new EventEmitter<boolean>(); - - constructor(private componentServiceNg2: ComponentServiceNg2, private ModalServiceNg2: ModalService, private translateService: TranslateService) { + constructor(private topologyTemplateService: TopologyTemplateService, private modalServiceNg2: ModalService, private translateService: TranslateService) { } ngOnInit() { this.isLoading = false; this.operatorTypes = [ - {label: ">", value: OPERATOR_TYPES.GREATER_THAN}, - {label: "<", value: OPERATOR_TYPES.LESS_THAN}, - {label: "=", value: OPERATOR_TYPES.EQUAL} + {label: '>', value: OPERATOR_TYPES.GREATER_THAN}, + {label: '<', value: OPERATOR_TYPES.LESS_THAN}, + {label: '=', value: OPERATOR_TYPES.EQUAL} ]; - this.componentServiceNg2.getComponentInputsWithProperties(this.compositeService).subscribe((result: ComponentGenericResponse) => { + this.topologyTemplateService.getComponentInputsWithProperties(this.compositeService.componentType, this.compositeService.uniqueId).subscribe((result: ComponentGenericResponse) => { this.parentServiceInputs = result.inputs; }); this.loadRules(); - this.translateService.languageChangedObservable.subscribe(lang => { + this.translateService.languageChangedObservable.subscribe((lang) => { I18nTexts.translateTexts(this.translateService); }); } ngOnChanges(changes) { - if(changes.currentServiceInstance) { + if (changes.currentServiceInstance) { this.currentServiceInstance = changes.currentServiceInstance.currentValue; this.isDependent = this.currentServiceInstance.isDependent(); } - if(changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) { + if (changes.selectedInstanceConstraints && changes.selectedInstanceConstraints.currentValue !== changes.selectedInstanceConstraints.previousValue) { this.selectedInstanceConstraints = changes.selectedInstanceConstraints.currentValue; this.loadRules(); } } public openRemoveDependencyModal = (): ComponentRef<ModalComponent> => { - let actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency); - let cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal); - let modalModel: ModalModel = new ModalModel('sm', I18nTexts.uncheckModalTitle, I18nTexts.uncheckModalText, [actionButton, cancelButton]); - return this.ModalServiceNg2.createCustomModal(modalModel); + const actionButton: ButtonModel = new ButtonModel(I18nTexts.modalApprove, 'blue', this.onUncheckDependency); + const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'grey', this.onCloseRemoveDependencyModal); + const modalModel: ModalModel = new ModalModel('sm', I18nTexts.uncheckModalTitle, I18nTexts.uncheckModalText, [actionButton, cancelButton]); + return this.modalServiceNg2.createCustomModal(modalModel); } loadRules() { @@ -178,60 +179,59 @@ export class ServiceDependenciesComponent { } onUncheckDependency = () => { - this.ModalServiceNg2.closeCurrentModal(); + this.modalServiceNg2.closeCurrentModal(); this.isLoading = true; - let isDepOrig = this.isDependent; - let rulesListOrig = this.rulesList; + const isDepOrig = this.isDependent; + const rulesListOrig = this.rulesList; this.currentServiceInstance.unmarkAsDependent(); this.updateComponentInstance(isDepOrig, rulesListOrig); } onCloseRemoveDependencyModal = () => { this.isDependent = true; - this.ModalServiceNg2.closeCurrentModal(); + this.modalServiceNg2.closeCurrentModal(); } onCheckDependency = () => { - let isDepOrig = this.isDependent; - let rulesListOrig = this.rulesList; + const isDepOrig = this.isDependent; + const rulesListOrig = this.rulesList; this.currentServiceInstance.markAsDependent(); this.rulesList = []; this.updateComponentInstance(isDepOrig, rulesListOrig); } onMarkAsDependent() { - if(!this.currentServiceInstance.isDependent()) { + if (!this.currentServiceInstance.isDependent()) { this.onCheckDependency(); - } - else { + } else { this.openRemoveDependencyModal().instance.open(); } } - updateComponentInstance(isDependent_origVal : boolean, rulesList_orig: Array<ConstraintObject>) { + updateComponentInstance(isDependentOrigVal: boolean, rulesListOrig: ConstraintObject[]) { this.isLoading = true; - this.componentServiceNg2.updateComponentInstance(this.compositeService, this.currentServiceInstance).subscribe((updatedServiceIns: ComponentInstance) => { + this.topologyTemplateService.updateComponentInstance(this.compositeService.uniqueId, this.currentServiceInstance).subscribe((updatedServiceIns: ComponentInstance) => { this.currentServiceInstance = new ComponentInstance(updatedServiceIns); this.isDependent = this.currentServiceInstance.isDependent(); this.dependencyStatus.emit(this.isDependent); - if(this.isDependent) { + if (this.isDependent) { this.loadRulesListEvent.emit(); } this.isLoading = false; - }, err=> { - this.isDependent = isDependent_origVal; - this.rulesList = rulesList_orig; + }, (err) => { + this.isDependent = isDependentOrigVal; + this.rulesList = rulesListOrig; this.isLoading = false; console.log('An error has occurred.'); }); } - onAddRule () { - let cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.ModalServiceNg2.closeCurrentModal); - let saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', this.createRule, this.getDisabled); - let modalModel: ModalModel = new ModalModel('l', I18nTexts.addRuleTxt, '', [saveButton, cancelButton], 'standard'); - this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel); - this.ModalServiceNg2.addDynamicContentToModal( + onAddRule() { + const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal); + const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalCreate, 'blue', this.createRule, this.getDisabled); + const modalModel: ModalModel = new ModalModel('l', I18nTexts.addRuleTxt, '', [saveButton, cancelButton], 'standard'); + this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel); + this.modalServiceNg2.addDynamicContentToModal( this.modalInstance, ServiceDependenciesEditorComponent, { @@ -247,16 +247,16 @@ export class ServiceDependenciesComponent { } onSelectRule(index: number) { - let cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.ModalServiceNg2.closeCurrentModal); - let saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateRules(), this.getDisabled); - let modalModel: ModalModel = new ModalModel('l', I18nTexts.updateRuleTxt, '', [saveButton, cancelButton], 'standard'); - this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel); - this.ModalServiceNg2.addDynamicContentToModal( + const cancelButton: ButtonModel = new ButtonModel(I18nTexts.modalCancel, 'outline white', this.modalServiceNg2.closeCurrentModal); + const saveButton: ButtonModel = new ButtonModel(I18nTexts.modalSave, 'blue', () => this.updateRules(), this.getDisabled); + const modalModel: ModalModel = new ModalModel('l', I18nTexts.updateRuleTxt, '', [saveButton, cancelButton], 'standard'); + this.modalInstance = this.modalServiceNg2.createCustomModal(modalModel); + this.modalServiceNg2.addDynamicContentToModal( this.modalInstance, ServiceDependenciesEditorComponent, { serviceRuleIndex: index, - serviceRules: _.map(this.rulesList, rule => new ConstraintObjectUI(rule)), + serviceRules: _.map(this.rulesList, (rule) => new ConstraintObjectUI(rule)), currentServiceName: this.currentServiceInstance.name, operatorTypes: this.operatorTypes, compositeServiceName: this.compositeService.name, @@ -268,40 +268,40 @@ export class ServiceDependenciesComponent { this.modalInstance.instance.open(); } - getDisabled = ():boolean => { + getDisabled = (): boolean => { return !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit(); - }; + } - createRule = ():void => { - let newRuleToCreate: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule); + createRule = (): void => { + const newRuleToCreate: ConstraintObject = new ConstraintObject(this.modalInstance.instance.dynamicContent.instance.currentRule); this.isLoading = true; - this.componentServiceNg2.createServiceFilterConstraints( - this.compositeService, - this.currentServiceInstance, + this.topologyTemplateService.createServiceFilterConstraints( + this.compositeService.uniqueId, + this.currentServiceInstance.uniqueId, newRuleToCreate ).subscribe( (response) => { this.updateRulesListEvent.emit(response.properties); this.isLoading = false; - }, err=> { + }, (err) => { this.isLoading = false; }); - this.ModalServiceNg2.closeCurrentModal(); - }; + this.modalServiceNg2.closeCurrentModal(); + } - updateRules = ():void => { - let allRulesToUpdate: Array<ConstraintObject> = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map(rule => new ConstraintObject(rule)); + updateRules = (): void => { + const allRulesToUpdate: ConstraintObject[] = this.modalInstance.instance.dynamicContent.instance.serviceRulesList.map((rule) => new ConstraintObject(rule)); this.isLoading = true; - this.componentServiceNg2.updateServiceFilterConstraints( - this.compositeService, - this.currentServiceInstance, + this.topologyTemplateService.updateServiceFilterConstraints( + this.compositeService.uniqueId, + this.currentServiceInstance.uniqueId, allRulesToUpdate ).subscribe((response) => { this.updateRulesListEvent.emit(response.properties); this.isLoading = false; - }, err => { + }, (err) => { this.isLoading = false; }); - this.ModalServiceNg2.closeCurrentModal(); + this.modalServiceNg2.closeCurrentModal(); } getSymbol(constraintOperator) { @@ -312,23 +312,23 @@ export class ServiceDependenciesComponent { } } - onDeleteRule = (index:number) => { + onDeleteRule = (index: number) => { this.isLoading = true; - this.componentServiceNg2.deleteServiceFilterConstraints( - this.compositeService, - this.currentServiceInstance, + this.topologyTemplateService.deleteServiceFilterConstraints( + this.compositeService.uniqueId, + this.currentServiceInstance.uniqueId, index ).subscribe( (response) => { this.updateRulesListEvent.emit(response.properties); this.isLoading = false; - }, err=> { + }, (err) => { this.isLoading = false; }); - this.ModalServiceNg2.closeCurrentModal(); - }; + this.modalServiceNg2.closeCurrentModal(); + } - openDeleteModal = (index:number) => { - this.ModalServiceNg2.createActionModal(I18nTexts.deleteRuleTxt, I18nTexts.deleteRuleMsg, + openDeleteModal = (index: number) => { + this.modalServiceNg2.createActionModal(I18nTexts.deleteRuleTxt, I18nTexts.deleteRuleMsg, I18nTexts.modalDelete, () => this.onDeleteRule(index), I18nTexts.modalCancel).instance.open(); } -}
\ No newline at end of file +} diff --git a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts index 7e66ed99c7..5e2d03d26c 100644 --- a/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts +++ b/catalog-ui/src/app/ng2/components/logic/service-dependencies/service-dependencies.module.ts @@ -1,9 +1,9 @@ -import { NgModule } from "@angular/core"; -import {CommonModule} from "@angular/common"; -import {ServiceDependenciesComponent} from "./service-dependencies.component"; -import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; -import {TranslateModule} from 'app/ng2/shared/translator/translate.module'; +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { UiElementsModule } from 'app/ng2/components/ui/ui-elements.module'; +import { TranslateModule } from 'app/ng2/shared/translator/translate.module'; +import { ServiceDependenciesComponent } from './service-dependencies.component'; @NgModule({ declarations: [ @@ -14,11 +14,13 @@ import {TranslateModule} from 'app/ng2/shared/translator/translate.module'; UiElementsModule, TranslateModule ], - exports: [], + exports: [ + ServiceDependenciesComponent + ], entryComponents: [ ServiceDependenciesComponent ], providers: [] }) export class ServiceDependenciesModule { -}
\ No newline at end of file +} diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.html b/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.html deleted file mode 100644 index e1a4f68a9b..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.html +++ /dev/null @@ -1,27 +0,0 @@ -<!-- - ~ 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. - --> - -<div class="service-path-selector"> - <label>Service Flows:</label> - <ui-element-dropdown - class="path-dropdown" - data-tests-id="service-path-selector" - [readonly]="dropdownOptions.length < 3" - [(value)]="selectedPathId" - [values]="dropdownOptions" - (valueChange)="onSelectPath()"> - </ui-element-dropdown> -</div> diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.less b/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.less deleted file mode 100644 index f3cb4a3c34..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.less +++ /dev/null @@ -1,24 +0,0 @@ -@import './../../../../../assets/styles/variables.less'; -.service-path-selector { - margin: 10px 35px 10px 0; - display: flex; - font-size: 12px; - - /deep/ .path-dropdown { - width: 150px; - select { - font-size: 14px; - font-family: @font-opensans-regular; - padding: 4px 10px; - } - } - - label { - margin-right: 10px; - align-self: center; - font-size: 14px; - font-family: @font-opensans-regular; - font-weight: normal; - margin-bottom: initial; - } -} diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.ts b/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.ts deleted file mode 100644 index e09001fc6c..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.component.ts +++ /dev/null @@ -1,133 +0,0 @@ -import {Component, Input, KeyValueDiffer, IterableDiffers, KeyValueDiffers, DoCheck} from '@angular/core'; -import {Service} from "app/models/components/service"; -import {TranslateService} from "app/ng2/shared/translator/translate.service"; -import {ForwardingPath} from "app/models/forwarding-path"; -import {DropdownValue} from "app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component"; - -@Component({ - selector: 'service-path-selector', - templateUrl: './service-path-selector.component.html', - styleUrls:['service-path-selector.component.less'], - providers: [TranslateService] -}) - -export class ServicePathSelectorComponent implements DoCheck { - - defaultSelectedId: string; - hideAllValue: string; - hideAllId: string = '0'; - showAllValue: string; - showAllId: string = '1'; - - paths: Array<ForwardingPath> = []; - dropdownOptions: Array<DropdownValue>; - differ: KeyValueDiffer; - - @Input() service: Service; - @Input() drawPath: Function; - @Input() deletePaths: Function; - @Input() selectedPathId: string; - - constructor(private differs: KeyValueDiffers, private translateService: TranslateService) { - - this.defaultSelectedId = this.hideAllId; - this.convertPathsToDropdownOptions(); - - this.translateService.languageChangedObservable.subscribe(lang => { - this.hideAllValue = this.translateService.translate("SERVICE_PATH_SELECTOR_HIDE_ALL_VALUE"); - this.showAllValue = this.translateService.translate("SERVICE_PATH_SELECTOR_SHOW_ALL_VALUE"); - this.convertPathsToDropdownOptions(); - }); - - } - - ngOnInit(): void { - - this.selectedPathId = this.defaultSelectedId; - this.differ = this.differs.find(this.service.forwardingPaths).create(null); - - } - - ngDoCheck(): void { - - const pathsChanged = this.differ.diff(this.service.forwardingPaths); - - if (pathsChanged) { - let oldPaths = _.cloneDeep(this.paths); - this.populatePathsFromService(); - - if (!(_.isEqual(oldPaths, this.paths))) { - this.convertPathsToDropdownOptions(); - - let temp = this.selectedPathId; - this.selectedPathId = '-1'; - - setTimeout(() => { - this.selectedPathId = temp; - this.onSelectPath(); - }, 0); - } - } - - } - - populatePathsFromService(): void { - - this.paths = []; - let {forwardingPaths} = this.service; - - _.forEach(forwardingPaths, path => { - this.paths.push(path); - }); - this.paths.sort((a:ForwardingPath, b:ForwardingPath)=> { - return a.name.localeCompare(b.name); - }); - - } - - convertPathsToDropdownOptions(): void { - - let result = [ - new DropdownValue(this.hideAllId, this.hideAllValue), - new DropdownValue(this.showAllId, this.showAllValue) - ]; - - _.forEach(this.paths, (value: ForwardingPath) => { - result[result.length] = new DropdownValue(value.uniqueId, value.name); - }); - - this.dropdownOptions = result; - - } - - onSelectPath = (): void => { - - if (this.selectedPathId !== '-1') { - this.deletePaths(); - - switch (this.selectedPathId) { - case this.hideAllId: - break; - - case this.showAllId: - _.forEach(this.paths, path => - this.drawPath(path) - ); - break; - - default: - let path = this.paths.find(path => - path.uniqueId === this.selectedPathId - ); - if (!path) { - this.selectedPathId = this.defaultSelectedId; - this.onSelectPath(); // currently does nothing in default case, but if one day it does, we want the selection to behave accordingly. - break; - } - this.drawPath(path); - break; - } - } - - } -} diff --git a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.module.ts b/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.module.ts deleted file mode 100644 index c07061ce9a..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path-selector/service-path-selector.module.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { NgModule } from "@angular/core"; -import {CommonModule} from "@angular/common"; -import {ServicePathSelectorComponent} from "./service-path-selector.component"; -import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; - -@NgModule({ - declarations: [ - ServicePathSelectorComponent - ], - imports: [ - CommonModule, - UiElementsModule - ], - exports: [], - entryComponents: [ - ServicePathSelectorComponent - ], - providers: [] -}) -export class ServicePathSelectorModule { -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.html b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.html deleted file mode 100644 index 2a6a72ab7a..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.html +++ /dev/null @@ -1,31 +0,0 @@ -<!-- - ~ 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. - --> - -<div class='service-path'> - <button class='zoom-icons create-path-button' data-tests-id="pathsMenuBtn" (click)="showServicePathMenu = !showServicePathMenu">...</button> - <div class="service-path-menu" *ngIf="showServicePathMenu"> - <div > - <ul> - <li *ngIf='!isViewOnly'><div class="hand" (click)="onCreateServicePath()" data-tests-id="createPathMenuItem"> - Create Service Flow - </div></li> - <li><div class="hand" (click)="onListServicePath()" data-tests-id="pathsListMenuItem"> - Service Flows List - </div></li> - </ul> - </div> - </div> -</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.less b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.less deleted file mode 100644 index 777b206714..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.less +++ /dev/null @@ -1,51 +0,0 @@ -//@import 'src/assets/styles/variables.less'; -@import './../../../../../assets/styles/variables.less'; -.service-path { - position: relative; - .create-path-button{ - &:extend(.search-bar-button); - width: 30px; - height: 30px; - &:hover { - color: @main_color_a; - } - &:active { - background: @main_color_a; - color: @main_color_p; - } - &:focus { - outline: none; - } - } - .service-path-menu { - border: 1px solid @main_color_o; - border-radius: 0 0 2px 2px; - border-top-color: @main_color_a; - border-top-width: 3px; - - box-sizing: border-box; - box-shadow: 0 2px 4px 0 rgba(0,0,0,0.30); - - background-color: @main_color_p; - - padding: 5px 0; - right: 34px; - position: absolute; - top: 10px; - width: 150px; - font-size: 13px; - font-family: @font-opensans-regular; - - li { - color: @main_color_m; - padding: 0 10px; - line-height: 20px; - &:hover { - cursor: pointer; - color: @main_color_a; - background-color: fade(@main_color_a, 5%); - } - } - - } -} diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.ts b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.ts deleted file mode 100644 index d66c5f0132..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.component.ts +++ /dev/null @@ -1,84 +0,0 @@ -/*- - * ============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 {Component, Input, ComponentRef} from '@angular/core'; -import {ModalService} from 'app/ng2/services/modal.service'; -import {ModalModel, ButtonModel} from 'app/models'; -import {ServicePathCreatorComponent} from 'app/ng2/pages/service-path-creator/service-path-creator.component'; -import {ModalComponent} from 'app/ng2/components/ui/modal/modal.component'; -import ServicePathsListComponent from "app/ng2/pages/service-paths-list/service-paths-list.component"; -import {Service} from "app/models/components/service"; - -@Component({ - selector: 'service-path', - templateUrl: './service-path.component.html', - styleUrls: ['service-path.component.less'], - providers: [ModalService] -}) - -export class ServicePathComponent { - showServicePathMenu: boolean = false; - modalInstance: ComponentRef<ModalComponent>; - @Input() service: Service; - @Input() onCreate: Function; - @Input() onSave: Function; - @Input() isViewOnly:boolean; - - constructor(private ModalServiceNg2: ModalService) {} - - onCreateServicePath = ():void => { - this.showServicePathMenu = false; - let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.ModalServiceNg2.closeCurrentModal); - let saveButton: ButtonModel = new ButtonModel('Create', 'blue', this.createPath, this.getDisabled ); - let modalModel: ModalModel = new ModalModel('l', 'Create Service Flow', '', [saveButton, cancelButton], 'standard', true); - this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel); - this.ModalServiceNg2.addDynamicContentToModal(this.modalInstance, ServicePathCreatorComponent, {service: this.service}); - this.modalInstance.instance.open(); - }; - - onListServicePath = ():void => { - this.showServicePathMenu = false; - let cancelButton: ButtonModel = new ButtonModel('Close', 'outline white', this.ModalServiceNg2.closeCurrentModal); - let modalModel: ModalModel = new ModalModel('md', 'Service Flows List','', [cancelButton], 'standard', true); - this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel); - this.ModalServiceNg2.addDynamicContentToModal(this.modalInstance, ServicePathsListComponent, {service: this.service, - onCreateServicePath: this.onCreateServicePath, onEditServicePath: this.onEditServicePath, isViewOnly: this.isViewOnly}); - this.modalInstance.instance.open(); - }; - - createPath = ():void => { - this.onCreate(this.modalInstance.instance.dynamicContent.instance.createServicePathData()); - this.ModalServiceNg2.closeCurrentModal(); - }; - - onEditServicePath = (id:string):void => { - let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline white', this.ModalServiceNg2.closeCurrentModal); - let saveButton: ButtonModel = new ButtonModel('Save', 'blue', this.createPath, this.getDisabled ); - let modalModel: ModalModel = new ModalModel('l', 'Edit Path', '', [saveButton, cancelButton], 'standard', true); - this.modalInstance = this.ModalServiceNg2.createCustomModal(modalModel); - this.ModalServiceNg2.addDynamicContentToModal(this.modalInstance, ServicePathCreatorComponent, {service: this.service, pathId: id}); - this.modalInstance.instance.open(); - }; - - getDisabled = ():boolean => { - return this.isViewOnly || !this.modalInstance.instance.dynamicContent.instance.checkFormValidForSubmit(); - }; -} - diff --git a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.module.ts b/catalog-ui/src/app/ng2/components/logic/service-path/service-path.module.ts deleted file mode 100644 index 96af247086..0000000000 --- a/catalog-ui/src/app/ng2/components/logic/service-path/service-path.module.ts +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * ============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 { NgModule } from "@angular/core"; -import {CommonModule} from "@angular/common"; -import {ServicePathComponent} from "./service-path.component"; -import {UiElementsModule} from "app/ng2/components/ui/ui-elements.module"; - -@NgModule({ - declarations: [ - ServicePathComponent - ], - imports: [CommonModule, - UiElementsModule], - exports: [], - entryComponents: [ - ServicePathComponent - ], - providers: [] -}) -export class ServicePathModule { -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.html b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.html new file mode 100644 index 0000000000..127531bfab --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.html @@ -0,0 +1,18 @@ +<form> + <div> + <div class="comment-modal-text" [innerHTML]="message"></div> + <sdc-textarea #comment1 + [(value)]="comment.text" + placeHolder="{{'CONFIRMATION_MODAL_PLACEHOLDER' | translate }}" + [required]="true" + name="comment1" + testId="checkindialog" + [maxLength]="256"> + </sdc-textarea> + <sdc-validation [validateElement]="comment1" (validityChanged)="onValidityChange($event)"> + <sdc-required-validator message="{{ 'VALIDATION_ERROR_REQUIRED' | translate:{'field': 'Comment' } }}"></sdc-required-validator> + <sdc-regex-validator message="{{ 'VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED' | translate}}" + [pattern]="commentValidationPattern"></sdc-regex-validator> + </sdc-validation> + </div> +</form> diff --git a/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.ts b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.ts new file mode 100644 index 0000000000..c66f60b5e7 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.component.ts @@ -0,0 +1,25 @@ +/** + * Created by rc2122 on 5/31/2018. + */ +import { Component, Input } from "@angular/core"; +import { ValidationConfiguration } from "app/models"; +import { Subject } from "rxjs/Subject"; + +@Component({ + selector: 'comment-modal', + templateUrl: './comment-modal.component.html', + styleUrls: ['./comment-modal.less'] +}) + +export class CommentModalComponent { + + @Input() message:string; + onValidationChange: Subject<boolean> = new Subject(); + //@Input() showComment:boolean; + private comment = {"text": ''}; + private commentValidationPattern = ValidationConfiguration.validation.validationPatterns.comment; + + private onValidityChange = (isValid: boolean):void => { + this.onValidationChange.next(isValid); + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.less b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.less new file mode 100644 index 0000000000..8e20e81115 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/comment-modal/comment-modal.less @@ -0,0 +1,3 @@ +.comment-modal-text { + padding-bottom: 5px; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/modals/modals.module.ts b/catalog-ui/src/app/ng2/components/modals/modals.module.ts new file mode 100644 index 0000000000..5aa7f08b60 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/modals.module.ts @@ -0,0 +1,29 @@ +/** + * Created by rc2122 on 5/24/2018. + */ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { NgxDatatableModule } from '@swimlane/ngx-datatable'; +import { CommentModalComponent } from 'app/ng2/components/modals/comment-modal/comment-modal.component'; +import { PopoverModule } from 'app/ng2/components/ui/popover/popover.module'; +import { TranslateModule } from 'app/ng2/shared/translator/translate.module'; +import { SdcUiComponentsModule } from 'onap-ui-angular'; +import { OnboardingService } from '../../services/onboarding.service'; +import { ImportVSPService } from './onboarding-modal/import-vsp.service'; +import { OnboardingModalComponent } from './onboarding-modal/onboarding-modal.component'; + +@NgModule({ + declarations: [CommentModalComponent, OnboardingModalComponent], + imports: [TranslateModule, + SdcUiComponentsModule, + CommonModule, + PopoverModule, + NgxDatatableModule], + exports: [CommentModalComponent, OnboardingModalComponent], + entryComponents: [CommentModalComponent, OnboardingModalComponent], + providers: [OnboardingService, ImportVSPService], + bootstrap: [] +}) + +export class ModalsModule { +} diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/import-vsp.service.ts b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/import-vsp.service.ts new file mode 100644 index 0000000000..8e7364660f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/import-vsp.service.ts @@ -0,0 +1,36 @@ +import { Injectable, Inject } from "@angular/core"; +import { OnboardingModalComponent } from "./onboarding-modal.component"; +import { SdcUiServices, SdcUiCommon } from "onap-ui-angular"; +import { Observable, Subject } from "rxjs"; +import { CHANGE_COMPONENT_CSAR_VERSION_FLAG } from "../../../../utils/constants"; +import { CacheService } from "../../../services/cache.service"; + + +@Injectable() +export class ImportVSPService { + + constructor(private modalService: SdcUiServices.ModalService, + private cacheService:CacheService, + @Inject("$state") private $state:ng.ui.IStateService){ + + } + + openOnboardingModal(csarUUID?: string, csarVersion?: string): Observable<any> { + var subject = new Subject<any>(); + const onboardingModalConfig = { + size: SdcUiCommon.ModalSize.xlarge, + title: 'Import VSP', + type: SdcUiCommon.ModalType.custom, + testId: 'sampleTestIdModal1', + } as SdcUiCommon.IModalConfig; + const onboardingModalInstance = this.modalService.openCustomModal(onboardingModalConfig, OnboardingModalComponent, {currentCsarUUID: csarUUID, currentCsarVersion: csarVersion}); + onboardingModalInstance.innerModalContent.instance.closeModalEvent.subscribe( + (result: any) => { + subject.next(result); + onboardingModalInstance.closeModal(); + }, (err) =>{} + ) + return subject.asObservable(); + } +} + diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.html b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.html new file mode 100644 index 0000000000..6ba1f428a1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.html @@ -0,0 +1,106 @@ +<div class="onboarding-modal"> + <div class="search-wrapper"> + <span class="sub-title-wrapper"> + <svg-icon class="info-button" + (click) = "openPopover($event, 'ON_BOARDING_GENERAL_INFO')" + [name]="'info-circle-o'" [mode]="'primary'" + [size]="'medium'"></svg-icon> + <span class="sub-title">{{ 'ON_BOARDING_MODAL_SUB_TITLE' | translate }}</span> + </span> + <span class="sdc-filter-bar-wrapper"> + <sdc-filter-bar + [placeHolder]="'Search'" + (keyup)="updateFilter($event)" + [testId]="'onboarding-search'"> + </sdc-filter-bar> + </span> + </div> + <div class="datatable-components-wapper"> + <ngx-datatable #componentsMetadataTable + columnMode="flex" + [headerHeight]="40" + [rowHeight]="35" + [rows]="componentsMetadataList" + [sorts]="[{prop: 'name', dir: 'asc'}]" + (select)='onSelectComponent($event)' + [selectionType]="'single'"> + <ngx-datatable-row-detail [rowHeight]="undefiend"> + <ng-template let-row="row" let-expanded="expanded" ngx-datatable-row-detail-template > + <div class="onboarding-components-details"> + <span class="row-details-description"> + <div> + <div class="th">VSP Description:</div> + <div>{{row.description}}</div> + </div> + </span> + <span class="row-details-metadata1"> + <div *ngIf="isCsarComponentExists"> + <div class="th">VF'S Meta Data:</div> + <div><span class="th">Name:</span>{{componentFromServer.name}}</div> + <div><span class="th">Lifecycle:</span>{{componentFromServer.lifecycleState}}</div> + <div><span class="th">Creator:</span>{{componentFromServer.creatorFullName}}</div> + </div> + </span> + <span class="row-details-metadata2"> + <div *ngIf="isCsarComponentExists"> + <div class="th"> </div> + <div><span class="th">UUID:</span> {{componentFromServer.uuid}}</div> + <div><span class="th">Version:</span> {{componentFromServer.version}}</div> + <div><span class="th">Modifier:</span> {{componentFromServer.lastUpdaterFullName}}</div> + <div *ngIf="checkNotCertified()"> + <span class="note">Designers cannot update a VSP if the VF is <br>checked out by another user.</span> + </div> + </div> + </span> + <span class="row-details-metadata3"> + <svg-icon class="info-button" + (click) = "openPopover($event, isCsarComponentExists ? 'ON_BOARDING_UPDATE_INFO' : 'ON_BOARDING_IMPORT_INFO')" + [name]="'info-circle-o'" [mode]="'primary'" + [size]="'medium'"></svg-icon> + </span> + <span class="row-details-icon"> + <div> + <sdc-button class="import-update-file-btn" + [text]="isCsarComponentExists ? 'Update VSP' : 'Import VSP'" + [testId]="isCsarComponentExists ? 'update-csar' : 'import-csar'" + [type]="'primary'" + [icon_name]="isCsarComponentExists ? 'sync-o' : 'alert-triangle-o'" + [icon_position]="'left'" + [icon_mode] = "'white'" + [size] = "'medium'" + (click)="importOrUpdateCsar()" + [disabled]="checkNotCertified()" + > + </sdc-button> + <svg-icon class="download-file-btn" sdc-tooltip [tooltip-text]="'Download-csar'" + [mode]="'primary'" [clickable]="true" [name]="'download-o'" + [testId]="'download-csar'" [size]="'medium'" (click)="downloadCsar(row.packageId)"> + </svg-icon> + </div> + </span> + </div> + <sdc-loader [global]="false" [active]="isLoad" [size]="'small'"[relative]="true"></sdc-loader> + </ng-template> + </ngx-datatable-row-detail> + <ngx-datatable-column *ngFor="let column of columns" [ngSwitch]="column.prop" [resizeable]="false" [draggable]="false" name={{column.name}} + [flexGrow]="column.flexGrow"> + <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchCase="'name'"> + <span data-tests-id="csar-row" class="sprite table-arrow" [ngClass]="{'opened': selectedComponent && row.packageId === selectedComponent.packageId}"></span> + {{row[column.prop]}} + </ng-template> + <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchCase="'categories'"> + <span *ngIf="row[column.prop][0]"> + {{row[column.prop][0].name}} + <span *ngIf="row[column.prop][0].subcategories[0]">{{row[column.prop][0].subcategories[0].name}}</span> + </span> + </ng-template> + <ng-template ngx-datatable-cell-template let-row="row" *ngSwitchDefault> + {{row[column.prop]}} + </ng-template> + </ngx-datatable-column> + </ngx-datatable> +</div> +</div> + + + diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.less b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.less new file mode 100644 index 0000000000..2e4abda35e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.less @@ -0,0 +1,97 @@ +@import "../../../../../assets/styles/variables"; +@import "../../../../../assets/styles/mixins"; + + +.onboarding-components-details{ + display: flex; +} +.row-details-description, +.row-details-metadata1, +.row-details-metadata2, +.row-details-metadata3{ + .th { .m_14_m; } + flex-basis: 0; + overflow: hidden; + padding: 5px 15px; + white-space: normal; +} +.row-details-description, +.row-details-metadata3 { + border-right: 1px solid @main_color_o; +} + +.row-details-icon { + flex-basis: 0; + overflow: hidden; + padding: 5px 10px; + align-self: center; +} + +.row-details-description { + flex-grow: 19; +} +.row-details-metadata1 { + flex-grow: 26.5; +} +.row-details-metadata2 { + flex-grow: 35; + .note { + color: @func_color_q; + } +} +.row-details-metadata3 { + flex-grow: 8; +} +.info-button{ + cursor: pointer; + float: right; +} +.row-details-icon { + flex-grow: 18; +} +.download-file-btn { + cursor: pointer; + margin-left: 6px; +} + +.import-update-file-btn { + cursor: pointer; +} +.sprite.table-arrow{ + margin-right: 7px; +} +.search-wrapper { + .sdc-filter-bar-wrapper { + flex: 0 0 30%; + } + .sub-title-wrapper { + flex: 0 0 70%; + font-size: 15px; + line-height: 35px; + font-family: OpenSans-Regular, sans-serif; + align-items: center; + display: inline-flex; + .sub-title{ + padding-left: 5px; + } + } + display: flex; + margin-top: 15px; + margin-bottom: 10px; + } + + :host ::ng-deep { + .datatable-row-detail{ + width: 1120px; + } + .datatable-body-row { + cursor: pointer; + } + } + + + + + + + diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.spec.ts b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.spec.ts new file mode 100644 index 0000000000..565398b6ad --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.spec.ts @@ -0,0 +1,122 @@ +import {async, ComponentFixture, TestBed} from "@angular/core/testing"; +import { NO_ERRORS_SCHEMA} from "@angular/core"; +import {ConfigureFn, configureTests} from "../../../../../jest/test-config.helper"; + +import {Observable} from "rxjs/Observable"; +import {NgxDatatableModule} from "@swimlane/ngx-datatable"; +import {SdcUiServices, SdcUiCommon} from "onap-ui-angular"; +import 'rxjs/add/observable/of'; +import {OnboardingService} from "../../../services/onboarding.service"; +import {TranslateService} from "../../../shared/translator/translate.service"; +import {CacheService} from "../../../services/cache.service"; +import {FileUtilsService} from "../../../services/file-utils.service"; +import {onboardingModalVSPMock, onboardingModalUniqueVSPMock, vspFromServerMock} from "../../../../../jest/mocks/onboarding-vsp.mock"; +import {OnboardingModalComponent} from "./onboarding-modal.component"; +import {TranslatePipe} from "../../../shared/translator/translate.pipe"; + +describe('onboarding modal component', () => { + + let fixture: ComponentFixture<OnboardingModalComponent>; + let onboardingServiceMock: Partial<OnboardingService>; + let translateServiceMock: Partial<TranslateService>; + let cacheServiceMock: Partial<CacheService>; + let fileUtilsServiceMock: Partial<FileUtilsService>; + let popoverServiceMock: Partial<SdcUiServices.PopoverService>; + let loaderServiceMock: Partial<SdcUiServices.LoaderService>; + + beforeEach( + async(() => { + + onboardingServiceMock = { + getOnboardingComponents: jest.fn().mockImplementation(()=> Observable.of(onboardingModalUniqueVSPMock)), + getComponentFromCsarUuid: jest.fn().mockImplementation(()=> Observable.of(vspFromServerMock)) + }; + + cacheServiceMock = { + set: jest.fn() + }; + + loaderServiceMock = { + activate: jest.fn(), + deactivate: jest.fn() + } + + + const configure: ConfigureFn = testBed => { + testBed.configureTestingModule({ + declarations: [OnboardingModalComponent, TranslatePipe], + imports: [NgxDatatableModule], + schemas: [NO_ERRORS_SCHEMA], + providers: [ + { provide: OnboardingService, useValue: onboardingServiceMock }, + { provide: TranslateService, useValue: translateServiceMock }, + { provide: CacheService, useValue: cacheServiceMock }, + { provide: FileUtilsService, useValue: fileUtilsServiceMock }, + { provide: SdcUiServices.PopoverService, useValue: popoverServiceMock }, + { provide: SdcUiServices.LoaderService, useValue: loaderServiceMock } + ], + }); + }; + configureTests(configure).then(testBed => { + fixture = testBed.createComponent(OnboardingModalComponent); + }); + }) + ); + + /*it('should match current snapshot of onboarding modal component', () => { + expect(fixture).toMatchSnapshot(); + });*/ + + it('should see exactly 2 vsp in onboarding modal and call initOnboardingComponentsList', () => { + fixture.componentInstance.initOnboardingComponentsList(); + expect(fixture.componentInstance.componentsMetadataList.length).toBe(2); + }); + + it('should see exactly 1 vsp in onboarding modal and call initOnboardingComponentsList', () => { + fixture.componentInstance.currentCsarUUID = "6348841e79a64871ba064ce340a968a4"; + fixture.componentInstance.initOnboardingComponentsList(); + expect(fixture.componentInstance.componentsMetadataList.length).toBe(1); + }); + + it('when get a list of vsp initMaxVersionOfItemsInList will return a list with unique items with the latest versions for each packageId', () => { + onboardingServiceMock.getOnboardingComponents = jest.fn().mockImplementation(() => Observable.of(onboardingModalVSPMock)); + fixture.componentInstance.initOnboardingComponentsList(); + expect(fixture.componentInstance.componentsMetadataList.length).toBe(2); + }); + + it('should filter out 1 vsp when searching and call updateFilter function', () => { + fixture.componentInstance.initOnboardingComponentsList(); + let event = { + target : { + value : 'test new vsp' + } + } + + expect(fixture.componentInstance.componentsMetadataList.length).toBe(2); + fixture.componentInstance.updateFilter(event); + expect(fixture.componentInstance.componentsMetadataList.length).toBe(1); + }); + + it('When select the selected vsp the row details closed and call onSelectComponent function', () => { + fixture.componentInstance.initOnboardingComponentsList(); + fixture.componentInstance.onSelectComponent({selected: []}); + expect(fixture.componentInstance.selectedComponent).toEqual(undefined); + expect(fixture.componentInstance.componentFromServer).toEqual(undefined); + }); + + it('When select vsp a row with its details will be opened and call onSelectComponent function', () => { + fixture.componentInstance.initOnboardingComponentsList(); + fixture.componentInstance.onSelectComponent({selected: onboardingModalVSPMock}); + expect(fixture.componentInstance.selectedComponent).not.toEqual(null); + expect(fixture.componentInstance.componentFromServer).not.toEqual(undefined); + expect(fixture.componentInstance.isCsarComponentExists).toEqual(true); + }); + it('When select new vsp a row with import and download buttons will be opened and call onSelectComponent function', () => { + fixture.componentInstance.initOnboardingComponentsList(); + onboardingServiceMock.getComponentFromCsarUuid.mockImplementation(() => Observable.of(undefined)); + fixture.componentInstance.onSelectComponent({selected: onboardingModalVSPMock}); + expect(fixture.componentInstance.selectedComponent).not.toEqual(null); + expect(fixture.componentInstance.componentFromServer).toEqual(undefined); + expect(fixture.componentInstance.isCsarComponentExists).toEqual(false); + }); +}); diff --git a/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.ts b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.ts new file mode 100644 index 0000000000..2e41716e0b --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modals/onboarding-modal/onboarding-modal.component.ts @@ -0,0 +1,193 @@ +/** + * Created by rc2122 on 6/3/2018. + */ +import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; +import * as _ from 'lodash'; +import { SdcUiServices } from 'onap-ui-angular'; +import { ComponentMetadata, IComponentMetadata } from '../../../../models/component-metadata'; +import { IUserProperties } from '../../../../models/user'; + +import { Resource } from '../../../../models/components/resource'; +import { ComponentType } from '../../../../utils/constants'; +import { CacheService } from '../../../services/cache.service'; +import { FileUtilsService } from '../../../services/file-utils.service'; +import { OnboardingService } from '../../../services/onboarding.service'; +import { TranslateService } from '../../../shared/translator/translate.service'; + +export interface ImportVSPdata { + componentCsar: Resource; + previousComponent?: Resource; + type: string; +} + +// tslint:disable-next-line:interface-name +export interface IPoint { + x: number; + y: number; +} + +@Component({ + selector: 'onboarding-modal', + templateUrl: './onboarding-modal.component.html', + styleUrls: ['onboarding-modal.component.less', '../../../../../assets/styles/table-style.less'] +}) +export class OnboardingModalComponent implements OnInit { + @Input() currentCsarUUID: string; + @Input() currentCsarVersion: string; + @ViewChild('componentsMetadataTable') table: any; + @Output() closeModalEvent: EventEmitter<ImportVSPdata> = new EventEmitter<ImportVSPdata>(); + + private columns = [ + {name: 'Name', prop: 'name', flexGrow: 22}, + {name: 'Vendor', prop: 'vendorName', flexGrow: 26}, + {name: 'Category', prop: 'categories', flexGrow: 33}, + {name: 'Version', prop: 'csarVersion', flexGrow: 10}, + {name: 'Type', prop: 'resourceType', flexGrow: 10}, + {name: '#', prop: '', flexGrow: 20} + ]; + private componentsMetadataList: IComponentMetadata[] = []; + private temp: IComponentMetadata[] = []; + private componentFromServer: ComponentMetadata; + private isCsarComponentExists: boolean = false; + private selectedComponent: ComponentMetadata; + private isLoading: boolean; + private user: IUserProperties; + + constructor(private onBoardingService: OnboardingService, + private translateService: TranslateService, + private cacheService: CacheService, + private fileUtilsService: FileUtilsService, + private popoverService: SdcUiServices.PopoverService, + private loaderService: SdcUiServices.LoaderService) { + } + + public ngOnInit(): void { + this.initOnboardingComponentsList(); + this.user = this.cacheService.get('user'); + } + + initMaxVersionOfItemsInList = (onboardingResponse: IComponentMetadata[]): void => { + // Get only the latest version of each item + this.componentsMetadataList = []; + + // group all items according to packageId + const groupByPackageIdItems = _.groupBy(onboardingResponse, 'packageId'); + // Loop on all the groups and push to componentsMetadataList the max version for each package + _.each(groupByPackageIdItems, (items: any): void => { + let maxItem: any = items[0]; + items.forEach((item) => { + if (parseFloat(maxItem.csarVersion) < parseFloat(item.csarVersion)) { + maxItem = item; + } + }); + if (maxItem) { + this.componentsMetadataList.push(maxItem); + } + }); + } + + onSelectComponent({selected}) { + this.table.rowDetail.collapseAllRows(); + if (selected[0] === this.selectedComponent) { + this.selectedComponent = undefined; + this.componentFromServer = undefined; + this.table.rowDetail.toggleExpandRow(null); + return; + } + this.isLoading = true; + this.componentFromServer = undefined; + this.selectedComponent = selected[0]; + this.onBoardingService.getComponentFromCsarUuid(this.selectedComponent.csarUUID).subscribe( + (componentFromServer: ComponentMetadata) => { + this.isLoading = false; + if (componentFromServer) { + this.componentFromServer = componentFromServer; + this.populateRowDetails(true); + } else { + this.populateRowDetails(false); + } + }, (error) => { + this.isLoading = false; + this.populateRowDetails(false); + }); + } + + populateRowDetails(isCsarComponentExists: boolean) { + this.isCsarComponentExists = isCsarComponentExists; + this.table.rowDetail.toggleExpandRow(this.selectedComponent); + } + + importOrUpdateCsar = (): void => { + const selectedComponentConverted = this.onBoardingService.convertMetaDataToComponent(this.selectedComponent); + const componentFromServerConverted = this.componentFromServer ? + this.onBoardingService.convertMetaDataToComponent(this.componentFromServer) : undefined; + const importVSPdata: ImportVSPdata = { + componentCsar: selectedComponentConverted, + previousComponent: componentFromServerConverted, + type: ComponentType.RESOURCE.toLowerCase() + }; + this.closeModalEvent.emit(importVSPdata); + } + + downloadCsar = (packageId: string): void => { + this.isLoading = true; + this.onBoardingService.downloadOnboardingCsar(packageId).subscribe( + (file: any): void => { + this.isLoading = false; + if (file.body) { + this.fileUtilsService.downloadFile(file.body, packageId + '.csar'); + } + }, (): void => { + this.isLoading = false; + } + ); + } + + updateFilter(event) { + const val = event.target.value.toLowerCase(); + + // filter our data + const temp = this.temp.filter((componentMetadata: ComponentMetadata) => { + return !val || + (componentMetadata.name && componentMetadata.name.toLowerCase().indexOf(val) !== -1) || + (componentMetadata.vendorName && componentMetadata.vendorName.toLowerCase().indexOf(val) !== -1) || + (componentMetadata.categories[0] && componentMetadata.categories[0].name.toLowerCase().indexOf(val) !== -1) || + (componentMetadata.categories[0] && componentMetadata.categories[0].subcategories[0] && componentMetadata.categories[0].subcategories[0].name.toLowerCase().indexOf(val) !== -1) || + (componentMetadata.csarVersion && componentMetadata.csarVersion.toLowerCase().indexOf(val) !== -1) || + (componentMetadata.description && componentMetadata.description.toLowerCase().indexOf(val) !== -1); + }); + + // update the rows + this.componentsMetadataList = temp; + } + + checkNotCertified = (): boolean => { + return this.componentFromServer && this.componentFromServer.lifecycleState === 'NOT_CERTIFIED_CHECKOUT' && + this.componentFromServer.lastUpdaterUserId !== this.user.userId; + } + + openPopover = ($event: any, popoverContent): void => { + this.popoverService.createPopOver('', this.translateService.translate(popoverContent), { + x: $event.pageX, + y: $event.pageY + }, 'bottom'); + } + + private initOnboardingComponentsList = (): void => { + this.loaderService.activate(); + this.onBoardingService.getOnboardingComponents().subscribe( + (onboardingResponse: IComponentMetadata[]) => { + this.loaderService.deactivate(); + if (this.currentCsarUUID) { + onboardingResponse = _.filter(onboardingResponse, (input): boolean => { + return (input as ComponentMetadata).csarUUID === this.currentCsarUUID; + }); + } + this.initMaxVersionOfItemsInList(onboardingResponse); + this.temp = [...this.componentsMetadataList]; + }, (error) => { + this.loaderService.deactivate(); + } + ); + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html deleted file mode 100644 index 50a93fac3c..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.html +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - ~ 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. - --> - - -<div class="sdc-canvas-zone {{class}}-zone" [class.minimized]="minimized" [class.hidden]="!visible" (click)="backgroundClicked()"> - <div class="sdc-canvas-zone__header" (click)="unminifyZone(); $event.stopPropagation();" > - <div class="sdc-canvas-zone__title">{{title}} - <span class="sdc-canvas-zone__counter">{{count}}</span> - </div> - <span class="sdc-canvas-zone__state-button">–</span> - </div> - <div class="sdc-canvas-zone__container" #scrollDiv > - <ng-content></ng-content> - </div> -</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less deleted file mode 100644 index 02880a9202..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.less +++ /dev/null @@ -1,62 +0,0 @@ -.sdc-canvas-zone { - width: 285px; - max-height:186px; - display:flex; - flex-direction:column; - align-self: flex-end; - color:white; - font-family:OpenSans-Regular, sans-serif; - transition: width .2s ease-in-out, max-height .2s ease-in-out .1s; - position:relative; - bottom:0px; - - .sdc-canvas-zone__header { - background: #5A5A5A; - border-radius: 2px 2px 0 0; - padding: 5px 10px; - display:flex; - justify-content: space-between; - font-size: 14px; - text-transform:uppercase; - .sdc-canvas-zone__state-button { - font-weight:bold; - cursor:pointer; - } - } - - .sdc-canvas-zone__container { - padding:5px; - background-color: #5A5A5A; - opacity:0.9; - flex: 1; - display:flex; - flex-direction: row; - align-items: flex-start; - flex-wrap:wrap; - overflow-y:auto; - min-height: 80px; - max-height: 170px; - } - - - &.minimized { - max-height:30px; - width:120px; - cursor:pointer; - - .sdc-canvas-zone__state-button { - display:none; - } - .sdc-canvas-zone__container { - flex: 0 0 0; - min-height: 0; - padding: 0; - overflow-y:hidden; - transition: min-height .2s ease-in-out .2s; - transition: padding .1s ease-in-out 0s; - } - } - &.hidden { - display:none; - } -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts deleted file mode 100644 index 4059ad6cae..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-container.component.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { Component, Input, Output, ViewEncapsulation, EventEmitter, OnInit } from '@angular/core'; -import { ZoneInstanceType } from '../../../../models/graph/zones/zone-instance'; - -@Component({ - selector: 'zone-container', - templateUrl: './zone-container.component.html', - styleUrls: ['./zone-container.component.less'], - encapsulation: ViewEncapsulation.None -}) - -export class ZoneContainerComponent implements OnInit { - @Input() title:string; - @Input() type:ZoneInstanceType; - @Input() count:number; - @Input() visible:boolean; - @Input() minimized:boolean; - @Output() minimize: EventEmitter<any> = new EventEmitter<any>(); - @Output() backgroundClick: EventEmitter<void> = new EventEmitter<void>(); - private class:string; - - constructor() {} - - ngOnInit() { - this.class = ZoneInstanceType[this.type].toLowerCase(); - } - - private unminifyZone = () => { - this.minimize.emit(); - } - - private backgroundClicked = () => { - this.backgroundClick.emit(); - } - -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html deleted file mode 100644 index 728764c427..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.html +++ /dev/null @@ -1,26 +0,0 @@ -<!-- - ~ 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. - --> - - -<div tooltip="{{zoneInstance.instanceData.name}}" #currentComponent - class="zone-instance mode-{{zoneInstance.mode}}" [class.locked]="activeInstanceMode > MODE.HOVER" [class.hiding]="hidden" - (mouseenter)="setMode(MODE.HOVER)" (mouseleave)="setMode(MODE.NONE)" (click)="setMode(MODE.SELECTED, $event)"> - <div *ngIf="zoneInstance.handle" class="target-handle {{zoneInstance.handle}}" (click)="tagHandleClicked($event)"></div> - <div *ngIf="!isViewOnly" class="zone-instance__handle" (click)="setMode(MODE.TAG, $event)">+</div> - <div class="zone-instance__body"> - <div class="zone-instance__body-content">{{zoneInstance.assignments.length || defaultIconText}}</div> - </div> - <div class="zone-instance__name">{{zoneInstance.instanceData.name}}</div> -</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less deleted file mode 100644 index b562c08514..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.less +++ /dev/null @@ -1,134 +0,0 @@ -@import '../../../../../../assets/styles/variables'; - -.zone-instance { - position:relative; - width:76px; - margin:5px; - opacity:1; - - .zone-instance__handle { - display:none; - position:absolute; - right:4px; - top:10px; - width:22px; - height:22px; - cursor:pointer; - border: solid @main_color_p 1px; - border-radius: 2px; - text-align: center; - font-weight:bold; - } - - .zone-instance__body { - margin:0 auto; - width:43px; - height:43px; - display:flex; - padding:3px; - } - - .zone-instance__body-content { - border-radius: 2px; - flex:1; - color:@main_color_p; - font-size:16px; - text-align:center; - display:flex; - align-items: center; - justify-content: center; - box-shadow:none; - transition:box-shadow 5s; - } - - .zone-instance__name { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - text-align:center; - } - /* Dynamic classes below */ - - .target-handle { - position:absolute; - width:18px; - height:18px; - display:block; - top: -4px; - right: 10px; - background-size: 100% 100%; - cursor: url("../../../../../../assets/styles/images/canvas-tagging-icons/policy_2.svg"), pointer; - - &.tagged-policy { - background-image: url('../../../../../../assets/styles/images/canvas-tagging-icons/policy_added.svg'); - } - - &.tag-available { - background-image: url('../../../../../../assets/styles/images/canvas-tagging-icons/indication.svg'); - } - } - - - &.mode-1, &.mode-2, &.mode-3 { //hover, selected, tag - .zone-instance__body { - border:solid 2px; - border-radius: 2px; - padding:2px; - cursor:pointer; - } - } - - &.mode-1, &.mode-2:hover{ - .zone-instance__handle{ - display:block; - } - } - - &.locked { - cursor: inherit; - } - - &.hiding { - opacity:0; - .zone-instance__body-content { - box-shadow: #CCC 0px 0px 15px; - } - } - - - &.mode-3 .zone-instance__handle { - width:24px; - height:24px; - right:3px; - top:9px; - display:block; - background-image: linear-gradient(-140deg, #009E98 0%, #97D648 100%); - border: 2px solid @main_color_p; - border-radius: 2px; - box-shadow: inset 2px -2px 3px 0 #007A3E; - } - -} -.sdc-canvas-zone.group-zone { - .zone-instance__handle { - background-color:@main_color_a; - } - .zone-instance__body { - border-color:@main_color_a; - .zone-instance__body-content { - background: @main_color_a; - } - } -} - -.sdc-canvas-zone.policy-zone { - .zone-instance__handle { - background-color:@main_color_r; - } - .zone-instance__body { - border-color:@main_color_r; - .zone-instance__body-content { - background: @main_color_r; - } - } -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts b/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts deleted file mode 100644 index 3c2dd45db5..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/canvas-zone/zone-instance/zone-instance.component.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Component, Input, Output, EventEmitter, ViewEncapsulation, OnInit, SimpleChange, ElementRef, ViewChild, SimpleChanges } from '@angular/core'; -import { - ZoneInstance, ZoneInstanceMode, ZoneInstanceType, - IZoneInstanceAssignment -} from 'app/models/graph/zones/zone-instance'; -import { PoliciesService } from '../../../../services/policies.service'; -import { GroupsService } from '../../../../services/groups.service'; -import { IZoneService } from "../../../../../models/graph/zones/zone"; -import { EventListenerService } from 'app/services'; -import { GRAPH_EVENTS } from '../../../../../utils'; -import { Subject, Observable } from 'rxjs'; - -@Component({ - selector: 'zone-instance', - templateUrl: './zone-instance.component.html', - styleUrls: ['./zone-instance.component.less'], - encapsulation: ViewEncapsulation.None -}) -export class ZoneInstanceComponent implements OnInit { - - @Input() zoneInstance:ZoneInstance; - @Input() defaultIconText:string; - @Input() isActive:boolean; - @Input() isViewOnly:boolean; - @Input() activeInstanceMode: ZoneInstanceMode; - @Input() hidden:boolean; - @Input() forceSave:Subject<Function>; - @Output() modeChange: EventEmitter<any> = new EventEmitter<any>(); - @Output() assignmentSaveStart: EventEmitter<void> = new EventEmitter<void>(); - @Output() assignmentSaveComplete: EventEmitter<boolean> = new EventEmitter<boolean>(); - @Output() tagHandleClick: EventEmitter<ZoneInstance> = new EventEmitter<ZoneInstance>(); - @ViewChild('currentComponent') currentComponent: ElementRef; - private MODE = ZoneInstanceMode; - private zoneService:IZoneService; - - constructor(private policiesService:PoliciesService, private groupsService:GroupsService, private eventListenerService:EventListenerService){} - - ngOnInit(){ - if(this.zoneInstance.type == ZoneInstanceType.POLICY){ - this.zoneService = this.policiesService; - } else { - this.zoneService = this.groupsService; - } - this.forceSave.subscribe((afterSaveFunction:Function) => { - this.setMode(ZoneInstanceMode.TAG, null, afterSaveFunction); - }) - } - - ngOnChanges(changes:SimpleChanges) { - if(changes.hidden){ - this.currentComponent.nativeElement.scrollIntoView({behavior: "smooth", block: "nearest", inline:"end"}); - } - } - - ngOnDestroy() { - this.forceSave.unsubscribe(); - } - - private setMode = (mode:ZoneInstanceMode, event?:any, afterSaveCallback?:Function):void => { - - if(event){ //prevent event from handle and then repeat event from zone instance - event.stopPropagation(); - } - - if(!this.isActive && this.activeInstanceMode === ZoneInstanceMode.TAG) { - return; //someone else is tagging. No events allowed - } - - if(this.isActive && this.zoneInstance.mode === ZoneInstanceMode.TAG){ - if(mode !== ZoneInstanceMode.TAG) { - return; //ignore all other events. The only valid option is saving changes. - } - - let oldAssignments:Array<IZoneInstanceAssignment> = this.zoneInstance.instanceData.getSavedAssignments(); - if(this.zoneInstance.isZoneAssignmentChanged(oldAssignments, this.zoneInstance.assignments)) { - - this.assignmentSaveStart.emit(); - - this.zoneService.updateZoneInstanceAssignments(this.zoneInstance.parentComponentType, this.zoneInstance.parentComponentID, this.zoneInstance.instanceData.uniqueId, this.zoneInstance.assignments).subscribe( - (success) => { - this.zoneInstance.instanceData.setSavedAssignments(this.zoneInstance.assignments); - if(this.zoneInstance.type === ZoneInstanceType.POLICY){ - this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_POLICY_INSTANCE_UPDATE, this.zoneInstance.instanceData); - } else { - this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_GROUP_INSTANCE_UPDATE, this.zoneInstance.instanceData); - } - this.assignmentSaveComplete.emit(true); - if(afterSaveCallback) afterSaveCallback(); - }, (error) => { - this.zoneInstance.assignments = oldAssignments; - this.assignmentSaveComplete.emit(false); - }); - } else { - if(afterSaveCallback) afterSaveCallback(); - } - this.modeChange.emit({newMode: ZoneInstanceMode.NONE, instance: this.zoneInstance}); - - } else { - this.modeChange.emit({newMode: mode, instance: this.zoneInstance}); - } - - - } - - private tagHandleClicked = (event:Event) => { - this.tagHandleClick.emit(this.zoneInstance); - event.stopPropagation(); - }; - -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/download-artifact/download-artifact.component.ts b/catalog-ui/src/app/ng2/components/ui/download-artifact/download-artifact.component.ts new file mode 100644 index 0000000000..8f47456a8f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/download-artifact/download-artifact.component.ts @@ -0,0 +1,145 @@ +import { Component, Input } from "@angular/core"; +import {IFileDownload, Component as TopologyTemplate, ArtifactModel, FullComponentInstance} from "app/models"; +import {EventListenerService} from "app/services"; +import {CacheService} from "app/services-ng2"; +import {EVENTS} from "app/utils"; +import { TopologyTemplateService } from "app/ng2/services/component-services/topology-template.service"; +import { WorkspaceService } from "app/ng2/pages/workspace/workspace.service"; +import { ComponentInstanceServiceNg2 } from "app/ng2/services/component-instance-services/component-instance.service"; + +@Component({ + selector: 'download-artifact', + template: ` + <svg-icon [mode]="'primary2'" [disabled]="disabled" [clickable]="!disabled" [name]="iconType" [testId]="testId" mode="info" clickable="true" size="medium" (click)="download($event)"></svg-icon> +` +}) +export class DownloadArtifactComponent { + + @Input() showLoader:boolean; + @Input() artifact:ArtifactModel; + @Input() isInstance: boolean; + @Input() downloadIconClass: string; + @Input() componentType: string; + @Input() componentId: string; + @Input() testId: string; + @Input() disabled: boolean; + + public iconType:string; + + private DOWNLOAD_CSS_CLASSES = { + DOWNLOAD_ICON: "download-o", + LOADER_ICON: "spinner" + } + constructor(private cacheService:CacheService, private EventListenerService:EventListenerService, private topologyTemplateService:TopologyTemplateService, + private componentInstanceService: ComponentInstanceServiceNg2, private workspaceService:WorkspaceService) { + + } + + ngOnInit () { + this.iconType = this.DOWNLOAD_CSS_CLASSES.DOWNLOAD_ICON; + this.initDownloadLoader(); + + } + + private initDownloadLoader = ()=> { + //if the artifact is in a middle of download progress register form callBack & change icon from download to loader + if (this.showLoader && this.cacheService.get(this.artifact.uniqueId)) { + this.EventListenerService.registerObserverCallback(EVENTS.DOWNLOAD_ARTIFACT_FINISH_EVENT + this.artifact.uniqueId, this.updateDownloadIcon); + window.setTimeout(():void => { + if (this.cacheService.get(this.artifact.uniqueId)) { + this.iconType = this.DOWNLOAD_CSS_CLASSES.LOADER_ICON; + } + }, 1000); + } + }; + + private updateDownloadIcon = () => { + this.iconType = this.downloadIconClass || this.DOWNLOAD_CSS_CLASSES.DOWNLOAD_ICON; + }; + + public download = (event) => { + event.stopPropagation(); + let onFaild = (response):void => { + console.info('onFaild', response); + this.removeDownloadedFileLoader(); + }; + + let onSuccess = (data:IFileDownload):void => { + this.downloadFile(data); + this.removeDownloadedFileLoader(); + }; + + this.setDownloadedFileLoader(); + + if (this.isInstance) { + this.componentInstanceService.downloadInstanceArtifact(this.workspaceService.metadata.componentType, this.workspaceService.metadata.uniqueId, this.componentId, this.artifact.uniqueId).subscribe(onSuccess, onFaild); + } else { + this.topologyTemplateService.downloadArtifact(this.componentType, this.componentId, this.artifact.uniqueId).subscribe(onSuccess, onFaild); + } + }; + + private setDownloadedFileLoader = ()=> { + if (this.showLoader) { + //set in cache service thet the artifact is in download progress + this.cacheService.set(this.artifact.uniqueId, true); + this.initDownloadLoader(); + } + }; + + private removeDownloadedFileLoader = ()=> { + if (this.showLoader) { + this.cacheService.set(this.artifact.uniqueId, false); + this.EventListenerService.notifyObservers(EVENTS.DOWNLOAD_ARTIFACT_FINISH_EVENT + this.artifact.uniqueId); + } + }; + + private downloadFile = (file:IFileDownload):void => { + if (file) { + let blob = this.base64toBlob(file.base64Contents, ''); + let fileName = file.artifactName; + this.triggerFileDownload(blob, fileName); + } + }; + + public base64toBlob = (base64Data, contentType):any => { + let byteCharacters = atob(base64Data); + return this.byteCharactersToBlob(byteCharacters, contentType); + }; + + public byteCharactersToBlob = (byteCharacters, contentType):any => { + contentType = contentType || ''; + let sliceSize = 1024; + let bytesLength = byteCharacters.length; + let slicesCount = Math.ceil(bytesLength / sliceSize); + let byteArrays = new Array(slicesCount); + + for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) { + let begin = sliceIndex * sliceSize; + let end = Math.min(begin + sliceSize, bytesLength); + + let bytes = new Array(end - begin); + for (let offset = begin, i = 0; offset < end; ++i, ++offset) { + bytes[i] = byteCharacters[offset].charCodeAt(0); + } + byteArrays[sliceIndex] = new Uint8Array(bytes); + } + return new Blob(byteArrays, {type: contentType}); + }; + + public triggerFileDownload = (blob, fileName):void=> { + let url = window.URL.createObjectURL(blob); + let downloadLink = document.createElement("a"); + + downloadLink.setAttribute('href', url); + downloadLink.setAttribute('download', fileName); + document.body.appendChild(downloadLink); + + var clickEvent = new MouseEvent("click", { + "view": window, + "bubbles": true, + "cancelable": true + }); + downloadLink.dispatchEvent(clickEvent); + + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts index 049d40831a..5e3214d888 100644 --- a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts @@ -37,11 +37,13 @@ enum DynamicElementComponentCreatorIdentifier { BOOLEAN, SUBNETPOOLID, ENUM, + LIST, DEFAULT } @Component({ selector: 'dynamic-element', + // Span - if constraints not empty template: `<div #target></div>`, styleUrls: ['./dynamic-element.component.less'], entryComponents: [ @@ -61,6 +63,7 @@ export class DynamicElementComponent { @Input() readonly:boolean; @Input() constraints: Array<any>; @Input() path:string;//optional param. used only for for subnetpoolid type + @Input() declared:boolean; @Input() value: any; @Output() valueChange: EventEmitter<any> = new EventEmitter<any>(); @@ -72,16 +75,19 @@ export class DynamicElementComponent { validation = ValidationConfiguration.validation; constructor( + private componentFactoryResolver: ComponentFactoryResolver, private compiler: Compiler, private el: ElementRef) { + + } updateComponent() { if (!this.isViewInitialized) { return; } - + // Factory to create component based on type or other property attributes. const prevElementCreatorIdentifier: DynamicElementComponentCreatorIdentifier = this.elementCreatorIdentifier; switch(true) { @@ -112,7 +118,7 @@ export class DynamicElementComponent { } // In case the dynamic element creator is changed, then destroy old and build new. - if (this.elementCreatorIdentifier !== prevElementCreatorIdentifier) { + if (this.declared || this.elementCreatorIdentifier !== prevElementCreatorIdentifier) { if (this.cmpRef) { this.cmpRef.destroy(); } @@ -149,64 +155,81 @@ export class DynamicElementComponent { } createComponentByIdentifier() { - switch(this.elementCreatorIdentifier) { - case DynamicElementComponentCreatorIdentifier.SUBNETPOOLID: - if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name - let pathArray = this.path.split("#"); - this.name = pathArray[pathArray.length - 2]; - } - this.createComponent(UiElementPopoverInputComponent); - break; + // if(!this.constraints || this.declared){ + switch(this.elementCreatorIdentifier) { + case DynamicElementComponentCreatorIdentifier.SUBNETPOOLID: + if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name + let pathArray = this.path.split("#"); + this.name = pathArray[pathArray.length - 2]; + } + this.createComponent(UiElementPopoverInputComponent); + break; + case DynamicElementComponentCreatorIdentifier.ENUM: + this.createComponent(UiElementDropDownComponent); + let validVals:Array<DropdownValue> = [...this.getValidValues()].map(val => new DropdownValue(val, val)); + if (this.type === 'float' || this.type === 'integer') { + this.value = this.value && Number(this.value); + validVals = _.map( + validVals, + (val) => new DropdownValue(Number(val.value), val.value) + ); + } + this.cmpRef.instance.values = validVals; + break; + case DynamicElementComponentCreatorIdentifier.INTEGER: + this.createComponent(UiElementIntegerInputComponent); + this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; + break; - case DynamicElementComponentCreatorIdentifier.ENUM: - this.createComponent(UiElementDropDownComponent); - let validVals:Array<DropdownValue> = [...this.getValidValues()].map(val => new DropdownValue(val, val)); - if (this.type === 'float' || this.type === 'integer') { - this.value = this.value && Number(this.value); - validVals = _.map( - validVals, - val => new DropdownValue(Number(val.value), val.value) - ); - } - this.cmpRef.instance.values = validVals; - break; + case DynamicElementComponentCreatorIdentifier.FLOAT: + this.createComponent(UiElementIntegerInputComponent); + this.cmpRef.instance.pattern = /^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/.source; + break; - case DynamicElementComponentCreatorIdentifier.INTEGER: - this.createComponent(UiElementIntegerInputComponent); - this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; - break; + case DynamicElementComponentCreatorIdentifier.STRING: + this.createComponent(UiElementInputComponent); + break; - case DynamicElementComponentCreatorIdentifier.FLOAT: - this.createComponent(UiElementIntegerInputComponent); - this.cmpRef.instance.pattern = /^[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/.source; - break; + case DynamicElementComponentCreatorIdentifier.BOOLEAN: + this.createComponent(UiElementDropDownComponent); - case DynamicElementComponentCreatorIdentifier.STRING: - this.createComponent(UiElementInputComponent); - break; - - case DynamicElementComponentCreatorIdentifier.BOOLEAN: - this.createComponent(UiElementDropDownComponent); - - // Build drop down values - let tmp = []; - tmp.push(new DropdownValue(true,'TRUE')); - tmp.push(new DropdownValue(false,'FALSE')); - this.cmpRef.instance.values = tmp; - try { - if (typeof this.value === 'string') { - this.value = JSON.parse(this.value); + // Build drop down values + let tmp = []; + tmp.push(new DropdownValue(true,'TRUE')); + tmp.push(new DropdownValue(false,'FALSE')); + this.cmpRef.instance.values = tmp; + try { + if(typeof this.value === 'string'){ + this.value = JSON.parse(this.value); + } + } catch (err) { + this.value = null; } - } catch(err) { - this.value = null; - } - break; + break; - case DynamicElementComponentCreatorIdentifier.DEFAULT: - default: - this.createComponent(UiElementInputComponent); - console.log("ERROR: No ui-models component to handle type: " + this.type); - } + case DynamicElementComponentCreatorIdentifier.DEFAULT: + default: + this.createComponent(UiElementInputComponent); + console.log("ERROR: No ui-models component to handle type: " + this.type); + } + // } + // //There are consraints + // else { + + // this.createComponent(UiElementDropDownComponent); + + // // Build drop down values + // let items = []; + // this.constraints.forEach( (element) => { + // items.push(new DropdownValue(element,element)); + // }); + + // items.push(new DropdownValue(this.value,this.value, true, true)); + // this.cmpRef.instance.values = items; + + + + // } // Subscribe to change event of of ui-models-element-basic and fire event to change the value this.cmpRef.instance.baseEmitter.subscribe((event) => { this.emitter.emit(event); }); diff --git a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts index 50b22505a9..dc12551e8f 100644 --- a/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts @@ -23,6 +23,12 @@ import {PopoverModule} from "../popover/popover.module"; import {TooltipModule} from "../tooltip/tooltip.module"; import {DynamicElementComponent} from "./dynamic-element.component"; import {FormElementsModule} from "../form-components/form-elements.module"; +// import {SdcUiComponentsModule} from "sdc-ui/lib/angular"; +// import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index"; +// import {SdcUiComponentsModule} from "onap-ui/lib/angular"; +import { SdcUiComponentsModule } from "onap-ui-angular"; + +import { CommonModule } from '@angular/common'; @NgModule({ declarations: [ @@ -31,7 +37,9 @@ import {FormElementsModule} from "../form-components/form-elements.module"; imports: [ PopoverModule, TooltipModule, - FormElementsModule + FormElementsModule, + SdcUiComponentsModule, + CommonModule ], exports: [ DynamicElementComponent diff --git a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html index fde7bca6d2..9b678b2790 100644 --- a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html +++ b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.html @@ -14,16 +14,15 @@ ~ limitations under the License. --> -<h1 class="w-sdc-designer-sidebar-section-title" - tooltip="{{titleTooltip}}" - [ngClass]="{'expanded': state == 0, 'collapsed': state == 1}" - (click)="toggleState()"> - {{caption}}<span class="w-sdc-designer-sidebar-section-title-icon"></span> - <ng-content select="header"></ng-content> - <span class="w-sdc-designer-sidebar-section-title-icon"></span> -</h1> +<div class="expand-collapse-container"> + <h1 class="expand-collapse-title" [ngClass]="{'expanded': state == 0, 'collapsed': state == 1}" + tooltip="{{titleTooltip}}" (click)="toggleState()">{{caption}} + <ng-content select="header"></ng-content> + <svg-icon name="caret1-down-o" mode="info" size="small" class="expand-collapse-title-icon"></svg-icon> + </h1> -<div class="expand-collapse-content" [ngClass]="{'visible': state === 0, 'hidden': state === 1}"> - <ng-content></ng-content> - <ng-content select="content"></ng-content> -</div> + <div class="expand-collapse-content" [ngClass]="{'expanded': state === 0, 'collapsed': state === 1}"> + <ng-content></ng-content> + <ng-content select="content"></ng-content> + </div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less index e5dd2527c1..deda687a09 100644 --- a/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less +++ b/catalog-ui/src/app/ng2/components/ui/expand-collapse/expand-collapse.component.less @@ -5,3 +5,51 @@ text-decoration: underline; text-align: left; } + + +.expand-collapse-title { + display:flex; + align-items: center; + cursor: pointer; + font-size: 14px; + text-transform: uppercase; + line-height: 32px; + padding: 0 10px 0 20px; + + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + + header { + flex: 1; + } + + .expand-collapse-title-icon { + padding-top: 10px; + padding-left: 2px; + transition: transform .3s ease-out; + + } + + &.expanded .expand-collapse-title-icon { + transform: rotate(0); + } + + &.collapsed .expand-collapse-title-icon { + transform: rotate(-180deg); + } + +} + +.expand-collapse-content { + overflow: hidden; + transition: max-height .3s ease-in; + + &.collapsed { + max-height: 0px; + overflow:hidden; + transition: all .3s cubic-bezier(0, 1, 0, 1); + + } + +} diff --git a/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.html b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.html new file mode 100644 index 0000000000..14fc6eefc7 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.html @@ -0,0 +1,6 @@ +<label> + <input type="file" class="i-sdc-dashboard-item-upload-input" + (change)="onFileSelect($event)" + [accept]="extensionsWithDot" + [attr.data-tests-id]="'file-' + testsId" /> +</label> diff --git a/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.less b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.less new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.less diff --git a/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.ts b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.ts new file mode 100644 index 0000000000..1d1d4cef0d --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/file-opener/file-opener.component.ts @@ -0,0 +1,45 @@ +import {Component, Input, Output, EventEmitter, SimpleChanges} from "@angular/core"; + +@Component({ + selector: 'file-opener', + templateUrl: './file-opener.component.html', + styleUrls: ['./file-opener.component.less'] +}) +export class FileOpenerComponent { + @Input() public testsId: string; + @Input() public extensions: string; + @Output() public onFileUpload: EventEmitter<any>; + + public extensionsWithDot: string; + + constructor() { + this.onFileUpload = new EventEmitter<any>(); + } + + public ngOnChanges(changes:SimpleChanges) { + if (changes.extensions) { + this.extensionsWithDot = this.getExtensionsWithDot(changes.extensions.currentValue); + } + } + + public onFileSelect(event) { + const importFile:any = event.target.files[0]; + const reader = new FileReader(); + reader.readAsBinaryString(importFile); + reader.onload = () => { + this.onFileUpload.emit({ + filename: importFile.name, + filetype: importFile.type, + filesize: importFile.size, + base64: btoa(reader.result) + }); + }; + } + + public getExtensionsWithDot(extensions:string):string { + extensions = extensions || this.extensions || ''; + return extensions.split(',') + .map(ext => '.' + ext.toString()) + .join(','); + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts index c8da016174..c7b0af6ecf 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts @@ -19,7 +19,7 @@ */ import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; -//import { trigger, state, style, transition, animate, keyframes } from '@angular/core'; +//import { trigger, state, style, transition, animate, keyframes } from '@angular/animations'; @Component({ selector: 'checkbox', diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html index 45fd77ee61..9dca01eb61 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html @@ -15,5 +15,5 @@ --> <select name='{{name}}' [(ngModel)]="value" (change)="onChange()" [ngClass]="{'disabled':readonly}" [attr.data-tests-id]="'value-' + testId"> - <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue">{{ddvalue.label||ddvalue}}</option> + <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue" [hidden]="ddvalue.hidden" [selected] = "ddvalue.selected">{{ddvalue.label||ddvalue}}</option> </select> diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts index 03a1fc6040..6db233529b 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts @@ -24,11 +24,21 @@ import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.comp export class DropdownValue { value:any; label:string; + hidden?: boolean; + selected?: boolean; - constructor(value:any,label:string) { + + constructor(value:any,label:string, hidden: boolean = false, selected: boolean = false) { this.value = value; this.label = label; + this.hidden = hidden; + this.selected = selected; + + // this.hidden = hidden ? true : "hidden": ""; + // this.selected = selected ? true : "selected": ""; } + + } @Component({ @@ -37,8 +47,8 @@ export class DropdownValue { styleUrls: ['./ui-element-dropdown.component.less'], }) export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface { - @Input() - values: DropdownValue[]|string[]; + + @Input() values: DropdownValue[]; constructor() { super(); diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts index e5bdf1f557..b35d3ae3f4 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts @@ -1,19 +1,19 @@ /** * Created by rc2122 on 9/5/2017. */ -import {NgModule} from "@angular/core"; -import {BrowserModule} from "@angular/platform-browser"; -import {FormsModule, ReactiveFormsModule} from "@angular/forms"; -import {UiElementPopoverInputComponent} from "./popover-input/ui-element-popover-input.component"; -import {UiElementIntegerInputComponent} from "./integer-input/ui-element-integer-input.component"; -import {UiElementInputComponent} from "./input/ui-element-input.component"; -import {UiElementDropDownComponent} from "./dropdown/ui-element-dropdown.component"; -import {UiElementBase} from "./ui-element-base.component"; -import {CheckboxModule} from "./checkbox/checkbox.module"; -import {RadioButtonComponent} from "./radio-buttons/radio-buttons.component"; -import {PopoverModule} from "../popover/popover.module"; -import {TooltipModule} from "../tooltip/tooltip.module"; - +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { BrowserModule } from '@angular/platform-browser'; +import { SdcUiComponentsModule } from 'onap-ui-angular/dist'; +import { PopoverModule } from '../popover/popover.module'; +import { TooltipModule } from '../tooltip/tooltip.module'; +import { CheckboxModule } from './checkbox/checkbox.module'; +import { UiElementDropDownComponent } from './dropdown/ui-element-dropdown.component'; +import { UiElementInputComponent } from './input/ui-element-input.component'; +import { UiElementIntegerInputComponent } from './integer-input/ui-element-integer-input.component'; +import { UiElementPopoverInputComponent } from './popover-input/ui-element-popover-input.component'; +import { RadioButtonComponent } from './radio-buttons/radio-buttons.component'; +import { UiElementBase } from './ui-element-base.component'; @NgModule({ imports: [ @@ -22,7 +22,8 @@ import {TooltipModule} from "../tooltip/tooltip.module"; PopoverModule, ReactiveFormsModule, TooltipModule, - CheckboxModule], + CheckboxModule, + SdcUiComponentsModule], declarations: [UiElementDropDownComponent, UiElementInputComponent, @@ -39,4 +40,4 @@ import {TooltipModule} from "../tooltip/tooltip.module"; TooltipModule, CheckboxModule] }) -export class FormElementsModule { }
\ No newline at end of file +export class FormElementsModule { } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html index 85089f12b8..f9cf17f087 100644 --- a/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html @@ -13,19 +13,18 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - -<input - class="value-input" - [ngClass]="{'error': control.invalid, 'disabled':readonly}" - type="text" - [name]="name" - [(ngModel)]="value" - (input)="onChange()" - [attr.maxlength]="validation.propertyValue.max" - [attr.minlength]="validation.propertyValue.min" - [pattern]="pattern" - [formControl]="control" - tooltip="{{value}}" - [readonly]="readonly" - [attr.data-tests-id]="'value-' + testId" - /> +<div sdc-tooltip [tooltip-text]="value"> + <input + class="value-input" + [ngClass]="{'error': control.invalid, 'disabled':readonly}" + type="text" + [name]="name" + [(ngModel)]="value" + (input)="onChange()" + [attr.maxlength]="validation.propertyValue.max" + [attr.minlength]="validation.propertyValue.min" + [pattern]="pattern" + [formControl]="control" + [attr.data-tests-id]="'value-' + testId" + /> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts b/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts index 34404e50a5..b401778bc2 100644 --- a/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/forms/modal-forms.module.ts @@ -1,15 +1,11 @@ import { NgModule } from "@angular/core"; import { CommonModule } from '@angular/common'; -import { SdcUiComponentsModule } from "sdc-ui/lib/angular"; -import { ValueEditComponent } from './value-edit/value-edit.component'; +import { SdcUiComponentsModule } from "onap-ui-angular"; import { UnsavedChangesComponent } from "./unsaved-changes/unsaved-changes.component"; import { UiElementsModule } from "../ui-elements.module"; - - @NgModule({ declarations: [ - ValueEditComponent, UnsavedChangesComponent ], imports: [ @@ -17,7 +13,7 @@ import { UiElementsModule } from "../ui-elements.module"; SdcUiComponentsModule, UiElementsModule ], - exports: [ValueEditComponent, UnsavedChangesComponent], + exports: [UnsavedChangesComponent], entryComponents: [ UnsavedChangesComponent ], providers: [] diff --git a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.html b/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.html deleted file mode 100644 index 75ee2d520f..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.html +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - ~ 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. - --> - -<div class="name-update-container"> - <sdc-input #updateNameInput - label="Instance Name" - required="true" - [maxLength]="50" - [(value)]="name" - testId="instanceName"></sdc-input> - <sdc-validation [validateElement]="updateNameInput" (validityChanged)="validityChanged($event)"> - <sdc-required-validator message="Name is required."></sdc-required-validator> - <sdc-regex-validator message="Special characters not allowed." [pattern]="pattern"></sdc-regex-validator> - </sdc-validation> -</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.less b/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.less deleted file mode 100644 index b958ca17b7..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.less +++ /dev/null @@ -1,3 +0,0 @@ -.name-update-container { - min-height: 90px; -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.ts b/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.ts deleted file mode 100644 index 08bc0586c7..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/forms/value-edit/value-edit.component.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Component, Input } from "@angular/core"; - -@Component({ - selector: 'value-edit', - templateUrl: './value-edit.component.html', - styleUrls: ['./value-edit.component.less'] -}) -export class ValueEditComponent { - - @Input() name:String; - @Input() validityChangedCallback: Function; - - private pattern:string = "^[\\s\\w\&_.:-]{1,1024}$" - constructor(){ - } - - private validityChanged = (value):void => { - if(this.validityChangedCallback) { - this.validityChangedCallback(value); - } - } - - - -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html index bfb9e1b1ae..00083050d8 100644 --- a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html @@ -14,7 +14,7 @@ ~ limitations under the License. --> -<div *ngIf="isVisible" data-tests-id="tlv-loader" [ngClass]="relative ? 'loader-relative' : 'loader-fixed'" +<div *ngIf="isVisible" data-tests-id="loader" [ngClass]="relative ? 'loader-relative' : 'loader-fixed'" [style.top]="offset.top" [style.left]="offset.left" [style.width]="offset.width" [style.height]="offset.height"> <div class="tlv-loader-back" [ngClass]="{'tlv-loader-relative':relative}"></div> <div class="tlv-loader {{size}}"></div> diff --git a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts index 585c36660e..9658e6b65c 100644 --- a/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts @@ -79,6 +79,13 @@ export class LoaderComponent { width: (parentElement.offsetWidth !== undefined) ? parentElement.offsetWidth + "px" : undefined, height: (parentElement.offsetHeight !== undefined) ? parentElement.offsetHeight + "px" : undefined }; + } else { + this.offset = { + left: '0px', + top: '0px', + width: '100%', + height: '100%' + } } this.isVisible = true; } diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts index 3820573e58..8b2006634e 100644 --- a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts @@ -1,5 +1,9 @@ /*- + * ============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 @@ -11,9 +15,9 @@ * 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 { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts index 939599f0bc..290c8d06af 100644 --- a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts @@ -1,5 +1,9 @@ /*- + * ============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 @@ -11,9 +15,9 @@ * 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 { Component, Input, ContentChildren, SimpleChanges, QueryList } from '@angular/core'; import { MenuItemComponent } from "./menu-item.component"; import { Point } from "app/models"; diff --git a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts index 1d05b27d68..ab367529d8 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.component.ts @@ -1,9 +1,9 @@ /** * Created by ob0695 on 11.04.2018. */ -import {Component, Input} from "@angular/core"; -import {UiBaseObject} from "../../../../../models/ui-models/ui-base-object"; -import {IDropDownOption} from "sdc-ui/lib/angular/form-elements/dropdown/dropdown-models"; +import { Component, Input } from "@angular/core"; +import { UiBaseObject } from "../../../../../models/ui-models/ui-base-object"; +import { IDropDownOption } from "onap-ui-angular/dist/form-elements/dropdown/dropdown-models"; @Component({ selector: 'add-elements', diff --git a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts index a1c34f5686..70ad0a389c 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/add-elements/add-elements.module.ts @@ -1,14 +1,11 @@ /** * Created by ob0695 on 11.04.2018. */ -import {NgModule} from "@angular/core"; -import {SdcUiComponentsModule} from "sdc-ui/lib/angular/index"; -import {AddElementsComponent} from "./add-elements.component"; -import {CommonModule} from "@angular/common"; +import { NgModule } from "@angular/core"; +import { SdcUiComponentsModule } from "onap-ui-angular"; +import { AddElementsComponent } from "./add-elements.component"; +import { CommonModule } from "@angular/common"; -/** - * Created by ob0695 on 9.04.2018. - */ @NgModule({ declarations: [ AddElementsComponent diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts index 777e9bdc06..2432c3bb37 100644 --- a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts @@ -36,7 +36,7 @@ export class ModalComponent implements OnInit, OnDestroy { @Input() isMovable: boolean; @Input() input: ModalModel; @Input() dynamicContent: any; - @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; //Allows for custom component as body instead of simple message. See ModalService.createActionModal for implementation details, and HttpService's catchError() for example. + @ViewChild('dynamicContentContainer', { read: ViewContainerRef }) dynamicContentContainer: ViewContainerRef; //Allows for custom component as body instead of simple message. See ModalService.createActionModal for implementation details, and HttpHelperService's catchError() for example. private modalElement: JQuery; constructor( el: ElementRef ) { diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts index 9219a30738..1986e34914 100644 --- a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts @@ -20,10 +20,8 @@ * limitations under the License. * ============LICENSE_END========================================================= */ -import { - Component, ElementRef, forwardRef, Inject, Input, trigger, state, style, - transition, animate, ViewChild, ViewContainerRef, ComponentRef -} from "@angular/core"; +import { Component, ElementRef, forwardRef, Inject, Input, ViewChild, ViewContainerRef, ComponentRef} from "@angular/core"; +import {trigger, state, style, transition, animate} from '@angular/animations'; import {StepModel} from "app/models"; import {ModalService} from "../../../services/modal.service"; import {ModalComponent} from "../modal/modal.component"; diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts index 3db217d282..81a90b8a9b 100644 --- a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts @@ -4,7 +4,7 @@ import { NgModule } from "@angular/core"; import {MultiStepsWizardComponent} from "./multi-steps-wizard.component"; import {CommonModule} from "@angular/common"; -import {ConnectionWizardModule} from "../../../pages/connection-wizard/connection-wizard.module"; +import {ConnectionWizardModule} from "app/ng2/pages/composition/graph/connection-wizard/connection-wizard.module"; @NgModule({ declarations: [ diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html deleted file mode 100644 index efd619687c..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.html +++ /dev/null @@ -1,20 +0,0 @@ -<!-- - ~ 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. - --> - -<div class="palette-animation-wrapper" [style.top]="from.y + 50 + 'px'" [style.left]="from.x + 'px'" [style.transform]="transformStyle" [class.hidden]="!visible" - (transitionend)="animationComplete()"> -<div class="medium small sprite-resource-icons sprite-{{iconName}}-icons {{iconName}}" ></div> -</div> diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less deleted file mode 100644 index 54f04189c0..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.less +++ /dev/null @@ -1,5 +0,0 @@ -.palette-animation-wrapper{ - position: absolute; - z-index: 100; - transition: all 2s ease-in-out; -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts deleted file mode 100644 index 7e45b9e55b..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.component.ts +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * ============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 {Component, Input } from '@angular/core'; -import {BrowserModule} from '@angular/platform-browser'; -import { setTimeout } from 'core-js/library/web/timers'; -import { EventListenerService } from 'app/services'; -import { GRAPH_EVENTS } from 'app/utils'; -import { Point } from 'app/models'; -import { ZoneInstanceType, ZoneInstance } from '../../../../models/graph/zones/zone-instance'; - - - -@Component({ - selector: 'palette-animation', - templateUrl: './palette-animation.component.html', - styleUrls:['./palette-animation.component.less'], -}) - -export class PaletteAnimationComponent { - - @Input() from : Point; - @Input() to : Point; - @Input() type: ZoneInstanceType; - @Input() iconName : string; - @Input() zoneInstance : ZoneInstance; - - public animation; - private visible:boolean = false; - private transformStyle:string = ""; - - - constructor(private eventListenerService:EventListenerService) {} - - - ngOnDestroy(){ - this.zoneInstance.hidden = false; //if animation component is destroyed before animation is complete - } - - public runAnimation() { - this.visible = true; - let positionDiff:Point = new Point(this.to.x - this.from.x, this.to.y - this.from.y); - setTimeout(()=>{ - this.transformStyle = 'translate('+ positionDiff.x + 'px,' + positionDiff.y +'px)'; - }, 0); - }; - - public animationComplete = (e) => { - this.visible = false; - this.zoneInstance.hidden = false; - }; - - -} diff --git a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts b/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts deleted file mode 100644 index 8674571138..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-animation/palette-animation.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule } from "@angular/core"; -import { CommonModule } from "@angular/common"; -import { PaletteAnimationComponent } from "./palette-animation.component"; - - -@NgModule({ - declarations: [ - PaletteAnimationComponent - ], - imports: [ CommonModule ], - exports: [ PaletteAnimationComponent ] -}) - -export class PaletteAnimationModule { - -}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html deleted file mode 100644 index 11261e95b4..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.html +++ /dev/null @@ -1,25 +0,0 @@ -<!-- - ~ 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. - --> - -<div class="popup-panel" [ngClass]="{'hide':!isShowPanel}" [style.left]="popupPanelPosition.x + 'px'" [style.top]="popupPanelPosition.y + 'px'" - (mousedown)="addZoneInstance()" - (mouseenter)="onMouseEnter()" - (mouseleave)="onMouseLeave()"> - <div class="popup-panel-group"> - <div class="popup-panel-plus">+</div> - <div class="popup-panel-title">{{panelTitle}}</div> - </div> -</div> diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less deleted file mode 100644 index 24f0485e76..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.less +++ /dev/null @@ -1,37 +0,0 @@ -.popup-panel { - position: absolute; - display: inline-block; - background-color: white; - border: solid 1px #d2d2d2; - border-top: solid 3px #13a7df; - left: 208px; top: 0px; - width: 140px; - height: 40px; - z-index: 10000; - - &:hover { - background-color: whitesmoke; - } - - .popup-panel-group { - padding-left: 8px; - padding-top: 8px; - cursor: pointer; - - .popup-panel-plus { - border-radius: 50%; - color: white; - background-color: #13a7df; - width: 20px; - text-align: center; - display: inline-block; - } - - .popup-panel-title { - padding-left: 10px; - display: inline-block; - } - - } - -} diff --git a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts b/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts deleted file mode 100644 index a10ca7dc81..0000000000 --- a/catalog-ui/src/app/ng2/components/ui/palette-popup-panel/palette-popup-panel.component.ts +++ /dev/null @@ -1,88 +0,0 @@ -import {Component, OnInit} from '@angular/core'; -import {GRAPH_EVENTS} from "app/utils"; -import {LeftPaletteComponent, Point} from "app/models"; -import {EventListenerService} from "app/services"; -import {LeftPaletteMetadataTypes} from "../../../../models/components/displayComponent"; - -@Component({ - selector: 'app-palette-popup-panel', - templateUrl: './palette-popup-panel.component.html', - styleUrls: [ './palette-popup-panel.component.less' ], -}) -export class PalettePopupPanelComponent implements OnInit { - - public panelTitle: string; - public isShowPanel: boolean; - private component: Component; - private displayComponent: LeftPaletteComponent; - private popupPanelPosition:Point = new Point(0,0); - - constructor(private eventListenerService: EventListenerService) { - this.isShowPanel = false; - } - - ngOnInit() { - this.registerObserverCallbacks(); - } - - public onMouseEnter() { - this.isShowPanel = true; - } - - public onMouseLeave() { - this.isShowPanel = false; - } - - public addZoneInstance(): void { - if(this.displayComponent) { - this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_ADD_ZONE_INSTANCE_FROM_PALETTE, this.component, this.displayComponent, this.popupPanelPosition); - this.hidePopupPanel(); - } - } - - private registerObserverCallbacks() { - - this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_SHOW_POPUP_PANEL, - (component: Component, displayComponent: LeftPaletteComponent, sectionElem: HTMLElement) => { - - this.component = component; - this.showPopupPanel(displayComponent, sectionElem); - }); - - this.eventListenerService.registerObserverCallback(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HIDE_POPUP_PANEL, () => this.hidePopupPanel()); - } - - private getPopupPanelPosition (sectionElem: HTMLElement):Point { - let pos: ClientRect = sectionElem.getBoundingClientRect(); - let offsetX: number = -30; - const offsetY: number = pos.height / 2; - return new Point((pos.right + offsetX), (pos.top - offsetY + window.pageYOffset)); - }; - - private setPopupPanelTitle(component: LeftPaletteComponent): void { - if (component.categoryType === LeftPaletteMetadataTypes.Group) { - this.panelTitle = "Add Group"; - return; - } - - if (component.categoryType === LeftPaletteMetadataTypes.Policy) { - this.panelTitle = "Add Policy"; - return; - } - } - - private showPopupPanel(displayComponent:LeftPaletteComponent, sectionElem: HTMLElement) { - if(!this.isShowPanel){ - this.displayComponent = displayComponent; - this.setPopupPanelTitle(displayComponent); - this.popupPanelPosition = this.getPopupPanelPosition(sectionElem); - this.isShowPanel = true; - } - }; - - private hidePopupPanel() { - if(this.isShowPanel){ - this.isShowPanel = false; - } - }; -} diff --git a/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.html b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.html new file mode 100644 index 0000000000..277702e336 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.html @@ -0,0 +1,11 @@ +<div class="w-sdc-designer-sidebar-toggle" [class.active]="(withSidebar$ | async)" (click)="toggleSidebarDisplay()"> + <div class="w-sdc-designer-sidebar-toggle-icon sprite-new pointer menu-open-left"></div> +</div> + +<div class="w-sdc-designer-sidebar"> + <ng-content></ng-content> +</div> + + + + diff --git a/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.less b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.less new file mode 100644 index 0000000000..cacb85d6b1 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.less @@ -0,0 +1,55 @@ +@import '../../../../../assets/styles/variables'; + +.w-sdc-designer-sidebar { + background-color:@main_color_p ; + font-family: @font-opensans-regular; + font-size: 13px; + color: #191919; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + bottom: 0; + position: fixed; + right: -302px; + width: 302px; + top: 103px; + transition: right 0.2s; + z-index: 1010; + box-shadow: -7px -3px 6px -8px @main_color_n; +} + +.w-sdc-designer-sidebar-toggle { + background-color: @main_color_p; + border-left: 1px solid @main_color_o; + border-bottom: 1px solid @main_color_o; + height: 21px; + position: absolute; + right: 0; + top: 53px; + width: 17px; + transition: right 0.2s; + z-index: 1005; + box-shadow: -1px 1px 3px 0 @main_color_n; + cursor: pointer; + + &.active { + right: 302px; + .w-sdc-designer-sidebar-toggle-icon{ + transform: rotate(180deg); + } + } +} + +.w-sdc-designer-sidebar-toggle-icon { + margin-left: 6px; + margin-top: 6px; +} + +.w-sdc-designer-sidebar-toggle.active + .w-sdc-designer-sidebar { + right: 0; + display: flex; + flex-direction: column; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.ts b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.ts new file mode 100644 index 0000000000..e9c4a7d354 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/panel-wrapper/panel-wrapper.component.ts @@ -0,0 +1,25 @@ +import {Component} from "@angular/core"; +import {Select, Store} from "@ngxs/store"; +import {Subscription} from "rxjs/Subscription"; +import {GraphState} from "../../../pages/composition/common/store/graph.state"; +import {OnSidebarOpenOrCloseAction} from "../../../pages/composition/common/store/graph.actions"; + +@Component({ + selector: 'panel-wrapper-component', + templateUrl: './panel-wrapper.component.html', + styleUrls: ['./panel-wrapper.component.less'] +}) +export class PanelWrapperComponent { + @Select(GraphState.withSidebar) withSidebar$: boolean; + + tabs: Array<any>; + subscription: Subscription; + + constructor(public store: Store) { + } + + private toggleSidebarDisplay = () => { + // this.withSidebar = !this.withSidebar; + this.store.dispatch(new OnSidebarOpenOrCloseAction()); + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/perfect-scroll-bar/perfect-scrollbar.directive.ts b/catalog-ui/src/app/ng2/components/ui/perfect-scroll-bar/perfect-scrollbar.directive.ts new file mode 100644 index 0000000000..ccc1e2181e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/perfect-scroll-bar/perfect-scrollbar.directive.ts @@ -0,0 +1,51 @@ +import {Directive, Input, ElementRef} from '@angular/core'; +import * as PerfectScrollbar from 'perfect-scrollbar'; + +interface IPerfectScrollbarOptions { + wheelSpeed?: number; + wheelPropagation?: boolean; + minScrollbarLength?: number; + useBothWheelAxes?: boolean; + useKeyboard?: boolean; + suppressScrollX?: boolean; + suppressScrollY?: boolean; + scrollXMarginOffset?: number; + scrollYMarginOffset?: number; + includePadding?: boolean; +} + +@Directive({ + selector: '[perfectScrollbar]' +}) +export class PerfectScrollbarDirective { + @Input() public perfectScrollbarOptions: IPerfectScrollbarOptions; + + private psOptions: IPerfectScrollbarOptions; + private updatingPS: boolean; + + constructor(public elemRef:ElementRef) { + console.log('PSbar: Constructor'); + this.psOptions = Object.assign({}, this.perfectScrollbarOptions); + this.updatingPS = false; + } + + public ngOnInit() { + console.log('PSbar: Initializing'); + PerfectScrollbar.initialize(this.elemRef.nativeElement, this.psOptions); + } + + public ngAfterContentChecked() { + // update perfect-scrollbar after content is checked (updated) - bounced + if (!this.updatingPS) { + this.updatingPS = true; + setTimeout(() => { + this.updatingPS = false; + PerfectScrollbar.update(this.elemRef.nativeElement); + }, 100); + } + } + + public ngOnDestroy() { + PerfectScrollbar.destroy(this.elemRef.nativeElement); + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html index cce1c40765..5294c67e31 100644 --- a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html +++ b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.html @@ -17,6 +17,7 @@ <div class="plugin-frame"> <div class="w-sdc-main-container"> <iframe *ngIf="plugin.isOnline" class="plugin-iframe" [src]="pluginUrl | safeUrlSanitizer"></iframe> - <plugin-not-connected [pluginName]="plugin.pluginId" *ngIf="!plugin.isOnline && isPluginCheckDone"></plugin-not-connected> + <plugin-not-connected [pluginName]="plugin.pluginId" + *ngIf="!plugin.isOnline && isPluginCheckDone"></plugin-not-connected> </div> </div> diff --git a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts index d70c448984..d94f24da28 100644 --- a/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/plugin/plugin-frame.component.ts @@ -38,8 +38,7 @@ export class PluginFrameComponent implements OnInit { } else { this.onLoadingDone.emit(); } - }) - + }); } private initPlugin() { diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html index 88906d96fa..9a280e169d 100644 --- a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html @@ -19,7 +19,7 @@ [style.left]="left + 'px'" [class.in]="isIn" [class.fade]="animation" - style="display: block" + [style.display] = "displayType" role="popover" [ngClass]="{'hide-arrow':hideArrow}"> <div [hidden]="!closeOnMouseOutside" class="virtual-area"></div> @@ -29,13 +29,11 @@ <span class="close-button" (click)="popover.hide()"></span> </div> <ng-content></ng-content> - <div class="popover-footer"> + <div class="popover-footer" *ngIf="buttons"> <button *ngFor="let buttonName of buttonsNames" - class="tlv-btn {{buttons[buttonName].cssClass}}" + class="tlv-btn {{buttons[buttonName].cssClass}}" [attr.data-tests-id]="'filter-' + buttons[buttonName].text.toLowerCase() + '-button'" [disabled] = "buttons[buttonName].getDisabled && buttons[buttonName].getDisabled()" (click) = "buttons[buttonName].callback()">{{buttons[buttonName].text}}</button> </div> </div> - - diff --git a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts index 6eb36287d0..bea592d2a6 100644 --- a/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts @@ -7,9 +7,9 @@ * 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. @@ -18,25 +18,25 @@ * ============LICENSE_END========================================================= */ -import {Component, Input, Output, AfterViewInit, ElementRef, ChangeDetectorRef, OnDestroy, ViewChild, EventEmitter, Renderer } from "@angular/core"; -import {ButtonsModelMap} from "app/models"; -import {PopoverComponent} from "./popover.component"; +import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, EventEmitter, Input, OnDestroy, Output, Renderer, ViewChild } from '@angular/core'; +import { ButtonsModelMap } from 'app/models'; +import { PopoverComponent } from './popover.component'; @Component({ - selector: "popover-content", - templateUrl:'./popover-content.component.html', - styleUrls:['popover-content.component.less'] + selector: 'popover-content', + templateUrl: './popover-content.component.html', + styleUrls: ['popover-content.component.less'] }) export class PopoverContentComponent implements AfterViewInit, OnDestroy { @Input() public title: string; - @Input() public buttons:ButtonsModelMap; + @Input() public buttons: ButtonsModelMap; @Input() content: string; @Input() - placement: "top"|"bottom"|"left"|"right"|"auto"|"auto top"|"auto bottom"|"auto left"|"auto right" = "bottom"; + placement: 'top'|'bottom'|'left'|'right'|'auto'|'auto top'|'auto bottom'|'auto left'|'auto right' = 'bottom'; @Input() animation: boolean = true; @@ -50,52 +50,56 @@ export class PopoverContentComponent implements AfterViewInit, OnDestroy { @Input() hideArrow: boolean = false; - @ViewChild("popoverDiv") + @ViewChild('popoverDiv') popoverDiv: ElementRef; - buttonsNames:Array<string>; + buttonsNames: string[]; popover: PopoverComponent; onCloseFromOutside = new EventEmitter(); - top: number = -10000; - left: number = -10000; + top: number = 250; + left: number = 300; isIn: boolean = false; - displayType: string = "none"; + displayType: string = 'none'; effectivePlacement: string; - onDocumentMouseDown = (event: any) => { - const element = this.element.nativeElement; - if (!element || !this.popover) return; - if (element.contains(event.target) || this.popover.getElement().contains(event.target)) return; - this.hide(); - this.onCloseFromOutside.emit(undefined); - }; - + listenClickFunc: any; + listenMouseFunc: any; constructor(protected element: ElementRef, protected cdr: ChangeDetectorRef, protected renderer: Renderer) { } - listenClickFunc: any; - listenMouseFunc: any; + onDocumentMouseDown = (event: any) => { + const element = this.element.nativeElement; + if (!element || !this.popover) { return; } + if (element.contains(event.target) || this.popover.getElement().contains(event.target)) { return; } + this.hide(); + this.onCloseFromOutside.emit(undefined); + } ngAfterViewInit(): void { - this.buttonsNames = Object.keys(this.buttons); - if (this.closeOnClickOutside) - this.listenClickFunc = this.renderer.listenGlobal("document", "mousedown", (event: any) => this.onDocumentMouseDown(event)); - if (this.closeOnMouseOutside) - this.listenMouseFunc = this.renderer.listenGlobal("document", "mouseover", (event: any) => this.onDocumentMouseDown(event)); + if ( this.buttons ) { + this.buttonsNames = Object.keys(this.buttons); + } + if (this.closeOnClickOutside) { + this.listenClickFunc = this.renderer.listenGlobal('document', 'mousedown', (event: any) => this.onDocumentMouseDown(event)); + } + if (this.closeOnMouseOutside) { + this.listenMouseFunc = this.renderer.listenGlobal('document', 'mouseover', (event: any) => this.onDocumentMouseDown(event)); + } - this.show(); this.cdr.detectChanges(); } ngOnDestroy() { - if (this.closeOnClickOutside) + if (this.closeOnClickOutside) { this.listenClickFunc(); - if (this.closeOnMouseOutside) + } + if (this.closeOnMouseOutside) { this.listenMouseFunc(); + } } // ------------------------------------------------------------------------- @@ -103,11 +107,12 @@ export class PopoverContentComponent implements AfterViewInit, OnDestroy { // ------------------------------------------------------------------------- show(): void { - if (!this.popover || !this.popover.getElement()) + if (!this.popover || !this.popover.getElement()) { return; + } const p = this.positionElements(this.popover.getElement(), this.popoverDiv.nativeElement, this.placement); - this.displayType = "block"; + this.displayType = 'block'; this.top = p.top; this.left = p.left; this.isIn = true; @@ -121,8 +126,7 @@ export class PopoverContentComponent implements AfterViewInit, OnDestroy { } hideFromPopover() { - this.top = -10000; - this.left = -10000; + this.displayType = 'none'; this.isIn = true; } @@ -131,56 +135,56 @@ export class PopoverContentComponent implements AfterViewInit, OnDestroy { // ------------------------------------------------------------------------- protected positionElements(hostEl: HTMLElement, targetEl: HTMLElement, positionStr: string, appendToBody: boolean = false): { top: number, left: number } { - let positionStrParts = positionStr.split("-"); + const positionStrParts = positionStr.split('-'); let pos0 = positionStrParts[0]; - let pos1 = positionStrParts[1] || "center"; - let hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); - let targetElWidth = targetEl.offsetWidth; - let targetElHeight = targetEl.offsetHeight; + const pos1 = positionStrParts[1] || 'center'; + const hostElPos = appendToBody ? this.offset(hostEl) : this.position(hostEl); + const targetElWidth = targetEl.offsetWidth; + const targetElHeight = targetEl.offsetHeight; this.effectivePlacement = pos0 = this.getEffectivePlacement(pos0, hostEl, targetEl); - let shiftWidth: any = { - center: function (): number { + const shiftWidth: any = { + center(): number { return hostElPos.left + hostElPos.width / 2 - targetElWidth / 2; }, - left: function (): number { + left(): number { return hostElPos.left; }, - right: function (): number { + right(): number { return hostElPos.left + hostElPos.width - targetElWidth; } }; - let shiftHeight: any = { - center: function (): number { + const shiftHeight: any = { + center(): number { return hostElPos.top + hostElPos.height / 2 - targetElHeight / 2; }, - top: function (): number { + top(): number { return hostElPos.top; }, - bottom: function (): number { + bottom(): number { return hostElPos.top + hostElPos.height - targetElHeight; } }; let targetElPos: { top: number, left: number }; switch (pos0) { - case "right": + case 'right': targetElPos = { top: shiftHeight[pos1](), left: hostElPos.left + hostElPos.width }; break; - case "left": + case 'left': targetElPos = { top: shiftHeight[pos1](), left: hostElPos.left - targetElWidth }; break; - case "bottom": + case 'bottom': targetElPos = { top: hostElPos.top + hostElPos.height, left: shiftWidth[pos1]() @@ -228,18 +232,20 @@ export class PopoverContentComponent implements AfterViewInit, OnDestroy { } protected getStyle(nativeEl: HTMLElement, cssProp: string): string { - if ((nativeEl as any).currentStyle) // IE + if ((nativeEl as any).currentStyle) { // IE return (nativeEl as any).currentStyle[cssProp]; + } - if (window.getComputedStyle) + if (window.getComputedStyle) { return (window.getComputedStyle as any)(nativeEl)[cssProp]; + } // finally try and get inline style return (nativeEl.style as any)[cssProp]; } protected isStaticPositioned(nativeEl: HTMLElement): boolean { - return (this.getStyle(nativeEl, "position") || "static" ) === "static"; + return (this.getStyle(nativeEl, 'position') || 'static' ) === 'static'; } protected parentOffsetEl(nativeEl: HTMLElement): any { @@ -251,26 +257,26 @@ export class PopoverContentComponent implements AfterViewInit, OnDestroy { } protected getEffectivePlacement(placement: string, hostElement: HTMLElement, targetElement: HTMLElement): string { - const placementParts = placement.split(" "); - if (placementParts[0] !== "auto") { + const placementParts = placement.split(' '); + if (placementParts[0] !== 'auto') { return placement; } const hostElBoundingRect = hostElement.getBoundingClientRect(); - const desiredPlacement = placementParts[1] || "bottom"; + const desiredPlacement = placementParts[1] || 'bottom'; - if (desiredPlacement === "top" && hostElBoundingRect.top - targetElement.offsetHeight < 0) { - return "bottom"; + if (desiredPlacement === 'top' && hostElBoundingRect.top - targetElement.offsetHeight < 0) { + return 'bottom'; } - if (desiredPlacement === "bottom" && hostElBoundingRect.bottom + targetElement.offsetHeight > window.innerHeight) { - return "top"; + if (desiredPlacement === 'bottom' && hostElBoundingRect.bottom + targetElement.offsetHeight > window.innerHeight) { + return 'top'; } - if (desiredPlacement === "left" && hostElBoundingRect.left - targetElement.offsetWidth < 0) { - return "right"; + if (desiredPlacement === 'left' && hostElBoundingRect.left - targetElement.offsetWidth < 0) { + return 'right'; } - if (desiredPlacement === "right" && hostElBoundingRect.right + targetElement.offsetWidth > window.innerWidth) { - return "left"; + if (desiredPlacement === 'right' && hostElBoundingRect.right + targetElement.offsetWidth > window.innerWidth) { + return 'left'; } return desiredPlacement; diff --git a/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.html b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.html new file mode 100644 index 0000000000..fba99ca8b5 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.html @@ -0,0 +1,12 @@ +<div class="sdc-element-icon"> + <svg-icon [ngClass]="{'service-proxy': elementType === 'ServiceProxy'}" + [type]="elementIcon.type" + [name]="elementIcon.iconName" + [mode]="elementIcon.color" + [size]="elementIcon.size" + [backgroundShape]="elementIcon.shape" + [backgroundColor]="elementIcon.backgroundColor"></svg-icon> + <span *ngIf="uncertified" class="uncertified-icon-wapper"> + <svg-icon class="element-non-certified" [name]="'alert-circle'" [mode]="'error'"></svg-icon> + </span> +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.less b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.less new file mode 100644 index 0000000000..7fd5cbd53e --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.less @@ -0,0 +1,25 @@ +@import "./../../../../../assets/styles/override"; +.service-proxy { + /deep/.svg-icon.bg-type-circle { + border: 2px solid @sdcui_color_blue; + } +} + +.element-non-certified { + position: absolute; + top: 0.4px; + left: 0.4px; +} +.sdc-element-icon { + position: relative; +} + +.uncertified-icon-wapper{ + height: 17px; + width: 17px; + background-color: white; + border-radius: 50%; + position: absolute; + top: -2px; + left: -1px; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.ts b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.ts new file mode 100644 index 0000000000..baadbd8e02 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/sdc-element-icon/sdc-element-icon.component.ts @@ -0,0 +1,69 @@ +import {Component, Input, OnInit} from "@angular/core"; +import {ComponentType, SdcElementType, ResourceType} from "../../../../utils/constants"; + + +export class ElementIcon { + iconName: string; + color: string; + backgroundColor: string; + type: string + shape: string; + size: string; + + constructor(name?: string, type?:string, backgroundColor?:string, color?:string, shape?: string, size?:string) { + this.iconName = name || 'default'; + this.type = type || 'resource_24'; + this.backgroundColor = backgroundColor || 'primary'; + this.color = color || "white"; + this.shape = shape || "circle"; + this.size = size || "x_large"; + } +} + +@Component({ + selector: 'sdc-element-icon', + templateUrl: './sdc-element-icon.component.html', + styleUrls: ['./sdc-element-icon.component.less'] +}) +export class SdcElementIconComponent { + + @Input() iconName: string; + @Input() elementType: string; + @Input() uncertified: boolean = false; + + public elementIcon; + + private createIconForDisplay = () => { + switch (this.elementType) { + + case ComponentType.SERVICE: + this.elementIcon = new ElementIcon(this.iconName, "services_24", "lightBlue"); + break; + case ComponentType.SERVICE_PROXY: + this.elementIcon = new ElementIcon(this.iconName, "services_24", "white", "primary"); + break; + case ResourceType.CONFIGURATION: + this.elementIcon = new ElementIcon(this.iconName, "resources_24", "purple", "white", 'circle', "medium"); + break; + case SdcElementType.GROUP: + this.elementIcon = new ElementIcon("group", "resources_24", "blue", 'white', 'rectangle'); + break; + case SdcElementType.POLICY: + this.elementIcon = new ElementIcon("policy", "resources_24", "darkBlue2", 'white', 'rectangle'); + break; + case ResourceType.CP: + case ResourceType.VL: + this.elementIcon = new ElementIcon(this.iconName, "resources_24", "purple", '', '', 'medium'); + break; + default: + this.elementIcon = new ElementIcon(this.iconName, "resources_24", "purple"); + } + } + + ngOnChanges():void { + this.createIconForDisplay(); + } +} + + + diff --git a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html index 8682473d14..1f952c46f5 100644 --- a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html @@ -1,21 +1,5 @@ -<!-- - ~ 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. - --> - -<div class="search-bar-container {{class}}"> - <input class="search-bar-input" type="text" [placeholder]="placeholder" [(ngModel)]="searchQuery" (ngModelChange)="searchQueryChange($event)"/> - <span class="clear-search-x" *ngIf="searchQuery" (click)="clearSearchQuery()">x</span> - <button class="search-bar-button" (click)="searchButtonClick()"></button> +<div class="sdc-search-bar-container {{class}}"> + <input class="sdc-search-bar-input" type="text" [placeholder]="placeholder" [(ngModel)]="searchQuery" (ngModelChange)="searchQueryChange($event)"/> + <span class="sdc-clear-search-x" *ngIf="searchQuery" (click)="clearSearchQuery()">x</span> + <button class="sdc-search-bar-button" (click)="searchButtonClick()"></button> </div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less index 751fceec35..c09951a284 100644 --- a/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less @@ -1,9 +1,9 @@ -.search-bar-container { +.sdc-search-bar-container { display:flex; border-radius: 4px; box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29); - .search-bar-input { + .sdc-search-bar-input { border: 1px solid #cdcdcd; border-radius: 4px; border-right:none; @@ -14,9 +14,11 @@ color: #5a5a5a; font-size: 1em; font-style: italic; + + } - .clear-search-x { + .sdc-clear-search-x { position:absolute; right:40px; top:5px; @@ -29,7 +31,7 @@ } } - .search-bar-button { + .sdc-search-bar-button { background: url('../../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px; background-color: rgba(234, 234, 234, 0.88); width: 30px; diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html index 82dbbf33d3..da9b2c9e24 100644 --- a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html @@ -14,9 +14,9 @@ ~ limitations under the License. --> -<div class="search-with-autocomplete-container {{searchBarClass}}" [class.autocomplete-visible]="autoCompleteValues && autoCompleteValues.length" [class.active]="searchQuery && searchQuery.length"> +<div class="sdc-search-with-autocomplete-container {{searchBarClass}}" [class.sdc-autocomplete-visible]="autoCompleteValues && autoCompleteValues.length" [class.active]="searchQuery && searchQuery.length"> <search-bar [placeholder]="searchPlaceholder" [searchQuery]="searchQuery" (searchButtonClicked)="updateSearch($event)" (searchChanged)="searchChange($event)"></search-bar> - <div class="autocomplete-results"> - <div *ngFor="let item of autoCompleteValues" class="autocomplete-result-item" (click)="updateSearch(item)">{{item}}</div> + <div class="sdc-autocomplete-results"> + <div *ngFor="let item of autoCompleteValues" class="sdc-autocomplete-result-item" (click)="updateSearch(item)">{{item}}</div> </div> </div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less index f1830846d3..9cd312adcb 100644 --- a/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less @@ -1,13 +1,13 @@ -.search-with-autocomplete-container{ - &.autocomplete-visible { +.sdc-search-with-autocomplete-container{ + &.sdc-autocomplete-visible { - .search-bar-input { + .sdc-search-bar-input { border-bottom-left-radius: 0; } - .search-bar-button { + .sdc-search-bar-button { border-bottom-right-radius: 0; } - .autocomplete-results { + .sdc-autocomplete-results { border: solid 1px #d2d2d2; border-top:none; border-bottom-left-radius: 4px; @@ -20,7 +20,7 @@ overflow-y: scroll; } - .autocomplete-result-item { + .sdc-autocomplete-result-item { color:#5a5a5a; padding: 5px 0; cursor:pointer; diff --git a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts index f4b410347b..cabac121f7 100644 --- a/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts @@ -21,7 +21,7 @@ import { Component, ContentChildren, QueryList, AfterContentInit, Input, Output, EventEmitter } from '@angular/core'; import { Tab } from './tab/tab.component'; import { ViewEncapsulation } from '@angular/core'; -import { trigger, state, style, transition, animate, keyframes } from '@angular/core'; +import { trigger, state, style, transition, animate, keyframes } from '@angular/animations'; export {Tab}; diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.module.ts b/catalog-ui/src/app/ng2/components/ui/tile/sdc-tile.module.ts index 55b34400d6..5dec67e495 100644 --- a/catalog-ui/src/app/ng2/components/ui/tile/tile.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/tile/sdc-tile.module.ts @@ -3,13 +3,13 @@ import { BrowserModule } from '@angular/platform-browser'; import { TileComponent } from './tile.component'; import { GlobalPipesModule } from "../../../pipes/global-pipes.module"; import { TooltipModule } from "../tooltip/tooltip.module"; -import {MultilineEllipsisModule} from "../../../shared/multiline-ellipsis/multiline-ellipsis.module"; +import {SdcUiComponentsModule} from "onap-ui-angular"; @NgModule({ - imports: [BrowserModule, GlobalPipesModule, TooltipModule, MultilineEllipsisModule], + imports: [BrowserModule, GlobalPipesModule, SdcUiComponentsModule, TooltipModule], declarations: [TileComponent], exports: [TileComponent], entryComponents: [TileComponent] }) -export class TileModule { } +export class SdcTileModule { } diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html index 018384db1f..239053e9f8 100644 --- a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html +++ b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.html @@ -23,15 +23,21 @@ <div class='sdc-tile-content' data-tests-id="dashboard-Elements" (click)="tileClicked()"> <div class='sdc-tile-content-icon'> - <div [ngClass]="[component.iconSprite, component.icon]" [ngClass]="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}" + <div [ngClass]="[component.iconSprite, component.icon]" + [ngClass]="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}" [attr.data-tests-id]="component.name"></div> </div> <div class='sdc-tile-content-info'> - <div class="sdc-tile-info-line title" [attr.data-tests-id]="component.name | resourceName" [tooltip]="component.name | resourceName" [tooltipDisabled]="!hasEllipsis"> - <multiline-ellipsis className="w-sdc-tile-multiline-ellipsis" [lines]="3" (hasEllipsisChanged)="hasEllipsis = $event">{{component.name | resourceName}}</multiline-ellipsis> + <div class="sdc-tile-info-line title" [attr.data-tests-id]="component.name | resourceName" + [tooltip]="component.name | resourceName" [tooltipDisabled]="!hasEllipsis"> + <multiline-ellipsis className="w-sdc-tile-multiline-ellipsis" [lines]="3" + (hasEllipsisChanged)="hasEllipsis = $event">{{component.name | resourceName}} + </multiline-ellipsis> + </div> + <div class="sdc-tile-info-line subtitle" [attr.data-tests-id]="component.name+'Version'">V + {{component.version}} </div> - <div class="sdc-tile-info-line subtitle" [attr.data-tests-id]="component.name+'Version'">V {{component.version}}</div> </div> </div> @@ -42,3 +48,32 @@ </div> </div> + +<!--<sdc-tile>--> +<!--<sdc-tile-header>--> +<!--<div [ngClass]="{'blue': component.isService(), 'purple': component.isResource()}">{{component.isResource() ?--> +<!--component.getComponentSubType(): 'S' }}--> +<!--</div>--> +<!--</sdc-tile-header>--> +<!--<sdc-tile-content>--> +<!--<div class='sdc-tile-content-icon blue'>--> +<!--<svg-icon--> +<!--[type]="catalogIcon.type"--> +<!--[name]="catalogIcon.iconName"--> +<!--[size]="catalogIcon.size"--> +<!--[mode]="catalogIcon.color"--> +<!--[backgroundShape]="catalogIcon.shape"--> +<!--[backgroundColor]="catalogIcon.backgroundColor"--> +<!--[disabled]="false"--> +<!-->--> +<!--</svg-icon>--> +<!--</div>--> +<!--<div class="sdc-tile-content-info">--> +<!--<span class="sdc-tile-info-line title">{{component.name | resourceName}}</span>--> +<!--<div class="sdc-tile-info-line subtitle">{{'V'+ component.version}}</div>--> +<!--</div>--> +<!--</sdc-tile-content>--> +<!--<sdc-tile-footer>--> +<!--<span class="sdc-tile-footer-cell">{{component.getStatus(sdcMenu)}}</span>--> +<!--</sdc-tile-footer>--> +<!--</sdc-tile>-->
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less index e69de29bb2..febf46e99c 100644 --- a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less +++ b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.less @@ -0,0 +1,15 @@ + + +//This was done as a fix for the wrong dispaly that was in every ui-tile. +//All other styles located in mail.less + +.sdc-tile { + display: block; + + .sdc-tile-content { + overflow: visible; + height: 80%; + .sdc-tile-content-icon { + } + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts index b6f63584be..f5d9e88934 100644 --- a/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tile/tile.component.ts @@ -1,6 +1,8 @@ import {Component, Input, Output, Inject, EventEmitter} from '@angular/core'; import {Component as ComponentModel} from 'app/models'; import {SdcMenuToken, IAppMenu} from "../../../config/sdc-menu.config"; +import {ElementIcon} from "../sdc-element-icon/sdc-element-icon.component"; +import {ComponentType, ResourceType, SdcElementType} from "../../../../utils/constants"; @Component({ selector: 'ui-tile', @@ -10,14 +12,42 @@ import {SdcMenuToken, IAppMenu} from "../../../config/sdc-menu.config"; export class TileComponent { @Input() public component: ComponentModel; @Output() public onTileClick: EventEmitter<ComponentModel>; - + public catalogIcon: ElementIcon; public hasEllipsis: boolean; - constructor(@Inject(SdcMenuToken) public sdcMenu:IAppMenu) { + constructor(@Inject(SdcMenuToken) public sdcMenu: IAppMenu) { this.onTileClick = new EventEmitter<ComponentModel>(); this.hasEllipsis = false; } + ngOnInit(): void { + switch (this.component.componentType) { + + case ComponentType.SERVICE: + if (this.component.icon === 'defaulticon') { + this.catalogIcon = new ElementIcon(this.component.icon, "services_60", 'lightBlue', 'white'); + } else { + this.catalogIcon = new ElementIcon(this.component.icon, "services_60", '', 'lightBlue'); + } + break; + case ComponentType.RESOURCE: + switch (this.component.getComponentSubType()) { + case ResourceType.CP: + case ResourceType.VL: + this.catalogIcon = new ElementIcon(this.component.icon, "resources_24", "purple", "white", "circle", 'medium'); + break; + default: + if (this.component.icon === 'defaulticon') { + this.catalogIcon = new ElementIcon(this.component.icon, "resources_60", "purple", "white", "circle", 'x_large'); + } else { + this.catalogIcon = new ElementIcon(this.component.icon, "resources_60", '', "error"); + } + + } + + } + } + public tileClicked() { this.onTileClick.emit(this.component); } diff --git a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts index e905db73a6..cdb173cb12 100644 --- a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts @@ -18,82 +18,89 @@ * ============LICENSE_END========================================================= */ -import { NgModule } from '@angular/core'; -import { NavbarModule } from "./navbar/navbar.module"; -import { DynamicElementModule } from "./dynamic-element/dynamic-element.module"; -import { FormElementsModule } from "./form-components/form-elements.module"; -import { LoaderComponent } from "./loader/loader.component"; -import { ModalModule } from "./modal/modal.module"; -import { PopoverModule } from "./popover/popover.module"; -import { SearchBarComponent } from "./search-bar/search-bar.component"; -import { SearchWithAutoCompleteComponent } from "./search-with-autocomplete/search-with-autocomplete.component"; -import { PalettePopupPanelComponent } from "./palette-popup-panel/palette-popup-panel.component"; -import { ZoneContainerComponent } from "./canvas-zone/zone-container.component"; -import { ZoneInstanceComponent } from "./canvas-zone/zone-instance/zone-instance.component"; -import { PaletteAnimationComponent } from "./palette-animation/palette-animation.component" -import { TabModule } from "./tabs/tabs.module"; -import { TooltipModule } from "./tooltip/tooltip.module"; -import { CommonModule } from "@angular/common"; -import { FormsModule } from "@angular/forms"; -import { BrowserModule } from "@angular/platform-browser"; -import { MultiStepsWizardModule } from "./multi-steps-wizard/multi-steps-wizard.module"; -import { MenuListModule } from "./menu/menu-list.module"; -import { MenuListNg2Module } from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module"; -import { ExpandCollapseComponent } from './expand-collapse/expand-collapse.component'; -import { SdcUiComponentsModule } from "sdc-ui/lib/angular"; -import { TileModule } from "./tile/tile.module"; +import {NgModule} from '@angular/core'; +import {NavbarModule} from "./navbar/navbar.module"; +import {DynamicElementModule} from "./dynamic-element/dynamic-element.module"; +import {FormElementsModule} from "./form-components/form-elements.module"; +import {LoaderComponent} from "./loader/loader.component"; +import {ModalModule} from "./modal/modal.module"; +import {PopoverModule} from "./popover/popover.module"; +import {SearchBarComponent} from "./search-bar/search-bar.component"; +import {SearchWithAutoCompleteComponent} from "./search-with-autocomplete/search-with-autocomplete.component"; +import { PaletteAnimationComponent } from "app/ng2/pages/composition/palette/palette-animation/palette-animation.component"; +import {TabModule} from "./tabs/tabs.module"; +import {TooltipModule} from "./tooltip/tooltip.module"; +import {CommonModule} from "@angular/common"; +import {FormsModule} from "@angular/forms"; +import {BrowserModule} from "@angular/platform-browser"; +import {MultiStepsWizardModule} from "./multi-steps-wizard/multi-steps-wizard.module"; +import {MenuListModule} from "./menu/menu-list.module"; +import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module"; +import {ExpandCollapseComponent} from './expand-collapse/expand-collapse.component'; +import {SdcUiComponentsModule} from "onap-ui-angular"; +import {SdcTileModule} from "./tile/sdc-tile.module"; +import {PerfectScrollbarDirective} from "./perfect-scroll-bar/perfect-scrollbar.directive"; +import {FileOpenerComponent} from "./file-opener/file-opener.component"; +import {DownloadArtifactComponent} from "app/ng2/components/ui/download-artifact/download-artifact.component"; +import {SdcElementIconComponent} from "./sdc-element-icon/sdc-element-icon.component"; +import {PanelWrapperComponent} from "./panel-wrapper/panel-wrapper.component"; @NgModule({ - declarations: [ - LoaderComponent, - SearchBarComponent, - SearchWithAutoCompleteComponent, - PalettePopupPanelComponent, - ZoneContainerComponent, - ZoneInstanceComponent, - PaletteAnimationComponent, - ExpandCollapseComponent -], - - imports: [ - SdcUiComponentsModule, - BrowserModule, - FormsModule, - CommonModule, - DynamicElementModule, - NavbarModule, - FormElementsModule, - ModalModule, - PopoverModule, - TabModule, - TooltipModule, - MultiStepsWizardModule, - MenuListModule, - MenuListNg2Module, - TileModule - ], - exports: [ - LoaderComponent, - MultiStepsWizardModule, - SearchBarComponent, - SearchWithAutoCompleteComponent, - PalettePopupPanelComponent, - ZoneContainerComponent, - ZoneInstanceComponent, - DynamicElementModule, - NavbarModule, - FormElementsModule, - ModalModule, - PopoverModule, - TabModule, - TooltipModule, - MenuListModule, - MenuListNg2Module, - PaletteAnimationComponent, - ExpandCollapseComponent, - TileModule - ], - entryComponents: [SearchWithAutoCompleteComponent, PalettePopupPanelComponent, ZoneContainerComponent, ZoneInstanceComponent, PaletteAnimationComponent] + declarations: [ + LoaderComponent, + SearchBarComponent, + SearchWithAutoCompleteComponent, + PaletteAnimationComponent, + ExpandCollapseComponent, + PerfectScrollbarDirective, + FileOpenerComponent, + SdcElementIconComponent, + DownloadArtifactComponent, + PanelWrapperComponent + ], + + imports: [ + SdcUiComponentsModule, + BrowserModule, + FormsModule, + CommonModule, + DynamicElementModule, + NavbarModule, + FormElementsModule, + ModalModule, + PopoverModule, + TabModule, + TooltipModule, + MultiStepsWizardModule, + MenuListModule, + MenuListNg2Module, + SdcTileModule + ], + exports: [ + LoaderComponent, + MultiStepsWizardModule, + SearchBarComponent, + SearchWithAutoCompleteComponent, + DynamicElementModule, + NavbarModule, + FormElementsModule, + ModalModule, + PopoverModule, + TabModule, + TooltipModule, + MenuListModule, + MenuListNg2Module, + PaletteAnimationComponent, + ExpandCollapseComponent, + SdcTileModule, + PerfectScrollbarDirective, + SdcElementIconComponent, + FileOpenerComponent, + DownloadArtifactComponent, + PanelWrapperComponent + ], + entryComponents: [SearchWithAutoCompleteComponent, SdcElementIconComponent, PaletteAnimationComponent] }) -export class UiElementsModule {} +export class UiElementsModule { +} |