blob: 92ec60b999f60bea200a62f4c206535fa3d0a810 [file] [log] [blame]
talig8e9c0652017-12-20 14:30:43 +02001/*!
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 */
16import {actionTypes, rules, dataRules, SyncStates} from './MergeEditorConstants.js';
17import cloneDeep from 'lodash/cloneDeep.js';
18import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
19import Configuration from 'sdc-app/config/Configuration.js';
20import ItemsHelper from '../../common/helpers/ItemsHelper.js';
21import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
22import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
23import i18n from 'nfvo-utils/i18n/i18n.js';
24import {optionsInputValues as epOptionsValues} from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js';
25import {optionsInputValues as laOptionsValues} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
26import {optionsInputValues as processOptionValues} from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
27import {selectValues as limitSelectValues} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
28import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
29import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
30import moment from 'moment';
31import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
32import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
33
34function softwareProductCategoriesUrl() {
ilanap785dc1e2018-01-08 15:50:18 +020035 const restCatalogPrefix = Configuration.get('restCatalogPrefix');
36 return `${restCatalogPrefix}/v1/categories/resources/`;
talig8e9c0652017-12-20 14:30:43 +020037}
38
39function versionUrl(itemId, versionId) {
40 const restPrefix = Configuration.get('restPrefix');
41 return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
42}
43
44function baseUrl(itemId, version, conflictId) {
45 const versionId = version.id;
46 const restPrefix = Configuration.get('restPrefix');
47 let baseUrl = `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}/conflicts`;
48 return conflictId ? `${baseUrl}/${conflictId}` : baseUrl;
49}
50
51function fetchConflicts({itemId, version}) {
52 return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
53}
54
55function fetchConflictById({itemId, version, cid}) {
56 return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
57}
58
59function resolveConflict({itemId, version, conflictId, resolution}) {
60 return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {resolution});
61}
62
63function fetchCategories() {
64 return RestAPIUtil.fetch(softwareProductCategoriesUrl());
65}
66
67function fetchVersion({vendorId, licensingVersion}) {
68 return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
69}
70
71function createCategoryStr(data, {categories}) {
72
73 let {category, subCategory} = data;
74 let foundCat = categories.find(element => element.uniqueId === category);
75 if (!foundCat) { return ''; }
76
77 let catName = foundCat.name;
78 let foundSub = foundCat.subcategories.find(element => element.uniqueId === subCategory);
79 if (!foundSub) { return `${catName}`; }
80
81 let subcatName = foundSub.name;
82 return `${catName} - ${subcatName}`;
83
84}
85
86function getEnumValues({enums, list}) {
87
88 if (!list) { return ''; }
89 return list.map(item => enums.find(el => el.enum === item).title);
90
91}
92
93const MergeEditorActionHelper = {
94
95 analyzeSyncResult(dispatch, {itemId, version}) {
96 return ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id}).then((response) => {
97 let inMerge = response && response.state && response.state.synchronizationState === SyncStates.MERGE;
98 if (inMerge) {
99 MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(() =>
100 dispatch({
101 type: modalActionTypes.GLOBAL_MODAL_SHOW,
102 data: {
103 modalComponentName: modalContentMapper.MERGE_EDITOR,
104 modalClassName: 'merge-editor-modal',
105 title: `${i18n('Merge Required')} - ${version.description}`,
106 onDeclined: () => {
107 dispatch({
108 type: modalActionTypes.GLOBAL_MODAL_CLOSE
109 });
110 },
111 modalComponentProps: {
112 size: 'lg',
113 type: 'default'
114 }
115 }
116 })
117 );
118 }
119 return Promise.resolve({updatedVersion: response, inMerge, isDirty: response.state.dirty});
120 });
121 },
122
123 fetchConflicts(dispatch, {itemId, version}) {
124 return fetchConflicts({itemId, version}).then(
125 (data) => {
126 dispatch({
127 type: actionTypes.LOAD_CONFLICTS,
128 data
129 });
130 return data;
131 }
132 );
133 },
134
135 fetchConflict(dispatch, {itemId, version, cid}) {
136 fetchConflictById({itemId, version, cid}).then(
137 (data) => {
138 let newData = {};
139 newData = MergeEditorActionHelper.processConflict(dispatch, {conflict: data, itemId, cid, version});
140 dispatch({
141 type: actionTypes.LOAD_CONFLICT,
142 data: newData
143 });
144 }
145 );
146 },
147
148 resolveConflict(dispatch, {itemId, version, conflictId, resolution, currentScreen}) {
149 resolveConflict({itemId, version, conflictId, resolution}).then(() => {
150 MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(conflicts => {
151 if(conflicts.conflictInfoList && conflicts.conflictInfoList.length === 0) {
152 dispatch({
153 type: modalActionTypes.GLOBAL_MODAL_CLOSE
154 });
155 ScreensHelper.loadLandingScreen(dispatch, {previousScreenName: currentScreen.screen, props: currentScreen.props});
156 ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id});
157 }
158 });
159 });
160 },
161
162 createConflictObject(data, {cid, conflict, dispatch, itemId, version, isYours}) {
163
164 let newData = {};
165
166 for (let key in data) {
167
168 if (data.hasOwnProperty(key)) {
169 let value = data[key];
170 let fieldRule = dataRules[conflict.type] && dataRules[conflict.type][key] || dataRules.general[key];
171
172 if (fieldRule) {
173 switch (fieldRule.rule) {
174
175 case rules.SKIP:
176 break;
177
178 case rules.BOOLEAN:
179 let {trueValue, falseValue} = fieldRule;
180 newData[key] = value === trueValue ? true : value === falseValue ? false : undefined;
181 break;
182
183 case rules.PARSE:
184 let {moveFields, subFields} = fieldRule;
185 if (moveFields) {
186 let fields = subFields || Object.keys(value);
187 fields.forEach(field => {
188 newData[field] = MergeEditorActionHelper.createConflictObject(
189 value[field], {cid, conflict, dispatch, itemId, version, isYours}
190 );
191 });
192 } else {
193 newData[key] = MergeEditorActionHelper.createConflictObject(
194 value, {cid, conflict, dispatch, itemId, version, isYours}
195 );
196 }
197 break;
198
199 case rules.FUNCTION:
200 let {args, functionName} = fieldRule;
201 newData[key] = MergeEditorActionHelper[functionName](data, {
202 cid, conflict, dispatch, version, fieldName: key, isYours, itemId, args
203 });
204 break;
205
206 default:
207 newData[key] = value;
208 break;
209 }
210
211 } else {
212 newData[key] = value;
213
214 }
215 }
216 }
217
218 return newData;
219
220 },
221
222 getNamesFromIDs(data, {version, cid, dispatch, itemId, fieldName, isYours, args}) {
223
224 let idList = data[fieldName] || [];
225 let {fetchFunction, fetchField} = args;
226
227 let promises = idList.map(id =>
228 new Promise(resolve =>
229 MergeEditorActionHelper[fetchFunction](
230 dispatch, {licenseModelId: itemId, [fetchField]: id, version}
231 ).then(item => resolve(item.name))
232 )
233 );
234
235 Promise.all(promises).then(fetchedItems => {
236 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
237 dispatch({
238 type: actionTypes.DATA_PROCESSED,
239 data: {
240 cid,
241 [yoursOrTheirs]: { name: fieldName, value: fetchedItems }
242 }
243 });
244 });
245
246 return idList;
247
248 },
249
250 getFeatureGroups(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
251
252 let featureGroups = data[fieldName] || [];
253 if (!(featureGroups instanceof Array)) {
254 featureGroups = [featureGroups];
255 }
256
257 let promises = featureGroups.map(featureGroupId =>
258 new Promise(resolve =>
259 FeatureGroupsActionHelper.fetchFeatureGroup(
260 dispatch, {licenseModelId: itemId, featureGroupId, version}
261 ).then(featureGroup => resolve(featureGroup.name))
262 .catch(reason => console.log(`getFeatureGroups Promise rejected ('${reason}')`))
263 )
264 );
265
266 Promise.all(promises).then(fetchedGroups => {
267 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
268 dispatch({
269 type: actionTypes.DATA_PROCESSED,
270 data: {
271 cid,
272 [yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
273 }
274 });
275 });
276
277 return featureGroups;
278
279 },
280
281 getLicenseAgreements(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
282
283 let licenseAgreements = data[fieldName] || [];
284 if (!(licenseAgreements instanceof Array)) {
285 licenseAgreements = [licenseAgreements];
286 }
287
288 let promises = licenseAgreements.map(licenseAgreementId =>
289 new Promise(resolve =>
290 LicenseAgreementActionHelper.fetchLicenseAgreement(
291 dispatch, {licenseModelId: itemId, licenseAgreementId, version}
292 ).then(licenseAgreement => resolve(licenseAgreement.name))
293 .catch(reason => console.log(`getLicenseAgreements Promise rejected ('${reason}')`))
294 )
295 );
296
297 Promise.all(promises).then(fetchedAgreements => {
298 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
299 dispatch({
300 type: actionTypes.DATA_PROCESSED,
301 data: {
302 cid,
303 [yoursOrTheirs]: { name: fieldName, value: fetchedAgreements }
304 }
305 });
306 });
307
308 return licenseAgreements;
309
310 },
311
312 processConflict(dispatch, {conflict, cid, version, itemId,}) {
313
314 let {id, type, yours, theirs} = conflict;
315
316 let newYours = MergeEditorActionHelper.createConflictObject(
317 cloneDeep(yours), {cid, conflict, dispatch, itemId, version, isYours: true}
318 );
319 let newTheirs = MergeEditorActionHelper.createConflictObject(
320 cloneDeep(theirs), {cid, conflict, dispatch, itemId, version, isYours: false}
321 );
322
323 return {
324 id,
325 type,
326 yours: newYours,
327 theirs: newTheirs
328 };
329
330 },
331
332 reduceList(data, {fieldName, args}) {
333
334 let {subField} = args;
335 return data[fieldName].map(el => el[subField]);
336
337 },
338
339 getEnumList({fieldName}) {
340
341 const enumLists = {
342 'licenseTerm': laOptionsValues.LICENSE_MODEL_TYPE,
343 'operationalScope': epOptionsValues.OPERATIONAL_SCOPE,
344 'processType': processOptionValues.PROCESS_TYPE,
345 'limitType': [
346 {title: 'Service Provider', enum: 'ServiceProvider'},
347 {title: 'Vendor', enum: 'Vendor'}
348 ],
349 'limitUnit': limitSelectValues.UNIT
350 };
351
352 return enumLists[fieldName];
353
354 },
355
356 getEnumValue(data, {fieldName, args = {}}) {
357
358 let value = data[fieldName];
359 let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
360 let enumValue = enumValues.find(el => el.enum === value);
361
362 return enumValue && enumValue.title || value;
363
364 },
365
366 processChoice(data, {fieldName, args = {}}) {
367
368 let value = data[fieldName];
369 let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
370 let newValue = value.other || enumValues && enumValues.find(el => el.enum === value.choice).title || value.choice;
371
372 return newValue;
373
374 },
375
376 processChoices(data, {fieldName, args = {}}) {
377
378 let value = data[fieldName];
379 let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
380 let newValue = value.other || getEnumValues({enums: enumValues, list: value.choices}) || value.choices;
381
382 return newValue;
383
384 },
385
386 convertArrayToObject(data, {fieldName}) {
387 let value = data[fieldName];
388 let newValue = {};
389 value.forEach((el, index) => {
390 newValue[index] = el;
391 });
392 return newValue;
393 },
394
395 fetchCategory(data, {cid, isYours, fieldName, dispatch}) {
396
397 fetchCategories().then((categories) => {
398 let value = createCategoryStr(data, {categories});
399 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
400
401 dispatch({
402 type: actionTypes.DATA_PROCESSED,
403 data: {
404 cid,
405 [yoursOrTheirs]: { name: fieldName, value }
406 }
407 });
408
409 });
410 },
411
412 fetchLMVersion(data, {cid, dispatch, isYours}) {
413
414 let {licensingVersion, vendorId} = data;
415 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
416
417 if (licensingVersion) {
418 fetchVersion({licensingVersion, vendorId}).then(response => {
419 dispatch({
420 type: actionTypes.DATA_PROCESSED,
421 data: {
422 cid,
423 [yoursOrTheirs]: {
424 name: 'licensingVersion',
425 value: response.name
426 }
427 }
428 });
429 });
430 }
431
432 },
433
434 parseDate(data, {fieldName}) {
435
436 let date = data[fieldName];
437 return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
438
439 }
440
441};
442
443export default MergeEditorActionHelper;