TaskContext as subset of ApiHookState

This commit is contained in:
AbdBarho
2023-01-29 11:38:16 +01:00
parent d7f2a6d0d9
commit 77cc96d401
8 changed files with 45 additions and 29 deletions
@@ -15,9 +15,9 @@ import Link from "next/link";
import { useTranslation } from "next-i18next";
import { useMemo } from "react";
import { getTypeSafei18nKey } from "src/lib/i18n";
import { TaskType } from "src/types/Task";
import { TaskCategory, TaskInfo, TaskType } from "src/types/Task";
import { TaskCategory, TaskCategoryLabels, TaskInfo, TaskInfos } from "../Tasks/TaskTypes";
import { TaskCategoryLabels, TaskInfos } from "../Tasks/TaskTypes";
export interface TasksOptionProps {
content: Partial<Record<TaskCategory, TaskType[]>>;
+12 -6
View File
@@ -19,9 +19,8 @@ export const TaskPage = ({ type }: TaskPageProps) => {
const taskApiHook = useMemo(() => taskApiHooks[type], [type]);
const hookState = taskApiHook(type);
const { response } = hookState;
const body = useMemo(() => {
const { response } = hookState;
switch (response.taskAvailability) {
case "AWAITING_INITIAL":
return <LoadingScreen text={t("common:loading")} />;
@@ -29,10 +28,17 @@ export const TaskPage = ({ type }: TaskPageProps) => {
case "NONE_AVAILABLE":
return <TaskEmptyState />;
case "AVAILABLE":
return <Task key={response.id} />;
case "AVAILABLE": {
const { task, taskInfo } = response;
const context = { ...hookState, task, taskInfo };
return (
<TaskContext.Provider value={context}>
<Task key={response.id} />
</TaskContext.Provider>
);
}
}
}, [response, t]);
}, [hookState, t]);
// NOTE: this is independent of the fetched task type, it is usually identical, but not for the random task.
const taskInfo = TaskInfos.find((taskType) => taskType.type === type);
@@ -42,7 +48,7 @@ export const TaskPage = ({ type }: TaskPageProps) => {
<title>{t(getTypeSafei18nKey(`${taskInfo.id}.label`))}</title>
<meta name="description" content={t(getTypeSafei18nKey(`${taskInfo.id}.desc`))} />
</Head>
<TaskContext.Provider value={hookState}>{body}</TaskContext.Provider>
{body}
</>
);
};
@@ -1,20 +1,22 @@
import React from "react";
import { Task } from "./Task";
import { Task } from "src/components/Tasks/Task";
import { TaskInfos } from "src/components/Tasks/TaskTypes";
import { TaskContext } from "src/context/TaskContext";
export default {
title: "tasks/Task",
component: Task,
};
const Template = ({ frontendId, task, isLoading, completeTask, skipTask }) => {
const Template = ({ providerValue }) => {
return (
<Task frontendId={frontendId} task={task} isLoading={isLoading} completeTask={completeTask} skipTask={skipTask} />
<TaskContext.Provider value={providerValue}>
<Task />
</TaskContext.Provider>
);
};
export const Default = Template.bind({});
Default.args = {
const exampleProviderValue = {
frontendId: "1234",
task: {
conversation: [],
@@ -25,11 +27,18 @@ Default.args = {
type: "label_prompter_reply",
valid_labels: ["spam", "fails_task"],
},
taskInfo: TaskInfos.find((t) => t.type === "label_prompter_reply"),
isLoading: false,
completeTask: (id, update_type, content) => {
completeTask: (content) => {
console.log(content);
},
skipTask: () => {
console.log("skip");
},
rejectTask: () => {
console.log("reject");
},
};
export const Default = Template.bind({});
Default.args = { providerValue: exampleProviderValue };
+3 -8
View File
@@ -66,7 +66,7 @@ export const Task = () => {
const { t } = useTranslation("tasks");
const rootEl = useRef<HTMLDivElement>(null);
const replyContent = useRef<TaskContent>(null);
const { rejectTask, completeTask, response, isLoading } = useTaskContext();
const { rejectTask, completeTask, isLoading, task, taskInfo } = useTaskContext();
const [taskStatus, taskEvent] = useReducer(
(
status: TaskStatus,
@@ -108,11 +108,6 @@ export const Task = () => {
{ mode: "EDIT", replyValidity: "INVALID" }
);
if (response.taskAvailability !== "AVAILABLE") {
throw new Error("Cannot render task when it is unavailable yet");
}
const { task, taskInfo } = response;
const updateValidity = useCallback(
(replyValidity: TaskReplyValidity) => taskEvent({ action: "UPDATE_VALIDITY", replyValidity }),
[taskEvent]
@@ -129,10 +124,10 @@ export const Task = () => {
[replyContent]
);
const submitResponse = useCallback(() => {
const submitResponse = useCallback(async () => {
if (taskStatus.mode === "REVIEW") {
completeTask(replyContent.current);
taskEvent({ action: "SET_SUBMITTED" });
await completeTask(replyContent.current);
scrollToTop(rootEl.current);
}
}, [taskStatus.mode, completeTask]);
@@ -1,8 +1,8 @@
import { HStack, IconButton, Link, Stack, Text, useColorModeValue } from "@chakra-ui/react";
import { HelpCircle } from "lucide-react";
import { useTranslation } from "next-i18next";
import type { TaskInfo } from "src/components/Tasks/TaskTypes";
import { getTypeSafei18nKey } from "src/lib/i18n";
import { TaskInfo } from "src/types/Task";
interface TaskHeaderProps {
/**
+8 -2
View File
@@ -1,7 +1,13 @@
import { createContext, useContext } from "react";
import { TaskApiHook } from "src/types/Hooks";
import { BaseTask } from "src/types/Task";
import { BaseTask, TaskInfo } from "src/types/Task";
export const TaskContext = createContext<TaskApiHook<BaseTask, unknown>>(null);
export interface TaskContextType<Task extends BaseTask, ResponseContent>
extends Omit<TaskApiHook<Task, ResponseContent>, "response"> {
task: Task;
taskInfo: TaskInfo;
}
export const TaskContext = createContext<TaskContextType<BaseTask, unknown>>(null);
export const useTaskContext = () => useContext(TaskContext);
@@ -6,7 +6,8 @@ import { BaseTask, ServerTaskResponse, TaskResponse, TaskType as TaskTypeEnum }
import useSWRImmutable from "swr/immutable";
import useSWRMutation from "swr/mutation";
export const useGenericTaskAPI = <TaskType extends BaseTask, ResponseContent>(
// TODO: provide type for the content reply, this will be much harder since the replies vary vastly
export const useGenericTaskAPI = <TaskType extends BaseTask, ResponseContent = any>(
taskType: TaskTypeEnum
): TaskApiHook<TaskType, ResponseContent> => {
const [response, setResponse] = useState<TaskResponse<TaskType>>({ taskAvailability: "AWAITING_INITIAL" });
+1 -2
View File
@@ -4,9 +4,8 @@ import { useTranslation } from "next-i18next";
import { useEffect, useMemo, useState } from "react";
import { LeaderboardWidget, TaskOption, WelcomeCard } from "src/components/Dashboard";
import { getDashboardLayout } from "src/components/Layout";
import { TaskCategory } from "src/components/Tasks/TaskTypes";
import { get } from "src/lib/api";
import { AvailableTasks, TaskType } from "src/types/Task";
import { AvailableTasks, TaskCategory, TaskType } from "src/types/Task";
export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_props";
import useSWR from "swr";