feat: add refresh ability to GitHub RHS sidebar#1026
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds automatic refresh when the RHS opens and a manual refresh control to the GitHub plugin right sidebar. Refresh actions are wired into ChangesSidebar Refresh Feature
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant SidebarButtons
participant SidebarRight
participant getSidebarContent
User->>SidebarButtons: Open or switch RHS view
SidebarButtons->>SidebarButtons: Update RHS state
SidebarButtons->>getSidebarContent: Request sidebar content
User->>SidebarRight: Click refresh button
SidebarRight->>getSidebarContent: Request sidebar content
getSidebarContent-->>SidebarButtons: Resolve refresh request
getSidebarContent-->>SidebarRight: Resolve refresh request
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
This PR has been automatically labelled "stale" because it hasn't had recent activity. |
|
|
||
| componentDidMount() { | ||
| // Auto-refresh on open to guarantee latest data (issue #131) | ||
| this.handleRefresh(); |
There was a problem hiding this comment.
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) => { |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
| alignItems: 'center', | ||
| }, | ||
| refreshButton: { | ||
| color: 'rgba(0, 0, 0, 0.4)', |
There was a problem hiding this comment.
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', |
There was a problem hiding this comment.
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.
|
@coderabbitai review |
✅ Action performedReview finished.
|
- 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
1dee6ca to
04c9fc2
Compare
|
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! |
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
webapp/src/components/sidebar_right/index.jsxwebapp/src/components/sidebar_right/sidebar_right.jsx
✅ Files skipped from review due to trivial changes (1)
- webapp/src/components/sidebar_right/index.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
04c9fc2 to
21dde9a
Compare
|
Hi @nang2049, I've addressed all the review feedback in commit 21dde9a:
Could you please re-review when you have a chance? Thanks! |
| } | ||
|
|
||
| render() { | ||
| const getStyle = makeStyleFromTheme((theme) => { |
There was a problem hiding this comment.
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().
There was a problem hiding this comment.
✅ 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).
ogi-m
left a comment
There was a problem hiding this comment.
Hi @rafaumeu, I've tested it and when the GitHub RHS panel is opened, it doesn't automatically load new data and displays stale data instead. The user must click the manual refresh button to see current data.
Screen.Recording.2026-07-20.at.14.02.44.mov
According to Claude:
Root cause: SidebarRight is permanently mounted by registerRightHandSidebarComponent — its componentDidMount fires only once at plugin load, never on panel open. The openRHS handler in sidebar_buttons.jsx only calls updateRhsState() + showRHSPlugin() with no data fetch. There is no isOpen visibility prop available to detect panel open events.
Suggested fix (webapp/src/components/sidebar_buttons/sidebar_buttons.jsx, openRHS):
openRHS = (rhsState) => {
this.props.actions.updateRhsState(rhsState);
this.props.showRHSPlugin();
if (this.props.connected) {
this.getData(); // fetch fresh data on open/tab switch
}
};
getData(), connected, and getSidebarContent are all already wired up on SidebarButtons — no other files need to change. The side effect is that switching tabs also refreshes data (acceptable, since there's no visibility prop to distinguish panel open from tab switch).
|
Just went back and read through the comments, the auto-refresh on open was removed intentionally? So now it's only about the manual button, right @rafaumeu ? |
- 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
- 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
0d143a3 to
fc68b3c
Compare
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
webapp/src/components/sidebar_buttons/sidebar_buttons.jsx (1)
63-79: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winPrevent the anchor default before returning for an in-flight refresh.
When
this.refreshingis true, Line 64 returns before Line 78 runs. A repeated click on the refresh<a href="#">then changes the URL fragment and can scroll the page.Proposed fix
getData = async (e) => { + if (e) { + e.preventDefault(); + } + if (this.refreshing) { return; } @@ - if (e) { - e.preventDefault(); - } - this.refreshing = true;🤖 Prompt for 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. In `@webapp/src/components/sidebar_buttons/sidebar_buttons.jsx` around lines 63 - 79, Update getData so an in-flight refresh still calls e.preventDefault() before returning, preventing repeated clicks on the refresh anchor from changing the URL fragment or scrolling. Preserve the existing early return and all other refresh and E2E-testing behavior.
🤖 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.
Outside diff comments:
In `@webapp/src/components/sidebar_buttons/sidebar_buttons.jsx`:
- Around line 63-79: Update getData so an in-flight refresh still calls
e.preventDefault() before returning, preventing repeated clicks on the refresh
anchor from changing the URL fragment or scrolling. Preserve the existing early
return and all other refresh and E2E-testing behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 3d443ecd-f247-4aac-a34f-c123c4dd683d
📒 Files selected for processing (4)
webapp/src/components/sidebar_buttons/sidebar_buttons.jsxwebapp/src/components/sidebar_buttons/sidebar_buttons.test.jsxwebapp/src/components/sidebar_right/index.jsxwebapp/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
|
Thanks for testing and for the detailed diagnosis, @ogi-m. Fixed in commit |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
webapp/src/components/sidebar_buttons/sidebar_buttons.test.jsx (1)
110-133: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winCover the unmount guard.
This test resolves the pending request while the component remains mounted, so it does not verify the added protection against post-unmount state updates. Unmount after starting the refresh, resolve the request, and assert that completion is harmless.
🤖 Prompt for 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. In `@webapp/src/components/sidebar_buttons/sidebar_buttons.test.jsx` around lines 110 - 133, Update the refresh pending test around renderSidebarButtons to unmount the rendered component after initiating the refresh and before resolving pendingRequest. Then resolve and await the request within act, asserting completion is harmless without post-unmount state updates; preserve the existing prevention of repeated anchor clicks.
🤖 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.
Nitpick comments:
In `@webapp/src/components/sidebar_buttons/sidebar_buttons.test.jsx`:
- Around line 110-133: Update the refresh pending test around
renderSidebarButtons to unmount the rendered component after initiating the
refresh and before resolving pendingRequest. Then resolve and await the request
within act, asserting completion is harmless without post-unmount state updates;
preserve the existing prevention of repeated anchor clicks.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: 12007cfb-08ed-4eae-8ed8-1737945f1e87
📒 Files selected for processing (2)
webapp/src/components/sidebar_buttons/sidebar_buttons.jsxwebapp/src/components/sidebar_buttons/sidebar_buttons.test.jsx
🚧 Files skipped from review as they are similar to previous changes (1)
- webapp/src/components/sidebar_buttons/sidebar_buttons.jsx
There was a problem hiding this comment.
Thanks @rafaumeu, all my earlier comments are addressed.
@ogi-m to answer your question: auto-refresh on RHS open is back but just moved to openRHS in sidebar_buttons.jsx per your suggestion instead of SidebarRight.componentDidMount since SidebarRight is permanently mounted. So you get both fresh data on open and tab-switch and the manual refresh button.
LGTM.
Summary
Adds the ability to refresh data in the GitHub plugin RHS sidebar, as requested in #131.
Two improvements:
getSidebarContentis called automatically to guarantee the latest data is available.getSidebarContentwith a spinner animation while loading.Resolves #131
Changes
sidebar_right/index.jsx: WiregetSidebarContentaction toSidebarRightsidebar_right/sidebar_right.jsx: Add refresh state, handler, auto-refresh on mount, and refresh button in headerRelease Notes
Change Impact: 🟡 Medium
Reasoning: The work is isolated to the GitHub RHS refresh UX (wiring
getSidebarContentand adding UI concurrency/unmount safety), but it introduces new async request timing and state transitions that can be sensitive to rapid user interactions and view switching.Regression Risk: Moderate due to potential race-condition edge cases (rapid opens/clicks, unmount during in-flight refresh), though the blast radius is limited to sidebar components and Redux action usage and there are targeted automated tests.
QA Recommendation: Perform targeted manual QA for RHS open/view switch triggering refresh, manual refresh button spinner/tooltip behavior, concurrent/deduped refresh while pending, unmount/navigation during refresh, and correct PRs/reviews/unreads/assignments rendering on both light and dark themes; manual QA can be skipped only if the full automated suite is green and you’ve validated the specific refresh flows in a staging environment.
Generated by CodeRabbitAI