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=========================================================
21 import {Component as NgComponent, Inject, OnInit} from '@angular/core';
22 import {Component, ComponentMetadata, IConfigRoles, IUserProperties, Resource, Service} from 'app/models';
23 import {HomeFilter} from 'app/models/home-filter';
24 import {AuthenticationService, CacheService, HomeService, ResourceServiceNg2} from 'app/services-ng2';
25 import {ComponentState, ModalsHandler} from 'app/utils';
26 import {SdcUiServices} from 'onap-ui-angular';
27 import {CHANGE_COMPONENT_CSAR_VERSION_FLAG, ComponentType, ResourceType} from '../../../utils/constants';
28 import {ImportVSPService} from '../../components/modals/onboarding-modal/import-vsp.service';
29 import {ISdcConfig, SdcConfigToken} from '../../config/sdc-config.config';
30 import {IAppMenu, SdcMenuToken} from '../../config/sdc-menu.config';
31 import {EntityFilterPipe} from '../../pipes/entity-filter.pipe';
32 import {TranslateService} from '../../shared/translator/translate.service';
33 import {FoldersItemsMenu, FoldersItemsMenuGroup, FoldersMenu} from './folders';
34 import {ImportVSPdata} from "../../components/modals/onboarding-modal/onboarding-modal.component";
35 import {DataTypeCatalogComponent} from "../../../models/data-type-catalog-component";
38 selector: 'home-page',
39 templateUrl: './home.component.html',
40 styleUrls: ['./home.component.less']
42 export class HomeComponent implements OnInit {
43 public numberOfItemToDisplay: number;
44 public homeItems: Component[];
45 public homeFilteredItems: Array<Component | DataTypeCatalogComponent>;
46 public homeFilteredSlicedItems: Array<Component | DataTypeCatalogComponent>;
47 public folders: FoldersMenu;
48 public roles: IConfigRoles;
49 public user: IUserProperties;
50 public showTutorial: boolean;
51 public isFirstTime: boolean;
52 public version: string;
53 public homeFilter: HomeFilter;
54 public vfcmtType: string;
55 public displayActions: boolean;
58 @Inject(SdcConfigToken) private sdcConfig: ISdcConfig,
59 @Inject(SdcMenuToken) public sdcMenu: IAppMenu,
60 @Inject('$state') private $state: ng.ui.IStateService,
61 private homeService: HomeService,
62 private authService: AuthenticationService,
63 private cacheService: CacheService,
64 private translateService: TranslateService,
65 private modalsHandler: ModalsHandler,
66 private modalService: SdcUiServices.ModalService,
67 private loaderService: SdcUiServices.LoaderService,
68 private importVSPService: ImportVSPService,
69 private resourceService: ResourceServiceNg2
73 this.initHomeComponentVars();
77 if (this.$state.params) {
78 if (this.$state.params.folder) {
79 const folderName = this.$state.params.folder.replaceAll('_', ' ');
81 const selectedFolder = this.folders.getFolders().find((tmpFolder: FoldersItemsMenu) => tmpFolder.text === folderName);
83 this.setSelectedFolder(selectedFolder);
85 // Show the tutorial if needed when the dashboard page is opened.<script src="bower_components/angular-filter/dist/angular-filter.min.js"></script>
86 // This is called from the welcome page.
87 } else if (this.$state.params.show === 'tutorial') {
88 this.showTutorial = true;
89 this.isFirstTime = true;
94 // Open onboarding modal
95 public notificationIconCallback(): void {
96 this.importVSPService.openOnboardingModal().subscribe((importVSPdata: ImportVSPdata) => {
97 const actualComponent = importVSPdata.previousComponent;
98 if (!actualComponent || actualComponent.csarVersion !== importVSPdata.componentCsar.csarVersion) {
99 this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, importVSPdata.componentCsar.csarVersion);
101 const vfExistsAndIsNotCheckedOut: boolean = actualComponent && actualComponent.lifecycleState != ComponentState.NOT_CERTIFIED_CHECKOUT;
102 if (vfExistsAndIsNotCheckedOut) {
103 this.checkoutAndRedirectToWorkspace(importVSPdata);
106 this.$state.go('workspace.general', {
107 id: actualComponent && actualComponent.uniqueId,
108 componentCsar: importVSPdata.componentCsar,
109 type: importVSPdata.type
114 private checkoutAndRedirectToWorkspace(importVSPdata: ImportVSPdata) {
115 this.loaderService.activate();
116 this.resourceService.checkout(importVSPdata.previousComponent.uniqueId)
117 .subscribe((componentMetadata: ComponentMetadata) => {
118 this.$state.go('workspace.general', {
119 id: componentMetadata.uniqueId,
120 componentCsar: importVSPdata.componentCsar,
121 type: importVSPdata.type
123 this.loaderService.deactivate();
125 this.loaderService.deactivate();
130 public onImportVf(file: any): void {
131 if (file && file.filename) {
132 // Check that the file has valid extension.
133 const fileExtension: string = file.filename.split('.').pop();
134 if (this.sdcConfig.csarFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
135 this.$state.go('workspace.general', {
136 type: ComponentType.RESOURCE.toLowerCase(),
138 resourceType: ResourceType.VF
141 const title: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE');
142 const message: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS', {extensions: this.sdcConfig.csarFileExtension});
143 this.modalService.openWarningModal(title, message, 'error-invalid-csar-ext');
148 public onImportVfc(file: any): void {
149 if (file && file.filename) {
150 // Check that the file has valid extension.
151 const fileExtension: string = file.filename.split('.').pop();
152 if (this.sdcConfig.toscaFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
153 this.$state.go('workspace.general', {
154 type: ComponentType.RESOURCE.toLowerCase(),
156 resourceType: ResourceType.VFC
159 const title: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS_TITLE');
160 const message: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_TOSCA_EXTENSIONS', {extensions: this.sdcConfig.toscaFileExtension});
161 this.modalService.openWarningModal(title, message, 'error-invalid-tosca-ext');
166 public onImportService(file: any): void {
167 if (file && file.filename) {
168 // Check that the file has valid extension.
169 const fileExtension: string = file.filename.split(".").pop();
170 if (this.sdcConfig.csarFileExtension.indexOf(fileExtension.toLowerCase()) !== -1) {
171 this.$state.go('workspace.general', {
172 type: ComponentType.SERVICE.toLowerCase(),
174 serviceType: 'Service'
177 const title: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS_TITLE');
178 const message: string = this.translateService.translate('NEW_SERVICE_RESOURCE_ERROR_VALID_CSAR_EXTENSIONS', {extensions: this.sdcConfig.csarFileExtension});
179 this.modalService.openWarningModal(title, message, 'error-invalid-csar-ext');
184 public openCreateModal(componentType: string, importedFile: any): void {
186 this.initEntities(true); // Return from import
188 this.$state.go('workspace.general', {type: componentType.toLowerCase()});
192 public createPNF(): void {
193 this.$state.go('workspace.general', {
194 type: ComponentType.RESOURCE.toLowerCase(),
195 resourceType: ResourceType.PNF
199 public createCR(): void {
200 this.$state.go('workspace.general', {
201 type: ComponentType.RESOURCE.toLowerCase(),
202 resourceType: ResourceType.CR
206 public entitiesCount(folderItem: FoldersItemsMenu): any {
207 let total: number = 0;
208 if (folderItem.isGroup()) {
209 this.folders.getFolders().forEach((tmpFolder: FoldersItemsMenu) => {
210 if (tmpFolder.group && tmpFolder.group === (folderItem as FoldersItemsMenuGroup).groupname) {
211 total = total + this._getTotalCounts(tmpFolder);
215 total = total + this._getTotalCounts(folderItem);
220 public updateFilter = () => {
221 this.$state.go('.', this.homeFilter.toUrlParam(), {location: 'replace', notify: false});
222 this.filterHomeItems();
225 public getCurrentFolderDistributed(): any[] {
228 const folderItem: FoldersItemsMenu = this.folders.getCurrentFolder();
229 if (folderItem.isGroup()) {
230 this.folders.getFolders().forEach((tmpFolder: FoldersItemsMenu) => {
231 if (tmpFolder.group && tmpFolder.group === (folderItem as FoldersItemsMenuGroup).groupname) {
232 this._setStates(tmpFolder, states);
236 this._setStates(folderItem, states);
242 public setSelectedFolder(folderItem: FoldersItemsMenu): void {
243 this.folders.setSelected(folderItem);
246 public goToComponent(component: Component): void {
247 const loaderService = this.loaderService;
248 loaderService.activate();
249 this.$state.go('workspace.general', {id: component.uniqueId, type: component.componentType.toLowerCase()}).then(() => {
250 loaderService.deactivate();
254 public raiseNumberOfElementToDisplay(recalculate: boolean = false) {
255 const scrollPageAmount = 35;
256 if (!this.homeItems) {
257 this.numberOfItemToDisplay = 0;
258 } else if (this.homeItems.length > this.numberOfItemToDisplay || recalculate) {
259 let fullPagesAmount = Math.ceil(this.numberOfItemToDisplay / scrollPageAmount) * scrollPageAmount;
260 if (!recalculate || fullPagesAmount === 0) { // TODO trigger infiniteScroll to check bottom and fire onBottomHit by itself (sdc-ui)
261 fullPagesAmount += scrollPageAmount;
263 this.numberOfItemToDisplay = Math.min(this.homeItems.length, fullPagesAmount);
264 this.homeFilteredSlicedItems = this.homeFilteredItems.slice(0, this.numberOfItemToDisplay);
268 public changeCheckboxesFilter(checkboxesFilterArray: string[], checkboxValue: string, checked?: boolean) {
269 const checkboxIdx = checkboxesFilterArray.indexOf(checkboxValue);
271 checked = (checked !== undefined) ? checked : checkboxIdx === -1;
272 if (checked && checkboxIdx === -1) {
273 checkboxesFilterArray.push(checkboxValue);
274 } else if (!checked && checkboxIdx !== -1) {
275 checkboxesFilterArray.splice(checkboxIdx, 1);
280 public changeFilterTerm(filterTerm: string): void {
281 this.homeFilter.search = { filterTerm };
285 public setDisplayActions(display?: boolean) {
286 this.displayActions = display !== undefined ? display : !this.displayActions;
289 private _getTotalCounts(tmpFolder): number {
290 let total: number = 0;
291 if (tmpFolder.dist !== undefined) {
292 const distributions = tmpFolder.dist.split(',');
293 distributions.forEach((item: any) => {
294 total = total + this.getEntitiesByStateDist(tmpFolder.state, item).length;
297 total = total + this.getEntitiesByStateDist(tmpFolder.state, tmpFolder.dist).length;
302 private _setStates(tmpFolder, states) {
303 if (tmpFolder.states !== undefined) {
304 tmpFolder.states.forEach((item: any) => {
305 states.push({state: item.state, dist: item.dist});
308 states.push({state: tmpFolder.state, dist: tmpFolder.dist});
312 private initEntities(reload?: boolean) {
313 if (reload || this.componentShouldReload()) {
314 this.loaderService.activate();
315 this.homeService.getAllComponents(true).subscribe(
316 (components: Component[]) => {
317 this.cacheService.set('breadcrumbsComponentsState', this.$state.current.name); // dashboard
318 this.cacheService.set('breadcrumbsComponents', components);
319 this.homeItems = components;
320 this.loaderService.deactivate();
321 this.filterHomeItems();
322 }, (error) => { this.loaderService.deactivate(); });
324 this.homeItems = this.cacheService.get('breadcrumbsComponents');
325 this.filterHomeItems();
329 private isDefaultFilter = (): boolean => {
330 const defaultFilter = new HomeFilter();
331 return angular.equals(defaultFilter, this.homeFilter);
334 private componentShouldReload = (): boolean => {
335 const breadcrumbsValid: boolean = (this.$state.current.name === this.cacheService.get('breadcrumbsComponentsState') && this.cacheService.contains('breadcrumbsComponents'));
336 return !breadcrumbsValid || this.isDefaultFilter();
339 private getEntitiesByStateDist(state: string, dist: string): Component[] {
340 let gObj: Component[];
341 if (this.homeItems && (state || dist)) {
342 gObj = this.homeItems.filter((obj: Component) => {
343 if (dist !== undefined && obj.distributionStatus === dist && obj.lifecycleState === state) {
345 } else if (dist === undefined && (obj.lifecycleState === state || obj.distributionStatus === state)) {
356 private filterHomeItems() {
357 this.homeFilteredItems = this.makeFilteredItems(this.homeItems, this.homeFilter);
358 this.raiseNumberOfElementToDisplay(true);
359 this.homeFilteredSlicedItems = this.homeFilteredItems.slice(0, this.numberOfItemToDisplay);
362 private makeFilteredItems(homeItems: Array<Component>, filter: HomeFilter) {
363 let filteredComponents: Array<Component | DataTypeCatalogComponent> = homeItems;
365 // filter: exclude all resources of type 'vfcmtType':
366 filteredComponents = filteredComponents.filter((c) =>
367 !c.isResource() || (c as Resource).resourceType.indexOf(this.vfcmtType) === -1);
369 // common entity filter
370 // --------------------------------------------------------------------------
371 filteredComponents = EntityFilterPipe.transform(filteredComponents, filter);
373 return filteredComponents;
376 private initFolders = (): void => {
377 // Note: Do not use SdcUi.ChecklistComponent for folders checkboxes, since from the data structure
378 // it is not determined that all checkboxes under the same group are managed by the same selectedValues array.
380 this.folders = new FoldersMenu(this.roles[this.user.role].folder);
384 private initHomeComponentVars(): void {
385 this.version = this.cacheService.get('version');
386 this.numberOfItemToDisplay = 0;
387 this.displayActions = false;
388 this.user = this.authService.getLoggedinUser();
389 this.roles = this.sdcMenu.roles;
390 this.showTutorial = false;
391 this.isFirstTime = false;
392 this.vfcmtType = ResourceType.VFCMT;
394 // Checkboxes filter init
395 this.homeFilter = new HomeFilter(this.$state.params);
397 // bind callbacks that are transferred as inputs
398 this.notificationIconCallback = this.notificationIconCallback.bind(this);