diff options
author | Tal Gitelman <tg851x@intl.att.com> | 2017-12-10 18:55:03 +0200 |
---|---|---|
committer | Tal Gitelman <tg851x@intl.att.com> | 2017-12-10 19:33:38 +0200 |
commit | 51d50f0ef642e0f996a1c8b8d2ef4838bdfec892 (patch) | |
tree | 3ac236a864d74d19b0f5c9020891a7a7e5c31b44 /catalog-ui/src/app | |
parent | b5cc2e0695f195716d6ccdc65e73807a6632ec70 (diff) |
Final commit to master merge from
Change-Id: Ib464f9a8828437c86fe6def8af238aaf83473507
Issue-ID: SDC-714
Signed-off-by: Tal Gitelman <tg851x@intl.att.com>
Diffstat (limited to 'catalog-ui/src/app')
243 files changed, 4096 insertions, 1794 deletions
diff --git a/catalog-ui/src/app/app.ts b/catalog-ui/src/app/app.ts index 805e5f0b5d..609ed48f3e 100644 --- a/catalog-ui/src/app/app.ts +++ b/catalog-ui/src/app/app.ts @@ -31,18 +31,17 @@ import './modules/service-module'; import './modules/view-model-module.ts'; import { - IUserResourceClass, DataTypesService, LeftPaletteLoaderService, EcompHeaderService, CookieService, ConfigurationUiService, CacheService, - IUserResource, SdcVersionService, ICategoryResourceClass, EntityService } from "./services"; +import { UserService } from "./ng2/services/user.service"; import {forwardRef} from '@angular/core'; import {UpgradeAdapter} from '@angular/upgrade'; import {CHANGE_COMPONENT_CSAR_VERSION_FLAG, States} from "./utils"; @@ -53,11 +52,12 @@ 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"; import {Categories} from "./models/categories"; +import {IUserProperties} from "./models/user"; +import {SearchWithAutoCompleteComponent} from "./ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component"; let moduleName:string = 'sdcApp'; @@ -225,7 +225,13 @@ ng1appModule.config([ resolve: { injectComponent: ['$stateParams', 'ComponentFactory', 'ComponentServiceNg2', function ($stateParams, ComponentFactory:ComponentFactory, ComponentServiceNg2:ComponentServiceNg2) { if ($stateParams.id) { - return ComponentFactory.getComponentWithMetadataFromServer($stateParams.type.toUpperCase(), $stateParams.id); + return ComponentFactory.getComponentWithMetadataFromServer($stateParams.type.toUpperCase(), $stateParams.id).then( + (component:Component)=> { + if ($stateParams.componentCsar){ + component = ComponentFactory.updateComponentFromCsar($stateParams.componentCsar, <Resource>component); + } + return component; + }); } else if ($stateParams.componentCsar && $stateParams.componentCsar.csarUUID) { return $stateParams.componentCsar; } else { @@ -546,8 +552,8 @@ ng1appModule.config([ templateUrl: './view-models/catalog/catalog-view.html', controller: viewModelsModuleName + '.CatalogViewModel', resolve: { - auth: ["$q", "Sdc.Services.UserResourceService", ($q:any, userResourceService:IUserResourceClass) => { - let userInfo:IUserResource = userResourceService.getLoggedinUser(); + auth: ["$q", "UserServiceNg2", ($q:any, userService:UserService) => { + let userInfo:IUserProperties = userService.getLoggedinUser(); if (userInfo) { return $q.when(userInfo); } else { @@ -592,6 +598,7 @@ ng1appModule.value('TagValidationPattern', /^[\s\w_.-]{1,50}$/); 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('ServiceTypeAndRoleValidationPattern', /^[\x20-\x21\x23-\x29\x2B-\x2E\x30-\x39\x3B\x3D\x40-\x5B\x5D-\x7B\x7D-\xFF]{1,256}$/); ng1appModule.value('ContactIdValidationPattern', /^[\s\w-]{1,50}$/); ng1appModule.value('UserIdValidationPattern', /^[\s\w-]{1,50}$/); ng1appModule.value('ProjectCodeValidationPattern', /^[\s\w-]{5,50}$/); @@ -614,7 +621,7 @@ ng1appModule.run([ 'Sdc.Services.CacheService', 'Sdc.Services.CookieService', 'Sdc.Services.ConfigurationUiService', - 'Sdc.Services.UserResourceService', + 'UserServiceNg2', 'Sdc.Services.CategoryResourceService', 'Sdc.Services.SdcVersionService', '$state', @@ -631,7 +638,7 @@ ng1appModule.run([ cacheService:CacheService, cookieService:CookieService, ConfigurationUi:ConfigurationUiService, - UserResourceClass:IUserResourceClass, + userService:UserService, categoryResourceService:ICategoryResourceClass, sdcVersionService:SdcVersionService, $state:ng.ui.IStateService, @@ -645,6 +652,7 @@ ng1appModule.run([ AngularJSBridge, $templateCache:ng.ITemplateCacheService):void => { $templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html')); + $templateCache.put('notification-custom-template.html', require('./view-models/shared/notification-custom-template.html')); //handle cache data - version let initAsdcVersion:Function = ():void => { @@ -756,27 +764,27 @@ ng1appModule.run([ toParams.previousState = fromParams.previousState; } - if (toState.name !== 'error-403' && !UserResourceClass.getLoggedinUser()) { + if (toState.name !== 'error-403' && !userService.getLoggedinUser()) { internalDeregisterStateChangeStartWatcher(); event.preventDefault(); - UserResourceClass.authorize().$promise.then((user:IUserResource) => { - if (!doesUserHasAccess(toState, user)) { + userService.authorize().subscribe((userInfo:IUserProperties) => { + if (!doesUserHasAccess(toState, userInfo)) { $state.go('error-403'); console.info('User has no permissions'); registerStateChangeStartWatcher(); return; } - UserResourceClass.setLoggedinUser(user); - cacheService.set('user', user); + userService.setLoggedinUser(userInfo); + cacheService.set('user', userInfo); initCategories(); - // initEcompMenu(user); + // initEcompMenu(userInfo); setTimeout(function () { removeLoader(); // initCategories(); - if (UserResourceClass.getLoggedinUser().role === 'ADMIN') { + if (userService.getLoggedinUser().role === 'ADMIN') { // toState.name = "adminDashboard"; $state.go("adminDashboard", toParams); registerStateChangeStartWatcher(); @@ -804,9 +812,9 @@ ng1appModule.run([ registerStateChangeStartWatcher(); }); } - else if (UserResourceClass.getLoggedinUser()) { + else if (userService.getLoggedinUser()) { internalDeregisterStateChangeStartWatcher(); - if (!doesUserHasAccess(toState, UserResourceClass.getLoggedinUser())) { + if (!doesUserHasAccess(toState, userService.getLoggedinUser())) { event.preventDefault(); $state.go('error-403'); console.info('User has no permissions'); diff --git a/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts b/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts index 1c5c333d27..14cafa98c4 100644 --- a/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts +++ b/catalog-ui/src/app/directives/capabilities-and-requirements/requirement/requirements-list-directive.ts @@ -28,7 +28,7 @@ * Created by obarda on 1/8/2017. */ 'use strict'; -import {RequirementsGroup, Component} from "app/models"; +import {RequirementsGroup, Component, Relationship, RelationshipModel} from "app/models"; export interface IRequirementsListScope extends ng.IScope { @@ -62,12 +62,11 @@ export class RequirementsListDirective implements ng.IDirective { scope.getRelation = (requirement:any):any => { if (scope.isInstanceSelected() && scope.component.componentInstancesRelations) { - let relationItem = _.filter(scope.component.componentInstancesRelations, (relation:any) => { + let relationItem:Array<RelationshipModel> = _.filter((<Component>scope.component).componentInstancesRelations, (relation:RelationshipModel) => { return relation.fromNode === scope.component.selectedInstance.uniqueId && - _.some(relation.relationships, { - 'requirement': requirement.name, - 'requirementOwnerId': requirement.ownerId - }); + _.filter(relation.relationships, (relationship:Relationship) => { + return relationship.relation.requirement == requirement.name && relationship.relation.requirementOwnerId == requirement.ownerId; + }).length; }); if (relationItem && relationItem.length) { diff --git a/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.html b/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.html deleted file mode 100644 index a50731443d..0000000000 --- a/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.html +++ /dev/null @@ -1,8 +0,0 @@ -<div class="footer-wrapper"> - <div class="divider-footer-bottom"> - <div class="footer-copyright-text"> - <p> - </p> - </div> - </div> -</div> diff --git a/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.less b/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.less deleted file mode 100644 index 4c54a11fec..0000000000 --- a/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.less +++ /dev/null @@ -1,47 +0,0 @@ - -.footer-wrapper { - position: fixed; - bottom: 0px; - left: 0px; - width: 100%; - background-color: #222222; - color: #ffffff; - font-family: "Arial"; - font-size: 11px; - height: @footer_height; -} - -.footer-wrapper a { - color: #ffffff; - margin: 0; - padding: 0; - text-decoration: underline; -} - -.divider-footer-bottom { - margin: 0 auto; - width: 1020px; -} - -.footer-copyright-text { - display: inline-block; - width:612px; - margin-top: 18px; - margin-left: 50px; - text-align: left; - vertical-align: top; -} - -.footer-logo1 { - display: inline-block; - margin-top: 20px; - margin-left: 124px; -} - -.footer-logo2 { - margin-top: 22px; - margin-left: 9px; - display: inline-block; - font-size: 24px; - vertical-align: top; -} diff --git a/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts b/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts index 7d616afba6..f73c82a190 100644 --- a/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts +++ b/catalog-ui/src/app/directives/ecomp-header/ecomp-header.ts @@ -20,7 +20,8 @@ 'use strict'; import {IAppConfigurtaion, User, IUser} from "app/models"; -import {IUserResourceClass, IUserResource} from "app/services"; +import {IUserProperties} from "../../models/user"; +import {UserService} from "../../ng2/services/user.service"; export class MenuItem { menuId:number; @@ -55,7 +56,7 @@ export class EcompHeaderDirective implements ng.IDirective { constructor(private $http:ng.IHttpService, private sdcConfig:IAppConfigurtaion, - private UserResourceClass:IUserResourceClass) { + private userService:UserService) { } @@ -90,14 +91,14 @@ export class EcompHeaderDirective implements ng.IDirective { let initUser = ():void => { let defaultUserId:string; - let user:IUserResource = this.UserResourceClass.getLoggedinUser(); - if (!user) { + let userInfo:IUserProperties = this.userService.getLoggedinUser(); + if (!userInfo) { defaultUserId = this.$http.defaults.headers.common[this.sdcConfig.cookie.userIdSuffix]; - user = this.UserResourceClass.get({id: defaultUserId}, ():void => { - $scope.user = new User(user); + this.userService.getUser(defaultUserId).subscribe((defaultUserInfo):void => { + $scope.user = new User(defaultUserInfo); }); } else { - $scope.user = new User(user); + $scope.user = new User(userInfo); } }; @@ -135,8 +136,8 @@ export class EcompHeaderDirective implements ng.IDirective { public static factory = ($http:ng.IHttpService, sdcConfig:IAppConfigurtaion, - UserResourceClass:IUserResourceClass)=> { - return new EcompHeaderDirective($http, sdcConfig, UserResourceClass); + userService:UserService)=> { + return new EcompHeaderDirective($http, sdcConfig, userService); }; } @@ -229,7 +230,7 @@ export class EcompHeaderController { }; } -EcompHeaderDirective.factory.$inject = ['$http', 'sdcConfig', 'Sdc.Services.UserResourceService']; +EcompHeaderDirective.factory.$inject = ['$http', 'sdcConfig', 'UserServiceNg2']; diff --git a/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts b/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts index f88db47524..2a7fd74e53 100644 --- a/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts +++ b/catalog-ui/src/app/directives/graphs-v2/common/common-graph-utils.ts @@ -164,12 +164,54 @@ export class CommonGraphUtils { if (!this.isRelationCertified(cy.nodes(), link.source, link.target)) { link.classes = 'not-certified-link'; } - cy.add({ + let linkElement = cy.add({ group: 'edges', data: link, classes: link.classes }); + this.initLinkTooltip(linkElement, link); + }; + + /** + * This function will init qtip tooltip on the link + * @params linkElement - the link we want the tooltip to apply on, + * link - the link obj + */ + public initLinkTooltip(linkElement:Cy.CollectionElements, link:CompositionCiLinkBase) { + + let opts = { + content: function () { + return '<div class="line">' + + '<span class="req-cap-label">R: </span>' + + '<span>'+ link.relation.relationships[0].relation.requirement + '</span>' + + '</div>' + + '<div class="line">' + + '<div class="sprite-new link-tooltip-arrow"></div>' + + '<span class="req-cap-label">C: </span>' + + '<span>' + link.relation.relationships[0].relation.capability + '</span>' + + '</div>'; + }, + position: { + my: 'top center', + at: 'bottom center', + adjust: {x:0, y:0} + }, + style: { + classes: 'qtip-dark qtip-rounded qtip-custom link-qtip', + tip: { + width: 16, + height: 8 + } + }, + show: { + event: 'mouseover', + delay: 1000 + }, + hide: {event: 'mouseout mousedown'}, + includeLabels: true + }; + linkElement.qtip(opts); }; /** 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 7e21f8293b..36c75c55fc 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 @@ -225,6 +225,23 @@ export class ComponentInstanceNodesStyle { css: { 'overlay-opacity': 0 } + }, { + selector: '.configuration-node', + css: { + 'background-color': 'rgb(255,255,255)', + 'shape': 'rectangle', + 'label': 'data(displayName)', + 'background-image': 'data(img)', + 'background-width': GraphUIObjects.SMALL_RESOURCE_WIDTH, + 'background-height': GraphUIObjects.SMALL_RESOURCE_WIDTH, + 'width': GraphUIObjects.SMALL_RESOURCE_WIDTH, + 'height': GraphUIObjects.SMALL_RESOURCE_WIDTH, + 'text-valign': 'bottom', + 'text-halign': 'center', + 'background-opacity': 0, + 'overlay-color': GraphColors.NODE_BACKGROUND_COLOR, + 'overlay-opacity': 0 + } } ] } 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 8b3a59ec1f..cdb163bda1 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 @@ -19,14 +19,20 @@ */ import { - MatchBase, + Match, LinkMenu, ComponentInstance, LeftPaletteComponent, + Capability, + Requirement, + Relationship, + PropertyModel, Component, - RelationMenuDirectiveObj, + ConnectRelationModel, CompositionCiNodeBase, CompositionCiNodeVl, + ModalModel, + ButtonModel, NodesFactory/*, AssetPopoverObj*/ } from "app/models"; @@ -42,6 +48,18 @@ import {ComponentInstanceNodesStyle} from "../common/style/component-instances-n import {CytoscapeEdgeEditation} from 'third-party/cytoscape.js-edge-editation/CytoscapeEdgeEditation.js'; import {ComponentServiceNg2} from "../../../ng2/services/component-services/component.service"; import {ComponentGenericResponse} from "../../../ng2/services/responses/component-generic-response"; +import {ModalService} from "../../../ng2/services/modal.service"; + +import {ConnectionWizardService} from "../../../ng2/pages/connection-wizard/connection-wizard.service"; +import {StepModel} from "../../../models/wizard-step"; +import {FromNodeStepComponent} from "app/ng2/pages/connection-wizard/from-node-step/from-node-step.component"; +import {PropertiesStepComponent} from "app/ng2/pages/connection-wizard/properties-step/properties-step.component"; +import {ToNodeStepComponent} from "app/ng2/pages/connection-wizard/to-node-step/to-node-step.component"; +import {ConnectionWizardHeaderComponent} from "app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component"; +import {ConnectionPropertiesViewComponent} from "../../../ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component"; +import {ComponentInstanceServiceNg2} from "../../../ng2/services/component-instance-services/component-instance.service"; +import {EVENTS} from "../../../utils/constants"; +import {PropertyBEModel} from "../../../models/properties-inputs/property-be-model"; interface ICompositionGraphScope extends ng.IScope { @@ -50,9 +68,10 @@ interface ICompositionGraphScope extends ng.IScope { isViewOnly: boolean; withSidebar: boolean; // Link menu - create link menu - relationMenuDirectiveObj:RelationMenuDirectiveObj; + relationMenuDirectiveObj:ConnectRelationModel; isLinkMenuOpen:boolean; - createLinkFromMenu:(chosenMatch:MatchBase, vl:Component)=>void; + createLinkFromMenu:(chosenMatch:Match, vl:Component)=>void; + saveChangedCapabilityProperties:()=>Promise<PropertyBEModel[]>; //modify link menu - for now only delete menu relationMenuTimeout:ng.IPromise<any>; @@ -64,6 +83,7 @@ interface ICompositionGraphScope extends ng.IScope { verifyDrop(event:JQueryEventObject, ui:any):void; //Links menus + viewRelation(link:Cy.CollectionEdges):void; deleteRelation(link:Cy.CollectionEdges):void; hideRelationMenu(); @@ -73,6 +93,8 @@ interface ICompositionGraphScope extends ng.IScope { zoomAll(nodes?:Cy.CollectionNodes): void; getAutoCompleteValues(searchTerm: string):void; highlightSearchMatches(searchTerm: string): void; + + canvasMenuProps:any; /*//asset popover menu assetPopoverObj:AssetPopoverObj; @@ -102,7 +124,10 @@ export class CompositionGraph implements ng.IDirective { private commonGraphUtils:CommonGraphUtils, private matchCapabilitiesRequirementsUtils:MatchCapabilitiesRequirementsUtils, private CompositionGraphPaletteUtils:CompositionGraphPaletteUtils, - private ComponentServiceNg2: ComponentServiceNg2) { + private ComponentServiceNg2: ComponentServiceNg2, + private ModalServiceNg2: ModalService, + private ConnectionWizardServiceNg2: ConnectionWizardService, + private ComponentInstanceServiceNg2: ComponentInstanceServiceNg2) { } @@ -131,6 +156,8 @@ export class CompositionGraph implements ng.IDirective { _.forEach(GRAPH_EVENTS, (event) => { this.eventListenerService.unRegisterObserver(event); }); + this.eventListenerService.unRegisterObserver(EVENTS.SHOW_LOADER_EVENT + 'composition-graph'); + this.eventListenerService.unRegisterObserver(EVENTS.HIDE_LOADER_EVENT + 'composition-graph'); }); }; @@ -190,7 +217,7 @@ export class CompositionGraph implements ng.IDirective { if (this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.containsKey(leftPaletteComponent.uniqueId)) { let cacheComponent = this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.getValue(leftPaletteComponent.uniqueId); - let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findByMatchingCapabilitiesToRequirements(cacheComponent, nodesData, nodesLinks); + let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(cacheComponent, nodesData, nodesLinks); this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy); this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy); @@ -207,7 +234,7 @@ export class CompositionGraph implements ng.IDirective { component.capabilities = response.capabilities; component.requirements = response.requirements; this.GeneralGraphUtils.componentRequirementsAndCapabilitiesCaching.setValue(leftPaletteComponent.uniqueId, component); - let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findByMatchingCapabilitiesToRequirements(component, nodesData, nodesLinks); + let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(component, nodesData, nodesLinks); this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy); this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy) }); @@ -321,18 +348,124 @@ export class CompositionGraph implements ng.IDirective { scope.zoomAll(matchingNodes); }; - scope.createLinkFromMenu = (chosenMatch:MatchBase):void => { + scope.saveChangedCapabilityProperties = ():Promise<PropertyBEModel[]> => { + return new Promise<PropertyBEModel[]>((resolve) => { + const capabilityPropertiesBE: PropertyBEModel[] = this.ConnectionWizardServiceNg2.changedCapabilityProperties.map((prop) => { + prop.value = prop.getJSONValue(); + const propBE = new PropertyBEModel(prop); + propBE.parentUniqueId = this.ConnectionWizardServiceNg2.selectedMatch.relationship.relation.capabilityOwnerId; + return propBE; + }); + if (capabilityPropertiesBE.length > 0) { + // if there are capability properties to update, then first update capability properties and then resolve promise + this.ComponentInstanceServiceNg2 + .updateInstanceCapabilityProperties( + scope.component, + this.ConnectionWizardServiceNg2.selectedMatch.toNode, + this.ConnectionWizardServiceNg2.selectedMatch.capability.type, + this.ConnectionWizardServiceNg2.selectedMatch.capability.name, + capabilityPropertiesBE + ) + .subscribe((response) => { + console.log("Update resource instance capability properties response: ", response); + response.forEach((resProperty) => { + this.ConnectionWizardServiceNg2.selectedMatch.capabilityProperties.find((property) => { + return property.uniqueId == resProperty.uniqueId; + }).value = resProperty.value; + }); + this.ConnectionWizardServiceNg2.changedCapabilityProperties = []; + resolve(capabilityPropertiesBE); + }); + } else { + // no capability properties to update, immediately resolve promise + resolve(capabilityPropertiesBE); + } + }); + }; + + scope.createLinkFromMenu = ():void => { scope.isLinkMenuOpen = false; - this.CompositionGraphLinkUtils.createLinkFromMenu(this._cy, chosenMatch, scope.component); + + scope.saveChangedCapabilityProperties().then(() => { + //create link: + this.CompositionGraphLinkUtils + .createLinkFromMenu(this._cy, this.ConnectionWizardServiceNg2.selectedMatch, scope.component); + }); }; scope.hideRelationMenu = () => { this.commonGraphUtils.safeApply(scope, () => { - scope.linkMenuObject = null; + delete scope.canvasMenuProps; this.$timeout.cancel(scope.relationMenuTimeout); }); }; + scope.viewRelation = (link:Cy.CollectionEdges) => { + scope.hideRelationMenu(); + + const linkData = link.data(); + const sourceNode:CompositionCiNodeBase = link.source().data(); + const targetNode:CompositionCiNodeBase = link.target().data(); + const relationship:Relationship = linkData.relation.relationships[0]; + + let capability:Capability; + _.some(_.values(targetNode.componentInstance.capabilities), (capGroup) => { + //item.uniqueId + item.ownerId + item.name === (selectedReqOrCapModel.uniqueId + selectedReqOrCapModel.ownerId + selectedReqOrCapModel.name) + capability = _.find<Capability>(_.values<Capability>(capGroup), (cap:Capability) => ( + cap.uniqueId === relationship.relation.capabilityUid && + cap.ownerId === relationship.relation.capabilityOwnerId && + cap.name === relationship.relation.capability + )); + return capability; + }); + let requirement:Requirement; + _.some(_.values(sourceNode.componentInstance.requirements), (reqGroup) => { + requirement = _.find<Requirement>(_.values<Requirement>(reqGroup), (req:Requirement) => ( + req.uniqueId === relationship.relation.requirementUid && + req.ownerId === relationship.relation.requirementOwnerId && + req.name === relationship.relation.requirement + )); + return requirement; + }); + + new Promise<{capability:Capability, requirement:Requirement}>((resolve, reject) => { + if (capability && requirement) { + resolve({capability, requirement}); + } + else { + scope.component.fetchRelation(relationship.relation.id).then((fetchedRelation) => { + resolve({ + capability: fetchedRelation.relationships[0].capability, + requirement: fetchedRelation.relationships[0].requirement + }); + }, reject); + } + }).then((objReqCap) => { + capability = objReqCap.capability; + requirement = objReqCap.requirement; + + this.ConnectionWizardServiceNg2.currentComponent = scope.component; + this.ConnectionWizardServiceNg2.connectRelationModel = new ConnectRelationModel(sourceNode, targetNode, []); + this.ConnectionWizardServiceNg2.selectedMatch = new Match(requirement, capability, true, linkData.source, linkData.target); + this.ConnectionWizardServiceNg2.selectedMatch.relationship = relationship; + + const title = `Connection Properties`; + const saveButton: ButtonModel = new ButtonModel('Save', 'blue', () => { + scope.saveChangedCapabilityProperties().then(() => { this.ModalServiceNg2.closeCurrentModal(); }) + }); + const cancelButton: ButtonModel = new ButtonModel('Cancel', 'white', () => { this.ModalServiceNg2.closeCurrentModal(); }); + const modal = new ModalModel('xl', title, '', [saveButton, cancelButton]); + const modalInstance = this.ModalServiceNg2.createCustomModal(modal); + this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent); + modalInstance.instance.open(); + + this.ComponentInstanceServiceNg2.getInstanceCapabilityProperties(scope.component, linkData.target, capability.type, capability.name) + .subscribe((response: Array<PropertyModel>) => { + this.ConnectionWizardServiceNg2.selectedMatch.capabilityProperties = response; + this.ModalServiceNg2.addDynamicContentToModal(modalInstance, ConnectionPropertiesViewComponent); + }, (error) => {}); + }, (error) => {}); + }; scope.deleteRelation = (link:Cy.CollectionEdges) => { scope.hideRelationMenu(); @@ -367,9 +500,26 @@ export class CompositionGraph implements ng.IDirective { this._cy.on('addedgemouseup', (event, data) => { scope.relationMenuDirectiveObj = this.CompositionGraphLinkUtils.onLinkDrawn(this._cy, data.source, data.target); if (scope.relationMenuDirectiveObj != null) { - scope.$apply(() => { - scope.isLinkMenuOpen = true; - }); + this.ConnectionWizardServiceNg2.setRelationMenuDirectiveObj(scope.relationMenuDirectiveObj); + this.ConnectionWizardServiceNg2.currentComponent = scope.component; + //TODO: init with the selected values + this.ConnectionWizardServiceNg2.selectedMatch = null; + + let steps:Array<StepModel> = []; + let fromNodeName:string = scope.relationMenuDirectiveObj.fromNode.componentInstance.name; + let toNodeName:string = scope.relationMenuDirectiveObj.toNode.componentInstance.name; + steps.push(new StepModel(fromNodeName, FromNodeStepComponent)); + steps.push(new StepModel(toNodeName, ToNodeStepComponent)); + steps.push(new StepModel('Properties', PropertiesStepComponent)); + let wizardTitle = 'Connect: ' + fromNodeName + ' to ' + toNodeName; + let modalInstance = this.ModalServiceNg2.createMultiStepsWizard(wizardTitle, steps, scope.createLinkFromMenu, ConnectionWizardHeaderComponent); + modalInstance.instance.open(); + + // + // this.ModalServiceNg2.createMultiStepsWizard('Connect', )Connect + // scope.$apply(() => { + // scope.isLinkMenuOpen = true; + // }); } }); this._cy.on('tapstart', 'node', (event:Cy.EventObject) => { @@ -424,7 +574,7 @@ export class CompositionGraph implements ng.IDirective { let nodesLinks = this.GeneralGraphUtils.getAllCompositionCiLinks(this._cy); let linkableNodes = this.commonGraphUtils.getLinkableNodes(this._cy, payload.node); - let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findByMatchingCapabilitiesToRequirements(payload.node.data().componentInstance, linkableNodes, nodesLinks); + let filteredNodesData = this.matchCapabilitiesRequirementsUtils.findMatchingNodes(payload.node.data().componentInstance, linkableNodes, nodesLinks); this.matchCapabilitiesRequirementsUtils.highlightMatchingComponents(filteredNodesData, this._cy); this.matchCapabilitiesRequirementsUtils.fadeNonMachingComponents(filteredNodesData, nodesData, this._cy, payload.node.data()); @@ -498,14 +648,39 @@ export class CompositionGraph implements ng.IDirective { };*/ private openModifyLinkMenu = (scope:ICompositionGraphScope, linkMenuObject:LinkMenu, timeOutInMilliseconds?:number) => { + scope.hideRelationMenu(); + this.$timeout(() => { + scope.canvasMenuProps = { + open: true, + styleClass: 'w-sdc-canvas-menu-list', + items: [], + position: { + x: `${linkMenuObject.position.x}px`, + y: `${linkMenuObject.position.y}px` + } + }; + + if (this._cy.$('edge:selected').length === 1) { + scope.canvasMenuProps.items.push({ + contents: 'View', + styleClass: 'w-sdc-canvas-menu-item-view', + action: () => { + scope.viewRelation(<Cy.CollectionEdges>linkMenuObject.link); + } + }); + } + scope.canvasMenuProps.items.push({ + contents: 'Delete', + styleClass: 'w-sdc-canvas-menu-item-delete', + action: () => { + scope.deleteRelation(<Cy.CollectionEdges>linkMenuObject.link); + } + }); - this.commonGraphUtils.safeApply(scope, () => { - scope.linkMenuObject = linkMenuObject; + scope.relationMenuTimeout = this.$timeout(() => { + scope.hideRelationMenu(); + }, timeOutInMilliseconds ? timeOutInMilliseconds : 6000); }); - - scope.relationMenuTimeout = this.$timeout(() => { - scope.hideRelationMenu(); - }, timeOutInMilliseconds ? timeOutInMilliseconds : 6000); }; private initGraphNodes(componentInstances:ComponentInstance[], isViewOnly:boolean) { @@ -571,7 +746,10 @@ export class CompositionGraph implements ng.IDirective { CommonGraphUtils, MatchCapabilitiesRequirementsUtils, CompositionGraphPaletteUtils, - ComponentServiceNg2) => { + ComponentServiceNg2, + ModalService, + ConnectionWizardService, + ComponentInstanceServiceNg2) => { return new CompositionGraph( $q, $log, @@ -587,7 +765,10 @@ export class CompositionGraph implements ng.IDirective { CommonGraphUtils, MatchCapabilitiesRequirementsUtils, CompositionGraphPaletteUtils, - ComponentServiceNg2); + ComponentServiceNg2, + ModalService, + ConnectionWizardService, + ComponentInstanceServiceNg2); } } @@ -606,5 +787,8 @@ CompositionGraph.factory.$inject = [ 'CommonGraphUtils', 'MatchCapabilitiesRequirementsUtils', 'CompositionGraphPaletteUtils', - 'ComponentServiceNg2' + 'ComponentServiceNg2', + 'ModalServiceNg2', + 'ConnectionWizardServiceNg2', + 'ComponentInstanceServiceNg2' ]; 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 248f19fb70..bbf2d6bbb2 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 @@ -8,17 +8,7 @@ <relation-menu relation-menu-directive-obj="relationMenuDirectiveObj" is-link-menu-open="isLinkMenuOpen" create-relation="createLinkFromMenu" cancel="cancelRelationMenu()"></relation-menu> - -<div class="w-sdc-canvas-menu" - data-ng-show="linkMenuObject" ng-style="{left: linkMenuObject.position.x, top: linkMenuObject.position.y}" - id="relationMenu"> - - <div class="w-sdc-canvas-menu-content hand" data-ng-click="deleteRelation(linkMenuObject.link)"> - <div class="w-sdc-canvas-menu-content-delete-button"></div> - Delete - </div> - -</div> +<menu-list-ng2 [props]="canvasMenuProps"></menu-list-ng2> <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)" 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 0ea38af825..da7d48e6ae 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 @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import {ComponentInstance, Component, MatchReqToCapability, MatchBase, CompositionCiLinkBase, CompositionCiNodeUcpeCp} from "app/models"; +import {ComponentInstance, Component, Match, CompositionCiLinkBase, CompositionCiNodeUcpeCp} from "app/models"; import {QueueUtils, Dictionary, GraphUIObjects} from "app/utils"; import {LoaderService} from "app/services"; import {MatchCapabilitiesRequirementsUtils} from "./match-capability-requierment-utils"; @@ -106,16 +106,16 @@ export class CompositionGraphGeneralUtils { * @param cy - Cytoscape instance * @param fromUcpeInstance * @param toComponentInstance - * @returns {MatchReqToCapability} + * @returns {Match} */ - public canBeHostedOn(cy:Cy.Instance, fromUcpeInstance:ComponentInstance, toComponentInstance:ComponentInstance):MatchReqToCapability { + public canBeHostedOn(cy:Cy.Instance, fromUcpeInstance:ComponentInstance, toComponentInstance:ComponentInstance):Match { - let matches:Array<MatchBase> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromUcpeInstance, toComponentInstance, this.getAllCompositionCiLinks(cy)); - let hostedOnMatch:MatchBase = _.find(matches, (match:MatchReqToCapability) => { + let matches:Array<Match> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromUcpeInstance, toComponentInstance, this.getAllCompositionCiLinks(cy)); + let hostedOnMatch:Match = _.find(matches, (match:Match) => { return match.requirement.capability.toLowerCase() === 'tosca.capabilities.container'; }); - return <MatchReqToCapability>hostedOnMatch; + return hostedOnMatch; }; @@ -128,7 +128,7 @@ export class CompositionGraphGeneralUtils { */ private isValidDropInsideUCPE(cy:Cy.Instance, nodeToInsert:ComponentInstance, ucpeNode:ComponentInstance):boolean { - let hostedOnMatch:MatchReqToCapability = this.canBeHostedOn(cy, ucpeNode, nodeToInsert); + let hostedOnMatch:Match = this.canBeHostedOn(cy, ucpeNode, nodeToInsert); let result:boolean = !angular.isUndefined(hostedOnMatch) || nodeToInsert.isVl(); //group validation return result; diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts index 05f99ae9ea..89c5e14602 100644 --- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/composition-graph-links-utils.ts @@ -21,25 +21,17 @@ /** * Created by obarda on 6/28/2016. */ -import {GraphUIObjects, ComponentInstanceFactory, ResourceType} from "app/utils"; -import {LeftPaletteLoaderService, LoaderService} from "app/services"; +import {GraphUIObjects} from "app/utils"; +import {LoaderService} from "app/services"; import { NodeUcpe, CompositionCiNodeVf, - MatchReqToCapability, - MatchBase, - MatchReqToReq, - ComponentInstance, + Match, CompositionCiNodeBase, RelationshipModel, - RelationMenuDirectiveObj, - CapabilitiesGroup, + ConnectRelationModel, LinksFactory, - NodesFactory, - RequirementsGroup, Component, - Relationship, - Capability, LinkMenu, Point, CompositionCiLinkBase @@ -105,16 +97,16 @@ export class CompositionGraphLinkUtils { ); }; - private createSimpleLink = (match:MatchReqToCapability, cy:Cy.Instance, component:Component):void => { + private createSimpleLink = (match:Match, cy:Cy.Instance, component:Component):void => { let newRelation:RelationshipModel = match.matchToRelationModel(); let linkObg:CompositionCiLinkBase = this.linksFactory.createGraphLink(cy, newRelation, newRelation.relationships[0]); this.createLink(linkObg, cy, component); }; - public createLinkFromMenu = (cy:Cy.Instance, chosenMatch:MatchBase, component:Component):void => { + public createLinkFromMenu = (cy:Cy.Instance, chosenMatch:Match, component:Component):void => { if (chosenMatch) { - if (chosenMatch && chosenMatch instanceof MatchReqToCapability) { + if (chosenMatch && chosenMatch instanceof Match) { this.createSimpleLink(chosenMatch, cy, component); } } @@ -128,18 +120,18 @@ export class CompositionGraphLinkUtils { * @param matchesArray * @returns {Array<MatchBase>} */ - public filterUcpeLinks(fromNode:CompositionCiNodeBase, toNode:CompositionCiNodeBase, matchesArray:Array<MatchBase>):any { + public filterUcpeLinks(fromNode:CompositionCiNodeBase, toNode:CompositionCiNodeBase, matchesArray:Array<Match>):any { - let matchLink:Array<MatchBase>; + let matchLink:Array<Match>; if (fromNode.isUcpePart) { - matchLink = _.filter(matchesArray, (match:MatchBase) => { + matchLink = _.filter(matchesArray, (match:Match) => { return match.isOwner(fromNode.id); }); } if (toNode.isUcpePart) { - matchLink = _.filter(matchesArray, (match:MatchBase) => { + matchLink = _.filter(matchesArray, (match:Match) => { return match.isOwner(toNode.id); }); } @@ -154,14 +146,14 @@ export class CompositionGraphLinkUtils { * @param toNode * @returns {any} */ - public onLinkDrawn(cy:Cy.Instance, fromNode:Cy.CollectionFirstNode, toNode:Cy.CollectionFirstNode):RelationMenuDirectiveObj { + public onLinkDrawn(cy:Cy.Instance, fromNode:Cy.CollectionFirstNode, toNode:Cy.CollectionFirstNode):ConnectRelationModel { if (!this.commonGraphUtils.nodeLocationsCompatible(cy, fromNode, toNode)) { return null; } let linkModel:Array<CompositionCiLinkBase> = this.generalGraphUtils.getAllCompositionCiLinks(cy); - let possibleRelations:Array<MatchBase> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromNode.data().componentInstance, + let possibleRelations:Array<Match> = this.matchCapabilitiesRequirementsUtils.getMatchedRequirementsCapabilities(fromNode.data().componentInstance, toNode.data().componentInstance, linkModel); //filter relations found to limit to specific ucpe-cp @@ -169,8 +161,8 @@ export class CompositionGraphLinkUtils { //if found possibleRelations between the nodes we create relation menu directive and open the link menu if (possibleRelations.length) { - let menuPosition = this.generalGraphUtils.getLinkMenuPosition(cy, toNode.renderedPoint()); - return new RelationMenuDirectiveObj(fromNode.data(), toNode.data(), menuPosition, possibleRelations); + // let menuPosition = this.generalGraphUtils.getLinkMenuPosition(cy, toNode.renderedPoint()); + return new ConnectRelationModel(fromNode.data(), toNode.data(), possibleRelations); } return null; }; @@ -209,7 +201,7 @@ export class CompositionGraphLinkUtils { * @param vfNode */ public createVfToUcpeLink = (component:Component, cy:Cy.Instance, ucpeNode:NodeUcpe, vfNode:CompositionCiNodeVf):void => { - let hostedOnMatch:MatchReqToCapability = this.generalGraphUtils.canBeHostedOn(cy, ucpeNode.componentInstance, vfNode.componentInstance); + let hostedOnMatch:Match = this.generalGraphUtils.canBeHostedOn(cy, ucpeNode.componentInstance, vfNode.componentInstance); /* create relation */ let newRelation = new RelationshipModel(); newRelation.fromNode = ucpeNode.id; @@ -224,13 +216,12 @@ export class CompositionGraphLinkUtils { /** * Handles click event on links. * If one edge selected: do nothing. - /*Two edges selected - always select all - /* Three or more edges: first click - select all, secondary click - select single. + * Two or more edges: first click - select all, secondary click - select single. * @param cy * @param event */ public handleLinkClick(cy:Cy.Instance, event:Cy.EventObject) { - if (cy.$('edge:selected').length > 2 && event.cyTarget[0].selected()) { + if (cy.$('edge:selected').length > 1 && event.cyTarget[0].selected()) { cy.$(':selected').unselect(); } else { @@ -256,7 +247,7 @@ export class CompositionGraphLinkUtils { * @returns {Point} */ public calculateLinkMenuPosition(event, elementWidth, elementHeight):Point { - let point:Point = new Point(event.originalEvent.x, event.originalEvent.y); + let point:Point = new Point(event.originalEvent.clientX, event.originalEvent.clientY); if (event.originalEvent.view.screen.height - elementHeight < point.y) { point.y = event.originalEvent.view.screen.height - elementHeight; } diff --git a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts index 5f717512f5..6a02381902 100644 --- a/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts +++ b/catalog-ui/src/app/directives/graphs-v2/composition-graph/utils/match-capability-requierment-utils.ts @@ -18,22 +18,17 @@ * ============LICENSE_END========================================================= */ -import {Requirement, CompositionCiLinkBase, ComponentInstance, CapabilitiesGroup, RequirementsGroup, MatchReqToCapability, MatchBase, - MatchReqToReq,CompositionCiNodeBase, Component, Capability} from "app/models"; +import { + Requirement, CompositionCiLinkBase, CapabilitiesGroup, RequirementsGroup, Match, + CompositionCiNodeBase, Component, Capability +} from "app/models"; +import {ComponentInstance} from "../../../../models/componentsInstances/componentInstance"; /** * Created by obarda on 1/1/2017. */ export class MatchCapabilitiesRequirementsUtils { - constructor() { - } - - public static linkable(requirement1:Requirement, requirement2:Requirement, vlCapability:Capability):boolean { - return MatchCapabilitiesRequirementsUtils.isMatch(requirement1, vlCapability) && MatchCapabilitiesRequirementsUtils.isMatch(requirement2, vlCapability); - }; - - /** * Shows + icon in corner of each node passed in * @param filteredNodesData @@ -77,9 +72,7 @@ export class MatchCapabilitiesRequirementsUtils { }) } - // -------------------------------------------ALL FUNCTIONS NEED REFACTORING---------------------------------------------------------------// - - private static requirementFulfilled(fromNodeId:string, requirement:any, links:Array<CompositionCiLinkBase>):boolean { + private static isRequirementFulfilled(fromNodeId:string, requirement:any, links:Array<CompositionCiLinkBase>):boolean { return _.some(links, { 'relation': { 'fromNode': fromNodeId, @@ -108,172 +101,97 @@ export class MatchCapabilitiesRequirementsUtils { return false; }; - private getFromToMatches(requirements1:RequirementsGroup, - requirements2:RequirementsGroup, - capabilities:CapabilitiesGroup, - links:Array<CompositionCiLinkBase>, - fromId:string, - toId:string, - vlCapability?:Capability):Array<MatchBase> { - let matches:Array<MatchBase> = new Array<MatchBase>(); - _.forEach(requirements1, (requirementValue:Array<Requirement>, key) => { - _.forEach(requirementValue, (requirement:Requirement) => { - if (requirement.name !== "dependency" && !MatchCapabilitiesRequirementsUtils.requirementFulfilled(fromId, requirement, links)) { - _.forEach(capabilities, (capabilityValue:Array<Capability>, key) => { - _.forEach(capabilityValue, (capability:Capability) => { - if (MatchCapabilitiesRequirementsUtils.isMatch(requirement, capability)) { - let match:MatchReqToCapability = new MatchReqToCapability(requirement, capability, true, fromId, toId); - matches.push(match); - } - }); - }); - if (vlCapability) { - _.forEach(requirements2, (requirement2Value:Array<Requirement>, key) => { - _.forEach(requirement2Value, (requirement2:Requirement) => { - if (!MatchCapabilitiesRequirementsUtils.requirementFulfilled(toId, requirement2, links) && MatchCapabilitiesRequirementsUtils.linkable(requirement, requirement2, vlCapability)) { - let match:MatchReqToReq = new MatchReqToReq(requirement, requirement2, true, fromId, toId); - matches.push(match); - } - }); - }); - } - } - }); - }); - return matches; - } - - private getToFromMatches(requirements:RequirementsGroup, capabilities:CapabilitiesGroup, links:Array<CompositionCiLinkBase>, fromId:string, toId:string):Array<MatchReqToCapability> { - let matches:Array<MatchReqToCapability> = []; - _.forEach(requirements, (requirementValue:Array<Requirement>, key) => { - _.forEach(requirementValue, (requirement:Requirement) => { - if (requirement.name !== "dependency" && !MatchCapabilitiesRequirementsUtils.requirementFulfilled(toId, requirement, links)) { - _.forEach(capabilities, (capabilityValue:Array<Capability>, key) => { - _.forEach(capabilityValue, (capability:Capability) => { - if (MatchCapabilitiesRequirementsUtils.isMatch(requirement, capability)) { - let match:MatchReqToCapability = new MatchReqToCapability(requirement, capability, false, toId, fromId); - matches.push(match); - } - }); - }); - } - }); - }); - return matches; - } - public getMatchedRequirementsCapabilities(fromComponentInstance:ComponentInstance, toComponentInstance:ComponentInstance, - links:Array<CompositionCiLinkBase>, - vl?:Component):Array<MatchBase> {//TODO allow for VL array - let linkCapability; - if (vl) { - let linkCapabilities:Array<Capability> = vl.capabilities.findValueByKey('linkable'); - if (linkCapabilities) { - linkCapability = linkCapabilities[0]; - } - } - let fromToMatches:Array<MatchBase> = this.getFromToMatches(fromComponentInstance.requirements, - toComponentInstance.requirements, + links:Array<CompositionCiLinkBase>):Array<Match> { + let fromToMatches:Array<Match> = this.getMatches(fromComponentInstance.requirements, toComponentInstance.capabilities, links, fromComponentInstance.uniqueId, - toComponentInstance.uniqueId, - linkCapability); - let toFromMatches:Array<MatchReqToCapability> = this.getToFromMatches(toComponentInstance.requirements, + toComponentInstance.uniqueId, true); + let toFromMatches:Array<Match> = this.getMatches(toComponentInstance.requirements, fromComponentInstance.capabilities, links, fromComponentInstance.uniqueId, - toComponentInstance.uniqueId); + toComponentInstance.uniqueId, false); return fromToMatches.concat(toFromMatches); } + /***** REFACTORED FUNCTIONS START HERE *****/ + + public getMatches(requirements:RequirementsGroup, capabilities:CapabilitiesGroup, links:Array<CompositionCiLinkBase>, + fromId:string, toId:string, isFromTo: boolean):Array<Match> { + let matches:Array<Match> = []; + let unfulfilledReqs = this.getUnfulfilledRequirements(fromId, requirements, links); + _.forEach(unfulfilledReqs, (req)=> { + _.forEach(_.flatten(_.values(capabilities)), (capability:Capability)=> { + if (MatchCapabilitiesRequirementsUtils.isMatch(req, capability)) { + if(isFromTo) { + matches.push(new Match(req, capability, isFromTo, fromId, toId)); + } else{ + matches.push(new Match(req, capability, isFromTo, toId, fromId)); + } + } + }); + }); + return matches; + } + + public getUnfulfilledRequirements = (fromNodeId:string, requirements:RequirementsGroup, links:Array<CompositionCiLinkBase>):Array<Requirement>=> { + + let requirementArray:Array<Requirement> = []; + _.forEach(_.flatten(_.values(requirements)), (requirement:Requirement)=> { + if (requirement.name !== "dependency" && !MatchCapabilitiesRequirementsUtils.isRequirementFulfilled(fromNodeId, requirement, links)) { + requirementArray.push(requirement); + } + }); + return requirementArray; + }; + /** - * Step I: Check if capabilities of component match requirements of nodeDataArray - * 1. Get component capabilities and loop on each capability - * 2. Inside the loop, perform another loop on all nodeDataArray, and fetch the requirements for each one - * 3. Loop on the requirements, and verify match (see in code the rules) - * - * Step II: Check if requirements of component match capabilities of nodeDataArray - * 1. Get component requirements and loop on each requirement - * 2. - * - * @param component - this is the hovered resource of the left panel of composition screen - * @param nodeDataArray - Array of resource instances that are on the canvas - * @param links -getMatchedRequirementsCapabilities - * @param vl - - * @returns {any[]|T[]} + * Returns true if there is a match between the capabilities and requirements that are passed in + * @param requirements + * @param capabilities + * @returns {boolean} */ - public findByMatchingCapabilitiesToRequirements(component:Component, - nodeDataArray:Array<CompositionCiNodeBase>, - links:Array<CompositionCiLinkBase>, - vl?:Component):Array<any> {//TODO allow for VL array - let res = []; - - // STEP I - { - let capabilities:any = component.capabilities; - _.forEach(capabilities, (capabilityValue:Array<any>, capabilityKey)=> { - _.forEach(capabilityValue, (capability)=> { - _.forEach(nodeDataArray, (node:CompositionCiNodeBase)=> { - if (node && node.componentInstance) { - let requirements:any = node.componentInstance.requirements; - let fromNodeId:string = node.componentInstance.uniqueId; - _.forEach(requirements, (requirementValue:Array<any>, requirementKey)=> { - _.forEach(requirementValue, (requirement)=> { - if (requirement.name !== "dependency" && MatchCapabilitiesRequirementsUtils.isMatch(requirement, capability) - && !MatchCapabilitiesRequirementsUtils.requirementFulfilled(fromNodeId, requirement, links)) { - res.push(node); - } - }); - }); - } - }); - }); + public containsMatch = (requirements:Array<Requirement>, capabilities:CapabilitiesGroup):boolean => { + return _.some(requirements, (req:Requirement)=> { + return _.some(_.flatten(_.values(capabilities)), (capability:Capability) => { + return MatchCapabilitiesRequirementsUtils.isMatch(req, capability); }); - } + }); + }; - // STEP II - { - let requirements:any = component.requirements; - let fromNodeId:string = component.uniqueId; - let linkCapability:Array<Capability> = vl ? vl.capabilities.findValueByKey('linkable') : undefined; + /** + * Returns array of nodes that can connect to the component. + * In order to connect, one of the following conditions must be met: + * 1. component has an unfulfilled requirement that matches a node's capabilities + * 2. node has an unfulfilled requirement that matches the component's capabilities + * 3. vl is passed in which has the capability to fulfill requirement from component and requirement on node. + */ + public findMatchingNodes(component:Component, nodeDataArray:Array<CompositionCiNodeBase>, + links:Array<CompositionCiLinkBase>):Array<any> //TODO allow for VL array and TEST + { + let componentRequirements:Array<Requirement> = this.getUnfulfilledRequirements(component.uniqueId, component.requirements, links); + return _.filter(nodeDataArray, (node:any)=> { + if (node && node.componentInstance) { + + //Check if component has an unfulfilled requirement that can be met by one of nodes's capabilities (#1) + if (componentRequirements.length && node.category !== 'groupCp' && this.containsMatch(componentRequirements, node.componentInstance.capabilities)) { + return true; - _.forEach(requirements, (requirementValue:Array<any>, requirementKey)=> { - _.forEach(requirementValue, (requirement)=> { - if (requirement.name !== "dependency" && !MatchCapabilitiesRequirementsUtils.requirementFulfilled(fromNodeId, requirement, links)) { - _.forEach(nodeDataArray, (node:any)=> { - if (node && node.componentInstance && node.category !== 'groupCp') { - let capabilities:any = node.componentInstance.capabilities; - _.forEach(capabilities, (capabilityValue:Array<any>, capabilityKey)=> { - _.forEach(capabilityValue, (capability)=> { - if (MatchCapabilitiesRequirementsUtils.isMatch(requirement, capability)) { - res.push(node); - } - }); - }); - if (linkCapability) { - let linkRequirements = node.componentInstance.requirements; - _.forEach(linkRequirements, (value:Array<any>, key)=> { - _.forEach(value, (linkRequirement)=> { - if (!MatchCapabilitiesRequirementsUtils.requirementFulfilled(node.componentInstance.uniqueId, linkRequirement, links) - && MatchCapabilitiesRequirementsUtils.linkable(requirement, linkRequirement, linkCapability[0])) { - res.push(node); - } - }); - }); - } - } - }); + } else { //Check if node has unfulfilled requirement that can be filled by component (#2) + let nodeRequirements:Array<Requirement> = this.getUnfulfilledRequirements(node.componentInstance.uniqueId, node.componentInstance.requirements, links); + if (!nodeRequirements.length) return false; + if (this.containsMatch(nodeRequirements, component.capabilities)) { + return true; } - }); - }); - } - - return _.uniq(res); - }; + } + } + }); + } } MatchCapabilitiesRequirementsUtils.$inject = []; diff --git a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts index ace9d1ce4c..127f43b734 100644 --- a/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts +++ b/catalog-ui/src/app/directives/graphs-v2/deployment-graph/deployment-graph.directive.ts @@ -27,6 +27,7 @@ import { ModulesNodesStyle } from "../common/style/module-node-style"; import { GRAPH_EVENTS } from "app/utils"; import { EventListenerService } from "app/services"; import '@bardit/cytoscape-expand-collapse'; +import {AngularJSBridge} from "../../../services/angular-js-bridge-service"; interface IDeploymentGraphScope extends ng.IScope { component: Component; @@ -105,6 +106,7 @@ export class DeploymentGraph implements ng.IDirective { private loadGraph = (scope: IDeploymentGraphScope, el: JQuery) => { let graphEl = el.find('.sdc-deployment-graph-wrapper'); + const imagePath = AngularJSBridge.getAngularConfig().imagesPath; this._cy = cytoscape({ container: graphEl, style: ComponentInstanceNodesStyle.getCompositionGraphStyle().concat(ModulesNodesStyle.getModuleGraphStyle()), @@ -124,8 +126,8 @@ export class DeploymentGraph implements ng.IDirective { fisheye: false, undoable: false, expandCollapseCueSize: 18, - expandCueImage: '/assets/styles/images/resource-icons/' + 'closeModule.png', - collapseCueImage: '/assets/styles/images/resource-icons/' + 'openModule.png', + expandCueImage: imagePath + '/assets/styles/images/resource-icons/' + 'closeModule.png', + collapseCueImage: imagePath + '/assets/styles/images/resource-icons/' + 'openModule.png', expandCollapseCueSensitivity: 2, cueOffset: -20 }); 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 f46dc6c939..8abf968c82 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 @@ -132,7 +132,7 @@ export class Palette implements ng.IDirective { private initLeftPanel(leftPanelComponents:Array<LeftPaletteComponent>, resourceFilterTypes:Array<string>):LeftPanelModel { let leftPanelModel = new LeftPanelModel(); - + if (resourceFilterTypes && resourceFilterTypes.length) { leftPanelComponents = this.leftPanelResourceFilter(leftPanelComponents, resourceFilterTypes); } @@ -171,40 +171,6 @@ export class Palette implements ng.IDirective { this.EventListenerService.notifyObservers(GRAPH_EVENTS.ON_PALETTE_COMPONENT_HOVER_IN, displayComponent); this.$log.debug('palette::onMouseOver:: fired'); - // - // if (this.CompositionGraphGeneralUtils.componentRequirementsAndCapabilitiesCaching.containsKey(displayComponent.uniqueId)) { - // this.$log.debug(`palette::onMouseOver:: component id ${displayComponent.uniqueId} found in cache`); - // let cacheComponent:Component = this.CompositionGraphGeneralUtils.componentRequirementsAndCapabilitiesCaching.getValue(displayComponent.uniqueId); - // - // //TODO: Danny: fire event to highlight matching nodes - // //showMatchingNodes(cacheComponent); - // return; - // } - // - // this.$log.debug(`palette::onMouseOver:: component id ${displayComponent.uniqueId} not found in cache, initiating server get`); - // // This will bring the component from the server including requirements and capabilities - // // Check that we do not fetch many times, because only in the success we add the component to componentRequirementsAndCapabilitiesCaching - // if (this.fetchingComponentFromServer) { - // return; - // } - // - // this.fetchingComponentFromServer = true; - // this.ComponentFactory.getComponentFromServer(displayComponent.componentSubType, displayComponent.uniqueId) - // .then((component:Component) => { - // this.$log.debug(`palette::onMouseOver:: component id ${displayComponent.uniqueId} fetch success`); - // // this.LeftPaletteLoaderService.updateSpecificComponentLeftPalette(component, scope.currentComponent.componentType); - // this.CompositionGraphGeneralUtils.componentRequirementsAndCapabilitiesCaching.setValue(component.uniqueId, component); - // this.fetchingComponentFromServer = false; - // - // //TODO: Danny: fire event to highlight matching nodes - // //showMatchingNodes(component); - // }) - // .catch(() => { - // this.$log.debug('palette::onMouseOver:: component id fetch error'); - // this.fetchingComponentFromServer = false; - // }); - - }; scope.onMouseOut = () => { @@ -226,8 +192,13 @@ 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); - scope.model = this.initLeftPanel(scope.components, resourceFilterTypes); + scope.components = this.LeftPaletteLoaderService.getLeftPanelComponentsForDisplay(scope.currentComponent); + //remove the container component from the list + let componentTempToDisplay = angular.copy(scope.components); + componentTempToDisplay = _.remove(componentTempToDisplay, function (component) { + return component.component.invariantUUID !== scope.currentComponent.invariantUUID; + }); + scope.model = this.initLeftPanel(componentTempToDisplay, resourceFilterTypes); scope.displaySortedCategories = angular.copy(scope.model.sortedCategories); }; diff --git a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html index 4b123e5777..7f9bfd1e0d 100644 --- a/catalog-ui/src/app/directives/graphs-v2/palette/palette.html +++ b/catalog-ui/src/app/directives/graphs-v2/palette/palette.html @@ -32,7 +32,7 @@ data-ng-repeat="component in components | orderBy: 'displayName' track by $index" data-tests-id={{component.displayName}}> <div class="i-sdc-designer-leftbar-section-content-item-icon-ph"> - <div class="medium {{component.iconClass}}" + <div class="medium small {{component.iconClass}}" data-tests-id="leftbar-section-content-item-{{component.displayName}}"> <div class="{{component.certifiedIconClass}}" uib-tooltip="Not certified" tooltip-class="uib-custom-tooltip" tooltip-placement="bottom" tooltip-popup-delay="700"> diff --git a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html index a0a9e4af27..e1cdf499a0 100644 --- a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html +++ b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.html @@ -1,46 +1,46 @@ -<div class="link-menu-open" data-tests-id="link-menu-open" data-ng-show="isLinkMenuOpen" ng-style="{left: relationMenuDirectiveObj.menuPosition.x, top: relationMenuDirectiveObj.menuPosition.y}" clicked-outside="{onClickedOutside: 'hideRelationMatch()', clickedOutsideEnable: 'isLinkMenuOpen'}" > +<div class="link-menu-open" data-tests-id="link-menu-open" data-ng-show="isLinkMenuOpen" ng-style="{left: connectRelationModel.menuPosition.x, top: connectRelationModel.menuPosition.y}" clicked-outside="{onClickedOutside: 'hideRelationMatch()', clickedOutsideEnable: 'isLinkMenuOpen'}" > <h4 sdc-smart-tooltip>{{relationMenuDirectiveObj.leftSideLink.componentInstance.name | resourceName}}</h4> <h4 sdc-smart-tooltip>{{relationMenuDirectiveObj.rightSideLink.componentInstance.name | resourceName}}</h4> <p>Select one of the options below to connect</p> <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container"> - <div class="inner-title" data-ng-show="hasMatchesToShow(relationMenuDirectiveObj.leftSideLink.requirements, relationMenuDirectiveObj.rightSideLink.selectedMatch)">Requirements</div> - <div class="link-item" data-tests-id="link-item-requirements" data-ng-repeat="(req ,matchArr) in relationMenuDirectiveObj.leftSideLink.requirements" - data-ng-click="relationMenuDirectiveObj.leftSideLink.selectMatchArr(matchArr); updateSelectionText()" - data-ng-show="showMatch(relationMenuDirectiveObj.rightSideLink.selectedMatch, matchArr)" - data-ng-class="{ 'selected': relationMenuDirectiveObj.leftSideLink.selectedMatch === matchArr}"> + <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.leftSideLink.requirements, connectRelationModel.rightSideLink.selectedMatch)">Requirements</div> + <div class="link-item" data-tests-id="link-item-requirements" data-ng-repeat="(req ,matchArr) in connectRelationModel.leftSideLink.requirements" + data-ng-click="connectRelationModel.leftSideLink.selectMatchArr(matchArr); updateSelectionText()" + data-ng-show="showMatch(connectRelationModel.rightSideLink.selectedMatch, matchArr)" + data-ng-class="{ 'selected': connectRelationModel.leftSideLink.selectedMatch === matchArr}"> <div sdc-smart-tooltip>{{matchArr[0].requirement.getFullTitle()}}</div> </div> - <div class="inner-title" data-ng-show="hasMatchesToShow(relationMenuDirectiveObj.leftSideLink.capabilities, relationMenuDirectiveObj.rightSideLink.selectedMatch)">Capabilities</div> - <div class="link-item" data-tests-id="link-item-capabilities" data-ng-repeat="(cap, matchArr) in relationMenuDirectiveObj.leftSideLink.capabilities" - data-ng-click="relationMenuDirectiveObj.leftSideLink.selectMatchArr(matchArr); updateSelectionText()" - data-ng-show="showMatch(relationMenuDirectiveObj.rightSideLink.selectedMatch, matchArr)" - data-ng-class="{ 'selected': relationMenuDirectiveObj.leftSideLink.selectedMatch === matchArr}"> + <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.leftSideLink.capabilities, connectRelationModel.rightSideLink.selectedMatch)">Capabilities</div> + <div class="link-item" data-tests-id="link-item-capabilities" data-ng-repeat="(cap, matchArr) in connectRelationModel.leftSideLink.capabilities" + data-ng-click="connectRelationModel.leftSideLink.selectMatchArr(matchArr); updateSelectionText()" + data-ng-show="showMatch(connectRelationModel.rightSideLink.selectedMatch, matchArr)" + data-ng-class="{ 'selected': connectRelationModel.leftSideLink.selectedMatch === matchArr}"> <div sdc-smart-tooltip>{{matchArr[0].capability.getFullTitle()}}</div> </div> </perfect-scrollbar> <perfect-scrollbar scroll-y-margin-offset="0" include-padding="true" class="scrollbar-container"> - <div class="inner-title" data-ng-show="hasMatchesToShow(relationMenuDirectiveObj.rightSideLink.requirements, relationMenuDirectiveObj.leftSideLink.selectedMatch)">Requirements</div> - <div class="link-item" data-tests-id="link-item-requirements" data-ng-repeat="(req, matchArr) in relationMenuDirectiveObj.rightSideLink.requirements" - data-ng-click="relationMenuDirectiveObj.rightSideLink.selectMatchArr(matchArr); updateSelectionText()" - data-ng-show="showMatch(relationMenuDirectiveObj.leftSideLink.selectedMatch, matchArr)" - data-ng-class="{ 'selected': relationMenuDirectiveObj.rightSideLink.selectedMatch === matchArr}"> + <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.rightSideLink.requirements, connectRelationModel.leftSideLink.selectedMatch)">Requirements</div> + <div class="link-item" data-tests-id="link-item-requirements" data-ng-repeat="(req, matchArr) in connectRelationModel.rightSideLink.requirements" + data-ng-click="connectRelationModel.rightSideLink.selectMatchArr(matchArr); updateSelectionText()" + data-ng-show="showMatch(connectRelationModel.leftSideLink.selectedMatch, matchArr)" + data-ng-class="{ 'selected': connectRelationModel.rightSideLink.selectedMatch === matchArr}"> <div sdc-smart-tooltip>{{matchArr[0].secondRequirement ? matchArr[0].secondRequirement.getFullTitle() : matchArr[0].requirement.getFullTitle()}}</div> </div> - <div class="inner-title" data-ng-show="hasMatchesToShow(relationMenuDirectiveObj.rightSideLink.capabilities, relationMenuDirectiveObj.leftSideLink.selectedMatch)">Capabilities</div> - <div class="link-item" data-tests-id="link-item-capabilities" data-ng-repeat="(cap, matchArr) in relationMenuDirectiveObj.rightSideLink.capabilities" - data-ng-click="relationMenuDirectiveObj.rightSideLink.selectMatchArr(matchArr); updateSelectionText()" - data-ng-show="showMatch(relationMenuDirectiveObj.leftSideLink.selectedMatch, matchArr)" - data-ng-class="{ 'selected': relationMenuDirectiveObj.rightSideLink.selectedMatch === matchArr}"> + <div class="inner-title" data-ng-show="hasMatchesToShow(connectRelationModel.rightSideLink.capabilities, connectRelationModel.leftSideLink.selectedMatch)">Capabilities</div> + <div class="link-item" data-tests-id="link-item-capabilities" data-ng-repeat="(cap, matchArr) in connectRelationModel.rightSideLink.capabilities" + data-ng-click="connectRelationModel.rightSideLink.selectMatchArr(matchArr); updateSelectionText()" + data-ng-show="showMatch(connectRelationModel.leftSideLink.selectedMatch, matchArr)" + data-ng-class="{ 'selected': connectRelationModel.rightSideLink.selectedMatch === matchArr}"> <div sdc-smart-tooltip>{{matchArr[0].capability.getFullTitle()}}</div> </div> </perfect-scrollbar> - <div class="vl-type" data-ng-class="{'disabled': !relationMenuDirectiveObj.leftSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.rightSideLink.selectedMatch[0].secondRequirement}"> + <div class="vl-type" data-ng-class="{'disabled': !connectRelationModel.leftSideLink.selectedMatch[0].secondRequirement || !connectRelationModel.rightSideLink.selectedMatch[0].secondRequirement}"> <sdc-radio-button sdc-model="relationMenuDirectiveObj.vlType" value="ptp" disabled="!relationMenuDirectiveObj.leftSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.rightSideLink.selectedMatch[0].secondRequirement || !relationMenuDirectiveObj.p2pVL" text="Point to point" elem-id="radioPTP" elem-name="vlType"></sdc-radio-button> @@ -57,7 +57,7 @@ </div> <button class="tlv-btn grey" data-tests-id="link-menu-button-cancel" data-ng-click="hideRelationMatch()">Cancel</button> - <button class="tlv-btn blue" data-tests-id="link-menu-button-connect" data-ng-disabled="!relationMenuDirectiveObj.leftSideLink.selectedMatch || !relationMenuDirectiveObj.rightSideLink.selectedMatch || - (relationMenuDirectiveObj.leftSideLink.selectedMatch[0].secondRequirement && !relationMenuDirectiveObj.vlType)" + <button class="tlv-btn blue" data-tests-id="link-menu-button-connect" data-ng-disabled="!connectRelationModel.leftSideLink.selectedMatch || !connectRelationModel.rightSideLink.selectedMatch || + (connectRelationModel.leftSideLink.selectedMatch[0].secondRequirement && !connectRelationModel.vlType)" data-ng-click="saveRelation()">Connect</button> </div> diff --git a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts index 6106d10c4e..f73e855c0e 100644 --- a/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts +++ b/catalog-ui/src/app/directives/graphs-v2/relation-menu/relation-menu.ts @@ -18,19 +18,19 @@ * ============LICENSE_END========================================================= */ 'use strict' -import {MatchBase, RelationMenuDirectiveObj} from "app/models"; +import {Match, ConnectRelationModel} from "app/models"; import {Component} from "../../../models/components/component"; export interface IRelationMenuScope extends ng.IScope { - relationMenuDirectiveObj:RelationMenuDirectiveObj; + relationMenuDirectiveObj:ConnectRelationModel; createRelation:Function; isLinkMenuOpen:boolean; hideRelationMatch:Function; cancel:Function; saveRelation(); - showMatch(arr1:Array<MatchBase>, arr2:Array<MatchBase>):boolean; - hasMatchesToShow(matchesObj:MatchBase, selectedMatch:Array<MatchBase>); + showMatch(arr1:Array<Match>, arr2:Array<Match>):boolean; + hasMatchesToShow(matchesObj:Match, selectedMatch:Array<Match>); updateSelectionText():void; } @@ -58,7 +58,7 @@ export class RelationMenuDirective implements ng.IDirective { scope.saveRelation = ():void=> { let chosenMatches:Array<any> = _.intersection(scope.relationMenuDirectiveObj.rightSideLink.selectedMatch, scope.relationMenuDirectiveObj.leftSideLink.selectedMatch); - let chosenMatch:MatchBase = chosenMatches[0]; + let chosenMatch:Match = chosenMatches[0]; scope.createRelation()(chosenMatch); }; @@ -69,14 +69,14 @@ export class RelationMenuDirective implements ng.IDirective { }; //to show options in link menu - scope.showMatch = (arr1:Array<MatchBase>, arr2:Array<MatchBase>):boolean => { + scope.showMatch = (arr1:Array<Match>, arr2:Array<Match>):boolean => { return !arr1 || !arr2 || _.intersection(arr1, arr2).length > 0; }; //to show requirements/capabilities title - scope.hasMatchesToShow = (matchesObj:MatchBase, selectedMatch:Array<MatchBase>):boolean => { + scope.hasMatchesToShow = (matchesObj:Match, selectedMatch:Array<Match>):boolean => { let result:boolean = false; - _.forEach(matchesObj, (matchesArr:Array<MatchBase>) => { + _.forEach(matchesObj, (matchesArr:Array<Match>) => { if (!result) { result = scope.showMatch(matchesArr, selectedMatch); } diff --git a/catalog-ui/src/app/directives/layout/top-nav/top-nav.html b/catalog-ui/src/app/directives/layout/top-nav/top-nav.html deleted file mode 100644 index 60d3d63855..0000000000 --- a/catalog-ui/src/app/directives/layout/top-nav/top-nav.html +++ /dev/null @@ -1,54 +0,0 @@ -<nav class="top-nav"> - - <div class="asdc-app-title-wrapper"> - <a class="asdc-app-title" translate="PROJECT_TITLE"></a> - <div class="asdc-version"> v.{{version}}</div> - </div> - - <ul class="top-menu" data-ng-show="!menuModel"> - <!-- no hierarchy & dropdowns mode --> - <li data-ng-repeat="item in topLvlMenu.menuItems" - data-ng-class="{'selected': $index == topLvlMenu.selectedIndex}"> - <a data-ng-click="menuItemClick(topLvlMenu, item)" - data-tests-id="main-menu-button-{{item.text | lowercase}}">{{item.text}}</a> - </li> - </ul> - - <ul class="top-menu" data-ng-show="menuModel"> - <!-- with hierarchy & dropdowns mode --> - <li data-ng-repeat-start="groupItem in menuModel" - data-ng-class="{'selected': $last }"> - <a data-ng-click="menuItemClick(groupItem, groupItem.menuItems[groupItem.selectedIndex])" - data-tests-id="breadcrumbs-button-{{$index}}"> - {{groupItem.menuItems[groupItem.selectedIndex].text}} - </a> - </li> - <li data-ng-repeat-end="" class="triangle-dropdown" - data-ng-class="{'item-click': groupItem.itemClick}" data-ng-mouseover="groupItem.itemClick = true"> - <div class="triangle"><span class="sprite-new arrow-right"></span></div> - <perfect-scrollbar scroll-y-margin-offset="15" include-padding="true"> - <ul> - <li data-ng-repeat="ddItem in groupItem.menuItems" - data-ng-click="menuItemClick(groupItem, ddItem)" - data-ng-class="{'selected': $index == groupItem.selectedIndex, 'disabled': ddItem.isDisabled}" - data-tests-id="sub-menu-button-{{ddItem.text | lowercase}}"> - <span sdc-smart-tooltip="">{{ddItem.text}}</span> - </li> - </ul> - </perfect-scrollbar> - </li> - </ul> - - <div class="top-search" data-ng-hide="hideSearch === true"> - <input type="text" - class="search-text" - placeholder="Search" - data-ng-model="searchBind" - data-tests-id="main-menu-input-search" - ng-model-options="{ debounce: 500 }" /> - <span class="w-sdc-search-icon magnification"></span> - </div> - - <div class="notification-icon" data-ng-disabled= "progress > 0" data-ng-class="{'disabled' : progress > 0}" data-ng-if="user.role === 'DESIGNER' && notificationIconCallback" data-ng-click="notificationIconCallback()" tooltips tooltip-side="left" tooltip-content="Vendor Software Product Repository" data-tests-id="repository-icon"></div> - -</nav> diff --git a/catalog-ui/src/app/directives/layout/top-nav/top-nav.less b/catalog-ui/src/app/directives/layout/top-nav/top-nav.less deleted file mode 100644 index 13b4a525f4..0000000000 --- a/catalog-ui/src/app/directives/layout/top-nav/top-nav.less +++ /dev/null @@ -1,218 +0,0 @@ -.top-nav { - position: fixed; - top: @header_height; - background-color: @main_color_p; - .box-shadow(0px 1px 3px 0px rgba(0, 0, 0, 0.33)); - width: 100%; - height: @top_nav_height; - line-height: @top_nav_height; - z-index: 10; - display: flex; - flex-direction: row; - align-items: center; - - .asdc-app-title-wrapper { - flex-grow: 1; - line-height: 16px; - margin: 0 20px; - - a.asdc-app-title { - .m_18_r; - text-decoration: none; - } - - .asdc-version { - .m_12_r; - .opacity(0.8); - line-height: 14px; - flex-grow: 1; - } - - } - - ul.top-menu { - list-style-type: none; - margin: 0 0 0 20px; - padding: 0; - flex-grow: 999; - - & > li { - float: left; - cursor: pointer; - line-height: 50px; - height: 50px; - padding: 0 20px; - - &.selected { - border-bottom: solid 4px @main_color_a; - - a { - color: @func_color_s; - } - } - - /*&:hover { - border-bottom: solid 4px @main_color_a; - }*/ - - a { - font-family: @font-opensans-medium; - color: @main_color_m; - font-size: 16px; - display: block; - text-align: center; - text-decoration: none; - } - - &.triangle-dropdown { - padding: 0; - position: relative; - - div.triangle { - margin-top: 15px; - border-radius: 2px; - width: 17px; - height: 18px; - - //temp use - until new triangle gets in - line-height: 18px; - text-align: center; - font-size: 10px; - - &:hover { - background-color: rgba(156, 156, 156, 0.2); - - span { - .arrow-right-hover; - } - } - } - - + li a { - font-size: 16px; - } - - .ps-container { - .perfect-scrollbar; - position: absolute; - left: 0; - top: 40px; - z-index: 1; - - overflow: hidden; - max-height: 0; - -webkit-transition: max-height 200ms ease-in; - -moz-transition: max-height 200ms ease-in; - -o-transition: max-height 200ms ease-in; - transition: max-height 200ms ease-in; - - div ul { - - padding: 0; - background-color: white; - - li { - - height: 35px; - background-color: white; - font-size: 13px; - width: 150px; - line-height: 35px; - padding: 0 10px; - - &.disabled { - opacity: 1; - } - &.selected { - background-color: @tlv_color_v; - font-weight: bold; - } - &:hover { - color: @main_color_a; - } - span { - height: 35px; - width: 130px; - display: inline-block; - } - } - } - } - &.item-click:hover .ps-container, - &.item-click:active .ps-container { - max-height: 500px; - border: 1px solid @func_color_b; - border-radius: 2px; - box-shadow: 0px 2px 2px 0px rgba(24, 24, 25, 0.1); - - div ul { - - } - } - } - } - - } - - .top-search { - position: relative; - flex-grow: 1; - padding: 0 20px; - - input.search-text { - .border-radius(2px); - width: 245px; - height: 32px; - line-height: 32px; - border: 1px solid @main_color_o; - outline: none; - text-indent: 10px; - - &::-webkit-input-placeholder { font-style: italic; } /* Safari, Chrome and Opera */ - &:-moz-placeholder { font-style: italic; } /* Firefox 18- */ - &::-moz-placeholder { font-style: italic; } /* Firefox 19+ */ - &:-ms-input-placeholder { font-style: italic; } /* IE 10+ */ - &:-ms-input-placeholder { font-style: italic; } /* Edge */ - /* font-style: italic; - }*/ - /* Firefox 18- */ - &::-moz-placeholder { - font-style: italic; - } - /* Firefox 19+ */ - &:-ms-input-placeholder { - font-style: italic; - } - /* IE 10+ */ - &:-ms-input-placeholder { - font-style: italic; - } - /* Edge */ - } - - .magnification { - position: absolute; - top: 19px; - right: 26px; - } - - } - - .notification-icon { - cursor: pointer; - flex-grow: 1; - margin: 0 10px 6px 0; - .sprite-new; - .vsp-list-icon; - - &:hover { - .vsp-list-icon-hover; - } - - &:active { - .vsp-list-icon-active; - } - - } - -} diff --git a/catalog-ui/src/app/directives/layout/top-nav/top-nav.ts b/catalog-ui/src/app/directives/layout/top-nav/top-nav.ts deleted file mode 100644 index 59e4d49647..0000000000 --- a/catalog-ui/src/app/directives/layout/top-nav/top-nav.ts +++ /dev/null @@ -1,161 +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 {IAppConfigurtaion, IHostedApplication, IUserProperties} from "app/models"; -import {IUserResourceClass} from "app/services"; -import {MenuItemGroup, MenuItem} from "app/utils"; - -export interface ITopNavScope extends ng.IScope { - topLvlSelectedIndex:number; - hideSearch:boolean; - searchBind:any; - menuModel:Array<MenuItemGroup>; - - topLvlMenu:MenuItemGroup; - goToState(state:string, params:Array<any>):ng.IPromise<boolean>; - menuItemClick:Function; - user:IUserProperties; - version:string; -} - - -export class TopNavDirective implements ng.IDirective { - - constructor(private $filter:ng.IFilterService, - private $state:ng.ui.IStateService, - private $q:ng.IQService, - private userResourceService:IUserResourceClass, - private sdcConfig:IAppConfigurtaion) { - } - - public replace = true; - public restrict = 'E'; - public transclude = false; - - - scope = { - topLvlSelectedIndex: '@?', - hideSearch: '=', - searchBind: '=', - version: '@', - notificationIconCallback: '=', - menuModel: '=?', - }; - - template = ():string => { - return require('./top-nav.html'); - }; - - public link = (scope:ITopNavScope, $elem:ng.IAugmentedJQuery, $attrs:angular.IAttributes) => { - - let getTopLvlSelectedIndexByState = ():number => { - if (!scope.topLvlMenu.menuItems) { - return 0; - } - - let result = -1; - - //set result to current state - scope.topLvlMenu.menuItems.forEach((item:MenuItem, index:number)=> { - if (item.state === this.$state.current.name) { - result = index; - } - }); - - //if it's a different state , checking previous state param - if (result === -1) { - scope.topLvlMenu.menuItems.forEach((item:MenuItem, index:number)=> { - if (item.state === this.$state.params['previousState']) { - result = index; - } - }); - } - - if (result === -1) { - result = 0; - } - - return result; - }; - - scope.user = this.userResourceService.getLoggedinUser(); - - let tmpArray:Array<MenuItem> = [ - new MenuItem(this.$filter('translate')("TOP_MENU_HOME_BUTTON"), null, "dashboard", "goToState", null, null), - new MenuItem(this.$filter('translate')("TOP_MENU_CATALOG_BUTTON"), null, "catalog", "goToState", null, null) - ]; - - // Only designer can perform onboarding - if (scope.user && scope.user.role === 'DESIGNER') { - tmpArray.push(new MenuItem(this.$filter('translate')("TOP_MENU_ON_BOARD_BUTTON"), null, "onboardVendor", "goToState", null, null)); - _.each(this.sdcConfig.hostedApplications, (hostedApp:IHostedApplication)=> { - if (hostedApp.exists) { - tmpArray.push(new MenuItem(hostedApp.navTitle, null, hostedApp.defaultState, "goToState", null, null)); - } - }); - } - - scope.topLvlMenu = new MenuItemGroup(0, tmpArray, true); - scope.topLvlMenu.selectedIndex = isNaN(scope.topLvlSelectedIndex) ? getTopLvlSelectedIndexByState() : scope.topLvlSelectedIndex; - - let generateMenu = () => { - if (scope.menuModel && scope.menuModel[0] !== scope.topLvlMenu) { - scope.menuModel.unshift(scope.topLvlMenu); - } - }; - scope.$watch('menuModel', generateMenu); - - generateMenu(); - - /////scope functions//// - - scope.goToState = (state:string, params:Array<any>):ng.IPromise<boolean> => { - let deferred = this.$q.defer(); - this.$state.go(state, params && params.length > 0 ? [0] : undefined); - deferred.resolve(true); - return deferred.promise; - }; - - scope.menuItemClick = (itemGroup:MenuItemGroup, item:MenuItem) => { - - itemGroup.itemClick = false; - - let onSuccess = ():void => { - itemGroup.selectedIndex = itemGroup.menuItems.indexOf(item); - }; - let onFailed = ():void => { - }; - - if (item.callback) { - (item.callback.apply(undefined, item.params)).then(onSuccess, onFailed); - } else { - scope[item.action](item.state, item.params).then(onSuccess, onFailed); - } - }; - }; - - public static factory = ($filter:ng.IFilterService, $state:ng.ui.IStateService, $q:ng.IQService, userResourceService:IUserResourceClass, sdcConfig:IAppConfigurtaion)=> { - return new TopNavDirective($filter, $state, $q, userResourceService, sdcConfig); - }; - -} - -TopNavDirective.factory.$inject = ['$filter', '$state', '$q', 'Sdc.Services.UserResourceService', 'sdcConfig']; diff --git a/catalog-ui/src/app/directives/loader/loader-directive.ts b/catalog-ui/src/app/directives/loader/loader-directive.ts index 36efc22079..7e056c774f 100644 --- a/catalog-ui/src/app/directives/loader/loader-directive.ts +++ b/catalog-ui/src/app/directives/loader/loader-directive.ts @@ -56,19 +56,14 @@ export class LoaderDirective implements ng.IDirective { let interval; - this.EventListenerService.registerObserverCallback(EVENTS.SHOW_LOADER_EVENT, (loaderType)=> { - if (scope.loaderType !== loaderType) { - return; - } - scope.display = true; - }); - this.EventListenerService.registerObserverCallback(EVENTS.HIDE_LOADER_EVENT, (loaderType)=> { - if (scope.loaderType !== loaderType) { - return; - } - scope.display = false; - }); - + if(scope.loaderType) { + this.EventListenerService.registerObserverCallback(EVENTS.SHOW_LOADER_EVENT + scope.loaderType, (loaderType)=> { + scope.display = true; + }); + this.EventListenerService.registerObserverCallback(EVENTS.HIDE_LOADER_EVENT + scope.loaderType, (loaderType)=> { + scope.display = false; + }); + } let calculateSizesForFixPosition = (positionStyle:string):void => { // This is problematic, I do not want to change the parent position. // set the loader on all the screen diff --git a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html index b62824d544..a2c29c5398 100644 --- a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html +++ b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.html @@ -8,7 +8,7 @@ <div tooltips tooltip-content="{{property.name}}"> <input class="i-sdc-form-input" type="text" - data-ng-disabled="true" + readonly="readonly" value="{{property.name}}"/> </div> </div> @@ -48,7 +48,7 @@ data-tests-id="{{fieldsPrefixName+property.name}}" ng-if="!((property.simpleType||property.type) == 'boolean')" data-ng-maxlength="100" - data-ng-disabled="readOnly" + data-ng-readonly="readOnly" maxlength="{{(property.simpleType||property.type) == 'integer'? 10 : 100}}" data-ng-model="valueObjRef[property.name]" type="text" diff --git a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.less b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.less index 5c65fdc9dc..abca49d7a3 100644 --- a/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.less +++ b/catalog-ui/src/app/directives/property-types/data-type-fields-structure/data-type-fields-structure.less @@ -29,6 +29,10 @@ .i-sdc-form-input:disabled{ .disabled; } + .i-sdc-form-input:read-only{ + opacity: 0.4; + cursor: auto; + } .property{ display: flex; 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 ec9aaf1f7f..dde4e8f32e 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 @@ -12,7 +12,7 @@ data-ng-pattern="MapKeyValidationPattern" data-ng-model-options="{ debounce: 200 }" data-ng-change="changeKeyOfMap(mapKeys[$index], $index,'mapKey'+fieldsPrefixName+$index);$event.stopPropagation();" - data-ng-disabled="readOnly" + data-ng-readonly="readOnly" data-required autofocus/> <div class="input-error" data-ng-show="parentFormObj['mapKey'+fieldsPrefixName+$index].$dirty && parentFormObj['mapKey'+fieldsPrefixName+$index].$invalid"> @@ -26,7 +26,7 @@ <label class="i-sdc-form-label required">Value</label> <input class="i-sdc-form-input" ng-if="!((schemaProperty.simpleType||schemaProperty.type) == 'boolean')" - data-ng-disabled="readOnly" + data-ng-readonly="readOnly" data-ng-model="valueObjRef[mapKeys[$index]]" type="text" name="mapValue{{fieldsPrefixName}}{{$index}}" diff --git a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less index 2480b626f2..6dc481dd26 100644 --- a/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less +++ b/catalog-ui/src/app/directives/property-types/type-map/type-map-directive.less @@ -79,5 +79,10 @@ &>.data-type-fields-structure{ padding: 0; } + + .i-sdc-form-input:read-only{ + opacity: 0.4; + cursor: auto; + } } } diff --git a/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.less b/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.less index 43d2d646a1..290a6468cb 100644 --- a/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.less +++ b/catalog-ui/src/app/directives/select-property-types/select-data-type-fields-structure/select-data-type-fields-structure.less @@ -45,9 +45,13 @@ margin-left: 22px; } - .i-sdc-form-input:disabled{ - .disabled; - &[type="text"]{ + .i-sdc-form-input{ + &:disabled{ + .disabled; + } + } + .property-name{ + .i-sdc-form-input:read-only{ opacity: 1 !important; background-color: @tlv_color_t; color:black; diff --git a/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts b/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts index eadca96bfa..1367906e21 100644 --- a/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts +++ b/catalog-ui/src/app/directives/user-header-details/user-header-details-directive.ts @@ -19,21 +19,17 @@ */ 'use strict'; -import {User, IUser, IAppConfigurtaion} from "app/models"; -import {IUserResourceClass, IUserResource} from "app/services"; +import {User, IUser, IAppConfigurtaion, IUserProperties} from "app/models"; +import { UserService } from "../../ng2/services/user.service"; export interface IUserHeaderDetailsScope extends ng.IScope { - name:string; - role:string; iconUrl:string; - UserResourceClass:IUserResourceClass; user:IUser; - sdcConfig:IAppConfigurtaion; initUser:Function; } export class UserHeaderDetailsDirective implements ng.IDirective { - constructor(private $http:ng.IHttpService, private sdcConfig:IAppConfigurtaion, private UserResourceClass:IUserResourceClass) { + constructor(private $http:ng.IHttpService, private sdcConfig:IAppConfigurtaion, private userService:UserService) { } scope = { @@ -50,23 +46,23 @@ export class UserHeaderDetailsDirective implements ng.IDirective { scope.initUser = ():void => { let defaultUserId:string; - let user:IUserResource = this.UserResourceClass.getLoggedinUser(); - if (!user) { + let userInfo:IUserProperties = this.userService.getLoggedinUser(); + if (!userInfo) { defaultUserId = this.$http.defaults.headers.common[this.sdcConfig.cookie.userIdSuffix]; - user = this.UserResourceClass.get({id: defaultUserId}, ():void => { - scope.user = new User(user); + this.userService.getUser(defaultUserId).subscribe((defaultUserInfo):void => { + scope.user = new User(defaultUserInfo); }); } else { - scope.user = new User(user); + scope.user = new User(userInfo); } }; scope.initUser(); }; - public static factory = ($http:ng.IHttpService, sdcConfig:IAppConfigurtaion, UserResourceClass:IUserResourceClass)=> { - return new UserHeaderDetailsDirective($http, sdcConfig, UserResourceClass); + public static factory = ($http:ng.IHttpService, sdcConfig:IAppConfigurtaion, userService:UserService)=> { + return new UserHeaderDetailsDirective($http, sdcConfig, userService); }; } -UserHeaderDetailsDirective.factory.$inject = ['$http', 'sdcConfig', 'Sdc.Services.UserResourceService']; +UserHeaderDetailsDirective.factory.$inject = ['$http', 'sdcConfig', 'UserServiceNg2']; diff --git a/catalog-ui/src/app/models.ts b/catalog-ui/src/app/models.ts index ec70ebe8b1..014525367d 100644 --- a/catalog-ui/src/app/models.ts +++ b/catalog-ui/src/app/models.ts @@ -40,6 +40,7 @@ export * from './models/components/service'; export * from './models/componentsInstances/componentInstance'; export * from './models/componentsInstances/resourceInstance'; export * from './models/componentsInstances/serviceInstance'; +export * from './models/componentsInstances/serviceProxyInstance'; export * from './models/csar-component'; //export * from './models/data-type-properties'; export * from './models/properties-inputs/property-be-model'; @@ -74,7 +75,9 @@ export * from './models/graph/nodes/base-common-node'; export * from './models/graph/nodes/common-ci-node-base'; export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-base'; export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-cp'; +export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration'; export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-service'; +export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy'; export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp'; export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe'; export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node-vf'; @@ -83,7 +86,7 @@ export * from './models/graph/nodes/composition-graph-nodes/composition-ci-node- export * from './models/graph/nodes/modules-graph-nodes/module-node-base'; export * from './models/graph/nodes/nodes-factory'; export * from './models/graph/point'; -export * from './models/graph/relationMenuObjects'; +export * from './models/graph/connectRelationModel'; export * from './models/graph/relationship'; export * from './models/heat-parameters'; export * from './models/input-property-base'; @@ -103,6 +106,8 @@ export * from './models/validate'; export * from './models/component-metadata'; export * from './models/modal'; export * from './models/button'; +export * from './models/wizard-step'; +export * from './models/radio-button'; export * from './models/filter-properties-assignment-data' export * from './models/properties-inputs/input-be-model' diff --git a/catalog-ui/src/app/models/capability.ts b/catalog-ui/src/app/models/capability.ts index 79cf425d92..2f2e3a8de6 100644 --- a/catalog-ui/src/app/models/capability.ts +++ b/catalog-ui/src/app/models/capability.ts @@ -23,7 +23,9 @@ */ 'use strict'; import {PropertyModel} from "./properties"; +import {Requirement} from "./requirement"; +export interface RequirementCapabilityModel{}; //this is an object contains keys, when each key has matching array. // for example: key = tosca.capabilities.network.Linkable and the match array is array of capabilities objects export class CapabilitiesGroup { @@ -44,7 +46,7 @@ export class CapabilitiesGroup { } } -export class Capability { +export class Capability implements RequirementCapabilityModel{ //server data name:string; @@ -53,11 +55,12 @@ export class Capability { type:string; uniqueId:string; capabilitySources:Array<String>; + leftOccurrences:string; minOccurrences:string; maxOccurrences:string; - properties:Array<PropertyModel>; description:string; validSourceTypes:Array<string>; + properties:Array<PropertyModel>; //custom selected:boolean; filterTerm:string; @@ -72,6 +75,7 @@ export class Capability { this.type = capability.type; this.uniqueId = capability.uniqueId; this.capabilitySources = capability.capabilitySources; + this.leftOccurrences = capability.leftOccurrences; this.minOccurrences = capability.minOccurrences; this.maxOccurrences = capability.maxOccurrences; this.properties = capability.properties; @@ -83,9 +87,13 @@ export class Capability { } } + public getTitle():string { + return this.ownerName + ': ' + this.name; + } + public getFullTitle():string { let maxOccurrences:string = this.maxOccurrences === 'UNBOUNDED' ? '∞' : this.maxOccurrences; - return this.ownerName + ': ' + this.name + ': [' + this.minOccurrences + ', ' + maxOccurrences + ']'; + return this.getTitle() + ': [' + this.minOccurrences + ', ' + maxOccurrences + ']'; } public toJSON = ():any => { @@ -110,6 +118,10 @@ export class Capability { }); } } + + public isFulfilled() { + return parseInt(this.leftOccurrences) === 0; + } } diff --git a/catalog-ui/src/app/models/components/component.ts b/catalog-ui/src/app/models/components/component.ts index 53e8f05cbe..daa4a19e19 100644 --- a/catalog-ui/src/app/models/components/component.ts +++ b/catalog-ui/src/app/models/components/component.ts @@ -29,6 +29,8 @@ import {CommonUtils} from "../../utils/common-utils"; import {QueueUtils} from "../../utils/functions"; import {ArtifactGroupType} from "../../utils/constants"; import {ComponentMetadata} from "../component-metadata"; +import {Capability} from "../capability"; +import {Requirement} from "../requirement"; // import {} export interface IComponent { @@ -82,6 +84,7 @@ export interface IComponent { createRelation(link:RelationshipModel):ng.IPromise<RelationshipModel>; deleteRelation(link:RelationshipModel):ng.IPromise<RelationshipModel>; + fetchRelation(linkId:string):ng.IPromise<RelationshipModel>; //Modules @@ -356,7 +359,6 @@ export abstract class Component implements IComponent { // find exist instance property in parent component for update the new value ( find bu uniqueId ) let existProperty:PropertyModel = <PropertyModel>_.find(this.properties, {uniqueId: newProperty.uniqueId}); let propertyIndex = this.properties.indexOf(existProperty); - newProperty.readonly = this.uniqueId != newProperty.parentUniqueId; this.properties[propertyIndex] = newProperty; deferred.resolve(newProperty); }; @@ -607,6 +609,58 @@ export abstract class Component implements IComponent { }; + public syncComponentByRelation(relation:RelationshipModel) { + relation.relationships.forEach((rel) => { + if (rel.capability) { + const toComponentInstance:ComponentInstance = this.componentInstances.find((inst) => inst.uniqueId === relation.toNode); + const toComponentInstanceCapability:Capability = toComponentInstance.findCapability( + rel.capability.type, rel.capability.uniqueId, rel.capability.ownerId, rel.capability.name); + const isCapabilityFulfilled:boolean = rel.capability.isFulfilled(); + if (isCapabilityFulfilled && toComponentInstanceCapability) { + // if capability is fulfilled and in component, then remove it + console.log('Capability is fulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences); + toComponentInstance.capabilities[rel.capability.type].splice( + toComponentInstance.capabilities[rel.capability.type].findIndex((cap) => cap === toComponentInstanceCapability), 1 + ) + } else if (!isCapabilityFulfilled && !toComponentInstanceCapability) { + // if capability is unfulfilled and not in component, then add it + console.log('Capability is unfulfilled', rel.capability.getFullTitle(), rel.capability.leftOccurrences); + toComponentInstance.capabilities[rel.capability.type].push(rel.capability); + } + } + if (rel.requirement) { + const fromComponentInstance:ComponentInstance = this.componentInstances.find((inst) => inst.uniqueId === relation.fromNode); + const fromComponentInstanceRequirement:Requirement = fromComponentInstance.findRequirement( + rel.requirement.capability, rel.requirement.uniqueId, rel.requirement.ownerId, rel.requirement.name); + const isRequirementFulfilled:boolean = rel.requirement.isFulfilled(); + if (isRequirementFulfilled && fromComponentInstanceRequirement) { + // if requirement is fulfilled and in component, then remove it + console.log('Requirement is fulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences); + fromComponentInstance.requirements[rel.requirement.capability].splice( + fromComponentInstance.requirements[rel.requirement.capability].findIndex((req) => req === fromComponentInstanceRequirement), 1 + ) + } else if (!isRequirementFulfilled && !fromComponentInstanceRequirement) { + // if requirement is unfulfilled and not in component, then add it + console.log('Requirement is unfulfilled', rel.requirement.getFullTitle(), rel.requirement.leftOccurrences); + fromComponentInstance.requirements[rel.requirement.capability].push(rel.requirement); + } + } + }); + } + + public fetchRelation = (linkId:string):ng.IPromise<RelationshipModel> => { + let deferred = this.$q.defer<RelationshipModel>(); + let onSuccess = (relation:RelationshipModel):void => { + this.syncComponentByRelation(relation); + deferred.resolve(relation); + }; + let onFailed = (error:any):void => { + deferred.reject(error); + }; + this.componentService.fetchRelation(this.uniqueId, linkId).then(onSuccess, onFailed); + return deferred.promise; + }; + public createRelation = (relation:RelationshipModel):ng.IPromise<RelationshipModel> => { let deferred = this.$q.defer(); let onSuccess = (relation:RelationshipModel):void => { @@ -615,6 +669,7 @@ export abstract class Component implements IComponent { this.componentInstancesRelations = []; } this.componentInstancesRelations.push(new RelationshipModel(relation)); + this.syncComponentByRelation(relation); deferred.resolve(relation); }; let onFailed = (error:any):void => { @@ -627,11 +682,11 @@ export abstract class Component implements IComponent { public deleteRelation = (relation:RelationshipModel):ng.IPromise<RelationshipModel> => { let deferred = this.$q.defer(); - let onSuccess = (responseRelation:RelationshipModel):void => { + let onSuccess = (relation:RelationshipModel):void => { console.log("Link Deleted In Server"); let relationToDelete = _.find(this.componentInstancesRelations, (item) => { return item.fromNode === relation.fromNode && item.toNode === relation.toNode && _.some(item.relationships, (relationship)=> { - return angular.equals(relation.relationships[0], relationship); + return angular.equals(relation.relationships[0].relation, relationship.relation); }); }); let index = this.componentInstancesRelations.indexOf(relationToDelete); @@ -640,11 +695,14 @@ export abstract class Component implements IComponent { this.componentInstancesRelations.splice(index, 1); } else { this.componentInstancesRelations[index].relationships = - _.reject(this.componentInstancesRelations[index].relationships, relation.relationships[0]); + _.reject(this.componentInstancesRelations[index].relationships, (relationship) => { + return angular.equals(relation.relationships[0].relation, relationship.relation); + }); } } else { console.error("Error while deleting relation - the return delete relation from server was not found in UI") } + this.syncComponentByRelation(relation); deferred.resolve(relation); }; let onFailed = (error:any):void => { @@ -658,8 +716,8 @@ export abstract class Component implements IComponent { public updateRequirementsCapabilities = ():ng.IPromise<any> => { let deferred = this.$q.defer(); let onSuccess = (response:any):void => { - this.capabilities = response.capabilities; - this.requirements = response.requirements; + this.capabilities = new CapabilitiesGroup(response.capabilities); + this.requirements = new RequirementsGroup(response.requirements); deferred.resolve(response); }; let onFailed = (error:any):void => { diff --git a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts index 06939a7a9e..59521ccfc8 100644 --- a/catalog-ui/src/app/models/componentsInstances/componentInstance.ts +++ b/catalog-ui/src/app/models/componentsInstances/componentInstance.ts @@ -23,7 +23,9 @@ */ 'use strict'; import {ArtifactGroupModel, CapabilitiesGroup,RequirementsGroup, PropertyModel, InputModel, Module} from "../../models"; -import {ResourceType} from "../../utils/constants"; +import {ResourceType,ComponentType} from "../../utils/constants"; +import {Capability} from "../capability"; +import {Requirement} from "../requirement"; export class ComponentInstance { @@ -46,6 +48,10 @@ export class ComponentInstance { public capabilities:CapabilitiesGroup; public requirements:RequirementsGroup; public customizationUUID:string; + public sourceModelInvariant:string; + public sourceModelName:string; + public sourceModelUid:string; + public sourceModelUuid:string; //custom properties public certified:boolean; public iconSprite:string; @@ -79,6 +85,10 @@ export class ComponentInstance { this.updatePosition(componentInstance.posX, componentInstance.posY); this.groupInstances = componentInstance.groupInstances; this.invariantName = componentInstance.invariantName; + this.sourceModelInvariant = componentInstance.sourceModelInvariant; + this.sourceModelName = componentInstance.sourceModelName; + this.sourceModelUid = componentInstance.sourceModelUid; + this.sourceModelUuid = componentInstance.sourceModelUuid; } } @@ -97,6 +107,10 @@ export class ComponentInstance { return this.originType === ResourceType.VF || this.originType === ResourceType.PNF || this.originType === ResourceType.CVFC ; } + public isServiceProxy = () :boolean => { + return this.originType === ComponentType.SERVICE_PROXY; + } + public setInstanceRC = ():void=> { _.forEach(this.requirements, (requirementValue:Array<any>, requirementKey)=> { _.forEach(requirementValue, (requirement)=> { @@ -121,6 +135,30 @@ export class ComponentInstance { this.posY = posY; } + public findRequirement(reqType:string, uniqueId:string, ownerId:string, name:string):Requirement|undefined { + let requirement:Requirement = undefined; + const searchGroup = (reqType) ? [this.requirements[reqType]] : this.requirements; + _.some(_.keys(searchGroup), (searchType) => { + requirement = _.find<Requirement>(searchGroup[searchType], (req:Requirement) => ( + req.uniqueId === uniqueId && req.ownerId === ownerId && req.name === name + )); + return requirement; + }); + return requirement; + } + + public findCapability(capType:string, uniqueId:string, ownerId:string, name:string):Capability|undefined { + let capability:Capability = undefined; + const searchGroup = (capType) ? [this.capabilities[capType]] : this.capabilities; + _.some(_.keys(searchGroup), (searchType) => { + capability = _.find<Capability>(searchGroup[searchType], (cap:Capability) => ( + cap.uniqueId === uniqueId && cap.ownerId === ownerId && cap.name === name + )); + return capability; + }); + return capability; + } + public toJSON = ():any => { let temp = angular.copy(this); temp.certified = undefined; diff --git a/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.ts b/catalog-ui/src/app/models/componentsInstances/serviceProxyInstance.ts index 7796f60d70..a035a17db8 100644 --- a/catalog-ui/src/app/directives/ecomp-footer/ecomp-footer.ts +++ b/catalog-ui/src/app/models/componentsInstances/serviceProxyInstance.ts @@ -18,36 +18,18 @@ * ============LICENSE_END========================================================= */ +/** + * Created by obarda on 2/4/2016. + */ 'use strict'; -import {IAppConfigurtaion} from "app/models"; - -export interface IEcompFooterDirectiveScope extends ng.IScope { - -} - -export class EcompFooterDirective implements ng.IDirective { +import {ComponentInstance} from "./componentInstance"; - constructor(private sdcConfig:IAppConfigurtaion) { +export class ServiceProxyInstance extends ComponentInstance { + constructor(componentInstance?:ServiceProxyInstance) { + super(componentInstance); + this.iconSprite = "sprite-proxy-services-icons"; + //this.originType = "ServiceProxy"; } - - public replace = true; - public restrict = 'E'; - - public scope = {}; - - template = ():string => { - return require('./ecomp-footer.html'); - }; - - link = (scope:IEcompFooterDirectiveScope, $elem:JQuery, attr:any) => { - - }; - - public static factory = (sdcConfig:IAppConfigurtaion)=> { - return new EcompFooterDirective(sdcConfig); - }; - } -EcompFooterDirective.factory.$inject = ['sdcConfig']; diff --git a/catalog-ui/src/app/models/graph/relationMenuObjects.ts b/catalog-ui/src/app/models/graph/connectRelationModel.ts index 37b7cee349..af9732fa59 100644 --- a/catalog-ui/src/app/models/graph/relationMenuObjects.ts +++ b/catalog-ui/src/app/models/graph/connectRelationModel.ts @@ -18,12 +18,11 @@ * ============LICENSE_END========================================================= */ 'use strict'; -import {MatchReqToReq, MatchBase} from "./match-relation"; +import {Match} from "./match-relation"; import {CompositionCiNodeBase} from "./nodes/composition-graph-nodes/composition-ci-node-base"; -import {Component} from "../components/component"; import {ComponentInstance} from "../componentsInstances/componentInstance"; -export class RelationMenuDirectiveObj { +export class ConnectRelationModel { fromNode:CompositionCiNodeBase; toNode:CompositionCiNodeBase; @@ -31,17 +30,16 @@ export class RelationMenuDirectiveObj { rightSideLink:GraphLinkMenuSide; leftSideLink:GraphLinkMenuSide; selectionText:string; - vlType:string; + possibleRelations:Array<Match>; - constructor(fromNode:CompositionCiNodeBase, toNode:CompositionCiNodeBase, menuPosition:Cy.Position, possibleRelations:Array<MatchBase>) { + constructor(fromNode:CompositionCiNodeBase, toNode:CompositionCiNodeBase, possibleRelations:Array<Match>) { this.fromNode = fromNode; this.toNode = toNode; - // this.modelLinks = modelLinks; - this.menuPosition = menuPosition; + this.leftSideLink = new GraphLinkMenuSide(this.fromNode.componentInstance); this.rightSideLink = new GraphLinkMenuSide(this.toNode.componentInstance); this.selectionText = ''; - this.vlType = null; + this.possibleRelations = possibleRelations; possibleRelations.forEach((match:any) => { @@ -57,20 +55,13 @@ export class RelationMenuDirectiveObj { //push the match to fromNode object (from node is always the requirement) this.leftSideLink.requirements[reqObjKey].push(match); - if (match instanceof MatchReqToReq) { - //init the right side requirements Array - if (!this.rightSideLink.requirements[capObjKey]) { - this.rightSideLink.requirements[capObjKey] = []; - } - this.rightSideLink.requirements[capObjKey].push(match); - } else { - //init the right side capabilities Array - if (!this.rightSideLink.capabilities[capObjKey]) { - this.rightSideLink.capabilities[capObjKey] = []; - } - //add to array - this.rightSideLink.capabilities[capObjKey].push(match); + //init the right side capabilities Array + if (!this.rightSideLink.capabilities[capObjKey]) { + this.rightSideLink.capabilities[capObjKey] = []; } + //add to array + this.rightSideLink.capabilities[capObjKey].push(match); + } else { if (!this.rightSideLink.requirements[reqObjKey]) { @@ -100,7 +91,7 @@ export class GraphLinkMenuSide { this.requirements = {}; } - public selectMatchArr(matchArr:Array<MatchBase>):void { + public selectMatchArr(matchArr:Array<Match>):void { if (this.selectedMatch === matchArr) { this.selectedMatch = undefined; } else { diff --git a/catalog-ui/src/app/models/graph/graph-links/composition-graph-links/composition-ci-ucpe-link.ts b/catalog-ui/src/app/models/graph/graph-links/composition-graph-links/composition-ci-ucpe-link.ts index 6b2e12a215..42cce998f1 100644 --- a/catalog-ui/src/app/models/graph/graph-links/composition-graph-links/composition-ci-ucpe-link.ts +++ b/catalog-ui/src/app/models/graph/graph-links/composition-graph-links/composition-ci-ucpe-link.ts @@ -29,7 +29,7 @@ export class CompositionCiUcpeLink extends CompositionCiLinkBase { super(relation, singleRelation); this.isFromUcpe = from; this.target = relation.toNode; - this.source = singleRelation.requirementOwnerId; + this.source = singleRelation.relation.requirementOwnerId; this.relation.relationships = [singleRelation]; this.color = GraphColors.BASE_LINK; } diff --git a/catalog-ui/src/app/models/graph/graph-links/links-factory.ts b/catalog-ui/src/app/models/graph/graph-links/links-factory.ts index 0be5d6faf6..88c5323330 100644 --- a/catalog-ui/src/app/models/graph/graph-links/links-factory.ts +++ b/catalog-ui/src/app/models/graph/graph-links/links-factory.ts @@ -46,7 +46,7 @@ export class LinksFactory { // newRelation = new CompositionCiUcpeLink(relation, fromNode.isUcpePart, singleRelation); // } // } else - if (singleRelation.relationship.type && _.includes(singleRelation.relationship.type.toLowerCase(), 'link')) { + if (singleRelation.relation.relationship.type && _.includes(singleRelation.relation.relationship.type.toLowerCase(), 'link')) { newRelation = new CompositionCiVLink(relation, singleRelation); } else { newRelation = new CompositionCiSimpleLink(relation, singleRelation); @@ -68,7 +68,7 @@ export class LinksFactory { let newRelation:ModuleCiLinkBase; - if (_.includes(singleRelation.relationship.type.toLowerCase(), 'link')) { + if (_.includes(singleRelation.relation.relationship.type.toLowerCase(), 'link')) { newRelation = new ModuleCiVlLink(relation, singleRelation); } else { newRelation = new ModuleCiLinkBase(relation, singleRelation); diff --git a/catalog-ui/src/app/models/graph/match-relation.ts b/catalog-ui/src/app/models/graph/match-relation.ts index 4fb073d579..8d139d6405 100644 --- a/catalog-ui/src/app/models/graph/match-relation.ts +++ b/catalog-ui/src/app/models/graph/match-relation.ts @@ -20,80 +20,49 @@ 'use strict'; import {Requirement} from "../requirement"; import {Capability} from "../capability"; -import {Relationship, RelationshipModel, RelationType} from "./relationship"; +import {Relationship, RelationshipModel} from "./relationship"; +import {PropertyModel} from "../properties"; -export class MatchBase { +export class Match { requirement:Requirement; + capability:Capability; isFromTo:boolean; fromNode:string; toNode:string; + capabilityProperties:Array<PropertyModel>; // use this to store the capability properties, since there are times the capability itself is not available (when fulfilled). + private _relationship:Relationship; - constructor(requirement:Requirement, isFromTo:boolean, fromNode:string, toNode:string) { + constructor(requirement:Requirement, capability:Capability, isFromTo:boolean, fromNode:string, toNode:string) { this.requirement = requirement; + this.capability = capability; this.isFromTo = isFromTo; this.fromNode = fromNode; this.toNode = toNode; } - public getDisplayText = (menuSide:string):string => { - return ''; - }; - - public isOwner = (id:string):boolean => { - return false; - } - -} - -export class MatchReqToReq extends MatchBase { - - secondRequirement:Requirement; - - constructor(requirement:Requirement, secondRequirement:Requirement, isFromTo:boolean, fromNode:string, toNode:string) { - super(requirement, isFromTo, fromNode, toNode); - this.secondRequirement = secondRequirement; - } - - public getDisplayText = (menuSide:string):string => { - if ('left' == menuSide) { - return this.requirement.getFullTitle(); + // NOTE: Hold the relationship instance for cases capability / requirement are not available (when fulfilled). + // In case relationship instance is not manually saved to here, then build the relationship from the given capability and requirement. + public get relationship():Relationship { + if (!this._relationship) { + this._relationship = this.matchToRelation(); } - return this.secondRequirement.getFullTitle(); - }; - - public isOwner = (id:string):boolean => { - return this.secondRequirement.ownerId === id || this.requirement.ownerId === id; + return this._relationship; } -} - -export class MatchReqToCapability extends MatchBase { - - capability:Capability; - - constructor(requirement:Requirement, capability:Capability, isFromTo:boolean, fromNode:string, toNode:string) { - super(requirement, isFromTo, fromNode, toNode); - this.capability = capability; + public set relationship(relationship) { + this._relationship = relationship; } public matchToRelation = ():Relationship => { - let relationship:Relationship = new Relationship(); - relationship.capability = this.capability.name; - relationship.capabilityOwnerId = this.capability.ownerId; - relationship.capabilityUid = this.capability.uniqueId; - relationship.relationship = new RelationType(this.capability.type); - relationship.requirement = this.requirement.name; - relationship.requirementOwnerId = this.requirement.ownerId; - relationship.requirementUid = this.requirement.uniqueId; + const relationship:Relationship = new Relationship(); + relationship.setRelationProperties(this.capability, this.requirement); return relationship; }; - public getDisplayText = (menuSide:string):string => { if (this.isFromTo && 'left' == menuSide || !this.isFromTo && 'right' == menuSide) { return this.requirement.getFullTitle(); } return this.capability.getFullTitle(); - }; public isOwner = (id:string):boolean => { @@ -108,4 +77,3 @@ export class MatchReqToCapability extends MatchBase { }; } - diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts index 681cebc8d2..3b634b1f6e 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-base.ts @@ -48,7 +48,6 @@ export abstract class CompositionCiNodeBase extends CommonCINodeBase implements this.isGroup = false; this.isUcpePart = false; this.isInsideGroup = false; - } public initUncertifiedImage(node:Cy.Collection, nodeMinSize:number):string { @@ -61,8 +60,10 @@ export abstract class CompositionCiNodeBase extends CommonCINodeBase implements uncertifiedCanvasWidth = nodeWidth + uncertifiedIconWidth/2; //expand canvas so that only half of the icon overlaps with the node } - this.imageCreator.getImageBase64(this.imagesPath + ImagesUrl.RESOURCE_ICONS + this.componentInstance.icon + '.png', - this.imagesPath + ImagesUrl.RESOURCE_ICONS + 'uncertified.png', nodeWidth, uncertifiedCanvasWidth, uncertifiedIconWidth) + + + this.imageCreator.getImageBase64(this.imagesPath + this.componentInstance.icon + '.png', + this.imagesPath + 'uncertified.png', nodeWidth, uncertifiedCanvasWidth, uncertifiedIconWidth) .then(imageBase64 => { this.img = imageBase64; node.style({ diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts new file mode 100644 index 0000000000..1182f5e664 --- /dev/null +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-configuration.ts @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants"; +import {ComponentInstance, CompositionCiNodeBase} from "../../../../models"; +import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service"; +export class CompositionCiNodeConfiguration extends CompositionCiNodeBase { + + constructor(instance:ComponentInstance, + imageCreator:ImageCreatorService) { + super(instance, imageCreator); + this.initConfiguration(); + } + + private initConfiguration():void { + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; + this.img = this.imagesPath + this.componentInstance.icon + '.png'; + this.imgWidth = GraphUIObjects.SMALL_RESOURCE_WIDTH; + this.type = "basic-small-node"; + this.classes = 'configuration-node'; + } +} diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts index cded0ea104..3bd57695ec 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-cp.ts @@ -34,7 +34,8 @@ export class CompositionCiNodeCp extends CompositionCiNodeBase { private initCp():void { let sdcConfig = AngularJSBridge.getAngularConfig(); - this.img = sdcConfig.imagesPath + ImagesUrl.RESOURCE_ICONS + this.componentInstance.icon + '.png'; + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; + this.img = this.imagesPath + this.componentInstance.icon + '.png'; this.imgWidth = GraphUIObjects.SMALL_RESOURCE_WIDTH; this.type = "basic-small-node"; //if the cp from type cpEndPointInstances create with another template diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts new file mode 100644 index 0000000000..b993490043 --- /dev/null +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service-proxy.ts @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { ImagesUrl, GraphUIObjects} from "../../../../utils/constants"; +import {ComponentInstance, CompositionCiNodeBase} from "../../../../models"; +import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service"; +export class CompositionCiNodeServiceProxy extends CompositionCiNodeBase { + + constructor(instance:ComponentInstance, + imageCreator:ImageCreatorService) { + super(instance, imageCreator); + this.initService(); + } + + private initService():void { + this.imagesPath = this.imagesPath + ImagesUrl.SERVICE_PROXY_ICONS; + this.img = this.imagesPath + this.componentInstance.icon + '.png'; + this.imgWidth = GraphUIObjects.DEFAULT_RESOURCE_WIDTH; + this.classes = 'service-node' + if (!this.certified) { + this.classes = this.classes + ' not-certified'; + } + + } +} diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts index 81ee61a14f..b4e6ac354a 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-service.ts @@ -30,7 +30,7 @@ export class CompositionCiNodeService extends CompositionCiNodeBase { } private initService():void { - + this.imagesPath = this.imagesPath + ImagesUrl.SERVICE_ICONS; this.img = this.imagesPath + ImagesUrl.SERVICE_ICONS + this.componentInstance.icon + '.png'; this.imgWidth = GraphUIObjects.DEFAULT_RESOURCE_WIDTH; this.classes = 'service-node' diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts index 5013e52457..a79b183db4 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe-cp.ts @@ -20,6 +20,7 @@ import {CompositionCiNodeCp, ComponentInstance} from "./../../../../models"; import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service"; +import { ImagesUrl} from "../../../../utils/constants"; export class CompositionCiNodeUcpeCp extends CompositionCiNodeCp { @@ -31,5 +32,6 @@ export class CompositionCiNodeUcpeCp extends CompositionCiNodeCp { this.parent = instance.uniqueId; this.type = 'ucpe-cp-node'; //the type is for the handle (plus icon) extension this.isDraggable = false; + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; } } diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts index b8f844cba8..3dd6a4e238 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-ucpe.ts @@ -21,6 +21,7 @@ import {ComponentInstance} from "../../../componentsInstances/componentInstance"; import {ImageCreatorService} from "../../../../directives/graphs-v2/image-creator/image-creator.service"; import {CompositionCiNodeBase} from "./composition-ci-node-base"; +import { ImagesUrl} from "../../../../utils/constants"; export class NodeUcpe extends CompositionCiNodeBase { constructor(instance:ComponentInstance, @@ -36,6 +37,7 @@ export class NodeUcpe extends CompositionCiNodeBase { this.classes = 'ucpe-node'; this.type = 'ucpe-node'; this.allowConnection = false; + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; if (!this.certified) { this.classes = this.classes + ' not-certified-ucpe'; diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts index 005804c11f..b5ad57a5c3 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vf.ts @@ -31,7 +31,8 @@ export class CompositionCiNodeVf extends CompositionCiNodeBase { } private initVf():void { - this.img = this.imagesPath + ImagesUrl.RESOURCE_ICONS + this.componentInstance.icon + '.png'; + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; + this.img = this.imagesPath + this.componentInstance.icon + '.png'; this.imgWidth = GraphUIObjects.DEFAULT_RESOURCE_WIDTH; this.classes = 'vf-node'; if (!this.certified) { diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts index c8ae004003..5f07986d5c 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vfc.ts @@ -29,6 +29,7 @@ export class CompositionCiNodeVfc extends CompositionCiNodeBase { } private initVfc():void { - this.img = this.imagesPath + ImagesUrl.RESOURCE_ICONS + this.componentInstance.icon + '.png'; + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; + this.img = this.imagesPath + this.componentInstance.icon + '.png'; } } diff --git a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts index bf52ec0408..29cd9256d9 100644 --- a/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts +++ b/catalog-ui/src/app/models/graph/nodes/composition-graph-nodes/composition-ci-node-vl.ts @@ -48,6 +48,7 @@ export class CompositionCiNodeVl extends CompositionCiNodeBase { } this.img = this.imagesPath + ImagesUrl.RESOURCE_ICONS + 'vl.png'; this.imgWidth = GraphUIObjects.SMALL_RESOURCE_WIDTH; + this.imagesPath = this.imagesPath + ImagesUrl.RESOURCE_ICONS; this.classes = 'vl-node'; if (!this.certified) { diff --git a/catalog-ui/src/app/models/graph/nodes/modules-graph-nodes/module-node-base.ts b/catalog-ui/src/app/models/graph/nodes/modules-graph-nodes/module-node-base.ts index ccc8ed4afa..4e9fb0b0ab 100644 --- a/catalog-ui/src/app/models/graph/nodes/modules-graph-nodes/module-node-base.ts +++ b/catalog-ui/src/app/models/graph/nodes/modules-graph-nodes/module-node-base.ts @@ -24,6 +24,7 @@ import {ImagesUrl} from "../../../../utils/constants"; import {Module} from "../../../modules/base-module"; import {CommonNodeBase} from "../base-common-node"; +import {AngularJSBridge} from "../../../../services/angular-js-bridge-service"; export interface IModuleNodeBase { } @@ -44,7 +45,7 @@ export class ModuleNodeBase extends CommonNodeBase implements IModuleNodeBase { this.name = this.module.name; this.displayName = this.module.name; this.isGroup = true; - this.img = ImagesUrl.MODULE_ICON; + this.img = AngularJSBridge.getAngularConfig().imagesPath + ImagesUrl.MODULE_ICON; this.classes = "module-node"; } diff --git a/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts b/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts index c7f8eaa126..245f2e10d9 100644 --- a/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts +++ b/catalog-ui/src/app/models/graph/nodes/nodes-factory.ts @@ -19,8 +19,8 @@ */ 'use strict'; -import {CompositionCiNodeUcpeCp, Module, ModuleNodeBase, CompositionCiNodeVf, CompositionCiNodeVl, CompositionCiNodeCp, - NodeUcpe, CompositionCiNodeService, CompositionCiNodeBase, ComponentInstance} from "./../../../models"; +import {CompositionCiNodeUcpeCp, Module, ModuleNodeBase, CompositionCiNodeVf, CompositionCiNodeVl, CompositionCiNodeCp, CompositionCiNodeConfiguration, + NodeUcpe, CompositionCiNodeService,CompositionCiNodeServiceProxy, CompositionCiNodeBase, ComponentInstance} from "./../../../models"; import {ComponentType, ResourceType} from "../../../utils/constants"; import {ImageCreatorService} from "../../../directives/graphs-v2/image-creator/image-creator.service"; @@ -37,12 +37,18 @@ export class NodesFactory { if (instance.originType === ComponentType.SERVICE) { return new CompositionCiNodeService(instance, this.imageCreator); } + if (instance.originType === ComponentType.SERVICE_PROXY) { + return new CompositionCiNodeServiceProxy(instance, this.imageCreator); + } if (instance.originType === ResourceType.CP) { return new CompositionCiNodeCp(instance, this.imageCreator); } if (instance.originType === ResourceType.VL) { return new CompositionCiNodeVl(instance, this.imageCreator); } + if (instance.originType === ResourceType.CONFIGURATION) { + return new CompositionCiNodeConfiguration(instance, this.imageCreator); + } return new CompositionCiNodeVf(instance, this.imageCreator); }; diff --git a/catalog-ui/src/app/models/graph/relationship.ts b/catalog-ui/src/app/models/graph/relationship.ts index 67a5488b59..57ff45ef00 100644 --- a/catalog-ui/src/app/models/graph/relationship.ts +++ b/catalog-ui/src/app/models/graph/relationship.ts @@ -58,7 +58,8 @@ export class RelationType { } } -export class Relationship { +export class RelationshipType { + id:string; capability:string; capabilityOwnerId:string; capabilityUid:string; @@ -67,8 +68,9 @@ export class Relationship { requirementOwnerId:string; requirementUid:string; - constructor(relationship?:Relationship) { + constructor(relationship?:RelationshipType) { if (relationship) { + this.id = relationship.id; this.capability = relationship.capability; this.capabilityOwnerId = relationship.capabilityOwnerId; this.capabilityUid = relationship.capabilityUid; @@ -79,17 +81,41 @@ export class Relationship { } else { this.relationship = new RelationType(); } - } - public setRelationProperties = (capability:Capability, requirement:Requirement)=> { - this.capability = capability.name; - this.capabilityOwnerId = capability.ownerId; - this.capabilityUid = capability.uniqueId; - this.relationship = new RelationType(capability.type); - this.requirement = requirement.name; - this.requirementOwnerId = requirement.ownerId; - this.requirementUid = requirement.uniqueId; + public setRelationProperties = (capability?:Capability, requirement?:Requirement)=> { + if (capability) { + this.capability = capability.name; + this.capabilityOwnerId = capability.ownerId; + this.capabilityUid = capability.uniqueId; + this.relationship = new RelationType(capability.type); + } + if (requirement) { + this.requirement = requirement.name; + this.requirementOwnerId = requirement.ownerId; + this.requirementUid = requirement.uniqueId; + } }; +} + +export class Relationship { + relation: RelationshipType; + capability?: Capability; + requirement?: Requirement; + + constructor(fullRelationship?:Relationship) { + if (fullRelationship) { + this.relation = new RelationshipType(fullRelationship.relation); + this.capability = fullRelationship.capability && new Capability(fullRelationship.capability); + this.requirement = fullRelationship.requirement && new Requirement(fullRelationship.requirement); + } else { + this.relation = new RelationshipType(); + } + } + public setRelationProperties(capability?:Capability, requirement?:Requirement) { + this.relation.setRelationProperties(capability, requirement); + this.capability = capability; + this.requirement = requirement; + }; } diff --git a/catalog-ui/src/app/models/heat-parameters.ts b/catalog-ui/src/app/models/heat-parameters.ts index a199c9d847..153108a5f4 100644 --- a/catalog-ui/src/app/models/heat-parameters.ts +++ b/catalog-ui/src/app/models/heat-parameters.ts @@ -31,6 +31,7 @@ export class HeatParameterModel { currentValue:string; defaultValue:string; + filterTerm:string; constructor(parameter?:HeatParameterModel) { } diff --git a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts index c46c8ad28d..14b6385f2f 100644 --- a/catalog-ui/src/app/models/properties-inputs/property-be-model.ts +++ b/catalog-ui/src/app/models/properties-inputs/property-be-model.ts @@ -55,7 +55,7 @@ export class PropertyBEModel { this.schema = property.schema; this.type = property.type; this.uniqueId = property.uniqueId; - this.value = property.value ? property.value : property.defaultValue; + this.value = property.value; this.definition = property.definition; this.getInputValues = property.getInputValues; } 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 b35bb27b65..6faa6ada84 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 @@ -38,6 +38,7 @@ export class PropertyFEModel extends PropertyBEModel { constructor(property: PropertyBEModel){ super(property); + this.value = property.value ? property.value : property.defaultValue;//In FE if a property doesn't have value - display the default value this.isSimpleType = PROPERTY_DATA.SIMPLE_TYPES.indexOf(this.type) > -1; this.setNonDeclared(); this.derivedDataType = this.getDerivedPropertyType(); diff --git a/catalog-ui/src/app/models/properties.ts b/catalog-ui/src/app/models/properties.ts index f46bf8beb0..7a1f1a39ef 100644 --- a/catalog-ui/src/app/models/properties.ts +++ b/catalog-ui/src/app/models/properties.ts @@ -21,6 +21,7 @@ 'use strict'; import {SchemaPropertyGroupModel, SchemaProperty} from "./aschema-property"; import {InputPropertyBase} from "./input-property-base"; +import {PropertyBEModel} from "./properties-inputs/property-be-model"; export class PropertiesGroup { constructor(propertiesObj?:PropertiesGroup) { @@ -54,8 +55,7 @@ export interface IPropertyModel extends InputPropertyBase { simpleType:string; } -export class PropertyModel implements IPropertyModel { - +export class PropertyModel extends PropertyBEModel implements IPropertyModel { //server data uniqueId:string; name:string; @@ -90,19 +90,10 @@ export class PropertyModel implements IPropertyModel { constructor(property?:PropertyModel) { + super(property); if (property) { - this.uniqueId = property.uniqueId; - this.name = property.name; this.constraints = property.constraints; - this.defaultValue = property.defaultValue; - this.description = property.description; - this.password = property.password; - this.required = property.required; - this.type = property.type; this.source = property.source; - this.parentUniqueId = property.parentUniqueId; - this.schema = property.schema; - this.value = property.value ? property.value : property.defaultValue; this.valueUniqueUid = property.valueUniqueUid; this.path = property.path; this.rules = property.rules; diff --git a/catalog-ui/src/app/models/radio-button.ts b/catalog-ui/src/app/models/radio-button.ts new file mode 100644 index 0000000000..e907b26bce --- /dev/null +++ b/catalog-ui/src/app/models/radio-button.ts @@ -0,0 +1,11 @@ +/** + * Created by rc2122 on 9/5/2017. + */ +export class RadioButtonModel{ + key: string; + value: any; + constructor(key: string, value: any){ + this.key = key; + this.value = value; + } +} diff --git a/catalog-ui/src/app/models/requirement.ts b/catalog-ui/src/app/models/requirement.ts index 53e870679d..d880456b06 100644 --- a/catalog-ui/src/app/models/requirement.ts +++ b/catalog-ui/src/app/models/requirement.ts @@ -22,6 +22,7 @@ * Created by obarda on 4/20/2016. */ 'use strict'; +import {RequirementCapabilityModel} from "./capability"; //this is an object contains keys, when each key has matching array. // for example: key = tosca.capabilities.network. and the match array is array of requirements objects export class RequirementsGroup { @@ -36,7 +37,7 @@ export class RequirementsGroup { } } -export class Requirement { +export class Requirement implements RequirementCapabilityModel{ //server data capability:string; @@ -46,6 +47,7 @@ export class Requirement { node:string; uniqueId:string; relationship:string; + leftOccurrences:string; minOccurrences:string; maxOccurrences:string; //custom @@ -61,6 +63,7 @@ export class Requirement { this.node = requirement.node; this.uniqueId = requirement.uniqueId; this.relationship = requirement.relationship; + this.leftOccurrences = requirement.leftOccurrences; this.minOccurrences = requirement.minOccurrences; this.maxOccurrences = requirement.maxOccurrences; this.initFilterTerm(); @@ -68,9 +71,12 @@ export class Requirement { } } + public getTitle():string { + return this.ownerName + ': ' + this.name; + } + public getFullTitle():string { - return this.ownerName + ': ' + this.name + - ': [' + this.minOccurrences + ', ' + this.maxOccurrences + ']'; + return this.getTitle() + ': [' + this.minOccurrences + ', ' + this.maxOccurrences + ']'; } public toJSON = ():any => { @@ -86,6 +92,10 @@ export class Requirement { (this.relationship ? (this.relationship.substring("tosca.relationships.".length) + " ") : "") + this.minOccurrences + "," + this.maxOccurrences; } + + public isFulfilled() { + return parseInt(this.leftOccurrences) === 0; + } } diff --git a/catalog-ui/src/app/models/user.ts b/catalog-ui/src/app/models/user.ts index 54ddf1e5f6..0fb5364290 100644 --- a/catalog-ui/src/app/models/user.ts +++ b/catalog-ui/src/app/models/user.ts @@ -19,7 +19,6 @@ */ 'use strict'; -import {IUserResource} from "../services/user-resource-service"; export enum UserRole { ADMIN, @@ -46,7 +45,7 @@ export interface IUserProperties extends IUserManager { } export interface IUser { - resource:IUserResource; + userInfo:IUserProperties; getRole():UserRole; getRoleToView():string; getName():string; @@ -56,32 +55,32 @@ export interface IUser { export class User implements IUser { - constructor(public resource:IUserResource) { + constructor(public userInfo:IUserProperties) { } public getLastName = () => { - return this.resource.lastName; - } + return this.userInfo.lastName; + }; public getFirstName = () => { - return this.resource.firstName; - } + return this.userInfo.firstName; + }; public getName = () => { - return this.resource.firstName + ' ' + this.resource.lastName; - } + return this.userInfo.firstName + ' ' + this.userInfo.lastName; + }; public getLastLogin = () => { - if (!this.resource.lastLoginTime || this.resource.lastLoginTime === "0") { + if (!this.userInfo.lastLoginTime || this.userInfo.lastLoginTime === "0") { return ""; } else { - return this.resource.lastLoginTime; + return this.userInfo.lastLoginTime; } - } + }; public getRole = ():UserRole => { let role:UserRole; - switch (UserRole[this.resource.role.toUpperCase()]) { + switch (UserRole[this.userInfo.role.toUpperCase()]) { case UserRole.ADMIN: role = UserRole.ADMIN; break; @@ -99,10 +98,10 @@ export class User implements IUser { break; } return role; - } + }; public getRoleToView = ():string => { - let role:string = this.resource.role.toLowerCase().replace('governor', 'governance_Rep'); + let role:string = this.userInfo.role.toLowerCase().replace('governor', 'governance_Rep'); return role.charAt(0).toUpperCase() + role.slice(1).replace('_', ' '); } } diff --git a/catalog-ui/src/app/models/wizard-step.ts b/catalog-ui/src/app/models/wizard-step.ts new file mode 100644 index 0000000000..b8484b2dd6 --- /dev/null +++ b/catalog-ui/src/app/models/wizard-step.ts @@ -0,0 +1,19 @@ +/** + * Created by rc2122 on 8/16/2017. + */ + +import {Type} from "@angular/core"; + +export interface IStepComponent { + preventNext():boolean; + preventBack():boolean; +} + +export class StepModel{ + title: string; + component: Type<IStepComponent>; + constructor(title: string, component: Type<IStepComponent>){ + this.title = title; + this.component = component; + } +} diff --git a/catalog-ui/src/app/modules/directive-module.ts b/catalog-ui/src/app/modules/directive-module.ts index 8142cc49bd..4039a7683a 100644 --- a/catalog-ui/src/app/modules/directive-module.ts +++ b/catalog-ui/src/app/modules/directive-module.ts @@ -40,7 +40,6 @@ import {ExpandCollapseMenuBoxDirective} from "../directives/utils/expand-collaps import {PunchOutDirective} from "../directives/punch-out/punch-out"; import {CustomValidationDirective} from "../directives/custom-validation/custom-validation"; import {EcompHeaderDirective} from "../directives/ecomp-header/ecomp-header"; -import {EcompFooterDirective} from "../directives/ecomp-footer/ecomp-footer"; import {EditNamePopoverDirective} from "../directives/edit-name-popover/edit-name-popover-directive"; import {DataTypeFieldsStructureDirective} from "../directives/property-types/data-type-fields-structure/data-type-fields-structure"; import {TypeMapDirective} from "../directives/property-types/type-map/type-map-directive"; @@ -54,7 +53,6 @@ import {SdcTabsDirective} from "../directives/sdc-tabs/sdc-tabs-directive"; import {SdcSingleTabDirective, InnerSdcSingleTabDirective} from "../directives/sdc-tabs/sdc-single-tab/sdc-single-tab-directive"; import {ExpandCollapseListHeaderDirective} from "../directives/utils/expand-collapse-list-header/expand-collapse-list-header"; import {JsonExportExcelDirective} from "../directives/export-json-to-excel/export-json-to-excel"; -import {TopNavDirective} from "../directives/layout/top-nav/top-nav"; import {TopProgressDirective} from "../directives/layout/top-progress/top-progress"; import {CheckboxElementDirective} from "../directives/elements/checkbox/checkbox"; import {RadiobuttonElementDirective} from "../directives/elements/radiobutton/radiobutton"; @@ -105,7 +103,6 @@ directiveModule.directive('expandCollapseMenuBox', ExpandCollapseMenuBoxDirectiv directiveModule.directive('punchOut', PunchOutDirective.factory); directiveModule.directive('customValidation', CustomValidationDirective.factory); directiveModule.directive('ecompHeader', EcompHeaderDirective.factory); -directiveModule.directive('ecompFooter', EcompFooterDirective.factory); directiveModule.directive('editNamePopover', EditNamePopoverDirective.factory); directiveModule.directive('fieldsStructure', DataTypeFieldsStructureDirective.factory); directiveModule.directive('typeMap', TypeMapDirective.factory); @@ -122,7 +119,6 @@ directiveModule.directive('jsonExportExcel', JsonExportExcelDirective.factory); directiveModule.directive('expandCollapseListHeader', ExpandCollapseListHeaderDirective.factory); // // // Layouts -directiveModule.directive('topNav', TopNavDirective.factory); directiveModule.directive('topProgress', TopProgressDirective.factory); // // // Elements @@ -170,3 +166,18 @@ directiveModule.service('DeploymentGraphGeneralUtils', DeploymentGraphGeneralUti //Compoisiton right tab directives directiveModule.directive('capabilitiesList', CapabilitiesListDirective.factory); directiveModule.directive('requirementsList', RequirementsListDirective.factory); + + +// *** NG2 Components (downgraded) *** // +import {MenuListNg2Component} from "../ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component"; +import {TopNavComponent} from "../ng2/components/layout/top-nav/top-nav.component"; + +directiveModule.directive('menuListNg2', downgradeComponent({ + component: MenuListNg2Component, + inputs: ['props'] +}) as angular.IDirectiveFactory); +directiveModule.directive('topNav', downgradeComponent({ + component: TopNavComponent, + inputs: ['version', 'menuModel', 'topLvlSelectedIndex', 'hideSearch', 'searchTerm', 'notificationIconCallback'], + outputs: ['searchTermChange'] +}) as ng.IDirectiveFactory); diff --git a/catalog-ui/src/app/modules/service-module.ts b/catalog-ui/src/app/modules/service-module.ts index 99624ada45..b677a6d842 100644 --- a/catalog-ui/src/app/modules/service-module.ts +++ b/catalog-ui/src/app/modules/service-module.ts @@ -43,8 +43,14 @@ import {FileUtils} from "../utils/file-utils"; import {ValidationUtils} from "../utils/validation-utils"; import {AngularJSBridge} from "../services/angular-js-bridge-service"; import {LoaderService} from "../services/loader-service"; -import {UserResourceService} from "../services/user-resource-service"; import {CategoryResourceService} from "../services/category-resource-service"; +import {downgradeInjectable} from "@angular/upgrade/static"; +import {ModalService} from "../ng2/services/modal.service"; +import {ComponentServiceNg2} from "../ng2/services/component-services/component.service"; +import {ServiceServiceNg2} from "../ng2/services/component-services/service.service"; +import {ConnectionWizardService} from "../ng2/pages/connection-wizard/connection-wizard.service"; +import {ComponentInstanceServiceNg2} from "../ng2/services/component-instance-services/component-instance.service"; +import {UserService as UserServiceNg2} from "../ng2/services/user.service"; let moduleName:string = 'Sdc.Services'; let serviceModule:ng.IModule = angular.module(moduleName, []); @@ -80,5 +86,12 @@ serviceModule.service('ValidationUtils', ValidationUtils); serviceModule.service('AngularJSBridge',AngularJSBridge); serviceModule.service('LoaderService', LoaderService); -serviceModule.factory('Sdc.Services.UserResourceService', UserResourceService.getResource); serviceModule.factory('Sdc.Services.CategoryResourceService', CategoryResourceService.getResource); + +// Angular2 upgraded services - This is in order to use the service in angular1 till we finish remove all angular1 code +serviceModule.factory('ComponentServiceNg2', downgradeInjectable(ComponentServiceNg2)); +serviceModule.factory('ServiceServiceNg2', downgradeInjectable(ServiceServiceNg2)); +serviceModule.factory('ModalServiceNg2', downgradeInjectable(ModalService)); +serviceModule.factory('ConnectionWizardServiceNg2', downgradeInjectable(ConnectionWizardService)); +serviceModule.factory('ComponentInstanceServiceNg2', downgradeInjectable(ComponentInstanceServiceNg2)); +serviceModule.factory('UserServiceNg2', downgradeInjectable(UserServiceNg2));
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/app.module.ts b/catalog-ui/src/app/ng2/app.module.ts index 88c2d876c4..291768a500 100644 --- a/catalog-ui/src/app/ng2/app.module.ts +++ b/catalog-ui/src/app/ng2/app.module.ts @@ -27,7 +27,7 @@ import {UpgradeAdapter} from '@angular/upgrade'; import {UpgradeModule} from '@angular/upgrade/static'; import {PropertiesAssignmentModule} from './pages/properties-assignment/properties-assignment.module'; import { - DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, + DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, StateServiceFactory, StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider } from "./utils/ng1-upgraded-provider"; import {ConfigService} from "./services/config.service"; @@ -38,9 +38,14 @@ import {Cookie2Service} from "./services/cookie.service"; import {ComponentServiceNg2} from "./services/component-services/component.service"; import {ServiceServiceNg2} from "./services/component-services/service.service"; import {ComponentInstanceServiceNg2} from "./services/component-instance-services/component-instance.service"; -import { XHRBackend, RequestOptions } from '@angular/http'; -import { SearchBarComponent } from './shared/search-bar/search-bar.component'; -import { SearchWithAutoCompleteComponent } from './shared/search-with-autocomplete/search-with-autocomplete.component'; +import {ModalService} from "./services/modal.service"; +import {UiElementsModule} from "./components/ui/ui-elements.module"; +import {ConnectionWizardModule} from "./pages/connection-wizard/connection-wizard.module"; +import {LayoutModule} from "./components/layout/layout.module"; +import {UserService} from "./services/user.service"; +import {SdcConfig} from "./config/sdc-config.config"; +import { TranslateModule } from "./shared/translator/translate.module"; +import { TranslationServiceConfig } from "./config/translation.service.config"; export const upgradeAdapter = new UpgradeAdapter(forwardRef(() => AppModule)); @@ -51,23 +56,28 @@ export function configServiceFactory(config:ConfigService) { @NgModule({ declarations: [ - AppComponent, - SearchBarComponent, - SearchWithAutoCompleteComponent + AppComponent ], imports: [ BrowserModule, UpgradeModule, FormsModule, HttpModule, + LayoutModule, + TranslateModule, + UiElementsModule, + + //We need to import them here since we use them in angular1 + ConnectionWizardModule, PropertiesAssignmentModule ], exports: [], - entryComponents: [SearchWithAutoCompleteComponent], + entryComponents: [], providers: [ DataTypesServiceProvider, SharingServiceProvider, CookieServiceProvider, + StateServiceFactory, StateParamsServiceFactory, CacheServiceProvider, EventListenerServiceProvider, @@ -75,9 +85,13 @@ export function configServiceFactory(config:ConfigService) { Cookie2Service, ConfigService, ComponentServiceNg2, + ModalService, ServiceServiceNg2, HttpService, + UserService, + SdcConfig, ComponentInstanceServiceNg2, + TranslationServiceConfig, { provide: APP_INITIALIZER, useFactory: configServiceFactory, @@ -90,9 +104,8 @@ export function configServiceFactory(config:ConfigService) { export class AppModule { - // ngDoBootstrap() {} - constructor(public upgrade:UpgradeModule) { + constructor(public upgrade:UpgradeModule) { } } diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.html b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.html new file mode 100644 index 0000000000..37686342e8 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.html @@ -0,0 +1,7 @@ +<menu-list [open]="props?.open" [position]="props?.position" [styleClass]="props?.styleClass"> + <menu-item *ngFor="let item of props?.items" + [action]="item?.action" + [styleClass]="item?.styleClass"> + {{ item?.contents }} + </menu-item> +</menu-list> diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts new file mode 100644 index 0000000000..85d1899d96 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.component.ts @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { Component, Input } from '@angular/core'; + +declare var window:any; +@Component({ + selector: 'canvas-menu', + templateUrl: './menu-list-ng2.component.html' +}) +export class MenuListNg2Component { + @Input() props:any = { + items: [] + }; + + constructor() { + window.menu2 = this; + } +} diff --git a/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module.ts b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module.ts new file mode 100644 index 0000000000..957ba35c5a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/downgrade-wrappers/menu-list-ng2/menu-list-ng2.module.ts @@ -0,0 +1,23 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from '@angular/common'; +import { MenuListModule } from "../../ui/menu/menu-list.module"; +import { MenuListNg2Component } from "./menu-list-ng2.component"; + +export { + MenuListNg2Component +}; + +@NgModule({ + declarations: [ + MenuListNg2Component + ], + imports: [CommonModule, MenuListModule], + exports: [ + MenuListNg2Component + ], + entryComponents: [ //need to add anything that will be dynamically created + MenuListNg2Component +] +}) +export class MenuListNg2Module { +} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html deleted file mode 100644 index a3e28c5f0b..0000000000 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.html +++ /dev/null @@ -1 +0,0 @@ -<input #{{name}} [(ngModel)]="value" type="checkbox" (change)="onSave(value)" [ngClass]="{'disabled':readonly}"/> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.less b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.less deleted file mode 100644 index bed097fe5e..0000000000 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.less +++ /dev/null @@ -1,2 +0,0 @@ -/deep/ ui-element-checkbox { -} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html deleted file mode 100644 index bfb927af71..0000000000 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.html +++ /dev/null @@ -1,3 +0,0 @@ -<select name='{{name}}' [(ngModel)]="value" #t (change)="onSave()" [ngClass]="{'disabled':readonly}"> - <option *ngFor="let ddvalue of values" [value]="ddvalue.value">{{ddvalue.label}}</option> -</select> diff --git a/catalog-ui/src/app/ng2/components/layout/layout.module.ts b/catalog-ui/src/app/ng2/components/layout/layout.module.ts new file mode 100644 index 0000000000..827209326c --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/layout.module.ts @@ -0,0 +1,24 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { FormsModule } from "@angular/forms"; +import { TranslateModule } from "../../shared/translator/translate.module"; +import { TopNavComponent } from "./top-nav/top-nav.component"; + +@NgModule({ + declarations: [ + TopNavComponent + ], + imports: [ + CommonModule, + FormsModule, + TranslateModule + ], + exports: [], + entryComponents: [ //need to add anything that will be dynamically created + TopNavComponent + ], + providers: [] +}) +export class LayoutModule { + +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html new file mode 100644 index 0000000000..55c4bf0460 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.html @@ -0,0 +1,53 @@ +<nav class="top-nav"> + + <div class="asdc-app-title-wrapper"> + <a class="asdc-app-title">{{ 'PROJECT_TITLE'|translate }}</a> + <div class="asdc-version"> v.{{version}}</div> + </div> + + <ul class="top-menu" *ngIf="!menuModel && topLvlMenu"> + <!-- no hierarchy & dropdowns mode --> + <li *ngFor="let item of topLvlMenu.menuItems; let i = index" + [ngClass]="{'selected': i == topLvlMenu.selectedIndex}"> + <a (click)="menuItemClick(topLvlMenu, item)" + [attr.data-tests-id]="'main-menu-button-' + item.text.toLowerCase()">{{item.text}}</a> + </li> + </ul> + + <ul class="top-menu" *ngIf="menuModel"> + <!-- with hierarchy & dropdowns mode --> + <ng-container *ngFor="let groupItem of menuModel; let $index = index; let $last = last"> + <li [ngClass]="{'selected': $last }"> + <a (click)="menuItemClick(groupItem, groupItem.menuItems[groupItem.selectedIndex])" + [attr.data-tests-id]="'breadcrumbs-button-' + $index"> + {{groupItem.menuItems[groupItem.selectedIndex].text}} + </a> + </li> + <li class="triangle-dropdown" + [ngClass]="{'item-click': groupItem.itemClick}" (mouseover)="groupItem.itemClick = true"> + <div class="triangle"><span class="sprite-new arrow-right"></span></div> + <ul class="sub-menu"> + <li *ngFor="let ddItem of groupItem.menuItems; let $index2 = index" + (click)="menuItemClick(groupItem, ddItem)" + [ngClass]="{'selected': $index2 == groupItem.selectedIndex, 'disabled': ddItem.isDisabled}" + [attr.data-tests-id]="'sub-menu-button-' + ddItem.text.toLowerCase()"> + <span sdc-smart-tooltip="">{{ddItem.text}}</span> + </li> + </ul> + </li> + </ng-container> + </ul> + + <div class="top-search" [hidden]="hideSearch === true"> + <input type="text" + class="search-text" + placeholder="Search" + [ngModel]="searchTerm" + (ngModelChange)="emitSearchTerm($event)" + data-tests-id="main-menu-input-search" /> + <span class="w-sdc-search-icon magnification"></span> + </div> + + <div class="notification-icon" [ngClass]="{'disabled' : progress > 0}" *ngIf="user.role === 'DESIGNER' && notificationIconCallback" (click)="notificationIconCallback()" tooltip="Vendor Software Product Repository" tooltipPlacement="left" data-tests-id="repository-icon"></div> + +</nav> diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less new file mode 100644 index 0000000000..dc666cbf00 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.less @@ -0,0 +1,225 @@ +@import "../../../../../assets/styles/variables"; +@import "../../../../../assets/styles/variables-old"; +@import "../../../../../assets/styles/mixins_old"; +@import "../../../../../assets/styles/sprite"; + +.top-nav { + position: fixed; + top: @header_height; + background-color: @main_color_p; + .box-shadow(0px 1px 3px 0px rgba(0, 0, 0, 0.33)); + width: 100%; + height: @top_nav_height; + line-height: @top_nav_height; + z-index: 10; + display: flex; + flex-direction: row; + align-items: center; + + .asdc-app-title-wrapper { + flex-grow: 1; + line-height: 16px; + margin: 0 20px; + + a.asdc-app-title { + //.m_18_r; + text-decoration: none; + } + + .asdc-version { + //.m_12_r; + .opacity(0.8); + line-height: 14px; + flex-grow: 1; + } + + } + + ul.top-menu { + list-style-type: none; + margin: 0 0 0 20px; + padding: 0; + flex-grow: 999; + + & > li { + float: left; + cursor: pointer; + line-height: 50px; + height: 50px; + padding: 0 20px; + + &.selected { + border-bottom: solid 4px @main_color_a; + + a { + color: @func_color_s; + } + } + + /*&:hover { + border-bottom: solid 4px @main_color_a; + }*/ + + a { + font-family: @font-opensans-medium; + color: @main_color_m; + font-size: 16px; + display: block; + text-align: center; + text-decoration: none; + } + + &.triangle-dropdown { + padding: 0; + position: relative; + + div.triangle { + margin-top: 15px; + border-radius: 2px; + width: 17px; + height: 18px; + + //temp use - until new triangle gets in + line-height: 18px; + text-align: center; + font-size: 10px; + + &:hover { + background-color: rgba(156, 156, 156, 0.2); + + span { + .arrow-right-hover; + } + } + } + + + li a { + font-size: 16px; + } + + ul.sub-menu { + .perfect-scrollbar; + position: absolute; + left: 0; + top: 40px; + z-index: 1; + + overflow-x: hidden; + overflow-y: auto; + max-height: 0; + -webkit-transition: max-height 200ms ease-in; + -moz-transition: max-height 200ms ease-in; + -o-transition: max-height 200ms ease-in; + transition: max-height 200ms ease-in; + + padding: 0; + background-color: white; + visibility: hidden; + + li { + + height: 35px; + background-color: white; + font-size: 13px; + width: 150px; + line-height: 35px; + padding: 0 10px; + + &.disabled { + opacity: 1; + } + &.selected { + background-color: @tlv_color_v; + font-weight: bold; + } + &:hover { + color: @main_color_a; + } + span { + height: 35px; + width: 130px; + display: inline; + white-space: nowrap; + overflow: hidden; + } + } + } + &.item-click:hover ul.sub-menu, + &.item-click:active ul.sub-menu { + visibility: visible; + max-height: 500px; + border: 1px solid @func_color_b; + border-radius: 2px; + box-shadow: 0px 2px 2px 0px rgba(24, 24, 25, 0.1); + + div ul { + + } + } + } + } + + } + + .top-search { + position: relative; + flex-grow: 1; + padding: 0 20px; + + input.search-text { + .border-radius(2px); + width: 245px; + height: 32px; + line-height: 32px; + border: 1px solid @main_color_o; + outline: none; + text-indent: 10px; + + &::-webkit-input-placeholder { font-style: italic; } /* Safari, Chrome and Opera */ + &:-moz-placeholder { font-style: italic; } /* Firefox 18- */ + &::-moz-placeholder { font-style: italic; } /* Firefox 19+ */ + &:-ms-input-placeholder { font-style: italic; } /* IE 10+ */ + &:-ms-input-placeholder { font-style: italic; } /* Edge */ + /* font-style: italic; + }*/ + /* Firefox 18- */ + &::-moz-placeholder { + font-style: italic; + } + /* Firefox 19+ */ + &:-ms-input-placeholder { + font-style: italic; + } + /* IE 10+ */ + &:-ms-input-placeholder { + font-style: italic; + } + /* Edge */ + } + + .magnification { + position: absolute; + top: 19px; + right: 26px; + } + + } + + .notification-icon { + cursor: pointer; + flex-grow: 1; + margin: 0 10px 6px 0; + .sprite-new; + .vsp-list-icon; + + &:hover { + .vsp-list-icon-hover; + } + + &:active { + .vsp-list-icon-active; + } + + } + +} diff --git a/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts new file mode 100644 index 0000000000..f48aa4801f --- /dev/null +++ b/catalog-ui/src/app/ng2/components/layout/top-nav/top-nav.component.ts @@ -0,0 +1,149 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import {Component, Inject, Input, Output, EventEmitter} from "@angular/core"; +import {IHostedApplication, IUserProperties} from "app/models"; +import {MenuItemGroup, MenuItem} from "app/utils"; +import {UserService} from "../../../services/user.service"; +import {SdcConfigToken, ISdcConfig} from "../../../config/sdc-config.config"; +import {TranslateService} from "../../../shared/translator/translate.service"; + + +declare const window:any; +@Component({ + selector: 'top-nav', + templateUrl: './top-nav.component.html', + styleUrls:['./top-nav.component.less'] +}) +export class TopNavComponent { + @Input() public version:string; + @Input() public menuModel:Array<MenuItemGroup>; + @Input() public topLvlSelectedIndex:number; + @Input() public hideSearch:boolean; + @Input() public searchTerm:string; + @Input() public notificationIconCallback:Function; + @Output() public searchTermChange:EventEmitter<string> = new EventEmitter<string>(); + emitSearchTerm(event:string) { + this.searchTermChange.emit(event); + } + + public topLvlMenu:MenuItemGroup; + public user:IUserProperties; + + constructor(private translateService:TranslateService, + @Inject('$state') private $state:ng.ui.IStateService, + private userService:UserService, + @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { + window.nav = this; + } + + private _getTopLvlSelectedIndexByState = ():number => { + if (!this.topLvlMenu.menuItems) { + return 0; + } + + let result = -1; + + //set result to current state + this.topLvlMenu.menuItems.forEach((item:MenuItem, index:number)=> { + if (item.state === this.$state.current.name) { + result = index; + } + }); + + //if it's a different state , checking previous state param + if (result === -1) { + this.topLvlMenu.menuItems.forEach((item:MenuItem, index:number)=> { + if (item.state === this.$state.params['previousState']) { + result = index; + } + }); + } + + if (result === -1) { + result = 0; + } + + return result; + }; + + ngOnChanges(changes) { + if (changes['menuModel']) { + console.log('menuModel was changed!'); + this.generateMenu(); + } + } + + ngOnInit() { + console.log('Nav is init!', this.menuModel); + this.user = this.userService.getLoggedinUser(); + + this.translateService.languageChangedObservable.subscribe((lang) => { + let tmpArray: Array<MenuItem> = [ + new MenuItem(this.translateService.translate("TOP_MENU_HOME_BUTTON"), null, "dashboard", "goToState", null, null), + new MenuItem(this.translateService.translate("TOP_MENU_CATALOG_BUTTON"), null, "catalog", "goToState", null, null) + ]; + + // Only designer can perform onboarding + if (this.user && this.user.role === 'DESIGNER') { + tmpArray.push(new MenuItem(this.translateService.translate("TOP_MENU_ON_BOARD_BUTTON"), null, "onboardVendor", "goToState", null, null)); + _.each(this.sdcConfig.hostedApplications, (hostedApp: IHostedApplication) => { + if (hostedApp.exists) { + tmpArray.push(new MenuItem(hostedApp.navTitle, null, hostedApp.defaultState, "goToState", null, null)); + } + }); + } + + this.topLvlMenu = new MenuItemGroup(0, tmpArray, true); + this.topLvlMenu.selectedIndex = isNaN(this.topLvlSelectedIndex) ? this._getTopLvlSelectedIndexByState() : this.topLvlSelectedIndex; + + this.generateMenu(); + }); + } + + generateMenu() { + if (this.menuModel && this.topLvlMenu && this.menuModel[0] !== this.topLvlMenu) { + this.menuModel.unshift(this.topLvlMenu); + } + } + + goToState(state:string, params:Array<any>):Promise<boolean> { + return new Promise((resolve, reject) => { + this.$state.go(state, params && params.length > 0 ? [0] : undefined); + resolve(true); + }); + } + + menuItemClick(itemGroup:MenuItemGroup, item:MenuItem) { + itemGroup.itemClick = false; + + let onSuccess = ():void => { + itemGroup.selectedIndex = itemGroup.menuItems.indexOf(item); + }; + let onFailed = ():void => { + }; + + if (item.callback) { + (item.callback.apply(undefined, item.params)).then(onSuccess, onFailed); + } else { + this[item.action](item.state, item.params).then(onSuccess, onFailed); + } + } +} diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.html b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html index 4d2b91f3b4..ddda82ab58 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.html +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.html @@ -4,7 +4,7 @@ <div class="field"> <label>Resource Type</label> <div> - <checkbox [label]="'All'" [(checked)]="allSelected" (checkedChange)="selectAll()"></checkbox> + <checkbox [label]="'All'" [(checked)]="allSelected" (checkedChange)="selectAll()" data-tests-id="filter-checkbox-all"></checkbox> </div> <div *ngFor="let type of typesOptions"> <checkbox [label]="type" [(checked)]="selectedTypes[type]" (checkedChange)="onTypeSelected(type)"></checkbox> @@ -17,10 +17,11 @@ [(ngModel)]="filterData.propertyName" placeholder="Type here" required + data-tests-id="filter-box" /> </div> </form> </popover-content> <div class="open-filter-button" [popover]="filterPopover" [ngClass]="{'open':showPopover}" (onShown)="showPopover = true" (onHidden)="showPopover = false"> - <div class="sprite-new filter-icon"></div> + <div class="sprite-new filter-icon" data-tests-id="filter-button"></div> </div> diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.less index 07f38d3011..25c1467b3b 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.less +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.less @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/variables'; +@import '../../../../../assets/styles/variables'; form{ margin: 0 20px; .field{ diff --git a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.ts b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.ts index c43c30db21..5a9bfbcecb 100644 --- a/catalog-ui/src/app/ng2/components/filter-properties-assignment/filter-properties-assignment.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/filter-properties-assignment/filter-properties-assignment.component.ts @@ -23,8 +23,8 @@ */ import {Component, Input, Output, EventEmitter, ViewChild} from '@angular/core'; import {ButtonModel, ButtonsModelMap, FilterPropertiesAssignmentData} from "app/models"; -import {PopoverComponent} from "../popover/popover.component"; -import * as sdcConfig from "../../../../../configurations/dev" +import * as sdcConfig from "../../../../../../configurations/dev" +import {PopoverComponent} from "../../ui/popover/popover.component"; @Component({ selector: 'filter-properties-assignment', diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-display-options.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-display-options.ts index c8d4566653..c8d4566653 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-display-options.ts +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-display-options.ts diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.html b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.html index 40a1c37cee..c3f9e5ac74 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.html +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.html @@ -1,7 +1,7 @@ <div class="navigation-wrapper"> <div class="node-item" *ngFor="let item of displayData" (click)="onClick($event, item)"> <div class="node-data-wrapper" [ngClass]="{'selected': selectedItem && selectedItem === item[displayOptions.idProperty]}"> - <span class="node-data" [ngClass]="{'mark':item[displayOptions.valueProperty] === displayOptions.searchText}">{{item[displayOptions.valueProperty]}}</span> + <span class="node-data" [ngClass]="{'mark':item[displayOptions.valueProperty] === displayOptions.searchText}" [attr.data-tests-id]="item[displayOptions.valueProperty]">{{item[displayOptions.valueProperty]}}</span> </div> <div class="children-node" *ngIf="item[displayOptions.childrenProperty]"> <hierarchy-navigation class="children-hierarchy" [displayData]="item[displayOptions.childrenProperty]" diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.less b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.less index 4befa2c797..4befa2c797 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.less +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.less diff --git a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.ts b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts index dc0a02c277..dc0a02c277 100644 --- a/catalog-ui/src/app/ng2/components/hierarchy-navigtion/hierarchy-navigation.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/hierarchy-navigtion/hierarchy-navigation.component.ts diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html index 2b58d0f086..57e0474c66 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.html @@ -37,7 +37,7 @@ [readonly]="readonly"> </dynamic-element> <div class="delete-button-container"> - <span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)"></span> + <span *ngIf="input.instanceUniqueId && !readonly" class="sprite-new delete-btn" (click)="openDeleteModal(input)" data-tests-id="delete-input-button"></span> </div> </div> diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less index 89c7287449..0545874f53 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.less +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.less @@ -1,5 +1,5 @@ -@import './../../../../assets/styles/variables.less'; +@import './../../../../../assets/styles/variables.less'; :host /deep/ input { width:100%;} diff --git a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts index 736655f3f7..0add1cd707 100644 --- a/catalog-ui/src/app/ng2/components/inputs-table/inputs-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/inputs-table/inputs-table.component.ts @@ -21,16 +21,14 @@ /** * Created by rc2122 on 5/4/2017. */ -import {Component, Input, Output, EventEmitter, ViewChild} from "@angular/core"; +import {Component, Input, Output, EventEmitter} from "@angular/core"; import {InputFEModel} from "app/models"; -import { ModalService } from 'app/ng2/services/modal.service'; - - +import {ModalService} from "../../../services/modal.service"; @Component({ selector: 'inputs-table', templateUrl: './inputs-table.component.html', - styleUrls: ['../inputs-table/inputs-table.component.less'] + styleUrls: ['../inputs-table/inputs-table.component.less'], }) export class InputsTableComponent { diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html index 3ffc9c16be..14b6c7d4c0 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.html @@ -1,11 +1,11 @@ <div *ngIf="!property.hidden" class="dynamic-property-row nested-level-{{nestedLevel}}" [@fadeIn] - [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName }" + [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.propertiesName, 'readonly': property.isDisabled ||property.isDeclared}" [class.with-top-border]="property.isChildOfListOrMap" (click)="onClickPropertyRow(property, $event)"> <!-- 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 *ngIf="hasDeclareOption" [(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 --> @@ -47,7 +47,8 @@ <ng-container *ngFor="let prop of property.flattenedChildren | filterChildProperties: expandedChildId; trackBy:prop?.propertiesName"> <dynamic-property [selectedPropertyId]="selectedPropertyId" - [canBeDeclared]="prop.canBeDeclared" + [hasDeclareOption]="hasDeclareOption" + [canBeDeclared]="hasDeclareOption && prop.canBeDeclared" [property]="prop" [expandedChildId]="expandedChildId" [propertyNameSearchText]="propertyNameSearchText" diff --git a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less index 48d3d035d0..0adce2c99d 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.less +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.less @@ -1,4 +1,4 @@ -@import '../../../../../assets/styles/variables.less'; +@import '../../../../../../assets/styles/variables.less'; .flat-children-container { .dynamic-property-row { /*create nested left border classes for up to 10 levels of nesting*/ @@ -25,6 +25,15 @@ flex-direction:row; align-items: stretch; + &.readonly{ + background-color: @tlv_color_t; + cursor: auto; + } + //for the case that the parent is disabled but the child is enabled + &:not(.readonly){ + background-color: @main_color_p; + } + .table-cell { flex: 1; padding:9px; @@ -72,3 +81,4 @@ 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/logic/properties-table/dynamic-property/dynamic-property.component.ts index 9cf043098b..04cb26d030 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/dynamic-property/dynamic-property.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/dynamic-property/dynamic-property.component.ts @@ -19,11 +19,11 @@ */ import {Component, Input, Output, EventEmitter} from "@angular/core"; -import { PropertyBEModel, PropertyFEModel, DerivedFEProperty, DerivedPropertyType, SchemaPropertyGroupModel, DataTypeModel } from "app/models"; -import { PROPERTY_DATA, PROPERTY_TYPES } from 'app/utils'; -import { PropertiesUtils } from "app/ng2/pages/properties-assignment/properties.utils"; -import { DataTypeService } from "../../../services/data-type.service"; +import { PropertyFEModel, DerivedFEProperty, DerivedPropertyType } from "app/models"; +import { PROPERTY_TYPES } from 'app/utils'; +import { DataTypeService } from "../../../../services/data-type.service"; import { trigger, state, style, transition, animate } from '@angular/core'; +import {PropertiesUtils} from "../../../../pages/properties-assignment/services/properties.utils"; @Component({ @@ -47,6 +47,7 @@ export class DynamicPropertyComponent { @Input() propertyNameSearchText: string; @Input() readonly: boolean; @Input() hasChildren: boolean; + @Input() hasDeclareOption:boolean; @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() expandChild: EventEmitter<string> = new EventEmitter<string>(); diff --git a/catalog-ui/src/app/ng2/pipes/filterChildProperties.pipe.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/pipes/filterChildProperties.pipe.ts index 4520469594..4520469594 100644 --- a/catalog-ui/src/app/ng2/pipes/filterChildProperties.pipe.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/pipes/filterChildProperties.pipe.ts diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html index a9dc499e7d..933b80f577 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.html +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.html @@ -2,38 +2,38 @@ <loader [display]="isLoading" [size]="'large'" [relative]="true" [loaderDelay]="500"></loader> <div class="table-header"> <div class="table-cell col1">Property Name</div> - <div class="table-cell col2">Type</div> - <div class="table-cell col3">ES</div> + <div class="table-cell col2" *ngIf="!hidePropertyType">Type</div> + <div class="table-cell col3" *ngIf="!hidePropertyType">ES</div> <div class="table-cell valueCol">Value</div> </div> - <div class="table-body"> + <div class="table-body" [ngClass]="{'view-mode': readonly}"> <div class="no-data" *ngIf="!fePropertiesMap || !(fePropertiesMap | keys).length">No data to display</div> <ng-container *ngFor="let instanceId of fePropertiesMap | keys; trackBy:instanceId"> - <div class="table-rows-header white-sub-header">{{feInstanceNamesMap[instanceId]}}</div> + <div class="table-rows-header white-sub-header" *ngIf="feInstanceNamesMap">{{feInstanceNamesMap[instanceId]}}</div> <div class="table-row" *ngFor="let property of fePropertiesMap[instanceId] | searchFilter:'name':searchTerm; trackBy:property?.name" (click)="onClickPropertyRow(property, instanceId, $event)" - [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name }"> + [ngClass]="{'selected': selectedPropertyId && selectedPropertyId === property.name, 'readonly': property.isDisabled || property.isDeclared}"> <div class="table-cell col1" [ngClass]="{'filtered':property.name === propertyNameSearchText}" [class.round-checkbox]="property.isDeclared"> <div class="property-name"> - <checkbox [(checked)]="property.isSelected" + <checkbox *ngIf="hasDeclareOption" [(checked)]="property.isSelected" [disabled]="property.isDisabled || property.isDeclared || readonly" - (checkedChange)="propertyChecked(property)"></checkbox> + (checkedChange)="propertyChecked(property)" [attr.data-tests-id]="property.name"></checkbox> <div class="inner-cell-div" tooltip="{{property.name}}"> <span>{{property.name}}</span> </div> </div> <span *ngIf="property.description" class="property-description-icon sprite-new show-desc" tooltip="{{property.description}}" tooltipDelay="0"></span> </div> - <div class="table-cell col2"> + <div class="table-cell col2" *ngIf="!hidePropertyType"> <div class="inner-cell-div" tooltip="{{property.type | contentAfterLastDot}}"> <span>{{property.type | contentAfterLastDot}}</span> </div> </div> - <div class="table-cell col3"> + <div class="table-cell col3" *ngIf="!hidePropertyType"> <div *ngIf="property.schema && property.schema.property && property.schema.property.type" class="inner-cell-div" tooltip="{{property.schema.property.type | contentAfterLastDot}}"> <span>{{property.schema.property.type | contentAfterLastDot}}</span> </div> @@ -42,7 +42,8 @@ <!-- [ngClass]="{'filtered':property.name === propertyNameSearchText}" (selectProperty)="propertySelected(property, $event, flatProperty.propertiesName)" [propType]="property.type" [propSchema]="property.schema" [propKey]="" [propValue]="property.value"--> <dynamic-property [selectedPropertyId]="selectedPropertyId" - [canBeDeclared]="true" + [hasDeclareOption]="hasDeclareOption" + [canBeDeclared]="hasDeclareOption && true" [property]="property" [expandedChildId]="property.expandedChildPropertyId" [propertyNameSearchText]="propertyNameSearchText" @@ -56,7 +57,6 @@ </div> </div> - </ng-container> </div> diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less index 9ede84faff..20da0b6ec2 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.less +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.less @@ -1,5 +1,5 @@ -@import './../../../../assets/styles/variables.less'; -@import '../../../../assets/styles/sprite'; +@import './../../../../../assets/styles/variables.less'; +@import '../../../../../assets/styles/sprite'; @smaller-screen: ~"only screen and (max-width: 1580px)"; :host /deep/ input { width:100%;} @@ -43,6 +43,7 @@ flex-direction: column; overflow-y:auto; flex: 1; + background-color: @main_color_p; .no-data { border: #d2d2d2 solid 1px; @@ -55,13 +56,25 @@ background-color: #e6f6fb; color: #009fdb; } + &.view-mode{ + /deep/ .dynamic-property-row:not(.selected){ + background-color:#f8f8f8; + } + } .table-row { display: flex; flex-direction:row; flex: 0 0 auto; + &.readonly{ + background-color: #f8f8f8; + cursor: auto; + } &:hover:not(.selected){ background-color:#f8f8f8; cursor:pointer; + /deep/ .dynamic-property-row:not(.selected){ + background-color:#f8f8f8; cursor:pointer; + } } .selected-row { @@ -100,7 +113,8 @@ .property-name { flex: 1; display: flex; - max-width: 90%; + overflow: hidden; + //max-width: 90%; fix bug 327139 } .property-description-icon { diff --git a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts index afb7189348..32bbb1b3a0 100644 --- a/catalog-ui/src/app/ng2/components/properties-table/properties-table.component.ts +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/properties-table.component.ts @@ -18,11 +18,9 @@ * ============LICENSE_END========================================================= */ -import { Component, Input, Output, EventEmitter, SimpleChanges, ViewChild, ElementRef } from "@angular/core"; -import {PropertyFEModel, DerivedFEProperty, DerivedPropertyType, InstanceFePropertiesMap} from "app/models"; -import {PropertiesService} from "../../services/properties.service"; -import { DynamicElementComponent } from 'app/ng2/components/dynamic-element/dynamic-element.component'; -import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; +import { Component, Input, Output, EventEmitter} from "@angular/core"; +import {PropertyFEModel, DerivedFEProperty, InstanceFePropertiesMap} from "app/models"; +import {PropertiesService} from "../../../services/properties.service"; @Component({ selector: 'properties-table', @@ -34,24 +32,25 @@ export class PropertiesTableComponent { @Input() fePropertiesMap: InstanceFePropertiesMap; @Input() feInstanceNamesMap: Map<string, string>; @Input() selectedPropertyId: string; - @Input() displayDeleteButton: boolean; @Input() propertyNameSearchText:string; @Input() searchTerm:string; @Input() readonly:boolean; @Input() isLoading:boolean; + @Input() hasDeclareOption:boolean; + @Input() hidePropertyType:boolean; @Output() valueChanged: EventEmitter<any> = new EventEmitter<any>(); @Output() selectPropertyRow: EventEmitter<PropertyRowSelectedEvent> = new EventEmitter<PropertyRowSelectedEvent>(); - @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>(); - //@Output() selectInstanceRow: EventEmitter<string> = new EventEmitter<string>(); + @Output() updateCheckedPropertyCount: EventEmitter<boolean> = new EventEmitter<boolean>();//only for hasDeclareOption - - constructor ( private propertiesService:PropertiesService ){ + constructor (private propertiesService:PropertiesService ){ + } + + ngOnInit() { } - propValueChanged = (property) => { - !property.isDeclared && this.valueChanged.emit(property); + this.valueChanged.emit(property); }; // Click on main row (row of propertyFEModel) diff --git a/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts new file mode 100644 index 0000000000..91f33485a9 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/properties-table/property-table.module.ts @@ -0,0 +1,29 @@ +import {NgModule} from "@angular/core"; +import {PropertiesTableComponent} from "./properties-table.component"; +import {DynamicPropertyComponent} from "./dynamic-property/dynamic-property.component"; +import {FormsModule} from "@angular/forms"; +import {UiElementsModule} from "../../ui/ui-elements.module"; +import {CommonModule} from "@angular/common"; +import {HttpModule} from "@angular/http"; +import {FilterChildPropertiesPipe} from "./pipes/filterChildProperties.pipe"; +import {GlobalPipesModule} from "../../../pipes/global-pipes.module"; +import {PropertiesService} from "../../../services/properties.service"; + +@NgModule({ + imports: [ + FormsModule, + HttpModule, + CommonModule, + GlobalPipesModule, + UiElementsModule + ], + declarations: [ + FilterChildPropertiesPipe, + DynamicPropertyComponent, + PropertiesTableComponent + ], + exports: [PropertiesTableComponent], + providers: [FilterChildPropertiesPipe, PropertiesService] +}) +export class PropertyTableModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-reqiurement-or-capability.component.less b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-reqiurement-or-capability.component.less new file mode 100644 index 0000000000..edcb87db3d --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-reqiurement-or-capability.component.less @@ -0,0 +1,77 @@ +@import './../../../../../assets/styles/variables.less'; +@import './../../../../../assets/styles/mixins.less'; +.main-container{ + color: @main_color_m; +} +.select-req-or-cap-span { + float: left; + margin-right: 15px; + font-size: 13px; +} +.select-type-label{ + .m_12_m; + margin-bottom: 2px; +} +.select-type{ + display: flex; + margin-bottom: 10px; + ui-element-dropdown{ + width: 40%; + font-size: 13px; + /deep/ select{ + height: 31px; + } + } +} +.table-and-list-container{ + display: flex; + padding-top: 10px; + .inner-container{ + height: 300px; + overflow-y: auto; + border: @main_color_o solid 1px; + } + .inner-container:not(:last-of-type){ + border-right: none; + } + .requirements-or-capabilities-container { + width: 40%; + &.empty-list{ + background-color: @tlv_color_t; + text-align: center; + &:before{ + content: 'Select "type" above'; + line-height: 298px; + } + } + .req-or-cap-item{ + border-bottom: @main_color_o solid 1px; + padding: 10px; + font-size: 13px; + &:hover:not(.selected){ + background-color:@tlv_color_t; cursor:pointer; + } + } + } + .properties-table-container{ + width: 60%; + display: flex; + &.cap-selected{ + background-color: @tlv_color_t; + border: @main_color_a solid 1px; + -webkit-box-shadow: inset 8px -2px 7px -9px rgba(84,84,84,1); + -moz-box-shadow: inset 8px -2px 7px -9px rgba(84,84,84,1); + box-shadow: inset 8px -2px 7px -9px rgba(84,84,84,1); + } + properties-table{ + margin: 15px; + width: 100%; + } + } +} + +.selected{ + color: @main_color_a; + background-color: @tlv_color_v; + border-left: @main_color_a solid 4px; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.html b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.html new file mode 100644 index 0000000000..bcd33efc30 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.html @@ -0,0 +1,36 @@ +<div class="main-container"> + <span class="select-req-or-cap-span">Select:</span><radio-buttons + [(value)]="selectedReqOrCapOption" + [options]="selectOptions" + [readonly]="disabledSelectReqOrCapOption" + [direction]="'horizontal'" + (valueChange)="onSelectRequirementOrCapability($event)"> + +</radio-buttons> + <label class="select-type-label">Select type:</label> + <div class="select-type"> + <ui-element-dropdown [values]="types" [(value)]="selectedType" (valueChange)="onTypeSelected($event)"></ui-element-dropdown> + </div> + + <div class="table-and-list-container"> + <div class="inner-container requirements-or-capabilities-container" [ngClass]="{'empty-list':!selectedType}"> + <div *ngFor="let item of displayCapReqListFilterByType" + class="req-or-cap-item" + (click)="selectReqOrCapFromList(item)" + [ngClass]="{'selected':selectedReqOrCapModel && (item.uniqueId + item.ownerId + item.name) == (selectedReqOrCapModel.uniqueId + selectedReqOrCapModel.ownerId + selectedReqOrCapModel.name)}"> + {{item.getFullTitle()}} + </div> + </div> + <div class="inner-container properties-table-container" *ngIf="selectedReqOrCapOption == 'Capability'" [ngClass]="{'cap-selected':selectedReqOrCapModel}"> + <properties-table *ngIf="selectedReqOrCapModel" + class="properties-table" + [readonly]="true" + [fePropertiesMap]="capabilityProperties" + [selectedPropertyId]="''" + [hidePropertyType]="true"> + </properties-table> + </div> + + </div> +</div> + diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts new file mode 100644 index 0000000000..ab67dc1850 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.component.ts @@ -0,0 +1,182 @@ +/** + * Created by rc2122 on 9/4/2017. + */ +import {Component, EventEmitter, Input, OnInit, Output, SimpleChanges} from '@angular/core'; +import {RadioButtonModel, Match, PropertyModel, InstanceFePropertiesMap, Component as ComponentModel} from "app/models"; +import {Dictionary} from "lodash"; +import {DropdownValue} from "../../ui/form-components/dropdown/ui-element-dropdown.component"; +import {ComponentInstanceServiceNg2} from "../../../services/component-instance-services/component-instance.service"; +import {PropertiesUtils} from "app/ng2/pages/properties-assignment/services/properties.utils"; +import {Requirement} from "../../../../models/requirement"; +import {Capability, RequirementCapabilityModel} from "../../../../models/capability"; + +const REQUIREMENT = 'Requirement'; +const CAPABILITY = 'Capability'; + +@Component({ + selector: 'select-requirement-or-capability', + templateUrl: './select-requirement-or-capability.component.html', + styleUrls: ['./select-reqiurement-or-capability.component.less'] +}) + +export class SelectRequirementOrCapabilityComponent implements OnInit { + + + @Input() optionalRequirementsMap:Dictionary<Requirement[]>; //optional requirement map - key is type, value is array of requirements + @Input() optionalCapabilitiesMap:Dictionary<Capability[]>; //optional capabilities map - key is type, value is array of capabilities + + @Input() selectedReqOrCapOption:string; // the selection value chosen by the user (options: requirement / capability ) + + @Input() currentComponent:ComponentModel; + @Input() componentInstanceId:string; + + @Input() selectedReqOrCapModel:RequirementCapabilityModel; + + @Output() updateSelectedReqOrCap:EventEmitter<RequirementCapabilityModel> = new EventEmitter<RequirementCapabilityModel>(); + @Output() updateCapabilityProperties:EventEmitter<Array<PropertyModel>> = new EventEmitter<Array<PropertyModel>>(); + + types:Array<string> = []; + selectedType:string; + + selectOptions:Array<RadioButtonModel>; + + requirementsTypes:Array<string> = []; + capabilitiesTypes:Array<string> = []; + + disabledSelectReqOrCapOption: boolean; // If we need to disable the option to choose requirement or capability + displayCapReqListFilterByType:RequirementCapabilityModel[]; + + capabilityProperties:InstanceFePropertiesMap; + + constructor(private componentInstanceServiceNg2:ComponentInstanceServiceNg2, + private propertiesUtils:PropertiesUtils) { + this.selectOptions = [new RadioButtonModel(REQUIREMENT, REQUIREMENT), new RadioButtonModel(CAPABILITY, CAPABILITY)]; + } + + private initDefaultReqOrCapSelection = (): void => { + if(this.selectedReqOrCapOption){//for second step + this.disabledSelectReqOrCapOption = true; + } + if (this.selectedReqOrCapModel) {//init when there is selected req or cap + if (this.selectedReqOrCapModel instanceof Capability) { + this.selectedReqOrCapOption = this.selectOptions[1].value; + this.selectedType = this.selectedReqOrCapModel.type; + } else { + this.selectedReqOrCapOption = this.selectOptions[0].value; + this.selectedType = (<Requirement>this.selectedReqOrCapModel).capability; + } + } + if(Object.keys(this.optionalCapabilitiesMap).length === 0) { // If instance don't have capabilities + this.disabledSelectReqOrCapOption = true; + this.selectedReqOrCapOption = this.selectOptions[0].value; + } else if(Object.keys(this.optionalRequirementsMap).length === 0) { // If instance don't have requirements + this.disabledSelectReqOrCapOption = true; + this.selectedReqOrCapOption = this.selectOptions[1].value; + } + this.selectedReqOrCapOption = this.selectedReqOrCapOption || this.selectOptions[1].value; + this.types = this.selectedReqOrCapOption == this.selectOptions[0].value ? this.requirementsTypes : this.capabilitiesTypes; + setTimeout(() => { + if (this.selectedType) { + this.initCapReqListFilterByType(); + } else { + this.setDefaultValueType(); + } + }); + } + + initCapabilityPropertiesTable = ():void => { + if(this.selectedReqOrCapModel instanceof Capability ) { + let selectedCapability = <Capability>this.selectedReqOrCapModel; + if(selectedCapability.properties){ + this.capabilityProperties = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({ CAPABILITY : selectedCapability.properties}, false); + } + } + } + + ngOnChanges(changes:SimpleChanges) { + if (changes.selectedReqOrCapModel) { + if (this.selectedReqOrCapModel && this.selectedReqOrCapOption === CAPABILITY) { + this.setCapabilityProperties(); + } + } + } + + ngOnInit() { + this.initTypesList(); + this.initDefaultReqOrCapSelection(); + this.initCapabilityPropertiesTable(); + } + + private initTypesList = ():void => { + this.requirementsTypes = _.keys(this.optionalRequirementsMap); + this.requirementsTypes.unshift('All'); + this.capabilitiesTypes = _.keys(this.optionalCapabilitiesMap); + this.capabilitiesTypes.unshift('All'); + } + + private fillInDisplayCapReqListFilterByType = (allOptionalTypesMap:Dictionary<RequirementCapabilityModel[]>):void => { + if(this.selectedType === 'All'){ + this.displayCapReqListFilterByType = []; + _.map(allOptionalTypesMap,(reqOrCapArray:RequirementCapabilityModel[])=>{ + this.displayCapReqListFilterByType = this.displayCapReqListFilterByType.concat(reqOrCapArray); + }) + }else{ + this.displayCapReqListFilterByType = allOptionalTypesMap[this.selectedType]; + } + + // automatically select a *single* requirement or capability: + if (this.displayCapReqListFilterByType.length === 1) { + const selectedReqCap:RequirementCapabilityModel = this.displayCapReqListFilterByType[0]; + this.selectReqOrCapFromList((this.selectedType === CAPABILITY) ? <Capability>selectedReqCap : <Requirement>selectedReqCap); + } + } + + private initCapReqListFilterByType = ():void => { + if (this.selectedReqOrCapOption === CAPABILITY) { + this.fillInDisplayCapReqListFilterByType(this.optionalCapabilitiesMap); + } else { + this.fillInDisplayCapReqListFilterByType(this.optionalRequirementsMap); + } + } + + private onTypeSelected = ():void => { + this.initCapReqListFilterByType(); + if (this.displayCapReqListFilterByType.indexOf(this.selectedReqOrCapModel) === -1) { + this.selectReqOrCapFromList(null); + } + } + + private setDefaultValueType = ():void =>{ + // automatically select a *single* type from the list: + this.selectedType = (this.types.length === 2) ? this.types[1] : this.types[0]; + this.initCapReqListFilterByType(); + } + + private onSelectRequirementOrCapability = ():void => { + this.types = this.selectedReqOrCapOption === REQUIREMENT ? this.requirementsTypes : this.capabilitiesTypes; + this.selectReqOrCapFromList(null); + this.setDefaultValueType(); + } + + private selectReqOrCapFromList = (selected:Requirement|Capability):void => { + if (this.selectedReqOrCapModel !== selected) { + this.selectedReqOrCapModel = selected; + this.updateSelectedReqOrCap.emit(selected); + } + } + + + private setCapabilityProperties = ():void => { + let selectedCapability = <Capability>this.selectedReqOrCapModel; + if (selectedCapability.properties === undefined) { + this.componentInstanceServiceNg2.getInstanceCapabilityProperties(this.currentComponent, this.componentInstanceId, selectedCapability.type, selectedCapability.name) + .subscribe((response:Array<PropertyModel>) => { + this.capabilityProperties = (response && response.length) ? this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({CAPABILITY : response}, false) : null; + this.updateCapabilityProperties.emit(response); + }, error => {}); + }else{ + this.capabilityProperties = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({CAPABILITY : selectedCapability.properties}, false); + this.updateCapabilityProperties.emit(selectedCapability.properties); + } + } +} diff --git a/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.module.ts b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.module.ts new file mode 100644 index 0000000000..cb12dea02a --- /dev/null +++ b/catalog-ui/src/app/ng2/components/logic/select-requirement-or-capability/select-requirement-or-capability.module.ts @@ -0,0 +1,24 @@ +import {NgModule} from "@angular/core"; +import {SelectRequirementOrCapabilityComponent} from "./select-requirement-or-capability.component"; +import {FormsModule} from "@angular/forms"; +import {FormElementsModule} from "../../ui/form-components/form-elements.module"; +import {CommonModule} from "@angular/common"; +import {GlobalPipesModule} from "app/ng2/pipes/global-pipes.module"; +import {PropertyTableModule} from "../properties-table/property-table.module"; + +@NgModule({ + declarations: [ + SelectRequirementOrCapabilityComponent + ], + imports: [ + CommonModule, + FormsModule, + FormElementsModule, + GlobalPipesModule, + PropertyTableModule], + + exports: [SelectRequirementOrCapabilityComponent], + providers: [] +}) +export class SelectRequirementOrCapabilityModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.less b/catalog-ui/src/app/ng2/components/modal/modal.component.less deleted file mode 100644 index c87162afb0..0000000000 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.less +++ /dev/null @@ -1,128 +0,0 @@ -@import '../../../../assets/styles/variables'; -@import '../../../../assets/styles/mixins'; -@import '../../../../assets/styles/sprite-old'; -/deep/ modal { - display: none; - - .custom-modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1000; - overflow: auto; - margin: auto; - display: flex; - align-items: center; - - .ng2-modal-content { - background: #fff; - width: 100%; - box-shadow: 0 5px 15px rgba(0,0,0,.5); - border-radius: 4px; - .ng2-modal-body{ - padding: 20px; - } - - .ng2-modal-header{ - .m_18_m; - font-weight: bold; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - height: 50px; - line-height: 50px; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - text-align: left; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - margin: 0px 20px; - - &.modal-type-standard { - border-bottom: solid 3px @main_color_a; - } - - &.modal-type-error { - border-bottom: solid 3px @func_color_q; - } - - &.modal-type-alert{ - border-bottom: solid 3px @main_color_h; - } - - .title{ - .s_18_m; - -webkit-box-flex: 999; - -ms-flex-positive: 999; - flex-grow: 999; - } - .close-button{ - .sprite; - .sprite.x-btn-black; - cursor: pointer; - } - } - - .ng2-modal-footer{ - background-color: @tlv_color_t; - padding: 17px 30px; - clear: both; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - flex-grow: 1; - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: end; - -ms-flex-pack: end; - justify-content: flex-end; - border-radius: 4px; - button{ - margin: 0 12px 0 6px; - } - } - } - } - - .modal-background { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - background-color: #000; - opacity: 0.5; - z-index: 900; - } -} - -.xl { - width: 1200px; -} - -.l { - width: 875px; -} - -.md { - width: 650px; -} - -.sm { - width: 552px; -} - -.xsm { - width: 432px; -} - -body.modal-open { - overflow: hidden; -} diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.less b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less index e219d49aa4..e219d49aa4 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.less +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts index 246258e44f..53d1590b1c 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.component.ts @@ -18,13 +18,13 @@ * ============LICENSE_END========================================================= */ -import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactory, ComponentFactoryResolver } from '@angular/core' -import { UiElementCheckBoxComponent } from './elements-ui/checkbox/ui-element-checkbox.component'; -import { UiElementDropDownComponent, DropdownValue } from './elements-ui/dropdown/ui-element-dropdown.component'; -import { UiElementInputComponent } from './elements-ui/input/ui-element-input.component'; -import {UiElementPopoverInputComponent} from "./elements-ui/popover-input/ui-element-popover-input.component"; +import { Component, Compiler, EventEmitter, ViewContainerRef, ViewChild, Input, Output, ElementRef, ComponentRef, ComponentFactoryResolver } from '@angular/core' import {ValidationConfiguration} from "app/models"; -import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-element-integer-input.component"; +import {UiElementInputComponent} from "../form-components/input/ui-element-input.component"; +import {UiElementPopoverInputComponent} from "../form-components/popover-input/ui-element-popover-input.component"; +import {UiElementIntegerInputComponent} from "../form-components/integer-input/ui-element-integer-input.component"; +import {UiElementDropDownComponent, DropdownValue} from "../form-components/dropdown/ui-element-dropdown.component"; +import {PROPERTY_DATA} from "../../../../utils/constants"; @Component({ selector: 'dynamic-element', @@ -33,7 +33,6 @@ import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-ele entryComponents: [ UiElementInputComponent, UiElementDropDownComponent, - UiElementCheckBoxComponent, UiElementPopoverInputComponent, UiElementIntegerInputComponent ] @@ -72,33 +71,30 @@ export class DynamicElementComponent { } // Factory to create component based on type or peroperty name. - switch(this.type) { - case 'list': - case 'integer': + switch(true) { + case this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1: + if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name + let pathArray = this.path.split("#"); + this.name = pathArray[pathArray.length - 2]; + } + this.createComponent(UiElementPopoverInputComponent); + break; + case this.type == 'integer': this.createComponent(UiElementIntegerInputComponent); this.cmpRef.instance.pattern = this.validation.validationPatterns.integer; break; - case 'string': - if (this.path && this.path.toUpperCase().indexOf("SUBNETPOOLID") !== -1) { - if(this.name.toUpperCase().indexOf("SUBNETPOOLID") == -1){//if it's an item of subnetpoolid list get the parent name - let pathArray = this.path.split("#"); - this.name = pathArray[pathArray.length - 2]; - } - this.createComponent(UiElementPopoverInputComponent); - } - else { - this.createComponent(UiElementInputComponent); - } + case PROPERTY_DATA.SCALAR_TYPES.indexOf(this.type) > -1: + case this.type == 'string': + this.createComponent(UiElementInputComponent); break; - case 'boolean': - //this.createComponent(UiElementCheckBoxComponent); + case this.type == 'boolean': this.createComponent(UiElementDropDownComponent); // Build drop down values let tmp = []; - tmp.push(new DropdownValue('true','TRUE')); - tmp.push(new DropdownValue('false','FALSE')); + tmp.push(new DropdownValue(true,'TRUE')); + tmp.push(new DropdownValue(false,'FALSE')); this.cmpRef.instance.values = tmp; break; default: @@ -131,7 +127,6 @@ export class DynamicElementComponent { } ngAfterContentInit() { - //console.log("DynamicElementComponent: ngAfterContentInit: type: " + this.type + " value: " + this.value); this.isViewInitialized = true; this.updateComponent(); } diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts index b57020a1d0..50b22505a9 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/dynamic-element.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/dynamic-element/dynamic-element.module.ts @@ -19,32 +19,19 @@ */ import { NgModule } from "@angular/core"; -import { UiElementCheckBoxComponent } from './elements-ui/checkbox/ui-element-checkbox.component'; -import { UiElementDropDownComponent } from './elements-ui/dropdown/ui-element-dropdown.component'; -import { UiElementInputComponent } from './elements-ui/input/ui-element-input.component'; -import { DynamicElementComponent } from "app/ng2/components/dynamic-element/dynamic-element.component"; -import { BrowserModule } from '@angular/platform-browser' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { UiElementPopoverInputComponent } from "./elements-ui/popover-input/ui-element-popover-input.component"; import {PopoverModule} from "../popover/popover.module"; import {TooltipModule} from "../tooltip/tooltip.module"; -import {UiElementIntegerInputComponent} from "./elements-ui/integer-input/ui-element-integer-input.component"; +import {DynamicElementComponent} from "./dynamic-element.component"; +import {FormElementsModule} from "../form-components/form-elements.module"; @NgModule({ declarations: [ DynamicElementComponent, - UiElementInputComponent, - UiElementCheckBoxComponent, - UiElementDropDownComponent, - UiElementPopoverInputComponent, - UiElementIntegerInputComponent ], imports: [ - BrowserModule, - FormsModule, PopoverModule, - ReactiveFormsModule, - TooltipModule + TooltipModule, + FormElementsModule ], exports: [ DynamicElementComponent diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html index 872bf90329..872bf90329 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.html diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less index 3a28c5fb42..9df2680b6f 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.less @@ -1,5 +1,5 @@ - @import '../../../../assets/styles/tlv-sprite'; -@import '../../../../assets/styles/sprite'; + @import '../../../../../../assets/styles/tlv-sprite'; +@import '../../../../../../assets/styles/sprite'; .checkbox-container { diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts index c8da016174..c8da016174 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.component.ts diff --git a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts index 4ac7f2d7cd..4ac7f2d7cd 100644 --- a/catalog-ui/src/app/ng2/shared/checkbox/checkbox.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/checkbox/checkbox.module.ts diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html new file mode 100644 index 0000000000..c6b8384183 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.html @@ -0,0 +1,3 @@ +<select name='{{name}}' [(ngModel)]="value" (change)="onSave()" [ngClass]="{'disabled':readonly}" data-tests-id="SelectType"> + <option *ngFor="let ddvalue of values" [ngValue]="ddvalue.label != undefined ? ddvalue.value : ddvalue">{{ddvalue.label||ddvalue}}</option> +</select> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less index ea3e35140e..ea3e35140e 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts index 970c61531f..5abf32c61b 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/dropdown/ui-element-dropdown.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/dropdown/ui-element-dropdown.component.ts @@ -18,15 +18,14 @@ * ============LICENSE_END========================================================= */ -import { Component, EventEmitter, Output, Input } from '@angular/core' -import { BrowserModule } from '@angular/platform-browser' +import {Component, EventEmitter, Output, Input} from '@angular/core' import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component'; export class DropdownValue { - value:string; + value:any; label:string; - constructor(value:string,label:string) { + constructor(value:any,label:string) { this.value = value; this.label = label; } @@ -37,16 +36,16 @@ export class DropdownValue { templateUrl: './ui-element-dropdown.component.html', styleUrls: ['./ui-element-dropdown.component.less'], }) -export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface { +export class UiElementDropDownComponent extends UiElementBase implements UiElementBaseInterface { @Input() - values: DropdownValue[]; + values: DropdownValue[]|string[]; constructor() { super(); } onSave() { - this.baseEmitter.emit(JSON.parse(this.value)); + this.baseEmitter.emit(this.value); } } diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts new file mode 100644 index 0000000000..e5bdf1f557 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/form-elements.module.ts @@ -0,0 +1,42 @@ +/** + * Created by rc2122 on 9/5/2017. + */ +import {NgModule} from "@angular/core"; +import {BrowserModule} from "@angular/platform-browser"; +import {FormsModule, ReactiveFormsModule} from "@angular/forms"; +import {UiElementPopoverInputComponent} from "./popover-input/ui-element-popover-input.component"; +import {UiElementIntegerInputComponent} from "./integer-input/ui-element-integer-input.component"; +import {UiElementInputComponent} from "./input/ui-element-input.component"; +import {UiElementDropDownComponent} from "./dropdown/ui-element-dropdown.component"; +import {UiElementBase} from "./ui-element-base.component"; +import {CheckboxModule} from "./checkbox/checkbox.module"; +import {RadioButtonComponent} from "./radio-buttons/radio-buttons.component"; +import {PopoverModule} from "../popover/popover.module"; +import {TooltipModule} from "../tooltip/tooltip.module"; + + +@NgModule({ + imports: [ + BrowserModule, + FormsModule, + PopoverModule, + ReactiveFormsModule, + TooltipModule, + CheckboxModule], + + declarations: [UiElementDropDownComponent, + UiElementInputComponent, + UiElementIntegerInputComponent, + UiElementPopoverInputComponent, + UiElementBase, + RadioButtonComponent], + + exports: [UiElementDropDownComponent, + UiElementInputComponent, + UiElementIntegerInputComponent, + UiElementPopoverInputComponent, + RadioButtonComponent, + TooltipModule, + CheckboxModule] +}) +export class FormElementsModule { }
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html index 814ebfd28b..b7d7c859c7 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.html @@ -1,6 +1,6 @@ <input class="value-input" - [ngClass]="{'error': control.invalid}" + [ngClass]="{'error': control.invalid, 'disabled':readonly}" type="text" [name]="name" [(ngModel)]="value" @@ -11,5 +11,4 @@ [formControl]="control" tooltip="{{value}}" [readonly]="readonly" - [ngClass]="{'disabled':readonly}" /> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less index d320c7ff8b..d320c7ff8b 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts index fb3b3db859..fb3b3db859 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/input/ui-element-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/input/ui-element-input.component.ts diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html index e5518d453f..9fbc9e1094 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.html @@ -1,6 +1,6 @@ <input class="value-input" - [ngClass]="{'error': control.invalid}" + [ngClass]="{'error': control.invalid, 'disabled':readonly}" type="text" [name]="name" [(ngModel)]="value" @@ -11,5 +11,4 @@ [formControl]="control" tooltip="{{value}}" [readonly]="readonly" - [ngClass]="{'disabled':readonly}" /> diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.less index 8073c3858e..8073c3858e 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts index 3339b605ca..1667f4393d 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/integer-input/ui-element-integer-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/integer-input/ui-element-integer-input.component.ts @@ -30,7 +30,7 @@ import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.comp export class UiElementIntegerInputComponent extends UiElementBase implements UiElementBaseInterface { constructor() { super(); - this.pattern = this.validation.validationPatterns.comment; + //this.pattern = this.validation.validationPatterns.comment; } onSave() { diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.html index 3bd51b4e36..3bd51b4e36 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.html +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.html diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.less index 5be443f7b6..5be443f7b6 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.less +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.less diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts index 67eb8822b4..61688df3f0 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/popover-input/ui-element-popover-input.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/popover-input/ui-element-popover-input.component.ts @@ -19,10 +19,9 @@ */ import {Component, ViewChild, ElementRef, Input} from '@angular/core'; -import {UiElementBase, UiElementBaseInterface} from "../ui-element-base.component"; import {ButtonsModelMap, ButtonModel} from "app/models"; -import { PopoverContentComponent } from "app/ng2/components/popover/popover-content.component" -import { PopoverComponent } from "app/ng2/components/popover/popover.component" +import {PopoverContentComponent} from "../../popover/popover-content.component"; +import {UiElementBase, UiElementBaseInterface} from "../ui-element-base.component"; @Component({ selector: 'ui-element-popover-input', diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less new file mode 100644 index 0000000000..b929486b10 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-button.component.less @@ -0,0 +1,42 @@ +@import './../../../../../../assets/styles/variables.less'; +.radio-buttons-container{ + display: flex; + &.vertical{ + flex-direction: column; + } + &.horizontal{ + flex-direction: row; + } +} +.radio-button { + margin: 0 10px 10px 0; + display: flex; +} + +input[type=radio] { + width:0; + height:0; + display:none; + &[disabled] ~ .radio-button { + + } +} + +.shown-radio-button{ + border: @main_color_n solid 1px; + height: 14px; + width: 14px; + border-radius: 50%; + padding: 1px; + margin: auto 5px; + .selected{ + background-color: @main_color_a; + height: 100%; + width: 100%; + border-radius: 50%; + } +} +span{ + margin: auto 0; + color: @func_color_s; +} diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html new file mode 100644 index 0000000000..6c927301db --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.html @@ -0,0 +1,8 @@ +<div class="radio-buttons-container {{direction}}"> + <div *ngFor="let option of options" class="radio-button" [ngClass]="{'disabled':readonly}"> + <input type="radio" [(ngModel)]="value" name="{{fieldName}}" value="{{option.value}}" [disabled]="readonly"/> + <div class="shown-radio-button" (click)="!readonly && select(option.value)"><div *ngIf="value==option.value" class="selected"></div></div> + <span>{{option.key}}</span> + </div> +</div> + diff --git a/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts new file mode 100644 index 0000000000..0f80e2ad44 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/form-components/radio-buttons/radio-buttons.component.ts @@ -0,0 +1,29 @@ +/** + * Created by rc2122 on 9/4/2017. + */ +import { Component, Input, Output, EventEmitter, ViewEncapsulation } from '@angular/core'; +import { RadioButtonModel } from 'app/models' +import {UiElementBaseInterface, UiElementBase} from "../ui-element-base.component"; + +@Component({ + selector: 'radio-buttons', + templateUrl: './radio-buttons.component.html', + styleUrls: ['./radio-button.component.less'] +}) +export class RadioButtonComponent extends UiElementBase implements UiElementBaseInterface { + + onSave() { + this.baseEmitter.emit(this.value); + } + + @Input() options:Array<RadioButtonModel>; + @Input() readonly:boolean; + @Input() direction:string = 'vertical'; //get 'horizontal' | 'vertical' + value:any; + + select(value:any) { + this.value = value; + this.baseEmitter.emit(this.value); + } +} + diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts index 4bc35e814a..ae2013ff70 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/ui-element-base.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/form-components/ui-element-base.component.ts @@ -41,11 +41,11 @@ export class UiElementBase { this.value = value; } - protected name: string; - protected type: string; - protected value: any; - protected pattern: any; - protected readonly:boolean; + @Input() name: string; + @Input() type: string; + @Input() value: any; + @Input() pattern: any; + @Input() readonly:boolean; constructor() { //this.control = new FormControl('', [Validators.required]); diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.html b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html index a62aa114d9..a62aa114d9 100644 --- a/catalog-ui/src/app/ng2/components/loader/loader.component.html +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.html diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.less b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less index ddb9915176..006c3bfa43 100644 --- a/catalog-ui/src/app/ng2/components/loader/loader.component.less +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.less @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/variables'; +@import '../../../../../assets/styles/variables'; .tlv-loader-back { background-color: @main_color_p; position: fixed; diff --git a/catalog-ui/src/app/ng2/components/loader/loader.component.ts b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts index f66aa551e2..f66aa551e2 100644 --- a/catalog-ui/src/app/ng2/components/loader/loader.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/loader/loader.component.ts diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html new file mode 100644 index 0000000000..54640c9414 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.html @@ -0,0 +1,3 @@ +<div class="w-sdc-menu-item" [ngClass]="styleClass" (click)="performAction()"> + <ng-content></ng-content> +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less new file mode 100644 index 0000000000..ceb4409144 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.less @@ -0,0 +1,13 @@ +@import "../../../../../assets/styles/variables"; + +.w-sdc-menu-item { + font-size: 14px; + line-height: 14px; + color: @main_color_m; + padding: 3px 6px; + + &:hover { + cursor: pointer; + background-color: @main_color_c; + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts index f73afd42c7..8b2006634e 100644 --- a/catalog-ui/src/app/ng2/components/dynamic-element/elements-ui/checkbox/ui-element-checkbox.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-item.component.ts @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,30 +18,27 @@ * ============LICENSE_END========================================================= */ -import { Component, ViewChild, ElementRef, ContentChildren, Input } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser' -import { UiElementBase, UiElementBaseInterface } from './../ui-element-base.component'; +import { Component, Input, Output, EventEmitter } from '@angular/core'; @Component({ - selector: 'ui-element-checkbox', - templateUrl: './ui-element-checkbox.component.html', - styleUrls: ['./ui-element-checkbox.component.less'], + selector: 'menu-item', + templateUrl: './menu-item.component.html', + styleUrls:['./menu-item.component.less'] }) -export class UiElementCheckBoxComponent extends UiElementBase implements UiElementBaseInterface { +export class MenuItemComponent { + @Input() action:Function; + @Input() styleClass:any; - constructor() { - super(); - } + public parentMenu:any; - ngAfterContentInit() { - // Convert the value to boolean (instanceOf does not work, the type is undefined). - if (this.value==='true' || this.value==='false') { - this.value = this.value==='true'?true:false; + constructor() { } - } - onSave() { - this.baseEmitter.emit(this.value); - } + performAction() { + this.action(); + if (this.parentMenu && typeof(this.parentMenu.close) === 'function') { + this.parentMenu.close(); + } + } } diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html new file mode 100644 index 0000000000..98c4d26fdd --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.html @@ -0,0 +1,9 @@ +<div + class="w-sdc-menu-list" + *ngIf="isOpen" + [ngClass]="styleClass" + [ngStyle]="{'left': position?.x || 0, 'top': position?.y || 0}"> + + <ng-content></ng-content> + +</div> diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less new file mode 100644 index 0000000000..1b45ea775c --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.less @@ -0,0 +1,13 @@ +.w-sdc-menu-list { + position: fixed; + z-index: 100; + + border-style: solid; + border-width: 1px; + border-color: #d8d8d8; + box-sizing: border-box; + background-color: #ffffff; + box-shadow: 0px 2px 2px 0px rgba(24, 24, 25, 0.1); + width: 91px; + padding: 6px 0; +} diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts new file mode 100644 index 0000000000..290c8d06af --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.component.ts @@ -0,0 +1,70 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { Component, Input, ContentChildren, SimpleChanges, QueryList } from '@angular/core'; +import { MenuItemComponent } from "./menu-item.component"; +import { Point } from "app/models"; + +@Component({ + selector: 'menu-list', + templateUrl: './menu-list.component.html', + styleUrls:['./menu-list.component.less'] +}) +export class MenuListComponent { + @Input('open') inputOpen:boolean = false; + @Input('position') inputPosition:Point = new Point(); + @Input() styleClass:any; + + @ContentChildren(MenuItemComponent) menuItems:QueryList<MenuItemComponent>; + + private position:Point; + private isOpen:boolean = false; + + constructor() { + } + + ngOnChanges(changes:SimpleChanges) { + if (changes.inputOpen) { + (changes.inputOpen.currentValue) ? this.open() : this.close(); + } + if (changes.inputPosition) { + this.changePosition(changes.inputPosition.currentValue); + } + } + + ngAfterContentInit() { + this.menuItems.forEach((c) => c.parentMenu = this); + this.menuItems.changes.subscribe((list) => { + list.forEach((c) => c.parentMenu = this); + }); + } + + open(): void { + this.isOpen = true; + } + + close(): void { + this.isOpen = false; + } + + changePosition(position:Point) { + this.position = position; + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts new file mode 100644 index 0000000000..fdbbf59f48 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/menu/menu-list.module.ts @@ -0,0 +1,27 @@ +import { NgModule } from "@angular/core"; +import { CommonModule } from '@angular/common'; +import { MenuListComponent } from "./menu-list.component"; +import { MenuItemComponent } from "./menu-item.component"; + +export { + MenuListComponent, + MenuItemComponent +}; + +@NgModule({ + declarations: [ + MenuListComponent, + MenuItemComponent + ], + imports: [CommonModule], + exports: [ + MenuListComponent, + MenuItemComponent + ], + entryComponents: [ //need to add anything that will be dynamically created + MenuListComponent, + MenuItemComponent + ] +}) +export class MenuListModule { +} diff --git a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.html b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html index 433bd4fd6f..433bd4fd6f 100644 --- a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.html +++ b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.html diff --git a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts index c0d6673412..c0d6673412 100644 --- a/catalog-ui/src/app/ng2/components/modal/error-message/error-message.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/error-message/error-message.component.ts diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.html b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html index d843867cdb..9a0fdf6bf4 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.html +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.html @@ -13,6 +13,7 @@ <button *ngFor="let button of input.buttons" class="tlv-btn {{button.cssClass}}" [disabled] = "button.getDisabled && button.getDisabled()" + [attr.data-tests-id] = "button.text" (click) = "button.callback()">{{button.text}}</button> </div> </div> diff --git a/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less new file mode 100644 index 0000000000..fac1ae74a8 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.less @@ -0,0 +1,129 @@ +@import '../../../../../assets/styles/variables'; +@import '../../../../../assets/styles/mixins'; +@import '../../../../../assets/styles/sprite-old'; +/deep/ modal { + display: none; +} + +.custom-modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 15007; + overflow: auto; + margin: auto; + display: flex; + align-items: center; + + .ng2-modal-content { + background: #fff; + width: 100%; + box-shadow: 0 5px 15px rgba(0,0,0,.5); + border-radius: 4px; + .ng2-modal-body{ + padding: 20px; + } + + .ng2-modal-header{ + .m_18_r; + font-weight: bold; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + height: 50px; + line-height: 50px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + text-align: left; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + margin: 0px 20px; + + &.modal-type-standard { + border-bottom: solid 3px @main_color_a; + } + + &.modal-type-error { + border-bottom: solid 3px @func_color_q; + } + + &.modal-type-alert{ + border-bottom: solid 3px @main_color_h; + } + + .title{ + .s_18_r; + -webkit-box-flex: 999; + -ms-flex-positive: 999; + flex-grow: 999; + } + .close-button{ + .sprite; + .sprite.x-btn-black; + cursor: pointer; + } + } + + .ng2-modal-footer{ + background-color: @tlv_color_t; + padding: 17px 30px; + clear: both; + -webkit-box-flex: 1; + -ms-flex-positive: 1; + flex-grow: 1; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + border-radius: 4px; + button{ + margin: 0 12px 0 6px; + } + } + } +} + +.modal-background { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: #000; + opacity: 0.5; + z-index: 900; +} + + +.xl { + width: 1200px; +} + +.l { + width: 875px; +} + +.md { + width: 650px; +} + +.sm { + width: 552px; +} + +.xsm { + width: 432px; +} + +body.modal-open { + overflow: hidden; +} diff --git a/catalog-ui/src/app/ng2/components/modal/modal.component.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts index 89db8d1140..89db8d1140 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.component.ts diff --git a/catalog-ui/src/app/ng2/components/modal/modal.module.ts b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts index 892f6993dd..c38e60194b 100644 --- a/catalog-ui/src/app/ng2/components/modal/modal.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/modal/modal.module.ts @@ -1,8 +1,8 @@ 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"; import { ErrorMessageComponent } from "./error-message/error-message.component"; +import {ModalComponent} from "./modal.component"; @NgModule({ declarations: [ @@ -10,7 +10,7 @@ import { ErrorMessageComponent } from "./error-message/error-message.component"; ErrorMessageComponent ], imports: [CommonModule], - exports: [], + exports: [ModalComponent, ErrorMessageComponent], entryComponents: [ //need to add anything that will be dynamically created ModalComponent, ErrorMessageComponent diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts new file mode 100644 index 0000000000..0c1669ec4b --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component.ts @@ -0,0 +1,10 @@ +/** + * Created by rc2122 on 9/27/2017. + */ +import {Component, Input} from "@angular/core"; +@Component({ +}) +export class WizardHeaderBaseComponent { + + @Input() currentStepIndex:number; +} diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html new file mode 100644 index 0000000000..9884b233ac --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.html @@ -0,0 +1,57 @@ +<div class="custom-modal {{input.size}}"> + <div class="ng2-modal-content w-sdc-classic-top-line-modal"> + <div class="ng2-modal-header modal-type-{{input.type}}"> + <span class="title">{{ input.title }}</span> + <span class="close-button" (click)="close()"></span> + </div> + <div class="ng2-modal-body" > + <div class="multi-steps-wizard-component"> + <header> + <div class="steps-header"> + <div *ngFor="let step of steps; let i = index" class="step-title" [ngClass]="{'active':i == currentStepIndex}"> + <div class="title-text">{{step.title}}</div> + <div class="line"> + <div class="inner-line" [@displayLineAnimation]="i <= currentStepIndex && i!=0" [hidden]="!i || i > currentStepIndex"></div> + </div> + <div class="circle" [ngClass]="{'full-circle': i < currentStepIndex}"></div> + </div> + </div> + <div class="dynamic-header-container"> + <div #dynamicHeaderContainer></div> + </div> + </header> + <div #dynamicContentContainer></div> + </div> + </div> + + <div class="ng2-modal-footer"> + <button *ngFor="let button of input.buttons" + class="tlv-btn {{button.cssClass}}" + [disabled] = "button.getDisabled && button.getDisabled()" + (click) = "button.callback()">{{button.text}}</button> + <div class="navigation-buttons"> + <button (click)="prevStep()" + class="navigation-button tlv-btn outline blue" + [disabled]="dynamicContent.instance.preventBack()"> + <div class="navigation-icon sprite-new blue-arrow-back"></div> + Back + </button> + <button (click)="nextStep()" + *ngIf="currentStepIndex < (steps.length - 1)" + [disabled]="dynamicContent.instance.preventNext()" + class="navigation-button tlv-btn blue"> + Next + <div class="navigation-icon sprite-new white-arrow-next"></div> + </button> + <button (click)="callback();modalService.closeCurrentModal();" + *ngIf="currentStepIndex == (steps.length - 1)" + [disabled]="dynamicContent.instance.preventNext()" + class="tlv-btn blue"> + Finish + </button> + </div> + + </div> + </div> +</div> +<div class="modal-background"></div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less new file mode 100644 index 0000000000..3a2168aeb0 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.less @@ -0,0 +1,90 @@ +@import './../../../../../assets/styles/variables.less'; + +@circle_size: 13px; + +.custom-modal{ + font-family: @font-opensans-regular; +} + +/deep/ multi-steps-wizard { + display: none; +} + +.ng2-modal-header{ + border: none !important; +} + +.ng2-modal-body{ + padding-top: 0 !important; +} + +header{ + margin-bottom: 10px; + .dynamic-header-container{ + position: relative; + top: -9px; + } + .steps-header{ + display: flex; + .step-title{ + flex: 1; + .title-text{ + width: 100%; + text-align: center; + line-height: 40px; + background-color: @tlv_color_u; + font-size: 13px; + } + .line{ + width: calc(~'100% - @{circle_size}'); + position: relative; + left: calc(~'(100% - @{circle_size})/2 * (-1)'); + float: left; + height: 2px; + .inner-line{ + background-color: @main_color_a; + height: 100%; + } + } + .circle{ + margin:0 auto; + border: @main_color_o solid 1px; + height: @circle_size; + width: @circle_size; + border-radius: 50%; + position: relative; + top: -@circle_size/2; + background-color: @main_color_p; + z-index: 1; + } + .full-circle{ + border-color: @main_color_a; + background-color: @main_color_a; + } + &.active{ + color: @main_color_a; + font-family: @font-opensans-medium; + .circle{ + border-color: @main_color_a; + } + } + } + } +} + +.navigation-buttons{ + padding-left: 6px; + border-left: 1px solid @main_color_a; + .navigation-button{ + padding: 0 8px; + .navigation-icon{ + margin: 3px 0; + &.blue-arrow-back{ + float: left; + } + &.white-arrow-next{ + float: right; + } + } + } +} diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts new file mode 100644 index 0000000000..9219a30738 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.component.ts @@ -0,0 +1,78 @@ +/** + * Created by rc2122 on 8/15/2017. + */ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +import { + Component, ElementRef, forwardRef, Inject, Input, trigger, state, style, + transition, animate, ViewChild, ViewContainerRef, ComponentRef +} from "@angular/core"; +import {StepModel} from "app/models"; +import {ModalService} from "../../../services/modal.service"; +import {ModalComponent} from "../modal/modal.component"; +import {WizardHeaderBaseComponent} from "./multi-steps-wizard-header-base.component"; + + +@Component({ + selector: 'multi-steps-wizard', + templateUrl: './multi-steps-wizard.component.html', + styleUrls: ['./../modal/modal.component.less','./multi-steps-wizard.component.less'], + animations: [ + trigger('displayLineAnimation', [ + state('true', style({ + width: '100%', + })), + state('false', style({ + width:'0px', + })), + transition('* => *', animate('500ms')), + ]), + ], +}) +export class MultiStepsWizardComponent extends ModalComponent { + + @Input() steps:Array<StepModel>; + @Input() callback: Function; + @Input() data:any; + @Input() dynamicHeader: ComponentRef<WizardHeaderBaseComponent>; + + @ViewChild('dynamicHeaderContainer', { read: ViewContainerRef }) dynamicHeaderContainer: ViewContainerRef; + constructor(@Inject(forwardRef(() => ModalService)) public modalService: ModalService, el: ElementRef ) { + super(el); + } + + private currentStepIndex:number = 0; + + nextStep = ():void => { + if(this.currentStepIndex + 1 < this.steps.length){ + this.currentStepIndex++; + this.modalService.addDynamicContentToModal(this.modalService.currentModal, this.steps[this.currentStepIndex].component); + this.dynamicHeader.instance.currentStepIndex = this.currentStepIndex; + } + } + + prevStep = ():void => { + if(this.currentStepIndex > 0){ + this.currentStepIndex--; + this.modalService.addDynamicContentToModal(this.modalService.currentModal, this.steps[this.currentStepIndex].component); + this.dynamicHeader.instance.currentStepIndex = this.currentStepIndex; + } + } +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts new file mode 100644 index 0000000000..3db217d282 --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard.module.ts @@ -0,0 +1,22 @@ +/** + * Created by rc2122 on 8/15/2017. + */ +import { NgModule } from "@angular/core"; +import {MultiStepsWizardComponent} from "./multi-steps-wizard.component"; +import {CommonModule} from "@angular/common"; +import {ConnectionWizardModule} from "../../../pages/connection-wizard/connection-wizard.module"; + +@NgModule({ + declarations: [ + MultiStepsWizardComponent + ], + imports: [CommonModule + ], + exports: [], + entryComponents: [ + MultiStepsWizardComponent + ], + providers: [] +}) +export class MultiStepsWizardModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar-routes.config.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts index ac58cbd063..ac58cbd063 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar-routes.config.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar-routes.config.ts diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.html b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html index d783be4c27..d783be4c27 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.html +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.html diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.less b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less index 3e5165b798..3e5165b798 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.less +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.less diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts index 68a26c4780..68a26c4780 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.component.ts diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.metadata.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts index 71cc3cb59f..71cc3cb59f 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.metadata.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.metadata.ts diff --git a/catalog-ui/src/app/ng2/shared/navbar/navbar.module.ts b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts index 4a754dfe99..4a754dfe99 100644 --- a/catalog-ui/src/app/ng2/shared/navbar/navbar.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/navbar/navbar.module.ts diff --git a/catalog-ui/src/app/ng2/components/popover/popover-content.component.html b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html index 6d76f0ad06..6d76f0ad06 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover-content.component.html +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.html diff --git a/catalog-ui/src/app/ng2/components/popover/popover-content.component.less b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less index 04cdd3914b..fbdec0b16b 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover-content.component.less +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.less @@ -1,6 +1,6 @@ -@import '../../../../assets/styles/variables'; -@import '../../../../assets/styles/mixins'; -@import '../../../../assets/styles/sprite-old'; +@import '../../../../../assets/styles/variables'; +@import '../../../../../assets/styles/mixins'; +@import '../../../../../assets/styles/sprite-old'; .popover .virtual-area { height: 11px; width: 100%; diff --git a/catalog-ui/src/app/ng2/components/popover/popover-content.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts index 6eb36287d0..6eb36287d0 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover-content.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover-content.component.ts diff --git a/catalog-ui/src/app/ng2/components/popover/popover.component.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts index e976bc7bf2..e976bc7bf2 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover.component.ts diff --git a/catalog-ui/src/app/ng2/components/popover/popover.module.ts b/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts index a9605c17b6..d8cacc1696 100644 --- a/catalog-ui/src/app/ng2/components/popover/popover.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/popover/popover.module.ts @@ -32,8 +32,6 @@ import {PopoverContentComponent} from "./popover-content.component"; PopoverContentComponent ], imports: [ - // PopoverComponent, - // PopoverContentComponent CommonModule ], exports: [ diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html index 36629594b0..36629594b0 100644 --- a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.html +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.html diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less index cfeb8d3b01..751fceec35 100644 --- a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.less +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.less @@ -30,8 +30,7 @@ } .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: url('../../../../../assets/styles/images/sprites/sprite-global.png') no-repeat -206px -1275px; background-color: rgba(234, 234, 234, 0.88); width: 30px; height: 30px; diff --git a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts index 08bdf2030f..08bdf2030f 100644 --- a/catalog-ui/src/app/ng2/shared/search-bar/search-bar.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/search-bar/search-bar.component.ts diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html index c9769ba5ae..c9769ba5ae 100644 --- a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.html +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.html diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less index 92b054cd85..f1830846d3 100644 --- a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.less +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.less @@ -1,5 +1,4 @@ - -.search-with-autocomplete-container{ +.search-with-autocomplete-container{ &.autocomplete-visible { .search-bar-input { diff --git a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts index ced056d1fc..ced056d1fc 100644 --- a/catalog-ui/src/app/ng2/shared/search-with-autocomplete/search-with-autocomplete.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/search-with-autocomplete/search-with-autocomplete.component.ts diff --git a/catalog-ui/src/app/ng2/shared/tabs/tab/tab.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts index bad7b80a51..bad7b80a51 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tab/tab.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tab/tab.component.ts diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.html b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html index 3e263a3862..57cf5d46c9 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.html +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.html @@ -1,5 +1,5 @@ <div class="tabs {{tabStyle}}"> - <div class="tab" *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active"> + <div class="tab" *ngFor="let tab of tabs" (click)="selectTab(tab)" [class.active]="tab.active" [attr.data-tests-id]="tab.title"> {{tab.title}} <div class="tab-indication" *ngIf="tab.indication" [@indicatorAnimation]="tab.indication">{{tab.indication}}</div> </div> diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.less b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less index 6f9e57aaf2..f7b18b1cc8 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.less +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.less @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/variables'; +@import '../../../../../assets/styles/variables'; tab { height: 100%; @@ -20,6 +20,7 @@ tab { flex: 1; width:100%; overflow-y:hidden; + overflow-x:hidden; } .tab-content { diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts index 21d2bbad43..21d2bbad43 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.component.ts diff --git a/catalog-ui/src/app/ng2/shared/tabs/tabs.module.ts b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts index 6bf19d4099..1300c41a90 100644 --- a/catalog-ui/src/app/ng2/shared/tabs/tabs.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/tabs/tabs.module.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import { Component, NgModule } from '@angular/core' +import { NgModule } from '@angular/core' import { BrowserModule } from '@angular/platform-browser' import { Tabs } from './tabs.component'; diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.html b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html index 1fbf45e39f..1fbf45e39f 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.html +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.html diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.less b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less index 1ff496f840..1ff496f840 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.less +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.less diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts index 4dcb64c499..4dcb64c499 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip-content.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip-content.component.ts diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip.component.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts index 79d35c6e0e..79d35c6e0e 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip.component.ts +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.component.ts diff --git a/catalog-ui/src/app/ng2/components/tooltip/tooltip.module.ts b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts index 84a3987081..24478cd716 100644 --- a/catalog-ui/src/app/ng2/components/tooltip/tooltip.module.ts +++ b/catalog-ui/src/app/ng2/components/ui/tooltip/tooltip.module.ts @@ -29,7 +29,6 @@ import {CommonModule} from "@angular/common"; TooltipContentComponent, ], imports: [ - CommonModule ], exports: [ TooltipComponent, diff --git a/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts new file mode 100644 index 0000000000..526096524c --- /dev/null +++ b/catalog-ui/src/app/ng2/components/ui/ui-elements.module.ts @@ -0,0 +1,80 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { NgModule } from '@angular/core'; +import { NavbarModule } from "./navbar/navbar.module"; +import {DynamicElementModule} from "./dynamic-element/dynamic-element.module"; +import {FormElementsModule} from "./form-components/form-elements.module"; +import {LoaderComponent} from "./loader/loader.component"; +import {ModalModule} from "./modal/modal.module"; +import {PopoverModule} from "./popover/popover.module"; +import {SearchBarComponent} from "./search-bar/search-bar.component"; +import {SearchWithAutoCompleteComponent} from "./search-with-autocomplete/search-with-autocomplete.component"; +import {TabModule} from "./tabs/tabs.module"; +import {TooltipModule} from "./tooltip/tooltip.module"; +import {CommonModule} from "@angular/common"; +import {FormsModule} from "@angular/forms"; +import {BrowserModule} from "@angular/platform-browser"; +import {MultiStepsWizardModule} from "./multi-steps-wizard/multi-steps-wizard.module"; +import {MenuListModule} from "./menu/menu-list.module"; +import {MenuListNg2Module} from "../downgrade-wrappers/menu-list-ng2/menu-list-ng2.module"; + +@NgModule({ + declarations: [ + LoaderComponent, + SearchBarComponent, + SearchWithAutoCompleteComponent + ], + + imports: [ + BrowserModule, + FormsModule, + CommonModule, + DynamicElementModule, + NavbarModule, + FormElementsModule, + ModalModule, + PopoverModule, + TabModule, + TooltipModule, + MultiStepsWizardModule, + MenuListModule, + MenuListNg2Module + ], + exports: [ + LoaderComponent, + MultiStepsWizardModule, + SearchBarComponent, + SearchWithAutoCompleteComponent, + DynamicElementModule, + NavbarModule, + FormElementsModule, + ModalModule, + PopoverModule, + TabModule, + TooltipModule, + MenuListModule, + MenuListNg2Module + ], + + entryComponents: [SearchWithAutoCompleteComponent] +}) + +export class UiElementsModule {} diff --git a/catalog-ui/src/app/ng2/config/sdc-config.config.factory.ts b/catalog-ui/src/app/ng2/config/sdc-config.config.factory.ts new file mode 100644 index 0000000000..b0fa17d3b6 --- /dev/null +++ b/catalog-ui/src/app/ng2/config/sdc-config.config.factory.ts @@ -0,0 +1,17 @@ +declare const __ENV__:string; + +export interface ISdcConfig { + [index:string]: any +} + +export function getSdcConfig() : ISdcConfig { + let sdcConfig:ISdcConfig = {}; + + if (__ENV__==='prod') { + sdcConfig = require('./../../../../configurations/prod.js'); + } else { + sdcConfig = require('./../../../../configurations/dev.js'); + } + + return sdcConfig; +} diff --git a/catalog-ui/src/app/ng2/config/sdc-config.config.ts b/catalog-ui/src/app/ng2/config/sdc-config.config.ts new file mode 100644 index 0000000000..197cc8b14b --- /dev/null +++ b/catalog-ui/src/app/ng2/config/sdc-config.config.ts @@ -0,0 +1,11 @@ +import {Provider, OpaqueToken} from "@angular/core"; +import {getSdcConfig, ISdcConfig} from "./sdc-config.config.factory"; + +export { ISdcConfig }; + +export const SdcConfigToken = new OpaqueToken('SdcConfigToken'); + +export const SdcConfig:Provider = { + provide: SdcConfigToken, + useFactory: getSdcConfig +}; diff --git a/catalog-ui/src/app/ng2/config/translation.service.config.factory.ts b/catalog-ui/src/app/ng2/config/translation.service.config.factory.ts new file mode 100644 index 0000000000..c435e45def --- /dev/null +++ b/catalog-ui/src/app/ng2/config/translation.service.config.factory.ts @@ -0,0 +1,13 @@ +import { ITranslateServiceConfig } from "../shared/translator/translate.service.config"; + +declare const __ENV__:string; + +export function getTranslationServiceConfig() : ITranslateServiceConfig { + const pathPrefix = (__ENV__ === 'prod') ? 'sdc1/' : ''; + return { + filePrefix: pathPrefix + 'assets/languages/', + fileSuffix: '.json', + allowedLanguages: ['en_US'], + defaultLanguage: 'en_US' + }; +} diff --git a/catalog-ui/src/app/ng2/config/translation.service.config.ts b/catalog-ui/src/app/ng2/config/translation.service.config.ts new file mode 100644 index 0000000000..9c2df7a098 --- /dev/null +++ b/catalog-ui/src/app/ng2/config/translation.service.config.ts @@ -0,0 +1,8 @@ +import { Provider } from "@angular/core"; +import { TranslateServiceConfigToken } from "../shared/translator/translate.service.config"; +import { getTranslationServiceConfig } from "./translation.service.config.factory"; + +export const TranslationServiceConfig:Provider = { + provide: TranslateServiceConfigToken, + useFactory: getTranslationServiceConfig +}; diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html new file mode 100644 index 0000000000..02e7694eb0 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.html @@ -0,0 +1,4 @@ +<div> + <connection-wizard-header currentStepIndex="2"></connection-wizard-header> + <properties-step></properties-step> +</div> diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less new file mode 100644 index 0000000000..07f9aa2135 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.less @@ -0,0 +1,4 @@ +connection-wizard-header { + display: block; + margin-bottom: 15px; +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts new file mode 100644 index 0000000000..5abb879013 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-properties-view/connection-properties-view.component.ts @@ -0,0 +1,10 @@ +import {Component} from "@angular/core"; + + +@Component({ + selector: 'connection-properties-view', + templateUrl: './connection-properties-view.component.html', + styleUrls:['./connection-properties-view.component.less'] +}) +export class ConnectionPropertiesViewComponent { +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html new file mode 100644 index 0000000000..369ab50cad --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.html @@ -0,0 +1,36 @@ +<div class="header-main-container"> + <div class="inner-container"> + <div class="node from-node" [ngClass]="{'selected':currentStepIndex == 0}"> + <div class="text"> + <div class="node-name"> + {{connectWizardService.connectRelationModel.fromNode.componentInstance.name}} + </div> + <div class="selected-req-or-cap" [ngClass]="{'selected': currentStepIndex == 2 && !connectWizardService.selectedMatch.isFromTo}"> + {{getSelectedReqOrCapName(true)}} + </div> + </div> + <div class="icon"> + <div class="small medium {{connectWizardService.connectRelationModel.fromNode.componentInstance.iconSprite}} {{connectWizardService.connectRelationModel.fromNode.componentInstance.icon}}"> + </div> + </div> + </div> + <div class="connection"> + + </div> + <div class="node to-node" [ngClass]="{'selected':currentStepIndex == 1}"> + <div class="icon"> + <div class="small medium {{connectWizardService.connectRelationModel.toNode.componentInstance.iconSprite}} {{connectWizardService.connectRelationModel.toNode.componentInstance.icon}}"> + </div> + </div> + + <div class="text"> + <div class="node-name"> + {{connectWizardService.connectRelationModel.toNode.componentInstance.name}} + </div> + <div class="selected-req-or-cap" [ngClass]="{'selected': currentStepIndex == 2 && connectWizardService.selectedMatch.isFromTo}"> + {{getSelectedReqOrCapName(false)}} + </div> + </div> + </div> + </div> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less new file mode 100644 index 0000000000..72fa6e813f --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.less @@ -0,0 +1,53 @@ +@import '../../../../../assets/styles/sprite-proxy-services-icons'; +@import '../../../../../assets/styles/variables'; +.header-main-container{ + background-color: #f8f8f8; + width: 100%; + height: 100px; + display: flex; + .inner-container{ + margin: 0 auto; + display: flex; + } +} +.selected { + color: @main_color_a; +} +.node{ + display: flex; + &.from-node{ + text-align: right; + } + &.to-node{ + text-align: left; + } + &.selected{ + .icon{ + border: solid 3px @main_color_a; + padding: 4px; + border-radius: 50%; + background-color: @main_color_p; + } + } + .icon{ + margin: auto 0; + display: flex; + } + .text{ + font-family: @font-opensans-medium; + margin: auto 10px; + min-width: 450px; + .node-name{ + font-size: 11px; + } + .selected-req-or-cap{ + font-size: 14px; + } + } +} +.connection{ + width: 67px; + height: 0px; + border-bottom: dashed 2px #979797; + margin: auto 0; +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts new file mode 100644 index 0000000000..f5bc3b7ca4 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard-header/connection-wizard-header.component.ts @@ -0,0 +1,37 @@ +/** + * Created by rc2122 on 9/27/2017. + */ +import {Component, Inject, forwardRef} from "@angular/core"; +import {ConnectionWizardService} from "../connection-wizard.service"; +import {WizardHeaderBaseComponent} from "app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component"; + +@Component({ + selector: 'connection-wizard-header', + templateUrl: './connection-wizard-header.component.html', + styleUrls:['./connection-wizard-header.component.less'] +}) + +export class ConnectionWizardHeaderComponent extends WizardHeaderBaseComponent{ + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) { + super(); + } + + private _getReqOrCapName(isFromNode:boolean) { + const attributeReqOrCap:string = isFromNode ? 'requirement' : 'capability'; + if (this.connectWizardService.selectedMatch[attributeReqOrCap]) { + return this.connectWizardService.selectedMatch[attributeReqOrCap].getTitle(); + } else if (this.connectWizardService.selectedMatch.relationship) { + return this.connectWizardService.selectedMatch.relationship.relation[attributeReqOrCap]; + } + return ''; + } + + private getSelectedReqOrCapName = (isFromNode:boolean):string => { + if(!this.connectWizardService.selectedMatch){ + return ''; + } + return this._getReqOrCapName(this.connectWizardService.selectedMatch.isFromTo ? isFromNode : !isFromNode); + } +} + diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts new file mode 100644 index 0000000000..6b4b4128c1 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.module.ts @@ -0,0 +1,43 @@ +import {ToNodeStepComponent} from "./to-node-step/to-node-step.component"; +import {NgModule} from "@angular/core"; +import {FromNodeStepComponent} from "./from-node-step/from-node-step.component"; +import {PropertiesStepComponent} from "./properties-step/properties-step.component"; +import {ConnectionWizardService} from "./connection-wizard.service"; +import {SelectRequirementOrCapabilityModule} from "../../components/logic/select-requirement-or-capability/select-requirement-or-capability.module"; +import {PropertyTableModule} from "../../components/logic/properties-table/property-table.module"; +import {FormElementsModule} from "../../components/ui/form-components/form-elements.module"; +import {ConnectionWizardHeaderComponent} from "./connection-wizard-header/connection-wizard-header.component"; +import {ConnectionPropertiesViewComponent} from "./connection-properties-view/connection-properties-view.component"; +import {BrowserModule} from "@angular/platform-browser"; + +@NgModule({ + declarations: [ + FromNodeStepComponent, + ToNodeStepComponent, + PropertiesStepComponent, + ConnectionWizardHeaderComponent, + ConnectionPropertiesViewComponent + ], + imports: [ + FormElementsModule, + PropertyTableModule, + SelectRequirementOrCapabilityModule, + BrowserModule + ], + exports: [ + FromNodeStepComponent, + ToNodeStepComponent, + PropertiesStepComponent, + ConnectionWizardHeaderComponent, + ConnectionPropertiesViewComponent + ], + entryComponents: [FromNodeStepComponent, + ToNodeStepComponent, + PropertiesStepComponent, + ConnectionWizardHeaderComponent, + ConnectionPropertiesViewComponent + ], + providers: [ConnectionWizardService] +}) +export class ConnectionWizardModule { +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts new file mode 100644 index 0000000000..a097fb04ea --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/connection-wizard.service.ts @@ -0,0 +1,67 @@ +import {ConnectRelationModel} from "../../../models/graph/connectRelationModel"; +import {Injectable} from "@angular/core"; +import { Requirement, Capability} from "app/models"; +import {Dictionary} from "lodash"; +import {Match, Component, PropertyFEModel} from "app/models"; + +@Injectable() +export class ConnectionWizardService { + + connectRelationModel:ConnectRelationModel; + currentComponent:Component; + selectedMatch:Match; + changedCapabilityProperties:PropertyFEModel[]; + + constructor() { + this.changedCapabilityProperties = []; + } + + public setRelationMenuDirectiveObj = (connectRelationModel:ConnectRelationModel) => { + this.connectRelationModel = connectRelationModel; + // this.selectedCapability = rel + } + + + // getComponentInstanceIdOfSelectedCapability = (): string => { + // if(this.selectedMatch.capability){ + // if(this.selectedMatch.isFromTo) { + // return this.selectedMatch.toNode; + // } else { + // return this.selectedMatch.fromNode; + // } + // } + // return ''; + // + // } + + getOptionalRequirementsByInstanceUniqueId = (isFromTo: boolean, matchWith?:Capability): Dictionary<Requirement[]> => { + let requirements: Array<Requirement> = []; + _.forEach(this.connectRelationModel.possibleRelations, (match: Match) => { + if(!matchWith || match.capability.uniqueId == matchWith.uniqueId){ + if(match.isFromTo == isFromTo){ + requirements.push(match.requirement); + } + } + }); + requirements = _.uniqBy(requirements, (req:Requirement)=>{ + return req.ownerId + req.uniqueId + req.name; + }); + return _.groupBy(requirements, 'capability'); + } + + getOptionalCapabilitiesByInstanceUniqueId = (isFromTo: boolean, matchWith?:Requirement): Dictionary<Capability[]> => { + let capabilities: Array<Capability> = []; + _.forEach(this.connectRelationModel.possibleRelations, (match: Match) => { + if(!matchWith || match.requirement.uniqueId == matchWith.uniqueId){ + if(match.isFromTo == isFromTo){ + capabilities.push(match.capability); + } + } + }); + capabilities = _.uniqBy(capabilities, (cap:Capability)=>{ + return cap.ownerId + cap.uniqueId + cap.name; + }); + return _.groupBy(capabilities, 'type'); + } +} + diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html new file mode 100644 index 0000000000..0c9d9e6e26 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.html @@ -0,0 +1,8 @@ +<select-requirement-or-capability [optionalRequirementsMap]="optionalRequirementsMap" + [optionalCapabilitiesMap]="optionalCapabilitiesMap" + [selectedReqOrCapModel]="connectWizardService.selectedMatch && (connectWizardService.selectedMatch.isFromTo ? connectWizardService.selectedMatch.requirement : connectWizardService.selectedMatch.capability)" + [currentComponent]="connectWizardService.currentComponent" + [componentInstanceId]="connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId" + (updateSelectedReqOrCap)="updateSelectedReqOrCap($event)" + (updateCapabilityProperties)="onCapabilityPropertiesUpdate($event)"> +</select-requirement-or-capability>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts new file mode 100644 index 0000000000..edbbf8a0a3 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/from-node-step/from-node-step.component.ts @@ -0,0 +1,49 @@ +import {Component, OnInit, Inject, forwardRef} from "@angular/core"; +import {IStepComponent} from "../../../../models/wizard-step"; +import {Dictionary} from "lodash"; +import { Match} from "app/models"; +import {ConnectionWizardService} from "../connection-wizard.service"; +import {Requirement} from "../../../../models/requirement"; +import {Capability} from "../../../../models/capability"; +import {PropertyModel} from "../../../../models/properties"; + +@Component({ + selector: 'from-node-step', + templateUrl: './from-node-step.component.html' +}) + +export class FromNodeStepComponent implements IStepComponent, OnInit{ + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) {} + + optionalRequirementsMap: Dictionary<Requirement[]>; + optionalCapabilitiesMap: Dictionary<Capability[]>; + + ngOnInit(){ + this.optionalRequirementsMap = this.connectWizardService.getOptionalRequirementsByInstanceUniqueId(true); + this.optionalCapabilitiesMap = this.connectWizardService.getOptionalCapabilitiesByInstanceUniqueId(false); + } + + preventNext = ():boolean => { + return !this.connectWizardService.selectedMatch || (!this.connectWizardService.selectedMatch.capability && !this.connectWizardService.selectedMatch.requirement); + } + + preventBack = ():boolean => { + return true; + } + + onCapabilityPropertiesUpdate(capabilityProperties:Array<PropertyModel>) { + this.connectWizardService.selectedMatch.capabilityProperties = capabilityProperties; + } + + private updateSelectedReqOrCap = (selected:Requirement|Capability):void => { + if(!selected){ + this.connectWizardService.selectedMatch = null; + } else if(selected instanceof Requirement){ + this.connectWizardService.selectedMatch = new Match(<Requirement>selected, null, true, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId, null); + } else{ + this.connectWizardService.selectedMatch = new Match(null,<Capability>selected , false, null, this.connectWizardService.connectRelationModel.fromNode.componentInstance.uniqueId); + } + } + +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html new file mode 100644 index 0000000000..9e34893272 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.html @@ -0,0 +1,13 @@ +<div class="title"> + <span class="capability-name"> + {{(connectWizardService.selectedMatch.capability && connectWizardService.selectedMatch.capability.getTitle()) || connectWizardService.selectedMatch.relationship.relation.capability}} + </span> +</div> +<div class="properties-table-container"> + <properties-table class="properties-table" + (valueChanged)="propertyValueChanged($event)" + [fePropertiesMap]="capabilityPropertiesMap" + [selectedPropertyId]="''" + [hidePropertyType]="true"> + </properties-table> +</div>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less new file mode 100644 index 0000000000..8e9e07c0d5 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.less @@ -0,0 +1,15 @@ +@import '../../../../../assets/styles/variables'; +.title{ + margin-bottom: 20px; + .capability-name-label{ + font-size: 13px; + } + .capability-name{ + font-family: @font-opensans-medium; + color: @main_color_a; + } +} +.properties-table-container{ + height: 362px; + overflow-y: auto; +}
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts new file mode 100644 index 0000000000..3e48785a3c --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/properties-step/properties-step.component.ts @@ -0,0 +1,67 @@ +/** + * Created by ob0695 on 9/4/2017. + */ +/** + * Created by rc2122 on 9/4/2017. + */ +import {Component, Inject, forwardRef} from '@angular/core'; +import {IStepComponent} from "app/models" +import {ConnectionWizardService} from "../connection-wizard.service"; +import {PropertyFEModel} from "../../../../models/properties-inputs/property-fe-model"; +import {InstanceFePropertiesMap} from "../../../../models/properties-inputs/property-fe-map"; +import {PropertiesUtils} from "../../properties-assignment/services/properties.utils"; +import {ComponentInstanceServiceNg2} from "../../../services/component-instance-services/component-instance.service"; + +@Component({ + selector: 'properties-step', + templateUrl: './properties-step.component.html', + styleUrls: ['./properties-step.component.less'] +}) + +export class PropertiesStepComponent implements IStepComponent{ + + capabilityPropertiesMap: InstanceFePropertiesMap; + savingProperty:boolean = false; + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService, private componentInstanceServiceNg2:ComponentInstanceServiceNg2, private propertiesUtils:PropertiesUtils) { + + this.capabilityPropertiesMap = this.propertiesUtils.convertPropertiesMapToFEAndCreateChildren({'capability' : connectWizardService.selectedMatch.capabilityProperties}, false); + } + + ngOnInit() { + this.connectWizardService.changedCapabilityProperties = []; + } + + onPropertySelectedUpdate = ($event) => { + console.log("==>" + 'PROPERTY VALUE SELECTED'); + // this.selectedFlatProperty = $event; + // let parentProperty:PropertyFEModel = this.propertiesService.getParentPropertyFEModelFromPath(this.instanceFePropertiesMap[this.selectedFlatProperty.instanceName], this.selectedFlatProperty.path); + // parentProperty.expandedChildPropertyId = this.selectedFlatProperty.path; + }; + + propertyValueChanged = (property: PropertyFEModel) => { + if (!property.isDeclared) { + const propChangedIdx = this.connectWizardService.changedCapabilityProperties.indexOf(property); + if (this.componentInstanceServiceNg2.hasPropertyChanged(property)) { + console.log("==>" + this.constructor.name + ": propertyValueChanged " + property); + if (propChangedIdx === -1) { + this.connectWizardService.changedCapabilityProperties.push(property); + } + } + else { + if (propChangedIdx !== -1) { + console.log("==>" + this.constructor.name + ": propertyValueChanged (reset to original) " + property); + this.connectWizardService.changedCapabilityProperties.splice(propChangedIdx, 1); + } + } + } + }; + + preventNext = ():boolean => { + return false; + } + + preventBack = ():boolean => { + return this.savingProperty; + } +} diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html new file mode 100644 index 0000000000..67bb12e6fc --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.html @@ -0,0 +1,9 @@ +<select-requirement-or-capability [optionalRequirementsMap]="optionalRequirementsMap" + [optionalCapabilitiesMap]="optionalCapabilitiesMap" + [selectedReqOrCapModel]="connectWizardService.selectedMatch.isFromTo ? connectWizardService.selectedMatch.capability : connectWizardService.selectedMatch.requirement" + [selectedReqOrCapOption]="displayRequirementsOrCapabilities" + [currentComponent]="connectWizardService.currentComponent" + [componentInstanceId]="connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId" + (updateSelectedReqOrCap)="updateSelectedReqOrCap($event)" + (updateCapabilityProperties)="onCapabilityPropertiesUpdate($event)"> +</select-requirement-or-capability>
\ No newline at end of file diff --git a/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts new file mode 100644 index 0000000000..9c7bf4dfe6 --- /dev/null +++ b/catalog-ui/src/app/ng2/pages/connection-wizard/to-node-step/to-node-step.component.ts @@ -0,0 +1,69 @@ +import {Component, forwardRef, Inject} from '@angular/core'; +import {IStepComponent} from "app/models" +import {Dictionary} from "lodash"; +import {ConnectionWizardService} from "../connection-wizard.service"; +import {Match} from "../../../../models/graph/match-relation"; +import {Requirement} from "../../../../models/requirement"; +import {Capability} from "../../../../models/capability"; +import {PropertyModel} from "../../../../models/properties"; + +@Component({ + selector: 'to-node-step', + templateUrl: './to-node-step.component.html' +}) + +export class ToNodeStepComponent implements IStepComponent{ + + displayRequirementsOrCapabilities:string; //get 'Requirement' or 'Capability' + optionalRequirementsMap: Dictionary<Requirement[]> = {}; + optionalCapabilitiesMap: Dictionary<Capability[]> ={}; + + constructor(@Inject(forwardRef(() => ConnectionWizardService)) public connectWizardService: ConnectionWizardService) { + } + + ngOnInit(){ + if(this.connectWizardService.selectedMatch.isFromTo){ + this.displayRequirementsOrCapabilities = 'Capability'; + this.optionalRequirementsMap = {}; + this.optionalCapabilitiesMap = this.connectWizardService.getOptionalCapabilitiesByInstanceUniqueId(true, this.connectWizardService.selectedMatch.requirement); + }else{ + this.displayRequirementsOrCapabilities = 'Requirement'; + this.optionalRequirementsMap = this.connectWizardService.getOptionalRequirementsByInstanceUniqueId(false, this.connectWizardService.selectedMatch.capability); + this.optionalCapabilitiesMap = {} + } + + + } + + preventNext = ():boolean => { + return !this.connectWizardService.selectedMatch.capability || !this.connectWizardService.selectedMatch.requirement; + } + + preventBack = ():boolean => { + return false; + } + + onCapabilityPropertiesUpdate(capabilityProperties:Array<PropertyModel>) { + this.connectWizardService.selectedMatch.capabilityProperties = capabilityProperties; + } + + private updateSelectedReqOrCap = (selected:Requirement|Capability):void => { + if (!selected) { + if (this.connectWizardService.selectedMatch.isFromTo) { + this.connectWizardService.selectedMatch.capability = undefined; + this.connectWizardService.selectedMatch.toNode = undefined; + } else { + this.connectWizardService.selectedMatch.requirement = undefined; + this.connectWizardService.selectedMatch.fromNode = undefined; + } + } else if (selected instanceof Requirement) { + this.connectWizardService.selectedMatch.requirement = <Requirement>selected; + this.connectWizardService.selectedMatch.fromNode = this.connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId; + } else { + this.connectWizardService.selectedMatch.capability = <Capability>selected; + this.connectWizardService.selectedMatch.toNode = this.connectWizardService.connectRelationModel.toNode.componentInstance.uniqueId; + } + this.connectWizardService.selectedMatch.relationship = undefined; + } + +} 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 1c6f51314d..203c75dd11 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 @@ -17,70 +17,43 @@ * limitations under the License. * ============LICENSE_END========================================================= */ - import { NgModule } from "@angular/core"; -import { PropertiesAssignmentComponent } from "./properties-assignment.page.component"; -import { HierarchyNavigationComponent } from "./../../components/hierarchy-navigtion/hierarchy-navigation.component"; -import { BrowserModule } from "@angular/platform-browser"; -import { FormsModule } from "@angular/forms"; -import { HttpModule } from "@angular/http"; -import { TabModule } from '../../shared/tabs/tabs.module'; -import { CheckboxModule} from '../../shared/checkbox/checkbox.module'; -import { PropertiesTableComponent } from '../../components/properties-table/properties-table.component'; -import { InputsTableComponent } from '../../components/inputs-table/inputs-table.component'; -import { ContentAfterLastDotPipe } from "../../pipes/contentAfterLastDot.pipe"; -import { SearchFilterPipe } from "../../pipes/searchFilter.pipe"; -import { FilterChildPropertiesPipe } from "../../pipes/filterChildProperties.pipe"; -import { DataTypeService } from './../../services/data-type.service'; -import { PropertiesService } from './../../services/properties.service'; -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 { 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 {LoaderComponent} from "app/ng2/components/loader/loader.component" +import {HierarchyNavigationComponent} from "../../components/logic/hierarchy-navigtion/hierarchy-navigation.component"; +import {HttpModule} from "@angular/http"; +import {FormsModule} from "@angular/forms"; +import {PropertyTableModule} from "../../components/logic/properties-table/property-table.module"; +import {UiElementsModule} from "../../components/ui/ui-elements.module"; +import {GlobalPipesModule} from "../../pipes/global-pipes.module"; +import {BrowserModule} from "@angular/platform-browser"; +import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component"; +import {InputsTableComponent} from "../../components/logic/inputs-table/inputs-table.component"; +import {PropertiesService} from "../../services/properties.service"; +import {DataTypeService} from "../../services/data-type.service"; +import {PropertiesAssignmentComponent} from "./properties-assignment.page.component"; +import {HierarchyNavService} from "./services/hierarchy-nav.service"; +import {PropertiesUtils} from "./services/properties.utils"; +import {ComponentModeService} from "../../services/component-services/component-mode.service"; @NgModule({ declarations: [ PropertiesAssignmentComponent, - PropertiesTableComponent, InputsTableComponent, - ContentAfterLastDotPipe, - GroupByPipe, - KeysPipe, - SearchFilterPipe, - FilterChildPropertiesPipe, HierarchyNavigationComponent, - DynamicPropertyComponent, - // PopoverContentComponent, - // PopoverComponent, - FilterPropertiesAssignmentComponent, - LoaderComponent + FilterPropertiesAssignmentComponent ], imports: [ BrowserModule, FormsModule, HttpModule, - TabModule, - CheckboxModule, - DynamicElementModule, - PopoverModule, - TooltipModule, - ModalModule - ], + GlobalPipesModule, + PropertyTableModule, + UiElementsModule], + entryComponents: [PropertiesAssignmentComponent], exports: [ PropertiesAssignmentComponent - // PopoverContentComponent, - // PopoverComponent ], - providers: [PropertiesService, HierarchyNavService, PropertiesUtils, DataTypeService, ContentAfterLastDotPipe, GroupByPipe, KeysPipe, ComponentModeService] + providers: [PropertiesService, HierarchyNavService, PropertiesUtils, DataTypeService, ComponentModeService] }) export class PropertiesAssignmentModule { diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html index be7e03dccd..beea3fe73f 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/properties-assignment.page.component.html @@ -11,6 +11,7 @@ [propertyNameSearchText]="searchPropertyName" [readonly]="isReadonly" [isLoading]="loadingProperties" + [hasDeclareOption]="true" (valueChanged)="propertyValueChanged($event)" (propertySelected)="propertySelected($event)" (selectPropertyRow)="selectPropertyRow($event)" @@ -31,12 +32,12 @@ </tabs> <div class="header"> <div class="search-filter-container" [class.without-filter]="isInpusTabSelected"> - <span *ngIf="displayClearSearch && !isInpusTabSelected" (click)="clickOnClearSearch()" class="clear-filter">Clear All</span> - <input type="text" class="search-box" placeholder="Search" [(ngModel)]="searchQuery" /> - <span class="sprite search-icon"></span> + <span *ngIf="displayClearSearch && !isInpusTabSelected" (click)="clickOnClearSearch()" class="clear-filter" data-tests-id="clear-filter-button">Clear All</span> + <input type="text" class="search-box" placeholder="Search" [(ngModel)]="searchQuery" data-tests-id="search-box"/> + <span class="sprite search-icon" data-tests-id="search-button"></span> <filter-properties-assignment *ngIf="!isInpusTabSelected" #advanceSearch class="advance-search" [componentType]="component.componentType" (searchProperties)="searchPropertiesInstances($event)"></filter-properties-assignment> </div> - <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly" (click)="declareProperties()">Declare</button> + <button class="tlv-btn blue declare-button" [disabled]="!checkedPropertiesCount || isReadonly" (click)="declareProperties()" data-tests-id="declare-button">Declare</button> </div> </div> <div class="right-column gray-border"> 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 82754f13f0..9603648bd8 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 @@ -20,21 +20,22 @@ import {Component, ViewChild, ElementRef, Renderer, Inject} from "@angular/core"; import { PropertiesService } from "../../services/properties.service"; -import { HierarchyNavService } from "../../services/hierarchy-nav.service"; -import { PropertiesUtils } from './properties.utils'; import { PropertyFEModel, InstanceFePropertiesMap, InstanceBePropertiesMap, InstancePropertiesAPIMap, Component as ComponentData, FilterPropertiesAssignmentData } from "app/models"; -import { PROPERTY_TYPES, ResourceType } from "app/utils"; +import { ResourceType } from "app/utils"; import property = require("lodash/property"); import {ComponentServiceNg2} from "../../services/component-services/component.service"; import {ComponentInstanceServiceNg2} from "../../services/component-instance-services/component-instance.service" -import { InputBEModel, InputFEModel, ComponentInstance, PropertyBEModel, DerivedPropertyType, DerivedFEProperty, ResourceInstance, SimpleFlatProperty } from "app/models"; -import {HierarchyDisplayOptions} from "../../components/hierarchy-navigtion/hierarchy-display-options" -import {PropertyRowSelectedEvent} from "./../../components/properties-table/properties-table.component"; +import { InputBEModel, InputFEModel, ComponentInstance, PropertyBEModel, DerivedFEProperty, ResourceInstance, SimpleFlatProperty } from "app/models"; import { KeysPipe } from 'app/ng2/pipes/keys.pipe'; -import {FilterPropertiesAssignmentComponent} from "../../components/filter-properties-assignment/filter-properties-assignment.component"; -import { ComponentModeService } from "app/ng2/services/component-mode.service" import {WorkspaceMode, EVENTS} from "../../../utils/constants"; import {EventListenerService} from "app/services/event-listener-service" +import {HierarchyDisplayOptions} from "../../components/logic/hierarchy-navigtion/hierarchy-display-options"; +import {FilterPropertiesAssignmentComponent} from "../../components/logic/filter-properties-assignment/filter-properties-assignment.component"; +import {PropertyRowSelectedEvent} from "../../components/logic/properties-table/properties-table.component"; +import {HierarchyNavService} from "./services/hierarchy-nav.service"; +import {PropertiesUtils} from "./services/properties.utils"; +import {ComponentModeService} from "../../services/component-services/component-mode.service"; + @Component({ templateUrl: './properties-assignment.page.component.html', styleUrls: ['./properties-assignment.page.component.less'] diff --git a/catalog-ui/src/app/ng2/services/hierarchy-nav.service.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/hierarchy-nav.service.ts index 016b04788e..016b04788e 100644 --- a/catalog-ui/src/app/ng2/services/hierarchy-nav.service.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/hierarchy-nav.service.ts diff --git a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts index d8d991d218..8f46c6f603 100644 --- a/catalog-ui/src/app/ng2/pages/properties-assignment/properties.utils.ts +++ b/catalog-ui/src/app/ng2/pages/properties-assignment/services/properties.utils.ts @@ -19,11 +19,10 @@ */ import { Injectable } from '@angular/core'; -import { DataTypeModel, PropertyFEModel, PropertyBEModel, InstanceBePropertiesMap, InstanceFePropertiesMap, SchemaProperty, DerivedFEProperty, DerivedFEPropertyMap, DerivedPropertyType, InputFEModel} from "app/models"; +import { DataTypeModel, PropertyFEModel, PropertyBEModel, InstanceBePropertiesMap, InstanceFePropertiesMap, DerivedFEProperty, DerivedPropertyType, InputFEModel} from "app/models"; import { DataTypeService } from "app/ng2/services/data-type.service"; import { PropertiesService } from "app/ng2/services/properties.service"; -import { PROPERTY_TYPES } from "app/utils"; -import { UUID } from "angular2-uuid"; +import { PROPERTY_TYPES, PROPERTY_DATA } from "app/utils"; @Injectable() export class PropertiesUtils { @@ -106,8 +105,16 @@ export class PropertiesUtils { public initValueObjectRef = (property: PropertyFEModel): void => { if (property.derivedDataType == DerivedPropertyType.SIMPLE || property.isDeclared) { //if property is declared, it gets a simple input instead. List and map values and pseudo-children will be handled in property component property.valueObj = property.value || property.defaultValue; - - if (property.isDeclared && typeof property.valueObj == 'object') property.valueObj = JSON.stringify(property.valueObj); + if (property.isDeclared) { + if(typeof property.valueObj == 'object'){ + property.valueObj = JSON.stringify(property.valueObj); + } + }else if(property.valueObj && + property.type !== PROPERTY_TYPES.STRING && + property.type !== PROPERTY_TYPES.JSON && + PROPERTY_DATA.SCALAR_TYPES.indexOf(property.type) == -1){ + property.valueObj = JSON.parse(property.valueObj);//The valueObj contains the real value ans not the value as string + } } else { if (property.derivedDataType == DerivedPropertyType.LIST) { property.valueObj = _.merge([], JSON.parse(property.defaultValue || '[]'), JSON.parse(property.value || '[]')); //value object should be merged value and default value. Value takes higher precendence. Set valueObj to empty obj if undefined. diff --git a/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts b/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts new file mode 100644 index 0000000000..1d81a1a4bf --- /dev/null +++ b/catalog-ui/src/app/ng2/pipes/global-pipes.module.ts @@ -0,0 +1,24 @@ +import {ContentAfterLastDotPipe} from "./contentAfterLastDot.pipe"; +import {SearchFilterPipe} from "./searchFilter.pipe"; +import {KeysPipe} from "./keys.pipe"; +import {GroupByPipe} from "./groupBy.pipe"; +import {NgModule} from "@angular/core"; + +@NgModule({ + declarations: [ + ContentAfterLastDotPipe, + GroupByPipe, + KeysPipe, + SearchFilterPipe + + ], + + exports: [ + ContentAfterLastDotPipe, + GroupByPipe, + KeysPipe, + SearchFilterPipe + ] +}) + +export class GlobalPipesModule {} diff --git a/catalog-ui/src/app/ng2/services/authentication.service.ts b/catalog-ui/src/app/ng2/services/authentication.service.ts index 876385c832..1c6502dd0d 100644 --- a/catalog-ui/src/app/ng2/services/authentication.service.ts +++ b/catalog-ui/src/app/ng2/services/authentication.service.ts @@ -18,26 +18,23 @@ * ============LICENSE_END========================================================= */ -import { Injectable } from '@angular/core'; -import { sdc2Config } from './../../../main'; +import {Injectable, Inject} from '@angular/core'; import {IAppConfigurtaion, ICookie} from "../../models/app-config"; import {Response, Headers, RequestOptions, Http} from '@angular/http'; import {Cookie2Service} from "./cookie.service"; import { Observable } from 'rxjs/Observable'; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class AuthenticationService { - private cookieService:Cookie2Service; - private http:Http; - - constructor(cookieService:Cookie2Service, http: Http) { + constructor(private cookieService:Cookie2Service, private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { this.cookieService = cookieService; this.http = http; } private getAuthHeaders():any { - let cookie:ICookie = sdc2Config.cookie; + let cookie:ICookie = this.sdcConfig.cookie; let authHeaders:any = {}; authHeaders[cookie.userFirstName] = this.cookieService.getFirstName(); authHeaders[cookie.userLastName] = this.cookieService.getLastName(); @@ -51,7 +48,7 @@ export class AuthenticationService { headers: new Headers(this.getAuthHeaders()) }); - let authUrl = sdc2Config.api.root + sdc2Config.api.GET_user_authorize; + let authUrl = this.sdcConfig.api.root + this.sdcConfig.api.GET_user_authorize; return this.http .get(authUrl, options) .map((res: Response) => res.json()); diff --git a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts index 27de59de82..b852539edd 100644 --- a/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts +++ b/catalog-ui/src/app/ng2/services/component-instance-services/component-instance.service.ts @@ -18,22 +18,23 @@ * ============LICENSE_END========================================================= */ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {Response, RequestOptions, Headers} from '@angular/http'; import { Observable } from 'rxjs/Observable'; -import {sdc2Config} from "../../../../main"; -import {PropertyBEModel} from "app/models"; +import {PropertyFEModel, PropertyBEModel} from "app/models"; import {CommonUtils} from "app/utils"; import {Component, ComponentInstance, InputModel} from "app/models"; import { HttpService } from '../http.service'; +import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; +import {isEqual} from "lodash"; @Injectable() export class ComponentInstanceServiceNg2 { protected baseUrl; - constructor(private http: HttpService) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; } getComponentInstanceProperties(component: Component, componentInstanceId: string): Observable<Array<PropertyBEModel>> { @@ -59,6 +60,24 @@ export class ComponentInstanceServiceNg2 { }) } + getInstanceCapabilityProperties(component: Component, componentInstanceId: string, capabilityType: string, capabilityName: string): Observable<Array<PropertyBEModel>> { + + return this.http.get(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capabilityType + + '/capabilityName/' + capabilityName + '/properties') + .map((res: Response) => { + return CommonUtils.initBeProperties(res.json()); + }) + } + + updateInstanceCapabilityProperties(component: Component, componentInstanceId: string, capabilityType: string, capabilityName: string, properties: PropertyBEModel[]): Observable<PropertyBEModel[]> { + + return this.http.put(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/componentInstances/' + componentInstanceId + '/capability/' + capabilityType + + '/capabilityName/' + capabilityName +'/properties', properties) + .map((res: Response) => { + return res.json().map((resProperty) => new PropertyBEModel(resProperty)); + }) + } + updateInstanceInput(component: Component, componentInstanceId: string, input: PropertyBEModel): Observable<PropertyBEModel> { return this.http.post(this.baseUrl + component.getTypeUrl() + component.uniqueId + '/resourceInstance/' + componentInstanceId + '/input', input) @@ -67,5 +86,9 @@ export class ComponentInstanceServiceNg2 { }) } - + hasPropertyChanged(property: PropertyFEModel) { + let oldValue: any = property.value; + const newValue = property.getJSONValue(); + return ((oldValue || newValue) && !isEqual(oldValue, newValue)); + } } diff --git a/catalog-ui/src/app/ng2/services/component-mode.service.ts b/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts index 2e60f6ac57..b0cc1b8f1a 100644 --- a/catalog-ui/src/app/ng2/services/component-mode.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/component-mode.service.ts @@ -22,7 +22,7 @@ * Created by rc2122 on 5/23/2017. */ import { Injectable } from '@angular/core'; -import {WorkspaceMode, ComponentState, Role} from "../../utils/constants"; +import {WorkspaceMode, ComponentState, Role} from "../../../utils/constants"; import { Component as ComponentData } from "app/models"; import { CacheService } from "app/services/cache-service" 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 c648711d5d..ba1cb15561 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 @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; @@ -27,11 +27,11 @@ import { Component, PropertyBEModel, InstancePropertiesAPIMap, FilterPropertiesA import {downgradeInjectable} from '@angular/upgrade/static'; import {COMPONENT_FIELDS} from "app/utils"; import {ComponentGenericResponse} from "../responses/component-generic-response"; -import {sdc2Config} from "../../../../main"; import {InstanceBePropertiesMap} from "../../../models/properties-inputs/property-fe-map"; import {API_QUERY_PARAMS} from "app/utils"; import { ComponentType, ServerTypeUrl } from "../../../utils/constants"; import { HttpService } from '../http.service'; +import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; declare var angular:angular.IAngularStatic; @@ -40,8 +40,8 @@ export class ComponentServiceNg2 { protected baseUrl; - constructor(private http:HttpService) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http:HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; } private getComponentDataByFieldsName(componentType:string, componentId: string, fields:Array<string>):Observable<ComponentGenericResponse> { @@ -151,17 +151,6 @@ export class ComponentServiceNg2 { .map((res: Response) => { return res.json(); }); - - // return {'ExtVL 0':[{definition: false,name:"network_assignments",password:false,required:true,type:"org.openecomp.datatypes.network.NetworkAssignments",uniqueId:"623cca1c-d605-4c9c-9f2b-935ec85ebcf8.network_assignments"}, - // {definition: false,name: "exVL_naming",password: false,required: true,type: "org.openecomp.datatypes.Naming",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.exVL_naming"}, - // {definition: false,name: "network_flows",password: false,required: false,type: "org.openecomp.datatypes.network.NetworkFlows",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.network_flows"}, - // {definition: false,name: "provider_network",password: false,required: true,type: "org.openecomp.datatypes.network.ProviderNetwork",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.provider_network"}, - // {definition: false,name: "network_homing",password: false,required: true,type: "org.openecomp.datatypes.EcompHoming",uniqueId: "623cca1c-d605-4c9c-9f2b-935ec85ebcf8.network_homing"}], - // 'NetworkCP 0':[{definition: false,description: "identifies MAC address assignments to the CP",name: "mac_requirements",password: false,required: false,type: "org.openecomp.datatypes.network.MacRequirements",uniqueId: "26ec2bfd-b904-46c7-87ed-b32775120f2c.mac_requirements"}], - // 'NetworkCP 1':[{definition: false,description: "identifies MAC address assignments to the CP",name: "mac_requirements",password: false,required: false,type: "org.openecomp.datatypes.network.MacRequirements",uniqueId: "26ec2bfd-b904-46c7-87ed-b32775120f2c.mac_requirements"}]}; - - } } -angular.module('Sdc.Services').factory('ComponentServiceNg2', downgradeInjectable(ComponentServiceNg2)); // This is in order to use the service in angular1 till we finish remove all angular1 code diff --git a/catalog-ui/src/app/ng2/services/component-services/service.service.ts b/catalog-ui/src/app/ng2/services/component-services/service.service.ts index ec912bbcf5..f38dbef595 100644 --- a/catalog-ui/src/app/ng2/services/component-services/service.service.ts +++ b/catalog-ui/src/app/ng2/services/component-services/service.service.ts @@ -18,15 +18,15 @@ * ============LICENSE_END========================================================= */ -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/toPromise'; import { Response } from '@angular/http'; import {Service} from "app/models"; import { downgradeInjectable } from '@angular/upgrade/static'; -import {sdc2Config} from "../../../../main"; import { HttpService } from '../http.service'; +import {SdcConfigToken, ISdcConfig} from "../../config/sdc-config.config"; @Injectable() @@ -34,8 +34,8 @@ export class ServiceServiceNg2 { protected baseUrl = ""; - constructor(private http: HttpService) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http: HttpService, @Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.baseUrl = sdcConfig.api.root + sdcConfig.api.component_api_root; } validateConformanceLevel(service: Service): Observable<boolean> { @@ -47,5 +47,3 @@ export class ServiceServiceNg2 { } } - -angular.module('Sdc.Services').factory('ServiceServiceNg2', downgradeInjectable(ServiceServiceNg2)); // This is in order to use the service in angular1 till we finish remove all angular1 code diff --git a/catalog-ui/src/app/ng2/services/config.service.ts b/catalog-ui/src/app/ng2/services/config.service.ts index cac850e91c..9bb7b7a075 100644 --- a/catalog-ui/src/app/ng2/services/config.service.ts +++ b/catalog-ui/src/app/ng2/services/config.service.ts @@ -22,13 +22,11 @@ * Created by ob0695 on 4/9/2017. */ -import { Injectable } from '@angular/core'; +import { Injectable, Inject } from '@angular/core'; import { Http, Response } from '@angular/http'; import 'rxjs/add/operator/toPromise'; import {IAppConfigurtaion, ValidationConfiguration, Validations} from "app/models"; -import {sdc2Config} from './../../../main'; - -declare var __ENV__: string; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class ConfigService { @@ -36,12 +34,12 @@ export class ConfigService { private baseUrl; public configuration: IAppConfigurtaion; - constructor(private http: Http) { - this.baseUrl = sdc2Config.api.root + sdc2Config.api.component_api_root; + constructor(private http: Http, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { + this.baseUrl = this.sdcConfig.api.root + this.sdcConfig.api.component_api_root; } loadValidationConfiguration(): Promise<ValidationConfiguration> { - let url: string = sdc2Config.validationConfigPath; + let url: string = this.sdcConfig.validationConfigPath; let promise: Promise<ValidationConfiguration> = this.http.get(url).map((res: Response) => res.json()).toPromise(); promise.then((validationData: Validations) => { ValidationConfiguration.validation = validationData; diff --git a/catalog-ui/src/app/ng2/services/cookie.service.ts b/catalog-ui/src/app/ng2/services/cookie.service.ts index e5f04f7afd..2a783fdd48 100644 --- a/catalog-ui/src/app/ng2/services/cookie.service.ts +++ b/catalog-ui/src/app/ng2/services/cookie.service.ts @@ -18,9 +18,9 @@ * ============LICENSE_END========================================================= */ -import { Injectable } from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {IAppConfigurtaion, ICookie} from "../../models/app-config"; -import {sdc2Config} from './../../../main'; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class Cookie2Service { @@ -28,8 +28,8 @@ export class Cookie2Service { private cookie:ICookie; private cookiePrefix:string; - constructor() { - this.cookie = sdc2Config.cookie; + constructor(@Inject(SdcConfigToken) sdcConfig:ISdcConfig) { + this.cookie = sdcConfig.cookie; this.cookiePrefix = ''; let junctionName:string = this.getCookieByName(this.cookie.junctionName); diff --git a/catalog-ui/src/app/ng2/services/http.service.ts b/catalog-ui/src/app/ng2/services/http.service.ts index 21fe09023a..2785688ace 100644 --- a/catalog-ui/src/app/ng2/services/http.service.ts +++ b/catalog-ui/src/app/ng2/services/http.service.ts @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -import {Injectable} from '@angular/core'; +import {Injectable, Inject} from '@angular/core'; import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http'; import {Observable} from 'rxjs/Observable'; import {UUID} from 'angular2-uuid'; @@ -27,15 +27,15 @@ import 'rxjs/add/operator/catch'; import 'rxjs/add/observable/throw'; import {Dictionary} from "../../utils/dictionary/dictionary"; import {SharingService, CookieService} from "app/services"; -import {sdc2Config} from './../../../main'; import { ModalService } from "app/ng2/services/modal.service"; import { ServerErrorResponse } from "app/models"; -import { ErrorMessageComponent } from 'app/ng2/components/modal/error-message/error-message.component'; +import {ErrorMessageComponent} from "../components/ui/modal/error-message/error-message.component"; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; @Injectable() export class HttpService extends Http { - constructor(backend: XHRBackend, options: RequestOptions, private sharingService: SharingService, private cookieService: CookieService, private modalService: ModalService) { + constructor(backend: XHRBackend, options: RequestOptions, private sharingService: SharingService, private cookieService: CookieService, private modalService: ModalService, @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { super(backend, options); this._defaultOptions.withCredentials = true; this._defaultOptions.headers.append(cookieService.getUserIdSuffix(), cookieService.getUserId()); @@ -73,7 +73,7 @@ export class HttpService extends Http { private getUuidValue = (url: string) :string => { let map:Dictionary<string, string> = this.sharingService.getUuidMap(); - if (map && url.indexOf(sdc2Config.api.root) > 0) { + if (map && url.indexOf(this.sdcConfig.api.root) > 0) { map.forEach((key:string) => { if (url.indexOf(key) !== -1) { return this.sharingService.getUuidValue(key); @@ -93,4 +93,8 @@ export class HttpService extends Http { return Observable.throw(response); }; + public static replaceUrlParams(url:string, urlParams:{[index:string]:any}):string { + return url.replace(/:(\w+)/g, (m, p1):string => urlParams[p1] || ''); + } + } diff --git a/catalog-ui/src/app/ng2/services/modal.service.ts b/catalog-ui/src/app/ng2/services/modal.service.ts index 65ff870769..22b56c7004 100644 --- a/catalog-ui/src/app/ng2/services/modal.service.ts +++ b/catalog-ui/src/app/ng2/services/modal.service.ts @@ -1,6 +1,11 @@ -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'; +import { + Injectable, Type, ViewContainerRef, ApplicationRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, + +} from '@angular/core'; +import { ModalModel, ButtonModel, StepModel } from 'app/models'; +import {MultiStepsWizardComponent} from "../components/ui/multi-steps-wizard/multi-steps-wizard.component"; +import {ModalComponent} from "../components/ui/modal/modal.component"; +import {WizardHeaderBaseComponent} from "app/ng2/components/ui/multi-steps-wizard/multi-steps-wizard-header-base.component"; @Injectable() @@ -54,6 +59,23 @@ export class ModalService { return customModal; } + public createMultiStepsWizard = (title: string, steps:Array<StepModel>, callback: Function, dynamicHeaderType?: Type<WizardHeaderBaseComponent>): ComponentRef<MultiStepsWizardComponent> => { + let cancelButton: ButtonModel = new ButtonModel('Cancel', 'outline blue', this.closeCurrentModal); + let modalModel: ModalModel = new ModalModel('xl', title, '', [cancelButton]); + let wizardInstance: ComponentRef<MultiStepsWizardComponent> = this.createDynamicComponent(MultiStepsWizardComponent); + wizardInstance.instance.input = modalModel; + wizardInstance.instance.steps = steps; + wizardInstance.instance.callback = callback; + if(dynamicHeaderType){ + let dynamicHeader = this.createDynamicComponent(dynamicHeaderType, wizardInstance.instance.dynamicHeaderContainer); + wizardInstance.instance.dynamicHeader = dynamicHeader; + wizardInstance.instance.dynamicHeader.instance.currentStepIndex = 0; + } + this.addDynamicContentToModal(wizardInstance, steps[0].component); + this.currentModal = wizardInstance; + return wizardInstance; + } + public closeCurrentModal = () => { if (!this.currentModal) return; @@ -62,7 +84,7 @@ export class ModalService { } - public addDynamicContentToModal = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput: any) => { + public addDynamicContentToModal = (modalInstance: ComponentRef<ModalComponent>, dynamicComponentType: Type<any>, dynamicComponentInput?: any) => { let dynamicContent = this.createDynamicComponent(dynamicComponentType, modalInstance.instance.dynamicContentContainer); dynamicContent.instance.input = dynamicComponentInput; @@ -72,14 +94,13 @@ export class ModalService { //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> { + private createDynamicComponent<T>(componentType: Type<T>, viewContainerRef?:ViewContainerRef): ComponentRef<T> { 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); - + let factory: ComponentFactory<T> = this.componentFactoryResolver.resolveComponentFactory(componentType); //Ref: https://angular.io/guide/dynamic-component-loader + let componentRef: ComponentRef<T> = viewContainerRef.createComponent(factory); return componentRef; } @@ -87,4 +108,6 @@ export class ModalService { private getRootViewContainerRef(): ViewContainerRef { return this.applicationRef.components[0].instance.viewContainerRef; } -}
\ No newline at end of file +} + + diff --git a/catalog-ui/src/app/ng2/services/properties.service.ts b/catalog-ui/src/app/ng2/services/properties.service.ts index 6f15de858a..86cd2f5c72 100644 --- a/catalog-ui/src/app/ng2/services/properties.service.ts +++ b/catalog-ui/src/app/ng2/services/properties.service.ts @@ -19,16 +19,12 @@ */ import { Injectable } from '@angular/core'; -import { DataTypeModel, PropertyFEModel, PropertyBEModel, SchemaProperty, PropertyDeclareAPIModel, DerivedFEProperty, DerivedFEPropertyMap, DerivedPropertyType, InputFEModel} from "app/models"; -import { DataTypeService } from "./data-type.service"; -import { PROPERTY_TYPES } from "app/utils"; -import { ContentAfterLastDotPipe } from "../pipes/contentAfterLastDot.pipe"; -import { UUID } from "angular2-uuid"; +import { PropertyFEModel, PropertyBEModel, PropertyDeclareAPIModel, DerivedFEProperty} from "app/models"; @Injectable() export class PropertiesService { - constructor(private dataTypeService: DataTypeService, private contentAfterLastDotPipe: ContentAfterLastDotPipe) { + constructor() { } public getParentPropertyFEModelFromPath = (properties: Array<PropertyFEModel>, path: string) => { diff --git a/catalog-ui/src/app/ng2/services/user.service.ts b/catalog-ui/src/app/ng2/services/user.service.ts new file mode 100644 index 0000000000..87e90432dc --- /dev/null +++ b/catalog-ui/src/app/ng2/services/user.service.ts @@ -0,0 +1,98 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { Injectable, Inject } from "@angular/core"; +import { Headers } from "@angular/http"; +import { Observable } from "rxjs/Observable"; +import { HttpService } from "./http.service"; +import { Cookie2Service } from "./cookie.service"; +import { IUserProperties } from "../../models/user"; + +import {ICookie} from "../../models/app-config"; +import {SdcConfigToken, ISdcConfig} from "../config/sdc-config.config"; + +@Injectable() +export class UserService { + private url:string; + private authorizeUrl:string; + + private _loggedinUser:IUserProperties; + + constructor(private httpService:HttpService, + private cookieService:Cookie2Service, + @Inject(SdcConfigToken) private sdcConfig:ISdcConfig) { + this.url = this.sdcConfig.api.root + this.sdcConfig.api.GET_user; + this.authorizeUrl = this.sdcConfig.api.root + this.sdcConfig.api.GET_user_authorize; + } + + public authorize() :Observable<IUserProperties> { + let cookie:ICookie = this.sdcConfig.cookie; + let authorizeHeaders:Headers = new Headers(); + authorizeHeaders.set(cookie.userFirstName, this.cookieService.getFirstName()); + authorizeHeaders.set(cookie.userLastName, this.cookieService.getLastName()); + authorizeHeaders.set(cookie.userEmail, this.cookieService.getEmail()); + authorizeHeaders.set(cookie.userIdSuffix, this.cookieService.getUserId()); + + return this.httpService.get( + this.authorizeUrl, + { headers: authorizeHeaders } + ).map(resp => resp.json()); + } + + public getAllUsers() :Observable<IUserProperties[]> { + return this.httpService.get( + this.sdcConfig.api.root + this.sdcConfig.api.GET_all_users + ).map(resp => resp.json()); + } + + public getUser(userId:string) :Observable<IUserProperties> { + return this.httpService.get( + HttpService.replaceUrlParams(this.url, { id: userId }) + ).map(resp => resp.json()); + } + + public createUser(userData:{[index:string]: any}) :Observable<IUserProperties> { + return this.httpService.post( + this.sdcConfig.api.root + this.sdcConfig.api.POST_create_user, + userData + ).map(resp => resp.json()); + } + + public deleteUser(userId:string) :Observable<IUserProperties> { + return this.httpService.delete( + HttpService.replaceUrlParams(this.sdcConfig.api.root + this.sdcConfig.api.DELETE_delete_user, { id: userId }) + ).map(resp => resp.json()); + } + + public editUserRole(userId:string, role:string) :Observable<IUserProperties> { + return this.httpService.post( + HttpService.replaceUrlParams(this.sdcConfig.api.root + this.sdcConfig.api.POST_edit_user_role, { id: userId }), + { role: role } + ).map(resp => resp.json()); + } + + public getLoggedinUser():IUserProperties { + return this._loggedinUser; + } + + public setLoggedinUser(loggedinUser:IUserProperties) { + this._loggedinUser = loggedinUser; + }; +} diff --git a/catalog-ui/src/app/ng2/shared/shared.module.ts b/catalog-ui/src/app/ng2/shared/translator/translate.module.ts index 2bc7d52ab8..feaec03bbd 100644 --- a/catalog-ui/src/app/ng2/shared/shared.module.ts +++ b/catalog-ui/src/app/ng2/shared/translator/translate.module.ts @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,23 +18,15 @@ * ============LICENSE_END========================================================= */ -import { NgModule } from '@angular/core'; +import { NgModule } from '@angular/core' -import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; -import { NavbarModule } from "./navbar/navbar.module"; +import { TranslateService } from "./translate.service"; +import { TranslatePipe } from "./translate.pipe"; -@NgModule({ - declarations: [ - ], - imports: [ - CommonModule, - RouterModule, - NavbarModule - ], - exports: [ - ] +@NgModule({ + providers: [TranslateService], + declarations: [TranslatePipe], + exports: [TranslatePipe] }) - -export class SharedModule {} +export class TranslateModule { } diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts b/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts new file mode 100644 index 0000000000..42e019829f --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/translator/translate.pipe.ts @@ -0,0 +1,62 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { Pipe, PipeTransform } from '@angular/core'; +import { TranslateService, ITranslateArgs } from "./translate.service"; + + +@Pipe({ + name: 'translate', + pure: false +}) +export class TranslatePipe implements PipeTransform { + private translated:string; + private lastParams: { + phrase: string; + args: {[index: string]: any}; + language: string; + } = { + phrase: undefined, + args: undefined, + language: undefined + }; + + constructor(private translateService:TranslateService) { + } + + private shouldUpdate(curParams:{[index:string]: any}) : boolean { + return ( + curParams.language !== this.lastParams.language || + curParams.args !== this.lastParams.args || + curParams.phrase !== this.lastParams.phrase + ); + } + + public transform(phrase:string, args:ITranslateArgs, language:string=this.translateService.activeLanguage) : string { + const curParams = { phrase, args, language }; + if (this.shouldUpdate(curParams)) { + this.lastParams = curParams; + this.translated = this.translateService.translate(phrase, args, language); + console.log('*updated:', this.translated); + } + + return this.translated; + } +} diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts b/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts new file mode 100644 index 0000000000..a1d7833062 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/translator/translate.service.config.ts @@ -0,0 +1,30 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { OpaqueToken } from "@angular/core"; + +export const TranslateServiceConfigToken = new OpaqueToken('TranslateServiceConfigToken'); + +export interface ITranslateServiceConfig { + filePrefix:string; + fileSuffix:string; + allowedLanguages:string[]; + defaultLanguage:string; +} diff --git a/catalog-ui/src/app/ng2/shared/translator/translate.service.ts b/catalog-ui/src/app/ng2/shared/translator/translate.service.ts new file mode 100644 index 0000000000..ff7c643b46 --- /dev/null +++ b/catalog-ui/src/app/ng2/shared/translator/translate.service.ts @@ -0,0 +1,235 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +import { Injectable, Inject } from "@angular/core"; +import { Response, Http } from "@angular/http"; +import { Observable, Observer, ConnectableObservable, Subscription } from "rxjs"; +import { ITranslateServiceConfig, TranslateServiceConfigToken } from "./translate.service.config"; + +export { ITranslateServiceConfig, TranslateServiceConfigToken }; + +export interface ITranslateLanguageJson { + [index:string]: string; +} + +export interface ITranslateArgs { + [index:string]: any; +} + +export class PhraseTranslator { + private _observable:ConnectableObservable<string>; + private _observer:Observer<string>; + private _languageChangeSubscription:Subscription; + + private _phraseKey:string; + private _args:ITranslateArgs; + private _language:string; + + private _markForCheck:boolean = false; + private _lastParams: { + phraseKey: string; + args: {[index: string]: any}; + language: string; + } = { + phraseKey: undefined, + args: undefined, + language: undefined + }; + + constructor(private translateService:TranslateService) { + this._observable = Observable.create(observer => { + this._observer = observer; + this._languageChangeSubscription = this.translateService.languageChangedObservable.subscribe(language => { + // using the active language, then force update + if (!this._language) { + this.update(true); + } + }); + }).publishReplay(1).refCount(); + } + + public get observable() { + return this._observable; + } + + public destroy() { + this._observer.complete(); + this._languageChangeSubscription.unsubscribe(); + + delete this._observable; + delete this._observer; + delete this._languageChangeSubscription; + } + + public shouldUpdate() : boolean { + if (!this._markForCheck) { + return false; + } + this._markForCheck = false; + return ( + this._language !== this._lastParams.language || + this._args !== this._lastParams.args || + this._phraseKey !== this._lastParams.phraseKey + ); + } + + public update(forceUpdate:boolean=false) : void { + // only update translation when having subscriptions connected. + if (this._observer && !this._observer.closed) { + if (forceUpdate || this.shouldUpdate()) { + this._lastParams = { + phraseKey: this._phraseKey, + args: this._args, + language: this._language + }; + this._markForCheck = false; + + const translated = this.translateService.translate(this._phraseKey, this._args, this._language); + this._observer.next(translated); + } + } + } + + private _changeParam(paramKey:string, value:any, update:boolean) : void { + this[`_${paramKey}`] = value; + this._markForCheck = true; + if (update) { + this.update(); + } + } + + public changePhraseKey(phraseKey:string, update:boolean=true) : void { + this._changeParam('phraseKey', phraseKey, update); + } + + public changeArgs(args:ITranslateArgs, update:boolean=true) :void { + this._changeParam('args', args, update); + } + + public changeLangauge(language:string, update:boolean=true) :void { + this._changeParam('language', language, update); + } + + public changeParams(phraseKey:string, args:ITranslateArgs={}, language?:string, forceUpdate:boolean=false) { + this._phraseKey = phraseKey; + this._args = args; + this._language = language; + this._markForCheck = true; + this.update(forceUpdate); + } +} + + +@Injectable() +export class TranslateService { + private _activeLanguage:string; + private _languageChangedObservable:ConnectableObservable<string>; + private _languageChangedObserver:Observer<string>; + private _cacheLanguagesJsons:{[index:string]:ITranslateLanguageJson} = {}; + private _cacheLanguagesLoaders:{[index:string]:Observable<ITranslateLanguageJson>} = {}; + + constructor(@Inject(TranslateServiceConfigToken) private config:ITranslateServiceConfig, private http:Http) { + this.initLanguageObservable(); + this.loadAndActivateLanguage(this.config.defaultLanguage); + } + + public get languageChangedObservable() : Observable<string> { + return this._languageChangedObservable; + } + + public get activeLanguage() { + return this._activeLanguage; + } + + private initLanguageObservable() { + this._languageChangedObservable = ConnectableObservable.create(observer => { + this._languageChangedObserver = observer; + }).publishReplay(1); // replay last emitted change on subscribe + this._languageChangedObservable.connect(); + } + + private loadLanguageJsonFile(language:string, emitOnLoad:boolean=true) : Observable<ITranslateLanguageJson> { + if (this.config.allowedLanguages.indexOf(language) === -1) { + return Observable.throw(`Language "${language}" is not available.`); + } + + if (this._cacheLanguagesJsons[language]) { + return Observable.of(this._cacheLanguagesJsons[language]); + } + + if (!(language in this._cacheLanguagesLoaders)) { + const filePath = `${this.config.filePrefix}${language}${this.config.fileSuffix}`; + this._cacheLanguagesLoaders[language] = this.http.get(filePath) + .map<Response, ITranslateLanguageJson>(resp => resp.json()) + .catch(() => Observable.throw(`Failed to load language file for "${language}"`)) + .publish(); + (<ConnectableObservable<ITranslateLanguageJson>>this._cacheLanguagesLoaders[language]).connect(); + this._cacheLanguagesLoaders[language].subscribe(languageJson => { + this._cacheLanguagesJsons[language] = languageJson; + delete this._cacheLanguagesLoaders[language]; + if (emitOnLoad) { + this._languageChangedObserver.next(language); + } + return languageJson; + }); + } + return this._cacheLanguagesLoaders[language]; + } + + public activateLanguage(language:string) : boolean { + if (this._cacheLanguagesJsons[language]) { + if (language !== this._activeLanguage) { + this._activeLanguage = language; + this._languageChangedObserver.next(this._activeLanguage); + } + return true; + } + return false; + } + + public loadAndActivateLanguage(language:string) : Observable<ITranslateLanguageJson> { + const loadLanguageObservable = this.loadLanguageJsonFile(language, false); + loadLanguageObservable.subscribe(() => { + this.activateLanguage(language); + }, () => {}); + return loadLanguageObservable; + } + + public translate(phraseKey:string, args:ITranslateArgs={}, language:string=this._activeLanguage) : string { + const phrase:string = (this._cacheLanguagesJsons[language] || {})[phraseKey] || ''; + let translated:string; + if (typeof(phrase) === 'string') { + translated = phrase + .replace( + /(^|[^\\]|\\\\)\{\{(\w+)\}\}/g, + (m, p1, p2) => `${p1}${args[p2]||''}` + ) + .replace('\\{{', '{{') + .replace('\\\\', '\\'); + } + return translated; + } + + public createPhraseTranslator(phraseKey?:string, args?:ITranslateArgs, language?:string) : PhraseTranslator { + const phraseTranslator = new PhraseTranslator(this); + phraseTranslator.changeParams(phraseKey, args, language); + return phraseTranslator; + } +} diff --git a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts index ce13a8c235..c21817c001 100644 --- a/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts +++ b/catalog-ui/src/app/ng2/utils/ng1-upgraded-provider.ts @@ -42,6 +42,10 @@ export function cookieServiceFactory(cacheObj: ICacheObject) { return cacheObj.get('Sdc.Services.CookieService'); } +export function stateServiceFactory(cacheObj: ICacheObject) { + return cacheObj.get('$state'); +} + export function stateParamsServiceFactory(cacheObj: ICacheObject) { return cacheObj.get('$stateParams'); } @@ -74,6 +78,12 @@ export const CookieServiceProvider = { deps: ['$injector'] }; +export const StateServiceFactory = { + provide: '$state', + useFactory: stateServiceFactory, + deps: ['$injector'] +}; + export const StateParamsServiceFactory = { provide: '$stateParams', useFactory: stateParamsServiceFactory, diff --git a/catalog-ui/src/app/services.ts b/catalog-ui/src/app/services.ts index 5dd08c2d20..79b5132634 100644 --- a/catalog-ui/src/app/services.ts +++ b/catalog-ui/src/app/services.ts @@ -46,6 +46,5 @@ export * from './services/progress-service'; export * from './services/sdc-version-service'; export * from './services/sharing-service'; export * from './services/url-tobase64-service'; -export * from './services/user-resource-service'; export * from './services/angular-js-bridge-service'; diff --git a/catalog-ui/src/app/services/components/component-service.ts b/catalog-ui/src/app/services/components/component-service.ts index bedfed5ee5..90ae850899 100644 --- a/catalog-ui/src/app/services/components/component-service.ts +++ b/catalog-ui/src/app/services/components/component-service.ts @@ -52,6 +52,7 @@ export interface IComponentService { deleteComponentInstance(componentId:string, componentInstanceId:string):ng.IPromise<ComponentInstance>; createRelation(componentId:string, link:RelationshipModel):ng.IPromise<RelationshipModel>; deleteRelation(componentId:string, link:RelationshipModel):ng.IPromise<RelationshipModel>; + fetchRelation(componentId:string, linkId:string):ng.IPromise<RelationshipModel>; getRequirementsCapabilities(componentId:string):ng.IPromise<any>; updateInstanceProperty(componentId:string, property:PropertyModel):ng.IPromise<PropertyModel>; updateInstanceAttribute(componentId:string, attribute:AttributeModel):ng.IPromise<AttributeModel>; @@ -513,7 +514,12 @@ export class ComponentService implements IComponentService { public createRelation = (componentId:string, link:RelationshipModel):ng.IPromise<RelationshipModel> => { let deferred = this.$q.defer(); - this.restangular.one(componentId).one("resourceInstance").one("associate").customPOST(JSON.stringify(link)).then((response:any) => { + const linkPayload:RelationshipModel = new RelationshipModel(link); + linkPayload.relationships.forEach((rel) => { + delete rel.capability; + delete rel.requirement; + }); + this.restangular.one(componentId).one("resourceInstance").one("associate").customPOST(JSON.stringify(linkPayload)).then((response:any) => { let relation:RelationshipModel = new RelationshipModel(response.plain()); console.log("Link created successfully ", relation); deferred.resolve(relation); @@ -526,7 +532,12 @@ export class ComponentService implements IComponentService { public deleteRelation = (componentId:string, link:RelationshipModel):ng.IPromise<RelationshipModel> => { let deferred = this.$q.defer(); - this.restangular.one(componentId).one("resourceInstance").one("dissociate").customPUT(JSON.stringify(link)).then((response:any) => { + const linkPayload:RelationshipModel = new RelationshipModel(link); + linkPayload.relationships.forEach((rel) => { + delete rel.capability; + delete rel.requirement; + }); + this.restangular.one(componentId).one("resourceInstance").one("dissociate").customPUT(JSON.stringify(linkPayload)).then((response:any) => { let relation:RelationshipModel = new RelationshipModel(response); console.log("Link deleted successfully ", relation); deferred.resolve(relation); @@ -537,6 +548,19 @@ export class ComponentService implements IComponentService { return deferred.promise; }; + public fetchRelation = (componentId:string, linkId:string):ng.IPromise<RelationshipModel> => { + let deferred = this.$q.defer<RelationshipModel>(); + this.restangular.one(componentId).one("relationId").one(linkId).get().then((response:any) => { + let relation:RelationshipModel = new RelationshipModel(response); + console.log("Link fetched successfully ", relation); + deferred.resolve(relation); + }, (err)=> { + console.log("Failed to fetch Link Id: " + linkId); + deferred.reject(err); + }); + return deferred.promise; + }; + public getRequirementsCapabilities = (componentId:string):ng.IPromise<any> => { let deferred = this.$q.defer(); this.restangular.one(componentId).one("requirmentsCapabilities").get().then((response:any) => { diff --git a/catalog-ui/src/app/services/entity-service.ts b/catalog-ui/src/app/services/entity-service.ts index 75ea036b3e..27b0513b39 100644 --- a/catalog-ui/src/app/services/entity-service.ts +++ b/catalog-ui/src/app/services/entity-service.ts @@ -23,6 +23,7 @@ import { Service, IApi, IAppConfigurtaion, Resource, Component} from "../models" import {SharingService} from "./sharing-service"; import {ComponentFactory} from "../utils/component-factory"; import {CacheService} from "./cache-service"; +import {ResourceType} from "app/utils"; interface IEntityService { getAllComponents():ng.IPromise<Array<Component>>; @@ -48,7 +49,7 @@ export class EntityService implements IEntityService { getCatalog = ():ng.IPromise<Array<Component>> => { let defer = this.$q.defer<Array<Component>>(); - this.$http.get(this.api.root + this.api.GET_catalog) + this.$http.get(this.api.root + this.api.GET_catalog, {params: {excludeTypes: [ResourceType.VFCMT, ResourceType.CONFIGURATION]}}) .then((response:any) => { let followedResponse: IComponentsArray = response.data; let componentsList:Array<Component> = new Array(); diff --git a/catalog-ui/src/app/services/loader-service.ts b/catalog-ui/src/app/services/loader-service.ts index 2f8746cbd8..6085eb16bf 100644 --- a/catalog-ui/src/app/services/loader-service.ts +++ b/catalog-ui/src/app/services/loader-service.ts @@ -32,12 +32,12 @@ export class LoaderService { } - public showLoader(...args) { - this.eventListenerService.notifyObservers(EVENTS.SHOW_LOADER_EVENT, ...args); + public showLoader(loaderType:string, ...args) { + this.eventListenerService.notifyObservers(EVENTS.SHOW_LOADER_EVENT + loaderType, ...args); } - public hideLoader(...args) { - this.eventListenerService.notifyObservers(EVENTS.HIDE_LOADER_EVENT, ...args); + public hideLoader(loaderType:string, ...args) { + this.eventListenerService.notifyObservers(EVENTS.HIDE_LOADER_EVENT + loaderType, ...args); } } diff --git a/catalog-ui/src/app/services/user-resource-service.ts b/catalog-ui/src/app/services/user-resource-service.ts deleted file mode 100644 index bdd9fc3303..0000000000 --- a/catalog-ui/src/app/services/user-resource-service.ts +++ /dev/null @@ -1,123 +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 {IUserProperties} from "../models/user"; -import {ICookie, IAppConfigurtaion} from "../models/app-config"; -import {CookieService} from "./cookie-service"; - -// Define an interface of the object you want to use, providing it's properties -export interface IUserResource extends IUserProperties,ng.resource.IResource<IUserResource> { - -} - -// Define your resource, adding the signature of the custom actions -export interface IUserResourceClass extends ng.resource.IResourceClass<IUserResource> { - authorize():IUserResource; - getLoggedinUser():IUserResource; - setLoggedinUser(user:IUserResource):void; - getAllUsers(success?:Function, error?:Function):Array<IUserResource>; - createUser(IResourceResource, success?:Function, error?:Function):void; - editUserRole(IResourceResource, success?:Function, error?:Function):void; - deleteUser(IResourceResource, success?:Function, error?:Function):void; -} - -export class UserResourceService { - - public static getResource = ($resource:ng.resource.IResourceService, - sdcConfig:IAppConfigurtaion, - cookieService:CookieService):IUserResourceClass => { - - let url:string = sdcConfig.api.root + sdcConfig.api.GET_user; - let authorizeUrl:string = sdcConfig.api.root + sdcConfig.api.GET_user_authorize; - let authorizeActionHeaders:any = {}; - let cookie:ICookie = sdcConfig.cookie; - authorizeActionHeaders[cookie.userFirstName] = cookieService.getFirstName(); - authorizeActionHeaders[cookie.userLastName] = cookieService.getLastName(); - authorizeActionHeaders[cookie.userEmail] = cookieService.getEmail(); - authorizeActionHeaders[cookie.userIdSuffix] = cookieService.getUserId(); - - // Define your custom actions here as IActionDescriptor - let authorizeAction:ng.resource.IActionDescriptor = { - method: 'GET', - isArray: false, - url: authorizeUrl, - headers: authorizeActionHeaders - }; - - let getAllUsers:ng.resource.IActionDescriptor = { - method: 'GET', - isArray: true, - url: sdcConfig.api.root + sdcConfig.api.GET_all_users - }; - - let editUserRole:ng.resource.IActionDescriptor = { - method: 'POST', - isArray: false, - url: sdcConfig.api.root + sdcConfig.api.POST_edit_user_role, - transformRequest: (data, headers)=> { - data.payloadData = undefined; - data.payloadName = undefined; - return JSON.stringify(data); - } - }; - - let deleteUser:ng.resource.IActionDescriptor = { - method: 'DELETE', - isArray: false, - url: sdcConfig.api.root + sdcConfig.api.DELETE_delete_user - }; - - let createUser:ng.resource.IActionDescriptor = { - method: 'POST', - isArray: false, - url: sdcConfig.api.root + sdcConfig.api.POST_create_user, - transformRequest: (data, headers)=> { - data.payloadData = undefined; - data.payloadName = undefined; - return JSON.stringify(data); - } - }; - let userResource:IUserResourceClass = <IUserResourceClass>$resource( - url, - {id: '@id'}, - { - authorize: authorizeAction, - getAllUsers: getAllUsers, - createUser: createUser, - editUserRole: editUserRole, - deleteUser: deleteUser - } - ); - - let _loggedinUser:IUserResource; - - userResource.getLoggedinUser = () => { - return _loggedinUser; - }; - - userResource.setLoggedinUser = (loggedinUser:IUserResource) => { - _loggedinUser = loggedinUser; - }; - - return userResource; - } -} -UserResourceService.getResource.$inject = ['$resource', 'sdcConfig', 'Sdc.Services.CookieService']; diff --git a/catalog-ui/src/app/utils/component-factory.ts b/catalog-ui/src/app/utils/component-factory.ts index b35918c0f6..f869ef68d3 100644 --- a/catalog-ui/src/app/utils/component-factory.ts +++ b/catalog-ui/src/app/utils/component-factory.ts @@ -70,6 +70,22 @@ export class ComponentFactory { return newResource; }; + public updateComponentFromCsar = (csarComponent:Resource, oldComponent:Resource):Component => { + _.pull(oldComponent.tags, oldComponent.name); + oldComponent.name = csarComponent.name; + oldComponent.selectedCategory = csarComponent.selectedCategory; + oldComponent.categories = csarComponent.categories; + oldComponent.vendorName = csarComponent.vendorName; + oldComponent.vendorRelease = csarComponent.vendorRelease; + oldComponent.csarUUID = csarComponent.csarUUID; + oldComponent.csarPackageType = csarComponent.csarPackageType; + oldComponent.csarVersion = csarComponent.csarVersion; + oldComponent.packageId = csarComponent.packageId; + oldComponent.description = csarComponent.description; + oldComponent.filterTerm = oldComponent.name + ' ' + oldComponent.description + ' ' + oldComponent.vendorName + ' ' + oldComponent.csarVersion + return oldComponent; + }; + public createFromCsarComponent = (csar:ICsarComponent):Component => { let newResource:Resource = <Resource>this.createEmptyComponent(ComponentType.RESOURCE); newResource.name = csar.vspName; @@ -124,7 +140,7 @@ export class ComponentFactory { let newComponent:Component; switch (componentType) { - + case ComponentType.SERVICE_PROXY: case ComponentType.SERVICE: newComponent = new Service(this.ServiceService, this.$q); break; @@ -136,6 +152,7 @@ export class ComponentFactory { case ResourceType.CP: case ResourceType.PNF: case ResourceType.CVFC: + case ResourceType.CONFIGURATION: newComponent = new Resource(this.ResourceService, this.$q); break; } diff --git a/catalog-ui/src/app/utils/component-instance-factory.ts b/catalog-ui/src/app/utils/component-instance-factory.ts index 9e25e6b02f..25916cc055 100644 --- a/catalog-ui/src/app/utils/component-instance-factory.ts +++ b/catalog-ui/src/app/utils/component-instance-factory.ts @@ -21,7 +21,8 @@ * Created by obarda on 3/7/2016. */ 'use strict'; -import {ComponentInstance, ServiceInstance, ResourceInstance, Component} from "../models"; +import {ComponentInstance, ServiceInstance, ResourceInstance, Component, ServiceProxyInstance} from "../models"; +import {ComponentType} from "app/utils"; import {LeftPaletteComponent} from "../models/components/displayComponent"; export class ComponentInstanceFactory { @@ -29,10 +30,12 @@ export class ComponentInstanceFactory { static createComponentInstance(componentInstance:ComponentInstance):ComponentInstance { let newComponentInstance:ComponentInstance; switch (componentInstance.originType) { - case 'SERVICE': + case ComponentType.SERVICE: newComponentInstance = new ServiceInstance(componentInstance); break; - + case ComponentType.SERVICE_PROXY: + newComponentInstance = new ServiceProxyInstance(componentInstance); + break; default : newComponentInstance = new ResourceInstance(componentInstance); break; @@ -43,10 +46,12 @@ export class ComponentInstanceFactory { public createEmptyComponentInstance = (componentInstanceType?:string):ComponentInstance => { let newComponentInstance:ComponentInstance; switch (componentInstanceType) { - case 'SERVICE': + case ComponentType.SERVICE: newComponentInstance = new ServiceInstance(); break; - + case ComponentType.SERVICE_PROXY: + newComponentInstance = new ServiceProxyInstance(); + break; default : newComponentInstance = new ResourceInstance(); break; @@ -62,6 +67,9 @@ export class ComponentInstanceFactory { newComponentInstance.name = component.name; newComponentInstance.componentVersion = component.version; newComponentInstance.originType = component.getComponentSubType(); + if(component.getComponentSubType() === ComponentType.SERVICE){ + newComponentInstance.originType = ComponentType.SERVICE_PROXY + } //new component instance -> req. & cap. are added on successful instance creation newComponentInstance.requirements = component.requirements; newComponentInstance.capabilities = component.capabilities; diff --git a/catalog-ui/src/app/utils/constants.ts b/catalog-ui/src/app/utils/constants.ts index 6ec6a7762b..3ea652a7dd 100644 --- a/catalog-ui/src/app/utils/constants.ts +++ b/catalog-ui/src/app/utils/constants.ts @@ -29,6 +29,7 @@ export let CHANGE_COMPONENT_CSAR_VERSION_FLAG = 'changeComponentCsarVersion'; export class ComponentType { static SERVICE = 'SERVICE'; static RESOURCE = 'RESOURCE'; + static SERVICE_PROXY = 'ServiceProxy' } export class ServerTypeUrl { @@ -44,6 +45,7 @@ export class ResourceType { static VFCMT = 'VFCMT'; static PNF = 'PNF'; static CVFC = 'CVFC'; + static CONFIGURATION = 'Configuration'; } export class ComponentState { @@ -114,6 +116,7 @@ export class SOURCES { export class PROPERTY_DATA { public static TYPES = [PROPERTY_TYPES.STRING, PROPERTY_TYPES.INTEGER, PROPERTY_TYPES.FLOAT, PROPERTY_TYPES.BOOLEAN, PROPERTY_TYPES.JSON, PROPERTY_TYPES.SCALAR, PROPERTY_TYPES.SCALAR_FREQUENCY, PROPERTY_TYPES.SCALAR_SIZE, PROPERTY_TYPES.SCALAR_TIME, PROPERTY_TYPES.LIST, PROPERTY_TYPES.MAP]; public static SIMPLE_TYPES = [PROPERTY_TYPES.STRING, PROPERTY_TYPES.INTEGER, PROPERTY_TYPES.FLOAT, PROPERTY_TYPES.BOOLEAN, PROPERTY_TYPES.JSON, PROPERTY_TYPES.SCALAR, PROPERTY_TYPES.SCALAR_FREQUENCY, PROPERTY_TYPES.SCALAR_SIZE, PROPERTY_TYPES.SCALAR_TIME]; + public static SCALAR_TYPES = [PROPERTY_TYPES.SCALAR, PROPERTY_TYPES.SCALAR_FREQUENCY, PROPERTY_TYPES.SCALAR_SIZE, PROPERTY_TYPES.SCALAR_TIME]; public static ROOT_DATA_TYPE = "tosca.datatypes.Root"; public static OPENECOMP_ROOT = "org.openecomp.datatypes.Root"; public static SUPPLEMENTAL_DATA = "supplemental_data"; @@ -150,6 +153,7 @@ export class WorkspaceMode { export class ImagesUrl { public static RESOURCE_ICONS = '/assets/styles/images/resource-icons/'; public static SERVICE_ICONS = '/assets/styles/images/service-icons/'; + public static SERVICE_PROXY_ICONS = '/assets/styles/images/service-proxy-icons/'; public static SELECTED_UCPE_INSTANCE = '/assets/styles/images/resource-icons/selectedUcpeInstance.png'; public static SELECTED_CP_INSTANCE = '/assets/styles/images/resource-icons/selectedCPInstance.png'; public static SELECTED_VL_INSTANCE = '/assets/styles/images/resource-icons/selectedVLInstance.png'; @@ -249,6 +253,7 @@ export class EVENTS { static ON_WORKSPACE_SAVE_BUTTON_SUCCESS = "onWorkspaceSaveButtonSuccess"; static ON_WORKSPACE_SAVE_BUTTON_ERROR = "onWorkspaceSaveButtonError"; static ON_CHECKOUT = "onCheckout"; + static ON_REVERT = "onRevert"; //Loader events static SHOW_LOADER_EVENT = "showLoaderEvent"; diff --git a/catalog-ui/src/app/utils/menu-handler.ts b/catalog-ui/src/app/utils/menu-handler.ts index 351311a48f..1a3215bf80 100644 --- a/catalog-ui/src/app/utils/menu-handler.ts +++ b/catalog-ui/src/app/utils/menu-handler.ts @@ -116,7 +116,11 @@ export class MenuHandler { }); } - result.selectedIndex = components.indexOf(selectedItem); + if(!selectedItem){ + result.selectedIndex = components.length; + }else{ + result.selectedIndex = components.indexOf(selectedItem); + } components[result.selectedIndex] = selected; let clickItemCallback = (component:Component):ng.IPromise<boolean> => { this.$state.go('workspace.general', { diff --git a/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view.html b/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view.html index 150f7c2554..924d46e932 100644 --- a/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view.html +++ b/catalog-ui/src/app/view-models/admin-dashboard/admin-dashboard-view.html @@ -22,5 +22,4 @@ <ng-include src="templateUrl" ng-if="true"></ng-include> </div> - <ecomp-footer></ecomp-footer> </div> diff --git a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts index e1f3a50b44..db94a475d1 100644 --- a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts +++ b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view-model.ts @@ -20,8 +20,8 @@ 'use strict'; import {ModalsHandler} from "app/utils"; -import {IUserResource, IUserResourceClass} from "app/services"; import {User, IUserProperties, IUser, IAppConfigurtaion} from "app/models"; +import {UserService} from "../../../ng2/services/user.service"; interface IUserManagementViewModelScope extends ng.IScope { sdcConfig:IAppConfigurtaion; @@ -33,7 +33,7 @@ interface IUserManagementViewModelScope extends ng.IScope { tableHeadersList:any; roles:Array<string>; newUser:IUser; - currentUser:IUserResource; + currentUser:IUserProperties; userIdValidationPattern:RegExp; editForm:ng.IFormController; getAllUsers():void; @@ -53,7 +53,7 @@ export class UserManagementViewModel { static '$inject' = [ '$scope', 'sdcConfig', - 'Sdc.Services.UserResourceService', + 'UserServiceNg2', 'UserIdValidationPattern', '$filter', 'ModalsHandler' @@ -61,7 +61,7 @@ export class UserManagementViewModel { constructor(private $scope:IUserManagementViewModelScope, private sdcConfig:IAppConfigurtaion, - private userResourceService:IUserResourceClass, + private userService:UserService, private UserIdValidationPattern:RegExp, private $filter:ng.IFilterService, private ModalsHandler:ModalsHandler) { @@ -85,7 +85,7 @@ export class UserManagementViewModel { }); this.$scope.isLoading = false; }; - this.userResourceService.getAllUsers(onSuccess, onError); + this.userService.getAllUsers().subscribe(onSuccess, onError); }; private updateUserFilterTerm = (user:IUserProperties):void => { @@ -111,11 +111,11 @@ export class UserManagementViewModel { this.$scope.reverse = false; this.$scope.roles = this.sdcConfig.roles; this.$scope.isNewUser = false; - this.$scope.currentUser = this.userResourceService.getLoggedinUser(); + this.$scope.currentUser = this.userService.getLoggedinUser(); this.getAllUsers(); - let resource:IUserResource = <IUserResource>{}; - this.$scope.newUser = new User(resource); + let userInfo:IUserProperties = <IUserProperties>{}; + this.$scope.newUser = new User(userInfo); this.$scope.sort = (sortBy:string):void => {//default sort by descending last update. default for alphabetical = ascending this.$scope.isNewUser = false; @@ -131,13 +131,12 @@ export class UserManagementViewModel { }; let onSuccess = (response:IUserProperties) => { - this.$scope.newUser.resource['index'] = this.$scope.usersList.length; - this.$scope.newUser.resource.lastLoginTime = "0"; - this.$scope.newUser.resource.status = response.status; - this.updateUserFilterTerm(this.$scope.newUser.resource); - this.$scope.usersList.unshift(this.$scope.newUser.resource); + this.$scope.newUser.userInfo.lastLoginTime = "0"; + this.$scope.newUser.userInfo.status = response.status; + this.updateUserFilterTerm(this.$scope.newUser.userInfo); + this.$scope.usersList.push(this.$scope.newUser.userInfo); this.$scope.isNewUser = true; - this.$scope.sortBy = 'index'; + this.$scope.sortBy = null; this.$scope.reverse = true; this.$scope.isLoading = false; this.$scope.newUser = new User(null); @@ -147,10 +146,10 @@ export class UserManagementViewModel { _self.$scope.isNewUser = false; }, 7000); }; - this.userResourceService.createUser({ - userId: this.$scope.newUser.resource.userId, - role: this.$scope.newUser.resource.role - }, onSuccess, onError); + this.userService.createUser({ + userId: this.$scope.newUser.userInfo.userId, + role: this.$scope.newUser.userInfo.role + }).subscribe(onSuccess, onError); }; @@ -174,7 +173,7 @@ export class UserManagementViewModel { this.updateUserFilterTerm(user); }; - this.userResourceService.editUserRole({id: user.userId, role: user.role}, onSuccess, onError); + this.userService.editUserRole(user.userId, user.role).subscribe(onSuccess, onError); }; this.$scope.saveUserChanges = (user:IUserProperties):void => { @@ -198,7 +197,7 @@ export class UserManagementViewModel { _.remove(this.$scope.usersList, {userId: userId}); this.$scope.isLoading = false; }; - this.userResourceService.deleteUser({id: userId}, onSuccess, onError); + this.userService.deleteUser(userId).subscribe(onSuccess, onError); }; let title:string = this.$filter('translate')("USER_MANAGEMENT_VIEW_DELETE_MODAL_TITLE"); diff --git a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html index d2983873cc..2f94fb4aee 100644 --- a/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html +++ b/catalog-ui/src/app/view-models/admin-dashboard/user-management/user-management-view.html @@ -14,7 +14,7 @@ <div class="sdc-user-management-top-bar-wrapper"> <div class="i-sdc-form-item sdc-user-management-top-bar-form-container" data-ng-class="{error:(editForm.contactId.$dirty && editForm.contactId.$invalid)}"> <input ng-focus="search.filterTerm=''" type="text" - data-ng-model="newUser.resource.userId" + data-ng-model="newUser.userInfo.userId" class="i-sdc-form-input" placeholder="{{ USER_MANAGEMENT_SEARCH_TEXT | translate}}" data-ng-model-options="{ updateOn: 'default blur', debounce: { 'default': 750, 'blur': 0 } }" @@ -36,7 +36,7 @@ data-required name="role" data-tests-id="selectrole" - data-ng-model = "newUser.resource.role" + data-ng-model = "newUser.userInfo.role" data-ng-options="role as (getTitle(role)) for role in roles | orderBy:'role'" ng-focus="search.filterTerm=''"> <option value="">Select Role</option> 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 ec9e888eed..10aa47e0ed 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 @@ -20,8 +20,9 @@ 'use strict'; import {Component, IMainCategory, IGroup, IConfigStatuses, IAppMenu, IAppConfigurtaion, IUserProperties, ISubCategory} from "app/models"; -import {EntityService, IUserResourceClass, CacheService} from "app/services"; +import {EntityService, CacheService} from "app/services"; import {ComponentFactory, ResourceType, MenuHandler, ChangeLifecycleStateHandler} from "app/utils"; +import {UserService} from "../../ng2/services/user.service"; interface Checkboxes { @@ -87,7 +88,7 @@ export class CatalogViewModel { 'sdcMenu', '$state', '$q', - 'Sdc.Services.UserResourceService', + 'UserServiceNg2', 'Sdc.Services.CacheService', 'ComponentFactory', 'ChangeLifecycleStateHandler', @@ -101,7 +102,7 @@ export class CatalogViewModel { private sdcMenu:IAppMenu, private $state:ng.ui.IStateService, private $q:ng.IQService, - private userResourceService:IUserResourceClass, + private userService:UserService, private cacheService:CacheService, private ComponentFactory:ComponentFactory, private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler, @@ -138,7 +139,7 @@ export class CatalogViewModel { this.$scope.sdcMenu = this.sdcMenu; this.$scope.confStatus = this.sdcMenu.statuses; this.$scope.expandedSection = ["type", "category", "status"]; - this.$scope.user = this.userResourceService.getLoggedinUser(); + this.$scope.user = this.userService.getLoggedinUser(); this.$scope.catalogMenuItem = this.sdcMenu.catalogMenuItem; this.$scope.version = this.cacheService.get('version'); this.$scope.sortBy = 'lastUpdateDate'; @@ -158,8 +159,6 @@ export class CatalogViewModel { this.$scope.checkboxesFilter.selectedStatuses = []; // this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.catalogFilterdItems.length; - - this.$scope.vfcmtType = ResourceType.VFCMT; }; private initScopeMethods = ():void => { diff --git a/catalog-ui/src/app/view-models/catalog/catalog-view.html b/catalog-ui/src/app/view-models/catalog/catalog-view.html index 03ca4cb81f..76f23573a1 100644 --- a/catalog-ui/src/app/view-models/catalog/catalog-view.html +++ b/catalog-ui/src/app/view-models/catalog/catalog-view.html @@ -135,7 +135,7 @@ <!-- HEADER --> <div> <div class="w-sdc-dashboard-catalog-header"> - {{getNumOfElements((catalogFilterdItems| filter:{resourceType:('!'+vfcmtType)} | entityFilter:checkboxesFilter | filter:search).length)}} + {{getNumOfElements((catalogFilterdItems| entityFilter:checkboxesFilter | filter:search).length)}} </div> <div class="w-sdc-dashboard-catalog-header-right"> <span class="w-sdc-dashboard-catalog-header-order" translate="SORT_CAPTION"></span> @@ -155,31 +155,32 @@ <!-- Tile new --> <div data-ng-init="component.filterTerm = component.name + ' ' + component.description + ' ' + component.tags.toString() + ' ' + component.version" - class="sdc-tile-catalog sdc-tile-fix-width" - data-ng-repeat="component in catalogFilterdItems| filter:{resourceType:('!'+vfcmtType)} | entityFilter:checkboxesFilter | filter:search | orderBy:sortBy:reverse | limitTo:numberOfItemToDisplay" + class="sdc-tile sdc-tile-fix-width" + data-ng-repeat="component in catalogFilterdItems| entityFilter:checkboxesFilter | filter:search | orderBy:sortBy:reverse | limitTo:numberOfItemToDisplay" > - <div class="sdc-tile-header"> - <div class='sdc-tile-header-type' data-ng-class="{'purple': component.isResource(), 'blue': !component.isResource()}"> - <div data-ng-if="component.isResource()" data-tests-id="asset-type">{{component.getComponentSubType()}}</div> - <div data-ng-if="component.isService()">S</div> - </div> + <div class='sdc-tile-header' data-ng-class="{'purple': component.isResource(), 'blue': !component.isResource()}"> + <div data-ng-if="component.isResource()" data-tests-id="asset-type">{{component.getComponentSubType()}}</div> + <div data-ng-if="component.isService()">S</div> </div> + <div class='sdc-tile-content' data-ng-click="gui.isLoading || goToComponent(component)"> - <div class='sdc-tile-content-icon'> + <div class='sdc-tile-content-icon centered'> <div class="{{component.iconSprite}} {{component.icon}}" data-ng-class="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}" 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-version-info"> - <div class="sdc-tile-content-info-version-info-text" data-tests-id="{{component.name}}Version">V {{component.version}}</div> + <div class="sdc-tile-info-line title" data-tests-id="{{component.name | resourceName}}" sdc-smart-tooltip>{{component.name | resourceName}}</div> + <div class="sdc-tile-info-line subtitle" data-tests-id="{{component.name}}Version"> + V {{component.version}} </div> </div> </div> <div class='sdc-tile-footer'> - <div class='sdc-tile-footer-text'>{{component.getStatus(sdcMenu)}}</div> + <div class="sdc-tile-footer-content"> + <div class='sdc-tile-footer-text'>{{component.getStatus(sdcMenu)}}</div> + </div> </div> </div> @@ -192,8 +193,7 @@ </div> - <top-nav top-lvl-selected-index="1" search-bind="search.filterTerm" version="{{version}}"></top-nav> + <top-nav [top-lvl-selected-index]="1" [search-term]="search.filterTerm" (search-term-change)="search.filterTerm=$event" [version]="version"></top-nav> - <ecomp-footer></ecomp-footer> </div> 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 5480e4f6cf..80a9bcac3e 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 @@ -20,9 +20,10 @@ 'use strict'; import {IConfigRoles, IAppConfigurtaion, IAppMenu, IUserProperties, Component} from "app/models"; -import {EntityService, IUserResourceClass, SharingService, CacheService} from "app/services"; +import {EntityService, SharingService, CacheService} from "app/services"; import {ComponentType, ResourceType, MenuHandler, ModalsHandler, ChangeLifecycleStateHandler, SEVERITY, ComponentFactory} from "app/utils"; import {IClientMessageModalModel} from "../modals/message-modal/message-client-modal/client-message-modal-view-model"; +import {UserService} from "../../ng2/services/user.service"; export interface IDashboardViewModelScope extends ng.IScope { @@ -171,7 +172,7 @@ export class DashboardViewModel { 'sdcMenu', '$state', '$stateParams', - 'Sdc.Services.UserResourceService', + 'UserServiceNg2', 'Sdc.Services.SharingService', 'Sdc.Services.CacheService', '$q', @@ -191,7 +192,7 @@ export class DashboardViewModel { private sdcMenu:IAppMenu, private $state:any, private $stateParams:any, - private userResourceService:IUserResourceClass, + private userService:UserService, private sharingService:SharingService, private cacheService:CacheService, private $q:ng.IQService, @@ -239,7 +240,7 @@ export class DashboardViewModel { this.$scope.isLoading = false; this.$scope.sdcConfig = this.sdcConfig; this.$scope.sdcMenu = this.sdcMenu; - this.$scope.user = this.userResourceService.getLoggedinUser(); + this.$scope.user = this.userService.getLoggedinUser(); this.$scope.roles = this.sdcMenu.roles; this.$scope.showTutorial = false; this.$scope.isFirstTime = false; 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 baf4aa6e51..0ef5f4a1f9 100644 --- a/catalog-ui/src/app/view-models/dashboard/dashboard-view.html +++ b/catalog-ui/src/app/view-models/dashboard/dashboard-view.html @@ -47,29 +47,30 @@ </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"> - - <div class="sdc-tile-header"> - <div class='sdc-tile-header-type' data-ng-class="{'purple': component.isResource(), 'blue': !component.isResource()}"> - <div data-ng-if="component.isResource()" data-tests-id="asset-type">{{component.getComponentSubType()}}</div> - <div data-ng-if="component.isService()">S</div> - </div> + <div class="sdc-tile sdc-tile-fix-width" data-ng-repeat="component in components | filter:{resourceType:('!'+vfcmtType)} | entityFilter:checkboxesFilter | filter:search"> + + <div class='sdc-tile-header' data-ng-class="{'purple': component.isResource(), 'blue': !component.isResource()}"> + <div data-ng-if="component.isResource()" data-tests-id="asset-type">{{component.getComponentSubType()}}</div> + <div data-ng-if="component.isService()">S</div> </div> + <div class='sdc-tile-content' data-tests-id="dashboard-Elements" data-ng-click="goToComponent(component)"> <div class='sdc-tile-content-icon'> <div class="{{component.iconSprite}} {{component.icon}}" data-ng-class="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}" 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-version-info"> - <div class="sdc-tile-content-info-version-info-text" data-tests-id="{{component.name}}Version">V {{component.version}}</div> - </div> + <div class="sdc-tile-info-line title" data-tests-id="{{component.name | resourceName}}" sdc-smart-tooltip>{{component.name | resourceName}}</div> + <div class="sdc-tile-info-line subtitle" data-tests-id="{{component.name}}Version">V {{component.version}}</div> </div> </div> + <div class='sdc-tile-footer'> - <div class='sdc-tile-footer-text'>{{component.getStatus(sdcMenu)}}</div> + <div class="sdc-tile-footer-content"> + <div class='sdc-tile-footer-text'>{{component.getStatus(sdcMenu)}}</div> + </div> </div> </div> @@ -103,10 +104,9 @@ </div> - <top-nav top-lvl-selected-index="0" version="{{version}}" search-bind="search.filterTerm" notification-icon-callback="notificationIconCallback" version="{{version}}"></top-nav> + <top-nav [top-lvl-selected-index]="0" [version]="version" [search-term]="search.filterTerm" (search-term-change)="search.filterTerm=$event" [notification-icon-callback]="notificationIconCallback"></top-nav> </div> <div data-ui-view=""></div> -<ecomp-footer></ecomp-footer> diff --git a/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html b/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html index af0d06787a..bb74374c01 100644 --- a/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html +++ b/catalog-ui/src/app/view-models/dcae-app/dcae-app-view.html @@ -12,6 +12,6 @@ <div id="main" ui-view="main"></div> </div> - <top-nav top-lvl-selected-index="3" search-bind="search.filterTerm" menu-model="topNavMenuModel" version="{{version}}"></top-nav> + <top-nav [top-lvl-selected-index]="3" [search-term]="search.filterTerm" (search-term-change)="search.filterTerm=$event" [menu-model]="topNavMenuModel" [version]="version"></top-nav> </div> diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html index ae13844532..5fd57f6b24 100644 --- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html +++ b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.html @@ -46,7 +46,8 @@ <div class="i-sdc-form-item" data-ng-class="{error:(forms.editForm[parameter.name].$dirty && forms.editForm[parameter.name].$invalid), required: (parameter.defaultValue)}"> <span class="required-symbol">*</span> <div class="input-parameter"> - <input class="i-sdc-form-input" data-ng-class="{error: (forms.editForm[parameter.name].$invalid)}" + <input class="i-sdc-form-input" data-ng-class="{error: (forms.editForm[parameter.name].$invalid), + 'default-value':(parameter.defaultValue && parameter.currentValue === parameter.defaultValue)}" data-ng-model-options="{ debounce: 200 }" data-ng-model="parameter.currentValue" value="{{parameter.currentValue}}" @@ -54,7 +55,7 @@ name="{{parameter.name}}" data-ng-pattern="getValidationPattern(parameter.type, 'heat')" data-ng-required="parameter.defaultValue" - data-ng-change="'json'==parameter.type && forms.editForm[parameter.name].$setValidity('pattern', validateJson(parameter.currentValue))" + data-ng-change="onValueChanged(parameter)" data-ng-blur="(forms.editForm[parameter.name].$error.required && (parameter.currentValue=parameter.defaultValue))" data-tests-id="value-field-of-{{parameter.name}}"/> diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less index a25a2c5f62..e797093271 100644 --- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less +++ b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.less @@ -1,4 +1,3 @@ - .sdc-env-form-container{ .w-sdc-modal-body{ padding: 20px 10px 2px 10px; @@ -110,6 +109,9 @@ width: 100%; display: inline-flex; padding-right: 33px; + &.default-value{ + border-color: @func_color_h; + } } .action-button{ border-left: solid 1px @main_color_o; diff --git a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts index f5962a2f79..a30fd15c63 100644 --- a/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts +++ b/catalog-ui/src/app/view-models/forms/env-parameters-form/env-parameters-form.ts @@ -37,6 +37,7 @@ export interface IEnvParametersFormViewModelScope extends ng.IScope { getValidationPattern(type:string):RegExp; isInstance():boolean; validateJson(json:string):boolean; + onValueChanged(parameter: HeatParameterModel):void; close():void; save():void; openDescPopover(selectedParam:HeatParameterModel):void; @@ -86,7 +87,10 @@ export class EnvParametersFormViewModel { this.$scope.envParametersModal = this.$uibModalInstance; this.$scope.artifactResource = this.artifact; this.$scope.heatParameters = angular.copy(this.artifact.heatParameters); - + //if param does not have a value - display the default + this.$scope.heatParameters.forEach((heatParam) => { + heatParam.currentValue = heatParam.currentValue || heatParam.defaultValue; + }); this.$scope.tableHeadersList = [ {title: "Parameter", property: "name"}, {title: "Default Value", property: "defaultValue", info: "DEFAULT_VALUE_INFO"}, @@ -114,13 +118,13 @@ export class EnvParametersFormViewModel { this.$scope.save = ():void => { this.$scope.buttons[0].disabled = true;//prevent double click (DE246266) this.$scope.isLoading = true; - this.artifact.heatParameters = this.$scope.heatParameters; + this.artifact.heatParameters = angular.copy(this.$scope.heatParameters); this.artifact.heatParameters.forEach((parameter:any):void => { if ("" === parameter.currentValue) { //[Bug 154465] - Update and erase current value field in Env parameters form return empty String ("") instead of null. parameter.currentValue = null; - }else if (!parameter.currentValue && parameter.defaultValue) { - parameter.currentValue = parameter.defaultValue; + } else if (parameter.defaultValue && parameter.defaultValue == parameter.currentValue) { + parameter.currentValue = undefined; } }); @@ -143,6 +147,13 @@ export class EnvParametersFormViewModel { this.component.addOrUpdateArtifact(this.$scope.artifactResource).then(success, error); }; + this.$scope.onValueChanged = (parameter: HeatParameterModel):void => { + parameter.filterTerm = parameter.name + ' ' + parameter.currentValue + ' ' + parameter.defaultValue + ' ' +parameter.description + if('json'==parameter.type){ + this.$scope.forms.editForm[parameter.name].$setValidity('pattern', this.$scope.validateJson(parameter.currentValue)); + } + } + this.$scope.close = ():void => { //this.artifact.heatParameters.forEach((parameter:any):void => { // if (!parameter.currentValue && parameter.defaultValue) { 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 ee2e94f934..0ad55715db 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 @@ -112,6 +112,7 @@ export class PropertyFormViewModel { private initResource = ():void => { this.$scope.editPropertyModel.property = new PropertyModel(this.property); this.$scope.editPropertyModel.property.type = this.property.type ? this.property.type : null; + this.$scope.editPropertyModel.property.value = this.$scope.editPropertyModel.property.value || this.$scope.editPropertyModel.property.defaultValue; this.setMaxLength(); this.initAddOnLabels(); }; @@ -241,7 +242,7 @@ export class PropertyFormViewModel { let onPropertySuccess = (propertyFromBE:PropertyModel):void => { console.info('onPropertyResourceSuccess : ', propertyFromBE); this.$scope.isLoading = false; - + this.filteredProperties[this.$scope.currentPropertyIndex] = propertyFromBE; if (!doNotCloseModal) { this.$uibModalInstance.close(propertyFromBE); } else { diff --git a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts b/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts index cf8c91c5e3..1cc3690e9f 100644 --- a/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts +++ b/catalog-ui/src/app/view-models/modals/onboarding-modal/onboarding-modal-view-model.ts @@ -125,6 +125,7 @@ export class OnboardingModalViewModel { this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, (<Resource>this.$scope.selectedComponent).csarVersion); this.$state.go('workspace.general', { id: this.$scope.componentFromServer.uniqueId, + componentCsar: this.$scope.selectedComponent, type: this.$scope.componentFromServer.componentType.toLowerCase(), disableButtons: true }); diff --git a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html index eec7c4758d..604a1c3647 100644 --- a/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html +++ b/catalog-ui/src/app/view-models/onboard-vendor/onboard-vendor-view.html @@ -5,8 +5,7 @@ <punch-out name="'onboarding/vendor'" data="vendorData" user="user" on-event="onVendorEvent"></punch-out> </div> - <top-nav top-lvl-selected-index="2" search-bind="search.filterTerm" menu-model="topNavMenuModel" version="{{version}}" hide-search="true"></top-nav> + <top-nav [top-lvl-selected-index]="2" [menu-model]="topNavMenuModel" [version]="version" [hide-search]="true"></top-nav> - <ecomp-footer></ecomp-footer> </div> 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 4b9dd6fc00..5236259f30 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 @@ -25,7 +25,7 @@ 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"; +import {ResourceType,ComponentType} from "../../../../utils/constants"; export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { @@ -48,6 +48,7 @@ export interface ICompositionViewModelScope extends IWorkspaceViewModelScope { setSelectedInstance(componentInstance:ComponentInstance):void; printScreen():void; isPNF():boolean; + isConfiguration():boolean; cacheComponentsInstancesFullData:Component; } @@ -167,9 +168,12 @@ export class CompositionViewModel { this.$scope.updateSelectedComponent = ():void => { if (this.$scope.currentComponent.selectedInstance) { - + let parentComponentUid = this.$scope.currentComponent.selectedInstance.componentUid + if(this.$scope.currentComponent.selectedInstance.originType === ComponentType.SERVICE_PROXY){ + parentComponentUid = this.$scope.currentComponent.selectedInstance.sourceModelUid; + } let componentParent = _.find(this.cacheComponentsInstancesFullData, (component) => { - return component.uniqueId === this.$scope.currentComponent.selectedInstance.componentUid; + return component.uniqueId === parentComponentUid; }); if (componentParent) { this.$scope.selectedComponent = componentParent; @@ -185,7 +189,7 @@ export class CompositionViewModel { console.log("Error updating selected component"); this.$scope.isLoadingRightPanel = false; }; - this.ComponentFactory.getComponentFromServer(this.$scope.currentComponent.selectedInstance.originType, this.$scope.currentComponent.selectedInstance.componentUid).then(onSuccess, onError); + this.ComponentFactory.getComponentFromServer(this.$scope.currentComponent.selectedInstance.originType, parentComponentUid).then(onSuccess, onError); } catch (e) { console.log("Error updating selected component", e); this.$scope.isLoadingRightPanel = false; @@ -247,6 +251,10 @@ export class CompositionViewModel { return this.$scope.selectedComponent.isResource() && (<Resource>this.$scope.selectedComponent).resourceType === ResourceType.PNF; }; + this.$scope.isConfiguration = (): boolean => { + return this.$scope.selectedComponent.isResource() && (<Resource>this.$scope.selectedComponent).resourceType === ResourceType.CONFIGURATION; + }; + this.eventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, this.$scope.reload); } 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 e05574e8c8..bfb2865348 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 @@ -58,29 +58,30 @@ data-ui-sref="workspace.composition.deployment" tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Deployment Artifacts" data-tests-id="deployment-artifact-tab" - data-ng-if="!isPNF()"> + data-ng-if="!isPNF() && !isConfiguration() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new deployment-artifacts"></div> </button> <button tooltips tooltip-class="tooltip-custom tab-tooltip" - tooltip-content="{{selectedComponent.isResource() ? 'Properties and Attributes': 'Inputs'}}" + tooltip-content="{{selectedComponent.isResource() || (isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()) ? 'Properties and Attributes': 'Inputs'}}" class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" data-ui-sref="workspace.composition.properties" data-tests-id="properties-and-attributes-tab"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new" - ng-class="selectedComponent.isResource() ? 'properties': 'inputs'"></div> + ng-class="selectedComponent.isResource() || (isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()) ? 'properties': 'inputs'"></div> </button> <button class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" data-ui-sref="workspace.composition.artifacts" + data-ng-if="!isConfiguration() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" tooltips tooltip-class="tooltip-custom tab-tooltip" tooltip-content="Information Artifacts"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new information-artifacts"></div> </button> - <button data-ng-show="!selectedComponent.isService()" class="i-sdc-designer-sidebar-tab" + <button data-ng-if="!selectedComponent.isService() || (isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" ui-sref="workspace.composition.relations" tooltips tooltip-class="tooltip-custom tab-tooltip tooltip-rightside" tooltip-content="Requirements and Capabilities"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new relations"></div> </button> - <button data-ng-show="selectedComponent.isService()" class="i-sdc-designer-sidebar-tab" + <button data-ng-if="selectedComponent.isService() && !(isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy())" class="i-sdc-designer-sidebar-tab" data-ui-sref-active="active" ui-sref="workspace.composition.api" data-tests-id="tab-api" tooltips tooltip-class="tooltip-custom tab-tooltip tooltip-rightside" tooltip-content="API"> <div class="i-sdc-designer-sidebar-tab-icon sprite-new api"></div> 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 262dfd9be8..624ed03431 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 @@ -21,6 +21,11 @@ } } } + + .custom-modal { + /* Hack solution to hide canvas tooltips under modals */ + z-index: 20000 !important; + } } .workspace-composition { @@ -68,7 +73,7 @@ .w-sdc-designer-sidebar { background-color:@main_color_p ; .noselect; - bottom: @footer_height; + bottom: 0; position: fixed; right: -302px; width: 302px; @@ -92,8 +97,8 @@ .w-sdc-designer-sidebar-logo-ph { display: inline-block; vertical-align: middle; - line-height: 48px; - height: 48px; + line-height: 60px; + height: 60px; } .w-sdc-designer-sidebar-logo { @@ -129,7 +134,7 @@ } .w-sdc-designer-sidebar-tabs { - .bg_e; + .bg_c; } .w-sdc-designer-sidebar-tabs::after { @@ -275,7 +280,9 @@ .g_7; .bg_c; border-radius: 4px; - display: inline-block; + //fix long name for firefox: + display: block; + float: left; line-height: 25px; margin: 0 4px 6px 0; min-width: 50px; @@ -620,7 +627,11 @@ display: inline-block; margin: 12px 0 12px 10px; pointer-events: auto; - + height: 45px; + width: 40px; + float: left; + display: flex; + align-items: center; .non-certified { position: relative; left: 27px; @@ -849,82 +860,30 @@ // --------------------------------------------------------------------------------------------------- // Canvas inline menu // --------------------------------------------------------------------------------------------------- - .w-sdc-canvas-menu { - position: fixed; - z-index: 100; - - border-style: solid; - border-width: 1px; - border-color: #d8d8d8; - box-sizing: border-box; - background-color: #ffffff; - box-shadow: 0px 2px 2px 0px rgba(24, 24, 25, 0.1); - width: 91px; - - /* &.vl-type-select{ - width: 173px; - } - */ + .w-sdc-canvas-menu-list { + .w-sdc-canvas-menu-item-view { + &::before { + content: ''; + display: inline-block; - h3 { - color: @func_color_s; - font-size: 14px; - font-weight: bold; - margin: 0; - padding: 7px 11px; - border-bottom: 1px solid #e5e5e5; + .sprite-new; + .view-icon; + vertical-align: top; + margin: 2px 6px 2px 4px; + } } - .w-sdc-canvas-menu-content { - padding: 5px 5px; - - &.vl-select{ - border-bottom: #d8d8d8 solid 1px; - line-height: 15px; - - .tlv-radio { - padding: 3px 0px; - - .tlv-radio-label { - padding: 3px 0px; - - &::before { - margin-right: 10px; - } - } - } - } + .w-sdc-canvas-menu-item-delete { + &::before { + content: ''; + display: inline-block; - .w-sdc-canvas-menu-content-update-button { - .sprite; - .sprite.e-sdc-small-icon-delete; - .hand; - position: absolute; - top: 15px; - right: 10px; + .sprite-new; + .delete-icon; + vertical-align: bottom; + margin: 1px 10px 0 7px; } - .w-sdc-canvas-menu-content-delete-button { - .sprite; - .sprite.e-sdc-small-icon-delete; - .hand; - margin: 0 8px 0 6px; - } - } - - .w-sdc-canvas-menu-arrow { - //TODO: Missing image for small blue triangle. - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDE0IDc5LjE1Njc5NywgMjAxNC8wOC8yMC0wOTo1MzowMiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE1OTIzNDI1MENFQjExRTU4ODRERTI1MDM2REZCOUYzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE1OTIzNDI2MENFQjExRTU4ODRERTI1MDM2REZCOUYzIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTU5MjM0MjMwQ0VCMTFFNTg4NERFMjUwMzZERkI5RjMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTU5MjM0MjQwQ0VCMTFFNTg4NERFMjUwMzZERkI5RjMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4gBXTlAAAAOElEQVR42mK0rp7NgASMgZgFiE/CBJjQJPcA8U4gNkdXAJMUAGJ+ZEVMaJIwAFfEhEUSRRFAgAEAVtgJyiLAPWAAAAAASUVORK5CYII='); - content: ''; - display: block; - height: 21px; - position: absolute; - right: 12px; - top: -24px; - width: 184px; - background-repeat: no-repeat; - background-position: 175px 16px; } - } } /*.right-tab-loader { 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 f0c8b1d86b..b80b63cac9 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 @@ -40,7 +40,7 @@ export interface IArtifactsViewModelScope extends ICompositionViewModelScope { artifactType:string; downloadFile:IFileDownload; isLoading:boolean; - displayDeleteButtonMap:Dictionary<string, boolean>; + allowDeleteAndUpdateArtifactMap:Dictionary<string, boolean>; getTitle():string; addOrUpdate(artifact:ArtifactModel):void; delete(artifact:ArtifactModel):void; @@ -126,9 +126,9 @@ export class ResourceArtifactsViewModel { } } this.$scope.artifacts = artifacts; - this.$scope.displayDeleteButtonMap = new Dictionary<string, boolean>(); + this.$scope.allowDeleteAndUpdateArtifactMap = new Dictionary<string, boolean>(); _.forEach(this.$scope.artifacts, (artifact:ArtifactModel)=>{ - this.$scope.displayDeleteButtonMap[artifact.artifactLabel] = this.displayDeleteButton(artifact); + this.$scope.allowDeleteAndUpdateArtifactMap[artifact.artifactLabel] = this.allowDeleteAndUpdateArtifact(artifact); }); this.$scope.isLoading = false; }; @@ -234,8 +234,8 @@ export class ResourceArtifactsViewModel { }); }; - private displayDeleteButton = (artifact:ArtifactModel):boolean => { - if(!this.$scope.isViewMode() && artifact.esId){ + private allowDeleteAndUpdateArtifact = (artifact:ArtifactModel):boolean => { + if(!this.$scope.isViewMode()){ 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 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 dfbd639eb4..f4102977b9 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 @@ -1,5 +1,6 @@ <perfect-scrollbar class="w-sdc-designer-sidebar-tab-content artifacts"> <div class="w-sdc-designer-sidebar-section"> + <loader data-display="isLoading"></loader> <expand-collapse expanded-selector=".w-sdc-designer-sidebar-section-content" class="w-sdc-designer-sidebar-section-title"> <span class="w-sdc-designer-sidebar-section-title-text" data-ng-bind="getTitle()" tooltips tooltip-content="{{getTitle()}}"></span> @@ -19,8 +20,8 @@ data-ng-if="artifact.artifactName"></div> <div> <span class="i-sdc-designer-sidebar-section-content-item-artifact-details-name" data-tests-id="artifact_Display_Name-{{artifact.artifactDisplayName}}" - data-ng-class="{'hand enabled': !isViewMode() && !artifact.isHEAT() && !artifact.isThirdParty() && !isLicenseArtifact(artifact)}" - data-ng-bind="artifact.artifactDisplayName" data-ng-click="!isViewMode() && !isLoading && !isComponentInstanceSelected() && !artifact.isHEAT() && !artifact.isThirdParty() && !isLicenseArtifact(artifact) && addOrUpdate(artifact)" + data-ng-class="{'hand enabled': allowDeleteAndUpdateArtifactMap[artifact.artifactLabel]}" + data-ng-bind="artifact.artifactDisplayName" data-ng-click="!isLoading && allowDeleteAndUpdateArtifactMap[artifact.artifactLabel] && addOrUpdate(artifact)" tooltips tooltip-content="{{artifact.artifactDisplayName}}"></span> <div class="i-sdc-designer-sidebar-section-content-item-artifact-heat-env" ng-if="artifact.heatParameters.length"> <span data-ng-bind="getEnvArtifactName(artifact)"data-tests-id="heat_env_{{artifact.artifactDisplayName}}"></span> @@ -36,7 +37,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="displayDeleteButtonMap[artifact.artifactLabel]" class="i-sdc-designer-sidebar-section-content-item-button delete sprite e-sdc-small-icon-delete" + <button ng-if="artifact.esId && allowDeleteAndUpdateArtifactMap[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" 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 0418515789..5020c73df4 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 @@ -11,7 +11,7 @@ <div class="w-sdc-designer-sidebar-section-content general"> <div class="i-sdc-designer-sidebar-section-content-item"> <span class="i-sdc-designer-sidebar-section-content-item-label">Type:</span> - <span class="i-sdc-designer-sidebar-section-content-item-value" data-tests-id="rightTab_componentType" data-ng-bind="selectedComponent.componentType"></span> + <span class="i-sdc-designer-sidebar-section-content-item-value" data-tests-id="rightTab_componentType" data-ng-bind="isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy() ? 'Service Proxy' : selectedComponent.componentType"></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">Resource Type:</span> @@ -103,8 +103,15 @@ <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="selectedComponent.contactId" data-tests-id="rightTab_contactId"></span> </div> + + <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="isComponentInstanceSelected() && currentComponent.selectedInstance.isServiceProxy()"> + <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_SOURCE_SERVICE_NAME"></span> + <span class="i-sdc-designer-sidebar-section-content-item-value" data-ng-bind="currentComponent.selectedInstance.sourceModelName" tooltips tooltip-class="tooltip-custom break-word-tooltip" tooltip-content="​{{currentComponent.selectedInstance.sourceModelName}}" + data-tests-id="rightTab_sourceModelName"></span> + </div> + <div class="i-sdc-designer-sidebar-section-content-item" data-ng-if="isViewMode() && currentComponent.isService() && selectedComponent.isResource()"> - <span class="i-sdc-designer-sidebar-section-content-item-label">Resource Customization UUID:</span><br> + <span class="i-sdc-designer-sidebar-section-content-item-label" translate="GENERAL_LABEL_RESOURCE_CUSTOMIZATION_UUID"></span><br> <span class="customization-uuid selectable" data-ng-bind="currentComponent.selectedInstance.customizationUUID" data-tests-id="rightTab_customizationModuleUUID"></span><br> </div> 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 0ed72e2f00..90bb5658c8 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 @@ -33,7 +33,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; - display: inline-block; + //display: inline-block; fix long name for firefox max-width: 160px; vertical-align:bottom; font-weight: normal; 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 c60a490b4b..6060130191 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 @@ -41,11 +41,16 @@ export class componentCategories {//categories field bind to this obj in order t selectedCategory:string; } +export interface IEnvironmentContext { + defaultValue:string; + validValues:Array<string>; +} export interface IGeneralScope extends IWorkspaceViewModelScope { validation:Validation; editForm:ng.IFormController; categories:Array<IMainCategory>; + environmentContextObj:IEnvironmentContext; latestCategoryId:string; latestVendorName:string; importedFileExtension:any; @@ -67,6 +72,7 @@ export interface IGeneralScope extends IWorkspaceViewModelScope { onEcompGeneratedNamingChange():void; openOnBoardingModal():void; initCategoreis():void; + initEnvironmentContext():void; updateIcon():void; possibleToUpdateIcon():boolean; } @@ -195,6 +201,9 @@ export class GeneralViewModel { // Init categories this.$scope.initCategoreis(); + // Init Environment Context + this.$scope.initEnvironmentContext(); + // Init the decision if to show file browse. this.$scope.isShowFileBrowse = false; if (this.$scope.component.isResource()) { @@ -239,6 +248,7 @@ export class GeneralViewModel { //TODO remove this after handling contact in UI if (this.$scope.isCreateMode()) { this.$scope.component.contactId = this.cacheService.get("user").userId; + this.$scope.originComponent.contactId = this.$scope.component.contactId; } }; @@ -288,6 +298,19 @@ export class GeneralViewModel { } }; + + this.$scope.initEnvironmentContext = ():void => { + if (this.$scope.componentType === ComponentType.SERVICE) { + this.$scope.environmentContextObj = this.cacheService.get('UIConfiguration').environmentContext; + var environmentContext:string =(<Service>this.$scope.component).environmentContext; + var isCheckout:boolean = ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState; + // In creation new service OR check outing old service without environmentContext parameter - set default value + if(this.$scope.isCreateMode() || (isCheckout && !environmentContext)){ + (<Service>this.$scope.component).environmentContext = this.$scope.environmentContextObj.defaultValue; + } + } + }; + this.$scope.validateField = (field:any):boolean => { if (field && field.$dirty && field.$invalid) { return true; @@ -416,5 +439,8 @@ export class GeneralViewModel { } }; this.EventListenerService.registerObserverCallback(EVENTS.ON_CHECKOUT, this.$scope.reload); + this.EventListenerService.registerObserverCallback(EVENTS.ON_REVERT, ()=>{ + this.$scope.componentCategories.selectedCategory = this.$scope.originComponent.selectedCategory; + }); }; } 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 3a3b2d316d..e3eb903a36 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 @@ -343,9 +343,9 @@ data-ng-model-options="{ debounce: 500 }" name="serviceType" data-tests-id="serviceType" - data-ng-maxlength="25" - data-ng-pattern="validation.VendorReleaseValidationPattern" - maxlength="25" + data-ng-maxlength="256" + data-ng-pattern="validation.ServiceTypeAndRoleValidationPattern" + maxlength="256" /> <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> @@ -365,9 +365,9 @@ data-ng-model-options="{ debounce: 500 }" name="serviceRole" data-tests-id="serviceRole" - data-ng-maxlength="25" - data-ng-pattern="validation.VendorReleaseValidationPattern" - maxlength="25" + data-ng-maxlength="256" + data-ng-pattern="validation.ServiceTypeAndRoleValidationPattern" + maxlength="256" /> <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> @@ -376,6 +376,26 @@ </div> <!--------------------- Service Role --------------------> + <!-------------------- ENVIRONMENT CONTEXT -----------------> + + <div ng-if="component.isService()" class="i-sdc-form-item"> + <loader data-display="!environmentContextObj && !initEnvironmentContext()" relative="true"></loader> + <label class="i-sdc-form-label">Environment Context</label> + <select class="i-sdc-form-select" + name="environmentContext" + data-ng-class="{'view-mode': isViewMode()}" + data-ng-model="component.environmentContext" + data-tests-id="environmentContext" + > + <option data-ng-repeat="environmentContextVal in (environmentContextObj.validValues) | orderBy" + value="{{environmentContextVal}}" + data-tests-id="{{environmentContextVal}}">{{environmentContextVal}}</option> + </select> + + </div> + <!--------------------- ENVIRONMENT CONTEXT ------------------> + + <div class="meta-data" data-ng-if="component.creationDate"> <div> <b>Created:</b> diff --git a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts index 3c9c7e9e4b..0360c9c805 100644 --- a/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts +++ b/catalog-ui/src/app/view-models/workspace/tabs/properties/properties-view-model.ts @@ -71,7 +71,8 @@ export class PropertiesViewModel { } private openEditPropertyModal = (property:PropertyModel):void => { - this.ModalsHandler.openEditPropertyModal(property, this.$scope.component, this.$scope.filteredProperties, false).then(() => { + this.ModalsHandler.openEditPropertyModal(property, this.$scope.component, this.$scope.filteredProperties, false).then((updatedProperty:PropertyModel) => { + //property = updatedProperty; }); }; 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 a3af8ca68e..226785e06f 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 @@ -393,7 +393,7 @@ export class WorkspaceViewModel { } else { this.$scope.component = this.ComponentFactory.createComponent(this.$scope.originComponent); } - + this.EventListenerService.notifyObservers(EVENTS.ON_REVERT); }; this.$scope.changeLifecycleState = (state:string):void => { 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 a7c9da05c4..0663074dbc 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace-view.html +++ b/catalog-ui/src/app/view-models/workspace/workspace-view.html @@ -7,11 +7,11 @@ {{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 class="expand-collapse-menu-box-item-text" ng-click="onMenuItemPressed(menuItem.state)" ng-class="{'disabled': menuItem.isDisabled }" data-tests-id="{{menuItem.text}}LeftSideMenu">{{menuItem.text}}</div> </div> </div> - <div include-padding="true" class="w-sdc-main-right-container" data-ng-class="{'composition':isComposition}"> + <div include-padding="true" class="w-sdc-main-right-container" data-ng-class="{'composition':isComposition, 'deployment':isDeployment}"> <loader data-display="isCreateProgress" data-ng-show="isCreateProgress" relative="false"></loader> <div class="sdc-workspace-top-bar"> @@ -63,8 +63,7 @@ <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" 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> @@ -78,6 +77,5 @@ </div> </div> </div> - <top-nav search-bind="search.filterTerm" hide-search="true" menu-model="breadcrumbsModel" version="{{version}}"></top-nav> - <ecomp-footer></ecomp-footer> + <top-nav [hide-search]="true" [menu-model]="breadcrumbsModel" [version]="version"></top-nav> </div> diff --git a/catalog-ui/src/app/view-models/workspace/workspace.less b/catalog-ui/src/app/view-models/workspace/workspace.less index 8b8b6d624a..84a3599d47 100644 --- a/catalog-ui/src/app/view-models/workspace/workspace.less +++ b/catalog-ui/src/app/view-models/workspace/workspace.less @@ -170,8 +170,10 @@ 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. + &.composition, &.deployment{ + .w-sdc-main-container-body-content { + height: 100%; + } } .w-sdc-main-container-body-content { // height:calc(~'100% - @{action_nav_height} - @{tab_title}'); |