Add links to docs, remove beta block from Dashboard and Request Logs (#208)

* Remove mission text

* Change wording

* Add link to Read the Docs

* Add links to docs in empty log tables

* Remove beta block from Dashboard and Request Logs

* Make ActionButton onClick optional
This commit is contained in:
arcticfly
2023-08-31 17:17:20 -07:00
committed by GitHub
parent 96a589e401
commit 5b8113d8e7
13 changed files with 160 additions and 99 deletions

View File

@@ -13,19 +13,17 @@ import {
Link, Link,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import { BsStars } from "react-icons/bs"; import { BsStars } from "react-icons/bs";
import { useRouter } from "next/router";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
export const BetaModal = () => { export const BetaModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) => {
const router = useRouter();
const session = useSession(); const session = useSession();
const email = session.data?.user.email ?? ""; const email = session.data?.user.email ?? "";
return ( return (
<Modal <Modal
isOpen isOpen={isOpen}
onClose={router.back} onClose={onClose}
closeOnOverlayClick={false} closeOnOverlayClick={false}
size={{ base: "xl", md: "2xl" }} size={{ base: "xl", md: "2xl" }}
> >
@@ -56,7 +54,7 @@ export const BetaModal = () => {
> >
Join Waitlist Join Waitlist
</Button> </Button>
<Button colorScheme="blue" onClick={router.back}> <Button colorScheme="blue" onClick={onClose}>
Done Done
</Button> </Button>
</HStack> </HStack>

View File

@@ -1,26 +0,0 @@
import { VStack, HStack, type StackProps, Text, Divider } from "@chakra-ui/react";
import Link, { type LinkProps } from "next/link";
const StatsCard = ({
title,
href,
children,
...rest
}: { title: string; href: string } & StackProps & LinkProps) => {
return (
<VStack flex={1} borderWidth={1} padding={4} borderRadius={4} borderColor="gray.300" {...rest}>
<HStack w="full" justifyContent="space-between">
<Text fontSize="md" fontWeight="bold">
{title}
</Text>
<Link href={href}>
<Text color="blue">View all</Text>
</Link>
</HStack>
<Divider />
{children}
</VStack>
);
};
export default StatsCard;

View File

@@ -2,11 +2,12 @@ import { Card, CardHeader, Heading, Table, Tbody, HStack, Button, Text } from "@
import { useState } from "react"; import { useState } from "react";
import Link from "next/link"; import Link from "next/link";
import { useLoggedCalls } from "~/utils/hooks"; import { useLoggedCalls } from "~/utils/hooks";
import { TableHeader, TableRow } from "../requestLogs/TableRow"; import { EmptyTableRow, TableHeader, TableRow } from "../requestLogs/TableRow";
export default function LoggedCallsTable() { export default function LoggedCallsTable() {
const { data: loggedCalls } = useLoggedCalls(false);
const [expandedRow, setExpandedRow] = useState<string | null>(null); const [expandedRow, setExpandedRow] = useState<string | null>(null);
const { data: loggedCalls } = useLoggedCalls();
return ( return (
<Card width="100%" overflow="hidden"> <Card width="100%" overflow="hidden">
@@ -23,22 +24,26 @@ export default function LoggedCallsTable() {
<Table> <Table>
<TableHeader /> <TableHeader />
<Tbody> <Tbody>
{loggedCalls?.calls.map((loggedCall) => { {loggedCalls?.calls.length ? (
return ( loggedCalls?.calls.map((loggedCall) => {
<TableRow return (
key={loggedCall.id} <TableRow
loggedCall={loggedCall} key={loggedCall.id}
isExpanded={loggedCall.id === expandedRow} loggedCall={loggedCall}
onToggle={() => { isExpanded={loggedCall.id === expandedRow}
if (loggedCall.id === expandedRow) { onToggle={() => {
setExpandedRow(null); if (loggedCall.id === expandedRow) {
} else { setExpandedRow(null);
setExpandedRow(loggedCall.id); } else {
} setExpandedRow(loggedCall.id);
}} }
/> }}
); />
})} );
})
) : (
<EmptyTableRow filtersApplied={false} />
)}
</Tbody> </Tbody>
</Table> </Table>
</Card> </Card>

View File

@@ -13,15 +13,18 @@ import {
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import Head from "next/head"; import Head from "next/head";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router";
import { BsGearFill, BsGithub, BsPersonCircle } from "react-icons/bs"; import { BsGearFill, BsGithub, BsPersonCircle } from "react-icons/bs";
import { IoStatsChartOutline } from "react-icons/io5"; import { IoStatsChartOutline } from "react-icons/io5";
import { RiHome3Line, RiFlaskLine } from "react-icons/ri"; import { RiHome3Line, RiFlaskLine } from "react-icons/ri";
import { AiOutlineThunderbolt } from "react-icons/ai"; import { AiOutlineThunderbolt } from "react-icons/ai";
import { FaReadme } from "react-icons/fa";
import { signIn, useSession } from "next-auth/react"; import { signIn, useSession } from "next-auth/react";
import ProjectMenu from "./ProjectMenu"; import ProjectMenu from "./ProjectMenu";
import NavSidebarOption from "./NavSidebarOption"; import NavSidebarOption from "./NavSidebarOption";
import IconLink from "./IconLink"; import IconLink from "./IconLink";
import { BetaModal } from "./BetaModal"; import { BetaModal } from "../BetaModal";
import { useAppStore } from "~/state/store"; import { useAppStore } from "~/state/store";
const Divider = () => <Box h="1px" bgColor="gray.300" w="full" />; const Divider = () => <Box h="1px" bgColor="gray.300" w="full" />;
@@ -73,8 +76,8 @@ const NavSidebar = () => {
<ProjectMenu /> <ProjectMenu />
<Divider /> <Divider />
<IconLink icon={RiHome3Line} label="Dashboard" href="/dashboard" beta /> <IconLink icon={RiHome3Line} label="Dashboard" href="/dashboard" />
<IconLink icon={IoStatsChartOutline} label="Request Logs" href="/request-logs" beta /> <IconLink icon={IoStatsChartOutline} label="Request Logs" href="/request-logs" />
<IconLink icon={AiOutlineThunderbolt} label="Fine Tunes" href="/fine-tunes" beta /> <IconLink icon={AiOutlineThunderbolt} label="Fine Tunes" href="/fine-tunes" beta />
<IconLink icon={RiFlaskLine} label="Experiments" href="/experiments" /> <IconLink icon={RiFlaskLine} label="Experiments" href="/experiments" />
<VStack w="full" alignItems="flex-start" spacing={0} pt={8}> <VStack w="full" alignItems="flex-start" spacing={0} pt={8}>
@@ -111,7 +114,22 @@ const NavSidebar = () => {
</NavSidebarOption> </NavSidebarOption>
)} )}
</VStack> </VStack>
<HStack
w="full"
px={{ base: 2, md: 4 }}
py={{ base: 1, md: 2 }}
as={ChakraLink}
justifyContent="start"
href="https://docs.openpipe.ai"
target="_blank"
color="gray.500"
spacing={1}
>
<Icon as={FaReadme} boxSize={4} mr={2} />
<Text fontWeight="bold" fontSize="sm">
Read the Docs
</Text>
</HStack>
<Divider /> <Divider />
<VStack spacing={0} align="center"> <VStack spacing={0} align="center">
<ChakraLink <ChakraLink
@@ -140,6 +158,7 @@ export default function AppShell({
requireBeta?: boolean; requireBeta?: boolean;
}) { }) {
const [vh, setVh] = useState("100vh"); // Default height to prevent flicker on initial render const [vh, setVh] = useState("100vh"); // Default height to prevent flicker on initial render
const router = useRouter();
useEffect(() => { useEffect(() => {
const setHeight = () => { const setHeight = () => {
@@ -181,7 +200,7 @@ export default function AppShell({
{children} {children}
</Box> </Box>
</Flex> </Flex>
{requireBeta && flagsLoaded && !flags.betaAccess && <BetaModal />} <BetaModal isOpen={!!requireBeta && flagsLoaded && !flags.betaAccess} onClose={router.back} />
</> </>
); );
} }

View File

@@ -1,29 +1,50 @@
import { useState } from "react";
import { Button, HStack, type ButtonProps, Icon, Text } from "@chakra-ui/react"; import { Button, HStack, type ButtonProps, Icon, Text } from "@chakra-ui/react";
import { type IconType } from "react-icons"; import { type IconType } from "react-icons";
import { useAppStore } from "~/state/store";
import { BetaModal } from "../BetaModal";
const ActionButton = ({ const ActionButton = ({
icon, icon,
label, label,
requireBeta = false,
onClick,
...buttonProps ...buttonProps
}: { icon: IconType; label: string } & ButtonProps) => { }: {
icon: IconType;
label: string;
requireBeta?: boolean;
onClick?: () => void;
} & ButtonProps) => {
const flags = useAppStore((s) => s.featureFlags.featureFlags);
const flagsLoaded = useAppStore((s) => s.featureFlags.flagsLoaded);
const [betaModalOpen, setBetaModalOpen] = useState(false);
const isBetaBlocked = requireBeta && flagsLoaded && !flags.betaAccess;
return ( return (
<Button <>
colorScheme="blue" <Button
color="black" colorScheme="blue"
bgColor="white" color="black"
borderColor="gray.300" bgColor="white"
borderRadius={4} borderColor="gray.300"
variant="outline" borderRadius={4}
size="sm" variant="outline"
fontSize="sm" size="sm"
fontWeight="normal" fontSize="sm"
{...buttonProps} fontWeight="normal"
> onClick={isBetaBlocked ? () => setBetaModalOpen(true) : onClick}
<HStack spacing={1}> {...buttonProps}
{icon && <Icon as={icon} />} >
<Text display={{ base: "none", md: "flex" }}>{label}</Text> <HStack spacing={1}>
</HStack> {icon && <Icon as={icon} color={requireBeta ? "orange.400" : undefined} />}
</Button> <Text display={{ base: "none", md: "flex" }}>{label}</Text>
</HStack>
</Button>
<BetaModal isOpen={betaModalOpen} onClose={() => setBetaModalOpen(false)} />
</>
); );
}; };

View File

@@ -47,6 +47,7 @@ const ExportButton = () => {
label="Export" label="Export"
icon={BiExport} icon={BiExport}
isDisabled={selectedLogIds.size === 0} isDisabled={selectedLogIds.size === 0}
requireBeta
/> />
<ExportLogsModal disclosure={disclosure} /> <ExportLogsModal disclosure={disclosure} />
</> </>

View File

@@ -41,6 +41,7 @@ const FineTuneButton = () => {
label="Fine Tune" label="Fine Tune"
icon={AiTwotoneThunderbolt} icon={AiTwotoneThunderbolt}
isDisabled={selectedLogIds.size === 0} isDisabled={selectedLogIds.size === 0}
requireBeta
/> />
<FineTuneModal disclosure={disclosure} /> <FineTuneModal disclosure={disclosure} />
</> </>

View File

@@ -1,7 +1,7 @@
import { Card, Table, Tbody } from "@chakra-ui/react"; import { Card, Table, Tbody } from "@chakra-ui/react";
import { useState } from "react"; import { useState } from "react";
import { useLoggedCalls } from "~/utils/hooks"; import { useLoggedCalls } from "~/utils/hooks";
import { TableHeader, TableRow } from "./TableRow"; import { TableHeader, TableRow, EmptyTableRow } from "./TableRow";
export default function LoggedCallsTable() { export default function LoggedCallsTable() {
const [expandedRow, setExpandedRow] = useState<string | null>(null); const [expandedRow, setExpandedRow] = useState<string | null>(null);
@@ -12,23 +12,27 @@ export default function LoggedCallsTable() {
<Table> <Table>
<TableHeader showOptions /> <TableHeader showOptions />
<Tbody> <Tbody>
{loggedCalls?.calls?.map((loggedCall) => { {loggedCalls?.calls.length ? (
return ( loggedCalls?.calls?.map((loggedCall) => {
<TableRow return (
key={loggedCall.id} <TableRow
loggedCall={loggedCall} key={loggedCall.id}
isExpanded={loggedCall.id === expandedRow} loggedCall={loggedCall}
onToggle={() => { isExpanded={loggedCall.id === expandedRow}
if (loggedCall.id === expandedRow) { onToggle={() => {
setExpandedRow(null); if (loggedCall.id === expandedRow) {
} else { setExpandedRow(null);
setExpandedRow(loggedCall.id); } else {
} setExpandedRow(loggedCall.id);
}} }
showOptions }}
/> showOptions
); />
})} );
})
) : (
<EmptyTableRow />
)}
</Tbody> </Tbody>
</Table> </Table>
</Card> </Card>

View File

@@ -13,6 +13,7 @@ import {
ButtonGroup, ButtonGroup,
Text, Text,
Checkbox, Checkbox,
Link as ChakraLink,
} from "@chakra-ui/react"; } from "@chakra-ui/react";
import Link from "next/link"; import Link from "next/link";
@@ -198,3 +199,41 @@ export const TableRow = ({
</> </>
); );
}; };
export const EmptyTableRow = ({ filtersApplied = true }: { filtersApplied?: boolean }) => {
const visibleColumns = useAppStore((s) => s.columnVisibility.visibleColumns);
const filters = useAppStore((state) => state.logFilters.filters);
const { isLoading } = useLoggedCalls();
if (isLoading) return null;
if (filters.length && filtersApplied) {
return (
<Tr>
<Td w="full" colSpan={visibleColumns.size + 1}>
<Text color="gray.500" textAlign="center" w="full" p={4}>
No matching request logs found. Try removing some filters.
</Text>
</Td>
</Tr>
);
}
return (
<Tr>
<Td w="full" colSpan={visibleColumns.size + 1}>
<Text color="gray.500" textAlign="center" w="full" p={4}>
This project has no request logs. Learn how to add request logs to your project in our{" "}
<ChakraLink
href="https://docs.openpipe.ai/getting-started/quick-start"
target="_blank"
color="blue.600"
>
Quick Start
</ChakraLink>{" "}
guide.
</Text>
</Td>
</Tr>
);
};

View File

@@ -33,7 +33,7 @@ export default function Dashboard() {
); );
return ( return (
<AppShell title="Dashboard" requireAuth requireBeta> <AppShell title="Dashboard" requireAuth>
<VStack px={8} py={8} alignItems="flex-start" spacing={4}> <VStack px={8} py={8} alignItems="flex-start" spacing={4}>
<Text fontSize="2xl" fontWeight="bold"> <Text fontSize="2xl" fontWeight="bold">
Dashboard Dashboard

View File

@@ -19,7 +19,7 @@ export default function LoggedCalls() {
const [filtersShown, setFiltersShown] = useState(true); const [filtersShown, setFiltersShown] = useState(true);
return ( return (
<AppShell title="Request Logs" requireAuth requireBeta> <AppShell title="Request Logs" requireAuth>
<Box h="100vh" overflowY="scroll"> <Box h="100vh" overflowY="scroll">
<VStack px={8} py={8} alignItems="flex-start" spacing={4} w="full"> <VStack px={8} py={8} alignItems="flex-start" spacing={4} w="full">
<Text fontSize="2xl" fontWeight="bold"> <Text fontSize="2xl" fontWeight="bold">
@@ -35,6 +35,7 @@ export default function LoggedCalls() {
label="Experiment" label="Experiment"
icon={RiFlaskLine} icon={RiFlaskLine}
isDisabled={selectedLogIds.size === 0} isDisabled={selectedLogIds.size === 0}
requireBeta
/> />
<ExportButton /> <ExportButton />
<ColumnVisiblityDropdown /> <ColumnVisiblityDropdown />

View File

@@ -148,13 +148,13 @@ export const useScenarioVars = () => {
); );
}; };
export const useLoggedCalls = () => { export const useLoggedCalls = (applyFilters = true) => {
const selectedProjectId = useAppStore((state) => state.selectedProjectId); const selectedProjectId = useAppStore((state) => state.selectedProjectId);
const { page, pageSize } = usePageParams(); const { page, pageSize } = usePageParams();
const filters = useAppStore((state) => state.logFilters.filters); const filters = useAppStore((state) => state.logFilters.filters);
const { data, isLoading, ...rest } = api.loggedCalls.list.useQuery( const { data, isLoading, ...rest } = api.loggedCalls.list.useQuery(
{ projectId: selectedProjectId ?? "", page, pageSize, filters }, { projectId: selectedProjectId ?? "", page, pageSize, filters: applyFilters ? filters : [] },
{ enabled: !!selectedProjectId }, { enabled: !!selectedProjectId },
); );

View File

@@ -7,9 +7,9 @@ description: "OpenPipe is a streamlined platform designed to help product-focuse
We're a team of full-stack engineers and machine learning researchers working to streamline the process of integrating fine-tuned models into any application. Our goal is to make the fine-tuning process accessible to everyone. We're a team of full-stack engineers and machine learning researchers working to streamline the process of integrating fine-tuned models into any application. Our goal is to make the fine-tuning process accessible to everyone.
## What We Offer ## What We Provide
Here are a few of the features we provide: Here are a few of the features we offer:
- **Data Capture**: OpenPipe automatically captures every request and response sent through our drop-in replacement sdk and stores it for your future use. - **Data Capture**: OpenPipe automatically captures every request and response sent through our drop-in replacement sdk and stores it for your future use.
@@ -27,6 +27,4 @@ Here are a few of the features we provide:
- **Experimentation**: The fine-tunes you've created on OpenPipe are immediately available for you to run inference on in our experimentation playground. - **Experimentation**: The fine-tunes you've created on OpenPipe are immediately available for you to run inference on in our experimentation playground.
Join us in our mission to make the benefits of hyper-efficient models accessible to everyone. Read through our documentation, and don't hesitate to throw a question our way.
Welcome to the OpenPipe community! Welcome to the OpenPipe community!