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