in client/src/components/pipelines/browser/metadata-controls/auto-fill-entities.js [234:448]
function buildAutoFillAction (options) {
const {
sourceItems,
targetItems,
insertedItems,
removedItems,
sourceColumns,
targetColumns,
removedColumns,
insertedColumns
} = options;
if (removedItems.length > 0 || removedColumns.length > 0) {
return undefined;
}
const getNumberShift = value => {
if (!value) {
return 0;
}
const exec = /^[\\-]?(0+[\d]+)$/.exec(`${value}`);
if (exec && exec.length === 2) {
return exec[1].length;
}
return 0;
};
const getShiftedNumber = (number, shift = 0) => {
const string = `${Math.abs(number)}`;
const sign = number < 0 ? '-' : '';
const appendZeroCount = Math.max(0, shift - string.length);
if (appendZeroCount > 0) {
return `${sign}${(new Array(appendZeroCount)).fill('0').join('')}${string}`;
}
return `${sign}${string}`;
};
const splitValue = value => {
if (!value) {
return {
value: undefined
};
}
if (!Number.isNaN(Number(value))) {
return {
value,
number: +value,
string: '',
shift: getNumberShift(value)
};
}
const exec = /^(.*[^\d])([\d]+)$/.exec(`${value}`);
if (exec && exec.length === 3) {
return {
value: exec[0],
string: exec[1],
number: +exec[2],
shift: getNumberShift(exec[2])
};
}
return {
value
};
};
const getValuesDiff = values => {
if (values.length === 0) {
return undefined;
}
if (values.some(value => value.number === undefined)) {
return undefined;
}
if ((new Set(values.map(value => value.string))).size > 1) {
return undefined;
}
if (values.length === 1) {
return Math.sign(values[0].number);
}
const diff = values[1].number - values[0].number;
for (let i = 2; i < values.length; i++) {
if (values[i].number - values[i - 1].number !== diff) {
return undefined;
}
}
return diff;
};
const getValuesShift = values => {
if (values.length === 0) {
return 0;
}
if (values.some(value => value.number === undefined)) {
return 0;
}
if ((new Set(values.map(value => value.string))).size > 1) {
return 0;
}
return Math.max(...values.map(value => value.shift || 0));
};
const valuesAreAutoIncrementable = values => !!getValuesDiff(values);
const values = [];
for (let sRow = 0; sRow < sourceItems.length; sRow++) {
const row = [];
for (let sColumn = 0; sColumn < sourceColumns.length; sColumn++) {
const source = sourceItems[sRow].item;
const column = sourceColumns[sColumn].key;
const value = source.hasOwnProperty(column)
? source[column].value
: undefined;
row.push(splitValue(value));
}
values.push(row);
}
const rotatedValues = [];
for (let sColumn = 0; sColumn < sourceColumns.length; sColumn++) {
const row = [];
for (let sRow = 0; sRow < sourceItems.length; sRow++) {
const source = sourceItems[sRow].item;
const column = sourceColumns[sColumn].key;
const value = source.hasOwnProperty(column)
? source[column].value
: undefined;
row.push(splitValue(value));
}
rotatedValues.push(row);
}
const getIncrementedValue = table => {
const diffs = table.map(getValuesDiff);
const shifts = table.map(getValuesShift);
return (source, incrementRatio) => {
if (source < 0 || source >= table.length) {
return undefined;
}
const row = table[source];
if (row.length === 0) {
return undefined;
}
const last = row[row.length - 1];
const diff = diffs[source];
const shift = shifts[source] || 0;
if (diff === undefined || last.number === undefined) {
return undefined;
}
const number = last.number + incrementRatio * diff;
const shiftedNumber = getShiftedNumber(
!last.string
? number
: Math.abs(number),
shift
);
return `${last.string || ''}${shiftedNumber}`;
};
};
if (insertedItems.length > 0 && rotatedValues.some(valuesAreAutoIncrementable)) {
const fn = getIncrementedValue(rotatedValues);
const processItem = (item, index) => {
const source = sourceItems[index % sourceItems.length].item;
const payload = {...item.item};
for (let c = 0; c < targetColumns.length; c++) {
const column = targetColumns[c].key;
const value = fn(c, index + 1);
const type = source.hasOwnProperty(column)
? source[column].type
: undefined;
if (value === undefined) {
delete payload[column];
} else {
payload[column] = {
value,
type: type || 'string'
};
}
}
return mapItemSaveOperation(payload, options);
};
return {
title: 'Fill cells',
loadingMessage: 'Filling...',
action: () => new Promise((resolve, reject) => {
Promise
.all(insertedItems.map(processItem))
.then(resolve)
.catch(reject);
})
};
}
if (insertedColumns.length > 0 && values.some(valuesAreAutoIncrementable)) {
const fn = getIncrementedValue(values);
const processItem = (item, index) => {
const payload = {...item.item};
for (let c = 0; c < insertedColumns.length; c++) {
const sourceColumn = sourceColumns[c % sourceColumns.length].key;
const targetColumn = insertedColumns[c].key;
const value = fn(index, c + 1);
const type = payload.hasOwnProperty(sourceColumn)
? payload[sourceColumn].type
: undefined;
if (value === undefined) {
delete payload[targetColumn];
} else {
payload[targetColumn] = {
value,
type: type || 'string'
};
}
}
return mapItemSaveOperation(payload, options);
};
return {
title: 'Fill cells',
loadingMessage: 'Filling...',
action: () => new Promise((resolve, reject) => {
Promise
.all(targetItems.map(processItem))
.then(resolve)
.catch(reject);
})
};
}
return undefined;
}