diff --git a/packages/datalib/src/runMacro.ts b/packages/datalib/src/runMacro.ts index 0e45bc4a1..37a136f5b 100644 --- a/packages/datalib/src/runMacro.ts +++ b/packages/datalib/src/runMacro.ts @@ -12,7 +12,12 @@ const getMacroFunction = { } `, transformRows: (code) => ` -(rows, args, modules, selectedCells, cols) => { +(rows, args, modules, selectedCells, cols, columns) => { + ${code} +} +`, +transformData: (code) => ` +(rows, args, modules, selectedCells, cols, columns) => { ${code} } `, @@ -80,7 +85,8 @@ function runTramsformValue( function removePreviewRowFlags(rows) { rows = rows.filter((row) => row.__rowStatus != 'deleted'); rows = rows.map((row) => { - if (row.__rowStatus || row.__modifiedFields) return _.omit(row, ['__rowStatus', '__modifiedFields']); + if (row.__rowStatus || row.__modifiedFields || row.__insertedFields || row.__deletedFields) + return _.omit(row, ['__rowStatus', '__modifiedFields', '__insertedFields', '__deletedFields']); return row; }); return rows; @@ -101,7 +107,8 @@ function runTramsformRows( macroArgs, modules, selectedCells, - data.structure.columns.map((x) => x.columnName) + data.structure.columns.map((x) => x.columnName), + data.structure.columns ); if (!preview) { rows = removePreviewRowFlags(rows); @@ -115,6 +122,39 @@ function runTramsformRows( }; } +function runTramsformData( + func, + macroArgs: {}, + data: FreeTableModel, + preview: boolean, + selectedCells: MacroSelectedCell[], + errors: string[] = [] +) { + try { + let { rows, columns, cols } = func( + data.rows, + macroArgs, + modules, + selectedCells, + data.structure.columns.map((x) => x.columnName), + data.structure.columns + ); + if (cols && !columns) { + columns = cols.map((columnName) => ({ columnName })); + } + if (!preview) { + rows = removePreviewRowFlags(rows); + } + return { + structure: { columns }, + rows, + }; + } catch (err) { + errors.push(`Error processing data: ${err.message}`); + } + return data; +} + export function runMacro( macro: MacroDefinition, macroArgs: {}, @@ -136,5 +176,9 @@ export function runMacro( if (macro.type == 'transformRows') { return runTramsformRows(func, macroArgs, data, preview, selectedCells, errors); } + if (macro.type == 'transformData') { + // @ts-ignore + return runTramsformData(func, macroArgs, data, preview, selectedCells, errors); + } return data; } diff --git a/packages/web/src/freetable/FreeTableGridCore.js b/packages/web/src/freetable/FreeTableGridCore.js index 4e0a73dd7..a81c15bed 100644 --- a/packages/web/src/freetable/FreeTableGridCore.js +++ b/packages/web/src/freetable/FreeTableGridCore.js @@ -30,10 +30,11 @@ export default function FreeTableGridCore(props) { macroPreview ? selectedCells : null, ] ); - const display = React.useMemo(() => new FreeTableGridDisplay(modelState.value, config, setConfig, cache, setCache), [ + const display = React.useMemo(() => new FreeTableGridDisplay(grider.model || modelState.value, config, setConfig, cache, setCache), [ modelState.value, config, cache, + grider, ]); const handleSelectionChanged = React.useCallback( diff --git a/packages/web/src/freetable/MacroPreviewGrider.ts b/packages/web/src/freetable/MacroPreviewGrider.ts index 6a42b8794..e33ea59a7 100644 --- a/packages/web/src/freetable/MacroPreviewGrider.ts +++ b/packages/web/src/freetable/MacroPreviewGrider.ts @@ -1,5 +1,13 @@ import { FreeTableModel, MacroDefinition, MacroSelectedCell, runMacro } from '@dbgate/datalib'; import Grider, { GriderRowStatus } from '../datagrid/Grider'; +import _ from 'lodash'; + +function convertToSet(row, field) { + if (!row) return null; + if (!row[field]) return null; + if (_.isSet(row[field])) return row[field]; + return new Set(row[field]); +} export default class MacroPreviewGrider extends Grider { model: FreeTableModel; @@ -17,7 +25,9 @@ export default class MacroPreviewGrider extends Grider { const row = this.model.rows[index]; return { status: (row && row.__rowStatus) || 'regular', - modifiedFields: row ? row.__modifiedFields : null, + modifiedFields: convertToSet(row, '__modifiedFields'), + insertedFields: convertToSet(row, '__insertedFields'), + deletedFields: convertToSet(row, '__deletedFields'), }; } diff --git a/packages/web/src/freetable/macros.js b/packages/web/src/freetable/macros.js index e357dc8ef..8d3f5c547 100644 --- a/packages/web/src/freetable/macros.js +++ b/packages/web/src/freetable/macros.js @@ -111,11 +111,11 @@ return value ? value.toString().replace(new RegExp(rtext, rflags), args.replace code: ` const selectedRowIndexes = modules.lodash.uniq(selectedCells.map(x => x.row)); const selectedRows = modules.lodash.groupBy(selectedCells, 'row'); -const maxIndex = _.max(selectedRowIndexes); +const maxIndex = modules.lodash.max(selectedRowIndexes); return [ ...rows.slice(0, maxIndex + 1), ...selectedRowIndexes.map(index => ({ - ..._.pick(rows[index], selectedRows[index].map(x=>x.column)), + ...modules.lodash.pick(rows[index], selectedRows[index].map(x => x.column)), __rowStatus: 'inserted', })), ...rows.slice(maxIndex + 1), @@ -136,7 +136,63 @@ return rows.map(row => { __rowStatus: 'deleted', }; }) -`} +`, + }, + { + title: 'Duplicate columns', + name: 'duplicateColumns', + group: 'Tools', + description: 'Duplicate selected columns', + type: 'transformData', + code: ` +const selectedColumnNames = modules.lodash.uniq(selectedCells.map(x => x.column)); +const selectedRowIndexes = modules.lodash.uniq(selectedCells.map(x => x.row)); +const addedColumnNames = selectedColumnNames.map(col => (args.prefix || '') + col + (args.postfix || '')); +const resultRows = rows.map((row, rowIndex) => ({ + ...row, + ...(selectedRowIndexes.includes(rowIndex) ? modules.lodash.fromPairs(selectedColumnNames.map(col => [(args.prefix || '') + col + (args.postfix || ''), row[col]])) : {}), + __insertedFields: addedColumnNames, +})); +const resultCols = [ + ...cols, + ...addedColumnNames, +]; +return { + rows: resultRows, + cols: resultCols, +} + `, + args: [ + { + type: 'text', + label: 'Prefix', + name: 'prefix', + }, + { + type: 'text', + label: 'Postfix', + name: 'postfix', + default: '_copy', + }, + ], + }, ]; +// function f() { +// const selectedColumnNames = modules.lodash.uniq(selectedCells.map((x) => x.column)); +// const addedColumnNames = selectedColumnNames.map((col) => (args.prefix || '') + col + (args.postfix || '')); +// const resultRows = rows.map((row) => ({ +// ...row, +// ...modules.lodash.fromPairs( +// selectedColumnNames.map((col) => [(args.prefix || '') + col + (args.postfix || ''), row[col]]) +// ), +// __insertedFields: addedColumnNames, +// })); +// const resultCols = [...cols, ...addedColumnNames]; +// return { +// rows: resultRows, +// cols: resultCols, +// }; +// } + export default macros;