2023-02-09 09:41:54 +00:00
|
|
|
|
import { useAppBridge, withAuthorization } from "@saleor/app-sdk/app-bridge";
|
|
|
|
|
import { SALEOR_API_URL_HEADER, SALEOR_AUTHORIZATION_BEARER_HEADER } from "@saleor/app-sdk/const";
|
2023-02-28 19:18:34 +00:00
|
|
|
|
|
2023-02-09 09:41:54 +00:00
|
|
|
|
import { ChangeEvent, SyntheticEvent, useEffect, useState } from "react";
|
|
|
|
|
|
2023-04-05 18:27:23 +00:00
|
|
|
|
import { useAppApi } from "../hooks/useAppApi";
|
2023-02-09 09:41:54 +00:00
|
|
|
|
import { AppColumnsLayout } from "../lib/ui/app-columns-layout";
|
2023-04-14 15:40:49 +00:00
|
|
|
|
import { useDashboardNotification } from "@saleor/apps-shared";
|
2023-06-28 07:45:35 +00:00
|
|
|
|
import { Box, BoxProps, Text, Input, Button } from "@saleor/macaw-ui/next";
|
2023-02-09 09:41:54 +00:00
|
|
|
|
|
|
|
|
|
interface ConfigurationField {
|
|
|
|
|
key: string;
|
|
|
|
|
value: string;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 07:45:35 +00:00
|
|
|
|
function Section(props: BoxProps) {
|
|
|
|
|
return <Box padding={4} {...props} />;
|
2023-02-09 09:41:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Instructions() {
|
|
|
|
|
const { appBridge } = useAppBridge();
|
|
|
|
|
|
|
|
|
|
const openExternalUrl = (url: string) => {
|
|
|
|
|
// eslint-disable-next-line
|
|
|
|
|
appBridge?.dispatch({
|
|
|
|
|
type: "redirect",
|
|
|
|
|
payload: {
|
|
|
|
|
newContext: true,
|
|
|
|
|
actionId: "redirect_from_klaviyo_app",
|
|
|
|
|
to: url,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<Section>
|
2023-06-28 07:45:35 +00:00
|
|
|
|
<Text as={"h3"} variant="heading">
|
2023-02-09 09:41:54 +00:00
|
|
|
|
How to set up
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</Text>
|
|
|
|
|
<Text as="p">App will send events as Klaviyo metrics each time Saleor Event occurs.</Text>
|
|
|
|
|
<Text as="p">
|
2023-02-09 09:41:54 +00:00
|
|
|
|
When first metric is sent, it should be available in Klaviyo to build on top of.
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</Text>
|
|
|
|
|
<Text as="p">
|
2023-02-09 09:41:54 +00:00
|
|
|
|
Metric name can be customized, PUBLIC_TOKEN must be provided to enable the app.
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</Text>
|
|
|
|
|
<Text as={"h3"} variant="heading">
|
|
|
|
|
Useful links
|
|
|
|
|
</Text>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>
|
|
|
|
|
<a
|
2023-02-09 09:41:54 +00:00
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
openExternalUrl("https://github.com/saleor/saleor-app-klaviyo");
|
|
|
|
|
}}
|
|
|
|
|
href="https://github.com/saleor/saleor-app-klaviyo"
|
|
|
|
|
>
|
|
|
|
|
Visit repository & readme
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<Text as={"h3"} variant="heading">
|
|
|
|
|
How to configure
|
|
|
|
|
</Text>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>
|
|
|
|
|
<a
|
2023-02-09 09:41:54 +00:00
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
openExternalUrl(
|
|
|
|
|
"https://help.klaviyo.com/hc/en-us/articles/115005062267-How-to-Manage-Your-Account-s-API-Keys"
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
href="https://help.klaviyo.com/hc/en-us/articles/115005062267-How-to-Manage-Your-Account-s-API-Keys"
|
|
|
|
|
>
|
|
|
|
|
Read about public tokens
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<a
|
2023-02-09 09:41:54 +00:00
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
openExternalUrl("https://www.klaviyo.com/account#api-keys-tab");
|
|
|
|
|
}}
|
|
|
|
|
href="https://www.klaviyo.com/account#api-keys-tab"
|
|
|
|
|
>
|
|
|
|
|
Get public token here
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
<a
|
2023-02-09 09:41:54 +00:00
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
|
|
|
|
openExternalUrl(
|
|
|
|
|
"https://help.klaviyo.com/hc/en-us/articles/115005076787-Guide-to-Managing-Your-Metrics"
|
|
|
|
|
);
|
|
|
|
|
}}
|
|
|
|
|
href="https://help.klaviyo.com/hc/en-us/articles/115005076787-Guide-to-Managing-Your-Metrics"
|
|
|
|
|
>
|
|
|
|
|
Read about metrics
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</a>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
2023-02-09 09:41:54 +00:00
|
|
|
|
</Section>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Configuration() {
|
|
|
|
|
const { appBridgeState } = useAppBridge();
|
2023-04-14 15:40:49 +00:00
|
|
|
|
const { notifySuccess, notifyError } = useDashboardNotification();
|
2023-02-09 09:41:54 +00:00
|
|
|
|
const [configuration, setConfiguration] = useState<ConfigurationField[]>();
|
|
|
|
|
|
|
|
|
|
const { data: configurationData, error } = useAppApi({
|
|
|
|
|
url: "/api/configuration",
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (configurationData && !configuration) {
|
|
|
|
|
setConfiguration(configurationData.data);
|
|
|
|
|
}
|
|
|
|
|
}, [configurationData, configuration]);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* TODO Rewrite to tRPC
|
|
|
|
|
*/
|
|
|
|
|
const handleSubmit = (event: SyntheticEvent) => {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
|
|
fetch("/api/configuration", {
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: [
|
|
|
|
|
["content-type", "application/json"],
|
|
|
|
|
[SALEOR_API_URL_HEADER, appBridgeState?.saleorApiUrl!],
|
|
|
|
|
[SALEOR_AUTHORIZATION_BEARER_HEADER, appBridgeState?.token!],
|
|
|
|
|
],
|
|
|
|
|
body: JSON.stringify({ data: configuration }),
|
|
|
|
|
})
|
|
|
|
|
.then(async (response) => {
|
|
|
|
|
if (response.status !== 200) {
|
|
|
|
|
throw new Error("Error saving configuration data");
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-14 15:40:49 +00:00
|
|
|
|
notifySuccess("Success", "Configuration updated successfully");
|
2023-02-09 09:41:54 +00:00
|
|
|
|
})
|
|
|
|
|
.catch(async () => {
|
2023-04-14 15:40:49 +00:00
|
|
|
|
await notifyError(
|
|
|
|
|
"Configuration update failed. Ensure fields are filled correctly and you have MANAGE_APPS permission"
|
|
|
|
|
);
|
2023-02-09 09:41:54 +00:00
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const onChange = (event: ChangeEvent) => {
|
|
|
|
|
const { name, value } = event.target as HTMLInputElement;
|
2023-04-18 13:10:00 +00:00
|
|
|
|
|
2023-02-09 09:41:54 +00:00
|
|
|
|
setConfiguration((prev) =>
|
|
|
|
|
prev!.map((prevField) => (prevField.key === name ? { ...prevField, value } : prevField))
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (error) {
|
|
|
|
|
console.error("Can't establish connection with the App API: ", error);
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<h1>⚠️ Can't connect with the App API</h1>
|
|
|
|
|
You may see this error because:
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Internet connection has been lost</li>
|
|
|
|
|
<li>
|
|
|
|
|
Application installation process is still in progress. If you use Vercel, you may need
|
|
|
|
|
to wait for redeployment of the app - try again in a minute.
|
|
|
|
|
</li>
|
|
|
|
|
<li>
|
|
|
|
|
Application is misconfigured. If you would like to know more how auth configuration is
|
|
|
|
|
kept,{" "}
|
|
|
|
|
<a
|
|
|
|
|
href="https://github.com/saleor/saleor-app-sdk/blob/main/docs/apl.md"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noreferrer"
|
|
|
|
|
>
|
|
|
|
|
go to APL documentation
|
|
|
|
|
</a>
|
|
|
|
|
.
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (configuration === undefined) {
|
2023-06-28 07:45:35 +00:00
|
|
|
|
return <p>Loading...</p>;
|
2023-02-09 09:41:54 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
2023-02-28 19:18:34 +00:00
|
|
|
|
<AppColumnsLayout>
|
|
|
|
|
<div />
|
|
|
|
|
<Section>
|
2023-06-28 07:45:35 +00:00
|
|
|
|
<Text variant={"heading"} marginBottom={4} as={"h2"}>
|
|
|
|
|
Klaviyo configuration
|
|
|
|
|
</Text>
|
|
|
|
|
<Box as={"form"} display={"grid"} gap={4} gridAutoFlow={"row"} onSubmit={handleSubmit}>
|
2023-02-28 19:18:34 +00:00
|
|
|
|
{configuration!.map(({ key, value }) => (
|
2023-06-28 07:45:35 +00:00
|
|
|
|
<div key={key}>
|
|
|
|
|
<Input label={key} name={key} onChange={onChange} value={value} />
|
2023-02-09 09:41:54 +00:00
|
|
|
|
</div>
|
2023-02-28 19:18:34 +00:00
|
|
|
|
))}
|
|
|
|
|
<div>
|
2023-06-28 07:45:35 +00:00
|
|
|
|
<Button type="submit" variant="primary">
|
|
|
|
|
Save
|
|
|
|
|
</Button>
|
2023-02-28 19:18:34 +00:00
|
|
|
|
</div>
|
2023-06-28 07:45:35 +00:00
|
|
|
|
</Box>
|
2023-02-28 19:18:34 +00:00
|
|
|
|
</Section>
|
|
|
|
|
<Instructions />
|
|
|
|
|
</AppColumnsLayout>
|
2023-02-09 09:41:54 +00:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 07:45:35 +00:00
|
|
|
|
export default Configuration;
|