Skip to content

✨ Add refresh button on watched repos and local directories in Mission Explorer#4059

Merged
clubanderson merged 1 commit intomainfrom
feat/refresh-button-repos
Apr 1, 2026
Merged

✨ Add refresh button on watched repos and local directories in Mission Explorer#4059
clubanderson merged 1 commit intomainfrom
feat/refresh-button-repos

Conversation

@clubanderson
Copy link
Copy Markdown
Collaborator

Summary

  • Adds a refresh (↻) button next to each watched GitHub repo and local directory in the Mission Explorer tree sidebar
  • Button spins while loading, re-fetches the node's contents from GitHub API or local filesystem
  • Also includes the tab-hiding fix from 🐛 Fix Mission Explorer: show GitHub repo file listing #4050: directory listing now properly replaces tab content when a repo is selected

Follow-up to #4045 (YAML/MD support) and #4047 (Contents API fix).

Test plan

  • Add a GitHub repo as a watched repo → verify refresh button appears next to it
  • Click refresh → verify spinner shows and contents re-load
  • Add a local directory → verify refresh button appears
  • Verify KubeStellar Community root node does NOT show refresh button

Each watched repo and local directory in the Mission Explorer tree now
shows a refresh (↻) button that re-fetches the node's contents. The
button spins while loading and appears next to the existing trash
button for watched nodes.

Signed-off-by: Andrew Anderson <andy@clubanderson.com>
Copilot AI review requested due to automatic review settings April 1, 2026 01:47
@clubanderson clubanderson merged commit b95ef50 into main Apr 1, 2026
@kubestellar-prow kubestellar-prow bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Apr 1, 2026
@kubestellar-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@netlify
Copy link
Copy Markdown

netlify bot commented Apr 1, 2026

Deploy Preview for kubestellarconsole ready!

Name Link
🔨 Latest commit 17ccc59
🔍 Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69cc79417581570007c630ef
😎 Deploy Preview https://deploy-preview-4059.console-deploy-preview.kubestellar.io
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@kubestellar-prow kubestellar-prow bot deleted the feat/refresh-button-repos branch April 1, 2026 01:47
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

👋 Hey @clubanderson — thanks for opening this PR!

🤖 This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


This is an automated message.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 1, 2026

Thank you for your contribution! Your PR has been merged.

Check out what's new:

Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey

@kubestellar-prow kubestellar-prow bot added the size/M Denotes a PR that changes 30-99 lines, ignoring generated files. label Apr 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a per-node “refresh” action in the Mission Explorer sidebar tree so watched GitHub repos and local directories can be reloaded on demand.

Changes:

  • Adds an onRefresh callback wiring in MissionBrowser intended to force a re-fetch by clearing node state and re-triggering expansion/selection.
  • Adds a refresh (↻) icon button to TreeNodeItem for GitHub/local directory nodes, with a spin animation tied to node.loading.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
web/src/components/missions/MissionBrowser.tsx Wires onRefresh for GitHub/local watched nodes by resetting node state and attempting a collapse/re-expand sequence.
web/src/components/missions/browser/TreeNodeItem.tsx Renders a refresh icon button for eligible tree nodes and forwards onRefresh through recursion.

Comment on lines +1416 to +1418
// Re-expand after a tick to trigger the useEffect
setTimeout(() => {
toggleNode(child)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The refresh handler calls toggleNode(child) after state updates, but toggleNode decides whether to fetch based on the passed node.loaded/node.loading and the expandedNodes value captured in its closure. Because child and toggleNode here are from the pre-refresh render, this can result in no re-fetch (e.g., child.loaded is still true) and/or immediately collapsing again (stale expandedNodes still contains the id), leaving the node expanded with empty children. Refactor refresh to operate by nodeId/current state (or pass an updated node object) and avoid relying on a delayed call into a closure with stale state.

Suggested change
// Re-expand after a tick to trigger the useEffect
setTimeout(() => {
toggleNode(child)
// Re-expand after a tick to trigger the useEffect, using latest state
setTimeout(() => {
setExpandedNodes((prev) => {
const next = new Set(prev)
next.add(child.id)
return next
})

Copilot uses AI. Check for mistakes.
Comment on lines +1416 to +1420
// Re-expand after a tick to trigger the useEffect
setTimeout(() => {
toggleNode(child)
selectNode(child)
}, 50)
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

setTimeout(..., 50) here is used to sequence collapse/re-expand, but it isn’t cleaned up on unmount (dialog close) and can fire after the component unmounts, causing setState calls on an unmounted component. Prefer a synchronous/state-driven refresh flow (or keep the timeout id in a ref and clear it in a cleanup).

Suggested change
// Re-expand after a tick to trigger the useEffect
setTimeout(() => {
toggleNode(child)
selectNode(child)
}, 50)
// Re-expand and re-select synchronously to trigger the useEffect
toggleNode(child)
selectNode(child)

Copilot uses AI. Check for mistakes.
Comment on lines +1410 to +1416
// Collapse and re-expand to trigger load
setExpandedNodes((prev) => {
const next = new Set(prev)
next.delete(child.id)
return next
})
// Re-expand after a tick to trigger the useEffect
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The comment says “trigger the useEffect”, but the load-on-expand logic is implemented in toggleNode (no useEffect involved). This is misleading for future maintenance—update the comment to describe the actual mechanism (re-invoking toggleNode’s lazy-load path).

Suggested change
// Collapse and re-expand to trigger load
setExpandedNodes((prev) => {
const next = new Set(prev)
next.delete(child.id)
return next
})
// Re-expand after a tick to trigger the useEffect
// Collapse the node so a subsequent toggle will re-run lazy-load logic
setExpandedNodes((prev) => {
const next = new Set(prev)
next.delete(child.id)
return next
})
// After a short delay, re-toggle to trigger toggleNode's lazy-load path

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +114
<button
onClick={(e) => {
e.stopPropagation()
onRefresh(node)
}}
className="p-1.5 min-h-8 min-w-8 rounded hover:bg-blue-500/20 text-muted-foreground hover:text-blue-400 transition-colors flex-shrink-0"
title="Refresh contents"
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

The refresh icon is an icon-only control. Relying on title alone is not a reliable accessible name for screen readers; add an aria-label (and consider type="button" to avoid accidental form submission if this component is ever rendered inside a form).

Suggested change
<button
onClick={(e) => {
e.stopPropagation()
onRefresh(node)
}}
className="p-1.5 min-h-8 min-w-8 rounded hover:bg-blue-500/20 text-muted-foreground hover:text-blue-400 transition-colors flex-shrink-0"
title="Refresh contents"
<button
type="button"
onClick={(e) => {
e.stopPropagation()
onRefresh(node)
}}
className="p-1.5 min-h-8 min-w-8 rounded hover:bg-blue-500/20 text-muted-foreground hover:text-blue-400 transition-colors flex-shrink-0"
title="Refresh contents"
aria-label="Refresh contents"

Copilot uses AI. Check for mistakes.
@clubanderson
Copy link
Copy Markdown
Collaborator Author

🔄 Auto-Applying Copilot Code Review

Copilot code review found 4 code suggestion(s) and 0 general comment(s).

@copilot Please apply all of the following code review suggestions:

  • web/src/components/missions/MissionBrowser.tsx (line 1418): // Re-expand after a tick to trigger the useEffect, using latest state ...
  • web/src/components/missions/MissionBrowser.tsx (line 1420): // Re-expand and re-select synchronously to trigger the useEffect ...
  • web/src/components/missions/MissionBrowser.tsx (line 1416): // Collapse the node so a subsequent toggle will re-run lazy-load logic ...
  • web/src/components/missions/browser/TreeNodeItem.tsx (line 114): <button type="button" onClick={(e) => { e....

Push all fixes in a single commit. Run cd web && npm run build && npm run lint before committing.


Auto-generated by copilot-review-apply workflow.

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

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants