Skip to content

Commit 68560aa

Browse files
skeptrunedevcdxker
authored andcommitted
feature: datasetstart checklist component for easier onboarding
1 parent c69bd5a commit 68560aa

File tree

2 files changed

+351
-3
lines changed

2 files changed

+351
-3
lines changed

frontends/dashboard/src/components/DatasetOverview.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,27 @@ import { CopyButton } from "./CopyButton";
2828
import { formatDate } from "../utils/formatters";
2929
import { TbReload } from "solid-icons/tb";
3030
import { createToast } from "../components/ShowToasts";
31+
import { OnboardingSteps } from "./OnboardingSteps";
32+
import { createQuery } from "@tanstack/solid-query";
33+
import { ApiContext } from "..";
3134

3235
const colHelp = createColumnHelper<DatasetAndUsage>();
3336

3437
export const DatasetOverview = () => {
35-
const [newDatasetModalOpen, setNewDatasetModalOpen] =
36-
createSignal<boolean>(false);
3738
const userContext = useContext(UserContext) as {
3839
selectedOrg: () => { id: string };
3940
};
40-
41+
const trieve = useContext(ApiContext);
4142
const navigate = useNavigate();
43+
44+
const [newDatasetModalOpen, setNewDatasetModalOpen] =
45+
createSignal<boolean>(false);
4246
const [page, setPage] = createSignal(0);
4347
const [datasetSearchQuery, setDatasetSearchQuery] = createSignal("");
4448
const [usage, setUsage] = createSignal<
4549
Record<string, { chunk_count: number }>
4650
>({});
51+
4752
const { datasets, maxPageDiscovered, maxDatasets, hasLoaded } =
4853
useDatasetPages({
4954
org: userContext.selectedOrg().id,
@@ -52,6 +57,15 @@ export const DatasetOverview = () => {
5257
setPage,
5358
});
5459

60+
const usageQuery = createQuery(() => ({
61+
queryKey: ["org-usage", userContext.selectedOrg().id],
62+
queryFn: async () => {
63+
return trieve.fetch("/api/organization/usage/{organization_id}", "get", {
64+
organizationId: userContext.selectedOrg().id,
65+
});
66+
},
67+
}));
68+
5569
const refetchChunks = async (datasetId: string) => {
5670
try {
5771
const api_host = import.meta.env.VITE_API_HOST as unknown as string;
@@ -243,6 +257,7 @@ export const DatasetOverview = () => {
243257
setNewDatasetModalOpen(false);
244258
}}
245259
/>
260+
<OnboardingSteps usageQuery={usageQuery} />
246261
<div class="flex items-center py-2">
247262
<div class="flex w-full items-end justify-between pt-2">
248263
<div>
Lines changed: 333 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,333 @@
1+
import { createQuery, CreateQueryResult } from "@tanstack/solid-query";
2+
import { FaSolidCheck } from "solid-icons/fa";
3+
import { createMemo, Show, useContext } from "solid-js";
4+
import { OrganizationUsageCount } from "trieve-ts-sdk";
5+
import { ApiContext } from "..";
6+
7+
export interface OnboardingStepsProps {
8+
usageQuery: CreateQueryResult<OrganizationUsageCount, Error>;
9+
}
10+
11+
export const OnboardingSteps = (props: OnboardingStepsProps) => {
12+
const trieve = useContext(ApiContext);
13+
const searchAnalyticsQuery = createQuery(() => ({
14+
queryKey: ["top-datasets", props.usageQuery.data?.org_id],
15+
queryFn: async () => {
16+
return trieve.fetch("/api/analytics/top", "post", {
17+
organizationId: props.usageQuery.data?.org_id as string,
18+
data: {
19+
type: "search",
20+
organization_id: props.usageQuery.data?.org_id as string,
21+
},
22+
});
23+
},
24+
}));
25+
26+
const ragAnalyticsQuery = createQuery(() => ({
27+
queryKey: ["top-datasets", props.usageQuery.data?.org_id],
28+
queryFn: async () => {
29+
return trieve.fetch("/api/analytics/top", "post", {
30+
organizationId: props.usageQuery.data?.org_id as string,
31+
data: {
32+
type: "rag",
33+
organization_id: props.usageQuery.data?.org_id as string,
34+
},
35+
});
36+
},
37+
}));
38+
39+
const activeDataset = createMemo(() => {
40+
if ((props.usageQuery?.data?.dataset_count ?? 0) == 0) {
41+
return 1;
42+
} else if ((props.usageQuery?.data?.chunk_count ?? 0) == 0) {
43+
return 2;
44+
} else if (
45+
searchAnalyticsQuery.data?.find(
46+
(top_dataset) => top_dataset.total_queries > 0,
47+
) &&
48+
ragAnalyticsQuery.data?.find(
49+
(top_dataset) => top_dataset.total_queries > 0,
50+
)
51+
) {
52+
return 4;
53+
}
54+
55+
return 3;
56+
});
57+
58+
return (
59+
<Show when={activeDataset() < 4}>
60+
<div class="rounded-lg bg-white shadow lg:border-b lg:border-t lg:border-gray-200">
61+
<nav class="w-full" aria-label="Progress">
62+
<ol
63+
role="list"
64+
class="w-full overflow-hidden rounded-md lg:flex lg:rounded-none lg:border-l lg:border-r lg:border-gray-200"
65+
>
66+
<li class="relative w-full overflow-hidden">
67+
<div class="w-full overflow-hidden rounded-t-md border border-b-0 border-gray-200 lg:border-0">
68+
{/* <!-- Completed Step --> */}
69+
<div class="group">
70+
<span
71+
classList={{
72+
"absolute left-0 top-0 h-full w-1 lg:bottom-0 lg:top-auto lg:h-0.5 lg:w-full":
73+
true,
74+
"bg-fuchsia-400": activeDataset() == 1,
75+
"bg-transparent": activeDataset() != 1,
76+
}}
77+
aria-hidden="true"
78+
/>
79+
<span class="flex items-start px-6 py-5 text-sm">
80+
<span class="flex-shrink-0">
81+
<Show
82+
when={activeDataset() != 1}
83+
fallback={
84+
<span class="flex h-10 w-10 items-center justify-center rounded-full border-2 border-fuchsia-400">
85+
<span class="font-medium text-fuchsia-600">01</span>
86+
</span>
87+
}
88+
>
89+
<span class="flex h-10 w-10 items-center justify-center rounded-full bg-fuchsia-600">
90+
<FaSolidCheck
91+
class="h-6 w-6 fill-current text-white"
92+
aria-hidden="true"
93+
/>
94+
</span>
95+
</Show>
96+
</span>
97+
<span class="ml-4 mt-0.5 flex min-w-0 flex-col">
98+
<span
99+
classList={{
100+
"text-sm font-medium": true,
101+
"text-fuchsia-600": activeDataset() == 1,
102+
}}
103+
>
104+
Create a Dataset
105+
</span>
106+
<span class="text-sm">
107+
Trieve's top-level storage container is a Dataset. Each
108+
Dataset is encrypted and isolated from other Datasets.
109+
API keys and requests are scoped to a specific Dataset.
110+
Click on the{" "}
111+
<span class="font-medium">Create Dataset</span> button
112+
below to get started.
113+
</span>
114+
</span>
115+
</span>
116+
</div>
117+
</div>
118+
</li>
119+
<li class="relative w-full overflow-hidden">
120+
<div class="w-full overflow-hidden border border-gray-200 lg:border-0">
121+
{/* <!-- Current Step --> */}
122+
<div>
123+
<span
124+
classList={{
125+
"absolute left-0 top-0 h-full w-1 lg:bottom-0 lg:top-auto lg:h-0.5 lg:w-full":
126+
true,
127+
"bg-fuchsia-600": activeDataset() == 2,
128+
"bg-transparent": activeDataset() != 2,
129+
}}
130+
aria-hidden="true"
131+
/>
132+
<span class="flex items-start px-6 py-5 text-sm lg:pl-9">
133+
<span class="flex-shrink-0">
134+
<Show
135+
when={activeDataset() < 3}
136+
fallback={
137+
<span class="flex h-10 w-10 items-center justify-center rounded-full bg-fuchsia-600">
138+
<FaSolidCheck
139+
class="h-6 w-6 fill-current text-white"
140+
aria-hidden="true"
141+
/>
142+
</span>
143+
}
144+
>
145+
<span
146+
classList={{
147+
"flex h-10 w-10 items-center justify-center rounded-full border-2":
148+
true,
149+
"border-gray-300": activeDataset() == 1,
150+
"border-fuchsia-400": activeDataset() == 2,
151+
}}
152+
>
153+
<span
154+
classList={{
155+
"text-gray-500": activeDataset() == 1,
156+
"text-fuchsia-600": activeDataset() == 2,
157+
}}
158+
>
159+
02
160+
</span>
161+
</span>
162+
</Show>
163+
</span>
164+
<span class="ml-4 mt-0.5 flex min-w-0 flex-col">
165+
<span
166+
classList={{
167+
"text-sm font-medium": true,
168+
"text-fuchsia-600": activeDataset() == 2,
169+
"text-gray-500": activeDataset() == 1,
170+
}}
171+
>
172+
Add Chunks or Files
173+
</span>
174+
<span
175+
classList={{
176+
"text-sm": true,
177+
"text-gray-500": activeDataset() < 3,
178+
}}
179+
>
180+
Once you have a Dataset, the next step is including
181+
data. You can add Chunks or Upload Files without code
182+
using the{" "}
183+
<a
184+
class="inline underline"
185+
href="https://search.trieve.ai"
186+
>
187+
Search Playground
188+
</a>{" "}
189+
or programmatically using either the{" "}
190+
<a
191+
class="inline underline"
192+
target="_blank"
193+
href="https://docs.trieve.ai/api-reference/chunk/create-or-upsert-chunk-or-chunks"
194+
>
195+
REST API
196+
</a>{" "}
197+
,{" "}
198+
<a
199+
class="inline underline"
200+
target="_blank"
201+
href="https://ts-sdk.trieve.ai/functions/Chunk_Methods.createChunk.html"
202+
>
203+
Typescript SDK
204+
</a>
205+
,or{" "}
206+
<a
207+
class="inline underline"
208+
target="_blank"
209+
href="https://pypi.org/project/trieve-py-client/"
210+
>
211+
Python SDK
212+
</a>
213+
.
214+
</span>
215+
</span>
216+
</span>
217+
</div>
218+
{/* <!-- Separator --> */}
219+
<div
220+
class="absolute inset-0 left-0 top-0 hidden w-3 lg:block"
221+
aria-hidden="true"
222+
>
223+
<svg
224+
class="h-full w-full text-gray-300"
225+
viewBox="0 0 12 82"
226+
fill="none"
227+
preserveAspectRatio="none"
228+
>
229+
<path
230+
d="M0.5 0V31L10.5 41L0.5 51V82"
231+
stroke="currentcolor"
232+
vector-effect="non-scaling-stroke"
233+
/>
234+
</svg>
235+
</div>
236+
</div>
237+
</li>
238+
<li class="relative w-full overflow-hidden">
239+
<div class="w-full overflow-hidden rounded-b-md border border-t-0 border-gray-200 lg:border-0">
240+
{/* <!-- Upcoming Step --> */}
241+
<div class="group">
242+
<span
243+
classList={{
244+
"absolute left-0 top-0 h-full w-1 lg:bottom-0 lg:top-auto lg:h-0.5 lg:w-full":
245+
true,
246+
"bg-fuchsia-600": activeDataset() == 3,
247+
"bg-transparent": activeDataset() != 3,
248+
}}
249+
aria-hidden="true"
250+
/>
251+
<span class="flex items-start px-6 py-5 text-sm lg:pl-9">
252+
<span class="flex-shrink-0">
253+
<span
254+
classList={{
255+
"flex h-10 w-10 items-center justify-center rounded-full border-2":
256+
true,
257+
"border-fuchsia-600": activeDataset() == 3,
258+
"border-gray-300": activeDataset() != 3,
259+
}}
260+
>
261+
<span
262+
classList={{
263+
"text-gray-500": activeDataset() != 3,
264+
"text-fuchsia-600": activeDataset() == 3,
265+
}}
266+
>
267+
03
268+
</span>
269+
</span>
270+
</span>
271+
<span class="ml-4 mt-0.5 flex min-w-0 flex-col">
272+
<span
273+
classList={{
274+
"text-sm font-medium": true,
275+
"text-fuchsia-600": activeDataset() == 3,
276+
"text-gray-500": activeDataset() != 3,
277+
}}
278+
>
279+
Evaluate and Tune
280+
</span>
281+
<span
282+
classList={{
283+
"text-sm": true,
284+
"text-gray-500": activeDataset() < 3,
285+
}}
286+
>
287+
Visit the{" "}
288+
<a
289+
class="inline underline"
290+
href="https://search.trieve.ai"
291+
>
292+
Search
293+
</a>{" "}
294+
and{" "}
295+
<a
296+
class="inline underline"
297+
href="https://chat.trieve.ai"
298+
>
299+
Chat
300+
</a>{" "}
301+
Playgrounds to evaluate your Dataset's performance with
302+
Trieve and make any necessary adjustments before
303+
integrating into your application.
304+
</span>
305+
</span>
306+
</span>
307+
</div>
308+
{/* <!-- Separator --> */}
309+
<div
310+
class="absolute inset-0 left-0 top-0 hidden w-3 lg:block"
311+
aria-hidden="true"
312+
>
313+
<svg
314+
class="h-full w-full text-gray-300"
315+
viewBox="0 0 12 82"
316+
fill="none"
317+
preserveAspectRatio="none"
318+
>
319+
<path
320+
d="M0.5 0V31L10.5 41L0.5 51V82"
321+
stroke="currentcolor"
322+
vector-effect="non-scaling-stroke"
323+
/>
324+
</svg>
325+
</div>
326+
</div>
327+
</li>
328+
</ol>
329+
</nav>
330+
</div>
331+
</Show>
332+
);
333+
};

0 commit comments

Comments
 (0)