diff --git a/app/src/components/nav/BetaModal.tsx b/app/src/components/BetaModal.tsx similarity index 88% rename from app/src/components/nav/BetaModal.tsx rename to app/src/components/BetaModal.tsx index bf66342..68f7864 100644 --- a/app/src/components/nav/BetaModal.tsx +++ b/app/src/components/BetaModal.tsx @@ -13,19 +13,17 @@ import { Link, } from "@chakra-ui/react"; import { BsStars } from "react-icons/bs"; -import { useRouter } from "next/router"; import { useSession } from "next-auth/react"; -export const BetaModal = () => { - const router = useRouter(); +export const BetaModal = ({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) => { const session = useSession(); const email = session.data?.user.email ?? ""; return ( @@ -56,7 +54,7 @@ export const BetaModal = () => { > Join Waitlist - diff --git a/app/src/components/StatsCard.tsx b/app/src/components/StatsCard.tsx deleted file mode 100644 index a44352e..0000000 --- a/app/src/components/StatsCard.tsx +++ /dev/null @@ -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 ( - - - - {title} - - - View all - - - - {children} - - ); -}; - -export default StatsCard; diff --git a/app/src/components/dashboard/LoggedCallsTable.tsx b/app/src/components/dashboard/LoggedCallsTable.tsx index 9bea54f..fc75a3b 100644 --- a/app/src/components/dashboard/LoggedCallsTable.tsx +++ b/app/src/components/dashboard/LoggedCallsTable.tsx @@ -2,11 +2,12 @@ import { Card, CardHeader, Heading, Table, Tbody, HStack, Button, Text } from "@ import { useState } from "react"; import Link from "next/link"; import { useLoggedCalls } from "~/utils/hooks"; -import { TableHeader, TableRow } from "../requestLogs/TableRow"; +import { EmptyTableRow, TableHeader, TableRow } from "../requestLogs/TableRow"; export default function LoggedCallsTable() { + const { data: loggedCalls } = useLoggedCalls(false); + const [expandedRow, setExpandedRow] = useState(null); - const { data: loggedCalls } = useLoggedCalls(); return ( @@ -23,22 +24,26 @@ export default function LoggedCallsTable() { - {loggedCalls?.calls.map((loggedCall) => { - return ( - { - if (loggedCall.id === expandedRow) { - setExpandedRow(null); - } else { - setExpandedRow(loggedCall.id); - } - }} - /> - ); - })} + {loggedCalls?.calls.length ? ( + loggedCalls?.calls.map((loggedCall) => { + return ( + { + if (loggedCall.id === expandedRow) { + setExpandedRow(null); + } else { + setExpandedRow(loggedCall.id); + } + }} + /> + ); + }) + ) : ( + + )}
diff --git a/app/src/components/nav/AppShell.tsx b/app/src/components/nav/AppShell.tsx index 5a40725..68a623f 100644 --- a/app/src/components/nav/AppShell.tsx +++ b/app/src/components/nav/AppShell.tsx @@ -13,15 +13,18 @@ import { } from "@chakra-ui/react"; import Head from "next/head"; import Link from "next/link"; +import { useRouter } from "next/router"; import { BsGearFill, BsGithub, BsPersonCircle } from "react-icons/bs"; import { IoStatsChartOutline } from "react-icons/io5"; import { RiHome3Line, RiFlaskLine } from "react-icons/ri"; import { AiOutlineThunderbolt } from "react-icons/ai"; +import { FaReadme } from "react-icons/fa"; import { signIn, useSession } from "next-auth/react"; + import ProjectMenu from "./ProjectMenu"; import NavSidebarOption from "./NavSidebarOption"; import IconLink from "./IconLink"; -import { BetaModal } from "./BetaModal"; +import { BetaModal } from "../BetaModal"; import { useAppStore } from "~/state/store"; const Divider = () => ; @@ -73,8 +76,8 @@ const NavSidebar = () => { - - + + @@ -111,7 +114,22 @@ const NavSidebar = () => { )} - + + + + Read the Docs + + { const setHeight = () => { @@ -181,7 +200,7 @@ export default function AppShell({ {children} - {requireBeta && flagsLoaded && !flags.betaAccess && } + ); } diff --git a/app/src/components/requestLogs/ActionButton.tsx b/app/src/components/requestLogs/ActionButton.tsx index f42b599..315274e 100644 --- a/app/src/components/requestLogs/ActionButton.tsx +++ b/app/src/components/requestLogs/ActionButton.tsx @@ -1,29 +1,50 @@ +import { useState } from "react"; + import { Button, HStack, type ButtonProps, Icon, Text } from "@chakra-ui/react"; import { type IconType } from "react-icons"; +import { useAppStore } from "~/state/store"; +import { BetaModal } from "../BetaModal"; const ActionButton = ({ icon, label, + requireBeta = false, + onClick, ...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 ( - + <> + + setBetaModalOpen(false)} /> + ); }; diff --git a/app/src/components/requestLogs/ExportButton.tsx b/app/src/components/requestLogs/ExportButton.tsx index 15389d3..af61af6 100644 --- a/app/src/components/requestLogs/ExportButton.tsx +++ b/app/src/components/requestLogs/ExportButton.tsx @@ -47,6 +47,7 @@ const ExportButton = () => { label="Export" icon={BiExport} isDisabled={selectedLogIds.size === 0} + requireBeta /> diff --git a/app/src/components/requestLogs/FineTuneButton.tsx b/app/src/components/requestLogs/FineTuneButton.tsx index a83d206..91dac22 100644 --- a/app/src/components/requestLogs/FineTuneButton.tsx +++ b/app/src/components/requestLogs/FineTuneButton.tsx @@ -41,6 +41,7 @@ const FineTuneButton = () => { label="Fine Tune" icon={AiTwotoneThunderbolt} isDisabled={selectedLogIds.size === 0} + requireBeta /> diff --git a/app/src/components/requestLogs/LoggedCallsTable.tsx b/app/src/components/requestLogs/LoggedCallsTable.tsx index 5d68400..eb89c03 100644 --- a/app/src/components/requestLogs/LoggedCallsTable.tsx +++ b/app/src/components/requestLogs/LoggedCallsTable.tsx @@ -1,7 +1,7 @@ import { Card, Table, Tbody } from "@chakra-ui/react"; import { useState } from "react"; import { useLoggedCalls } from "~/utils/hooks"; -import { TableHeader, TableRow } from "./TableRow"; +import { TableHeader, TableRow, EmptyTableRow } from "./TableRow"; export default function LoggedCallsTable() { const [expandedRow, setExpandedRow] = useState(null); @@ -12,23 +12,27 @@ export default function LoggedCallsTable() { - {loggedCalls?.calls?.map((loggedCall) => { - return ( - { - if (loggedCall.id === expandedRow) { - setExpandedRow(null); - } else { - setExpandedRow(loggedCall.id); - } - }} - showOptions - /> - ); - })} + {loggedCalls?.calls.length ? ( + loggedCalls?.calls?.map((loggedCall) => { + return ( + { + if (loggedCall.id === expandedRow) { + setExpandedRow(null); + } else { + setExpandedRow(loggedCall.id); + } + }} + showOptions + /> + ); + }) + ) : ( + + )}
diff --git a/app/src/components/requestLogs/TableRow.tsx b/app/src/components/requestLogs/TableRow.tsx index 85fac83..0ca1372 100644 --- a/app/src/components/requestLogs/TableRow.tsx +++ b/app/src/components/requestLogs/TableRow.tsx @@ -13,6 +13,7 @@ import { ButtonGroup, Text, Checkbox, + Link as ChakraLink, } from "@chakra-ui/react"; 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 ( + + + + No matching request logs found. Try removing some filters. + + + + ); + } + + return ( + + + + This project has no request logs. Learn how to add request logs to your project in our{" "} + + Quick Start + {" "} + guide. + + + + ); +}; diff --git a/app/src/pages/dashboard/index.tsx b/app/src/pages/dashboard/index.tsx index 7f58582..aa790b4 100644 --- a/app/src/pages/dashboard/index.tsx +++ b/app/src/pages/dashboard/index.tsx @@ -33,7 +33,7 @@ export default function Dashboard() { ); return ( - + Dashboard diff --git a/app/src/pages/request-logs/index.tsx b/app/src/pages/request-logs/index.tsx index 4799361..f9016dc 100644 --- a/app/src/pages/request-logs/index.tsx +++ b/app/src/pages/request-logs/index.tsx @@ -19,7 +19,7 @@ export default function LoggedCalls() { const [filtersShown, setFiltersShown] = useState(true); return ( - + @@ -35,6 +35,7 @@ export default function LoggedCalls() { label="Experiment" icon={RiFlaskLine} isDisabled={selectedLogIds.size === 0} + requireBeta /> diff --git a/app/src/utils/hooks.ts b/app/src/utils/hooks.ts index 4628a00..9815f3f 100644 --- a/app/src/utils/hooks.ts +++ b/app/src/utils/hooks.ts @@ -148,13 +148,13 @@ export const useScenarioVars = () => { ); }; -export const useLoggedCalls = () => { +export const useLoggedCalls = (applyFilters = true) => { const selectedProjectId = useAppStore((state) => state.selectedProjectId); const { page, pageSize } = usePageParams(); const filters = useAppStore((state) => state.logFilters.filters); const { data, isLoading, ...rest } = api.loggedCalls.list.useQuery( - { projectId: selectedProjectId ?? "", page, pageSize, filters }, + { projectId: selectedProjectId ?? "", page, pageSize, filters: applyFilters ? filters : [] }, { enabled: !!selectedProjectId }, ); diff --git a/docs/overview.mdx b/docs/overview.mdx index 35c793d..0ec296b 100644 --- a/docs/overview.mdx +++ b/docs/overview.mdx @@ -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. -## 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. @@ -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. -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!