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