blob: 92ec60b999f60bea200a62f4c206535fa3d0a810 [file] [log] [blame]
/*!
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import {actionTypes, rules, dataRules, SyncStates} from './MergeEditorConstants.js';
import cloneDeep from 'lodash/cloneDeep.js';
import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
import Configuration from 'sdc-app/config/Configuration.js';
import ItemsHelper from '../../common/helpers/ItemsHelper.js';
import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js';
import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
import i18n from 'nfvo-utils/i18n/i18n.js';
import {optionsInputValues as epOptionsValues} from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js';
import {optionsInputValues as laOptionsValues} from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js';
import {optionsInputValues as processOptionValues} from 'sdc-app/onboarding/softwareProduct/components/processes/SoftwareProductComponentProcessesConstants.js';
import {selectValues as limitSelectValues} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
import FeatureGroupsActionHelper from 'sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js';
import LicenseAgreementActionHelper from 'sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js';
import moment from 'moment';
import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
function softwareProductCategoriesUrl() {
const restCatalogPrefix = Configuration.get('restCatalogPrefix');
return `${restCatalogPrefix}/v1/categories/resources/`;
}
function versionUrl(itemId, versionId) {
const restPrefix = Configuration.get('restPrefix');
return `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}`;
}
function baseUrl(itemId, version, conflictId) {
const versionId = version.id;
const restPrefix = Configuration.get('restPrefix');
let baseUrl = `${restPrefix}/v1.0/items/${itemId}/versions/${versionId}/conflicts`;
return conflictId ? `${baseUrl}/${conflictId}` : baseUrl;
}
function fetchConflicts({itemId, version}) {
return RestAPIUtil.fetch(`${baseUrl(itemId, version)}`);
}
function fetchConflictById({itemId, version, cid}) {
return RestAPIUtil.fetch(`${baseUrl(itemId, version, cid)}`);
}
function resolveConflict({itemId, version, conflictId, resolution}) {
return RestAPIUtil.put(`${baseUrl(itemId, version, conflictId)}`, {resolution});
}
function fetchCategories() {
return RestAPIUtil.fetch(softwareProductCategoriesUrl());
}
function fetchVersion({vendorId, licensingVersion}) {
return RestAPIUtil.fetch(versionUrl(vendorId, licensingVersion));
}
function createCategoryStr(data, {categories}) {
let {category, subCategory} = data;
let foundCat = categories.find(element => element.uniqueId === category);
if (!foundCat) { return ''; }
let catName = foundCat.name;
let foundSub = foundCat.subcategories.find(element => element.uniqueId === subCategory);
if (!foundSub) { return `${catName}`; }
let subcatName = foundSub.name;
return `${catName} - ${subcatName}`;
}
function getEnumValues({enums, list}) {
if (!list) { return ''; }
return list.map(item => enums.find(el => el.enum === item).title);
}
const MergeEditorActionHelper = {
analyzeSyncResult(dispatch, {itemId, version}) {
return ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id}).then((response) => {
let inMerge = response && response.state && response.state.synchronizationState === SyncStates.MERGE;
if (inMerge) {
MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(() =>
dispatch({
type: modalActionTypes.GLOBAL_MODAL_SHOW,
data: {
modalComponentName: modalContentMapper.MERGE_EDITOR,
modalClassName: 'merge-editor-modal',
title: `${i18n('Merge Required')} - ${version.description}`,
onDeclined: () => {
dispatch({
type: modalActionTypes.GLOBAL_MODAL_CLOSE
});
},
modalComponentProps: {
size: 'lg',
type: 'default'
}
}
})
);
}
return Promise.resolve({updatedVersion: response, inMerge, isDirty: response.state.dirty});
});
},
fetchConflicts(dispatch, {itemId, version}) {
return fetchConflicts({itemId, version}).then(
(data) => {
dispatch({
type: actionTypes.LOAD_CONFLICTS,
data
});
return data;
}
);
},
fetchConflict(dispatch, {itemId, version, cid}) {
fetchConflictById({itemId, version, cid}).then(
(data) => {
let newData = {};
newData = MergeEditorActionHelper.processConflict(dispatch, {conflict: data, itemId, cid, version});
dispatch({
type: actionTypes.LOAD_CONFLICT,
data: newData
});
}
);
},
resolveConflict(dispatch, {itemId, version, conflictId, resolution, currentScreen}) {
resolveConflict({itemId, version, conflictId, resolution}).then(() => {
MergeEditorActionHelper.fetchConflicts(dispatch, {itemId, version}).then(conflicts => {
if(conflicts.conflictInfoList && conflicts.conflictInfoList.length === 0) {
dispatch({
type: modalActionTypes.GLOBAL_MODAL_CLOSE
});
ScreensHelper.loadLandingScreen(dispatch, {previousScreenName: currentScreen.screen, props: currentScreen.props});
ItemsHelper.checkItemStatus(dispatch, {itemId, versionId: version.id});
}
});
});
},
createConflictObject(data, {cid, conflict, dispatch, itemId, version, isYours}) {
let newData = {};
for (let key in data) {
if (data.hasOwnProperty(key)) {
let value = data[key];
let fieldRule = dataRules[conflict.type] && dataRules[conflict.type][key] || dataRules.general[key];
if (fieldRule) {
switch (fieldRule.rule) {
case rules.SKIP:
break;
case rules.BOOLEAN:
let {trueValue, falseValue} = fieldRule;
newData[key] = value === trueValue ? true : value === falseValue ? false : undefined;
break;
case rules.PARSE:
let {moveFields, subFields} = fieldRule;
if (moveFields) {
let fields = subFields || Object.keys(value);
fields.forEach(field => {
newData[field] = MergeEditorActionHelper.createConflictObject(
value[field], {cid, conflict, dispatch, itemId, version, isYours}
);
});
} else {
newData[key] = MergeEditorActionHelper.createConflictObject(
value, {cid, conflict, dispatch, itemId, version, isYours}
);
}
break;
case rules.FUNCTION:
let {args, functionName} = fieldRule;
newData[key] = MergeEditorActionHelper[functionName](data, {
cid, conflict, dispatch, version, fieldName: key, isYours, itemId, args
});
break;
default:
newData[key] = value;
break;
}
} else {
newData[key] = value;
}
}
}
return newData;
},
getNamesFromIDs(data, {version, cid, dispatch, itemId, fieldName, isYours, args}) {
let idList = data[fieldName] || [];
let {fetchFunction, fetchField} = args;
let promises = idList.map(id =>
new Promise(resolve =>
MergeEditorActionHelper[fetchFunction](
dispatch, {licenseModelId: itemId, [fetchField]: id, version}
).then(item => resolve(item.name))
)
);
Promise.all(promises).then(fetchedItems => {
let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
dispatch({
type: actionTypes.DATA_PROCESSED,
data: {
cid,
[yoursOrTheirs]: { name: fieldName, value: fetchedItems }
}
});
});
return idList;
},
getFeatureGroups(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
let featureGroups = data[fieldName] || [];
if (!(featureGroups instanceof Array)) {
featureGroups = [featureGroups];
}
let promises = featureGroups.map(featureGroupId =>
new Promise(resolve =>
FeatureGroupsActionHelper.fetchFeatureGroup(
dispatch, {licenseModelId: itemId, featureGroupId, version}
).then(featureGroup => resolve(featureGroup.name))
.catch(reason => console.log(`getFeatureGroups Promise rejected ('${reason}')`))
)
);
Promise.all(promises).then(fetchedGroups => {
let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
dispatch({
type: actionTypes.DATA_PROCESSED,
data: {
cid,
[yoursOrTheirs]: { name: fieldName, value: fetchedGroups }
}
});
});
return featureGroups;
},
getLicenseAgreements(data, {version, cid, dispatch, itemId, fieldName, isYours}) {
let licenseAgreements = data[fieldName] || [];
if (!(licenseAgreements instanceof Array)) {
licenseAgreements = [licenseAgreements];
}
let promises = licenseAgreements.map(licenseAgreementId =>
new Promise(resolve =>
LicenseAgreementActionHelper.fetchLicenseAgreement(
dispatch, {licenseModelId: itemId, licenseAgreementId, version}
).then(licenseAgreement => resolve(licenseAgreement.name))
.catch(reason => console.log(`getLicenseAgreements Promise rejected ('${reason}')`))
)
);
Promise.all(promises).then(fetchedAgreements => {
let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
dispatch({
type: actionTypes.DATA_PROCESSED,
data: {
cid,
[yoursOrTheirs]: { name: fieldName, value: fetchedAgreements }
}
});
});
return licenseAgreements;
},
processConflict(dispatch, {conflict, cid, version, itemId,}) {
let {id, type, yours, theirs} = conflict;
let newYours = MergeEditorActionHelper.createConflictObject(
cloneDeep(yours), {cid, conflict, dispatch, itemId, version, isYours: true}
);
let newTheirs = MergeEditorActionHelper.createConflictObject(
cloneDeep(theirs), {cid, conflict, dispatch, itemId, version, isYours: false}
);
return {
id,
type,
yours: newYours,
theirs: newTheirs
};
},
reduceList(data, {fieldName, args}) {
let {subField} = args;
return data[fieldName].map(el => el[subField]);
},
getEnumList({fieldName}) {
const enumLists = {
'licenseTerm': laOptionsValues.LICENSE_MODEL_TYPE,
'operationalScope': epOptionsValues.OPERATIONAL_SCOPE,
'processType': processOptionValues.PROCESS_TYPE,
'limitType': [
{title: 'Service Provider', enum: 'ServiceProvider'},
{title: 'Vendor', enum: 'Vendor'}
],
'limitUnit': limitSelectValues.UNIT
};
return enumLists[fieldName];
},
getEnumValue(data, {fieldName, args = {}}) {
let value = data[fieldName];
let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
let enumValue = enumValues.find(el => el.enum === value);
return enumValue && enumValue.title || value;
},
processChoice(data, {fieldName, args = {}}) {
let value = data[fieldName];
let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
let newValue = value.other || enumValues && enumValues.find(el => el.enum === value.choice).title || value.choice;
return newValue;
},
processChoices(data, {fieldName, args = {}}) {
let value = data[fieldName];
let enumValues = MergeEditorActionHelper.getEnumList({fieldName: args.listName || fieldName});
let newValue = value.other || getEnumValues({enums: enumValues, list: value.choices}) || value.choices;
return newValue;
},
convertArrayToObject(data, {fieldName}) {
let value = data[fieldName];
let newValue = {};
value.forEach((el, index) => {
newValue[index] = el;
});
return newValue;
},
fetchCategory(data, {cid, isYours, fieldName, dispatch}) {
fetchCategories().then((categories) => {
let value = createCategoryStr(data, {categories});
let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
dispatch({
type: actionTypes.DATA_PROCESSED,
data: {
cid,
[yoursOrTheirs]: { name: fieldName, value }
}
});
});
},
fetchLMVersion(data, {cid, dispatch, isYours}) {
let {licensingVersion, vendorId} = data;
let yoursOrTheirs = isYours ? 'yoursField' : 'theirsField';
if (licensingVersion) {
fetchVersion({licensingVersion, vendorId}).then(response => {
dispatch({
type: actionTypes.DATA_PROCESSED,
data: {
cid,
[yoursOrTheirs]: {
name: 'licensingVersion',
value: response.name
}
}
});
});
}
},
parseDate(data, {fieldName}) {
let date = data[fieldName];
return date && moment(date, DATE_FORMAT).format(DATE_FORMAT);
}
};
export default MergeEditorActionHelper;