Use PageHeaderContainer for all breadcrumbs

This commit is contained in:
David Corbitt
2023-08-07 11:16:54 -07:00
parent 6b304f8456
commit 1a838824ae
10 changed files with 167 additions and 119 deletions

View File

@@ -25,6 +25,7 @@ declare module "nextjs-routes" {
| StaticRoute<"/home">
| StaticRoute<"/">
| StaticRoute<"/sentry-example-page">
| StaticRoute<"/settings">
| StaticRoute<"/world-champs">
| StaticRoute<"/world-champs/signup">;

View File

@@ -12,7 +12,7 @@ import {
} from "@chakra-ui/react";
import Head from "next/head";
import Link from "next/link";
import { BsGithub, BsPersonCircle } from "react-icons/bs";
import { BsGearFill, BsGithub, BsPersonCircle } from "react-icons/bs";
import { RiDatabase2Line, RiFlaskLine } from "react-icons/ri";
import { signIn, useSession } from "next-auth/react";
import UserMenu from "./UserMenu";
@@ -76,6 +76,21 @@ const NavSidebar = () => {
</NavSidebarOption>
)}
</VStack>
<VStack w="full" alignItems="flex-start" spacing={0}>
<Text
pl={2}
pb={2}
fontSize="xs"
fontWeight="bold"
color="gray.500"
display={{ base: "none", md: "flex" }}
>
CONFIGURATION
</Text>
<NavSidebarOption activeHrefPattern="/settings">
<IconLink icon={BsGearFill} label="Project Settings" href="/settings" />
</NavSidebarOption>
</VStack>
{user && <UserMenu user={user} borderColor={"gray.200"} />}
<Divider />
<VStack spacing={0} align="center">

View File

@@ -0,0 +1,15 @@
import { Flex, type FlexProps } from "@chakra-ui/react";
const PageHeaderContainer = (props: FlexProps) => {
return <Flex
px={8}
py={2}
w="full"
direction={{ base: "column", sm: "row" }}
alignItems={{ base: "flex-start", sm: "center" }}
justifyContent="space-between"
{...props}
/>;
};
export default PageHeaderContainer;

View File

@@ -8,7 +8,6 @@ import {
PopoverTrigger,
PopoverContent,
Link,
useColorMode,
type StackProps,
} from "@chakra-ui/react";
import { type Session } from "next-auth";
@@ -17,7 +16,6 @@ import { BsBoxArrowRight, BsChevronRight, BsPersonCircle } from "react-icons/bs"
import NavSidebarOption from "./NavSidebarOption";
export default function UserMenu({ user, ...rest }: { user: Session } & StackProps) {
const { colorMode } = useColorMode();
const profileImage = user.user.image ? (
<Image src={user.user.image} alt="profile picture" boxSize={8} borderRadius="50%" />
@@ -28,17 +26,6 @@ export default function UserMenu({ user, ...rest }: { user: Session } & StackPro
return (
<>
<Popover placement="right">
<VStack w="full" alignItems="flex-start" spacing={0} {...rest}>
<Text
pl={2}
pb={2}
fontSize="xs"
fontWeight="bold"
color="gray.500"
display={{ base: "none", md: "flex" }}
>
ACCOUNT
</Text>
<PopoverTrigger>
<NavSidebarOption>
<HStack
@@ -46,6 +33,7 @@ export default function UserMenu({ user, ...rest }: { user: Session } & StackPro
py={2}
px={1}
spacing={3}
{...rest}
>
{profileImage}
<VStack spacing={0} align="start" flex={1} flexShrink={1}>
@@ -60,7 +48,6 @@ export default function UserMenu({ user, ...rest }: { user: Session } & StackPro
</HStack>
</NavSidebarOption>
</PopoverTrigger>
</VStack>
<PopoverContent _focusVisible={{ boxShadow: "unset", outline: "unset" }} maxW="200px">
<VStack align="stretch" spacing={0}>
{/* sign out */}

View File

@@ -18,6 +18,7 @@ import { api } from "~/utils/api";
import { useDataset, useHandledAsyncCallback } from "~/utils/hooks";
import DatasetEntriesTable from "~/components/datasets/DatasetEntriesTable";
import { DatasetHeaderButtons } from "~/components/datasets/DatasetHeaderButtons/DatasetHeaderButtons";
import PageHeaderContainer from "~/components/nav/PageHeaderContainer";
export default function Dataset() {
const router = useRouter();
@@ -55,14 +56,8 @@ export default function Dataset() {
return (
<AppShell title={dataset.data?.name}>
<VStack h="full">
<Flex
px={8}
py={2}
w="full"
direction={{ base: "column", sm: "row" }}
alignItems={{ base: "flex-start", sm: "center" }}
>
<Breadcrumb flex={1} mt={1}>
<PageHeaderContainer>
<Breadcrumb>
<BreadcrumbItem>
<Link href="/data">
<Flex alignItems="center" _hover={{ textDecoration: "underline" }}>
@@ -88,7 +83,7 @@ export default function Dataset() {
</BreadcrumbItem>
</Breadcrumb>
<DatasetHeaderButtons />
</Flex>
</PageHeaderContainer>
<Box w="full" overflowX="auto" flex={1} px={8} pt={8} pb={16}>
{datasetId && <DatasetEntriesTable />}
</Box>

View File

@@ -1,14 +1,12 @@
import {
SimpleGrid,
Icon,
VStack,
Breadcrumb,
BreadcrumbItem,
Flex,
Center,
Text,
Link,
HStack,
} from "@chakra-ui/react";
import AppShell from "~/components/nav/AppShell";
import { api } from "~/utils/api";
@@ -19,6 +17,7 @@ import {
DatasetCardSkeleton,
NewDatasetCard,
} from "~/components/datasets/DatasetCard";
import PageHeaderContainer from "~/components/nav/PageHeaderContainer";
export default function DatasetsPage() {
const datasets = api.datasets.list.useQuery();
@@ -50,17 +49,16 @@ export default function DatasetsPage() {
return (
<AppShell title="Data">
<VStack alignItems={"flex-start"} px={8} py={2}>
<HStack minH={8} align="center" pt={2}>
<Breadcrumb flex={1}>
<BreadcrumbItem>
<PageHeaderContainer>
<Breadcrumb>
<BreadcrumbItem minH={8}>
<Flex alignItems="center">
<Icon as={RiDatabase2Line} boxSize={4} mr={2} /> Datasets
</Flex>
</BreadcrumbItem>
</Breadcrumb>
</HStack>
<SimpleGrid w="full" columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing={8} py="4">
</PageHeaderContainer>
<SimpleGrid w="full" columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing={8} py={4} px={8}>
<NewDatasetCard />
{datasets.data && !datasets.isLoading ? (
datasets?.data?.map((dataset) => (
@@ -77,7 +75,6 @@ export default function DatasetsPage() {
</>
)}
</SimpleGrid>
</VStack>
</AppShell>
);
}

View File

@@ -23,6 +23,7 @@ import { useAppStore } from "~/state/store";
import { useSyncVariantEditor } from "~/state/sync";
import { ExperimentHeaderButtons } from "~/components/experiments/ExperimentHeaderButtons/ExperimentHeaderButtons";
import Head from "next/head";
import PageHeaderContainer from "~/components/nav/PageHeaderContainer";
// TODO: import less to fix deployment with server side props
// export const getServerSideProps = async (context: GetServerSidePropsContext<{ id: string }>) => {
@@ -104,15 +105,8 @@ export default function Experiment() {
)}
<AppShell title={experiment.data?.label}>
<VStack h="full">
<Flex
pl={8}
pr={4}
py={2}
w="full"
direction={{ base: "column", sm: "row" }}
alignItems={{ base: "flex-start", sm: "center" }}
>
<Breadcrumb flex={1}>
<PageHeaderContainer>
<Breadcrumb>
<BreadcrumbItem>
<Link href="/experiments">
<Flex alignItems="center" _hover={{ textDecoration: "underline" }}>
@@ -144,7 +138,7 @@ export default function Experiment() {
</BreadcrumbItem>
</Breadcrumb>
<ExperimentHeaderButtons />
</Flex>
</PageHeaderContainer>
<ExperimentSettingsDrawer />
<Box w="100%" overflowX="auto" flex={1}>
<OutputsTable experimentId={router.query.id as string | undefined} />

View File

@@ -1,14 +1,12 @@
import {
SimpleGrid,
Icon,
VStack,
Breadcrumb,
BreadcrumbItem,
Flex,
Center,
Text,
Link,
HStack,
} from "@chakra-ui/react";
import { RiFlaskLine } from "react-icons/ri";
import AppShell from "~/components/nav/AppShell";
@@ -19,6 +17,7 @@ import {
NewExperimentCard,
} from "~/components/experiments/ExperimentCard";
import { signIn, useSession } from "next-auth/react";
import PageHeaderContainer from "~/components/nav/PageHeaderContainer";
export default function ExperimentsPage() {
const experiments = api.experiments.list.useQuery();
@@ -50,17 +49,16 @@ export default function ExperimentsPage() {
return (
<AppShell title="Experiments">
<VStack alignItems={"flex-start"} px={8} py={2}>
<HStack minH={8} align="center" pt={2}>
<Breadcrumb flex={1}>
<BreadcrumbItem>
<PageHeaderContainer>
<Breadcrumb>
<BreadcrumbItem minH={8}>
<Flex alignItems="center">
<Icon as={RiFlaskLine} boxSize={4} mr={2} /> Experiments
</Flex>
</BreadcrumbItem>
</Breadcrumb>
</HStack>
<SimpleGrid w="full" columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing={8} py="4">
</PageHeaderContainer>
<SimpleGrid w="full" columns={{ base: 1, md: 2, lg: 3, xl: 4 }} spacing={8} py="4" px={8}>
<NewExperimentCard />
{experiments.data && !experiments.isLoading ? (
experiments?.data?.map((exp) => <ExperimentCard key={exp.id} exp={exp} />)
@@ -72,7 +70,6 @@ export default function ExperimentsPage() {
</>
)}
</SimpleGrid>
</VStack>
</AppShell>
);
}

View File

@@ -1,6 +1,7 @@
import { Breadcrumb, BreadcrumbItem, HStack, Input } from "@chakra-ui/react";
import { Breadcrumb, BreadcrumbItem, Input } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import AppShell from "~/components/nav/AppShell";
import PageHeaderContainer from "~/components/nav/PageHeaderContainer";
import { api } from "~/utils/api";
import { useHandledAsyncCallback, useSelectedOrg } from "~/utils/hooks";
@@ -25,13 +26,7 @@ export default function HomePage() {
}, [selectedOrg?.name]);
return (
<AppShell>
<HStack
px={4}
py={2}
w="full"
direction={{ base: "column", sm: "row" }}
alignItems={{ base: "flex-start", sm: "center" }}
>
<PageHeaderContainer>
<Breadcrumb flex={1}>
<BreadcrumbItem isCurrentPage>
<Input
@@ -50,7 +45,7 @@ export default function HomePage() {
/>
</BreadcrumbItem>
</Breadcrumb>
</HStack>
</PageHeaderContainer>
</AppShell>
);
}

View File

@@ -0,0 +1,52 @@
import { Breadcrumb, BreadcrumbItem, Input } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import AppShell from "~/components/nav/AppShell";
import PageHeaderContainer from "~/components/nav/PageHeaderContainer";
import { api } from "~/utils/api";
import { useHandledAsyncCallback, useSelectedOrg } from "~/utils/hooks";
export default function Settings() {
const utils = api.useContext();
const { data: selectedOrg } = useSelectedOrg();
const updateMutation = api.organizations.update.useMutation();
const [onSaveName] = useHandledAsyncCallback(async () => {
if (name && name !== selectedOrg?.name && selectedOrg?.id) {
await updateMutation.mutateAsync({
id: selectedOrg.id,
updates: { name },
});
await Promise.all([utils.organizations.get.invalidate({ id: selectedOrg.id })]);
}
}, [updateMutation, selectedOrg]);
const [name, setName] = useState(selectedOrg?.name);
useEffect(() => {
setName(selectedOrg?.name);
}, [selectedOrg?.name]);
return (
<AppShell>
<PageHeaderContainer>
<Breadcrumb>
<BreadcrumbItem isCurrentPage>
<Input
size="sm"
value={name}
onChange={(e) => setName(e.target.value)}
onBlur={onSaveName}
borderWidth={1}
borderColor="transparent"
fontSize={16}
px={0}
minW={{ base: 100, lg: 300 }}
flex={1}
_hover={{ borderColor: "gray.300" }}
_focus={{ borderColor: "blue.500", outline: "none" }}
/>
</BreadcrumbItem>
</Breadcrumb>
</PageHeaderContainer>
</AppShell>
);
}