Add collaboration feature
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / SoftwareProductActionHelper.js
1 /*!
2  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
13  * or implied. See the License for the specific language governing
14  * permissions and limitations under the License.
15  */
16 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
17 import Configuration from 'sdc-app/config/Configuration.js';
18 import i18n from 'nfvo-utils/i18n/i18n.js';
19 import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
20 import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
21 import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
22
23 import {actionTypes, onboardingOriginTypes, PRODUCT_QUESTIONNAIRE, forms} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
24 import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
25 import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js';
26 import {actionsEnum as VersionControllerActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
27 import {actionTypes as HeatSetupActions} from 'sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
28 import {actionTypes as featureGroupsActionConstants} from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js';
29 import {actionTypes as licenseAgreementActionTypes} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
30 import {actionTypes as componentActionTypes} from './components/SoftwareProductComponentsConstants.js';
31 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
32 import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
33 import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
34 import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
35 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
36 import {enums, screenTypes} from 'sdc-app/onboarding/OnboardingConstants.js';
37 import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js';
38 import {CommitModalType} from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
39 import {actionTypes as commonActionTypes} from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
40 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
41 import {itemTypes} from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
42 import {catalogItemStatuses} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
43 import getValue from 'nfvo-utils/getValue.js';
44
45 function getLicensingData(licensingData = {}) {
46         const {licenseAgreement, featureGroups} = licensingData;
47         const newlicenseAgreement = getValue(licenseAgreement);
48         const newfeatureGroups = getValue(featureGroups);
49         return newlicenseAgreement ? {
50                 licenseAgreement: newlicenseAgreement,
51                 featureGroups: newfeatureGroups
52         } : undefined;
53 };
54
55 function baseUrl() {
56         const restPrefix = Configuration.get('restPrefix');
57         return `${restPrefix}/v1.0/vendor-software-products/`;
58 }
59 function softwareProductCategoriesUrl() {
60         const restATTPrefix = Configuration.get('restATTPrefix');
61         return `${restATTPrefix}/v1/categories/resources/`;
62 }
63
64 function uploadFile(vspId, formData, version) {
65         return RestAPIUtil.post(`${baseUrl()}${vspId}/versions/${version.id}/orchestration-template-candidate`, formData);
66
67 }
68
69 function putSoftwareProduct({softwareProduct, version}) {
70         return RestAPIUtil.put(`${baseUrl()}${softwareProduct.id}/versions/${version.id}`, {
71                 name: softwareProduct.name,
72                 description: softwareProduct.description,
73                 category: softwareProduct.category,
74                 subCategory: softwareProduct.subCategory,
75                 vendorId: softwareProduct.vendorId,
76                 vendorName: softwareProduct.vendorName,
77                 licensingVersion: softwareProduct.licensingVersion ? softwareProduct.licensingVersion : undefined,
78                 icon: softwareProduct.icon,
79                 licensingData: getLicensingData(softwareProduct.licensingData)
80         });
81 }
82
83 function putSoftwareProductQuestionnaire(vspId, qdata, version) {
84         return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`, qdata);
85 }
86
87 function putSoftwareProductAction(id, action, version) {
88         return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, {action: action});
89 }
90
91 function fetchSoftwareProductList() {
92         return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=Draft`);
93 }
94
95 function fetchFinalizedSoftwareProductList() {
96         return RestAPIUtil.fetch(`${baseUrl()}?versionFilter=Certified`);
97 }
98
99 function fetchSoftwareProduct(vspId, version) {
100         return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`);
101 }
102
103 function fetchSoftwareProductQuestionnaire(vspId, version) {
104         return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}/questionnaire`);
105 }
106
107 function updateSoftwareProductHeatCandidate(softwareProductId, heatCandidate, version) {
108         return RestAPIUtil.put(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`, heatCandidate);
109 }
110 function validateHeatCandidate(softwareProductId, version) {
111         return RestAPIUtil.put(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/process`);
112 }
113
114 function fetchOrchestrationTemplateCandidate(softwareProductId, version, ) {
115         return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate`, {dataType: 'binary'});
116 }
117
118 function objToString(obj) {
119         let str = '';
120         if (obj instanceof Array) {
121                 obj.forEach((item) => {
122                         str += objToString(item) + '\n';
123                 });
124         }
125         else {
126                 for (let p in obj) {
127                         if (obj.hasOwnProperty(p)) {
128                                 str += obj[p] + '\n';
129                         }
130                 }
131         }
132         return str.replace(/\n$/, '');
133 }
134
135 function parseUploadErrorMsg(error) {
136         let message = '';
137         for (let key in error) {
138                 if (error.hasOwnProperty(key)) {
139                         message += objToString(error[key]) + '\n';
140                 }
141         }
142         return message.replace(/\n$/, '');
143 }
144
145 function fetchSoftwareProductCategories(dispatch) {
146         let handleResponse = response => dispatch({
147                 type: actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED,
148                 softwareProductCategories: response
149         });
150         return RestAPIUtil.fetch(softwareProductCategoriesUrl())
151                 .then(handleResponse)
152                 .catch(() => handleResponse(null));
153 }
154
155 function loadLicensingData(dispatch, {licenseModelId, licensingVersion}) {
156         return ItemsHelper.fetchVersion({itemId: licenseModelId, versionId: licensingVersion}).then(() => {
157                 return Promise.all([
158                         LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: {id: licensingVersion}}),
159                         FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: {id: licensingVersion}})
160                 ]);
161         });
162 }
163
164 function getExpandedItemsId(items, itemIdToToggle) {
165         for (let i = 0; i < items.length; i++) {
166                 if (items[i].id === itemIdToToggle) {
167                         if (items[i].expanded) {
168                                 return {};
169                         }
170                         else {
171                                 return {[itemIdToToggle]: true};
172                         }
173                 }
174                 else if (items[i].items && items[i].items.length > 0) {
175                         let mapOfExpandedIds = getExpandedItemsId(items[i].items, itemIdToToggle);
176                         if (mapOfExpandedIds !== false) {
177                                 mapOfExpandedIds[items[i].id] = true;
178                                 return mapOfExpandedIds;
179                         }
180                 }
181         }
182         return false;
183 }
184
185 function getTimestampString() {
186         let date = new Date();
187         let z = n => n < 10 ? '0' + n : n;
188         return `${date.getFullYear()}-${z(date.getMonth())}-${z(date.getDate())}_${z(date.getHours())}-${z(date.getMinutes())}`;
189 }
190
191 function showFileSaveDialog({blob, xhr, defaultFilename, addTimestamp}) {
192         let filename;
193         let contentDisposition = xhr.getResponseHeader('content-disposition') ? xhr.getResponseHeader('content-disposition') : '';
194         let match = contentDisposition.match(/filename=(.*?)(;|$)/);
195         if (match) {
196                 filename = match[1];
197         }
198         else {
199                 filename = defaultFilename;
200         }
201
202         if (addTimestamp) {
203                 filename = filename.replace(/(^.*?)\.([^.]+$)/, `$1_${getTimestampString()}.$2`);
204         }
205
206         let link = document.createElement('a');
207         let url = URL.createObjectURL(blob);
208         link.href = url;
209         link.download = filename;
210         link.style.display = 'none';
211         document.body.appendChild(link);
212         link.click();
213         setTimeout(function(){
214                 document.body.removeChild(link);
215                 URL.revokeObjectURL(url);
216         }, 0);
217 }
218
219 function migrateSoftwareProduct(vspId, version) {
220         return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`);
221 }
222
223
224
225 const SoftwareProductActionHelper = {
226
227         fetchFinalizedSoftwareProductList(dispatch) {
228                 return fetchFinalizedSoftwareProductList().then(response => dispatch({
229                         type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED,
230                         response
231                 }));
232         },
233
234         loadSoftwareProductAssociatedData(dispatch) {
235                 fetchSoftwareProductCategories(dispatch);
236                 LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
237         },
238
239         loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion}) {
240                 SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
241                 if (licensingVersion) {
242                         return loadLicensingData(dispatch, {licenseModelId, licensingVersion});
243                 }
244                 return Promise.resolve();
245         },
246
247         fetchSoftwareProductList(dispatch) {
248                 return fetchSoftwareProductList().then(response => dispatch({
249                         type: actionTypes.SOFTWARE_PRODUCT_LIST_LOADED,
250                         response
251                 }));
252         },
253
254         loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version}){
255                 return RestAPIUtil.fetch(`${baseUrl()}${softwareProductId}/versions/${version.id}/orchestration-template-candidate/manifest`).then(response => dispatch({
256                         type: HeatSetupActions.MANIFEST_LOADED,
257                         response
258                 }));
259         },
260
261         loadLicensingVersionsList(dispatch, {licenseModelId}){
262                 return ItemsHelper.fetchVersions({itemId: licenseModelId}).then(response => {
263                         dispatch({
264                                 type: actionTypes.LOAD_LICENSING_VERSIONS_LIST,
265                                 licensingVersionsList: response.results
266                         });
267                 });
268         },
269         updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version}){
270                 return updateSoftwareProductHeatCandidate(softwareProductId, heatCandidate, version);
271         },
272
273         processAndValidateHeatCandidate(dispatch, {softwareProductId, version}){
274                 return validateHeatCandidate(softwareProductId, version).then(response => {
275                         if (response.status === 'Success') {
276                                 SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
277                                 SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version});
278                         }
279                 });
280         },
281
282         uploadFile(dispatch, {softwareProductId, formData, failedNotificationTitle, version}) {
283                 dispatch({
284                         type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
285                         payload: {}
286                 });
287
288                 Promise.resolve()
289                         .then(() => uploadFile(softwareProductId, formData, version))
290                         .then(response => {
291                                 if (response.status === 'Success') {
292                                         dispatch({
293                                                 type: commonActionTypes.DATA_CHANGED,
294                                                 deltaData: {onboardingOrigin: response.onboardingOrigin},
295                                                 formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
296                                         });
297                                         switch(response.onboardingOrigin){
298                                                 case onboardingOriginTypes.ZIP:
299                                                         ScreensHelper.loadScreen(dispatch, {
300                                                                 screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_SETUP, screenType: screenTypes.SOFTWARE_PRODUCT,
301                                                                 props: {softwareProductId, version}
302                                                         });
303                                                         break;
304                                                 case onboardingOriginTypes.CSAR:
305                                                         ScreensHelper.loadScreen(dispatch, {
306                                                                 screen: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION, screenType: screenTypes.SOFTWARE_PRODUCT,
307                                                                 props: {softwareProductId, version}
308                                                         });
309                                                         break;
310                                         }
311                                 }
312                                 else {
313                                         throw new Error(parseUploadErrorMsg(response.errors));
314                                 }
315                         })
316                         .catch(error => {
317                                 dispatch({
318                                         type: modalActionTypes.GLOBAL_MODAL_ERROR,
319                                         data: {
320                                                 title: failedNotificationTitle,
321                                                 msg: error.message || (error.responseJSON && error.responseJSON.message)
322                                         }
323                                 });
324                         });
325         },
326
327         downloadHeatFile(dispatch, {softwareProductId, heatCandidate, isReadOnlyMode, version}){
328                 let p = isReadOnlyMode ? Promise.resolve() : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(dispatch, {softwareProductId, heatCandidate, version});
329                 p.then(() => {
330                         fetchOrchestrationTemplateCandidate(softwareProductId, version)
331                                 .then((blob, statusText, xhr) => showFileSaveDialog({blob, xhr, defaultFilename: 'HEAT_file.zip', addTimestamp: true}));
332                 }, null/* do not download if data was not saved correctly*/);
333         },
334
335         hideUploadConfirm (dispatch) {
336                 dispatch({
337                         type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION
338                 });
339         },
340         updateSoftwareProduct(dispatch, {softwareProduct, version, qdata}) {
341                 return Promise.all([
342                         SoftwareProductActionHelper.updateSoftwareProductData(dispatch, {softwareProduct, version}).then(
343                                 () => dispatch({
344                                         type: actionTypes.SOFTWARE_PRODUCT_LIST_EDIT,
345                                         payload: {softwareProduct}
346                                 })
347                         ),
348                         SoftwareProductActionHelper.updateSoftwareProductQuestionnaire(dispatch, {
349                                 softwareProductId: softwareProduct.id,
350                                 qdata,
351                                 version
352                         })
353                 ]);
354         },
355
356         updateSoftwareProductData(dispatch, {softwareProduct, version}) {
357                 return putSoftwareProduct({softwareProduct, version});
358         },
359
360         updateSoftwareProductQuestionnaire(dispatch, {softwareProductId, qdata, version}) {
361                 return putSoftwareProductQuestionnaire(softwareProductId, qdata, version);
362         },
363
364         softwareProductEditorDataChanged(dispatch, {deltaData}) {
365                 dispatch({
366                         type: actionTypes.softwareProductEditor.DATA_CHANGED,
367                         deltaData
368                 });
369         },
370
371         softwareProductQuestionnaireUpdate(dispatch, {data}) {
372                 dispatch({
373                         type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE,
374                         payload: {qdata: data}
375                 });
376         },
377
378         softwareProductEditorVendorChanged(dispatch, {deltaData, formName}) {
379                 if (deltaData.licensingVersion){
380                         return loadLicensingData(dispatch, {licenseModelId: deltaData.vendorId, licensingVersion: deltaData.licensingVersion}).then(() => {
381                                 ValidationHelper.dataChanged(dispatch, {deltaData, formName});
382                                 return Promise.resolve();
383                         });
384                 } else if (deltaData.vendorId) {
385                         ValidationHelper.dataChanged(dispatch, {deltaData, formName});
386                         return SoftwareProductActionHelper.loadLicensingVersionsList(dispatch, {
387                                 licenseModelId: deltaData.vendorId
388                         }).then( () =>
389                                 OnboardingActionHelper.forceBreadCrumbsUpdate(dispatch)
390                         );
391                 } else {
392                         ValidationHelper.dataChanged(dispatch, {deltaData, formName});
393
394                         dispatch({
395                                 type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
396                                 response: {results: []}
397                         });
398
399                         dispatch({
400                                 type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
401                                 response: {results: []}
402                         });
403                 }
404
405         },
406
407         setIsValidityData(dispatch, {isValidityData}) {
408                 dispatch({
409                         type: actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED,
410                         isValidityData
411                 });
412         },
413
414         fetchSoftwareProduct(dispatch, {softwareProductId, version}) {
415                 return Promise.all([
416                         fetchSoftwareProduct(softwareProductId, version).then(response => {
417                                 dispatch({
418                                         type: actionTypes.SOFTWARE_PRODUCT_LOADED,
419                                         response
420                                 });
421                                 return response;
422                         }),
423                         fetchSoftwareProductQuestionnaire(softwareProductId, version).then(response => {
424                                 ValidationHelper.qDataLoaded(dispatch, {response: {qdata: response.data ? JSON.parse(response.data) : {},
425                                         qschema: JSON.parse(response.schema)}, qName: PRODUCT_QUESTIONNAIRE});
426                         })
427                 ]);
428         },
429
430         manageSubmitAction(dispatch, {softwareProductId, version, isDirty}) {
431                 if (isDirty) {
432                         const onCommit = comment => {
433                                 return this.performVCAction(dispatch, {softwareProductId, action: VersionControllerActionsEnum.COMMIT, version, comment}).then(() => {
434                                         return this.performSubmitAction(dispatch, {softwareProductId, version});
435                                 });
436                         };
437                         dispatch({
438                                 type: modalActionTypes.GLOBAL_MODAL_SHOW,
439                                 data: {
440                                         modalComponentName: modalContentMapper.COMMIT_COMMENT,
441                                         modalComponentProps: {
442                                                 onCommit,
443                                                 type: CommitModalType.COMMIT_SUBMIT
444                                         },
445                                         title: i18n('Commit & Submit')
446                                 }
447                         });
448                         return Promise.resolve(version);
449                 }
450                 return this.performSubmitAction(dispatch, {softwareProductId, version});
451         },
452
453         performSubmitAction(dispatch, {softwareProductId, version}) {
454                 return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.SUBMIT, version).then(() => {
455                         return putSoftwareProductAction(softwareProductId, VersionControllerActionsEnum.CREATE_PACKAGE, version).then(() => {
456                                 return ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id}).then(updatedVersion => {
457                                         dispatch({
458                                                 type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
459                                                 data: {
460                                                         title: i18n('Submit Succeeded'),
461                                                         msg: i18n('This software product successfully submitted'),
462                                                         cancelButtonText: i18n('OK'),
463                                                         timeout: 2000
464                                                 }
465                                         });
466                                         versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId});
467                                         return Promise.resolve(updatedVersion);
468                                 });
469                         });
470                 }, error =>
471                 {
472                         dispatch({
473                                 type: modalActionTypes.GLOBAL_MODAL_ERROR,
474                                 data: {
475                                         modalComponentName: modalContentMapper.SUMBIT_ERROR_RESPONSE,
476                                         title: i18n('Submit Failed'),
477                                         modalComponentProps: {
478                                                 validationResponse: error.responseJSON
479                                         },
480                                         cancelButtonText: i18n('OK')
481                                 }
482                         });
483                         return Promise.reject(error.responseJSON);
484                 });
485         },
486
487         performVCAction(dispatch, {softwareProductId, action, version, comment}) {
488                 return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: softwareProductId, version}).then(({inMerge, isDirty, updatedVersion}) => {
489                         if (updatedVersion.status === catalogItemStatuses.CERTIFIED &&
490                                          (action === VersionControllerActionsEnum.COMMIT || action === VersionControllerActionsEnum.SYNC)) {
491                                 versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.SOFTWARE_PRODUCT, itemId: softwareProductId});
492                                 dispatch({
493                                         type: modalActionTypes.GLOBAL_MODAL_WARNING,
494                                         data: {
495                                                 title: i18n('Commit error'),
496                                                 msg: i18n('Item version already Certified'),
497                                                 cancelButtonText: i18n('Cancel')
498                                         }
499                                 });
500                                 return Promise.resolve(updatedVersion);
501                         }
502                         if (!inMerge) {
503                                 if (action === VersionControllerActionsEnum.SUBMIT) {
504                                         return this.manageSubmitAction(dispatch, {softwareProductId, version, isDirty});
505                                 }
506                                 else {
507                                         let isCallActionValid = action !== VersionControllerActionsEnum.COMMIT || isDirty;
508                                         if(isCallActionValid) {
509                                                 return  ItemsHelper.performVCAction({itemId: softwareProductId, action, version, comment}).then(() => {
510                                                         versionPageActionHelper.fetchVersions(dispatch, {itemType: itemTypes.LICENSE_MODEL, itemId: softwareProductId});
511                                                         if (action === VersionControllerActionsEnum.SYNC) {
512                                                                 return MergeEditorActionHelper.analyzeSyncResult(dispatch, {itemId: softwareProductId, version}).then(({updatedVersion}) => {
513                                                                         return Promise.resolve(updatedVersion);
514                                                                 });
515                                                         } else {
516                                                                 return ItemsHelper.checkItemStatus(dispatch, {itemId: softwareProductId, versionId: version.id});
517                                                         }
518                                                 });
519                                         }
520                                         else {
521                                                 dispatch({
522                                                         type: modalActionTypes.GLOBAL_MODAL_ERROR,
523                                                         data: {
524                                                                 title: i18n('Commit Failed'),
525                                                                 msg: i18n('There is nothing to commit')
526                                                         }
527                                                 });
528                                         }
529                                 }
530                         }
531                 });
532         },
533
534         toggleNavigationItems(dispatch, {items, itemIdToExpand}) {
535                 let mapOfExpandedIds = getExpandedItemsId(items, itemIdToExpand);
536                 dispatch({
537                         type: actionTypes.TOGGLE_NAVIGATION_ITEM,
538                         mapOfExpandedIds
539                 });
540         },
541
542         /** for the next verision */
543         addComponent(dispatch, {softwareProductId, modalClassName, version}) {
544                 SoftwareProductComponentsActionHelper.clearComponentCreationData(dispatch);
545                 dispatch({
546                         type: componentActionTypes.COMPONENT_CREATE_OPEN
547                 });
548                 dispatch({
549                         type: modalActionTypes.GLOBAL_MODAL_SHOW,
550                         data: {
551                                 modalComponentName: modalContentMapper.COMPONENT_CREATION,
552                                 modalComponentProps: {softwareProductId, version},
553                                 modalClassName,
554                                 title: 'Create Virtual Function Component'
555                         }
556                 });
557         },
558
559         migrateSoftwareProduct(dispatch, {softwareProduct}) {
560                 let {id: softwareProductId, version} = softwareProduct;
561                 const  newVer = version.id;
562                 migrateSoftwareProduct(softwareProductId, version).then(() => ScreensHelper.loadScreen(dispatch, {
563                         screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, screenType: screenTypes.SOFTWARE_PRODUCT,
564                         props: {softwareProductId, version: {id: newVer, label: newVer}}
565                 }));
566         }
567
568 };
569
570 export default SoftwareProductActionHelper;