Skip to content

Commit 51a123d

Browse files
skeptrunedevcdxker
authored andcommitted
feat(trieve-shopify-extension): enhance app metadata and improve login feedback
1 parent 1175f95 commit 51a123d

5 files changed

Lines changed: 118 additions & 52 deletions

File tree

clients/trieve-shopify-extension/app/root.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,43 @@ export default function App() {
2424
<head>
2525
<meta charSet="utf-8" />
2626
<meta name="viewport" content="width=device-width,initial-scale=1" />
27+
<meta property="og:title" content="Trieve Shopify App" />
28+
<meta
29+
property="og:site_name"
30+
content="Trieve - AI Sales Associate for Ecommerce"
31+
/>
32+
<meta property="og:url" content="https://docsearch.trieve.ai" />
33+
<meta
34+
property="og:description"
35+
content="Replicate your best sales associate with Trieve. Our AI assistant helps you answer customer questions, generate product descriptions, and more."
36+
/>
37+
<meta
38+
property="og:image"
39+
content="https://cdn.trieve.ai/trieve-og.png"
40+
/>
2741
<link rel="preconnect" href="https://cdn.shopify.com/" />
2842
<link
2943
rel="stylesheet"
3044
href="https://cdn.shopify.com/static/fonts/inter/v4/styles.css"
3145
/>
46+
<link
47+
rel="apple-touch-icon"
48+
sizes="180x180"
49+
href="https://cdn.trieve.ai/apple-touch-icon.png"
50+
/>
51+
<link
52+
rel="icon"
53+
type="image/png"
54+
sizes="32x32"
55+
href="https://cdn.trieve.ai/favicon-32x32.png"
56+
/>
57+
<link
58+
rel="icon"
59+
type="image/png"
60+
sizes="16x16"
61+
href="https://cdn.trieve.ai/favicon-16x16.png"
62+
/>
63+
<title>Trieve Shopify App</title>
3264
<Meta />
3365
<Links />
3466
</head>

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

Lines changed: 78 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,17 @@ export const action = async ({ request }: LoaderFunctionArgs) => {
2727
const decoded = jwt.decode(idToken.toString()) as JwtPayload;
2828

2929
if (type === "insert") {
30+
const existingKey = await prisma.apiKey.findFirst({
31+
where: {
32+
userId: decoded.sub ?? "",
33+
organizationId: orgId.toString(),
34+
shop: decoded.dest ?? "",
35+
},
36+
});
37+
if (existingKey) {
38+
return existingKey;
39+
}
40+
3041
const key = await prisma.apiKey.create({
3142
data: {
3243
userId: decoded.sub ?? "",
@@ -55,6 +66,7 @@ type Orgs = {
5566
export default function App() {
5667
const fetcher = useFetcher<typeof action>();
5768
const [orgs, setOrgs] = useState<Orgs[]>([]);
69+
const [successfulLogin, setSuccessfulLogin] = useState(false);
5870
const envs = useEnvs();
5971

6072
useEffect(() => {
@@ -77,7 +89,7 @@ export default function App() {
7789

7890
useEffect(() => {
7991
if (fetcher.data?.key) {
80-
window.close();
92+
setSuccessfulLogin(true);
8193
}
8294
}, [fetcher.data?.key]);
8395

@@ -93,21 +105,26 @@ export default function App() {
93105
"TR-Organization": selectedOrg.toString(),
94106
},
95107
body: JSON.stringify({ name: "Shopify-Access", role: 2 }),
96-
}).then((response) => {
97-
response.json().then((data) => {
98-
let params = new URLSearchParams(window.location.search);
99-
100-
fetcher.submit(
101-
{
102-
apiKey: data.api_key,
103-
orgId: selectedOrg,
104-
idToken: params.get("token"),
105-
type: "insert",
106-
},
107-
{ method: "POST" },
108-
);
108+
})
109+
.then((response) => {
110+
response.json().then((data) => {
111+
let params = new URLSearchParams(window.location.search);
112+
113+
fetcher.submit(
114+
{
115+
apiKey: data.api_key,
116+
orgId: selectedOrg,
117+
idToken: params.get("token"),
118+
type: "insert",
119+
},
120+
{ method: "POST" },
121+
);
122+
});
123+
})
124+
.catch((error) => {
125+
console.error("Error generating API key:", error);
126+
setSuccessfulLogin(true);
109127
});
110-
});
111128
};
112129

113130
return (
@@ -120,28 +137,53 @@ export default function App() {
120137
/>
121138
<span className="text-2xl font-semibold">Trieve</span>
122139
</div>
123-
{orgs.length > 0 && (
124-
<div className="rounded-md border border-neutral-300 bg-white p-4 md:min-w-[500px]">
125-
<div className="flex justify-between">
126-
<div className="text-lg font-medium">Select An Organization</div>
127-
</div>
128-
<div className="flex flex-col py-2">
129-
{orgs?.map((org) => (
130-
<button
131-
onClick={() => {
132-
generateApiKey(org.id);
133-
}}
134-
className="flex cursor-pointer items-center justify-between rounded-md border-b border-b-neutral-200 p-2 last:border-b-transparent hover:bg-neutral-100"
135-
>
136-
<div className="flex w-full items-center justify-between">
137-
<div className="text-sm font-medium">{org.name}</div>
138-
<div className="text-xs text-neutral-500">{org.id}</div>
140+
<div className="rounded-md border border-neutral-300 bg-white p-4 md:min-w-[500px]">
141+
{successfulLogin && (
142+
<>
143+
<div className="flex justify-between">
144+
<div className="text-lg font-medium">Login Successful 🎉</div>
145+
</div>
146+
<div className="py-2 text-sm text-neutral-700">
147+
You can now close this window and return to your Shopify store.
148+
</div>
149+
<div className="py-2 text-sm text-neutral-700">
150+
If you don't see the app, please refresh the page.
151+
</div>
152+
</>
153+
)}
154+
{!successfulLogin &&
155+
(orgs.length > 0 ? (
156+
<>
157+
<div className="flex justify-between">
158+
<div className="text-lg font-medium">
159+
Select An Organization
139160
</div>
140-
</button>
141-
))}
142-
</div>
143-
</div>
144-
)}
161+
</div>
162+
<div className="flex flex-col py-2">
163+
{orgs?.map((org) => (
164+
<button
165+
key={org.id}
166+
onClick={() => {
167+
generateApiKey(org.id);
168+
}}
169+
className="flex cursor-pointer items-center justify-between rounded-md border-b border-b-neutral-200 p-2 last:border-b-transparent hover:bg-neutral-100"
170+
>
171+
<div className="flex w-full items-center justify-between">
172+
<div className="text-sm font-medium">{org.name}</div>
173+
<div className="text-xs text-neutral-500">{org.id}</div>
174+
</div>
175+
</button>
176+
))}
177+
</div>
178+
</>
179+
) : (
180+
<div className="flex justify-center items-center w-full">
181+
<div className="flex h-10 w-10 animate-spin items-center justify-center rounded-full border-4 border-neutral-300 border-t-transparent">
182+
<div className="h-6 w-6 animate-spin rounded-full border-4 border-neutral-300 border-t-transparent" />
183+
</div>
184+
</div>
185+
))}
186+
</div>
145187
</div>
146188
);
147189
}

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

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
1-
import { ActionFunctionArgs, json, LoaderFunctionArgs } from "@remix-run/node";
2-
import { useLoaderData, useRouteLoaderData } from "@remix-run/react";
1+
import { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
2+
import { useLoaderData } from "@remix-run/react";
33
import { Box } from "@shopify/polaris";
44
import { useSuspenseQuery } from "@tanstack/react-query";
55
import { sdkFromKey, validateTrieveAuth } from "app/auth";
66
import { DatasetSettings as DatasetSettings } from "app/components/DatasetSettings";
77
import { useTrieve } from "app/context/trieveContext";
8-
import { Loader } from "app/loaders";
9-
import { createClientLoader } from "app/loaders/clientLoader";
10-
import { buildAdminApiFetcherForServer, createServerLoader } from "app/loaders/serverLoader";
8+
import { buildAdminApiFetcherForServer } from "app/loaders/serverLoader";
119
import { sendChunks } from "app/processors/getProducts";
12-
import { scrapeOptionsQuery } from "app/queries/scrapeOptions";
1310
import { shopDatasetQuery } from "app/queries/shopDataset";
1411
import { authenticate } from "app/shopify.server";
1512
import { type Dataset } from "trieve-ts-sdk";
@@ -29,7 +26,6 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
2926
return Response.json({ crawlSettings: crawlSettings?.crawlSettings });
3027
};
3128

32-
3329
export const action = async ({ request }: ActionFunctionArgs) => {
3430
const { session } = await authenticate.admin(request);
3531
const key = await validateTrieveAuth(request);
@@ -45,7 +41,7 @@ export const action = async ({ request }: ActionFunctionArgs) => {
4541
datasetId_shop: {
4642
datasetId: datasetId as string,
4743
shop: session.shop,
48-
}
44+
},
4945
},
5046
update: {
5147
crawlSettings,
@@ -58,13 +54,9 @@ export const action = async ({ request }: ActionFunctionArgs) => {
5854
session.accessToken!,
5955
);
6056

61-
sendChunks(
62-
datasetId as string,
63-
key,
64-
fetcher,
65-
session,
66-
crawlSettings,
67-
).catch(console.error);
57+
sendChunks(datasetId as string, key, fetcher, session, crawlSettings).catch(
58+
console.error,
59+
);
6860
return Response.json({ success: true });
6961
} else if (type === "dataset") {
7062
const datasetSettingsString = formData.get("dataset_settings");

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const links = () => [{ rel: "stylesheet", href: polarisStyles }];
2222
export const loader = async () => {
2323
return {
2424
apiKey: process.env.SHOPIFY_API_KEY || "",
25-
trieveAuthUrl: process.env.TRIEVE_AUTH_URL!,
25+
trieveAuthUrl: process.env.REMIX_SERVER_URL!,
2626
shopifyThemeAppExtensionUuid: process.env.SHOPIFY_THEME_APP_EXTENSION_UUID,
2727
};
2828
};
-16.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)