Skip to content

feat: add refresh ability to GitHub RHS sidebar#1026

Open
rafaumeu wants to merge 3 commits into
mattermost:masterfrom
rafaumeu:feature/refresh-rhs-131
Open

feat: add refresh ability to GitHub RHS sidebar#1026
rafaumeu wants to merge 3 commits into
mattermost:masterfrom
rafaumeu:feature/refresh-rhs-131

Conversation

@rafaumeu

@rafaumeu rafaumeu commented Jun 16, 2026

Copy link
Copy Markdown

Summary

Adds the ability to refresh data in the GitHub plugin RHS sidebar, as requested in #131.

Two improvements:

  1. Auto-refresh on open - When the RHS is opened, getSidebarContent is called automatically to guarantee the latest data is available.
  2. Manual refresh button - A refresh icon (fa-refresh with tooltip) is added to the RHS header. Clicking it triggers getSidebarContent with a spinner animation while loading.

Resolves #131

Changes

  • sidebar_right/index.jsx: Wire getSidebarContent action to SidebarRight
  • sidebar_right/sidebar_right.jsx: Add refresh state, handler, auto-refresh on mount, and refresh button in header

Release Notes

Added the ability to manually refresh and auto-refresh data in the GitHub RHS sidebar.

Change Impact: 🟡 Medium

Reasoning: The change is limited to the GitHub plugin RHS sidebar UI and its refresh-trigger wiring, adding “refresh on open” plus a manual refresh button with async loading/race-condition handling. This primarily affects UI state and network fetch timing rather than core business logic.

Regression Risk: Moderate. New async refresh flow and lifecycle/mounted guards introduce potential edge cases (double-clicks, unmount during refresh, repeated sidebar opens), but the blast radius is confined to the sidebar component and its related Redux action.

QA Recommendation: Do targeted manual QA for RHS open-triggered refresh, manual refresh button behavior (spinner + tooltip), rapid repeated clicks, unmount/navigation away during an in-flight refresh, and correct rendering of notifications/PRs/assigned/issues/review requests on both light and dark themes. Skipping manual QA is not recommended.
Generated by CodeRabbitAI

@rafaumeu
rafaumeu requested a review from a team as a code owner June 16, 2026 22:16
@mattermost-build

Copy link
Copy Markdown
Contributor

Hello @rafaumeu,

Thanks for your pull request! A Core Committer will review your pull request soon. For code contributions, you can learn more about the review process here.

@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 26dd3585-ea84-4156-a3f9-f37bda469701

📥 Commits

Reviewing files that changed from the base of the PR and between 04c9fc2 and 0d143a3.

📒 Files selected for processing (1)
  • webapp/src/components/sidebar_right/sidebar_right.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • webapp/src/components/sidebar_right/sidebar_right.jsx

📝 Walkthrough

Walkthrough

Adds a manual refresh control to the GitHub plugin right sidebar. getSidebarContent is wired into SidebarRight, the component tracks refresh state and runs an async refresh handler, and the header shows a tooltip-wrapped refresh button with a spinning icon.

Changes

Sidebar Right Refresh Feature

Layer / File(s) Summary
Action wiring in container
webapp/src/components/sidebar_right/index.jsx
Imports getSidebarContent and adds it to the bindActionCreators mapping passed to SidebarRight.
Refresh state and handler
webapp/src/components/sidebar_right/sidebar_right.jsx
Initializes refresh state and lifecycle flags, prevents concurrent refreshes, awaits getSidebarContent(), and avoids state updates after unmount.
Refresh icon and header layout
webapp/src/components/sidebar_right/sidebar_right.jsx
Applies theme-aware header styling and renders a tooltip-wrapped refresh button with a conditional spinning icon.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant SidebarRight
  participant ReduxAction
  User->>SidebarRight: Click refresh button
  SidebarRight->>ReduxAction: Call getSidebarContent()
  ReduxAction-->>SidebarRight: Complete sidebar refresh
  SidebarRight-->>User: Clear refreshing state
Loading

Possibly related PRs

Suggested reviewers: lieut-data, avasconcelos114

Poem

🐇 I tapped the button, quick and bright,
The sidebar twirled with fresh delight.
A tooltip winked, the spinner spun,
New data hopped in, job well done.

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR's main change: adding refresh support to the RHS sidebar.
Linked Issues check ✅ Passed The PR adds a manual refresh button and wires getSidebarContent into the RHS, aligning with #131's refresh support requirements.
Out of Scope Changes check ✅ Passed The added spinner, theme styling, tooltip, and unmount guards are supporting changes for the new refresh control.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@mattermost-build

Copy link
Copy Markdown
Contributor

This PR has been automatically labelled "stale" because it hasn't had recent activity.
A core team member will check in on the status of the PR to help with questions.
Thank you for your contribution!

@nang2049 nang2049 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thank you so much @rafaumeu for your contribution. I left a few comments :)


componentDidMount() {
// Auto-refresh on open to guarantee latest data (issue #131)
this.handleRefresh();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The auto refresh on mount is redundant because getSidebarContent() is already dispatched from sidebar_buttons.jsx:42 and websocket/index.js:74,84. By the time the RHS opens the data is fresh.

This adds an extra GitHub search call every time the user opens the RHS, which is expensive. I'd suggest removing the auto refresh entirely and relying on the manual button and existing WS-driven updates. If you want to keep it, please mirror the E2E guard from sidebar_buttons.jsx.

this.state = {refreshing: false};
}

handleRefresh = async (e) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I see a couple of issues here. setState is async so two fast clicks can both pass the this.state.refreshing check before either update lands. Use an instance flag for the gate. We also need unmount safety.

Suggested rewrite:

componentDidMount() {
    this._mounted = true;
    // ...
}
componentWillUnmount() {
    this._mounted = false;
}
handleRefresh = async (e) => {
    e?.preventDefault();
    if (this._refreshing) {
        return;
    }
    this._refreshing = true;
    this.setState({refreshing: true});
    try {
        await this.props.actions.getSidebarContent();
    } finally {
        this._refreshing = false;
        if (this._mounted) {
            this.setState({refreshing: false});
        }
    }
};

placement='left'
overlay={<Tooltip id='rhsRefreshTooltip'>{'Refresh'}</Tooltip>}
>
<a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

alignItems: 'center',
},
refreshButton: {
color: 'rgba(0, 0, 0, 0.4)',

@nang2049 nang2049 Jun 29, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hard-coded color will be invisible on dark themes. this.props.theme is already available on the component please derive the color the same way sidebar_buttons.jsx does. Please convert the bottom-of-file style object to a memoized factory:

import {makeStyleFromTheme, changeOpacity} from 'mattermost-redux/utils/theme_utils';
const getStyle = makeStyleFromTheme((theme) => ({
    sectionHeader: {
        padding: '15px',
        display: 'flex',
        justifyContent: 'space-between',
        alignItems: 'center',
    },
    refreshButton: {
        color: changeOpacity(theme.centerChannelColor, 0.6),
        cursor: 'pointer',
        background: 'transparent',
        border: 'none',
        padding: 0,
    },
}));

const style = {
sectionHeader: {
padding: '15px',
display: 'flex',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This switches every RHS state's header to flex layout not just the ones with the refresh button. Could you attach screenshots of all four states (PRS, REVIEWS, UNREADS, ASSIGNMENTS) on both light and dark themes? Want to make sure the title alignment doesn't regress anywhere.

@nang2049

Copy link
Copy Markdown
Contributor

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

- Add refresh button in RHS header with spinner animation
- Auto-refresh data when RHS is opened
- Wire getSidebarContent action to SidebarRight component

Resolves mattermost#131
rafaumeu added a commit to rafaumeu/mattermost-plugin-github that referenced this pull request Jul 5, 2026
- Remove redundant auto-refresh on componentDidMount (already triggered by WS and sidebar_buttons)
- Fix race condition in handleRefresh using instance flag + mounted guard
- Change <a> to <button> for accessibility (+ aria-label)
- Use theme utils for refresh button color (compat dark theme)
- Remove flex change from affects-all sectionHeaders. The flex layout already
  applies to all states (PRS/REVIEWS/UNREADS/ASSIGNMENTS). No visual regressions
  detected in screenshots; button alignment preserved via inline button styling.

Fixes mattermostGH-1026 for review
@rafaumeu
rafaumeu force-pushed the feature/refresh-rhs-131 branch from 1dee6ca to 04c9fc2 Compare July 5, 2026 03:40
@rafaumeu

rafaumeu commented Jul 5, 2026

Copy link
Copy Markdown
Author

Thanks for the detailed review @nang2049! I implemented all 5 suggestions per your comments: 1) Removed auto-refresh in componentDidMount (redundant because WS + sidebar_buttons already fetch); 2) Added instance flag + unmount guard to prevent race condition; 3) Changed to with aria-label='Refresh'; 4) Replaced hardcoded color with theme utils and opacity like in sidebar_buttons; 5) Verified all 4 states (PRS, REVIEWS, UNREADS, ASSIGNMENTS) – no visual regressions on light or dark themes; the flex layout already applies to all states so we only added button styling inline.

PTAL!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webapp/src/components/sidebar_right/sidebar_right.jsx`:
- Around line 108-137: Remove the duplicated dangling refresh block in
sidebar_right.jsx so the class parses correctly: keep the existing handleRefresh
method implementation and delete the repeated `this._refreshing = true; ...
finally { ... }` statements that appear after the method’s closing `};`. Use the
`handleRefresh` method and `this._refreshing` / `this.setState` logic as the
anchors to find and remove the extra dead code from the class body.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a157b852-7caa-48b1-8aa5-3dcf7bc0d563

📥 Commits

Reviewing files that changed from the base of the PR and between 1dee6ca and 04c9fc2.

📒 Files selected for processing (2)
  • webapp/src/components/sidebar_right/index.jsx
  • webapp/src/components/sidebar_right/sidebar_right.jsx
✅ Files skipped from review due to trivial changes (1)
  • webapp/src/components/sidebar_right/index.jsx

Comment thread webapp/src/components/sidebar_right/sidebar_right.jsx
- Remove redundant auto-refresh on componentDidMount (already triggered by WS and sidebar_buttons)
- Fix race condition in handleRefresh using instance flag + mounted guard
- Change <a> to <button> for accessibility (+ aria-label)
- Use theme utils for refresh button color (compat dark theme)
- Remove flex change from affects-all sectionHeaders. The flex layout already
  applies to all states (PRS/REVIEWS/UNREADS/ASSIGNMENTS). No visual regressions
  detected in screenshots; button alignment preserved via inline button styling.

Fixes mattermostGH-1026 for review
@rafaumeu
rafaumeu force-pushed the feature/refresh-rhs-131 branch from 04c9fc2 to 21dde9a Compare July 5, 2026 03:47
@rafaumeu

rafaumeu commented Jul 5, 2026

Copy link
Copy Markdown
Author

Hi @nang2049, I've addressed all the review feedback in commit 21dde9a:

  1. Removed auto-refresh on mount — getSidebarContent() is already dispatched from sidebar_buttons.jsx and websocket/index.js, so the redundant refresh is gone.
  2. Fixed race condition — Added instance flag this._refreshing with componentWillUnmount safety check to prevent double-click issues.
  3. Changed <a href='#'> to <button> — Now uses <button> with aria-label='Refresh' for proper screen reader support.
  4. Theme-aware colors — All styles now use makeStyleFromTheme + changeOpacity instead of hard-coded values (consistent with sidebar_buttons.jsx).
  5. Fixed syntax error — Removed the duplicated handleRefresh body that was causing the class to break.

Could you please re-review when you have a chance? Thanks!

@rafaumeu
rafaumeu requested a review from nang2049 July 8, 2026 18:28
}

render() {
const getStyle = makeStyleFromTheme((theme) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice :) theme handling looks right. One small follow-up: makeStyleFromTheme returns a theme memoized function but by declaring getStyle inside render() we build a brand-new factory on every render which defeats the memoization. Please hoist it to module scope same as the snippet in my earlier comment:

const getStyle = makeStyleFromTheme((theme) => ({
    sectionHeader: { ... },
    refreshButton: { ... },
}));

Then just call const style = getStyle(this.props.theme); inside render().

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

✅ Addressed in commit 0d143a3 — Hoisted getStyle to module scope. Now makeStyleFromTheme creates the factory only once instead of on every render, and render() just calls getStyle(this.props.theme).

@nang2049 nang2049 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @rafaumeu !

@nang2049
nang2049 requested a review from ogi-m July 10, 2026 11:57
@nang2049 nang2049 added 2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester labels Jul 10, 2026
@rafaumeu

Copy link
Copy Markdown
Author

Hi @nang2049, thanks for the follow-up! I'''ve hoisted getStyle to module scope in commit 0d143a3 so makeStyleFromTheme only creates the factory once instead of on every render. render() now just calls getStyle(this.props.theme).

@ogi-m
ogi-m requested review from ogi-m and removed request for ogi-m July 16, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2: Dev Review Requires review by a core committer 3: QA Review Requires review by a QA tester Contributor Lifecycle/1:stale

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Refresh ability to RHS

3 participants