Merge pull request #167 from LAION-AI/dark-mode-implementation

Dark mode implementation
This commit is contained in:
Keith Stevens
2023-01-03 14:45:36 +09:00
committed by GitHub
41 changed files with 5133 additions and 460 deletions
+4 -1
View File
@@ -3,7 +3,10 @@ const nextConfig = {
output: "standalone",
reactStrictMode: true,
experimental: {
scrollRestoration: true,
/* Disabling this for now only because it causes a warning in the console that cannot be silenced for eslint
If this can be resolved, we should re-enable this.
*/
// scrollRestoration: true,
},
};
+4444 -30
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -22,6 +22,7 @@
"@dnd-kit/core": "^6.0.6",
"@dnd-kit/modifiers": "^6.0.1",
"@dnd-kit/sortable": "^7.0.1",
"@dnd-kit/utilities": "^3.2.1",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
"@headlessui/react": "^1.7.7",
@@ -39,9 +40,11 @@
"eslint-plugin-simple-import-sort": "^8.0.0",
"focus-visible": "^5.2.0",
"framer-motion": "^6.5.1",
"install": "^0.13.0",
"next": "13.0.6",
"next-auth": "^4.18.6",
"nodemailer": "^6.8.0",
"npm": "^9.2.0",
"postcss-focus-visible": "^7.1.0",
"react": "18.2.0",
"react-dom": "18.2.0",
+2 -2
View File
@@ -1,11 +1,11 @@
export function AuthLayout({ children }) {
return (
<main className="flex items-center justify-center sm:py-4 subpixel-antialiased">
<div className="flex items-center justify-center sm:py-4 subpixel-antialiased">
<div className="flex items-center w-full max-w-2xl flex-col px-4 sm:px-6">
<div className="flex-auto items-center justify-center w-full py-10 px-4 sm:mx-0 sm:flex-none sm:rounded-2xl sm:p-4">
{children}
</div>
</div>
</main>
</div>
);
}
+38 -6
View File
@@ -1,16 +1,48 @@
import { CircleBackground } from "./CircleBackground";
import { useColorMode } from "@chakra-ui/react";
import { useId } from "react";
import { Container } from "./Container";
export function CallToAction() {
function CircleBackground({ width = 558, height = 558, ...props }) {
const id = useId();
const { colorMode } = useColorMode();
const baseRingColor = colorMode === "light" ? "#777" : "#000";
const gradStopColor = colorMode === "light" ? "#fff" : "#000";
return (
<section id="join-us" className="relative overflow-hidden bg-gray-900 py-20 sm:py-28">
<svg viewBox="0 0 558 558" width={width} height={height} fill="none" aria-hidden="true" {...props}>
<defs>
<linearGradient id={id} x1="79" y1="16" x2="105" y2="237" gradientUnits="userSpaceOnUse">
<stop stopColor={gradStopColor} />
<stop offset="1" stopColor={baseRingColor} stopOpacity="0" />
</linearGradient>
</defs>
<path
opacity=".2"
d="M1 279C1 125.465 125.465 1 279 1s278 124.465 278 278-124.465 278-278 278S1 432.535 1 279Z"
stroke={baseRingColor}
/>
<path d="M1 279C1 125.465 125.465 1 279 1" stroke={`url(#${id})`} strokeLinecap="round" />
</svg>
);
}
export function CallToAction() {
const { colorMode } = useColorMode();
const bgColorClass = colorMode === "light" ? "bg-gray-900" : "bg-gray-50";
const headingColorClass = colorMode === "light" ? "text-white" : "text-black";
const textColorClass = colorMode === "light" ? "text-gray-300" : "text-black";
return (
<section id="join-us" className={`relative overflow-hidden py-20 sm:py-28 ${bgColorClass} ${textColorClass}`}>
<div className="absolute top-1/2 left-20 -translate-y-1/2 sm:left-1/2 sm:-translate-x-1/2">
<CircleBackground color="#fff" className="animate-spin-slower" />
<CircleBackground className="animate-spin-slower" />
</div>
<Container className="relative">
<div className="mx-auto max-w-md sm:text-center">
<h2 className="text-3xl font-medium tracking-tight text-white sm:text-4xl">Join Us</h2>
<p className="mt-4 text-lg text-gray-300">
<h2 className={`text-3xl font-medium tracking-tight sm:text-4xl ${headingColorClass}`}>Join Us</h2>
<p className="mt-4 text-lg">
All open source projects begin with people like you. Open source is the belief that if we collaborate we can
together gift our knowledge and technology to the world for the benefit of humanity. Are you in? Find us
here:
@@ -1,22 +0,0 @@
import { useId } from "react";
export function CircleBackground({ color, width = 558, height = 558, ...props }) {
const id = useId();
return (
<svg viewBox="0 0 558 558" width={width} height={height} fill="none" aria-hidden="true" {...props}>
<defs>
<linearGradient id={id} x1="79" y1="16" x2="105" y2="237" gradientUnits="userSpaceOnUse">
<stop stopColor={color} />
<stop offset="1" stopColor={color} stopOpacity="0" />
</linearGradient>
</defs>
<path
opacity=".2"
d="M1 279C1 125.465 125.465 1 279 1s278 124.465 278 278-124.465 278-278 278S1 432.535 1 279Z"
stroke={color}
/>
<path d="M1 279C1 125.465 125.465 1 279 1" stroke={`url(#${id})`} strokeLinecap="round" />
</svg>
);
}
+10 -3
View File
@@ -1,3 +1,5 @@
import { useColorMode } from "@chakra-ui/react";
import { Container } from "./Container";
const faqs = [
@@ -25,11 +27,16 @@ const faqs = [
];
export function Faq() {
const { colorMode } = useColorMode();
const headingColorClass = colorMode === "light" ? "text-gray-900" : "text-white";
const textColorClass = colorMode === "light" ? "text-gray-700" : "text-gray-100";
return (
<section id="faq" aria-labelledby="faqs-title" className="border-t border-gray-200 py-20 sm:py-32">
<Container className="">
<div className="mx-auto max-w-2xl lg:mx-0">
<h2 id="faqs-title" className="text-3xl font-medium tracking-tight text-gray-900">
<h2 id="faqs-title" className={`text-3xl font-medium tracking-tight ${headingColorClass}`}>
Frequently Asked Questions
</h2>
{/* <p className="mt-2 text-lg text-gray-600">
@@ -52,8 +59,8 @@ export function Faq() {
<ul role="list" className="space-y-10">
{column.map((faq, faqIndex) => (
<li key={faqIndex}>
<h3 className="text-lg font-semibold leading-6 text-gray-900">{faq.question}</h3>
<p className="mt-4 text-sm text-gray-700">{faq.answer}</p>
<h3 className={`text-lg font-semibold leading-6 ${headingColorClass}`}>{faq.question}</h3>
<p className={`mt-4 text-sm ${textColorClass}`}>{faq.answer}</p>
</li>
))}
</ul>
+70 -60
View File
@@ -1,71 +1,81 @@
import { useColorMode } from "@chakra-ui/react";
import Image from "next/image";
import Link from "next/link";
import { Container } from "./Container";
export function Footer() {
return (
<footer className="border-t border-gray-200 bg-white">
<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="52" height="52" alt="logo" />
</Link>
const { colorMode } = useColorMode();
const bgColorClass = colorMode === "light" ? "bg-transparent" : "bg-gray-800";
const borderClass = colorMode === "light" ? "border-slate-200" : "border-transparent";
<div className="ml-2">
<p className="text-base font-bold">Open Assistant</p>
<p className="text-sm">Conversational AI for everyone.</p>
return (
<footer className={bgColorClass}>
<div className={`flex mx-auto max-w-7xl justify-between py-10 px-10 border-t ${borderClass}`}>
<div className="flex items-center pr-8">
<Link href="/" aria-label="Home" className="flex items-center">
<Image src="/images/logos/logo.svg" className="mx-auto object-fill" width="52" height="52" alt="logo" />
</Link>
<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="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>
<nav className="flex justify-center gap-20">
<div className="flex flex-col text-sm leading-7">
<b>Legal</b>
<div className="flex flex-col leading-5">
<Link href="/privacy-policy" aria-label="Privacy Policy" className="hover:underline underline-offset-2">
Privacy Policy
</Link>
<Link
href="/terms-of-service"
aria-label="Terms of Service"
className="hover:underline underline-offset-2"
>
Terms of Service
</Link>
</div>
</div>
<nav className="flex justify-center gap-20">
<div className="flex flex-col text-sm leading-7">
<b>Legal</b>
<div className="flex flex-col leading-5">
<Link
href="/privacy-policy"
aria-label="Privacy Policy"
className="hover:underline underline-offset-2"
>
Privacy Policy
</Link>
<Link
href="/terms-of-service"
aria-label="Terms of Service"
className="hover:underline underline-offset-2"
>
Terms of Service
</Link>
</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 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>
</Container>
</main>
</div>
</nav>
{/* </div> */}
</nav>
</div>
</footer>
);
}
@@ -22,4 +22,15 @@ const Template = (args) => {
};
export const Default = Template.bind({});
Default.args = { session: { data: { user: { name: "StoryBook user" } }, status: "authenticated" }, transparent: false };
Default.args = {
session: {
data: {
user: {
name: "StoryBook user",
},
},
status: "authenticated",
},
transparent: false,
borderClass: undefined,
};
+70 -59
View File
@@ -1,13 +1,12 @@
import { Button } from "@chakra-ui/react";
import { Box, Button, useColorMode } from "@chakra-ui/react";
import { Popover } from "@headlessui/react";
import clsx from "clsx";
import { AnimatePresence, motion } from "framer-motion";
import Image from "next/image";
import Link from "next/link";
import { useSession } from "next-auth/react";
import { FaUser } from "react-icons/fa";
import { Container } from "src/components/Container";
import { ColorModeIconToggle } from "../UI/ColorModeIconToggle";
import { NavLinks } from "./NavLinks";
import { UserMenu } from "./UserMenu";
@@ -55,63 +54,75 @@ function AccountButton() {
}
export function Header(props) {
const transparent = props.transparent ?? false;
const { colorMode } = useColorMode();
const borderClass = props.transparent
? ""
: colorMode === "light"
? "border-b border-gray-400"
: "border-b border-zinc-800";
return (
<header className={clsx(!transparent && "bg-white")}>
<nav>
<Container className="relative z-10 flex justify-between py-8">
<div className="relative z-10 flex items-center gap-16">
<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" />
<span className="text-2xl font-bold ml-3">Open Assistant</span>
</Link>
<nav className={`oa-basic-theme ${borderClass}`}>
<Box className="flex mx-auto max-w-7xl justify-between py-8 px-10">
<div className="relative z-10 flex items-center gap-16">
<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" />
<span className="text-2xl font-bold ml-3">Open Assistant</span>
</Link>
<div className="hidden lg:flex lg:gap-10">
<NavLinks />
</div>
<div className="flex items-center gap-4">
<Popover className="lg:hidden">
{({ open }) => (
<>
<Popover.Button
className="relative z-10 inline-flex items-center rounded-lg stroke-gray-900 p-2 hover:bg-gray-200/50 hover:stroke-gray-600 active:stroke-gray-900 [&:not(:focus-visible)]:focus:outline-none"
aria-label="Toggle site navigation"
>
{({ open }) => (open ? <ChevronUpIcon className="h-6 w-6" /> : <MenuIcon className="h-6 w-6" />)}
</Popover.Button>
<AnimatePresence initial={false}>
{open && (
<>
<Popover.Overlay
static
as={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-1 bg-gray-300/60 backdrop-blur"
/>
<Popover.Panel
static
as={motion.div}
initial={{ opacity: 0, y: -32 }}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: -32,
transition: { duration: 0.2 },
}}
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-white px-6 pb-6 pt-32 shadow-2xl shadow-gray-900/20"
>
<div className="mt-8 flex flex-col gap-4"></div>
</Popover.Panel>
</>
)}
</AnimatePresence>
</>
)}
</Popover>
<AccountButton />
<UserMenu />
</div>
</Container>
</nav>
</header>
</div>
<div className="flex items-center gap-4">
<Popover className="lg:hidden">
{({ open }) => (
<>
<Popover.Button
className="relative z-10 inline-flex items-center rounded-lg stroke-gray-900 p-2 hover:bg-gray-200/50 hover:stroke-gray-600 active:stroke-gray-900 [&:not(:focus-visible)]:focus:outline-none"
aria-label="Toggle site navigation"
>
{({ open }) => (open ? <ChevronUpIcon className="h-6 w-6" /> : <MenuIcon className="h-6 w-6" />)}
</Popover.Button>
<AnimatePresence initial={false}>
{open && (
<>
<Popover.Overlay
static
as={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-1 bg-gray-300/60 backdrop-blur"
/>
<Popover.Panel
static
as={motion.div}
initial={{ opacity: 0, y: -32 }}
animate={{ opacity: 1, y: 0 }}
exit={{
opacity: 0,
y: -32,
transition: { duration: 0.2 },
}}
className="absolute inset-x-0 top-0 z-0 origin-top rounded-b-2xl bg-white px-6 pb-6 pt-32 shadow-2xl shadow-gray-900/20"
>
<div className="space-y-4">
<MobileNavLink href="/#join-us">Join Us</MobileNavLink>
<MobileNavLink href="/#faqs">FAQs</MobileNavLink>
</div>
<div className="mt-8 flex flex-col gap-4"></div>
</Popover.Panel>
</>
)}
</AnimatePresence>
</>
)}
</Popover>
<AccountButton />
<UserMenu />
<ColorModeIconToggle className="ml-5" />
</div>
</Box>
</nav>
);
}
+8 -2
View File
@@ -1,9 +1,15 @@
import { useColorMode } from "@chakra-ui/react";
import { AnimatePresence, motion } from "framer-motion";
import Link from "next/link";
import { useState } from "react";
export function NavLinks(): JSX.Element {
const [hoveredIndex, setHoveredIndex] = useState(null);
const { colorMode } = useColorMode();
const linkColor = colorMode === "light" ? "text-gray-700 hover:text-gray-900" : "text-gray-50 hover:text-white";
const hoverBgColor = colorMode === "light" ? "bg-gray-100" : "bg-gray-800";
return (
<>
@@ -14,14 +20,14 @@ export function NavLinks(): JSX.Element {
<Link
key={label}
href={href}
className="relative -my-2 -mx-3 rounded-lg px-3 py-2 text-sm text-gray-700 transition-colors delay-150 hover:text-gray-900 hover:delay-[0ms]"
className={`${linkColor} relative -my-2 -mx-3 rounded-lg px-3 py-2 text-sm transition-colors delay-150 hover:delay-[0ms]`}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
>
<AnimatePresence>
{hoveredIndex === index && (
<motion.span
className="absolute inset-0 rounded-lg bg-gray-100"
className={`${hoverBgColor} absolute inset-0 rounded-lg`}
layoutId="hoverBackground"
initial={{ opacity: 0 }}
animate={{ opacity: 1, transition: { duration: 0.15 } }}
+8 -6
View File
@@ -1,3 +1,4 @@
import { Box, useColorModeValue } from "@chakra-ui/react";
import { Popover } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import Image from "next/image";
@@ -7,6 +8,7 @@ import { FaCog, FaSignOutAlt } from "react-icons/fa";
export function UserMenu() {
const { data: session } = useSession();
const backgroundColor = useColorModeValue("#FFFFFF", "#000000");
if (!session) {
return <></>;
@@ -26,7 +28,7 @@ export function UserMenu() {
{({ open }) => (
<>
<Popover.Button aria-label="Toggle Account Options" className="flex">
<div className="flex items-center gap-4 p-1 lg:pr-6 rounded-full bg-white border border-slate-300/70 hover:bg-gray-200/50 transition-colors duration-300">
<div className="flex items-center gap-4 p-1 lg:pr-6 rounded-full border border-slate-300/70 hover:bg-gray-200/50 transition-colors duration-300">
<Image
src="/images/temp-avatars/av1.jpg"
alt="Profile Picture"
@@ -41,7 +43,7 @@ export function UserMenu() {
</Popover.Button>
<AnimatePresence initial={false}>
{open && (
<>
<Box backgroundColor={backgroundColor}>
<Popover.Panel
static
as={motion.div}
@@ -52,9 +54,9 @@ export function UserMenu() {
y: -10,
transition: { duration: 0.2 },
}}
className="absolute right-0 mt-3 w-screen max-w-xs p-4 rounded-md bg-white border border-slate-300/70"
className="absolute right-0 mt-3 w-screen bg-inherit max-w-xs p-4 rounded-md border border-slate-300/70"
>
<div className="flex flex-col gap-1">
<Box className="flex flex-col gap-1">
{accountOptions.map((item) => (
<a
key={item.name}
@@ -81,9 +83,9 @@ export function UserMenu() {
<p>Sign Out</p>
</div>
</a>
</div>
</Box>
</Popover.Panel>
</>
</Box>
)}
</AnimatePresence>
</>
+22 -10
View File
@@ -1,3 +1,4 @@
import { useColorMode } from "@chakra-ui/react";
import Image from "next/image";
import { useId } from "react";
@@ -6,6 +7,10 @@ import { Container } from "./Container";
function BackgroundIllustration(props) {
const id = useId();
const { colorMode } = useColorMode();
const baseRingColor = colorMode === "light" ? "#d4d4d4" : "#005a69";
const gradStopColor = colorMode === "light" ? "#06b6d4" : "#00f2ff";
return (
<div {...props}>
<svg
@@ -16,14 +21,14 @@ function BackgroundIllustration(props) {
>
<path
d="M1025 513c0 282.77-229.23 512-512 512S1 795.77 1 513 230.23 1 513 1s512 229.23 512 512Z"
stroke="#D4D4D4"
stroke={baseRingColor}
strokeOpacity="0.7"
/>
<path d="M513 1025C230.23 1025 1 795.77 1 513" stroke={`url(#${id}-gradient-1)`} strokeLinecap="round" />
<defs>
<linearGradient id={`${id}-gradient-1`} x1="1" y1="513" x2="1" y2="1025" gradientUnits="userSpaceOnUse">
<stop stopColor="#06b6d4" />
<stop offset="1" stopColor="#06b6d4" stopOpacity="0" />
<stop stopColor={gradStopColor} />
<stop offset="1" stopColor={gradStopColor} stopOpacity="0" />
</linearGradient>
</defs>
</svg>
@@ -35,14 +40,14 @@ function BackgroundIllustration(props) {
>
<path
d="M913 513c0 220.914-179.086 400-400 400S113 733.914 113 513s179.086-400 400-400 400 179.086 400 400Z"
stroke="#D4D4D4"
stroke={baseRingColor}
strokeOpacity="0.7"
/>
<path d="M913 513c0 220.914-179.086 400-400 400" stroke={`url(#${id}-gradient-2)`} strokeLinecap="round" />
<defs>
<linearGradient id={`${id}-gradient-2`} x1="913" y1="513" x2="913" y2="913" gradientUnits="userSpaceOnUse">
<stop stopColor="#06b6d4" />
<stop offset="1" stopColor="#06b6d4" stopOpacity="0" />
<stop stopColor={gradStopColor} />
<stop offset="1" stopColor={gradStopColor} stopOpacity="0" />
</linearGradient>
</defs>
</svg>
@@ -51,17 +56,24 @@ function BackgroundIllustration(props) {
}
export function Hero() {
const { colorMode } = useColorMode();
const pTextColor = colorMode === "light" ? "text-gray-600" : "text-white";
const fancyTextGradientClasses =
colorMode === "light" ? "from-blue-600 via-sky-400 to-blue-700" : "from-blue-500 via-sky-300 to-blue-400";
return (
<div className="overflow-hidden py-20 sm:py-32 lg:pb-32 xl:pb-36">
<Container className="">
<div className="lg:grid lg:grid-cols-12 lg:gap-x-8 lg:gap-y-20">
<div className="relative z-10 mx-auto max-w-2xl lg:col-span-7 lg:max-w-none lg:pt-6 xl:col-span-6">
<h1 className="text-5xl mb-6 font-bold tracking-tight text-gray-900">Open Assistant</h1>
<p className="mt-8 text-3xl inline bg-gradient-to-r from-indigo-600 via-sky-400 to-indigo-700 bg-clip-text font-display tracking-tight text-transparent">
<h1 className="text-5xl mb-6 font-bold tracking-tight">Open Assistant</h1>
<p
className={`bg-gradient-to-r ${fancyTextGradientClasses} mt-8 text-3xl inline bg-clip-text font-display tracking-tight text-transparent`}
>
<b>Conversational AI for everyone.</b>
</p>
<p className="mt-6 text-lg text-gray-600">We believe we can create a revolution.</p>
<p className="mt-6 text-lg text-gray-600">
<p className={`mt-6 text-lg ${pTextColor}`}>We believe we can create a revolution.</p>
<p className={`mt-6 text-lg ${pTextColor}`}>
In the same way that Stable Diffusion helped the world make art and images in new ways, we want to improve
the world by providing amazing conversational AI.
</p>
@@ -1,12 +1,18 @@
import { Progress } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
export const LoadingScreen = ({ text }) => (
<div className="bg-slate-100">
<Progress size="xs" isIndeterminate />
{text && (
<div className="flex h-full">
<div className="text-xl font-bold text-gray-800 mx-auto my-auto">{text}</div>
</div>
)}
</div>
);
export const LoadingScreen = ({ text }) => {
const { colorMode } = useColorMode();
const mainClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
return (
<div className={`h-full ${mainClasses}`}>
<Progress size="sm" isIndeterminate />
{text && (
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">{text}</div>
</div>
)}
</div>
);
};
+15 -2
View File
@@ -1,4 +1,6 @@
import { Grid } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { FlaggableElement } from "./FlaggableElement";
export interface Message {
@@ -6,13 +8,24 @@ export interface Message {
is_assistant: boolean;
}
const getColor = (isAssistant: boolean) => (isAssistant ? "bg-slate-800" : "bg-sky-900");
const getBgColor = (isAssistant: boolean, colorMode: "light" | "dark") => {
if (colorMode === "light") {
return isAssistant ? "bg-slate-800" : "bg-sky-900";
} else {
return isAssistant ? "bg-black" : "bg-sky-900";
}
};
export const Messages = ({ messages, post_id }: { messages: Message[]; post_id: string }) => {
const { colorMode } = useColorMode();
const items = messages.map(({ text, is_assistant }: Message, i: number) => {
return (
<FlaggableElement text={text} post_id={post_id} key={i + text}>
<div key={i + text} className={`${getColor(is_assistant)} p-4 rounded-md text-white whitespace-pre-wrap`}>
<div
key={i + text}
className={`${getBgColor(is_assistant, colorMode)} p-4 rounded-md text-white whitespace-pre-wrap`}
>
{text}
</div>
</FlaggableElement>
+9 -6
View File
@@ -2,9 +2,9 @@ import { Flex } from "@chakra-ui/react";
import {
closestCenter,
DndContext,
KeyboardSensor,
PointerSensor,
TouchSensor,
KeyboardSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
@@ -23,6 +23,7 @@ import { SortableItem } from "./SortableItem";
export interface SortableProps {
items: ReactNode[];
onChange: (newSortedIndices: number[]) => void;
className?: string;
}
interface SortableItems {
@@ -31,18 +32,18 @@ interface SortableItems {
item: ReactNode;
}
export const Sortable = ({ items, onChange }: SortableProps) => {
export const Sortable = (props: SortableProps) => {
const [itemsWithIds, setItemsWithIds] = useState<SortableItems[]>([]);
useEffect(() => {
setItemsWithIds(
items.map((item, idx) => ({
props.items.map((item, idx) => ({
item,
id: idx + 1, // +1 because dndtoolkit has problem with "falsy" ids
originalIndex: idx,
}))
);
}, [items]);
}, [props.items]);
const sensors = useSensors(
useSensor(PointerSensor),
@@ -50,6 +51,8 @@ export const Sortable = ({ items, onChange }: SortableProps) => {
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
);
const extraClasses = props.className || "";
return (
<DndContext
sensors={sensors}
@@ -58,7 +61,7 @@ export const Sortable = ({ items, onChange }: SortableProps) => {
modifiers={[restrictToVerticalAxis]}
>
<SortableContext items={itemsWithIds} strategy={verticalListSortingStrategy}>
<Flex direction="column" gap={2}>
<Flex direction="column" gap={2} className={extraClasses}>
{itemsWithIds.map(({ id, item }) => (
<SortableItem key={id} id={id}>
{item}
@@ -78,7 +81,7 @@ export const Sortable = ({ items, onChange }: SortableProps) => {
const oldIndex = items.findIndex((x) => x.id === active.id);
const newIndex = items.findIndex((x) => x.id === over.id);
const newArray = arrayMove(items, oldIndex, newIndex);
onChange(newArray.map((item) => item.originalIndex));
props.onChange(newArray.map((item) => item.originalIndex));
return newArray;
});
}
@@ -1,8 +1,9 @@
import { Button } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { RxDragHandleDots2 } from "react-icons/rx";
import { PropsWithChildren } from "react";
import { RxDragHandleDots2 } from "react-icons/rx";
export const SortableItem = ({ children, id }: PropsWithChildren<{ id: number }>) => {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
@@ -13,9 +14,15 @@ export const SortableItem = ({ children, id }: PropsWithChildren<{ id: number }>
touchAction: "none",
};
const { colorMode } = useColorMode();
const themedClasses =
colorMode === "light"
? "bg-slate-600 hover:bg-slate-500 text-white"
: "bg-black hover:bg-slate-900 text-white ring-1 ring-white/30 ring-inset hover:ring-slate-200/50";
return (
<li
className="grid grid-cols-[min-content_1fr] items-center rounded-lg shadow-md gap-x-2 p-2 bg-white hover:bg-slate-50"
className={`grid grid-cols-[min-content_1fr] items-center rounded-lg shadow-md gap-x-2 p-2 ${themedClasses}`}
ref={setNodeRef}
style={style}
>
@@ -0,0 +1,20 @@
import { useColorMode } from "@chakra-ui/react";
interface SurveyCardProps {
className?: string;
children: React.ReactNode;
}
export const SurveyCard = (props: SurveyCardProps) => {
const extraClases = props.className || "";
const { colorMode } = useColorMode();
const baseCardClasses = "rounded-lg h-full block p-6";
const cardClases =
colorMode === "light"
? `${baseCardClasses} bg-slate-50 text-gray-800 shadow-lg ${extraClases}`
: // `${baseCardClasses} bg-slate-800 text-white shadow-xl${extraClases}`;
`${baseCardClasses} bg-slate-800 text-slate-400 shadow-xl ring-1 ring-white/10 ring-inset ${extraClases}`;
return <div className={cardClases}>{props.children}</div>;
};
@@ -0,0 +1,40 @@
import { useColorMode } from "@chakra-ui/react";
import { Flex } from "@chakra-ui/react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
interface TaskControlsProps {
// we need a task type
// eslint-disable-next-line @typescript-eslint/no-explicit-any
tasks: any[];
className?: string;
onSubmitResponse: (task: { id: string }) => void;
onSkip: () => void;
}
export const TaskControls = (props: TaskControlsProps) => {
const extraClases = props.className || "";
const { colorMode } = useColorMode();
const baseClasses = "flex flex-row justify-items-stretch mb-8 p-4 rounded-lg max-w-7xl mx-auto";
const taskControlClases =
colorMode === "light"
? `${baseClasses} bg-white text-gray-800 shadow-lg ${extraClases}`
: `${baseClasses} bg-slate-800 text-slate-400 shadow-xl ring-1 ring-white/10 ring-inset ${extraClases}`;
const endTask = props.tasks[props.tasks.length - 1];
return (
<section className={taskControlClases}>
<TaskInfo id={props.tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton onClick={() => props.onSubmitResponse(props.tasks[0])}>Submit</SubmitButton>
) : (
<SubmitButton onClick={props.onSkip}>Next Task</SubmitButton>
)}
</Flex>
</section>
);
};
@@ -0,0 +1,16 @@
import { SurveyCard } from "src/components/Survey/SurveyCard";
export const TwoColumnsWithCards = ({ children }: { children: React.ReactNode[] }) => {
if (!Array.isArray(children) || children.length !== 2) {
throw new Error("TwoColumns expects 2 children");
}
const [first, second] = children;
return (
<div className="mb-8 mx-auto max-w-7xl lt-lg:mb-12 grid lg:gap-x-12 lg:grid-cols-2">
<SurveyCard>{first}</SurveyCard>
<SurveyCard className="lg:mt-0 lt-lg:mt-6">{second}</SurveyCard>
</div>
);
};
+1 -1
View File
@@ -1,6 +1,6 @@
export const TaskInfo = ({ id, output }: { id: string; output: string }) => {
return (
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<div className="grid grid-cols-[min-content_auto] gap-x-2 ">
<b>Prompt</b>
<span data-cy="task-id">{id}</span>
<b>Output</b>
@@ -1,12 +1,24 @@
import { Flex } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import React from "react";
import { TaskOption } from "./TaskOption";
import { TaskOptions } from "./TaskOptions";
export const TaskSelection = () => {
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
return (
<Flex gap={10} wrap="wrap" justifyContent="space-evenly" width="full" height="full" alignItems={"center"}>
<Flex
gap={10}
wrap="wrap"
justifyContent="space-evenly"
width="full"
height="full"
alignItems={"center"}
className={mainBgClasses}
>
<TaskOptions key="create" title="Create">
{/* <TaskOption
alt="Summarize Stories"
-14
View File
@@ -1,14 +0,0 @@
export const TwoColumns = ({ children }: { children: React.ReactNode[] }) => {
if (!Array.isArray(children) || children.length !== 2) {
throw new Error("TwoColumns expects 2 children");
}
const [first, second] = children;
return (
<section className="mb-8 lt-lg:mb-12 grid lg:gap-x-12 lg:grid-cols-2">
<div className="rounded-lg shadow-lg h-full block bg-white p-6">{first}</div>
<div className="rounded-lg shadow-lg h-full block bg-white p-6 mt-6 lg:mt-0">{second}</div>
</section>
);
};
@@ -0,0 +1,23 @@
import { useColorMode } from "@chakra-ui/react";
import { CiDark } from "react-icons/ci";
import { CiLight } from "react-icons/ci";
export function ColorModeIconToggle(props) {
const { colorMode, toggleColorMode } = useColorMode();
const propsClassName = props.className ?? "";
return (
<button
type="button"
className={`flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5 ${propsClassName}`}
aria-label="Toggle dark mode"
onClick={toggleColorMode}
>
{colorMode === "light" ? (
<CiDark className="h-5 w-5 stroke-zinc-900 dark:hidden" />
) : (
<CiLight className="h-5 w-5 stroke-white" />
)}
</button>
);
}
@@ -0,0 +1,16 @@
import { Switch, useColorMode } from "@chakra-ui/react";
import React from "react";
const ColorModeSwitch = () => {
const { colorMode, toggleColorMode } = useColorMode();
return (
<Switch
onChange={toggleColorMode}
defaultChecked={colorMode === "light"}
checked={colorMode === "light"}
size="lg"
/>
);
};
export default ColorModeSwitch;
+5 -28
View File
@@ -1,48 +1,25 @@
import "../styles/globals.css";
import "focus-visible";
import { ChakraProvider } from "@chakra-ui/react";
import { extendTheme } from "@chakra-ui/react";
import { Inter } from "@next/font/google";
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
import { getDefaultLayout, NextPageWithLayout } from "src/components/Layout";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const inter = Inter({
subsets: ["latin"],
variable: "--font-inter",
});
const theme = extendTheme({
styles: {
global: {
body: {
bg: "white",
},
main: {
fontFamily: "Inter",
},
header: {
fontFamily: "Inter",
},
},
},
});
import { Chakra, getServerSideProps } from "../styles/Chakra";
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
function MyApp({ Component, pageProps: { session, ...pageProps } }: AppPropsWithLayout) {
function MyApp({ Component, pageProps: { session, cookies, ...pageProps } }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? getDefaultLayout;
const page = getLayout(<Component {...pageProps} />);
return (
<ChakraProvider theme={theme}>
<Chakra cookies={cookies}>
<SessionProvider session={session}>{page}</SessionProvider>
</ChakraProvider>
</Chakra>
);
}
export { getServerSideProps };
export default MyApp;
@@ -64,6 +64,8 @@ const handler = async (req, res) => {
}),
});
ackRes; // calling this only to get rid of the unused variable warning... not sure if anything is intended to be done with ackRes
// Send the results to the client.
res.status(200).json(registeredTask);
};
+30 -12
View File
@@ -1,13 +1,16 @@
import { Button, Input, Stack } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import Head from "next/head";
import Link from "next/link";
import { getCsrfToken, getProviders, signIn } from "next-auth/react";
import React, { useRef } from "react";
import { FaBug, FaDiscord, FaEnvelope, FaGithub } from "react-icons/fa";
import { AuthLayout } from "src/components/AuthLayout";
import { Footer } from "src/components/Footer";
import { Header } from "src/components/Header";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function Signin({ csrfToken, providers }) {
function Signin({ csrfToken, providers }) {
const { discord, email, github, credentials } = providers;
const emailEl = useRef(null);
const signinWithEmail = (ev: React.FormEvent) => {
@@ -21,8 +24,14 @@ export default function Signin({ csrfToken, providers }) {
signIn(credentials.id, { callbackUrl: "/", username: debugUsernameEl.current.value });
}
const { colorMode } = useColorMode();
const bgColorClass = colorMode === "light" ? "bg-gray-50" : "bg-chakra-gray-900";
const buttonBgColor = colorMode === "light" ? "#2563eb" : "#2563eb";
const buttonColorScheme = colorMode === "light" ? "blue" : "dark-blue-btn";
return (
<>
<div className={bgColorClass}>
<Head>
<title>Sign Up - Open Assistant</title>
<meta name="Sign Up" content="Sign up to access Open Assistant" />
@@ -30,11 +39,11 @@ export default function Signin({ csrfToken, providers }) {
<AuthLayout>
<Stack spacing="2">
{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>
<form onSubmit={signinWithDebugCredentials} className="border-2 border-orange-600 rounded-md p-4 relative">
<span className={`text-orange-600 absolute -top-3 left-5 ${bgColorClass} 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">
<Button size={"lg"} leftIcon={<FaBug />} colorScheme={buttonColorScheme} color="white" type="submit">
Continue with Debug User
</Button>
</Stack>
@@ -43,13 +52,13 @@ export default function Signin({ csrfToken, providers }) {
{email && (
<form onSubmit={signinWithEmail}>
<Stack>
<Input data-cy="email-address" variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Input variant="outline" size="lg" placeholder="Email Address" ref={emailEl} />
<Button
data-cy="signin-email-button"
size={"lg"}
leftIcon={<FaEnvelope />}
colorScheme="gray"
type="submit"
colorScheme={buttonColorScheme}
color="white"
>
Continue with Email
</Button>
@@ -58,7 +67,7 @@ export default function Signin({ csrfToken, providers }) {
)}
{discord && (
<Button
bg="#5865F2"
bg={buttonBgColor}
_hover={{ bg: "#4A57E3" }}
_active={{
bg: "#454FBF",
@@ -107,12 +116,21 @@ export default function Signin({ csrfToken, providers }) {
</Link>
</div>
</AuthLayout>
</>
</div>
);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function getServerSideProps(context) {
Signin.getLayout = (page) => (
<div className="grid grid-rows-[min-content_1fr_min-content] h-full justify-items-stretch">
<Header transparent={true} />
{page}
<Footer />
</div>
);
export default Signin;
export async function getServerSideProps() {
const csrfToken = await getCsrfToken();
const providers = await getProviders();
return {
+14 -27
View File
@@ -1,11 +1,10 @@
import { Flex, Textarea } from "@chakra-ui/react";
import { Container, Textarea } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { useRef, useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Messages } from "src/components/Messages";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { TwoColumns } from "src/components/TwoColumns";
import { TaskControls } from "src/components/Survey/TaskControls";
import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -45,43 +44,31 @@ const AssistantReply = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">No tasks found...</div>;
return <Container className="p-6 text-center text-gray-800">No tasks found...</Container>;
}
const task = tasks[0].task;
const endTask = tasks[tasks.length - 1];
return (
<div className="p-6 bg-slate-100 text-gray-800">
<TwoColumns>
<div className={`p-12 ${mainBgClasses}`}>
<TwoColumnsWithCards>
<>
<h5 className="text-lg font-semibold">Reply as the assistant</h5>
<p className="text-lg py-1">Given the following conversation, provide an adequate reply</p>
<Messages messages={task.conversation.messages} post_id={task.id} />
</>
<Textarea name="reply" data-cy="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumns>
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumnsWithCards>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton data-cy="submit" onClick={() => submitResponse(tasks[0])}>
Submit
</SubmitButton>
) : (
<SubmitButton data-cy="next-task" onClick={fetchNextTask}>
Next Task
</SubmitButton>
)}
</Flex>
</section>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</div>
);
};
+18 -23
View File
@@ -1,11 +1,9 @@
import { Flex, Textarea } from "@chakra-ui/react";
import Head from "next/head";
import { Textarea } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { useRef, useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { TwoColumns } from "src/components/TwoColumns";
import { TaskControls } from "src/components/Survey/TaskControls";
import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -20,7 +18,7 @@ const SummarizeStory = () => {
// Fetch the very fist task. We can ignore everything except isLoading
// because the onSuccess handler will update `tasks` when ready.
const { isLoading } = useSWRImmutable("/api/new_task/summarize_story", fetcher, {
const { isLoading, mutate } = useSWRImmutable("/api/new_task/summarize_story", fetcher, {
onSuccess: (data) => {
setTasks([data]);
},
@@ -50,6 +48,14 @@ const SummarizeStory = () => {
});
};
const fetchNextTask = () => {
inputRef.current.value = "";
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
@@ -59,31 +65,20 @@ const SummarizeStory = () => {
}
return (
<>
<Head>
<title>Summarize A Story</title>
<meta name="description" content="Summarize a story to train our model." />
</Head>
<div className={`p-12 ${mainBgClasses}`}>
<main className="p-6 h-full mx-auto bg-slate-100 text-gray-800">
<TwoColumns>
<TwoColumnsWithCards>
<>
<h5 className="text-lg font-semibold">Instruction</h5>
<p className="text-lg py-1">Summarize the following story</p>
<div className="bg-slate-800 p-6 rounded-xl text-white whitespace-pre-wrap">{tasks[0].task.story}</div>
</>
<Textarea name="summary" placeholder="Summary" ref={inputRef} />
</TwoColumns>
</TwoColumnsWithCards>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
</Flex>
</section>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</main>
</>
</div>
);
};
+20 -26
View File
@@ -1,11 +1,10 @@
import { Flex, Textarea } from "@chakra-ui/react";
import { Textarea } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { useRef, useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Messages } from "src/components/Messages";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { TwoColumns } from "src/components/TwoColumns";
import { TaskControls } from "src/components/Survey/TaskControls";
import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -45,43 +44,38 @@ const UserReply = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">No tasks found...</div>;
return (
<div className={`p-12 ${mainBgClasses}`}>
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">No tasks found...</div>
</div>
</div>
);
}
const task = tasks[0].task;
const endTask = tasks[tasks.length - 1];
return (
<div className="p-6 bg-slate-100 text-gray-800">
<TwoColumns>
<div className={`p-12 ${mainBgClasses}`}>
<TwoColumnsWithCards>
<>
<h5 className="text-lg font-semibold">Reply as a user</h5>
<p className="text-lg py-1">Given the following conversation, provide an adequate reply</p>
<Messages messages={task.conversation.messages} post_id={task.id} />
{task.hint && <p className="text-lg py-1">Hint: {task.hint}</p>}
</>
<Textarea name="reply" data-cy="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumns>
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
</TwoColumnsWithCards>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton data-cy="submit" onClick={() => submitResponse(tasks[0])}>
Submit
</SubmitButton>
) : (
<SubmitButton data-cy="next-task" onClick={fetchNextTask}>
Next Task
</SubmitButton>
)}
</Flex>
</section>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</div>
);
};
@@ -1,11 +1,10 @@
import { Flex } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Sortable } from "src/components/Sortable/Sortable";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SurveyCard } from "src/components/Survey/SurveyCard";
import { TaskControls } from "src/components/Survey/TaskControls";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -47,48 +46,42 @@ const RankAssistantReplies = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">Loading...</div>;
return (
<div className={`p-12 ${mainBgClasses}`}>
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">No tasks found...</div>
</div>
</div>
);
}
const replies = tasks[0].task.replies as string[];
const endTask = tasks[tasks.length - 1];
return (
<>
<Head>
<title>Rank Assistant Replies</title>
<meta name="description" content="Rank Assistant Replies." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<div className="rounded-lg shadow-lg block bg-white p-6 mb-8">
<div className={`p-12 ${mainBgClasses}`}>
<SurveyCard className="max-w-7xl mx-auto h-fit mb-24">
<h5 className="text-lg font-semibold mb-4">Instructions</h5>
<p className="text-lg py-1">
Given the following replies, sort them from best to worst, best being first, worst being last.
</p>
<Sortable items={replies} onChange={setRanking} />
</div>
<Sortable items={replies} onChange={setRanking} className="my-8" />
</SurveyCard>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton data-cy="submit" onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
Submit
</SubmitButton>
) : (
<SubmitButton data-cy="next-task" onClick={fetchNextTask}>
Next Task
</SubmitButton>
)}
</Flex>
</section>
</main>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</div>
</>
);
};
@@ -1,11 +1,10 @@
import { Flex } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Sortable } from "src/components/Sortable/Sortable";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SurveyCard } from "src/components/Survey/SurveyCard";
import { TaskControls } from "src/components/Survey/TaskControls";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -18,6 +17,7 @@ const RankInitialPrompts = () => {
* The best prompt will have index 0, and the worst is the last.
*/
const [ranking, setRanking] = useState<number[]>([]);
// const bg = useColorModeValue("gray.100", "gray.800");
const { isLoading, mutate } = useSWRImmutable("/api/new_task/rank_initial_prompts", fetcher, {
onSuccess: (data) => {
@@ -47,47 +47,40 @@ const RankInitialPrompts = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">No tasks found...</div>;
return (
<div className={`p-12 ${mainBgClasses}`}>
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">No tasks found...</div>
</div>
</div>
);
}
const endTask = tasks[tasks.length - 1];
return (
<>
<Head>
<title>Rank Initial Prompts</title>
<meta name="description" content="Rank initial prompts." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<div className="rounded-lg shadow-lg block bg-white p-6 mb-8">
<div className={`p-12 ${mainBgClasses}`}>
<SurveyCard className="max-w-7xl mx-auto h-fit mb-24">
<h5 className="text-lg font-semibold mb-4">Instructions</h5>
<p className="text-lg py-1">
Given the following prompts, sort them from best to worst, best being first, worst being last.
</p>
<Sortable items={tasks[0].task.prompts} onChange={setRanking} />
</div>
<Sortable items={tasks[0].task.prompts} onChange={setRanking} className="my-8" />
</SurveyCard>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton data-cy="submit" onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
Submit
</SubmitButton>
) : (
<SubmitButton data-cy="next-task" onClick={fetchNextTask}>
Next Task
</SubmitButton>
)}
</Flex>
</section>
</main>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</div>
</>
);
};
@@ -1,11 +1,10 @@
import { Flex } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { Sortable } from "src/components/Sortable/Sortable";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { SurveyCard } from "src/components/Survey/SurveyCard";
import { TaskControls } from "src/components/Survey/TaskControls";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -47,48 +46,41 @@ const RankUserReplies = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">Loading...</div>;
return (
<div className={`p-12 ${mainBgClasses}`}>
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">No tasks found...</div>
</div>
</div>
);
}
const replies = tasks[0].task.replies as string[];
const endTask = tasks[tasks.length - 1];
return (
<>
<Head>
<title>Rank User Replies</title>
<meta name="description" content="Rank User Replies." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<div className="rounded-lg shadow-lg block bg-white p-6 mb-8">
<div className={`p-12 ${mainBgClasses}`}>
<SurveyCard className="max-w-7xl mx-auto h-fit mb-24">
<h5 className="text-lg font-semibold mb-4">Instructions</h5>
<p className="text-lg py-1">
Given the following replies, sort them from best to worst, best being first, worst being last.
</p>
<Sortable items={replies} onChange={setRanking} />
</div>
<Sortable items={replies} onChange={setRanking} className="my-8" />
</SurveyCard>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton data-cy="submit" onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
Submit
</SubmitButton>
) : (
<SubmitButton data-cy="next-task" onClick={fetchNextTask}>
Next Task
</SubmitButton>
)}
</Flex>
</section>
</main>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</div>
</>
);
};
+21 -21
View File
@@ -1,13 +1,12 @@
import { Flex, Textarea } from "@chakra-ui/react";
import { Textarea } from "@chakra-ui/react";
import { useColorMode } from "@chakra-ui/react";
import { QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
import Head from "next/head";
import { useState } from "react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import RatingRadioGroup from "src/components/RatingRadioGroup";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
import { TwoColumns } from "src/components/TwoColumns";
import { TaskControls } from "src/components/Survey/TaskControls";
import { TwoColumnsWithCards } from "src/components/Survey/TwoColumnsWithCards";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
@@ -50,15 +49,27 @@ const RateSummary = () => {
});
};
const fetchNextTask = () => {
mutate();
};
const { colorMode } = useColorMode();
const mainBgClasses = colorMode === "light" ? "bg-slate-300 text-gray-800" : "bg-slate-900 text-white";
if (isLoading) {
return <LoadingScreen text="Loading..." />;
}
if (tasks.length == 0) {
return <div className="p-6 bg-slate-100 text-gray-800">No tasks found...</div>;
return (
<div className={`p-12 ${mainBgClasses}`}>
<div className="flex h-full">
<div className="text-xl font-bold mx-auto my-auto">No tasks found...</div>
</div>
</div>
);
}
const endTask = tasks[tasks.length - 1];
return (
<>
<Head>
@@ -66,7 +77,7 @@ const RateSummary = () => {
<meta name="description" content="Rate a proposed story summary." />
</Head>
<main className="p-6 bg-slate-100 text-gray-800">
<TwoColumns>
<TwoColumnsWithCards>
<>
<h5 className="text-lg font-semibold mb-4">Instruction</h5>
<div className="bg-slate-800 p-6 rounded-xl text-white whitespace-pre-wrap">{tasks[0].task.full_text}</div>
@@ -89,20 +100,9 @@ const RateSummary = () => {
</ul>
<Textarea name="notes" placeholder="Optional notes" />
</section>
</TwoColumns>
</TwoColumnsWithCards>
<section className="mb-8 p-4 rounded-lg shadow-lg bg-white flex flex-row justify-items-stretch ">
<TaskInfo id={tasks[0].id} output="Submit your answer" />
<Flex justify="center" ml="auto" gap={2}>
<SkipButton>Skip</SkipButton>
{endTask.task.type !== "task_done" ? (
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
) : (
<SubmitButton onClick={mutate}>Next Task</SubmitButton>
)}
</Flex>
</section>
<TaskControls tasks={tasks} onSubmitResponse={submitResponse} onSkip={fetchNextTask} />
</main>
</>
);
+2 -4
View File
@@ -20,11 +20,9 @@ const Home = () => {
/>
</Head>
{session ? (
<main className="my-4">
<TaskSelection />
</main>
<TaskSelection />
) : (
<main>
<main className="oa-basic-theme">
<Hero />
<CallToAction />
<Faq />
+24
View File
@@ -0,0 +1,24 @@
import { ChakraProvider, cookieStorageManagerSSR, localStorageManager } from "@chakra-ui/react";
import { theme } from "./Theme";
export function Chakra({ cookies, children }) {
const colorModeManager = typeof cookies === "string" ? cookieStorageManagerSSR(cookies) : localStorageManager;
return (
<ChakraProvider theme={theme} colorModeManager={colorModeManager}>
{children}
</ChakraProvider>
);
}
// also export a reusable function getServerSideProps
export function getServerSideProps({ req }) {
return {
props: {
// first time users will not have any cookies and you may not return
// undefined here, hence ?? is necessary
cookies: req.headers.cookie ?? "",
},
};
}
+14
View File
@@ -0,0 +1,14 @@
export const colors = {
light: {
bg: "rgb(250,250,250)",
text: "black",
},
dark: {
bg: "gray.900",
text: "white",
},
"dark-blue-btn": {
200: "rgb(29,78,216)",
300: "blue",
},
};
@@ -0,0 +1,14 @@
import { defineStyleConfig } from "@chakra-ui/styled-system";
const baseStyle = {};
const variants = {
"no-padding": {
padding: 0,
},
};
export const containerTheme = defineStyleConfig({
baseStyle,
variants,
});
+37
View File
@@ -0,0 +1,37 @@
import { type ThemeConfig, extendTheme } from "@chakra-ui/react";
import { Styles } from "@chakra-ui/theme-tools";
import { colors } from "./colors";
import { containerTheme } from "./components/Container";
const config: ThemeConfig = {
initialColorMode: "light",
useSystemColorMode: true,
disableTransitionOnChange: false,
};
const components = {
Container: containerTheme,
};
const styles: Styles = {
global: (props) => ({
"*": {
transition: "background-color 200ms cubic-bezier(0.4, 0, 1, 1)",
// bg: props.colorMode === "light" ? colors.light.bg : colors.dark.bg,
// color: props.colorMode === "light" ? colors.light.text : colors.dark.text,
},
".oa-basic-theme": {
bg: props.colorMode === "light" ? colors.light.bg : colors.dark.bg,
color: props.colorMode === "light" ? colors.light.text : colors.dark.text,
},
main: {
fontFamily: "Inter",
},
header: {
fontFamily: "Inter",
},
}),
};
export const theme = extendTheme({ colors, config, styles, components });
+4
View File
@@ -71,6 +71,10 @@ module.exports = {
maxWidth: {
"2xl": "40rem",
},
colors: {
"chakra-gray-900": "#171923",
},
},
},
plugins: [require("@tailwindcss/forms")],