2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
22 import {IConfigRoles, IAppConfigurtaion, IAppMenu, IUserProperties, Component} from "app/models";
23 import {EntityService, SharingService, CacheService} from "app/services";
24 import {ComponentType, ResourceType, MenuHandler, ModalsHandler, ChangeLifecycleStateHandler, SEVERITY, ComponentFactory, CHANGE_COMPONENT_CSAR_VERSION_FLAG} from "app/utils";
25 import {IClientMessageModalModel} from "../modals/message-modal/message-client-modal/client-message-modal-view-model";
26 import {UserService} from "../../ng2/services/user.service";
29 export interface IDashboardViewModelScope extends ng.IScope {
32 numberOfItemToDisplay:number;
33 components:Array<Component>;
37 sdcConfig:IAppConfigurtaion;
39 sharingService:SharingService;
43 filterParams:DashboardFilter;
46 changeFilterParams():void;
47 updateSearchTerm(newTerm:string):void;
48 onImportVfc(file:any):void;
49 onImportVf(file:any):void;
50 openCreateModal(componentType:ComponentType, importedFile:any):void;
51 openWhatsNewModal(version:string):void;
52 openDesignerModal(isResource:boolean, uniqueId:string):void;
53 setSelectedFolder(folderItem:FoldersItemsMenu):void;
54 entitiesCount(folderItem:FoldersItemsMenu):number;
55 getCurrentFolderDistributed():Array<Component>;
56 changeLifecycleState(entity:any, data:any):void;
57 goToComponent(component:Component):void;
58 raiseNumberOfElementToDisplay():void;
59 wizardDebugEdit:Function;
60 notificationIconCallback:Function;
63 interface ICheckboxesFilter {
65 selectedStatuses:Array<string>;
67 distributed:Array<string>;
70 export interface IItemMenu {
74 export interface IMenuItemProperties {
83 export interface IQueryFilterParams {
84 'filter.term': string;
85 'filter.distributed': string;
86 'filter.status': string
90 export class DashboardFilter {
92 checkboxes: ICheckboxesFilter;
94 constructor(params = {}) {
95 this.searchTerm = params['filter.term'] || "";
97 selectedStatuses : params['filter.status']? params['filter.status'].split(',') : [],
98 distributed : params['filter.distributed']? params['filter.distributed'].split(',') : []
102 public toParam = ():IQueryFilterParams => {
104 'filter.term': this.searchTerm,
105 'filter.distributed': this.checkboxes && this.checkboxes.distributed.join(',') || null,
106 'filter.status': this.checkboxes && this.checkboxes.selectedStatuses.join(',') || null
112 export class FoldersMenu {
114 private _folders:Array<FoldersItemsMenu> = [];
116 constructor(folders:Array<IMenuItemProperties>) {
118 folders.forEach(function (folder:IMenuItemProperties) {
119 if (folder.groupname) {
120 self._folders.push(new FoldersItemsMenuGroup(folder));
122 self._folders.push(new FoldersItemsMenu(folder));
125 self._folders[0].setSelected(true);
128 public getFolders = ():Array<FoldersItemsMenu> => {
129 return this._folders;
132 public getCurrentFolder = ():FoldersItemsMenu => {
133 let menuItem:FoldersItemsMenu = undefined;
134 this.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
135 if (tmpFolder.isSelected()) {
136 menuItem = tmpFolder;
142 public setSelected = (folder:FoldersItemsMenu):void => {
143 this.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
144 tmpFolder.setSelected(false);
146 folder.setSelected(true);
151 export class FoldersItemsMenu implements IItemMenu {
157 public states:Array<any>;
159 private selected:boolean = false;
161 constructor(menuProperties:IMenuItemProperties) {
162 this.text = menuProperties.text;
163 this.group = menuProperties.group;
164 this.state = menuProperties.state;
165 this.states = menuProperties.states;
166 this.dist = menuProperties.dist;
169 public isSelected = ():boolean => {
170 return this.selected;
173 public setSelected = (value:boolean):void => {
174 this.selected = value;
177 public isGroup = ():boolean => {
183 export class FoldersItemsMenuGroup extends FoldersItemsMenu {
185 public groupname:string;
187 constructor(menuProperties:IMenuItemProperties) {
188 super(menuProperties);
189 this.groupname = menuProperties.groupname;
192 public isGroup = ():boolean => {
198 export class DashboardViewModel {
202 'Sdc.Services.EntityService',
209 'Sdc.Services.SharingService',
210 'Sdc.Services.CacheService',
213 'ChangeLifecycleStateHandler',
218 private components:Array<Component>;
220 constructor(private $scope:IDashboardViewModelScope,
221 private $filter:ng.IFilterService,
222 private entityService:EntityService,
223 private $http:ng.IHttpService,
224 private sdcConfig:IAppConfigurtaion,
225 private sdcMenu:IAppMenu,
226 private $state:ng.ui.IStateService,
227 private $stateParams:any,
228 private userService:UserService,
229 private sharingService:SharingService,
230 private cacheService:CacheService,
231 private $q:ng.IQService,
232 private ComponentFactory:ComponentFactory,
233 private ChangeLifecycleStateHandler:ChangeLifecycleStateHandler,
234 private ModalsHandler:ModalsHandler,
235 private MenuHandler:MenuHandler) {
240 if (this.$stateParams) {
242 if (this.$state.params.folder) {
244 let folderName = this.$state.params.folder.replaceAll("_", " ");
246 this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
247 if (tmpFolder.text === folderName) {
248 self.$scope.setSelectedFolder(tmpFolder);
253 // Show the tutorial if needed when the dashboard page is opened.<script src="bower_components/angular-filter/dist/angular-filter.min.js"></script>
254 // This is called from the welcome page.
255 else if (this.$stateParams.show === 'tutorial') {
256 this.$scope.showTutorial = true;
257 this.$scope.isFirstTime = true;
262 private initFolders = ():void => {
263 if (this.$scope.user) {
264 this.$scope.folders = new FoldersMenu(this.$scope.roles[this.$scope.user.role].folder);
268 private initScope = ():void => {
271 this.$scope.version = this.cacheService.get('version');
272 this.$scope.sharingService = this.sharingService;
273 this.$scope.numberOfItemToDisplay = 0;
274 this.$scope.isLoading = false;
275 this.$scope.sdcConfig = this.sdcConfig;
276 this.$scope.sdcMenu = this.sdcMenu;
277 this.$scope.user = this.userService.getLoggedinUser();
278 this.$scope.roles = this.sdcMenu.roles;
279 this.$scope.showTutorial = false;
280 this.$scope.isFirstTime = false;
281 this.$scope.vfcmtType = ResourceType.VFCMT;
282 this.$scope.filterParams = new DashboardFilter(this.$state.params);
284 // Open onboarding modal
285 this.$scope.notificationIconCallback = ():void => {
286 this.ModalsHandler.openOnboadrdingModal('Import').then((result)=> {
288 if(!result.previousComponent || result.previousComponent.csarVersion != result.componentCsar.csarVersion) {
289 this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, result.componentCsar.csarVersion);
292 this.$state.go('workspace.general', {
293 id: result.previousComponent && result.previousComponent.uniqueId,
294 componentCsar: result.componentCsar,
302 this.$scope.onImportVf = (file:any):void => {
303 if (file && file.filename) {
304 // Check that the file has valid extension.
305 let fileExtension:string = file.filename.split(".").pop();
306 if (this.sdcConfig.csarFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
307 this.$state.go('workspace.general', {
308 type: ComponentType.RESOURCE.toLowerCase(),
310 resourceType: ResourceType.VF
313 let data:IClientMessageModalModel = {
314 title: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE"),
315 message: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS", "{'extensions': '" + this.sdcConfig.csarFileExtension + "'}"),
316 severity: SEVERITY.ERROR
318 this.ModalsHandler.openClientMessageModal(data);
323 this.$scope.onImportVfc = (file:any):void => {
324 if (file && file.filename) {
325 // Check that the file has valid extension.
326 let fileExtension:string = file.filename.split(".").pop();
327 if (this.sdcConfig.toscaFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
328 this.$state.go('workspace.general', {
329 type: ComponentType.RESOURCE.toLowerCase(),
331 resourceType: ResourceType.VFC
334 let data:IClientMessageModalModel = {
335 title: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE"),
336 message: self.$filter('translate')("NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS", "{'extensions': '" + this.sdcConfig.toscaFileExtension + "'}"),
337 severity: SEVERITY.ERROR
339 this.ModalsHandler.openClientMessageModal(data);
344 this.$scope.openCreateModal = (componentType:string, importedFile:any):void => {
346 this.initEntities(true); // Return from import
348 this.$state.go('workspace.general', {type: componentType.toLowerCase()});
353 this.$scope.createPNF = ():void => {
354 this.$state.go('workspace.general', {
355 type: ComponentType.RESOURCE.toLowerCase(),
356 resourceType: ResourceType.PNF
360 this.$scope.createCR = ():void => {
361 this.$state.go('workspace.general', {
362 type: ComponentType.RESOURCE.toLowerCase(),
363 resourceType: ResourceType.CR
367 this.$scope.entitiesCount = (folderItem:FoldersItemsMenu):any => {
369 let total:number = 0;
370 if (folderItem.isGroup()) {
371 this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
372 if (tmpFolder.group && tmpFolder.group === (<FoldersItemsMenuGroup>folderItem).groupname) {
373 total = total + self._getTotalCounts(tmpFolder, self);
377 total = total + self._getTotalCounts(folderItem, self);
382 this.$scope.getCurrentFolderDistributed = ():Array<any> => {
385 if (this.$scope.folders) {
386 let folderItem:FoldersItemsMenu = this.$scope.folders.getCurrentFolder();
387 if (folderItem.isGroup()) {
388 this.$scope.folders.getFolders().forEach(function (tmpFolder:FoldersItemsMenu) {
389 if (tmpFolder.group && tmpFolder.group === (<FoldersItemsMenuGroup>folderItem).groupname) {
390 self._setStates(tmpFolder, states);
394 self._setStates(folderItem, states);
400 this.$scope.setSelectedFolder = (folderItem:FoldersItemsMenu):void => {
401 this.$scope.folders.setSelected(folderItem);
404 this.$scope.goToComponent = (component:Component):void => {
405 this.$scope.isLoading = true;
406 this.$state.go('workspace.general', {id: component.uniqueId, type: component.componentType.toLowerCase()});
409 this.$scope.raiseNumberOfElementToDisplay = ():void => {
410 this.$scope.numberOfItemToDisplay = this.$scope.numberOfItemToDisplay + 35;
411 if (this.$scope.components) {
412 this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.components.length;
416 this.$scope.updateSearchTerm = (newTerm: string):void => {
417 this.$scope.filterParams.searchTerm = newTerm;
420 this.$scope.changeFilterParams = ():void => {
421 this.$state.go('.', this.$scope.filterParams.toParam(), {location: 'replace', notify: false});
425 private _getTotalCounts(tmpFolder, self):number {
426 let total:number = 0;
427 if (tmpFolder.dist !== undefined) {
428 let distributions = tmpFolder.dist.split(',');
429 distributions.forEach((item:any) => {
430 total = total + self.getEntitiesByStateDist(tmpFolder.state, item).length;
434 total = total + self.getEntitiesByStateDist(tmpFolder.state, tmpFolder.dist).length;
439 private _setStates(tmpFolder, states) {
440 if (tmpFolder.states !== undefined) {
441 tmpFolder.states.forEach(function (item:any) {
442 states.push({"state": item.state, "dist": item.dist});
445 states.push({"state": tmpFolder.state, "dist": tmpFolder.dist});
449 private initEntities = (forceReload?:boolean):void => {
451 if(forceReload || this.componentShouldReload()){
452 this.$scope.isLoading = true;
453 this.entityService.getAllComponents(true).then(
454 (components:Array<Component>) => {
455 this.cacheService.set('breadcrumbsComponentsState', this.$state.current.name); //dashboard
456 this.cacheService.set('breadcrumbsComponents', components);
457 this.components = components;
458 this.$scope.components = components;
459 this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.components.length;
460 this.$scope.isLoading = false;
463 this.components = this.cacheService.get('breadcrumbsComponents');
464 this.$scope.components = this.components;
465 this.$scope.isAllItemDisplay = this.$scope.numberOfItemToDisplay >= this.$scope.components.length;
471 private isDefaultFilter = (): boolean => {
472 let defaultFilter = new DashboardFilter();
473 return angular.equals(defaultFilter, this.$scope.filterParams);
476 private componentShouldReload = ():boolean => {
477 let breadcrumbsValid: boolean = (this.$state.current.name === this.cacheService.get('breadcrumbsComponentsState') && this.cacheService.contains('breadcrumbsComponents'));
478 return !breadcrumbsValid || this.isDefaultFilter();
481 private getEntitiesByStateDist = (state:string, dist:string):Array<Component> => {
482 let gObj:Array<Component>;
483 if (this.components && (state || dist)) {
484 gObj = this.components.filter(function (obj:Component) {
485 if (dist !== undefined && obj.distributionStatus === dist && obj.lifecycleState === state) {
487 } else if (dist === undefined && obj.lifecycleState === state) {