2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
22 * Created by obarda on 3/30/2016.
25 import * as _ from 'lodash';
26 import {Component, IAppMenu, IUserProperties, Plugin, PluginsConfiguration, Resource, Service} from 'app/models';
28 CHANGE_COMPONENT_CSAR_VERSION_FLAG,
29 ChangeLifecycleStateHandler,
36 PREVIOUS_CSAR_COMPONENT,
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';
55 export interface IWorkspaceViewModelScope extends ng.IScope {
58 isCreateProgress: boolean;
60 originComponent: Component;
61 componentType: string;
63 leftBarTabs: MenuItemGroup;
65 isFromImport: boolean;
67 isActiveTopBar: boolean;
69 breadcrumbsModel: Array<MenuItemGroup>;
71 changeLifecycleStateButtons: any;
73 versionsList: Array<any>;
75 isComposition: boolean;
76 isDeployment: boolean;
78 $state: ng.ui.IStateService;
79 user: IUserProperties;
81 disabledButtons: boolean;
82 menuComponentTitle: string;
83 progressService: ProgressService;
84 progressMessage: string;
85 ComponentServiceNg2: ComponentServiceNg2;
86 unsavedChanges: boolean;
87 unsavedChangesCallback: Function;
89 hasNoDependencies: boolean;
90 models: Array<string>;
92 startProgress(message: string): void;
94 updateBreadcrumbs(component: Component): void;
95 updateUnsavedFileFlag(isUnsaved: boolean): void;
96 showChangeStateButton(): boolean;
97 getComponent(): Component;
98 setComponent(component: Component): void;
99 setOriginComponent(component: Component): void;
100 onMenuItemPressed(state: string, params: any): ng.IPromise<boolean>;
102 save(): Promise<void>;
103 setValidState(isValid: boolean): void;
104 changeLifecycleState(state: string): void;
105 handleChangeLifecycleState(state: string, newCsarVersion?: string, errorFunction?: Function): void;
106 disableMenuItems(): void;
107 enableMenuItems(): void;
108 isDesigner(): boolean;
109 isViewMode(): boolean;
110 isEditMode(): boolean;
111 isCreateMode(): boolean;
112 isDisableMode(): boolean;
113 isGeneralView(): boolean;
114 goToBreadcrumbHome(): void;
115 onVersionChanged(selectedId: string): void;
116 getLatestVersion(): void;
118 showLifecycleIcon(): boolean;
119 updateSelectedMenuItem(state: string): void;
120 isSelected(menuItem: MenuItem): boolean;
121 uploadFileChangedInGeneralTab(): void;
122 updateMenuComponentName(ComponentName: string): void;
123 getTabTitle(): string;
124 reload(component: Component): void;
127 export class WorkspaceViewModel {
137 'Sdc.Services.CacheService',
138 'ChangeLifecycleStateHandler',
139 'LeftPaletteLoaderService',
141 'EventListenerService',
146 'Sdc.Services.ProgressService',
147 'ComponentServiceNg2',
148 'AutomatedUpgradeService',
152 'WorkspaceNg1BridgeService',
156 constructor(private $scope: IWorkspaceViewModelScope,
157 private injectComponent: Component,
158 private ComponentFactory: ComponentFactory,
159 private $state: ng.ui.IStateService,
160 private sdcMenu: IAppMenu,
161 private $q: ng.IQService,
162 private MenuHandler: MenuHandler,
163 private cacheService: CacheService,
164 private ChangeLifecycleStateHandler: ChangeLifecycleStateHandler,
165 private LeftPaletteLoaderService: LeftPaletteLoaderService,
166 private $filter: ng.IFilterService,
167 private EventListenerService: EventListenerService,
168 private Notification: any,
169 private $stateParams: any,
170 private homeService: HomeService,
171 private catalogService: CatalogService,
172 private progressService: ProgressService,
173 private ComponentServiceNg2: ComponentServiceNg2,
174 private AutomatedUpgradeService: AutomatedUpgradeService,
175 private eventBusService: EventBusService,
176 private modalServiceSdcUI: SdcUiServices.ModalService,
177 private pluginsService: PluginsService,
178 private workspaceNg1BridgeService: WorkspaceNg1BridgeService,
179 private workspaceService: WorkspaceService) {
182 this.$scope.updateSelectedMenuItem(this.$state.current.name);
185 private role: string;
186 private category: string;
187 private components: Component[];
189 private initViewMode = ():WorkspaceMode => {
190 let mode = WorkspaceMode.VIEW;
192 if (!this.$state.params['id']) { //&& !this.$state.params['vspComponent']
193 mode = WorkspaceMode.CREATE;
195 if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT &&
196 this.$scope.component.lastUpdaterUserId === this.cacheService.get('user').userId) {
197 if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role === Role.DESIGNER) {
198 mode = WorkspaceMode.EDIT;
202 this.workspaceNg1BridgeService.updateIsViewOnly(mode === WorkspaceMode.VIEW);
206 private initChangeLifecycleStateButtons = (): void => {
208 if (this.$scope.component.isService() && this.$scope.component.lifecycleState === 'CERTIFIED') {
209 state = this.$scope.component.distributionStatus;
211 state = this.$scope.component.lifecycleState;
213 this.$scope.changeLifecycleStateButtons = (this.sdcMenu.roles[this.role].changeLifecycleStateButtons[state] || [])[this.$scope.component.componentType.toUpperCase()];
216 private initScope = (): void => {
217 this.$scope.component = this.injectComponent;
218 this.$scope.menuComponentTitle = this.$scope.component.name;
219 this.$scope.disabledButtons = false;
220 this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
221 this.$scope.componentType = this.$scope.component.componentType;
222 this.$scope.version = this.cacheService.get('version');
223 this.$scope.user = this.cacheService.get('user');
224 this.role = this.$scope.user.role;
225 this.category = this.$scope.component.selectedCategory;
226 this.$scope.mode = this.initViewMode();
227 this.$scope.isValidForm = true;
228 this.initChangeLifecycleStateButtons();
229 this.initVersionObject();
230 this.$scope.$state = this.$state;
231 this.$scope.isLoading = false;
232 this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1);
233 this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT;
234 this.$scope.progressService = this.progressService;
235 this.$scope.unsavedChanges = false;
237 this.$scope.hasNoDependencies = true;
238 this.verifyIfDependenciesExist();
240 this.EventListenerService.registerObserverCallback(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.setWorkspaceButtonState);
241 this.$scope.getComponent = (): Component => {
242 return this.$scope.component;
245 this.$scope.updateMenuComponentName = (ComponentName:string):void => {
246 this.$scope.menuComponentTitle = ComponentName;
249 this.$scope.sdcMenu = this.sdcMenu;
250 // Will be called from each step after save to update the resource.
251 this.$scope.setComponent = (component:Component):void => {
252 this.$scope.component = component;
255 this.$scope.setOriginComponent = (component:Component):void => {
256 this.$scope.originComponent = component;
259 this.$scope.uploadFileChangedInGeneralTab = ():void => {
260 // In case user select browse file, and in update mode, need to disable submit for testing and checkin buttons.
261 if (this.$scope.isEditMode() && this.$scope.component.isResource() && (<Resource>this.$scope.component).resourceType == ResourceType.VF) {
262 // NOTE: Commented out the disabling of the workspace buttons on CSAR updating due fix of a bug [417534]
263 // this.$scope.disabledButtons = true;
267 this.$scope.archiveComponent = ():void => {
268 this.$scope.isLoading = true;
269 const typeComponent = this.$scope.component.componentType;
270 this.ComponentServiceNg2.archiveComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
271 this.$scope.isLoading = false;
272 if (this.$state.params.previousState) {
273 switch (this.$state.params.previousState) {
276 this.$state.go(this.$state.params.previousState);
282 this.$scope.component.isArchived = true;
283 this.deleteArchiveCache();
285 this.Notification.success({
286 message: this.$scope.component.name + ' ' + this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TEXT"),
287 title: this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TITLE")
289 }, (error) => { this.$scope.isLoading = false; });
292 this.$scope.restoreComponent = ():void => {
293 this.$scope.isLoading = true;
294 const typeComponent = this.$scope.component.componentType;
295 this.ComponentServiceNg2.restoreComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
296 this.$scope.isLoading = false;
297 this.Notification.success({
298 message: this.$scope.component.name + ' ' + this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TEXT"),
299 title: this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TITLE")
301 this.$scope.reload(this.$scope.component);
303 this.$scope.component.isArchived = false;
304 this.deleteArchiveCache();
307 this.$scope.$on('$stateChangeStart', (event, toState, toParams, fromState, fromParams) => {
308 if(this.$scope.isEditMode()){
309 if (fromParams.id == toParams.id && this.$state.current.data && this.$state.current.data.unsavedChanges) {
310 event.preventDefault();
311 if(this.$scope.isValidForm){
312 this.$scope.save().then(() => {
313 this.$scope.onMenuItemPressed(toState.name, toParams);
315 console.error("Save failed, unable to navigate to " + toState.name);
318 console.error("Form is invalid, unable to navigate to " + toState.name);
325 this.$scope.$on('$stateChangeSuccess', (event, toState) => {
326 this.$scope.updateSelectedMenuItem(this.$state.current.name);
329 this.$scope.onMenuItemPressed = (state:string, params:any):ng.IPromise<boolean> => {
331 let deferred:ng.IDeferred<boolean> = this.$q.defer();
332 let goToState = ():void => {
333 this.$state.go(state, Object.assign({
334 id: this.$scope.component.uniqueId,
335 type: this.$scope.component.componentType.toLowerCase(),
336 components: this.components
338 deferred.resolve(true);
341 if (this.$scope.isEditMode() && //this is a workaround for amdocs - we need to get the artifact in order to avoid saving the vf when moving from their tabs
342 (this.$state.current.name === States.WORKSPACE_MANAGEMENT_WORKFLOW || this.$state.current.name === States.WORKSPACE_NETWORK_CALL_FLOW)) {
343 let onGetSuccess = (component:Component) => {
344 this.$scope.isLoading = false;
345 // Update the components
346 this.$scope.component = component;
349 let onFailed = () => {
350 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
351 this.$scope.isLoading = false; // stop the progress.
352 deferred.reject(false);
354 this.$scope.component.getComponent().then(onGetSuccess, onFailed);
358 return deferred.promise;
361 this.$scope.setValidState = (isValid:boolean):void => {
362 this.$scope.isValidForm = isValid;
365 this.$scope.onVersionChanged = (selectedId:string):void => {
366 if (this.$scope.isGeneralView() && this.$state.current.data.unsavedChanges) {
367 this.$scope.changeVersion.selectedVersion = _.find(this.$scope.versionsList, (versionObj)=> {
368 return versionObj.versionId === this.$scope.component.uniqueId;
373 uuid: this.$scope.component.uuid,
374 version: this.$scope.changeVersion.selectedVersion.versionNumber
377 this.eventBusService.notify("VERSION_CHANGED", eventData).subscribe(() => {
378 this.$scope.isLoading = true;
380 this.$state.go(this.$state.current.name, {
382 type: this.$scope.componentType.toLowerCase(),
383 mode: WorkspaceMode.VIEW,
384 components: this.$state.params['components']
389 this.$scope.getLatestVersion = ():void => {
390 this.$scope.onVersionChanged(_.first(this.$scope.versionsList).versionId);
393 this.$scope.create = () => {
395 this.$scope.startProgress("Creating Asset...");
396 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = true;//disabled click on general tab (DE246274)
398 // In case we import CSAR. Notify user that import VF will take long time (the create is performed in the background).
399 if (this.$scope.component.isResource() && (<Resource>this.$scope.component).csarUUID) {
400 this.Notification.info({
401 message: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_DESCRIPTION"),
402 title: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_TITLE")
406 let onFailed = () => {
407 this.$scope.stopProgress();
408 this.$scope.isLoading = false; // stop the progress.
409 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = false;//enabled click on general tab (DE246274)
410 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
411 let modalInstance:ng.ui.bootstrap.IModalServiceInstance;
412 modalInstance && modalInstance.close(); // Close the modal in case it is opened.
413 this.$scope.component.tags = _.without(this.$scope.component.tags, this.$scope.component.name);// for fix DE246217
415 this.$scope.setValidState(true); // Set the form valid (if sent form is valid, the error from server).
418 let onSuccessCreate = (component:Component) => {
420 this.$scope.stopProgress();
421 this.showSuccessNotificationMessage();
423 // Update the components list for breadcrumbs
424 this.components.unshift(component);
426 this.$state.go(States.WORKSPACE_GENERAL, {
427 id: component.uniqueId,
428 type: component.componentType.toLowerCase(),
429 components: this.components
430 }, {inherit: false});
433 console.log(this.$scope.component, "this.$scope.component")
434 if ((<Service>this.$scope.component).serviceType == "Service") {
435 this.ComponentFactory.importComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
437 this.ComponentFactory.createComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
444 this.$scope.save = ():Promise<void> => {
446 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_CLICK);
448 this.$scope.startProgress("Updating Asset...");
449 this.$scope.disableMenuItems();
451 return new Promise<void>((resolve, reject) => {
452 let stopProgressAndEnableUI = () => {
453 this.$scope.disabledButtons = false;
454 this.$scope.isLoading = false;
455 this.$scope.enableMenuItems();
456 this.$scope.stopProgress();
459 let onFailed = () => {
460 stopProgressAndEnableUI();
461 this.$scope.updateUnsavedFileFlag(true);
462 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
467 let onSuccessUpdate = (component:Component) => {
468 stopProgressAndEnableUI();
469 this.showSuccessNotificationMessage();
471 component.tags = _.reject(component.tags, (item)=> {
472 return item === component.name
475 this.$scope.updateBreadcrumbs(component);
477 //update the component
478 this.$scope.setComponent(component);
479 this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
481 if (this.cacheService.contains(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
482 this.cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
484 if (this.cacheService.contains(PREVIOUS_CSAR_COMPONENT)) {
485 this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
489 this.$state.current.data.unsavedChanges = false;
490 this.$scope.unsavedFile = false;
491 this.$scope.reload(component);
495 this.$scope.component.updateComponent().then(onSuccessUpdate, onFailed);
500 this.$scope.changeLifecycleState = (state:string):void => {
501 if (this.$scope.isGeneralView() && state !== 'deleteVersion') {
502 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE, state);
504 this.$scope.handleChangeLifecycleState(state);
508 let defaultActionAfterChangeLifecycleState = ():void => {
509 if (this.$state.current.data && this.$state.current.data.unsavedChanges) {
510 this.$state.current.data.unsavedChanges = false;
512 this.$state.go('dashboard');
515 this.$scope.handleChangeLifecycleState = (state:string, newCsarVersion?:string, onError?: Function) => {
516 if ('monitor' === state) {
517 this.$state.go('workspace.distribution');
521 let data = this.$scope.changeLifecycleStateButtons[state];
522 if (!data && this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
523 data = {text: 'Check Out', url: 'lifecycleState/CHECKOUT'};
525 const onSuccess = (component, url:string):void => {
526 // Updating the component from server response
528 // Creating the data object to notify the plugins with
529 const eventData: any = {
530 uuid: this.$scope.component.uuid,
531 version: this.$scope.component.version
534 // the server returns only metaData (small component) except checkout (Full component) ,so we update only the statuses of distribution & lifecycle
535 this.$scope.component.lifecycleState = component.lifecycleState;
536 this.$scope.component.distributionStatus = component.distributionStatus;
539 case 'lifecycleState/CHECKOUT':
540 this.workspaceNg1BridgeService.updateIsViewOnly(false);
541 this.eventBusService.notify("CHECK_OUT", eventData, false).subscribe(() => {
542 // only checkOut get the full component from server
543 // this.$scope.component = component;
544 // Work around to change the csar version
546 this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, newCsarVersion);
547 (this.$scope.component as Resource).csarVersion = newCsarVersion;
550 //when checking out a minor version uuid remains
551 const bcIdx = _.findIndex(this.components, (item) => {
552 return item.uuid === component.uuid;
555 this.components[bcIdx] = component;
557 //when checking out a major(certified) version
558 this.components.unshift(component);
560 this.$scope.mode = this.initViewMode();
561 this.initChangeLifecycleStateButtons();
562 this.initVersionObject();
563 this.$scope.isLoading = false;
564 this.EventListenerService.notifyObservers(EVENTS.ON_CHECKOUT, component);
565 this.workspaceService.setComponentMetadata(component.componentMetadata);
567 this.Notification.success({
568 message: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TEXT"),
569 title: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TITLE")
574 case 'lifecycleState/CHECKIN':
575 this.workspaceNg1BridgeService.updateIsViewOnly(true);
576 defaultActionAfterChangeLifecycleState();
577 this.Notification.success({
578 message: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TEXT"),
579 title: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TITLE")
582 case 'lifecycleState/UNDOCHECKOUT':
583 this.eventBusService.notify("UNDO_CHECK_OUT", eventData, false).subscribe(() => {
584 defaultActionAfterChangeLifecycleState();
585 this.Notification.success({
586 message: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
587 title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
591 case 'lifecycleState/certify':
592 this.$scope.handleCertification(component);
593 this.verifyIfDependenciesExist();
594 this.$scope.reload(component);
596 case 'distribution/PROD/activate':
597 this.Notification.success({
598 message: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TEXT"),
599 title: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TITLE")
601 this.initChangeLifecycleStateButtons();
604 defaultActionAfterChangeLifecycleState();
606 if (data.url !== 'lifecycleState/CHECKOUT') {
607 this.$scope.isLoading = false;
610 this.ChangeLifecycleStateHandler.changeLifecycleState(this.$scope.component, data, this.$scope, onSuccess);
613 this.$scope.deleteArchivedComponent = (): void => {
614 const modalTitle: string = this.$filter('translate')("COMPONENT_VIEW_DELETE_MODAL_TITLE");
615 const modalMessage: string = this.$filter('translate')("COMPONENT_VIEW_DELETE_MODAL_TEXT");
616 const modalButton = {
618 text: this.sdcMenu.alertMessages.okButton,
619 type: SdcUiCommon.ButtonType.warning,
620 callback: this.$scope.handleDeleteArchivedComponent,
622 } as SdcUiComponents.ModalButtonComponent;
623 this.modalServiceSdcUI.openWarningModal(modalTitle, modalMessage, 'alert-modal', [modalButton]);
626 this.$scope.handleDeleteArchivedComponent = (): void => {
627 this.$scope.isLoading = true;
628 const typeComponent = this.$scope.component.componentType;
629 this.ComponentServiceNg2.deleteComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
630 this.deleteArchiveCache();
631 this.Notification.success({
632 message: this.$scope.component.name + ' ' + this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
633 title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
635 if (this.$state.params.previousState) {
636 switch (this.$state.params.previousState) {
639 this.$state.go(this.$state.params.previousState);
642 this.$state.go('dashboard');
646 this.$scope.isLoading = false;
648 this.Notification.error({
649 message: this.$scope.component.name + ' ' + this.$filter('translate')('DELETE_FAILURE_MESSAGE_TEXT'),
650 title: this.$filter('translate')('DELETE_FAILURE_MESSAGE_TITLE')
652 this.$scope.isLoading = false;
656 this.$scope.isViewMode = ():boolean => {
657 return this.$scope.mode === WorkspaceMode.VIEW;
660 this.$scope.isDesigner = ():boolean => {
661 return this.role == Role.DESIGNER;
664 this.$scope.isDisableMode = ():boolean => {
665 return this.$scope.mode === WorkspaceMode.VIEW && this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKIN;
668 this.$scope.isGeneralView = ():boolean => {
669 //we show revert and save icons only in general view
670 return this.$state.current.name === States.WORKSPACE_GENERAL;
673 this.$scope.isCreateMode = ():boolean => {
674 return this.$scope.mode === WorkspaceMode.CREATE;
677 this.$scope.checkDisableButton = (button: any):boolean => {
678 // Logic moved from html to component
679 if (this.$scope.isCreateMode() || button.disabled || this.$scope.disabledButtons || !this.$scope.isValidForm || this.$scope.unsavedChanges || this.$scope.component.isArchived){
683 // Specific verification for Checkout - enabled only in case the component is the latest version.
684 let result: boolean = false;
686 if (button.url === 'lifecycleState/CHECKOUT') {
687 result = !this.$scope.component.isLatestVersion();
692 this.$scope.isEditMode = ():boolean => {
693 return this.$scope.mode === WorkspaceMode.EDIT;
696 this.$scope.goToBreadcrumbHome = ():void => {
697 let bcHome:MenuItemGroup = this.$scope.breadcrumbsModel[0];
698 this.$state.go(bcHome.menuItems[bcHome.selectedIndex].state);
701 this.$scope.showLifecycleIcon = ():boolean => {
702 return this.role == Role.DESIGNER;
705 this.$scope.getStatus = ():string => {
706 if (this.$scope.isCreateMode()) {
710 return this.$scope.component.getStatus(this.sdcMenu);
713 this.initMenuItems();
715 this.$scope.showLatestVersion = (): boolean => {
716 let result: boolean = true;
717 if (!this.$scope.component.isLatestVersion()) {
720 if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) {
726 this.$scope.updateSelectedMenuItem = (state:string):void => {
727 let stateArray:Array<string> = state.split('.', 2);
728 let stateWithoutInternalNavigate:string = stateArray[0] + '.' + stateArray[1];
729 let selectedItem:MenuItem = _.find(this.$scope.leftBarTabs.menuItems, (item:MenuItem) => {
730 let itemStateArray:Array<string> = item.state.split('.', 2);
731 let itemStateWithoutNavigation:string = itemStateArray[0] + '.' + itemStateArray[1];
732 return (itemStateWithoutNavigation === stateWithoutInternalNavigate);
735 let selectedIndex = selectedItem ? this.$scope.leftBarTabs.menuItems.indexOf(selectedItem) : 0;
737 if (stateArray[1] === 'plugins') {
738 _.forEach(PluginsConfiguration.plugins, (plugin) => {
739 if (plugin.pluginStateUrl == this.$state.params.path) {
742 else if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
748 this.$scope.leftBarTabs.selectedIndex = selectedIndex;
751 this.$scope.isSelected = (menuItem: MenuItem): boolean => {
752 return this.$scope.leftBarTabs.selectedIndex === _.indexOf(this.$scope.leftBarTabs.menuItems, menuItem);
755 this.$scope.$watch('$state.current.name', (newVal: string): void => {
757 this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1);
758 this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT;
759 this.$scope.isPlugins = newVal == States.WORKSPACE_PLUGINS;
763 this.$scope.getTabTitle = (): string => {
764 return this.$scope.leftBarTabs.menuItems.find((menuItem: MenuItem) => {
765 return menuItem.state == this.$scope.$state.current.name;
769 this.$scope.reload = (component: Component): void => {
770 const isGeneralTab = this.$state.current.name === States.WORKSPACE_GENERAL;
771 // nullify the componentCsar in case we are in general tab so we know we didnt came from updateVsp Modal
773 this.$state.go(this.$state.current.name, {id: component.uniqueId, componentCsar: null}, {reload: true});
775 this.$state.go(this.$state.current.name, {id: component.uniqueId}, {reload: true});
779 this.$scope.$on('$destroy', () => {
780 this.EventListenerService.unRegisterObserver(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES);
783 this.$scope.openAutomatedUpgradeModal = ():void => {
784 this.$scope.isLoading = true;
785 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>)=> {
786 this.$scope.isLoading = false;
787 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, false);
791 this.$scope.handleCertification = (certifyComponent): void => {
792 if (this.$scope.component.getComponentSubType() === ResourceType.VF || this.$scope.component.isService()) {
793 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>) => {
794 this.$scope.isLoading = false;
796 const isUpgradeNeeded = _.filter(response, (componentToUpgrade:IDependenciesServerResponse) => {
797 return componentToUpgrade.dependencies && componentToUpgrade.dependencies.length > 0;
799 if (isUpgradeNeeded.length === 0) {
800 this.onSuccessWithoutUpgradeNeeded();
803 this.refreshDataAfterChangeLifecycleState(certifyComponent);
804 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, true);
807 this.onSuccessWithoutUpgradeNeeded();
811 this.$scope.disableMenuItems = () => {
812 this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
813 item.isDisabled = (States.WORKSPACE_GENERAL !== item.state);
817 this.$scope.enableMenuItems = () => {
818 this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
819 item.isDisabled = false;
824 this.$scope.startProgress = (message: string): void => {
825 this.progressService.initCreateComponentProgress(this.$scope.component.uniqueId);
826 this.$scope.isCreateProgress = true;
827 this.$scope.progressMessage = message;
830 this.$scope.stopProgress = (): void => {
831 this.$scope.isCreateProgress = false;
832 this.progressService.deleteProgressValue(this.$scope.component.uniqueId);
835 this.$scope.updateBreadcrumbs = (component: Component): void => {
836 // Update the components list for breadcrumbs
837 const bcIdx = this.MenuHandler.findBreadcrumbComponentIndex(this.components, component);
839 this.components[bcIdx] = component;
840 this.initBreadcrumbs(); // re-calculate breadcrumbs
844 this.$scope.updateUnsavedFileFlag = (isUnsaved:boolean) => {
845 this.$scope.unsavedFile = isUnsaved;
850 private onSuccessWithoutUpgradeNeeded = (): void => {
851 this.$scope.isLoading = false;
852 this.Notification.success({
853 message: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TEXT'),
854 title: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TITLE')
856 this.initVersionObject();
857 this.initChangeLifecycleStateButtons();
860 private refreshDataAfterChangeLifecycleState = (component:Component):void => {
861 this.$scope.isLoading = false;
862 this.$scope.mode = this.initViewMode();
863 this.initChangeLifecycleStateButtons();
864 this.initVersionObject();
865 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE, component);
868 private initAfterScope = (): void => {
869 // In case user select csar from the onboarding modal, need to disable checkout and submit for testing.
870 if (this.$state.params['disableButtons'] === true) {
871 this.$scope.uploadFileChangedInGeneralTab();
875 private initVersionObject = (): void => {
876 this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse();
877 this.$scope.changeVersion = {
878 selectedVersion: _.find(this.$scope.versionsList, (versionObj) => {
879 return versionObj.versionId === this.$scope.component.uniqueId;
884 private getNewComponentBreadcrumbItem = (): MenuItem => {
886 if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
887 text = this.$scope.component.getComponentSubType() + ': ' + this.$scope.component.name;
889 text = 'Create new ' + this.$state.params['type'];
891 return new MenuItem(text, null, States.WORKSPACE_GENERAL, 'goToState', [this.$state.params]);
894 private updateMenuItemByRole = (menuItems: any[], role: string) => {
895 const tempMenuItems: any[] = new Array<any>();
896 menuItems.forEach((item: any) => {
897 //remove item if role is disabled
898 if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) {
899 tempMenuItems.push(item);
902 return tempMenuItems;
905 private updateMenuItemByCategory = (menuItems:Array<any>, category:string) => {
906 let tempMenuItems:Array<any> = new Array<any>();
907 menuItems.forEach((item:any) => {
908 //update flag disabledCategory to true if category is disabled
909 item.disabledCategory = false;
910 if ((item.disabledCategories && item.disabledCategories.indexOf(category) > -1))
912 item.disabledCategory = true;
914 tempMenuItems.push(item);
916 return tempMenuItems;
920 private deleteArchiveCache = () => {
921 this.cacheService.remove('archiveComponents'); // delete the cache to ensure the archive is reloaded from server
924 private initBreadcrumbs = () => {
925 this.components = this.cacheService.get('breadcrumbsComponents');
926 const breadcrumbsComponentsLvl = this.MenuHandler.generateBreadcrumbsModelFromComponents(this.components, this.$scope.component);
928 if (this.$scope.isCreateMode()) {
929 const createItem = this.getNewComponentBreadcrumbItem();
930 if (!breadcrumbsComponentsLvl.menuItems) {
931 breadcrumbsComponentsLvl.menuItems = [];
933 breadcrumbsComponentsLvl.menuItems.unshift(createItem);
934 breadcrumbsComponentsLvl.selectedIndex = 0;
937 this.$scope.breadcrumbsModel = [breadcrumbsComponentsLvl, this.$scope.leftBarTabs];
940 private initMenuItems() {
942 const inCreateMode = this.$scope.isCreateMode();
943 this.$scope.leftBarTabs = new MenuItemGroup();
944 let menuItemsObjects: any[] = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
945 if (this.$scope.component.getComponentSubType() === 'SERVICE') {
946 const menuItemsObjectsCategory: any[] = this.updateMenuItemByCategory(menuItemsObjects, this.category);
947 menuItemsObjects = menuItemsObjectsCategory;
950 // Only adding plugins to the workspace if they can be displayed for the current user role
951 _.each(PluginsConfiguration.plugins, (plugin: Plugin) => {
952 if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
953 menuItemsObjects.push({
954 text: plugin.pluginDisplayOptions['context'].displayName,
955 action: 'onMenuItemPressed',
956 state: 'workspace.plugins',
957 params: {path: plugin.pluginStateUrl}
962 this.$scope.leftBarTabs.menuItems = menuItemsObjects.map((item: MenuItem) => {
963 const menuItem = new MenuItem(item.text, item.callback, item.state, item.action, item.params, item.blockedForTypes, item.disabledCategory);
964 if (menuItem.params) {
965 menuItem.params.state = menuItem.state;
968 menuItem.params = {state: menuItem.state};
970 menuItem.callback = () => this.$scope[menuItem.action](menuItem.state, menuItem.params);
971 menuItem.isDisabled = (inCreateMode && States.WORKSPACE_GENERAL !== menuItem.state) ||
972 (States.WORKSPACE_DEPLOYMENT === menuItem.state && this.$scope.component.modules
973 && this.$scope.component.modules.length === 0 && this.$scope.component.isResource()) ||
974 (menuItem.disabledCategory === true);
978 if (this.cacheService.get('breadcrumbsComponents')) {
979 this.initBreadcrumbs();
982 this.initBreadcrumbsComponents();
986 private showSuccessNotificationMessage = ():void => {
987 this.Notification.success({
988 message: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_DESCRIPTION'),
989 title: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_TITLE')
993 private setWorkspaceButtonState = (newState: boolean, callback?: Function) => {
994 this.$scope.unsavedChanges = newState;
995 this.$scope.unsavedChangesCallback = callback;
998 private initBreadcrumbsComponents = (): void => {
999 let breadcrumbsComponentsObservable;
1000 if (this.$stateParams.previousState === 'dashboard') {
1001 breadcrumbsComponentsObservable = this.homeService.getAllComponents(true);
1002 } else if (this.$stateParams.previousState === 'catalog') {
1003 breadcrumbsComponentsObservable = this.catalogService.getCatalog();
1005 this.cacheService.remove('breadcrumbsComponentsState');
1006 this.cacheService.remove('breadcrumbsComponents');
1009 breadcrumbsComponentsObservable.subscribe((components) => {
1010 this.cacheService.set('breadcrumbsComponentsState', this.$stateParams.previousState);
1011 this.cacheService.set('breadcrumbsComponents', components);
1012 this.initBreadcrumbs();
1017 private verifyIfDependenciesExist(): void {
1018 let containsDependencies = [];
1019 if (this.$scope.component.componentType && this.$scope.component.uniqueId &&
1020 this.$scope.component.lifecycleState === 'CERTIFIED' && (this.$scope.component.isService() || this.$scope.component.getComponentSubType() === 'VF')) {
1021 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response: IDependenciesServerResponse[]) => {
1022 containsDependencies = response.filter((version) => version.dependencies);
1023 if (containsDependencies.length > 0) {
1024 this.$scope.hasNoDependencies = false;
1026 this.$scope.hasNoDependencies = true;