Skip to content

Conversation

@cmatzenbach
Copy link
Contributor

Description

Motivation and Context

Impact

Test Plan

Contributor checklist

  • Please make sure your submission complies with our contributing guide, in particular code style and commit standards.
  • PR description addresses the issue accurately and concisely. If the change is non-trivial, a GitHub Issue is referenced.
  • Documented new properties (with its default value), SQL syntax, functions, or other functionality.
  • If release notes are required, they follow the release notes guidelines.
  • Adequate tests were added if applicable.
  • CI passed.
  • If adding new dependencies, verified they have an OpenSSF Scorecard score of 5.0 or higher (or obtained explicit TSC approval for lower scores).

Release Notes

Please follow release notes guidelines and fill in the release notes below.

== RELEASE NOTES ==

General Changes
* ... 
* ... 

Hive Connector Changes
* ... 
* ... 

If release note is NOT required, use:

== NO RELEASE NOTE ==

@cmatzenbach cmatzenbach requested review from a team and yhwang as code owners October 29, 2025 17:46
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 29, 2025

Reviewer's Guide

This PR refactors the UI layer by converting multiple React class components into functional components using hooks, modernizes helper functions into standalone arrow functions, and replaces traditional lifecycle and binding patterns with useState, useEffect, useRef, and useCallback. QueryList, QueryDetail, and QueryHeader have been updated to leverage the functional paradigm, streamlining state management, event handling, and rendering logic.

Class diagram for refactored QueryList components

classDiagram
    class QueryList {
        +useState
        +useRef
        +useEffect
        +useCallback
        +sortAndLimitQueries()
        +filterQueries()
        +refreshLoop()
        +handleSearchStringChange()
        +executeSearch()
        +handleMaxQueriesClick()
        +handleReorderClick()
        +handleSortClick()
        +handleStateFilterClick()
        +handleErrorTypeFilterClick()
        +renderMaxQueriesListItem()
        +renderReorderListItem()
        +renderSortListItem()
        +renderFilterButton()
        +renderErrorTypeListItem()
    }
    class DisplayedQueriesList {
        +queries
    }
    class QueryListItem {
        +query
        +renderWarning()
    }
    QueryList --> DisplayedQueriesList
    DisplayedQueriesList --> QueryListItem
Loading

Class diagram for refactored QueryDetail components

classDiagram
    class StageList {
        +outputStage
        +getStages()
    }
    class StageSummary {
        +stage
        +useState
        +useRef
        +useEffect
        +getExpandedIcon()
        +getExpandedStyle()
        +toggleExpanded()
        +renderHistogram()
        +renderBarChart()
        +renderTaskList()
        +renderStageExecutionAttemptsTasks()
        +handleTaskFilterClick()
        +renderTaskFilterListItem()
        +renderTaskFilter()
    }
    class RuntimeStatsList {
        +stats
        +useState
        +getExpandedIcon()
        +getExpandedStyle()
        +toggleExpanded()
        +renderMetricValue()
    }
    StageList --> StageSummary
    StageSummary --> RuntimeStatsList
Loading

Class diagram for refactored QueryHeader component

classDiagram
    class QueryHeader {
        +query
        +renderProgressBar()
        +isActive()
    }
Loading

File-Level Changes

Change Details Files
Convert QueryList-related class components to functional components with hooks
  • Replaced QueryList, QueryListItem, and DisplayedQueriesList classes with const arrow components
  • Migrated state and timers to useState/useRef and useEffect instead of setState and componentDidMount
  • Refactored filter, sort, and slice logic into standalone arrow functions with closures
  • Removed all this.bind calls, destructured props directly in function signatures
presto-ui/src/components/QueryList.jsx
Extract and modernize utility functions in QueryList
  • Transformed getHumanReadableStateFromInfo, ResourceGroupLinks, and stripQueryTextWhitespace into const arrow helpers
  • Removed static method definitions and inlined logic into pure functions
  • Adjusted JSX to call helpers directly and dropped class scoping
presto-ui/src/components/QueryList.jsx
Convert QueryDetail class components to functional components with hooks
  • Replaced RuntimeStatsList, StageSummary, and StageList classes with functional components using useState, useRef, useEffect
  • Modularized histogram and bar chart rendering into helper functions inside hooks
  • Simplified expanded/task filter toggles with state hooks and removed all this references
presto-ui/src/components/QueryDetail.jsx
Convert QueryHeader from class to functional component
  • Changed QueryHeader to a const arrow component with destructured props
  • Replaced renderProgressBar and isActive methods with inline arrow functions
  • Dropped constructor and this usage, using hooks for any internal logic
presto-ui/src/components/QueryHeader.jsx

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • QueryList bundles a lot of imperative state and ref logic—consider refactoring data fetching, filtering, and sorting into a custom hook or useReducer to replace the ad-hoc dataSet.current pattern and improve readability.
  • Tooltip initialization only runs on mount, so dynamically added items may not have working Bootstrap tooltips—consider re-initializing $('[data-bs-toggle="tooltip"]').tooltip() in a useEffect after displayedQueries change.
  • Handlers and inline render functions in large list components are recreated on every render; use useCallback or React.memo for stateless subcomponents to reduce unnecessary re-renders.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- QueryList bundles a lot of imperative state and ref logic—consider refactoring data fetching, filtering, and sorting into a custom hook or useReducer to replace the ad-hoc dataSet.current pattern and improve readability.
- Tooltip initialization only runs on mount, so dynamically added items may not have working Bootstrap tooltips—consider re-initializing $('[data-bs-toggle="tooltip"]').tooltip() in a useEffect after displayedQueries change.
- Handlers and inline render functions in large list components are recreated on every render; use useCallback or React.memo for stateless subcomponents to reduce unnecessary re-renders.

## Individual Comments

### Comment 1
<location> `presto-ui/src/components/QueryList.jsx:538-43` </location>
<code_context>
+    };

-    renderMaxQueriesListItem(maxQueries, maxQueriesText) {
+    const handleMaxQueriesClick = (newMaxQueries) => {
+        const filteredQueries = filterQueries(dataSet.current.allQueries, dataSet.current.stateFilters, dataSet.current.errorTypeFilters, dataSet.current.searchString);
+        sortAndLimitQueries(filteredQueries, dataSet.current.currentSortType, dataSet.current.currentSortOrder, newMaxQueries);
+
+        dataSet.current.maxQueries = newMaxQueries;
+        dataSet.current.displayedQueries = filteredQueries;
+        setState(prev => ({ ...prev, maxQueries: newMaxQueries, displayedQueries: filteredQueries }));
+    };
+
+    const renderMaxQueriesListItem = (maxQueriesValue, maxQueriesText) => {
</code_context>

<issue_to_address>
**suggestion:** handleMaxQueriesClick does not prevent default on anchor click.

Since the anchor uses href="#" and a click handler, not calling event.preventDefault() may cause unwanted page jumps. Pass the event to the handler and call preventDefault to avoid this issue.

Suggested implementation:

```javascript
    const handleMaxQueriesClick = (event, newMaxQueries) => {
        event.preventDefault();
        const filteredQueries = filterQueries(dataSet.current.allQueries, dataSet.current.stateFilters, dataSet.current.errorTypeFilters, dataSet.current.searchString);
        sortAndLimitQueries(filteredQueries, dataSet.current.currentSortType, dataSet.current.currentSortOrder, newMaxQueries);

        dataSet.current.maxQueries = newMaxQueries;
        dataSet.current.displayedQueries = filteredQueries;
        setState(prev => ({ ...prev, maxQueries: newMaxQueries, displayedQueries: filteredQueries }));
    };

```

```javascript
    const renderMaxQueriesListItem = (maxQueriesValue, maxQueriesText) => {
        return (
            <li>
                <a
                    href="#"
                    className={`dropdown-item text-dark ${state.maxQueries === maxQueriesValue ? "active bg-info text-white" : "text-dark"}`}
                    onClick={event => handleMaxQueriesClick(event, maxQueriesValue)}
                >
                    {maxQueriesText}
                </a>
            </li>
        );
    };

```
</issue_to_address>

### Comment 2
<location> `presto-ui/src/components/QueryDetail.jsx:510` </location>
<code_context>

</code_context>

<issue_to_address>
**issue (code-quality):** Don't reassign parameter - tasks ([`dont-reassign-parameters`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/dont-reassign-parameters))

<details><summary>Explanation</summary>Reassigning parameters can lead to unexpected behavior, especially when accessing the arguments object.
It can also cause optimization issues, especially in V8.

From the [Airbnb JavaScript Style Guide](https://airbnb.io/javascript/#functions--reassign-params)
</details>
</issue_to_address>

### Comment 3
<location> `presto-ui/src/components/QueryDetail.jsx:511` </location>
<code_context>

</code_context>

<issue_to_address>
**issue (code-quality):** Don't reassign parameter - tasks ([`dont-reassign-parameters`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/dont-reassign-parameters))

<details><summary>Explanation</summary>Reassigning parameters can lead to unexpected behavior, especially when accessing the arguments object.
It can also cause optimization issues, especially in V8.

From the [Airbnb JavaScript Style Guide](https://airbnb.io/javascript/#functions--reassign-params)
</details>
</issue_to_address>

### Comment 4
<location> `presto-ui/src/components/QueryHeader.jsx:86` </location>
<code_context>
    const queryId = query.queryId;

</code_context>

<issue_to_address>
**suggestion (code-quality):** Prefer object destructuring when accessing and using properties. ([`use-object-destructuring`](https://docs.sourcery.ai/Reference/Rules-and-In-Line-Suggestions/JavaScript/Default-Rules/use-object-destructuring))

```suggestion
    const {queryId} = query;
```

<br/><details><summary>Explanation</summary>Object destructuring can often remove an unnecessary temporary reference, as well as making your code more succinct.

From the [Airbnb Javascript Style Guide](https://airbnb.io/javascript/#destructuring--object)
</details>
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@cmatzenbach cmatzenbach changed the title Function component conversion 3 1 refactor(ui): Function component conversion, pt 2-2 Oct 29, 2025
@cmatzenbach cmatzenbach changed the title refactor(ui): Function component conversion, pt 2-2 refactor(ui): Function component conversion, pt 2-1 Oct 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant