basic table with no info

This commit is contained in:
Kyle Corbitt
2023-06-22 08:05:22 -07:00
parent 0f3c381e1d
commit 788911898b
10 changed files with 227 additions and 14 deletions

View File

@@ -5,9 +5,7 @@ const path = require("path");
const config = { const config = {
overrides: [ overrides: [
{ {
extends: [ extends: ["plugin:@typescript-eslint/recommended-requiring-type-checking"],
"plugin:@typescript-eslint/recommended-requiring-type-checking",
],
files: ["*.ts", "*.tsx"], files: ["*.ts", "*.tsx"],
parserOptions: { parserOptions: {
project: path.join(__dirname, "tsconfig.json"), project: path.join(__dirname, "tsconfig.json"),
@@ -29,6 +27,7 @@ const config = {
}, },
], ],
"@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }], "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
"@typescript-eslint/no-unsafe-member-access": "off",
}, },
}; };

View File

@@ -14,6 +14,7 @@
"@emotion/react": "^11.11.1", "@emotion/react": "^11.11.1",
"@emotion/server": "^11.11.0", "@emotion/server": "^11.11.0",
"@mantine/core": "^6.0.14", "@mantine/core": "^6.0.14",
"@mantine/dates": "^6.0.14",
"@mantine/form": "^6.0.14", "@mantine/form": "^6.0.14",
"@mantine/hooks": "^6.0.14", "@mantine/hooks": "^6.0.14",
"@mantine/next": "^6.0.14", "@mantine/next": "^6.0.14",
@@ -26,7 +27,9 @@
"@trpc/next": "^10.26.0", "@trpc/next": "^10.26.0",
"@trpc/react-query": "^10.26.0", "@trpc/react-query": "^10.26.0",
"@trpc/server": "^10.26.0", "@trpc/server": "^10.26.0",
"dayjs": "^1.11.8",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"mantine-react-table": "1.0.0-beta.13",
"next": "^13.4.2", "next": "^13.4.2",
"next-auth": "^4.22.1", "next-auth": "^4.22.1",
"react": "18.2.0", "react": "18.2.0",

99
pnpm-lock.yaml generated
View File

@@ -14,6 +14,9 @@ dependencies:
'@mantine/core': '@mantine/core':
specifier: ^6.0.14 specifier: ^6.0.14
version: 6.0.14(@emotion/react@11.11.1)(@mantine/hooks@6.0.14)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0) version: 6.0.14(@emotion/react@11.11.1)(@mantine/hooks@6.0.14)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0)
'@mantine/dates':
specifier: ^6.0.14
version: 6.0.14(@mantine/core@6.0.14)(@mantine/hooks@6.0.14)(dayjs@1.11.8)(react@18.2.0)
'@mantine/form': '@mantine/form':
specifier: ^6.0.14 specifier: ^6.0.14
version: 6.0.14(react@18.2.0) version: 6.0.14(react@18.2.0)
@@ -50,9 +53,15 @@ dependencies:
'@trpc/server': '@trpc/server':
specifier: ^10.26.0 specifier: ^10.26.0
version: 10.26.0 version: 10.26.0
dayjs:
specifier: ^1.11.8
version: 1.11.8
dotenv: dotenv:
specifier: ^16.3.1 specifier: ^16.3.1
version: 16.3.1 version: 16.3.1
mantine-react-table:
specifier: 1.0.0-beta.13
version: 1.0.0-beta.13(@emotion/react@11.11.1)(@mantine/core@6.0.14)(@mantine/dates@6.0.14)(@mantine/hooks@6.0.14)(@tabler/icons-react@2.22.0)(react-dom@18.2.0)(react@18.2.0)
next: next:
specifier: ^13.4.2 specifier: ^13.4.2
version: 13.4.2(react-dom@18.2.0)(react@18.2.0) version: 13.4.2(react-dom@18.2.0)(react@18.2.0)
@@ -591,6 +600,21 @@ packages:
- '@types/react' - '@types/react'
dev: false dev: false
/@mantine/dates@6.0.14(@mantine/core@6.0.14)(@mantine/hooks@6.0.14)(dayjs@1.11.8)(react@18.2.0):
resolution: {integrity: sha512-iQxZcqTpH/sHv1ZdCru3hFLlXQFA+qT/19a1EmtSJrspITZQJ8xYf8xSkkLyY6Wc6KviX2Lp0fSDE72mQvNbyg==}
peerDependencies:
'@mantine/core': 6.0.14
'@mantine/hooks': 6.0.14
dayjs: '>=1.0.0'
react: '>=16.8.0'
dependencies:
'@mantine/core': 6.0.14(@emotion/react@11.11.1)(@mantine/hooks@6.0.14)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0)
'@mantine/hooks': 6.0.14(react@18.2.0)
'@mantine/utils': 6.0.14(react@18.2.0)
dayjs: 1.11.8
react: 18.2.0
dev: false
/@mantine/form@6.0.14(react@18.2.0): /@mantine/form@6.0.14(react@18.2.0):
resolution: {integrity: sha512-2QlDN3PBMxHUxtoBy0ycc3InpATGje5sJXmw/Co9qiVtKUHe5pxcVl341CnA+MCI91uC2Ycucf20n/8GTLezrw==} resolution: {integrity: sha512-2QlDN3PBMxHUxtoBy0ycc3InpATGje5sJXmw/Co9qiVtKUHe5pxcVl341CnA+MCI91uC2Ycucf20n/8GTLezrw==}
peerDependencies: peerDependencies:
@@ -981,6 +1005,13 @@ packages:
resolution: {integrity: sha512-lOsGHqRPIKNARMWHHFkUUJH78C8ptQmUcDnumFBUI4YLRKFouKa7uAZL3ZfuH0HjDpOhsnWqUYZ7FhMCLcGpAQ==} resolution: {integrity: sha512-lOsGHqRPIKNARMWHHFkUUJH78C8ptQmUcDnumFBUI4YLRKFouKa7uAZL3ZfuH0HjDpOhsnWqUYZ7FhMCLcGpAQ==}
dev: false dev: false
/@tanstack/match-sorter-utils@8.8.4:
resolution: {integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==}
engines: {node: '>=12'}
dependencies:
remove-accents: 0.4.2
dev: false
/@tanstack/query-core@4.29.7: /@tanstack/query-core@4.29.7:
resolution: {integrity: sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==} resolution: {integrity: sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==}
dev: false dev: false
@@ -1003,6 +1034,36 @@ packages:
use-sync-external-store: 1.2.0(react@18.2.0) use-sync-external-store: 1.2.0(react@18.2.0)
dev: false dev: false
/@tanstack/react-table@8.9.2(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-Irvw4wqVF9hhuYzmNrlae4IKdlmgSyoRWnApSLebvYzqHoi5tEsYzBj6YPd0hX78aB/L+4w/jgK2eBQVpGfThQ==}
engines: {node: '>=12'}
peerDependencies:
react: '>=16'
react-dom: '>=16'
dependencies:
'@tanstack/table-core': 8.9.2
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/@tanstack/react-virtual@3.0.0-beta.54(react@18.2.0):
resolution: {integrity: sha512-D1mDMf4UPbrtHRZZriCly5bXTBMhylslm4dhcHqTtDJ6brQcgGmk8YD9JdWBGWfGSWPKoh2x1H3e7eh+hgPXtQ==}
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
dependencies:
'@tanstack/virtual-core': 3.0.0-beta.54
react: 18.2.0
dev: false
/@tanstack/table-core@8.9.2:
resolution: {integrity: sha512-ajc0OF+karBAdaSz7OK09rCoAHB1XI1+wEhu+tDNMPc+XcO+dTlXXN/Vc0a8vym4kElvEjXEDd9c8Zfgt4bekA==}
engines: {node: '>=12'}
dev: false
/@tanstack/virtual-core@3.0.0-beta.54:
resolution: {integrity: sha512-jtkwqdP2rY2iCCDVAFuaNBH3fiEi29aTn2RhtIoky8DTTiCdc48plpHHreLwmv1PICJ4AJUUESaq3xa8fZH8+g==}
dev: false
/@trpc/client@10.26.0(@trpc/server@10.26.0): /@trpc/client@10.26.0(@trpc/server@10.26.0):
resolution: {integrity: sha512-ojHxQFIE97rBEGPK8p1ijbzo0T1IdEBoJ9fFSgWWL9FMuEEA/DNQ9s0uuiOrDKhCCdTFT1unfRharoJhB2/O2w==} resolution: {integrity: sha512-ojHxQFIE97rBEGPK8p1ijbzo0T1IdEBoJ9fFSgWWL9FMuEEA/DNQ9s0uuiOrDKhCCdTFT1unfRharoJhB2/O2w==}
peerDependencies: peerDependencies:
@@ -1542,6 +1603,10 @@ packages:
resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==}
dev: true dev: true
/dayjs@1.11.8:
resolution: {integrity: sha512-LcgxzFoWMEPO7ggRv1Y2N31hUf2R0Vj7fuy/m+Bg1K8rr+KAs1AEy4y9jd5DXe8pbHgX+srkHNS7TH6Q6ZhYeQ==}
dev: false
/debug@3.2.7: /debug@3.2.7:
resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
peerDependencies: peerDependencies:
@@ -2379,6 +2444,11 @@ packages:
dependencies: dependencies:
function-bind: 1.1.1 function-bind: 1.1.1
/highlight-words@1.2.2:
resolution: {integrity: sha512-Mf4xfPXYm8Ay1wTibCrHpNWeR2nUMynMVFkXCi4mbl+TEgmNOe+I4hV7W3OCZcSvzGL6kupaqpfHOemliMTGxQ==}
engines: {node: '>= 16', npm: '>= 8'}
dev: false
/hoist-non-react-statics@3.3.2: /hoist-non-react-statics@3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
dependencies: dependencies:
@@ -2751,6 +2821,31 @@ packages:
dependencies: dependencies:
yallist: 4.0.0 yallist: 4.0.0
/mantine-react-table@1.0.0-beta.13(@emotion/react@11.11.1)(@mantine/core@6.0.14)(@mantine/dates@6.0.14)(@mantine/hooks@6.0.14)(@tabler/icons-react@2.22.0)(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-GOC536sjdsWgct9ErNjyWmn54PHxAt6PcvnGnUCeECF5MoyY2mNO3ukgD377dGL0b+e+kjCXCxY4W7MHV1/WqQ==}
engines: {node: '>=14'}
peerDependencies:
'@emotion/react': '>=11'
'@mantine/core': '>=6'
'@mantine/dates': '>=6'
'@mantine/hooks': '>=6'
'@tabler/icons-react': '>=2'
react: '>=17.0'
react-dom: '>=17.0'
dependencies:
'@emotion/react': 11.11.1(@types/react@18.2.6)(react@18.2.0)
'@mantine/core': 6.0.14(@emotion/react@11.11.1)(@mantine/hooks@6.0.14)(@types/react@18.2.6)(react-dom@18.2.0)(react@18.2.0)
'@mantine/dates': 6.0.14(@mantine/core@6.0.14)(@mantine/hooks@6.0.14)(dayjs@1.11.8)(react@18.2.0)
'@mantine/hooks': 6.0.14(react@18.2.0)
'@tabler/icons-react': 2.22.0(react@18.2.0)
'@tanstack/match-sorter-utils': 8.8.4
'@tanstack/react-table': 8.9.2(react-dom@18.2.0)(react@18.2.0)
'@tanstack/react-virtual': 3.0.0-beta.54(react@18.2.0)
highlight-words: 1.2.2
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
/merge-stream@2.0.0: /merge-stream@2.0.0:
resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
dev: true dev: true
@@ -3281,6 +3376,10 @@ packages:
functions-have-names: 1.2.3 functions-have-names: 1.2.3
dev: true dev: true
/remove-accents@0.4.2:
resolution: {integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==}
dev: false
/resolve-from@4.0.0: /resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'} engines: {node: '>=4'}

View File

@@ -0,0 +1,64 @@
import { MRT_ColumnDef, MantineReactTable } from "mantine-react-table";
import { useMemo } from "react";
import { RouterOutputs, api } from "~/utils/api";
type CellData = {
variant: NonNullable<RouterOutputs["promptVariants"]["list"]>[0];
scenario: NonNullable<RouterOutputs["scenarios"]["list"]>[0];
};
type TableRow = {
scenario: NonNullable<RouterOutputs["scenarios"]["list"]>[0];
} & Record<string, CellData>;
export default function OutputsTable({ experimentId }: { experimentId: string }) {
const experiment = api.experiments.get.useQuery({ id: experimentId });
const variants = api.promptVariants.list.useQuery({ experimentId: experimentId });
const scenarios = api.scenarios.list.useQuery({ experimentId: experimentId });
const columns = useMemo<MRT_ColumnDef<TableRow>[]>(
() => [
{
id: "scenario",
header: "Scenario",
Cell: ({ row }) => {
return <div>{JSON.stringify(row.original.scenario.variableValues)}</div>;
},
},
...(variants.data?.map(
(variant): MRT_ColumnDef<TableRow> => ({
id: variant.id,
header: variant.label,
Cell: ({ row }) => {
const cellData = row.original[variant.id];
return (
<div>
{row.original.scenario.id} | {variant.id}
</div>
);
},
})
) ?? []),
],
[variants.data]
);
const tableData = useMemo(
() =>
scenarios.data?.map((scenario) => {
return {
scenario,
// ...variants.data?.reduce(
// (acc, variant) => ({ ...acc, [variant.id]: { variant, scenario } }),
// {} as Record<string, CellData>
// ),
} as TableRow;
}) ?? [],
[variants.data, scenarios.data]
);
return <MantineReactTable columns={columns} data={tableData} enableFullScreenToggle={false} />;
// return <div>OutputsTable</div>;
}

View File

@@ -1,5 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { createStyles, Navbar, Group, Code, getStylesRef, rem } from "@mantine/core"; import { createStyles, Navbar, Group, Code, getStylesRef, rem, Box } from "@mantine/core";
import { import {
IconBellRinging, IconBellRinging,
IconFingerprint, IconFingerprint,
@@ -11,6 +11,7 @@ import {
IconSwitchHorizontal, IconSwitchHorizontal,
IconLogout, IconLogout,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import Head from "next/head";
// import { MantineLogo } from '@mantine/ds'; // import { MantineLogo } from '@mantine/ds';
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
@@ -78,7 +79,7 @@ const data = [
{ link: "", label: "Other Settings", icon: IconSettings }, { link: "", label: "Other Settings", icon: IconSettings },
]; ];
export default function AppNav({ children }: { children: React.ReactNode }) { export default function AppNav(props: { children: React.ReactNode; title?: string }) {
const { classes, cx } = useStyles(); const { classes, cx } = useStyles();
const [active, setActive] = useState("Billing"); const [active, setActive] = useState("Billing");
@@ -99,7 +100,10 @@ export default function AppNav({ children }: { children: React.ReactNode }) {
return ( return (
<Group h="100vh"> <Group h="100vh">
<Navbar height="100%" width={{ sm: 300 }} p="md"> <Head>
<title>{props.title && `${props.title} | `}Prompt Bench</title>
</Head>
<Navbar height="100%" width={{ sm: 250 }} p="md">
<Navbar.Section grow> <Navbar.Section grow>
<Group className={classes.header} position="apart"> <Group className={classes.header} position="apart">
{/* <MantineLogo size={28} /> */} {/* <MantineLogo size={28} /> */}
@@ -120,7 +124,7 @@ export default function AppNav({ children }: { children: React.ReactNode }) {
</a> </a>
</Navbar.Section> </Navbar.Section>
</Navbar> </Navbar>
{children} <Box sx={{ flex: 1 }}>{props.children}</Box>
</Group> </Group>
); );
} }

View File

@@ -1,9 +1,27 @@
import { Center } from "@mantine/core";
import { useRouter } from "next/router";
import OutputsTable from "~/components/OutputsTable";
import AppNav from "~/components/nav/AppNav"; import AppNav from "~/components/nav/AppNav";
import { api } from "~/utils/api";
export default function Experiment() { export default function Experiment() {
const router = useRouter();
const experiment = api.experiments.get.useQuery({ id: router.query.id as string });
if (!experiment.data) {
return ( return (
<AppNav> <AppNav title="Experiment not found">
<div>test content</div> <Center>
<div>Experiment not found 😕</div>
</Center>
</AppNav>
);
}
return (
<AppNav title={experiment.data.label}>
<OutputsTable experimentId={router.query.id as string} />
</AppNav> </AppNav>
); );
} }

View File

@@ -1,5 +1,7 @@
import { promptVariantsRouter } from "~/server/api/routers/promptVariants.router"; import { promptVariantsRouter } from "~/server/api/routers/promptVariants.router";
import { createTRPCRouter } from "~/server/api/trpc"; import { createTRPCRouter } from "~/server/api/trpc";
import { experimentsRouter } from "./routers/experiments.router";
import { scenariosRouter } from "./routers/scenarios.router";
/** /**
* This is the primary router for your server. * This is the primary router for your server.
@@ -8,6 +10,8 @@ import { createTRPCRouter } from "~/server/api/trpc";
*/ */
export const appRouter = createTRPCRouter({ export const appRouter = createTRPCRouter({
promptVariants: promptVariantsRouter, promptVariants: promptVariantsRouter,
experiments: experimentsRouter,
scenarios: scenariosRouter,
}); });
// export type definition of API // export type definition of API

View File

@@ -0,0 +1,13 @@
import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db";
export const experimentsRouter = createTRPCRouter({
get: publicProcedure.input(z.object({ id: z.string() })).query(async ({ input }) => {
return await prisma.experiment.findFirst({
where: {
id: input.id,
},
});
}),
});

View File

@@ -3,15 +3,11 @@ import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/
import { prisma } from "~/server/db"; import { prisma } from "~/server/db";
export const promptVariantsRouter = createTRPCRouter({ export const promptVariantsRouter = createTRPCRouter({
getAll: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => { list: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => {
return await prisma.promptVariant.findMany({ return await prisma.promptVariant.findMany({
where: { where: {
experimentId: input.experimentId, experimentId: input.experimentId,
}, },
}); });
}), }),
getSecretMessage: protectedProcedure.query(() => {
return "you can now see this secret message!";
}),
}); });

View File

@@ -0,0 +1,13 @@
import { z } from "zod";
import { createTRPCRouter, publicProcedure, protectedProcedure } from "~/server/api/trpc";
import { prisma } from "~/server/db";
export const scenariosRouter = createTRPCRouter({
list: publicProcedure.input(z.object({ experimentId: z.string() })).query(async ({ input }) => {
return await prisma.testScenario.findMany({
where: {
experimentId: input.experimentId,
},
});
}),
});