diff options
Diffstat (limited to 'catalog-ui/src/app')
104 files changed, 1398 insertions, 1444 deletions
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts index 50b99e8ab9..805e5f0b5d 100644 --- a/catalog-ui/src/app/app.ts +++ b/catalog-ui/src/app/app.ts @@ -53,6 +53,7 @@ import {downgradeComponent} from "@angular/upgrade/static"; import {AppModule} from './ng2/app.module'; import {PropertiesAssignmentComponent} from "./ng2/pages/properties-assignment/properties-assignment.page.component"; +import { SearchWithAutoCompleteComponent } from "./ng2/shared/search-with-autocomplete/search-with-autocomplete.component"; import {Component} from "./models/components/component"; import {ComponentServiceNg2} from "./ng2/services/component-services/component.service"; import {ComponentMetadata} from "./models/component-metadata"; @@ -145,6 +146,13 @@ _.each(hostedApplications, (hostedApp)=> { export const ng1appModule:ng.IModule = angular.module(moduleName, dependentModules); angular.module('sdcApp').directive('propertiesAssignment', downgradeComponent({component: PropertiesAssignmentComponent}) as angular.IDirectiveFactory); +angular.module('sdcApp').directive('ng2SearchWithAutocomplete', + downgradeComponent({ + component: SearchWithAutoCompleteComponent, + inputs: ['searchPlaceholder', 'searchBarClass', 'autoCompleteValues'], + outputs: ['searchChanged', 'searchButtonClicked'] + }) as angular.IDirectiveFactory); + ng1appModule.config([ '$stateProvider', @@ -161,7 +169,7 @@ ng1appModule.config([ NotificationProvider:any):void => { NotificationProvider.setOptions({ - delay: 10000, + delay: 5000, startTop: 10, startRight: 10, closeOnClick: true, @@ -170,6 +178,7 @@ ng1appModule.config([ positionX: 'right', positionY: 'top' }); + NotificationProvider.options.templateUrl = 'notification-custom-template.html'; $translateProvider.useStaticFilesLoader({ prefix: pathPrefix + 'assets/languages/', @@ -245,17 +254,6 @@ ng1appModule.config([ data: {unsavedChanges: false, bodyClass: 'general'} } ); - // - $stateProvider.state( - States.WORKSPACE_ICONS, { - url: 'icons', - parent: 'workspace', - controller: viewModelsModuleName + '.IconsViewModel', - templateUrl: './view-models/workspace/tabs/icons/icons-view.html', - data: {unsavedChanges: false, bodyClass: 'icons'} - - } - ); $stateProvider.state( States.WORKSPACE_ACTIVITY_LOG, { @@ -280,17 +278,6 @@ ng1appModule.config([ ); $stateProvider.state( - States.WORKSPACE_HIERARCHY, { - url: 'hierarchy', - parent: 'workspace', - controller: viewModelsModuleName + '.ProductHierarchyViewModel', - templateUrl: './view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html', - data: {unsavedChanges: false} - - } - ); - - $stateProvider.state( States.WORKSPACE_INFORMATION_ARTIFACTS, { url: 'information_artifacts', parent: 'workspace', @@ -602,7 +589,7 @@ ng1appModule.value('ValidationPattern', /^[\s\w\&_.:-]{1,1024}$/); ng1appModule.value('ComponentNameValidationPattern', /^(?=.*[^. ])[\s\w\&_.:-]{1,1024}$/); //DE250513 - same as ValidationPattern above, plus requirement that name not consist of dots and/or spaces alone. ng1appModule.value('PropertyNameValidationPattern', /^[a-zA-Z0-9_:-]{1,50}$/);// DE210977 ng1appModule.value('TagValidationPattern', /^[\s\w_.-]{1,50}$/); -ng1appModule.value('VendorValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,25}$/); +ng1appModule.value('VendorReleaseValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,25}$/); ng1appModule.value('VendorNameValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,60}$/); ng1appModule.value('VendorModelNumberValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,65}$/); ng1appModule.value('ContactIdValidationPattern', /^[\s\w-]{1,50}$/); @@ -639,6 +626,7 @@ ng1appModule.run([ 'LeftPaletteLoaderService', 'Sdc.Services.DataTypesService', 'AngularJSBridge', + '$templateCache', ($http:ng.IHttpService, cacheService:CacheService, cookieService:CookieService, @@ -654,8 +642,9 @@ ng1appModule.run([ ecompHeaderService:EcompHeaderService, LeftPaletteLoaderService:LeftPaletteLoaderService, DataTypesService:DataTypesService, - AngularJSBridge):void => { - + AngularJSBridge, + $templateCache:ng.ITemplateCacheService):void => { + $templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html')); //handle cache data - version let initAsdcVersion:Function = ():void => { @@ -696,7 +685,6 @@ ng1appModule.run([ categoryResourceService.getAllCategories((categories: Categories):void => { cacheService.set('serviceCategories', categories.serviceCategories); cacheService.set('resourceCategories', categories.resourceCategories); - cacheService.set('productCategories', categories.productCategories); }, onError); }; diff --git a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts index 0a13ebd799..64197594e2 100644 --- a/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.ts +++ b/catalog-ui/src/app/directives/graphs-v2/common/style/component-instances-nodes-style.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. @@ -44,7 +44,8 @@ export class ComponentInstanceNodesStyle { { selector: 'node', css: { - 'font-family': 'omnes-regular,sans-serif', + 'font-family': 'OpenSans-Regular,sans-serif', + 'font-size': 14, 'events': 'yes', 'text-events': 'yes', @@ -230,7 +231,7 @@ export class ComponentInstanceNodesStyle { public static getBasicNodeHanlde = () => { return { - positionX: "center", + positionX: "right", positionY: "top", offsetX: 15, offsetY: -20, @@ -247,7 +248,7 @@ export class ComponentInstanceNodesStyle { public static getBasicSmallNodeHandle = () => { return { - positionX: "center", + positionX: "right", positionY: "top", offsetX: 3, offsetY: -25, diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts index 651a4281fa..9aa7941272 100644 --- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.directive.ts @@ -47,7 +47,8 @@ interface ICompositionGraphScope extends ng.IScope { component:Component; isLoading: boolean; - isViewOnly:boolean; + isViewOnly: boolean; + withSidebar: boolean; // Link menu - create link menu relationMenuDirectiveObj:RelationMenuDirectiveObj; isLinkMenuOpen:boolean; @@ -65,6 +66,14 @@ interface ICompositionGraphScope extends ng.IScope { //Links menus deleteRelation(link:Cy.CollectionEdges):void; hideRelationMenu(); + + //search,zoom in/out/all + componentInstanceNames: Array<string>; //id, name + zoom(zoomIn: boolean): void; + zoomAll(nodes?:Cy.CollectionNodes): void; + getAutoCompleteValues(searchTerm: string):void; + highlightSearchMatches(searchTerm: string): void; + /*//asset popover menu assetPopoverObj:AssetPopoverObj; assetPopoverOpen:boolean; @@ -101,7 +110,8 @@ export class CompositionGraph implements ng.IDirective { template = require('./composition-graph.html'); scope = { component: '=', - isViewOnly: '=' + isViewOnly: '=', + withSidebar: '=' }; link = (scope:ICompositionGraphScope, el:JQuery) => { @@ -147,7 +157,11 @@ export class CompositionGraph implements ng.IDirective { this._cy = cytoscape({ container: graphEl, style: ComponentInstanceNodesStyle.getCompositionGraphStyle(), - zoomingEnabled: false, + zoomingEnabled: true, + maxZoom: 2.5, + minZoom: .1, + userZoomingEnabled: false, + userPanningEnabled: true, selectionType: 'single', boxSelectionEnabled: true, autolock: isViewOnly, @@ -270,6 +284,40 @@ export class CompositionGraph implements ng.IDirective { this.loadGraphData(scope); }); + scope.zoom = (zoomIn: boolean):void => { + let currentZoom: number = this._cy.zoom(); + if (zoomIn) { + this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom + .1); + } else { + this.GeneralGraphUtils.zoomGraphTo(this._cy, currentZoom - .1); + } + } + + //Zooms to fit all of the nodes in the collection passed in. If no nodes are passed in, will zoom to fit all nodes on graph + scope.zoomAll = (nodes?:Cy.CollectionNodes) => { + scope.withSidebar = false; + this._cy.animate({ + fit: { eles: nodes, padding: 20 }, + center: { eles: nodes } + }, { duration: 400 }); + }; + + scope.getAutoCompleteValues = (searchTerm: string) => { + if (searchTerm.length > 1) { //US requirement: only display search results after 2nd letter typed. + let nodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm); + scope.componentInstanceNames = _.map(nodes, node => node.data('name')); + } else { + scope.componentInstanceNames = []; + } + }; + + scope.highlightSearchMatches = (searchTerm: string) => { + if (searchTerm === undefined) return; //dont zoom & highlight if click on Search initially (searchTerm will be undefined). However, allow highlights to be cleared after subsequent search (searchTerm will be "") + + this.NodesGraphUtils.highlightMatchingNodesByName(this._cy, searchTerm); + let matchingNodes: Cy.CollectionNodes = this.NodesGraphUtils.getMatchingNodesByName(this._cy, searchTerm); + scope.zoomAll(matchingNodes); + }; scope.createLinkFromMenu = (chosenMatch:MatchBase):void => { scope.isLinkMenuOpen = false; @@ -367,7 +415,7 @@ export class CompositionGraph implements ng.IDirective { });*/ this._cy.on('handlemouseover', (event, payload) => { - if (payload.node.grabbed() /* || this._cy.scratch('_edge_editation_highlights') === true*/) { //no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes + if (payload.node.grabbed() || this._cy.scratch('_edge_editation_highlights') === true) { //no need to add opacity while we are dragging and hovering othe nodes- or if opacity was already calculated for these nodes return; } let nodesData = this.NodesGraphUtils.getAllNodesData(this._cy.nodes()); @@ -377,9 +425,9 @@ export class CompositionGraph implements ng.IDirective { let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findByMatchingCapabilitiesToRequirements(payload.node.data().componentInstance, linkableNodes, nodesLinks); this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy); this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy, payload.node.data()); - /* + this._cy.scratch()._edge_editation_highlights = true; - scope.hideAssetPopover();*/ + /*scope.hideAssetPopover();*/ }); this._cy.on('handlemouseout', () => { diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html index 1e69d3384a..248f19fb70 100644 --- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/composition-graph.html @@ -20,4 +20,11 @@ </div> + <div class="w-sdc-search-menu" data-ng-class="{'with-sidebar': withSidebar}"> + <ng2-search-with-autocomplete [search-placeholder]="'Type to search'" [auto-complete-values]="componentInstanceNames" (search-changed)="getAutoCompleteValues($event)" (search-button-clicked)="highlightSearchMatches($event)" + [search-bar-class]="'composition-search'"></ng2-search-with-autocomplete> + <div class="zoom-icons sprite-new canvas-fit-all" data-ng-click="zoomAll()"></div> + <div class="zoom-icons sprite-new zoom-plus" data-ng-click="zoom(true)"></div> + <div class="zoom-icons sprite-new zoom-minus" data-ng-click="zoom(false)"></div> + </div> <!--<asset-popover ng-if="assetPopoverOpen" asset-popover-obj="assetPopoverObj" delete-asset="deleteNode(assetPopoverObj.nodeId)"></asset-popover>--> diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts index 608031430b..0ea38af825 100644 --- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-general-utils.ts @@ -64,6 +64,14 @@ export class CompositionGraphGeneralUtils { }; + public zoomGraphTo = (cy:Cy.Instance, zoomLevel: number):void => { + let zy = cy.height() / 2; + let zx = cy.width() / 2; + cy.zoom({ + level: zoomLevel, + renderedPosition: { x: zx, y: zy } + }); + } /** * will return true/false if two nodes overlapping * diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts index feb6ac9a54..449d551cc0 100644 --- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-nodes-utils.ts @@ -48,6 +48,21 @@ export class CompositionGraphNodesUtils { }) }; + + public highlightMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string) => { + + cy.batch(() => { + cy.nodes("[name !@^= '" + nameToMatch + "']").style({ 'background-image-opacity': 0.4 }); + cy.nodes("[name @^= '" + nameToMatch + "']").style({ 'background-image-opacity': 1 }); + }) + + } + + //Returns all nodes whose name starts with searchTerm + public getMatchingNodesByName = (cy: Cy.Instance, nameToMatch: string): Cy.CollectionNodes => { + return cy.nodes("[name @^= '" + nameToMatch + "']"); + }; + /** * Deletes component instances on server and then removes it from the graph as well * @param cy diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts index f1c3405cfa..f46dc6c939 100644 --- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts +++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.directive.ts @@ -17,21 +17,14 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - -import { - Component, - IAppMenu, - LeftPanelModel, - NodesFactory, - LeftPaletteComponent, - CompositionCiNodeBase, - ComponentInstance -} from "app/models"; +import {Component, IAppMenu, LeftPanelModel, NodesFactory, LeftPaletteComponent, CompositionCiNodeBase, ComponentInstance} from "app/models"; import {CompositionGraphGeneralUtils} from "../composition-graph/utils/composition-graph-general-utils"; import {EventListenerService} from "app/services"; import {ResourceType, GRAPH_EVENTS, EVENTS, ComponentInstanceFactory, ModalsHandler} from "app/utils"; import 'sdc-angular-dragdrop'; import {LeftPaletteLoaderService} from "../../../services/components/utils/composition-left-palette-service"; +import {Resource} from "app/models/components/resource"; +import {ComponentType} from "app/utils/constants"; interface IPaletteScope { components:Array<LeftPaletteComponent>; @@ -92,7 +85,7 @@ export class Palette implements ng.IDirective { el.append(this.nodeHtmlSubstitute); this.registerEventListenerForLeftPalette(scope); // this.LeftPaletteLoaderService.loadLeftPanel(scope.currentComponent.componentType); - + this.initComponents(scope); this.initEvents(scope); this.initDragEvents(scope); @@ -103,34 +96,31 @@ export class Palette implements ng.IDirective { }); }; - private registerEventListenerForLeftPalette = (scope:IPaletteScope):void => { - if (scope.currentComponent.isResource()) { - this.EventListenerService.registerObserverCallback(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT, () => { - this.updateLeftPanelDisplay(scope); - }); - } - if (scope.currentComponent.isService()) { - this.EventListenerService.registerObserverCallback(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT, () => { - this.updateLeftPanelDisplay(scope); - }); - } - if (scope.currentComponent.isProduct()) { - this.EventListenerService.registerObserverCallback(EVENTS.PRODUCT_LEFT_PALETTE_UPDATE_EVENT, () => { - this.updateLeftPanelDisplay(scope); - }); + private getUpdateLeftPaletteEventName = (component:Component):string => { + switch (component.componentType) { + case ComponentType.SERVICE: + return EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT; + case ComponentType.RESOURCE: + if((<Resource>component).resourceType == ResourceType.PNF){ + return EVENTS.RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT; + }else{ + return EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT; + } + default: + console.log('ERROR: Component type '+ component.componentType + ' is not exists'); } }; + private registerEventListenerForLeftPalette = (scope:IPaletteScope):void => { + let updateEventName:string = this.getUpdateLeftPaletteEventName(scope.currentComponent); + this.EventListenerService.registerObserverCallback(updateEventName, () => { + this.updateLeftPanelDisplay(scope); + }); + }; + private unRegisterEventListenerForLeftPalette = (scope:IPaletteScope):void => { - if (scope.currentComponent.isResource()) { - this.EventListenerService.unRegisterObserver(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT); - } - if (scope.currentComponent.isService()) { - this.EventListenerService.unRegisterObserver(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT); - } - if (scope.currentComponent.isProduct()) { - this.EventListenerService.unRegisterObserver(EVENTS.PRODUCT_LEFT_PALETTE_UPDATE_EVENT); - } + let updateEventName:string = this.getUpdateLeftPaletteEventName(scope.currentComponent); + this.EventListenerService.unRegisterObserver(updateEventName); }; private leftPanelResourceFilter(resourcesNotAbstract:Array<LeftPaletteComponent>, resourceFilterTypes:Array<string>):Array<LeftPaletteComponent> { @@ -236,7 +226,7 @@ export class Palette implements ng.IDirective { private updateLeftPanelDisplay(scope:IPaletteScope) { let entityType:string = scope.currentComponent.componentType.toLowerCase(); let resourceFilterTypes:Array<string> = this.sdcConfig.resourceTypesFilter[entityType]; - scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType); + scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent); scope.model = this.initLeftPanel(scope.components, resourceFilterTypes); scope.displaySortedCategories = angular.copy(scope.model.sortedCategories); }; @@ -267,7 +257,7 @@ export class Palette implements ng.IDirective { return; } - let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType), (componentFullData:LeftPaletteComponent) => { + let component = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (componentFullData:LeftPaletteComponent) => { return displayComponent.uniqueId === componentFullData.uniqueId; }); this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_START, scope.dragElement, component); @@ -287,7 +277,7 @@ export class Palette implements ng.IDirective { this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_DRAG_ACTION, event); }; scope.setElementTemplate = (e) => { - let dragComponent:LeftPaletteComponent = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent.componentType), + let dragComponent:LeftPaletteComponent = _.find(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent), (fullComponent:LeftPaletteComponent) => { return (<any>angular.element(e.currentTarget).scope()).component.uniqueId === fullComponent.uniqueId; }); diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html index 3a4720676c..ec9aaf1f7f 100644 --- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html +++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.html @@ -56,7 +56,7 @@ </div> <div data-ng-if="isSchemaTypeDataType" class="i-sdc-form-item map-item-field"> <label class="i-sdc-form-label">Value</label> - <fields-structure value-obj-ref="valueObjRef[mapKeys[$index]]" + <fields-structure value-obj-ref="valueObjRef[mapKeysStatic[$index]]" type-name="schemaProperty.type" parent-form-obj="parentFormObj" fields-prefix-name="'mapValue'+fieldsPrefixName+''+$index" diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts index a2274654c8..5718cdd9b5 100644 --- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts +++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.ts @@ -33,6 +33,7 @@ export interface ITypeMapScope extends ng.IScope { isSchemaTypeDataType:boolean; valueObjRef:any; mapKeys:Array<string>;//array of map keys + mapKeysStatic:Array<string>; MapKeyValidationPattern:RegExp; fieldsPrefixName:string; readOnly:boolean; @@ -82,6 +83,8 @@ export class TypeMapDirective implements ng.IDirective { scope.isSchemaTypeDataType = this.DataTypesService.isDataTypeForSchemaType(scope.schemaProperty); if (scope.valueObjRef) { scope.mapKeys = Object.keys(scope.valueObjRef); + //keeping another copy of the keys, as the mapKeys gets overridden sometimes + scope.mapKeysStatic = Object.keys(scope.valueObjRef); } }); @@ -91,6 +94,8 @@ export class TypeMapDirective implements ng.IDirective { scope.valueObjRef = {}; } scope.mapKeys = Object.keys(scope.valueObjRef); + //keeping another copy of the keys, as the mapKeys gets overridden sometimes + scope.mapKeysStatic = Object.keys(scope.valueObjRef); if ($attr.defaultValue) { scope.mapDefaultValue = JSON.parse($attr.defaultValue); diff --git a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html index 7d8a883b33..706dbefb80 100644 --- a/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html +++ b/catalog-ui/src/app/directives/structure-tree/structure-tree-directive.html @@ -6,7 +6,7 @@ <ul> <li data-ng-repeat="firstLevelResourcesInstances in structureTree.serviceRoot.resourceInstancesList"> <div class="component-container"> - <div class="small {{firstLevelResourcesInstances.icon}}" ng-class="{'sprite-resource-icons': !component.isProduct(), 'sprite-services-icons': component.isProduct()}"> + <div class="small sprite-resource-icons {{firstLevelResourcesInstances.icon}}"> <div data-ng-class="{'non-certified':!firstLevelResourcesInstances.certified}" tooltips tooltip-side="top" tooltip-content="Not certified"> </div> diff --git a/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less b/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less index 942196e663..af24776cd3 100644 --- a/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less +++ b/catalog-ui/src/app/directives/utils/sdc-tags/sdc-tags.less @@ -1,10 +1,10 @@ .tags-box { - height: 297px; + height: 100px; .bg_c; .perfect-scrollbar { - height: 265px; + height: 70px; } .new-tag-input { diff --git a/catalog-ui/src/app/models.ts b/catalog-ui/src/app/models.ts index c7b7577268..f3eb5d5fa6 100644 --- a/catalog-ui/src/app/models.ts +++ b/catalog-ui/src/app/models.ts @@ -35,11 +35,9 @@ export * from './models/category'; export * from './models/comments'; export * from './models/components/component'; export * from './models/components/displayComponent'; -export * from './models/components/product'; export * from './models/components/resource'; export * from './models/components/service'; export * from './models/componentsInstances/componentInstance'; -export * from './models/componentsInstances/productInstance'; export * from './models/componentsInstances/resourceInstance'; export * from './models/componentsInstances/serviceInstance'; export * from './models/csar-component'; @@ -102,7 +100,7 @@ export * from './models/tooltip-data'; export * from './models/user'; export * from './models/validate'; export * from './models/component-metadata'; - +export * from './models/modal'; export * from './models/button'; export * from './models/filter-properties-assignment-data' export * from './models/properties-inputs/input-be-model' diff --git a/catalog-ui/src/app/models/app-config.ts b/catalog-ui/src/app/models/app-config.ts index ef6c195731..40eb18b8b4 100644 --- a/catalog-ui/src/app/models/app-config.ts +++ b/catalog-ui/src/app/models/app-config.ts @@ -54,10 +54,7 @@ export interface IApi { GET_activity_log:string; GET_configuration_ui:string; GET_service:string; - PUT_product:string; - GET_product:string; GET_ecomp_menu_items:string; - GET_product_validate_name:string; GET_service_validate_name:string; GET_service_distributions:string; GET_service_distributions_components:string; @@ -85,13 +82,6 @@ export interface IApi { GET_onboarding:string; GET_component_from_csar_uuid:string; kibana:string; - - //Added by Ikram -- starts - GET_product_category:string; - GET_product_category_temp:string; - GET_product_sub_category:string; - //Added by Ikram -- ends - } export interface ILogConfig { @@ -132,8 +122,6 @@ export interface IConfigRoles { TESTER:IConfigRole; OPS:IConfigRole; GOVERNOR:IConfigRole; - PRODUCT_MANAGER:IConfigRole; - PRODUCT_STRATEGIST:IConfigRole; } export interface IConfigRole { diff --git a/catalog-ui/src/app/models/categories.ts b/catalog-ui/src/app/models/categories.ts index b46c3a6612..0921ca158b 100644 --- a/catalog-ui/src/app/models/categories.ts +++ b/catalog-ui/src/app/models/categories.ts @@ -25,6 +25,5 @@ import {IMainCategory} from "./category"; export class Categories { resourceCategories:Array<IMainCategory>; - productCategories:Array<IMainCategory>; serviceCategories:Array<IMainCategory>; } diff --git a/catalog-ui/src/app/models/component-metadata.ts b/catalog-ui/src/app/models/component-metadata.ts index 2501f0bab5..8c6ed5593d 100644 --- a/catalog-ui/src/app/models/component-metadata.ts +++ b/catalog-ui/src/app/models/component-metadata.ts @@ -56,12 +56,15 @@ export class ComponentMetadata { public vendorName:string; public vendorRelease:string; public derivedFrom: Array<string>; + public resourceVendorModelNumber:string; //Service only public projectCode:string; public distributionStatus:string; public ecompGeneratedNaming: boolean; public namingPolicy: string; + public serviceType:string; + public serviceRole:string; //backend lifecycleState @@ -103,6 +106,9 @@ export class ComponentMetadata { this.ecompGeneratedNaming = response.ecompGeneratedNaming; this.namingPolicy = response.namingPolicy; this.derivedFrom = response.derivedFrom; + this.resourceVendorModelNumber = response.resourceVendorModelNumber; + this.serviceType = response.serviceType; + this.serviceRole = response.serviceRole; return this; } diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts index 0c47cc4cb2..53e8f05cbe 100644 --- a/catalog-ui/src/app/models/components/component.ts +++ b/catalog-ui/src/app/models/components/component.ts @@ -22,7 +22,7 @@ import {AsdcComment, ArtifactModel, ArtifactGroupModel, IFileDownload, PropertyModel, PropertiesGroup, AttributeModel, AttributesGroup, ComponentInstance, InputModel, DisplayModule, Module, IValidate, RelationshipModel, IMainCategory, RequirementsGroup, CapabilitiesGroup, AdditionalInformationModel, - Resource, IAppMenu, Product, Service} from "../../models"; + Resource, IAppMenu, Service} from "../../models"; import {IComponentService} from "../../services/components/component-service"; import {CommonUtils} from "../../utils/common-utils"; @@ -92,7 +92,6 @@ export interface IComponent { getComponentSubType():string; isAlreadyCertified():boolean; - isProduct():boolean; isService():boolean; isResource():boolean; isComplex():boolean; @@ -797,10 +796,6 @@ export abstract class Component implements IComponent { //------------------------------------------ Help Functions ----------------------------------------------------------------// - public isProduct = ():boolean => { - return this instanceof Product; - }; - public isService = ():boolean => { return this instanceof Service; }; @@ -928,16 +923,17 @@ export abstract class Component implements IComponent { } public toJSON = ():any => { - this.componentService = undefined; - this.filterTerm = undefined; - this.iconSprite = undefined; - this.mainCategory = undefined; - this.subCategory = undefined; - this.selectedInstance = undefined; - this.showMenu = undefined; - this.$q = undefined; - this.selectedCategory = undefined; - return this; + let temp = angular.copy(this); + temp.componentService = undefined; + temp.filterTerm = undefined; + temp.iconSprite = undefined; + temp.mainCategory = undefined; + temp.subCategory = undefined; + temp.selectedInstance = undefined; + temp.showMenu = undefined; + temp.$q = undefined; + temp.selectedCategory = undefined; + return temp; }; } diff --git a/catalog-ui/src/app/models/components/displayComponent.ts b/catalog-ui/src/app/models/components/displayComponent.ts index a5407e6d17..3a9cbfdaf3 100644 --- a/catalog-ui/src/app/models/components/displayComponent.ts +++ b/catalog-ui/src/app/models/components/displayComponent.ts @@ -97,9 +97,6 @@ export class LeftPaletteComponent { case ComponentType.SERVICE: this.iconClass = "sprite-services-icons " + icon; break; - case ComponentType.PRODUCT: - this.iconClass = "sprite-product-icons " + icon; - break; default: this.iconClass = "sprite-resource-icons " + icon; } diff --git a/catalog-ui/src/app/models/components/product.ts b/catalog-ui/src/app/models/components/product.ts deleted file mode 100644 index dfb429b971..0000000000 --- a/catalog-ui/src/app/models/components/product.ts +++ /dev/null @@ -1,125 +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========================================================= - */ - -/** - * Created by obarda on 2/4/2016. - */ -'use strict'; -import {Component} from "./component"; -import {IProductService} from "../../services/components/product-service"; -import {IGroup, ISubCategory, IMainCategory, ICategoryBase} from "../category"; -import {ComponentMetadata} from "../component-metadata"; - -export class Product extends Component { - - public contacts:Array<string>; - public componentService:IProductService; - public fullName:string; - - constructor(componentService:IProductService, $q:ng.IQService, component?:Product) { - super(componentService, $q, component); - - if (component) { - this.fullName = component.fullName; - this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version; - this.contacts = component.contacts; - } - this.componentService = componentService; - this.iconSprite = "sprite-product-icons"; - } - - public deleteGroup = (uniqueId:string):void => { - _.forEach(this.categories, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - subcategory.groupings = _.reject(subcategory.groupings, (group:IGroup) => { - return group.uniqueId === uniqueId; - }); - if (subcategory.groupings.length == 0) { // if there is no groups, delete the subcategory - category.subcategories = _.reject(category.subcategories, (subcategoryObj:ISubCategory) => { - return subcategoryObj.uniqueId === subcategory.uniqueId; - }); - if (category.subcategories.length == 0) { // if there is no subcategory, delete the category - this.categories = _.reject(this.categories, (categoryObj:IMainCategory) => { - return categoryObj.uniqueId === category.uniqueId; - }); - } - } - }); - }); - }; - - private getCategoryObjectById = (categoriesArray:Array<ICategoryBase>, categoryUniqueId:string):ICategoryBase => { - let categorySelected = _.find(categoriesArray, (category) => { - return category.uniqueId === categoryUniqueId; - }); - return categorySelected; - }; - - public addGroup = (category:IMainCategory, subcategory:ISubCategory, group:IGroup):void => { - if (!this.categories) { - this.categories = new Array<IMainCategory>(); - } - let existingCategory:IMainCategory = <IMainCategory>this.getCategoryObjectById(this.categories, category.uniqueId); - let newGroup = angular.copy(group); - newGroup.filterTerms = undefined; - newGroup.isDisabled = undefined; - if (!existingCategory) { - let newCategory:IMainCategory = angular.copy(category); - newCategory.filteredGroup = undefined; - newCategory.subcategories = []; - let newSubcategory:ISubCategory = angular.copy(subcategory); - newSubcategory.groupings = []; - newSubcategory.groupings.push(newGroup); - newCategory.subcategories.push(newSubcategory); - this.categories.push(newCategory); - } - else { - let existingSubcategory:ISubCategory = <ISubCategory> this.getCategoryObjectById(existingCategory.subcategories, subcategory.uniqueId); - if (!existingSubcategory) { - let newSubcategory:ISubCategory = angular.copy(subcategory); - newSubcategory.groupings = []; - newSubcategory.groupings.push(newGroup); - existingCategory.subcategories.push(newSubcategory); - - } else { - let existingGroup:IGroup = <IGroup> this.getCategoryObjectById(existingSubcategory.groupings, group.uniqueId); - if (!existingGroup) { - existingSubcategory.groupings.push(newGroup); - } - } - } - }; - - getTypeUrl():string { - return 'products/'; - } - - public setComponentMetadata(componentMetadata:ComponentMetadata) { - super.setComponentMetadata(componentMetadata); - this.setComponentDisplayData(); - }; - - setComponentDisplayData():void { - this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version; - this.iconSprite = "sprite-product-icons"; - } -} - - diff --git a/catalog-ui/src/app/models/components/resource.ts b/catalog-ui/src/app/models/components/resource.ts index 9f7a123486..cd839786c5 100644 --- a/catalog-ui/src/app/models/components/resource.ts +++ b/catalog-ui/src/app/models/components/resource.ts @@ -41,6 +41,7 @@ export class Resource extends Component { public payloadData:string; public payloadName:string; public importedFile:FileUploadModel; + public resourceVendorModelNumber:string; // Onboarding parameters public csarUUID:string; @@ -59,6 +60,7 @@ export class Resource extends Component { this.resourceType = component.resourceType; this.csarUUID = component.csarUUID; this.csarVersion = component.csarVersion; + this.resourceVendorModelNumber = component.resourceVendorModelNumber; this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version + ' ' + this.resourceType; if (component.categories && component.categories[0] && component.categories[0].subcategories && component.categories[0].subcategories[0]) { component.mainCategory = component.categories[0].name; @@ -80,6 +82,7 @@ export class Resource extends Component { this.csarUUID = componentMetadata.csarUUID; this.csarVersion = componentMetadata.csarVersion; this.derivedFrom = componentMetadata.derivedFrom; + this.resourceVendorModelNumber = componentMetadata.resourceVendorModelNumber; this.setComponentDisplayData(); }; @@ -88,7 +91,7 @@ export class Resource extends Component { }; public isComplex = ():boolean => { - return this.resourceType === ResourceType.VF; + return this.resourceType === ResourceType.VF || this.resourceType === ResourceType.PNF || this.resourceType === ResourceType.CVFC; }; public isVl = ():boolean => { @@ -160,17 +163,18 @@ export class Resource extends Component { }; public toJSON = ():any => { - this.componentService = undefined; - this.filterTerm = undefined; - this.iconSprite = undefined; - this.mainCategory = undefined; - this.subCategory = undefined; - this.selectedInstance = undefined; - this.showMenu = undefined; - this.$q = undefined; - this.selectedCategory = undefined; - this.importedFile = undefined; - return this; + let temp = angular.copy(this); + temp.componentService = undefined; + temp.filterTerm = undefined; + temp.iconSprite = undefined; + temp.mainCategory = undefined; + temp.subCategory = undefined; + temp.selectedInstance = undefined; + temp.showMenu = undefined; + temp.$q = undefined; + temp.selectedCategory = undefined; + temp.importedFile = undefined; + return temp; }; } diff --git a/catalog-ui/src/app/models/components/service.ts b/catalog-ui/src/app/models/components/service.ts index fbe32519c3..90a38e895b 100644 --- a/catalog-ui/src/app/models/components/service.ts +++ b/catalog-ui/src/app/models/components/service.ts @@ -34,6 +34,8 @@ export class Service extends Component { public componentService:IServiceService; public ecompGeneratedNaming:boolean; public namingPolicy:string; + public serviceType:string; + public serviceRole:string; constructor(componentService:IServiceService, $q:ng.IQService, component?:Service) { super(componentService, $q, component); @@ -43,6 +45,8 @@ export class Service extends Component { this.filterTerm = this.name + ' ' + this.description + ' ' + (this.tags ? this.tags.toString() : '') + ' ' + this.version; this.ecompGeneratedNaming = component.ecompGeneratedNaming; this.namingPolicy = component.namingPolicy; + this.serviceType = component.serviceType; + this.serviceRole = component.serviceRole; if (component.categories && component.categories[0]) { this.mainCategory = component.categories[0].name; this.selectedCategory = this.mainCategory; @@ -155,6 +159,8 @@ export class Service extends Component { super.setComponentMetadata(componentMetadata); this.ecompGeneratedNaming = componentMetadata.ecompGeneratedNaming; this.namingPolicy = componentMetadata.namingPolicy; + this.serviceType = componentMetadata.serviceType; + this.serviceRole = componentMetadata.serviceRole; this.setComponentDisplayData(); } diff --git a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts index 726e3382ba..06939a7a9e 100644 --- a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts +++ b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts @@ -52,6 +52,7 @@ export class ComponentInstance { public inputs:Array<InputModel>; public properties:Array<PropertyModel>; public groupInstances:Array<Module>; + public invariantName:string; constructor(componentInstance?:ComponentInstance) { @@ -77,6 +78,7 @@ export class ComponentInstance { this.customizationUUID = componentInstance.customizationUUID; this.updatePosition(componentInstance.posX, componentInstance.posY); this.groupInstances = componentInstance.groupInstances; + this.invariantName = componentInstance.invariantName; } } @@ -92,7 +94,7 @@ export class ComponentInstance { }; public isComplex = () : boolean => { - return this.originType === ResourceType.VF; + return this.originType === ResourceType.VF || this.originType === ResourceType.PNF || this.originType === ResourceType.CVFC ; } public setInstanceRC = ():void=> { diff --git a/catalog-ui/src/app/models/componentsInstances/productInstance.ts b/catalog-ui/src/app/models/componentsInstances/productInstance.ts deleted file mode 100644 index 91f0999b9a..0000000000 --- a/catalog-ui/src/app/models/componentsInstances/productInstance.ts +++ /dev/null @@ -1,33 +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========================================================= - */ - -/** - * Created by obarda on 2/4/2016. - */ -'use strict'; -import {ComponentInstance} from "./componentInstance"; - -export class ProductInstance extends ComponentInstance { - - constructor(componentInstance?:ProductInstance) { - super(componentInstance); - this.iconSprite = "sprite-product-icons"; - } -} diff --git a/catalog-ui/src/app/models/modal.ts b/catalog-ui/src/app/models/modal.ts new file mode 100644 index 0000000000..51aa5e19a7 --- /dev/null +++ b/catalog-ui/src/app/models/modal.ts @@ -0,0 +1,16 @@ +import { ButtonModel } from 'app/models'; + +export class ModalModel { + size: string; 'xl|l|md|sm|xsm' + title: string; + content: any; + buttons: Array<ButtonModel>; + + constructor(size?: string, title?: string, content?: any, buttons?: Array<ButtonModel>) { + this.size = size; + this.title = title; + this.content = content; + this.buttons = buttons; + } +} + diff --git a/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts index 04a224bff7..630374aac3 100644 --- a/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/input-fe-model.ts @@ -40,4 +40,4 @@ export class InputFEModel extends InputBEModel { } } -} +}
\ No newline at end of file diff --git a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts index 78d01d9af2..b35bb27b65 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-fe-model.ts @@ -55,7 +55,7 @@ export class PropertyFEModel extends PropertyBEModel { } catch (e){} } - return (this.derivedDataType == DerivedPropertyType.SIMPLE) ? this.valueObj : JSON.stringify(this.valueObj); + return (this.derivedDataType == DerivedPropertyType.SIMPLE) ? this.valueObj : JSON.stringify(this.valueObj); } public setNonDeclared = (childPath?: string): void => { @@ -101,16 +101,16 @@ export class PropertyFEModel extends PropertyBEModel { // this.flattenedChildren.filter(prop => prop.parentName == item.parentName).map(prop => prop.propertiesName).indexOf(item.propertiesName) // } - /* Updates parent valueObj when a child prop's value has changed */ - public childPropUpdated = (childProp: DerivedFEProperty): void => { + /* Updates parent valueObj when a child prop's value has changed */ + public childPropUpdated = (childProp: DerivedFEProperty): void => { let parentNames = this.getParentNamesArray(childProp.propertiesName, []); if (parentNames.length) { _.set(this.valueObj, parentNames.join('.'), childProp.valueObj); } }; - /* Returns array of individual parents for given prop path, with list/map UUIDs replaced with index/mapkey */ - private getParentNamesArray = (parentPropName: string, parentNames?: Array<string>): Array<string> => { + /* Returns array of individual parents for given prop path, with list/map UUIDs replaced with index/mapkey */ + public getParentNamesArray = (parentPropName: string, parentNames?: Array<string>): Array<string> => { if (parentPropName.indexOf("#") == -1) { return parentNames; } //finished recursing parents. return let parentProp: DerivedFEProperty = this.flattenedChildren.find(prop => prop.propertiesName === parentPropName); diff --git a/catalog-ui/src/app/models/user.ts b/catalog-ui/src/app/models/user.ts index ec42aed553..54ddf1e5f6 100644 --- a/catalog-ui/src/app/models/user.ts +++ b/catalog-ui/src/app/models/user.ts @@ -26,9 +26,7 @@ export enum UserRole { DESIGNER, TESTER, GOVERNOR, - OPS, - PRODUCT_MANAGER, - PRODUCT_STRATEGIST + OPS } export interface IUserManager { @@ -99,12 +97,6 @@ export class User implements IUser { case UserRole.OPS: role = UserRole.OPS; break; - case UserRole.PRODUCT_MANAGER: - role = UserRole.PRODUCT_MANAGER; - break; - case UserRole.PRODUCT_STRATEGIST: - role = UserRole.PRODUCT_STRATEGIST; - break; } return role; } diff --git a/catalog-ui/src/app/modules/service-module.ts b/catalog-ui/src/app/modules/service-module.ts index bf9ebce749..99624ada45 100644 --- a/catalog-ui/src/app/modules/service-module.ts +++ b/catalog-ui/src/app/modules/service-module.ts @@ -35,7 +35,6 @@ import {DataTypesService} from "../services/data-types-service"; import {ComponentService} from "../services/components/component-service"; import {ServiceService} from "../services/components/service-service"; import {ResourceService} from "../services/components/resource-service"; -import {ProductService} from "../services/components/product-service"; import {LeftPaletteLoaderService} from "../services/components/utils/composition-left-palette-service"; import {EventListenerService} from "../services/event-listener-service"; import {ProgressService} from "../services/progress-service"; @@ -69,7 +68,6 @@ serviceModule.service('Sdc.Services.DataTypesService', DataTypesService); serviceModule.service('Sdc.Services.Components.ComponentService', ComponentService); serviceModule.service('Sdc.Services.Components.ServiceService',ServiceService); serviceModule.service('Sdc.Services.Components.ResourceService', ResourceService); -serviceModule.service('Sdc.Services.Components.ProductService', ProductService); serviceModule.service('LeftPaletteLoaderService', LeftPaletteLoaderService); serviceModule.service('EventListenerService', EventListenerService); serviceModule.service('Sdc.Services.ProgressService', ProgressService); diff --git a/catalog-ui/src/app/modules/view-model-module.ts b/catalog-ui/src/app/modules/view-model-module.ts index de7bc5ac1f..f94bfc3218 100644 --- a/catalog-ui/src/app/modules/view-model-module.ts +++ b/catalog-ui/src/app/modules/view-model-module.ts @@ -56,13 +56,12 @@ import {OnboardingModalViewModel} from "../view-models/modals/onboarding-modal/o import {DistributionStatusModalViewModel} from "../view-models/workspace/tabs/distribution/disribution-status-modal/disribution-status-modal-view-model"; import {DcaeAppViewModel} from "../view-models/dcae-app/dcae-app-view-model"; import {GeneralViewModel} from "../view-models/workspace/tabs/general/general-view-model"; -import {IconsViewModel} from "../view-models/workspace/tabs/icons/icons-view-model"; +import {IconsModalViewModel} from "../view-models/modals/icons-modal/icons-modal-view"; import {DeploymentArtifactsViewModel} from "../view-models/workspace/tabs/deployment-artifacts/deployment-artifacts-view-model"; import {InformationArtifactsViewModel} from "../view-models/workspace/tabs/information-artifacts/information-artifacts-view-model"; import {ToscaArtifactsViewModel} from "../view-models/workspace/tabs/tosca-artifacts/tosca-artifacts-view-model"; import {PropertiesViewModel} from "../view-models/workspace/tabs/properties/properties-view-model"; import {AttributesViewModel} from "../view-models/workspace/tabs/attributes/attributes-view-model"; -import {ProductHierarchyViewModel} from "../view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model"; import {ActivityLogViewModel} from "../view-models/workspace/tabs/activity-log/activity-log"; import {ManagementWorkflowViewModel} from "../view-models/workspace/tabs/management-workflow/management-workflow-view-model"; import {NetworkCallFlowViewModel} from "../view-models/workspace/tabs/network-call-flow/network-call-flow-view-model"; @@ -114,6 +113,7 @@ viewModelModule .controller(moduleName + '.UserManagementViewModel', UserManagementViewModel) .controller(moduleName + '.CategoryManagementViewModel', CategoryManagementViewModel) .controller(moduleName + '.OnboardingModalViewModel', OnboardingModalViewModel) + .controller(moduleName + '.IconsModalViewModel', IconsModalViewModel) .controller(moduleName + '.DistributionStatusModalViewModel', DistributionStatusModalViewModel) .controller(moduleName + '.DcaeAppViewModel', DcaeAppViewModel) // @@ -122,13 +122,11 @@ viewModelModule .controller(moduleName + '.ConformanceLevelModalViewModel', ConformanceLevelModalViewModel) .controller(moduleName + '.CompositionViewModel', CompositionViewModel) .controller(moduleName + '.GeneralViewModel', GeneralViewModel) - .controller(moduleName + '.IconsViewModel', IconsViewModel) .controller(moduleName + '.DeploymentArtifactsViewModel', DeploymentArtifactsViewModel) .controller(moduleName + '.InformationArtifactsViewModel', InformationArtifactsViewModel) .controller(moduleName + '.ToscaArtifactsViewModel', ToscaArtifactsViewModel) .controller(moduleName + '.PropertiesViewModel', PropertiesViewModel) .controller(moduleName + '.AttributesViewModel', AttributesViewModel) - .controller(moduleName + '.ProductHierarchyViewModel', ProductHierarchyViewModel) .controller(moduleName + '.ActivityLogViewModel', ActivityLogViewModel) .controller(moduleName + '.ManagementWorkflowViewModel', ManagementWorkflowViewModel) .controller(moduleName + '.NetworkCallFlowViewModel', NetworkCallFlowViewModel) diff --git a/catalog-ui/src/app/ng2/app.component.ts b/catalog-ui/src/app/ng2/app.component.ts index 58f483ae11..cb10581c93 100644 --- a/catalog-ui/src/app/ng2/app.component.ts +++ b/catalog-ui/src/app/ng2/app.component.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import { Component, Inject } from '@angular/core'; +import { Component, Inject, ViewContainerRef } from '@angular/core'; import { AuthenticationService } from './services/authentication.service'; @Component({ @@ -28,7 +28,7 @@ import { AuthenticationService } from './services/authentication.service'; }) export class AppComponent { - constructor(auth:AuthenticationService){ + constructor(auth:AuthenticationService, public viewContainerRef:ViewContainerRef){ } diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 09b40e920f..57adb8fd66 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -40,6 +40,8 @@ import {ComponentInstanceServiceNg2} from "./services/component-instance-service import { InterceptorService } from 'ng2-interceptors'; import { XHRBackend, RequestOptions } from '@angular/http'; import {HttpInterceptor} from "./services/http.interceptor.service"; +import { SearchBarComponent } from './shared/search-bar/search-bar.component'; +import { SearchWithAutoCompleteComponent } from './shared/search-with-autocomplete/search-with-autocomplete.component'; export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule)); @@ -60,7 +62,9 @@ export function interceptorFactory(xhrBackend: XHRBackend, requestOptions: Reque @NgModule({ declarations: [ - AppComponent + AppComponent, + SearchBarComponent, + SearchWithAutoCompleteComponent ], imports: [ BrowserModule, @@ -70,7 +74,7 @@ export function interceptorFactory(xhrBackend: XHRBackend, requestOptions: Reque PropertiesAssignmentModule ], exports: [], - entryComponents: [], + entryComponents: [SearchWithAutoCompleteComponent], providers: [ DataTypesServiceProvider, SharingServiceProvider, diff --git a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html deleted file mode 100644 index 7fdd95b304..0000000000 --- a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.html +++ /dev/null @@ -1,3 +0,0 @@ -<modal #confirmationModal title="Delete Input" size="sm" [buttons]="footerButtons"> - Are you sure you want to delete this input? -</modal> diff --git a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts b/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts deleted file mode 100644 index f73692f525..0000000000 --- a/catalog-ui/src/app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component.ts +++ /dev/null @@ -1,58 +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========================================================= - */ - -/** - * Created by rc2122 on 6/1/2017. - */ -import {Component, Output, EventEmitter, ViewChild} from "@angular/core"; -import {ButtonsModelMap, ButtonModel} from "app/models/button"; -import {ModalComponent} from "app/ng2/components/modal/modal.component"; - -@Component({ - selector: 'confirm-delete-input', - templateUrl: './confirmation-delete-input.component.html' -}) -export class ConfirmationDeleteInputComponent { - - @Output() deleteInput: EventEmitter<any> = new EventEmitter<any>(); - @ViewChild ('confirmationModal') confirmationModal:ModalComponent; - footerButtons:ButtonsModelMap = {}; - - constructor (){ - } - - ngOnInit() { - this.footerButtons['Delete'] = new ButtonModel('Delete', 'blue', this.onDeleteInput); - this.footerButtons['Close'] = new ButtonModel('Close', 'grey', this.closeModal); - } - - onDeleteInput = (input) => { - this.deleteInput.emit(input); - this.closeModal(); - }; - - openModal = () => { - this.confirmationModal.open(); - } - - closeModal = () => { - this.confirmationModal.close(); - } -} diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html index 331415c26f..38de3ce649 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html @@ -45,6 +45,5 @@ </div> </div> </div> -<confirm-delete-input #deleteInputConfirmation (deleteInput)="onDeleteInput()"></confirm-delete-input> diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less index 05378f0eb9..89c7287449 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less @@ -85,7 +85,7 @@ border-right:#d2d2d2 solid 1px; } &.col1 { - flex: 0 0 300px; + flex: 1 0 200px; max-width:300px; display: flex; justify-content: space-between; diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts index 526f5de360..30cdb89d8e 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts @@ -23,7 +23,9 @@ */ import {Component, Input, Output, EventEmitter, ViewChild} from "@angular/core"; import {InputFEModel} from "app/models"; -import {ConfirmationDeleteInputComponent} from "./confirmation-delete-input/confirmation-delete-input.component"; +import { ModalService } from 'app/ng2/services/modal.service'; + + @Component({ selector: 'inputs-table', @@ -38,11 +40,10 @@ export class InputsTableComponent { @Input() isLoading:boolean; @Output() inputValueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() deleteInput: EventEmitter<any> = new EventEmitter<any>(); - @ViewChild ('deleteInputConfirmation') deleteInputConfirmation:ConfirmationDeleteInputComponent; selectedInputToDelete:InputFEModel; - constructor (){ + constructor(private modalService: ModalService){ } onInputValueChanged = (input) => { @@ -51,11 +52,12 @@ export class InputsTableComponent { onDeleteInput = () => { this.deleteInput.emit(this.selectedInputToDelete); + this.modalService.closeCurrentModal(); }; openDeleteModal = (input:InputFEModel) => { this.selectedInputToDelete = input; - this.deleteInputConfirmation.openModal(); + this.modalService.openActionModal("Delete Input", "Are you sure you want to delete this input?", "Delete", this.onDeleteInput, "Close"); } } diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.html b/catalog-ui/src/app/ng2/components/modal/modal.component.html index 4882449596..cc411bc751 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.html +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.html @@ -1,17 +1,15 @@ -<div class="custom-modal {{size}}"> +<div class="custom-modal {{input.size}}"> <div class="ng2-modal-content"> <div class="ng2-modal-header"> - <span class="title">{{ title }}</span> + <span class="title">{{ input.title }}</span> <span class="close-button" (click)="close()"></span> </div> - <div class="ng2-modal-body"> - <ng-content></ng-content> - </div> + <div class="ng2-modal-body" >{{input.content}}</div> <div class="ng2-modal-footer"> - <button *ngFor="let buttonName of buttonsNames" - class="tlv-btn {{buttons[buttonName].cssClass}}" - [disabled] = "buttons[buttonName].getDisabled && buttons[buttonName].getDisabled()" - (click) = "buttons[buttonName].callback()">{{buttons[buttonName].text}}</button> + <button *ngFor="let button of input.buttons" + class="tlv-btn {{button.cssClass}}" + [disabled] = "button.getDisabled && button.getDisabled()" + (click) = "button.callback()">{{button.text}}</button> </div> </div> </div> diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/modal/modal.component.ts index e432a6fde0..09fb9abdd1 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.ts +++ b/catalog-ui/src/app/ng2/components/modal/modal.component.ts @@ -22,8 +22,9 @@ * Created by rc2122 on 6/1/2017. */ import { Component, ElementRef, Input, OnInit, OnDestroy } from '@angular/core'; +//import {ViewContainerRef, ViewChild} from '@angular/core'; import * as $ from 'jquery'; -import {ButtonsModelMap} from "app/models/button"; +import { ButtonsModelMap, ModalModel } from 'app/models'; @Component({ selector: 'modal', @@ -32,22 +33,17 @@ import {ButtonsModelMap} from "app/models/button"; }) export class ModalComponent implements OnInit, OnDestroy { - @Input() size: string; 'xl|l|md|sm|xsm' - @Input() title: string; - @Input() public buttons:ButtonsModelMap; + @Input() input: ModalModel; private modalElement: JQuery; - private buttonsNames:Array<string>; + //@ViewChild('modalBody', { read: ViewContainerRef }) modalContainer: ViewContainerRef; //TODO: allow for custom component as body instead of simple message + constructor( el: ElementRef ) { this.modalElement = $(el.nativeElement); } ngOnInit(): void { - let modal = this; this.modalElement.appendTo('body'); - if(this.buttons){ - this.buttonsNames = Object.keys(this.buttons); - } } ngOnDestroy(): void { diff --git a/catalog-ui/src/app/ng2/components/modal/modal.module.ts b/catalog-ui/src/app/ng2/components/modal/modal.module.ts new file mode 100644 index 0000000000..d77be2cd23 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/modal/modal.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from '@angular/common'; +import { ModalService } from 'app/ng2/services/modal.service'; +import { ModalComponent } from "app/ng2/components/modal/modal.component" + +@NgModule({ + declarations: [ + ModalComponent, + ], + imports: [CommonModule], + exports: [], + entryComponents: [ + ModalComponent + ], + providers: [ModalService] +}) +export class ModalModule { + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html index 92948b3b0d..95cc79dce9 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html @@ -5,12 +5,12 @@ <!-- LEFT CELL --> <ng-container *ngIf="!isPropertyFEModel"> <div class="table-cell" *ngIf="canBeDeclared" [ngClass]="{'filtered':property.name === propertyNameSearchText}" [class.round-checkbox]="property.isDeclared"> <!-- simple children of complex type [@checkEffect]="property.isDeclared"--> - <checkbox [(checked)]="property.isSelected" [disabled]="property.isDisabled ||property.isDeclared || readonly" (checkedChange)="checkProperty.emit(property.propertiesName)" ></checkbox> + <checkbox [(checked)]="property.isSelected" [disabled]="property.isDisabled ||property.isDeclared || readonly" (checkedChange)="checkProperty.emit(property.propertiesName)" ></checkbox> <div class="inner-cell-div" tooltip="{{property.name}}"><span>{{property.name}}</span></div> </div> <div class="table-cell" *ngIf="!canBeDeclared && !property.isChildOfListOrMap">{{property.name}}</div> <!-- simple children of complex type within map or list --> <div class="table-cell map-entry" *ngIf="property.isChildOfListOrMap && propType == derivedPropertyTypes.MAP"><!-- map left cell --> - <input [value]="property.mapKey" #mapKey (change)="mapKeyChanged.emit(mapKey.value)" [readonly]="readonly" type="text" [ngClass]="{'disabled':readonly}" /> + <input [value]="property.mapKey" #mapKey (change)="mapKeyChanged.emit(mapKey)" [readonly]="readonly" type="text" [ngClass]="{'disabled':readonly, 'error':!mapKey.validity.valid}" /> </div> </ng-container> <!-- RIGHT CELL OR FULL WIDTH CELL--> @@ -36,7 +36,7 @@ </ng-container> <!-- ICONS: add, delete, and expand --> <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}">Add value to list</a> + <a *ngIf="(propType == derivedPropertyTypes.LIST || propType == derivedPropertyTypes.MAP) && !property.isChildOfListOrMap" class="property-icon add-item" (click)="createNewChildProperty();" [ngClass]="{'disabled':readonly || preventInsertItem(property)}">Add value to list</a> <span *ngIf="property.isChildOfListOrMap" (click)="deleteItem.emit(property);" class="property-icon sprite-new delete-item-icon" [ngClass]="{'disabled':readonly}"></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"></span> </ng-container> diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less index 4da98ec736..48d3d035d0 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less @@ -1,3 +1,4 @@ +@import '../../../../../assets/styles/variables.less'; .flat-children-container { .dynamic-property-row { /*create nested left border classes for up to 10 levels of nesting*/ @@ -64,4 +65,10 @@ overflow: hidden; display: inline; padding-left: 8px; -}
\ No newline at end of file +} +.error { + border: solid 1px @func_color_q; + color: @func_color_q; + outline: none; + box-sizing: border-box; +} diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts index e078b74d65..59811b582d 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts +++ b/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts @@ -88,7 +88,7 @@ export class DynamicPropertyComponent { } createNewChildProperty = (): void => { - + let newProps: Array<DerivedFEProperty> = this.propertiesUtils.createListOrMapChildren(this.property, "", undefined); if (this.property instanceof PropertyFEModel) { this.addChildProps(newProps, this.property.name); @@ -98,11 +98,22 @@ export class DynamicPropertyComponent { } addChildProps = (newProps: Array<DerivedFEProperty>, childPropName: string) => { - + if (this.property instanceof PropertyFEModel) { - let insertIndex: number = this.property.getIndexOfChild(childPropName) + this.property.getCountOfChildren(childPropName); //insert after parent prop and existing children - this.property.flattenedChildren.splice(insertIndex, 0, ...newProps); //using ES6 spread operator + let insertIndex: number = this.property.getIndexOfChild(childPropName) + this.property.getCountOfChildren(childPropName); //insert after parent prop and existing children + this.property.flattenedChildren.splice(insertIndex, 0, ...newProps); //using ES6 spread operator this.expandChildById(newProps[0].propertiesName); + + + if(!newProps[0].schema.property.isSimpleType){ + angular.forEach(newProps, (prop:DerivedFEProperty):void => { //Update parent PropertyFEModel with value for each child, including nested props + (<PropertyFEModel>this.property).childPropUpdated(prop); + },this); + //grab the cumulative value for the new item from parent PropertyFEModel and assign that value to DerivedFEProp[0] (which is the list or map parent with UUID of the set we just added) + let parentNames = (<PropertyFEModel>this.property).getParentNamesArray(newProps[0].propertiesName, []); + newProps[0].valueObj = _.get(this.property.valueObj, parentNames.join('.')); + this.valueChanged.emit(this.property.name); + } } } @@ -113,7 +124,7 @@ export class DynamicPropertyComponent { this.dataTypeService.checkForCustomBehavior(this.property); this.valueChanged.emit(this.property.name); } - } + } deleteListOrMapItem = (item: DerivedFEProperty) => { if (this.property instanceof PropertyFEModel) { @@ -123,15 +134,22 @@ export class DynamicPropertyComponent { } } - removeValueFromParent = (item: DerivedFEProperty, replaceKey?: string) => { + removeValueFromParent = (item: DerivedFEProperty, target?: any) => { if (this.property instanceof PropertyFEModel) { let itemParent = (item.parentName == this.property.name) ? this.property : this.property.flattenedChildren.find(prop => prop.propertiesName == item.parentName); if (item.derivedDataType == DerivedPropertyType.MAP) { let oldKey = item.mapKey; - if (typeof replaceKey == 'string') { //allow saving empty string - _.set(itemParent.valueObj, replaceKey, itemParent.valueObj[oldKey]); - item.mapKey = replaceKey; + if (target && typeof target.value == 'string') { //allow saving empty string + let replaceKey:string = target.value; + if(Object.keys(itemParent.valueObj).indexOf(replaceKey) > -1){//the key is exists + target.setCustomValidity('This key is already exists.'); + return; + }else { + target.setCustomValidity(''); + _.set(itemParent.valueObj, replaceKey, itemParent.valueObj[oldKey]); + item.mapKey = replaceKey; + } } delete itemParent.valueObj[oldKey]; } else { @@ -147,4 +165,11 @@ export class DynamicPropertyComponent { } } + preventInsertItem = (property:DerivedFEProperty):boolean => { + if(property.type == PROPERTY_TYPES.MAP && Object.keys(property.valueObj).indexOf('') > -1 ){ + return true; + } + return false; + } + } diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less index 3eb7e960ab..9ede84faff 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less +++ b/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less @@ -91,7 +91,7 @@ border-right:#d2d2d2 solid 1px; } &.col1 { - flex: 0 0 300px; + flex: 1 0 210px; max-width:300px; display: flex; justify-content: space-between; @@ -100,7 +100,7 @@ .property-name { flex: 1; display: flex; - max-width: 270px; + max-width: 90%; } .property-description-icon { @@ -123,7 +123,7 @@ } &.valueCol { - flex: 1 0 350px; + flex: 2 0 300px; display: flex; @media @smaller-screen { flex: 1 0 40%;} } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts index 1e09c9e4c6..3a5daba711 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.module.ts @@ -37,14 +37,13 @@ import { HierarchyNavService } from './../../services/hierarchy-nav.service'; import { PropertiesUtils } from './properties.utils'; import { DynamicElementModule } from 'app/ng2/components/dynamic-element/dynamic-element.module'; import { DynamicPropertyComponent } from './../../components/properties-table/dynamic-property/dynamic-property.component'; -import {ConfirmationDeleteInputComponent} from "app/ng2/components/inputs-table/confirmation-delete-input/confirmation-delete-input.component" -import { PopoverModule } from "../../components/popover/popover.module" +import { PopoverModule } from "../../components/popover/popover.module"; +import { ModalModule } from "../../components/modal/modal.module"; import { FilterPropertiesAssignmentComponent } from "./../../components/filter-properties-assignment/filter-properties-assignment.component"; import { GroupByPipe } from 'app/ng2/pipes/groupBy.pipe'; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; import {TooltipModule} from "../../components/tooltip/tooltip.module"; import { ComponentModeService } from "app/ng2/services/component-mode.service" -import { ModalComponent } from "app/ng2/components/modal/modal.component" import {LoaderComponent} from "app/ng2/components/loader/loader.component" import {HttpInterceptor} from "../../services/http.interceptor.service"; @@ -63,8 +62,6 @@ import {HttpInterceptor} from "../../services/http.interceptor.service"; // PopoverContentComponent, // PopoverComponent, FilterPropertiesAssignmentComponent, - ModalComponent, - ConfirmationDeleteInputComponent, LoaderComponent ], imports: [ @@ -75,7 +72,8 @@ import {HttpInterceptor} from "../../services/http.interceptor.service"; CheckboxModule, DynamicElementModule, PopoverModule, - TooltipModule + TooltipModule, + ModalModule ], entryComponents: [PropertiesAssignmentComponent], exports: [ diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less index ab059b1240..8151d001e8 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.less @@ -27,7 +27,6 @@ .left-column { flex: 1 0 500px; position: relative; - margin: 0 0 1em 0; /deep/ .tabs { width:33%; @@ -119,7 +118,7 @@ display:flex; flex:0 0 350px; flex-direction:column; - margin: 45px 0 1em 1em; + margin: 45px 0 0 1em; overflow-x:auto; /deep/ .tabs { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts index 30ba6c0755..6782b72fa2 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.ts @@ -170,6 +170,10 @@ export class PropertiesAssignmentComponent { }); } + if(resourceInstance.componentName === "vnfConfiguration") { + this.isReadonly = true; + } + if( this.searchPropertyName ){ this.clearSearch(); } @@ -298,7 +302,7 @@ export class PropertiesAssignmentComponent { angular.forEach(instancesIds, (instanceId: string): void => { let selectedInstanceData: ResourceInstance = this.instances.find(instance => instance.uniqueId == instanceId); - let originType: string = (selectedInstanceData) ? selectedInstanceData.originType : this.selectedInstanceType; + let originType: string = (selectedInstanceData) ? selectedInstanceData.originType : this.selectedInstanceType; if (!this.isInput(originType)) { selectedProperties[instanceId] = this.propertiesService.getCheckedProperties(this.instanceFePropertiesMap[instanceId]); } else { @@ -408,7 +412,7 @@ export class PropertiesAssignmentComponent { }; private isInput = (instanceType:string):boolean =>{ - return instanceType === ResourceType.VF || instanceType === ResourceType.PNF; + return instanceType === ResourceType.VF || instanceType === ResourceType.PNF || instanceType === ResourceType.CVFC; } } diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts index a3507feb6f..a04d23a16a 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts @@ -56,21 +56,21 @@ export class PropertiesUtils { if (newFEProp.getInputValues && newFEProp.getInputValues.length) { //if this prop (or any children) are declared, set isDeclared and disable checkbox on parents/children newFEProp.getInputValues.forEach(propInputDetail => { let inputPath = propInputDetail.inputPath; - if (!isVF && !inputPath) { //TODO: this is a workaround until Marina adds inputPath + if (!inputPath) { //TODO: this is a workaround until Marina adds inputPath let input = inputs.find(input => input.uniqueId == propInputDetail.inputId); if (!input) { console.log("CANNOT FIND INPUT FOR " + propInputDetail.inputId); return; } else inputPath = input.inputPath; } - if (isVF || inputPath == newFEProp.name) inputPath = undefined; + if (inputPath == newFEProp.name) inputPath = undefined; // if not complex we need to remove the inputPath from FEModel so we not look for a child newFEProp.setAsDeclared(inputPath); //if a path is sent, its a child prop. this param is optional this.propertiesService.disableRelatedProperties(newFEProp, inputPath); }); - } + } this.initValueObjectRef(newFEProp); //initialize valueObj. propertyFeArray.push(newFEProp); newFEProp.updateExpandedChildPropertyId(newFEProp.name); //display only the first level of children this.dataTypeService.checkForCustomBehavior(newFEProp); - } + } }); instanceFePropertiesMap[instanceId] = propertyFeArray; @@ -101,8 +101,8 @@ export class PropertiesUtils { this.dataTypeService.getDerivedDataTypeProperties(dataTypeObj, tempProps, parentName); return tempProps; } - - /* Sets the valueObj of parent property and its children. + + /* Sets the valueObj of parent property and its children. * Note: This logic is different than assignflattenedchildrenvalues - here we merge values, there we pick either the parents value, props value, or default value - without merging. */ public initValueObjectRef = (property: PropertyFEModel): void => { @@ -138,9 +138,12 @@ export class PropertiesUtils { let propNameInObj = prop.propertiesName.substring(prop.propertiesName.indexOf(parentName) + parentName.length + 1).split('#').join('.'); //extract everything after parent name prop.valueObj = _.get(parentValueJSON, propNameInObj, prop.value || prop.defaultValue); //assign value -first value of parent if exists. If not, prop.value if not, prop.defaultvalue - - if ((prop.derivedDataType == DerivedPropertyType.SIMPLE || prop.isDeclared) && typeof prop.valueObj == 'object') { //Stringify objects that should be strings + + if ( prop.isDeclared && typeof prop.valueObj == 'object') { //Stringify objects of items that are declared prop.valueObj = JSON.stringify(prop.valueObj); + } else if(typeof prop.valueObj == PROPERTY_TYPES.STRING + && (prop.type == PROPERTY_TYPES.INTEGER || prop.type == PROPERTY_TYPES.FLOAT || prop.type == PROPERTY_TYPES.BOOLEAN)){ //parse ints and non-string simple types + prop.valueObj = JSON.parse(prop.valueObj); } else { //parse strings that should be objects if (prop.derivedDataType == DerivedPropertyType.COMPLEX && typeof prop.valueObj != 'object') { prop.valueObj = JSON.parse(prop.valueObj || '{}'); @@ -148,7 +151,7 @@ export class PropertiesUtils { prop.valueObj = JSON.parse(prop.valueObj || '[]'); } else if (prop.derivedDataType == DerivedPropertyType.MAP && typeof prop.valueObj != 'object' && (!prop.isChildOfListOrMap || !prop.schema.property.isSimpleType)) { //dont parse values for children of map of simple prop.valueObj = JSON.parse(prop.valueObj || '{}'); - } + } if ((prop.derivedDataType == DerivedPropertyType.LIST || prop.derivedDataType == DerivedPropertyType.MAP) && typeof prop.valueObj == 'object' && Object.keys(prop.valueObj).length) { let newProps: Array<DerivedFEProperty> = []; Object.keys(prop.valueObj).forEach((key) => { diff --git a/catalog-ui/src/app/ng2/services/component-services/component.service.ts b/catalog-ui/src/app/ng2/services/component-services/component.service.ts index c6865fde9d..cd593d5e3e 100644 --- a/catalog-ui/src/app/ng2/services/component-services/component.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component.service.ts @@ -59,8 +59,6 @@ export class ComponentServiceNg2 { private getServerTypeUrl = (componentType:string):string => { switch (componentType) { - case ComponentType.PRODUCT: - return ServerTypeUrl.PRODUCTS; case ComponentType.SERVICE: return ServerTypeUrl.SERVICES; default: diff --git a/catalog-ui/src/app/ng2/services/http.interceptor.service.ts b/catalog-ui/src/app/ng2/services/http.interceptor.service.ts index e1653cf0bc..c90bfd2848 100644 --- a/catalog-ui/src/app/ng2/services/http.interceptor.service.ts +++ b/catalog-ui/src/app/ng2/services/http.interceptor.service.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. @@ -21,8 +21,8 @@ import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; import 'rxjs/Rx'; -import { sdc2Config } from './../../../main'; -import { Interceptor, InterceptedRequest, InterceptedResponse } from 'ng2-interceptors'; +import {sdc2Config} from './../../../main'; +import {Interceptor, InterceptedRequest, InterceptedResponse} from 'ng2-interceptors'; import {SharingService} from "../../services/sharing-service"; import {ReflectiveInjector} from '@angular/core'; import {Cookie2Service} from "./cookie.service"; @@ -31,23 +31,23 @@ import {Dictionary} from "../../utils/dictionary/dictionary"; import {SEVERITY} from "../../utils/constants"; import {IServerMessageModalModel} from "../../view-models/modals/message-modal/message-server-modal/server-message-modal-view-model"; + export class HttpInterceptor implements Interceptor { - private cookieService: Cookie2Service; + private cookieService:Cookie2Service; private sharingService:SharingService; + constructor() { - let injector = ReflectiveInjector.resolveAndCreate([Cookie2Service,SharingService]); + let injector = ReflectiveInjector.resolveAndCreate([Cookie2Service, SharingService]); this.cookieService = injector.get(Cookie2Service); this.sharingService = injector.get(SharingService); } - public interceptBefore(request: InterceptedRequest): InterceptedRequest { - + public interceptBefore(request:InterceptedRequest):InterceptedRequest { /** * For every request to the server, that the service id, or resource id is sent in the URL, need to pass UUID in the header. * Check if the unique id exists in uuidMap, and if so get the UUID and add it to the header. */ - request.options.headers.append(this.cookieService.getUserIdSuffix(), this.cookieService.getUserId()); request.options.withCredentials = true; var uuidValue = this.getUuidValue(request.url); @@ -56,7 +56,6 @@ export class HttpInterceptor implements Interceptor { } request.options.headers.set('X-ECOMP-RequestID', UUID.UUID()); return request; - } public interceptAfter(response:InterceptedResponse):InterceptedResponse { @@ -66,10 +65,9 @@ export class HttpInterceptor implements Interceptor { //console.log("Error from BE:",response); } return response; - } - private getUuidValue = (url: string) :string => { + private getUuidValue = (url:string):string => { let map:Dictionary<string, string> = this.sharingService.getUuidMap(); if (map && url.indexOf(sdc2Config.api.root) > 0) { map.forEach((key:string) => { @@ -158,9 +156,7 @@ export class HttpInterceptor implements Interceptor { severity: SEVERITY.ERROR }; } - // let modalsHandler = this.$injector.get('ModalsHandler'); - // this.modalsHandler.openServerMessageModal(data); console.error('ERROR data',data); } } diff --git a/catalog-ui/src/app/ng2/services/modal.service.ts b/catalog-ui/src/app/ng2/services/modal.service.ts new file mode 100644 index 0000000000..32192f40c2 --- /dev/null +++ b/catalog-ui/src/app/ng2/services/modal.service.ts @@ -0,0 +1,73 @@ +import { Injectable, Type, ViewContainerRef, ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef } from '@angular/core'; +import { ModalModel, ButtonModel } from 'app/models'; +import { ModalComponent } from 'app/ng2/components/modal/modal.component'; + + +@Injectable() +export class ModalService { + currentModal: ComponentRef<any>; + + + constructor(private componentFactoryResolver: ComponentFactoryResolver, private applicationRef: ApplicationRef) { } + + + /* Shortcut method to open a simple modal with title, message, and close button that simply closes the modal. */ + public openAlertModal(title: string, message: string, closeButtonText?:string) { + let closeButton: ButtonModel = new ButtonModel(closeButtonText || 'Close', 'grey', this.closeCurrentModal); + let modalModel: ModalModel = new ModalModel('sm', title, message, [closeButton]); + this.createCustomModal(modalModel).instance.open(); + } + + + /** + * Shortcut method to open a basic modal with title, message, and an action button with callback, as well as close button. + * NOTE: To close the modal from within the callback, use modalService.closeCurrentModal() //if you run into zone issues with callbacks see:https://stackoverflow.com/questions/36566698/how-to-dynamically-create-bootstrap-modals-as-angular2-components + * @param title Heading for modal + * @param message Message for modal + * @param actionButtonText Blue call to action button + * @param actionButtonCallback function to invoke when button is clicked + * @param cancelButtonText text for close/cancel button + */ + public openActionModal = (title:string, message:string, actionButtonText:string, actionButtonCallback:Function, cancelButtonText:string) => { + let actionButton: ButtonModel = new ButtonModel(actionButtonText, 'blue', actionButtonCallback); + let cancelButton: ButtonModel = new ButtonModel(cancelButtonText, 'grey', this.closeCurrentModal); + let modalModel: ModalModel = new ModalModel('sm', title, message, [actionButton, cancelButton]); + this.createCustomModal(modalModel).instance.open(); + } + + + /* Use this method to create a modal with title, message, and completely custom buttons. Use response.instance.open() to open */ + public createCustomModal = (customModalData: ModalModel): ComponentRef<ModalComponent> => { + let customModal: ComponentRef<ModalComponent> = this.createDynamicComponent(ModalComponent); + customModal.instance.input = customModalData; + this.currentModal = customModal; + + return customModal; + } + + + public closeCurrentModal = () => { + if (!this.currentModal) return; + this.currentModal.instance.close(); + this.currentModal.destroy(); + } + + + //Creates a component dynamically (aka during runtime). If a view container is not specified, it will append the new component to the app root. + //To subscribe to an event from invoking component: componentRef.instance.clicked.subscribe((m) => console.log(m.name)); + private createDynamicComponent<T>(componentType: Type<T>, viewContainerRef?:ViewContainerRef): ComponentRef<any> { + + viewContainerRef = viewContainerRef || this.getRootViewContainerRef(); + viewContainerRef.clear(); + + let factory: ComponentFactory<any> = this.componentFactoryResolver.resolveComponentFactory(componentType); //Ref: https://angular.io/guide/dynamic-component-loader + let componentRef = viewContainerRef.createComponent(factory); + + return componentRef; + } + + + private getRootViewContainerRef(): ViewContainerRef { + return this.applicationRef.components[0].instance.viewContainerRef; + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html new file mode 100644 index 0000000000..36629594b0 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html @@ -0,0 +1,5 @@ +<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>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less new file mode 100644 index 0000000000..cfeb8d3b01 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less @@ -0,0 +1,58 @@ +.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 { + border: 1px solid #cdcdcd; + border-radius: 4px; + border-right:none; + border-top-right-radius: 0; + border-bottom-right-radius: 0; + outline:none; + padding:2px 50px 2px 10px; + color: #5a5a5a; + font-size: 1em; + font-style: italic; + } + + .clear-search-x { + position:absolute; + right:40px; + top:5px; + padding: 0 5px; + + &:hover { + border-radius:2px; + background-color: #ebebeb; + cursor:pointer; + } + } + + .search-bar-button { + //background: url('../../../../assets/styles/svg/source/search-magnify.svg') no-repeat 50%; + background: url('../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px; + background-color: rgba(234, 234, 234, 0.88); + width: 30px; + height: 30px; + padding: 0; + cursor:pointer; + border:solid 1px #cdcdcd; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; + + &:hover { + background-position:-126px -1275px; + } + + &:active { + background-color: rgba(31, 171, 223, 0.88); + background-position:-45px -1275px; + border-left:none; + } + &:focus { + outline:none; + } + + } +} diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts new file mode 100644 index 0000000000..2835d20ba4 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts @@ -0,0 +1,30 @@ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; + +@Component({ + selector: 'search-bar', + templateUrl: './search-bar.component.html', + styleUrls: ['./search-bar.component.less'], + encapsulation: ViewEncapsulation.None +}) +export class SearchBarComponent { + + @Input() placeholder: string; + @Input() class: string; + @Input() searchQuery: string; + @Output() searchChanged: EventEmitter<any> = new EventEmitter<any>(); + @Output() searchButtonClicked: EventEmitter<string> = new EventEmitter<string>(); + + searchButtonClick = (): void => { + this.searchButtonClicked.emit(this.searchQuery); + } + + searchQueryChange = ($event): void => { + this.searchChanged.emit($event); + } + + private clearSearchQuery = (): void => { + this.searchQuery = ""; + this.searchButtonClick(); + } +} + diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html new file mode 100644 index 0000000000..c9769ba5ae --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html @@ -0,0 +1,6 @@ +<div class="search-with-autocomplete-container {{searchBarClass}}" [class.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> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less new file mode 100644 index 0000000000..92b054cd85 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less @@ -0,0 +1,35 @@ + +.search-with-autocomplete-container{ + &.autocomplete-visible { + + .search-bar-input { + border-bottom-left-radius: 0; + } + .search-bar-button { + border-bottom-right-radius: 0; + } + .autocomplete-results { + border: solid 1px #d2d2d2; + border-top:none; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + background-color: #fff; + padding: 10px 20px; + width:100%; + position:absolute; + max-height: 200px; + overflow-y: scroll; + } + + .autocomplete-result-item { + color:#5a5a5a; + padding: 5px 0; + cursor:pointer; + + &:hover { + color: #999; + } + } + } +} + diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts new file mode 100644 index 0000000000..ced056d1fc --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts @@ -0,0 +1,30 @@ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; +import { SearchBarComponent } from '../search-bar/search-bar.component'; + +@Component({ + selector: 'search-with-autocomplete', + templateUrl: './search-with-autocomplete.component.html', + styleUrls: ['./search-with-autocomplete.component.less'], + encapsulation: ViewEncapsulation.None +}) +export class SearchWithAutoCompleteComponent { + + @Input() searchPlaceholder: string; + @Input() searchBarClass: string; + @Input() searchQuery: string; + @Input() autoCompleteValues: Array<string>; + @Output() searchChanged: EventEmitter<any> = new EventEmitter<any>(); + @Output() searchButtonClicked: EventEmitter<string> = new EventEmitter<string>(); + + searchChange = (searchTerm: string) => { + this.searchQuery = searchTerm; + this.searchChanged.emit(searchTerm); + } + + updateSearch = (searchTerm: string) => { + this.searchQuery = searchTerm; + this.searchButtonClicked.emit(searchTerm); + this.autoCompleteValues = []; + } +} + diff --git a/catalog-ui/src/app/services.ts b/catalog-ui/src/app/services.ts index ce4a8e32d3..5dd08c2d20 100644 --- a/catalog-ui/src/app/services.ts +++ b/catalog-ui/src/app/services.ts @@ -27,7 +27,6 @@ export * from './services/cache-service'; export * from './services/configuration-ui-service'; export * from './services/category-resource-service'; export * from './services/components/component-service'; -export * from './services/components/product-service'; export * from './services/components/resource-service'; export * from './services/components/service-service'; export * from './services/components/resource-service'; diff --git a/catalog-ui/src/app/services/available-icons-service.ts b/catalog-ui/src/app/services/available-icons-service.ts index ebb6c5ff77..13b6caea2a 100644 --- a/catalog-ui/src/app/services/available-icons-service.ts +++ b/catalog-ui/src/app/services/available-icons-service.ts @@ -81,23 +81,6 @@ export class AvailableIconsService implements IAvailableIconsService { 'firewall' ]; break; - - case ComponentType.PRODUCT: - icons = [ - 'vfw', - 'network', - 'security', - 'cloud', - 'setting', - 'orphan', - 'wanx', - 'vrouter', - 'ucpe', - 'mobility' - - ]; - break; - } return icons; } diff --git a/catalog-ui/src/app/services/components/product-service.ts b/catalog-ui/src/app/services/components/product-service.ts deleted file mode 100644 index 09199ea172..0000000000 --- a/catalog-ui/src/app/services/components/product-service.ts +++ /dev/null @@ -1,55 +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========================================================= - */ - -/** - * Created by obarda on 2/8/2016. - */ -'use strict'; -import {IComponentService, ComponentService} from "./component-service"; -import {SharingService} from "../sharing-service"; -import {Product, Component, IAppConfigurtaion} from "../../models"; - -export interface IProductService extends IComponentService { - -} - -export class ProductService extends ComponentService implements IProductService { - - static '$inject' = [ - 'Restangular', - 'sdcConfig', - 'Sdc.Services.SharingService', - '$q', - '$base64' - ]; - - constructor(protected restangular:restangular.IElement, - protected sdcConfig:IAppConfigurtaion, - protected sharingService:SharingService, - protected $q:ng.IQService, - protected $base64:any) { - super(restangular, sdcConfig, sharingService, $q, $base64); - this.restangular = restangular.one("products"); - } - - createComponentObject = (component:Component):Component => { - return new Product(this, this.$q, <Product>component); - }; -} diff --git a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts index 52cb78f6d5..a1fa65159f 100644 --- a/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts +++ b/catalog-ui/src/app/services/components/utils/composition-left-palette-service.ts @@ -28,6 +28,7 @@ import {ComponentFactory} from "../../../utils/component-factory"; import {IAppConfigurtaion} from "../../../models/app-config"; import {ResourceType, ComponentType, EVENTS} from "../../../utils/constants"; import {ComponentMetadata} from "../../../models/component-metadata"; +import {Resource} from "app/models/components/resource"; export class LeftPaletteDataObject { displayLeftPanelComponents:Array<LeftPaletteComponent>; @@ -58,24 +59,27 @@ export class LeftPaletteLoaderService { protected EventListenerService:EventListenerService) { this.restangular.setBaseUrl(sdcConfig.api.root + sdcConfig.api.component_api_root); - + } private serviceLeftPaletteData:LeftPaletteDataObject; private resourceLeftPaletteData:LeftPaletteDataObject; - private productLeftPaletteData:LeftPaletteDataObject; + private resourcePNFLeftPaletteData:LeftPaletteDataObject; private vlData:LeftPaletteDataObject; - public loadLeftPanel = (componentType: string):void => { + public loadLeftPanel = (component:Component):void => { this.serviceLeftPaletteData = new LeftPaletteDataObject(EVENTS.SERVICE_LEFT_PALETTE_UPDATE_EVENT); this.resourceLeftPaletteData = new LeftPaletteDataObject(EVENTS.RESOURCE_LEFT_PALETTE_UPDATE_EVENT); - this.updateComponentLeftPalette(componentType); + this.resourcePNFLeftPaletteData = new LeftPaletteDataObject(EVENTS.RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT); + this.updateComponentLeftPalette(component); } - - private getTypeUrl = (componentType:string):string => { - return ComponentType.PRODUCT === componentType ? "services" : "resources"; - }; + private getResourceLeftPaletteDataByResourceType = (resourceType:string):LeftPaletteDataObject => { + if(resourceType == ResourceType.PNF) { + return this.resourcePNFLeftPaletteData; + } + return this.resourceLeftPaletteData; + } private onFinishLoading = (componentType:string, leftPaletteData:LeftPaletteDataObject):void => { this.EventListenerService.notifyObservers(leftPaletteData.onFinishLoadingEvent); @@ -83,7 +87,7 @@ export class LeftPaletteLoaderService { private updateLeftPalette = (componentType, componentInternalType:string, leftPaletteData:LeftPaletteDataObject):void => { - this.restangular.one(this.getTypeUrl(componentType)).one('/latestversion/notabstract/metadata').get({'internalComponentType': componentInternalType}).then((leftPaletteComponentMetadata:Array<ComponentMetadata>) => { + this.restangular.one("resources").one('/latestversion/notabstract/metadata').get({'internalComponentType': componentInternalType}).then((leftPaletteComponentMetadata:Array<ComponentMetadata>) => { _.forEach(leftPaletteComponentMetadata, (componentMetadata:ComponentMetadata) => { leftPaletteData.displayLeftPanelComponents.push(new LeftPaletteComponent(componentMetadata)); }); @@ -91,30 +95,25 @@ export class LeftPaletteLoaderService { }); }; - public getLeftPanelComponentsForDisplay = (componentType:string):Array<LeftPaletteComponent> => { - switch (componentType) { + public getLeftPanelComponentsForDisplay = (component:Component):Array<LeftPaletteComponent> => { + switch (component.componentType) { case ComponentType.SERVICE: return this.serviceLeftPaletteData.displayLeftPanelComponents; - case ComponentType.PRODUCT: - return this.productLeftPaletteData.displayLeftPanelComponents; - default: - return this.resourceLeftPaletteData.displayLeftPanelComponents; + default://resource + return this.getResourceLeftPaletteDataByResourceType((<Resource>component).resourceType).displayLeftPanelComponents; } }; - public updateComponentLeftPalette = (componentType):void => { - switch (componentType) { - case ResourceType.VL: - this.updateLeftPalette(ComponentType.RESOURCE, ResourceType.VL, this.vlData); - break; + public updateComponentLeftPalette = (component:Component):void => { + switch (component.componentType) { case ComponentType.SERVICE: this.updateLeftPalette(ComponentType.SERVICE, ComponentType.SERVICE, this.serviceLeftPaletteData); break; - case ComponentType.PRODUCT: - this.updateLeftPalette(ComponentType.PRODUCT, ComponentType.SERVICE, this.productLeftPaletteData); + case ComponentType.RESOURCE: + this.updateLeftPalette(ComponentType.RESOURCE, (<Resource>component).resourceType, this.getResourceLeftPaletteDataByResourceType((<Resource>component).resourceType)); break; default: - this.updateLeftPalette(ComponentType.RESOURCE, ResourceType.VF, this.resourceLeftPaletteData); + console.log('ERROR: Component type '+ component.componentType + ' is not exists'); } }; } diff --git a/catalog-ui/src/app/services/data-types-service.ts b/catalog-ui/src/app/services/data-types-service.ts index a6dbf7f12d..84fe42e9f3 100644 --- a/catalog-ui/src/app/services/data-types-service.ts +++ b/catalog-ui/src/app/services/data-types-service.ts @@ -132,7 +132,8 @@ export class DataTypesService implements IDataTypesService { public isDataTypeForDataTypePropertyType = (property:DataTypePropertyModel):boolean=> { property.simpleType = ""; - if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1) { + let isScalarForNFoD:boolean = property.type === 'scalar-unit.size'; + if (property.type && PROPERTY_DATA.TYPES.indexOf(property.type) > -1 || isScalarForNFoD) { return false; } let simpleType = this.getTypeForDataTypeDerivedFromSimple(property.type); diff --git a/catalog-ui/src/app/services/entity-service.ts b/catalog-ui/src/app/services/entity-service.ts index a255dcff34..75ea036b3e 100644 --- a/catalog-ui/src/app/services/entity-service.ts +++ b/catalog-ui/src/app/services/entity-service.ts @@ -19,7 +19,7 @@ */ 'use strict'; -import {Product, Service, IApi, IAppConfigurtaion, Resource, Component} from "../models"; +import { Service, IApi, IAppConfigurtaion, Resource, Component} from "../models"; import {SharingService} from "./sharing-service"; import {ComponentFactory} from "../utils/component-factory"; import {CacheService} from "./cache-service"; @@ -31,7 +31,6 @@ interface IEntityService { interface IComponentsArray { services:Array<Service>; resources:Array<Resource>; - products:Array<Product>; } export class EntityService implements IEntityService { @@ -66,13 +65,6 @@ export class EntityService implements IEntityService { this.sharingService.addUuidValue(component.uniqueId, component.uuid); }); - followedResponse.products.forEach((productResponse:Product) => { - - let component:Product = this.ComponentFactory.createProduct(productResponse); - componentsList.push(component); - this.sharingService.addUuidValue(component.uniqueId, component.uuid); - }); - this.cacheService.set('breadcrumbsComponents', componentsList); defer.resolve(componentsList); },(responce) => { @@ -99,12 +91,7 @@ export class EntityService implements IEntityService { componentsList.push(component); this.sharingService.addUuidValue(component.uniqueId, component.uuid); }); - - componentResponse.products && componentResponse.products.forEach((productsResponse:Product) => { - let component:Product = this.ComponentFactory.createProduct(productsResponse); - componentsList.push(component); - this.sharingService.addUuidValue(component.uniqueId, component.uuid); - }); + this.cacheService.set('breadcrumbsComponents', componentsList); defer.resolve(componentsList); }); diff --git a/catalog-ui/src/app/utils/component-factory.ts b/catalog-ui/src/app/utils/component-factory.ts index c202a1c8f5..b35918c0f6 100644 --- a/catalog-ui/src/app/utils/component-factory.ts +++ b/catalog-ui/src/app/utils/component-factory.ts @@ -20,8 +20,8 @@ 'use strict'; import {DEFAULT_ICON, ResourceType, ComponentType} from "./constants"; -import {ServiceService, CacheService, ResourceService, ProductService} from "app/services"; -import {IMainCategory, ISubCategory, ICsarComponent, Component, Resource, Service, Product} from "app/models"; +import {ServiceService, CacheService, ResourceService} from "app/services"; +import {IMainCategory, ISubCategory, ICsarComponent, Component, Resource, Service} from "app/models"; import {ComponentMetadata} from "../models/component-metadata"; import {ComponentServiceNg2} from "../ng2/services/component-services/component.service"; import {ComponentGenericResponse} from "../ng2/services/responses/component-generic-response"; @@ -32,7 +32,6 @@ export class ComponentFactory { static '$inject' = [ 'Sdc.Services.Components.ResourceService', 'Sdc.Services.Components.ServiceService', - 'Sdc.Services.Components.ProductService', 'Sdc.Services.CacheService', '$q', 'ComponentServiceNg2' @@ -40,7 +39,6 @@ export class ComponentFactory { constructor(private ResourceService:ResourceService, private ServiceService:ServiceService, - private ProductService:ProductService, private cacheService:CacheService, private $q:ng.IQService, private ComponentServiceNg2: ComponentServiceNg2) { @@ -58,18 +56,10 @@ export class ComponentFactory { newComponent = new Resource(this.ResourceService, this.$q, <Resource> component); break; - case 'PRODUCT': - newComponent = new Product(this.ProductService, this.$q, <Product> component); - break; } return newComponent; }; - public createProduct = (product:Product):Product => { - let newProduct:Product = new Product(this.ProductService, this.$q, <Product> product); - return newProduct; - }; - public createService = (service:Service):Service => { let newService:Service = new Service(this.ServiceService, this.$q, <Service> service); return newService; @@ -144,12 +134,10 @@ export class ComponentFactory { case ResourceType.VL: case ResourceType.VFC: case ResourceType.CP: + case ResourceType.PNF: + case ResourceType.CVFC: newComponent = new Resource(this.ResourceService, this.$q); break; - - case ComponentType.PRODUCT: - newComponent = new Product(this.ProductService, this.$q); - break; } newComponent.componentType = componentType; newComponent.tags = []; diff --git a/catalog-ui/src/app/utils/component-instance-factory.ts b/catalog-ui/src/app/utils/component-instance-factory.ts index c020c53705..9e25e6b02f 100644 --- a/catalog-ui/src/app/utils/component-instance-factory.ts +++ b/catalog-ui/src/app/utils/component-instance-factory.ts @@ -21,7 +21,7 @@ * Created by obarda on 3/7/2016. */ 'use strict'; -import {ComponentInstance, ServiceInstance, ProductInstance, ResourceInstance, Component} from "../models"; +import {ComponentInstance, ServiceInstance, ResourceInstance, Component} from "../models"; import {LeftPaletteComponent} from "../models/components/displayComponent"; export class ComponentInstanceFactory { @@ -33,10 +33,6 @@ export class ComponentInstanceFactory { newComponentInstance = new ServiceInstance(componentInstance); break; - case 'PRODUCT': - newComponentInstance = new ProductInstance(componentInstance); - break; - default : newComponentInstance = new ResourceInstance(componentInstance); break; @@ -51,10 +47,6 @@ export class ComponentInstanceFactory { newComponentInstance = new ServiceInstance(); break; - case 'PRODUCT': - newComponentInstance = new ProductInstance(); - break; - default : newComponentInstance = new ResourceInstance(); break; diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts index 636c0c4fbf..d239019455 100644 --- a/catalog-ui/src/app/utils/constants.ts +++ b/catalog-ui/src/app/utils/constants.ts @@ -29,13 +29,11 @@ export let CHANGE_COMPONENT_CSAR_VERSION_FLAG = 'changeComponentCsarVersion'; export class ComponentType { static SERVICE = 'SERVICE'; static RESOURCE = 'RESOURCE'; - static PRODUCT = 'PRODUCT'; } export class ServerTypeUrl { static RESOURCES = 'resources/'; static SERVICES = 'services/'; - static PRODUCTS = 'product/'; } export class ResourceType { @@ -45,6 +43,7 @@ export class ResourceType { static VFC = 'VFC'; static VFCMT = 'VFCMT'; static PNF = 'PNF'; + static CVFC = 'CVFC'; } export class ComponentState { @@ -129,8 +128,6 @@ export class PROPERTY_VALUE_CONSTRAINTS { export class Role { public static ADMIN = 'ADMIN'; public static DESIGNER = 'DESIGNER'; - public static PRODUCT_STRATEGIST = 'PRODUCT_STRATEGIST'; - public static PRODUCT_MANAGER = 'PRODUCT_MANAGER'; public static TESTER = 'TESTER'; public static OPS = 'OPS'; public static GOVERNOR = 'GOVERNOR'; @@ -213,14 +210,12 @@ export class GraphUIObjects { export class States { public static WORKSPACE_GENERAL = 'workspace.general'; - public static WORKSPACE_ICONS = 'workspace.icons'; public static WORKSPACE_ACTIVITY_LOG = 'workspace.activity_log'; public static WORKSPACE_DEPLOYMENT_ARTIFACTS = 'workspace.deployment_artifacts'; public static WORKSPACE_PROPERTIES = 'workspace.properties'; public static WORKSPACE_SERVICE_INPUTS = 'workspace.service_inputs'; public static WORKSPACE_RESOURCE_INPUTS = 'workspace.resource_inputs'; public static WORKSPACE_ATTRIBUTES = 'workspace.attributes'; - public static WORKSPACE_HIERARCHY = 'workspace.hierarchy'; public static WORKSPACE_INFORMATION_ARTIFACTS = 'workspace.information_artifacts'; public static WORKSPACE_TOSCA_ARTIFACTS = 'workspace.tosca_artifacts'; public static WORKSPACE_COMPOSITION = 'workspace.composition'; @@ -237,7 +232,6 @@ export class EVENTS { static RESOURCE_LEFT_PALETTE_UPDATE_EVENT = "resourceLeftPanelUpdateEvent"; static RESOURCE_PNF_LEFT_PALETTE_UPDATE_EVENT = "resourcePNFLeftPanelUpdateEvent"; static SERVICE_LEFT_PALETTE_UPDATE_EVENT = "serviceLeftPanelUpdateEvent"; - static PRODUCT_LEFT_PALETTE_UPDATE_EVENT = "productLeftPanelUdateEvent"; static VL_LEFT_PALETTE_UPDATE_EVENT = "vlLeftPanelUdateEvent"; static ON_CSAR_LOADING = "onCsarLoading"; static DOWNLOAD_ARTIFACT_FINISH_EVENT = "downloadArtifactFinishEvent"; diff --git a/catalog-ui/src/app/utils/modals-handler.ts b/catalog-ui/src/app/utils/modals-handler.ts index ae91b2acb7..0d17683116 100644 --- a/catalog-ui/src/app/utils/modals-handler.ts +++ b/catalog-ui/src/app/utils/modals-handler.ts @@ -187,6 +187,24 @@ export class ModalsHandler implements IModalsHandler { return deferred.promise; }; + openUpdateIconModal = (component: Component):ng.IPromise<any> => { + let deferred = this.$q.defer(); + let modalOptions:ng.ui.bootstrap.IModalSettings = { + templateUrl: '../view-models/modals/icons-modal/icons-modal-view.html', + controller: 'Sdc.ViewModels.IconsModalViewModel', + size: 'sdc-auto', + backdrop: 'static', + resolve: { + component: ():Component => { + return component; + } + } + }; + let modalInstance:ng.ui.bootstrap.IModalServiceInstance = this.$uibModal.open(modalOptions); + deferred.resolve(modalInstance.result); + return deferred.promise; + }; + openEditEnvParametersModal = (artifactResource:ArtifactModel, component?:Component):ng.IPromise<any> => { let deferred = this.$q.defer(); let modalOptions:ng.ui.bootstrap.IModalSettings = { diff --git a/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts b/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts index 8925be0fff..ec9e888eed 100644 --- a/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts +++ b/catalog-ui/src/app/view-models/catalog/catalog-view-model.ts @@ -117,7 +117,7 @@ export class CatalogViewModel { let onSuccess = (followedResponse:Array<Component>):void => { this.$scope.catalogFilterdItems = followedResponse; this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.catalogFilterdItems.length; - this.$scope.categories = this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')).concat(this.cacheService.get('productCategories')); + this.$scope.categories = this.cacheService.get('serviceCategories').concat(this.cacheService.get('resourceCategories')); this.$scope.gui.isLoading = false; }; @@ -137,7 +137,7 @@ export class CatalogViewModel { //this.$scope.categories = this.cacheService.get('categoriesMap'); this.$scope.sdcMenu = this.sdcMenu; this.$scope.confStatus = this.sdcMenu.statuses; - this.$scope.expandedSection = ["type", "category", "product-category", "status"]; + this.$scope.expandedSection = ["type", "category", "status"]; this.$scope.user = this.userResourceService.getLoggedinUser(); this.$scope.catalogMenuItem = this.sdcMenu.catalogMenuItem; this.$scope.version = this.cacheService.get('version'); @@ -147,8 +147,8 @@ export class CatalogViewModel { // Checklist init this.$scope.checkboxes = <Checkboxes>{}; - this.$scope.checkboxes.componentTypes = ['Resource', 'Service', 'Product']; - this.$scope.checkboxes.resourceSubTypes = ['VF', 'VFC', 'CP', 'VL']; + this.$scope.checkboxes.componentTypes = ['Resource', 'Service']; + this.$scope.checkboxes.resourceSubTypes = ['VF', 'VFC', 'PNF', 'CP', 'VL']; // Checkboxes filter init this.$scope.checkboxesFilter = <CheckboxesFilter>{}; diff --git a/catalog-ui/src/app/view-models/catalog/catalog.less b/catalog-ui/src/app/view-models/catalog/catalog.less index ff50202243..1f473c9638 100644 --- a/catalog-ui/src/app/view-models/catalog/catalog.less +++ b/catalog-ui/src/app/view-models/catalog/catalog.less @@ -67,28 +67,6 @@ //text-indent: -10px; } - /*Added by - Ikram */ - .i-sdc-product-input, - .i-sdc-product-select { - border: 1px solid @border_color_f; - min-height: 30px; - padding: 0; - width: 100%; - margin: 1px 0; - background-color: #F2F2F2; - outline: none; - - &:disabled { - .disabled; - } - optgroup{ - color: @color_u; - option{ - color: @color_b; - } - } - } - .i-sdc-categories-list-item-icon { display: inline-block; float: right; diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts b/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts index b9e51f098a..5480e4f6cf 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts +++ b/catalog-ui/src/app/view-models/dashboard/dashboard-view-model.ts @@ -310,6 +310,13 @@ export class DashboardViewModel { }; + this.$scope.createPNF = ():void => { + this.$state.go('workspace.general', { + type: ComponentType.RESOURCE.toLowerCase(), + resourceType: ResourceType.PNF + }); + }; + this.$scope.entitiesCount = (folderItem:FoldersItemsMenu):any => { let self = this; let total:number = 0; diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html b/catalog-ui/src/app/view-models/dashboard/dashboard-view.html index 806bb8138d..baf4aa6e51 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html +++ b/catalog-ui/src/app/view-models/dashboard/dashboard-view.html @@ -13,15 +13,15 @@ <div class='w-sdc-row-flex-items'> <!-- ADD Component --> - <div ng-if="user.role === 'DESIGNER' || user.role === 'PRODUCT_MANAGER'" class="w-sdc-dashboard-card-new" + <div ng-if="user.role === 'DESIGNER'" class="w-sdc-dashboard-card-new" data-ng-mouseleave="displayActions = false" data-ng-mouseover="displayActions = true" data-ng-init="displayActions = false"> <div class="w-sdc-dashboard-card-new-content" data-tests-id="AddButtonsArea"> <div class="w-sdc-dashboard-card-new-content-plus" data-ng-show="!displayActions"></div> <div class="sdc-dashboard-create-element-container" data-ng-show="displayActions"> - <button data-ng-if="roles[user.role].dashboard.showCreateNewProduct" data-tests-id="createProductButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('PRODUCT')">Create Product</button> <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createResourceButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('RESOURCE')">Add VF</button> + <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createPNFButton" class="tlv-btn outline blue" data-ng-click="createPNF()">Add PNF</button> <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createServiceButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('SERVICE')">Add Service</button> </div> </div> @@ -44,8 +44,8 @@ </div> </div> </div> - </div> - + </div> + <!-- Tile new --> <div class="sdc-tile-catalog sdc-tile-fix-width" data-ng-repeat="component in components | filter:{resourceType:('!'+vfcmtType)} | entityFilter:checkboxesFilter | filter:search"> @@ -62,7 +62,7 @@ data-tests-id="{{component.name}}"></div> </div> <div class='sdc-tile-content-info'> - <div class="sdc-tile-content-info-item-name" data-tests-id="{{component.name | resourceName}}" sdc-smart-tooltip>{{component.name | resourceName}}</div> + <div class="sdc-tile-content-info-item-name" data-tests-id="{{component.name | resourceName}}" sdc-smart-tooltip>{{component.name | resourceName}}</div> <div class="sdc-tile-content-info-version-info"> <div class="sdc-tile-content-info-version-info-text" data-tests-id="{{component.name}}Version">V {{component.version}}</div> </div> @@ -70,11 +70,11 @@ </div> <div class='sdc-tile-footer'> <div class='sdc-tile-footer-text'>{{component.getStatus(sdcMenu)}}</div> - </div> + </div> </div> <!-- Tile new --> - + </div> </perfect-scrollbar> diff --git a/catalog-ui/src/app/view-models/dashboard/dashboard.less b/catalog-ui/src/app/view-models/dashboard/dashboard.less index 7993390769..02280cdb42 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard.less +++ b/catalog-ui/src/app/view-models/dashboard/dashboard.less @@ -244,13 +244,6 @@ } } - &.PRODUCT { - .b_14_m; - &::before { - content: 'P'; - } - } - &.green { .d_12; &::before { diff --git a/catalog-ui/src/app/view-models/dcae-app/dcae-app.less b/catalog-ui/src/app/view-models/dcae-app/dcae-app.less index bc1404d7c4..71a3101412 100644 --- a/catalog-ui/src/app/view-models/dcae-app/dcae-app.less +++ b/catalog-ui/src/app/view-models/dcae-app/dcae-app.less @@ -48,28 +48,6 @@ //text-indent: -10px; } - /*Added by - Ikram */ - .i-sdc-product-input, - .i-sdc-product-select { - border: 1px solid @border_color_f; - min-height: 30px; - padding: 0; - width: 100%; - margin: 1px 0; - background-color: #F2F2F2; - outline: none; - - &:disabled { - .disabled; - } - optgroup{ - color: @color_u; - option{ - color: @color_b; - } - } - } - .i-sdc-categories-list-item-icon { display: inline-block; float: right; diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts index 8b9acbcab7..ee2e94f934 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view-model.ts @@ -23,6 +23,7 @@ import { PROPERTY_TYPES, ModalsHandler, ValidationUtils, PROPERTY_VALUE_CONSTRAINTS, FormState, PROPERTY_DATA} from "app/utils"; import {DataTypesService} from "app/services"; import {PropertyModel, DataTypesMap, Component} from "app/models"; +import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance"; export interface IEditPropertyModel { property:PropertyModel; @@ -50,6 +51,7 @@ interface IPropertyFormViewModelScope extends ng.IScope { isTypeDataType:boolean; maxLength:number; isPropertyValueOwner:boolean; + isVnfConfiguration:boolean; validateJson(json:string):boolean; save(doNotCloseModal?:boolean):void; @@ -192,6 +194,17 @@ export class PropertyFormViewModel { this.$scope.isPropertyValueOwner = this.isPropertyValueOwner; this.initEditPropertyModel(); + //check if property of VnfConfiguration + this.$scope.isVnfConfiguration = false; + if(angular.isArray(this.component.componentInstances)) { + var componentPropertyOwner:ComponentInstance = this.component.componentInstances.find((ci:ComponentInstance) => { + return ci.uniqueId === this.property.resourceInstanceUniqueId; + }); + if (componentPropertyOwner.componentName === 'vnfConfiguration') { + this.$scope.isVnfConfiguration = true; + } + } + this.$scope.nonPrimitiveTypes = _.filter(Object.keys(this.$scope.dataTypes), (type:string)=> { return this.$scope.editPropertyModel.types.indexOf(type) == -1; }); diff --git a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html index f92d9a5ddc..743de298cd 100644 --- a/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html +++ b/catalog-ui/src/app/view-models/forms/property-forms/component-property-form/property-form-view.html @@ -142,7 +142,7 @@ schema-property="editPropertyModel.property.schema.property" parent-form-obj="forms.editForm" fields-prefix-name="currentPropertyIndex" - read-only="editPropertyModel.property.readonly && !isPropertyValueOwner" + read-only="(editPropertyModel.property.readonly && !isPropertyValueOwner) || isVnfConfiguration" default-value="{{getDefaultValue()}}" max-length="maxLength"></type-map> </div> diff --git a/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html new file mode 100644 index 0000000000..4b89701201 --- /dev/null +++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.html @@ -0,0 +1,18 @@ +<sdc-modal modal="modalIcons" type="classic" class="w-sdc-modal-icons" buttons="footerButtons" header="Choose Icon" show-close-button="true"> + + <div class="suggested-icons-container"> + <div class ="suggested-icon-wrapper" data-ng-class="{'selected': selectedIcon == iconSrc}" data-ng-repeat="iconSrc in icons track by $index"> + <div class="i-sdc-form-item-suggested-icon large hand {{iconSprite}} {{iconSrc}}" + data-tests-id="{{iconSrc}} iconBox" + data-ng-click="changeIcon(iconSrc)" + tooltips tooltip-content='{{iconSrc | translate}}' + > + </div> + </div> + </div> + + <div class="w-sdc-modal-footer classic"> + <button class="tlv-btn blue" data-tests-id="OK" data-ng-click="updateIcon()">OK</button> + <button class="tlv-btn grey" data-tests-id="Cancel" data-ng-click="cancel()" >Cancel</button> + </div> +</sdc-modal> diff --git a/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less new file mode 100644 index 0000000000..660846c883 --- /dev/null +++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.less @@ -0,0 +1,33 @@ +.suggested-icons-container { + text-align: left; + width: 370px; + margin-bottom: 20px; + position: relative; + + .suggested-icon-wrapper { + padding: 5px; + margin: 14px 0 14px 28px; + display: inline-block; + height: 71px; + width: 71px; + + &.selected { + border: 2px solid @main_color_a; + border-radius: 35px; + display: inline-block; + line-height: 0px; + padding: 3px; + } + + } + .i-sdc-form-item-suggested-icon { + opacity: 0.8; + &:hover{ + opacity: 1; + } + } + .suggested-icon-wrapper:nth-child(4n+1) { + margin-left: 0; + } +} + diff --git a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view-model.ts b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.ts index c25bc4a1f1..eeadcd4e83 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view-model.ts +++ b/catalog-ui/src/app/view-models/modals/icons-modal/icons-modal-view.ts @@ -19,53 +19,60 @@ */ /** - * Created by obarda on 4/4/2016. + * Created by rc2122 on 7/4/2017. */ 'use strict'; import {ComponentFactory} from "app/utils"; import {AvailableIconsService} from "app/services"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; import {IMainCategory, ISubCategory} from "app/models"; - -export interface IIconsScope extends IWorkspaceViewModelScope { - icons:Array<string>; - iconSprite:string; - setComponentIcon(iconSrc:string):void; +import {Component} from "app/models"; +import {ResourceType} from "app/utils/constants"; + +interface IIconsModalViewModelScope { + modalIcons:ng.ui.bootstrap.IModalServiceInstance; + icons:Array<string>, + iconSprite:string, + selectedIcon:string, + changeIcon(icon:string):void, + cancel():void + updateIcon():void; } -export class IconsViewModel { - +export class IconsModalViewModel { static '$inject' = [ '$scope', 'Sdc.Services.AvailableIconsService', 'ComponentFactory', - '$state' + '$state', + '$uibModalInstance', + 'component' ]; - constructor(private $scope:IIconsScope, + constructor(private $scope:IIconsModalViewModelScope, private availableIconsService:AvailableIconsService, private ComponentFactory:ComponentFactory, - private $state:ng.ui.IStateService) { - - + private $state:ng.ui.IStateService, + private $uibModalInstance:ng.ui.bootstrap.IModalServiceInstance, + private component: Component) { this.initScope(); - this.initIcons(); - this.$scope.updateSelectedMenuItem(); - this.$scope.iconSprite = this.$scope.component.iconSprite; + this._initIcons(); + this.$scope.iconSprite = this.component.iconSprite; + this.$scope.selectedIcon = this.component.icon; - if (this.$scope.component.isResource()) { + if (this.component.isResource()) { this.initVendor(); } + } - private initialIcon:string = this.$scope.component.icon; - private initIcons = ():void => { + private _initIcons = ():void => { // For subcategories that where created by admin, there is no icons this.$scope.icons = new Array<string>(); - if (this.$scope.component.categories && this.$scope.component.categories.length > 0) { + if (this.component.categories && this.component.categories.length > 0) { - _.forEach(this.$scope.component.categories, (category:IMainCategory):void => { + _.forEach(this.component.categories, (category:IMainCategory):void => { if (category.icons) { this.$scope.icons = this.$scope.icons.concat(category.icons); } @@ -79,26 +86,26 @@ export class IconsViewModel { }); } - if (this.$scope.component.isResource()) { - let resourceType:string = this.$scope.component.getComponentSubType(); - if (resourceType === 'VL') { + if (this.component.isResource()) { + let resourceType:string = this.component.getComponentSubType(); + if (resourceType === ResourceType.VL) { this.$scope.icons = ['vl']; } - if (resourceType === 'CP') { + if (resourceType === ResourceType.CP) { this.$scope.icons = ['cp']; } } if (this.$scope.icons.length === 0) { - this.$scope.icons = this.availableIconsService.getIcons(this.$scope.component.componentType); + this.$scope.icons = this.availableIconsService.getIcons(this.component.componentType); } //we always add the defual icon to the list this.$scope.icons.push('defaulticon'); }; private initVendor = ():void => { - let vendors:Array<string> = this.availableIconsService.getIcons(this.$scope.component.componentType).slice(5, 19); - let vendorName = this.$scope.component.vendorName.toLowerCase(); + let vendors:Array<string> = this.availableIconsService.getIcons(this.component.componentType).slice(5, 19); + let vendorName = this.component.vendorName.toLowerCase(); if ('at&t' === vendorName) { vendorName = 'att'; } @@ -115,17 +122,22 @@ export class IconsViewModel { }; private initScope():void { + this.$scope.modalIcons = this.$uibModalInstance; this.$scope.icons = []; - this.$scope.setValidState(true); - //if(this.$scope.component.icon === DEFAULT_ICON){ - // //this.$scope.setValidState(false); - //} - - this.$scope.setComponentIcon = (iconSrc:string):void => { - this.$state.current.data.unsavedChanges = !this.$scope.isViewMode() && (iconSrc != this.initialIcon); - this.$scope.component.icon = iconSrc; - // this.$scope.setValidState(true); + this.$scope.changeIcon = (icon:string):void => { + this.$scope.selectedIcon = icon; }; - + this.$scope.cancel = ():void => { + this.$uibModalInstance.dismiss(); + }; + this.$scope.updateIcon = ():void => { + let isDirty:boolean = this.component.icon != this.$scope.selectedIcon; + this.component.icon = this.$scope.selectedIcon; + this.$uibModalInstance.close(isDirty); + } } + } + + + diff --git a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less index bc1404d7c4..71a3101412 100644 --- a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less +++ b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor.less @@ -48,28 +48,6 @@ //text-indent: -10px; } - /*Added by - Ikram */ - .i-sdc-product-input, - .i-sdc-product-select { - border: 1px solid @border_color_f; - min-height: 30px; - padding: 0; - width: 100%; - margin: 1px 0; - background-color: #F2F2F2; - outline: none; - - &:disabled { - .disabled; - } - optgroup{ - color: @color_u; - option{ - color: @color_b; - } - } - } - .i-sdc-categories-list-item-icon { display: inline-block; float: right; diff --git a/catalog-ui/src/app/view-models/shared/notification-custom-template.html b/catalog-ui/src/app/view-models/shared/notification-custom-template.html new file mode 100644 index 0000000000..d8fdf135b9 --- /dev/null +++ b/catalog-ui/src/app/view-models/shared/notification-custom-template.html @@ -0,0 +1,14 @@ +<div class="ui-notification"> + <div class="notification-container"> + <div class="icon-container"> + <div class="icon-circle"> + <div class="icon sprite-new"> + </div> + </div> + </div> + <div class="msg-content"> + <h3 ng-show="title" ng-bind-html="title"></h3> + <div class="message" ng-bind-html="message"></div> + </div> + </div> +</div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less index 61bb3e9f01..24f83ec503 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/activity-log/activity-log.less @@ -1,7 +1,4 @@ .activity-log { - - margin-top: 30px; - .title-wrapper { display: flex; justify-content: flex-end; @@ -10,7 +7,7 @@ .table-container-flex .table .body .scrollbar-container { max-height: 448px; } - + .view-mode { background-color: @main_color_p; } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less index ffd28afce4..932daa167d 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/attributes/attributes.less @@ -13,7 +13,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; .text{ overflow: hidden; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts index 894f8aeb2a..0e5a5fcd6c 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view-model.ts @@ -18,17 +18,20 @@ * ============LICENSE_END========================================================= */ 'use strict'; -import {Component, Product, ComponentInstance, IAppMenu} from "app/models"; +import {Component, ComponentInstance, IAppMenu} from "app/models"; import {SharingService, CacheService, EventListenerService, LeftPaletteLoaderService} from "app/services"; import {ModalsHandler, GRAPH_EVENTS, ComponentFactory, ChangeLifecycleStateHandler, MenuHandler, EVENTS} from "app/utils"; import {IWorkspaceViewModelScope} from "../../workspace-view-model"; import {ComponentServiceNg2} from "app/ng2/services/component-services/component.service"; import {ComponentGenericResponse} from "app/ng2/services/responses/component-generic-response"; +import {Resource} from "app/models/components/resource"; +import {ResourceType} from "../../../../utils/constants"; export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { currentComponent:Component; - selectedComponent:Component; + selectedComponent: Component; + componentInstanceNames: Array<string>; isLoading:boolean; graphApi:any; sharingService:SharingService; @@ -128,7 +131,6 @@ export class CompositionViewModel { private openUpdateComponentInstanceNameModal = ():void => { this.ModalsHandler.openUpdateComponentInstanceNameModal(this.$scope.currentComponent).then(()=> { this.eventListenerService.notifyObservers(GRAPH_EVENTS.ON_COMPONENT_INSTANCE_NAME_CHANGED, this.$scope.currentComponent.selectedInstance); - }); }; @@ -205,9 +207,6 @@ export class CompositionViewModel { if (this.$state.current.name === 'workspace.composition.api') { this.$state.go('workspace.composition.details'); } - if (this.$state.current.name === 'workspace.composition.relations' && this.$scope.currentComponent.isProduct()) { - this.$state.go('workspace.composition.details'); - } }; this.$scope.onBackgroundClick = ():void => { @@ -226,7 +225,7 @@ export class CompositionViewModel { this.$scope.openUpdateModal = ():void => { this.openUpdateComponentInstanceNameModal(); }; - + this.$scope.deleteSelectedComponentInstance = ():void => { let state = "deleteInstance"; let onOk = ():void => { @@ -238,7 +237,7 @@ export class CompositionViewModel { this.ModalsHandler.openAlertModal(title, message).then(onOk); }; - this.$scope.onComponentInstanceVersionChange = (component:Product):void => { + this.$scope.onComponentInstanceVersionChange = (component:Component):void => { this.$scope.currentComponent = component; this.$scope.setComponent(this.$scope.currentComponent); this.$scope.updateSelectedComponent(); diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html index 761ae53909..e05574e8c8 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition-view.html @@ -6,7 +6,7 @@ is-loading="isLoading"></palette> <composition-graph component="currentComponent" data-tests-id="canvas" - is-view-only="isViewOnly"></composition-graph> + is-view-only="isViewOnly" with-sidebar="displayDesignerRightSidebar"></composition-graph> </div> <div class="w-sdc-designer-sidebar-toggle" data-ng-class="{'active': displayDesignerRightSidebar}" @@ -21,7 +21,7 @@ <div class="w-sdc-designer-sidebar-logo-ph"> <div class="large {{selectedComponent.iconSprite}} {{selectedComponent.icon}}"> <div ng-if="isComponentInstanceSelected()" - data-ng-class="{'non-certified':'CERTIFIED' !== selectedComponent.lifecycleState, 'smaller-icon': selectedComponent.icon==='vl' || selectedComponent.icon==='cp'}" + data-ng-class="{'non-certified':'CERTIFIED' !== selectedComponent.lifecycleState}" tooltips tooltip-side="top" tooltip-content="Not certified"></div> </div> </div> @@ -57,7 +57,8 @@ <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" data-ui-sref="workspace.composition.deployment" tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Deployment Artifacts" - data-tests-id="deployment-artifact-tab"> + data-tests-id="deployment-artifact-tab" + data-ng-if="!isPNF()"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new deployment-artifacts"></div> </button> <button tooltips tooltip-class="tooltip-custom tab-tooltip" diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less index 7a775bdb11..262dfd9be8 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/composition.less @@ -781,6 +781,71 @@ line-height: 18px; } + //Canvas search menu + .w-sdc-search-menu { + position:absolute; + right: 18px; + top:53px; + transition: right 0.2s; + display: flex; + flex-direction: column; + align-items: flex-end; + margin-right:10px; + + &.with-sidebar { + right:320px; + } + + .search-with-autocomplete-container.composition-search { + margin-top: 12px; + + .search-bar-input { + width: 250px; + padding:2px 50px 2px 10px; + transition:all 0.4s; + } + .clear-search-x { + top: 17px + } + + &:not(:hover):not(.autocomplete-visible):not(.active){ + border-radius: 0; + box-shadow:none; + + .search-bar-input:not(:focus){ + width: 0px; + padding:0; + border:none; + } + .clear-search-x { + display:none; + } + .search-bar-input:not(:focus) ~ .search-bar-button { + border-radius: 2px; + border:solid 1px #fff; + } + } + } + + .zoom-icons { + border:solid 1px #fff; + border-radius: 2px; + box-shadow: 0px 2px 3.88px 0.12px rgba(0, 0, 0, 0.29); + background-color: rgba(234, 234, 234, 0.88); + background-repeat: no-repeat; + margin-top: 10px; + + &:hover { + cursor:pointer; + } + + &:active { + border:none; + background-color: rgba(31, 171, 223, 0.88); + } + } + } + // --------------------------------------------------------------------------------------------------- // Canvas inline menu // --------------------------------------------------------------------------------------------------- diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts index 83e4653954..c4c63fae06 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view-model.ts @@ -33,13 +33,14 @@ import {ICompositionViewModelScope} from "../../composition-view-model"; import {ArtifactsUtils, ModalsHandler, ArtifactGroupType} from "app/utils"; import {GRAPH_EVENTS} from "app/utils/constants"; import {EventListenerService} from "app/services/event-listener-service"; +import {Dictionary} from "../../../../../../utils/dictionary/dictionary"; export interface IArtifactsViewModelScope extends ICompositionViewModelScope { artifacts:Array<ArtifactModel>; artifactType:string; downloadFile:IFileDownload; isLoading:boolean; - + displayDeleteButtonMap:Dictionary<string, boolean>; getTitle():string; addOrUpdate(artifact:ArtifactModel):void; delete(artifact:ArtifactModel):void; @@ -125,6 +126,10 @@ export class ResourceArtifactsViewModel { } } this.$scope.artifacts = artifacts; + this.$scope.displayDeleteButtonMap = new Dictionary<string, boolean>(); + _.forEach(this.$scope.artifacts, (artifact:ArtifactModel)=>{ + this.$scope.displayDeleteButtonMap[artifact.artifactLabel] = this.displayDeleteButton(artifact); + }); this.$scope.isLoading = false; }; @@ -229,6 +234,17 @@ export class ResourceArtifactsViewModel { }); }; + private displayDeleteButton = (artifact:ArtifactModel):boolean => { + if(!this.$scope.isViewMode() && artifact.esId){ + if(this.$scope.isComponentInstanceSelected()){//is artifact of instance + return !this.$scope.selectedComponent.deploymentArtifacts || !this.$scope.selectedComponent.deploymentArtifacts[artifact.artifactLabel];//if the artifact is not from instance parent + }else{//is artifact of main component + return (!artifact.isHEAT() && !artifact.isThirdParty() && !this.$scope.isLicenseArtifact(artifact)); + } + } + return false; +}; + private initScope = ():void => { this.$scope.isLoading = false; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html index 01cb9d4ee4..dfbd639eb4 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/artifacts/artifacts-view.html @@ -36,7 +36,7 @@ <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-desc-label" data-ng-show="artifact.description">Description:</span>{{artifact.description}} </div> </div> - <button ng-if="!isViewMode() && artifact.esId && !isComponentInstanceSelected() && !artifact.isHEAT() && !artifact.isThirdParty() && !isLicenseArtifact(artifact)" class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete" + <button ng-if="displayDeleteButtonMap[artifact.artifactLabel]" class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete" data-tests-id="delete_{{artifact.artifactDisplayName}}" data-ng-click="delete(artifact)" type="button"></button> <button ng-if="!isViewMode() && artifact.isHEAT() && isComponentInstanceSelected() && artifact.heatParameters.length" class="i-sdc-designer-sidebar-section-content-item-button attach sprite e-sdc-small-icon-pad" @@ -60,7 +60,7 @@ </div> </div> - <div class="w-sdc-designer-sidebar-section-footer" data-ng-if="!isViewMode() && artifactType!=='api' && (!isComponentInstanceSelected()||selectedComponent.resourceType=='VF') && !currentComponent.isProduct() && ('deployment' != artifactType || selectedComponent.isComplex())"> + <div class="w-sdc-designer-sidebar-section-footer" data-ng-if="!isViewMode() && artifactType!=='api' && (!isComponentInstanceSelected()||selectedComponent.resourceType=='VF') && ('deployment' != artifactType || selectedComponent.isComplex())"> <button class="w-sdc-designer-sidebar-section-footer-action tlv-btn blue" data-tests-id="add_Artifact_Button" data-ng-click="addOrUpdate({})" type="button">Add Artifact</button> </div> </div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts index 223d6cf964..0d8d17ec73 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view-model.ts @@ -82,7 +82,7 @@ export class DetailsViewModel { let highestVersion = _.last(Object.keys(this.$scope.selectedComponent.allVersions)); if (parseFloat(highestVersion) % 1) { //if highest is minor, make sure it is the latest checked in - - let latestVersionComponent:LeftPaletteComponent = _.maxBy(_.filter(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(this.$scope.currentComponent.componentType), (component:LeftPaletteComponent) => { //latest checked in + let latestVersionComponent:LeftPaletteComponent = _.maxBy(_.filter(this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(this.$scope.currentComponent), (component:LeftPaletteComponent) => { //latest checked in return (component.systemName === this.$scope.selectedComponent.systemName || component.uuid === this.$scope.selectedComponent.uuid); }),(component)=>{return component.version}); diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html index 70dc58075a..0418515789 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details-view.html @@ -23,9 +23,9 @@ <span class="i-sdc-designer-sidebar-section-content-item-label">Version:</span> <span class="i-sdc-designer-sidebar-section-content-item-value" - data-ng-if="!isComponentInstanceSelected() || selectedComponent.isVl()" data-tests-id="rightTab_version" data-ng-bind="selectedComponent.version"></span> + data-ng-if="!isComponentInstanceSelected()" data-tests-id="rightTab_version" data-ng-bind="selectedComponent.version"></span> - <ng-form name="editForm" data-ng-if="isComponentInstanceSelected() && !selectedComponent.isVl()"> + <ng-form name="editForm" data-ng-if="isComponentInstanceSelected()"> <select data-ng-model="editResourceVersion.changeVersion" name="changeVersion" data-tests-id="changeVersion" data-ng-disabled="$parent.isViewOnly" class="i-sdc-designer-sidebar-section-content-item-value i-sdc-form-select" data-ng-class="{'minor': (editResourceVersion.changeVersion)%1}" @@ -77,6 +77,27 @@ data-tests-id="rightTab_vendorRelease"> </span> </div> + <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isResource()"> + <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_RESOURCE_MODEL_NUMBER"></span> + <span class="i-sdc-designer-sidebar-section-content-item-value vendor-model-number" data-ng-bind="selectedComponent.resourceVendorModelNumber" + tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.resourceVendorModelNumber}}" + data-tests-id="rightTab_resourceVendorModelNumber"> + </span> + </div> + <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isService()"> + <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_SERVICE_TYPE"></span> + <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.serviceType" + tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.serviceType}}" + data-tests-id="rightTab_serviceType"> + </span> + </div> + <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="selectedComponent.isService()"> + <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_SERVICE_ROLE"></span> + <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.serviceRole" + tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{selectedComponent.serviceRole}}" + data-tests-id="rightTab_serviceRole"> + </span> + </div> <div class="i-sdc-designer-sidebar-section-content-item"> <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_CONTACT_ID"></span> <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.contactId" diff --git a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less index 3ebb14c2b8..0ed72e2f00 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/composition/tabs/details/details.less @@ -37,6 +37,9 @@ max-width: 160px; vertical-align:bottom; font-weight: normal; + &.vendor-model-number{ + max-width: 110px; + } &.additional-information{ max-width:160px; display: inline-block; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less index 3596a217b8..f67d088b5a 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/deployment-artifacts/deployment-artifacts.less @@ -71,7 +71,7 @@ .table-container-flex { - margin-top: 27px; + margin-top: 0; .text{ overflow: hidden; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts index 05b3324bbb..1dc326a7c0 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view-model.ts @@ -22,14 +22,16 @@ import {ModalsHandler, ValidationUtils, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, DEFAULT_ICON, ResourceType} from "app/utils"; import {CacheService, EventListenerService, ProgressService} from "app/services"; -import {IAppConfigurtaion, Product, IValidate, IMainCategory, Resource, ISubCategory,Service} from "app/models"; +import {IAppConfigurtaion, IValidate, IMainCategory, Resource, ISubCategory,Service} from "app/models"; import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; export class Validation { componentNameValidationPattern:RegExp; contactIdValidationPattern:RegExp; tagValidationPattern:RegExp; - vendorValidationPattern:RegExp; + VendorReleaseValidationPattern:RegExp; + VendorNameValidationPattern:RegExp; + VendorModelNumberValidationPattern:RegExp; commentValidationPattern:RegExp; projectCodeValidationPattern:RegExp; } @@ -63,6 +65,8 @@ export interface IGeneralScope extends IWorkspaceViewModelScope { onEcompGeneratedNamingChange():void; openOnBoardingModal():void; initCategoreis():void; + updateIcon():void; + possibleToUpdateIcon():boolean; } export class GeneralViewModel { @@ -73,7 +77,9 @@ export class GeneralViewModel { 'ComponentNameValidationPattern', 'ContactIdValidationPattern', 'TagValidationPattern', - 'VendorValidationPattern', + 'VendorReleaseValidationPattern', + 'VendorNameValidationPattern', + 'VendorModelNumberValidationPattern', 'CommentValidationPattern', 'ValidationUtils', 'sdcConfig', @@ -93,7 +99,9 @@ export class GeneralViewModel { private ComponentNameValidationPattern:RegExp, private ContactIdValidationPattern:RegExp, private TagValidationPattern:RegExp, - private VendorValidationPattern:RegExp, + private VendorReleaseValidationPattern:RegExp, + private VendorNameValidationPattern:RegExp, + private VendorModelNumberValidationPattern:RegExp, private CommentValidationPattern:RegExp, private ValidationUtils:ValidationUtils, private sdcConfig:IAppConfigurtaion, @@ -121,7 +129,9 @@ export class GeneralViewModel { this.$scope.validation.componentNameValidationPattern = this.ComponentNameValidationPattern; this.$scope.validation.contactIdValidationPattern = this.ContactIdValidationPattern; this.$scope.validation.tagValidationPattern = this.TagValidationPattern; - this.$scope.validation.vendorValidationPattern = this.VendorValidationPattern; + this.$scope.validation.VendorReleaseValidationPattern = this.VendorReleaseValidationPattern; + this.$scope.validation.VendorNameValidationPattern = this.VendorNameValidationPattern; + this.$scope.validation.VendorModelNumberValidationPattern = this.VendorModelNumberValidationPattern; this.$scope.validation.commentValidationPattern = this.CommentValidationPattern; this.$scope.validation.projectCodeValidationPattern = this.ProjectCodeValidationPattern; }; @@ -140,12 +150,6 @@ export class GeneralViewModel { this.$scope.componentCategories = new componentCategories(); this.$scope.componentCategories.selectedCategory = this.$scope.component.selectedCategory; - // Workaround to short vendor name to 25 chars - // Amdocs send 27 chars, and the validation pattern is 25 chars. - if (this.$scope.component.vendorName) { - this.$scope.component.vendorName = this.$scope.component.vendorName.substr(0, 25); - } - // Init UIModel this.$scope.component.tags = _.without(this.$scope.component.tags, this.$scope.component.name); @@ -202,10 +206,7 @@ export class GeneralViewModel { }; //TODO remove this after handling contact in UI - if (this.$scope.component.isProduct() && this.$scope.isCreateMode()) { - (<Product>this.$scope.component).contacts = []; - (<Product>this.$scope.component).contacts.push(this.cacheService.get("user").userId); - } else if (this.$scope.isCreateMode()) { + if (this.$scope.isCreateMode()) { this.$scope.component.contactId = this.cacheService.get("user").userId; } @@ -273,6 +274,24 @@ export class GeneralViewModel { }); }; + this.$scope.updateIcon = ():void => { + this.ModalsHandler.openUpdateIconModal(this.$scope.component).then((isDirty:boolean)=> { + if(!this.$scope.isCreateMode()){ + this.$state.current.data.unsavedChanges = this.$state.current.data.unsavedChanges || isDirty; + } + }, ()=> { + // ERROR + }); + }; + + this.$scope.possibleToUpdateIcon = ():boolean => { + if(this.$scope.componentCategories.selectedCategory && (!this.$scope.component.isResource() || this.$scope.component.vendorName)){ + return true; + }else{ + return false; + } + } + this.$scope.validateName = (isInit:boolean):void => { if (isInit === undefined) { isInit = false; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html index 2ad0cbacd6..d3626803e9 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general-view.html @@ -4,122 +4,121 @@ <div class="w-sdc-form-section-container"> - <!--------------------- IMPORT TOSCA FILE USING BROWSE (ALSO VFC) --------------------> - <div class="i-sdc-form-item" ng-if="isShowFileBrowse"> - <label class="i-sdc-form-label" data-ng-class="{'required':isCreateMode()}">{{browseFileLabel}}</label> - <file-upload id="fileUploadElement" - class="i-sdc-form-input" - element-name="fileElement" - element-disabled="{{!isCreateMode()&&!(isEditMode()&&component.resourceType=='VF')}} || {{isViewMode()}}" - form-element="editForm" - file-model="component.importedFile" - on-file-changed-in-directive="uploadFileChangedInGeneralTab" - extensions="{{importedFileExtension}}" - default-text="'Browse to select file'" - data-ng-class="{'error':!(isEditMode()&&component.resourceType=='VF') && (!editForm.fileElement.$valid || !component.importedFile.filename)}"></file-upload> - </div> - - <!--------------------- IMPORT TOSCA FILE USING ONBOARDING --------------------> - <div class="i-sdc-form-item" ng-if="isShowOnboardingSelectionBrowse"> - <label class="i-sdc-form-label required">Select VSP</label> - <div class="i-sdc-form-file-upload i-sdc-form-input"> - <span class="i-sdc-form-file-name" data-tests-id="filename">{{(fileModel && fileModel.filename) || importedToscaBrowseFileText}}</span> - <div class="i-sdc-form-file-upload-x-btn" ng-click="cancel()" data-ng-show="fileModel.filename && fileModel.filename!=='' && elementDisabled!=='true'"></div> - <input type="button" name="fileElement"/> - <div class="file-upload-browse-btn" data-ng-click="openOnBoardingModal()" data-tests-id="browseButton">Browse</div> - </div> - </div> - - <div class="input-error-file-upload" data-ng-show="component.importedFile && (!editForm.fileElement.$valid || !component.importedFile.filename)"> - <!-- editForm.fileElement.$error.required <== Can not use this, because the browse is done from outside for the first time --> - <span ng-show="!(isEditMode()&&component.resourceType=='VF')&&!component.importedFile.filename" translate="NEW_SERVICE_RESOURCE_ERROR_TOSCA_FILE_REQUIRED"></span><!-- Required --> - <span ng-show="editForm.fileElement.$error.maxsize" translate="VALIDATION_ERROR_MAX_FILE_SIZE"></span> - <span ng-show="editForm.fileElement.$error.filetype" translate="NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS" translate-values="{'extensions': '{{importedFileExtension}}' }"></span> - <span ng-show="editForm.fileElement.$error.emptyFile" translate="VALIDATION_ERROR_EMPTY_FILE"></span> - </div> - <!--------------------- IMPORT TOSCA FILE --------------------> - <div class="w-sdc-form-columns-wrapper"> <div class="w-sdc-form-column"> - - <!--------------------- NAME --------------------> - <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.componentName)}"> - <label class="i-sdc-form-label required">Name</label> - <input class="i-sdc-form-input" - data-ng-class="{'view-mode': isViewMode()}" - name="componentName" - data-ng-init="isCreateMode() && validateName(true)" - data-ng-maxlength="{{component.isProduct()?'25':'50'}}" - maxlength="{{component.isProduct()?'25':'50'}}" - data-ng-minlength="{{component.isProduct()?'4':'0'}}" - minlength="{{component.isProduct()?'4':'0'}}" - data-ng-model="component.name" - type="text" - data-required - data-ng-model-options="{ debounce: 500 }" - data-ng-pattern="validation.componentNameValidationPattern" - data-ng-disabled="component.isAlreadyCertified()" - data-tests-id="name" - autofocus - ng-readonly="isViewMode()" - /> - - <div class="input-error" data-ng-show="validateField(editForm.componentName)"> - <span ng-show="editForm.componentName.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_RESOURCE_NAME_REQUIRED"></span> - <span ng-show="editForm.componentName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span> - <span ng-show="editForm.componentName.$error.minlength" translate="VALIDATION_ERROR_MIN_LENGTH" translate-values="{'min': '4' }"></span> - <span ng-show="editForm.componentName.$error.nameExist" translate="NEW_SERVICE_RESOURCE_ERROR_NAME_EXISTS"></span> - <span ng-show="editForm.componentName.$error.pattern" translate="VALIDATION_ERROR_INVALID_NAME"></span> + <div class="upper-general-fields"> + <div class="selected-icon-container" data-ng-class="{'show-only-on-over':'defaulticon'!=component.icon && !isViewMode()}"> + <div class="selected-icon-inner-container"> + <div class="sprite-new update-component-icon" data-ng-click="updateIcon()" data-ng-if="!isViewMode() && possibleToUpdateIcon()"></div> + <div class="i-sdc-form-item-suggested-icon large selected-icon {{component.iconSprite}} {{component.icon}}" + data-ng-class="{ 'disable': isViewMode() || !possibleToUpdateIcon() }" + ng-model="component.icon" + tooltips tooltip-content='{{component.icon | translate}}' + > + </div> + </div> + </div> + <div class="name-and-category-fields"> + <!--------------------- NAME --------------------> + <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.componentName)}"> + <label class="i-sdc-form-label required">Name</label> + <input class="i-sdc-form-input" + data-ng-class="{'view-mode': isViewMode()}" + name="componentName" + data-ng-init="isCreateMode() && validateName(true)" + data-ng-maxlength="50" + maxlength="50" + data-ng-model="component.name" + type="text" + data-required + data-ng-model-options="{ debounce: 500 }" + data-ng-pattern="validation.componentNameValidationPattern" + data-ng-disabled="component.isAlreadyCertified()" + data-tests-id="name" + autofocus + ng-readonly="isViewMode()" + /> + + <div class="input-error" data-ng-show="validateField(editForm.componentName)"> + <span ng-show="editForm.componentName.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_RESOURCE_NAME_REQUIRED"></span> + <span ng-show="editForm.componentName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span> + <span ng-show="editForm.componentName.$error.minlength" translate="VALIDATION_ERROR_MIN_LENGTH" translate-values="{'min': '4' }"></span> + <span ng-show="editForm.componentName.$error.nameExist" translate="NEW_SERVICE_RESOURCE_ERROR_NAME_EXISTS"></span> + <span ng-show="editForm.componentName.$error.pattern" translate="VALIDATION_ERROR_INVALID_NAME"></span> + </div> + </div> + <!--------------------- NAME --------------------> + + + + <!--------------------- CATEGORIES --------------------> + <div class="i-sdc-form-item" + data-ng-class="{'error': validateField(editForm.category)}"> + <loader data-display="!categories && !initCategoreis()" relative="true"></loader> + <label class="i-sdc-form-label required">Category</label> + <select class="i-sdc-form-select" + data-required + name="category" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-change="onCategoryChange()" + data-ng-disabled="component.isAlreadyCertified() || (component.isCsarComponent() && component.selectedCategory && component.selectedCategory!=='')" + data-ng-model="componentCategories.selectedCategory" + data-tests-id="selectGeneralCategory" + > + <option value="">Select category</option> + <optgroup ng-if="component.isResource()" data-ng-repeat="mainCategory in categories | orderBy:['name']" label="{{mainCategory.name}}" data-tests-id="{{mainCategory.name}}"> + <option data-ng-repeat="subCategory in mainCategory.subcategories track by $index" + data-ng-selected="componentCategories.selectedCategory === calculateUnique(mainCategory.name,subCategory.name)" + data-tests-id="{{subCategory.name}}" + value="{{calculateUnique(mainCategory.name, subCategory.name)}}">{{subCategory.name}} + + </option> + </optgroup> + <option ng-if="component.isService()" data-ng-repeat="mainCategory in categories | orderBy:['name']" + data-ng-selected="component.selectedCategory===mainCategory.name" + value="{{mainCategory.name}}" + data-tests-id="{{mainCategory.name}}">{{mainCategory.name}}</option> + </select> + + <div class="input-error" data-ng-show="validateField(editForm.category)"> + <span ng-show="editForm.category.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_CATEGORY_REQUIRED"></span> + </div> + </div> + <!--------------------- CATEGORIES --------------------> + </div> </div> - </div> - <!--------------------- NAME --------------------> + <!--------------------- RESOURCE TAGS --------------------> + <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.tags)}"> + <label class="i-sdc-form-label">Tags</label> - <!--------------------- FULL NAME --------------------> - <div ng-if="component.isProduct()" class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.fullName)}"> - <label class="i-sdc-form-label required">Full Name</label> - <input class="i-sdc-form-input" - name="fullName" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-change="validateName()" - data-ng-maxlength="100" - maxlength="100" - data-ng-minlength="4" - minlength="4" - data-ng-model="component.fullName" - type="text" - data-required - data-ng-model-options="{ debounce: 500 }" - data-ng-pattern="validation.commentValidationPattern" - data-tests-id="fullName" - autofocus - ng-readonly="isViewMode()" - /> + <sdc-tags form-element="editForm" element-name="tags" max-tags="20" class="i-sdc-form-item-tags" + sdc-disabled="isViewMode()" + tags="component.tags" + pattern="validation.tagValidationPattern" + special-tag="component.name"></sdc-tags> - <div class="input-error" data-ng-show="validateField(editForm.fullName)"> - <span ng-show="editForm.fullName.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_RESOURCE_NAME_REQUIRED"></span> - <span ng-show="editForm.fullName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '50' }"></span> - <span ng-show="editForm.fullName.$error.minlength" translate="VALIDATION_ERROR_MIN_LENGTH" translate-values="{'min': '4' }"></span> - <span ng-show="editForm.fullName.$error.nameExist" translate="NEW_SERVICE_RESOURCE_ERROR_NAME_EXISTS"></span> - <span ng-show="editForm.fullName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + <div class="input-error" data-ng-show="validateField(editForm.tags)"> + <span ng-show="editForm.tags.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + <span ng-show="editForm.tags.$error.nameExist" translate="NEW_SERVICE_RESOURCE_ERROR_TAG_NAME_EXIST"></span> </div> </div> - <!--------------------- NAME --------------------> + <!--------------------- RESOURCE TAGS --------------------> <!--------------------- DESCRIPTION --------------------> - <div class="i-sdc-form-item" + <div class="i-sdc-form-item description-field" data-ng-class="{'error': validateField(editForm.description)}"> <label class="i-sdc-form-label required">Description</label> - <textarea class="description" - name="description" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-maxlength="1024" - data-required - data-ng-model="component.description" - data-ng-model-options="{ debounce: 500 }" - data-ng-pattern="validation.commentValidationPattern" - maxlength="1024" - data-tests-id="description"></textarea> + <textarea class="description" + name="description" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-maxlength="1024" + data-required + data-ng-model="component.description" + data-ng-model-options="{ debounce: 500 }" + data-ng-pattern="validation.commentValidationPattern" + maxlength="1024" + data-tests-id="description"></textarea> <!-- placeholder="Description here..." --> <div class="input-error" data-ng-show="validateField(editForm.description)"> @@ -130,110 +129,85 @@ </div> <!--------------------- DESCRIPTION --------------------> - <!--------------------- CATEGORIES --------------------> - <div class="i-sdc-form-item" - data-ng-class="{'error': validateField(editForm.category)}" - data-ng-if="!component.isProduct()"> - <loader data-display="!categories && !initCategoreis()" relative="true"></loader> - <label class="i-sdc-form-label required">Category</label> - <select class="i-sdc-form-select" - data-required - name="category" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-change="onCategoryChange()" - data-ng-disabled="component.isAlreadyCertified() || (component.isCsarComponent() && component.selectedCategory && component.selectedCategory!=='')" - data-ng-model="componentCategories.selectedCategory" - data-tests-id="selectGeneralCategory" - > - <option value="">Select category</option> - <optgroup ng-if="component.isResource()" data-ng-repeat="mainCategory in categories | orderBy:['name']" label="{{mainCategory.name}}" data-tests-id="{{mainCategory.name}}"> - <option data-ng-repeat="subCategory in mainCategory.subcategories track by $index" - data-ng-selected="componentCategories.selectedCategory === calculateUnique(mainCategory.name,subCategory.name)" - data-tests-id="{{subCategory.name}}" - value="{{calculateUnique(mainCategory.name, subCategory.name)}}">{{subCategory.name}} - - </option> - </optgroup> - <option ng-if="component.isService()" data-ng-repeat="mainCategory in categories | orderBy:['name']" - data-ng-selected="component.selectedCategory===mainCategory.name" - value="{{mainCategory.name}}" - data-tests-id="{{mainCategory.name}}">{{mainCategory.name}}</option> - </select> - - <div class="input-error" data-ng-show="validateField(editForm.category)"> - <span ng-show="editForm.category.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_CATEGORY_REQUIRED"></span> - </div> - </div> - <!--------------------- CATEGORIES --------------------> - - <!--------------------- PROJECT CODE --------------------> - <div class="i-sdc-form-item" data-ng-if="!component.isResource()" - data-ng-class="{'error': validateField(editForm.projectCode)}"> - <label class="i-sdc-form-label required" translate="GENERAL_LABEL_PROJECT_CODE"></label> - <input class="i-sdc-form-input" type="text" - data-ng-model="component.projectCode" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-model-options="{ debounce: 500 }" - maxlength="50" - data-required - name="projectCode" - data-ng-pattern="validation.projectCodeValidationPattern" - data-tests-id="projectCode" - /> + </div><!-- Close w-sdc-form-column --> - <div class="input-error" data-ng-show="validateField(editForm.projectCode)"> - <span ng-show="editForm.projectCode.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_PROJECT_CODE_REQUIRED"></span> - <span ng-show="editForm.projectCode.$error.pattern" translate="NEW_SERVICE_RESOURCE_ERROR_PROJECT_CODE_NOT_VALID"></span> + <div class="w-sdc-form-column"> + <!--------------------- IMPORT TOSCA FILE USING BROWSE (ALSO VFC) --------------------> + <div class="i-sdc-form-item" ng-if="isShowFileBrowse"> + <label class="i-sdc-form-label" data-ng-class="{'required':isCreateMode()}">{{browseFileLabel}}</label> + <file-upload id="fileUploadElement" + class="i-sdc-form-input" + element-name="fileElement" + element-disabled="{{!isCreateMode()&&!(isEditMode()&&component.resourceType=='VF')}} || {{isViewMode()}}" + form-element="editForm" + file-model="component.importedFile" + on-file-changed-in-directive="uploadFileChangedInGeneralTab" + extensions="{{importedFileExtension}}" + default-text="'Browse to select file'" + data-ng-class="{'error':!(isEditMode()&&component.resourceType=='VF') && (!editForm.fileElement.$valid || !component.importedFile.filename)}"></file-upload> </div> - </div> + <!--------------------- IMPORT TOSCA FILE USING ONBOARDING --------------------> + <div class="i-sdc-form-item" ng-if="isShowOnboardingSelectionBrowse"> + <label class="i-sdc-form-label required">Select VSP</label> + <div class="i-sdc-form-file-upload i-sdc-form-input"> + <span class="i-sdc-form-file-name" data-tests-id="filename">{{(fileModel && fileModel.filename) || importedToscaBrowseFileText}}</span> + <div class="i-sdc-form-file-upload-x-btn" ng-click="cancel()" data-ng-show="fileModel.filename && fileModel.filename!=='' && elementDisabled!=='true'"></div> + <input type="button" name="fileElement"/> + <div class="file-upload-browse-btn" data-ng-click="openOnBoardingModal()" data-tests-id="browseButton">Browse</div> + </div> + </div> - <!--------------------- ECOMPGENERATEDNAMING --------------------> + <div class="input-error-file-upload" data-ng-show="component.importedFile && (!editForm.fileElement.$valid || !component.importedFile.filename)"> + <!-- editForm.fileElement.$error.required <== Can not use this, because the browse is done from outside for the first time --> + <span ng-show="!(isEditMode()&&component.resourceType=='VF')&&!component.importedFile.filename" translate="NEW_SERVICE_RESOURCE_ERROR_TOSCA_FILE_REQUIRED"></span><!-- Required --> + <span ng-show="editForm.fileElement.$error.maxsize" translate="VALIDATION_ERROR_MAX_FILE_SIZE"></span> + <span ng-show="editForm.fileElement.$error.filetype" translate="NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS" translate-values="{'extensions': '{{importedFileExtension}}' }"></span> + <span ng-show="editForm.fileElement.$error.emptyFile" translate="VALIDATION_ERROR_EMPTY_FILE"></span> + </div> + <!--------------------- IMPORT TOSCA FILE --------------------> - <div class="i-sdc-form-item" - data-ng-class="{'error': validateField(editForm.ecompGeneratedNaming)}" - data-ng-if="component.isService()"> - <label class="i-sdc-form-label">Ecomp Generated Naming</label> - <select class="i-sdc-form-select" - data-required - name="ecompGeneratedNaming" - data-ng-change="onEcompGeneratedNamingChange()" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-model="component.ecompGeneratedNaming" - data-tests-id="ecompGeneratedNaming"> - <option ng-value="true">true</option> - <option ng-value="false">false</option> - </select> - <div class="input-error" data-ng-show="validateField(editForm.ecompGeneratedNaming)"> + <!--------------------- USER ID --------------------> + <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.contactId)}"> + <label class="i-sdc-form-label required" translate="GENERAL_LABEL_CONTACT_ID"></label> + <input class="i-sdc-form-input" type="text" + data-ng-model="component.contactId" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-required="true" + name="contactId" + data-ng-pattern="validation.contactIdValidationPattern" + data-ng-model-options="{ debounce: 500 }" + data-tests-id="contactId" + maxlength="50" + /> + <div class="input-error" data-ng-show="validateField(editForm.contactId)"> + <span ng-show="editForm.contactId.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_CONTACT_REQUIRED"></span> + <span ng-show="editForm.contactId.$error.pattern" translate="NEW_SERVICE_RESOURCE_ERROR_CONTACT_NOT_VALID"></span> </div> </div> - <!--------------------- CATEGORIES --------------------> - - <!--------------------- NAMING POLICY --------------------> - <div ng-if="component.isService()" class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.namingPolicy)}"> - <label class="i-sdc-form-label">Naming policy</label> - <input class="i-sdc-form-input" - name="fullName" - data-ng-class="{'view-mode': isViewMode() || !component.ecompGeneratedNaming}" - data-ng-maxlength="100" - maxlength="100" - data-ng-model="component.namingPolicy" - type="text" + <!--------------------- USER ID --------------------> + + <!--------------------- PROJECT CODE --------------------> + <div class="i-sdc-form-item" data-ng-if="!component.isResource()" + data-ng-class="{'error': validateField(editForm.projectCode)}"> + <label class="i-sdc-form-label required" translate="GENERAL_LABEL_PROJECT_CODE"></label> + <input class="i-sdc-form-input" type="text" + data-ng-model="component.projectCode" + data-ng-class="{'view-mode': isViewMode()}" data-ng-model-options="{ debounce: 500 }" - data-ng-pattern="validation.commentValidationPattern" - data-tests-id="namingPolicy" - autofocus - ng-readonly="isViewMode() || !component.ecompGeneratedNaming" + maxlength="50" + data-required + name="projectCode" + data-ng-pattern="validation.projectCodeValidationPattern" + data-tests-id="projectCode" /> - <div class="input-error" data-ng-show="validateField(editForm.namingPolicy)"> - <span ng-show="editForm.namingPolicy.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span> - <span ng-show="editForm.namingPolicy.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + <div class="input-error" data-ng-show="validateField(editForm.projectCode)"> + <span ng-show="editForm.projectCode.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_PROJECT_CODE_REQUIRED"></span> + <span ng-show="editForm.projectCode.$error.pattern" translate="NEW_SERVICE_RESOURCE_ERROR_PROJECT_CODE_NOT_VALID"></span> </div> </div> - <!--------------------- NAMING POLICY --------------------> - <!--------------------- VENDOR NAME --------------------> <div ng-if="component.isResource()" class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.vendorName)}"> @@ -242,20 +216,20 @@ data-ng-class="{'view-mode': isViewMode()}" data-ng-model="component.vendorName" data-ng-model-options="{ debounce: 500 }" - data-ng-maxlength="25" + data-ng-maxlength="60" data-required ng-click="oldValue = component.vendorName" name="vendorName" data-ng-change="onVendorNameChange(oldValue)" - data-ng-pattern="validation.vendorValidationPattern" - maxlength="25" + data-ng-pattern="validation.VendorNameValidationPattern" + maxlength="60" data-ng-disabled="component.isAlreadyCertified() || (component.isCsarComponent() && component.vendorName && component.vendorName!=='')" data-tests-id="vendorName" - /> + /> <div class="input-error" data-ng-show="validateField(editForm.vendorName)"> <span ng-show="editForm.vendorName.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_VENDOR_NAME_REQUIRED"></span> - <span ng-show="editForm.vendorName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span> + <span ng-show="editForm.vendorName.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '60' }"></span> <span ng-show="editForm.vendorName.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> </div> @@ -275,80 +249,160 @@ data-ng-maxlength="25" data-required name="vendorRelease" - data-ng-pattern="validation.vendorValidationPattern" + data-ng-pattern="validation.VendorReleaseValidationPattern" maxlength="25" data-ng-disabled="component.isCsarComponent() && component.vendorRelease && component.vendorRelease!==''" data-tests-id="vendorRelease" - /> + /> <div class="input-error" data-ng-show="validateField(editForm.vendorRelease)"> <span ng-show="editForm.vendorRelease.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_VENDOR_RELEASE_REQUIRED"></span> - <span ng-show="editForm.vendorRelease.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '128' }"></span> + <span ng-show="editForm.vendorRelease.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span> <span ng-show="editForm.vendorRelease.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> </div> </div> <!--------------------- VENDOR RELEASE --------------------> + <!--------------------- Resource Model Number --------------------> + <div ng-if="component.isResource()" + class="i-sdc-form-item" + data-ng-class="{'error': validateField(editForm.resourceVendorModelNumber)}"> + <label class="i-sdc-form-label" translate="GENERAL_TAB_LABEL_RESOURCE_MODEL_NUMBER"></label> + <input class="i-sdc-form-input" type="text" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-model="component.resourceVendorModelNumber" + data-ng-model-options="{ debounce: 500 }" + data-ng-maxlength="65" + name="resourceVendorModelNumber" + data-ng-pattern="validation.VendorModelNumberValidationPattern" + maxlength="65" + data-tests-id="resourceVendorModelNumber" + /> + <div class="input-error" data-ng-show="validateField(editForm.resourceVendorModelNumber)"> + <span ng-show="editForm.resourceVendorModelNumber.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '65' }"></span> + <span ng-show="editForm.resourceVendorModelNumber.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + </div> + </div> + <!--------------------- Resource Model Number --------------------> - </div><!-- Close w-sdc-form-column --> - - <div class="w-sdc-form-column"> - - <!--------------------- RESOURCE TAGS --------------------> - <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.tags)}"> - <label class="i-sdc-form-label">Tags</label> + <!--------------------- ECOMPGENERATEDNAMING --------------------> - <sdc-tags form-element="editForm" element-name="tags" max-tags="20" class="i-sdc-form-item-tags" - sdc-disabled="isViewMode()" - tags="component.tags" - pattern="validation.tagValidationPattern" - special-tag="component.name"></sdc-tags> + <div class="i-sdc-form-item" + data-ng-class="{'error': validateField(editForm.ecompGeneratedNaming)}" + data-ng-if="component.isService()"> + <label class="i-sdc-form-label">Ecomp Generated Naming</label> + <select class="i-sdc-form-select" + data-required + name="ecompGeneratedNaming" + data-ng-change="onEcompGeneratedNamingChange()" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-model="component.ecompGeneratedNaming" + data-tests-id="ecompGeneratedNaming"> + <option ng-value="true">true</option> + <option ng-value="false">false</option> + </select> + <div class="input-error" data-ng-show="validateField(editForm.ecompGeneratedNaming)"> - <div class="input-error" data-ng-show="validateField(editForm.tags)"> - <span ng-show="editForm.tags.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> - <span ng-show="editForm.tags.$error.nameExist" translate="NEW_SERVICE_RESOURCE_ERROR_TAG_NAME_EXIST"></span> + </div> </div> - </div> - <!--------------------- RESOURCE TAGS --------------------> + <!--------------------- CATEGORIES --------------------> - <!--------------------- USER ID --------------------> - <div class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.contactId)}"> - <label class="i-sdc-form-label " data-ng-class="{'required':!component.isProduct()}" translate="GENERAL_LABEL_CONTACT_ID"></label> - <input class="i-sdc-form-input" type="text" data-ng-if="!component.isProduct()" - data-ng-model="component.contactId" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-required="!component.isProduct()" - name="contactId" - data-ng-pattern="validation.contactIdValidationPattern" - data-ng-model-options="{ debounce: 500 }" - data-tests-id="contactId" - maxlength="50" + <!--------------------- NAMING POLICY --------------------> + <div ng-if="component.isService()" class="i-sdc-form-item" data-ng-class="{'error': validateField(editForm.namingPolicy)}"> + <label class="i-sdc-form-label">Naming policy</label> + <input class="i-sdc-form-input" + name="fullName" + data-ng-class="{'view-mode': isViewMode() || !component.ecompGeneratedNaming}" + data-ng-maxlength="100" + maxlength="100" + data-ng-model="component.namingPolicy" + type="text" + data-ng-model-options="{ debounce: 500 }" + data-ng-pattern="validation.commentValidationPattern" + data-tests-id="namingPolicy" + autofocus + ng-readonly="isViewMode() || !component.ecompGeneratedNaming" /> - <input class="i-sdc-form-input" type="text" data-ng-if="component.isProduct()" - data-ng-model="component.contacts[0]" - data-ng-class="{'view-mode': isViewMode()}" - data-ng-required="!component.isProduct()" - name="contactId" - data-ng-pattern="validation.contactIdValidationPattern" - data-ng-model-options="{ debounce: 500 }" - data-tests-id="contactId" - maxlength="50" - /> - <div class="input-error" data-ng-show="validateField(editForm.contactId)"> - <span ng-show="editForm.contactId.$error.required" translate="NEW_SERVICE_RESOURCE_ERROR_CONTACT_REQUIRED"></span> - <span ng-show="editForm.contactId.$error.pattern" translate="NEW_SERVICE_RESOURCE_ERROR_CONTACT_NOT_VALID"></span> + <div class="input-error" data-ng-show="validateField(editForm.namingPolicy)"> + <span ng-show="editForm.namingPolicy.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '100' }"></span> + <span ng-show="editForm.namingPolicy.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + </div> </div> - </div> - <!--------------------- USER ID --------------------> - + <!--------------------- NAMING POLICY --------------------> + <!--------------------- Service Type --------------------> + <div ng-if="component.isService()" + class="i-sdc-form-item" + data-ng-class="{'error': validateField(editForm.serviceType)}"> + <label class="i-sdc-form-label" translate="GENERAL_TAB_LABEL_SERVICE_TYPE"></label> + <input class="i-sdc-form-input" type="text" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-model="component.serviceType" + data-ng-model-options="{ debounce: 500 }" + name="serviceType" + data-tests-id="serviceType" + data-ng-maxlength="25" + data-ng-pattern="validation.VendorReleaseValidationPattern" + maxlength="25" + /> + <div class="input-error" data-ng-show="validateField(editForm.serviceType)"> + <span ng-show="editForm.serviceType.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span> + <span ng-show="editForm.serviceType.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + </div> + </div> + <!--------------------- Service Type --------------------> + + <!--------------------- Service Role --------------------> + <div ng-if="component.isService()" + class="i-sdc-form-item" + data-ng-class="{'error': validateField(editForm.serviceRole)}"> + <label class="i-sdc-form-label" translate="GENERAL_TAB_LABEL_SERVICE_ROLE"></label> + <input class="i-sdc-form-input" type="text" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-model="component.serviceRole" + data-ng-model-options="{ debounce: 500 }" + name="serviceRole" + data-tests-id="serviceRole" + data-ng-maxlength="25" + data-ng-pattern="validation.VendorReleaseValidationPattern" + maxlength="25" + /> + <div class="input-error" data-ng-show="validateField(editForm.serviceRole)"> + <span ng-show="editForm.serviceRole.$error.maxlength" translate="VALIDATION_ERROR_MAX_LENGTH" translate-values="{'max': '25' }"></span> + <span ng-show="editForm.serviceRole.$error.pattern" translate="VALIDATION_ERROR_SPECIAL_CHARS_NOT_ALLOWED"></span> + </div> + </div> + <!--------------------- Service Role --------------------> + <div class="meta-data" data-ng-if="component.creationDate"> + <div> + <b>Created:</b> + </div> + <div class="meta-data-item-value">{{component.creationDate | date:'MM/dd/yyyy'}}, {{component.creatorFullName}}</div> + <div> + <b>Modifed:</b> + </div> + <div class="meta-data-item-value"> + {{component.lastUpdateDate | date:'MM/dd/yyyy'}} + </div> + <div> + <b>UUID:</b> + </div> + <div class="meta-data-item-value"> + {{component.uuid}} + </div> + <div> + <b>Invariant UUID:</b> + </div> + <div class="meta-data-item-value"> + {{component.invariantUUID}} + </div> + </div> </div><!-- Close w-sdc-form-column --> </div> </div><!-- Close w-sdc-form-section-container --> </form> - </div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/general/general.less b/catalog-ui/src/app/view-models/workspace/tabs/general/general.less index caa755cce3..9633ec5bb6 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/general/general.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/general/general.less @@ -1,8 +1,8 @@ .sdc-workspace-general-step { - + display: flex; .w-sdc-form { padding: 0; - + flex-grow: 10; .i-sdc-form-file-upload{ input[type="button"] { cursor: pointer; @@ -33,6 +33,14 @@ } } + .description{ + height: 300px; + } + + .i-sdc-form-item.description-field{ + margin-bottom: 0; + } + .w-sdc-form-section-container { text-align: center; } @@ -43,6 +51,7 @@ width: auto; padding: 10px; } + margin-bottom: 15px; } .i-sdc-form-label { @@ -63,6 +72,73 @@ } + .w-sdc-form-column { + position: relative; + } + + .meta-data{ + padding: 8px 0 2px 20px; + text-align: left; + background-color: @tlv_color_t; + position: absolute; + bottom: 0; + width: 100%; + .meta-data-item-value{ + padding-bottom: 6px; + } + } + + .upper-general-fields{ + display: flex; + } + + .selected-icon-container{ + flex-grow: 1; + display: flex; + align-items: center; + .selected-icon-inner-container{ + height: 64px; + width: 64px; + margin: 0 auto; + } + .update-component-icon{ + position: relative; + float: right; + cursor: pointer; + } + .selected-icon{ + position: relative; + top: -20px; + z-index: -1; + &.disable{ + position: inherit; + } + } + &.show-only-on-over{ + .update-component-icon{ + display: none; + } + .selected-icon{ + position: inherit; + } + &:hover{ + .update-component-icon{ + display: inline-block; + } + .selected-icon{ + position: relative; + } + } + } + } + + .name-and-category-fields{ + flex-grow: 5; + } + + + + } diff --git a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html b/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html deleted file mode 100644 index aac14e0e84..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons-view.html +++ /dev/null @@ -1,26 +0,0 @@ -<div class="workspace-icons"> - - <form novalidate class="w-sdc-form" name="iconForm"> - <label class="i-sdc-form-label icons-label required">Icons</label> - <div class="selected-icon-container" data-ng-class="{'view-mode': isViewMode()}"> - <div class="i-sdc-form-item-suggested-icon large selected-icon {{iconSprite}} {{component.icon}}" - data-ng-class="{ 'disable': isViewMode() }" - ng-model="component.icon" - tooltips tooltip-content='{{component.icon | translate}}' - > - </div> - </div> - <div data-ng-class="{'view-mode': isViewMode()}" class="icons-text">Select one of the icons below for the asset</div> - <div class="i-sdc-form-item suggested-icons-container" data-ng-class="{'view-mode no-pointer-events' : isViewMode()}"> - <div class ="suggested-icon-wrapper" ng-class="component.icon==='{{iconSrc}}' ? 'selected' : '' " data-ng-repeat="iconSrc in icons track by $index"> - <div class="i-sdc-form-item-suggested-icon large {{iconSprite}} {{iconSrc}}" data-ng-class="component.isAlreadyCertified() || isViewMode() ? 'disable':'hand'" - ng-model="component.icon" - data-tests-id="{{iconSrc}} iconBox" - data-ng-click="!component.isAlreadyCertified() && setComponentIcon(iconSrc)" - tooltips tooltip-content='{{iconSrc | translate}}' - > - </div> - </div> - </div> - </form> -</div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less b/catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less deleted file mode 100644 index 65f946f395..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/icons/icons.less +++ /dev/null @@ -1,65 +0,0 @@ -.workspace-icons { - - width: 89%; - display: inline-block; - text-align: center; - align-items: center; - - .w-sdc-form { - padding-top: 0px; - padding-bottom: 0px; - .selected-icon-container { - text-align: left; - border: 1px solid #cfcfcf; - clear: both; - margin-bottom: 30px; - padding: 2px 0px 5px 5px; - .selected-icon { - margin: 8px 5px 0px 6px; - } - } - - .suggested-icons-container { - text-align: left; - border: 1px solid #cfcfcf; - clear: both; - padding: 2px 0px 5px 5px; - height: 340px; - margin-bottom: 0px; - - .suggested-icon-wrapper { - margin: 8px 5px 0px 6px; - display: inline-block; - - &.selected { - border: 2px solid @main_color_a; - border-radius: 35px; - display: inline-block; - line-height: 0px; - padding: 3px; - } - - } - .suggested-icon { - // margin: 8px 5px 0px 6px; - display: inline-block; - &.disable{ - opacity: 0.4; - } - } - } - - .icons-label { - float: left; - } - - .icons-text { - text-align: left; - line-height: 32px; - padding-left: 10px; - width: 100%; - border: 1px solid #cfcfcf; - border-bottom: none; - } - } -} diff --git a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less index 3ba9cf47d5..5e69c44e9b 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/information-artifacts/information-artifacts.less @@ -12,7 +12,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; .item-opened{ word-wrap: break-word; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less b/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less index eff5c5395b..17c18e1741 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/inputs/inputs.less @@ -216,7 +216,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; width: 46%; min-width: 46%; display: inline-block; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts deleted file mode 100644 index c891875f52..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view-model.ts +++ /dev/null @@ -1,129 +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========================================================= - */ - -'use strict'; -import {ComponentFactory} from "app/utils"; -import {Product, IGroup, ISubCategory, IMainCategory} from "app/models"; -import {IWorkspaceViewModelScope} from "app/view-models/workspace/workspace-view-model"; -import {CacheService} from "app/services"; - -export interface IProductHierarchyScope extends IWorkspaceViewModelScope { - - categoriesOptions:Array<IMainCategory>; - product:Product; - isLoading:boolean; - showDropDown:boolean; - - onInputTextClicked():void; - onGroupSelected(category:IMainCategory, subcategory:ISubCategory, group:IGroup):void; - clickOutside():void; - deleteGroup(uniqueId:string):void; -} - -export class ProductHierarchyViewModel { - - static '$inject' = [ - '$scope', - 'Sdc.Services.CacheService', - 'ComponentFactory', - '$state' - ]; - - constructor(private $scope:IProductHierarchyScope, - private cacheService:CacheService, - private ComponentFactory:ComponentFactory, - private $state:ng.ui.IStateService) { - - - this.$scope.product = <Product>this.$scope.getComponent(); - this.$scope.setValidState(true); - this.initScope(); - this.$scope.updateSelectedMenuItem(); - } - - private initCategories = () => { - this.$scope.categoriesOptions = angular.copy(this.cacheService.get('productCategories')); - let selectedGroup:Array<IGroup> = []; - _.forEach(this.$scope.product.categories, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - selectedGroup = selectedGroup.concat(subcategory.groupings); - }); - }); - _.forEach(this.$scope.categoriesOptions, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - _.forEach(subcategory.groupings, (group:ISubCategory) => { - let componentGroup:IGroup = _.find(selectedGroup, (componentGroupObj) => { - return componentGroupObj.uniqueId == group.uniqueId; - }); - if (componentGroup) { - group.isDisabled = true; - } - }); - }); - }); - }; - - private setFormValidation = ():void => { - - this.$scope.setValidState(true); - - }; - - private initScope = ():void => { - this.$scope.isLoading = false; - this.$scope.showDropDown = false; - this.initCategories(); - this.setFormValidation(); - - this.$scope.onGroupSelected = (category:IMainCategory, subcategory:ISubCategory, group:IGroup):void => { - this.$scope.product.addGroup(category, subcategory, group); - this.$state.current.data.unsavedChanges = !this.$scope.isViewMode(); - group.isDisabled = true; - this.$scope.showDropDown = false; - this.setFormValidation(); - }; - - this.$scope.onInputTextClicked = ():void => {//just edit the component in place, no pop up nor server update ? - this.$scope.showDropDown = !this.$scope.showDropDown; - }; - - this.$scope.clickOutside = ():any => { - this.$scope.showDropDown = false; - }; - - this.$scope.deleteGroup = (uniqueId:string):void => { - //delete group from component - this.$scope.product.deleteGroup(uniqueId); - this.$state.current.data.unsavedChanges = !this.$scope.isViewMode(); - this.setFormValidation(); - //enabled group - _.forEach(this.$scope.categoriesOptions, (category:IMainCategory) => { - _.forEach(category.subcategories, (subcategory:ISubCategory) => { - let groupObj:IGroup = _.find(subcategory.groupings, (group) => { - return group.uniqueId === uniqueId; - }); - if (groupObj) { - groupObj.isDisabled = false; - } - }); - }); - } - }; -} diff --git a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html b/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html deleted file mode 100644 index 2335ad7c74..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy-view.html +++ /dev/null @@ -1,40 +0,0 @@ -<div class="workspace-hierarchy"> - <div class="dropdown-container" clicked-outside="{onClickedOutside: 'clickOutside()', clickedOutsideEnable: 'true'}" > - <input placeholder="Add Group" data-ng-click="onInputTextClicked()" class="dropdown-input-text" data-ng-model="search.filterTerms" data-ng-disabled="isViewMode()" data-ng-class="{'view-mode': isViewMode()}" data-ng-model-options="{debounce: 200}"/> - <div data-ng-class="{'show': showDropDown}" class="dropdown-content" > - <perfect-scrollbar scroll-y-margin-offset="0" include-padding="false" class="scrollbar-container"> - <div ng-repeat="category in categoriesOptions track by $index"> - <div ng-repeat="subcategory in category.subcategories track by $index"> - <div class="dropdown-option" ng-show="!category.filteredGroup || category.filteredGroup.length > 0"> - <div class="category-container"> - <div class="category">{{category.name}}</div> - <div class="subcategory">{{subcategory.name}}</div> - </div> - <div class="groupings-container"> - <div ng-init="group.filterTerms = group.name + ' ' + category.name + ' ' + subcategory.name" - ng-repeat="group in (category.filteredGroup = (subcategory.groupings | filter:search )) track by $index"> - <div class="group" data-ng-disabled="group.isDisabled" data-ng-class="{'disabled-group': group.isDisabled}" ng-click="onGroupSelected(category, subcategory, group)"> - <span >{{group.name}}</span> - </div> - </div> - </div> - </div> - </div> - </div> - </perfect-scrollbar> - </div> - </div> - <div class="hierarchy-groups-container no-border-top" data-ng-class="{'view-mode': isViewMode()}"> - <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container"> - <div ng-if="!product.categories.length || product.categories.length === 0" class="no-groups-text" translate="NEW_PRODUCT_NO_CATEGORIES_TO_DISPLAY"></div> - <div ng-repeat="category in product.categories track by $index"> - <div ng-repeat="subcategory in category.subcategories track by $index"> - <div class="group-tag" ng-repeat="group in subcategory.groupings track by $index" - data-ng-init="tooltip = '<b>' + category.name + '</b><br />' + subcategory.name"> - <sdc-tag sdc-disable="isViewMode()" data-on-delete="deleteGroup(uniqueId)" data-tag-data="{tag: group.name, tooltip: tooltip, id: group.uniqueId }"></sdc-tag> - </div> - </div> - </div> - </perfect-scrollbar> - </div> -</div> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less b/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less deleted file mode 100644 index c992558ed2..0000000000 --- a/catalog-ui/src/app/view-models/workspace/tabs/product-hierarchy/product-hierarchy.less +++ /dev/null @@ -1,130 +0,0 @@ -.workspace-hierarchy { - display: inline-block; - width: 93%; - - .scrollbar-container{ - max-height:400px; - .perfect-scrollbar; - } - - .dropdown-container { - position: relative; - display: inline-block; - width: 100%; - - &:after{ - top: 47%; - right: 1%; - border: solid transparent; - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - border-color: rgba(0, 0, 0, 0); - border-top-color: black; - border-width: 4px; - margin-left: -4px; - } - - .dropdown-input-text { - width: 100%; - padding: 4px 10px; - } - - .dropdown-content { - .perfect-scrollbar; - border: 1px solid #d8d8d8; - display: none; - position: absolute; - overflow: hidden; - width: 100%; - .bg_c; - max-height: 400px; - z-index: 999999; - - .dropdown-option { - border-bottom: 1px solid #d8d8d8; - display: inline-block; - width: 100%; - } - - .category-container{ - width: 250px; - float: left; - padding-left: 5px; - - .category { - .bold; - padding: 3px 3px 2px 3px; - &:after{ - .sprite; - .arrow-left; - content: ''; - margin-left: 5px; - transform: rotate(180deg); - } - } - .subcategory { - padding-left: 3px; - } - } - - .groupings-container{ - display: inline-block; - width: 424px; - border-left: 1px solid #d8d8d8; - min-height: 55px; - .group{ - padding: 3px 3px 3px 10px; - &:hover{ - .hand; - .bg_n; - } - &.disabled-group { - opacity: 0.5; - &:hover{ - cursor: auto; - .bg_c; - } - } - } - } - - .seperator { - height: 1px; - width: 100%; - .bg_j; - margin: 5px 0px; - } - } - .show { - display: block; - } - } - - .hierarchy-groups-container{ - .b_9; - width: 100%; - border: 1px solid #d8d8d8; - height: 425px; - padding: 15px; - text-align: center; - - .scrollbar-container { - z-index: 0; - } - - .no-group-text{ - text-align: center; - margin-top:25px; - a { - cursor: pointer; - } - } - .group-tag{ - display: inline-block; - float: left; - } - } -} diff --git a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less index 3e8d6c3fbd..48c462e143 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties.less @@ -76,7 +76,7 @@ } .table-container-flex { - margin-top: 27px; + margin-top: 0; .text{ overflow: hidden; diff --git a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less index 6dfec2980f..23be3c3548 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less +++ b/catalog-ui/src/app/view-models/workspace/tabs/tosca-artifacts/tosca-artifacts.less @@ -1,5 +1,5 @@ .workspace-tosca-artifact { - width: 93%; + width: 100%; display: inline-block; .w-sdc-classic-btn { float: right; @@ -18,8 +18,7 @@ .table-container-flex { - margin-top: 27px; - + margin-top: 0; .item-opened{ word-wrap: break-word; } diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts index 21bd199aac..ec8b04dbdb 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/workspace-view-model.ts @@ -77,7 +77,6 @@ export interface IWorkspaceViewModelScope extends ng.IScope { changeLifecycleState(state:string):void; enabledTabs():void isDesigner():boolean; - isProductManager():boolean; isViewMode():boolean; isEditMode():boolean; isCreateMode():boolean; @@ -91,6 +90,7 @@ export interface IWorkspaceViewModelScope extends ng.IScope { updateSelectedMenuItem():void; uploadFileChangedInGeneralTab():void; updateMenuComponentName(ComponentName:string):void; + getTabTitle():string; reload(component:Component):void; } @@ -149,9 +149,6 @@ export class WorkspaceViewModel { } else { if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT && this.$scope.component.lastUpdaterUserId === this.cacheService.get("user").userId) { - if (this.$scope.component.isProduct() && this.role == Role.PRODUCT_MANAGER) { - mode = WorkspaceMode.EDIT; - } if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role == Role.DESIGNER) { mode = WorkspaceMode.EDIT; } @@ -171,7 +168,7 @@ export class WorkspaceViewModel { }; private initLeftPalette = ():void => { - this.LeftPaletteLoaderService.loadLeftPanel(this.$scope.component.componentType); + this.LeftPaletteLoaderService.loadLeftPanel(this.$scope.component); }; private initScope = ():void => { @@ -192,7 +189,7 @@ export class WorkspaceViewModel { this.$scope.$state = this.$state; this.$scope.isLoading = false; this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1); - this.$scope.isDeployment = (this.$state.current.name.indexOf(States.WORKSPACE_DEPLOYMENT) > -1); + this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT; this.$scope.progressService = this.progressService; this.$scope.getComponent = ():Component => { @@ -269,7 +266,7 @@ export class WorkspaceViewModel { type: this.$scope.componentType.toLowerCase(), mode: WorkspaceMode.VIEW, components: this.$state.params['components'] - },{reload: true}); + }, {reload: true}); }; @@ -431,7 +428,7 @@ export class WorkspaceViewModel { switch (url) { case 'lifecycleState/CHECKOUT': // only checkOut get the full component from server - // this.$scope.component = component; + // this.$scope.component = component; // Work around to change the csar version if (this.cacheService.get(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) { (<Resource>this.$scope.component).csarVersion = this.cacheService.get(CHANGE_COMPONENT_CSAR_VERSION_FLAG); @@ -565,18 +562,13 @@ export class WorkspaceViewModel { return this.role == Role.DESIGNER; }; - this.$scope.isProductManager = ():boolean => { - return this.role == Role.PRODUCT_MANAGER; - }; - this.$scope.isDisableMode = ():boolean => { return this.$scope.mode === WorkspaceMode.VIEW && this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKIN; }; this.$scope.showFullIcons = ():boolean => { - //we show revert and save icons only in general\icon view - return this.$state.current.name === States.WORKSPACE_GENERAL || - this.$state.current.name === States.WORKSPACE_ICONS; + //we show revert and save icons only in general view + return this.$state.current.name === States.WORKSPACE_GENERAL; }; this.$scope.isCreateMode = ():boolean => { @@ -593,8 +585,7 @@ export class WorkspaceViewModel { }; this.$scope.showLifecycleIcon = ():boolean => { - return this.role == Role.DESIGNER || - this.role == Role.PRODUCT_MANAGER; + return this.role == Role.DESIGNER; }; this.$scope.getStatus = ():string => { @@ -612,13 +603,6 @@ export class WorkspaceViewModel { if (!this.$scope.component.isLatestVersion() && Role.OPS != this.role && Role.GOVERNOR != this.role) { result = false; } - if (this.role === Role.PRODUCT_MANAGER && !this.$scope.component.isProduct()) { - result = false; - } - if ((this.role === Role.DESIGNER || this.role === Role.TESTER) - && this.$scope.component.isProduct()) { - result = false; - } if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) { result = false; } @@ -639,10 +623,16 @@ export class WorkspaceViewModel { this.$scope.$watch('$state.current.name', (newVal:string):void => { if (newVal) { this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1); - this.$scope.isDeployment = (newVal.indexOf(States.WORKSPACE_DEPLOYMENT) > -1); + this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT; } }); + this.$scope.getTabTitle = ():string => { + return this.$scope.leftBarTabs.menuItems.find((menuItem:MenuItem)=>{ + return menuItem.state == this.$scope.$state.current.name; + }).text; + }; + this.$scope.reload = (component:Component):void => { this.$state.go(this.$state.current.name,{id:component.uniqueId},{reload:true}); }; @@ -658,7 +648,11 @@ export class WorkspaceViewModel { private initVersionObject = ():void => { this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse(); - this.$scope.changeVersion = {selectedVersion: _.find(this.$scope.versionsList, {versionId: this.$scope.component.uniqueId})}; + this.$scope.changeVersion = { + selectedVersion: _.find(this.$scope.versionsList, (versionObj)=> { + return versionObj.versionId === this.$scope.component.uniqueId; + }) + }; }; private getNewComponentBreadcrumbItem = ():MenuItem => { diff --git a/catalog-ui/src/app/view-models/workspace/workspace-view.html b/catalog-ui/src/app/view-models/workspace/workspace-view.html index dbb7fa6d63..19ebefe7a5 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view.html +++ b/catalog-ui/src/app/view-models/workspace/workspace-view.html @@ -3,8 +3,11 @@ <div class="w-sdc-main-container"> <div class="w-sdc-left-sidebar" data-ng-if="!isComposition"> - <div class="i-sdc-left-sidebar-item"> - <expand-collapse-menu-box menu-items-group="leftBarTabs" menu-title="{{menuComponentTitle}}" parent-scope="this"> </expand-collapse-menu-box> + <div class="menu-header" tooltips tooltip-content="{{menuComponentTitle}}"> + {{menuComponentTitle}} + </div> + <div class="i-sdc-designer-sidebar-section-content-item" ng-class="{'selected': menuItem.state == $state.current.name}" ng-repeat="menuItem in leftBarTabs.menuItems track by $index"> + <div class="expand-collapse-menu-box-item-text" ng-click="onMenuItemPressed(menuItem.state)" ng-class="{'disabled': menuItem.isDisabled }" data-tests-id="{{menuItem.text}}">{{menuItem.text}}</div> </div> </div> @@ -54,22 +57,22 @@ <button ng-if="!isViewMode() && isCreateMode()" data-ng-disabled="!isValidForm || isDisableMode() || isLoading" ng-click="save()" class="tlv-btn outline green" data-tests-id="create/save">Create</button> - <span data-ng-if="(isDesigner() || isProductManager()) && !isCreateMode() && component.lifecycleState === 'NOT_CERTIFIED_CHECKOUT'" sdc-smart-tooltip="" + <span data-ng-if="isDesigner() && !isCreateMode() && component.lifecycleState === 'NOT_CERTIFIED_CHECKOUT'" sdc-smart-tooltip="" data-ng-class="{'disabled' : !isValidForm || isDisableMode() || isViewMode()}" ng-click="changeLifecycleState('deleteVersion')" class="sprite-new delete-btn" data-tests-id="delete_version" sdc-smart-tooltip="">Delete</span> <span data-ng-if="isDesigner()" data-ng-class="{'disabled' :isDisableMode() || isViewMode()}" ng-click="revert()" class="sprite-new revert-btn" data-tests-id="revert" data-ng-show="showFullIcons()" sdc-smart-tooltip="">Revert</span> - <span data-ng-if="isComposition && !component.isProduct()" class="sprite-new print-screen-btn" entity="component" print-graph-screen data-tests-id="printScreen"></span> + <span data-ng-if="isComposition" class="sprite-new print-screen-btn" entity="component" print-graph-screen data-tests-id="printScreen"></span> <span class="delimiter"></span> <span class="sprite-new x-btn" data-ng-click="goToBreadcrumbHome()" sdc-smart-tooltip="">Close</span> </div> </div> - - <div data-ng-if="component.creationDate && (!isComposition && !isDeployment)" class="sdc-asset-creation-info"><b>Created:</b> {{component.creationDate | date:'MM/dd/yyyy'}}, {{component.creatorFullName}} | <b>Modifed:</b> {{component.lastUpdateDate | date:'MM/dd/yyyy'}} | <b>UUID:</b> {{component.uuid}}<b> Invariant UUID:</b> {{component.invariantUUID}}</div> - + <div class="tab-title" data-ng-if="!isComposition && !isDeployment"> + {{getTabTitle()}} + </div> <div class="w-sdc-main-container-body-content" data-ng-class="{'third-party':thirdParty}" data-ui-view></div> </div> </div> diff --git a/catalog-ui/src/app/view-models/workspace/workspace.less b/catalog-ui/src/app/view-models/workspace/workspace.less index 278708ca33..d0799f4bac 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace.less +++ b/catalog-ui/src/app/view-models/workspace/workspace.less @@ -27,10 +27,46 @@ } .w-sdc-left-sidebar { - padding: 3px 3px 0px 0px; - background-color: @main_color_p; - box-shadow: 7px -3px 6px -8px @main_color_n; + padding: 0px; + background-color: @tlv_color_t; + box-shadow: none; z-index: 2; + border-right: 1px solid @main_color_o; + .menu-header{ + border-bottom: 1px solid @main_color_o; + height: 53px; + .f-type._16_m; + font-weight: 700; + line-height: 53px; + padding-left: 40px; + padding-right: 10px; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + white-space: nowrap; + } + .i-sdc-designer-sidebar-section-content-item{ + .f-type._13_m; + color: @main_color_m; + margin-left: 20px; + padding-left: 20px; + margin-top: 20px; + height: 17px; + .hand; + &:hover{ + color: @func_color_s; + font-weight: 600; + } + &.selected{ + border-left: 4px solid @main_color_a; + color: @main_color_a; + margin-left: 18px; + padding-left: 18px; + font-weight: 600; + + } + } } .sdc-asset-creation-info { @@ -128,17 +164,24 @@ margin-top: 6px; } } + .tab-title{ + height: 110px; + padding-left: 100px; + line-height: 110px; + .f-type ._28; + } + &.composition .w-sdc-main-container-body-content { + height: calc(~'100% - @{action_nav_height}'); //composition is the only tab without a tab title. need to exclude from calculation. + } .w-sdc-main-container-body-content { - height:calc(~'100% - @{action_nav_height}'); - - text-align: center; + height:calc(~'100% - @{action_nav_height} - @{tab_title}'); align-items: center; - padding: 40px 14% 20px 14%; + padding: 0 100px 20px 100px; &.third-party { text-align: left; padding: 0; position: absolute; - top: @action_nav_height; + top: @action_nav_height + @tab_title; left: 0; right: 0; bottom: 0; @@ -147,7 +190,3 @@ } } - -.properties-assignment .sdc-workspace-container .w-sdc-main-right-container .w-sdc-main-container-body-content{ - padding: 80px 2% 40px 2%; -} |