more visual tweaks
This commit is contained in:
@@ -17,7 +17,8 @@
|
||||
"lint": "next lint",
|
||||
"start": "next start",
|
||||
"codegen": "tsx src/codegen/export-openai-types.ts",
|
||||
"seed": "tsx prisma/seed.ts"
|
||||
"seed": "tsx prisma/seed.ts",
|
||||
"check": "concurrently 'pnpm lint' 'pnpm tsc' 'pnpm prettier . --check'"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/preset-typescript": "^7.22.5",
|
||||
@@ -27,6 +28,7 @@
|
||||
"@emotion/react": "^11.11.1",
|
||||
"@emotion/server": "^11.11.0",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fontsource/inconsolata": "^5.0.5",
|
||||
"@monaco-editor/loader": "^1.3.3",
|
||||
"@next-auth/prisma-adapter": "^1.0.5",
|
||||
"@prisma/client": "^4.14.0",
|
||||
|
||||
7
pnpm-lock.yaml
generated
7
pnpm-lock.yaml
generated
@@ -26,6 +26,9 @@ dependencies:
|
||||
'@emotion/styled':
|
||||
specifier: ^11.11.0
|
||||
version: 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.6)(react@18.2.0)
|
||||
'@fontsource/inconsolata':
|
||||
specifier: ^5.0.5
|
||||
version: 5.0.5
|
||||
'@monaco-editor/loader':
|
||||
specifier: ^1.3.3
|
||||
version: 1.3.3(monaco-editor@0.40.0)
|
||||
@@ -2261,6 +2264,10 @@ packages:
|
||||
'@floating-ui/core': 1.3.1
|
||||
dev: false
|
||||
|
||||
/@fontsource/inconsolata@5.0.5:
|
||||
resolution: {integrity: sha512-uU9t2j/hq4UweFXTjo+geLPFqhTucDdeei/a4BEHdtFPwJIfXLXmzlHeDrjOatHYGbRlJlydS4Ipr16A4O/e5A==}
|
||||
dev: false
|
||||
|
||||
/@graphile/logger@0.2.0:
|
||||
resolution: {integrity: sha512-jjcWBokl9eb1gVJ85QmoaQ73CQ52xAaOCF29ukRbYNl6lY+ts0ErTaDYOBlejcbUs2OpaiqYLO5uDhyLFzWw4w==}
|
||||
dev: false
|
||||
|
||||
@@ -1,15 +1,4 @@
|
||||
import {
|
||||
Card,
|
||||
CardBody,
|
||||
HStack,
|
||||
Icon,
|
||||
VStack,
|
||||
Text,
|
||||
CardHeader,
|
||||
Divider,
|
||||
Spinner,
|
||||
AspectRatio,
|
||||
} from "@chakra-ui/react";
|
||||
import { HStack, Icon, VStack, Text, Divider, Spinner, AspectRatio } from "@chakra-ui/react";
|
||||
import { RiFlaskLine } from "react-icons/ri";
|
||||
import { formatTimePast } from "~/utils/dayjs";
|
||||
import Link from "next/link";
|
||||
@@ -30,22 +19,24 @@ type ExperimentData = {
|
||||
|
||||
export const ExperimentCard = ({ exp }: { exp: ExperimentData }) => {
|
||||
return (
|
||||
<Card
|
||||
as={Link}
|
||||
bg="gray.50"
|
||||
_hover={{ bg: "gray.100" }}
|
||||
transition="background 0.2s"
|
||||
cursor="pointer"
|
||||
href={{ pathname: "/experiments/[id]", query: { id: exp.id } }}
|
||||
>
|
||||
<CardHeader>
|
||||
<AspectRatio ratio={1.2} w="full">
|
||||
<VStack
|
||||
as={Link}
|
||||
href={{ pathname: "/experiments/[id]", query: { id: exp.id } }}
|
||||
bg="gray.50"
|
||||
_hover={{ bg: "gray.100" }}
|
||||
transition="background 0.2s"
|
||||
cursor="pointer"
|
||||
borderColor="gray.200"
|
||||
borderWidth={1}
|
||||
p={4}
|
||||
justify="space-between"
|
||||
>
|
||||
<HStack w="full" color="gray.700" justify="center">
|
||||
<Icon as={RiFlaskLine} boxSize={4} />
|
||||
<Text fontWeight="bold">{exp.label}</Text>
|
||||
</HStack>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<HStack w="full" mb={8} spacing={4}>
|
||||
<HStack h="full" spacing={4} flex={1} align="center">
|
||||
<CountLabel label="Variants" count={exp.promptVariantCount} />
|
||||
<Divider h={12} orientation="vertical" />
|
||||
<CountLabel label="Scenarios" count={exp.testScenarioCount} />
|
||||
@@ -55,8 +46,8 @@ export const ExperimentCard = ({ exp }: { exp: ExperimentData }) => {
|
||||
<Divider h={4} orientation="vertical" />
|
||||
<Text flex={1}>Updated {formatTimePast(exp.updatedAt)}</Text>
|
||||
</HStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</VStack>
|
||||
</AspectRatio>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -75,7 +66,6 @@ const CountLabel = ({ label, count }: { label: string; count: number }) => {
|
||||
|
||||
export const NewExperimentCard = () => {
|
||||
const router = useRouter();
|
||||
const utils = api.useContext();
|
||||
const createMutation = api.experiments.create.useMutation();
|
||||
const [createExperiment, isLoading] = useHandledAsyncCallback(async () => {
|
||||
const newExperiment = await createMutation.mutateAsync({ label: "New Experiment" });
|
||||
@@ -83,15 +73,23 @@ export const NewExperimentCard = () => {
|
||||
}, [createMutation, router]);
|
||||
|
||||
return (
|
||||
<Card _hover={{ cursor: "pointer", bgColor: "gray.50" }} onClick={createExperiment}>
|
||||
<AspectRatio ratio={1} w="full">
|
||||
<VStack align="center" justify="center" h="100%" spacing={6}>
|
||||
<Icon as={isLoading ? Spinner : BsPlusSquare} boxSize={8} />
|
||||
<Text display={{ base: "none", md: "block" }} ml={2}>
|
||||
New Experiment
|
||||
</Text>
|
||||
</VStack>
|
||||
</AspectRatio>
|
||||
</Card>
|
||||
<AspectRatio ratio={1.2} w="full">
|
||||
<VStack
|
||||
align="center"
|
||||
justify="center"
|
||||
_hover={{ cursor: "pointer", bg: "gray.50" }}
|
||||
transition="background 0.2s"
|
||||
cursor="pointer"
|
||||
borderColor="gray.200"
|
||||
borderWidth={1}
|
||||
p={4}
|
||||
onClick={createExperiment}
|
||||
>
|
||||
<Icon as={isLoading ? Spinner : BsPlusSquare} boxSize={8} />
|
||||
<Text display={{ base: "none", md: "block" }} ml={2}>
|
||||
New Experiment
|
||||
</Text>
|
||||
</VStack>
|
||||
</AspectRatio>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,24 +1,22 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import {
|
||||
Heading,
|
||||
VStack,
|
||||
Icon,
|
||||
HStack,
|
||||
Image,
|
||||
Grid,
|
||||
GridItem,
|
||||
Divider,
|
||||
Text,
|
||||
Box,
|
||||
type BoxProps,
|
||||
type LinkProps,
|
||||
Link,
|
||||
Flex,
|
||||
} from "@chakra-ui/react";
|
||||
import Head from "next/head";
|
||||
import { BsGithub, BsPersonCircle } from "react-icons/bs";
|
||||
import { useRouter } from "next/router";
|
||||
import { type IconType } from "react-icons";
|
||||
import { RiFlaskLine } from "react-icons/ri";
|
||||
import { useState, useEffect } from "react";
|
||||
import { signIn, useSession } from "next-auth/react";
|
||||
import UserMenu from "./UserMenu";
|
||||
|
||||
@@ -28,40 +26,48 @@ const IconLink = ({ icon, label, href, target, color, ...props }: IconLinkProps)
|
||||
const router = useRouter();
|
||||
const isActive = href && router.pathname.startsWith(href);
|
||||
return (
|
||||
<Box
|
||||
<HStack
|
||||
w="full"
|
||||
p={4}
|
||||
color={color}
|
||||
as={Link}
|
||||
href={href}
|
||||
target={target}
|
||||
w="full"
|
||||
bgColor={isActive ? "gray.300" : "transparent"}
|
||||
bgColor={isActive ? "gray.200" : "transparent"}
|
||||
_hover={{ bgColor: "gray.200", textDecoration: "none" }}
|
||||
py={4}
|
||||
justifyContent="start"
|
||||
cursor="pointer"
|
||||
{...props}
|
||||
>
|
||||
<HStack w="full" px={4} color={color}>
|
||||
<Icon as={icon} boxSize={6} mr={2} />
|
||||
<Text fontWeight="bold">{label}</Text>
|
||||
</HStack>
|
||||
</Box>
|
||||
<Icon as={icon} boxSize={6} mr={2} />
|
||||
<Text fontWeight="bold" fontSize="sm">
|
||||
{label}
|
||||
</Text>
|
||||
</HStack>
|
||||
);
|
||||
};
|
||||
|
||||
const Divider = () => <Box h="1px" bgColor="gray.200" />;
|
||||
|
||||
const NavSidebar = () => {
|
||||
const user = useSession().data;
|
||||
|
||||
return (
|
||||
<VStack align="stretch" bgColor="gray.100" py={2} pb={0} height="100%">
|
||||
<Link href="/" w="full" _hover={{ textDecoration: "none" }}>
|
||||
<HStack spacing={0} pl="3">
|
||||
<Image src="/logo.svg" alt="" w={8} h={8} />
|
||||
<Heading size="md" p={2} pl={{ base: 16, md: 2 }}>
|
||||
OpenPipe
|
||||
</Heading>
|
||||
</HStack>
|
||||
</Link>
|
||||
<Divider />
|
||||
<VStack
|
||||
align="stretch"
|
||||
bgColor="gray.100"
|
||||
py={2}
|
||||
pb={0}
|
||||
height="100%"
|
||||
w={{ base: "56px", md: "200px" }}
|
||||
overflow="hidden"
|
||||
>
|
||||
<HStack as={Link} href="/" _hover={{ textDecoration: "none" }} spacing={0} px={4} py={2}>
|
||||
<Image src="/logo.svg" alt="" boxSize={6} mr={4} />
|
||||
<Heading size="md" fontFamily="inconsolata, monospace">
|
||||
OpenPipe
|
||||
</Heading>
|
||||
</HStack>
|
||||
<VStack spacing={0} align="flex-start" overflowY="auto" overflowX="hidden" flex={1}>
|
||||
{user != null && (
|
||||
<>
|
||||
@@ -115,22 +121,14 @@ export default function AppShell(props: { children: React.ReactNode; title?: str
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Grid
|
||||
h={vh}
|
||||
w="100vw"
|
||||
templateColumns={{ base: "56px minmax(0, 1fr)", md: "220px minmax(0, 1fr)" }}
|
||||
templateRows="1fr"
|
||||
templateAreas={'"sidebar main"'}
|
||||
>
|
||||
<Flex h={vh} w="100vw">
|
||||
<Head>
|
||||
<title>{props.title ? `${props.title} | OpenPipe` : "OpenPipe"}</title>
|
||||
</Head>
|
||||
<GridItem area="sidebar" overflow="hidden">
|
||||
<NavSidebar />
|
||||
</GridItem>
|
||||
<GridItem area="main" overflowY="auto">
|
||||
<NavSidebar />
|
||||
<Box h="100%" flex={1} overflowY="auto">
|
||||
{props.children}
|
||||
</GridItem>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,13 +15,7 @@ import { BsBoxArrowRight, BsChevronRight, BsPersonCircle } from "react-icons/bs"
|
||||
|
||||
export default function UserMenu({ user }: { user: Session }) {
|
||||
const profileImage = user.user.image ? (
|
||||
<Image
|
||||
src={user.user.image}
|
||||
alt="profile picture"
|
||||
boxSize={8}
|
||||
borderRadius="50%"
|
||||
// mr={{ base: 2, md: 0 }}
|
||||
/>
|
||||
<Image src={user.user.image} alt="profile picture" boxSize={8} borderRadius="50%" />
|
||||
) : (
|
||||
<Icon as={BsPersonCircle} boxSize={6} />
|
||||
);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import {
|
||||
SimpleGrid,
|
||||
HStack,
|
||||
Icon,
|
||||
VStack,
|
||||
Breadcrumb,
|
||||
@@ -9,6 +8,7 @@ import {
|
||||
Center,
|
||||
Text,
|
||||
Link,
|
||||
HStack,
|
||||
} from "@chakra-ui/react";
|
||||
import { RiFlaskLine } from "react-icons/ri";
|
||||
import AppShell from "~/components/nav/AppShell";
|
||||
@@ -43,8 +43,8 @@ export default function ExperimentsPage() {
|
||||
|
||||
return (
|
||||
<AppShell title="Experiments">
|
||||
<VStack alignItems={"flex-start"} m={4} mt={1}>
|
||||
<HStack w="full" mb={4}>
|
||||
<VStack alignItems={"flex-start"} px={4} py={2}>
|
||||
<HStack minH={8} align="center">
|
||||
<Breadcrumb flex={1}>
|
||||
<BreadcrumbItem>
|
||||
<Flex alignItems="center">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { extendTheme } from "@chakra-ui/react";
|
||||
import "@fontsource/inconsolata";
|
||||
|
||||
const systemFont =
|
||||
'ui-sans-serif, -apple-system, "system-ui", "Segoe UI", Helvetica, "Apple Color Emoji", Arial, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol"';
|
||||
|
||||
Reference in New Issue
Block a user