diff --git a/packages/datalib/src/runMacro.ts b/packages/datalib/src/runMacro.ts index 537d0863f..a5b266dda 100644 --- a/packages/datalib/src/runMacro.ts +++ b/packages/datalib/src/runMacro.ts @@ -25,9 +25,16 @@ export function runMacro( macroArgs: {}, data: FreeTableModel, preview: boolean, - selectedCells: MacroSelectedCell[] + selectedCells: MacroSelectedCell[], + errors: string[] = [] ): FreeTableModel { - const func = eval(getMacroFunction[macro.type](macro.code)); + let func; + try { + func = eval(getMacroFunction[macro.type](macro.code)); + } catch (err) { + errors.push(`Error compiling macro ${macro.name}: ${err.message}`); + return data; + } if (macro.type == 'transformValue') { const selectedRows = _.groupBy(selectedCells, 'row'); const rows = data.rows.map((row, rowIndex) => { @@ -38,7 +45,12 @@ export function runMacro( for (const cell of selectedRow) { const { column } = cell; const oldValue = row[column]; - const newValue = func(oldValue, macroArgs, modules, rowIndex, row, column); + let newValue = oldValue; + try { + newValue = func(oldValue, macroArgs, modules, rowIndex, row, column); + } catch (err) { + errors.push(`Error processing column ${column} on row ${rowIndex}: ${err.message}`); + } if (newValue != oldValue) { if (res == null) { res = { ...row }; diff --git a/packages/web/src/datagrid/DataGridCore.js b/packages/web/src/datagrid/DataGridCore.js index d435d5d7b..449b15c5f 100644 --- a/packages/web/src/datagrid/DataGridCore.js +++ b/packages/web/src/datagrid/DataGridCore.js @@ -298,6 +298,16 @@ export default function DataGridCore(props) { return ; } + if (grider.errors && grider.errors.length > 0) { + return ( +
+ {grider.errors.map((err, index) => ( + + ))} +
+ ); + } + const handleRowScroll = (value) => { setFirstVisibleRowScrollIndex(value); }; diff --git a/packages/web/src/datagrid/Grider.ts b/packages/web/src/datagrid/Grider.ts index bb8165c7e..0f24aeea4 100644 --- a/packages/web/src/datagrid/Grider.ts +++ b/packages/web/src/datagrid/Grider.ts @@ -50,6 +50,9 @@ export default abstract class Grider { get disableLoadNextPage() { return false; } + get errors() { + return null; + } updateRow(index, changeObject) { for (const key of Object.keys(changeObject)) { this.setCellValue(index, key, changeObject[key]); diff --git a/packages/web/src/freetable/MacroPreviewGrider.ts b/packages/web/src/freetable/MacroPreviewGrider.ts index 0a3682072..1c3081715 100644 --- a/packages/web/src/freetable/MacroPreviewGrider.ts +++ b/packages/web/src/freetable/MacroPreviewGrider.ts @@ -3,9 +3,14 @@ import Grider, { GriderRowStatus } from '../datagrid/Grider'; export default class MacroPreviewGrider extends Grider { model: FreeTableModel; + _errors: string[] = []; constructor(model: FreeTableModel, macro: MacroDefinition, macroArgs: {}, selectedCells: MacroSelectedCell[]) { super(); - this.model = runMacro(macro, macroArgs, model, true, selectedCells); + this.model = runMacro(macro, macroArgs, model, true, selectedCells, this._errors); + } + + get errors() { + return this._errors; } getRowStatus(index): GriderRowStatus { diff --git a/packages/web/src/widgets/ErrorInfo.js b/packages/web/src/widgets/ErrorInfo.js index 04e50d8ee..03905effc 100644 --- a/packages/web/src/widgets/ErrorInfo.js +++ b/packages/web/src/widgets/ErrorInfo.js @@ -14,7 +14,20 @@ const Icon = styled.div` margin: 10px; `; -export default function ErrorInfo({ message, icon = 'fas fa-times-circle red' }) { +const ContainerSmall = styled.div` + display: flex; + margin-right: 10px; +`; + +export default function ErrorInfo({ message, icon = 'fas fa-times-circle red', isSmall = false }) { + if (isSmall) { + return ( + + + {message} + + ); + } return (