diff options
Diffstat (limited to 'catalog-ui/app/scripts/view-models/dashboard')
6 files changed, 1309 insertions, 0 deletions
diff --git a/catalog-ui/app/scripts/view-models/dashboard/cover/dashboard-cover-view-model.ts b/catalog-ui/app/scripts/view-models/dashboard/cover/dashboard-cover-view-model.ts new file mode 100644 index 0000000000..9979b6451b --- /dev/null +++ b/catalog-ui/app/scripts/view-models/dashboard/cover/dashboard-cover-view-model.ts @@ -0,0 +1,91 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ +/// <reference path="../../../references"/> +module Sdc.ViewModels { + + 'use strict'; + + export interface IDashboardCoverViewModelScope extends ng.IScope { + showTutorial:boolean; + version:string; + modalInstance:ng.ui.bootstrap.IModalServiceInstance; + } + + export class DashboardCoverViewModel { + static '$inject' = [ + '$scope', + '$stateParams', + 'Sdc.Services.CacheService', + '$templateCache', + '$state', + '$modal', + 'sdcConfig' + ]; + + constructor(private $scope:IDashboardCoverViewModelScope, + private $stateParams:any, + private cacheService:Services.CacheService, + private $templateCache:ng.ITemplateCacheService, + private $state:any, + private $modal:ng.ui.bootstrap.IModalService, + private sdcConfig:Models.IAppConfigurtaion) { + + // Show the tutorial if needed when the dashboard page is opened.<script src="bower_components/angular-filter/dist/angular-filter.min.js"></script> + // This is called from the welcome page. + if (this.$stateParams.show === 'tutorial') { + this.$scope.showTutorial = true; + } else if (this.$stateParams.show === 'whatsnew') { + this.$scope.version = this.cacheService.get('version'); + this.openWhatsNewModal(this.$scope); + } + + this.initScope(); + } + + private initScope = ():void => { + + }; + + private openWhatsNewModal = (scope:IDashboardCoverViewModelScope):void => { + + let onOk = ():void => {}; + + let onCancel = ():void => { + this.$state.go('dashboard.welcome', {show: ''}); + }; + + let modalOptions:ng.ui.bootstrap.IModalSettings = { + template: this.$templateCache.get('/app/scripts/view-models/whats-new/whats-new-view.html'), + controller: 'Sdc.ViewModels.WhatsNewViewModel', + size: 'sdc-l', + backdrop: 'static', + scope: scope, + resolve: { + 'version': scope.version + } + }; + + scope.modalInstance = this.$modal.open(modalOptions); + scope.modalInstance.result.then(onOk, onCancel); + }; + + } + +} diff --git a/catalog-ui/app/scripts/view-models/dashboard/cover/dashboard-cover-view.html b/catalog-ui/app/scripts/view-models/dashboard/cover/dashboard-cover-view.html new file mode 100644 index 0000000000..c8657cba23 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/dashboard/cover/dashboard-cover-view.html @@ -0,0 +1 @@ +<div class="sdc-welcome-page"></div> diff --git a/catalog-ui/app/scripts/view-models/dashboard/dashboard-view-model-tests.ts b/catalog-ui/app/scripts/view-models/dashboard/dashboard-view-model-tests.ts new file mode 100644 index 0000000000..d97d9bb5ec --- /dev/null +++ b/catalog-ui/app/scripts/view-models/dashboard/dashboard-view-model-tests.ts @@ -0,0 +1,276 @@ +/*- + * ============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========================================================= + */ +/// <reference path="../../references"/> + +describe("dashboard View Model ", () => { + + let $controllerMock:ng.IControllerService; + let $qMock:ng.IQService; + let $httpBackendMock:ng.IHttpBackendService; + let $scopeMock:Sdc.ViewModels.IDashboardViewModelScope; + let $stateMock:ng.ui.IStateService; + let $stateParams:any; + let entityServiceMock; + + + let getAllEntitiesResponseMock = [ + { + "uniqueId": "855acdc7-7976-4913-9fa6-25220bd5a069", + "uuid": "8bc54f94-082c-42fa-9049-84767df3ff05", + "contactId": "qa1234", + "category": "VoIP Call Control", + "creationDate": 1447234712398, + "description": "ddddd", + "highestVersion": true, + "icon": "mobility", + "lastUpdateDate": 1447234712398, + "lastUpdaterUserId": "cs0008", + "lastUpdaterFullName": "Carlos Santana", + "lifecycleState": "NOT_CERTIFIED_CHECKOUT", + "distributionStatus": "DISTRIBUTION_NOT_APPROVED", + "projectCode": "233233", + "name": "mas mas mas mas mas mas mas mas mas mas mas mas ma", + "version": "0.1", + "type": 0, + "tags": [ + "mas mas mas mas mas mas mas mas mas mas mas mas ma" + ], + "systemName": "MasMasMasMasMasMasMasMasMasMasMasMasMa", + "vnf": true, + "$$hashKey": "object:30" + }, + { + "uniqueId": "4bb577ce-cb2c-4cb7-bb39-58644b5e73cb", + "uuid": "e27f4723-c9ec-4160-89da-dbf84d19a7e3", + "contactId": "qa1111", + "category": "Mobility", + "creationDate": 1447238503181, + "description": "aqa", + "highestVersion": true, + "icon": "call_controll", + "lastUpdateDate": 1447248991388, + "lastUpdaterUserId": "jm0007", + "lastUpdaterFullName": "Joni Mitchell", + "lifecycleState": "CERTIFIED", + "distributionStatus": "DISTRIBUTION_REJECTED", + "projectCode": "111111", + "name": "martin18", + "version": "1.0", + "type": 0, + "tags": [ + "martin18" + ], + "systemName": "Martin18", + "vnf": true + }, + { + "uniqueId": "f192f4a6-7fbf-42e4-a546-37509df28dc1", + "uuid": "0b77dc0d-222e-4d10-85cd-e420c9481417", + "contactId": "fd1212", + "category": "Application Layer 4+/Web Server", + "creationDate": 1447233679778, + "description": "geefw", + "highestVersion": true, + "icon": "database", + "lastUpdateDate": 1447233681582, + "lastUpdaterUserId": "cs0008", + "lastUpdaterFullName": "Carlos Santana", + "lifecycleState": "NOT_CERTIFIED_CHECKOUT", + "name": "ger", + "version": "0.1", + "type": 1, + "tags": [ + "ger" + ], + "vendorName": "fewwfe", + "vendorRelease": "fewew", + "systemName": "Ger", + "$$hashKey": "object:31" + }, + { + "uniqueId": "78392d08-1859-47c2-b1f2-1a35b7f8c30e", + "uuid": "8cdd63b2-6a62-4376-9012-624f424f71d4", + "contactId": "qw1234", + "category": "Application Layer 4+/Application Servers", + "creationDate": 1447234046114, + "description": "test", + "highestVersion": true, + "icon": "router", + "lastUpdateDate": 1447234050545, + "lastUpdaterUserId": "cs0008", + "lastUpdaterFullName": "Carlos Santana", + "lifecycleState": "NOT_CERTIFIED_CHECKOUT", + "name": "test", + "version": "0.1", + "type": 1, + "tags": [ + "test" + ], + "vendorName": "test", + "vendorRelease": "test", + "systemName": "Test", + "$$hashKey": "object:32" + }, + { + "uniqueId": "939e153d-2236-410f-b4a9-3b4bf8c79c9e", + "uuid": "84862547-4f56-4058-b78e-40df5f374d7e", + "contactId": "qw1234", + "category": "Application Layer 4+/Application Servers", + "creationDate": 1447235242560, + "description": "jlk", + "highestVersion": true, + "icon": "database", + "lastUpdateDate": 1447235328062, + "lastUpdaterUserId": "cs0008", + "lastUpdaterFullName": "Carlos Santana", + "lifecycleState": "NOT_CERTIFIED_CHECKIN", + "name": "new", + "version": "0.1", + "type": 1, + "tags": [ + "new" + ], + "vendorName": "e", + "vendorRelease": "e", + "systemName": "New", + "$$hashKey": "object:33" + }, + { + "uniqueId": "ece818e0-fd59-477a-baf6-e27461a7ce23", + "uuid": "8db823c2-6a9c-4636-8676-f5e713270dd7", + "contactId": "uf2345", + "category": "Network Layer 2-3/Router", + "creationDate": 1447235352429, + "description": "u", + "highestVersion": true, + "icon": "network", + "lastUpdateDate": 1447235370064, + "lastUpdaterUserId": "cs0008", + "lastUpdaterFullName": "Carlos Santana", + "lifecycleState": "NOT_CERTIFIED_CHECKOUT", + "name": "u", + "version": "0.1", + "type": 1, + "tags": [ + "u" + ], + "vendorName": "u", + "vendorRelease": "u", + "systemName": "U", + "$$hashKey": "object:34" + } + ]; + let getAllEntitiesDefered:ng.IDeferred<any> = null; + + beforeEach(angular.mock.module('sdcApp')); + + beforeEach(angular.mock.inject((_$controller_:ng.IControllerService, + _$httpBackend_:ng.IHttpBackendService, + _$rootScope_, + _$q_:ng.IQService, + _$state_:ng.ui.IStateService, + _$stateParams_:any) => { + + $controllerMock = _$controller_; + $httpBackendMock = _$httpBackend_ + $scopeMock = _$rootScope_.$new(); + $qMock = _$q_; + $stateMock = _$state_; + $stateParams = _$stateParams_; + + + //handle all http request thet not relevant to the tests + $httpBackendMock.expectGET(/.*languages\/en_US.json.*/).respond(200, JSON.stringify({})); + // $httpBackendMock.expectGET(/.*resources\/certified\/abstract.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*rest\/version.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*configuration\/ui.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*user\/authorize.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*categories\/services.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*categories\/resources.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET(/.*categories\/products.*/).respond(200, JSON.stringify({})); + $httpBackendMock.expectGET('http://feHost:8181/sdc1/feProxy/rest/version').respond(200, JSON.stringify({})); + + /** + * Mock the service + * @type {any} + */ + getAllEntitiesDefered = $qMock.defer(); + getAllEntitiesDefered.resolve(getAllEntitiesResponseMock); + entityServiceMock = jasmine.createSpyObj('entityServiceMock', ['getAllComponents']); + entityServiceMock.getAllComponents.and.returnValue(getAllEntitiesDefered.promise); + + // $stateParams['show'] = ''; + + /** + * Need to inject into the controller only the objects that we want to MOCK + * those that we need to change theirs behaviors + */ + $controllerMock(Sdc.ViewModels.DashboardViewModel, { + '$scope': $scopeMock, + '$stateParams': $stateParams, + 'Sdc.Services.EntityService': entityServiceMock, + }); + + })); + + + describe("when Controller 'DashboardViewModel' created", () => { + + it('should generate all entities', () => { + $scopeMock.$apply(); + expect($scopeMock.components.length).toBe(getAllEntitiesResponseMock.length); + }); + + + it('should show tutorial page ', () => { + $stateParams.show = 'tutorial'; + + $controllerMock(Sdc.ViewModels.DashboardViewModel, { + '$scope': $scopeMock, + '$stateParams': $stateParams, + 'Sdc.Services.EntityService': entityServiceMock, + //to complete injects + }); + + $scopeMock.$apply(); + expect($scopeMock.isFirstTime).toBeTruthy(); + expect($scopeMock.showTutorial).toBeTruthy(); + }); + + }); + + + describe("when function 'entitiesCount' invoked", () => { + + beforeEach(() => { + $controllerMock(Sdc.ViewModels.DashboardViewModel, { + '$scope': $scopeMock, + 'Sdc.Services.EntityService': entityServiceMock, + }); + $scopeMock.$apply(); + }); + + it('should return entities count per folder', () => { + + }); + + + }); +}); diff --git a/catalog-ui/app/scripts/view-models/dashboard/dashboard-view-model.ts b/catalog-ui/app/scripts/view-models/dashboard/dashboard-view-model.ts new file mode 100644 index 0000000000..8325a3f133 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/dashboard/dashboard-view-model.ts @@ -0,0 +1,415 @@ +/*- + * ============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========================================================= + */ +/// <reference path="../../references"/> +module Sdc.ViewModels { + + 'use strict'; + import ResourceType = Sdc.Utils.Constants.ResourceType; + + export interface IDashboardViewModelScope extends ng.IScope { + + isLoading: boolean; + components: Array<Models.Components.Component>; + folders: FoldersMenu; + roles: Models.IConfigRoles; + user: Models.IUserProperties; + sdcConfig:Models.IAppConfigurtaion; + sdcMenu:Models.IAppMenu; + sharingService:Sdc.Services.SharingService; + showTutorial:boolean; + isFirstTime:boolean; + version:string; + checkboxesFilter:CheckboxesFilter; + + onImportVfc(file:any):void; + onImportVf(file:any):void; + openCreateModal(componentType: Utils.Constants.ComponentType, importedFile:any): void; + openWhatsNewModal(version:string):void; + openDesignerModal(isResource:boolean, uniqueId:string): void; + openViewerModal(entity:any) : void; + setSelectedFolder(folderItem: FoldersItemsMenu): void; + entitiesCount(folderItem: FoldersItemsMenu): number; + getCurrentFolderDistributed(): Array<Models.Components.Component>; + changeLifecycleState(entity:any, data:any): void; + goToComponent(component:Models.Components.Component):void; + wizardDebugEdit:Function; + notificationIconCallback:Function; + } + + interface CheckboxesFilter { + // Statuses + selectedStatuses:Array<string>; + // distributed + distributed:Array<string>; + } + + export interface IItemMenu { + + } + + export interface IMenuItemProperties { + text: string; + group: string; + state: string; + dist: string; + groupname: string; + states: Array<any>; + } + + export class FoldersMenu { + + private _folders: Array<FoldersItemsMenu> = []; + + constructor(folders: Array<IMenuItemProperties>) { + let self = this; + folders.forEach(function(folder: IMenuItemProperties) { + if (folder.groupname){ + self._folders.push(new FoldersItemsMenuGroup(folder)); + } else { + self._folders.push(new FoldersItemsMenu(folder)); + } + }); + self._folders[0].setSelected(true); + } + + public getFolders = (): Array<FoldersItemsMenu> => { + return this._folders; + }; + + public getCurrentFolder = (): FoldersItemsMenu => { + let menuItem: FoldersItemsMenu = undefined; + this.getFolders().forEach(function(tmpFolder: FoldersItemsMenu) { + if (tmpFolder.isSelected()){ + menuItem = tmpFolder; + } + }); + return menuItem; + }; + + public setSelected = (folder: FoldersItemsMenu):void => { + this.getFolders().forEach(function(tmpFolder: FoldersItemsMenu) { + tmpFolder.setSelected(false); + }); + folder.setSelected(true); + } + + } + + export class FoldersItemsMenu implements IItemMenu { + + public text:string; + public group: string; + public state: string; + public dist: string; + public states: Array<any>; + + private selected: boolean = false; + + constructor(menuProperties: IMenuItemProperties) { + this.text = menuProperties.text; + this.group = menuProperties.group; + this.state = menuProperties.state; + this.states = menuProperties.states; + this.dist = menuProperties.dist; + } + + public isSelected = ():boolean => { + return this.selected; + }; + + public setSelected = (value: boolean):void => { + this.selected = value; + }; + + public isGroup = ():boolean => { + return false; + } + + } + + export class FoldersItemsMenuGroup extends FoldersItemsMenu { + + public groupname:string; + + constructor(menuProperties: IMenuItemProperties) { + super(menuProperties); + this.groupname = menuProperties.groupname; + } + + public isGroup = ():boolean => { + return true; + } + + } + + export class DashboardViewModel { + static '$inject' = [ + '$scope', + '$filter', + 'Sdc.Services.EntityService', + '$http', + 'sdcConfig', + 'sdcMenu', + '$modal', + '$templateCache', + '$state', + '$stateParams', + 'Sdc.Services.UserResourceService', + 'Sdc.Services.SharingService', + 'Sdc.Services.CacheService', + '$q', + 'ComponentFactory', + 'ChangeLifecycleStateHandler', + 'ModalsHandler', + 'MenuHandler' + ]; + + private components: Array<Models.Components.Component>; + + constructor(private $scope:IDashboardViewModelScope, + private $filter:ng.IFilterService, + private entityService:Services.EntityService, + private $http:ng.IHttpService, + private sdcConfig:Models.IAppConfigurtaion, + private sdcMenu:Models.IAppMenu, + private $modal:ng.ui.bootstrap.IModalService, + private $templateCache:ng.ITemplateCacheService, + private $state:any, + private $stateParams:any, + private userResourceService:Sdc.Services.IUserResourceClass, + private sharingService:Services.SharingService, + private cacheService:Services.CacheService, + private $q:ng.IQService, + private ComponentFactory: Sdc.Utils.ComponentFactory, + private ChangeLifecycleStateHandler: Sdc.Utils.ChangeLifecycleStateHandler, + private ModalsHandler: Sdc.Utils.ModalsHandler, + private MenuHandler: Utils.MenuHandler + ) { + this.initScope(); + this.initFolders(); + this.initEntities(true); + + if (this.$stateParams){ + + if (this.$state.params.folder){ + let self = this; + let folderName = this.$state.params.folder.replaceAll("_"," "); + + this.$scope.folders.getFolders().forEach(function(tmpFolder: FoldersItemsMenu) { + if (tmpFolder.text === folderName){ + self.$scope.setSelectedFolder(tmpFolder); + } + }); + } + + // Show the tutorial if needed when the dashboard page is opened.<script src="bower_components/angular-filter/dist/angular-filter.min.js"></script> + // This is called from the welcome page. + else if (this.$stateParams.show==='tutorial'){ + this.$scope.showTutorial = true; + this.$scope.isFirstTime = true; + } + } + } + + private initFolders = ():void => { + if (this.$scope.user) { + this.$scope.folders = new FoldersMenu(this.$scope.roles[this.$scope.user.role].folder); + } + }; + + private initScope = ():void => { + let self = this; + + this.$scope.version = this.cacheService.get('version'); + this.$scope.sharingService = this.sharingService; + this.$scope.isLoading = false; + this.$scope.sdcConfig = this.sdcConfig; + this.$scope.sdcMenu = this.sdcMenu; + this.$scope.user = this.userResourceService.getLoggedinUser(); + this.$scope.roles = this.sdcMenu.roles; + this.$scope.showTutorial = false; + this.$scope.isFirstTime = false; + + // Open onboarding modal + this.$scope.notificationIconCallback = ():void => { + this.ModalsHandler.openOnboadrdingModal('Import').then(()=>{ + // OK + }, ()=>{ + // ERROR + }); + }; + + // Checkboxes filter init + this.$scope.checkboxesFilter = <CheckboxesFilter>{}; + this.$scope.checkboxesFilter.selectedStatuses = []; + this.$scope.checkboxesFilter.distributed = []; + + let appendTemplateAndControllerForProduct:Function = (modalOptions:ng.ui.bootstrap.IModalSettings, isViewer:boolean):void => { + let viewModelsHtmlBasePath:string = '/app/scripts/view-models/'; + + if (isViewer) { + modalOptions.template = this.$templateCache.get(viewModelsHtmlBasePath + 'entity-viewer/product-viewer-view.html'); + modalOptions.controller = 'Sdc.ViewModels.ResourceViewerViewModel'; + } else { + modalOptions.template = this.$templateCache.get(viewModelsHtmlBasePath + 'entity-handler/product-form/product-form-view.html'); + modalOptions.controller = 'Sdc.ViewModels.ProductFormViewModel'; + } + + }; + + this.$scope.onImportVf = (file:any):void => { + if(file && file.filename) { + // Check that the file has valid extension. + let fileExtension:string = file.filename.split(".").pop(); + if (this.sdcConfig.csarFileExtension.indexOf(fileExtension.toLowerCase()) !== -1){ + this.$state.go('workspace.general', {type:Utils.Constants.ComponentType.RESOURCE.toLowerCase(), importedFile: file, resourceType: ResourceType.VF}); + }else { + let data:Sdc.ViewModels.IClientMessageModalModel = { + title: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE"), + message: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS", "{'extensions': '" + this.sdcConfig.csarFileExtension + "'}"), + severity: Utils.Constants.SEVERITY.ERROR + }; + this.ModalsHandler.openClientMessageModal(data); + } + } + }; + + this.$scope.onImportVfc = (file:any):void => { + if(file && file.filename) { + // Check that the file has valid extension. + let fileExtension:string = file.filename.split(".").pop(); + if (this.sdcConfig.toscaFileExtension.indexOf(fileExtension.toLowerCase()) !== -1){ + this.$state.go('workspace.general', {type:Utils.Constants.ComponentType.RESOURCE.toLowerCase(), importedFile: file, resourceType: ResourceType.VFC}); + }else { + let data:Sdc.ViewModels.IClientMessageModalModel = { + title: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE"), + message: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS", "{'extensions': '" + this.sdcConfig.toscaFileExtension + "'}"), + severity: Utils.Constants.SEVERITY.ERROR + }; + this.ModalsHandler.openClientMessageModal(data); + } + } + }; + + this.$scope.openCreateModal = (componentType: string, importedFile:any):void => { + if (importedFile){ + this.initEntities(true); // Return from import + } else { + this.$state.go('workspace.general', {type:componentType.toLowerCase()}); + } + + }; + + this.$scope.entitiesCount = (folderItem: FoldersItemsMenu): any => { + let self = this; + let total: number = 0; + if (folderItem.isGroup()){ + this.$scope.folders.getFolders().forEach(function(tmpFolder: FoldersItemsMenu){ + if (tmpFolder.group && tmpFolder.group===(<FoldersItemsMenuGroup>folderItem).groupname){ + total = total + self._getTotalCounts(tmpFolder, self); + } + }); + } else { + total = total + self._getTotalCounts(folderItem, self); + } + return total; + }; + + this.$scope.getCurrentFolderDistributed = (): Array<any> => { + let self = this; + let states = []; + if (this.$scope.folders) { + let folderItem:FoldersItemsMenu = this.$scope.folders.getCurrentFolder(); + if (folderItem.isGroup()) { + this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) { + if (tmpFolder.group && tmpFolder.group === (<FoldersItemsMenuGroup>folderItem).groupname) { + self._setStates(tmpFolder, states); + } + }); + } else { + self._setStates(folderItem, states); + } + } + return states; + }; + + this.$scope.setSelectedFolder = (folderItem: FoldersItemsMenu):void => { + this.$scope.folders.setSelected(folderItem); + }; + + this.$scope.goToComponent = (component:Models.Components.Component):void => { + this.$scope.isLoading=true; + this.$state.go('workspace.general', {id: component.uniqueId, type:component.componentType.toLowerCase() }); + }; + + }; + + private _getTotalCounts(tmpFolder, self): number { + let total: number = 0; + if (tmpFolder.dist !== undefined) { + let distributions = tmpFolder.dist.split(','); + distributions.forEach((item:any) => { + total = total + self.getEntitiesByStateDist(tmpFolder.state, item).length; + }); + } + else { + total = total + self.getEntitiesByStateDist(tmpFolder.state, tmpFolder.dist).length; + } + return total; + } + + private _setStates(tmpFolder, states) { + if (tmpFolder.states !== undefined) { + tmpFolder.states.forEach(function (item:any) { + states.push({"state": item.state, "dist": item.dist}); + }); + } else { + states.push({"state": tmpFolder.state, "dist": tmpFolder.dist}); + } + } + + private initEntities = (reload:boolean):void => { + this.$scope.isLoading = reload; + this.entityService.getAllComponents().then( + (components: Array<Models.Components.Component>) => { + this.components = components; + this.$scope.components = components; + this.$scope.isLoading = false; + }); + }; + + private getEntitiesByStateDist = (state: string, dist: string) : Array<Models.Components.Component> => { + let gObj:Array<Models.Components.Component>; + if (this.components && (state || dist)) { + gObj = this.components.filter(function (obj:Models.Components.Component) { + if (dist !== undefined && obj.distributionStatus === dist && obj.lifecycleState === state){ + return true; + } else if (dist === undefined && obj.lifecycleState === state) { + return true; + } + return false; + }); + } else { + gObj = []; + } + return gObj; + } + } +} diff --git a/catalog-ui/app/scripts/view-models/dashboard/dashboard-view.html b/catalog-ui/app/scripts/view-models/dashboard/dashboard-view.html new file mode 100644 index 0000000000..0aef4e19c6 --- /dev/null +++ b/catalog-ui/app/scripts/view-models/dashboard/dashboard-view.html @@ -0,0 +1,106 @@ +<div class="sdc-catalog-container"> + <loader data-display="isLoading"></loader> + + <!-- HEADER --> +<!-- + <ecomp-header menu-data="menuItems" version="{{version}}"></ecomp-header> +--> + + <div class="w-sdc-main-container"> + + <perfect-scrollbar include-padding="true" class="w-sdc-main-right-container"> + + <!-- ADD Component --> + <div ng-if="user.role === 'DESIGNER' || user.role === 'PRODUCT_MANAGER'" class="w-sdc-dashboard-card-new" + data-ng-mouseleave="displayActions = false" + data-ng-mouseover="displayActions = true" + data-ng-init="displayActions = false"> + <div class="w-sdc-dashboard-card-new-content" data-tests-id="AddButtonsArea"> + <div class="w-sdc-dashboard-card-new-content-plus" data-ng-show="!displayActions"></div> + <div class="sdc-dashboard-create-element-container" data-ng-show="displayActions"> + <button data-ng-if="roles[user.role].dashboard.showCreateNewProduct" class="tlv-btn outline blue" data-ng-click="openCreateModal('PRODUCT')">Create Product</button> + <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createResourceButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('RESOURCE')">Add VF</button> + <button data-ng-if="roles[user.role].dashboard.showCreateNew" data-tests-id="createServiceButton" class="tlv-btn outline blue" data-ng-click="openCreateModal('SERVICE')">Add Service</button> + </div> + </div> + </div> + + <!-- Import Component --> + <div ng-if="user.role === 'DESIGNER'" class="w-sdc-dashboard-card-new" + data-ng-mouseleave="displayActions = false" + data-ng-mouseover="displayActions = true" + data-ng-init="displayActions = false"> + <div class="w-sdc-dashboard-card-new-content" data-tests-id="importButtonsArea" > + <div class="w-sdc-dashboard-card-import-content-plus" data-ng-show="!displayActions"></div> + <div class="sdc-dashboard-import-element-container" data-ng-show="displayActions"> + <div data-ng-if="roles[user.role].dashboard.showCreateNew" class="tlv-btn outline blue">Import VFC + <file-opener on-file-upload="onImportVfc(file)" data-tests-id="importVFCbutton" extensions="{{sdcConfig.toscaFileExtension}}" data-ng-click="displayActions=false"></file-opener> + </div> + <div data-ng-if="roles[user.role].dashboard.showCreateNew" class="tlv-btn outline blue" data-ng-click="notificationIconCallback()">Import VSP</div> + <div data-ng-if="roles[user.role].dashboard.showCreateNew" class="tlv-btn outline blue import-dcae">Import DCAE asset + <file-opener on-file-upload="onImportVf(file)" data-tests-id="importVFbutton" extensions="{{sdcConfig.csarFileExtension}}" data-ng-click="displayActions=false"></file-opener> + </div> + </div> + </div> + </div> + + <div + data-ng-class="{'sdc-hide-popover': hidePopover,'resource' : component.isResource(),'service' : component.isService()}" + class="w-sdc-dashboard-card" + data-ng-repeat="component in components | entityFilter:checkboxesFilter | filter:search" + > + <div class="w-sdc-dashboard-card-body" data-tests-id="dashboard-Elements" data-ng-click="goToComponent(component)"> + <!--<div class="w-sdc-dashboard-card-description">{{entity.description}}</div>--> + <div class="w-sdc-dashboard-card-avatar"><span data-tests-id="asset-type" class="{{component.getComponentSubType()}}"></span></div> + <!--<div class="w-sdc-dashboard-card-edit" data-ng-class="component.lifecycleState" data-tests-id="{{component.lifecycleState}}"></div>--> + <div class="w-sdc-dashboard-card-schema-image {{component.iconSprite}} {{component.icon}}" + data-ng-class="{'sprite-resource-icons': component.isResource(), 'sprite-services-icons': component.isService()}" + data-tests-id="{{component.name}}"></div> + <div class="w-sdc-dashboard-card-info-name-container"> + <span class="w-sdc-dashboard-card-info-name" tooltips + tooltip-content="{{component.name | resourceName}}"> {{component.name | resourceName}}</span> + </div> + </div> + <div class="w-sdc-dashboard-card-footer"> + + <div class="w-sdc-dashboard-card-info"> + <div class="w-sdc-dashboard-card-info-lifecycleState"> + <span class="w-sdc-dashboard-card-info-lifecycleState" tooltips + tooltip-content="{{component.getStatus(sdcMenu)}}"> {{component.getStatus(sdcMenu)}}</span> + </div> + <div class="w-sdc-dashboard-card-info-user"data-tests-id="{{component.name}}Version">V {{component.version}}</div> + </div> + <!--<div class="w-sdc-dashboard-card-info-lifecycleState-icon sprite-new {{sdcMenu.LifeCycleStatuses[component.lifecycleState].icon}}"></div>--> + </div> + </div> + + </perfect-scrollbar> + + <div class="w-sdc-left-sidebar"> + <div class="i-sdc-left-sidebar-item " + data-ng-repeat="folder in folders.getFolders()" + data-ng-class="{'category-title': folder.isGroup(), 'selectedLink': folder.isSelected()}" + > + <span data-ng-if="folder.isGroup()">{{folder.text}}</span> + + <sdc-checkbox data-ng-if="!folder.isGroup() && !folder.dist" + elem-id="checkbox-{{folder.text | lowercase | clearWhiteSpaces}}" + sdc-checklist-model="checkboxesFilter.selectedStatuses" + sdc-checklist-value="folder.state" + text="{{folder.text}}"></sdc-checkbox> + + <sdc-checkbox data-ng-if="!folder.isGroup() && folder.dist" + elem-id="checkbox-{{folder.text | lowercase | clearWhiteSpaces}}" + sdc-checklist-model="checkboxesFilter.distributed" + sdc-checklist-value="folder.dist" + text="{{folder.text}}"></sdc-checkbox> + <span class="i-sdc-left-sidebar-item-state-count">{{entitiesCount(folder)}}</span> + </div> + </div> + + </div> + + <top-nav top-lvl-selected-index="0" version="{{version}}" search-bind="search.filterTerm" notification-icon-callback="notificationIconCallback" version="{{version}}"></top-nav> + +</div> +<div data-ui-view=""></div> diff --git a/catalog-ui/app/scripts/view-models/dashboard/dashboard.less b/catalog-ui/app/scripts/view-models/dashboard/dashboard.less new file mode 100644 index 0000000000..7b2522113b --- /dev/null +++ b/catalog-ui/app/scripts/view-models/dashboard/dashboard.less @@ -0,0 +1,420 @@ +.sdc-dashboard-container { + .tlv-loader { + top: -110px; + left: 80px; + } + .sdc-hide-popover { + .popover { + display: none !important; + } + } +} + +.w-sdc-left-sidebar-nav { + margin-top: 46px; +} + +.w-sdc-main-right-container-element { + float: left; + height: 217px; + width: 217px; + margin: 10px; + position: relative; +} + +.w-sdc-main-right-container-element-details-container { + position: absolute; + top: 165px; + left: 50px; +} + +.w-sdc-main-right-container-element-name { + font-weight: bold; +} + +.w-sdc-main-right-container-element-owner { + +} + +//////////////////////////////Cards//////////////////// +.w-sdc-dashboard-card-new { + border: 2px dashed @color_m; + .border-radius(2px); + cursor: pointer; + display: inline-block; + height: 200px; + margin: 9px; + position: relative; + vertical-align: middle; + width: 204px; +} + +.w-sdc-dashboard-card-new-content { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + height: 100%; +} + +.w-sdc-dashboard-card-new-content-plus { + .sprite-new; + .add-icon; + position: relative; + margin-bottom: 20px; + + &:after { + .n_14_m; + content: 'ADD'; + position: absolute; + top: 25px; + left: -3px; + vertical-align: -50%; + } +} + +.w-sdc-dashboard-card-import-content-plus { + .sprite-new; + .import-icon; + position: relative; + margin-bottom: 20px; + + &:after { + .n_14_m; + content: 'IMPORT'; + position: absolute; + top: 25px; + left: -16px; + vertical-align: -50%; + } +} + +.sdc-dashboard-create-element-container, +.sdc-dashboard-import-element-container { + + width: 140px; + + .tlv-btn.import-dcae { + padding: 0; + } + + .tlv-btn { + position: relative; + width: 100%; + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + + input[type="file"] { + cursor: inherit; + filter: alpha(opacity=0); + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: 138px; + height: 30px; + } +} + +.w-sdc-dashboard-card { + width: 204px; + height: 200px; + background-color: @main_color_p; + .border-radius(2px); + .box-shadow(0px 2px 2px 0px rgba(24, 24, 25, 0.05)); + display: inline-block; + margin: 10px; + position: relative; + vertical-align: middle; + border: solid 1px @main_color_p; + + &:hover { + border: solid 1px @main_color_o; + .box-shadow(3px 3px 2px 0px rgba(24, 24, 25, 0.05)); + } + + &:active { + border: solid 1px @main_color_c; + .box-shadow(3px 3px 2px 0px rgba(24, 24, 25, 0.05)); + } +} + +.w-sdc-dashboard-card-body { + .hand; + border-bottom: 1px solid @color_j; + height: 155px; + position: relative; + text-align: center; +} + +.w-sdc-dashboard-card-description { + .c_3; + .hand; + background-color: rgba(57, 73, 84, 0.9); + border-radius: 4px 4px 0 0; + bottom: 0; + left: 0; + opacity: 0; + padding: 10px; + position: absolute; + right: 0; + text-align: left; + top: 0; + word-wrap: break-word; + z-index: 4; + min-height: 100px; + overflow: hidden; +} + + +.w-sdc-dashboard-card-schema { + margin-top: 30px; +} + +.w-sdc-dashboard-card-edit { + .hand; + position: absolute; + right: 13px; + top: 15px; + z-index: 2; +} + +.w-sdc-dashboard-card-footer { + padding: 3px 12px 10px 12px; + position: relative; +} + +.w-sdc-dashboard-card-avatar { + .uppercase; + border-radius: 50%; + display: inline-block; + position: absolute; + left: -6px; + text-align: center; + top: -6px; + + span { + + background-color: @main_color_p; + .border-radius(15px); + color: @color_c; + content: ''; + height: 30px; + text-align: center; + display: block; + border: solid 2px #ECEFF3; + padding: 3px 10px 2px 10px; + + &.VF { + .j_14_m; + &::before { + content: 'VF'; + } + } + + &.VFC { + .j_14_m; + &::before { + content: 'VFC'; + } + } + + &.CP { + .j_14_m; + &::before { + content: 'CP'; + } + } + + &.VL { + .j_14_m; + &::before { + content: 'VL'; + } + } + + &.SERVICE { + .c_14_m; + &::before { + content: 'S'; + } + } + + &.PRODUCT { + .b_14_m; + &::before { + content: 'P'; + } + } + + &.green { + .d_12; + &::before { + content: 'R'; + } + } + &.red { + .r_12; + &::before { + content: 'S'; + } + } + &.dblack { + .s_12; + &::before { + content: 'P'; + } + } + } +} + +.w-sdc-dashboard-card-info { + display: inline-block; + vertical-align: middle; + max-width: 165px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.w-sdc-dashboard-card-info-name-container{ + position: absolute; + bottom: 0; + left: 0; + margin: 0 0 2px 10px; +} +.w-sdc-dashboard-card-info-name { + .m_14_m; + display: inline-block; + vertical-align: middle; + max-width: 165px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.w-sdc-dashboard-card-info-lifecycleState { + .m_13_m; + display: inline-block; + vertical-align: middle; + max-width: 165px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.w-sdc-dashboard-card-info-user { + .n_13_r; + line-height: 18px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; +} + +.w-sdc-dashboard-card-menu-button { + display: inline-block; + padding: 12px 0 0 10px; + position: absolute; + right: 12px; + top: 8px; + border-left: solid 1px @color_k; + height: 42px; + + &:hover { + .w-sdc-dashboard-card-menu { + display: block; + } + } +} + +.w-sdc-dashboard-card-menu { + .bg_c; + border-radius: 0 0 4px 4px; + border-top: 3px solid @color_a; + box-shadow: 0 2px 2px 0px rgba(0, 0, 0, 0.2); + color: @color_s; + display: none; + min-height: 30px; + padding: 9px 0; + position: absolute; + right: -27px; + width: 208px; + z-index: 9; + max-height: 164px; + + &::before { + //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: 24px; + top: -24px; + width: 184px; + background-repeat: no-repeat; + background-position: 175px 16px; + } +} + +.i-sdc-dashboard-card-menu-item { + .hand; + line-height: 24px; + padding: 0 10px; + &:hover { .a_7; } +} + +.w-sdc-dashboard-card-info-lifecycleState-icon{ + position:absolute; + bottom:18px; + right:10px; +} + +// Same for dashboard and catalog view. +.w-sdc-dashboard-card-schema-image { + position: absolute; + top: 41%; + + //TODO: Israel - remove this after getting the services sprite. + height: 45px; + width: 53px; + background-repeat: no-repeat; + + // Center the icon vertical and horizontal. + margin: auto; + left: 0; + right: 0; + top: -10px; + bottom: 0; +} + +/* dashboard card main icons */ +.w-sdc-dashboard-card-schema-image.service { .s-sdc-service } +.w-sdc-dashboard-card-schema-image.resource { .s-sdc-resource } + +/* dashboard card statuses icons */ +.w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKIN { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKIN; } +.w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKOUT { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKOUT; } +.w-sdc-dashboard-card-edit.CERTIFIED { .sprite; .s-sdc-state.CERTIFIED; } +.w-sdc-dashboard-card-edit.READY_FOR_CERTIFICATION { .sprite; .s-sdc-state.READY_FOR_CERTIFICATION; } +.w-sdc-dashboard-card-edit.CERTIFICATION_IN_PROGRESS { .sprite; .s-sdc-state.CERTIFICATION_IN_PROGRESS; } +.w-sdc-dashboard-card-edit.DISTRIBUTED { .sprite; .s-sdc-state.DISTRIBUTED; } + +.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKIN { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKIN.green; } +.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKOUT { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKOUT.green; } +.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.CERTIFIED { .sprite; .s-sdc-state.CERTIFIED.green; } +.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.READY_FOR_CERTIFICATION { .sprite; .s-sdc-state.READY_FOR_CERTIFICATION.green; } +.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.CERTIFICATION_IN_PROGRESS { .sprite; .s-sdc-state.CERTIFICATION_IN_PROGRESS.green; } +.w-sdc-dashboard-card-avatar.green + .w-sdc-dashboard-card-edit.DISTRIBUTED { .sprite; .s-sdc-state.DISTRIBUTED.green; } + +.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKIN { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKIN.red; } +.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.NOT_CERTIFIED_CHECKOUT { .sprite; .s-sdc-state.NOT_CERTIFIED_CHECKOUT.red; } +.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.CERTIFIED { .sprite; .s-sdc-state.CERTIFIED.red; } +.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.READY_FOR_CERTIFICATION { .sprite; .s-sdc-state.READY_FOR_CERTIFICATION.red; } +.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.CERTIFICATION_IN_PROGRESS { .sprite; .s-sdc-state.CERTIFICATION_IN_PROGRESS.red; } +.w-sdc-dashboard-card-avatar.red + .w-sdc-dashboard-card-edit.DISTRIBUTED { .sprite; .s-sdc-state.DISTRIBUTED.red; } |