blob: c54b9feb93056e18e3c87464fc38560afd0c8693 [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;