Fix view attachment for onboarded CSAR packages
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / SoftwareProduct.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 { connect } from 'react-redux';
17
18 import i18n from 'nfvo-utils/i18n/i18n.js';
19 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
20 import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx';
21
22 import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
23 import {
24     onboardingMethod as onboardingMethodTypes,
25     onboardingOriginTypes
26 } from './SoftwareProductConstants.js';
27 import SoftwareProductActionHelper from './SoftwareProductActionHelper.js';
28 import SoftwareProductComponentsActionHelper from './components/SoftwareProductComponentsActionHelper.js';
29 import PermissionsActionHelper from './../permissions/PermissionsActionHelper.js';
30 import RevisionsActionHelper from './../revisions/RevisionsActionHelper.js';
31 import HeatSetupActionHelper from './attachments/setup/HeatSetupActionHelper.js';
32 import { actionsEnum as versionControllerActions } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
33 import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
34 import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
35 import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
36 import { onboardingMethod as onboardingMethodType } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
37 import { SyncStates } from 'sdc-app/common/merge/MergeEditorConstants.js';
38 import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
39
40 function getActiveNavigationId(screen, componentId) {
41     let activeItemId = componentId ? screen + '|' + componentId : screen;
42     return activeItemId;
43 }
44
45 const buildComponentNavigationBarGroups = ({ componentId, meta }) => {
46     const groups = [
47         {
48             id:
49                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL +
50                 '|' +
51                 componentId,
52             name: i18n('General'),
53             disabled: false,
54             meta
55         },
56         {
57             id:
58                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE +
59                 '|' +
60                 componentId,
61             name: i18n('Compute'),
62             disabled: false,
63             meta
64         },
65         {
66             id:
67                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING +
68                 '|' +
69                 componentId,
70             name: i18n('High Availability & Load Balancing'),
71             disabled: false,
72             meta
73         },
74         {
75             id:
76                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK +
77                 '|' +
78                 componentId,
79             name: i18n('Networks'),
80             disabled: false,
81             meta
82         },
83         {
84             id:
85                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE +
86                 '|' +
87                 componentId,
88             name: i18n('Storage'),
89             disabled: false,
90             meta
91         },
92         {
93             id:
94                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES +
95                 '|' +
96                 componentId,
97             name: i18n('Images'),
98             disabled: false,
99             meta
100         },
101         {
102             id:
103                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES +
104                 '|' +
105                 componentId,
106             name: i18n('Process Details'),
107             disabled: false,
108             meta
109         },
110         {
111             id:
112                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING +
113                 '|' +
114                 componentId,
115             name: i18n('Monitoring'),
116             disabled: false,
117             meta
118         }
119     ];
120
121     return groups;
122 };
123
124 const buildNavigationBarProps = ({
125     softwareProduct,
126     meta,
127     screen,
128     componentId,
129     componentsList,
130     mapOfExpandedIds,
131     isCertified
132 }) => {
133     const {
134         softwareProductEditor: { data: currentSoftwareProduct = {} }
135     } = softwareProduct;
136     const {
137         id,
138         name,
139         onboardingMethod,
140         candidateOnboardingOrigin,
141         onboardingOrigin
142     } = currentSoftwareProduct;
143     let { isValidationDisabled } = softwareProduct.softwareProductValidation;
144     const groups = [
145         {
146             id: id,
147             name: name,
148             items: [
149                 {
150                     id: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
151                     name: i18n('Overview'),
152                     disabled: false,
153                     meta
154                 },
155                 {
156                     id: enums.SCREEN.SOFTWARE_PRODUCT_DETAILS,
157                     name: i18n('General'),
158                     disabled: false,
159                     meta
160                 },
161                 {
162                     id: enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT,
163                     name: i18n('Deployment Flavors'),
164                     disabled: false,
165                     hidden: onboardingMethod !== onboardingMethodTypes.MANUAL,
166                     meta
167                 },
168                 {
169                     id: enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES,
170                     name: i18n('Process Details'),
171                     disabled: false,
172                     meta
173                 },
174                 {
175                     id: enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS,
176                     name: i18n('Networks'),
177                     disabled: false,
178                     meta
179                 },
180                 {
181                     id: enums.SCREEN.SOFTWARE_PRODUCT_VALIDATION,
182                     name: i18n('Validation'),
183                     disabled: false,
184                     hidden: isValidationDisabled,
185                     meta
186                 },
187                 {
188                     id: enums.SCREEN.SOFTWARE_PRODUCT_VALIDATION_RESULTS,
189                     name: i18n('Validation Results'),
190                     disabled: false,
191                     hidden: isValidationDisabled,
192                     meta
193                 },
194                 {
195                     id: enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS,
196                     name: i18n('Attachments'),
197                     disabled: false,
198                     hidden: !candidateOnboardingOrigin && !onboardingOrigin,
199                     meta
200                 },
201                 {
202                     id: enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG,
203                     name: i18n('Activity Log'),
204                     disabled: false,
205                     meta
206                 },
207                 {
208                     id: enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES,
209                     name: i18n('Component Dependencies'),
210                     hidden: componentsList.length <= 1,
211                     disabled: false,
212                     meta
213                 },
214                 {
215                     id: enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS,
216                     name: i18n('Components'),
217                     hidden: componentsList.length <= 0,
218                     meta,
219                     expanded:
220                         mapOfExpandedIds[
221                             enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS
222                         ] === true &&
223                         screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
224                     items: [
225                         ...componentsList.map(({ id, displayName }) => ({
226                             id:
227                                 enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS +
228                                 '|' +
229                                 id,
230                             name: displayName,
231                             meta,
232                             expanded:
233                                 mapOfExpandedIds[
234                                     enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS +
235                                         '|' +
236                                         id
237                                 ] === true &&
238                                 screen !==
239                                     enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
240                             items: buildComponentNavigationBarGroups({
241                                 componentId: id,
242                                 meta
243                             })
244                         }))
245                     ]
246                 }
247             ]
248         }
249     ];
250     let activeItemId = getActiveNavigationId(screen, componentId);
251     return {
252         activeItemId,
253         groups,
254         disabled: !!candidateOnboardingOrigin && !isCertified
255     };
256 };
257
258 const buildVersionControllerProps = ({
259     softwareProduct,
260     versions,
261     currentVersion,
262     permissions,
263     userInfo,
264     isArchived,
265     usersList,
266     itemPermission,
267     isReadOnlyMode
268 }) => {
269     const { softwareProductEditor = { data: {} } } = softwareProduct;
270     const {
271         isValidityData = true,
272         data: { name, onboardingMethod, candidateOnboardingOrigin }
273     } = softwareProductEditor;
274
275     return {
276         version: currentVersion,
277         viewableVersions: versions,
278         isFormDataValid: isValidityData,
279         permissions,
280         itemName: name,
281         itemPermission,
282         isReadOnlyMode,
283         isArchived,
284         userInfo,
285         usersList,
286         isManual: onboardingMethod === onboardingMethodType.MANUAL,
287         candidateInProcess:
288             !!candidateOnboardingOrigin && !itemPermission.isCertified
289     };
290 };
291
292 function buildMeta({
293     softwareProduct,
294     componentId,
295     softwareProductDependencies,
296     isReadOnlyMode
297 }) {
298     const {
299         softwareProductEditor,
300         softwareProductComponents,
301         softwareProductQuestionnaire,
302         softwareProductAttachments
303     } = softwareProduct;
304     const { data: currentSoftwareProduct = {} } = softwareProductEditor;
305     const {
306         version,
307         onboardingOrigin,
308         candidateOnboardingOrigin
309     } = currentSoftwareProduct;
310     const { qdata } = softwareProductQuestionnaire;
311     const { heatSetup, heatSetupCache } = softwareProductAttachments;
312     let currentComponentMeta = {};
313     if (componentId) {
314         const {
315             componentEditor: { data: componentData = {}, qdata: componentQdata }
316         } = softwareProductComponents;
317         currentComponentMeta = { componentData, componentQdata };
318     }
319     const meta = {
320         softwareProduct: currentSoftwareProduct,
321         qdata,
322         version,
323         onboardingOrigin,
324         candidateOnboardingOrigin,
325         heatSetup,
326         heatSetupCache,
327         isReadOnlyMode,
328         currentComponentMeta,
329         softwareProductDependencies
330     };
331     return meta;
332 }
333
334 const mapStateToProps = (
335     {
336         softwareProduct,
337         users: { usersList, userInfo },
338         versionsPage: { versionsList: { versions }, permissions }
339     },
340     {
341         currentScreen: {
342             screen,
343             itemPermission,
344             props: { version: currentVersion, componentId, isReadOnlyMode }
345         }
346     }
347 ) => {
348     const {
349         softwareProductEditor,
350         softwareProductComponents,
351         softwareProductDependencies
352     } = softwareProduct;
353     const { mapOfExpandedIds = [] } = softwareProductEditor;
354     const { componentsList = [] } = softwareProductComponents;
355
356     const meta = buildMeta({
357         softwareProduct,
358         componentId,
359         softwareProductDependencies,
360         isReadOnlyMode
361     });
362     return {
363         versionControllerProps: buildVersionControllerProps({
364             softwareProduct,
365             versions,
366             currentVersion,
367             userInfo,
368             usersList,
369             isArchived: itemPermission.isArchived,
370             permissions,
371             itemPermission: { ...itemPermission, isDirty: true },
372             isReadOnlyMode
373         }),
374         navigationBarProps: buildNavigationBarProps({
375             softwareProduct,
376             meta,
377             screen,
378             componentId,
379             componentsList,
380             mapOfExpandedIds,
381             isCertified: itemPermission.isCertified
382         }),
383         meta
384     };
385 };
386
387 const autoSaveBeforeNavigate = ({
388     dispatch,
389     screen,
390     softwareProductId,
391     version,
392     componentId,
393     meta: {
394         isReadOnlyMode,
395         softwareProduct,
396         qdata,
397         currentComponentMeta: { componentData, componentQdata }
398     }
399 }) => {
400     let promise;
401     if (isReadOnlyMode) {
402         promise = Promise.resolve();
403     } else {
404         switch (screen) {
405             case enums.SCREEN.SOFTWARE_PRODUCT_DETAILS:
406                 promise = SoftwareProductActionHelper.updateSoftwareProduct(
407                     dispatch,
408                     { softwareProduct, version, qdata }
409                 );
410                 break;
411             case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_GENERAL:
412                 promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(
413                     dispatch,
414                     {
415                         softwareProductId,
416                         version,
417                         vspComponentId: componentId,
418                         componentData,
419                         qdata: componentQdata
420                     }
421                 );
422                 break;
423             case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_COMPUTE:
424             case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_STORAGE:
425             case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_NETWORK:
426             case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
427             case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_LOAD_BALANCING:
428                 promise = SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(
429                     dispatch,
430                     {
431                         softwareProductId,
432                         version,
433                         vspComponentId: componentId,
434                         qdata: componentQdata
435                     }
436                 );
437                 break;
438             default:
439                 promise = Promise.resolve();
440                 break;
441         }
442     }
443     return promise;
444 };
445
446 const mapActionsToProps = (
447     dispatch,
448     {
449         currentScreen: {
450             screen,
451             props: {
452                 softwareProductId,
453                 licenseModelId,
454                 version,
455                 componentId: currentComponentId
456             }
457         }
458     }
459 ) => {
460     const props = {
461         onVersionSwitching: (versionToSwitch, meta) => {
462             ScreensHelper.loadScreen(dispatch, {
463                 screen: enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
464                 screenType: screenTypes.SOFTWARE_PRODUCT,
465                 props: {
466                     softwareProductId: meta.softwareProduct.id,
467                     version: versionToSwitch
468                 }
469             });
470         },
471         onOpenPermissions: ({ users }) => {
472             return PermissionsActionHelper.fetchItemUsers(dispatch, {
473                 itemId: softwareProductId,
474                 allUsers: users
475             });
476         },
477         onOpenRevisionsModal: () => {
478             return RevisionsActionHelper.openRevisionsView(dispatch, {
479                 itemId: softwareProductId,
480                 version: version,
481                 itemType: screenTypes.SOFTWARE_PRODUCT
482             });
483         },
484         onOpenCommentCommitModal: ({ onCommit, title }) =>
485             dispatch({
486                 type: modalActionTypes.GLOBAL_MODAL_SHOW,
487                 data: {
488                     modalComponentName: modalContentMapper.COMMIT_COMMENT,
489                     modalComponentProps: {
490                         onCommit,
491                         type: CommitModalType.COMMIT
492                     },
493                     title
494                 }
495             }),
496         onMoreVersionsClick: ({ itemName, users }) => {
497             ScreensHelper.loadScreen(dispatch, {
498                 screen: enums.SCREEN.SOFTWARE_PRODUCT_VERSIONS_PAGE,
499                 screenType: screenTypes.SOFTWARE_PRODUCT,
500                 props: {
501                     softwareProductId,
502                     softwareProduct: {
503                         name: itemName,
504                         vendorId: licenseModelId
505                     },
506                     usersList: users
507                 }
508             });
509         },
510         onToggle: (groups, itemIdToExpand) =>
511             groups.map(({ items }) =>
512                 SoftwareProductActionHelper.toggleNavigationItems(dispatch, {
513                     items,
514                     itemIdToExpand
515                 })
516             ),
517         onNavigate: ({ id, meta, newVersion }) => {
518             let navigationVersion = newVersion || version;
519             let {
520                 onboardingOrigin,
521                 candidateOnboardingOrigin,
522                 heatSetup,
523                 heatSetupCache
524             } = meta;
525             let heatSetupPopupPromise =
526                 screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS
527                     ? HeatSetupActionHelper.heatSetupLeaveConfirmation(
528                           dispatch,
529                           { softwareProductId, heatSetup, heatSetupCache }
530                       )
531                     : Promise.resolve();
532             let preNavigate = meta
533                 ? autoSaveBeforeNavigate({
534                       dispatch,
535                       screen,
536                       meta,
537                       version,
538                       softwareProductId,
539                       componentId: currentComponentId
540                   })
541                 : Promise.resolve();
542             version = version || (meta ? meta.version : undefined);
543             Promise.all([preNavigate, heatSetupPopupPromise])
544                 .then(() => {
545                     let [nextScreen, nextComponentId] = id.split('|');
546                     if (
547                         nextScreen ===
548                             enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS &&
549                         nextComponentId &&
550                         nextComponentId === currentComponentId
551                     ) {
552                         ScreensHelper.loadScreen(dispatch, {
553                             screen: nextScreen,
554                             screenType: screenTypes.SOFTWARE_PRODUCT,
555                             props: {
556                                 softwareProductId,
557                                 version: navigationVersion
558                             }
559                         });
560                     } else {
561                         if (
562                             nextScreen ===
563                             enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS
564                         ) {
565                             if (
566                                 onboardingOrigin ===
567                                     onboardingOriginTypes.ZIP ||
568                                 candidateOnboardingOrigin ===
569                                     onboardingOriginTypes.ZIP
570                             ) {
571                                 nextScreen =
572                                     enums.SCREEN
573                                         .SOFTWARE_PRODUCT_ATTACHMENTS_SETUP;
574                             } else if (
575                                 onboardingOrigin === onboardingOriginTypes.CSAR
576                             ) {
577                                 nextScreen =
578                                     enums.SCREEN
579                                         .SOFTWARE_PRODUCT_ATTACHMENTS_VIEW_VALIDATION;
580                             }
581                         }
582                         ScreensHelper.loadScreen(dispatch, {
583                             screen: nextScreen,
584                             screenType: screenTypes.SOFTWARE_PRODUCT,
585                             props: {
586                                 softwareProductId,
587                                 version: navigationVersion,
588                                 componentId: nextComponentId
589                             }
590                         });
591                     }
592                 })
593                 .catch(e => {
594                     console.error(e);
595                 });
596         }
597     };
598
599     switch (screen) {
600         case enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE:
601         case enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS:
602         case enums.SCREEN.SOFTWARE_PRODUCT_PROCESSES:
603         case enums.SCREEN.SOFTWARE_PRODUCT_NETWORKS:
604         case enums.SCREEN.SOFTWARE_PRODUCT_VALIDATION:
605         case enums.SCREEN.SOFTWARE_PRODUCT_VALIDATION_RESULTS:
606         case enums.SCREEN.SOFTWARE_PRODUCT_DEPENDENCIES:
607         case enums.SCREEN.SOFTWARE_PRODUCT_ACTIVITY_LOG:
608         case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENTS:
609         case enums.SCREEN.SOFTWARE_PRODUCT_DEPLOYMENT:
610         case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_PROCESSES:
611         case enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING:
612             props.onSave = () => Promise.resolve();
613             break;
614         default:
615             props.onSave = ({ softwareProduct, qdata }) =>
616                 SoftwareProductActionHelper.updateSoftwareProduct(dispatch, {
617                     softwareProduct,
618                     qdata,
619                     version
620                 });
621             break;
622     }
623
624     props.onVersionControllerAction = (action, version, comment, meta) => {
625         let { heatSetup, heatSetupCache } = meta;
626         let autoSavePromise = meta
627             ? autoSaveBeforeNavigate({
628                   dispatch,
629                   screen,
630                   meta,
631                   version,
632                   softwareProductId,
633                   componentId: currentComponentId
634               })
635             : Promise.resolve();
636         let heatSetupPopupPromise =
637             screen === enums.SCREEN.SOFTWARE_PRODUCT_ATTACHMENTS &&
638             action === versionControllerActions.COMMIT
639                 ? HeatSetupActionHelper.heatSetupLeaveConfirmation(dispatch, {
640                       softwareProductId,
641                       heatSetup,
642                       heatSetupCache
643                   })
644                 : Promise.resolve();
645         Promise.all([autoSavePromise, heatSetupPopupPromise])
646             .then(() => {
647                 return SoftwareProductActionHelper.performVCAction(dispatch, {
648                     softwareProductId,
649                     action,
650                     version,
651                     comment,
652                     meta
653                 }).then(updatedVersion => {
654                     const inMerge =
655                         updatedVersion &&
656                         updatedVersion.state &&
657                         updatedVersion.state.synchronizationState ===
658                             SyncStates.MERGE;
659                     if (
660                         (action === versionControllerActions.SYNC &&
661                             !inMerge) ||
662                         ((action === versionControllerActions.COMMIT ||
663                             action === versionControllerActions.SYNC) &&
664                             updatedVersion.status ===
665                                 catalogItemStatuses.CERTIFIED)
666                     ) {
667                         ScreensHelper.loadLandingScreen(dispatch, {
668                             previousScreenName: screen,
669                             props: {
670                                 softwareProductId,
671                                 version: updatedVersion
672                             }
673                         });
674                     } else {
675                         ScreensHelper.loadScreen(dispatch, {
676                             screen,
677                             screenType: screenTypes.SOFTWARE_PRODUCT,
678                             props: {
679                                 softwareProductId,
680                                 version: updatedVersion,
681                                 componentId: currentComponentId
682                             }
683                         });
684                     }
685                 });
686             })
687             .catch(e => {
688                 console.error(e);
689             });
690     };
691
692     props.onManagePermissions = () =>
693         PermissionsActionHelper.openPermissonsManager(dispatch, {
694             itemId: softwareProductId,
695             askForRights: false
696         });
697     return props;
698 };
699
700 export default connect(mapStateToProps, mapActionsToProps)(TabulatedEditor);