Skip to content

Commit

Permalink
Merge pull request #35 from Amaxa-Impact/feat/permissions
Browse files Browse the repository at this point in the history
Permissions System
  • Loading branch information
not-ani authored Jul 31, 2024
2 parents 40cb61a + bd42f3f commit 4ce0c51
Show file tree
Hide file tree
Showing 44 changed files with 2,003 additions and 98 deletions.
4 changes: 3 additions & 1 deletion apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"build": "pnpm with-env next build",
"clean": "git clean -xdf .next .turbo node_modules",
"dev": "pnpm with-env next dev --turbo",
"dev": "pnpm with-env next dev",
"format": "prettier --check . --ignore-path ../../.gitignore",
"lint": "eslint",
"start": "pnpm with-env next start",
Expand All @@ -29,10 +29,12 @@
"@trpc/react-query": "11.0.0-rc.364",
"@trpc/server": "11.0.0-rc.364",
"@xyflow/react": "^12.0.3",
"date-fns": "^3.6.0",
"geist": "^1.3.0",
"next": "^14.2.3",
"react": "18.3.1",
"react-dom": "18.3.1",
"react-notion": "^0.10.0",
"reactflow": "^11.11.4",
"recharts": "^2.12.7",
"superjson": "2.2.1",
Expand Down
72 changes: 72 additions & 0 deletions apps/nextjs/src/app/(auth)/sign-in/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Link from "next/link";

import { signIn } from "@amaxa/auth";
import { Button } from "@amaxa/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@amaxa/ui/card";
import { Input } from "@amaxa/ui/input";
import { Label } from "@amaxa/ui/label";

import { env } from "~/env";

export default function LoginForm() {
return (
<div className="flex h-screen flex-col items-center justify-center">
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Enter your email below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
{env.NODE_ENV === "development" ? (
<>
<form
action={async (data) => {
"use server";
await signIn("email", {
password: data.get("password"),
redirectTo: "/",
});
}}
>
<div className="flex flex-col gap-4">
<Label htmlFor="password"> Password</Label>
<Input id="password" type="password" required />
</div>
<Button type="submit" className="w-full">
Login
</Button>
</form>
</>
) : null}

<form
action={async () => {
"use server";
await signIn("google", { redirectTo: "/" });
}}
>
<Button variant="outline" className="w-full" type="submit">
Login with Google
</Button>
</form>
</div>
<div className="mt-4 text-center text-sm">
Have question&apos;s about how we use your data?{" "}
<Link href="/data-privacy" className="underline">
Read our privacy statement here
</Link>
</div>
</CardContent>
</Card>
</div>
);
}
73 changes: 73 additions & 0 deletions apps/nextjs/src/app/(auth)/sign-out/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from "react";
import Link from "next/link";

import { signIn } from "@amaxa/auth";
import { Button } from "@amaxa/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@amaxa/ui/card";
import { Input } from "@amaxa/ui/input";
import { Label } from "@amaxa/ui/label";

import { env } from "~/env";

export default function LoginForm() {
return (
<div className="flex h-screen flex-col items-center justify-center">
<Card className="mx-auto max-w-sm">
<CardHeader>
<CardTitle className="text-2xl">Login</CardTitle>
<CardDescription>
Enter your email below to login to your account
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
{env.NODE_ENV === "development" ? (
<>
<form
action={async (data) => {
"use server";
await signIn("email", {
password: data.get("password"),
redirectTo: "/",
});
}}
>
<div className="flex flex-col gap-4">
<Label htmlFor="password"> Password</Label>
<Input id="password" type="password" required />
</div>
<Button type="submit" className="w-full">
Login
</Button>
</form>
</>
) : null}

<form
action={async () => {
"use server";
await signIn("google", { redirectTo: "/" });
}}
>
<Button variant="outline" className="w-full" type="submit">
Login with Google
</Button>
</form>
</div>
<div className="mt-4 text-center text-sm">
Have question&apos;s about how we use your data?{" "}
<Link href="/data-privacy" className="underline">
Read our privacy statement here
</Link>
</div>
</CardContent>
</Card>
</div>
);
}
10 changes: 9 additions & 1 deletion apps/nextjs/src/app/(dashboard)/project/[id]/(root)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import React, { cache } from "react";
import Link from "next/link";
import { notFound } from "next/navigation";
import { House, User, Search, Settings, Workflow, ChartArea } from "lucide-react";
import {
ChartArea,
House,
Search,
Settings,
User,
Workflow,
} from "lucide-react";

import { db } from "@amaxa/db/client";
import {
Breadcrumb,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"use client";

import React from "react";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";

import { Button } from "@amaxa/ui/button";
import { Combobox } from "@amaxa/ui/combobox";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@amaxa/ui/dialog";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@amaxa/ui/form";

const addUserSchema = z.object({
userId: z.string(),
permissions: z.array(z.string()),
});

type AddUserForm = z.infer<typeof addUserSchema>;

export default function AddUserForm({
userMap,
}: {
userMap: {
value: string;
label: string;
}[];
}) {
const form = useForm<AddUserForm>({
resolver: zodResolver(addUserSchema),
});

function onSubmit(data: AddUserForm) {
console.log(data);
}

return (
<Dialog>
<DialogTrigger asChild>
<Button>Invite User</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Add A User</DialogTitle>
</DialogHeader>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="userId"
render={({ field }) => (
<FormItem>
<FormLabel>User</FormLabel>
<FormControl>
<Combobox {...field} options={userMap} />
</FormControl>
<FormDescription>
Select a user to add to the project
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">Add User</Button>
</form>
</Form>
</DialogContent>
</Dialog>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { api } from "~/trpc/server";
import AddUserForm from "./add-user-form";

export async function AddUser() {
const data = await api.users.usersNotInProject();

const userMap = data.map((user) => {
return {
value: user.id,
label: user.name ?? "No Name User",
};
});

return (
<div>
<AddUserForm userMap={userMap} />
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
TableRow,
} from "@amaxa/ui/table";

import { AddUser } from "./_components/add-user";
import PermissionsModal from "./_components/permissions-dialog";

export default function Page({
Expand All @@ -46,7 +47,7 @@ export default function Page({
<main className="flex min-h-[calc(100vh_-_theme(spacing.16))] flex-1 flex-col gap-4 bg-muted/40 p-4 md:gap-8 md:p-10">
<div className="mx-auto flex w-full max-w-6xl items-center gap-4">
<h1 className="text-2xl font-bold">Permissions</h1>
<Button>Invite User</Button>
<AddUser />
</div>
<div className="mx-auto w-full max-w-6xl">
<Card>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from "react";

export default function Layout({ children }: { children: React.ReactNode }) {
return <div>{children}</div>;
}
25 changes: 25 additions & 0 deletions apps/nextjs/src/app/(home)/@modal/(...)guide/[id]/com.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react";

import "react-notion/src/styles.css";

import type { BlockMapType } from "react-notion";
import { NotionRenderer } from "react-notion";

import { Card, CardContent, CardHeader, CardTitle } from "@amaxa/ui/card";

export const Com = async (props: { id: string }) => {
const data = (await fetch(
`https://notion-api.splitbee.io/v1/page/${props.id}`,
).then((res) => res.json())) as BlockMapType;

return (
<Card className="container mx-auto my-8 h-[750px] w-[1000px] items-start overflow-y-scroll px-4 md:px-6 lg:px-8">
<CardHeader>
<CardTitle className="text-3xl">Action Guide</CardTitle>
</CardHeader>
<CardContent>
<NotionRenderer blockMap={data} />
</CardContent>
</Card>
);
};
20 changes: 20 additions & 0 deletions apps/nextjs/src/app/(home)/@modal/(...)guide/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

import Modal from "@amaxa/ui/modal";

import { Com } from "./com";

export default function Page(props: {
params: {
id: string;
};
}) {
const { id } = props.params;
console.log(id);

return (
<Modal>
<Com id={id} />
</Modal>
);
}
3 changes: 3 additions & 0 deletions apps/nextjs/src/app/(home)/@modal/default.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function Default() {
return null;
}
Loading

0 comments on commit 4ce0c51

Please sign in to comment.