Skip to content

Fix #426 Add loading states#427

Open
Anchel123 wants to merge 14 commits intostagingfrom
add-loading-states
Open

Fix #426 Add loading states#427
Anchel123 wants to merge 14 commits intostagingfrom
add-loading-states

Conversation

@Anchel123
Copy link
Copy Markdown
Contributor

@Anchel123 Anchel123 commented Mar 26, 2025

PR Type

Enhancement, Bug fix


Description

  • Added loading indicators for graph fetching and options loading.

    • Introduced isFetchingGraph state for graph loading.
    • Updated CodeGraph to display a spinner during graph fetching.
    • Enhanced Combobox to show a loading state when fetching options.
  • Improved Combobox behavior:

    • Disabled selection when no options are available and not fetching.
    • Added a spinner and message for fetching options.
  • Fixed minor issues and improved user experience:

    • Removed unnecessary debugger statement in GraphView.
    • Enhanced error handling for API fetch failures.

Changes walkthrough 📝

Relevant files
Enhancement
code-graph.tsx
Added loading state and spinner for graph fetching             

app/components/code-graph.tsx

  • Added isFetchingGraph state to manage graph loading.
  • Displayed a spinner when fetching the graph.
  • Updated UI to handle empty graph state more gracefully.
  • +16/-7   
    combobox.tsx
    Enhanced combobox with loading state and error handling   

    app/components/combobox.tsx

  • Added isFetchingOptions state for options loading.
  • Disabled combobox when no options are available.
  • Displayed spinner and messages during options fetching.
  • Improved API fetch error handling.
  • +44/-23 
    page.tsx
    Added graph loading state and improved error handling       

    app/page.tsx

  • Added isFetchingGraph state to manage graph loading.
  • Enhanced error handling for graph fetching API calls.
  • Updated CodeGraph component to use the new loading state.
  • +25/-18 
    Bug fix
    graphView.tsx
    Minor cleanup and zoom behavior improvement                           

    app/components/graphView.tsx

  • Removed unnecessary debugger statement.
  • Improved zoom behavior by resetting zoomed nodes.
  • +0/-1     

    Need help?
  • Type /help how to ... in the comments thread for any questions about Qodo Merge usage.
  • Check out the documentation for more information.
  • PR Summary by Typo

    Overview

    This PR addresses issue #426 by implementing loading states across the application, enhancing user experience during data fetching for graph visualizations and repository selection.

    Key Changes

    • Introduced isFetchingGraph state to display a loading spinner and message while fetching graph data in CodeGraph.tsx.
    • Added isFetchingOptions state and a loading spinner to the repository Combobox.tsx when fetching available repositories, along with a 30-second caching mechanism.
    • Disabled the combobox when options are being fetched or none are found.
    • Integrated the isFetchingGraph state into page.tsx to manage the loading status for graph data.
    • Removed an unnecessary debugger statement from graphView.tsx.

    Work Breakdown

    Category Lines Changed
    New Work 53 (52.0%)
    Churn 17 (16.7%)
    Refactor 32 (31.4%)
    Total Changes 102
    To turn off PR summary, please visit Notification settings.

    Summary by CodeRabbit

    • New Features

      • Graph area now shows a fetching spinner and the message “Fetching graph...” while a graph is loading.
      • Combobox shows a loading indicator and a “Fetching options...” placeholder while repository options are being retrieved.
    • Improvements

      • Repository option requests are throttled to at most once every 30 seconds.
      • Combobox is disabled during fetches and displays clear “No options found” feedback when appropriate.

    - Introduced `isFetchingGraph` state to manage loading state in the graph component.
    - Updated `CodeGraph` to display a loading spinner while fetching the graph.
    - Enhanced `Combobox` to show a loading state when fetching options.
    - Updated the Combobox component to disable the select input when there are no options and not fetching options, improving user experience.
    @vercel
    Copy link
    Copy Markdown

    vercel bot commented Mar 26, 2025

    The latest updates on your projects. Learn more about Vercel for GitHub.

    Project Deployment Review Updated (UTC)
    code-graph Error Error Dec 22, 2025 2:36pm

    @coderabbitai
    Copy link
    Copy Markdown
    Contributor

    coderabbitai bot commented Mar 26, 2025

    No actionable comments were generated in the recent review. 🎉

    ℹ️ Recent review info
    ⚙️ Run configuration

    Configuration used: defaults

    Review profile: CHILL

    Plan: Pro

    Run ID: 765a8cf7-d425-4adf-b7e5-05807f6643a4

    📥 Commits

    Reviewing files that changed from the base of the PR and between 17706ca and e3fcf8e.

    📒 Files selected for processing (3)
    • app/src/App.tsx
    • app/src/components/code-graph.tsx
    • app/src/components/combobox.tsx
    🚧 Files skipped from review as they are similar to previous changes (1)
    • app/src/components/combobox.tsx

    📝 Walkthrough

    Walkthrough

    App now tracks graph-fetching with an isFetchingGraph boolean and passes it to CodeGraph, which shows a loading UI and owns its own options state. Combobox adds throttled (30s) option fetching with loading UI, toast error handling, and refined disabled/placeholder behavior.

    Changes

    Cohort / File(s) Summary
    App & CodeGraph
    app/src/App.tsx, app/src/components/code-graph.tsx
    Added isFetchingGraph state in App; CodeGraph props updated to accept isFetchingGraph and no longer receive options/setOptions. CodeGraph now manages local options state and shows a spinner + “Fetching graph...” when isFetchingGraph is true.
    Combobox (options fetching)
    app/src/components/combobox.tsx
    Implements fetchOptions with try/catch/finally, isFetchingOptions loading state, toast-based error reporting, 30s throttling via lastFetch, conditional disabled state and placeholder text, and renders loading/empty states inside SelectContent.
    Imports/UI changes
    app/src/components/code-graph.tsx, app/src/components/combobox.tsx
    Replaced Download import with Loader2 for loading indicators; UI placeholders and select behavior updated to reflect fetching states.

    Sequence Diagram(s)

    sequenceDiagram
        participant User
        participant App
        participant CodeGraph
        participant Server
        Note over User,App: User triggers graph fetch (e.g., create/select project)
        User->>App: requestFetchGraph(repo)
        App->>CodeGraph: set isFetchingGraph = true
        App->>Server: fetch graph data(repo)
        Server-->>App: graph data / error
        App->>CodeGraph: set isFetchingGraph = false
        CodeGraph->>CodeGraph: update local options if needed
        CodeGraph-->>User: render graph or placeholder (shows spinner while fetching)
    
    Loading
    sequenceDiagram
        participant User
        participant Combobox
        participant Server
        Note over User,Combobox: User opens/selects combobox
        User->>Combobox: open()
        Combobox->>Combobox: check lastFetch (throttle 30s)
        alt allowed
          Combobox->>Server: fetch repositories
          Server-->>Combobox: repositories / error
          Combobox->>Combobox: setOptions(repos), set isFetchingOptions=false
          Combobox-->>User: show options
        else throttled
          Combobox-->>User: use cached options or show “Fetching options...” if empty
        end
    
    Loading

    Estimated code review effort

    🎯 3 (Moderate) | ⏱️ ~20 minutes

    Poem

    I nibble on code while spinners hum,
    Fetching graphs till the changes come,
    Throttled hops keep requests polite,
    Options appear in gentle light,
    A rabbit cheers — the UI’s bright! 🐰

    🚥 Pre-merge checks | ✅ 2 | ❌ 1

    ❌ Failed checks (1 warning)

    Check name Status Explanation Resolution
    Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
    ✅ Passed checks (2 passed)
    Check name Status Explanation
    Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
    Title check ✅ Passed The title 'Fix #426 Add loading states' directly summarizes the main objective of the PR, which is to implement loading states across the application for graph fetching and options loading.

    ✏️ Tip: You can configure your own custom pre-merge checks in the settings.

    ✨ Finishing Touches
    📝 Generate docstrings
    • Create stacked PR
    • Commit on current branch
    🧪 Generate unit tests (beta)
    • Create PR with unit tests
    • Commit unit tests in branch add-loading-states

    Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

    ❤️ Share

    Comment @coderabbitai help to get the list of available commands and usage tips.

    @Anchel123 Anchel123 requested a review from barakb March 26, 2025 12:48
    @Anchel123 Anchel123 linked an issue Mar 26, 2025 that may be closed by this pull request
    @qodo-code-review
    Copy link
    Copy Markdown
    Contributor

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Prop Inconsistency

    The component signature has changed with options/setOptions being moved from props to internal state, but the component is still being called with these props in page.tsx.

    const [options, setOptions] = useState<string[]>([]);
    Error Handling

    The error handling in fetchOptions doesn't properly handle network errors (like connection failures) which could cause the loading state to remain indefinitely.

    try {
        const result = await fetch(`/api/repo`, {
            method: 'GET',
        })
    
        if (!result.ok) {
            toast({
                variant: "destructive",
                title: "Uh oh! Something went wrong.",
                description: await result.text(),
            })
            return 
        }
    
        const json = await result.json()
        setOptions(json.result)
    } finally {
        setIsFetchingOptions(false)
    }

    @qodo-code-review
    Copy link
    Copy Markdown
    Contributor

    qodo-code-review bot commented Mar 26, 2025

    Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

    PR Code Suggestions ✨

    Explore these optional code suggestions:

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix parameter mismatch

    The function parameters don't match the Props interface. The options and
    setOptions parameters are missing in the function signature but are used later
    in the component. This mismatch could cause runtime errors.

    app/components/code-graph.tsx [48-58]

     export function CodeGraph({
         graph,
         data,
         setData,
         onFetchGraph,
         isFetchingGraph,
         onFetchNode,
    +    options,
    +    setOptions,
         isShowPath,
         setPath,
         chartRef,
         selectedValue,
    • Apply this suggestion
    Suggestion importance[1-10]: 9

    __

    Why: The function signature is missing the options and setOptions parameters that are defined in the Props interface and used in the component. This mismatch would cause runtime errors when the component tries to access these undefined props.

    High
    Remove duplicate state definition

    This component is redefining options and setOptions as local state, but these
    are also passed as props. This creates a conflict where the local state shadows
    the props, making the component ignore the props values and potentially causing
    inconsistent behavior.

    app/components/code-graph.tsx [85]

    -const [options, setOptions] = useState<string[]>([]);
    +// Remove this line as options and setOptions should be used from props
    +// const [options, setOptions] = useState<string[]>([]);
    • Apply this suggestion
    Suggestion importance[1-10]: 8

    __

    Why: The component defines local state for options and setOptions while also receiving them as props, creating a conflict where the local state shadows the props. This would cause the component to ignore the props values, breaking expected behavior.

    Medium
    Fix invalid select value

    The value prop is using string literals like "Fetching options..." and "No
    options found" which might not exist in the options array. This can cause React
    Select to have an invalid state where the selected value doesn't match any
    available option, potentially causing rendering issues or unexpected behavior.

    app/components/combobox.tsx [63]

    -<Select open={open} onOpenChange={setOpen} disabled={options.length === 0 && !isFetchingOptions} value={isFetchingOptions ? "Fetching options..." : options.length !== 0 ? selectedValue : "No options found"} onValueChange={onSelectedValue}>
    +<Select 
    +  open={open} 
    +  onOpenChange={setOpen} 
    +  disabled={options.length === 0 && !isFetchingOptions} 
    +  value={options.includes(selectedValue) ? selectedValue : ""} 
    +  onValueChange={onSelectedValue}
    +>
    • Apply this suggestion
    Suggestion importance[1-10]: 6

    __

    Why: The current implementation uses string literals as values that don't exist in the options array, which can cause React Select to have an invalid state. The improved code ensures the value is always valid by checking if the selectedValue exists in options.

    Low
    • Update

    AviAvni
    AviAvni previously approved these changes Apr 3, 2025
    @typo-app
    Copy link
    Copy Markdown

    typo-app bot commented Dec 22, 2025

    Static Code Review 📊

    ✅ All quality checks passed!

    Copy link
    Copy Markdown

    @typo-app typo-app bot left a comment

    Choose a reason for hiding this comment

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

    AI Code Review 🤖

    Files Reviewed: 4
    Comments Added: 1
    Lines of Code Analyzed: 134
    Critical Issues: 0

    PR Health: Excellent 🔥

    Give 👍 or 👎 on each review comment to help us improve.

    Resolve merge conflicts:
    - app/components/graphView.tsx: accept deletion (debugger fix already in staging)
    - app/page.tsx: accept deletion, apply isFetchingGraph to app/src/App.tsx
    - app/src/components/code-graph.tsx: merge Loader2+Button imports, add loading spinner
    - app/src/components/combobox.tsx: merge loading state with staging API/headers
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    …tion or class'
    
    Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
    Copy link
    Copy Markdown
    Contributor

    @coderabbitai coderabbitai bot left a comment

    Choose a reason for hiding this comment

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

    Actionable comments posted: 2

    🧹 Nitpick comments (1)
    app/src/components/combobox.tsx (1)

    61-66: Throttle timestamp set before async fetch completes.

    setLastFetch(now) is called before fetchOptions() starts. If the fetch fails, users must still wait 30 seconds before retrying. Consider moving setLastFetch into the try block after a successful fetch, or into finally, so failed fetches don't block immediate retries.

    ♻️ Proposed fix
             //check if last fetch was less than 30 seconds ago
             if (lastFetch && now - lastFetch < 30000) return;
    -        
    -        setLastFetch(now);
    -        
    -        fetchOptions()
    +
    +        fetchOptions().then(() => setLastFetch(now))
         }, [open])

    Or update the timestamp in fetchOptions after success.

    🤖 Prompt for AI Agents
    Verify each finding against the current code and only fix it if needed.
    
    In `@app/src/components/combobox.tsx` around lines 61 - 66, The throttle timestamp
    is set before the async fetch completes, which blocks retries if fetchOptions()
    fails; move the setLastFetch(now) call out of the pre-fetch path and instead
    update lastFetch only after a successful fetch (e.g. inside the try after await
    fetchOptions()) or alternatively in a finally block if you want to always record
    attempts; adjust the code around lastFetch, setLastFetch, fetchOptions and now
    so errors don't prevent immediate retry.
    
    🤖 Prompt for all review comments with AI agents
    Verify each finding against the current code and only fix it if needed.
    
    Inline comments:
    In `@app/src/components/combobox.tsx`:
    - Line 70: The Select is allowing placeholder strings to be chosen (causing
    onSelectedValue to receive "Fetching options..." or "No options found"); update
    the Select usage (component named Select with props
    open/onOpenChange/setOpen/disabled/value/onValueChange) to prevent selection of
    placeholders by disabling the control while options are loading or empty (i.e.,
    include isFetchingOptions in the disabled expression), and ensure the value
    passed is undefined/null when showing a placeholder instead of using the
    placeholder text as the selected value; alternatively remove placeholder items
    from the option list so only real options can be selected and onSelectedValue is
    only called for actual option values.
    - Around line 27-48: The fetch call in the async block that populates options
    can throw network errors which are currently swallowed; wrap the await
    fetch(...) and response handling in a try/catch (or add a catch after the
    existing try/finally) to catch exceptions, call toast with a descriptive error
    message (using the caught error.message) and ensure setIsFetchingOptions(false)
    remains in the finally; update the logic around setOptions(...) so it only runs
    on success and reference the existing symbols fetch(`/api/list_repos`),
    setOptions, setIsFetchingOptions, and toast when implementing the catch and
    toast error handling.
    
    ---
    
    Nitpick comments:
    In `@app/src/components/combobox.tsx`:
    - Around line 61-66: The throttle timestamp is set before the async fetch
    completes, which blocks retries if fetchOptions() fails; move the
    setLastFetch(now) call out of the pre-fetch path and instead update lastFetch
    only after a successful fetch (e.g. inside the try after await fetchOptions())
    or alternatively in a finally block if you want to always record attempts;
    adjust the code around lastFetch, setLastFetch, fetchOptions and now so errors
    don't prevent immediate retry.
    

    ℹ️ Review info
    ⚙️ Run configuration

    Configuration used: defaults

    Review profile: CHILL

    Plan: Pro

    Run ID: 21575903-fc11-444c-b409-d821e572aeac

    📥 Commits

    Reviewing files that changed from the base of the PR and between 887b82f and 17706ca.

    📒 Files selected for processing (3)
    • app/src/App.tsx
    • app/src/components/code-graph.tsx
    • app/src/components/combobox.tsx

    Anchel123 and others added 2 commits March 21, 2026 12:56
    - Introduced `isFetchingGraph` state to manage loading state in the graph component.
    - Updated `CodeGraph` to display a loading spinner while fetching the graph.
    - Enhanced `Combobox` to show a loading state when fetching options.
    …tion or class'
    
    Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
    @gkorland gkorland force-pushed the add-loading-states branch from 17706ca to 1b62f19 Compare March 21, 2026 10:57
    Copy link
    Copy Markdown
    Contributor

    @gkorland gkorland left a comment

    Choose a reason for hiding this comment

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

    Rebased on staging and addressed review comments:

    1. Network error handling: Added catch block in fetchOptions() to show an error toast on fetch failures (network errors were previously swallowed).

    2. Placeholder selection prevention: Disabled the Select during loading (isFetchingOptions) and when no options are available. Changed value to undefined instead of placeholder text so onSelectedValue can never receive placeholder strings.

    3. Rebase conflicts: Resolved conflicts with staging's restructured paths (app/components/app/src/components/), API changes (/api/repo/api/list_repos), and styling updates (text-gray-400text-muted-foreground).

    gkorland and others added 2 commits March 21, 2026 13:35
    Add isFetchingGraph state to App.tsx and pass it to both desktop and
    mobile CodeGraph components. Set true on fetch start, false in finally
    block so the loading spinner renders correctly.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    gkorland and others added 4 commits March 24, 2026 23:09
    The PR bundled test refactors that assumed entity classes (Function, Struct,
    Class) and a File(path, name, ext) constructor that don't exist on staging.
    Also reverts incorrect pygit2 -> gitpython switch.
    
    Keeps the frontend loading state changes (the actual purpose of this PR)
    intact while fixing all File.__init__ wrong-argument issues.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    - Add catch block for network errors with toast notification
    - Disable Select during loading and when no options available
    - Use placeholder prop instead of selectable placeholder items
    - Move lastFetch timestamp update to after successful fetch
    
    Addresses CodeRabbit review comments on combobox.tsx.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    CodeGraph now manages options locally instead of receiving them from
    App. Remove the dead props from the interface and stop passing them
    from App.tsx. The Combobox inside CodeGraph fetches options on its own.
    
    Addresses typo-app review comment about local state shadowing props.
    
    Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
    @gkorland
    Copy link
    Copy Markdown
    Contributor

    Agent Review Summary

    Comments Fixed (agreed & resolved)

    • typo-app[bot] — Local options state shadows props in code-graph.tsx → fixed in e3fcf8e — removed unused options/setOptions from Props interface and App.tsx
    • coderabbitai — Network errors silently swallowed in combobox.tsx → fixed in dafc549 — added catch block with toast notification
    • coderabbitai — Placeholder items selectable in combobox.tsx → fixed in dafc549 — disabled Select during loading, use placeholder prop
    • coderabbitai (nit) — Throttle timestamp set before fetch completes → fixed in dafc549 — moved setLastFetch to after successful fetch
    • github-code-qualityFile.__init__ wrong number of args (graph.py + 3 test files) → fixed in 78780de — reverted broken entity model changes
    • github-code-qualityimport * pollutes namespace (test_graph_ops.py) → fixed in 78780de — reverted to explicit imports
    • github-code-quality — Unused List/Optional imports (test_graph_ops.py) → fixed in 78780de — reverted test changes
    • github-code-quality — Unused Download import (code-graph.tsx) → already fixed in PR (replaced with Loader2)

    Comments Declined

    None — all actionable comments were addressed.

    Tests Added / Updated

    No new tests required — changes are frontend-only (loading states, error handling, prop cleanup).

    CI Status

    All 10 checks passing ✅ (Build, Docker, CodeQL ×4, CodeRabbit, Playwright ×2)

    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Projects

    None yet

    Development

    Successfully merging this pull request may close these issues.

    Add loading states

    3 participants