mirror of
https://github.com/wassname/Open-Assistant.git
synced 2026-07-15 01:00:53 +08:00
Merge branch 'main' into dark-mode-implementation
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
import React from "react";
|
||||
|
||||
import { Container } from "./Container";
|
||||
|
||||
describe("<Container />", () => {
|
||||
it("renders", () => {
|
||||
// see: https://on.cypress.io/mounting-react
|
||||
const className = "my-class";
|
||||
const text = "test_container";
|
||||
cy.mount(<Container className={className}>{text}</Container>);
|
||||
cy.get(`div.${className}`).should("have.class", className).should("be.visible").should("contain", text);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,216 @@
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Flex,
|
||||
Popover,
|
||||
PopoverAnchor,
|
||||
PopoverArrow,
|
||||
PopoverBody,
|
||||
PopoverCloseButton,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
Slider,
|
||||
SliderFilledTrack,
|
||||
SliderThumb,
|
||||
SliderTrack,
|
||||
Spacer,
|
||||
useBoolean,
|
||||
} from "@chakra-ui/react";
|
||||
import { FlagIcon, QuestionMarkCircleIcon } from "@heroicons/react/20/solid";
|
||||
import { useState } from "react";
|
||||
import poster from "src/lib/poster";
|
||||
import useSWRMutation from "swr/mutation";
|
||||
|
||||
export const FlaggableElement = (props) => {
|
||||
const [isEditing, setIsEditing] = useBoolean();
|
||||
const { trigger } = useSWRMutation("/api/v1/text_labels", poster, {
|
||||
onSuccess: () => {
|
||||
setIsEditing.off;
|
||||
},
|
||||
});
|
||||
|
||||
const submitResponse = () => {
|
||||
const label_map: Map<string, number> = new Map();
|
||||
TEXT_LABEL_FLAGS.forEach((flag, i) => {
|
||||
if (checkboxValues[i]) {
|
||||
label_map.set(flag.attributeName, sliderValues[i]);
|
||||
}
|
||||
});
|
||||
trigger({ post_id: props.post_id, label_map: Object.fromEntries(label_map), text: props.text });
|
||||
};
|
||||
const [checkboxValues, setCheckboxValues] = useState(new Array(TEXT_LABEL_FLAGS.length).fill(false));
|
||||
const [sliderValues, setSliderValues] = useState(new Array(TEXT_LABEL_FLAGS.length).fill(1));
|
||||
|
||||
const handleCheckboxState = (isChecked, idx) => {
|
||||
setCheckboxValues(
|
||||
checkboxValues.map((val, i) => {
|
||||
return i == idx ? isChecked : val;
|
||||
})
|
||||
);
|
||||
};
|
||||
const handleSliderState = (newVal, idx) => {
|
||||
setSliderValues(
|
||||
sliderValues.map((val, i) => {
|
||||
return i == idx ? newVal : val;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Popover
|
||||
isOpen={isEditing}
|
||||
onOpen={setIsEditing.on}
|
||||
onClose={setIsEditing.off}
|
||||
closeOnBlur={false}
|
||||
isLazy
|
||||
lazyBehavior="keepMounted"
|
||||
>
|
||||
<div className="inline-block float-left">
|
||||
<PopoverAnchor>{props.children}</PopoverAnchor>
|
||||
<PopoverTrigger>
|
||||
<Button color="transparent">
|
||||
<FlagIcon
|
||||
className="h-5 w-5 ml-3 align-center text-gray-400 group-hover:text-gray-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
</div>
|
||||
|
||||
<PopoverContent width="fit-content">
|
||||
<PopoverArrow />
|
||||
<PopoverCloseButton />
|
||||
<div className="flex mt-3 ">
|
||||
<PopoverBody>
|
||||
<ul>
|
||||
{TEXT_LABEL_FLAGS.map((option, i) => {
|
||||
return (
|
||||
<FlagCheckboxLi
|
||||
option={option}
|
||||
key={i}
|
||||
idx={i}
|
||||
checkboxValues={checkboxValues}
|
||||
sliderValues={sliderValues}
|
||||
checkboxHandler={handleCheckboxState}
|
||||
sliderHandler={handleSliderState}
|
||||
></FlagCheckboxLi>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className="flex justify-center ml-auto">
|
||||
<Button
|
||||
isDisabled={
|
||||
!checkboxValues.reduce((all, current) => {
|
||||
return all | current;
|
||||
}, false)
|
||||
}
|
||||
onClick={() => submitResponse()}
|
||||
className="bg-indigo-600 text-black hover:bg-indigo-700"
|
||||
>
|
||||
Report
|
||||
</Button>
|
||||
</div>
|
||||
</PopoverBody>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
function FlagCheckboxLi(props: {
|
||||
option: textFlagLabels;
|
||||
idx: number;
|
||||
checkboxValues: boolean[];
|
||||
sliderValues: number[];
|
||||
checkboxHandler: (newVal: boolean, idx: number) => void;
|
||||
sliderHandler: (newVal: number, idx: number) => void;
|
||||
}): JSX.Element {
|
||||
let AdditionalExplanation = null;
|
||||
if (props.option.additionalExplanation) {
|
||||
AdditionalExplanation = (
|
||||
<a href="#" className="group flex items-center space-x-2.5 text-sm ">
|
||||
<QuestionMarkCircleIcon
|
||||
className="flex h-5 w-5 ml-3 text-gray-400 group-hover:text-gray-500"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li>
|
||||
<Flex>
|
||||
<Checkbox
|
||||
onChange={(e) => {
|
||||
props.checkboxHandler(e.target.checked, props.idx);
|
||||
}}
|
||||
/>
|
||||
<label
|
||||
className=" ml-1 mr-1 text-sm form-check-label hover:cursor-pointer"
|
||||
htmlFor={props.option.attributeName}
|
||||
>
|
||||
<span className="text-gray-800 hover:text-blue-700 float-left">{props.option.labelText}</span>
|
||||
{AdditionalExplanation}
|
||||
</label>
|
||||
<Spacer />
|
||||
<Slider
|
||||
width="100px"
|
||||
isDisabled={!props.checkboxValues[props.idx]}
|
||||
defaultValue={100}
|
||||
onChangeEnd={(val) => {
|
||||
props.sliderHandler(val / 100, props.idx);
|
||||
}}
|
||||
>
|
||||
<SliderTrack>
|
||||
<SliderFilledTrack />
|
||||
<SliderThumb />
|
||||
</SliderTrack>
|
||||
</Slider>
|
||||
</Flex>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
interface textFlagLabels {
|
||||
attributeName: string;
|
||||
labelText: string;
|
||||
additionalExplanation?: string;
|
||||
}
|
||||
const TEXT_LABEL_FLAGS: textFlagLabels[] = [
|
||||
// For the time being this list is configured on the FE.
|
||||
// In the future it may be provided by the API.
|
||||
{
|
||||
attributeName: "fails_task",
|
||||
labelText: "Fails to follow the correct instruction / task",
|
||||
additionalExplanation: "__TODO__",
|
||||
},
|
||||
{
|
||||
attributeName: "not_customer_assistant_appropriate",
|
||||
labelText: "Inappropriate for customer assistant",
|
||||
additionalExplanation: "__TODO__",
|
||||
},
|
||||
{
|
||||
attributeName: "contains_sexual_content",
|
||||
labelText: "Contains sexual content",
|
||||
},
|
||||
{
|
||||
attributeName: "contains_violent_content",
|
||||
labelText: "Contains violent content",
|
||||
},
|
||||
{
|
||||
attributeName: "encourages_violence",
|
||||
labelText: "Encourages or fails to discourage violence/abuse/terrorism/self-harm",
|
||||
},
|
||||
{
|
||||
attributeName: "denigrates_a_protected_class",
|
||||
labelText: "Denigrates a protected class",
|
||||
},
|
||||
{
|
||||
attributeName: "gives_harmful_advice",
|
||||
labelText: "Fails to follow the correct instruction / task",
|
||||
additionalExplanation:
|
||||
"The advice given in the output is harmful or counter-productive. This may be in addition to, but is distinct from the question about encouraging violence/abuse/terrorism/self-harm.",
|
||||
},
|
||||
{
|
||||
attributeName: "expresses_moral_judgement",
|
||||
labelText: "Expresses moral judgement",
|
||||
},
|
||||
];
|
||||
@@ -5,11 +5,11 @@ import { useColorMode } from "@chakra-ui/react";
|
||||
export function Footer() {
|
||||
const { colorMode } = useColorMode();
|
||||
const bgColorClass = colorMode === "light" ? "bg-transparent" : "bg-gray-800";
|
||||
const borderClass = colorMode === "light" ? "border-slate-200" : "border-gray-900";
|
||||
const borderClass = colorMode === "light" ? "border-slate-200" : "border-transparent";
|
||||
|
||||
return (
|
||||
<footer className={bgColorClass}>
|
||||
<div className={`flex justify-evenly py-10 px-10 border-t ${borderClass}`}>
|
||||
<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" />
|
||||
@@ -20,18 +20,7 @@ export function Footer() {
|
||||
<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>Information</b>
|
||||
@@ -44,30 +33,51 @@ export function Footer() {
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<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 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>
|
||||
<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> */}
|
||||
</nav>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Button, Box } 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";
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NavLinks } from "./NavLinks";
|
||||
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
export default {
|
||||
title: "Header/NavLinks",
|
||||
component: NavLinks,
|
||||
|
||||
@@ -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";
|
||||
|
||||
import { useColorMode } from "@chakra-ui/react";
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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";
|
||||
import { Box, useColorModeValue } from "@chakra-ui/react";
|
||||
|
||||
@@ -14,7 +14,6 @@ export function UserMenu() {
|
||||
return <></>;
|
||||
}
|
||||
if (session && session.user) {
|
||||
const email = session.user.email;
|
||||
const accountOptions = [
|
||||
{
|
||||
name: "Account Settings",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export { Header } from "./Header";
|
||||
export { UserMenu } from "./UserMenu";
|
||||
export { NavLinks } from "./NavLinks";
|
||||
export { UserMenu } from "./UserMenu";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useId } from "react";
|
||||
import Image from "next/image";
|
||||
import { useColorMode } from "@chakra-ui/react";
|
||||
|
||||
import { useId } from "react";
|
||||
import { Container } from "./Container";
|
||||
|
||||
function BackgroundIllustration(props) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { FlaggableElement } from "./FlaggableElement";
|
||||
|
||||
export interface Message {
|
||||
text: string;
|
||||
is_assistant: boolean;
|
||||
@@ -5,11 +7,18 @@ export interface Message {
|
||||
|
||||
const getColor = (isAssistant: boolean) => (isAssistant ? "bg-slate-800" : "bg-sky-900");
|
||||
|
||||
export const Messages = ({ messages }: { messages: Message[] }) => {
|
||||
export const Messages = ({ messages, post_id }: { messages: Message[]; post_id: string }) => {
|
||||
const items = messages.map(({ text, is_assistant }: Message, i: number) => {
|
||||
return (
|
||||
<div key={i + text} className={`${getColor(is_assistant)} p-4 my-1 rounded-xl text-white whitespace-pre-wrap`}>
|
||||
{text}
|
||||
<div className="flex" key={i + text}>
|
||||
<FlaggableElement text={text} post_id={post_id}>
|
||||
<div
|
||||
key={i + text}
|
||||
className={`${getColor(is_assistant)} p-4 my-1 rounded-xl text-white whitespace-pre-wrap float-left mr-3`}
|
||||
>
|
||||
{text}
|
||||
</div>
|
||||
</FlaggableElement>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -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,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();
|
||||
|
||||
@@ -1,4 +1,23 @@
|
||||
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 {
|
||||
@@ -6,43 +25,61 @@ export interface SortableProps {
|
||||
onChange: (newSortedIndices: number[]) => void;
|
||||
}
|
||||
|
||||
export const Sortable = ({ items, onChange }) => {
|
||||
const [sortOrder, setSortOrder] = useState<number[]>([]);
|
||||
interface SortableItems {
|
||||
id: number;
|
||||
originalIndex: number;
|
||||
item: ReactNode;
|
||||
}
|
||||
|
||||
const update = (newRanking: number[]) => {
|
||||
setSortOrder(newRanking);
|
||||
onChange(newRanking);
|
||||
};
|
||||
export const Sortable = ({ items, onChange }: SortableProps) => {
|
||||
const [itemsWithIds, setItemsWithIds] = useState<SortableItems[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const indices = Array.from({ length: items.length }).map((_, i) => i);
|
||||
setSortOrder(indices);
|
||||
onChange(indices);
|
||||
}, [items, onChange]);
|
||||
setItemsWithIds(
|
||||
items.map((item, idx) => ({
|
||||
item,
|
||||
id: idx + 1, // +1 because dndtoolkit has problem with "falsy" ids
|
||||
originalIndex: idx,
|
||||
}))
|
||||
);
|
||||
}, [items]);
|
||||
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
useSensor(TouchSensor),
|
||||
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||
);
|
||||
|
||||
return (
|
||||
<ul className="flex flex-col gap-4">
|
||||
{sortOrder.map((rank, i) => (
|
||||
<SortableItem
|
||||
key={`${rank}`}
|
||||
canIncrement={i > 0}
|
||||
onIncrement={() => {
|
||||
const newRanking = sortOrder.slice();
|
||||
const newIdx = i - 1;
|
||||
[newRanking[i], newRanking[newIdx]] = [newRanking[newIdx], newRanking[i]];
|
||||
update(newRanking);
|
||||
}}
|
||||
canDecrement={i < sortOrder.length - 1}
|
||||
onDecrement={() => {
|
||||
const newRanking = sortOrder.slice();
|
||||
const newIdx = i + 1;
|
||||
[newRanking[i], newRanking[newIdx]] = [newRanking[newIdx], newRanking[i]];
|
||||
update(newRanking);
|
||||
}}
|
||||
>
|
||||
{items[rank]}
|
||||
</SortableItem>
|
||||
))}
|
||||
</ul>
|
||||
<DndContext
|
||||
sensors={sensors}
|
||||
collisionDetection={closestCenter}
|
||||
onDragEnd={handleDragEnd}
|
||||
modifiers={[restrictToVerticalAxis]}
|
||||
>
|
||||
<SortableContext items={itemsWithIds} strategy={verticalListSortingStrategy}>
|
||||
<Flex direction="column" gap={2}>
|
||||
{itemsWithIds.map(({ id, item }) => (
|
||||
<SortableItem key={id} id={id}>
|
||||
{item}
|
||||
</SortableItem>
|
||||
))}
|
||||
</Flex>
|
||||
</SortableContext>
|
||||
</DndContext>
|
||||
);
|
||||
|
||||
function handleDragEnd(event: DragEndEvent) {
|
||||
const { active, over } = event;
|
||||
if (active.id === over.id) {
|
||||
return;
|
||||
}
|
||||
setItemsWithIds((items) => {
|
||||
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));
|
||||
return newArray;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,40 +1,32 @@
|
||||
<<<<<<< HEAD
|
||||
import { ArrowDownIcon, ArrowUpIcon } from "@heroicons/react/20/solid";
|
||||
=======
|
||||
>>>>>>> main
|
||||
import { Button } from "@chakra-ui/react";
|
||||
import clsx from "clsx";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import { RxDragHandleDots2 } from "react-icons/rx";
|
||||
import { PropsWithChildren } from "react";
|
||||
|
||||
export interface SortableItemProps {
|
||||
canIncrement: boolean;
|
||||
canDecrement: boolean;
|
||||
onIncrement: () => void;
|
||||
onDecrement: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
export const SortableItem = ({ children, id }: PropsWithChildren<{ id: number }>) => {
|
||||
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
|
||||
|
||||
const style = {
|
||||
transform: CSS.Transform.toString(transform),
|
||||
transition,
|
||||
touchAction: "none",
|
||||
};
|
||||
|
||||
export const SortableItem = ({ canIncrement, canDecrement, onIncrement, onDecrement, children }: SortableItemProps) => {
|
||||
return (
|
||||
<li className="grid grid-cols-[min-content_1fr] items-center rounded-lg shadow-md gap-x-2 p-2">
|
||||
<ArrowButton active={canIncrement} onClick={onIncrement}>
|
||||
<ArrowUpIcon width={28} />
|
||||
</ArrowButton>
|
||||
<span style={{ gridRow: "span 2" }}>{children}</span>
|
||||
|
||||
<ArrowButton active={canDecrement} onClick={onDecrement}>
|
||||
<ArrowDownIcon width={28} />
|
||||
</ArrowButton>
|
||||
<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"
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
>
|
||||
<Button justifyContent="center" variant="ghost" {...attributes} {...listeners}>
|
||||
<RxDragHandleDots2 />
|
||||
</Button>
|
||||
{children}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
interface ArrowButtonProps {
|
||||
active: boolean;
|
||||
onClick: () => void;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
const ArrowButton = ({ children, active, onClick }: ArrowButtonProps) => {
|
||||
return (
|
||||
<Button justifyContent="center" variant="ghost" onClick={onClick} disabled={!active}>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 ">
|
||||
<b>Prompt</b>
|
||||
|
||||
@@ -1,11 +1,20 @@
|
||||
import React from "react";
|
||||
import { TaskOptions } from "./TaskOptions";
|
||||
import { Flex } from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import { useColorMode } from "@chakra-ui/react";
|
||||
|
||||
import { TaskOption } from "./TaskOption";
|
||||
import { TaskOptions } from "./TaskOptions";
|
||||
|
||||
export const TaskSelection = () => {
|
||||
|
||||
const { colorMode } = useColorMode();
|
||||
const bgColorClass = colorMode === "light" ? "bg-gray-50" : "bg-gray-600";
|
||||
const buttonBgColor = colorMode === "light" ? "#2563eb" : "#2563eb";
|
||||
const borderClass = colorMode === "light" ? "border-slate-200" : "border-transparent";
|
||||
|
||||
|
||||
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={bgColorClass}>
|
||||
<TaskOptions key="create" title="Create">
|
||||
{/* <TaskOption
|
||||
alt="Summarize Stories"
|
||||
@@ -22,7 +31,9 @@ export const TaskSelection = () => {
|
||||
/>
|
||||
</TaskOptions>
|
||||
<TaskOptions key="evaluate" title="Evaluate">
|
||||
{/* <TaskOption
|
||||
{/*
|
||||
Commented out while the backend does not support them.
|
||||
<TaskOption
|
||||
alt="Rate Prompts"
|
||||
img="/images/logos/logo.svg"
|
||||
title="Rate Prompts"
|
||||
|
||||
@@ -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,7 +4,7 @@ declare global {
|
||||
var prisma: PrismaClient | undefined;
|
||||
}
|
||||
|
||||
const client = new PrismaClient();
|
||||
const client = globalThis.prisma || new PrismaClient();
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
globalThis.prisma = client;
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 = [];
|
||||
@@ -43,10 +41,19 @@ if (boolean(process.env.DEBUG_LOGIN) || process.env.NODE_ENV === "development")
|
||||
username: { label: "Username", type: "text" },
|
||||
},
|
||||
async authorize(credentials) {
|
||||
return {
|
||||
const user = {
|
||||
id: credentials.username,
|
||||
name: credentials.username,
|
||||
};
|
||||
// save the user to the database
|
||||
await prisma.user.upsert({
|
||||
where: {
|
||||
id: user.id,
|
||||
},
|
||||
update: {},
|
||||
create: user,
|
||||
});
|
||||
return user;
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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:
|
||||
@@ -62,10 +60,10 @@ const handler = async (req, res) => {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
post_id: registeredTask.id,
|
||||
message_id: registeredTask.id,
|
||||
}),
|
||||
});
|
||||
const ack = await ackRes.json();
|
||||
await ackRes.json();
|
||||
|
||||
// Send the results to the client.
|
||||
res.status(200).json(registeredTask);
|
||||
|
||||
@@ -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.
|
||||
@@ -22,7 +20,7 @@ const handler = async (req, res) => {
|
||||
}
|
||||
|
||||
// Parse out the local task ID and the interaction contents.
|
||||
const { id, content } = await JSON.parse(req.body);
|
||||
const { id, content, update_type } = await JSON.parse(req.body);
|
||||
|
||||
// Log the interaction locally to create our user_post_id needed by the Task
|
||||
// Backend.
|
||||
@@ -46,14 +44,14 @@ const handler = async (req, res) => {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
type: "post_rating",
|
||||
type: update_type,
|
||||
user: {
|
||||
id: token.sub,
|
||||
display_name: token.name || token.email,
|
||||
auth_method: "local",
|
||||
},
|
||||
post_id: id,
|
||||
user_post_id: interaction.id,
|
||||
message_id: id,
|
||||
user_message_id: interaction.id,
|
||||
...content,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Footer } from "src/components/Footer";
|
||||
import { AuthLayout } from "src/components/AuthLayout";
|
||||
import { useColorMode } from "@chakra-ui/react";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function Signin({ csrfToken, providers }) {
|
||||
const { discord, email, github, credentials } = providers;
|
||||
const emailEl = useRef(null);
|
||||
@@ -71,7 +72,7 @@ function Signin({ csrfToken, providers }) {
|
||||
size="lg"
|
||||
leftIcon={<FaDiscord />}
|
||||
color="white"
|
||||
onClick={() => signIn(discord, { callbackUrl: "/" })}
|
||||
onClick={() => signIn(discord.id, { callbackUrl: "/" })}
|
||||
// isDisabled="false"
|
||||
>
|
||||
Continue with Discord
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,31 +1,28 @@
|
||||
import { Container, 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([]);
|
||||
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const { isLoading } = useSWRImmutable("/api/new_task/assistant_reply ", fetcher, {
|
||||
const { isLoading, mutate } = useSWRImmutable("/api/new_task/assistant_reply ", fetcher, {
|
||||
onSuccess: (data) => {
|
||||
console.log(data);
|
||||
setTasks([data]);
|
||||
},
|
||||
});
|
||||
|
||||
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]);
|
||||
@@ -36,13 +33,18 @@ const AssistantReply = () => {
|
||||
const text = inputRef.current.value.trim();
|
||||
trigger({
|
||||
id: task.id,
|
||||
update_type: "text_reply_to_post",
|
||||
update_type: "text_reply_to_message",
|
||||
content: {
|
||||
text,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const fetchNextTask = () => {
|
||||
inputRef.current.value = "";
|
||||
mutate();
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen text="Loading..." />;
|
||||
}
|
||||
@@ -52,13 +54,14 @@ const AssistantReply = () => {
|
||||
}
|
||||
|
||||
const task = tasks[0].task;
|
||||
const endTask = tasks[tasks.length - 1];
|
||||
return (
|
||||
<Container className="p-6 text-gray-800">
|
||||
<TwoColumns>
|
||||
<>
|
||||
<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} />
|
||||
<Messages messages={task.conversation.messages} post_id={task.id} />
|
||||
</>
|
||||
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
|
||||
</TwoColumns>
|
||||
@@ -68,7 +71,11 @@ const AssistantReply = () => {
|
||||
|
||||
<Flex justify="center" ml="auto" gap={2}>
|
||||
<SkipButton>Skip</SkipButton>
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
|
||||
{endTask.task.type !== "task_done" ? (
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
|
||||
) : (
|
||||
<SubmitButton onClick={fetchNextTask}>Next Task</SubmitButton>
|
||||
)}
|
||||
</Flex>
|
||||
</section>
|
||||
</Container>
|
||||
|
||||
@@ -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.
|
||||
@@ -45,7 +43,7 @@ const SummarizeStory = () => {
|
||||
const text = inputRef.current.value.trim();
|
||||
trigger({
|
||||
id: task.id,
|
||||
update_type: "text_reply_to_post",
|
||||
update_type: "text_reply_to_message",
|
||||
content: {
|
||||
text,
|
||||
},
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { Container, Flex, Textarea, useColorModeValue } from "@chakra-ui/react";
|
||||
import { Flex, Textarea, useColorModeValue } from "@chakra-ui/react";
|
||||
import { Container } from "src/components/Container";
|
||||
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([]);
|
||||
@@ -19,14 +18,13 @@ const UserReply = () => {
|
||||
|
||||
const inputRef = useRef<HTMLTextAreaElement>(null);
|
||||
|
||||
const { isLoading } = useSWRImmutable("/api/new_task/user_reply", fetcher, {
|
||||
const { isLoading, mutate } = useSWRImmutable("/api/new_task/prompter_reply", fetcher, {
|
||||
onSuccess: (data) => {
|
||||
console.log(data);
|
||||
setTasks([data]);
|
||||
},
|
||||
});
|
||||
|
||||
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]);
|
||||
@@ -37,13 +35,18 @@ const UserReply = () => {
|
||||
const text = inputRef.current.value.trim();
|
||||
trigger({
|
||||
id: task.id,
|
||||
update_type: "text_reply_to_post",
|
||||
update_type: "text_reply_to_message",
|
||||
content: {
|
||||
text,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const fetchNextTask = () => {
|
||||
inputRef.current.value = "";
|
||||
mutate();
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen text="Loading..." />;
|
||||
}
|
||||
@@ -53,13 +56,14 @@ const UserReply = () => {
|
||||
}
|
||||
|
||||
const task = tasks[0].task;
|
||||
const endTask = tasks[tasks.length - 1];
|
||||
return (
|
||||
<Container className="p-6">
|
||||
<TwoColumns>
|
||||
<>
|
||||
<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} />
|
||||
<Messages messages={task.conversation.messages} post_id={task.id} />
|
||||
{task.hint && <p className="text-lg py-1">Hint: {task.hint}</p>}
|
||||
</>
|
||||
<Textarea name="reply" placeholder="Reply..." ref={inputRef} />
|
||||
@@ -67,10 +71,13 @@ const UserReply = () => {
|
||||
|
||||
<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>
|
||||
{endTask.task.type !== "task_done" ? (
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
|
||||
) : (
|
||||
<SubmitButton onClick={fetchNextTask}>Next Task</SubmitButton>
|
||||
)}
|
||||
</Flex>
|
||||
</section>
|
||||
</Container>
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
import { Button, Container, Flex, useColorModeValue } 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([]);
|
||||
@@ -20,14 +18,15 @@ const RankAssistantReplies = () => {
|
||||
* The best reply will have index 0, and the worst is the last.
|
||||
*/
|
||||
const [ranking, setRanking] = useState<number[]>([]);
|
||||
|
||||
const bg = useColorModeValue("gray.100", "gray.800");
|
||||
const { isLoading } = useSWRImmutable("/api/new_task/rank_assistant_replies", fetcher, {
|
||||
const { isLoading, mutate } = useSWRImmutable("/api/new_task/rank_assistant_replies", fetcher, {
|
||||
onSuccess: (data) => {
|
||||
setTasks([data]);
|
||||
},
|
||||
});
|
||||
|
||||
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]);
|
||||
@@ -37,13 +36,18 @@ const RankAssistantReplies = () => {
|
||||
const submitResponse = (task) => {
|
||||
trigger({
|
||||
id: task.id,
|
||||
update_type: "post_ranking",
|
||||
update_type: "message_ranking",
|
||||
content: {
|
||||
ranking,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const fetchNextTask = () => {
|
||||
setRanking([]);
|
||||
mutate();
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen text="Loading..." />;
|
||||
}
|
||||
@@ -51,8 +55,9 @@ const RankAssistantReplies = () => {
|
||||
if (tasks.length == 0) {
|
||||
return <Container className="p-6 bg-slate-100 text-gray-800">No Tasks Found...</Container>;
|
||||
}
|
||||
const replies = tasks[0].task.replies as string[];
|
||||
|
||||
const replies = tasks[0].task.replies as string[];
|
||||
const endTask = tasks[tasks.length - 1];
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -73,9 +78,13 @@ const RankAssistantReplies = () => {
|
||||
|
||||
<Flex justify="center" ml="auto" gap={2}>
|
||||
<SkipButton>Skip</SkipButton>
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
|
||||
Submit
|
||||
</SubmitButton>
|
||||
{endTask.task.type !== "task_done" ? (
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
|
||||
Submit
|
||||
</SubmitButton>
|
||||
) : (
|
||||
<SubmitButton onClick={fetchNextTask}>Next Task</SubmitButton>
|
||||
)}
|
||||
</Flex>
|
||||
</Container>
|
||||
</Container>
|
||||
|
||||
@@ -1,18 +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 { Container, useColorModeValue } from "@chakra-ui/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 { 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([]);
|
||||
@@ -23,13 +20,13 @@ const RankInitialPrompts = () => {
|
||||
const [ranking, setRanking] = useState<number[]>([]);
|
||||
const bg = useColorModeValue("gray.100", "gray.800");
|
||||
|
||||
const { isLoading } = useSWRImmutable("/api/new_task/rank_initial_prompts", fetcher, {
|
||||
const { isLoading, mutate } = useSWRImmutable("/api/new_task/rank_initial_prompts", fetcher, {
|
||||
onSuccess: (data) => {
|
||||
setTasks([data]);
|
||||
},
|
||||
});
|
||||
|
||||
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]);
|
||||
@@ -39,13 +36,18 @@ const RankInitialPrompts = () => {
|
||||
const submitResponse = (task) => {
|
||||
trigger({
|
||||
id: task.id,
|
||||
update_type: "post_ranking",
|
||||
update_type: "message_ranking",
|
||||
content: {
|
||||
ranking,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const fetchNextTask = () => {
|
||||
setRanking([]);
|
||||
mutate();
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen text="Loading..." />;
|
||||
}
|
||||
@@ -54,6 +56,7 @@ const RankInitialPrompts = () => {
|
||||
return <Container className="p-6 bg-slate-100 text-gray-800">No tasks found...</Container>;
|
||||
}
|
||||
|
||||
const endTask = tasks[tasks.length - 1];
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -74,9 +77,13 @@ const RankInitialPrompts = () => {
|
||||
|
||||
<Flex justify="center" ml="auto" gap={2}>
|
||||
<SkipButton>Skip</SkipButton>
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
|
||||
Submit
|
||||
</SubmitButton>
|
||||
{endTask.task.type !== "task_done" ? (
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
|
||||
Submit
|
||||
</SubmitButton>
|
||||
) : (
|
||||
<SubmitButton onClick={fetchNextTask}>Next Task</SubmitButton>
|
||||
)}
|
||||
</Flex>
|
||||
</section>
|
||||
</Container>
|
||||
|
||||
@@ -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 { Container, Flex, useColorModeValue } 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([]);
|
||||
@@ -20,14 +18,15 @@ const RankUserReplies = () => {
|
||||
* The best reply will have index 0, and the worst is the last.
|
||||
*/
|
||||
const [ranking, setRanking] = useState<number[]>([]);
|
||||
|
||||
const bg = useColorModeValue("gray.100", "gray.800");
|
||||
const { isLoading } = useSWRImmutable("/api/new_task/rank_user_replies", fetcher, {
|
||||
const { isLoading, mutate } = useSWRImmutable("/api/new_task/rank_prompter_replies", fetcher, {
|
||||
onSuccess: (data) => {
|
||||
setTasks([data]);
|
||||
},
|
||||
});
|
||||
|
||||
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]);
|
||||
@@ -37,13 +36,18 @@ const RankUserReplies = () => {
|
||||
const submitResponse = (task) => {
|
||||
trigger({
|
||||
id: task.id,
|
||||
update_type: "post_ranking",
|
||||
update_type: "message_ranking",
|
||||
content: {
|
||||
ranking,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const fetchNextTask = () => {
|
||||
setRanking([]);
|
||||
mutate();
|
||||
};
|
||||
|
||||
if (isLoading) {
|
||||
return <LoadingScreen text="Loading..." />;
|
||||
}
|
||||
@@ -53,6 +57,7 @@ const RankUserReplies = () => {
|
||||
}
|
||||
const replies = tasks[0].task.replies as string[];
|
||||
|
||||
const endTask = tasks[tasks.length - 1];
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -73,9 +78,13 @@ const RankUserReplies = () => {
|
||||
|
||||
<Flex justify="center" ml="auto" gap={2}>
|
||||
<SkipButton>Skip</SkipButton>
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
|
||||
Submit
|
||||
</SubmitButton>
|
||||
{endTask.task.type !== "task_done" ? (
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])} disabled={ranking.length === 0}>
|
||||
Submit
|
||||
</SubmitButton>
|
||||
) : (
|
||||
<SubmitButton onClick={fetchNextTask}>Next Task</SubmitButton>
|
||||
)}
|
||||
</Flex>
|
||||
</section>
|
||||
</Container>
|
||||
|
||||
@@ -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
|
||||
@@ -23,9 +21,8 @@ const RateSummary = () => {
|
||||
|
||||
// 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/rate_summary", fetcher, {
|
||||
const { isLoading, mutate } = useSWRImmutable("/api/new_task/rate_summary", fetcher, {
|
||||
onSuccess: (data) => {
|
||||
console.log(data);
|
||||
setTasks([data]);
|
||||
},
|
||||
});
|
||||
@@ -33,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.
|
||||
@@ -46,6 +43,7 @@ const RateSummary = () => {
|
||||
const submitResponse = (t) => {
|
||||
trigger({
|
||||
id: t.id,
|
||||
update_type: "message_rating",
|
||||
content: {
|
||||
rating: rating,
|
||||
},
|
||||
@@ -60,6 +58,7 @@ const RateSummary = () => {
|
||||
return <div className="p-6 bg-slate-100 text-gray-800">No tasks found...</div>;
|
||||
}
|
||||
|
||||
const endTask = tasks[tasks.length - 1];
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
@@ -97,7 +96,11 @@ const RateSummary = () => {
|
||||
|
||||
<Flex justify="center" ml="auto" gap={2}>
|
||||
<SkipButton>Skip</SkipButton>
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
|
||||
{endTask.task.type !== "task_done" ? (
|
||||
<SubmitButton onClick={() => submitResponse(tasks[0])}>Submit</SubmitButton>
|
||||
) : (
|
||||
<SubmitButton onClick={mutate}>Next Task</SubmitButton>
|
||||
)}
|
||||
</Flex>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
@@ -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";
|
||||
import { Box, Container } from "@chakra-ui/react";
|
||||
|
||||
const Home = () => {
|
||||
@@ -22,16 +21,12 @@ const Home = () => {
|
||||
/>
|
||||
</Head>
|
||||
{session ? (
|
||||
<Container>
|
||||
<TaskSelection />
|
||||
</Container>
|
||||
) : (
|
||||
<main className="oa-basic-theme">
|
||||
{/* <Container className="min-w-full" variant="no-padding"> */}
|
||||
<Hero />
|
||||
<CallToAction />
|
||||
<Faq />
|
||||
{/* </Container> */}
|
||||
</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 };
|
||||
|
||||
Reference in New Issue
Block a user