System config parameter view

This commit is contained in:
notmd
2023-02-02 20:23:00 +07:00
parent caa6331a72
commit 28ee771a97
12 changed files with 223 additions and 178 deletions
+15 -8
View File
@@ -2,8 +2,9 @@ import "../styles/globals.css";
import "focus-visible";
import type { AppProps } from "next/app";
import Head from "next/head";
import { SessionProvider } from "next-auth/react";
import { appWithTranslation } from "next-i18next";
import { appWithTranslation, useTranslation } from "next-i18next";
import { FlagsProvider } from "react-feature-flags";
import { getDefaultLayout, NextPageWithLayout } from "src/components/Layout";
import flags from "src/flags";
@@ -24,15 +25,21 @@ const swrConfig: SWRConfiguration = {
function MyApp({ Component, pageProps: { session, cookies, ...pageProps } }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? getDefaultLayout;
const page = getLayout(<Component {...pageProps} />);
const { t } = useTranslation();
return (
<FlagsProvider value={flags}>
<Chakra cookies={cookies}>
<SWRConfig value={swrConfig}>
<SessionProvider session={session}>{page}</SessionProvider>
</SWRConfig>
</Chakra>
</FlagsProvider>
<>
<Head>
<meta name="description" key="description" content={t("index:description")} />
</Head>
<FlagsProvider value={flags}>
<Chakra cookies={cookies}>
<SWRConfig value={swrConfig}>
<SessionProvider session={session}>{page}</SessionProvider>
</SWRConfig>
</Chakra>
</FlagsProvider>
</>
);
}
export { getServerSideProps };
+4 -31
View File
@@ -1,7 +1,4 @@
import Head from "next/head";
import { useRouter } from "next/router";
import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { AdminArea } from "src/components/AdminArea";
import { getAdminLayout } from "src/components/Layout";
import { UserTable } from "src/components/UserTable";
export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_props";
@@ -11,34 +8,10 @@ export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_
* admins the ability to manage their access rights.
*/
const AdminIndex = () => {
const router = useRouter();
const { data: session, status } = useSession();
// 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]);
return (
<>
<Head>
<title>Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
</Head>
<main>{status === "loading" ? "loading..." : <UserTable />}</main>
</>
<AdminArea title="Open Assistant">
<UserTable />
</AdminArea>
);
};
+36
View File
@@ -0,0 +1,36 @@
import { Card, CardBody, CircularProgress } from "@chakra-ui/react";
import Head from "next/head";
import { AdminArea } from "src/components/AdminArea";
import { getAdminLayout } from "src/components/Layout";
import { get } from "src/lib/api";
import useSWRImmutable from "swr/immutable";
export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_props";
export default function Parameters() {
const { data, isLoading, error } = useSWRImmutable("/api/admin/parameters", get);
return (
<>
<Head>
<title>Parameters - Open Assistant</title>
</Head>
<AdminArea>
<Card>
<CardBody>
{isLoading && <CircularProgress isIndeterminate></CircularProgress>}
{error && "Unable to load data"}
{data && (
<Card variant="json" overflowX="auto">
<CardBody>
<pre>{JSON.stringify(data, null, 2)}</pre>
</CardBody>
</Card>
)}
</CardBody>
</Card>
</AdminArea>
</>
);
}
Parameters.getLayout = getAdminLayout;
+105 -128
View File
@@ -13,12 +13,9 @@ import {
Th,
Thead,
Tr,
useColorMode,
} from "@chakra-ui/react";
import Head from "next/head";
import { useRouter } from "next/router";
import { useSession } from "next-auth/react";
import { useEffect } from "react";
import { AdminArea } from "src/components/AdminArea";
import { getAdminLayout } from "src/components/Layout";
import { get } from "src/lib/api";
import useSWRImmutable from "swr/immutable";
@@ -30,31 +27,7 @@ export { getDefaultStaticProps as getStaticProps } from "src/lib/default_static_
*/
const StatusIndex = () => {
const router = useRouter();
const { data: session, status } = useSession();
const { colorMode } = useColorMode();
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 {
data: dataStatus,
error: errorStatus,
isLoading: isLoadingStatus,
} = useSWRImmutable("/api/admin/status", get);
const { data: dataStatus, error: errorStatus } = useSWRImmutable("/api/admin/status", get);
const { tasksAvailability, stats, treeManager } = dataStatus || {};
@@ -62,110 +35,114 @@ const StatusIndex = () => {
<>
<Head>
<title>Status - Open Assistant</title>
<meta
name="description"
content="Conversational AI for everyone. An open source project to create a chat enabled GPT LLM run by LAION and contributors around the world."
/>
</Head>
<SimpleGrid columns={[1, 1, 1, 1, 1, 2]} gap={4}>
<Card>
<CardBody>
<Text as="h1" fontSize="3xl" textAlign="center">
/api/v1/tasks/availability
</Text>
<Box bg={dataBackgroundColor} borderRadius="xl" p="6" pt="4" pr="12">
{tasksAvailability?.status === "fulfilled" ? (
<pre>{JSON.stringify(tasksAvailability.value, null, 2)}</pre>
) : tasksAvailability?.status === "rejected" ? (
<pre>{JSON.stringify(tasksAvailability.reason, null, 2)}</pre>
) : errorStatus ? (
<pre>{JSON.stringify(errorStatus, null, 2)}</pre>
) : (
<CircularProgress isIndeterminate />
)}
</Box>
</CardBody>
</Card>
<Card>
<CardBody>
<Text as="h1" fontSize="3xl" textAlign="center">
/api/v1/stats/
</Text>
<Box bg={dataBackgroundColor} borderRadius="xl" p="6" pt="4" pr="12">
{stats?.status === "fulfilled" ? (
<pre>{JSON.stringify(stats.value, null, 2)}</pre>
) : stats?.status === "rejected" ? (
<pre>{JSON.stringify(stats.reason, null, 2)}</pre>
) : errorStatus ? (
<pre>{JSON.stringify(errorStatus, null, 2)}</pre>
) : (
<CircularProgress isIndeterminate />
)}
</Box>
</CardBody>
</Card>
</SimpleGrid>
<br />
<Card>
<CardBody>
<Text as="h1" fontSize="3xl" textAlign="center">
/api/v1/stats/tree_manager
</Text>
{treeManager?.status === "fulfilled" ? (
<Box>
<Text as="h2" fontSize="2xl">
state_counts
<AdminArea>
<SimpleGrid columns={[1, 1, 1, 1, 1, 2]} gap={4}>
<Card>
<CardBody>
<Text as="h1" fontSize="3xl" textAlign="center">
/api/v1/tasks/availability
</Text>
<Box bg={dataBackgroundColor} borderRadius="xl" p="6" pt="4" pr="12">
<pre>{JSON.stringify(treeManager.value.state_counts, null, 2)}</pre>
</Box>
<TableContainer>
<br />
<Card variant="json">
<CardBody>
{tasksAvailability?.status === "fulfilled" ? (
<pre>{JSON.stringify(tasksAvailability.value, null, 2)}</pre>
) : tasksAvailability?.status === "rejected" ? (
<pre>{JSON.stringify(tasksAvailability.reason, null, 2)}</pre>
) : errorStatus ? (
<pre>{JSON.stringify(errorStatus, null, 2)}</pre>
) : (
<CircularProgress isIndeterminate />
)}
</CardBody>
</Card>
</CardBody>
</Card>
<Card>
<CardBody>
<Text as="h1" fontSize="3xl" textAlign="center">
/api/v1/stats/
</Text>
<Card variant="json">
<CardBody>
{stats?.status === "fulfilled" ? (
<pre>{JSON.stringify(stats.value, null, 2)}</pre>
) : stats?.status === "rejected" ? (
<pre>{JSON.stringify(stats.reason, null, 2)}</pre>
) : errorStatus ? (
<pre>{JSON.stringify(errorStatus, null, 2)}</pre>
) : (
<CircularProgress isIndeterminate />
)}
</CardBody>
</Card>
</CardBody>
</Card>
</SimpleGrid>
<br />
<Card>
<CardBody>
<Text as="h1" fontSize="3xl" textAlign="center">
/api/v1/stats/tree_manager
</Text>
{treeManager?.status === "fulfilled" ? (
<Box>
<Text as="h2" fontSize="2xl">
message_counts
state_counts
</Text>
<Table variant="simple">
<TableCaption>Tree Manager</TableCaption>
<Thead>
<Tr>
<Th>Message Tree ID</Th>
<Th>State</Th>
<Th>Depth</Th>
<Th>Oldest</Th>
<Th>Youngest</Th>
<Th>Count</Th>
<Th>Goal Tree Size</Th>
</Tr>
</Thead>
<Tbody>
{treeManager.value.message_counts.map(
({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => (
<Tr key={message_tree_id}>
<Td>{message_tree_id}</Td>
<Td>{state}</Td>
<Td>{depth}</Td>
<Td>{oldest}</Td>
<Td>{youngest}</Td>
<Td>{count}</Td>
<Td>{goal_tree_size}</Td>
</Tr>
)
)}
</Tbody>
</Table>
</TableContainer>
</Box>
) : treeManager?.status === "rejected" ? (
<pre>{JSON.stringify(treeManager.reason, null, 2)}</pre>
) : errorStatus ? (
<pre>{JSON.stringify(errorStatus, null, 2)}</pre>
) : (
<CircularProgress isIndeterminate />
)}
</CardBody>
</Card>
<Card variant="json">
<CardBody>
<pre>{JSON.stringify(treeManager.value.state_counts, null, 2)}</pre>
</CardBody>
</Card>
<TableContainer>
<br />
<Text as="h2" fontSize="2xl">
message_counts
</Text>
<Table variant="simple">
<TableCaption>Tree Manager</TableCaption>
<Thead>
<Tr>
<Th>Message Tree ID</Th>
<Th>State</Th>
<Th>Depth</Th>
<Th>Oldest</Th>
<Th>Youngest</Th>
<Th>Count</Th>
<Th>Goal Tree Size</Th>
</Tr>
</Thead>
<Tbody>
{treeManager.value.message_counts.map(
({ message_tree_id, state, depth, oldest, youngest, count, goal_tree_size }) => (
<Tr key={message_tree_id}>
<Td>{message_tree_id}</Td>
<Td>{state}</Td>
<Td>{depth}</Td>
<Td>{oldest}</Td>
<Td>{youngest}</Td>
<Td>{count}</Td>
<Td>{goal_tree_size}</Td>
</Tr>
)
)}
</Tbody>
</Table>
</TableContainer>
</Box>
) : treeManager?.status === "rejected" ? (
<pre>{JSON.stringify(treeManager.reason, null, 2)}</pre>
) : errorStatus ? (
<pre>{JSON.stringify(errorStatus, null, 2)}</pre>
) : (
<CircularProgress isIndeterminate />
)}
</CardBody>
</Card>
</AdminArea>
</>
);
};
+16
View File
@@ -0,0 +1,16 @@
import { withRole } from "src/lib/auth";
import { createApiClient } from "src/lib/oasst_client_factory";
export default withRole("admin", async (_, res, token) => {
const client = await createApiClient(token);
try {
const fullSettings = await client.fetch_full_settings();
return res.json(fullSettings);
} catch {
const publicSettings = await client.fetch_public_settings();
return res.json(publicSettings);
}
});
+1 -1
View File
@@ -41,7 +41,7 @@ const Dashboard = () => {
<>
<Head>
<title>{`${t("dashboard")} - ${t("common:title")}`}</title>
<meta name="description" content="Chat with Open Assistant and provide feedback." />
<meta name="description" content="Chat with Open Assistant and provide feedback." key="description" />
</Head>
<Flex direction="column" gap="10">
<WelcomeCard />
-1
View File
@@ -24,7 +24,6 @@ const Home = () => {
<>
<Head>
<title>{t("title")}</title>
<meta name="description" content={t("index:description")} />
</Head>
<Box as="main" className="oa-basic-theme">
<Hero />