Merge branch 'main' of github.com:LAION-AI/Open-Chat-GPT

This commit is contained in:
Yannic Kilcher
2023-01-01 17:17:09 +01:00
46 changed files with 380 additions and 183 deletions
+3 -2
View File
@@ -57,7 +57,8 @@ repos:
- id: next-lint-website
name: Lint website
files: ^website/
exclude: ^website/node_modules/
types_or: [javascript, jsx, ts, tsx]
language: system
language: node
pass_filenames: false
entry: bash -c "cd website && npm install && npm run lint"
entry: website/next-lint.js
+77
View File
@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-
"""Bot logic."""
from datetime import datetime
import aiosqlite
import hikari
import lightbulb
import miru
from bot.api_client import OasstApiClient
from bot.settings import Settings
from bot.utils import EMPTY, mention
settings = Settings()
@@ -38,3 +41,77 @@ async def on_stopping(event: hikari.StoppingEvent):
"""Cleanup."""
await bot.d.db.close()
await bot.d.oasst_api.close()
async def _send_error_embed(
content: str, exception: lightbulb.errors.LightbulbError | BaseException, ctx: lightbulb.Context
) -> None:
ctx.command
embed = hikari.Embed(
title=f"`{exception.__class__.__name__}` Error{f' in `{ctx.command.name}`' if ctx.command else '' }",
description=content,
color=0xFF0000,
timestamp=datetime.now().astimezone(),
).set_author(name=ctx.author.username, url=str(ctx.author.avatar_url))
await ctx.respond(EMPTY, embed=embed)
@bot.listen(lightbulb.CommandErrorEvent)
async def on_error(event: lightbulb.CommandErrorEvent) -> None:
"""Error handler for the bot."""
# Unwrap the exception to get the original cause
exc = event.exception.__cause__ or event.exception
ctx = event.context
if isinstance(event.exception, lightbulb.CommandInvocationError):
if not event.context.command:
await _send_error_embed("Something went wrong", exc, ctx)
else:
await _send_error_embed(
f"Something went wrong during invocation of command `{event.context.command.name}`.", exc, ctx
)
raise event.exception
# Not an owner
if isinstance(exc, lightbulb.NotOwner):
await _send_error_embed("You are not the owner of this bot.", exc, ctx)
# Command is on cooldown
elif isinstance(exc, lightbulb.CommandIsOnCooldown):
await _send_error_embed(f"This command is on cooldown. Retry in `{exc.retry_after:.2f}` seconds.", exc, ctx)
# Missing permissions
elif isinstance(exc, lightbulb.errors.MissingRequiredPermission):
await _send_error_embed(
f"You do not have permission to use this command. Missing permissions: {exc.missing_perms}", exc, ctx
)
# Missing roles
elif isinstance(exc, lightbulb.errors.MissingRequiredRole):
assert event.context.guild_id is not None # Roles only exist in guilds
await _send_error_embed(
f"You do not have the correct role to use this command. Missing role(s): {[mention(r, 'role') for r in exc.missing_roles]}",
exc,
ctx,
)
# Only a guild command
elif isinstance(exc, lightbulb.errors.OnlyInGuild):
await _send_error_embed("This command can only be run in servers.", exc, ctx)
# Only a DM command
elif isinstance(exc, lightbulb.errors.OnlyInDM):
await _send_error_embed("This command can only be run in DMs.", exc, ctx)
# Not enough arguments
elif isinstance(exc, lightbulb.errors.NotEnoughArguments):
await _send_error_embed(
f"Not enough arguments were supplied to the command. {[opt.name for opt in exc.missing_options]}", exc, ctx
)
# Bot missing permission
elif isinstance(exc, lightbulb.errors.BotMissingRequiredPermission):
await _send_error_embed(
f"The bot does not have the correct permission(s) to execute this command. Missing permissions: {exc.missing_perms}",
exc,
ctx,
)
elif isinstance(exc, lightbulb.errors.MissingRequiredAttachment):
await _send_error_embed("Not enough attachemnts were supplied to this command.", exc, ctx)
else:
raise exc
+20 -10
View File
@@ -5,7 +5,7 @@ import lightbulb
from aiosqlite import Connection
from bot.db.schemas import GuildSettings
from bot.utils import mention
from lightbulb.utils.permissions import permissions_in
from lightbulb.utils import permissions_in
from loguru import logger
plugin = lightbulb.Plugin("GuildSettings")
@@ -56,32 +56,42 @@ if guild_settings.log_channel_id else 'not set'}
@settings.child
@lightbulb.option("channel", "The channel to use.", hikari.TextableGuildChannel)
@lightbulb.command("log_channel", "Set the channel that the bot logs task and label completions in.")
@lightbulb.command("log_channel", "Set the channel that the bot logs task and label completions in.", ephemeral=True)
@lightbulb.implements(lightbulb.SlashSubCommand)
async def log_channel(ctx: lightbulb.SlashContext) -> None:
"""Set the channel that the bot logs task and label completions in."""
channel: hikari.TextableGuildChannel = ctx.options.channel
conn: Connection = ctx.bot.d.db
assert ctx.guild_id is not None # `guild_only` check
assert isinstance(channel, hikari.PermissibleGuildChannel)
# Check if the bot can send messages in that channel
assert (me := ctx.bot.get_me()) is not None # non-None after `StartedEvent`
if (own_member := ctx.bot.cache.get_member(ctx.guild_id, me.id)) is None:
own_member = await ctx.bot.rest.fetch_member(ctx.guild_id, me.id)
perms = permissions_in(channel, own_member)
if perms & ~hikari.Permissions.SEND_MESSAGES:
await ctx.respond("I don't have permission to send messages in that channel.")
assert isinstance(channel, hikari.InteractionChannel) # Slash commands are interactions
me = ctx.bot.cache.get_me() or await ctx.bot.rest.fetch_my_user()
own_member = ctx.bot.cache.get_member(ctx.guild_id, me.id) or await ctx.bot.rest.fetch_member(ctx.guild_id, me.id)
# Get the channel from the cache if it is there, otherwise fetch it
if (ch := ctx.bot.cache.get_guild_channel(channel.id)) is None:
ch = {ch.id: ch for ch in await ctx.bot.rest.fetch_guild_channels(channel.id)}[channel.id]
if not isinstance(ch, hikari.GuildTextChannel):
await ctx.respond(f"{ch.mention} is not a text channel.")
return
# if the bot's permissions for this channel don't contain SEND_MESSAGE
# This will also filter out categories and voice channels
print(permissions_in(ch, own_member) & hikari.Permissions.SEND_MESSAGES)
if not permissions_in(ch, own_member) & hikari.Permissions.SEND_MESSAGES:
await ctx.respond(f"I don't have permission to send messages in {ch.mention}.")
return
await ctx.respond(f"Setting `log_channel` to {channel.mention}.")
# update the database
async with conn.cursor() as cursor:
await cursor.execute(
"INSERT OR REPLACE INTO guild_settings (guild_id, log_channel_id) VALUES (?, ?)",
(ctx.guild_id, channel.id),
)
await conn.commit()
logger.info(f"Updated `log_channel` for {ctx.guild_id} to {channel.id}.")
+5 -2
View File
@@ -6,6 +6,9 @@
"next/core-web-vitals"
],
"rules": {
"sort-imports": "warn"
}
"unused-imports/no-unused-imports": "warn",
"simple-import-sort/imports": "warn",
"simple-import-sort/exports": "warn"
},
"plugins": ["simple-import-sort", "unused-imports"]
}
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env node
const { spawnSync } = require("child_process");
async function npmLint() {
const spawnOption = {
shell: true,
env: process.env,
stdio: "inherit",
cwd: "./website",
};
let npmInstall;
let npmRunLint;
try {
npmInstall = await spawnSync("npm", ["install"], spawnOption);
if (npmInstall.status !== 0) {
process.exit(npmInstall.status);
}
npmRunLint = await spawnSync("npm", ["run lint"], spawnOption);
process.exit(npmRunLint.status);
} catch (error) {
console.error(error);
process.exit(1);
}
}
npmLint();
+84
View File
@@ -10,6 +10,7 @@
"dependencies": {
"@chakra-ui/react": "^2.4.4",
"@dnd-kit/core": "^6.0.6",
"@dnd-kit/modifiers": "^6.0.1",
"@dnd-kit/sortable": "^7.0.1",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
@@ -25,6 +26,7 @@
"clsx": "^1.2.1",
"eslint": "8.29.0",
"eslint-config-next": "13.0.6",
"eslint-plugin-simple-import-sort": "^8.0.0",
"focus-visible": "^5.2.0",
"framer-motion": "^6.5.1",
"next": "13.0.6",
@@ -58,6 +60,7 @@
"cypress": "^12.2.0",
"cypress-image-diff-js": "^1.23.0",
"eslint-plugin-storybook": "^0.6.8",
"eslint-plugin-unused-imports": "^2.0.0",
"prettier": "2.8.1",
"prisma": "^4.7.1",
"typescript": "4.9.4"
@@ -3354,6 +3357,19 @@
"react-dom": ">=16.8.0"
}
},
"node_modules/@dnd-kit/modifiers": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz",
"integrity": "sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==",
"dependencies": {
"@dnd-kit/utilities": "^3.2.1",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@dnd-kit/core": "^6.0.6",
"react": ">=16.8.0"
}
},
"node_modules/@dnd-kit/sortable": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.1.tgz",
@@ -16343,6 +16359,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/eslint-plugin-simple-import-sort": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
"integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
"peerDependencies": {
"eslint": ">=5.0.0"
}
},
"node_modules/eslint-plugin-storybook": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.8.tgz",
@@ -16370,6 +16394,36 @@
"lodash": "^4.17.15"
}
},
"node_modules/eslint-plugin-unused-imports": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz",
"integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==",
"dev": true,
"dependencies": {
"eslint-rule-composer": "^0.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"peerDependencies": {
"@typescript-eslint/eslint-plugin": "^5.0.0",
"eslint": "^8.0.0"
},
"peerDependenciesMeta": {
"@typescript-eslint/eslint-plugin": {
"optional": true
}
}
},
"node_modules/eslint-rule-composer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz",
"integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==",
"dev": true,
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
@@ -30865,6 +30919,15 @@
"tslib": "^2.0.0"
}
},
"@dnd-kit/modifiers": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-6.0.1.tgz",
"integrity": "sha512-rbxcsg3HhzlcMHVHWDuh9LCjpOVAgqbV78wLGI8tziXY3+qcMQ61qVXIvNKQFuhj75dSfD+o+PYZQ/NUk2A23A==",
"requires": {
"@dnd-kit/utilities": "^3.2.1",
"tslib": "^2.0.0"
}
},
"@dnd-kit/sortable": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.1.tgz",
@@ -40973,6 +41036,12 @@
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
"requires": {}
},
"eslint-plugin-simple-import-sort": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
"integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
"requires": {}
},
"eslint-plugin-storybook": {
"version": "0.6.8",
"resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.8.tgz",
@@ -40996,6 +41065,21 @@
}
}
},
"eslint-plugin-unused-imports": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-2.0.0.tgz",
"integrity": "sha512-3APeS/tQlTrFa167ThtP0Zm0vctjr4M44HMpeg1P4bK6wItarumq0Ma82xorMKdFsWpphQBlRPzw/pxiVELX1A==",
"dev": true,
"requires": {
"eslint-rule-composer": "^0.3.0"
}
},
"eslint-rule-composer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz",
"integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==",
"dev": true
},
"eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+7 -1
View File
@@ -12,11 +12,15 @@
"build-storybook": "build-storybook",
"cypress": "cypress open",
"cypress:run": "cypress run",
"cypress:image-baseline": "cypress-image-diff -u"
"cypress:image-baseline": "cypress-image-diff -u",
"fix:lint": "eslint --fix src/ --ext .js,.jsx,.ts,.tsx",
"fix:format": "prettier --write ./src",
"fix": "npm run fix:format && npm run fix:lint"
},
"dependencies": {
"@chakra-ui/react": "^2.4.4",
"@dnd-kit/core": "^6.0.6",
"@dnd-kit/modifiers": "^6.0.1",
"@dnd-kit/sortable": "^7.0.1",
"@emotion/react": "^11.10.5",
"@emotion/styled": "^11.10.5",
@@ -32,6 +36,7 @@
"clsx": "^1.2.1",
"eslint": "8.29.0",
"eslint-config-next": "13.0.6",
"eslint-plugin-simple-import-sort": "^8.0.0",
"focus-visible": "^5.2.0",
"framer-motion": "^6.5.1",
"next": "13.0.6",
@@ -65,6 +70,7 @@
"cypress": "^12.2.0",
"cypress-image-diff-js": "^1.23.0",
"eslint-plugin-storybook": "^0.6.8",
"eslint-plugin-unused-imports": "^2.0.0",
"prettier": "2.8.1",
"prisma": "^4.7.1",
"typescript": "4.9.4"
+1
View File
@@ -1,4 +1,5 @@
import React from "react";
import { Container } from "./Container";
describe("<Container />", () => {
-2
View File
@@ -1,5 +1,3 @@
import Link from "next/link";
import { Container } from "./Container";
const faqs = [
+11 -13
View File
@@ -1,5 +1,6 @@
import Image from "next/image";
import Link from "next/link";
import { Container } from "./Container";
export function Footer() {
@@ -19,24 +20,21 @@ export function Footer() {
</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>
<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">
<Link
href="/privacy-policy"
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">
<Link
href="/terms-of-service"
aria-label="Terms of Service"
className="hover:underline underline-offset-2"
>
Terms of Service
</Link>
</div>
@@ -3,6 +3,7 @@ import React from "react";
import { Header } from "./Header";
// eslint-disable-next-line import/no-anonymous-default-export
export default {
title: "Header/Header",
component: Header,
+4 -12
View File
@@ -1,14 +1,13 @@
import { Button } 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 { signOut, useSession } from "next-auth/react";
import { FaUser, FaSignOutAlt } from "react-icons/fa";
import clsx from "clsx";
import { useSession } from "next-auth/react";
import { FaUser } from "react-icons/fa";
import { Container } from "src/components/Container";
import { NavLinks } from "./NavLinks";
import { UserMenu } from "./UserMenu";
@@ -66,9 +65,6 @@ export function Header(props) {
<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>
<div className="flex items-center gap-4">
<Popover className="lg:hidden">
@@ -103,10 +99,6 @@ export function Header(props) {
}}
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>
</>
@@ -1,5 +1,6 @@
import { NavLinks } from "./NavLinks";
// eslint-disable-next-line import/no-anonymous-default-export
export default {
title: "Header/NavLinks",
component: NavLinks,
+2 -2
View File
@@ -1,6 +1,6 @@
import { useState } from "react";
import Link from "next/link";
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);
@@ -3,6 +3,7 @@ import React from "react";
import UserMenu from "./UserMenu";
// eslint-disable-next-line import/no-anonymous-default-export
export default {
title: "Header/UserMenu",
component: UserMenu,
+3 -4
View File
@@ -1,8 +1,8 @@
import React from "react";
import { signOut, useSession } from "next-auth/react";
import Image from "next/image";
import { Popover } from "@headlessui/react";
import { AnimatePresence, motion } from "framer-motion";
import Image from "next/image";
import { signOut, useSession } from "next-auth/react";
import React from "react";
import { FaCog, FaSignOutAlt } from "react-icons/fa";
export function UserMenu() {
@@ -12,7 +12,6 @@ export function UserMenu() {
return <></>;
}
if (session && session.user) {
const email = session.user.email;
const accountOptions = [
{
name: "Account Settings",
+1 -1
View File
@@ -1,3 +1,3 @@
export { Header } from "./Header";
export { UserMenu } from "./UserMenu";
export { NavLinks } from "./NavLinks";
export { UserMenu } from "./UserMenu";
+1 -1
View File
@@ -1,5 +1,5 @@
import { useId } from "react";
import Image from "next/image";
import { useId } from "react";
import { Container } from "./Container";
+1 -1
View File
@@ -1,9 +1,9 @@
// https://nextjs.org/docs/basic-features/layouts
import type { NextPage } from "next";
import { Header } from "src/components/Header";
import { Footer } from "./Footer";
import { Header } from "src/components/Header";
export type NextPageWithLayout<P = unknown, IP = P> = NextPage<P, IP> & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
@@ -1,5 +1,6 @@
import { LoadingScreen } from "./LoadingScreen";
// eslint-disable-next-line import/no-anonymous-default-export
export default {
title: "Example/LoadingScreen",
component: LoadingScreen,
+2 -2
View File
@@ -2,8 +2,8 @@ const RankItem = ({ username, score }) => {
return (
<div className="flex flex-row justify-between p-6 border-2 border-slate-100 text-left font-semibold hover:bg-sky-50">
<div>1</div>
<div>@username</div>
<div>20.5</div>
<div>{username}</div>
<div>{score}</div>
<div>gold</div>
</div>
);
+1 -1
View File
@@ -1,7 +1,7 @@
import { Box, HStack, useRadio, useRadioGroup } from "@chakra-ui/react";
const RatingRadioButton = (props) => {
const { state, getInputProps, getCheckboxProps } = useRadio(props);
const { getInputProps, getCheckboxProps } = useRadio(props);
const input = getInputProps();
const checkbox = getCheckboxProps();
+30 -6
View File
@@ -1,8 +1,23 @@
import { DndContext, PointerSensor, TouchSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
import { ReactNode, useEffect, useState } from "react";
import { SortableContext, arrayMove, verticalListSortingStrategy } from "@dnd-kit/sortable";
import type { DragEndEvent } from "@dnd-kit/core/dist/types/events";
import { Flex } from "@chakra-ui/react";
import {
closestCenter,
DndContext,
PointerSensor,
TouchSensor,
KeyboardSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
import type { DragEndEvent } from "@dnd-kit/core/dist/types/events";
import { restrictToVerticalAxis } from "@dnd-kit/modifiers";
import {
arrayMove,
SortableContext,
sortableKeyboardCoordinates,
verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { ReactNode, useEffect, useState } from "react";
import { SortableItem } from "./SortableItem";
export interface SortableProps {
@@ -29,10 +44,19 @@ export const Sortable = ({ items, onChange }: SortableProps) => {
);
}, [items]);
const sensors = useSensors(useSensor(PointerSensor), useSensor(TouchSensor));
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(TouchSensor),
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
);
return (
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragEnd={handleDragEnd}
modifiers={[restrictToVerticalAxis]}
>
<SortableContext items={itemsWithIds} strategy={verticalListSortingStrategy}>
<Flex direction="column" gap={2}>
{itemsWithIds.map(({ id, item }) => (
@@ -1,6 +1,8 @@
import { CSS } from "@dnd-kit/utilities";
import { PropsWithChildren } from "react";
import { Button } 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";
export const SortableItem = ({ children, id }: PropsWithChildren<{ id: number }>) => {
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
@@ -13,12 +15,13 @@ export const SortableItem = ({ children, id }: PropsWithChildren<{ id: number }>
return (
<li
className="rounded-lg shadow-md p-4 bg-white hover:bg-slate-50"
className="grid grid-cols-[min-content_1fr] items-center rounded-lg shadow-md gap-x-2 p-2 bg-white hover:bg-slate-50"
ref={setNodeRef}
style={style}
{...attributes}
{...listeners}
>
<Button justifyContent="center" variant="ghost" {...attributes} {...listeners}>
<RxDragHandleDots2 />
</Button>
{children}
</li>
);
+1 -1
View File
@@ -1,4 +1,4 @@
export const TaskInfo = ({ id, output }: { id: string; output: any }) => {
export const TaskInfo = ({ id, output }: { id: string; output: string }) => {
return (
<div className="grid grid-cols-[min-content_auto] gap-x-2 text-gray-700">
<b>Prompt</b>
@@ -1,7 +1,8 @@
import React from "react";
import { TaskOptions } from "./TaskOptions";
import { Flex } from "@chakra-ui/react";
import React from "react";
import { TaskOption } from "./TaskOption";
import { TaskOptions } from "./TaskOptions";
export const TaskSelection = () => {
return (
@@ -1,3 +1,3 @@
export { TaskSelection } from "./TaskSelection";
export { TaskOptions } from "./TaskOptions";
export { TaskOption } from "./TaskOption";
export { TaskOptions } from "./TaskOptions";
export { TaskSelection } from "./TaskSelection";
-4
View File
@@ -1,8 +1,4 @@
import { useSession } from "next-auth/react";
import { Footer } from "../components/Footer";
import { Header } from "src/components/Header";
import Head from "next/head";
import Link from "next/link";
export default function Error() {
return (
+8 -8
View File
@@ -1,14 +1,14 @@
import { ChakraProvider } from "@chakra-ui/react";
import { SessionProvider } from "next-auth/react";
import { Inter } from "@next/font/google";
import { extendTheme } from "@chakra-ui/react";
import type { AppProps } from "next/app";
import { NextPageWithLayout, getDefaultLayout } from "src/components/Layout";
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",
+3 -3
View File
@@ -1,8 +1,8 @@
import React, { useState } from "react";
import { useSession } from "next-auth/react";
import { Button, Input, InputGroup, Stack } from "@chakra-ui/react";
import { Button, Input, InputGroup } from "@chakra-ui/react";
import Head from "next/head";
import Router from "next/router";
import { useSession } from "next-auth/react";
import React, { useState } from "react";
export default function Account() {
const { data: session } = useSession();
+3 -2
View File
@@ -1,13 +1,14 @@
import { Button } from "@chakra-ui/react";
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";
import React, { useState } from "react";
export default function Account() {
const { data: session } = useSession();
const [username, setUsername] = useState("null");
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const handleUpdate = async () => {
const response = await fetch("../api/update", {
method: "POST",
+5 -7
View File
@@ -1,12 +1,10 @@
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";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { boolean } from "boolean";
import type { AuthOptions } from "next-auth";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import DiscordProvider from "next-auth/providers/discord";
import EmailProvider from "next-auth/providers/email";
import prisma from "src/lib/prismadb";
const providers = [];
@@ -1,7 +1,5 @@
import { getToken } from "next-auth/jwt";
import prisma from "src/lib/prismadb";
import { authOptions } from "src/pages/api/auth/[...nextauth]";
/**
* Returns a new task created from the Task Backend. We do a few things here:
@@ -65,7 +63,7 @@ const handler = async (req, res) => {
message_id: registeredTask.id,
}),
});
const ack = await ackRes.json();
await ackRes.json();
// Send the results to the client.
res.status(200).json(registeredTask);
-2
View File
@@ -1,7 +1,5 @@
import { getToken } from "next-auth/jwt";
import prisma from "src/lib/prismadb";
import { authOptions } from "src/pages/api/auth/[...nextauth]";
/**
* Stores the task interaction with the Task Backend and then returns the next task generated.
-3
View File
@@ -1,13 +1,10 @@
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({
+4 -3
View File
@@ -1,12 +1,12 @@
import { Button, Input, Stack } from "@chakra-ui/react";
import Head from "next/head";
import { FaDiscord, FaEnvelope, FaGithub, FaBug } from "react-icons/fa";
import Link from "next/link";
import { getCsrfToken, getProviders, signIn } from "next-auth/react";
import React, { useRef } from "react";
import Link from "next/link";
import { FaBug, FaDiscord, FaEnvelope, FaGithub } from "react-icons/fa";
import { AuthLayout } from "src/components/AuthLayout";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default function Signin({ csrfToken, providers }) {
const { discord, email, github, credentials } = providers;
const emailEl = useRef(null);
@@ -105,6 +105,7 @@ export default function Signin({ csrfToken, providers }) {
);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function getServerSideProps(context) {
const csrfToken = await getCsrfToken();
const providers = await getProviders();
+2 -3
View File
@@ -1,7 +1,5 @@
import Head from "next/head";
import { getCsrfToken, getProviders, signIn } from "next-auth/react";
import Link from "next/link";
import { getCsrfToken, getProviders } from "next-auth/react";
import { AuthLayout } from "src/components/AuthLayout";
export default function Verify() {
@@ -18,6 +16,7 @@ export default function Verify() {
);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function getServerSideProps(context) {
const csrfToken = await getCsrfToken();
const providers = await getProviders();
+9 -11
View File
@@ -1,17 +1,15 @@
import { Flex, Textarea } from "@chakra-ui/react";
import { useRef, useState } from "react";
import useSWRMutation from "swr/mutation";
import useSWRImmutable from "swr/immutable";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { Messages } from "src/components/Messages";
import { TwoColumns } from "src/components/TwoColumns";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
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 fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const AssistantReply = () => {
const [tasks, setTasks] = useState([]);
@@ -24,7 +22,7 @@ const AssistantReply = () => {
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
+8 -10
View File
@@ -1,17 +1,15 @@
import { Flex, Textarea } from "@chakra-ui/react";
import Head from "next/head";
import { useRef, useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TwoColumns } from "src/components/TwoColumns";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
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 fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const SummarizeStory = () => {
// Use an array of tasks that record the sequence of steps until a task is
@@ -31,7 +29,7 @@ const SummarizeStory = () => {
// Every time we submit an answer to the latest task, let the backend handle
// all the interactions then add the resulting task to the queue. This ends
// when we hit the done task.
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
// This is the more efficient way to update a react state array.
+7 -9
View File
@@ -1,17 +1,15 @@
import { Flex, Textarea } from "@chakra-ui/react";
import { useRef, useState } from "react";
import useSWRMutation from "swr/mutation";
import useSWRImmutable from "swr/immutable";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
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 { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const UserReply = () => {
const [tasks, setTasks] = useState([]);
@@ -24,7 +22,7 @@ const UserReply = () => {
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
@@ -1,17 +1,15 @@
import { Button, Flex } from "@chakra-ui/react";
import { Flex } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
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 { SubmitButton } from "src/components/Buttons/Submit";
import { SkipButton } from "src/components/Buttons/Skip";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const RankAssistantReplies = () => {
const [tasks, setTasks] = useState([]);
@@ -27,7 +25,7 @@ const RankAssistantReplies = () => {
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
@@ -1,17 +1,15 @@
import { Flex } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
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 { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const RankInitialPrompts = () => {
const [tasks, setTasks] = useState([]);
@@ -27,7 +25,7 @@ const RankInitialPrompts = () => {
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
@@ -1,17 +1,15 @@
import { Flex } from "@chakra-ui/react";
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
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 { Flex } from "@chakra-ui/react";
import { SkipButton } from "src/components/Buttons/Skip";
import { SubmitButton } from "src/components/Buttons/Submit";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const RankUserReplies = () => {
const [tasks, setTasks] = useState([]);
@@ -27,7 +25,7 @@ const RankUserReplies = () => {
},
});
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
setTasks((oldTasks) => [...oldTasks, newTask]);
+9 -11
View File
@@ -2,18 +2,16 @@ import { Flex, Textarea } from "@chakra-ui/react";
import { QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
import Head from "next/head";
import { useState } from "react";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
import RatingRadioGroup from "src/components/RatingRadioGroup";
import fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import { LoadingScreen } from "src/components/Loading/LoadingScreen";
import { TwoColumns } from "src/components/TwoColumns";
import { TaskInfo } from "src/components/TaskInfo/TaskInfo";
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 fetcher from "src/lib/fetcher";
import poster from "src/lib/poster";
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
const RateSummary = () => {
// Use an array of tasks that record the sequence of steps until a task is
@@ -32,7 +30,7 @@ const RateSummary = () => {
// Every time we submit an answer to the latest task, let the backend handle
// all the interactions then add the resulting task to the queue. This ends
// when we hit the done task.
const { trigger, isMutating } = useSWRMutation("/api/update_task", poster, {
const { trigger } = useSWRMutation("/api/update_task", poster, {
onSuccess: async (data) => {
const newTask = await data.json();
// This is the more efficient way to update a react state array.
+2 -4
View File
@@ -1,12 +1,11 @@
import Head from "next/head";
import { useSession } from "next-auth/react";
import { CallToAction } from "src/components/CallToAction";
import { Faq } from "src/components/Faq";
import { Footer } from "src/components/Footer";
import { Header } from "src/components/Header";
import { Hero } from "src/components/Hero";
import { TaskSelection } from "src/components/TaskSelection";
import { Header } from "src/components/Header";
import { Footer } from "src/components/Footer";
const Home = () => {
const { data: session } = useSession();
@@ -28,7 +27,6 @@ const Home = () => {
<main>
<Hero />
<CallToAction />
<Faq />
</main>
)}
@@ -1,5 +1,5 @@
import RankItem from "src/components/RankItem";
import { HiBarsArrowDown } from "react-icons/hi2";
import RankItem from "src/components/RankItem";
const LeaderBoard = () => {
const PlaceHolderProps = { username: "test_user", score: 10 };