Skip to content

Commit aa97732

Browse files
densumeshskeptrunedev
authored andcommitted
feature: add progress bar for component loads
1 parent 1d86726 commit aa97732

10 files changed

Lines changed: 178 additions & 67 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { useSubmit } from "@remix-run/react";
2+
import { BlockStack, Box, Button, Card, DescriptionList, DescriptionListProps, InlineStack, Text } from "@shopify/polaris";
3+
import { ProgressBar } from "./ProgressBar";
4+
5+
export const PlanView = ({
6+
planItems,
7+
setShowCancelModal,
8+
usagePercentage,
9+
}: {
10+
planItems: DescriptionListProps["items"];
11+
setShowCancelModal: (show: boolean) => void;
12+
usagePercentage: number;
13+
}) => {
14+
const submit = useSubmit();
15+
16+
return (
17+
<Card>
18+
<BlockStack gap="400">
19+
<Box paddingInline="400" paddingBlockStart="400">
20+
<InlineStack align="space-between">
21+
<Text variant="headingMd" as="h2">
22+
Plan Details
23+
</Text>
24+
<div className="flex gap-2">
25+
<Button
26+
onClick={() => {
27+
submit({
28+
action: "modify",
29+
}, {
30+
method: "post",
31+
});
32+
}}
33+
>
34+
Modify
35+
</Button>
36+
<Button
37+
onClick={() => {
38+
setShowCancelModal(true);
39+
}}
40+
>
41+
Cancel
42+
</Button>
43+
</div>
44+
</InlineStack>
45+
</Box>
46+
47+
<Box paddingInline="400" paddingBlockEnd="400">
48+
<ProgressBar progress={usagePercentage} />
49+
<DescriptionList items={planItems} />
50+
</Box>
51+
</BlockStack>
52+
</Card>
53+
);
54+
};
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Box, Text, InlineStack } from "@shopify/polaris";
2+
import React from "react";
3+
4+
interface ProgressBarProps {
5+
progress: number;
6+
}
7+
8+
export const ProgressBar: React.FC<ProgressBarProps> = ({ progress }) => {
9+
const progressPercentage = Math.max(0, Math.min(100, progress));
10+
11+
return (
12+
<Box paddingBlockEnd="200">
13+
<div className="w-full bg-gray-200 rounded overflow-hidden h-2 mb-1">
14+
<div
15+
className="bg-[#800080e6] h-full transition-width duration-300 ease-in-out"
16+
style={{ width: `${progressPercentage}%` }}
17+
/>
18+
</div>
19+
<InlineStack align="space-between" blockAlign="center" gap="0">
20+
<Text as="span" variant="bodySm" tone="subdued">0%</Text>
21+
<Text as="span" variant="bodySm" tone="subdued">25%</Text>
22+
<Text as="span" variant="bodySm" tone="subdued">50%</Text>
23+
<Text as="span" variant="bodySm" tone="subdued">75%</Text>
24+
<Text as="span" variant="bodySm" tone="subdued">100%</Text>
25+
</InlineStack>
26+
</Box>
27+
);
28+
};

clients/trieve-shopify-extension/app/components/onboarding/WelcomeOnboarding.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { useTrieve } from "app/context/trieveContext";
55
import { useClientAdminApi } from "app/loaders/clientLoader";
66
import { trackCustomerEvent } from "app/processors/shopifyTrackers";
77
import { shopifyVariantsCountQuery } from "app/queries/onboarding";
8-
import { usageQuery } from "app/queries/usage";
8+
import { datasetUsageQuery } from "app/queries/usage";
99
import { OnboardingBody } from "app/utils/onboarding";
1010
import { useEffect, useState } from "react";
1111

@@ -19,7 +19,7 @@ export const WelcomeOnboarding: OnboardingBody = ({
1919
const [refetch, setRefetch] = useState(true);
2020

2121
const { data: usage } = useQuery({
22-
...usageQuery(trieve),
22+
...datasetUsageQuery(trieve),
2323
refetchInterval: 1000,
2424
enabled: refetch,
2525
});

clients/trieve-shopify-extension/app/queries/usage.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
import { QueryOptions } from "@tanstack/react-query";
22
import { TrieveSDK } from "trieve-ts-sdk";
33

4-
export const usageQuery = (trieve: TrieveSDK) => {
4+
export const datasetUsageQuery = (trieve: TrieveSDK) => {
55
return {
6-
queryKey: ["usage", trieve.datasetId],
6+
queryKey: ["dataset-usage", trieve.datasetId],
77
queryFn: async () => {
8-
const usage = await trieve.getDatasetUsageById(trieve.datasetId!);
8+
const usage = await trieve.getDatasetUsageById(trieve.datasetId || "");
9+
return usage;
10+
},
11+
} satisfies QueryOptions;
12+
};
13+
14+
export const organizationUsageQuery = (trieve: TrieveSDK) => {
15+
return {
16+
queryKey: ["organization-usage", trieve.organizationId],
17+
queryFn: async () => {
18+
const usage = await trieve.getOrganizationUsage(trieve.organizationId || "");
919
return usage;
1020
},
1121
} satisfies QueryOptions;

clients/trieve-shopify-extension/app/routes/app._dashboard._index.tsx

Lines changed: 19 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
QuestionCircleIcon,
2424
RefreshIcon,
2525
} from "@shopify/polaris-icons";
26-
import { usageQuery } from "app/queries/usage";
26+
import { organizationUsageQuery, datasetUsageQuery } from "app/queries/usage";
2727
import { useQuery } from "@tanstack/react-query";
2828
import { Onboarding } from "app/components/onboarding/Onboarding";
2929
import { Loader } from "app/loaders";
@@ -39,7 +39,7 @@ import { defaultSearchAnalyticsFilter } from "app/queries/analytics/search";
3939
import { Granularity } from "trieve-ts-sdk";
4040
import { ActionFunctionArgs } from "@remix-run/node";
4141
import { authenticate } from "app/shopify.server";
42-
42+
import { PlanView } from "app/components/PlanView";
4343
const load: Loader = async ({ adminApiFetcher, queryClient }) => {
4444
await queryClient.ensureQueryData(lastStepIdQuery(adminApiFetcher));
4545
return;
@@ -79,11 +79,16 @@ export default function Dashboard() {
7979
const submit = useSubmit();
8080

8181
const {
82-
data: usage,
82+
data: datasetUsage,
8383
isLoading,
8484
dataUpdatedAt,
8585
refetch,
86-
} = useQuery(usageQuery(trieve));
86+
} = useQuery(datasetUsageQuery(trieve));
87+
88+
const {
89+
data: organizationUsage,
90+
isLoading: organizationUsageLoading,
91+
} = useQuery(organizationUsageQuery(trieve));
8792

8893
const planType = organization?.plan?.name || "Free";
8994

@@ -94,7 +99,7 @@ export default function Dashboard() {
9499
<SkeletonBodyText lines={1} />
95100
) : (
96101
<InlineStack align="space-between">
97-
{usage?.chunk_count.toLocaleString()}
102+
{datasetUsage?.chunk_count.toLocaleString()}
98103
<Button
99104
icon={RefreshIcon}
100105
onClick={() => {
@@ -123,25 +128,16 @@ export default function Dashboard() {
123128
},
124129
];
125130

126-
if ((organization?.plan as any)?.type === "flat") {
131+
if (organization?.plan?.type === "flat") {
127132
planItems.push(
128133
{
129-
term: "Chunk Limit",
130-
description: organization?.plan?.chunk_count?.toLocaleString() || "N/A",
131-
},
132-
{
133-
term: "Dataset Limit",
134-
description:
135-
organization?.plan?.dataset_count?.toLocaleString() || "N/A",
136-
},
137-
{
138-
term: "Message Limit",
139-
description:
140-
organization?.plan?.message_count.toLocaleString() || "N/A",
134+
term: "Messages Sent",
135+
description: organizationUsage?.current_months_message_count?.toLocaleString() || "N/A",
141136
},
142137
);
143138
}
144139

140+
145141
return (
146142
<>
147143
<Modal open={showCancelModal} onClose={() => { setShowCancelModal(false) }} title="Cancel Subscription">
@@ -281,41 +277,11 @@ export default function Dashboard() {
281277
</Box>
282278
</BlockStack>
283279
</Card>
284-
<Card>
285-
<BlockStack gap="400">
286-
<Box paddingInline="400" paddingBlockStart="400">
287-
<InlineStack align="space-between">
288-
<Text variant="headingMd" as="h2">
289-
Plan Details
290-
</Text>
291-
<div className="flex gap-2">
292-
<Button
293-
onClick={() => {
294-
submit({
295-
action: "modify",
296-
}, {
297-
method: "post",
298-
});
299-
}}
300-
>
301-
Modify
302-
</Button>
303-
<Button
304-
onClick={() => {
305-
setShowCancelModal(true);
306-
}}
307-
>
308-
Cancel
309-
</Button>
310-
</div>
311-
</InlineStack>
312-
</Box>
313-
314-
<Box paddingInline="400">
315-
<DescriptionList items={planItems} />
316-
</Box>
317-
</BlockStack>
318-
</Card>
280+
<PlanView
281+
planItems={planItems}
282+
setShowCancelModal={setShowCancelModal}
283+
usagePercentage={(organizationUsage?.current_months_message_count ?? 0) / organization?.plan?.component_loads}
284+
/>
319285
</BlockStack>
320286
</Layout.Section>
321287
</Layout>

clients/trieve-shopify-extension/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@
5252
"react-dom": "^18.2.0",
5353
"tailwind-merge": "^3.1.0",
5454
"tailwindcss": "^3.4.17",
55-
"trieve-ts-sdk": "0.0.81",
56-
"vite-tsconfig-paths": "^5.0.1",
57-
"trieve-search-component": "0.4.55"
55+
"trieve-search-component": "0.4.55",
56+
"trieve-ts-sdk": "*",
57+
"vite-tsconfig-paths": "^5.0.1"
5858
},
5959
"devDependencies": {
6060
"@remix-run/eslint-config": "^2.7.1",

clients/trieve-shopify-extension/yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9352,16 +9352,16 @@ trieve-search-component@0.4.55:
93529352
tailwind-merge "^3.0.2"
93539353
trieve-ts-sdk "0.0.73"
93549354

9355+
trieve-ts-sdk@*:
9356+
version "0.0.82"
9357+
resolved "https://registry.yarnpkg.com/trieve-ts-sdk/-/trieve-ts-sdk-0.0.82.tgz#32dcd5cfe37706bd4cff952f415f2d3b15e1f198"
9358+
integrity sha512-d3qvhYd+KjsImB313xt8rbbJ0ZaaIMKmxhzZaFeXy6uPRvjWPUWKIDYKG4E/a0wvsEkW++zfmP+UlYBB2W+e6w==
9359+
93559360
trieve-ts-sdk@0.0.73:
93569361
version "0.0.73"
93579362
resolved "https://registry.yarnpkg.com/trieve-ts-sdk/-/trieve-ts-sdk-0.0.73.tgz#9de17428ddb4b1f6d68709695f371d185c4bda79"
93589363
integrity sha512-68iG/OlmKSGmnmI/J33S6VKleEAfq4txzARhvKv1g+CYSaG7HOH76n0cFDMtUUEEKn1PD4nV82uh5ZFtfIxD0A==
93599364

9360-
trieve-ts-sdk@0.0.81:
9361-
version "0.0.81"
9362-
resolved "https://registry.yarnpkg.com/trieve-ts-sdk/-/trieve-ts-sdk-0.0.81.tgz#85313acd01aff48798d5a37e0ba8a5d0bf6592e3"
9363-
integrity sha512-HLUH6xCeH3OTPGRN5cMnhV6NPAI46y/eJ386sIkq9HuuSQA2HwQi2NpA3Bp6wabo4QdlxwzVzzJLawec8aUwXQ==
9364-
93659365
trim-lines@^3.0.0:
93669366
version "3.0.1"
93679367
resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338"

clients/ts-sdk/openapi.json

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12209,7 +12209,8 @@
1220912209
"tokens_ingested",
1221012210
"ocr_pages_ingested",
1221112211
"website_pages_scraped",
12212-
"events_ingested"
12212+
"events_ingested",
12213+
"current_months_message_count"
1221312214
],
1221412215
"properties": {
1221512216
"bytes_ingested": {
@@ -12221,6 +12222,11 @@
1222112222
"type": "integer",
1222212223
"format": "int32"
1222312224
},
12225+
"current_months_message_count": {
12226+
"type": "integer",
12227+
"format": "int64",
12228+
"minimum": 0
12229+
},
1222412230
"dataset_count": {
1222512231
"type": "integer",
1222612232
"format": "int32"
@@ -19690,6 +19696,11 @@
1969019696
"type": "integer",
1969119697
"format": "int32"
1969219698
},
19699+
"component_loads": {
19700+
"type": "integer",
19701+
"format": "int32",
19702+
"nullable": true
19703+
},
1969319704
"created_at": {
1969419705
"type": "string",
1969519706
"format": "date-time"
@@ -19731,6 +19742,7 @@
1973119742
"example": {
1973219743
"amount": 1000,
1973319744
"chunk_count": 1000,
19745+
"component_loads": 1000,
1973419746
"created_at": "2021-01-01 00:00:00.000",
1973519747
"dataset_count": 1,
1973619748
"file_storage": 512,

clients/ts-sdk/src/functions/organization/index.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { TrieveSDK } from "../../sdk";
88
import {
99
CreateApiKeyReqPayload,
1010
CreateApiKeyResponse,
11+
ExtendedOrganizationUsageCount,
1112
OrganizationWithSubAndPlan,
1213
} from "../../types.gen";
1314

@@ -71,3 +72,41 @@ export async function getOrganizationById(
7172
signal
7273
);
7374
}
75+
76+
export const formatDateForApi = (date: Date) => {
77+
return date
78+
.toLocaleString("en-CA", {
79+
year: "numeric",
80+
month: "2-digit",
81+
day: "2-digit",
82+
hour: "2-digit",
83+
minute: "2-digit",
84+
second: "2-digit",
85+
hour12: false,
86+
timeZone: "UTC",
87+
})
88+
.replace(",", "");
89+
};
90+
91+
export async function getOrganizationUsage(
92+
/** @hidden */
93+
this: TrieveSDK,
94+
organizationId: string,
95+
signal?: AbortSignal
96+
): Promise<ExtendedOrganizationUsageCount> {
97+
return this.trieve.fetch(
98+
"/api/organization/usage/{organization_id}",
99+
"post",
100+
{
101+
organizationId,
102+
data: {
103+
v1_usage: false,
104+
date_range: {
105+
gte: formatDateForApi(new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)),
106+
lte: formatDateForApi(new Date()),
107+
},
108+
},
109+
},
110+
signal
111+
);
112+
}

clients/ts-sdk/src/types.gen.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,7 @@ export type EventsForTopicResponse = {
17901790
export type ExtendedOrganizationUsageCount = {
17911791
bytes_ingested: number;
17921792
chunk_count: number;
1793+
current_months_message_count: number;
17931794
dataset_count: number;
17941795
events_ingested: number;
17951796
file_storage: number;
@@ -3898,6 +3899,7 @@ export type StripeInvoice = {
38983899
export type StripePlan = {
38993900
amount: number;
39003901
chunk_count: number;
3902+
component_loads?: (number) | null;
39013903
created_at: string;
39023904
dataset_count: number;
39033905
file_storage: number;

0 commit comments

Comments
 (0)