19684512a16627b7b6b64498c93badde425002e8
[sdc.git] / openecomp-ui / src / sdc-app / onboarding / softwareProduct / attachments / validation / HeatValidationReducer.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 { actionTypes as softwareProductsActionTypes } from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
17 import { actionTypes, nodeFilters } from './HeatValidationConstants.js';
18
19 const mapNestedData = ({ fileName, env, errors }) => ({
20     name: fileName,
21     expanded: true,
22     type: 'heat',
23     children: env && [
24         {
25             name: env.fileName,
26             errors: env.errors,
27             type: 'env'
28         }
29     ],
30     errors
31 });
32
33 const mapVolumeData = ({ fileName, env, errors, nested }) => ({
34     name: fileName,
35     expanded: true,
36     type: 'volume',
37     children: [
38         ...(env
39             ? [
40                   {
41                       name: env.fileName,
42                       errors: env.errors,
43                       type: 'env'
44                   }
45               ]
46             : []),
47         ...(nested ? nested.map(mapNestedData) : [])
48     ],
49     errors
50 });
51
52 const mapNetworkData = ({ fileName, env, errors }) => ({
53     name: fileName,
54     expanded: true,
55     type: 'network',
56     children: env && [
57         {
58             name: env.fileName,
59             errors: env.errors,
60             type: 'env'
61         }
62     ],
63     errors
64 });
65
66 const mapArtifactsData = ({ fileName, errors }) => ({
67     name: fileName,
68     type: 'artifact',
69     errors
70 });
71
72 const mapOtherData = ({ fileName, errors }) => ({
73     name: fileName,
74     type: 'other',
75     errors
76 });
77
78 const mapHeatData = ({
79     fileName,
80     env,
81     nested,
82     volume,
83     network,
84     artifacts,
85     errors,
86     other
87 }) => ({
88     name: fileName,
89     expanded: true,
90     type: 'heat',
91     errors,
92     children: [
93         ...(volume ? volume.map(mapVolumeData) : []),
94         ...(network ? network.map(mapNetworkData) : []),
95         ...(env
96             ? [
97                   {
98                       name: env.fileName,
99                       errors: env.errors,
100                       type: 'env'
101                   }
102               ]
103             : []),
104         ...(artifacts ? artifacts.map(mapArtifactsData) : []),
105         ...(other ? other.map(mapOtherData) : []),
106         ...(nested ? nested.map(mapHeatData) : [])
107     ]
108 });
109
110 function createErrorList(node, parent, deep = 0, errorList = []) {
111     if (node.errors) {
112         errorList.push(
113             ...node.errors.map(error => ({
114                 level: error.level,
115                 errorMessage: error.message,
116                 name: node.name,
117                 hasParent: deep > 2,
118                 parentName: parent.name,
119                 type: node.type
120             }))
121         );
122     }
123     if (node.children && node.children.length) {
124         node.children.map(child =>
125             createErrorList(child, node, deep + 1, errorList)
126         );
127     }
128     return errorList;
129 }
130
131 const mapValidationDataToTree = (validationData, packageName) => {
132     let { heat, nested, volume, network, artifacts, other } =
133         validationData.importStructure || {};
134     return {
135         children: [
136             {
137                 name: packageName,
138                 expanded: true,
139                 type: 'heat',
140                 header: true,
141                 children: heat
142                     ? heat.map(mapHeatData)
143                     : nested ? nested.map(mapHeatData) : []
144             },
145             ...(artifacts
146                 ? [
147                       {
148                           name: 'artifacts',
149                           expanded: true,
150                           type: 'artifact',
151                           children: artifacts
152                               ? artifacts.map(mapArtifactsData)
153                               : []
154                       }
155                   ]
156                 : []),
157             ...(network
158                 ? [
159                       {
160                           name: 'networks',
161                           expanded: true,
162                           type: 'network',
163                           children: network ? network.map(mapNetworkData) : []
164                       }
165                   ]
166                 : []),
167             ...(volume
168                 ? [
169                       {
170                           name: 'volume',
171                           expanded: true,
172                           type: 'volume',
173                           children: volume ? volume.map(mapVolumeData) : []
174                       }
175                   ]
176                 : []),
177             ...(other
178                 ? [
179                       {
180                           name: 'other',
181                           expanded: true,
182                           type: 'other',
183                           children: other ? other.map(mapOtherData) : []
184                       }
185                   ]
186                 : [])
187         ]
188     };
189 };
190
191 const toggleExpanded = (node, path) => {
192     let newNode = { ...node };
193     if (path.length === 0) {
194         newNode.expanded = !node.expanded;
195     } else {
196         let index = path[0];
197         newNode.children = [
198             ...node.children.slice(0, index),
199             toggleExpanded(node.children[index], path.slice(1)),
200             ...node.children.slice(index + 1)
201         ];
202     }
203     return newNode;
204 };
205
206 const expandSelected = (node, selectedNode) => {
207     let shouldExpand = node.name === selectedNode;
208     let children =
209         node.children &&
210         node.children.map(child => {
211             let {
212                 shouldExpand: shouldExpandChild,
213                 node: newChild
214             } = expandSelected(child, selectedNode);
215             shouldExpand = shouldExpand || shouldExpandChild;
216             return newChild;
217         });
218
219     return {
220         node: {
221             ...node,
222             expanded: node.expanded || shouldExpand,
223             children
224         },
225         shouldExpand
226     };
227 };
228
229 export default (state = { attachmentsTree: {} }, action) => {
230     switch (action.type) {
231         case softwareProductsActionTypes.SOFTWARE_PRODUCT_LOADED:
232             let currentSoftwareProduct = action.response;
233             const packageName = currentSoftwareProduct.networkPackageName;
234             let attachmentsTree = currentSoftwareProduct.validationData
235                 ? mapValidationDataToTree(
236                       currentSoftwareProduct.validationData,
237                       packageName
238                   )
239                 : {};
240             let errorList = createErrorList(attachmentsTree);
241             return {
242                 ...state,
243                 attachmentsTree,
244                 errorList,
245                 selectedNode: nodeFilters.ALL
246             };
247         case actionTypes.TOGGLE_EXPANDED:
248             return {
249                 ...state,
250                 attachmentsTree: toggleExpanded(
251                     state.attachmentsTree,
252                     action.path
253                 )
254             };
255         case actionTypes.SELECTED_NODE:
256             let selectedNode = action.nodeName;
257             return {
258                 ...state,
259                 attachmentsTree: expandSelected(
260                     state.attachmentsTree,
261                     selectedNode
262                 ).node,
263                 selectedNode
264             };
265         case actionTypes.UNSELECTED_NODE:
266             return {
267                 ...state,
268                 selectedNode: nodeFilters.ALL
269             };
270         default:
271             return state;
272     }
273 };