From 36fcd40ab3f174c8ebca61d7d83b85ebb306b560 Mon Sep 17 00:00:00 2001 From: Dexter Storey <36115192+DexterStorey@users.noreply.github.com> Date: Sun, 28 Jan 2024 22:10:07 -0500 Subject: [PATCH] Teams Features (#99) * Update README.md * Teams (#97) * Add prisma adapter. Remove unused code. Add session & accounts data in database. * Update prisma scheme to allow teams * Remove unused files in favour of CSS classes * Add team name * Add util for getting current user * Update dashboard route name * Add dialog to create team * Ensure github username, name and email are stored upon auth * Ensure user id is accessible in session * Automatically create team upon new user sign in. Add option to create new teams and route accordingly. * Redirect after team is successfully created * Add route for settings & add option to delete team * Ensure nav works correctly. Add route to handle team settings. Add placeholder button. * Fetch projects for a team * Ensure only projects per team are fetched * Update schema to track requests for adding projects * Add button to create project * Break up github webhook into smaller files. Ensure team id is matched with relevant project. * Update lockfile * Ensure all pathname work. Rename repo to project for consistency. * Refactor instructions * Remove unused code * Add slug to projects * Make sure all routes are consistent * Ensure feedback works. Allow longer feedback input. * Fix * Fix nav * Fix * Add back commented code * Update stripe API route * Update env variable name * Fix * Fix * Fix * Update schema for clarity * Rename files, remove unnecessary toasts * Ensure search works * Add team slug to usage redirects. Rename repo to project for consistency. * UI fixes * Make sure all nav components are consistent * Update README.md * Schema commit * migration schema (#98) * migration schema * onboarding flow for next-auth * onboard legacy projects * only connect orphaned projects * reinstall * set rubric ts pack at latest --------- Co-authored-by: Dexter Storey <36115192+DexterStorey@users.noreply.github.com> Co-authored-by: DexterStorey --------- Co-authored-by: Sarim Malik --- .vscode/settings.json | 3 + README.md | 2 - app/{dashboard => [slug]}/(base)/layout.tsx | 4 +- app/[slug]/(base)/page.tsx | 34 +++ app/[slug]/(base)/settings/page.tsx | 15 ++ .../(base)/usage/[[...metric]]/layout.tsx | 6 +- .../(base)/usage/[[...metric]]/loading.tsx | 0 .../(base)/usage/[[...metric]]/page.tsx | 2 + app/[slug]/layout.tsx | 34 +++ .../[projectId]/instructions/page.tsx | 24 ++- .../project}/[projectId]/layout.tsx | 12 +- app/[slug]/project/[projectId]/page.tsx | 10 + .../project}/[projectId]/runs/page.tsx | 0 .../project/[projectId]/settings/page.tsx | 15 ++ app/api/webhook/github/route.ts | 198 ++++------------- app/api/webhook/stripe/route.ts | 8 +- app/dashboard/(base)/page.tsx | 40 ---- app/dashboard/layout.tsx | 23 -- .../repo/[projectId]/instructions/actions.ts | 26 --- app/dashboard/repo/[projectId]/page.tsx | 14 -- .../repo/[projectId]/settings/page.tsx | 3 - app/page.tsx | 40 +++- bun.lockb | Bin 376084 -> 386081 bytes lib/actions/add-project.ts | 43 ++++ lib/actions/create-instruction.ts | 31 +++ lib/actions/create-team.ts | 49 +++++ lib/actions/delete-instruction.ts | 17 ++ lib/actions/delete-team.ts | 40 ++++ lib/actions/feedback.ts | 23 -- lib/actions/submit-feedback.ts | 46 ++++ ...{instructions.ts => update-instruction.ts} | 0 lib/agents/engineer.ts | 4 +- lib/authOptions.ts | 51 +++-- lib/components/Auth.tsx | 2 +- lib/components/Feedback.tsx | 65 ------ .../dashboard/Buttons/PrimaryButton.tsx | 3 +- .../dashboard/Buttons/SecondaryButton.tsx | 5 +- lib/components/dashboard/Buttons/Sun.tsx | 2 +- .../dashboard/Feedback/FeedbackDialog.tsx | 25 +++ .../dashboard/Feedback/FeedbackForm.tsx | 62 ++++++ .../dashboard/Instructions/Instructions.tsx | 25 ++- .../Instructions/new-instruction.tsx | 7 +- lib/components/dashboard/Metrics/Charts.tsx | 8 +- .../dashboard/Metrics/ChartsLinks.tsx | 10 +- .../dashboard/Metrics/CustomTable.tsx | 12 +- lib/components/dashboard/Metrics/Search.tsx | 7 +- .../dashboard/Metrics/TableWrapper.tsx | 15 +- .../{Header.tsx => DashboardHeader.tsx} | 51 ++--- .../{MainNavigation.tsx => MainNav.tsx} | 15 +- .../dashboard/Navigation/ProjectNav.tsx | 48 +++++ .../dashboard/Navigation/RepoNavigation.tsx | 51 ----- .../dashboard/Navigation/TeamNav.tsx | 62 ++++++ .../dashboard/Navigation/actions.tsx | 8 - lib/components/dashboard/Navigation/index.ts | 2 - .../dashboard/Navigation/projectHeader.tsx | 21 -- .../dashboard/Projects/AddProject.tsx | 58 +++++ .../ProjectOptions.tsx} | 2 +- .../dashboard/Projects/ProjectsList.tsx | 46 ++++ .../dashboard/Repositories/Repositories.tsx | 72 ------- .../dashboard/Repositories/index.ts | 1 - lib/components/dashboard/Team/CreateTeam.tsx | 26 +++ lib/components/dashboard/Team/TeamForm.tsx | 64 ++++++ lib/components/dashboard/Text/LargeBody.tsx | 5 - .../dashboard/Text/LargeHeading.tsx | 5 - lib/components/dashboard/Text/MediumBody.tsx | 5 - lib/components/dashboard/Text/SmallBody.tsx | 5 - .../dashboard/Text/SmallHeading.tsx | 5 - lib/components/dashboard/Text/Subtext.tsx | 5 - lib/components/dashboard/Text/index.ts | 6 - lib/components/ui/button.tsx | 6 +- lib/env.mjs | 6 +- lib/styles/globals.css | 1 - lib/tools/commitCode.ts | 4 +- lib/tools/updateInstructions.ts | 9 +- lib/{types.ts => types/index.ts} | 0 lib/types/prisma.ts | 5 + lib/utils.ts | 8 + lib/utils/github.ts | 199 +++++++++++++++++- lib/utils/payment.ts | 4 +- lib/utils/session.ts | 8 + package.json | 175 +++++++-------- prisma/schema.prisma | 188 ++++++++++++++--- types/next-auth.d.ts | 12 +- 83 files changed, 1452 insertions(+), 801 deletions(-) rename app/{dashboard => [slug]}/(base)/layout.tsx (75%) create mode 100644 app/[slug]/(base)/page.tsx create mode 100644 app/[slug]/(base)/settings/page.tsx rename app/{dashboard => [slug]}/(base)/usage/[[...metric]]/layout.tsx (88%) rename app/{dashboard => [slug]}/(base)/usage/[[...metric]]/loading.tsx (100%) rename app/{dashboard => [slug]}/(base)/usage/[[...metric]]/page.tsx (90%) create mode 100644 app/[slug]/layout.tsx rename app/{dashboard/repo => [slug]/project}/[projectId]/instructions/page.tsx (57%) rename app/{dashboard/repo => [slug]/project}/[projectId]/layout.tsx (61%) create mode 100644 app/[slug]/project/[projectId]/page.tsx rename app/{dashboard/repo => [slug]/project}/[projectId]/runs/page.tsx (100%) create mode 100644 app/[slug]/project/[projectId]/settings/page.tsx delete mode 100644 app/dashboard/(base)/page.tsx delete mode 100644 app/dashboard/layout.tsx delete mode 100644 app/dashboard/repo/[projectId]/instructions/actions.ts delete mode 100644 app/dashboard/repo/[projectId]/page.tsx delete mode 100644 app/dashboard/repo/[projectId]/settings/page.tsx create mode 100644 lib/actions/add-project.ts create mode 100644 lib/actions/create-instruction.ts create mode 100644 lib/actions/create-team.ts create mode 100644 lib/actions/delete-instruction.ts create mode 100644 lib/actions/delete-team.ts delete mode 100644 lib/actions/feedback.ts create mode 100644 lib/actions/submit-feedback.ts rename lib/actions/{instructions.ts => update-instruction.ts} (100%) delete mode 100644 lib/components/Feedback.tsx create mode 100644 lib/components/dashboard/Feedback/FeedbackDialog.tsx create mode 100644 lib/components/dashboard/Feedback/FeedbackForm.tsx rename lib/components/dashboard/Navigation/{Header.tsx => DashboardHeader.tsx} (61%) rename lib/components/dashboard/Navigation/{MainNavigation.tsx => MainNav.tsx} (71%) create mode 100644 lib/components/dashboard/Navigation/ProjectNav.tsx delete mode 100644 lib/components/dashboard/Navigation/RepoNavigation.tsx create mode 100644 lib/components/dashboard/Navigation/TeamNav.tsx delete mode 100644 lib/components/dashboard/Navigation/actions.tsx delete mode 100644 lib/components/dashboard/Navigation/index.ts delete mode 100644 lib/components/dashboard/Navigation/projectHeader.tsx create mode 100644 lib/components/dashboard/Projects/AddProject.tsx rename lib/components/dashboard/{Repositories/options.tsx => Projects/ProjectOptions.tsx} (92%) create mode 100644 lib/components/dashboard/Projects/ProjectsList.tsx delete mode 100644 lib/components/dashboard/Repositories/Repositories.tsx delete mode 100644 lib/components/dashboard/Repositories/index.ts create mode 100644 lib/components/dashboard/Team/CreateTeam.tsx create mode 100644 lib/components/dashboard/Team/TeamForm.tsx delete mode 100644 lib/components/dashboard/Text/LargeBody.tsx delete mode 100644 lib/components/dashboard/Text/LargeHeading.tsx delete mode 100644 lib/components/dashboard/Text/MediumBody.tsx delete mode 100644 lib/components/dashboard/Text/SmallBody.tsx delete mode 100644 lib/components/dashboard/Text/SmallHeading.tsx delete mode 100644 lib/components/dashboard/Text/Subtext.tsx delete mode 100644 lib/components/dashboard/Text/index.ts rename lib/{types.ts => types/index.ts} (100%) create mode 100644 lib/types/prisma.ts create mode 100644 lib/utils/session.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 432bb85b..b85dd206 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,5 +9,8 @@ "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" + }, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" } } diff --git a/README.md b/README.md index 4505a565..67eb29f1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # Maige -_Staging2_ - Repo maintenance made simpler. Quickly set up Maige and let AI handle your issue labels with ease. Get started at [Maige.app](https://maige.app). diff --git a/app/dashboard/(base)/layout.tsx b/app/[slug]/(base)/layout.tsx similarity index 75% rename from app/dashboard/(base)/layout.tsx rename to app/[slug]/(base)/layout.tsx index 201305d2..a7ce2127 100644 --- a/app/dashboard/(base)/layout.tsx +++ b/app/[slug]/(base)/layout.tsx @@ -1,5 +1,5 @@ import {Toaster} from 'sonner' -import {MainNavigation} from '~/components/dashboard/Navigation' +import MainNav from '~/components/dashboard/Navigation/MainNav' export default async function RootLayout({ children @@ -9,7 +9,7 @@ export default async function RootLayout({ return (
- +
{children}
) diff --git a/app/[slug]/(base)/page.tsx b/app/[slug]/(base)/page.tsx new file mode 100644 index 00000000..3513838a --- /dev/null +++ b/app/[slug]/(base)/page.tsx @@ -0,0 +1,34 @@ +import {redirect} from 'next/navigation' +import {Suspense} from 'react' +import Projects from '~/components/dashboard/Projects/ProjectsList' +import {getCurrentUser} from '~/utils/session' + +export default async function Dashboard({params}: {params: {slug: string}}) { + const user = await getCurrentUser() + if (!user) redirect('/') + + const team = await prisma.team.findUnique({ + where: {slug: params.slug}, + select: {id: true} + }) + const projects = await prisma.project.findMany({ + where: { + teamId: team.id + }, + include: { + instructions: true + } + }) + + return ( +
+ Loading...

}> + +
+
+ ) +} diff --git a/app/[slug]/(base)/settings/page.tsx b/app/[slug]/(base)/settings/page.tsx new file mode 100644 index 00000000..6747fc11 --- /dev/null +++ b/app/[slug]/(base)/settings/page.tsx @@ -0,0 +1,15 @@ +import {TrashIcon} from 'lucide-react' +import {Button} from '~/components/ui/button' + +export default function Settings() { + return ( +
+

Settings

+ +
+ ) +} diff --git a/app/dashboard/(base)/usage/[[...metric]]/layout.tsx b/app/[slug]/(base)/usage/[[...metric]]/layout.tsx similarity index 88% rename from app/dashboard/(base)/usage/[[...metric]]/layout.tsx rename to app/[slug]/(base)/usage/[[...metric]]/layout.tsx index af04345b..0c49da19 100644 --- a/app/dashboard/(base)/usage/[[...metric]]/layout.tsx +++ b/app/[slug]/(base)/usage/[[...metric]]/layout.tsx @@ -10,6 +10,7 @@ export default async function RootLayout({ }: { children: React.ReactNode params: { + slug: string metric: string[] | undefined } }) { @@ -24,7 +25,10 @@ export default async function RootLayout({ return (
- +
{children} diff --git a/app/dashboard/(base)/usage/[[...metric]]/loading.tsx b/app/[slug]/(base)/usage/[[...metric]]/loading.tsx similarity index 100% rename from app/dashboard/(base)/usage/[[...metric]]/loading.tsx rename to app/[slug]/(base)/usage/[[...metric]]/loading.tsx diff --git a/app/dashboard/(base)/usage/[[...metric]]/page.tsx b/app/[slug]/(base)/usage/[[...metric]]/page.tsx similarity index 90% rename from app/dashboard/(base)/usage/[[...metric]]/page.tsx rename to app/[slug]/(base)/usage/[[...metric]]/page.tsx index 975147a0..1e2b2758 100644 --- a/app/dashboard/(base)/usage/[[...metric]]/page.tsx +++ b/app/[slug]/(base)/usage/[[...metric]]/page.tsx @@ -6,6 +6,7 @@ export default async function Usage({ }: { searchParams: {[key: string]: string | string[] | undefined} params: { + slug: string metric: string[] | undefined } }) { @@ -13,6 +14,7 @@ export default async function Usage({ return ( diff --git a/app/[slug]/layout.tsx b/app/[slug]/layout.tsx new file mode 100644 index 00000000..a170c0e7 --- /dev/null +++ b/app/[slug]/layout.tsx @@ -0,0 +1,34 @@ +import DashboardHeader from '~/components/dashboard/Navigation/DashboardHeader' +import {getCurrentUser} from '~/utils/session' + +async function Teams() { + const user = await getCurrentUser() + if (!user) return <> + + const teams = await prisma.membership + .findMany({ + where: {userId: user.id}, + select: {team: true} + }) + .then(memberships => memberships.map(m => m.team)) + + return ( + + ) +} + +export default async function RootLayout({ + children +}: { + children: React.ReactNode +}) { + return ( +
+ +
{children}
+
+ ) +} diff --git a/app/dashboard/repo/[projectId]/instructions/page.tsx b/app/[slug]/project/[projectId]/instructions/page.tsx similarity index 57% rename from app/dashboard/repo/[projectId]/instructions/page.tsx rename to app/[slug]/project/[projectId]/instructions/page.tsx index 8b9d0b5d..dc691e16 100644 --- a/app/dashboard/repo/[projectId]/instructions/page.tsx +++ b/app/[slug]/project/[projectId]/instructions/page.tsx @@ -3,26 +3,40 @@ import {Instructions} from '~/components/dashboard/Instructions' import {PanelSkeletons} from '~/components/dashboard/Loader' import prisma from '~/prisma' -export default async function Page({params}: {params: {projectId: string}}) { +export default async function Page({ + params +}: { + params: {projectId: string; slug: string} +}) { return ( }>
-
Custom Instructions
- +

Instructions

+
) } -async function InstructionsWrapper({projectId}: {projectId: string}) { +async function InstructionsWrapper({ + projectId, + teamSlug +}: { + projectId: string + teamSlug: string +}) { const instructions = await prisma.instruction.findMany({ where: { - projectId + projectId: projectId } }) return ( diff --git a/app/dashboard/repo/[projectId]/layout.tsx b/app/[slug]/project/[projectId]/layout.tsx similarity index 61% rename from app/dashboard/repo/[projectId]/layout.tsx rename to app/[slug]/project/[projectId]/layout.tsx index 23179cd0..0177ba72 100644 --- a/app/dashboard/repo/[projectId]/layout.tsx +++ b/app/[slug]/project/[projectId]/layout.tsx @@ -1,20 +1,24 @@ import {getServerSession} from 'next-auth' import {redirect} from 'next/navigation' import {authOptions} from '~/authOptions' -import {RepoNavigation} from '~/components/dashboard/Navigation/RepoNavigation' +import ProjectNav from '~/components/dashboard/Navigation/ProjectNav' export default async function Layout({ + params, children }: { - params: {projectId: string} + params: {slug: string; projectId: string} children: React.ReactNode }) { const session = await getServerSession(authOptions) - if (!session) redirect('/dashboard') + if (!session) redirect('/') return (
- +
{children}
) diff --git a/app/[slug]/project/[projectId]/page.tsx b/app/[slug]/project/[projectId]/page.tsx new file mode 100644 index 00000000..ca2dfbd9 --- /dev/null +++ b/app/[slug]/project/[projectId]/page.tsx @@ -0,0 +1,10 @@ +export default async function Page({params}: {params: {projectId: string}}) { + const project = await prisma.project.findUnique({ + where: {id: params.projectId} + }) + return ( +
+

{project.name}

+
+ ) +} diff --git a/app/dashboard/repo/[projectId]/runs/page.tsx b/app/[slug]/project/[projectId]/runs/page.tsx similarity index 100% rename from app/dashboard/repo/[projectId]/runs/page.tsx rename to app/[slug]/project/[projectId]/runs/page.tsx diff --git a/app/[slug]/project/[projectId]/settings/page.tsx b/app/[slug]/project/[projectId]/settings/page.tsx new file mode 100644 index 00000000..e62b1c8b --- /dev/null +++ b/app/[slug]/project/[projectId]/settings/page.tsx @@ -0,0 +1,15 @@ +import {TrashIcon} from 'lucide-react' +import {Button} from '~/components/ui/button' + +export default function Settings() { + return ( +
+

Settings

+ +
+ ) +} diff --git a/app/api/webhook/github/route.ts b/app/api/webhook/github/route.ts index 4bce32c2..a2122e54 100644 --- a/app/api/webhook/github/route.ts +++ b/app/api/webhook/github/route.ts @@ -1,12 +1,13 @@ import {App} from '@octokit/app' import {maige} from '~/agents/maige' -import {GITHUB} from '~/constants' import env from '~/env.mjs' -import prisma from '~/prisma' import {stripe} from '~/stripe' -import {Label, Repository} from '~/types' -import Weaviate from '~/utils/embeddings/db' -import {getMainBranch, getRepoMeta, openUsageIssue} from '~/utils/github' +import {Label} from '~/types' +import { + getRepoMeta, + handleInstallationEvents, + openUsageIssue +} from '~/utils/github' import {validateSignature} from '~/utils/index' import {incrementUsage} from '~/utils/payment' @@ -29,131 +30,13 @@ export const POST = async (req: Request) => { } const payload = JSON.parse(text) - const {action} = payload - - /** - * Installation-related events. Sync repos/user to database. - */ - if (payload?.installation?.account?.login) { - const { - installation: { - account: {login} - } - } = payload - - if (action === 'created') { - // Installed GitHub App - - const {repositories} = payload - - const customer = await prisma.customer.create({ - data: { - name: login, - projects: { - create: repositories.map((repo: Repository) => ({ - name: repo.name - })) - } - } - }) - - // Clone, vectorize, and save public code to database - const vectorDB = new Weaviate(customer.id) - - for (const repo of repositories) { - const branch = await getMainBranch(repo.full_name) - - await vectorDB.embedRepo(repo.full_name, branch) - } - - return new Response(`Added customer ${login}`) - } else if (action === 'deleted') { - // Uninstalled GitHub App - - try { - await prisma.customer.delete({ - where: { - name: login - } - }) - } catch (error) { - console.warn(error) - } - - return new Response(`Deleted customer ${login}`) - } else if (['added', 'removed'].includes(action)) { - // Added or removed repos from GitHub App - - const {repositories_added: addedRepos, repositories_removed: removedRepos} = - payload - - const customer = await prisma.customer.upsert({ - where: { - name: login - }, - create: { - name: login - }, - update: {}, - select: { - id: true, - projects: { - select: { - name: true - } - } - } - }) - - if (!customer?.id) - return new Response(`Could not find or create customer ${login}`, { - status: 500 - }) - - const newRepos = addedRepos.filter((repo: Repository) => { - return !customer.projects.some( - (project: {name: string}) => project.name === repo.name - ) - }) - - // Clone, vectorize, and save public code to database - const vectorDB = new Weaviate(customer.id) - - const createProjects = prisma.project.createMany({ - data: newRepos.map((repo: Repository) => ({ - name: repo.name, - customerId: customer.id - })), - skipDuplicates: true - }) - - const deleteProjects = prisma.project.deleteMany({ - where: { - customerId: customer.id, - name: { - in: removedRepos.map((repo: Repository) => repo.name) - } - } - }) - - // Sync repos to database in a single transaction - await prisma.$transaction([createProjects, deleteProjects]) - - for (const repo of addedRepos) { - const repoUrl = `${GITHUB.BASE_URL}/${repo.full_name}` - const branch = await getMainBranch(repo.full_name) - - await vectorDB.embedRepo(repoUrl, branch) - } - - return new Response(`Successfully updated repos for ${login}`) - } - } + await handleInstallationEvents({payload: payload}) /** * Issue-related events. We care about new issues and comments. */ const { + action, comment, sender: {login: sender}, installation: {id: instanceId} @@ -183,9 +66,9 @@ export const POST = async (req: Request) => { } } = payload - const customer = await prisma.customer.findUnique({ + const user = await prisma.user.findUnique({ where: { - name: owner || undefined + userName: owner || undefined }, select: { id: true, @@ -199,17 +82,17 @@ export const POST = async (req: Request) => { select: { id: true, name: true, - customInstructions: true + instructions: true } } } }) - if (!customer) return new Response('Could not find customer', {status: 500}) + if (!user) return new Response('Could not find user', {status: 500}) - const {id: customerId, usage, usageLimit, usageWarned, projects} = customer + const {id: userId, usage, usageLimit, usageWarned, projects} = user const instructions = - projects?.[0]?.customInstructions.map(ci => ci.content).join('. ') || '' + projects?.[0]?.instructions.map(ci => ci.content).join('. ') || '' const projectId = projects?.[0]?.id @@ -228,10 +111,10 @@ export const POST = async (req: Request) => { if (usage > usageLimit) { if (!usageWarned || usage == usageLimit + 10) try { - await openUsageIssue(stripe, octokit, customerId, repoId) - await prisma.customer.update({ + await openUsageIssue(stripe, octokit, userId, repoId) + await prisma.user.update({ where: { - id: customerId + id: userId }, data: { usageWarned: true @@ -270,39 +153,37 @@ export const POST = async (req: Request) => { owner, name }) - const isComment = action === 'created' const beta = comment?.body && comment.body.toLowerCase().includes('maige beta') const labels = issue?.existingLabels?.map((l: Label) => l.name).join(', ') - const prompt = ` -Hey, here's an incoming ${isComment ? 'comment' : pr ? 'PR' : 'issue'}. -First, some context: -Repo full name: ${owner}/${name}. -Repo description: ${repoDescription}. -${ - pr || prComment - ? ` -PR number: ${pr?.number || issue.number}. -PR title: ${pr?.title || issue.title}. -PR body: ${pr?.body || issue.body}. - ` - : ` -Issue number: ${issue.number}. -Issue title: ${issue.title}. -Issue body: ${issue.body}. -Issue labels: ${labels}. -` -} -${isComment ? `The comment by @${comment.user.login}: ${comment?.body}.` : ''} -Your instructions: ${instructions || 'do nothing'}. -`.replaceAll('\n', ' ') + Hey, here's an incoming ${isComment ? 'comment' : pr ? 'PR' : 'issue'}. + First, some context: + Repo full name: ${owner}/${name}. + Repo description: ${repoDescription}. + ${ + pr || prComment + ? ` + PR number: ${pr?.number || issue.number}. + PR title: ${pr?.title || issue.title}. + PR body: ${pr?.body || issue.body}. + ` + : ` + Issue number: ${issue.number}. + Issue title: ${issue.title}. + Issue body: ${issue.body}. + Issue labels: ${labels}. + ` + } + ${isComment ? `The comment by @${comment.user.login}: ${comment?.body}.` : ''} + Your instructions: ${instructions || 'do nothing'}. + `.replaceAll('\n', ' ') await maige({ input: prompt, octokit, - customerId, + customerId: userId, projectId, repoFullName: `${owner}/${name}`, issueNumber: issue?.number, @@ -312,7 +193,6 @@ Your instructions: ${instructions || 'do nothing'}. comment, beta }) - return new Response('ok', {status: 200}) } catch (error) { console.error(error) diff --git a/app/api/webhook/stripe/route.ts b/app/api/webhook/stripe/route.ts index 3fc2e19d..496f1601 100644 --- a/app/api/webhook/stripe/route.ts +++ b/app/api/webhook/stripe/route.ts @@ -51,7 +51,7 @@ export const POST = async (req: Request) => { {status: 400} ) - await prisma.customer.update({ + await prisma.user.update({ where: { id: customerId }, @@ -76,7 +76,7 @@ export const POST = async (req: Request) => { {status: 400} ) - await prisma.customer.update({ + await prisma.user.update({ where: { stripeCustomerId: customer }, @@ -89,7 +89,7 @@ export const POST = async (req: Request) => { * Customer deleted */ try { - await prisma.customer.delete({ + await prisma.user.delete({ where: { stripeCustomerId: customer } @@ -116,7 +116,7 @@ export const POST = async (req: Request) => { ) try { - await prisma.customer.update({ + await prisma.user.update({ where: { stripeCustomerId: customer }, diff --git a/app/dashboard/(base)/page.tsx b/app/dashboard/(base)/page.tsx deleted file mode 100644 index 7dc84ced..00000000 --- a/app/dashboard/(base)/page.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import {getServerSession} from 'next-auth' -import {redirect} from 'next/navigation' -import {Suspense} from 'react' -import {authOptions} from '~/authOptions' -import {Repositories} from '~/components/dashboard/Repositories' -import prisma from '~/prisma' - -export default async function Page() { - const session = await getServerSession(authOptions) - - if (!session?.user?.githubUserId) redirect('/') - - const customer = await prisma.customer.findUnique({ - where: { - githubUserId: session.user.githubUserId - } - }) - - const projects = customer - ? await prisma.project.findMany({ - where: { - customerId: customer.id - }, - select: { - id: true, - name: true, - createdAt: true, - customInstructions: true - } - }) - : [] - - return ( -
- Loading...

}> - -
-
- ) -} diff --git a/app/dashboard/layout.tsx b/app/dashboard/layout.tsx deleted file mode 100644 index 65755d4a..00000000 --- a/app/dashboard/layout.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import {getServerSession} from 'next-auth' -import {authOptions} from '~/authOptions' -import {DashboardHeader} from '~/components/dashboard/Navigation/Header' - -export default async function RootLayout({ - children -}: { - children: React.ReactNode -}) { - const session = await getServerSession(authOptions) - - return ( -
- {session && ( - - )} -
{children}
-
- ) -} diff --git a/app/dashboard/repo/[projectId]/instructions/actions.ts b/app/dashboard/repo/[projectId]/instructions/actions.ts deleted file mode 100644 index 61460d49..00000000 --- a/app/dashboard/repo/[projectId]/instructions/actions.ts +++ /dev/null @@ -1,26 +0,0 @@ -'use server' - -import {revalidatePath} from 'next/cache' -import {redirect} from 'next/navigation' - -export async function createInstruction(projectId: string, content: string) { - const req = await prisma.instruction.create({ - data: { - projectId: projectId, - content: content, - creatorUsername: 'Dashboard' - } - }) - revalidatePath(`/dashboard/repo/${projectId}/instructions`) - redirect(`/dashboard/repo/${projectId}/instructions#${req.id}`) -} - -export async function deleteInstruction(projectId: string, id: string) { - await prisma.instruction.delete({ - where: { - id: id - } - }) - revalidatePath(`/dashboard/repo/${projectId}/instructions`) - redirect(`/dashboard/repo/${projectId}/instructions`) -} diff --git a/app/dashboard/repo/[projectId]/page.tsx b/app/dashboard/repo/[projectId]/page.tsx deleted file mode 100644 index cc7f1eb7..00000000 --- a/app/dashboard/repo/[projectId]/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import {getServerSession} from 'next-auth' -import {redirect} from 'next/navigation' -import {authOptions} from '~/authOptions' - -export default async function Page({params}: {params: {projectId: string}}) { - const session = await getServerSession(authOptions) - if (!session) redirect('/dashboard') - - return ( -
-

Coming soon...

-
- ) -} diff --git a/app/dashboard/repo/[projectId]/settings/page.tsx b/app/dashboard/repo/[projectId]/settings/page.tsx deleted file mode 100644 index 8d1b3082..00000000 --- a/app/dashboard/repo/[projectId]/settings/page.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function Settings() { - return
Coming soon...
-} diff --git a/app/page.tsx b/app/page.tsx index 54b04335..7f9eec8b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,5 +1,6 @@ import Image from 'next/image' import Link from 'next/link' +import {redirect} from 'next/navigation' import fullFlow from '~/assets/full-flow.png' import future from '~/assets/future.png' import joshuaTreeDay from '~/assets/joshua-tree-day.png' @@ -9,6 +10,7 @@ import {Auth} from '~/components/Auth' import {Header} from '~/components/Header' import {Cal, Highlight, Precedent, Trigger} from '~/components/logos' import {Nuxt} from '~/components/logos/Nuxt' +import {getCurrentUser} from '~/utils/session' const loomConfig = { hide_owner: 'true', @@ -34,7 +36,43 @@ const DemoVideo = () => ( const todayString = new Date().toISOString().split('T')[0].replaceAll('-', '/') -const Page = () => { +const Page = async () => { + const user = await getCurrentUser() + if (user) { + // Check if a team already exists + const existingTeam = await prisma.membership.findFirst({ + where: {userId: user.id}, + include: { + team: true + } + }) + if (existingTeam) redirect(`/${existingTeam.team.slug}`) + + // If no team, create a playground team + const userData = await prisma.user.findFirst({ + where: {id: user.id}, + select: { + userName: true, + projects: {where: {teamId: '1'}, select: {id: true}} + } + }) + + const newTeam = await prisma.team.create({ + data: { + createdBy: user.id, + slug: userData.userName, + name: user.name, + memberships: {create: [{userId: user.id, role: 'ADMIN'}]}, + + // onboarding flow for legacy accounts + ...(userData.projects && { + Project: {connect: userData.projects.map(({id}) => ({id}))} + }) + } + }) + if (newTeam) redirect(`/${newTeam.slug}`) + } + return (
diff --git a/bun.lockb b/bun.lockb index 3d6c068e09578121f5ea311b75752e7aba84a680..e3f0b8f8f937905d0721763963029cf9ed2da596 100755 GIT binary patch delta 83316 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

i!YOU=yca&~hP4%1WxB4`2)SKou{59P7Vvp8a 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 TIJTCOQ|4~yXh-KKwu*lN5XS5{ delta 77254 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 z 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 AI{*Lx diff --git a/lib/actions/add-project.ts b/lib/actions/add-project.ts new file mode 100644 index 00000000..30be1259 --- /dev/null +++ b/lib/actions/add-project.ts @@ -0,0 +1,43 @@ +'use server' +import {z} from 'zod' +import {getCurrentUser} from '~/utils/session' + +const schema = z.object({ + teamId: z.string() +}) + +export default async function addProject(prevState: any, formData: FormData) { + const user = await getCurrentUser() + if (!user) + return { + message: 'Unauthorized, no session', + type: 'error' + } + + const parsed = schema.parse({ + teamId: formData.get('teamId') + }) + + try { + const response = await prisma.addProject.create({ + data: { + createdBy: user.id, + teamId: parsed.teamId + } + }) + return { + message: `Successfully created request to add project`, + type: 'success' + } + } catch (err) { + if (err instanceof Error) + return { + message: err.message, + type: 'error' + } + return { + message: JSON.stringify(err), + type: 'error' + } + } +} diff --git a/lib/actions/create-instruction.ts b/lib/actions/create-instruction.ts new file mode 100644 index 00000000..d813ca2a --- /dev/null +++ b/lib/actions/create-instruction.ts @@ -0,0 +1,31 @@ +'use server' +import {revalidatePath} from 'next/cache' +import {redirect} from 'next/navigation' +import {getCurrentUser} from '~/utils/session' + +export default async function createInstruction( + teamSlug: string, + projectId: string, + content: string +) { + const user = await getCurrentUser() + if (!user) + return { + message: 'Unauthorized, no session', + type: 'error' + } + + const response = await prisma.instruction.create({ + data: { + projectId: projectId, + content: content, + creatorUsername: 'Dashboard', + createdBy: user.id + } + }) + + if (response) { + revalidatePath(`/${teamSlug}/project/${projectId}/instructions`) + redirect(`/${teamSlug}/project/${projectId}/instructions#${response.id}`) + } +} diff --git a/lib/actions/create-team.ts b/lib/actions/create-team.ts new file mode 100644 index 00000000..02382a08 --- /dev/null +++ b/lib/actions/create-team.ts @@ -0,0 +1,49 @@ +'use server' +import {z} from 'zod' +import {slugify} from '~/utils' +import {getCurrentUser} from '~/utils/session' + +const schema = z.object({ + name: z.string() +}) + +export default async function createTeam(prevState: any, formData: FormData) { + const user = await getCurrentUser() + if (!user) + return { + message: 'Unauthorized, no session', + type: 'error' + } + + const parsed = schema.parse({ + name: formData.get('name') + }) + + try { + const response = await prisma.team.create({ + data: { + name: parsed.name, + slug: slugify(parsed.name), + createdBy: user.id, + memberships: { + create: {userId: user.id, role: 'ADMIN'} + } + } + }) + return { + message: `Successfully created ${parsed.name}`, + type: 'success', + data: {slug: response.slug} + } + } catch (err) { + if (err instanceof Error) + return { + message: err.message, + type: 'error' + } + return { + message: JSON.stringify(err), + type: 'error' + } + } +} diff --git a/lib/actions/delete-instruction.ts b/lib/actions/delete-instruction.ts new file mode 100644 index 00000000..d38c2352 --- /dev/null +++ b/lib/actions/delete-instruction.ts @@ -0,0 +1,17 @@ +'use server' +import {revalidatePath} from 'next/cache' +import {redirect} from 'next/navigation' + +export default async function deleteInstruction( + teamSlug: string, + projectId: string, + instructionId: string +) { + await prisma.instruction.delete({ + where: { + id: instructionId + } + }) + revalidatePath(`/${teamSlug}/project/${projectId}/instructions`) + redirect(`/${teamSlug}/project/${projectId}/instructions`) +} diff --git a/lib/actions/delete-team.ts b/lib/actions/delete-team.ts new file mode 100644 index 00000000..9128b713 --- /dev/null +++ b/lib/actions/delete-team.ts @@ -0,0 +1,40 @@ +'use server' +import {z} from 'zod' +import {getCurrentUser} from '~/utils/session' + +const schema = z.object({ + name: z.string(), + slug: z.string() +}) + +export default async function deleteTeam(prevState: any, formData: FormData) { + const user = await getCurrentUser() + if (!user) + return { + message: 'Unauthorized, no session', + type: 'error' + } + + const parsed = schema.parse({ + name: formData.get('name'), + slug: formData.get('slug') + }) + + try { + await prisma.team.delete({where: {slug: parsed.slug}}) + return { + message: `Successfully deleted ${parsed.name}`, + type: 'success' + } + } catch (err) { + if (err instanceof Error) + return { + message: err.message, + type: 'error' + } + return { + message: JSON.stringify(err), + type: 'error' + } + } +} diff --git a/lib/actions/feedback.ts b/lib/actions/feedback.ts deleted file mode 100644 index 8c5f5b7b..00000000 --- a/lib/actions/feedback.ts +++ /dev/null @@ -1,23 +0,0 @@ -'use server' - -import {getServerSession} from 'next-auth' -import {authOptions} from '~/authOptions' -import prisma from '~/prisma' - -export async function submitFeedback(content: string) { - const session = await getServerSession(authOptions) - if (!session) return 'not logged in' - - const customer = await prisma.customer.findUnique({ - where: { - githubUserId: session.user.githubUserId - } - }) - - await prisma.feedback.create({ - data: { - content, - customerId: customer.id - } - }) -} diff --git a/lib/actions/submit-feedback.ts b/lib/actions/submit-feedback.ts new file mode 100644 index 00000000..30b45a83 --- /dev/null +++ b/lib/actions/submit-feedback.ts @@ -0,0 +1,46 @@ +'use server' +import {z} from 'zod' +import {getCurrentUser} from '~/utils/session' + +const schema = z.object({ + content: z.string() +}) + +export default async function submitFeedback( + prevState: any, + formData: FormData +) { + const user = await getCurrentUser() + if (!user) + return { + message: 'Unauthorized, no session', + type: 'error' + } + + const parsed = schema.parse({ + content: formData.get('content') + }) + + try { + const response = await prisma.feedback.create({ + data: { + content: parsed.content, + createdBy: user.id + } + }) + return { + message: `Thank you for your feedback`, + type: 'success' + } + } catch (err) { + if (err instanceof Error) + return { + message: err.message, + type: 'error' + } + return { + message: JSON.stringify(err), + type: 'error' + } + } +} diff --git a/lib/actions/instructions.ts b/lib/actions/update-instruction.ts similarity index 100% rename from lib/actions/instructions.ts rename to lib/actions/update-instruction.ts diff --git a/lib/agents/engineer.ts b/lib/agents/engineer.ts index b373d0b6..63b0bfe8 100644 --- a/lib/agents/engineer.ts +++ b/lib/agents/engineer.ts @@ -65,8 +65,8 @@ export async function engineer({ const branch = `maige/${issueNumber}-${Date.now()}` const [owner, repo] = repoFullName.split('/') - const botUserName = `${env.GITHUB_APP_NAME}[bot]` // Replace with your GitHub App's bot user name - const botUserEmail = `${env.GITHUB_APP_ID}+${env.GITHUB_APP_NAME}[bot]@users.noreply.github.com` // Replace with your GitHub App's bot user email + const botUserName = `${env.NEXT_PUBLIC_GITHUB_APP_NAME}[bot]` // Replace with your GitHub App's bot user name + const botUserEmail = `${env.GITHUB_APP_ID}+${env.NEXT_PUBLIC_GITHUB_APP_NAME}[bot]@users.noreply.github.com` // Replace with your GitHub App's bot user email const repoSetup = `git config --global user.email "${botUserEmail}" && git config --global user.name "${botUserName}" && git clone https://x-access-token:${installationToken}@github.com/${repoFullName}.git && cd ${repo} && git checkout -b ${branch}` diff --git a/lib/authOptions.ts b/lib/authOptions.ts index bda3d30b..3359d874 100644 --- a/lib/authOptions.ts +++ b/lib/authOptions.ts @@ -1,42 +1,53 @@ -import {AuthOptions, Profile} from 'next-auth' -import GithubProvider, {GithubProfile} from 'next-auth/providers/github' +import {PrismaAdapter} from '@auth/prisma-adapter' +import {AuthOptions} from 'next-auth' +import {AdapterUser} from 'next-auth/adapters' +import GithubProvider, {type GithubProfile} from 'next-auth/providers/github' import prisma from '~/prisma' import env from './env.mjs' +const prismaAdapter = PrismaAdapter(prisma) + +prismaAdapter.createUser = (data: AdapterUser & {userName: string}) => { + return prisma.user.upsert({ + // migration flow + where: {userName: data.userName}, + update: data, + + // default flow + create: data + }) +} + export const authOptions: AuthOptions = { + adapter: prismaAdapter, + session: { + strategy: 'jwt' + }, providers: [ GithubProvider({ clientId: env.GITHUB_CLIENT_ID as string, clientSecret: env.GITHUB_CLIENT_SECRET as string, profile(profile: GithubProfile) { + // Add user profile information return { id: profile.id.toString(), name: profile.name, - userName: profile.login, email: profile.email, - image: profile.avatar_url + image: profile.avatar_url, + userName: profile.login } } }) ], - // attach the githubUserId that we store server side below to our session callbacks: { - async session({session, token}) { - session.user.githubUserId = token.sub + session: async ({token, session}) => { + if (token) { + session.user.id = token.sub + session.user.name = token.name + session.user.email = token.email + session.user.image = token.picture + } return session } - }, - // by design, NextAuth does not expose a user's Github username to the client and in our session object, only their github numeric user ID. So, we need to store this numeric ID in our DB - // this is so we can know who is making the request on the server - events: { - async signIn({account, profile}) { - const typedProfile: Profile & {userName?: string} = profile - await prisma.customer.update({ - where: {name: typedProfile.userName}, - data: { - githubUserId: account.providerAccountId - } - }) - } } } diff --git a/lib/components/Auth.tsx b/lib/components/Auth.tsx index 5a95cb1f..8d7f933d 100644 --- a/lib/components/Auth.tsx +++ b/lib/components/Auth.tsx @@ -6,7 +6,7 @@ export function Auth({text}: {text?: string}) { return ( ) diff --git a/lib/components/Feedback.tsx b/lib/components/Feedback.tsx deleted file mode 100644 index 32e89797..00000000 --- a/lib/components/Feedback.tsx +++ /dev/null @@ -1,65 +0,0 @@ -'use client' - -import {MessageSquareMoreIcon} from 'lucide-react' -import {useState} from 'react' -import {toast} from 'sonner' -import {submitFeedback} from '~/actions/feedback' -import {Button} from './ui/button' -import {Dialog, DialogContent, DialogTrigger} from './ui/dialog' -import {Textarea} from './ui/textarea' - -type Props = {} - -export default function Feedback({}: Props) { - const [content, setContent] = useState('') - const [openDialog, setOpenDialog] = useState(false) - - function sendFeedback(content: string) { - setOpenDialog(false) - const promise = submitFeedback(content) - setContent('') - toast.promise(promise, { - loading: 'Submitting...', - success: () => { - return `Feedback submitted` - }, - error: 'Oops, something went wrong.' - }) - } - return ( - setOpenDialog(prev => !prev)}> - - {/* Making this a button throws a button-in-button HTML error */} -
- -
-
- -
-

Submit feedback

-