diff --git a/lib/DataHarmonizer.js b/lib/DataHarmonizer.js index 20187c60..576c47ea 100644 --- a/lib/DataHarmonizer.js +++ b/lib/DataHarmonizer.js @@ -763,14 +763,13 @@ class DataHarmonizer { } addRowsToBottom(numRows) { - console.log(this.context.currentSelection, numRows); // Get the starting row index where the new rows will be added const startRowIndex = this.hot.countRows(); // Insert the new rows below the last existing row - this.hot.alter('insert_row_below', startRowIndex - 1, numRows); + this.hot.alter('insert_row_below', startRowIndex, numRows); // Validate and process the current selection - if (this.context.currentSelection !== null) { + if (this.context.currentSelection !== null && this.context.currentSelection.valueToMatch !== null) { // Find the nearest index after the last non-empty row in the specified column const baseColCoord = this.findNearestIndexAfterLastNonEmpty(0); this.populateNewRows(numRows, baseColCoord); diff --git a/lib/utils/1m.js b/lib/utils/1m.js index de60878e..3973497f 100644 --- a/lib/utils/1m.js +++ b/lib/utils/1m.js @@ -141,6 +141,25 @@ const findUniqueKeysForClass = (schema) => (cls_key) => { return unique_keys_acc; }; +const findActiveDataHarmonizer = appContext => { + // active = focused + let active_dh = null; + for (let dh_name in appContext) { + if (appContext[dh_name].active) { + active_dh = dh_name; + break; + } + } + return active_dh; +}; + +const setActiveDataHarmonizer = appContext => active_dh_name => { + for (let dh_name in appContext) { + appContext[dh_name].active = false; + } + appContext[active_dh_name].active = true; +} + const add_child_classes_to_unique_keys_for_appContext = appContext => { for (let dh_class_name in appContext) { for (let key in appContext[dh_class_name].unique_keys) { @@ -237,7 +256,6 @@ Later we can add an efficiency function that the filtering of records isn’t pe const handsontableUpdateRouter = (appContext) => (dhs) => { document.addEventListener('handsontableUpdate', (event) => { const { emitted_by, key_name, action, target } = event.detail; - // TOOD: appContext is being cached? pbv? const classCanFire = emitted_by in appContext && key_name in appContext[emitted_by].unique_keys; const unique_key = appContext[emitted_by]?.unique_keys[key_name]; @@ -250,21 +268,22 @@ const handsontableUpdateRouter = (appContext) => (dhs) => { console.groupEnd(); event.detail.target = emitted_by; handleAction(appContext)(dhs[emitted_by])(action, event.detail); - triggerCurrentSelection(makeCurrentSelection(appContext)(dhs[emitted_by])); + triggerCurrentSelection(makeCurrentSelection(appContext)(dhs[findActiveDataHarmonizer(appContext)])); } else if (action === ACTION.FILTER) { - console.log('reading', ACTION.FILTER, event.detail); + event.detail.currentSelection = makeCurrentSelection(appContext)(dhs[findActiveDataHarmonizer(appContext)]); handleAction(appContext)(dhs[target])(action, event.detail); - } else if (classHasForeignKey || !STRATEGY && classHasChildClasses) { + } else if (classHasForeignKey || classHasChildClasses ) { console.groupEnd(); // TODO: this code goes into an infinite loop? why? // TODO: can this be refactored to use namespaces for events? - if (classHasForeignKey) { - dhs[unique_key.foreign_key_class].hot.runHooks( - `classDataRowKeyChange`, - action, - event.detail - ); - } else if (classHasChildClasses) { + // if (classHasForeignKey) { + // dhs[unique_key.foreign_key_class].hot.runHooks( + // `classDataRowKeyChange`, + // action, + // event.detail + // ); + // } else + if (classHasChildClasses) { for (let dh_key of unique_key.child_classes) { const dh = dhs[dh_key]; event.detail.target = dh_key; @@ -600,30 +619,6 @@ const clearRow = (hot, rowIndex) => { } }; -function filterRowsByCondition(hotInstance, columnIndex, conditionFunction) { - const totalRows = hotInstance.countRows(); // Get total rows in the table - let rowsToHide = []; // Array to store rows to hide - - // Iterate through each row - for (let row = 0; row < totalRows; row++) { - // Get the value of the cell in the specified column - let cellValue = hotInstance.getDataAtCell(row, columnIndex); - - // If the cell value does not satisfy the condition, add the row index to rowsToHide - if (!conditionFunction(cellValue)) { - rowsToHide.push(row); - } - } - - // Use the hiddenRows plugin to hide the rows - const hiddenRowsPlugin = hotInstance.getPlugin('hiddenRows'); - hiddenRowsPlugin.showRows(hiddenRowsPlugin.getHiddenRows()); // Reset any previously hidden rows - hiddenRowsPlugin.hideRows(rowsToHide); // Hide the rows that don't meet the condition - - // Render the table to apply changes - hotInstance.render(); -} - const handleChange = (hot, [col, oldVal, newVal]) => { hot.batch(() => { const data = hot.getSourceData(); @@ -659,6 +654,52 @@ const triggerCurrentSelection = (currentSelection) => { $(document).trigger('dhCurrentSelectionChange', { currentSelection }); } +function filterRowsMatchingValueAtColumn(dh, columnIndex, valueToMatch) { + const hotInstance = dh.hot; + // Use the hiddenRows plugin to hide the rows + const hiddenRowsPlugin = hotInstance.getPlugin('hiddenRows'); + console.warn('filterRowsMatchingValueAtColumn', hiddenRowsPlugin.getHiddenRows()); + const totalRows = hotInstance.countRows(); // Get total rows in the table + hiddenRowsPlugin.showRows(hiddenRowsPlugin.getHiddenRows()); // Reset any previously hidden rows + + + let rowsToHide = []; // Array to store rows to hide + + // Iterate through each row + for (let row = 0; row < totalRows; row++) { + // Get the value of the cell in the specified column + let cellValue = hotInstance.getDataAtCell(row, columnIndex); + console.warn(row, columnIndex, cellValue, valueToMatch); + // If the cell value does not satisfy the condition, add the row index to rowsToHide + if (cellValue !== valueToMatch) { + rowsToHide.push(row); + } + } + + hiddenRowsPlugin.hideRows(rowsToHide); // Hide the rows that don't meet the condition + + // Render the table to apply changes + hotInstance.render(); +} + +function filterAllRows(dh) { + const hotInstance = dh.hot; + // Use the hiddenRows plugin to hide the rows + const hiddenRowsPlugin = hotInstance.getPlugin('hiddenRows'); + console.warn('filterAllRows', hiddenRowsPlugin.getHiddenRows()); + + hiddenRowsPlugin.showRows(hiddenRowsPlugin.getHiddenRows()); // Reset any previously hidden rows + const totalRows = hotInstance.countRows(); // Get total rows in the table + let numbers = []; + for (let i = 0; i < totalRows; i++) { + numbers.push(i); + } + hiddenRowsPlugin.hideRows(numbers); // Hide the rows that don't meet the condition + + // Render the table to apply changes + hotInstance.render(); +} + const handleAction = (appContext) => (dh) => (action, details) => { const { emitted_by, @@ -688,6 +729,7 @@ const handleAction = (appContext) => (dh) => (action, details) => { if (col !== appContext[target].column && !isEmptyUnitVal(col)) { appContext[target].column = col; } + setActiveDataHarmonizer(appContext)(target); if ('child_classes' in shared_key_details) { for (let child_class of shared_key_details.child_classes) { console.log(child_class); @@ -700,13 +742,13 @@ const handleAction = (appContext) => (dh) => (action, details) => { } break; case ACTION.FILTER: - console.log(ACTION.FILTER, emitted_by, dh.class_assignment, target, key_name); - const column = dh.getColumnIndexByFieldName(key_name); - filterRowsByCondition( - dh.hot, - column, - val => val === appContext[emitted_by].unique_keys[key_name], - ); + const { currentSelection } = details; + console.warn(ACTION.FILTER, emitted_by, dh.class_assignment, target, key_name, currentSelection); + if (currentSelection.valueToMatch === null) { + filterAllRows(dh); + } else { + filterRowsMatchingValueAtColumn(dh, appContext[target].unique_keys[key_name].key_indexes[0], currentSelection.valueToMatch); + } break; case ACTION.UPDATE: // TODO: guaranteed to be the same length? @@ -720,6 +762,7 @@ const handleAction = (appContext) => (dh) => (action, details) => { new_changes[col_index], ]); } + // read after update to update filters dispatchHandsontableUpdate(ACTION.READ, { ...details, key_name, @@ -738,16 +781,16 @@ const handleAction = (appContext) => (dh) => (action, details) => { const bindActionHandler = (appContext) => (dh) => { // TODO: key in unique_keys? // TODO: pre-processing? check if the received event is from a proper child - if (STRATEGY) { - dh.hot.addHook('classDataRowKeyChange', (action, details) => { - console.log('handling action', action); - handleAction(appContext)(dh)(action, details); - }); - } else { - dh.hot.addHook(`classDataRowKeyChange:${dh.class_assignment}`, (action, details) => { - handleAction(appContext)(dh)(action, details); - }); - } + // if (STRATEGY) { + // dh.hot.addHook('classDataRowKeyChange', (action, details) => { + // console.log('handling action', action); + // handleAction(appContext)(dh)(action, details); + // }); + // } else { + dh.hot.addHook(`classDataRowKeyChange:${dh.class_assignment}`, (action, details) => { + handleAction(appContext)(dh)(action, details); + }); + // } }; function createRowFocusTracker(hotInstance, onFocusChange) { @@ -821,6 +864,7 @@ const makeCurrentSelection = appContext => dh => { shared_key_name: unique_keys[key_name].name, // TODO: translate to "is shared key" key_name, valueToMatch: maybeValueToMatch, + parentRow: row, parentCol: column }; }