Merge pull request #91 from rsandb/main

updated avatar component name, added ability to change username (only works server side for now), updated signin page, updated Footer
This commit is contained in:
Keith Stevens
2022-12-29 07:47:59 +09:00
committed by GitHub
11 changed files with 217 additions and 107 deletions
+58 -14
View File
@@ -1,31 +1,75 @@
import Image from "next/image";
import Link from "next/link";
import { FaGithub, FaDiscord } from "react-icons/fa";
import { Container } from "./Container";
import { NavLinks } from "./NavLinks";
export function Footer() {
return (
<footer className="border-t border-gray-200 bg-white">
<Container className="">
<div className="flex flex-col items-start justify-between gap-y-12 pt-16 pb-6 lg:flex-row lg:items-center lg:py-6">
<div>
<div className="flex items-center text-gray-900">
<main>
<Container className="">
<div className="flex flex-wrap justify-between gap-y-12 py-10 lg:items-center lg:py-16">
<div className="flex items-center text-black pr-8">
<Link href="/" aria-label="Home" className="flex items-center">
<Image src="/images/logos/logo.svg" className="mx-auto object-fill" width="50" height="50" alt="logo" />
<Image src="/images/logos/logo.svg" className="mx-auto object-fill" width="52" height="52" alt="logo" />
</Link>
<div className="ml-4">
<p className="text-base font-semibold">Open Assistant</p>
<p className="mt-1 text-sm">Conversational AI for everyone.</p>
<div className="ml-2">
<p className="text-base font-bold">Open Assistant</p>
<p className="text-sm">Conversational AI for everyone.</p>
</div>
</div>
{/* <nav className="mt-11 flex gap-8">
<NavLinks />
</nav> */}
<nav className="flex justify-center gap-20">
<div className="flex flex-col text-sm leading-7">
<b>Information</b>
<div className="flex flex-col leading-5">
<Link href="#" aria-label="Our Team" className="hover:underline underline-offset-2">
Our Team
</Link>
<Link href="#join-us" aria-label="Join Us" className="hover:underline underline-offset-2">
Join Us
</Link>
</div>
</div>
<div className="flex flex-col text-sm leading-7">
<b>Legal</b>
<div className="flex flex-col leading-5">
<Link href="#" aria-label="Privacy Policy" className="hover:underline underline-offset-2">
Privacy Policy
</Link>
<Link href="#" aria-label="Terms of Service" className="hover:underline underline-offset-2">
Terms of Service
</Link>
</div>
</div>
<div className="flex flex-col text-sm leading-7">
<b>Connect</b>
<div className="flex flex-col leading-5">
<Link
href="https://github.com/LAION-AI/Open-Assistant"
rel="noopener noreferrer nofollow"
target="_blank"
aria-label="Privacy Policy"
className="hover:underline underline-offset-2"
>
Github
</Link>
<Link
href="https://discord.gg/pXtnYk9c"
rel="noopener noreferrer nofollow"
target="_blank"
aria-label="Terms of Service"
className="hover:underline underline-offset-2"
>
Discord
</Link>
</div>
</div>
</nav>
</div>
</div>
</Container>
</Container>
</main>
</footer>
);
}
+4 -4
View File
@@ -6,7 +6,7 @@ import Link from "next/link";
import { signOut, useSession } from "next-auth/react";
import { FaUser, FaSignOutAlt } from "react-icons/fa";
import { Avatar } from "./Avatar";
import { UserMenu } from "./UserMenu";
import { Container } from "./Container";
import { NavLinks } from "./NavLinks";
@@ -45,9 +45,9 @@ function AccountButton() {
return;
}
return (
<Link href="/auth/signup" aria-label="Home" className="flex items-center">
<Link href="/auth/signin" aria-label="Home" className="flex items-center">
<Button variant="outline" leftIcon={<FaUser />}>
Log in
Sign in
</Button>
</Link>
);
@@ -113,7 +113,7 @@ export function Header() {
)}
</Popover>
<AccountButton />
<Avatar />
<UserMenu />
</div>
</Container>
</nav>
@@ -5,18 +5,18 @@ import { Popover } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import { FaCog, FaSignOutAlt, FaGithub } from "react-icons/fa";
export function Avatar() {
export function UserMenu() {
const { data: session } = useSession();
if (!session) {
return <></>;
}
if (session && session.user) {
const displayName = session.user.name || session.user.email;
const email = session.user.email;
const accountOptions = [
{
name: "Account Settings",
href: "#",
href: "/account",
desc: "Account Settings",
icon: FaCog,
//For future use
@@ -35,8 +35,7 @@ export function Avatar() {
height="40"
className="rounded-full"
></Image>
<p className="hidden lg:flex">{displayName}</p>
{/* Will be changed to username once it is implemented */}
<p className="hidden lg:flex">{session.user.name || session.user.email}</p>
</div>
</Popover.Button>
<AnimatePresence initial={false}>
@@ -72,7 +71,7 @@ export function Avatar() {
))}
<a
className="flex items-center rounded-md hover:bg-gray-100 cursor-pointer"
onClick={() => signOut()}
onClick={() => signOut({ callbackUrl: "/" })}
>
<div className="p-4">
<FaSignOutAlt />
@@ -93,4 +92,4 @@ export function Avatar() {
}
}
export default Avatar;
export default UserMenu;
+1 -1
View File
@@ -4,5 +4,5 @@ export { default } from "next-auth/middleware";
* Guards all pages under `/grading` and redirects them to the sign in page.
*/
export const config = {
matcher: ["/create/:path*", "/evaluate/:path*"],
matcher: ["/create/:path*", "/evaluate/:path*", "/account/:path*"],
};
+4 -30
View File
@@ -5,41 +5,15 @@ import Head from "next/head";
import Link from "next/link";
export default function Error() {
const { data: session } = useSession();
if (!session) {
return (
<>
<Head>
<title>Open Assistant</title>
<meta name="404" content="Sorry, this page doesn't exist." />
</Head>
<Header />
<main className="flex h-3/4 items-center justify-center overflow-hidden subpixel-antialiased text-xl">
{"Sorry, the page you're looking for does not exist."}
</main>
<Footer />
</>
);
}
return (
<>
<Head>
<title>Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
<title>404 - Open Assistant</title>
<meta name="404" content="Sorry, this page doesn't exist." />
</Head>
<Header />
<main>
<h2>Open Chat Gpt</h2>
<p>You are logged in</p>
<Link href="/grading/grade-output">~Rate a prompt and output now~</Link>
<main className="flex h-3/4 items-center justify-center overflow-hidden subpixel-antialiased text-xl">
<p>Sorry, the page you are looking for does not exist.</p>
</main>
<Footer />
</>
);
}
+56
View File
@@ -0,0 +1,56 @@
import React, { useState } from "react";
import { useSession } from "next-auth/react";
import { Button, Input, InputGroup, Stack } from "@chakra-ui/react";
import Head from "next/head";
import Router from "next/router";
export default function Account() {
const { data: session } = useSession();
const [username, setUsername] = useState("");
const updateUser = async (e: React.SyntheticEvent) => {
e.preventDefault();
try {
const body = { username };
await fetch("/api/username", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
await Router.push("/account");
} catch (error) {
console.error(error);
}
};
if (!session) {
return;
}
return (
<>
<Head>
<title>Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
</Head>
<main className="h-3/4 z-0 bg-white flex flex-col items-center justify-center">
<p>{session.user.name || "No username"}</p>
<form onSubmit={updateUser}>
<InputGroup>
<Input
onChange={(e) => setUsername(e.target.value)}
placeholder="Edit Username"
type="text"
value={username}
></Input>
<Button disabled={!username} type="submit" value="Change">
Submit
</Button>
</InputGroup>
</form>
<p>{session.user.email}</p>
</main>
</>
);
}
+44
View File
@@ -0,0 +1,44 @@
import Head from "next/head";
import Link from "next/link";
import React, { useState } from "react";
import { useSession } from "next-auth/react";
import { Button } from "@chakra-ui/react";
export default function Account() {
const { data: session } = useSession();
const [username, setUsername] = useState("null");
const handleUpdate = async () => {
const response = await fetch("../api/update", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ username }),
});
const { name } = await response.json();
setUsername(name);
};
if (!session) {
return;
}
return (
<>
<Head>
<title>Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
</Head>
<main className="h-3/4 z-0 bg-white flex flex-col items-center justify-center">
<p>{username}</p>
<Button>
<Link href="/account/edit">Edit Username</Link>
</Button>
<p>{session.user.email}</p>
</main>
</>
);
}
+2 -1
View File
@@ -1,5 +1,6 @@
import type { AuthOptions } from "next-auth";
import NextAuth from "next-auth";
import { NextApiHandler } from "next";
import DiscordProvider from "next-auth/providers/discord";
import EmailProvider from "next-auth/providers/email";
import CredentialsProvider from "next-auth/providers/credentials";
@@ -55,7 +56,7 @@ export const authOptions: AuthOptions = {
adapter: PrismaAdapter(prisma),
providers,
pages: {
signIn: "/auth/signup",
signIn: "/auth/signin",
verifyRequest: "/auth/verify",
// error: "/auth/error", -Will be used later
},
+22
View File
@@ -0,0 +1,22 @@
import { getSession } from "next-auth/react";
import { Prisma } from "@prisma/client";
import Email from "next-auth/providers/email";
// POST /api/post
// Required fields in body: title
// Optional fields in body: content
export default async function handle(req, res) {
const { username } = req.body;
const { email } = req.body;
const session = await getSession({ req });
const result = await prisma.user.update({
where: {
email: session.user.email,
},
data: {
name: username,
},
});
res.json({ name: result.name });
}
@@ -1,35 +1,19 @@
import { Button, Input, Stack } from "@chakra-ui/react";
import Head from "next/head";
import Link from "next/link";
import { FaDiscord, FaEnvelope, FaGithub } from "react-icons/fa";
import { getCsrfToken, getProviders, signIn } from "next-auth/react";
import { useRef } from "react";
import { FaBug, FaDiscord, FaEnvelope, FaGithub } from "react-icons/fa";
import Link from "next/link";
import { AuthLayout } from "src/components/AuthLayout";
export default function Signin({ csrfToken, providers }) {
const { discord, email, github, credentials } = providers;
const { discord, email, github } = providers;
const emailEl = useRef(null);
const debugUsernameEl = useRef(null);
const signinWithDiscord = () => {
signIn(discord.id, { callbackUrl: "/" });
};
const signinWithEmail = (ev: React.FormEvent) => {
ev.preventDefault();
const signinWithEmail = () => {
signIn(email.id, { callbackUrl: "/", email: emailEl.current.value });
};
const signinWithGithub = () => {
signIn(github.id, { callbackUrl: "/" });
};
function signinWithDebugCredentials(ev: React.FormEvent) {
ev.preventDefault();
signIn(credentials.id, { callbackUrl: "/", username: debugUsernameEl.current.value });
}
return (
<>
<Head>
@@ -37,27 +21,20 @@ export default function Signin({ csrfToken, providers }) {
<meta name="Sign Up" content="Sign up to access Open Assistant" />
</Head>
<AuthLayout>
<Stack spacing="6">
{credentials && (
<form onSubmit={signinWithDebugCredentials} className="border-2 border-orange-200 rounded-md p-4 relative">
<span className="text-orange-600 absolute -top-3 left-5 bg-white px-1">For Debugging Only</span>
<Stack>
<Input variant="outline" size="lg" placeholder="Username" ref={debugUsernameEl} />
<Button size={"lg"} leftIcon={<FaBug />} colorScheme="gray" type="submit">
Continue with Debug User
</Button>
</Stack>
</form>
)}
<Stack spacing="2">
{email && (
<form onSubmit={signinWithEmail}>
<Stack>
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button size={"lg"} leftIcon={<FaEnvelope />} colorScheme="gray">
Continue with Email
</Button>
</Stack>
</form>
<Stack>
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button
size={"lg"}
leftIcon={<FaEnvelope />}
colorScheme="gray"
onClick={signinWithEmail}
// isDisabled="false"
>
Continue with Email
</Button>
</Stack>
)}
{discord && (
<Button
@@ -69,7 +46,8 @@ export default function Signin({ csrfToken, providers }) {
size="lg"
leftIcon={<FaDiscord />}
color="white"
onClick={signinWithDiscord}
onClick={() => signIn(discord, { callbackUrl: "/" })}
// isDisabled="false"
>
Continue with Discord
</Button>
@@ -84,7 +62,7 @@ export default function Signin({ csrfToken, providers }) {
size={"lg"}
leftIcon={<FaGithub />}
colorScheme="blue"
onClick={signinWithGithub}
// isDisabled="false"
>
Continue with Github
</Button>
-8
View File
@@ -13,14 +13,6 @@ export default function Verify() {
</Head>
<AuthLayout>
<h1 className="text-lg">A sign-in link has been sent to your email address.</h1>
<hr className="mt-14 mb-4 h-px bg-gray-200 border-0" />
<Link
href="#"
aria-label="Log In"
className="flex justify-center font-medium text-black hover:underline underline-offset-4"
>
Already have an account? Log In
</Link>
</AuthLayout>
</>
);