Onboarding filter
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / SoftwareProductActionHelper.js
1 /*!
2  * Copyright © 2016-2018 European Support Limited
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 showFileSaveDialog from 'nfvo-utils/ShowFileSaveDialog.js';
18 import Configuration from 'sdc-app/config/Configuration.js';
19 import i18n from 'nfvo-utils/i18n/i18n.js';
20 import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
21 import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
22 import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
23
24 import {
25     actionTypes,
26     onboardingOriginTypes,
27     PRODUCT_QUESTIONNAIRE,
28     forms
29 } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
30 import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js';
31 import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js';
32 import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
33 import { actionTypes as HeatSetupActions } from 'sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupConstants.js';
34 import { actionTypes as featureGroupsActionConstants } from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js';
35 import { actionTypes as licenseAgreementActionTypes } from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
36 import { actionTypes as componentActionTypes } from './components/SoftwareProductComponentsConstants.js';
37 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
38 import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
39 import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
40 import { default as ItemsHelper } from 'sdc-app/common/helpers/ItemsHelper.js';
41 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
42 import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
43 import MergeEditorActionHelper from 'sdc-app/common/merge/MergeEditorActionHelper.js';
44 import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
45 import { actionTypes as commonActionTypes } from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
46 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
47 import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
48 import getValue from 'nfvo-utils/getValue.js';
49 import {
50     itemStatus,
51     versionStatus
52 } from 'sdc-app/common/helpers/ItemsHelperConstants.js';
53
54 function getLicensingData(licensingData = {}) {
55     const { licenseAgreement, featureGroups } = licensingData;
56     const newlicenseAgreement = getValue(licenseAgreement);
57     const newfeatureGroups = getValue(featureGroups);
58     return newlicenseAgreement
59         ? {
60               licenseAgreement: newlicenseAgreement,
61               featureGroups: newfeatureGroups
62           }
63         : undefined;
64 }
65
66 function baseUrl() {
67     const restPrefix = Configuration.get('restPrefix');
68     return `${restPrefix}/v1.0/vendor-software-products/`;
69 }
70 function softwareProductCategoriesUrl() {
71     const restCatalogPrefix = Configuration.get('restCatalogPrefix');
72     return `${restCatalogPrefix}/v1/categories/resources/`;
73 }
74
75 function uploadFile(vspId, formData, version) {
76     return RestAPIUtil.post(
77         `${baseUrl()}${vspId}/versions/${
78             version.id
79         }/orchestration-template-candidate`,
80         formData
81     );
82 }
83
84 function putSoftwareProduct({ softwareProduct, version }) {
85     return RestAPIUtil.put(
86         `${baseUrl()}${softwareProduct.id}/versions/${version.id}`,
87         {
88             name: softwareProduct.name,
89             description: softwareProduct.description,
90             category: softwareProduct.category,
91             subCategory: softwareProduct.subCategory,
92             vendorId: softwareProduct.vendorId,
93             vendorName: softwareProduct.vendorName,
94             licensingVersion: softwareProduct.licensingVersion
95                 ? softwareProduct.licensingVersion
96                 : undefined,
97             icon: softwareProduct.icon,
98             licensingData: getLicensingData(softwareProduct.licensingData)
99         }
100     );
101 }
102
103 function putSoftwareProductQuestionnaire(vspId, qdata, version) {
104     return RestAPIUtil.put(
105         `${baseUrl()}${vspId}/versions/${version.id}/questionnaire`,
106         qdata
107     );
108 }
109
110 function putSoftwareProductAction(id, action, version) {
111     return RestAPIUtil.put(`${baseUrl()}${id}/versions/${version.id}/actions`, {
112         action: action
113     });
114 }
115
116 function fetchSoftwareProductList() {
117     return RestAPIUtil.fetch(
118         `${baseUrl()}?versionFilter=${versionStatus.DRAFT}`
119     );
120 }
121
122 function fetchArchivedSoftwareProductList() {
123     return RestAPIUtil.fetch(`${baseUrl()}?Status=${itemStatus.ARCHIVED}`);
124 }
125
126 function fetchFinalizedSoftwareProductList() {
127     return RestAPIUtil.fetch(
128         `${baseUrl()}?versionFilter=${versionStatus.CERTIFIED}`
129     );
130 }
131
132 function fetchSoftwareProduct(vspId, version) {
133     return RestAPIUtil.fetch(`${baseUrl()}${vspId}/versions/${version.id}`);
134 }
135
136 function fetchSoftwareProductQuestionnaire(vspId, version) {
137     return RestAPIUtil.fetch(
138         `${baseUrl()}${vspId}/versions/${version.id}/questionnaire`
139     );
140 }
141
142 function updateSoftwareProductHeatCandidate(
143     softwareProductId,
144     heatCandidate,
145     version
146 ) {
147     return RestAPIUtil.put(
148         `${baseUrl()}${softwareProductId}/versions/${
149             version.id
150         }/orchestration-template-candidate/manifest`,
151         heatCandidate
152     );
153 }
154 function validateHeatCandidate(softwareProductId, version) {
155     return RestAPIUtil.put(
156         `${baseUrl()}${softwareProductId}/versions/${
157             version.id
158         }/orchestration-template-candidate/process`
159     );
160 }
161
162 function fetchOrchestrationTemplateCandidate(softwareProductId, version) {
163     return RestAPIUtil.fetch(
164         `${baseUrl()}${softwareProductId}/versions/${
165             version.id
166         }/orchestration-template-candidate`,
167         { dataType: 'binary' }
168     );
169 }
170
171 function abortValidationProcess(softwareProductId, version) {
172     return RestAPIUtil.destroy(
173         `${baseUrl()}${softwareProductId}/versions/${
174             version.id
175         }/orchestration-template-candidate`
176     );
177 }
178
179 function objToString(obj) {
180     let str = '';
181     if (obj instanceof Array) {
182         obj.forEach(item => {
183             str += objToString(item) + '\n';
184         });
185     } else {
186         for (let p in obj) {
187             if (obj.hasOwnProperty(p)) {
188                 str += obj[p] + '\n';
189             }
190         }
191     }
192     return str.replace(/\n$/, '');
193 }
194
195 function parseUploadErrorMsg(error) {
196     let message = '';
197     for (let key in error) {
198         if (error.hasOwnProperty(key)) {
199             message += objToString(error[key]) + '\n';
200         }
201     }
202     return message.replace(/\n$/, '');
203 }
204
205 function fetchSoftwareProductCategories(dispatch) {
206     let handleResponse = response =>
207         dispatch({
208             type: actionTypes.SOFTWARE_PRODUCT_CATEGORIES_LOADED,
209             softwareProductCategories: response
210         });
211     return RestAPIUtil.fetch(softwareProductCategoriesUrl())
212         .then(handleResponse)
213         .catch(() => handleResponse(null));
214 }
215
216 function loadLicensingData(dispatch, { licenseModelId, licensingVersion }) {
217     return ItemsHelper.fetchVersion({
218         itemId: licenseModelId,
219         versionId: licensingVersion
220     }).then(() => {
221         return Promise.all([
222             LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {
223                 licenseModelId,
224                 version: { id: licensingVersion }
225             }),
226             FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {
227                 licenseModelId,
228                 version: { id: licensingVersion }
229             })
230         ]);
231     });
232 }
233
234 function getExpandedItemsId(items, itemIdToToggle) {
235     for (let i = 0; i < items.length; i++) {
236         if (items[i].id === itemIdToToggle) {
237             if (items[i].expanded) {
238                 return {};
239             } else {
240                 return { [itemIdToToggle]: true };
241             }
242         } else if (items[i].items && items[i].items.length > 0) {
243             let mapOfExpandedIds = getExpandedItemsId(
244                 items[i].items,
245                 itemIdToToggle
246             );
247             if (mapOfExpandedIds !== false) {
248                 mapOfExpandedIds[items[i].id] = true;
249                 return mapOfExpandedIds;
250             }
251         }
252     }
253     return false;
254 }
255
256 function migrateSoftwareProduct(vspId, version) {
257     return RestAPIUtil.put(`${baseUrl()}${vspId}/versions/${version.id}/heal`);
258 }
259
260 const SoftwareProductActionHelper = {
261     fetchFinalizedSoftwareProductList(dispatch) {
262         return fetchFinalizedSoftwareProductList().then(response =>
263             dispatch({
264                 type: actionTypes.FINALIZED_SOFTWARE_PRODUCT_LIST_LOADED,
265                 response
266             })
267         );
268     },
269
270     fetchArchivedSoftwareProductList(dispatch) {
271         return fetchArchivedSoftwareProductList().then(response =>
272             dispatch({
273                 type: actionTypes.ARCHIVED_SOFTWARE_PRODUCT_LIST_LOADED,
274                 response
275             })
276         );
277     },
278
279     loadSoftwareProductAssociatedData(dispatch) {
280         fetchSoftwareProductCategories(dispatch);
281         LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
282     },
283
284     loadSoftwareProductDetailsData(
285         dispatch,
286         { licenseModelId, licensingVersion }
287     ) {
288         SoftwareProductActionHelper.loadSoftwareProductAssociatedData(dispatch);
289         if (licensingVersion) {
290             return loadLicensingData(dispatch, {
291                 licenseModelId,
292                 licensingVersion
293             });
294         }
295         return Promise.resolve();
296     },
297
298     fetchSoftwareProductList(dispatch) {
299         return fetchSoftwareProductList().then(response =>
300             dispatch({
301                 type: actionTypes.SOFTWARE_PRODUCT_LIST_LOADED,
302                 response
303             })
304         );
305     },
306
307     loadSoftwareProductHeatCandidate(dispatch, { softwareProductId, version }) {
308         return RestAPIUtil.fetch(
309             `${baseUrl()}${softwareProductId}/versions/${
310                 version.id
311             }/orchestration-template-candidate/manifest`
312         ).then(response =>
313             dispatch({
314                 type: HeatSetupActions.MANIFEST_LOADED,
315                 response
316             })
317         );
318     },
319
320     loadLicensingVersionsList(dispatch, { licenseModelId }) {
321         return ItemsHelper.fetchVersions({ itemId: licenseModelId }).then(
322             response => {
323                 dispatch({
324                     type: actionTypes.LOAD_LICENSING_VERSIONS_LIST,
325                     licensingVersionsList: response.results
326                 });
327             }
328         );
329     },
330     updateSoftwareProductHeatCandidate(
331         dispatch,
332         { softwareProductId, heatCandidate, version }
333     ) {
334         return updateSoftwareProductHeatCandidate(
335             softwareProductId,
336             heatCandidate,
337             version
338         );
339     },
340
341     processAndValidateHeatCandidate(dispatch, { softwareProductId, version }) {
342         return validateHeatCandidate(softwareProductId, version).then(
343             response => {
344                 if (response.status === 'Success') {
345                     SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
346                         dispatch,
347                         { softwareProductId, version }
348                     );
349                     SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
350                         softwareProductId,
351                         version
352                     });
353                 } else {
354                     SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
355                         softwareProductId,
356                         version
357                     });
358                 }
359             }
360         );
361     },
362
363     uploadFile(
364         dispatch,
365         { softwareProductId, formData, failedNotificationTitle, version }
366     ) {
367         dispatch({
368             type: HeatSetupActions.FILL_HEAT_SETUP_CACHE,
369             payload: {}
370         });
371
372         Promise.resolve()
373             .then(() => uploadFile(softwareProductId, formData, version))
374             .then(response => {
375                 if (response.status === 'Success') {
376                     dispatch({
377                         type: commonActionTypes.DATA_CHANGED,
378                         deltaData: {
379                             onboardingOrigin: response.onboardingOrigin
380                         },
381                         formName: forms.VENDOR_SOFTWARE_PRODUCT_DETAILS
382                     });
383                     switch (response.onboardingOrigin) {
384                         case onboardingOriginTypes.ZIP:
385                             ScreensHelper.loadScreen(dispatch, {
386                                 screen:
387                                     enums.SCREEN
388                                         .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP,
389                                 screenType: screenTypes.SOFTWARE_PRODUCT,
390                                 props: { softwareProductId, version }
391                             });
392                             dispatch({
393                                 type: actionTypes.CANDIDATE_IN_PROCESS,
394                                 inProcess: true
395                             });
396                             break;
397                         case onboardingOriginTypes.CSAR:
398                             ScreensHelper.loadScreen(dispatch, {
399                                 screen:
400                                     enums.SCREEN
401                                         .SOFTWARE_PRODUCT_ATTACHMENTS_VALIDATION,
402                                 screenType: screenTypes.SOFTWARE_PRODUCT,
403                                 props: { softwareProductId, version }
404                             });
405                             break;
406                     }
407                 } else {
408                     throw new Error(parseUploadErrorMsg(response.errors));
409                 }
410             })
411             .catch(error => {
412                 dispatch({
413                     type: modalActionTypes.GLOBAL_MODAL_ERROR,
414                     data: {
415                         title: failedNotificationTitle,
416                         msg:
417                             error.message ||
418                             (error.responseJSON && error.responseJSON.message)
419                     }
420                 });
421             });
422     },
423
424     downloadHeatFile(
425         dispatch,
426         { softwareProductId, heatCandidate, isReadOnlyMode, version }
427     ) {
428         let p = isReadOnlyMode
429             ? Promise.resolve()
430             : SoftwareProductActionHelper.updateSoftwareProductHeatCandidate(
431                   dispatch,
432                   {
433                       softwareProductId,
434                       heatCandidate,
435                       version
436                   }
437               );
438         p.then(() => {
439             fetchOrchestrationTemplateCandidate(
440                 softwareProductId,
441                 version
442             ).then(response => {
443                 showFileSaveDialog({
444                     blob: response.blob,
445                     headers: response.headers,
446                     defaultFilename: 'HEAT_file.zip',
447                     addTimestamp: true
448                 });
449             });
450         }, null /* do not download if data was not saved correctly*/);
451     },
452
453     hideUploadConfirm(dispatch) {
454         dispatch({
455             type: actionTypes.softwareProductEditor.UPLOAD_CONFIRMATION
456         });
457     },
458     updateSoftwareProduct(dispatch, { softwareProduct, version, qdata }) {
459         return Promise.all([
460             SoftwareProductActionHelper.updateSoftwareProductData(dispatch, {
461                 softwareProduct,
462                 version
463             }).then(() =>
464                 dispatch({
465                     type: actionTypes.SOFTWARE_PRODUCT_LIST_EDIT,
466                     payload: { softwareProduct }
467                 })
468             ),
469             SoftwareProductActionHelper.updateSoftwareProductQuestionnaire(
470                 dispatch,
471                 {
472                     softwareProductId: softwareProduct.id,
473                     qdata,
474                     version
475                 }
476             )
477         ]);
478     },
479
480     updateSoftwareProductData(dispatch, { softwareProduct, version }) {
481         return putSoftwareProduct({ softwareProduct, version });
482     },
483
484     updateSoftwareProductQuestionnaire(
485         dispatch,
486         { softwareProductId, qdata, version }
487     ) {
488         return putSoftwareProductQuestionnaire(
489             softwareProductId,
490             qdata,
491             version
492         );
493     },
494
495     softwareProductEditorDataChanged(dispatch, { deltaData }) {
496         dispatch({
497             type: actionTypes.softwareProductEditor.DATA_CHANGED,
498             deltaData
499         });
500     },
501
502     softwareProductQuestionnaireUpdate(dispatch, { data }) {
503         dispatch({
504             type: actionTypes.SOFTWARE_PRODUCT_QUESTIONNAIRE_UPDATE,
505             payload: { qdata: data }
506         });
507     },
508
509     softwareProductEditorVendorChanged(dispatch, { deltaData, formName }) {
510         if (deltaData.licensingVersion) {
511             return loadLicensingData(dispatch, {
512                 licenseModelId: deltaData.vendorId,
513                 licensingVersion: deltaData.licensingVersion
514             }).then(() => {
515                 ValidationHelper.dataChanged(dispatch, { deltaData, formName });
516                 return Promise.resolve();
517             });
518         } else if (deltaData.vendorId) {
519             ValidationHelper.dataChanged(dispatch, { deltaData, formName });
520             return SoftwareProductActionHelper.loadLicensingVersionsList(
521                 dispatch,
522                 {
523                     licenseModelId: deltaData.vendorId
524                 }
525             ).then(() =>
526                 OnboardingActionHelper.forceBreadCrumbsUpdate(dispatch)
527             );
528         } else {
529             ValidationHelper.dataChanged(dispatch, { deltaData, formName });
530
531             dispatch({
532                 type: licenseAgreementActionTypes.LICENSE_AGREEMENT_LIST_LOADED,
533                 response: { results: [] }
534             });
535
536             dispatch({
537                 type: featureGroupsActionConstants.FEATURE_GROUPS_LIST_LOADED,
538                 response: { results: [] }
539             });
540         }
541     },
542
543     setIsValidityData(dispatch, { isValidityData }) {
544         dispatch({
545             type: actionTypes.softwareProductEditor.IS_VALIDITY_DATA_CHANGED,
546             isValidityData
547         });
548     },
549
550     fetchSoftwareProduct(dispatch, { softwareProductId, version }) {
551         return Promise.all([
552             fetchSoftwareProduct(softwareProductId, version).then(response => {
553                 dispatch({
554                     type: actionTypes.SOFTWARE_PRODUCT_LOADED,
555                     response
556                 });
557                 return response;
558             }),
559             fetchSoftwareProductQuestionnaire(softwareProductId, version).then(
560                 response => {
561                     ValidationHelper.qDataLoaded(dispatch, {
562                         response: {
563                             qdata: response.data
564                                 ? JSON.parse(response.data)
565                                 : {},
566                             qschema: JSON.parse(response.schema)
567                         },
568                         qName: PRODUCT_QUESTIONNAIRE
569                     });
570                 }
571             )
572         ]);
573     },
574
575     manageSubmitAction(dispatch, { softwareProductId, version, isDirty }) {
576         if (isDirty) {
577             const onCommit = comment => {
578                 return this.performVCAction(dispatch, {
579                     softwareProductId,
580                     action: VersionControllerActionsEnum.COMMIT,
581                     version,
582                     comment
583                 }).then(() => {
584                     return this.performSubmitAction(dispatch, {
585                         softwareProductId,
586                         version
587                     });
588                 });
589             };
590             dispatch({
591                 type: modalActionTypes.GLOBAL_MODAL_SHOW,
592                 data: {
593                     modalComponentName: modalContentMapper.COMMIT_COMMENT,
594                     modalComponentProps: {
595                         onCommit,
596                         type: CommitModalType.COMMIT_SUBMIT
597                     },
598                     title: i18n('Commit & Submit')
599                 }
600             });
601             return Promise.resolve(version);
602         }
603         return this.performSubmitAction(dispatch, {
604             softwareProductId,
605             version
606         });
607     },
608
609     performSubmitAction(dispatch, { softwareProductId, version }) {
610         return putSoftwareProductAction(
611             softwareProductId,
612             VersionControllerActionsEnum.SUBMIT,
613             version
614         ).then(
615             () => {
616                 return putSoftwareProductAction(
617                     softwareProductId,
618                     VersionControllerActionsEnum.CREATE_PACKAGE,
619                     version
620                 ).then(() => {
621                     return ItemsHelper.checkItemStatus(dispatch, {
622                         itemId: softwareProductId,
623                         versionId: version.id
624                     }).then(updatedVersion => {
625                         dispatch({
626                             type: modalActionTypes.GLOBAL_MODAL_SUCCESS,
627                             data: {
628                                 title: i18n('Submit Succeeded'),
629                                 msg: i18n(
630                                     'This software product successfully submitted'
631                                 ),
632                                 cancelButtonText: i18n('OK'),
633                                 timeout: 2000
634                             }
635                         });
636                         versionPageActionHelper.fetchVersions(dispatch, {
637                             itemType: itemTypes.SOFTWARE_PRODUCT,
638                             itemId: softwareProductId
639                         });
640                         return Promise.resolve(updatedVersion);
641                     });
642                 });
643             },
644             error => {
645                 dispatch({
646                     type: modalActionTypes.GLOBAL_MODAL_ERROR,
647                     data: {
648                         modalComponentName:
649                             modalContentMapper.SUMBIT_ERROR_RESPONSE,
650                         title: i18n('Submit Failed'),
651                         modalComponentProps: {
652                             validationResponse: error.responseJSON
653                         },
654                         cancelButtonText: i18n('OK')
655                     }
656                 });
657                 return Promise.reject(error.responseJSON);
658             }
659         );
660     },
661
662     performVCAction(dispatch, { softwareProductId, action, version, comment }) {
663         return MergeEditorActionHelper.analyzeSyncResult(dispatch, {
664             itemId: softwareProductId,
665             version
666         }).then(({ inMerge, isDirty, updatedVersion }) => {
667             if (
668                 (updatedVersion.status === versionStatus.CERTIFIED ||
669                     updatedVersion.archivedStatus === itemStatus.ARCHIVED) &&
670                 (action === VersionControllerActionsEnum.COMMIT ||
671                     action === VersionControllerActionsEnum.SYNC)
672             ) {
673                 versionPageActionHelper.fetchVersions(dispatch, {
674                     itemType: itemTypes.SOFTWARE_PRODUCT,
675                     itemId: softwareProductId
676                 });
677                 const msg =
678                     updatedVersion.archivedStatus === itemStatus.ARCHIVED
679                         ? i18n('Item was Archived')
680                         : i18n('Item version already Certified');
681                 dispatch({
682                     type: modalActionTypes.GLOBAL_MODAL_WARNING,
683                     data: {
684                         title: i18n('Commit error'),
685                         msg,
686                         cancelButtonText: i18n('Cancel')
687                     }
688                 });
689                 return Promise.resolve(updatedVersion);
690             }
691             if (!inMerge) {
692                 if (action === VersionControllerActionsEnum.SUBMIT) {
693                     return this.manageSubmitAction(dispatch, {
694                         softwareProductId,
695                         version,
696                         isDirty
697                     });
698                 } else {
699                     let isCallActionValid =
700                         action !== VersionControllerActionsEnum.COMMIT ||
701                         isDirty;
702                     if (isCallActionValid) {
703                         return ItemsHelper.performVCAction({
704                             itemId: softwareProductId,
705                             action,
706                             version,
707                             comment
708                         }).then(() => {
709                             versionPageActionHelper.fetchVersions(dispatch, {
710                                 itemType: itemTypes.LICENSE_MODEL,
711                                 itemId: softwareProductId
712                             });
713                             if (action === VersionControllerActionsEnum.SYNC) {
714                                 return MergeEditorActionHelper.analyzeSyncResult(
715                                     dispatch,
716                                     { itemId: softwareProductId, version }
717                                 ).then(({ updatedVersion }) => {
718                                     return Promise.resolve(updatedVersion);
719                                 });
720                             } else {
721                                 return ItemsHelper.checkItemStatus(dispatch, {
722                                     itemId: softwareProductId,
723                                     versionId: version.id
724                                 });
725                             }
726                         });
727                     } else {
728                         dispatch({
729                             type: modalActionTypes.GLOBAL_MODAL_ERROR,
730                             data: {
731                                 title: i18n('Commit Failed'),
732                                 msg: i18n('There is nothing to commit')
733                             }
734                         });
735                     }
736                 }
737             }
738         });
739     },
740
741     toggleNavigationItems(dispatch, { items, itemIdToExpand }) {
742         let mapOfExpandedIds = getExpandedItemsId(items, itemIdToExpand);
743         dispatch({
744             type: actionTypes.TOGGLE_NAVIGATION_ITEM,
745             mapOfExpandedIds
746         });
747     },
748
749     /** for the next verision */
750     addComponent(dispatch, { softwareProductId, modalClassName, version }) {
751         SoftwareProductComponentsActionHelper.clearComponentCreationData(
752             dispatch
753         );
754         dispatch({
755             type: componentActionTypes.COMPONENT_CREATE_OPEN
756         });
757         dispatch({
758             type: modalActionTypes.GLOBAL_MODAL_SHOW,
759             data: {
760                 modalComponentName: modalContentMapper.COMPONENT_CREATION,
761                 modalComponentProps: { softwareProductId, version },
762                 modalClassName,
763                 title: 'Create Virtual Function Component'
764             }
765         });
766     },
767
768     migrateSoftwareProduct(dispatch, { softwareProduct }) {
769         let { id: softwareProductId, version } = softwareProduct;
770         const newVer = version.id;
771         migrateSoftwareProduct(softwareProductId, version).then(() =>
772             ScreensHelper.loadScreen(dispatch, {
773                 screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
774                 screenType: screenTypes.SOFTWARE_PRODUCT,
775                 props: {
776                     softwareProductId,
777                     version: { id: newVer, label: newVer }
778                 }
779             })
780         );
781     },
782
783     abortCandidateValidation(dispatch, { softwareProductId, version }) {
784         return abortValidationProcess(softwareProductId, version);
785     }
786 };
787
788 export default SoftwareProductActionHelper;