Files
dbgate/packages/datalib/src/runMacro.ts
2023-02-25 09:51:08 +01:00

111 lines
3.1 KiB
TypeScript

import _ from 'lodash';
import uuidv1 from 'uuid/v1';
import uuidv4 from 'uuid/v4';
import moment from 'moment';
import { MacroDefinition, MacroSelectedCell } from './MacroDefinition';
import { ChangeSet, setChangeSetValue, setChangeSetRowData } from './ChangeSet';
import { GridDisplay } from './GridDisplay';
const getMacroFunction = {
transformValue: code => `
(value, args, modules, rowIndex, row, columnName) => {
${code}
}
`,
transformRow: code => `
(row, args, modules, rowIndex, columns) => {
${code}
}
`,
};
const modules = {
lodash: _,
uuidv1,
uuidv4,
moment,
};
export function compileMacroFunction(macro: MacroDefinition, errors = []) {
if (!macro) return null;
let func;
try {
func = eval(getMacroFunction[macro.type](macro.code));
return func;
} catch (err) {
errors.push(`Error compiling macro ${macro.name}: ${err.message}`);
return null;
}
}
export function runMacroOnValue(compiledFunc, macroArgs, value, rowIndex: number, row, column: string, errors = []) {
if (!compiledFunc) return value;
try {
const res = compiledFunc(value, macroArgs, modules, rowIndex, row, column);
return res;
} catch (err) {
errors.push(`Error processing column ${column} on row ${rowIndex}: ${err.message}`);
return value;
}
}
export function runMacroOnRow(compiledFunc, macroArgs, rowIndex: number, row: any, columns: string[], errors = []) {
if (!compiledFunc) return row;
try {
const res = compiledFunc(row, macroArgs, modules, rowIndex, columns);
return res;
} catch (err) {
errors.push(`Error processing row ${rowIndex}: ${err.message}`);
return row;
}
}
export function runMacroOnChangeSet(
macro: MacroDefinition,
macroArgs: {},
selectedCells: MacroSelectedCell[],
changeSet: ChangeSet,
display: GridDisplay,
useRowIndexInsteaOfCondition: boolean
): ChangeSet {
const errors = [];
const compiledMacroFunc = compileMacroFunction(macro, errors);
if (!compiledMacroFunc) return null;
if (macro.type == 'transformValue') {
let res = changeSet;
for (const cell of selectedCells) {
const definition = display.getChangeSetField(
cell.rowData,
cell.column,
undefined,
useRowIndexInsteaOfCondition ? cell.row : undefined,
useRowIndexInsteaOfCondition
);
const macroResult = runMacroOnValue(
compiledMacroFunc,
macroArgs,
cell.value,
cell.row,
cell.rowData,
cell.column,
errors
);
res = setChangeSetValue(res, definition, macroResult);
}
return res;
}
if (macro.type == 'transformRow') {
let res = changeSet;
const rowIndexes = _.uniq(selectedCells.map(x => x.row));
for (const index of rowIndexes) {
const rowData = selectedCells.find(x => x.row == index)?.rowData;
const columns = _.uniq(selectedCells.map(x => x.column));
const definition = display.getChangeSetRow(rowData, null, index, true);
const newRow = runMacroOnRow(compiledMacroFunc, macroArgs, index, rowData, columns);
res = setChangeSetRowData(res, definition, newRow);
}
return res;
}
}