diff --git a/packages/datalib/src/MacroDefinition.ts b/packages/datalib/src/MacroDefinition.ts index 0ef83d0cf..e7fa0b5b1 100644 --- a/packages/datalib/src/MacroDefinition.ts +++ b/packages/datalib/src/MacroDefinition.ts @@ -19,4 +19,6 @@ export interface MacroDefinition { export interface MacroSelectedCell { column: string; row: number; + rowData: any; + value: any; } diff --git a/packages/datalib/src/runMacro.ts b/packages/datalib/src/runMacro.ts index 89591b26e..19d70385c 100644 --- a/packages/datalib/src/runMacro.ts +++ b/packages/datalib/src/runMacro.ts @@ -4,6 +4,8 @@ import uuidv1 from 'uuid/v1'; import uuidv4 from 'uuid/v4'; import moment from 'moment'; import { MacroDefinition, MacroSelectedCell } from './MacroDefinition'; +import { ChangeSet, setChangeSetValue } from './ChangeSet'; +import { GridDisplay } from './GridDisplay'; const getMacroFunction = { transformValue: code => ` @@ -183,3 +185,55 @@ export function runMacro( } return data; } + +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, row, column, 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 runMacroOnChangeSet( + macro: MacroDefinition, + macroArgs: {}, + selectedCells: MacroSelectedCell[], + changeSet: ChangeSet, + display: GridDisplay +): ChangeSet { + const errors = []; + const compiledMacroFunc = compileMacroFunction(macro, errors); + if (!compiledMacroFunc) return null; + + let res = changeSet; + for (const cell of selectedCells) { + const definition = display.getChangeSetField(cell.rowData, cell.column, undefined); + const macroResult = runMacroOnValue( + compiledMacroFunc, + macroArgs, + cell.value, + cell.row, + cell.rowData, + cell.column, + errors + ); + res = setChangeSetValue(res, definition, macroResult); + } + + return res; +} diff --git a/packages/web/src/commands/recentDatabaseSwitch.ts b/packages/web/src/commands/recentDatabaseSwitch.ts index 586f0192a..a977fbc25 100644 --- a/packages/web/src/commands/recentDatabaseSwitch.ts +++ b/packages/web/src/commands/recentDatabaseSwitch.ts @@ -3,7 +3,6 @@ import { recentDatabases, currentDatabase, getRecentDatabases } from '../stores' import registerCommand from './registerCommand'; currentDatabase.subscribe(value => { - console.log('DB', value); if (!value) return; recentDatabases.update(list => { const res = [ diff --git a/packages/web/src/datagrid/ChangeSetGrider.ts b/packages/web/src/datagrid/ChangeSetGrider.ts index ba642eb4f..2136789a6 100644 --- a/packages/web/src/datagrid/ChangeSetGrider.ts +++ b/packages/web/src/datagrid/ChangeSetGrider.ts @@ -7,8 +7,12 @@ import { findExistingChangeSetItem, getChangeSetInsertedRows, GridDisplay, + MacroDefinition, + MacroSelectedCell, revertChangeSetRowChanges, setChangeSetValue, + compileMacroFunction, + runMacroOnValue, } from 'dbgate-datalib'; import Grider, { GriderRowStatus } from './Grider'; @@ -21,8 +25,18 @@ export default class ChangeSetGrider extends Grider { private rowStatusCache; private rowDefinitionsCache; private batchChangeSet: ChangeSet; + private _errors = null; + private compiledMacroFunc; - constructor(public sourceRows: any[], public changeSetState, public dispatchChangeSet, public display: GridDisplay) { + constructor( + public sourceRows: any[], + public changeSetState, + public dispatchChangeSet, + public display: GridDisplay, + public macro: MacroDefinition, + public macroArgs: {}, + public selectedCells: MacroSelectedCell[] + ) { super(); this.changeSet = changeSetState && changeSetState.value; this.insertedRows = getChangeSetInsertedRows(this.changeSet, display.baseTable); @@ -32,6 +46,11 @@ export default class ChangeSetGrider extends Grider { this.rowStatusCache = {}; this.rowDefinitionsCache = {}; this.batchChangeSet = null; + this.compiledMacroFunc = compileMacroFunction(macro, this._errors); + } + + get errors() { + return this._errors; } getRowSource(index: number) { @@ -49,7 +68,11 @@ export default class ChangeSetGrider extends Grider { const insertedRowIndex = this.getInsertedRowIndex(index); const rowDefinition = this.display.getChangeSetRow(row, insertedRowIndex); const [matchedField, matchedChangeSetItem] = findExistingChangeSetItem(this.changeSet, rowDefinition); - const rowUpdated = matchedChangeSetItem ? { ...row, ...matchedChangeSetItem.fields } : row; + const rowUpdated = matchedChangeSetItem + ? { ...row, ...matchedChangeSetItem.fields } + : this.compiledMacroFunc + ? { ...row } + : row; let status = 'regular'; if (matchedChangeSetItem && matchedField == 'updates') status = 'updated'; if (matchedField == 'deletes') status = 'deleted'; @@ -59,6 +82,23 @@ export default class ChangeSetGrider extends Grider { modifiedFields: matchedChangeSetItem && matchedChangeSetItem.fields ? new Set(Object.keys(matchedChangeSetItem.fields)) : null, }; + + if (this.compiledMacroFunc) { + for (const cell of this.selectedCells) { + if (cell.row != index) continue; + const newValue = runMacroOnValue( + this.compiledMacroFunc, + this.macroArgs, + rowUpdated[cell.column], + index, + rowUpdated, + cell.column, + this._errors + ); + rowUpdated[cell.column] = newValue; + } + } + this.rowDataCache[index] = rowUpdated; this.rowStatusCache[index] = rowStatus; this.rowDefinitionsCache[index] = rowDefinition; diff --git a/packages/web/src/datagrid/DataGrid.svelte b/packages/web/src/datagrid/DataGrid.svelte index ae0648482..a999faf3b 100644 --- a/packages/web/src/datagrid/DataGrid.svelte +++ b/packages/web/src/datagrid/DataGrid.svelte @@ -1,6 +1,15 @@ @@ -40,18 +73,36 @@ > + + + macro.type == 'transformValue'} /> + - {#if isFormView} - - {:else} - - {/if} + + + {#if isFormView} + + {:else} + (selectedCellsPublished = value)} + macroValues={extractMacroValuesForMacro($macroValues, $selectedMacro)} + macroPreview={$selectedMacro} + {selectedCellsPublished} + /> + {/if} + + + + {#if $selectedMacro} + + {/if} + + diff --git a/packages/web/src/datagrid/SqlDataGridCore.svelte b/packages/web/src/datagrid/SqlDataGridCore.svelte index b9ee666f9..cf71c61d7 100644 --- a/packages/web/src/datagrid/SqlDataGridCore.svelte +++ b/packages/web/src/datagrid/SqlDataGridCore.svelte @@ -66,11 +66,26 @@ export let changeSetState; export let dispatchChangeSet; + export let macroPreview; + export let macroValues; + export let selectedCellsPublished; + + // export let onChangeGrider = undefined; + let loadedRows = []; // $: console.log('loadedRows BIND', loadedRows); - $: grider = new ChangeSetGrider(loadedRows, changeSetState, dispatchChangeSet, display); + $: grider = new ChangeSetGrider( + loadedRows, + changeSetState, + dispatchChangeSet, + display, + macroPreview, + macroValues, + selectedCellsPublished + ); // $: console.log('GRIDER', grider); + // $: if (onChangeGrider) onChangeGrider(grider); async function handleConfirmSql(sql) { const resp = await axiosInstance.request({ @@ -162,6 +177,7 @@ onOpenQuery={openQuery} onOpenActiveChart={openActiveChart} bind:loadedRows + frameSelection={!!macroPreview} {grider} onSave={handleSave} /> diff --git a/packages/web/src/datagrid/TableDataGrid.svelte b/packages/web/src/datagrid/TableDataGrid.svelte index d36db7df3..61352c1ab 100644 --- a/packages/web/src/datagrid/TableDataGrid.svelte +++ b/packages/web/src/datagrid/TableDataGrid.svelte @@ -119,6 +119,7 @@ {display} {formDisplay} showReferences + showMacros onReferenceSourceChanged={reference ? handleReferenceSourceChanged : null} onReferenceClick={value => { if (value && value.referenceId && reference && reference.referenceId == value.referenceId) { diff --git a/packages/web/src/freetable/FreeTableGrid.svelte b/packages/web/src/freetable/FreeTableGrid.svelte index 8dcd3f287..52cc82c03 100644 --- a/packages/web/src/freetable/FreeTableGrid.svelte +++ b/packages/web/src/freetable/FreeTableGrid.svelte @@ -1,5 +1,5 @@ - data.group} /> + (macroCondition ? macroCondition(x) : true))} + module={macroAppObject} + {filter} + groupFunc={data => data.group} + />