blob: c54b9feb93056e18e3c87464fc38560afd0c8693 [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 epOptionsValues } from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js';
30import { optionsInputValues as laOptionsValues } from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
31import { optionsInputValues as processOptionValues } from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
32import { selectValues as limitSelectValues } from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
talig8e9c0652017-12-20 14:30:43 +020033import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
34import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
35import moment from 'moment';
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020036import { DATE_FORMAT } from 'sdc-app/onboarding/OnboardingConstants.js';
talig8e9c0652017-12-20 14:30:43 +020037import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
38
39function softwareProductCategoriesUrl() {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020040 const restCatalogPrefix = Configuration.get('restCatalogPrefix');
41 return `${restCatalogPrefix}/v1/categories/resources/`;
talig8e9c0652017-12-20 14:30:43 +020042}
43
44function versionUrl(itemId, versionId) {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020045 const restPrefix = Configuration.get('restPrefix');
46 return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
talig8e9c0652017-12-20 14:30:43 +020047}
48
49function baseUrl(itemId, version, conflictId) {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020050 const versionId = version.id;
51 const restPrefix = Configuration.get('restPrefix');
52 let baseUrl = `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}/conflicts`;
53 return conflictId ? `${baseUrl}/${conflictId}` : baseUrl;
talig8e9c0652017-12-20 14:30:43 +020054}
55
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020056function fetchConflicts({ itemId, version }) {
57 return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
talig8e9c0652017-12-20 14:30:43 +020058}
59
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020060function fetchConflictById({ itemId, version, cid }) {
61 return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
talig8e9c0652017-12-20 14:30:43 +020062}
63
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020064function resolveConflict({ itemId, version, conflictId, resolution }) {
65 return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {
66 resolution
67 });
talig8e9c0652017-12-20 14:30:43 +020068}
69
70function fetchCategories() {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020071 return RestAPIUtil.fetch(softwareProductCategoriesUrl());
talig8e9c0652017-12-20 14:30:43 +020072}
73
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020074function fetchVersion({ vendorId, licensingVersion }) {
75 return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
talig8e9c0652017-12-20 14:30:43 +020076}
77
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020078function createCategoryStr(data, { categories }) {
79 let { category, subCategory } = data;
80 let foundCat = categories.find(element => element.uniqueId === category);
81 if (!foundCat) {
82 return '';
83 }
talig8e9c0652017-12-20 14:30:43 +020084
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020085 let catName = foundCat.name;
86 let foundSub = foundCat.subcategories.find(
87 element => element.uniqueId === subCategory
88 );
89 if (!foundSub) {
90 return `${catName}`;
91 }
talig8e9c0652017-12-20 14:30:43 +020092
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020093 let subcatName = foundSub.name;
94 return `${catName} - ${subcatName}`;
talig8e9c0652017-12-20 14:30:43 +020095}
96
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +020097function getEnumValues({ enums, list }) {
98 if (!list) {
99 return '';
100 }
101 return list.map(item => enums.find(el => el.enum === item).title);
talig8e9c0652017-12-20 14:30:43 +0200102}
103
104const MergeEditorActionHelper = {
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200105 analyzeSyncResult(dispatch, { itemId, version }) {
106 return ItemsHelper.checkItemStatus(dispatch, {
107 itemId,
108 versionId: version.id
109 }).then(response => {
110 let inMerge =
111 response &&
112 response.state &&
113 response.state.synchronizationState === SyncStates.MERGE;
114 if (inMerge) {
115 MergeEditorActionHelper.fetchConflicts(dispatch, {
116 itemId,
117 version
118 }).then(() =>
119 dispatch({
120 type: modalActionTypes.GLOBAL_MODAL_SHOW,
121 data: {
122 modalComponentName: modalContentMapper.MERGE_EDITOR,
123 modalClassName: 'merge-editor-modal',
124 title: `${i18n('Merge Required')} - ${
125 version.description
126 }`,
127 onDeclined: () => {
128 dispatch({
129 type: modalActionTypes.GLOBAL_MODAL_CLOSE
130 });
131 },
132 modalComponentProps: {
133 size: 'lg',
134 type: 'default'
135 }
136 }
137 })
138 );
139 }
140 return Promise.resolve({
141 updatedVersion: response,
142 inMerge,
143 isDirty: response.state.dirty
144 });
145 });
146 },
talig8e9c0652017-12-20 14:30:43 +0200147
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200148 fetchConflicts(dispatch, { itemId, version }) {
149 return fetchConflicts({ itemId, version }).then(data => {
150 dispatch({
151 type: actionTypes.LOAD_CONFLICTS,
152 data
153 });
154 return data;
155 });
156 },
talig8e9c0652017-12-20 14:30:43 +0200157
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200158 fetchConflict(dispatch, { itemId, version, cid }) {
159 fetchConflictById({ itemId, version, cid }).then(data => {
160 let newData = {};
161 newData = MergeEditorActionHelper.processConflict(dispatch, {
162 conflict: data,
163 itemId,
164 cid,
165 version
166 });
167 dispatch({
168 type: actionTypes.LOAD_CONFLICT,
169 data: newData
170 });
171 });
172 },
talig8e9c0652017-12-20 14:30:43 +0200173
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200174 resolveConflict(
175 dispatch,
176 { itemId, version, conflictId, resolution, currentScreen }
177 ) {
178 resolveConflict({ itemId, version, conflictId, resolution }).then(
179 () => {
180 MergeEditorActionHelper.fetchConflicts(dispatch, {
181 itemId,
182 version
183 }).then(conflicts => {
184 if (
185 conflicts.conflictInfoList &&
186 conflicts.conflictInfoList.length === 0
187 ) {
188 dispatch({
189 type: modalActionTypes.GLOBAL_MODAL_CLOSE
190 });
191 ScreensHelper.loadLandingScreen(dispatch, {
192 previousScreenName: currentScreen.screen,
193 props: currentScreen.props
194 });
195 ItemsHelper.checkItemStatus(dispatch, {
196 itemId,
197 versionId: version.id
198 });
199 }
200 });
201 }
202 );
203 },
talig8e9c0652017-12-20 14:30:43 +0200204
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200205 createConflictObject(
206 data,
207 { cid, conflict, dispatch, itemId, version, isYours }
208 ) {
209 let newData = {};
talig8e9c0652017-12-20 14:30:43 +0200210
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200211 for (let key in data) {
212 if (data.hasOwnProperty(key)) {
213 let value = data[key];
214 let fieldRule =
215 (dataRules[conflict.type] &&
216 dataRules[conflict.type][key]) ||
217 dataRules.general[key];
talig8e9c0652017-12-20 14:30:43 +0200218
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200219 if (fieldRule) {
220 switch (fieldRule.rule) {
221 case rules.SKIP:
222 break;
talig8e9c0652017-12-20 14:30:43 +0200223
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200224 case rules.BOOLEAN:
225 let { trueValue, falseValue } = fieldRule;
226 newData[key] =
227 value === trueValue
228 ? true
229 : value === falseValue ? false : undefined;
230 break;
talig8e9c0652017-12-20 14:30:43 +0200231
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200232 case rules.PARSE:
233 let { moveFields, subFields } = fieldRule;
234 if (moveFields) {
235 let fields = subFields || Object.keys(value);
236 fields.forEach(field => {
237 newData[
238 field
239 ] = MergeEditorActionHelper.createConflictObject(
240 value[field],
241 {
242 cid,
243 conflict,
244 dispatch,
245 itemId,
246 version,
247 isYours
248 }
249 );
250 });
251 } else {
252 newData[
253 key
254 ] = MergeEditorActionHelper.createConflictObject(
255 value,
256 {
257 cid,
258 conflict,
259 dispatch,
260 itemId,
261 version,
262 isYours
263 }
264 );
265 }
266 break;
talig8e9c0652017-12-20 14:30:43 +0200267
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200268 case rules.FUNCTION:
269 let { args, functionName } = fieldRule;
270 newData[key] = MergeEditorActionHelper[
271 functionName
272 ](data, {
273 cid,
274 conflict,
275 dispatch,
276 version,
277 fieldName: key,
278 isYours,
279 itemId,
280 args
281 });
282 break;
talig8e9c0652017-12-20 14:30:43 +0200283
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200284 default:
285 newData[key] = value;
286 break;
287 }
288 } else {
289 newData[key] = value;
290 }
291 }
292 }
talig8e9c0652017-12-20 14:30:43 +0200293
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200294 return newData;
295 },
talig8e9c0652017-12-20 14:30:43 +0200296
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200297 getNamesFromIDs(
298 data,
299 { version, cid, dispatch, itemId, fieldName, isYours, args }
300 ) {
301 let idList = data[fieldName] || [];
302 let { fetchFunction, fetchField } = args;
talig8e9c0652017-12-20 14:30:43 +0200303
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200304 let promises = idList.map(
305 id =>
306 new Promise(resolve =>
307 MergeEditorActionHelper[fetchFunction](dispatch, {
308 licenseModelId: itemId,
309 [fetchField]: id,
310 version
311 }).then(item => resolve(item.name))
312 )
313 );
talig8e9c0652017-12-20 14:30:43 +0200314
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200315 Promise.all(promises).then(fetchedItems => {
316 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
317 dispatch({
318 type: actionTypes.DATA_PROCESSED,
319 data: {
320 cid,
321 [yoursOrTheirs]: { name: fieldName, value: fetchedItems }
322 }
323 });
324 });
talig8e9c0652017-12-20 14:30:43 +0200325
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200326 return idList;
327 },
talig8e9c0652017-12-20 14:30:43 +0200328
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200329 getFeatureGroups(
330 data,
331 { version, cid, dispatch, itemId, fieldName, isYours }
332 ) {
333 let featureGroups = data[fieldName] || [];
334 if (!(featureGroups instanceof Array)) {
335 featureGroups = [featureGroups];
336 }
talig8e9c0652017-12-20 14:30:43 +0200337
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200338 let promises = featureGroups.map(
339 featureGroupId =>
340 new Promise(resolve =>
341 FeatureGroupsActionHelper.fetchFeatureGroup(dispatch, {
342 licenseModelId: itemId,
343 featureGroupId,
344 version
345 })
346 .then(featureGroup => resolve(featureGroup.name))
347 .catch(reason =>
348 console.log(
349 `getFeatureGroups Promise rejected ('${reason}')`
350 )
351 )
352 )
353 );
talig8e9c0652017-12-20 14:30:43 +0200354
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200355 Promise.all(promises).then(fetchedGroups => {
356 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
357 dispatch({
358 type: actionTypes.DATA_PROCESSED,
359 data: {
360 cid,
361 [yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
362 }
363 });
364 });
talig8e9c0652017-12-20 14:30:43 +0200365
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200366 return featureGroups;
367 },
talig8e9c0652017-12-20 14:30:43 +0200368
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200369 getLicenseAgreements(
370 data,
371 { version, cid, dispatch, itemId, fieldName, isYours }
372 ) {
373 let licenseAgreements = data[fieldName] || [];
374 if (!(licenseAgreements instanceof Array)) {
375 licenseAgreements = [licenseAgreements];
376 }
talig8e9c0652017-12-20 14:30:43 +0200377
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200378 let promises = licenseAgreements.map(
379 licenseAgreementId =>
380 new Promise(resolve =>
381 LicenseAgreementActionHelper.fetchLicenseAgreement(
382 dispatch,
383 {
384 licenseModelId: itemId,
385 licenseAgreementId,
386 version
387 }
388 )
389 .then(licenseAgreement =>
390 resolve(licenseAgreement.name)
391 )
392 .catch(reason =>
393 console.log(
394 `getLicenseAgreements Promise rejected ('${reason}')`
395 )
396 )
397 )
398 );
talig8e9c0652017-12-20 14:30:43 +0200399
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200400 Promise.all(promises).then(fetchedAgreements => {
401 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
402 dispatch({
403 type: actionTypes.DATA_PROCESSED,
404 data: {
405 cid,
406 [yoursOrTheirs]: {
407 name: fieldName,
408 value: fetchedAgreements
409 }
410 }
411 });
412 });
talig8e9c0652017-12-20 14:30:43 +0200413
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200414 return licenseAgreements;
415 },
talig8e9c0652017-12-20 14:30:43 +0200416
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200417 processConflict(dispatch, { conflict, cid, version, itemId }) {
418 let { id, type, yours, theirs } = conflict;
talig8e9c0652017-12-20 14:30:43 +0200419
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200420 let newYours = MergeEditorActionHelper.createConflictObject(
421 cloneDeep(yours),
422 { cid, conflict, dispatch, itemId, version, isYours: true }
423 );
424 let newTheirs = MergeEditorActionHelper.createConflictObject(
425 cloneDeep(theirs),
426 { cid, conflict, dispatch, itemId, version, isYours: false }
427 );
talig8e9c0652017-12-20 14:30:43 +0200428
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200429 return {
430 id,
431 type,
432 yours: newYours,
433 theirs: newTheirs
434 };
435 },
talig8e9c0652017-12-20 14:30:43 +0200436
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200437 reduceList(data, { fieldName, args }) {
438 let { subField } = args;
439 return data[fieldName].map(el => el[subField]);
440 },
talig8e9c0652017-12-20 14:30:43 +0200441
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200442 getEnumList({ fieldName }) {
443 const enumLists = {
444 licenseTerm: laOptionsValues.LICENSE_MODEL_TYPE,
445 operationalScope: epOptionsValues.OPERATIONAL_SCOPE,
446 processType: processOptionValues.PROCESS_TYPE,
447 limitType: [
448 { title: 'Service Provider', enum: 'ServiceProvider' },
449 { title: 'Vendor', enum: 'Vendor' }
450 ],
451 limitUnit: limitSelectValues.UNIT
452 };
talig8e9c0652017-12-20 14:30:43 +0200453
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200454 return enumLists[fieldName];
455 },
talig8e9c0652017-12-20 14:30:43 +0200456
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200457 getEnumValue(data, { fieldName, args = {} }) {
458 let value = data[fieldName];
459 let enumValues = MergeEditorActionHelper.getEnumList({
460 fieldName: args.listName || fieldName
461 });
462 let enumValue = enumValues.find(el => el.enum === value);
talig8e9c0652017-12-20 14:30:43 +0200463
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200464 return (enumValue && enumValue.title) || value;
465 },
talig8e9c0652017-12-20 14:30:43 +0200466
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200467 processChoice(data, { fieldName, args = {} }) {
468 let value = data[fieldName];
469 let enumValues = MergeEditorActionHelper.getEnumList({
470 fieldName: args.listName || fieldName
471 });
472 let newValue =
473 value.other ||
474 (enumValues &&
475 enumValues.find(el => el.enum === value.choice).title) ||
476 value.choice;
talig8e9c0652017-12-20 14:30:43 +0200477
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200478 return newValue;
479 },
talig8e9c0652017-12-20 14:30:43 +0200480
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200481 processChoices(data, { fieldName, args = {} }) {
482 let value = data[fieldName];
483 let enumValues = MergeEditorActionHelper.getEnumList({
484 fieldName: args.listName || fieldName
485 });
486 let newValue =
487 value.other ||
488 getEnumValues({ enums: enumValues, list: value.choices }) ||
489 value.choices;
talig8e9c0652017-12-20 14:30:43 +0200490
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200491 return newValue;
492 },
talig8e9c0652017-12-20 14:30:43 +0200493
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200494 convertArrayToObject(data, { fieldName }) {
495 let value = data[fieldName];
496 let newValue = {};
497 value.forEach((el, index) => {
498 newValue[index] = el;
499 });
500 return newValue;
501 },
talig8e9c0652017-12-20 14:30:43 +0200502
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200503 fetchCategory(data, { cid, isYours, fieldName, dispatch }) {
504 fetchCategories().then(categories => {
505 let value = createCategoryStr(data, { categories });
506 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
talig8e9c0652017-12-20 14:30:43 +0200507
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200508 dispatch({
509 type: actionTypes.DATA_PROCESSED,
510 data: {
511 cid,
512 [yoursOrTheirs]: { name: fieldName, value }
513 }
514 });
515 });
516 },
talig8e9c0652017-12-20 14:30:43 +0200517
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200518 fetchLMVersion(data, { cid, dispatch, isYours }) {
519 let { licensingVersion, vendorId } = data;
520 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
talig8e9c0652017-12-20 14:30:43 +0200521
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200522 if (licensingVersion) {
523 fetchVersion({ licensingVersion, vendorId }).then(response => {
524 dispatch({
525 type: actionTypes.DATA_PROCESSED,
526 data: {
527 cid,
528 [yoursOrTheirs]: {
529 name: 'licensingVersion',
530 value: response.name
531 }
532 }
533 });
534 });
535 }
536 },
talig8e9c0652017-12-20 14:30:43 +0200537
Einav Weiss Keidar7fdf7332018-03-20 14:45:40 +0200538 parseDate(data, { fieldName }) {
539 let date = data[fieldName];
540 return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
541 }
talig8e9c0652017-12-20 14:30:43 +0200542};
543
544export default MergeEditorActionHelper;