blob: 50d2a5ba9324d33ff010922f7587137889ae638b [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 */
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020016import {
17 actionTypes,
18 rules,
19 dataRules,
20 SyncStates
21} from './MergeEditorConstants.js';
talig8e9c0652017-12-20 14:30:43 +020022import cloneDeep from 'lodash/cloneDeep.js';
23import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
24import Configuration from 'sdc-app/config/Configuration.js';
25import ItemsHelper from '../../common/helpers/ItemsHelper.js';
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020026import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
27import { actionTypes as modalActionTypes } from 'nfvo-components/modal/GlobalModalConstants.js';
talig8e9c0652017-12-20 14:30:43 +020028import i18n from 'nfvo-utils/i18n/i18n.js';
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020029import { optionsInputValues as laOptionsValues } from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
30import { optionsInputValues as processOptionValues } from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
31import { selectValues as limitSelectValues } from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
talig8e9c0652017-12-20 14:30:43 +020032import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
33import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
34import moment from 'moment';
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020035import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
talig8e9c0652017-12-20 14:30:43 +020036import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
37
38function softwareProductCategoriesUrl() {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020039 const restCatalogPrefix = Configuration.get('restCatalogPrefix');
40 return `${restCatalogPrefix}/v1/categories/resources/`;
talig8e9c0652017-12-20 14:30:43 +020041}
42
43function versionUrl(itemId, versionId) {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020044 const restPrefix = Configuration.get('restPrefix');
45 return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
talig8e9c0652017-12-20 14:30:43 +020046}
47
48function baseUrl(itemId, version, conflictId) {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020049 const versionId = version.id;
50 const restPrefix = Configuration.get('restPrefix');
51 let baseUrl = `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}/conflicts`;
52 return conflictId ? `${baseUrl}/${conflictId}` : baseUrl;
talig8e9c0652017-12-20 14:30:43 +020053}
54
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020055function fetchConflicts({ itemId, version }) {
56 return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
talig8e9c0652017-12-20 14:30:43 +020057}
58
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020059function fetchConflictById({ itemId, version, cid }) {
60 return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
talig8e9c0652017-12-20 14:30:43 +020061}
62
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020063function resolveConflict({ itemId, version, conflictId, resolution }) {
64 return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {
65 resolution
66 });
talig8e9c0652017-12-20 14:30:43 +020067}
68
69function fetchCategories() {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020070 return RestAPIUtil.fetch(softwareProductCategoriesUrl());
talig8e9c0652017-12-20 14:30:43 +020071}
72
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020073function fetchVersion({ vendorId, licensingVersion }) {
74 return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
talig8e9c0652017-12-20 14:30:43 +020075}
76
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020077function createCategoryStr(data, { categories }) {
78 let { category, subCategory } = data;
79 let foundCat = categories.find(element => element.uniqueId === category);
80 if (!foundCat) {
81 return '';
82 }
talig8e9c0652017-12-20 14:30:43 +020083
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020084 let catName = foundCat.name;
85 let foundSub = foundCat.subcategories.find(
86 element => element.uniqueId === subCategory
87 );
88 if (!foundSub) {
89 return `${catName}`;
90 }
talig8e9c0652017-12-20 14:30:43 +020091
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020092 let subcatName = foundSub.name;
93 return `${catName} - ${subcatName}`;
talig8e9c0652017-12-20 14:30:43 +020094}
95
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020096function getEnumValues({ enums, list }) {
97 if (!list) {
98 return '';
99 }
100 return list.map(item => enums.find(el => el.enum === item).title);
talig8e9c0652017-12-20 14:30:43 +0200101}
102
103const MergeEditorActionHelper = {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200104 analyzeSyncResult(dispatch, { itemId, version }) {
105 return ItemsHelper.checkItemStatus(dispatch, {
106 itemId,
107 versionId: version.id
108 }).then(response => {
109 let inMerge =
110 response &&
111 response.state &&
112 response.state.synchronizationState === SyncStates.MERGE;
113 if (inMerge) {
114 MergeEditorActionHelper.fetchConflicts(dispatch, {
115 itemId,
116 version
117 }).then(() =>
118 dispatch({
119 type: modalActionTypes.GLOBAL_MODAL_SHOW,
120 data: {
121 modalComponentName: modalContentMapper.MERGE_EDITOR,
122 modalClassName: 'merge-editor-modal',
123 title: `${i18n('Merge Required')} - ${
124 version.description
125 }`,
126 onDeclined: () => {
127 dispatch({
128 type: modalActionTypes.GLOBAL_MODAL_CLOSE
129 });
130 },
131 modalComponentProps: {
132 size: 'lg',
133 type: 'default'
134 }
135 }
136 })
137 );
138 }
139 return Promise.resolve({
140 updatedVersion: response,
141 inMerge,
142 isDirty: response.state.dirty
143 });
144 });
145 },
talig8e9c0652017-12-20 14:30:43 +0200146
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200147 fetchConflicts(dispatch, { itemId, version }) {
148 return fetchConflicts({ itemId, version }).then(data => {
149 dispatch({
150 type: actionTypes.LOAD_CONFLICTS,
151 data
152 });
153 return data;
154 });
155 },
talig8e9c0652017-12-20 14:30:43 +0200156
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200157 fetchConflict(dispatch, { itemId, version, cid }) {
158 fetchConflictById({ itemId, version, cid }).then(data => {
159 let newData = {};
160 newData = MergeEditorActionHelper.processConflict(dispatch, {
161 conflict: data,
162 itemId,
163 cid,
164 version
165 });
166 dispatch({
167 type: actionTypes.LOAD_CONFLICT,
168 data: newData
169 });
170 });
171 },
talig8e9c0652017-12-20 14:30:43 +0200172
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200173 resolveConflict(
174 dispatch,
175 { itemId, version, conflictId, resolution, currentScreen }
176 ) {
177 resolveConflict({ itemId, version, conflictId, resolution }).then(
178 () => {
179 MergeEditorActionHelper.fetchConflicts(dispatch, {
180 itemId,
181 version
182 }).then(conflicts => {
183 if (
184 conflicts.conflictInfoList &&
185 conflicts.conflictInfoList.length === 0
186 ) {
187 dispatch({
188 type: modalActionTypes.GLOBAL_MODAL_CLOSE
189 });
190 ScreensHelper.loadLandingScreen(dispatch, {
191 previousScreenName: currentScreen.screen,
192 props: currentScreen.props
193 });
194 ItemsHelper.checkItemStatus(dispatch, {
195 itemId,
196 versionId: version.id
197 });
198 }
199 });
200 }
201 );
202 },
talig8e9c0652017-12-20 14:30:43 +0200203
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200204 createConflictObject(
205 data,
206 { cid, conflict, dispatch, itemId, version, isYours }
207 ) {
208 let newData = {};
talig8e9c0652017-12-20 14:30:43 +0200209
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200210 for (let key in data) {
211 if (data.hasOwnProperty(key)) {
212 let value = data[key];
213 let fieldRule =
214 (dataRules[conflict.type] &&
215 dataRules[conflict.type][key]) ||
216 dataRules.general[key];
talig8e9c0652017-12-20 14:30:43 +0200217
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200218 if (fieldRule) {
219 switch (fieldRule.rule) {
220 case rules.SKIP:
221 break;
talig8e9c0652017-12-20 14:30:43 +0200222
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200223 case rules.BOOLEAN:
224 let { trueValue, falseValue } = fieldRule;
225 newData[key] =
226 value === trueValue
227 ? true
228 : value === falseValue ? false : undefined;
229 break;
talig8e9c0652017-12-20 14:30:43 +0200230
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200231 case rules.PARSE:
232 let { moveFields, subFields } = fieldRule;
233 if (moveFields) {
234 let fields = subFields || Object.keys(value);
235 fields.forEach(field => {
236 newData[
237 field
238 ] = MergeEditorActionHelper.createConflictObject(
239 value[field],
240 {
241 cid,
242 conflict,
243 dispatch,
244 itemId,
245 version,
246 isYours
247 }
248 );
249 });
250 } else {
251 newData[
252 key
253 ] = MergeEditorActionHelper.createConflictObject(
254 value,
255 {
256 cid,
257 conflict,
258 dispatch,
259 itemId,
260 version,
261 isYours
262 }
263 );
264 }
265 break;
talig8e9c0652017-12-20 14:30:43 +0200266
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200267 case rules.FUNCTION:
268 let { args, functionName } = fieldRule;
269 newData[key] = MergeEditorActionHelper[
270 functionName
271 ](data, {
272 cid,
273 conflict,
274 dispatch,
275 version,
276 fieldName: key,
277 isYours,
278 itemId,
279 args
280 });
281 break;
talig8e9c0652017-12-20 14:30:43 +0200282
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200283 default:
284 newData[key] = value;
285 break;
286 }
287 } else {
288 newData[key] = value;
289 }
290 }
291 }
talig8e9c0652017-12-20 14:30:43 +0200292
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200293 return newData;
294 },
talig8e9c0652017-12-20 14:30:43 +0200295
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200296 getNamesFromIDs(
297 data,
298 { version, cid, dispatch, itemId, fieldName, isYours, args }
299 ) {
300 let idList = data[fieldName] || [];
301 let { fetchFunction, fetchField } = args;
talig8e9c0652017-12-20 14:30:43 +0200302
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200303 let promises = idList.map(
304 id =>
305 new Promise(resolve =>
306 MergeEditorActionHelper[fetchFunction](dispatch, {
307 licenseModelId: itemId,
308 [fetchField]: id,
309 version
310 }).then(item => resolve(item.name))
311 )
312 );
talig8e9c0652017-12-20 14:30:43 +0200313
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200314 Promise.all(promises).then(fetchedItems => {
315 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
316 dispatch({
317 type: actionTypes.DATA_PROCESSED,
318 data: {
319 cid,
320 [yoursOrTheirs]: { name: fieldName, value: fetchedItems }
321 }
322 });
323 });
talig8e9c0652017-12-20 14:30:43 +0200324
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200325 return idList;
326 },
talig8e9c0652017-12-20 14:30:43 +0200327
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200328 getFeatureGroups(
329 data,
330 { version, cid, dispatch, itemId, fieldName, isYours }
331 ) {
332 let featureGroups = data[fieldName] || [];
333 if (!(featureGroups instanceof Array)) {
334 featureGroups = [featureGroups];
335 }
talig8e9c0652017-12-20 14:30:43 +0200336
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200337 let promises = featureGroups.map(
338 featureGroupId =>
339 new Promise(resolve =>
340 FeatureGroupsActionHelper.fetchFeatureGroup(dispatch, {
341 licenseModelId: itemId,
342 featureGroupId,
343 version
344 })
345 .then(featureGroup => resolve(featureGroup.name))
346 .catch(reason =>
347 console.log(
348 `getFeatureGroups Promise rejected ('${reason}')`
349 )
350 )
351 )
352 );
talig8e9c0652017-12-20 14:30:43 +0200353
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200354 Promise.all(promises).then(fetchedGroups => {
355 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
356 dispatch({
357 type: actionTypes.DATA_PROCESSED,
358 data: {
359 cid,
360 [yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
361 }
362 });
363 });
talig8e9c0652017-12-20 14:30:43 +0200364
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200365 return featureGroups;
366 },
talig8e9c0652017-12-20 14:30:43 +0200367
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200368 getLicenseAgreements(
369 data,
370 { version, cid, dispatch, itemId, fieldName, isYours }
371 ) {
372 let licenseAgreements = data[fieldName] || [];
373 if (!(licenseAgreements instanceof Array)) {
374 licenseAgreements = [licenseAgreements];
375 }
talig8e9c0652017-12-20 14:30:43 +0200376
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200377 let promises = licenseAgreements.map(
378 licenseAgreementId =>
379 new Promise(resolve =>
380 LicenseAgreementActionHelper.fetchLicenseAgreement(
381 dispatch,
382 {
383 licenseModelId: itemId,
384 licenseAgreementId,
385 version
386 }
387 )
388 .then(licenseAgreement =>
389 resolve(licenseAgreement.name)
390 )
391 .catch(reason =>
392 console.log(
393 `getLicenseAgreements Promise rejected ('${reason}')`
394 )
395 )
396 )
397 );
talig8e9c0652017-12-20 14:30:43 +0200398
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200399 Promise.all(promises).then(fetchedAgreements => {
400 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
401 dispatch({
402 type: actionTypes.DATA_PROCESSED,
403 data: {
404 cid,
405 [yoursOrTheirs]: {
406 name: fieldName,
407 value: fetchedAgreements
408 }
409 }
410 });
411 });
talig8e9c0652017-12-20 14:30:43 +0200412
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200413 return licenseAgreements;
414 },
talig8e9c0652017-12-20 14:30:43 +0200415
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200416 processConflict(dispatch, { conflict, cid, version, itemId }) {
417 let { id, type, yours, theirs } = conflict;
talig8e9c0652017-12-20 14:30:43 +0200418
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200419 let newYours = MergeEditorActionHelper.createConflictObject(
420 cloneDeep(yours),
421 { cid, conflict, dispatch, itemId, version, isYours: true }
422 );
423 let newTheirs = MergeEditorActionHelper.createConflictObject(
424 cloneDeep(theirs),
425 { cid, conflict, dispatch, itemId, version, isYours: false }
426 );
talig8e9c0652017-12-20 14:30:43 +0200427
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200428 return {
429 id,
430 type,
431 yours: newYours,
432 theirs: newTheirs
433 };
434 },
talig8e9c0652017-12-20 14:30:43 +0200435
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200436 reduceList(data, { fieldName, args }) {
437 let { subField } = args;
438 return data[fieldName].map(el => el[subField]);
439 },
talig8e9c0652017-12-20 14:30:43 +0200440
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200441 getEnumList({ fieldName }) {
442 const enumLists = {
443 licenseTerm: laOptionsValues.LICENSE_MODEL_TYPE,
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200444 processType: processOptionValues.PROCESS_TYPE,
445 limitType: [
446 { title: 'Service Provider', enum: 'ServiceProvider' },
447 { title: 'Vendor', enum: 'Vendor' }
448 ],
449 limitUnit: limitSelectValues.UNIT
450 };
talig8e9c0652017-12-20 14:30:43 +0200451
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200452 return enumLists[fieldName];
453 },
talig8e9c0652017-12-20 14:30:43 +0200454
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200455 getEnumValue(data, { fieldName, args = {} }) {
456 let value = data[fieldName];
457 let enumValues = MergeEditorActionHelper.getEnumList({
458 fieldName: args.listName || fieldName
459 });
460 let enumValue = enumValues.find(el => el.enum === value);
talig8e9c0652017-12-20 14:30:43 +0200461
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200462 return (enumValue && enumValue.title) || value;
463 },
talig8e9c0652017-12-20 14:30:43 +0200464
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200465 processChoice(data, { fieldName, args = {} }) {
466 let value = data[fieldName];
467 let enumValues = MergeEditorActionHelper.getEnumList({
468 fieldName: args.listName || fieldName
469 });
470 let newValue =
471 value.other ||
472 (enumValues &&
473 enumValues.find(el => el.enum === value.choice).title) ||
474 value.choice;
talig8e9c0652017-12-20 14:30:43 +0200475
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200476 return newValue;
477 },
talig8e9c0652017-12-20 14:30:43 +0200478
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200479 processChoices(data, { fieldName, args = {} }) {
480 let value = data[fieldName];
481 let enumValues = MergeEditorActionHelper.getEnumList({
482 fieldName: args.listName || fieldName
483 });
484 let newValue =
485 value.other ||
486 getEnumValues({ enums: enumValues, list: value.choices }) ||
487 value.choices;
talig8e9c0652017-12-20 14:30:43 +0200488
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200489 return newValue;
490 },
talig8e9c0652017-12-20 14:30:43 +0200491
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200492 convertArrayToObject(data, { fieldName }) {
493 let value = data[fieldName];
494 let newValue = {};
495 value.forEach((el, index) => {
496 newValue[index] = el;
497 });
498 return newValue;
499 },
talig8e9c0652017-12-20 14:30:43 +0200500
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200501 fetchCategory(data, { cid, isYours, fieldName, dispatch }) {
502 fetchCategories().then(categories => {
503 let value = createCategoryStr(data, { categories });
504 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
talig8e9c0652017-12-20 14:30:43 +0200505
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200506 dispatch({
507 type: actionTypes.DATA_PROCESSED,
508 data: {
509 cid,
510 [yoursOrTheirs]: { name: fieldName, value }
511 }
512 });
513 });
514 },
talig8e9c0652017-12-20 14:30:43 +0200515
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200516 fetchLMVersion(data, { cid, dispatch, isYours }) {
517 let { licensingVersion, vendorId } = data;
518 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
talig8e9c0652017-12-20 14:30:43 +0200519
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200520 if (licensingVersion) {
521 fetchVersion({ licensingVersion, vendorId }).then(response => {
522 dispatch({
523 type: actionTypes.DATA_PROCESSED,
524 data: {
525 cid,
526 [yoursOrTheirs]: {
527 name: 'licensingVersion',
528 value: response.name
529 }
530 }
531 });
532 });
533 }
534 },
talig8e9c0652017-12-20 14:30:43 +0200535
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200536 parseDate(data, { fieldName }) {
537 let date = data[fieldName];
538 return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
539 }
talig8e9c0652017-12-20 14:30:43 +0200540};
541
542export default MergeEditorActionHelper;