From 6d2bf8b8a3ffc1334be06c4550deffa719af7a74 Mon Sep 17 00:00:00 2001 From: David Tsay Date: Mon, 2 Dec 2024 15:44:17 -0800 Subject: [PATCH] WIP: fix reactivity on row updates --- .../telemetryTable/TelemetryTableRow.js | 13 +++-- .../collections/TableRowCollection.js | 47 +++++++++++++++---- .../components/TableComponent.vue | 2 + .../telemetryTable/components/TableRow.vue | 7 ++- 4 files changed, 54 insertions(+), 15 deletions(-) diff --git a/src/plugins/telemetryTable/TelemetryTableRow.js b/src/plugins/telemetryTable/TelemetryTableRow.js index 53083f6a9a..411830069c 100644 --- a/src/plugins/telemetryTable/TelemetryTableRow.js +++ b/src/plugins/telemetryTable/TelemetryTableRow.js @@ -91,15 +91,20 @@ export default class TelemetryTableRow { return [VIEW_DATUM_ACTION_KEY, VIEW_HISTORICAL_DATA_ACTION_KEY]; } - updateWithDatum(updatesToDatum) { - const normalizedUpdatesToDatum = createNormalizedDatum(updatesToDatum, this.columns); + /** + * Merges the row datum with the given row datum. This is used to merge rows + * when the user has selected multiple rows. + * @param {TelemetryTableRow} row + */ + updateWithDatum(row) { this.datum = { ...this.datum, - ...normalizedUpdatesToDatum + ...row.datum }; + this.fullDatum = { ...this.fullDatum, - ...updatesToDatum + ...row.fullDatum }; } } diff --git a/src/plugins/telemetryTable/collections/TableRowCollection.js b/src/plugins/telemetryTable/collections/TableRowCollection.js index 1e9fcc2f2b..74a1852e00 100644 --- a/src/plugins/telemetryTable/collections/TableRowCollection.js +++ b/src/plugins/telemetryTable/collections/TableRowCollection.js @@ -23,6 +23,10 @@ import { EventEmitter } from 'eventemitter3'; import _ from 'lodash'; import { ORDER } from '../constants.js'; +/** + * @typedef {import('.TelemetryTableRow.js').default} TelemetryTableRow + */ + /** * @constructor */ @@ -59,12 +63,6 @@ export default class TableRowCollection extends EventEmitter { let rowsToAdd = this.filterRows(rows); this.sortAndMergeRows(rowsToAdd); - - // we emit filter no matter what to trigger - // an update of visible rows - if (rowsToAdd.length > 0) { - this.emit('add', rowsToAdd); - } } clearRowsFromTableAndFilter(rows) { @@ -92,6 +90,8 @@ export default class TableRowCollection extends EventEmitter { if (this.rows.length === 0) { this.rows = sortedRows; + this.emit('add', sortedRows); + return; } @@ -124,10 +124,22 @@ export default class TableRowCollection extends EventEmitter { return foundIndex; } - updateRowInPlace(row, index) { - const foundRow = this.rows[index]; - foundRow.updateWithDatum(row.datum); - this.rows[index] = foundRow; + /** + * Incoming row exists in the collection, + * so merge existing and incoming row properties + * + * Do to reactivity of Vue, we want to emit the new row object + * @param {TelemetryTableRow} incomingRow to update rather than add to the collection + * @param {number} index of the existing row in the collection + */ + updateRowInPlace(incomingRow, index) { + // Merge the existing row with the incoming row + const existingRow = this.rows[index]; + incomingRow.updateWithDatum(existingRow); + + // Emit the updated incoming row to trigger reactivity + this.rows.splice(index, 1, incomingRow); + this.emit('update', incomingRow); } setLimit(rowLimit) { @@ -150,6 +162,8 @@ export default class TableRowCollection extends EventEmitter { } insertOrUpdateRows(rowsToAdd, addToBeginning) { + const rowsAdded = []; + rowsToAdd.forEach((row, addRowsIndex) => { const index = this.getInPlaceUpdateIndex(row); if (index > -1) { @@ -157,15 +171,22 @@ export default class TableRowCollection extends EventEmitter { } else { if (addToBeginning) { this.rows.splice(addRowsIndex, 0, row); + rowsAdded.push(row); } else { this.rows.push(row); + rowsAdded.push(row); } } }); + + if (rowsAdded.length > 0) { + this.emit('add', rowsAdded); + } } mergeSortedRows(incomingRows) { const mergedRows = []; + const addedRows = []; let existingRowIndex = 0; let incomingRowIndex = 0; @@ -184,6 +205,7 @@ export default class TableRowCollection extends EventEmitter { } else { mergedRows.push(incomingRow); incomingRowIndex++; + addedRows.push(existingRow); } } } @@ -199,10 +221,15 @@ export default class TableRowCollection extends EventEmitter { if (incomingRowIndex < incomingRows.length) { for (incomingRowIndex; incomingRowIndex < incomingRows.length; incomingRowIndex++) { mergedRows.push(incomingRows[incomingRowIndex]); + addedRows.push(incomingRows[incomingRowIndex]); } } this.rows = mergedRows; + + if (addedRows.length > 0) { + this.emit('add', addedRows); + } } firstRowInSortOrder(row1, row2) { diff --git a/src/plugins/telemetryTable/components/TableComponent.vue b/src/plugins/telemetryTable/components/TableComponent.vue index 082a4ab66d..c646d07f04 100644 --- a/src/plugins/telemetryTable/components/TableComponent.vue +++ b/src/plugins/telemetryTable/components/TableComponent.vue @@ -543,6 +543,7 @@ export default { this.table.configuration.on('change', this.handleConfigurationChanges); this.table.tableRows.on('add', this.rowsAdded); + this.table.tableRows.on('update', this.throttledUpdateVisibleRows); this.table.tableRows.on('remove', this.rowsRemoved); this.table.tableRows.on('sort', this.throttledUpdateVisibleRows); this.table.tableRows.on('filter', this.throttledUpdateVisibleRows); @@ -577,6 +578,7 @@ export default { this.table.configuration.off('change', this.handleConfigurationChanges); this.table.tableRows.off('add', this.rowsAdded); + this.table.tableRows.off('update', this.throttledUpdateVisibleRows); this.table.tableRows.off('remove', this.rowsRemoved); this.table.tableRows.off('sort', this.throttledUpdateVisibleRows); this.table.tableRows.off('filter', this.throttledUpdateVisibleRows); diff --git a/src/plugins/telemetryTable/components/TableRow.vue b/src/plugins/telemetryTable/components/TableRow.vue index 571a8ac074..91076653e9 100644 --- a/src/plugins/telemetryTable/components/TableRow.vue +++ b/src/plugins/telemetryTable/components/TableRow.vue @@ -99,6 +99,9 @@ export default { }, {}) }; }, + beforeUnmount() { + console.log('destroyed row'); + }, computed: { ariaLabel() { return this.marked ? 'Selected Table Row' : 'Table Row'; @@ -126,7 +129,9 @@ export default { watch: { rowOffset: 'calculateRowTop', row: { - handler: 'formatRow', + handler() { + this.formatRow(this.row); + }, deep: true } },