2 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 import {actionTypes, rules, dataRules, SyncStates} from './MergeEditorConstants.js';
17 import cloneDeep from 'lodash/cloneDeep.js';
18 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
19 import Configuration from 'sdc-app/config/Configuration.js';
20 import ItemsHelper from '../../common/helpers/ItemsHelper.js';
21 import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
22 import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
23 import i18n from 'nfvo-utils/i18n/i18n.js';
24 import {optionsInputValues as epOptionsValues} from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js';
25 import {optionsInputValues as laOptionsValues} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
26 import {optionsInputValues as processOptionValues} from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
27 import {selectValues as limitSelectValues} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
28 import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
29 import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
30 import moment from 'moment';
31 import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
32 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
34 function softwareProductCategoriesUrl() {
35 const restATTPrefix = Configuration.get('restATTPrefix');
36 return `${restATTPrefix}/v1/categories/resources/`;
39 function versionUrl(itemId, versionId) {
40 const restPrefix = Configuration.get('restPrefix');
41 return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
44 function 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;
51 function fetchConflicts({itemId, version}) {
52 return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
55 function fetchConflictById({itemId, version, cid}) {
56 return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
59 function resolveConflict({itemId, version, conflictId, resolution}) {
60 return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {resolution});
63 function fetchCategories() {
64 return RestAPIUtil.fetch(softwareProductCategoriesUrl());
67 function fetchVersion({vendorId, licensingVersion}) {
68 return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
71 function createCategoryStr(data, {categories}) {
73 let {category, subCategory} = data;
74 let foundCat = categories.find(element => element.uniqueId === category);
75 if (!foundCat) { return ''; }
77 let catName = foundCat.name;
78 let foundSub = foundCat.subcategories.find(element => element.uniqueId === subCategory);
79 if (!foundSub) { return `${catName}`; }
81 let subcatName = foundSub.name;
82 return `${catName} - ${subcatName}`;
86 function getEnumValues({enums, list}) {
88 if (!list) { return ''; }
89 return list.map(item => enums.find(el => el.enum === item).title);
93 const MergeEditorActionHelper = {
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;
99 MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(() =>
101 type: modalActionTypes.GLOBAL_MODAL_SHOW,
103 modalComponentName: modalContentMapper.MERGE_EDITOR,
104 modalClassName: 'merge-editor-modal',
105 title: `${i18n('Merge Required')} - ${version.description}`,
108 type: modalActionTypes.GLOBAL_MODAL_CLOSE
111 modalComponentProps: {
119 return Promise.resolve({updatedVersion: response, inMerge, isDirty: response.state.dirty});
123 fetchConflicts(dispatch, {itemId, version}) {
124 return fetchConflicts({itemId, version}).then(
127 type: actionTypes.LOAD_CONFLICTS,
135 fetchConflict(dispatch, {itemId, version, cid}) {
136 fetchConflictById({itemId, version, cid}).then(
139 newData = MergeEditorActionHelper.processConflict(dispatch, {conflict: data, itemId, cid, version});
141 type: actionTypes.LOAD_CONFLICT,
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) {
153 type: modalActionTypes.GLOBAL_MODAL_CLOSE
155 ScreensHelper.loadLandingScreen(dispatch, {previousScreenName: currentScreen.screen, props: currentScreen.props});
156 ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id});
162 createConflictObject(data, {cid, conflict, dispatch, itemId, version, isYours}) {
166 for (let key in data) {
168 if (data.hasOwnProperty(key)) {
169 let value = data[key];
170 let fieldRule = dataRules[conflict.type] && dataRules[conflict.type][key] || dataRules.general[key];
173 switch (fieldRule.rule) {
179 let {trueValue, falseValue} = fieldRule;
180 newData[key] = value === trueValue ? true : value === falseValue ? false : undefined;
184 let {moveFields, subFields} = fieldRule;
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}
193 newData[key] = MergeEditorActionHelper.createConflictObject(
194 value, {cid, conflict, dispatch, itemId, version, isYours}
200 let {args, functionName} = fieldRule;
201 newData[key] = MergeEditorActionHelper[functionName](data, {
202 cid, conflict, dispatch, version, fieldName: key, isYours, itemId, args
207 newData[key] = value;
212 newData[key] = value;
222 getNamesFromIDs(data, {version, cid, dispatch, itemId, fieldName, isYours, args}) {
224 let idList = data[fieldName] || [];
225 let {fetchFunction, fetchField} = args;
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))
235 Promise.all(promises).then(fetchedItems => {
236 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
238 type: actionTypes.DATA_PROCESSED,
241 [yoursOrTheirs]: { name: fieldName, value: fetchedItems }
250 getFeatureGroups(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
252 let featureGroups = data[fieldName] || [];
253 if (!(featureGroups instanceof Array)) {
254 featureGroups = [featureGroups];
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}')`))
266 Promise.all(promises).then(fetchedGroups => {
267 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
269 type: actionTypes.DATA_PROCESSED,
272 [yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
277 return featureGroups;
281 getLicenseAgreements(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
283 let licenseAgreements = data[fieldName] || [];
284 if (!(licenseAgreements instanceof Array)) {
285 licenseAgreements = [licenseAgreements];
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}')`))
297 Promise.all(promises).then(fetchedAgreements => {
298 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
300 type: actionTypes.DATA_PROCESSED,
303 [yoursOrTheirs]: { name: fieldName, value: fetchedAgreements }
308 return licenseAgreements;
312 processConflict(dispatch, {conflict, cid, version, itemId,}) {
314 let {id, type, yours, theirs} = conflict;
316 let newYours = MergeEditorActionHelper.createConflictObject(
317 cloneDeep(yours), {cid, conflict, dispatch, itemId, version, isYours: true}
319 let newTheirs = MergeEditorActionHelper.createConflictObject(
320 cloneDeep(theirs), {cid, conflict, dispatch, itemId, version, isYours: false}
332 reduceList(data, {fieldName, args}) {
334 let {subField} = args;
335 return data[fieldName].map(el => el[subField]);
339 getEnumList({fieldName}) {
342 'licenseTerm': laOptionsValues.LICENSE_MODEL_TYPE,
343 'operationalScope': epOptionsValues.OPERATIONAL_SCOPE,
344 'processType': processOptionValues.PROCESS_TYPE,
346 {title: 'Service Provider', enum: 'ServiceProvider'},
347 {title: 'Vendor', enum: 'Vendor'}
349 'limitUnit': limitSelectValues.UNIT
352 return enumLists[fieldName];
356 getEnumValue(data, {fieldName, args = {}}) {
358 let value = data[fieldName];
359 let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
360 let enumValue = enumValues.find(el => el.enum === value);
362 return enumValue && enumValue.title || value;
366 processChoice(data, {fieldName, args = {}}) {
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;
376 processChoices(data, {fieldName, args = {}}) {
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;
386 convertArrayToObject(data, {fieldName}) {
387 let value = data[fieldName];
389 value.forEach((el, index) => {
390 newValue[index] = el;
395 fetchCategory(data, {cid, isYours, fieldName, dispatch}) {
397 fetchCategories().then((categories) => {
398 let value = createCategoryStr(data, {categories});
399 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
402 type: actionTypes.DATA_PROCESSED,
405 [yoursOrTheirs]: { name: fieldName, value }
412 fetchLMVersion(data, {cid, dispatch, isYours}) {
414 let {licensingVersion, vendorId} = data;
415 let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
417 if (licensingVersion) {
418 fetchVersion({licensingVersion, vendorId}).then(response => {
420 type: actionTypes.DATA_PROCESSED,
424 name: 'licensingVersion',
434 parseDate(data, {fieldName}) {
436 let date = data[fieldName];
437 return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
443 export default MergeEditorActionHelper;