From ea7e320a7853ded66f6e2c6ff5286523b4b7b60a Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Thu, 19 Jan 2023 21:06:37 -0500 Subject: [PATCH 01/18] add status option in admin page left bar --- website/src/components/Layout.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/website/src/components/Layout.tsx b/website/src/components/Layout.tsx index 484d16ec..55085550 100644 --- a/website/src/components/Layout.tsx +++ b/website/src/components/Layout.tsx @@ -2,7 +2,7 @@ import { Box, Grid } from "@chakra-ui/react"; import type { NextPage } from "next"; -import { FiBarChart2, FiLayout, FiMessageSquare, FiUsers } from "react-icons/fi"; +import { FiBarChart2, FiLayout, FiMessageSquare, FiUsers, FiActivity } from "react-icons/fi"; import { Header } from "src/components/Header"; import { SlimFooter } from "./Dashboard/SlimFooter"; @@ -75,6 +75,12 @@ export const getAdminLayout = (page: React.ReactElement) => ( desc: "Users Dashboard", icon: FiUsers, }, + { + label: "Status", + pathname: "/admin/status", + desc: "Status Dashboard", + icon: FiActivity, + }, ]} > {page} From 812c8cb209f9c4d76350b08c63305767e655ab09 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Fri, 20 Jan 2023 01:35:48 -0500 Subject: [PATCH 02/18] create status page --- website/src/pages/admin/status/index.tsx | 168 ++++++++++++++++++ website/src/pages/api/admin/stats.ts | 18 ++ .../src/pages/api/admin/tasks_availability.ts | 28 +++ website/src/pages/api/admin/tree_manager.ts | 18 ++ 4 files changed, 232 insertions(+) create mode 100644 website/src/pages/admin/status/index.tsx create mode 100644 website/src/pages/api/admin/stats.ts create mode 100644 website/src/pages/api/admin/tasks_availability.ts create mode 100644 website/src/pages/api/admin/tree_manager.ts diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx new file mode 100644 index 00000000..6af65b61 --- /dev/null +++ b/website/src/pages/admin/status/index.tsx @@ -0,0 +1,168 @@ +import { Box, Button, Container, Flex, FormControl, FormLabel, Input, Select, SimpleGrid, Stack, Text, useToast } from "@chakra-ui/react"; +import { + Spacer, + Table, + TableCaption, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, + useColorMode +} from "@chakra-ui/react"; +/* import { Field, Form, Formik } from "formik"; */ +import Head from "next/head"; +import { useRouter } from "next/router"; +import { useSession } from "next-auth/react"; +import { useEffect } from "react"; +import { getAdminLayout } from "src/components/Layout"; +import poster from "src/lib/poster"; +import prisma from "src/lib/prismadb"; +import useSWR from "swr/mutation"; + +import { useState } from "react"; +import useSWRMutation from "swr/mutation"; +import useSWRImmutable from "swr/immutable"; +import { get, post } from "src/lib/api"; + +/* import TreeManagerCell from "src/components/TreeManagerCell"; */ + +/** + * Provides the admin status page that shows result of calls to several backend API endpoints, + * namely /api/v1/tasks/availability, /api/v1/stats/, /api/v1/stats/tree_manager + */ + +const StatusIndex = ({ user }) => { + const toast = useToast(); + const router = useRouter(); + const { data: session, status } = useSession(); + + const { colorMode } = useColorMode(); + const backgroundColor = colorMode === "light" ? "white" : "gray.700"; + const dataBackgroundColor = colorMode === "light" ? "gray.100" : "gray.700"; + // Check when the user session is loaded and re-route if the user is not an + // admin. This follows the suggestion by NextJS for handling private pages: + // https://nextjs.org/docs/api-reference/next/router#usage + // + // All admin pages should use the same check and routing steps. + useEffect(() => { + if (status === "loading") { + return; + } + if (session?.user?.role === "admin") { + return; + } + router.push("/"); + }, [router, session, status]); + + const [availability, setAvailability] = useState(0); + const [stats, setStats] = useState(0); + const [treeManager, setTreeManager] = useState(0); + + const {data: dataAvailability, error: errorAvailability, isLoading: isLoadingAvailability} = useSWRImmutable("/api/admin/tasks_availability", get, { + onSuccess: (data) => { + setAvailability(data); } + }); + const {data: dataStats, error: errorStats, isLoading: isLoadingStats} = useSWRImmutable("/api/admin/stats", get, { + onSuccess: (data) => { setStats(data); } + }); + const {data: dataTreeManager, error: errorTreeManager, isLoading: isLoadingTreeManager} = useSWRImmutable("/api/admin/tree_manager", get, { + onSuccess: (data) => { + setTreeManager(data); } + }); + + return ( + <> + + Status - Open Assistant + + + + + + + /api/v1/tasks/availability + + +
+                            {availability ? JSON.stringify(availability, null, 2) : "None"}
+                        
+
+
+ + + + /api/v1/stats/ + + +
+                            {stats ? JSON.stringify(stats, null, 2) : "None"}
+                        
+
+
+ +
+
+ + + + + /api/v1/stats/tree_manager + + + {treeManager ? + + + state_counts + + +
+                                 {JSON.stringify(treeManager.state_counts, null, 2)}
+                             
+
+ +
+ + message_counts + + + Tree Manager + + + + + + + + + + + + + {treeManager.message_counts.map(({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => ( + + + + + + + + + + ))} + +
Message Tree IDStateDepthOldestYoungestCountGoal Tree Size
{message_tree_id}{state}{depth}{oldest}{youngest}{count}{goal_tree_size}
+
+ : "None"} +
+ + ); +}; + +StatusIndex.getLayout = getAdminLayout; + +export default StatusIndex; diff --git a/website/src/pages/api/admin/stats.ts b/website/src/pages/api/admin/stats.ts new file mode 100644 index 00000000..1dedbd30 --- /dev/null +++ b/website/src/pages/api/admin/stats.ts @@ -0,0 +1,18 @@ +import { withRole } from "src/lib/auth"; + +/** + * Returns the messages recorded by the backend for a user. + */ +const handler = withRole("admin", async (req, res) => { + const statsRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/stats/`, { + method: "GET", + headers: { + "X-API-Key": process.env.FASTAPI_KEY, + }, + }); + const stats = await statsRes.json(); + + res.status(statsRes.status).json(stats); +}); + +export default handler; diff --git a/website/src/pages/api/admin/tasks_availability.ts b/website/src/pages/api/admin/tasks_availability.ts new file mode 100644 index 00000000..6d64d88b --- /dev/null +++ b/website/src/pages/api/admin/tasks_availability.ts @@ -0,0 +1,28 @@ +import { withRole } from "src/lib/auth"; +import { oasstApiClient } from "src/lib/oasst_api_client"; +import type { Message } from "src/types/Conversation"; + +/** + * Returns the messages recorded by the backend for a user. + */ +const handler = withRole("admin", async (req, res) => { + + const tasksAvailabilityRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/tasks/availability`, { + method: "POST", + headers: { + "X-API-Key": process.env.FASTAPI_KEY, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id: "__dummy_user__", + display_name: "Dummy User", + auth_method: "local", + }), + + }); + const tasksAvailability = await tasksAvailabilityRes.json(); + + res.status(tasksAvailabilityRes.status).json(tasksAvailability); +}); + +export default handler; diff --git a/website/src/pages/api/admin/tree_manager.ts b/website/src/pages/api/admin/tree_manager.ts new file mode 100644 index 00000000..b47562bf --- /dev/null +++ b/website/src/pages/api/admin/tree_manager.ts @@ -0,0 +1,18 @@ +import { withRole } from "src/lib/auth"; + +/** + * Returns the messages recorded by the backend for a user. + */ +const handler = withRole("admin", async (req, res) => { + const treeManagerRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/stats/tree_manager`, { + method: "GET", + headers: { + "X-API-Key": process.env.FASTAPI_KEY, + }, + }); + const treeManager = await treeManagerRes.json(); + + res.status(treeManagerRes.status).json(treeManager); +}); + +export default handler; From 91bb5603833da5b021202586d0488163de445cf1 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Fri, 20 Jan 2023 12:16:06 -0500 Subject: [PATCH 03/18] clean up status page code --- website/src/pages/admin/status/index.tsx | 300 ++++++++++++----------- website/src/pages/api/admin/stats.ts | 1 + 2 files changed, 162 insertions(+), 139 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 6af65b61..4eaa5a7e 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -1,32 +1,31 @@ -import { Box, Button, Container, Flex, FormControl, FormLabel, Input, Select, SimpleGrid, Stack, Text, useToast } from "@chakra-ui/react"; import { - Spacer, - Table, - TableCaption, - TableContainer, - Tbody, - Td, - Th, - Thead, - Tr, - useColorMode + Box, + Button, + CircularProgress, + Container, + SimpleGrid, + Text, + Table, + TableCaption, + TableContainer, + Tbody, + Td, + Th, + Thead, + Tr, + View, + useColorMode, + useToast, } from "@chakra-ui/react"; -/* import { Field, Form, Formik } from "formik"; */ import Head from "next/head"; import { useRouter } from "next/router"; import { useSession } from "next-auth/react"; -import { useEffect } from "react"; +import { useEffect, useState } from "react"; +import useSWRImmutable from "swr/immutable"; import { getAdminLayout } from "src/components/Layout"; import poster from "src/lib/poster"; import prisma from "src/lib/prismadb"; -import useSWR from "swr/mutation"; - -import { useState } from "react"; -import useSWRMutation from "swr/mutation"; -import useSWRImmutable from "swr/immutable"; -import { get, post } from "src/lib/api"; - -/* import TreeManagerCell from "src/components/TreeManagerCell"; */ +import { get } from "src/lib/api"; /** * Provides the admin status page that shows result of calls to several backend API endpoints, @@ -34,133 +33,156 @@ import { get, post } from "src/lib/api"; */ const StatusIndex = ({ user }) => { - const toast = useToast(); - const router = useRouter(); - const { data: session, status } = useSession(); + const toast = useToast(); + const router = useRouter(); + const { data: session, status } = useSession(); - const { colorMode } = useColorMode(); - const backgroundColor = colorMode === "light" ? "white" : "gray.700"; - const dataBackgroundColor = colorMode === "light" ? "gray.100" : "gray.700"; - // Check when the user session is loaded and re-route if the user is not an - // admin. This follows the suggestion by NextJS for handling private pages: - // https://nextjs.org/docs/api-reference/next/router#usage - // - // All admin pages should use the same check and routing steps. - useEffect(() => { - if (status === "loading") { - return; - } - if (session?.user?.role === "admin") { - return; - } - router.push("/"); - }, [router, session, status]); + const { colorMode } = useColorMode(); + const backgroundColor = colorMode === "light" ? "white" : "gray.700"; + const dataBackgroundColor = colorMode === "light" ? "gray.100" : "gray.800"; + // Check when the user session is loaded and re-route if the user is not an + // admin. This follows the suggestion by NextJS for handling private pages: + // https://nextjs.org/docs/api-reference/next/router#usage + // + // All admin pages should use the same check and routing steps. + useEffect(() => { + if (status === "loading") { + return; + } + if (session?.user?.role === "admin") { + return; + } + router.push("/"); + }, [router, session, status]); - const [availability, setAvailability] = useState(0); - const [stats, setStats] = useState(0); - const [treeManager, setTreeManager] = useState(0); + const [availability, setAvailability] = useState(0); + const [stats, setStats] = useState(0); + const [treeManager, setTreeManager] = useState(0); - const {data: dataAvailability, error: errorAvailability, isLoading: isLoadingAvailability} = useSWRImmutable("/api/admin/tasks_availability", get, { - onSuccess: (data) => { - setAvailability(data); } - }); - const {data: dataStats, error: errorStats, isLoading: isLoadingStats} = useSWRImmutable("/api/admin/stats", get, { - onSuccess: (data) => { setStats(data); } - }); - const {data: dataTreeManager, error: errorTreeManager, isLoading: isLoadingTreeManager} = useSWRImmutable("/api/admin/tree_manager", get, { - onSuccess: (data) => { - setTreeManager(data); } - }); + const { + data: dataAvailability, + error: errorAvailability, + isLoading: isLoadingAvailability, + } = useSWRImmutable("/api/admin/tasks_availability", get, { + onSuccess: (data) => { + setAvailability(data); + }, + onError: (error) => { + setAvailability(error); + }, + }); + const { + data: dataStats, + error: errorStats, + isLoading: isLoadingStats, + } = useSWRImmutable("/api/admin/stats", get, { + onSuccess: (data) => { + setStats(data); + }, + onError: (error) => { + setStats(error); + }, + }); + const { + data: dataTreeManager, + error: errorTreeManager, + isLoading: isLoadingTreeManager, + } = useSWRImmutable("/api/admin/tree_manager", get, { + onSuccess: (data) => { + setTreeManager(data); + }, + onError: (error) => { + setTreeManager(error); + }, + }); - return ( - <> - - Status - Open Assistant - - + return ( + <> + + Status - Open Assistant + + - - - /api/v1/tasks/availability - - -
-                            {availability ? JSON.stringify(availability, null, 2) : "None"}
-                        
-
-
- - - - /api/v1/stats/ - - -
-                            {stats ? JSON.stringify(stats, null, 2) : "None"}
-                        
-
-
+ + + /api/v1/tasks/availability + + +
+              {availability ? JSON.stringify(availability, null, 2) : }
+            
+
+
+ + + /api/v1/stats/ + + +
{stats ? JSON.stringify(stats, null, 2) : }
+
+
-
+
+ + + /api/v1/stats/tree_manager + - - - - /api/v1/stats/tree_manager - - - {treeManager ? - - - state_counts - - -
-                                 {JSON.stringify(treeManager.state_counts, null, 2)}
-                             
-
- -
- - message_counts - - - Tree Manager - - - - - - - - - - - - - {treeManager.message_counts.map(({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => ( - - - - - - - - - - ))} - -
Message Tree IDStateDepthOldestYoungestCountGoal Tree Size
{message_tree_id}{state}{depth}{oldest}{youngest}{count}{goal_tree_size}
-
- : "None"} -
- - ); + {treeManager ? ( + + + state_counts + + +
{JSON.stringify(treeManager.state_counts, null, 2)}
+
+ +
+ + message_counts + + + Tree Manager + + + + + + + + + + + + + {treeManager.message_counts.map( + ({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => ( + + + + + + + + + + ) + )} + +
Message Tree IDStateDepthOldestYoungestCountGoal Tree Size
{message_tree_id}{state}{depth}{oldest}{youngest}{count}{goal_tree_size}
+
+
+ ) : ( + + )} +
+ + ); }; StatusIndex.getLayout = getAdminLayout; diff --git a/website/src/pages/api/admin/stats.ts b/website/src/pages/api/admin/stats.ts index 1dedbd30..dfc4768b 100644 --- a/website/src/pages/api/admin/stats.ts +++ b/website/src/pages/api/admin/stats.ts @@ -10,6 +10,7 @@ const handler = withRole("admin", async (req, res) => { "X-API-Key": process.env.FASTAPI_KEY, }, }); + const stats = await statsRes.json(); res.status(statsRes.status).json(stats); From 0f2a65ea3c211649019ddb948cf237a5d92a8d7e Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Fri, 20 Jan 2023 12:37:58 -0500 Subject: [PATCH 04/18] remove unnecessary imports --- website/src/pages/api/admin/tasks_availability.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/website/src/pages/api/admin/tasks_availability.ts b/website/src/pages/api/admin/tasks_availability.ts index 6d64d88b..687daa36 100644 --- a/website/src/pages/api/admin/tasks_availability.ts +++ b/website/src/pages/api/admin/tasks_availability.ts @@ -1,12 +1,9 @@ import { withRole } from "src/lib/auth"; -import { oasstApiClient } from "src/lib/oasst_api_client"; -import type { Message } from "src/types/Conversation"; /** * Returns the messages recorded by the backend for a user. */ const handler = withRole("admin", async (req, res) => { - const tasksAvailabilityRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/tasks/availability`, { method: "POST", headers: { @@ -18,7 +15,6 @@ const handler = withRole("admin", async (req, res) => { display_name: "Dummy User", auth_method: "local", }), - }); const tasksAvailability = await tasksAvailabilityRes.json(); From 4ccc88e0bb4ac679ceff130be5d8490caf1646b4 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Fri, 20 Jan 2023 12:59:24 -0500 Subject: [PATCH 05/18] fix admin status api handler comments --- website/src/pages/api/admin/stats.ts | 2 +- website/src/pages/api/admin/tasks_availability.ts | 2 +- website/src/pages/api/admin/tree_manager.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/website/src/pages/api/admin/stats.ts b/website/src/pages/api/admin/stats.ts index dfc4768b..7f8a43a0 100644 --- a/website/src/pages/api/admin/stats.ts +++ b/website/src/pages/api/admin/stats.ts @@ -1,7 +1,7 @@ import { withRole } from "src/lib/auth"; /** - * Returns the messages recorded by the backend for a user. + * Returns the message stats. */ const handler = withRole("admin", async (req, res) => { const statsRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/stats/`, { diff --git a/website/src/pages/api/admin/tasks_availability.ts b/website/src/pages/api/admin/tasks_availability.ts index 687daa36..c7f1d1c5 100644 --- a/website/src/pages/api/admin/tasks_availability.ts +++ b/website/src/pages/api/admin/tasks_availability.ts @@ -1,7 +1,7 @@ import { withRole } from "src/lib/auth"; /** - * Returns the messages recorded by the backend for a user. + * Returns result of tasks availability query using a dummy user. */ const handler = withRole("admin", async (req, res) => { const tasksAvailabilityRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/tasks/availability`, { diff --git a/website/src/pages/api/admin/tree_manager.ts b/website/src/pages/api/admin/tree_manager.ts index b47562bf..c127f635 100644 --- a/website/src/pages/api/admin/tree_manager.ts +++ b/website/src/pages/api/admin/tree_manager.ts @@ -1,7 +1,7 @@ import { withRole } from "src/lib/auth"; /** - * Returns the messages recorded by the backend for a user. + * Returns tree manager stats. */ const handler = withRole("admin", async (req, res) => { const treeManagerRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/stats/tree_manager`, { From b8ef87fb548fbae63f67755f2caf591cc60a2061 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Fri, 20 Jan 2023 21:42:56 -0500 Subject: [PATCH 06/18] use Card component for status page --- website/src/pages/admin/status/index.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 4eaa5a7e..5e1aba13 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -1,5 +1,6 @@ import { Box, + Card, Button, CircularProgress, Container, @@ -107,7 +108,7 @@ const StatusIndex = ({ user }) => { - + /api/v1/tasks/availability @@ -116,19 +117,19 @@ const StatusIndex = ({ user }) => { {availability ? JSON.stringify(availability, null, 2) : } - + - + /api/v1/stats/
{stats ? JSON.stringify(stats, null, 2) : }
-
+

- + /api/v1/stats/tree_manager @@ -180,7 +181,7 @@ const StatusIndex = ({ user }) => { ) : ( )} - + ); }; From a2932d1613e5aa9be240f9ff8dc824bfe9e3c55a Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Fri, 20 Jan 2023 23:44:11 -0500 Subject: [PATCH 07/18] unify 3 status endpoints and move status fetches to oasst_api_client --- website/src/lib/oasst_api_client.ts | 21 +++++++++ website/src/pages/admin/status/index.tsx | 47 +++---------------- website/src/pages/api/admin/stats.ts | 19 -------- website/src/pages/api/admin/status.ts | 26 ++++++++++ .../src/pages/api/admin/tasks_availability.ts | 24 ---------- website/src/pages/api/admin/tree_manager.ts | 18 ------- 6 files changed, 54 insertions(+), 101 deletions(-) delete mode 100644 website/src/pages/api/admin/stats.ts create mode 100644 website/src/pages/api/admin/status.ts delete mode 100644 website/src/pages/api/admin/tasks_availability.ts delete mode 100644 website/src/pages/api/admin/tree_manager.ts diff --git a/website/src/lib/oasst_api_client.ts b/website/src/lib/oasst_api_client.ts index 1e74b020..44d8ae7c 100644 --- a/website/src/lib/oasst_api_client.ts +++ b/website/src/lib/oasst_api_client.ts @@ -148,6 +148,27 @@ export class OasstApiClient { }); } + /** + * Returns the tasks availability information for given `user`. + */ + async fetch_tasks_availability(user: object): Promise { + return this.post("/api/v1/tasks/availability", user); + } + + /** + * Returns the message stats from the backend. + */ + async fetch_stats(): Promise { + return this.get("/api/v1/stats/"); + } + + /** + * Returns the tree manager stats from the backend. + */ + async fetch_tree_manager(): Promise { + return this.get("/api/v1/stats/tree_manager"); + } + /** * Returns the `BackendUser` associated with `user_id` */ diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 5e1aba13..5d5d9ba4 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -56,46 +56,13 @@ const StatusIndex = ({ user }) => { router.push("/"); }, [router, session, status]); - const [availability, setAvailability] = useState(0); - const [stats, setStats] = useState(0); - const [treeManager, setTreeManager] = useState(0); + const { + data: dataStatus, + error: errorStatus, + isLoading: isLoadingStatus, + } = useSWRImmutable("/api/admin/status", get); - const { - data: dataAvailability, - error: errorAvailability, - isLoading: isLoadingAvailability, - } = useSWRImmutable("/api/admin/tasks_availability", get, { - onSuccess: (data) => { - setAvailability(data); - }, - onError: (error) => { - setAvailability(error); - }, - }); - const { - data: dataStats, - error: errorStats, - isLoading: isLoadingStats, - } = useSWRImmutable("/api/admin/stats", get, { - onSuccess: (data) => { - setStats(data); - }, - onError: (error) => { - setStats(error); - }, - }); - const { - data: dataTreeManager, - error: errorTreeManager, - isLoading: isLoadingTreeManager, - } = useSWRImmutable("/api/admin/tree_manager", get, { - onSuccess: (data) => { - setTreeManager(data); - }, - onError: (error) => { - setTreeManager(error); - }, - }); + const { tasksAvailability, stats, treeManager } = dataStatus || {}; return ( <> @@ -114,7 +81,7 @@ const StatusIndex = ({ user }) => {
-              {availability ? JSON.stringify(availability, null, 2) : }
+              {tasksAvailability ? JSON.stringify(tasksAvailability, null, 2) : }
             
diff --git a/website/src/pages/api/admin/stats.ts b/website/src/pages/api/admin/stats.ts deleted file mode 100644 index 7f8a43a0..00000000 --- a/website/src/pages/api/admin/stats.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { withRole } from "src/lib/auth"; - -/** - * Returns the message stats. - */ -const handler = withRole("admin", async (req, res) => { - const statsRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/stats/`, { - method: "GET", - headers: { - "X-API-Key": process.env.FASTAPI_KEY, - }, - }); - - const stats = await statsRes.json(); - - res.status(statsRes.status).json(stats); -}); - -export default handler; diff --git a/website/src/pages/api/admin/status.ts b/website/src/pages/api/admin/status.ts new file mode 100644 index 00000000..4fb91857 --- /dev/null +++ b/website/src/pages/api/admin/status.ts @@ -0,0 +1,26 @@ +import { withRole } from "src/lib/auth"; +import { oasstApiClient } from "src/lib/oasst_api_client"; + +/** + * Returns tasks availability, stats, and tree manager stats. + */ +const handler = withRole("admin", async (req, res) => { + const dummy_user = { + id: "__dummy_user__", + display_name: "Dummy User", + auth_method: "local", + }; + const tasksAvailabilityData = await oasstApiClient.fetch_tasks_availability(dummy_user); + const statsData = await oasstApiClient.fetch_stats(); + const treeManagerData = await oasstApiClient.fetch_tree_manager(); + + const status = { + tasksAvailability: tasksAvailabilityData, + stats: statsData, + treeManager: treeManagerData, + }; + + res.status(200).json(status); +}); + +export default handler; diff --git a/website/src/pages/api/admin/tasks_availability.ts b/website/src/pages/api/admin/tasks_availability.ts deleted file mode 100644 index c7f1d1c5..00000000 --- a/website/src/pages/api/admin/tasks_availability.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { withRole } from "src/lib/auth"; - -/** - * Returns result of tasks availability query using a dummy user. - */ -const handler = withRole("admin", async (req, res) => { - const tasksAvailabilityRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/tasks/availability`, { - method: "POST", - headers: { - "X-API-Key": process.env.FASTAPI_KEY, - "Content-Type": "application/json", - }, - body: JSON.stringify({ - id: "__dummy_user__", - display_name: "Dummy User", - auth_method: "local", - }), - }); - const tasksAvailability = await tasksAvailabilityRes.json(); - - res.status(tasksAvailabilityRes.status).json(tasksAvailability); -}); - -export default handler; diff --git a/website/src/pages/api/admin/tree_manager.ts b/website/src/pages/api/admin/tree_manager.ts deleted file mode 100644 index c127f635..00000000 --- a/website/src/pages/api/admin/tree_manager.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { withRole } from "src/lib/auth"; - -/** - * Returns tree manager stats. - */ -const handler = withRole("admin", async (req, res) => { - const treeManagerRes = await fetch(`${process.env.FASTAPI_URL}/api/v1/stats/tree_manager`, { - method: "GET", - headers: { - "X-API-Key": process.env.FASTAPI_KEY, - }, - }); - const treeManager = await treeManagerRes.json(); - - res.status(treeManagerRes.status).json(treeManager); -}); - -export default handler; From 93969bd49d22a2ee7786cab190705dbdae8f6916 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 00:11:02 -0500 Subject: [PATCH 08/18] status use current admin user --- website/src/pages/api/admin/status.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/website/src/pages/api/admin/status.ts b/website/src/pages/api/admin/status.ts index 4fb91857..3046bb27 100644 --- a/website/src/pages/api/admin/status.ts +++ b/website/src/pages/api/admin/status.ts @@ -1,3 +1,4 @@ +import { getToken } from "next-auth/jwt"; import { withRole } from "src/lib/auth"; import { oasstApiClient } from "src/lib/oasst_api_client"; @@ -5,12 +6,13 @@ import { oasstApiClient } from "src/lib/oasst_api_client"; * Returns tasks availability, stats, and tree manager stats. */ const handler = withRole("admin", async (req, res) => { - const dummy_user = { - id: "__dummy_user__", - display_name: "Dummy User", + const token = await getToken({ req }); + const currentUser = { + id: token.sub, + display_name: token.name, auth_method: "local", }; - const tasksAvailabilityData = await oasstApiClient.fetch_tasks_availability(dummy_user); + const tasksAvailabilityData = await oasstApiClient.fetch_tasks_availability(currentUser); const statsData = await oasstApiClient.fetch_stats(); const treeManagerData = await oasstApiClient.fetch_tree_manager(); From 2d7d14b4c91703892e912271059aa27832a853b5 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 11:44:49 -0500 Subject: [PATCH 09/18] Update website/src/pages/admin/status/index.tsx Co-authored-by: notmd <33456881+notmd@users.noreply.github.com> --- website/src/pages/admin/status/index.tsx | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 5d5d9ba4..e4f510d7 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -75,15 +75,17 @@ const StatusIndex = ({ user }) => { - - - /api/v1/tasks/availability - - -
-              {tasksAvailability ? JSON.stringify(tasksAvailability, null, 2) : }
-            
-
+ + + + /api/v1/tasks/availability + + +
+                {tasksAvailability ? JSON.stringify(tasksAvailability, null, 2) : }
+              
+
+
From 56fb28f953b35f3e7263e9411a110f89942ec904 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 11:45:56 -0500 Subject: [PATCH 10/18] use CardBody in website/src/pages/admin/status/index.tsx Co-authored-by: notmd <33456881+notmd@users.noreply.github.com> --- website/src/pages/admin/status/index.tsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index e4f510d7..0abe1404 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -88,13 +88,15 @@ const StatusIndex = ({ user }) => { - - - /api/v1/stats/ - - -
{stats ? JSON.stringify(stats, null, 2) : }
-
+ + + + /api/v1/stats/ + + +
{stats ? JSON.stringify(stats, null, 2) : }
+
+

From 05dce5b4a95807c42147f3817b7c43919bab9da6 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 11:46:16 -0500 Subject: [PATCH 11/18] Use CardBody website/src/pages/admin/status/index.tsx Co-authored-by: notmd <33456881+notmd@users.noreply.github.com> --- website/src/pages/admin/status/index.tsx | 101 ++++++++++++----------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 0abe1404..30c55c9a 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -100,58 +100,59 @@ const StatusIndex = ({ user }) => {
- - - /api/v1/stats/tree_manager - - - {treeManager ? ( - - - state_counts - - -
{JSON.stringify(treeManager.state_counts, null, 2)}
-
- -
+ + + + /api/v1/stats/tree_manager + + {treeManager ? ( + - message_counts + state_counts - - Tree Manager - - - - - - - - - - - - - {treeManager.message_counts.map( - ({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => ( - - - - - - - - - - ) - )} - -
Message Tree IDStateDepthOldestYoungestCountGoal Tree Size
{message_tree_id}{state}{depth}{oldest}{youngest}{count}{goal_tree_size}
-
-
- ) : ( - - )} + +
{JSON.stringify(treeManager.state_counts, null, 2)}
+
+ +
+ + message_counts + + + Tree Manager + + + + + + + + + + + + + {treeManager.message_counts.map( + ({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => ( + + + + + + + + + + ) + )} + +
Message Tree IDStateDepthOldestYoungestCountGoal Tree Size
{message_tree_id}{state}{depth}{oldest}{youngest}{count}{goal_tree_size}
+
+ + ) : ( + + )} +
); From 72d61cc44c9f152647db284ee595a72073afe228 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 11:46:40 -0500 Subject: [PATCH 12/18] use Promise.all website/src/pages/api/admin/status.ts Co-authored-by: notmd <33456881+notmd@users.noreply.github.com> --- website/src/pages/api/admin/status.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/website/src/pages/api/admin/status.ts b/website/src/pages/api/admin/status.ts index 3046bb27..fb93740f 100644 --- a/website/src/pages/api/admin/status.ts +++ b/website/src/pages/api/admin/status.ts @@ -12,9 +12,11 @@ const handler = withRole("admin", async (req, res) => { display_name: token.name, auth_method: "local", }; - const tasksAvailabilityData = await oasstApiClient.fetch_tasks_availability(currentUser); - const statsData = await oasstApiClient.fetch_stats(); - const treeManagerData = await oasstApiClient.fetch_tree_manager(); + const [tasksAvailabilityData, statsData, treeManagerData] = await Promise.all([ + oasstApiClient.fetch_tasks_availability(currentUser), + oasstApiClient.fetch_stats(), + oasstApiClient.fetch_tree_manager(), + ]); const status = { tasksAvailability: tasksAvailabilityData, From fbc2ba468b39ff39428a20806b0033678496bf79 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 11:48:30 -0500 Subject: [PATCH 13/18] removed unnecessary element id --- website/src/pages/admin/status/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 30c55c9a..8894888f 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -81,7 +81,7 @@ const StatusIndex = ({ user }) => { /api/v1/tasks/availability -
+              
                 {tasksAvailability ? JSON.stringify(tasksAvailability, null, 2) : }
               
@@ -94,7 +94,7 @@ const StatusIndex = ({ user }) => { /api/v1/stats/ -
{stats ? JSON.stringify(stats, null, 2) : }
+
{stats ? JSON.stringify(stats, null, 2) : }
@@ -111,7 +111,7 @@ const StatusIndex = ({ user }) => { state_counts -
{JSON.stringify(treeManager.state_counts, null, 2)}
+
{JSON.stringify(treeManager.state_counts, null, 2)}

From 4dd809585e77da4ac0205a906b98143a2b2e5ed8 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 12:24:15 -0500 Subject: [PATCH 14/18] handle error/loading case correctly in status page --- website/src/pages/admin/status/index.tsx | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index 8894888f..efb734b2 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -1,9 +1,8 @@ import { Box, Card, - Button, + CardBody, CircularProgress, - Container, SimpleGrid, Text, Table, @@ -14,7 +13,6 @@ import { Th, Thead, Tr, - View, useColorMode, useToast, } from "@chakra-ui/react"; @@ -81,9 +79,13 @@ const StatusIndex = ({ user }) => { /api/v1/tasks/availability -
-                {tasksAvailability ? JSON.stringify(tasksAvailability, null, 2) : }
-              
+ {tasksAvailability ? ( +
{JSON.stringify(tasksAvailability, null, 2)}
+ ) : errorStatus ? ( +
{JSON.stringify(errorStatus, null, 2)}
+ ) : ( + + )}
@@ -94,7 +96,13 @@ const StatusIndex = ({ user }) => { /api/v1/stats/ -
{stats ? JSON.stringify(stats, null, 2) : }
+ {stats ? ( +
{JSON.stringify(stats, null, 2)}
+ ) : errorStatus ? ( +
{JSON.stringify(errorStatus, null, 2)}
+ ) : ( + + )}
@@ -149,6 +157,8 @@ const StatusIndex = ({ user }) => {
+ ) : errorStatus ? ( +
{JSON.stringify(errorStatus, null, 2)}
) : ( )} From a75c13ef423d99ea210284d767c63de158635fea Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 13:13:15 -0500 Subject: [PATCH 15/18] use getBackendUserCore for taskAvailability --- website/src/pages/api/admin/status.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/website/src/pages/api/admin/status.ts b/website/src/pages/api/admin/status.ts index fb93740f..64299db8 100644 --- a/website/src/pages/api/admin/status.ts +++ b/website/src/pages/api/admin/status.ts @@ -1,17 +1,14 @@ import { getToken } from "next-auth/jwt"; import { withRole } from "src/lib/auth"; import { oasstApiClient } from "src/lib/oasst_api_client"; +import { getBackendUserCore } from "src/lib/users"; /** * Returns tasks availability, stats, and tree manager stats. */ const handler = withRole("admin", async (req, res) => { const token = await getToken({ req }); - const currentUser = { - id: token.sub, - display_name: token.name, - auth_method: "local", - }; + const currentUser = await getBackendUserCore(token.sub); const [tasksAvailabilityData, statsData, treeManagerData] = await Promise.all([ oasstApiClient.fetch_tasks_availability(currentUser), oasstApiClient.fetch_stats(), From 323f5a19a2599ed1a72701c2196d610a191e9c45 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 14:01:58 -0500 Subject: [PATCH 16/18] use Promise.allSettled for admin status --- website/src/pages/admin/status/index.tsx | 20 +++++++++++++------- website/src/pages/api/admin/status.ts | 8 ++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index efb734b2..ae0f2f1d 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -79,8 +79,10 @@ const StatusIndex = ({ user }) => { /api/v1/tasks/availability - {tasksAvailability ? ( -
{JSON.stringify(tasksAvailability, null, 2)}
+ {tasksAvailability?.status === "fulfilled" ? ( +
{JSON.stringify(tasksAvailability.value, null, 2)}
+ ) : tasksAvailability?.status === "rejected" ? ( +
{JSON.stringify(tasksAvailability.reason, null, 2)}
) : errorStatus ? (
{JSON.stringify(errorStatus, null, 2)}
) : ( @@ -96,8 +98,10 @@ const StatusIndex = ({ user }) => { /api/v1/stats/ - {stats ? ( -
{JSON.stringify(stats, null, 2)}
+ {stats?.status === "fulfilled" ? ( +
{JSON.stringify(stats.value, null, 2)}
+ ) : stats?.status === "rejected" ? ( +
{JSON.stringify(stats.reason, null, 2)}
) : errorStatus ? (
{JSON.stringify(errorStatus, null, 2)}
) : ( @@ -113,13 +117,13 @@ const StatusIndex = ({ user }) => { /api/v1/stats/tree_manager - {treeManager ? ( + {treeManager?.status === "fulfilled" ? ( state_counts -
{JSON.stringify(treeManager.state_counts, null, 2)}
+
{JSON.stringify(treeManager.value.state_counts, null, 2)}

@@ -140,7 +144,7 @@ const StatusIndex = ({ user }) => { - {treeManager.message_counts.map( + {treeManager.value.message_counts.map( ({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => ( {message_tree_id} @@ -157,6 +161,8 @@ const StatusIndex = ({ user }) => {
+ ) : treeManager?.status === "rejected" ? ( +
{JSON.stringify(treeManager.reason, null, 2)}
) : errorStatus ? (
{JSON.stringify(errorStatus, null, 2)}
) : ( diff --git a/website/src/pages/api/admin/status.ts b/website/src/pages/api/admin/status.ts index 64299db8..1f0ba915 100644 --- a/website/src/pages/api/admin/status.ts +++ b/website/src/pages/api/admin/status.ts @@ -9,16 +9,16 @@ import { getBackendUserCore } from "src/lib/users"; const handler = withRole("admin", async (req, res) => { const token = await getToken({ req }); const currentUser = await getBackendUserCore(token.sub); - const [tasksAvailabilityData, statsData, treeManagerData] = await Promise.all([ + const [tasksAvailabilityOutcome, statsOutcome, treeManagerOutcome] = await Promise.allSettled([ oasstApiClient.fetch_tasks_availability(currentUser), oasstApiClient.fetch_stats(), oasstApiClient.fetch_tree_manager(), ]); const status = { - tasksAvailability: tasksAvailabilityData, - stats: statsData, - treeManager: treeManagerData, + tasksAvailability: tasksAvailabilityOutcome, + stats: statsOutcome, + treeManager: treeManagerOutcome, }; res.status(200).json(status); From 19652d5cec066195ba62b158e2cff1019d3d08a4 Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 20:42:34 -0500 Subject: [PATCH 17/18] remove unnecessary imports --- website/src/pages/admin/status/index.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/website/src/pages/admin/status/index.tsx b/website/src/pages/admin/status/index.tsx index ae0f2f1d..12eb0785 100644 --- a/website/src/pages/admin/status/index.tsx +++ b/website/src/pages/admin/status/index.tsx @@ -14,16 +14,13 @@ import { Thead, Tr, useColorMode, - useToast, } from "@chakra-ui/react"; import Head from "next/head"; import { useRouter } from "next/router"; import { useSession } from "next-auth/react"; -import { useEffect, useState } from "react"; +import { useEffect } from "react"; import useSWRImmutable from "swr/immutable"; import { getAdminLayout } from "src/components/Layout"; -import poster from "src/lib/poster"; -import prisma from "src/lib/prismadb"; import { get } from "src/lib/api"; /** @@ -31,13 +28,11 @@ import { get } from "src/lib/api"; * namely /api/v1/tasks/availability, /api/v1/stats/, /api/v1/stats/tree_manager */ -const StatusIndex = ({ user }) => { - const toast = useToast(); +const StatusIndex = () => { const router = useRouter(); const { data: session, status } = useSession(); const { colorMode } = useColorMode(); - const backgroundColor = colorMode === "light" ? "white" : "gray.700"; const dataBackgroundColor = colorMode === "light" ? "gray.100" : "gray.800"; // Check when the user session is loaded and re-route if the user is not an // admin. This follows the suggestion by NextJS for handling private pages: From a31da35fb0eb272461b82c4ca3ce39b800d0068a Mon Sep 17 00:00:00 2001 From: ml729 <85370083+ml729@users.noreply.github.com> Date: Sat, 21 Jan 2023 21:08:09 -0500 Subject: [PATCH 18/18] use dummy user for tasks availability --- website/src/pages/api/admin/status.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/website/src/pages/api/admin/status.ts b/website/src/pages/api/admin/status.ts index 1f0ba915..1da03da8 100644 --- a/website/src/pages/api/admin/status.ts +++ b/website/src/pages/api/admin/status.ts @@ -7,10 +7,13 @@ import { getBackendUserCore } from "src/lib/users"; * Returns tasks availability, stats, and tree manager stats. */ const handler = withRole("admin", async (req, res) => { - const token = await getToken({ req }); - const currentUser = await getBackendUserCore(token.sub); + const dummyUser = { + id: "__dummy_user__", + display_name: "Dummy User", + auth_method: "local", + }; const [tasksAvailabilityOutcome, statsOutcome, treeManagerOutcome] = await Promise.allSettled([ - oasstApiClient.fetch_tasks_availability(currentUser), + oasstApiClient.fetch_tasks_availability(dummyUser), oasstApiClient.fetch_stats(), oasstApiClient.fetch_tree_manager(), ]);