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';
37 MenuItem, ModalsHandler, States, EVENTS, CHANGE_COMPONENT_CSAR_VERSION_FLAG, ResourceType, PREVIOUS_CSAR_COMPONENT,
38 WorkspaceMode, ComponentFactory, ChangeLifecycleStateHandler, Role, ComponentState, MenuItemGroup, MenuHandler
42 LeftPaletteLoaderService,
44 } from 'app/services';
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';
58 interface ModelSelectOption {
63 export interface IWorkspaceViewModelScope extends ng.IScope {
66 isCreateProgress: boolean;
68 originComponent: Component;
69 componentType: string;
71 leftBarTabs: MenuItemGroup;
73 isFromImport: boolean;
75 isActiveTopBar: boolean;
77 breadcrumbsModel: Array<MenuItemGroup>;
79 changeLifecycleStateButtons: any;
81 versionsList: Array<any>;
83 isComposition: boolean;
84 isDeployment: boolean;
86 $state: ng.ui.IStateService;
87 user: IUserProperties;
89 disabledButtons: boolean;
90 menuComponentTitle: string;
91 progressService: ProgressService;
92 progressMessage: string;
93 ComponentServiceNg2: ComponentServiceNg2;
94 // leftPanelComponents:Array<Models.Components.Component>; //this is in order to load the left panel once, and not wait long time when moving to composition
95 unsavedChanges: boolean;
96 unsavedChangesCallback: Function;
98 hasNoDependencies: boolean;
99 models: Array<ModelSelectOption>;
102 startProgress(message: string): void;
103 stopProgress(): void;
104 updateBreadcrumbs(component: Component): void;
105 updateUnsavedFileFlag(isUnsaved: boolean): void;
106 showChangeStateButton(): boolean;
107 getComponent(): Component;
108 setComponent(component: Component): void;
109 setOriginComponent(component: Component): void;
110 onMenuItemPressed(state: string, params: any): ng.IPromise<boolean>;
112 save(): Promise<void>;
113 setValidState(isValid: boolean): void;
114 changeLifecycleState(state: string): void;
115 handleChangeLifecycleState(state: string, newCsarVersion?: string, errorFunction?: Function): void;
116 disableMenuItems(): void;
117 enableMenuItems(): void;
118 isDesigner(): boolean;
119 isViewMode(): boolean;
120 isEditMode(): boolean;
121 isCreateMode(): boolean;
122 isDisableMode(): boolean;
123 isGeneralView(): boolean;
124 goToBreadcrumbHome(): void;
125 onVersionChanged(selectedId: string): void;
126 getLatestVersion(): void;
128 showLifecycleIcon(): boolean;
129 updateSelectedMenuItem(state: string): void;
130 isSelected(menuItem: MenuItem): boolean;
131 uploadFileChangedInGeneralTab(): void;
132 updateMenuComponentName(ComponentName: string): void;
133 getTabTitle(): string;
134 reload(component: Component): void;
137 export class WorkspaceViewModel {
147 'Sdc.Services.CacheService',
148 'ChangeLifecycleStateHandler',
149 'LeftPaletteLoaderService',
151 'EventListenerService',
156 'Sdc.Services.ProgressService',
157 'ComponentServiceNg2',
158 'AutomatedUpgradeService',
161 'WorkspaceNg1BridgeService',
165 constructor(private $scope: IWorkspaceViewModelScope,
166 private injectComponent: Component,
167 private ComponentFactory: ComponentFactory,
168 private $state: ng.ui.IStateService,
169 private sdcMenu: IAppMenu,
170 private $q: ng.IQService,
171 private MenuHandler: MenuHandler,
172 private cacheService: CacheService,
173 private ChangeLifecycleStateHandler: ChangeLifecycleStateHandler,
174 private LeftPaletteLoaderService: LeftPaletteLoaderService,
175 private $filter: ng.IFilterService,
176 private EventListenerService: EventListenerService,
177 private Notification: any,
178 private $stateParams: any,
179 private homeService: HomeService,
180 private catalogService: CatalogService,
181 private progressService: ProgressService,
182 private ComponentServiceNg2: ComponentServiceNg2,
183 private AutomatedUpgradeService: AutomatedUpgradeService,
184 private eventBusService: EventBusService,
185 private pluginsService: PluginsService,
186 private workspaceNg1BridgeService: WorkspaceNg1BridgeService,
187 private workspaceService: WorkspaceService) {
190 // this.initAfterScope();
191 this.$scope.updateSelectedMenuItem(this.$state.current.name);
194 private role: string;
195 private category: string;
196 private components: Component[];
198 private initViewMode = ():WorkspaceMode => {
199 let mode = WorkspaceMode.VIEW;
201 if (!this.$state.params['id']) { //&& !this.$state.params['vspComponent']
202 mode = WorkspaceMode.CREATE;
204 if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT &&
205 this.$scope.component.lastUpdaterUserId === this.cacheService.get('user').userId) {
206 if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role === Role.DESIGNER) {
207 mode = WorkspaceMode.EDIT;
211 this.workspaceNg1BridgeService.updateIsViewOnly(mode === WorkspaceMode.VIEW);
215 private initChangeLifecycleStateButtons = (): void => {
217 if (this.$scope.component.isService() && this.$scope.component.lifecycleState === 'CERTIFIED') {
218 state = this.$scope.component.distributionStatus;
220 state = this.$scope.component.lifecycleState;
222 this.$scope.changeLifecycleStateButtons = (this.sdcMenu.roles[this.role].changeLifecycleStateButtons[state] || [])[this.$scope.component.componentType.toUpperCase()];
225 private initScope = (): void => {
226 this.$scope.component = this.injectComponent;
227 this.$scope.menuComponentTitle = this.$scope.component.name;
228 this.$scope.disabledButtons = false;
229 this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
230 this.$scope.componentType = this.$scope.component.componentType;
231 this.$scope.version = this.cacheService.get('version');
232 this.$scope.user = this.cacheService.get('user');
233 this.role = this.$scope.user.role;
234 this.category = this.$scope.component.selectedCategory;
235 this.$scope.mode = this.initViewMode();
236 this.$scope.isValidForm = true;
237 this.initChangeLifecycleStateButtons();
238 this.initVersionObject();
239 this.$scope.$state = this.$state;
240 this.$scope.isLoading = false;
241 this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1);
242 this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT;
243 this.$scope.progressService = this.progressService;
244 this.$scope.unsavedChanges = false;
246 this.$scope.hasNoDependencies = true;
247 this.verifyIfDependenciesExist();
249 this.EventListenerService.registerObserverCallback(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.setWorkspaceButtonState);
250 this.$scope.getComponent = (): Component => {
251 return this.$scope.component;
254 this.$scope.updateMenuComponentName = (ComponentName:string):void => {
255 this.$scope.menuComponentTitle = ComponentName;
258 this.$scope.sdcMenu = this.sdcMenu;
259 // Will be called from each step after save to update the resource.
260 this.$scope.setComponent = (component:Component):void => {
261 this.$scope.component = component;
264 this.$scope.setOriginComponent = (component:Component):void => {
265 this.$scope.originComponent = component;
268 this.$scope.uploadFileChangedInGeneralTab = ():void => {
269 // In case user select browse file, and in update mode, need to disable submit for testing and checkin buttons.
270 if (this.$scope.isEditMode() && this.$scope.component.isResource() && (<Resource>this.$scope.component).resourceType == ResourceType.VF) {
271 // NOTE: Commented out the disabling of the workspace buttons on CSAR updating due fix of a bug [417534]
272 // this.$scope.disabledButtons = true;
276 this.$scope.archiveComponent = ():void => {
277 this.$scope.isLoading = true;
278 const typeComponent = this.$scope.component.componentType;
279 this.ComponentServiceNg2.archiveComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
280 this.$scope.isLoading = false;
281 if (this.$state.params.previousState) {
282 switch (this.$state.params.previousState) {
285 this.$state.go(this.$state.params.previousState);
291 this.$scope.component.archived = true;
292 this.deleteArchiveCache();
294 this.Notification.success({
295 message: this.$scope.component.name + ' ' + this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TEXT"),
296 title: this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TITLE")
298 }, (error) => { this.$scope.isLoading = false; });
301 this.$scope.restoreComponent = ():void => {
302 this.$scope.isLoading = true;
303 const typeComponent = this.$scope.component.componentType;
304 this.ComponentServiceNg2.restoreComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
305 this.$scope.isLoading = false;
306 this.Notification.success({
307 message: this.$scope.component.name + ' ' + this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TEXT"),
308 title: this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TITLE")
311 this.$scope.component.archived = false;
312 this.deleteArchiveCache();
315 this.$scope.$on('$stateChangeStart', (event, toState, toParams, fromState, fromParams) => {
316 if(this.$scope.isEditMode()){
317 if (fromParams.id == toParams.id && this.$state.current.data && this.$state.current.data.unsavedChanges) {
318 event.preventDefault();
319 if(this.$scope.isValidForm){
320 this.$scope.save().then(() => {
321 this.$scope.onMenuItemPressed(toState.name, toParams);
323 console.error("Save failed, unable to navigate to " + toState.name);
326 console.error("Form is invalid, unable to navigate to " + toState.name);
333 this.$scope.$on('$stateChangeSuccess', (event, toState) => {
334 this.$scope.updateSelectedMenuItem(this.$state.current.name);
337 this.$scope.onMenuItemPressed = (state:string, params:any):ng.IPromise<boolean> => {
339 let deferred:ng.IDeferred<boolean> = this.$q.defer();
340 let goToState = ():void => {
341 this.$state.go(state, Object.assign({
342 id: this.$scope.component.uniqueId,
343 type: this.$scope.component.componentType.toLowerCase(),
344 components: this.components
346 deferred.resolve(true);
349 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
350 (this.$state.current.name === States.WORKSPACE_MANAGEMENT_WORKFLOW || this.$state.current.name === States.WORKSPACE_NETWORK_CALL_FLOW)) {
351 let onGetSuccess = (component:Component) => {
352 this.$scope.isLoading = false;
353 // Update the components
354 this.$scope.component = component;
357 let onFailed = () => {
358 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
359 this.$scope.isLoading = false; // stop the progress.
360 deferred.reject(false);
362 this.$scope.component.getComponent().then(onGetSuccess, onFailed);
366 return deferred.promise;
369 this.$scope.setValidState = (isValid:boolean):void => {
370 this.$scope.isValidForm = isValid;
373 this.$scope.onVersionChanged = (selectedId:string):void => {
374 if (this.$scope.isGeneralView() && this.$state.current.data.unsavedChanges) {
375 this.$scope.changeVersion.selectedVersion = _.find(this.$scope.versionsList, (versionObj)=> {
376 return versionObj.versionId === this.$scope.component.uniqueId;
381 uuid: this.$scope.component.uuid,
382 version: this.$scope.changeVersion.selectedVersion.versionNumber
385 this.eventBusService.notify("VERSION_CHANGED", eventData).subscribe(() => {
386 this.$scope.isLoading = true;
388 this.$state.go(this.$state.current.name, {
390 type: this.$scope.componentType.toLowerCase(),
391 mode: WorkspaceMode.VIEW,
392 components: this.$state.params['components']
397 this.$scope.getLatestVersion = ():void => {
398 this.$scope.onVersionChanged(_.first(this.$scope.versionsList).versionId);
401 this.$scope.create = () => {
403 this.$scope.startProgress("Creating Asset...");
404 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = true;//disabled click on general tab (DE246274)
406 // In case we import CSAR. Notify user that import VF will take long time (the create is performed in the background).
407 if (this.$scope.component.isResource() && (<Resource>this.$scope.component).csarUUID) {
408 this.Notification.info({
409 message: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_DESCRIPTION"),
410 title: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_TITLE")
414 let onFailed = () => {
415 this.$scope.stopProgress();
416 this.$scope.isLoading = false; // stop the progress.
417 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = false;//enabled click on general tab (DE246274)
418 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
419 let modalInstance:ng.ui.bootstrap.IModalServiceInstance;
420 modalInstance && modalInstance.close(); // Close the modal in case it is opened.
421 this.$scope.component.tags = _.without(this.$scope.component.tags, this.$scope.component.name);// for fix DE246217
423 this.$scope.setValidState(true); // Set the form valid (if sent form is valid, the error from server).
426 let onSuccessCreate = (component:Component) => {
428 this.$scope.stopProgress();
429 this.showSuccessNotificationMessage();
431 // Update the components list for breadcrumbs
432 this.components.unshift(component);
434 this.$state.go(States.WORKSPACE_GENERAL, {
435 id: component.uniqueId,
436 type: component.componentType.toLowerCase(),
437 components: this.components
438 }, {inherit: false});
441 console.log(this.$scope.component, "this.$scope.component")
442 if ((<Service>this.$scope.component).serviceType == "Service") {
443 this.ComponentFactory.importComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
445 this.ComponentFactory.createComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
452 this.$scope.save = ():Promise<void> => {
454 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_CLICK);
456 this.$scope.startProgress("Updating Asset...");
457 this.$scope.disableMenuItems();
459 return new Promise<void>((resolve, reject) => {
460 let stopProgressAndEnableUI = () => {
461 this.$scope.disabledButtons = false;
462 this.$scope.isLoading = false;
463 this.$scope.enableMenuItems();
464 this.$scope.stopProgress();
467 let onFailed = () => {
468 stopProgressAndEnableUI();
469 this.$scope.updateUnsavedFileFlag(true);
470 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
475 let onSuccessUpdate = (component:Component) => {
476 stopProgressAndEnableUI();
477 this.showSuccessNotificationMessage();
479 component.tags = _.reject(component.tags, (item)=> {
480 return item === component.name
483 this.$scope.updateBreadcrumbs(component);
485 //update the component
486 this.$scope.setComponent(component);
487 this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
489 if (this.cacheService.contains(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
490 this.cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
492 if (this.cacheService.contains(PREVIOUS_CSAR_COMPONENT)) {
493 this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
497 this.$state.current.data.unsavedChanges = false;
498 this.$scope.unsavedFile = false;
499 this.$scope.reload(component);
503 this.$scope.component.updateComponent().then(onSuccessUpdate, onFailed);
508 this.$scope.changeLifecycleState = (state:string):void => {
509 if (this.$scope.isGeneralView() && state !== 'deleteVersion') {
510 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE, state);
512 this.$scope.handleChangeLifecycleState(state);
516 let defaultActionAfterChangeLifecycleState = ():void => {
517 if (this.$state.current.data && this.$state.current.data.unsavedChanges) {
518 this.$state.current.data.unsavedChanges = false;
520 this.$state.go('dashboard');
523 this.$scope.handleChangeLifecycleState = (state:string, newCsarVersion?:string, onError?: Function) => {
524 if ('monitor' === state) {
525 this.$state.go('workspace.distribution');
529 let data = this.$scope.changeLifecycleStateButtons[state];
530 if (!data && this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
531 data = {text: 'Check Out', url: 'lifecycleState/CHECKOUT'};
533 const onSuccess = (component, url:string):void => {
534 // Updating the component from server response
536 // Creating the data object to notify the plugins with
537 const eventData: any = {
538 uuid: this.$scope.component.uuid,
539 version: this.$scope.component.version
542 // the server returns only metaData (small component) except checkout (Full component) ,so we update only the statuses of distribution & lifecycle
543 this.$scope.component.lifecycleState = component.lifecycleState;
544 this.$scope.component.distributionStatus = component.distributionStatus;
547 case 'lifecycleState/CHECKOUT':
548 this.workspaceNg1BridgeService.updateIsViewOnly(false);
549 this.eventBusService.notify("CHECK_OUT", eventData, false).subscribe(() => {
550 // only checkOut get the full component from server
551 // this.$scope.component = component;
552 // Work around to change the csar version
554 this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, newCsarVersion);
555 (this.$scope.component as Resource).csarVersion = newCsarVersion;
558 //when checking out a minor version uuid remains
559 const bcIdx = _.findIndex(this.components, (item) => {
560 return item.uuid === component.uuid;
563 this.components[bcIdx] = component;
565 //when checking out a major(certified) version
566 this.components.unshift(component);
568 this.$scope.mode = this.initViewMode();
569 this.initChangeLifecycleStateButtons();
570 this.initVersionObject();
571 this.$scope.isLoading = false;
572 this.EventListenerService.notifyObservers(EVENTS.ON_CHECKOUT, component);
573 this.workspaceService.setComponentMetadata(component);
575 this.Notification.success({
576 message: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TEXT"),
577 title: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TITLE")
582 case 'lifecycleState/CHECKIN':
583 this.workspaceNg1BridgeService.updateIsViewOnly(true);
584 defaultActionAfterChangeLifecycleState();
585 this.Notification.success({
586 message: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TEXT"),
587 title: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TITLE")
590 case 'lifecycleState/UNDOCHECKOUT':
591 this.eventBusService.notify("UNDO_CHECK_OUT", eventData, false).subscribe(() => {
592 defaultActionAfterChangeLifecycleState();
593 this.Notification.success({
594 message: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
595 title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
599 case 'lifecycleState/certify':
600 this.$scope.handleCertification(component);
601 this.verifyIfDependenciesExist();
602 this.$scope.reload(component);
604 case 'distribution/PROD/activate':
605 this.Notification.success({
606 message: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TEXT"),
607 title: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TITLE")
609 this.initChangeLifecycleStateButtons();
612 defaultActionAfterChangeLifecycleState();
614 if (data.url !== 'lifecycleState/CHECKOUT') {
615 this.$scope.isLoading = false;
618 this.ChangeLifecycleStateHandler.changeLifecycleState(this.$scope.component, data, this.$scope, onSuccess);
623 this.$scope.isViewMode = ():boolean => {
624 return this.$scope.mode === WorkspaceMode.VIEW;
627 this.$scope.isDesigner = ():boolean => {
628 return this.role == Role.DESIGNER;
631 this.$scope.isDisableMode = ():boolean => {
632 return this.$scope.mode === WorkspaceMode.VIEW && this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKIN;
635 this.$scope.isGeneralView = ():boolean => {
636 //we show revert and save icons only in general view
637 return this.$state.current.name === States.WORKSPACE_GENERAL;
640 this.$scope.isCreateMode = ():boolean => {
641 return this.$scope.mode === WorkspaceMode.CREATE;
644 this.$scope.checkDisableButton = (button: any):boolean => {
645 // Logic moved from html to component
646 if (this.$scope.isCreateMode() || button.disabled || this.$scope.disabledButtons || !this.$scope.isValidForm || this.$scope.unsavedChanges || this.$scope.component.archived){
650 // Specific verification for Checkout - enabled only in case the component is the latest version.
651 let result: boolean = false;
653 if (button.url === 'lifecycleState/CHECKOUT') {
654 result = !this.$scope.component.isLatestVersion();
659 this.$scope.isEditMode = ():boolean => {
660 return this.$scope.mode === WorkspaceMode.EDIT;
663 this.$scope.goToBreadcrumbHome = ():void => {
664 let bcHome:MenuItemGroup = this.$scope.breadcrumbsModel[0];
665 this.$state.go(bcHome.menuItems[bcHome.selectedIndex].state);
668 this.$scope.showLifecycleIcon = ():boolean => {
669 return this.role == Role.DESIGNER;
672 this.$scope.getStatus = ():string => {
673 if (this.$scope.isCreateMode()) {
677 return this.$scope.component.getStatus(this.sdcMenu);
680 this.initMenuItems();
682 this.$scope.showLatestVersion = (): boolean => {
683 let result: boolean = true;
684 if (!this.$scope.component.isLatestVersion()) {
687 if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) {
693 this.$scope.updateSelectedMenuItem = (state:string):void => {
694 let stateArray:Array<string> = state.split('.', 2);
695 let stateWithoutInternalNavigate:string = stateArray[0] + '.' + stateArray[1];
696 let selectedItem:MenuItem = _.find(this.$scope.leftBarTabs.menuItems, (item:MenuItem) => {
697 let itemStateArray:Array<string> = item.state.split('.', 2);
698 let itemStateWithoutNavigation:string = itemStateArray[0] + '.' + itemStateArray[1];
699 return (itemStateWithoutNavigation === stateWithoutInternalNavigate);
702 let selectedIndex = selectedItem ? this.$scope.leftBarTabs.menuItems.indexOf(selectedItem) : 0;
704 if (stateArray[1] === 'plugins') {
705 _.forEach(PluginsConfiguration.plugins, (plugin) => {
706 if (plugin.pluginStateUrl == this.$state.params.path) {
709 else if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
715 this.$scope.leftBarTabs.selectedIndex = selectedIndex;
718 this.$scope.isSelected = (menuItem: MenuItem): boolean => {
719 return this.$scope.leftBarTabs.selectedIndex === _.indexOf(this.$scope.leftBarTabs.menuItems, menuItem);
722 this.$scope.$watch('$state.current.name', (newVal: string): void => {
724 this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1);
725 this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT;
726 this.$scope.isPlugins = newVal == States.WORKSPACE_PLUGINS;
730 this.$scope.getTabTitle = (): string => {
731 return this.$scope.leftBarTabs.menuItems.find((menuItem: MenuItem) => {
732 return menuItem.state == this.$scope.$state.current.name;
736 this.$scope.reload = (component: Component): void => {
737 const isGeneralTab = this.$state.current.name === 'workspace.general';
738 // nullify the componentCsar in case we are in general tab so we know we didnt came from updateVsp Modal
740 this.$state.go(this.$state.current.name, {id: component.uniqueId, componentCsar: null}, {reload: true});
742 this.$state.go(this.$state.current.name, {id: component.uniqueId}, {reload: true});
746 this.$scope.$on('$destroy', () => {
747 this.EventListenerService.unRegisterObserver(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES);
750 this.$scope.openAutomatedUpgradeModal = ():void => {
751 this.$scope.isLoading = true;
752 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>)=> {
753 this.$scope.isLoading = false;
754 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, false);
758 this.$scope.handleCertification = (certifyComponent): void => {
759 if (this.$scope.component.getComponentSubType() === ResourceType.VF || this.$scope.component.isService()) {
760 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>) => {
761 this.$scope.isLoading = false;
763 const isUpgradeNeeded = _.filter(response, (componentToUpgrade:IDependenciesServerResponse) => {
764 return componentToUpgrade.dependencies && componentToUpgrade.dependencies.length > 0;
766 if (isUpgradeNeeded.length === 0) {
767 this.onSuccessWithoutUpgradeNeeded();
770 this.refreshDataAfterChangeLifecycleState(certifyComponent);
771 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, true);
774 this.onSuccessWithoutUpgradeNeeded();
778 this.$scope.disableMenuItems = () => {
779 this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
780 item.isDisabled = (States.WORKSPACE_GENERAL !== item.state);
784 this.$scope.enableMenuItems = () => {
785 this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
786 item.isDisabled = false;
791 this.$scope.startProgress = (message: string): void => {
792 this.progressService.initCreateComponentProgress(this.$scope.component.uniqueId);
793 this.$scope.isCreateProgress = true;
794 this.$scope.progressMessage = message;
797 this.$scope.stopProgress = (): void => {
798 this.$scope.isCreateProgress = false;
799 this.progressService.deleteProgressValue(this.$scope.component.uniqueId);
802 this.$scope.updateBreadcrumbs = (component: Component): void => {
803 // Update the components list for breadcrumbs
804 const bcIdx = this.MenuHandler.findBreadcrumbComponentIndex(this.components, component);
806 this.components[bcIdx] = component;
807 this.initBreadcrumbs(); // re-calculate breadcrumbs
811 this.$scope.updateUnsavedFileFlag = (isUnsaved:boolean) => {
812 this.$scope.unsavedFile = isUnsaved;
817 private onSuccessWithoutUpgradeNeeded = (): void => {
818 this.$scope.isLoading = false;
819 this.Notification.success({
820 message: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TEXT'),
821 title: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TITLE')
823 this.initVersionObject();
824 this.initChangeLifecycleStateButtons();
827 private refreshDataAfterChangeLifecycleState = (component:Component):void => {
828 this.$scope.isLoading = false;
829 this.$scope.mode = this.initViewMode();
830 this.initChangeLifecycleStateButtons();
831 this.initVersionObject();
832 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE, component);
835 private initAfterScope = (): void => {
836 // In case user select csar from the onboarding modal, need to disable checkout and submit for testing.
837 if (this.$state.params['disableButtons'] === true) {
838 this.$scope.uploadFileChangedInGeneralTab();
842 private initVersionObject = (): void => {
843 this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse();
844 this.$scope.changeVersion = {
845 selectedVersion: _.find(this.$scope.versionsList, (versionObj) => {
846 return versionObj.versionId === this.$scope.component.uniqueId;
851 private getNewComponentBreadcrumbItem = (): MenuItem => {
853 if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
854 text = this.$scope.component.getComponentSubType() + ': ' + this.$scope.component.name;
856 text = 'Create new ' + this.$state.params['type'];
858 return new MenuItem(text, null, States.WORKSPACE_GENERAL, 'goToState', [this.$state.params]);
861 private updateMenuItemByRole = (menuItems: any[], role: string) => {
862 const tempMenuItems: any[] = new Array<any>();
863 menuItems.forEach((item: any) => {
864 //remove item if role is disabled
865 if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) {
866 tempMenuItems.push(item);
869 return tempMenuItems;
872 private updateMenuItemByCategory = (menuItems:Array<any>, category:string) => {
873 let tempMenuItems:Array<any> = new Array<any>();
874 menuItems.forEach((item:any) => {
875 //update flag disabledCategory to true if category is disabled
876 item.disabledCategory = false;
877 if ((item.disabledCategories && item.disabledCategories.indexOf(category) > -1))
879 item.disabledCategory = true;
881 tempMenuItems.push(item);
883 return tempMenuItems;
887 private deleteArchiveCache = () => {
888 this.cacheService.remove('archiveComponents'); // delete the cache to ensure the archive is reloaded from server
891 private initBreadcrumbs = () => {
892 this.components = this.cacheService.get('breadcrumbsComponents');
893 const breadcrumbsComponentsLvl = this.MenuHandler.generateBreadcrumbsModelFromComponents(this.components, this.$scope.component);
895 if (this.$scope.isCreateMode()) {
896 const createItem = this.getNewComponentBreadcrumbItem();
897 if (!breadcrumbsComponentsLvl.menuItems) {
898 breadcrumbsComponentsLvl.menuItems = [];
900 breadcrumbsComponentsLvl.menuItems.unshift(createItem);
901 breadcrumbsComponentsLvl.selectedIndex = 0;
904 this.$scope.breadcrumbsModel = [breadcrumbsComponentsLvl, this.$scope.leftBarTabs];
907 private initMenuItems() {
909 const inCreateMode = this.$scope.isCreateMode();
910 this.$scope.leftBarTabs = new MenuItemGroup();
911 let menuItemsObjects: any[] = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
912 if (this.$scope.component.getComponentSubType() === 'SERVICE') {
913 const menuItemsObjectsCategory: any[] = this.updateMenuItemByCategory(menuItemsObjects, this.category);
914 menuItemsObjects = menuItemsObjectsCategory;
917 // Only adding plugins to the workspace if they can be displayed for the current user role
918 _.each(PluginsConfiguration.plugins, (plugin: Plugin) => {
919 if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
920 menuItemsObjects.push({
921 text: plugin.pluginDisplayOptions['context'].displayName,
922 action: 'onMenuItemPressed',
923 state: 'workspace.plugins',
924 params: {path: plugin.pluginStateUrl}
929 this.$scope.leftBarTabs.menuItems = menuItemsObjects.map((item: MenuItem) => {
930 const menuItem = new MenuItem(item.text, item.callback, item.state, item.action, item.params, item.blockedForTypes, item.disabledCategory);
931 if (menuItem.params) {
932 menuItem.params.state = menuItem.state;
935 menuItem.params = {state: menuItem.state};
937 menuItem.callback = () => this.$scope[menuItem.action](menuItem.state, menuItem.params);
938 menuItem.isDisabled = (inCreateMode && States.WORKSPACE_GENERAL !== menuItem.state) ||
939 (States.WORKSPACE_DEPLOYMENT === menuItem.state && this.$scope.component.modules
940 && this.$scope.component.modules.length === 0 && this.$scope.component.isResource()) ||
941 (menuItem.disabledCategory === true);
945 if (this.cacheService.get('breadcrumbsComponents')) {
946 this.initBreadcrumbs();
949 this.initBreadcrumbsComponents();
953 private showSuccessNotificationMessage = ():void => {
954 this.Notification.success({
955 message: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_DESCRIPTION'),
956 title: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_TITLE')
960 private setWorkspaceButtonState = (newState: boolean, callback?: Function) => {
961 this.$scope.unsavedChanges = newState;
962 this.$scope.unsavedChangesCallback = callback;
965 private initBreadcrumbsComponents = (): void => {
966 let breadcrumbsComponentsObservable;
967 if (this.$stateParams.previousState === 'dashboard') {
968 breadcrumbsComponentsObservable = this.homeService.getAllComponents(true);
969 } else if (this.$stateParams.previousState === 'catalog') {
970 breadcrumbsComponentsObservable = this.catalogService.getCatalog();
972 this.cacheService.remove('breadcrumbsComponentsState');
973 this.cacheService.remove('breadcrumbsComponents');
976 breadcrumbsComponentsObservable.subscribe((components) => {
977 this.cacheService.set('breadcrumbsComponentsState', this.$stateParams.previousState);
978 this.cacheService.set('breadcrumbsComponents', components);
979 this.initBreadcrumbs();
984 private verifyIfDependenciesExist(): void {
985 let containsDependencies = [];
986 if (this.$scope.component.componentType && this.$scope.component.uniqueId &&
987 this.$scope.component.lifecycleState === 'CERTIFIED' && (this.$scope.component.isService() || this.$scope.component.getComponentSubType() === 'VF')) {
988 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response: IDependenciesServerResponse[]) => {
989 containsDependencies = response.filter((version) => version.dependencies);
990 if (containsDependencies.length > 0) {
991 this.$scope.hasNoDependencies = false;
993 this.$scope.hasNoDependencies = true;