Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 137 additions & 100 deletions frontends/analytics/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { UserContext } from "../contexts/UserAuthContext";
import { DatasetAndUsage } from "shared/types";
import { usePathname } from "../hooks/usePathname";
import { useBetterNav } from "../utils/useBetterNav";
import { Select } from "shared/ui";
import { Select, Tooltip } from "shared/ui";
import {
AiOutlineLineChart,
AiOutlineTable,
Expand Down Expand Up @@ -50,15 +50,48 @@ const navbarRoutes = [
},
];

const dashboardURL = import.meta.env.VITE_DASHBOARD_URL as string;
const searchUrl = import.meta.env.VITE_SEARCH_UI_URL as string;
const chatUrl = import.meta.env.VITE_CHAT_UI_URL as string;

export const Sidebar = (props: NavbarProps) => {
const userContext = useContext(UserContext);
const orgContext = useContext(OrgContext);

const domainNavbarRoutes = createMemo(() => {
const domainNavbarRoutes = [
{
href: `${dashboardURL}/dashboard/dataset/${props.selectedDataset
?.dataset.id}/start?org=${orgContext.selectedOrg().id}`,
label: "Dashboard",
icon: TbLayoutDashboard,
},
{
href: "https://docs.trieve.ai/api-reference/",
label: "API Docs",
icon: AiOutlineApi,
},
{
href: `${searchUrl}?organization=${
orgContext.selectedOrg().id
}&dataset=${props.selectedDataset?.dataset.id}`,
label: "Search Playground",
icon: HiOutlineMagnifyingGlass,
},
{
href: `${chatUrl}?organization=${
orgContext.selectedOrg().id
}&dataset=${props.selectedDataset?.dataset.id}`,
label: "Chat Playground",
icon: IoChatboxOutline,
},
];
return domainNavbarRoutes;
});

const pathname = usePathname();
const navigate = useBetterNav();

const dashboardURL = import.meta.env.VITE_DASHBOARD_URL as string;

const logOut = () => {
void fetch(`${apiHost}/auth?redirect_uri=${window.origin}`, {
method: "DELETE",
Expand All @@ -76,118 +109,122 @@ export const Sidebar = (props: NavbarProps) => {
});
};

//Construct a7b64c7f-01ad-43b2-aaaf-c78192ca3d72/start?org=ca34dafa-7826-41b4-9953-cd58617834f1
const orgDatasetParams = createMemo(() => {
const orgId = orgContext?.selectedOrg().id;
const datasetId = props.selectedDataset?.dataset.id;
let params = "";
if (datasetId) params += datasetId;
if (orgId && datasetId) params += `/start?org=${orgId}`;
return params;
});

return (
<div class="relative hidden h-screen flex-col justify-start overflow-y-auto border border-r-neutral-300 bg-neutral-100 p-4 lg:flex">
<div class="flex items-center gap-1">
<img
class="h-12 w-12 cursor-pointer"
src="https://cdn.trieve.ai/trieve-logo.png"
alt="Logo"
/>
<div>
<div class="text-2xl font-semibold leading-none">Trieve</div>
<div class="pl-1 text-sm leading-tight text-neutral-600">
Analytics
<div class="relative hidden h-screen flex-col justify-start overflow-y-auto border border-r-neutral-300 bg-neutral-100 lg:flex">
<div class="flex flex-grow flex-col p-4">
<div class="flex items-center gap-1">
<img
class="h-12 w-12 cursor-pointer"
src="https://cdn.trieve.ai/trieve-logo.png"
alt="Logo"
/>
<div>
<div class="text-2xl font-semibold leading-none">Trieve</div>
<div class="pl-1 text-sm leading-tight text-neutral-600">
Analytics
</div>
</div>
</div>
</div>
<div class="border-neutral-20 h-4 border-b" />
<div>
<Select
label={<div class="pt-2 text-sm opacity-60">Organization</div>}
class="min-w-[220px]"
options={userContext?.user().orgs || []}
display={(org) => org.name}
onSelected={(e) => {
orgContext.selectOrg(e.id);
}}
selected={orgContext.selectedOrg()}
id="dataset-select"
/>
</div>
<Show when={props.datasetOptions.length > 0 && props.selectedDataset}>
{(selected) => (
<div class="border-neutral-20 h-4 border-b" />
<div>
<Select
label={<div class="pt-2 text-sm opacity-60">Dataset</div>}
label={<div class="pt-2 text-sm opacity-60">Organization</div>}
class="min-w-[220px]"
options={props.datasetOptions}
display={(dataset) => dataset.dataset.name}
options={userContext?.user().orgs || []}
display={(org) => org.name}
onSelected={(e) => {
props.setSelectedDataset(e);
orgContext.selectOrg(e.id);
}}
selected={selected()}
selected={orgContext.selectedOrg()}
id="dataset-select"
/>
)}
</Show>
<div class="border-neutral-20 h-4 border-b" />
<div class="flex flex-col gap-4 px-2 pt-4">
<For each={navbarRoutes}>
{(link) => {
return (
<div
role="link"
classList={{
"cursor-pointer flex items-center gap-2": true,
"text-purple-900 underline": pathname() === link.href,
"text-black": pathname() !== link.href,
}}
onClick={() => {
navigate(link.href);
</div>
<Show when={props.datasetOptions.length > 0 && props.selectedDataset}>
{(selected) => (
<Select
label={<div class="pt-2 text-sm opacity-60">Dataset</div>}
class="min-w-[220px]"
options={props.datasetOptions}
display={(dataset) => dataset.dataset.name}
onSelected={(e) => {
props.setSelectedDataset(e);
}}
selected={selected()}
id="dataset-select"
/>
)}
</Show>
<div class="border-neutral-20 h-4 border-b" />
<div class="flex flex-grow flex-col justify-between">
<div class="flex flex-col gap-4 px-2 pt-4">
<For each={navbarRoutes}>
{(link) => {
return (
<div
role="link"
classList={{
"cursor-pointer flex items-center gap-2": true,
"text-purple-900 underline": pathname() === link.href,
"text-black": pathname() !== link.href,
}}
onClick={() => {
navigate(link.href);
}}
>
{link.icon({ size: "18px" })}
{link.label}
</div>
);
}}
</For>
</div>
<div>
<div class="h-4 border-b border-neutral-400/50" />

<div class="flex flex-col gap-2 px-2 pt-4">
<For each={domainNavbarRoutes()}>
{(link) => {
return (
<a
role="link"
classList={{
"cursor-pointer flex items-center text-sm gap-2 hover:text-fuchsia-500":
true,
"text-purple-900 underline": pathname() === link.href,
"text-black": pathname() !== link.href,
}}
href={link.href}
target="_blank"
>
{link.icon({ size: "14px" })}
{link.label}
</a>
);
}}
>
{link.icon({ size: "18px" })}
{link.label}
</div>
);
}}
</For>
</div>
<div class="absolute bottom-0 left-0 right-0 flex flex-col items-start border-t border-t-neutral-300 bg-neutral-200/50">
<div class="flex flex-col px-4 pt-4">
<button type="button" class="hover:text-fuchsia-800">
<a
href={`${dashboardURL}/dashboard/dataset/${orgDatasetParams()}`}
class="flex w-full flex-row items-center gap-2"
target="_blank"
>
Dashboard
<TbLayoutDashboard class="text-sm" />
</a>
</button>
<button type="button" class="hover:text-fuchsia-800">
<a
href="https://docs.trieve.ai/api-reference/"
class="flex w-full flex-row items-center gap-2"
target="_blank"
>
API Docs
<AiOutlineApi class="text-sm" />
</a>
</button>
</For>
</div>
</div>
</div>
<hr class="my-2 w-full border border-neutral-300" />
<div class="px-4 pb-4">
</div>
<div class="justify-self-end border-t border-t-neutral-300 bg-neutral-200/50">
<div class="flex w-full items-center justify-between gap-2 px-6 py-4">
<div class="flex items-center gap-2">
<p>{userContext?.user().email}</p>
<AiOutlineUser class="h-4 w-4" />
<span>{userContext?.user().email}</span>
</div>
<button
class="flex items-center gap-2 hover:text-fuchsia-800"
onClick={logOut}
<Tooltip
tooltipClass="text-sm border border-neutral-300 bg-neutral-200 min-w-max"
unsetWidth
tooltipText="Log Out"
direction="top"
>
Log Out <IoLogOutOutline class="inline-block h-4 w-4" />
</button>
<button
class="flex items-center gap-2 justify-self-end p-1 pl-2 opacity-60 hover:text-fuchsia-800"
onClick={logOut}
>
<IoLogOutOutline class="inline-block h-4 w-4" />
</button>
</Tooltip>
</div>
</div>
</div>
Expand Down
13 changes: 9 additions & 4 deletions frontends/shared/ui/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import type { JSX } from "solid-js/jsx-runtime";
export type TooltipDirection = "top" | "bottom" | "left" | "right";

export interface TooltipProps {
body: JSX.Element;
body?: JSX.Element;
children?: JSX.Element;
tooltipText: string;
direction?: TooltipDirection;
tooltipClass?: string;
unsetWidth?: boolean;
}

export const Tooltip = (props: TooltipProps) => {
Expand All @@ -24,21 +27,23 @@ export const Tooltip = (props: TooltipProps) => {
setShow(false);
}}
>
{props.body}
{props.children ? props.children : props.body}
</div>
<Show when={show()}>
<div
class={props.tooltipClass}
classList={{
"absolute z-10 inline-block w-[300px] rounded bg-[#fffee6] p-2 text-center shadow-lg dark:bg-[#fffee6] text-black text-wrap":
"absolute z-10 inline-block rounded bg-[#fffee6] p-2 text-center shadow-lg dark:bg-[#fffee6] text-black text-wrap":
true,
"w-[300px]": !props.unsetWidth,
"bottom-full left-1/2 -translate-x-1/2 translate-y-3":
direction() === "top",
"right-full top-1/2 -translate-y-1/2 -translate-x-3":
direction() === "left",
"left-full top-1/2 -translate-y-1/2 translate-x-3":
direction() === "right",
"top-full left-1/2 -translate-x-1/2 translate-y-3":
direction() === "bottom"
direction() === "bottom",
}}
>
{props.tooltipText}
Expand Down