codeant-ai-for-open-source[bot] commented on code in PR #37555:
URL: https://github.com/apache/superset/pull/37555#discussion_r2834926835


##########
superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx:
##########
@@ -2205,7 +2236,7 @@ class DatasourceEditor extends PureComponent<
             </Fieldset>
           </FormContainer>
         }
-        collection={sortedMetrics}
+        collection={filteredMetrics}

Review Comment:
   **Suggestion:** Passing only the filtered metrics array into the editable 
CollectionTable means that when a user edits, reorders, or deletes metrics 
while a search filter is active, all metrics that do not match the filter will 
be dropped from the dataset because the change handler receives and saves only 
the filtered subset, not the full list. To avoid silently losing metrics, the 
table should operate on the full sorted list instead of the filtered subset. 
[logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Dataset metrics silently removed when editing under search filter.
   - ❌ Charts using removed metrics break or stop rendering.
   - ⚠️ Dataset editor can corrupt metric configuration unexpectedly.
   ```
   </details>
   
   ```suggestion
           collection={sortedMetrics}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render the dataset editor UI which uses `DatasourceEditor` (exported as
   `DataSourceComponent` at the bottom of
   
`superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx`)
   for an existing dataset that has multiple metrics in 
`props.datasource.metrics`.
   
   2. In `DatasourceEditor.render()` (around lines 2353–2371), switch to the 
"Metrics" tab,
   which calls `this.renderMetricCollection()` (defined around line 2120).
   
   3. In `renderMetricCollection()` (lines ~2120–2145), type a search string 
into the
   `<Input.Search>` control (line ~2137). This updates 
`this.state.metricSearchTerm` and
   causes `filteredMetrics` (lines ~2124–2133) to contain only metrics whose 
`metric_name` or
   `verbose_name` matches the search.
   
   4. Edit or delete a metric in the `CollectionTable` rendered in 
`renderMetricCollection()`
   (lines ~2145–2310). Because `collection={filteredMetrics}` (line 2239) and
   `onChange={this.onDatasourcePropChange.bind(this, 'metrics')}` (lines 
~2241–2242),
   `onDatasourcePropChange` (defined around lines 154–177) is called with 
*only* the filtered
   subset. It then sets `this.state.datasource.metrics` to that subset and 
triggers
   `onChange` up to the parent, permanently dropping all non-matching metrics 
from the
   dataset configuration.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx
   **Line:** 2239:2239
   **Comment:**
        *Logic Error: Passing only the filtered metrics array into the editable 
CollectionTable means that when a user edits, reorders, or deletes metrics 
while a search filter is active, all metrics that do not match the filter will 
be dropped from the dataset because the change handler receives and saves only 
the filtered subset, not the full list. To avoid silently losing metrics, the 
table should operate on the full sorted list instead of the filtered subset.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=db9c4ab7049993c84b053d7d4c8e9a8f2f1641907dd48f604f154e5108a42872&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=db9c4ab7049993c84b053d7d4c8e9a8f2f1641907dd48f604f154e5108a42872&reaction=dislike'>👎</a>



##########
superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx:
##########
@@ -2349,9 +2377,28 @@ class DatasourceEditor extends PureComponent<
                       </Button>
                     </StyledButtonWrapper>
                   </ColumnButtonWrapper>
+                  <Input.Search
+                    placeholder={t('Search columns by name')}
+                    value={this.state.columnSearchTerm}
+                    onChange={e =>
+                      this.setState({ columnSearchTerm: e.target.value })
+                    }
+                    style={{ marginBottom: 16, width: 300 }}
+                    allowClear
+                  />
                   <ColumnCollectionTable
                     className="columns-table"
-                    columns={this.state.databaseColumns}
+                    columns={
+                      this.state.columnSearchTerm
+                        ? this.state.databaseColumns.filter(col =>
+                            col.column_name
+                              ?.toLowerCase()
+                              .includes(
+                                this.state.columnSearchTerm.toLowerCase(),
+                              ),
+                          )
+                        : this.state.databaseColumns
+                    }

Review Comment:
   **Suggestion:** In the Columns tab, passing a filtered subset of columns 
into ColumnCollectionTable means that when the user edits or deletes columns 
while a search filter is active, any columns that do not match the filter will 
be removed from state because the onColumnsChange callback receives only the 
filtered subset. To prevent unintended column loss, ColumnCollectionTable 
should receive the full columns list rather than the filtered one. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Dataset columns disappear after editing under a column search.
   - ❌ Charts depending on removed columns may fail or misbehave.
   - ⚠️ Dataset schema can be unintentionally corrupted by editors.
   ```
   </details>
   
   ```suggestion
                       columns={this.state.databaseColumns}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render the dataset editor UI using `DatasourceEditor` (default export
   `DataSourceComponent` in
   
`superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx`)
   for a dataset with many physical columns in `props.datasource.columns`.
   
   2. In `DatasourceEditor.render()` (lines ~2353–2413), switch to the 
"Columns" tab. This
   renders the `<Input.Search>` for columns (lines ~2380–2388) and the
   `<ColumnCollectionTable>` (starting around line 2389).
   
   3. Type a search term in the columns search box so that 
`this.state.columnSearchTerm` is
   non-empty. The `columns` prop passed into `ColumnCollectionTable` (lines 
2391–2401)
   becomes a filtered subset of `this.state.databaseColumns`, only those whose 
`column_name`
   matches the search.
   
   4. Edit or delete a column in the filtered table. `ColumnCollectionTable` 
(defined earlier
   in the same file around lines 140–230) passes its `collection={columns}` 
prop straight to
   the underlying `CollectionTable` and forwards changes via 
`onChange={onColumnsChange}`. In
   the Columns tab, `onColumnsChange` is `databaseColumns => this.setColumns({
   databaseColumns })` (lines ~2398–2405), so `this.state.databaseColumns` is 
overwritten
   with the filtered subset, permanently dropping all non-matching columns from 
the dataset.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx
   **Line:** 2391:2401
   **Comment:**
        *Logic Error: In the Columns tab, passing a filtered subset of columns 
into ColumnCollectionTable means that when the user edits or deletes columns 
while a search filter is active, any columns that do not match the filter will 
be removed from state because the onColumnsChange callback receives only the 
filtered subset. To prevent unintended column loss, ColumnCollectionTable 
should receive the full columns list rather than the filtered one.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=8e6469611979003eee3e2ed40bcebfbdffc8afc309468087fa43938f349b8d94&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=8e6469611979003eee3e2ed40bcebfbdffc8afc309468087fa43938f349b8d94&reaction=dislike'>👎</a>



##########
superset-frontend/src/components/Datasource/components/CollectionTable/index.tsx:
##########
@@ -416,6 +435,16 @@ export default class CRUDCollection extends PureComponent<
         }
       : undefined;
 
+    // Build controlled pagination config
+    const paginationConfig: false | TablePaginationConfig | undefined =
+      pagination === false || pagination === undefined
+        ? pagination
+        : {
+            ...(typeof pagination === 'object' ? pagination : {}),
+            current: this.state.currentPage,
+            pageSize: this.state.pageSize,

Review Comment:
   **Suggestion:** When the underlying collection shrinks (for example due to 
filtering/search), the controlled `currentPage` can exceed the number of 
available pages, causing the table to render an empty page instead of 
automatically resetting to a valid page; you should clamp the current page 
based on the current collection size before passing it to the Table's 
pagination config. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ⚠️ Metrics tab search can show blank page with results.
   - ⚠️ Users may think metrics were deleted after filtering.
   - ⚠️ Affects datasource editor performance-focused metrics workflow.
   ```
   </details>
   
   ```suggestion
       const totalItems = this.state.collectionArray.length;
       const pageSize = this.state.pageSize || 10;
       const maxPage =
         totalItems > 0 ? Math.max(1, Math.ceil(totalItems / pageSize)) : 1;
       const currentPage = Math.min(this.state.currentPage || 1, maxPage);
   
       const paginationConfig: false | TablePaginationConfig | undefined =
         pagination === false || pagination === undefined
           ? pagination
           : {
               ...(typeof pagination === 'object' ? pagination : {}),
               current: currentPage,
               pageSize,
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Open any dataset in the Datasource Editor UI (implemented in
   
`superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx`,
   class `DatasourceEditor`, file start line 307) that has more than 50 metrics 
so that
   pagination is needed.
   
   2. Navigate to the "Metrics" tab, which renders the metrics table via
   `this.renderMetricCollection()` and uses `<CollectionTable />` 
(`CRUDCollection`) with
   `pagination={{ pageSize: 25, showSizeChanger: true, pageSizeOptions: [10, 
25, 50, 100] }}`
   and `collection={filteredMetrics}` (see `renderMetricCollection` in
   `DatasourceEditor.tsx`).
   
   3. In the metrics table, use the pagination controls (from
   `@superset-ui/core/components/Table`) to go to page 3; this triggers
   `CRUDCollection.handleTableChange` in `CollectionTable/index.tsx` (around 
lines 249–270),
   which updates `this.state.currentPage` to 3 without changing anything else.
   
   4. In the search box above the metrics table (`Input.Search` in 
`renderMetricCollection`),
   type a filter that reduces `filteredMetrics` to fewer than 25 items (one 
page).
   `DatasourceEditor` re-renders with the smaller `collection` prop,
   `CRUDCollection.componentDidUpdate` rebuilds `collectionArray`, but 
`currentPage` remains
   3. The subsequent `render()` call builds `paginationConfig` using the 
existing code at
   lines 438–446, passing `current: this.state.currentPage` (3) and `pageSize:
   this.state.pageSize` to `<Table>`. The table then renders an empty page 
(showing the empty
   text like "No items") even though matching metrics exist, until the user 
manually changes
   back to page 1.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/components/Datasource/components/CollectionTable/index.tsx
   **Line:** 439:445
   **Comment:**
        *Logic Error: When the underlying collection shrinks (for example due 
to filtering/search), the controlled `currentPage` can exceed the number of 
available pages, causing the table to render an empty page instead of 
automatically resetting to a valid page; you should clamp the current page 
based on the current collection size before passing it to the Table's 
pagination config.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=3c3ee2622145ac221b1232f575176ac1519cb4b3cc70fcf86208462472024cbd&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=3c3ee2622145ac221b1232f575176ac1519cb4b3cc70fcf86208462472024cbd&reaction=dislike'>👎</a>



##########
superset-frontend/src/components/Datasource/components/DatasourceEditor/components/DatasetUsageTab/index.tsx:
##########
@@ -289,15 +294,52 @@ const DatasetUsageTab = ({
     [handleSortChange, sortColumn, sortDirection],
   );
 
+  const filteredCharts = useMemo(() => {
+    if (!searchTerm) return charts;
+
+    const lowerSearch = searchTerm.toLowerCase();
+    return charts.filter(chart => {
+      // Search in chart name
+      if (chart.slice_name?.toLowerCase().includes(lowerSearch)) return true;
+
+      // Search in owner names
+      if (
+        chart.owners?.some(
+          owner =>
+            owner.first_name?.toLowerCase().includes(lowerSearch) ||
+            owner.last_name?.toLowerCase().includes(lowerSearch),
+        )
+      )
+        return true;
+
+      // Search in dashboard titles
+      if (
+        chart.dashboards?.some(dashboard =>
+          dashboard.dashboard_title?.toLowerCase().includes(lowerSearch),
+        )
+      )
+        return true;
+
+      return false;
+    });
+  }, [charts, searchTerm]);
+
   return (

Review Comment:
   **Suggestion:** When a user is on a later page and then enters a search 
term, the filtered data set can shrink to fewer pages but the `currentPage` 
state is left unchanged, so the table can request/render a non-existent page 
and show an empty "No items" state even though matches exist on page 1; 
resetting `currentPage` when search results reduce the available pages avoids 
this inconsistent pagination state. [logic error]
   
   <details>
   <summary><b>Severity Level:</b> Major ⚠️</summary>
   
   ```mdx
   - ❌ Dataset Usage search can show empty results incorrectly.
   - ⚠️ Users may think charts have no usage records.
   ```
   </details>
   
   ```suggestion
     useEffect(() => {
       if (!searchTerm) {
         return;
       }
       const maxPage = Math.max(1, Math.ceil(filteredCharts.length / 
PAGE_SIZE));
       if (currentPage > maxPage) {
         setCurrentPage(1);
       }
     }, [searchTerm, filteredCharts.length, currentPage]);
   
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Run Superset with this PR code and open a dataset in the datasource 
editor; navigate to
   the "Usage" tab which renders `DatasetUsageTab`
   
(`superset-frontend/src/components/Datasource/components/DatasourceEditor/components/DatasetUsageTab/index.tsx`).
   
   2. Ensure the selected dataset has more than `PAGE_SIZE` (25) related charts 
so that
   pagination is active; use the table pagination controls rendered by 
`<Table>` (pagination
   prop defined around lines 340–347 in the same file) to switch to page 3 or 
higher, which
   updates the `currentPage` state via `handleTableChange` and 
`handlePageChange`.
   
   3. While still on page 3+, type a search term into the search box rendered by
   `<Input.Search>` (lines 327–335), so that `searchTerm` state changes and 
`filteredCharts`
   (lines 297–325) recomputes to a non-empty subset of `charts` for that page; 
note that
   `currentPage` is not changed anywhere in response to `searchTerm`.
   
   4. Observe that the `<Table>` component receives `data={filteredCharts}` and
   `pagination={{ current: currentPage, total: filteredCharts.length, pageSize: 
PAGE_SIZE,
   ... }}` (lines 336–347); with `currentPage` still set to 3 while `total` is 
now at most 25
   (one page), the underlying table pagination logic (Ant Design-based
   `@superset-ui/core/components/Table`) will render an out-of-range page, 
resulting in an
   empty table with the `locale.emptyText` value `"No items"` even though 
`filteredCharts`
   contains matching rows for the search.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/components/Datasource/components/DatasourceEditor/components/DatasetUsageTab/index.tsx
   **Line:** 327:327
   **Comment:**
        *Logic Error: When a user is on a later page and then enters a search 
term, the filtered data set can shrink to fewer pages but the `currentPage` 
state is left unchanged, so the table can request/render a non-existent page 
and show an empty "No items" state even though matches exist on page 1; 
resetting `currentPage` when search results reduce the available pages avoids 
this inconsistent pagination state.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=37bc6d2c986961f8bc0374023a02c3e2186af69746e0b68478b8334df38896da&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=37bc6d2c986961f8bc0374023a02c3e2186af69746e0b68478b8334df38896da&reaction=dislike'>👎</a>



##########
superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx:
##########
@@ -2372,12 +2419,29 @@ class DatasourceEditor extends PureComponent<
               ),
               children: (
                 <StyledTableTabWrapper>
-                  {this.renderDefaultColumnSettings()}
-                  <DefaultColumnSettingsTitle>
-                    {t('Column Settings')}
-                  </DefaultColumnSettingsTitle>
+                  <Input.Search
+                    placeholder={t('Search calculated columns by name')}
+                    value={this.state.calculatedColumnSearchTerm}
+                    onChange={e =>
+                      this.setState({
+                        calculatedColumnSearchTerm: e.target.value,
+                      })
+                    }
+                    style={{ marginBottom: 16, width: 300 }}
+                    allowClear
+                  />
                   <ColumnCollectionTable
-                    columns={this.state.calculatedColumns}
+                    columns={
+                      this.state.calculatedColumnSearchTerm
+                        ? this.state.calculatedColumns.filter(col =>
+                            col.column_name
+                              ?.toLowerCase()
+                              .includes(
+                                
this.state.calculatedColumnSearchTerm.toLowerCase(),
+                              ),
+                          )
+                        : this.state.calculatedColumns

Review Comment:
   **Suggestion:** In the Calculated Columns tab, providing a filtered subset 
of calculated columns to ColumnCollectionTable means that edits or deletions 
performed while a search is active will cause all non-matching calculated 
columns to disappear from the dataset, since the change handler receives only 
the filtered subset. The table should instead receive the full 
calculatedColumns array to avoid inadvertently dropping hidden items. [logic 
error]
   
   <details>
   <summary><b>Severity Level:</b> Critical 🚨</summary>
   
   ```mdx
   - ❌ Non-matching calculated columns lost when editing under search.
   - ❌ Charts relying on removed calculated columns may stop working.
   - ⚠️ Dataset's derived fields can be unintentionally pruned.
   ```
   </details>
   
   ```suggestion
                     columns={this.state.calculatedColumns}
   ```
   <details>
   <summary><b>Steps of Reproduction ✅ </b></summary>
   
   ```mdx
   1. Render `DatasourceEditor` (default export `DataSourceComponent` in
   
`superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx`)
   for a dataset that has several calculated columns (columns with `expression` 
set) in
   `props.datasource.columns`.
   
   2. In `DatasourceEditor.render()` (lines ~2412–2470), switch to the 
"Calculated columns"
   tab. This tab renders an `<Input.Search>` bound to 
`this.state.calculatedColumnSearchTerm`
   (lines ~2422–2431) and a `<ColumnCollectionTable>` whose `columns` prop is 
conditionally
   filtered (lines 2433–2443).
   
   3. Enter a search term so that `this.state.calculatedColumnSearchTerm` is 
non-empty,
   causing `columns` passed to `ColumnCollectionTable` to be a filtered subset 
of
   `this.state.calculatedColumns` where `column_name` matches the search.
   
   4. Edit or delete a calculated column in the table. `ColumnCollectionTable` 
passes its
   `collection={columns}` through to `CollectionTable` and calls
   `onColumnsChange={calculatedColumns => this.setColumns({ calculatedColumns 
})}` (lines
   ~2445–2452). `setColumns` (defined around lines 200–214) then sets
   `this.state.calculatedColumns` to the filtered subset, dropping all 
non-matching
   calculated columns from state and from the dataset once `onChange` is 
propagated.
   ```
   </details>
   <details>
   <summary><b>Prompt for AI Agent 🤖 </b></summary>
   
   ```mdx
   This is a comment left during a code review.
   
   **Path:** 
superset-frontend/src/components/Datasource/components/DatasourceEditor/DatasourceEditor.tsx
   **Line:** 2433:2443
   **Comment:**
        *Logic Error: In the Calculated Columns tab, providing a filtered 
subset of calculated columns to ColumnCollectionTable means that edits or 
deletions performed while a search is active will cause all non-matching 
calculated columns to disappear from the dataset, since the change handler 
receives only the filtered subset. The table should instead receive the full 
calculatedColumns array to avoid inadvertently dropping hidden items.
   
   Validate the correctness of the flagged issue. If correct, How can I resolve 
this? If you propose a fix, implement it and please make it concise.
   ```
   </details>
   <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=a9778d0ac58859c0b1d474e92ea92a1202ad4a42bfa8e5b2a9fabf958ec24fe7&reaction=like'>👍</a>
 | <a 
href='https://app.codeant.ai/feedback?pr_url=https%3A%2F%2Fgithub.com%2Fapache%2Fsuperset%2Fpull%2F37555&comment_hash=a9778d0ac58859c0b1d474e92ea92a1202ad4a42bfa8e5b2a9fabf958ec24fe7&reaction=dislike'>👎</a>



-- 
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