0778b2d803dcf3aa58774d1c5d526f11765daf6a
[sdc.git] / catalog-ui / src / app / view-models / workspace / workspace-view-model.ts
1 /*-
2  * ============LICENSE_START=======================================================
3  * SDC
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
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
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=========================================================
19  */
20
21 /**
22  * Created by obarda on 3/30/2016.
23  */
24 'use strict';
25 import * as _ from 'lodash';
26 import {Component, IAppMenu, IUserProperties, Plugin, PluginsConfiguration, Resource, Service} from 'app/models';
27 import {
28     CHANGE_COMPONENT_CSAR_VERSION_FLAG,
29     ChangeLifecycleStateHandler,
30     ComponentFactory,
31     ComponentState,
32     EVENTS,
33     MenuHandler,
34     MenuItem,
35     MenuItemGroup,
36     PREVIOUS_CSAR_COMPONENT,
37     ResourceType,
38     Role,
39     States,
40     WorkspaceMode
41 } from 'app/utils';
42 import {EventListenerService, LeftPaletteLoaderService, ProgressService} from 'app/services';
43 import {CacheService} from 'app/services-ng2';
44 import {SdcUiCommon, SdcUiComponents, SdcUiServices} from 'onap-ui-angular';
45 import {AutomatedUpgradeService} from '../../ng2/pages/automated-upgrade/automated-upgrade.service';
46 import {CatalogService} from '../../ng2/services/catalog.service';
47 import {ComponentServiceNg2} from '../../ng2/services/component-services/component.service';
48 import {EventBusService} from '../../ng2/services/event-bus.service';
49 import {HomeService} from '../../ng2/services/home.service';
50 import {PluginsService} from '../../ng2/services/plugins.service';
51 import {IDependenciesServerResponse} from '../../ng2/services/responses/dependencies-server-response';
52 import {WorkspaceNg1BridgeService} from '../../ng2/pages/workspace/workspace-ng1-bridge-service';
53 import {WorkspaceService} from '../../ng2/pages/workspace/workspace.service';
54
55 export interface IWorkspaceViewModelScope extends ng.IScope {
56
57     isLoading: boolean;
58     isCreateProgress: boolean;
59     component: Component;
60     originComponent: Component;
61     componentType: string;
62     importFile: any;
63     leftBarTabs: MenuItemGroup;
64     isNew: boolean;
65     isFromImport: boolean;
66     isValidForm: boolean;
67     isActiveTopBar: boolean;
68     mode: WorkspaceMode;
69     breadcrumbsModel: Array<MenuItemGroup>;
70     sdcMenu: IAppMenu;
71     changeLifecycleStateButtons: any;
72     version: string;
73     versionsList: Array<any>;
74     changeVersion: any;
75     isComposition: boolean;
76     isDeployment: boolean;
77     isPlugins: boolean;
78     $state: ng.ui.IStateService;
79     user: IUserProperties;
80     thirdParty: boolean;
81     disabledButtons: boolean;
82     menuComponentTitle: string;
83     progressService: ProgressService;
84     progressMessage: string;
85     ComponentServiceNg2: ComponentServiceNg2;
86     unsavedChanges: boolean;
87     unsavedChangesCallback: Function;
88     unsavedFile: boolean;
89     hasNoDependencies: boolean;
90     models: Array<string>;
91
92     startProgress(message: string): void;
93     stopProgress(): void;
94     updateBreadcrumbs(component: Component): void;
95     updateUnsavedFileFlag(isUnsaved: boolean): void;
96     showChangeStateButton(): boolean;
97     getComponent(): Component;
98     setComponent(component: Component): void;
99     setOriginComponent(component: Component): void;
100     onMenuItemPressed(state: string, params: any): ng.IPromise<boolean>;
101     create(): void;
102     save(): Promise<void>;
103     setValidState(isValid: boolean): void;
104     changeLifecycleState(state: string): void;
105     handleChangeLifecycleState(state: string, newCsarVersion?: string, errorFunction?: Function): void;
106     disableMenuItems(): void;
107     enableMenuItems(): void;
108     isDesigner(): boolean;
109     isViewMode(): boolean;
110     isEditMode(): boolean;
111     isCreateMode(): boolean;
112     isDisableMode(): boolean;
113     isGeneralView(): boolean;
114     goToBreadcrumbHome(): void;
115     onVersionChanged(selectedId: string): void;
116     getLatestVersion(): void;
117     getStatus(): string;
118     showLifecycleIcon(): boolean;
119     updateSelectedMenuItem(state: string): void;
120     isSelected(menuItem: MenuItem): boolean;
121     uploadFileChangedInGeneralTab(): void;
122     updateMenuComponentName(ComponentName: string): void;
123     getTabTitle(): string;
124     reload(component: Component): void;
125 }
126
127 export class WorkspaceViewModel {
128
129     static '$inject' = [
130         '$scope',
131         'injectComponent',
132         'ComponentFactory',
133         '$state',
134         'sdcMenu',
135         '$q',
136         'MenuHandler',
137         'Sdc.Services.CacheService',
138         'ChangeLifecycleStateHandler',
139         'LeftPaletteLoaderService',
140         '$filter',
141         'EventListenerService',
142         'Notification',
143         '$stateParams',
144         'HomeService',
145         'CatalogService',
146         'Sdc.Services.ProgressService',
147         'ComponentServiceNg2',
148         'AutomatedUpgradeService',
149         'EventBusService',
150         'ModalServiceSdcUI',
151         'PluginsService',
152         'WorkspaceNg1BridgeService',
153         'workspaceService'
154     ];
155
156     constructor(private $scope: IWorkspaceViewModelScope,
157                 private injectComponent: Component,
158                 private ComponentFactory: ComponentFactory,
159                 private $state: ng.ui.IStateService,
160                 private sdcMenu: IAppMenu,
161                 private $q: ng.IQService,
162                 private MenuHandler: MenuHandler,
163                 private cacheService: CacheService,
164                 private ChangeLifecycleStateHandler: ChangeLifecycleStateHandler,
165                 private LeftPaletteLoaderService: LeftPaletteLoaderService,
166                 private $filter: ng.IFilterService,
167                 private EventListenerService: EventListenerService,
168                 private Notification: any,
169                 private $stateParams: any,
170                 private homeService: HomeService,
171                 private catalogService: CatalogService,
172                 private progressService: ProgressService,
173                 private ComponentServiceNg2: ComponentServiceNg2,
174                 private AutomatedUpgradeService: AutomatedUpgradeService,
175                 private eventBusService: EventBusService,
176                 private modalServiceSdcUI: SdcUiServices.ModalService,
177                 private pluginsService: PluginsService,
178                 private workspaceNg1BridgeService: WorkspaceNg1BridgeService,
179                 private workspaceService: WorkspaceService) {
180
181                 this.initScope();
182                 this.$scope.updateSelectedMenuItem(this.$state.current.name);
183     }
184
185     private role: string;
186     private category: string;
187     private components: Component[];
188     
189     private initViewMode = ():WorkspaceMode => {
190         let mode = WorkspaceMode.VIEW;
191
192         if (!this.$state.params['id']) {   //&& !this.$state.params['vspComponent']
193             mode = WorkspaceMode.CREATE;
194         } else {
195             if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT &&
196                 this.$scope.component.lastUpdaterUserId === this.cacheService.get('user').userId) {
197                 if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role === Role.DESIGNER) {
198                     mode = WorkspaceMode.EDIT;
199                 }
200             }
201         }
202         this.workspaceNg1BridgeService.updateIsViewOnly(mode === WorkspaceMode.VIEW);
203         return mode;
204     }
205
206     private initChangeLifecycleStateButtons = (): void => {
207         let state: string;
208         if (this.$scope.component.isService() && this.$scope.component.lifecycleState === 'CERTIFIED') {
209             state = this.$scope.component.distributionStatus;
210         } else {
211             state = this.$scope.component.lifecycleState;
212         }
213         this.$scope.changeLifecycleStateButtons = (this.sdcMenu.roles[this.role].changeLifecycleStateButtons[state] || [])[this.$scope.component.componentType.toUpperCase()];
214     }
215
216     private initScope = (): void => {
217         this.$scope.component = this.injectComponent;
218         this.$scope.menuComponentTitle = this.$scope.component.name;
219         this.$scope.disabledButtons = false;
220         this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
221         this.$scope.componentType = this.$scope.component.componentType;
222         this.$scope.version = this.cacheService.get('version');
223         this.$scope.user = this.cacheService.get('user');
224         this.role = this.$scope.user.role;
225         this.category = this.$scope.component.selectedCategory;
226         this.$scope.mode = this.initViewMode();
227         this.$scope.isValidForm = true;
228         this.initChangeLifecycleStateButtons();
229         this.initVersionObject();
230         this.$scope.$state = this.$state;
231         this.$scope.isLoading = false;
232         this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1);
233         this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT;
234         this.$scope.progressService = this.progressService;
235         this.$scope.unsavedChanges = false;
236
237         this.$scope.hasNoDependencies = true;
238         this.verifyIfDependenciesExist();
239
240         this.EventListenerService.registerObserverCallback(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.setWorkspaceButtonState);
241         this.$scope.getComponent = (): Component => {
242             return this.$scope.component;
243         };
244
245         this.$scope.updateMenuComponentName = (ComponentName:string):void => {
246             this.$scope.menuComponentTitle = ComponentName;
247         };
248
249         this.$scope.sdcMenu = this.sdcMenu;
250         // Will be called from each step after save to update the resource.
251         this.$scope.setComponent = (component:Component):void => {
252             this.$scope.component = component;
253         };
254
255         this.$scope.setOriginComponent = (component:Component):void => {
256             this.$scope.originComponent = component;
257         }
258
259         this.$scope.uploadFileChangedInGeneralTab = ():void => {
260             // In case user select browse file, and in update mode, need to disable submit for testing and checkin buttons.
261             if (this.$scope.isEditMode() && this.$scope.component.isResource() && (<Resource>this.$scope.component).resourceType == ResourceType.VF) {
262                 // NOTE: Commented out the disabling of the workspace buttons on CSAR updating due fix of a bug [417534]
263                 // this.$scope.disabledButtons = true;
264             }
265         };
266
267         this.$scope.archiveComponent = ():void => {
268             this.$scope.isLoading = true;
269             const typeComponent = this.$scope.component.componentType;
270             this.ComponentServiceNg2.archiveComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
271                 this.$scope.isLoading = false;
272                 if (this.$state.params.previousState) {
273                     switch (this.$state.params.previousState) {
274                         case 'catalog':
275                         case 'dashboard':
276                             this.$state.go(this.$state.params.previousState);
277                             break;
278                         default:
279                             break;
280                     }
281                 }
282                 this.$scope.component.isArchived = true;
283                 this.deleteArchiveCache();
284
285                 this.Notification.success({
286                     message: this.$scope.component.name + ' ' + this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TEXT"),
287                     title: this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TITLE")
288                 });
289             }, (error) => { this.$scope.isLoading = false; });
290         }
291
292         this.$scope.restoreComponent = ():void => {
293             this.$scope.isLoading = true;
294             const typeComponent = this.$scope.component.componentType;
295             this.ComponentServiceNg2.restoreComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
296                 this.$scope.isLoading = false;
297                 this.Notification.success({
298                     message: this.$scope.component.name + ' ' + this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TEXT"),
299                     title: this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TITLE")
300                 });
301                 this.$scope.reload(this.$scope.component);
302             });
303             this.$scope.component.isArchived = false;
304             this.deleteArchiveCache();
305         }
306
307         this.$scope.$on('$stateChangeStart', (event, toState, toParams, fromState, fromParams) => {
308             if(this.$scope.isEditMode()){
309                 if (fromParams.id == toParams.id && this.$state.current.data && this.$state.current.data.unsavedChanges) {
310                     event.preventDefault();
311                     if(this.$scope.isValidForm){
312                         this.$scope.save().then(() => {
313                             this.$scope.onMenuItemPressed(toState.name, toParams);
314                         }, ()=> {
315                             console.error("Save failed, unable to navigate to " + toState.name);
316                         })
317                     } else {
318                         console.error("Form is invalid, unable to navigate to " + toState.name);
319                     }
320                 }
321             }
322
323         });
324
325         this.$scope.$on('$stateChangeSuccess', (event, toState) => {
326             this.$scope.updateSelectedMenuItem(this.$state.current.name);
327         });
328
329         this.$scope.onMenuItemPressed = (state:string, params:any):ng.IPromise<boolean> => {
330
331             let deferred:ng.IDeferred<boolean> = this.$q.defer();
332             let goToState = ():void => {
333                 this.$state.go(state, Object.assign({
334                     id: this.$scope.component.uniqueId,
335                     type: this.$scope.component.componentType.toLowerCase(),
336                     components: this.components
337                 }, params));
338                 deferred.resolve(true);
339             };
340
341             if (this.$scope.isEditMode() && //this is a workaround for amdocs - we need to get the artifact in order to avoid saving the vf when moving from their tabs
342                 (this.$state.current.name === States.WORKSPACE_MANAGEMENT_WORKFLOW || this.$state.current.name === States.WORKSPACE_NETWORK_CALL_FLOW)) {
343                 let onGetSuccess = (component:Component) => {
344                     this.$scope.isLoading = false;
345                     // Update the components
346                     this.$scope.component = component;
347                     goToState();
348                 };
349                 let onFailed = () => {
350                     this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
351                     this.$scope.isLoading = false; // stop the progress.
352                     deferred.reject(false);
353                 };
354                 this.$scope.component.getComponent().then(onGetSuccess, onFailed);
355             } else {
356                 goToState();
357             }
358             return deferred.promise;
359         };
360
361         this.$scope.setValidState = (isValid:boolean):void => {
362             this.$scope.isValidForm = isValid;
363         };
364
365         this.$scope.onVersionChanged = (selectedId:string):void => {
366             if (this.$scope.isGeneralView() && this.$state.current.data.unsavedChanges) {
367                 this.$scope.changeVersion.selectedVersion = _.find(this.$scope.versionsList, (versionObj)=> {
368                     return versionObj.versionId === this.$scope.component.uniqueId;
369                 });
370             }
371
372             let eventData = {
373                 uuid: this.$scope.component.uuid,
374                 version: this.$scope.changeVersion.selectedVersion.versionNumber
375             };
376
377             this.eventBusService.notify("VERSION_CHANGED", eventData).subscribe(() => {
378                 this.$scope.isLoading = true;
379
380                 this.$state.go(this.$state.current.name, {
381                     id: selectedId,
382                     type: this.$scope.componentType.toLowerCase(),
383                     mode: WorkspaceMode.VIEW,
384                     components: this.$state.params['components']
385                 }, {reload: true});
386             });
387         };
388
389         this.$scope.getLatestVersion = ():void => {
390             this.$scope.onVersionChanged(_.first(this.$scope.versionsList).versionId);
391         };
392
393         this.$scope.create = () => {
394
395             this.$scope.startProgress("Creating Asset...");
396             _.first(this.$scope.leftBarTabs.menuItems).isDisabled = true;//disabled click on general tab (DE246274)
397
398              // In case we import CSAR. Notify user that import VF will take long time (the create is performed in the background).
399              if (this.$scope.component.isResource() && (<Resource>this.$scope.component).csarUUID) {
400                 this.Notification.info({
401                     message: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_DESCRIPTION"),
402                     title: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_TITLE")
403                 });
404             }
405
406             let onFailed = () => {
407                 this.$scope.stopProgress();
408                 this.$scope.isLoading = false; // stop the progress.
409                 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = false;//enabled click on general tab (DE246274)
410                 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
411                 let modalInstance:ng.ui.bootstrap.IModalServiceInstance;
412                 modalInstance && modalInstance.close();  // Close the modal in case it is opened.
413                 this.$scope.component.tags = _.without(this.$scope.component.tags, this.$scope.component.name);// for fix DE246217
414
415                 this.$scope.setValidState(true);  // Set the form valid (if sent form is valid, the error from server).
416             };
417
418             let onSuccessCreate = (component:Component) => {
419
420                 this.$scope.stopProgress();
421                 this.showSuccessNotificationMessage();
422
423                 // Update the components list for breadcrumbs
424                 this.components.unshift(component);
425
426                 this.$state.go(States.WORKSPACE_GENERAL, {
427                     id: component.uniqueId,
428                     type: component.componentType.toLowerCase(),
429                     components: this.components
430                 }, {inherit: false});
431             };
432             
433             console.log(this.$scope.component, "this.$scope.component")
434             if ((<Service>this.$scope.component).serviceType == "Service") {
435                 this.ComponentFactory.importComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
436             } else {
437                 this.ComponentFactory.createComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
438             }
439
440
441
442         };
443
444         this.$scope.save = ():Promise<void> => {
445
446             this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_CLICK);
447
448             this.$scope.startProgress("Updating Asset...");
449             this.$scope.disableMenuItems();
450
451             return new Promise<void>((resolve, reject) => {
452                 let stopProgressAndEnableUI = () => {
453                     this.$scope.disabledButtons = false;
454                     this.$scope.isLoading = false;
455                     this.$scope.enableMenuItems();
456                     this.$scope.stopProgress();
457                 }
458
459                 let onFailed = () => {
460                     stopProgressAndEnableUI();
461                     this.$scope.updateUnsavedFileFlag(true);
462                     this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
463
464                     reject();
465                 };
466
467                 let onSuccessUpdate = (component:Component) => {
468                     stopProgressAndEnableUI();
469                     this.showSuccessNotificationMessage();
470
471                     component.tags = _.reject(component.tags, (item)=> {
472                         return item === component.name
473                     });
474
475                     this.$scope.updateBreadcrumbs(component);
476
477                     //update the component
478                     this.$scope.setComponent(component);
479                     this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
480
481                     if (this.cacheService.contains(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
482                         this.cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
483                     }
484                     if (this.cacheService.contains(PREVIOUS_CSAR_COMPONENT)) {
485                         this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
486                     }
487
488                     //clear edit flags
489                     this.$state.current.data.unsavedChanges = false;
490                     this.$scope.unsavedFile = false;
491                     this.$scope.reload(component);
492                     resolve();
493                 };
494
495                 this.$scope.component.updateComponent().then(onSuccessUpdate, onFailed);
496             });
497
498         };
499
500         this.$scope.changeLifecycleState = (state:string):void => {
501             if (this.$scope.isGeneralView() && state !== 'deleteVersion') {
502                 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE, state);
503             } else {
504                 this.$scope.handleChangeLifecycleState(state);
505             }
506         };
507
508         let defaultActionAfterChangeLifecycleState = ():void => {
509             if (this.$state.current.data && this.$state.current.data.unsavedChanges) {
510                 this.$state.current.data.unsavedChanges = false;
511             }
512             this.$state.go('dashboard');
513         };
514
515         this.$scope.handleChangeLifecycleState = (state:string, newCsarVersion?:string, onError?: Function) => {
516             if ('monitor' === state) {
517                 this.$state.go('workspace.distribution');
518                 return;
519             }
520
521             let data = this.$scope.changeLifecycleStateButtons[state];
522             if (!data && this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
523                 data = {text: 'Check Out', url: 'lifecycleState/CHECKOUT'};
524             }
525             const onSuccess = (component, url:string):void => {
526                 // Updating the component from server response
527  
528                 // Creating the data object to notify the plugins with
529                 const eventData: any = {
530                     uuid: this.$scope.component.uuid,
531                     version: this.$scope.component.version
532                 };
533
534                 // the server returns only metaData (small component) except checkout (Full component)  ,so we update only the statuses of distribution & lifecycle
535                 this.$scope.component.lifecycleState = component.lifecycleState;
536                 this.$scope.component.distributionStatus = component.distributionStatus;
537
538                 switch (url) {
539                     case 'lifecycleState/CHECKOUT':
540                         this.workspaceNg1BridgeService.updateIsViewOnly(false);
541                         this.eventBusService.notify("CHECK_OUT", eventData, false).subscribe(() => {
542                             // only checkOut get the full component from server
543                             //   this.$scope.component = component;
544                             // Work around to change the csar version
545                             if(newCsarVersion) {
546                                 this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, newCsarVersion);
547                                 (this.$scope.component as Resource).csarVersion = newCsarVersion;
548                             }
549
550                             //when checking out a minor version uuid remains
551                             const bcIdx = _.findIndex(this.components, (item) => {
552                                 return item.uuid === component.uuid;
553                             });
554                             if (bcIdx !== -1) {
555                                 this.components[bcIdx] = component;
556                             } else {
557                                 //when checking out a major(certified) version
558                                 this.components.unshift(component);
559                             }
560                             this.$scope.mode = this.initViewMode();
561                             this.initChangeLifecycleStateButtons();
562                             this.initVersionObject();
563                             this.$scope.isLoading = false;
564                             this.EventListenerService.notifyObservers(EVENTS.ON_CHECKOUT, component);
565                             this.workspaceService.setComponentMetadata(component.componentMetadata);
566
567                             this.Notification.success({
568                                 message: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TEXT"),
569                                 title: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TITLE")
570                             });
571
572                         });
573                         break;
574                     case 'lifecycleState/CHECKIN':
575                         this.workspaceNg1BridgeService.updateIsViewOnly(true);
576                         defaultActionAfterChangeLifecycleState();
577                         this.Notification.success({
578                             message: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TEXT"),
579                             title: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TITLE")
580                         });
581                         break;
582                     case 'lifecycleState/UNDOCHECKOUT':
583                         this.eventBusService.notify("UNDO_CHECK_OUT", eventData, false).subscribe(() => {
584                             defaultActionAfterChangeLifecycleState();
585                             this.Notification.success({
586                                 message: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
587                                 title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
588                             });
589                         });
590                         break;
591                     case 'lifecycleState/certify':
592                         this.$scope.handleCertification(component);
593                         this.verifyIfDependenciesExist();
594                         this.$scope.reload(component);
595                         break;
596                     case 'distribution/PROD/activate':
597                         this.Notification.success({
598                             message: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TEXT"),
599                             title: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TITLE")
600                         });
601                         this.initChangeLifecycleStateButtons();
602                         break;
603                     default :
604                         defaultActionAfterChangeLifecycleState();
605                 }
606                 if (data.url !== 'lifecycleState/CHECKOUT') {
607                     this.$scope.isLoading = false;
608                 }
609             };
610             this.ChangeLifecycleStateHandler.changeLifecycleState(this.$scope.component, data, this.$scope, onSuccess);
611         };
612
613         this.$scope.deleteArchivedComponent = (): void => {
614             const modalTitle: string = this.$filter('translate')("COMPONENT_VIEW_DELETE_MODAL_TITLE");
615             const modalMessage: string = this.$filter('translate')("COMPONENT_VIEW_DELETE_MODAL_TEXT");
616             const modalButton = {
617                 testId: 'ok-button',
618                 text: this.sdcMenu.alertMessages.okButton,
619                 type: SdcUiCommon.ButtonType.warning,
620                 callback: this.$scope.handleDeleteArchivedComponent,
621                 closeModal: true
622             } as SdcUiComponents.ModalButtonComponent;
623             this.modalServiceSdcUI.openWarningModal(modalTitle, modalMessage, 'alert-modal', [modalButton]);
624         };
625
626         this.$scope.handleDeleteArchivedComponent = (): void => {
627             this.$scope.isLoading = true;
628             const typeComponent = this.$scope.component.componentType;
629             this.ComponentServiceNg2.deleteComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
630                 this.deleteArchiveCache();
631                 this.Notification.success({
632                     message: this.$scope.component.name + ' ' + this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
633                     title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
634                 });
635                 if (this.$state.params.previousState) {
636                     switch (this.$state.params.previousState) {
637                         case 'catalog':
638                         case 'dashboard':
639                             this.$state.go(this.$state.params.previousState);
640                             break;
641                         default:
642                             this.$state.go('dashboard');
643                             break;
644                     }
645                 }
646                 this.$scope.isLoading = false;
647             }, () => {
648                 this.Notification.error({
649                     message: this.$scope.component.name + ' ' + this.$filter('translate')('DELETE_FAILURE_MESSAGE_TEXT'),
650                     title: this.$filter('translate')('DELETE_FAILURE_MESSAGE_TITLE')
651                 });
652                 this.$scope.isLoading = false;
653             });
654         };
655
656         this.$scope.isViewMode = ():boolean => {
657             return this.$scope.mode === WorkspaceMode.VIEW;
658         };
659
660         this.$scope.isDesigner = ():boolean => {
661             return this.role == Role.DESIGNER;
662         };
663
664         this.$scope.isDisableMode = ():boolean => {
665             return this.$scope.mode === WorkspaceMode.VIEW && this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKIN;
666         };
667
668         this.$scope.isGeneralView = ():boolean => {
669             //we show revert and save icons only in general view
670             return this.$state.current.name === States.WORKSPACE_GENERAL;
671         };
672
673         this.$scope.isCreateMode = ():boolean => {
674             return this.$scope.mode === WorkspaceMode.CREATE;
675         };
676
677         this.$scope.checkDisableButton = (button: any):boolean => {
678             // Logic moved from html to component
679             if (this.$scope.isCreateMode() || button.disabled || this.$scope.disabledButtons || !this.$scope.isValidForm || this.$scope.unsavedChanges || this.$scope.component.isArchived){
680                 return true;
681             }
682
683             // Specific verification for Checkout - enabled only in case the component is the latest version.
684             let result: boolean = false;
685
686             if (button.url === 'lifecycleState/CHECKOUT') {
687                 result = !this.$scope.component.isLatestVersion();
688             }
689             return result;
690         };
691
692         this.$scope.isEditMode = ():boolean => {
693             return this.$scope.mode === WorkspaceMode.EDIT;
694         };
695
696         this.$scope.goToBreadcrumbHome = ():void => {
697             let bcHome:MenuItemGroup = this.$scope.breadcrumbsModel[0];
698             this.$state.go(bcHome.menuItems[bcHome.selectedIndex].state);
699         };
700
701         this.$scope.showLifecycleIcon = ():boolean => {
702             return this.role == Role.DESIGNER;
703         };
704
705         this.$scope.getStatus = ():string => {
706             if (this.$scope.isCreateMode()) {
707                 return 'IN DESIGN';
708             }
709
710             return this.$scope.component.getStatus(this.sdcMenu);
711         };
712
713         this.initMenuItems();
714
715         this.$scope.showLatestVersion = (): boolean => {
716             let result: boolean = true;
717             if (!this.$scope.component.isLatestVersion()) {
718                 result = false;
719             }
720             if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) {
721                 result = false;
722             }
723             return result;
724         };
725
726         this.$scope.updateSelectedMenuItem = (state:string):void => {
727             let stateArray:Array<string> = state.split('.', 2);
728             let stateWithoutInternalNavigate:string = stateArray[0] + '.' + stateArray[1];
729             let selectedItem:MenuItem = _.find(this.$scope.leftBarTabs.menuItems, (item:MenuItem) => {
730                 let itemStateArray:Array<string> = item.state.split('.', 2);
731                 let itemStateWithoutNavigation:string = itemStateArray[0] + '.' + itemStateArray[1];
732                 return (itemStateWithoutNavigation === stateWithoutInternalNavigate);
733             });
734
735             let selectedIndex = selectedItem ? this.$scope.leftBarTabs.menuItems.indexOf(selectedItem) : 0;
736
737             if (stateArray[1] === 'plugins') {
738                 _.forEach(PluginsConfiguration.plugins, (plugin) => {
739                     if (plugin.pluginStateUrl == this.$state.params.path) {
740                         return false;
741                     }
742                     else if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
743                         selectedIndex++;
744                     }
745                 });
746             }
747
748             this.$scope.leftBarTabs.selectedIndex = selectedIndex;
749         };
750
751         this.$scope.isSelected = (menuItem: MenuItem): boolean => {
752             return this.$scope.leftBarTabs.selectedIndex === _.indexOf(this.$scope.leftBarTabs.menuItems, menuItem);
753         };
754
755         this.$scope.$watch('$state.current.name', (newVal: string): void => {
756             if (newVal) {
757                 this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1);
758                 this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT;
759                 this.$scope.isPlugins = newVal == States.WORKSPACE_PLUGINS;
760             }
761         });
762
763         this.$scope.getTabTitle = (): string => {
764             return this.$scope.leftBarTabs.menuItems.find((menuItem: MenuItem) => {
765                 return menuItem.state == this.$scope.$state.current.name;
766             }).text;
767         };
768
769         this.$scope.reload = (component: Component): void => {
770             const isGeneralTab = this.$state.current.name === States.WORKSPACE_GENERAL;
771             // nullify the componentCsar in case we are in general tab so we know we didnt came from updateVsp Modal
772             if (isGeneralTab) {
773                 this.$state.go(this.$state.current.name, {id: component.uniqueId, componentCsar: null}, {reload: true});
774             } else {
775                 this.$state.go(this.$state.current.name, {id: component.uniqueId}, {reload: true});
776             }
777         };
778
779         this.$scope.$on('$destroy', () => {
780             this.EventListenerService.unRegisterObserver(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES);
781         });
782
783         this.$scope.openAutomatedUpgradeModal = ():void => {
784             this.$scope.isLoading = true;
785             this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>)=> {
786                 this.$scope.isLoading = false;
787                 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, false);
788             });
789         }
790
791         this.$scope.handleCertification = (certifyComponent): void => {
792             if (this.$scope.component.getComponentSubType() === ResourceType.VF || this.$scope.component.isService()) {
793                 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>) => {
794                     this.$scope.isLoading = false;
795
796                     const isUpgradeNeeded = _.filter(response, (componentToUpgrade:IDependenciesServerResponse) => {
797                         return componentToUpgrade.dependencies && componentToUpgrade.dependencies.length > 0;
798                     });
799                     if (isUpgradeNeeded.length === 0) {
800                         this.onSuccessWithoutUpgradeNeeded();
801                         return;
802                     }
803                     this.refreshDataAfterChangeLifecycleState(certifyComponent);
804                     this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, true);
805                 });
806             } else {
807                 this.onSuccessWithoutUpgradeNeeded();
808             }
809         }
810
811         this.$scope.disableMenuItems = () => {
812             this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
813                 item.isDisabled = (States.WORKSPACE_GENERAL !== item.state);
814             });
815         }
816
817         this.$scope.enableMenuItems = () => {
818             this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
819                 item.isDisabled = false;
820             });
821         };
822
823
824         this.$scope.startProgress = (message: string): void => {
825             this.progressService.initCreateComponentProgress(this.$scope.component.uniqueId);
826             this.$scope.isCreateProgress = true;
827             this.$scope.progressMessage = message;
828         };
829
830         this.$scope.stopProgress = (): void => {
831             this.$scope.isCreateProgress = false;
832             this.progressService.deleteProgressValue(this.$scope.component.uniqueId);
833         }
834
835         this.$scope.updateBreadcrumbs = (component: Component): void => {
836             // Update the components list for breadcrumbs
837             const bcIdx = this.MenuHandler.findBreadcrumbComponentIndex(this.components, component);
838             if (bcIdx !== -1) {
839                 this.components[bcIdx] = component;
840                 this.initBreadcrumbs();  // re-calculate breadcrumbs
841             }
842         };
843
844         this.$scope.updateUnsavedFileFlag = (isUnsaved:boolean) => {
845             this.$scope.unsavedFile = isUnsaved;
846         };
847
848     }
849
850     private onSuccessWithoutUpgradeNeeded = (): void => {
851         this.$scope.isLoading = false;
852         this.Notification.success({
853             message: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TEXT'),
854             title: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TITLE')
855         });
856         this.initVersionObject();
857         this.initChangeLifecycleStateButtons();
858     }
859
860     private refreshDataAfterChangeLifecycleState = (component:Component):void => {
861         this.$scope.isLoading = false;
862         this.$scope.mode = this.initViewMode();
863         this.initChangeLifecycleStateButtons();
864         this.initVersionObject();
865         this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE, component);
866     }
867
868     private initAfterScope = (): void => {
869         // In case user select csar from the onboarding modal, need to disable checkout and submit for testing.
870         if (this.$state.params['disableButtons'] === true) {
871             this.$scope.uploadFileChangedInGeneralTab();
872         }
873     };
874
875     private initVersionObject = (): void => {
876         this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse();
877         this.$scope.changeVersion = {
878             selectedVersion: _.find(this.$scope.versionsList, (versionObj) => {
879                 return versionObj.versionId === this.$scope.component.uniqueId;
880             })
881         };
882     }
883
884     private getNewComponentBreadcrumbItem = (): MenuItem => {
885         let text = '';
886         if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
887             text = this.$scope.component.getComponentSubType() + ': ' + this.$scope.component.name;
888         } else {
889             text = 'Create new ' + this.$state.params['type'];
890         }
891         return new MenuItem(text, null, States.WORKSPACE_GENERAL, 'goToState', [this.$state.params]);
892     }
893
894     private updateMenuItemByRole = (menuItems: any[], role: string) => {
895         const tempMenuItems: any[] = new Array<any>();
896         menuItems.forEach((item: any) => {
897             //remove item if role is disabled
898             if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) {
899                 tempMenuItems.push(item);
900             }
901         });
902         return tempMenuItems;
903     }
904
905         private updateMenuItemByCategory = (menuItems:Array<any>, category:string) => {
906         let tempMenuItems:Array<any> = new Array<any>();
907         menuItems.forEach((item:any) => {
908             //update flag disabledCategory to true if category is disabled
909             item.disabledCategory = false;
910             if ((item.disabledCategories && item.disabledCategories.indexOf(category) > -1))
911             {
912                 item.disabledCategory = true;
913             }
914             tempMenuItems.push(item);
915         });
916         return tempMenuItems;
917     };
918
919
920     private deleteArchiveCache = () => {
921         this.cacheService.remove('archiveComponents'); // delete the cache to ensure the archive is reloaded from server
922     }
923
924     private initBreadcrumbs = () => {
925         this.components = this.cacheService.get('breadcrumbsComponents');
926         const breadcrumbsComponentsLvl = this.MenuHandler.generateBreadcrumbsModelFromComponents(this.components, this.$scope.component);
927
928         if (this.$scope.isCreateMode()) {
929             const createItem = this.getNewComponentBreadcrumbItem();
930             if (!breadcrumbsComponentsLvl.menuItems) {
931                 breadcrumbsComponentsLvl.menuItems = [];
932             }
933             breadcrumbsComponentsLvl.menuItems.unshift(createItem);
934             breadcrumbsComponentsLvl.selectedIndex = 0;
935         }
936
937         this.$scope.breadcrumbsModel = [breadcrumbsComponentsLvl, this.$scope.leftBarTabs];
938     }
939
940     private initMenuItems() {
941
942         const inCreateMode = this.$scope.isCreateMode();
943         this.$scope.leftBarTabs = new MenuItemGroup();
944         let menuItemsObjects: any[] = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
945         if (this.$scope.component.getComponentSubType() === 'SERVICE') {
946             const menuItemsObjectsCategory: any[] = this.updateMenuItemByCategory(menuItemsObjects, this.category);
947             menuItemsObjects = menuItemsObjectsCategory;
948         }
949
950         // Only adding plugins to the workspace if they can be displayed for the current user role
951         _.each(PluginsConfiguration.plugins, (plugin: Plugin) => {
952             if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
953                 menuItemsObjects.push({
954                     text: plugin.pluginDisplayOptions['context'].displayName,
955                     action: 'onMenuItemPressed',
956                     state: 'workspace.plugins',
957                     params: {path: plugin.pluginStateUrl}
958                 });
959             }
960         });
961
962         this.$scope.leftBarTabs.menuItems = menuItemsObjects.map((item: MenuItem) => {
963             const menuItem = new MenuItem(item.text, item.callback, item.state, item.action, item.params, item.blockedForTypes, item.disabledCategory);
964             if (menuItem.params) {
965                 menuItem.params.state = menuItem.state;
966             }
967             else {
968                 menuItem.params = {state: menuItem.state};
969             }
970             menuItem.callback = () => this.$scope[menuItem.action](menuItem.state, menuItem.params);
971             menuItem.isDisabled = (inCreateMode && States.WORKSPACE_GENERAL !== menuItem.state) ||
972                 (States.WORKSPACE_DEPLOYMENT === menuItem.state && this.$scope.component.modules
973                 && this.$scope.component.modules.length === 0 && this.$scope.component.isResource()) ||
974                 (menuItem.disabledCategory === true);
975             return menuItem;
976         });
977
978         if (this.cacheService.get('breadcrumbsComponents')) {
979             this.initBreadcrumbs();
980         }
981         else {
982             this.initBreadcrumbsComponents();
983         }
984     }
985
986     private showSuccessNotificationMessage = ():void => {
987         this.Notification.success({
988             message: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_DESCRIPTION'),
989             title: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_TITLE')
990         });
991     }
992
993     private setWorkspaceButtonState = (newState: boolean, callback?: Function) => {
994         this.$scope.unsavedChanges = newState;
995         this.$scope.unsavedChangesCallback = callback;
996     }
997
998     private initBreadcrumbsComponents = (): void => {
999         let breadcrumbsComponentsObservable;
1000         if (this.$stateParams.previousState === 'dashboard') {
1001             breadcrumbsComponentsObservable = this.homeService.getAllComponents(true);
1002         } else if (this.$stateParams.previousState === 'catalog') {
1003             breadcrumbsComponentsObservable = this.catalogService.getCatalog();
1004         } else {
1005             this.cacheService.remove('breadcrumbsComponentsState');
1006             this.cacheService.remove('breadcrumbsComponents');
1007             return;
1008         }
1009         breadcrumbsComponentsObservable.subscribe((components) => {
1010             this.cacheService.set('breadcrumbsComponentsState', this.$stateParams.previousState);
1011             this.cacheService.set('breadcrumbsComponents', components);
1012             this.initBreadcrumbs();
1013         });
1014
1015     }
1016
1017     private verifyIfDependenciesExist(): void {
1018         let containsDependencies = [];
1019         if (this.$scope.component.componentType && this.$scope.component.uniqueId &&
1020             this.$scope.component.lifecycleState === 'CERTIFIED' && (this.$scope.component.isService() || this.$scope.component.getComponentSubType() === 'VF')) {
1021             this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response: IDependenciesServerResponse[]) => {
1022                 containsDependencies = response.filter((version) => version.dependencies);
1023                 if (containsDependencies.length > 0) {
1024                     this.$scope.hasNoDependencies = false;
1025                 } else {
1026                     this.$scope.hasNoDependencies = true;
1027                 }
1028             });
1029         }
1030     }
1031 }