Skip to content

Conversation

@ArjinAlbay
Copy link
Owner

@ArjinAlbay ArjinAlbay commented Nov 17, 2025

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

Summary by CodeRabbit

  • New Features
    • Added ability to close GitHub issues and pull requests directly from the action-required page.
    • Enhanced action item menu with Kanban board integration, allowing users to add items to specific columns with optional notes.
    • Implemented automatic marking of items as read when closed or actioned upon.

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
@vercel
Copy link

vercel bot commented Nov 17, 2025

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

Project Deployment Preview Comments Updated (UTC)
githubmon Ready Ready Preview Comment Nov 17, 2025 6:16pm

@coderabbitai
Copy link

coderabbitai bot commented Nov 17, 2025

Walkthrough

Introduces 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

Cohort / File(s) Summary
Page component updates
src/app/action-required/page.tsx
Replaced AddToKanbanButton with QuickActionsMenu; added handleItemClosed callback; destructured markAsRead from action items store; wired item closure events to markAsRead for per-item "read" state tracking.
New QuickActionsMenu component
src/components/action-required/QuickActionsMenu.tsx
New client component with Kanban integration (add/remove to board with column selection and notes), GitHub item closure (confirm dialog, API call with org token), local UI state management (dialogs, loading states, success confirmation), and error handling.
GitHub API client extensions
src/lib/api/github-api-client.ts
Added closeIssue and closePullRequest methods with token validation, PATCH request handling, structured error responses, and exception catching.
Action items store
useActionItemsStore
Added public markAsRead method accepting item type ("assigned" | "mentions" | "stale") and itemId to track item closure events.

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
Loading
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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • QuickActionsMenu component: Multiple dialog flows, state management complexity, and integration with stores and API client warrant careful review of logic paths and error handling.
  • GitHub API client methods: Verify token validation, PATCH request construction, and error message formatting are correct.
  • Page component updates: Confirm proper wiring of handleItemClosed callback and markAsRead method destructuring from store.
  • Store hook extension: Ensure markAsRead implementation correctly updates state for each item type.

Possibly related PRs

Poem

🐰 A menu swift with actions bright,
To Kanban boards or close with might,
GitHub's gate now sealed with care,
Quick as carrots, debts we share! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add one-click quick actions for task management' accurately summarizes the main change: introducing the QuickActionsMenu component with one-click actions (Close and Add to Kanban) for managing tasks on the Action Required page.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/resolve-github-issues-019Ta9ukzJAZDFnXUcHsTuPf

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.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example:

"Create a concise high-level summary as a bullet-point list. Then include a Markdown table showing lines added and removed by each contributing author."

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.

❤️ Share

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

Copy link

@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: 1

🧹 Nitpick comments (3)
src/lib/api/github-api-client.ts (2)

1236-1320: Refactor to eliminate duplication.

The closeIssue and closePullRequest methods 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

📥 Commits

Reviewing files that changed from the base of the PR and between eeb8b1a and c8373d0.

📒 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—markAsRead exists in the store with the correct signature.

The verification confirms that markAsRead is properly defined in src/stores/actionItems.ts with 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 in src/app/action-required/page.tsx (lines 77, 142-144) matches this signature and is correct.

Comment on lines +136 to +148
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
);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 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.ts

Length 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".

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants