-
Notifications
You must be signed in to change notification settings - Fork 93
feat: Connect conversations to GitHub issues (#12) #47
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
feat: Connect conversations to GitHub issues (#12) #47
Conversation
conversationSummary?: string | string[] | null; | ||
} | ||
|
||
// Define the GitHub issue type |
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.
I think most of the comments in this PR are unnecessary, the code reads well on its own
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.
I will cleanup the comments
updatedAt: string; | ||
} | ||
|
||
export const GitHubIssueButton = ({ |
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.
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.
I updated the button to now be in 'command bar' instead of in conversation tabs.
checkout this commit : 7a2b578
const [selectedIssueNumber, setSelectedIssueNumber] = useState<number | null>(null); | ||
|
||
// Get conversation details to check if a GitHub issue is already linked | ||
const { data: conversation, refetch: refetchConversation } = api.mailbox.conversations.get.useQuery( |
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.
Would be a bit nicer to use useConversationContext
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.
this fixes redundancy : 3d6ba2d
<> | ||
<span className="inline-flex items-center rounded-full bg-muted px-1.5 py-0.5 text-xs font-medium text-muted-foreground mr-1"> | ||
Closed | ||
</span> | ||
<HumanizedTime time={conversation.closedAt ?? conversation.updatedAt} titlePrefix="Closed on" /> | ||
</> |
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.
This doesn't look related?
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.
fixed at : 2913a77
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.
There's still a diff (adding the fragment), please check
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.
simplified : 40bc1bc
try { | ||
setIsLoading(true); | ||
setRepositories( | ||
await utils.client.mailbox.github.repositories.query({ |
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.
useQuery
should simplify the state handling here (or let me know if there's a reason you're not using it!)
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.
tried using it, but then it bombarded with so much errors for onError
so went with this option
apps/nextjs/src/lib/github/client.ts
Outdated
|
||
return { | ||
accessToken: data.access_token, | ||
username: userResponse.data.login, |
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.
Why do we save the username?
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.
currently not any particular reason for it, but just for identification and displays purposes, that being said, its absolutely not essential part of core functionality.
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.
Let's keep things simple and remove it until we need it then
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.
simplified it : 052aaba
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.
@vikaswakde _a Thanks for the PR, the functionality looks great! I've added some initial comments (in 2 reviews because I mis-clicked ...), could you take a look?
Apologies some of these weren't clear, we haven't had a chance to document things in detail yet
apps/nextjs/src/lib/github/client.ts
Outdated
console.error("Error listing repository issues:", error); | ||
throw new Error("Failed to list issues for this repository"); |
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.
In general I think we can let things like this fail rather than having custom error handlers (if it's for the message, we should throw a tRPC error class in the procedure)
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.
fix: 2e889c3
import { createGitHubIssue, getGitHubIssue, listRepositoryIssues, updateGitHubIssueState } from "@/lib/github/client"; | ||
import { mailboxProcedure } from "./procedure"; | ||
|
||
export const githubConversationsRouter = { |
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.
How about we nest this under conversations
and use conversationProcedure
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.
nested it under conversations
and used conversationProcedure
: aea30d7
|
||
if (mailbox?.githubAccessToken) { | ||
// Map conversation status to GitHub issue state | ||
const githubState = updatedConversation.status === "closed" ? "closed" : "open"; |
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.
I don't think we should do this, "closed" for the conversation just means we've replied, not that the issue is fixed
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.
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.
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.
Sorry, missed this - let's keep this simple and remove the button
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.
(misclick again, I need coffee ...)
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.
@vikaswakde Added a few more comments; could you also check my last two above? Otherwise this is looking good!
Mind listing (or screenshotting) what permissions the GH app needs so I can test it?
const [isCreating, setIsCreating] = useState(false); | ||
const [isLinking, setIsLinking] = useState(false); | ||
const [isUpdatingState, setIsUpdatingState] = useState(false); |
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.
Can we just use isPending
from useMutation
for these?
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.
simplified : d0a71f0
) : issues && issues.length > 0 ? ( | ||
<div className="space-y-2"> | ||
<Label htmlFor="issue">Select an issue</Label> | ||
<Select |
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.
This should ideally be a combobox which searches issues matching the filter
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.
great suggestion I updated the simple selector with more ux friendly combobox : 9749f22
@@ -120,7 +126,7 @@ export function TicketCommandBar({ | |||
} | |||
break; | |||
case "ArrowLeft": | |||
if (page === "previous-replies" || page === "assignees") { | |||
if (page === "previous-replies" || page === "assignees" || page === "github-issue") { |
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.
Don't think these are needed since the github-issue page doesn't use the command component
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.
const { data: issues, isLoading: isLoadingIssues } = (api.mailbox.conversations as any).listRepositoryIssues.useQuery( | ||
{ | ||
state: "open", | ||
mailboxSlug, | ||
}, | ||
{ | ||
enabled: activeTab === "link", | ||
staleTime: 30000, | ||
}, | ||
); | ||
|
||
const conversationWithGitHub = conversation as any; |
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.
These shouldn't need as any
if tRPC is working correctly
apps/nextjs/src/lib/github/client.ts
Outdated
|
||
return { | ||
accessToken: data.access_token, | ||
username: userResponse.data.login, |
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.
Let's keep things simple and remove it until we need it then
console.log(`Updated conversation ${conversation.id} status to closed`); | ||
|
||
// Add a message to the conversation that the issue was closed | ||
await db.insert(conversationMessages).values({ |
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.
I think what we should do here is
- Use
createReply
to send a friendly message to the customer (ideally configurable in settings, but could just be hardcoded to something like "Hi, our team has resolved the issue so this should work now. Please let us know if you continue having problems.") - Add the message you have here as a note using
addNote
- notes can use markdown IIRC so would be nice to link to the issue
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.
how does this look : 93bf858
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.
Looks good. Don't think we need the logs, we can tell if it worked from whether the db records are created
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.
sure cleaned up: 9567907
@@ -120,6 +126,38 @@ export const disconnectSlack = async (mailboxId: number): Promise<void> => { | |||
.where(eq(mailboxes.id, mailboxId)); | |||
}; | |||
|
|||
export const disconnectGitHub = async (mailboxId: number): Promise<void> => { |
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.
Should (can) we also make an API call to disconnect the app in GitHub?
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.
made it : d6ffcb4
} | ||
|
||
return ( | ||
<DialogContent className="sm:max-w-[600px]"> |
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.
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.
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.
Yeah that looks good!
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.
I just changed how the command bar displays; if you commit that I'm happy to deal with the conflicts and get it working with the new design
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.
sounds great : 74f54c9
@binary-koan here is the gist where I explain the steps needed to connect and use GitHub with helper : |
(will look at this properly again tomorrow, sorry for the delay!) |
@vikaswakde I merged main and did a couple more tweaks here: #52. Could you please merge that in? Also, when I try to create an issue after connecting my GH account in settings I get this error, even though I've added the Read & write Issues permission in our GitHub app settings. I think the app is maybe authorized but not installed? Could you check if the flow is requesting the right permissions?
And could you please update the demo videos above to show the latest design so we can get Sahil's input on the UX? |
@binary-koan hello, I tried to recreate the issue but I was not able to get the similar issue, I checkout to /github-integration-fix #52 branch , and I was able to create a new issue without any error! steps I followed:
Values I entered for creating that app : Homepage URL > https://helperai.devCallback URL > https://helperai.dev/api/connect/github/callback2) get `client id` and `client secret` and update `local.env`
|
@slavingia Any feedback on the UX? (see videos in the description) Apart from working through the permissions issue I'm seeing this is good to go from my side |
Looks good! Maybe the color of the GitHub icon should change upon hover, as you can't see it. |
Screen.Recording.1403-12-25.at.10.09.57.PM.mov |
@binary-koan how to fix this |
@vikaswakde Easiest to recreate the migration:
Looks like main has an (IIRC Drizzle is planning to release a better migration tool soonish which should have a less hacky way to do it) |
so, if I could do this successfully, then should I merge main into my branch ? or what I need to do now ? |
Yeah sorry, I mean merge main after deleting the files and before running Once conflicts are solved we can merge this and I'll work on a small follow-up to fix the permissions issue (since I can reproduce it with our app) |
Signed-off-by: Vikas Wakde <110342308+vikaswakde@users.noreply.github.com>
I merged main into my branch and solved the conflicts that occurred |
Thanks! Trying to get it working with our app today (think we need to authenticate as an app instead of via OAuth), will merge once I have that |
Improves #47 so it works with our GitHub app and can be installed on other orgs
Implements GitHub integration for Helper, allowing users to:
helperai-github-integration-demo.mov
Screen.Recording.1403-12-25.at.8.31.53.PM.mov
Screen.Recording.1403-12-25.at.8.35.29.PM.mov
Screen.Recording.1403-12-25.at.9.17.54.PM.mov
This integration enables teams to track support requests and bugs directly
from Helper conversations, with bidirectional synchronization ensuring
that issue status is always up-to-date in both systems.
Closes #12