EnxDev commented on PR #42088:
URL: https://github.com/apache/superset/pull/42088#issuecomment-5339755374

   ## EnxDev's Review Agent โ€” apache/superset#42088 ยท HEAD 0d975a4
   **request changes** โ€” all six of @sadpandajoe's 2026-08-12 findings 
reproduce at this HEAD (last commit 2026-08-07), and one of them is a 
regression the HEAD commit itself introduced.
   
   Context: the three findings from 2026-08-06 (`semantic_view` coercion, 
`getCellStyle` source-vs-target, `isEqualColumns` currency inputs) are 
**genuinely fixed** โ€” verified in the code, not just claimed. The 2026-08-12 
batch has had no commits since. I re-derived each one independently below 
rather than restating it.
   
   ### ๐Ÿ”ด Functional
   
   - 
**`superset-frontend/plugins/plugin-chart-ag-grid-table/src/utils/useColDefs.ts:247-250,435-436`**
 ยท _High_ โ€” Introduced by `0d975a4` ("Fix memoization"). `ColorFormatters` 
entries carry the actual color logic in `getColorFromValue`, a function, and 
`JSON.stringify` drops it โ€” the serialized form is only 
`column`/`toAllRow`/`toTextColor`/`columnFormatting`/`objectFormatting`. 
Editing a conditional-formatting rule's color scheme, operator, or threshold 
without changing its column or scope therefore yields an identical dep string, 
`getCommonColProps` is not recreated, and `colDefs` (deps `[stringifiedCols, 
getCommonColProps]`, line 479) keeps the old closures โ€” the table keeps 
rendering the **previous** colors until something else rebuilds the columns. 
Signature over the serializable source rules (`conditional_formatting` config) 
instead of the built formatters? **regression test:** render with one rule, 
change only `targetValue`, assert the cell's `backgroundColor` changes
 .
   
   - **`superset/migrations/shared/migrate_viz/processors.py:661,886,904`** ยท 
_High_ โ€” `_get_table_chart_time_offsets` has no `isTimeComparison` gate. 
`buildQuery.ts:111,119` gates both chart-level shift branches on 
`isTimeComparison(formData, baseQueryObject)` โ€” which requires 
`comparison_type` โˆˆ `ComparisonType` **and** a non-empty metric-offset map โ€” 
and leaves only the `extra_form_data` override ungated. The migration reads 
`time_compare` unconditionally, so a chart carrying stale `time_compare` 
(comparison_type cleared, or raw mode where there are no metrics) gets 
`time_offsets` persisted into `query_context` that neither runtime chart would 
ever send. Raw mode is internally inconsistent about it too: `post_processing: 
[]` but `time_offsets` populated. Pass the base query object in and apply the 
same gate, leaving the `extra_form_data` override ungated? **regression test:** 
migrate a chart with `time_compare` set and no `comparison_type`, assert 
`query_context["queries"
 ][0]["time_offsets"] == []` โ€” nothing asserts `time_offsets` today 
(`SOURCE_FORM_DATA` has neither key).
   
   - 
**`superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx:498`**
 ยท _High_ โ€” The snapshot keys columns by `column.getColId()`, but for 
time-comparison main columns `useColDefs.ts:282-284` strips `Main ` from the 
colId while the row keeps the original key. `formatValue.ts`'s `valueGetter` is 
the proof: it rebuilds `` `Main ${params.column.getColId()}` `` to read the 
data. Since line 521 pushes raw `node.data`, Export Current View emits a 
**blank main-metric column**. Retain the data key separately from the grid 
column id in the snapshot? **regression test:** time-comparison table โ†’ sort โ†’ 
export current view โ†’ assert the main metric column has values.
   
   - 
**`superset-frontend/plugins/plugin-chart-ag-grid-table/src/stateConversion.ts:360`**
 ยท _High_ โ€” Returning `{}` when `!serverPagination` fixes the requery loop, but 
the dashboard export path builds `exportOwnState` through the same converter 
(`src/dashboard/components/gridComponents/Chart/Chart.tsx:568-575`), and 
dashboards never consume `clientView` โ€” only Explore's 
`useExploreAdditionalActionsMenu` does. Exporting a client-paginated V2 table 
from a dashboard after sorting or filtering now sends the **default** query. 
The requery suppression and the state the download needs are two different 
concerns; gate at the ownState diff/fold site rather than inside the converter? 
**regression test:** dashboard client-mode table โ†’ sort โ†’ export CSV โ†’ assert 
the request carries `sortBy`.
   
   - 
**`superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx:528`**
 ยท _Medium_ โ€” A client filter matching zero rows produces `{rows: [], count: 
0}`. The consumer gates on `ownState?.clientView?.rows?.length` 
(`useExploreAdditionalActionsMenu/index.tsx:970`), so `0` is falsy and it falls 
back to a backend query that knows nothing about the grid filter โ€” the user 
looking at an empty table exports the **entire unfiltered dataset**. Shared 
with V1's `clientView` contract rather than newly introduced, but newly 
reachable for V2. Handle an empty snapshot on the client path (headers-only 
file)? **regression test:** filter to zero rows, export current view, assert no 
backend export request is issued.
   
   - 
**`superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx:390`**
 ยท _Medium_ โ€” The init-skip guard sits *inside* the debounced body, so the 
initial `onStateUpdated` and any user sort/filter/column-move within 
`SLOW_DEBOUNCE` coalesce into one invocation that takes the 
`!hasCapturedInitialGridStateRef.current` branch and returns โ€” the first user 
change is never persisted to chart state. `handleModelUpdated` (line 488) has 
the same shape. Mark initialization before debouncing, or track the init 
signature outside the debounced closure? **regression test:** fire the init 
state event, then a sort inside the debounce window, assert 
`onColumnStateChange` fires.
   
   ### ๐ŸŸก Should-fix
   
   - **`superset/migrations/shared/migrate_viz/base.py:168-169`** โ€” 
`form_data_bak` is deep-copied *after* the synthesized `datasource` is 
injected, so `downgrade_slice` restores params carrying a `datasource` key the 
original never had. Not a clean revert. 
`test_migration_without_datasource_key_in_params` only asserts the upgrade, so 
nothing catches it. Take the backup before injecting. Benign at runtime 
(`Slice.form_data` synthesizes the same value), but this also changes downgrade 
output for the already-shipped processors that share this base.
   - **Patch coverage 58.9%, `processors.py` at 12.79% / 75 lines missing** โ€” 
the `time_offsets` gap above sits squarely in that untested region. The 
`_build_query` paths deserve assertions on the emitted `query_context`, not 
just on `params`.
   
   ### ๐Ÿ”ต Nits
   
   - `superset/migrations/shared/migrate_viz/base.py:244,272` โ€” the `unchanged` 
sentinel is dead code: every branch assigns `new_query_context`, so the guard 
is always true and the comment describes a "leave untouched" branch that 
doesn't exist.
   - 
`superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx:655`
 โ€” `<div style={gridFlexStyles}>` inline style prop; move to an Emotion 
`css`/styled block.
   - 
`superset-frontend/src/components/Chart/ChartContextMenu/ChartContextMenu.tsx:398`
 โ€” the `if (!visible)` guard assumes `visible` has flushed between AG Grid's 
two `contextmenu` events. If both land in one task the guard reads stale 
`false` and the menu still toggles closed. A test asserting two rapid `open()` 
calls leave it open would pin the assumption down.
   
   ### ๐Ÿ™Œ Praise
   
   - The three 2026-08-06 findings are fixed properly, with real assertions 
rather than smoke tests โ€” `DATASOURCE_TYPE_MAP` + 
`test_migration_preserves_semantic_view_datasource_type` asserting `{"id": 7, 
"type": "semantic_view"}` is exactly the right guard.
   - `upgrade_slice`/`downgrade_slice` deferring every slice mutation until all 
steps succeed removes a real half-migrated-slice failure mode, and the "why no 
DB migration" rationale is the right call for an `IN DEVELOPMENT` viz type.
   
   <!-- enxdev-review-agent:0d975a4 -->
   _Reviewed by EnxDev's Review Agent โ€” @EnxDev ยท HEAD 0d975a4._
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to