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 { SdcUiCommon, SdcUiComponents, SdcUiServices } from 'onap-ui-angular';
49 import { AutomatedUpgradeService } from '../../ng2/pages/automated-upgrade/automated-upgrade.service';
50 import { CatalogService } from '../../ng2/services/catalog.service';
51 import { ComponentServiceNg2 } from '../../ng2/services/component-services/component.service';
52 import { EventBusService } from '../../ng2/services/event-bus.service';
53 import { HomeService } from '../../ng2/services/home.service';
54 import { PluginsService } from '../../ng2/services/plugins.service';
55 import { IDependenciesServerResponse } from '../../ng2/services/responses/dependencies-server-response';
56 import { WorkspaceNg1BridgeService } from '../../ng2/pages/workspace/workspace-ng1-bridge-service';
57 import { WorkspaceService } from '../../ng2/pages/workspace/workspace.service';
59 export interface IWorkspaceViewModelScope extends ng.IScope {
62 isCreateProgress: boolean;
64 originComponent: Component;
65 componentType: string;
67 leftBarTabs: MenuItemGroup;
69 isFromImport: boolean;
71 isActiveTopBar: boolean;
73 breadcrumbsModel: Array<MenuItemGroup>;
75 changeLifecycleStateButtons: any;
77 versionsList: Array<any>;
79 isComposition: boolean;
80 isDeployment: boolean;
82 $state: ng.ui.IStateService;
83 user: IUserProperties;
85 disabledButtons: boolean;
86 menuComponentTitle: string;
87 progressService: ProgressService;
88 progressMessage: string;
89 ComponentServiceNg2: ComponentServiceNg2;
90 // leftPanelComponents:Array<Models.Components.Component>; //this is in order to load the left panel once, and not wait long time when moving to composition
91 unsavedChanges: boolean;
92 unsavedChangesCallback: Function;
94 hasNoDependencies: boolean;
95 models: Array<string>;
97 startProgress(message: string): void;
99 updateBreadcrumbs(component: Component): void;
100 updateUnsavedFileFlag(isUnsaved: boolean): void;
101 showChangeStateButton(): boolean;
102 getComponent(): Component;
103 setComponent(component: Component): void;
104 setOriginComponent(component: Component): void;
105 onMenuItemPressed(state: string, params: any): ng.IPromise<boolean>;
107 save(): Promise<void>;
108 setValidState(isValid: boolean): void;
109 changeLifecycleState(state: string): void;
110 handleChangeLifecycleState(state: string, newCsarVersion?: string, errorFunction?: Function): void;
111 disableMenuItems(): void;
112 enableMenuItems(): void;
113 isDesigner(): boolean;
114 isViewMode(): boolean;
115 isEditMode(): boolean;
116 isCreateMode(): boolean;
117 isDisableMode(): boolean;
118 isGeneralView(): boolean;
119 goToBreadcrumbHome(): void;
120 onVersionChanged(selectedId: string): void;
121 getLatestVersion(): void;
123 showLifecycleIcon(): boolean;
124 updateSelectedMenuItem(state: string): void;
125 isSelected(menuItem: MenuItem): boolean;
126 uploadFileChangedInGeneralTab(): void;
127 updateMenuComponentName(ComponentName: string): void;
128 getTabTitle(): string;
129 reload(component: Component): void;
132 export class WorkspaceViewModel {
142 'Sdc.Services.CacheService',
143 'ChangeLifecycleStateHandler',
144 'LeftPaletteLoaderService',
146 'EventListenerService',
151 'Sdc.Services.ProgressService',
152 'ComponentServiceNg2',
153 'AutomatedUpgradeService',
157 'WorkspaceNg1BridgeService',
161 constructor(private $scope: IWorkspaceViewModelScope,
162 private injectComponent: Component,
163 private ComponentFactory: ComponentFactory,
164 private $state: ng.ui.IStateService,
165 private sdcMenu: IAppMenu,
166 private $q: ng.IQService,
167 private MenuHandler: MenuHandler,
168 private cacheService: CacheService,
169 private ChangeLifecycleStateHandler: ChangeLifecycleStateHandler,
170 private LeftPaletteLoaderService: LeftPaletteLoaderService,
171 private $filter: ng.IFilterService,
172 private EventListenerService: EventListenerService,
173 private Notification: any,
174 private $stateParams: any,
175 private homeService: HomeService,
176 private catalogService: CatalogService,
177 private progressService: ProgressService,
178 private ComponentServiceNg2: ComponentServiceNg2,
179 private AutomatedUpgradeService: AutomatedUpgradeService,
180 private eventBusService: EventBusService,
181 private modalServiceSdcUI: SdcUiServices.ModalService,
182 private pluginsService: PluginsService,
183 private workspaceNg1BridgeService: WorkspaceNg1BridgeService,
184 private workspaceService: WorkspaceService) {
187 // this.initAfterScope();
188 this.$scope.updateSelectedMenuItem(this.$state.current.name);
191 private role: string;
192 private category: string;
193 private components: Component[];
195 private initViewMode = ():WorkspaceMode => {
196 let mode = WorkspaceMode.VIEW;
198 if (!this.$state.params['id']) { //&& !this.$state.params['vspComponent']
199 mode = WorkspaceMode.CREATE;
201 if (this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKOUT &&
202 this.$scope.component.lastUpdaterUserId === this.cacheService.get('user').userId) {
203 if ((this.$scope.component.isService() || this.$scope.component.isResource()) && this.role === Role.DESIGNER) {
204 mode = WorkspaceMode.EDIT;
208 this.workspaceNg1BridgeService.updateIsViewOnly(mode === WorkspaceMode.VIEW);
212 private initChangeLifecycleStateButtons = (): void => {
214 if (this.$scope.component.isService() && this.$scope.component.lifecycleState === 'CERTIFIED') {
215 state = this.$scope.component.distributionStatus;
217 state = this.$scope.component.lifecycleState;
219 this.$scope.changeLifecycleStateButtons = (this.sdcMenu.roles[this.role].changeLifecycleStateButtons[state] || [])[this.$scope.component.componentType.toUpperCase()];
222 private initScope = (): void => {
223 this.$scope.component = this.injectComponent;
224 this.$scope.menuComponentTitle = this.$scope.component.name;
225 this.$scope.disabledButtons = false;
226 this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
227 this.$scope.componentType = this.$scope.component.componentType;
228 this.$scope.version = this.cacheService.get('version');
229 this.$scope.user = this.cacheService.get('user');
230 this.role = this.$scope.user.role;
231 this.category = this.$scope.component.selectedCategory;
232 this.$scope.mode = this.initViewMode();
233 this.$scope.isValidForm = true;
234 this.initChangeLifecycleStateButtons();
235 this.initVersionObject();
236 this.$scope.$state = this.$state;
237 this.$scope.isLoading = false;
238 this.$scope.isComposition = (this.$state.current.name.indexOf(States.WORKSPACE_COMPOSITION) > -1);
239 this.$scope.isDeployment = this.$state.current.name == States.WORKSPACE_DEPLOYMENT;
240 this.$scope.progressService = this.progressService;
241 this.$scope.unsavedChanges = false;
243 this.$scope.hasNoDependencies = true;
244 this.verifyIfDependenciesExist();
246 this.EventListenerService.registerObserverCallback(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES, this.setWorkspaceButtonState);
247 this.$scope.getComponent = (): Component => {
248 return this.$scope.component;
251 this.$scope.updateMenuComponentName = (ComponentName:string):void => {
252 this.$scope.menuComponentTitle = ComponentName;
255 this.$scope.sdcMenu = this.sdcMenu;
256 // Will be called from each step after save to update the resource.
257 this.$scope.setComponent = (component:Component):void => {
258 this.$scope.component = component;
261 this.$scope.setOriginComponent = (component:Component):void => {
262 this.$scope.originComponent = component;
265 this.$scope.uploadFileChangedInGeneralTab = ():void => {
266 // In case user select browse file, and in update mode, need to disable submit for testing and checkin buttons.
267 if (this.$scope.isEditMode() && this.$scope.component.isResource() && (<Resource>this.$scope.component).resourceType == ResourceType.VF) {
268 // NOTE: Commented out the disabling of the workspace buttons on CSAR updating due fix of a bug [417534]
269 // this.$scope.disabledButtons = true;
273 this.$scope.archiveComponent = ():void => {
274 this.$scope.isLoading = true;
275 const typeComponent = this.$scope.component.componentType;
276 this.ComponentServiceNg2.archiveComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
277 this.$scope.isLoading = false;
278 if (this.$state.params.previousState) {
279 switch (this.$state.params.previousState) {
282 this.$state.go(this.$state.params.previousState);
288 this.$scope.component.isArchived = true;
289 this.deleteArchiveCache();
291 this.Notification.success({
292 message: this.$scope.component.name + ' ' + this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TEXT"),
293 title: this.$filter('translate')("ARCHIVE_SUCCESS_MESSAGE_TITLE")
295 }, (error) => { this.$scope.isLoading = false; });
298 this.$scope.restoreComponent = ():void => {
299 this.$scope.isLoading = true;
300 const typeComponent = this.$scope.component.componentType;
301 this.ComponentServiceNg2.restoreComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
302 this.$scope.isLoading = false;
303 this.Notification.success({
304 message: this.$scope.component.name + ' ' + this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TEXT"),
305 title: this.$filter('translate')("RESTORE_SUCCESS_MESSAGE_TITLE")
307 this.$scope.reload(this.$scope.component);
309 this.$scope.component.isArchived = false;
310 this.deleteArchiveCache();
313 this.$scope.$on('$stateChangeStart', (event, toState, toParams, fromState, fromParams) => {
314 if(this.$scope.isEditMode()){
315 if (fromParams.id == toParams.id && this.$state.current.data && this.$state.current.data.unsavedChanges) {
316 event.preventDefault();
317 if(this.$scope.isValidForm){
318 this.$scope.save().then(() => {
319 this.$scope.onMenuItemPressed(toState.name, toParams);
321 console.error("Save failed, unable to navigate to " + toState.name);
324 console.error("Form is invalid, unable to navigate to " + toState.name);
331 this.$scope.$on('$stateChangeSuccess', (event, toState) => {
332 this.$scope.updateSelectedMenuItem(this.$state.current.name);
335 this.$scope.onMenuItemPressed = (state:string, params:any):ng.IPromise<boolean> => {
337 let deferred:ng.IDeferred<boolean> = this.$q.defer();
338 let goToState = ():void => {
339 this.$state.go(state, Object.assign({
340 id: this.$scope.component.uniqueId,
341 type: this.$scope.component.componentType.toLowerCase(),
342 components: this.components
344 deferred.resolve(true);
347 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
348 (this.$state.current.name === States.WORKSPACE_MANAGEMENT_WORKFLOW || this.$state.current.name === States.WORKSPACE_NETWORK_CALL_FLOW)) {
349 let onGetSuccess = (component:Component) => {
350 this.$scope.isLoading = false;
351 // Update the components
352 this.$scope.component = component;
355 let onFailed = () => {
356 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
357 this.$scope.isLoading = false; // stop the progress.
358 deferred.reject(false);
360 this.$scope.component.getComponent().then(onGetSuccess, onFailed);
364 return deferred.promise;
367 this.$scope.setValidState = (isValid:boolean):void => {
368 this.$scope.isValidForm = isValid;
371 this.$scope.onVersionChanged = (selectedId:string):void => {
372 if (this.$scope.isGeneralView() && this.$state.current.data.unsavedChanges) {
373 this.$scope.changeVersion.selectedVersion = _.find(this.$scope.versionsList, (versionObj)=> {
374 return versionObj.versionId === this.$scope.component.uniqueId;
379 uuid: this.$scope.component.uuid,
380 version: this.$scope.changeVersion.selectedVersion.versionNumber
383 this.eventBusService.notify("VERSION_CHANGED", eventData).subscribe(() => {
384 this.$scope.isLoading = true;
386 this.$state.go(this.$state.current.name, {
388 type: this.$scope.componentType.toLowerCase(),
389 mode: WorkspaceMode.VIEW,
390 components: this.$state.params['components']
395 this.$scope.getLatestVersion = ():void => {
396 this.$scope.onVersionChanged(_.first(this.$scope.versionsList).versionId);
399 this.$scope.create = () => {
401 this.$scope.startProgress("Creating Asset...");
402 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = true;//disabled click on general tab (DE246274)
404 // In case we import CSAR. Notify user that import VF will take long time (the create is performed in the background).
405 if (this.$scope.component.isResource() && (<Resource>this.$scope.component).csarUUID) {
406 this.Notification.info({
407 message: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_DESCRIPTION"),
408 title: this.$filter('translate')("IMPORT_VF_MESSAGE_CREATE_TAKES_LONG_TIME_TITLE")
412 let onFailed = () => {
413 this.$scope.stopProgress();
414 this.$scope.isLoading = false; // stop the progress.
415 _.first(this.$scope.leftBarTabs.menuItems).isDisabled = false;//enabled click on general tab (DE246274)
416 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
417 let modalInstance:ng.ui.bootstrap.IModalServiceInstance;
418 modalInstance && modalInstance.close(); // Close the modal in case it is opened.
419 this.$scope.component.tags = _.without(this.$scope.component.tags, this.$scope.component.name);// for fix DE246217
421 this.$scope.setValidState(true); // Set the form valid (if sent form is valid, the error from server).
424 let onSuccessCreate = (component:Component) => {
426 this.$scope.stopProgress();
427 this.showSuccessNotificationMessage();
429 // Update the components list for breadcrumbs
430 this.components.unshift(component);
432 this.$state.go(States.WORKSPACE_GENERAL, {
433 id: component.uniqueId,
434 type: component.componentType.toLowerCase(),
435 components: this.components
436 }, {inherit: false});
439 console.log(this.$scope.component, "this.$scope.component")
440 if ((<Service>this.$scope.component).serviceType == "Service") {
441 this.ComponentFactory.importComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
443 this.ComponentFactory.createComponentOnServer(this.$scope.component).then(onSuccessCreate, onFailed);
450 this.$scope.save = ():Promise<void> => {
452 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_CLICK);
454 this.$scope.startProgress("Updating Asset...");
455 this.$scope.disableMenuItems();
457 return new Promise<void>((resolve, reject) => {
458 let stopProgressAndEnableUI = () => {
459 this.$scope.disabledButtons = false;
460 this.$scope.isLoading = false;
461 this.$scope.enableMenuItems();
462 this.$scope.stopProgress();
465 let onFailed = () => {
466 stopProgressAndEnableUI();
467 this.$scope.updateUnsavedFileFlag(true);
468 this.EventListenerService.notifyObservers(EVENTS.ON_WORKSPACE_SAVE_BUTTON_ERROR);
473 let onSuccessUpdate = (component:Component) => {
474 stopProgressAndEnableUI();
475 this.showSuccessNotificationMessage();
477 component.tags = _.reject(component.tags, (item)=> {
478 return item === component.name
481 this.$scope.updateBreadcrumbs(component);
483 //update the component
484 this.$scope.setComponent(component);
485 this.$scope.originComponent = this.ComponentFactory.createComponent(this.$scope.component);
487 if (this.cacheService.contains(CHANGE_COMPONENT_CSAR_VERSION_FLAG)) {
488 this.cacheService.remove(CHANGE_COMPONENT_CSAR_VERSION_FLAG);
490 if (this.cacheService.contains(PREVIOUS_CSAR_COMPONENT)) {
491 this.cacheService.remove(PREVIOUS_CSAR_COMPONENT);
495 this.$state.current.data.unsavedChanges = false;
496 this.$scope.unsavedFile = false;
497 this.$scope.reload(component);
501 this.$scope.component.updateComponent().then(onSuccessUpdate, onFailed);
506 this.$scope.changeLifecycleState = (state:string):void => {
507 if (this.$scope.isGeneralView() && state !== 'deleteVersion') {
508 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE_WITH_SAVE, state);
510 this.$scope.handleChangeLifecycleState(state);
514 let defaultActionAfterChangeLifecycleState = ():void => {
515 if (this.$state.current.data && this.$state.current.data.unsavedChanges) {
516 this.$state.current.data.unsavedChanges = false;
518 this.$state.go('dashboard');
521 this.$scope.handleChangeLifecycleState = (state:string, newCsarVersion?:string, onError?: Function) => {
522 if ('monitor' === state) {
523 this.$state.go('workspace.distribution');
527 let data = this.$scope.changeLifecycleStateButtons[state];
528 if (!data && this.$stateParams.componentCsar && !this.$scope.isCreateMode()) {
529 data = {text: 'Check Out', url: 'lifecycleState/CHECKOUT'};
531 const onSuccess = (component, url:string):void => {
532 // Updating the component from server response
534 // Creating the data object to notify the plugins with
535 const eventData: any = {
536 uuid: this.$scope.component.uuid,
537 version: this.$scope.component.version
540 // the server returns only metaData (small component) except checkout (Full component) ,so we update only the statuses of distribution & lifecycle
541 this.$scope.component.lifecycleState = component.lifecycleState;
542 this.$scope.component.distributionStatus = component.distributionStatus;
545 case 'lifecycleState/CHECKOUT':
546 this.workspaceNg1BridgeService.updateIsViewOnly(false);
547 this.eventBusService.notify("CHECK_OUT", eventData, false).subscribe(() => {
548 // only checkOut get the full component from server
549 // this.$scope.component = component;
550 // Work around to change the csar version
552 this.cacheService.set(CHANGE_COMPONENT_CSAR_VERSION_FLAG, newCsarVersion);
553 (this.$scope.component as Resource).csarVersion = newCsarVersion;
556 //when checking out a minor version uuid remains
557 const bcIdx = _.findIndex(this.components, (item) => {
558 return item.uuid === component.uuid;
561 this.components[bcIdx] = component;
563 //when checking out a major(certified) version
564 this.components.unshift(component);
566 this.$scope.mode = this.initViewMode();
567 this.initChangeLifecycleStateButtons();
568 this.initVersionObject();
569 this.$scope.isLoading = false;
570 this.EventListenerService.notifyObservers(EVENTS.ON_CHECKOUT, component);
571 this.workspaceService.setComponentMetadata(component.componentMetadata);
573 this.Notification.success({
574 message: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TEXT"),
575 title: this.$filter('translate')("CHECKOUT_SUCCESS_MESSAGE_TITLE")
580 case 'lifecycleState/CHECKIN':
581 this.workspaceNg1BridgeService.updateIsViewOnly(true);
582 defaultActionAfterChangeLifecycleState();
583 this.Notification.success({
584 message: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TEXT"),
585 title: this.$filter('translate')("CHECKIN_SUCCESS_MESSAGE_TITLE")
588 case 'lifecycleState/UNDOCHECKOUT':
589 this.eventBusService.notify("UNDO_CHECK_OUT", eventData, false).subscribe(() => {
590 defaultActionAfterChangeLifecycleState();
591 this.Notification.success({
592 message: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
593 title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
597 case 'lifecycleState/certify':
598 this.$scope.handleCertification(component);
599 this.verifyIfDependenciesExist();
600 this.$scope.reload(component);
602 case 'distribution/PROD/activate':
603 this.Notification.success({
604 message: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TEXT"),
605 title: this.$filter('translate')("DISTRIBUTE_SUCCESS_MESSAGE_TITLE")
607 this.initChangeLifecycleStateButtons();
610 defaultActionAfterChangeLifecycleState();
612 if (data.url !== 'lifecycleState/CHECKOUT') {
613 this.$scope.isLoading = false;
616 this.ChangeLifecycleStateHandler.changeLifecycleState(this.$scope.component, data, this.$scope, onSuccess);
619 this.$scope.deleteArchivedComponent = (): void => {
620 const modalTitle: string = this.$filter('translate')("COMPONENT_VIEW_DELETE_MODAL_TITLE");
621 const modalMessage: string = this.$filter('translate')("COMPONENT_VIEW_DELETE_MODAL_TEXT");
622 const modalButton = {
624 text: this.sdcMenu.alertMessages.okButton,
625 type: SdcUiCommon.ButtonType.warning,
626 callback: this.$scope.handleDeleteArchivedComponent,
628 } as SdcUiComponents.ModalButtonComponent;
629 this.modalServiceSdcUI.openWarningModal(modalTitle, modalMessage, 'alert-modal', [modalButton]);
632 this.$scope.handleDeleteArchivedComponent = (): void => {
633 this.$scope.isLoading = true;
634 const typeComponent = this.$scope.component.componentType;
635 this.ComponentServiceNg2.deleteComponent(typeComponent, this.$scope.component.uniqueId).subscribe(()=> {
636 this.deleteArchiveCache();
637 this.Notification.success({
638 message: this.$scope.component.name + ' ' + this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TEXT"),
639 title: this.$filter('translate')("DELETE_SUCCESS_MESSAGE_TITLE")
641 if (this.$state.params.previousState) {
642 switch (this.$state.params.previousState) {
645 this.$state.go(this.$state.params.previousState);
648 this.$state.go('dashboard');
652 this.$scope.isLoading = false;
654 this.Notification.error({
655 message: this.$scope.component.name + ' ' + this.$filter('translate')('DELETE_FAILURE_MESSAGE_TEXT'),
656 title: this.$filter('translate')('DELETE_FAILURE_MESSAGE_TITLE')
658 this.$scope.isLoading = false;
662 this.$scope.isViewMode = ():boolean => {
663 return this.$scope.mode === WorkspaceMode.VIEW;
666 this.$scope.isDesigner = ():boolean => {
667 return this.role == Role.DESIGNER;
670 this.$scope.isDisableMode = ():boolean => {
671 return this.$scope.mode === WorkspaceMode.VIEW && this.$scope.component.lifecycleState === ComponentState.NOT_CERTIFIED_CHECKIN;
674 this.$scope.isGeneralView = ():boolean => {
675 //we show revert and save icons only in general view
676 return this.$state.current.name === States.WORKSPACE_GENERAL;
679 this.$scope.isCreateMode = ():boolean => {
680 return this.$scope.mode === WorkspaceMode.CREATE;
683 this.$scope.checkDisableButton = (button: any):boolean => {
684 // Logic moved from html to component
685 if (this.$scope.isCreateMode() || button.disabled || this.$scope.disabledButtons || !this.$scope.isValidForm || this.$scope.unsavedChanges || this.$scope.component.isArchived){
689 // Specific verification for Checkout - enabled only in case the component is the latest version.
690 let result: boolean = false;
692 if (button.url === 'lifecycleState/CHECKOUT') {
693 result = !this.$scope.component.isLatestVersion();
698 this.$scope.isEditMode = ():boolean => {
699 return this.$scope.mode === WorkspaceMode.EDIT;
702 this.$scope.goToBreadcrumbHome = ():void => {
703 let bcHome:MenuItemGroup = this.$scope.breadcrumbsModel[0];
704 this.$state.go(bcHome.menuItems[bcHome.selectedIndex].state);
707 this.$scope.showLifecycleIcon = ():boolean => {
708 return this.role == Role.DESIGNER;
711 this.$scope.getStatus = ():string => {
712 if (this.$scope.isCreateMode()) {
716 return this.$scope.component.getStatus(this.sdcMenu);
719 this.initMenuItems();
721 this.$scope.showLatestVersion = (): boolean => {
722 let result: boolean = true;
723 if (!this.$scope.component.isLatestVersion()) {
726 if (ComponentState.NOT_CERTIFIED_CHECKOUT === this.$scope.component.lifecycleState && this.$scope.isViewMode()) {
732 this.$scope.updateSelectedMenuItem = (state:string):void => {
733 let stateArray:Array<string> = state.split('.', 2);
734 let stateWithoutInternalNavigate:string = stateArray[0] + '.' + stateArray[1];
735 let selectedItem:MenuItem = _.find(this.$scope.leftBarTabs.menuItems, (item:MenuItem) => {
736 let itemStateArray:Array<string> = item.state.split('.', 2);
737 let itemStateWithoutNavigation:string = itemStateArray[0] + '.' + itemStateArray[1];
738 return (itemStateWithoutNavigation === stateWithoutInternalNavigate);
741 let selectedIndex = selectedItem ? this.$scope.leftBarTabs.menuItems.indexOf(selectedItem) : 0;
743 if (stateArray[1] === 'plugins') {
744 _.forEach(PluginsConfiguration.plugins, (plugin) => {
745 if (plugin.pluginStateUrl == this.$state.params.path) {
748 else if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
754 this.$scope.leftBarTabs.selectedIndex = selectedIndex;
757 this.$scope.isSelected = (menuItem: MenuItem): boolean => {
758 return this.$scope.leftBarTabs.selectedIndex === _.indexOf(this.$scope.leftBarTabs.menuItems, menuItem);
761 this.$scope.$watch('$state.current.name', (newVal: string): void => {
763 this.$scope.isComposition = (newVal.indexOf(States.WORKSPACE_COMPOSITION) > -1);
764 this.$scope.isDeployment = newVal == States.WORKSPACE_DEPLOYMENT;
765 this.$scope.isPlugins = newVal == States.WORKSPACE_PLUGINS;
769 this.$scope.getTabTitle = (): string => {
770 return this.$scope.leftBarTabs.menuItems.find((menuItem: MenuItem) => {
771 return menuItem.state == this.$scope.$state.current.name;
775 this.$scope.reload = (component: Component): void => {
776 const isGeneralTab = this.$state.current.name === 'workspace.general';
777 // nullify the componentCsar in case we are in general tab so we know we didnt came from updateVsp Modal
779 this.$state.go(this.$state.current.name, {id: component.uniqueId, componentCsar: null}, {reload: true});
781 this.$state.go(this.$state.current.name, {id: component.uniqueId}, {reload: true});
785 this.$scope.$on('$destroy', () => {
786 this.EventListenerService.unRegisterObserver(EVENTS.ON_WORKSPACE_UNSAVED_CHANGES);
789 this.$scope.openAutomatedUpgradeModal = ():void => {
790 this.$scope.isLoading = true;
791 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>)=> {
792 this.$scope.isLoading = false;
793 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, false);
797 this.$scope.handleCertification = (certifyComponent): void => {
798 if (this.$scope.component.getComponentSubType() === ResourceType.VF || this.$scope.component.isService()) {
799 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response:Array<IDependenciesServerResponse>) => {
800 this.$scope.isLoading = false;
802 const isUpgradeNeeded = _.filter(response, (componentToUpgrade:IDependenciesServerResponse) => {
803 return componentToUpgrade.dependencies && componentToUpgrade.dependencies.length > 0;
805 if (isUpgradeNeeded.length === 0) {
806 this.onSuccessWithoutUpgradeNeeded();
809 this.refreshDataAfterChangeLifecycleState(certifyComponent);
810 this.AutomatedUpgradeService.openAutomatedUpgradeModal(response, this.$scope.component, true);
813 this.onSuccessWithoutUpgradeNeeded();
817 this.$scope.disableMenuItems = () => {
818 this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
819 item.isDisabled = (States.WORKSPACE_GENERAL !== item.state);
823 this.$scope.enableMenuItems = () => {
824 this.$scope.leftBarTabs.menuItems.forEach((item: MenuItem) => {
825 item.isDisabled = false;
830 this.$scope.startProgress = (message: string): void => {
831 this.progressService.initCreateComponentProgress(this.$scope.component.uniqueId);
832 this.$scope.isCreateProgress = true;
833 this.$scope.progressMessage = message;
836 this.$scope.stopProgress = (): void => {
837 this.$scope.isCreateProgress = false;
838 this.progressService.deleteProgressValue(this.$scope.component.uniqueId);
841 this.$scope.updateBreadcrumbs = (component: Component): void => {
842 // Update the components list for breadcrumbs
843 const bcIdx = this.MenuHandler.findBreadcrumbComponentIndex(this.components, component);
845 this.components[bcIdx] = component;
846 this.initBreadcrumbs(); // re-calculate breadcrumbs
850 this.$scope.updateUnsavedFileFlag = (isUnsaved:boolean) => {
851 this.$scope.unsavedFile = isUnsaved;
856 private onSuccessWithoutUpgradeNeeded = (): void => {
857 this.$scope.isLoading = false;
858 this.Notification.success({
859 message: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TEXT'),
860 title: this.$filter('translate')('SERVICE_CERTIFICATION_STATUS_TITLE')
862 this.initVersionObject();
863 this.initChangeLifecycleStateButtons();
866 private refreshDataAfterChangeLifecycleState = (component:Component):void => {
867 this.$scope.isLoading = false;
868 this.$scope.mode = this.initViewMode();
869 this.initChangeLifecycleStateButtons();
870 this.initVersionObject();
871 this.EventListenerService.notifyObservers(EVENTS.ON_LIFECYCLE_CHANGE, component);
874 private initAfterScope = (): void => {
875 // In case user select csar from the onboarding modal, need to disable checkout and submit for testing.
876 if (this.$state.params['disableButtons'] === true) {
877 this.$scope.uploadFileChangedInGeneralTab();
881 private initVersionObject = (): void => {
882 this.$scope.versionsList = (this.$scope.component.getAllVersionsAsSortedArray()).reverse();
883 this.$scope.changeVersion = {
884 selectedVersion: _.find(this.$scope.versionsList, (versionObj) => {
885 return versionObj.versionId === this.$scope.component.uniqueId;
890 private getNewComponentBreadcrumbItem = (): MenuItem => {
892 if (this.$scope.component.isResource() && (<Resource>this.$scope.component).isCsarComponent()) {
893 text = this.$scope.component.getComponentSubType() + ': ' + this.$scope.component.name;
895 text = 'Create new ' + this.$state.params['type'];
897 return new MenuItem(text, null, States.WORKSPACE_GENERAL, 'goToState', [this.$state.params]);
900 private updateMenuItemByRole = (menuItems: any[], role: string) => {
901 const tempMenuItems: any[] = new Array<any>();
902 menuItems.forEach((item: any) => {
903 //remove item if role is disabled
904 if (!(item.disabledRoles && item.disabledRoles.indexOf(role) > -1)) {
905 tempMenuItems.push(item);
908 return tempMenuItems;
911 private updateMenuItemByCategory = (menuItems:Array<any>, category:string) => {
912 let tempMenuItems:Array<any> = new Array<any>();
913 menuItems.forEach((item:any) => {
914 //update flag disabledCategory to true if category is disabled
915 item.disabledCategory = false;
916 if ((item.disabledCategories && item.disabledCategories.indexOf(category) > -1))
918 item.disabledCategory = true;
920 tempMenuItems.push(item);
922 return tempMenuItems;
926 private deleteArchiveCache = () => {
927 this.cacheService.remove('archiveComponents'); // delete the cache to ensure the archive is reloaded from server
930 private initBreadcrumbs = () => {
931 this.components = this.cacheService.get('breadcrumbsComponents');
932 const breadcrumbsComponentsLvl = this.MenuHandler.generateBreadcrumbsModelFromComponents(this.components, this.$scope.component);
934 if (this.$scope.isCreateMode()) {
935 const createItem = this.getNewComponentBreadcrumbItem();
936 if (!breadcrumbsComponentsLvl.menuItems) {
937 breadcrumbsComponentsLvl.menuItems = [];
939 breadcrumbsComponentsLvl.menuItems.unshift(createItem);
940 breadcrumbsComponentsLvl.selectedIndex = 0;
943 this.$scope.breadcrumbsModel = [breadcrumbsComponentsLvl, this.$scope.leftBarTabs];
946 private initMenuItems() {
948 const inCreateMode = this.$scope.isCreateMode();
949 this.$scope.leftBarTabs = new MenuItemGroup();
950 let menuItemsObjects: any[] = this.updateMenuItemByRole(this.sdcMenu.component_workspace_menu_option[this.$scope.component.getComponentSubType()], this.role);
951 if (this.$scope.component.getComponentSubType() === 'SERVICE') {
952 const menuItemsObjectsCategory: any[] = this.updateMenuItemByCategory(menuItemsObjects, this.category);
953 menuItemsObjects = menuItemsObjectsCategory;
956 // Only adding plugins to the workspace if they can be displayed for the current user role
957 _.each(PluginsConfiguration.plugins, (plugin: Plugin) => {
958 if (this.pluginsService.isPluginDisplayedInContext(plugin, this.role, this.$scope.component.getComponentSubType())) {
959 menuItemsObjects.push({
960 text: plugin.pluginDisplayOptions['context'].displayName,
961 action: 'onMenuItemPressed',
962 state: 'workspace.plugins',
963 params: {path: plugin.pluginStateUrl}
968 this.$scope.leftBarTabs.menuItems = menuItemsObjects.map((item: MenuItem) => {
969 const menuItem = new MenuItem(item.text, item.callback, item.state, item.action, item.params, item.blockedForTypes, item.disabledCategory);
970 if (menuItem.params) {
971 menuItem.params.state = menuItem.state;
974 menuItem.params = {state: menuItem.state};
976 menuItem.callback = () => this.$scope[menuItem.action](menuItem.state, menuItem.params);
977 menuItem.isDisabled = (inCreateMode && States.WORKSPACE_GENERAL !== menuItem.state) ||
978 (States.WORKSPACE_DEPLOYMENT === menuItem.state && this.$scope.component.modules
979 && this.$scope.component.modules.length === 0 && this.$scope.component.isResource()) ||
980 (menuItem.disabledCategory === true);
984 if (this.cacheService.get('breadcrumbsComponents')) {
985 this.initBreadcrumbs();
988 this.initBreadcrumbsComponents();
992 private showSuccessNotificationMessage = ():void => {
993 this.Notification.success({
994 message: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_DESCRIPTION'),
995 title: this.$filter('translate')('IMPORT_VF_MESSAGE_CREATE_FINISHED_TITLE')
999 private setWorkspaceButtonState = (newState: boolean, callback?: Function) => {
1000 this.$scope.unsavedChanges = newState;
1001 this.$scope.unsavedChangesCallback = callback;
1004 private initBreadcrumbsComponents = (): void => {
1005 let breadcrumbsComponentsObservable;
1006 if (this.$stateParams.previousState === 'dashboard') {
1007 breadcrumbsComponentsObservable = this.homeService.getAllComponents(true);
1008 } else if (this.$stateParams.previousState === 'catalog') {
1009 breadcrumbsComponentsObservable = this.catalogService.getCatalog();
1011 this.cacheService.remove('breadcrumbsComponentsState');
1012 this.cacheService.remove('breadcrumbsComponents');
1015 breadcrumbsComponentsObservable.subscribe((components) => {
1016 this.cacheService.set('breadcrumbsComponentsState', this.$stateParams.previousState);
1017 this.cacheService.set('breadcrumbsComponents', components);
1018 this.initBreadcrumbs();
1023 private verifyIfDependenciesExist(): void {
1024 let containsDependencies = [];
1025 if (this.$scope.component.componentType && this.$scope.component.uniqueId &&
1026 this.$scope.component.lifecycleState === 'CERTIFIED' && (this.$scope.component.isService() || this.$scope.component.getComponentSubType() === 'VF')) {
1027 this.ComponentServiceNg2.getDependencies(this.$scope.component.componentType, this.$scope.component.uniqueId).subscribe((response: IDependenciesServerResponse[]) => {
1028 containsDependencies = response.filter((version) => version.dependencies);
1029 if (containsDependencies.length > 0) {
1030 this.$scope.hasNoDependencies = false;
1032 this.$scope.hasNoDependencies = true;