-
Notifications
You must be signed in to change notification settings - Fork 0
Add one-click quick actions for task management (#110) #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add one-click quick actions for task management (#110) #9
Conversation
Implement quick action buttons for the Action Required page to streamline workflow: - Add QuickActionsMenu component with Close and Add to Kanban actions - Implement closeIssue and closePullRequest methods in GitHub API client - Replace AddToKanbanButton with QuickActionsMenu in action-required page - Add hover tooltips for better UX - Support removing closed items from the list Resolves issue HappyHackingSpace#110
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughIntroduces QuickActionsMenu component to replace AddToKanbanButton, enabling users to add action items to a personal Kanban board and close GitHub issues/pull requests. Adds markAsRead method to action items store and implements GitHub API methods for closing issues and pull requests. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant QuickActionsMenu
participant Dialog
participant KanbanStore
participant Router
User->>QuickActionsMenu: Click "Add to Kanban"
QuickActionsMenu->>Dialog: Open kanban dialog
Dialog->>KanbanStore: Fetch columns & order
User->>Dialog: Select column + add notes
User->>Dialog: Confirm add
Dialog->>KanbanStore: Create task with item data
KanbanStore-->>Dialog: Task created
Dialog->>QuickActionsMenu: Show success
QuickActionsMenu->>Router: Navigate to dashboard
sequenceDiagram
participant User
participant QuickActionsMenu
participant ConfirmDialog
participant GitHubAPIClient
participant AuthStore
participant GitHub
User->>QuickActionsMenu: Click "Close"
QuickActionsMenu->>ConfirmDialog: Open confirmation
User->>ConfirmDialog: Confirm close
ConfirmDialog->>AuthStore: Get org token
ConfirmDialog->>GitHubAPIClient: closeIssue/closePullRequest
GitHubAPIClient->>GitHub: PATCH /repos/.../issues or /pulls
alt Success
GitHub-->>GitHubAPIClient: 200 OK
GitHubAPIClient-->>ConfirmDialog: {success: true}
ConfirmDialog->>QuickActionsMenu: Trigger onItemClosed
else Failure
GitHub-->>GitHubAPIClient: Error response
GitHubAPIClient-->>ConfirmDialog: {success: false, error: "..."}
ConfirmDialog->>User: Display error message
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Tip 📝 Customizable high-level summaries are now available in beta!You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.
Example:
Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later. 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
src/lib/api/github-api-client.ts (2)
1236-1320: Refactor to eliminate duplication.The
closeIssueandclosePullRequestmethods share identical logic except for the endpoint path (/issues/vs/pulls/). Consider consolidating them into a single private method.Apply this refactor:
+ private async closeItem( + owner: string, + repo: string, + number: number, + itemType: "issues" | "pulls" + ): Promise<{ success: boolean; error?: string }> { + if (!this.githubToken) { + return { success: false, error: "No GitHub token available" }; + } + + try { + const headers: HeadersInit = { + Accept: "application/vnd.github.v3+json", + "User-Agent": "GitHubMon/1.0", + Authorization: `Bearer ${this.githubToken}`, + "Content-Type": "application/json", + }; + + const response = await fetch( + `${this.baseUrl}/repos/${owner}/${repo}/${itemType}/${number}`, + { + method: "PATCH", + headers, + body: JSON.stringify({ state: "closed" }), + } + ); + + if (!response.ok) { + const errorText = await response.text(); + return { + success: false, + error: `HTTP ${response.status}: ${errorText}`, + }; + } + + return { success: true }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : "Unknown error", + }; + } + } + async closeIssue( owner: string, repo: string, issueNumber: number ): Promise<{ success: boolean; error?: string }> { - if (!this.githubToken) { - return { success: false, error: "No GitHub token available" }; - } - - try { - const headers: HeadersInit = { - Accept: "application/vnd.github.v3+json", - "User-Agent": "GitHubMon/1.0", - Authorization: `Bearer ${this.githubToken}`, - "Content-Type": "application/json", - }; - - const response = await fetch( - `${this.baseUrl}/repos/${owner}/${repo}/issues/${issueNumber}`, - { - method: "PATCH", - headers, - body: JSON.stringify({ state: "closed" }), - } - ); - - if (!response.ok) { - const errorText = await response.text(); - return { - success: false, - error: `HTTP ${response.status}: ${errorText}`, - }; - } - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : "Unknown error", - }; - } + return this.closeItem(owner, repo, issueNumber, "issues"); } async closePullRequest( owner: string, repo: string, prNumber: number ): Promise<{ success: boolean; error?: string }> { - if (!this.githubToken) { - return { success: false, error: "No GitHub token available" }; - } - - try { - const headers: HeadersInit = { - Accept: "application/vnd.github.v3+json", - "User-Agent": "GitHubMon/1.0", - Authorization: `Bearer ${this.githubToken}`, - "Content-Type": "application/json", - }; - - const response = await fetch( - `${this.baseUrl}/repos/${owner}/${repo}/pulls/${prNumber}`, - { - method: "PATCH", - headers, - body: JSON.stringify({ state: "closed" }), - } - ); - - if (!response.ok) { - const errorText = await response.text(); - return { - success: false, - error: `HTTP ${response.status}: ${errorText}`, - }; - } - - return { success: true }; - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : "Unknown error", - }; - } + return this.closeItem(owner, repo, prNumber, "pulls"); }
1236-1320: Consider cache invalidation after closing items.After successfully closing an issue or PR, the cached data for action items (assigned, mentions, stale) becomes stale. The closed item will still appear in the UI until the cache expires or is manually refreshed.
Consider invalidating relevant cache entries after a successful close:
async closeIssue( owner: string, repo: string, issueNumber: number ): Promise<{ success: boolean; error?: string }> { // ... existing implementation ... if (!response.ok) { const errorText = await response.text(); return { success: false, error: `HTTP ${response.status}: ${errorText}`, }; } + // Invalidate action items cache + const keysToDelete = Array.from(this.cache.keys()).filter((key) => + key.includes('/search/issues?q=') + ); + keysToDelete.forEach((key) => this.cache.delete(key)); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error", }; } }src/components/action-required/QuickActionsMenu.tsx (1)
116-166: Add user-facing error feedback.Errors during the close operation are only logged to the console (lines 119, 125, 156, 159). Users receive no feedback when closing fails. Consider displaying a toast notification or error message to inform users of failures.
Example using a toast library:
import { toast } from "@/components/ui/use-toast"; const handleClose = async () => { const parsed = parseRepoFromUrl(item.url); if (!parsed) { toast({ title: "Error", description: "Could not parse repository information from URL", variant: "destructive", }); setConfirmCloseOpen(false); return; } if (!orgData?.token) { toast({ title: "Error", description: "GitHub token not available", variant: "destructive", }); setConfirmCloseOpen(false); return; } // ... rest of the function ... if (result.success) { toast({ title: "Success", description: `${item.type === "issue" ? "Issue" : "PR"} closed successfully`, }); setConfirmCloseOpen(false); if (onItemClosed) { onItemClosed(item.id.toString()); } } else { toast({ title: "Failed to close", description: result.error || "Unknown error occurred", variant: "destructive", }); } };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/app/action-required/page.tsx(4 hunks)src/components/action-required/QuickActionsMenu.tsx(1 hunks)src/lib/api/github-api-client.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/app/action-required/page.tsx (1)
src/components/action-required/QuickActionsMenu.tsx (1)
QuickActionsMenu(49-370)
src/components/action-required/QuickActionsMenu.tsx (2)
src/stores/actionItems.ts (4)
ActionItem(6-24)AssignedItem(26-28)MentionItem(30-33)StalePR(35-39)src/lib/api/github-api-client.ts (1)
githubAPIClient(1323-1323)
🔇 Additional comments (2)
src/app/action-required/page.tsx (2)
356-359: LGTM! Clean integration of QuickActionsMenu.The component integration correctly passes the item and wires up the closure callback to update the store state via
handleItemClosed.
77-77: No issues found—markAsReadexists in the store with the correct signature.The verification confirms that
markAsReadis properly defined insrc/stores/actionItems.tswith the signature(type: "assigned" | "mentions" | "stale", id: string) => void, and the implementation correctly handles all three types by filtering items from the respective state arrays. The usage insrc/app/action-required/page.tsx(lines 77, 142-144) matches this signature and is correct.
| if (item.type === "issue") { | ||
| result = await githubAPIClient.closeIssue( | ||
| parsed.owner, | ||
| parsed.repo, | ||
| parsed.number | ||
| ); | ||
| } else { | ||
| result = await githubAPIClient.closePullRequest( | ||
| parsed.owner, | ||
| parsed.repo, | ||
| parsed.number | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify item type values match the condition.
The condition checks item.type === "issue", but according to the ActionItem interface in src/stores/actionItems.ts, the type is "issue" | "pullRequest". Ensure the else branch correctly handles "pullRequest" (and not "pr").
Run the following script to verify the type values used:
🏁 Script executed:
#!/bin/bash
# Description: Verify ActionItem type values and usage
# Check ActionItem type definition
rg -A 3 'type.*:.*"issue".*"pullRequest"|type.*:.*"issue".*"pr"' src/stores/actionItems.ts
# Check how item.type is set when items are created
rg 'type:.*"(issue|pr|pullRequest)"' src/lib/api/github-api-client.tsLength of output: 411
Fix type mismatch between ActionItem interface and actual runtime values.
The ActionItem interface in src/stores/actionItems.ts defines type: "issue" | "pullRequest", but actual items created in src/lib/api/github-api-client.ts use type: "pr" (not "pullRequest"). The code at lines 136-148 works by accident since the else branch handles any non-"issue" type, but the type definition is inconsistent with runtime values. Update the ActionItem interface to use type: "issue" | "pr" to match the actual data being created.
🤖 Prompt for AI Agents
In src/components/action-required/QuickActionsMenu.tsx around lines 136-148, the
code assumes runtime items use type "pr" but the ActionItem interface declares
"pullRequest"; update the ActionItem type in src/stores/actionItems.ts to
"issue" | "pr" (replace "pullRequest" with "pr") so the interface matches actual
data, then run TypeScript checks and update any other references or tests that
expect "pullRequest" to use "pr".
Implement quick action buttons for the Action Required page to streamline workflow:
Resolves issue HappyHackingSpace#110
Summary by CodeRabbit