@manta-eu/react 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/components/chart/AreaChart.d.ts.map +1 -1
- package/dist/components/chart/AreaChart.js +4 -6
- package/dist/components/chart/BarChart.d.ts.map +1 -1
- package/dist/components/chart/BarChart.js +5 -6
- package/dist/components/chart/ComposedChart.d.ts.map +1 -1
- package/dist/components/chart/ComposedChart.js +15 -7
- package/dist/components/chart/LineChart.d.ts.map +1 -1
- package/dist/components/chart/LineChart.js +4 -6
- package/dist/components/chart/annotations.d.ts +4 -0
- package/dist/components/chart/annotations.d.ts.map +1 -1
- package/dist/components/chart/annotations.js +10 -2
- package/dist/components/chart/chart-schemas.d.ts +1960 -54
- package/dist/components/chart/chart-schemas.d.ts.map +1 -1
- package/dist/components/chart/chart-schemas.js +137 -15
- package/dist/components/chart/series.d.ts +28 -0
- package/dist/components/chart/series.d.ts.map +1 -0
- package/dist/components/chart/series.js +61 -0
- package/dist/components/chart/stacks.d.ts +9 -0
- package/dist/components/chart/stacks.d.ts.map +1 -0
- package/dist/components/chart/stacks.js +11 -0
- package/dist/components/chat-view/ChatHeaders.d.ts.map +1 -1
- package/dist/components/chat-view/ChatHeaders.js +2 -2
- package/dist/components/layouts/Sidebar.d.ts.map +1 -1
- package/dist/components/layouts/Sidebar.js +14 -3
- package/dist/components/planning/ActioningView.d.ts.map +1 -1
- package/dist/components/planning/ActioningView.js +7 -49
- package/dist/components/planning/ExecutionSectionItem.d.ts +6 -4
- package/dist/components/planning/ExecutionSectionItem.d.ts.map +1 -1
- package/dist/components/planning/ExecutionSectionItem.js +2 -2
- package/dist/components/planning/ExecutionSections.d.ts +6 -4
- package/dist/components/planning/ExecutionSections.d.ts.map +1 -1
- package/dist/components/planning/ExecutionSections.js +2 -2
- package/dist/components/planning/ManualActionCard.d.ts +14 -8
- package/dist/components/planning/ManualActionCard.d.ts.map +1 -1
- package/dist/components/planning/ManualActionCard.js +44 -24
- package/dist/components/planning/ManualActionList.d.ts +22 -0
- package/dist/components/planning/ManualActionList.d.ts.map +1 -0
- package/dist/components/planning/ManualActionList.js +35 -0
- package/dist/components/planning/manual-action-targets.d.ts +4 -0
- package/dist/components/planning/manual-action-targets.d.ts.map +1 -0
- package/dist/components/planning/manual-action-targets.js +19 -0
- package/dist/components/sidebar/index.d.ts +2 -0
- package/dist/components/sidebar/index.d.ts.map +1 -1
- package/dist/components/sidebar/index.js +1 -0
- package/dist/components/sidebar/nav-user.d.ts +1 -1
- package/dist/components/sidebar/nav-user.d.ts.map +1 -1
- package/dist/components/sidebar/nav-user.js +3 -3
- package/dist/components/sidebar/user-avatar.d.ts +7 -0
- package/dist/components/sidebar/user-avatar.d.ts.map +1 -0
- package/dist/components/sidebar/user-avatar.js +9 -0
- package/dist/globals.css +6 -13
- package/dist/hooks/use-connection-problems.d.ts.map +1 -1
- package/dist/hooks/use-manual-actions.d.ts +13 -3
- package/dist/hooks/use-manual-actions.d.ts.map +1 -1
- package/dist/hooks/use-manual-actions.js +16 -10
- package/dist/hooks/useAuth.d.ts +1 -0
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +7 -1
- package/dist/hooks/useConversations.d.ts +1 -0
- package/dist/hooks/useConversations.d.ts.map +1 -1
- package/dist/hooks/useResolveManualAction.d.ts +14 -0
- package/dist/hooks/useResolveManualAction.d.ts.map +1 -0
- package/dist/hooks/useResolveManualAction.js +47 -0
- package/dist/hooks/useValidateActionPlan.d.ts.map +1 -1
- package/dist/ldo-ui.d.ts +2 -1
- package/dist/ldo-ui.d.ts.map +1 -1
- package/dist/ldo-ui.js +2 -1
- package/dist/lib/build-config.d.ts +2 -0
- package/dist/lib/build-config.d.ts.map +1 -1
- package/dist/lib/build-config.js +2 -0
- package/dist/lib/chat-types.d.ts +1 -0
- package/dist/lib/chat-types.d.ts.map +1 -1
- package/dist/lib/datastore-route-table.d.ts +2 -0
- package/dist/lib/datastore-route-table.d.ts.map +1 -1
- package/dist/lib/datastore-route-table.js +3 -1
- package/dist/lib/datastore-routes.d.ts +7 -1
- package/dist/lib/datastore-routes.d.ts.map +1 -1
- package/dist/lib/datastore-routes.js +7 -2
- package/dist/lib/decode-chart-entities.d.ts.map +1 -1
- package/dist/lib/decode-chart-entities.js +5 -1
- package/dist/lib/manual-actions.d.ts +1 -0
- package/dist/lib/manual-actions.d.ts.map +1 -1
- package/dist/lib/manual-actions.js +4 -1
- package/dist/lib/structured-data/types.d.ts +7 -2
- package/dist/lib/structured-data/types.d.ts.map +1 -1
- package/dist/providers/ChatManagerProvider.d.ts.map +1 -1
- package/dist/providers/ChatManagerProvider.js +18 -16
- package/dist/providers/NavExtrasProvider.d.ts +23 -0
- package/dist/providers/NavExtrasProvider.d.ts.map +1 -0
- package/dist/providers/NavExtrasProvider.js +10 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -0
- package/dist/routes/explain/ExplainEmpty.d.ts.map +1 -1
- package/dist/routes/explain/ExplainEmpty.js +2 -1
- package/dist/routes/integrations/catalog-shape.d.ts +2 -1
- package/dist/routes/integrations/catalog-shape.d.ts.map +1 -1
- package/dist/routes/integrations/components/AddIntegrationModal.d.ts.map +1 -1
- package/dist/routes/integrations/components/AddIntegrationModal.js +1 -1
- package/dist/routes/integrations/components/MantaSyncPluginDownload.d.ts +13 -0
- package/dist/routes/integrations/components/MantaSyncPluginDownload.d.ts.map +1 -0
- package/dist/routes/integrations/components/MantaSyncPluginDownload.js +23 -0
- package/dist/routes/integrations/components/connect-forms/ConnectFormHeader.d.ts +1 -1
- package/dist/routes/integrations/components/connect-forms/ConnectFormHeader.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/ConnectWizardShell.d.ts +1 -1
- package/dist/routes/integrations/components/connect-forms/ConnectWizardShell.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/ConnectionStringInput.d.ts +11 -0
- package/dist/routes/integrations/components/connect-forms/ConnectionStringInput.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/ConnectionStringInput.js +49 -0
- package/dist/routes/integrations/components/connect-forms/DashConnectForm.d.ts +7 -0
- package/dist/routes/integrations/components/connect-forms/DashConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/DashConnectForm.js +87 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.d.ts +20 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionConnectForm.js +144 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionFieldInputs.d.ts +8 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionFieldInputs.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/DataConnectionFieldInputs.js +44 -0
- package/dist/routes/integrations/components/connect-forms/FigmaConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/FigmaConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/FigmaConnectForm.js +20 -0
- package/dist/routes/integrations/components/connect-forms/GmailConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/GmailConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/GmailConnectForm.js +11 -0
- package/dist/routes/integrations/components/connect-forms/GoogleAdsConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/GoogleAdsConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/GoogleAdsConnectForm.js +37 -0
- package/dist/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/GoogleAnalyticsConnectForm.js +37 -0
- package/dist/routes/integrations/components/connect-forms/ImportStartedNotice.d.ts +21 -0
- package/dist/routes/integrations/components/connect-forms/ImportStartedNotice.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/ImportStartedNotice.js +25 -0
- package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.d.ts +45 -0
- package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/InferalCredentialConnectForm.js +187 -0
- package/dist/routes/integrations/components/connect-forms/KlaviyoConnectForm.d.ts +6 -0
- package/dist/routes/integrations/components/connect-forms/KlaviyoConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/KlaviyoConnectForm.js +68 -0
- package/dist/routes/integrations/components/connect-forms/LinkedinConnectForm.d.ts +10 -0
- package/dist/routes/integrations/components/connect-forms/LinkedinConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/LinkedinConnectForm.js +124 -0
- package/dist/routes/integrations/components/connect-forms/MetaAdsConnectForm.d.ts +14 -0
- package/dist/routes/integrations/components/connect-forms/MetaAdsConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/MetaAdsConnectForm.js +183 -0
- package/dist/routes/integrations/components/connect-forms/OAuthConnectLink.d.ts +10 -0
- package/dist/routes/integrations/components/connect-forms/OAuthConnectLink.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/OAuthConnectLink.js +17 -0
- package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.d.ts +45 -0
- package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/OAuthSetupConnectForm.js +136 -0
- package/dist/routes/integrations/components/connect-forms/OAuthSingleAccountConnectForm.d.ts +23 -0
- package/dist/routes/integrations/components/connect-forms/OAuthSingleAccountConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/OAuthSingleAccountConnectForm.js +63 -0
- package/dist/routes/integrations/components/connect-forms/ShopifyConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/ShopifyConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/ShopifyConnectForm.js +14 -0
- package/dist/routes/integrations/components/connect-forms/SlackConnectForm.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/SlackConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/SlackConnectForm.js +10 -0
- package/dist/routes/integrations/components/connect-forms/TriplewhaleConnectForm.d.ts +5 -0
- package/dist/routes/integrations/components/connect-forms/TriplewhaleConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/TriplewhaleConnectForm.js +35 -0
- package/dist/routes/integrations/components/connect-forms/WoocommerceConnectForm.d.ts +5 -0
- package/dist/routes/integrations/components/connect-forms/WoocommerceConnectForm.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/WoocommerceConnectForm.js +47 -0
- package/dist/routes/integrations/components/connect-forms/connection-string-fields.d.ts +13 -0
- package/dist/routes/integrations/components/connect-forms/connection-string-fields.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/connection-string-fields.js +110 -0
- package/dist/routes/integrations/components/connect-forms/dash-folder-tree.d.ts +6 -0
- package/dist/routes/integrations/components/connect-forms/dash-folder-tree.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/dash-folder-tree.js +14 -0
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts +35 -0
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/data-connection-fields.js +88 -0
- package/dist/routes/integrations/components/connect-forms/google-ads-account-tree.d.ts +11 -0
- package/dist/routes/integrations/components/connect-forms/google-ads-account-tree.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/google-ads-account-tree.js +36 -0
- package/dist/routes/integrations/components/connect-forms/google-analytics-property-tree.d.ts +6 -0
- package/dist/routes/integrations/components/connect-forms/google-analytics-property-tree.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/google-analytics-property-tree.js +34 -0
- package/dist/routes/integrations/components/connect-forms/oauth-setup-phase.d.ts +12 -0
- package/dist/routes/integrations/components/connect-forms/oauth-setup-phase.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/oauth-setup-phase.js +33 -0
- package/dist/routes/integrations/components/connect-forms/setup-account-unavailable-reason.d.ts +3 -0
- package/dist/routes/integrations/components/connect-forms/setup-account-unavailable-reason.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/setup-account-unavailable-reason.js +8 -0
- package/dist/routes/integrations/components/connect-forms/types.d.ts +5 -1
- package/dist/routes/integrations/components/connect-forms/types.d.ts.map +1 -1
- package/dist/routes/integrations/components/connect-forms/useConnectWizard.d.ts +19 -0
- package/dist/routes/integrations/components/connect-forms/useConnectWizard.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/useConnectWizard.js +28 -0
- package/dist/routes/integrations/components/connect-forms/useConnectedExternalIds.d.ts +4 -0
- package/dist/routes/integrations/components/connect-forms/useConnectedExternalIds.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/useConnectedExternalIds.js +17 -0
- package/dist/routes/integrations/components/connect-forms/useWindowFocusPoll.d.ts +7 -0
- package/dist/routes/integrations/components/connect-forms/useWindowFocusPoll.d.ts.map +1 -0
- package/dist/routes/integrations/components/connect-forms/useWindowFocusPoll.js +18 -0
- package/dist/routes/integrations/connect-forms.d.ts +16 -0
- package/dist/routes/integrations/connect-forms.d.ts.map +1 -0
- package/dist/routes/integrations/connect-forms.js +14 -0
- package/dist/routes/integrations/filter-connected-providers.d.ts +3 -0
- package/dist/routes/integrations/filter-connected-providers.d.ts.map +1 -0
- package/dist/routes/integrations/filter-connected-providers.js +15 -0
- package/dist/routes/integrations/overview.d.ts +3 -0
- package/dist/routes/integrations/overview.d.ts.map +1 -0
- package/dist/routes/integrations/overview.js +2 -0
- package/dist/routes/integrations/use-connected-account-entities.d.ts +10 -0
- package/dist/routes/integrations/use-connected-account-entities.d.ts.map +1 -0
- package/dist/routes/integrations/use-connected-account-entities.js +29 -0
- package/dist/routes/memories/components/EmptyStates.d.ts.map +1 -1
- package/dist/routes/memories/components/EmptyStates.js +2 -1
- package/dist/routes/plans/components/actionPlansTableConfig.d.ts +12 -12
- package/package.json +47 -8
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GQLMetaSetupStateEnum, type GQLMetaAdAccount } from "@manta-eu/client";
|
|
2
|
+
import type { ConnectFormProps } from "./types.js";
|
|
3
|
+
type Phase = "idle" | "awaitingOAuth" | "loadingAccounts" | "pickingAccount" | "submitting" | "done" | "failed";
|
|
4
|
+
type DerivePhaseInput = {
|
|
5
|
+
states: GQLMetaSetupStateEnum[] | undefined;
|
|
6
|
+
hasStartedOAuth: boolean;
|
|
7
|
+
hasSeenActiveState: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function derivePhase({ states, hasStartedOAuth, hasSeenActiveState }: DerivePhaseInput): Phase;
|
|
10
|
+
export declare function isSelectableAccount(account: GQLMetaAdAccount, alreadyConnectedExternalIds: ReadonlySet<string>, reconnectableExternalIds?: ReadonlySet<string>): boolean;
|
|
11
|
+
export declare function accountHint(account: GQLMetaAdAccount, alreadyConnectedExternalIds: ReadonlySet<string>, reconnectableExternalIds?: ReadonlySet<string>): string | undefined;
|
|
12
|
+
export declare function MetaAdsConnectForm(props: ConnectFormProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=MetaAdsConnectForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MetaAdsConnectForm.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/MetaAdsConnectForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,qBAAqB,EAIrB,KAAK,gBAAgB,EACtB,MAAM,kBAAkB,CAAC;AAY1B,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,SAAS,CAAC;AAY9D,KAAK,KAAK,GAAG,MAAM,GAAG,eAAe,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEhH,KAAK,gBAAgB,GAAG;IACtB,MAAM,EAAE,qBAAqB,EAAE,GAAG,SAAS,CAAC;IAC5C,eAAe,EAAE,OAAO,CAAC;IACzB,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAoBF,wBAAgB,WAAW,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,kBAAkB,EAAE,EAAE,gBAAgB,GAAG,KAAK,CAYpG;AAkBD,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,gBAAgB,EACzB,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAAC,EAChD,wBAAwB,GAAE,WAAW,CAAC,MAAM,CAAa,GACxD,OAAO,CAKT;AAED,wBAAgB,WAAW,CACzB,OAAO,EAAE,gBAAgB,EACzB,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAAC,EAChD,wBAAwB,GAAE,WAAW,CAAC,MAAM,CAAa,GACxD,MAAM,GAAG,SAAS,CAKpB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,2CA6HzD"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { GQLIntegration, GQLMetaSetupStateEnum, useConnectedAccountsQuery, useMetaSetupConnectMutation, useMetaSetupProgressQuery, } from "@manta-eu/client";
|
|
3
|
+
import { parseError } from "@manta-eu/client/shared/error-utils";
|
|
4
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
5
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
6
|
+
import { ArrowLeft } from "lucide-react";
|
|
7
|
+
import { useEffect, useRef, useState } from "react";
|
|
8
|
+
import { toast } from "sonner";
|
|
9
|
+
import { match } from "ts-pattern";
|
|
10
|
+
import { ConnectFormHeader } from "./ConnectFormHeader.js";
|
|
11
|
+
import { ImportStartedNotice } from "./ImportStartedNotice.js";
|
|
12
|
+
import { OAuthConnectLink } from "./OAuthConnectLink.js";
|
|
13
|
+
import { unavailableReasonLabel } from "./setup-account-unavailable-reason.js";
|
|
14
|
+
import { useReconnectableExternalIds } from "./useConnectedExternalIds.js";
|
|
15
|
+
import { useWindowFocusPoll } from "./useWindowFocusPoll.js";
|
|
16
|
+
import { Banner } from "#components/banner/index";
|
|
17
|
+
import { Button } from "#components/button/index";
|
|
18
|
+
import { Loader } from "#components/loader/index";
|
|
19
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "#components/select/index";
|
|
20
|
+
import { cn } from "#lib/utils";
|
|
21
|
+
import { useMantaClient } from "#providers/index";
|
|
22
|
+
const pollIntervalMs = 3000;
|
|
23
|
+
const statePriority = [
|
|
24
|
+
GQLMetaSetupStateEnum.Finished,
|
|
25
|
+
GQLMetaSetupStateEnum.FatallyFailed,
|
|
26
|
+
GQLMetaSetupStateEnum.TimedOut,
|
|
27
|
+
GQLMetaSetupStateEnum.ConnectingAccounts,
|
|
28
|
+
GQLMetaSetupStateEnum.SelectingAccounts,
|
|
29
|
+
GQLMetaSetupStateEnum.FetchingAccounts,
|
|
30
|
+
GQLMetaSetupStateEnum.Setup,
|
|
31
|
+
];
|
|
32
|
+
const terminalStates = [
|
|
33
|
+
GQLMetaSetupStateEnum.Finished,
|
|
34
|
+
GQLMetaSetupStateEnum.FatallyFailed,
|
|
35
|
+
GQLMetaSetupStateEnum.TimedOut,
|
|
36
|
+
];
|
|
37
|
+
const activePhases = ["awaitingOAuth", "loadingAccounts", "pickingAccount", "submitting"];
|
|
38
|
+
export function derivePhase({ states, hasStartedOAuth, hasSeenActiveState }) {
|
|
39
|
+
const defaultPhase = hasStartedOAuth ? "awaitingOAuth" : "idle";
|
|
40
|
+
const dominant = statePriority.find((state) => states?.includes(state));
|
|
41
|
+
if (dominant && terminalStates.includes(dominant) && !hasSeenActiveState)
|
|
42
|
+
return defaultPhase;
|
|
43
|
+
return match(dominant)
|
|
44
|
+
.returnType()
|
|
45
|
+
.with(GQLMetaSetupStateEnum.Finished, () => "done")
|
|
46
|
+
.with(GQLMetaSetupStateEnum.FatallyFailed, GQLMetaSetupStateEnum.TimedOut, () => "failed")
|
|
47
|
+
.with(GQLMetaSetupStateEnum.ConnectingAccounts, () => "submitting")
|
|
48
|
+
.with(GQLMetaSetupStateEnum.SelectingAccounts, () => "pickingAccount")
|
|
49
|
+
.with(GQLMetaSetupStateEnum.FetchingAccounts, GQLMetaSetupStateEnum.Setup, () => "loadingAccounts")
|
|
50
|
+
.otherwise(() => defaultPhase);
|
|
51
|
+
}
|
|
52
|
+
function isReconnectable(account, reconnectableExternalIds) {
|
|
53
|
+
return isPresent(account.externalId) && reconnectableExternalIds.has(account.externalId);
|
|
54
|
+
}
|
|
55
|
+
function isAlreadyConnected(account, alreadyConnectedExternalIds, reconnectableExternalIds) {
|
|
56
|
+
return (isPresent(account.externalId) &&
|
|
57
|
+
alreadyConnectedExternalIds.has(account.externalId) &&
|
|
58
|
+
!isReconnectable(account, reconnectableExternalIds));
|
|
59
|
+
}
|
|
60
|
+
export function isSelectableAccount(account, alreadyConnectedExternalIds, reconnectableExternalIds = new Set()) {
|
|
61
|
+
return (account.isConnectable === true &&
|
|
62
|
+
!isAlreadyConnected(account, alreadyConnectedExternalIds, reconnectableExternalIds));
|
|
63
|
+
}
|
|
64
|
+
export function accountHint(account, alreadyConnectedExternalIds, reconnectableExternalIds = new Set()) {
|
|
65
|
+
if (account.isConnectable !== true)
|
|
66
|
+
return unavailableReasonLabel(account.unavailableReason);
|
|
67
|
+
if (isReconnectable(account, reconnectableExternalIds))
|
|
68
|
+
return "Reconnect";
|
|
69
|
+
if (isAlreadyConnected(account, alreadyConnectedExternalIds, reconnectableExternalIds))
|
|
70
|
+
return "Already connected";
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
export function MetaAdsConnectForm(props) {
|
|
74
|
+
const { onBack, onChanged, onDismiss, provider, resumedFromOAuth = false, importNotice } = props;
|
|
75
|
+
const { mantaClient } = useMantaClient();
|
|
76
|
+
const queryClient = useQueryClient();
|
|
77
|
+
const [hasStartedOAuth, setHasStartedOAuth] = useState(resumedFromOAuth);
|
|
78
|
+
const [hasSeenActiveState, setHasSeenActiveState] = useState(resumedFromOAuth);
|
|
79
|
+
const [selectedAccountId, setSelectedAccountId] = useState("");
|
|
80
|
+
const hasDismissedRef = useRef(false);
|
|
81
|
+
const progressQuery = useMetaSetupProgressQuery(mantaClient, undefined, { staleTime: 0 });
|
|
82
|
+
const progress = progressQuery.data?.metaSetupProgress;
|
|
83
|
+
const phase = derivePhase({ states: progress?.state, hasStartedOAuth, hasSeenActiveState });
|
|
84
|
+
useWindowFocusPoll(progressQuery.refetch, { enabled: activePhases.includes(phase), intervalMs: pollIntervalMs });
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
const states = progress?.state;
|
|
87
|
+
if (!isPresent(states))
|
|
88
|
+
return;
|
|
89
|
+
const isActive = states.some((state) => !terminalStates.includes(state) && state !== GQLMetaSetupStateEnum.NotFound);
|
|
90
|
+
if (isActive)
|
|
91
|
+
setHasSeenActiveState(true);
|
|
92
|
+
}, [progress]);
|
|
93
|
+
const connectedAccountsQuery = useConnectedAccountsQuery(mantaClient, undefined);
|
|
94
|
+
const alreadyConnectedExternalIds = new Set((connectedAccountsQuery.data?.connectedAccounts ?? [])
|
|
95
|
+
.filter((account) => account.integration === GQLIntegration.Meta)
|
|
96
|
+
.map((account) => account.externalId));
|
|
97
|
+
const reconnectableExternalIds = useReconnectableExternalIds(GQLIntegration.Meta);
|
|
98
|
+
const connectMutation = useMetaSetupConnectMutation(mantaClient);
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (phase !== "done" || hasDismissedRef.current)
|
|
101
|
+
return;
|
|
102
|
+
hasDismissedRef.current = true;
|
|
103
|
+
toast.success("Meta connected");
|
|
104
|
+
onChanged();
|
|
105
|
+
if (!importNotice)
|
|
106
|
+
onDismiss();
|
|
107
|
+
}, [phase, onChanged, onDismiss, importNotice]);
|
|
108
|
+
function resetProgressCache() {
|
|
109
|
+
queryClient.setQueryData(useMetaSetupProgressQuery.getKey(), {
|
|
110
|
+
metaSetupProgress: { state: [], accounts: null, lastError: null },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
function handleOpened() {
|
|
114
|
+
resetProgressCache();
|
|
115
|
+
setHasSeenActiveState(false);
|
|
116
|
+
setHasStartedOAuth(true);
|
|
117
|
+
}
|
|
118
|
+
async function handleSubmit() {
|
|
119
|
+
if (!selectedAccountId)
|
|
120
|
+
return;
|
|
121
|
+
try {
|
|
122
|
+
await connectMutation.mutateAsync({ accountIds: [selectedAccountId] });
|
|
123
|
+
await progressQuery.refetch();
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const info = parseError(err, "Failed to connect Meta");
|
|
127
|
+
toast.error(info.message, { description: info.description });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function handleRetry() {
|
|
131
|
+
setSelectedAccountId("");
|
|
132
|
+
hasDismissedRef.current = false;
|
|
133
|
+
resetProgressCache();
|
|
134
|
+
setHasStartedOAuth(false);
|
|
135
|
+
setHasSeenActiveState(false);
|
|
136
|
+
}
|
|
137
|
+
return (_jsxs("div", { className: "grid gap-6", children: [_jsx(ConnectFormHeader, { provider: provider, status: phase === "done" ? "Connected" : "Not connected" }), _jsx("div", { className: "min-h-40", children: match(phase)
|
|
138
|
+
.with("idle", () => _jsx(IdleView, {}))
|
|
139
|
+
.with("awaitingOAuth", () => _jsx(AwaitingOAuthView, {}))
|
|
140
|
+
.with("loadingAccounts", () => _jsx(LoadingAccountsView, {}))
|
|
141
|
+
.with("pickingAccount", () => (_jsx(PickingAccountView, { accounts: progress?.accounts ?? [], alreadyConnectedExternalIds: alreadyConnectedExternalIds, reconnectableExternalIds: reconnectableExternalIds, selectedAccountId: selectedAccountId, onSelect: setSelectedAccountId })))
|
|
142
|
+
.with("submitting", () => _jsx(SubmittingView, {}))
|
|
143
|
+
.with("done", () => _jsx(DoneView, { providerName: provider.name, importNotice: importNotice }))
|
|
144
|
+
.with("failed", () => (_jsx(FailedView, { title: progress?.lastError?.title, message: progress?.lastError?.message, onRetry: handleRetry })))
|
|
145
|
+
.exhaustive() }), _jsxs("div", { className: cn("flex items-center pt-2", phase === "done" ? "justify-end" : "justify-between"), children: [phase !== "done" && (_jsx(Button, { variant: "tertiary", onClick: onBack, icon: ArrowLeft, children: "Back" })), phase === "idle" && (_jsx(OAuthConnectLink, { href: "/oauth/meta/start", label: "Continue with Meta", onOpened: handleOpened })), phase === "pickingAccount" && (_jsx(Button, { onClick: () => void handleSubmit(), disabled: !selectedAccountId, isLoading: connectMutation.isPending, children: "Connect account" })), phase === "done" && importNotice && _jsx(Button, { onClick: onDismiss, children: "Done" })] })] }));
|
|
146
|
+
}
|
|
147
|
+
function IdleView() {
|
|
148
|
+
return (_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: "Sign in with Meta" }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "We'll take you to Meta sign-in so you can grant Manta access to your Meta ad accounts." })] }));
|
|
149
|
+
}
|
|
150
|
+
function AwaitingOAuthView() {
|
|
151
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: "Waiting for Meta sign-in" }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "Finish signing in to Meta. We'll pick it up automatically when you come back." })] }), _jsxs("div", { className: "flex items-center gap-2 text-muted-foreground typography-caption", role: "status", "aria-live": "polite", children: [_jsx(Loader, { className: "size-4", "aria-hidden": true }), " Listening for the connection\u2026"] })] }));
|
|
152
|
+
}
|
|
153
|
+
function LoadingAccountsView() {
|
|
154
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: "Loading your Meta ad accounts" }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "This usually takes a few seconds." })] }), _jsxs("div", { className: "flex items-center gap-2 text-muted-foreground typography-caption", role: "status", "aria-live": "polite", children: [_jsx(Loader, { className: "size-4", "aria-hidden": true }), " Fetching accounts\u2026"] })] }));
|
|
155
|
+
}
|
|
156
|
+
function PickingAccountView(props) {
|
|
157
|
+
const { accounts, alreadyConnectedExternalIds, reconnectableExternalIds, selectedAccountId, onSelect } = props;
|
|
158
|
+
if (!isPresent(accounts)) {
|
|
159
|
+
return (_jsx(Banner, { type: "warning", label: "We couldn't find any Meta ad accounts on this Facebook identity. Sign in with a different account or check your Meta ad account access." }));
|
|
160
|
+
}
|
|
161
|
+
const selectableCount = accounts.filter((account) => isSelectableAccount(account, alreadyConnectedExternalIds, reconnectableExternalIds)).length;
|
|
162
|
+
if (selectableCount === 0) {
|
|
163
|
+
return (_jsx(Banner, { type: "info", label: "No connectable Meta ad accounts remain on this Facebook identity \u2014 they are already connected or unavailable. Sign in with a different Facebook account to connect a new one." }));
|
|
164
|
+
}
|
|
165
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: "Pick the Meta ad account to connect" }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "Choose the account whose campaigns Manta should manage." })] }), _jsxs(Select, { value: selectedAccountId, onValueChange: onSelect, children: [_jsx(SelectTrigger, { label: "Meta ad account", id: "meta-ad-account", className: "w-full h-10", children: _jsx(SelectValue, { placeholder: "Select an account" }) }), _jsx(SelectContent, { children: accounts.map((account) => {
|
|
166
|
+
const label = account.name ?? account.id;
|
|
167
|
+
const hint = accountHint(account, alreadyConnectedExternalIds, reconnectableExternalIds);
|
|
168
|
+
return (_jsx(SelectItem, { value: account.id, disabled: !isSelectableAccount(account, alreadyConnectedExternalIds, reconnectableExternalIds), children: hint ? `${label} · ${hint}` : label }, account.id));
|
|
169
|
+
}) })] })] }));
|
|
170
|
+
}
|
|
171
|
+
function SubmittingView() {
|
|
172
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: "Connecting your account" }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "Hold tight \u2014 this usually takes a few seconds." })] }), _jsxs("div", { className: "flex items-center gap-2 text-muted-foreground typography-caption", role: "status", "aria-live": "polite", children: [_jsx(Loader, { className: "size-4", "aria-hidden": true }), " Provisioning\u2026"] })] }));
|
|
173
|
+
}
|
|
174
|
+
function DoneView(props) {
|
|
175
|
+
const { providerName, importNotice } = props;
|
|
176
|
+
if (importNotice)
|
|
177
|
+
return _jsx(ImportStartedNotice, { providerName: providerName, notice: importNotice });
|
|
178
|
+
return (_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: "Meta connected" }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "Closing this dialog\u2026" })] }));
|
|
179
|
+
}
|
|
180
|
+
function FailedView(props) {
|
|
181
|
+
const { title, message, onRetry } = props;
|
|
182
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsx(Banner, { type: "error", size: "loose", label: title ?? "Meta connection failed", description: message ?? undefined }), _jsx(Button, { onClick: onRetry, children: "Try again" })] }));
|
|
183
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ButtonVariant } from "#components/button/index";
|
|
2
|
+
type OAuthConnectLinkProps = {
|
|
3
|
+
href: string;
|
|
4
|
+
label: string;
|
|
5
|
+
onOpened: () => void;
|
|
6
|
+
variant?: ButtonVariant;
|
|
7
|
+
};
|
|
8
|
+
export declare function OAuthConnectLink(props: OAuthConnectLinkProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=OAuthConnectLink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthConnectLink.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/OAuthConnectLink.tsx"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAGpE,KAAK,qBAAqB,GAAG;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB,CAAC;AAOF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CAkB5D"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { withDatastoreQueryParam } from "@manta-eu/client/shared/datastore-path";
|
|
3
|
+
import { Link } from "#components/button/index";
|
|
4
|
+
import { useMantaClient } from "#providers/index";
|
|
5
|
+
const middleMouseButton = 1;
|
|
6
|
+
// Query param, not /d/<id> in the path: the provider's callback URL is fixed, and a prefixed
|
|
7
|
+
// start route isn't reliably reachable past the SW (vite.config.ts).
|
|
8
|
+
// useMantaClient(), not useActiveDatastore(): also covers an explicit datastoreId prop (embedded usage).
|
|
9
|
+
export function OAuthConnectLink(props) {
|
|
10
|
+
const { href, label, onOpened, variant = "primary" } = props;
|
|
11
|
+
const { datastoreId } = useMantaClient();
|
|
12
|
+
const scopedHref = withDatastoreQueryParam(href, datastoreId);
|
|
13
|
+
return (_jsx(Link, { href: scopedHref, variant: variant, onClick: onOpened, onAuxClick: (event) => {
|
|
14
|
+
if (event.button === middleMouseButton)
|
|
15
|
+
onOpened();
|
|
16
|
+
}, children: label }));
|
|
17
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { GQLGoogleSetupStateEnum, type GQLIntegration } from "@manta-eu/client";
|
|
2
|
+
import type { ConnectFormProps } from "./types.js";
|
|
3
|
+
import { type TreeMultiSelectProps, type TreeSelectItem } from "#components/tree-multi-select/index";
|
|
4
|
+
export type SetupRow = {
|
|
5
|
+
id: string;
|
|
6
|
+
};
|
|
7
|
+
export type SetupProgress<Row extends SetupRow> = {
|
|
8
|
+
state: GQLGoogleSetupStateEnum[];
|
|
9
|
+
rows?: Row[] | null;
|
|
10
|
+
lastError?: {
|
|
11
|
+
title?: string | null;
|
|
12
|
+
message: string;
|
|
13
|
+
} | null;
|
|
14
|
+
};
|
|
15
|
+
export type OAuthSetup<Row extends SetupRow> = {
|
|
16
|
+
progress?: SetupProgress<Row>;
|
|
17
|
+
refetchProgress: () => unknown;
|
|
18
|
+
resetProgress: () => void;
|
|
19
|
+
connect: (ids: string[]) => Promise<unknown>;
|
|
20
|
+
isConnecting: boolean;
|
|
21
|
+
};
|
|
22
|
+
export type SetupTreeOptions = Pick<TreeMultiSelectProps, "defaultCollapsed" | "includeDescendants">;
|
|
23
|
+
export type SetupCopy = {
|
|
24
|
+
providerName: string;
|
|
25
|
+
identityProviderName: string;
|
|
26
|
+
entitySingular: string;
|
|
27
|
+
entityPlural: string;
|
|
28
|
+
signInDescription: string;
|
|
29
|
+
pickTitle: string;
|
|
30
|
+
pickDescription: string;
|
|
31
|
+
noEntitiesLabel: string;
|
|
32
|
+
noneConnectableLabel: string;
|
|
33
|
+
retryGuidance?: string;
|
|
34
|
+
};
|
|
35
|
+
export type OAuthSetupConnectFormProps<Row extends SetupRow> = ConnectFormProps & {
|
|
36
|
+
integration: GQLIntegration;
|
|
37
|
+
oauthStartPath: string;
|
|
38
|
+
copy: SetupCopy;
|
|
39
|
+
setup: OAuthSetup<Row>;
|
|
40
|
+
treeItems: (rows: Row[], alreadyConnectedExternalIds: ReadonlySet<string>, reconnectableExternalIds: ReadonlySet<string>) => TreeSelectItem[];
|
|
41
|
+
treeOptions?: SetupTreeOptions;
|
|
42
|
+
resumesUnfinishedSetup?: boolean;
|
|
43
|
+
};
|
|
44
|
+
export declare function OAuthSetupConnectForm<Row extends SetupRow>(props: OAuthSetupConnectFormProps<Row>): import("react/jsx-runtime").JSX.Element;
|
|
45
|
+
//# sourceMappingURL=OAuthSetupConnectForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthSetupConnectForm.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/OAuthSetupConnectForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAWhF,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,SAAS,CAAC;AAM9D,OAAO,EAAmB,KAAK,oBAAoB,EAAE,KAAK,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAKtH,MAAM,MAAM,QAAQ,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtC,MAAM,MAAM,aAAa,CAAC,GAAG,SAAS,QAAQ,IAAI;IAChD,KAAK,EAAE,uBAAuB,EAAE,CAAC;IACjC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC/D,CAAC;AAGF,MAAM,MAAM,UAAU,CAAC,GAAG,SAAS,QAAQ,IAAI;IAC7C,QAAQ,CAAC,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC9B,eAAe,EAAE,MAAM,OAAO,CAAC;IAC/B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,kBAAkB,GAAG,oBAAoB,CAAC,CAAC;AAGrG,MAAM,MAAM,SAAS,GAAG;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,oBAAoB,EAAE,MAAM,CAAC;IAE7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,0BAA0B,CAAC,GAAG,SAAS,QAAQ,IAAI,gBAAgB,GAAG;IAChF,WAAW,EAAE,cAAc,CAAC;IAC5B,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;IACvB,SAAS,EAAE,CACT,IAAI,EAAE,GAAG,EAAE,EACX,2BAA2B,EAAE,WAAW,CAAC,MAAM,CAAC,EAChD,wBAAwB,EAAE,WAAW,CAAC,MAAM,CAAC,KAC1C,cAAc,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,gBAAgB,CAAC;IAC/B,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,GAAG,SAAS,QAAQ,EAAE,KAAK,EAAE,0BAA0B,CAAC,GAAG,CAAC,2CAmHjG"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { GQLGoogleSetupStateEnum } from "@manta-eu/client";
|
|
3
|
+
import { parseError } from "@manta-eu/client/shared/error-utils";
|
|
4
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
5
|
+
import { ArrowLeft } from "lucide-react";
|
|
6
|
+
import { useEffect, useRef, useState } from "react";
|
|
7
|
+
import { toast } from "sonner";
|
|
8
|
+
import { match } from "ts-pattern";
|
|
9
|
+
import { ConnectFormHeader } from "./ConnectFormHeader.js";
|
|
10
|
+
import { ImportStartedNotice } from "./ImportStartedNotice.js";
|
|
11
|
+
import { activePhases, derivePhase, terminalStates } from "./oauth-setup-phase.js";
|
|
12
|
+
import { OAuthConnectLink } from "./OAuthConnectLink.js";
|
|
13
|
+
import { useConnectedExternalIds, useReconnectableExternalIds } from "./useConnectedExternalIds.js";
|
|
14
|
+
import { useWindowFocusPoll } from "./useWindowFocusPoll.js";
|
|
15
|
+
import { Banner } from "#components/banner/index";
|
|
16
|
+
import { Button } from "#components/button/index";
|
|
17
|
+
import { Loader } from "#components/loader/index";
|
|
18
|
+
import { TreeMultiSelect } from "#components/tree-multi-select/index";
|
|
19
|
+
import { cn } from "#lib/utils";
|
|
20
|
+
const pollIntervalMs = 3000;
|
|
21
|
+
export function OAuthSetupConnectForm(props) {
|
|
22
|
+
const { onBack, onChanged, onDismiss, provider, resumedFromOAuth = false, importNotice } = props;
|
|
23
|
+
const { integration, oauthStartPath, copy, setup, treeItems, treeOptions, resumesUnfinishedSetup } = props;
|
|
24
|
+
const { providerName } = copy;
|
|
25
|
+
const [hasStartedOAuth, setHasStartedOAuth] = useState(resumedFromOAuth);
|
|
26
|
+
const [hasSeenActiveState, setHasSeenActiveState] = useState(resumedFromOAuth);
|
|
27
|
+
const [selectedIds, setSelectedIds] = useState(new Set());
|
|
28
|
+
const hasDismissedRef = useRef(false);
|
|
29
|
+
const states = setup.progress?.state;
|
|
30
|
+
const phase = derivePhase({ states, hasStartedOAuth, hasSeenActiveState, resumesUnfinishedSetup });
|
|
31
|
+
useWindowFocusPoll(setup.refetchProgress, { enabled: activePhases.includes(phase), intervalMs: pollIntervalMs });
|
|
32
|
+
const alreadyConnectedExternalIds = useConnectedExternalIds(integration);
|
|
33
|
+
const reconnectableExternalIds = useReconnectableExternalIds(integration);
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!isPresent(states))
|
|
36
|
+
return;
|
|
37
|
+
const isActive = states.some((state) => !terminalStates.includes(state) && state !== GQLGoogleSetupStateEnum.NotFound);
|
|
38
|
+
if (isActive)
|
|
39
|
+
setHasSeenActiveState(true);
|
|
40
|
+
}, [states]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (phase !== "done" || hasDismissedRef.current)
|
|
43
|
+
return;
|
|
44
|
+
hasDismissedRef.current = true;
|
|
45
|
+
toast.success(`${providerName} connected`);
|
|
46
|
+
onChanged();
|
|
47
|
+
if (!importNotice)
|
|
48
|
+
onDismiss();
|
|
49
|
+
}, [phase, onChanged, onDismiss, providerName, importNotice]);
|
|
50
|
+
function handleOpened() {
|
|
51
|
+
setup.resetProgress();
|
|
52
|
+
setHasSeenActiveState(false);
|
|
53
|
+
setHasStartedOAuth(true);
|
|
54
|
+
}
|
|
55
|
+
function toggleId(id, checked) {
|
|
56
|
+
setSelectedIds((current) => {
|
|
57
|
+
const next = new Set(current);
|
|
58
|
+
if (checked)
|
|
59
|
+
next.add(id);
|
|
60
|
+
else
|
|
61
|
+
next.delete(id);
|
|
62
|
+
return next;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async function handleSubmit() {
|
|
66
|
+
if (selectedIds.size === 0)
|
|
67
|
+
return;
|
|
68
|
+
try {
|
|
69
|
+
await setup.connect([...selectedIds]);
|
|
70
|
+
await setup.refetchProgress();
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
const info = parseError(err, `Failed to connect ${providerName}`);
|
|
74
|
+
toast.error(info.message, { description: info.description });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function handleRetry() {
|
|
78
|
+
setSelectedIds(new Set());
|
|
79
|
+
hasDismissedRef.current = false;
|
|
80
|
+
setup.resetProgress();
|
|
81
|
+
setHasStartedOAuth(false);
|
|
82
|
+
setHasSeenActiveState(false);
|
|
83
|
+
}
|
|
84
|
+
return (_jsxs("div", { className: "grid gap-6", children: [_jsx(ConnectFormHeader, { provider: provider, status: phase === "done" ? "Connected" : "Not connected" }), _jsx("div", { className: "min-h-40", children: match(phase)
|
|
85
|
+
.with("idle", () => _jsx(IdleView, { copy: copy, oauthStartPath: oauthStartPath, onOpened: handleOpened }))
|
|
86
|
+
.with("awaitingOAuth", () => _jsx(AwaitingOAuthView, { copy: copy }))
|
|
87
|
+
.with("loadingAccounts", () => _jsx(LoadingEntitiesView, { copy: copy }))
|
|
88
|
+
.with("pickingAccount", () => (_jsx(PickingEntityView, { copy: copy, items: treeItems(setup.progress?.rows ?? [], alreadyConnectedExternalIds, reconnectableExternalIds), selectedIds: selectedIds, onToggle: toggleId, treeOptions: treeOptions })))
|
|
89
|
+
.with("submitting", () => _jsx(SubmittingView, { copy: copy }))
|
|
90
|
+
.with("done", () => _jsx(DoneView, { copy: copy, importNotice: importNotice }))
|
|
91
|
+
.with("failed", () => (_jsx(FailedView, { copy: copy, title: setup.progress?.lastError?.title, message: setup.progress?.lastError?.message, onRetry: handleRetry })))
|
|
92
|
+
.exhaustive() }), _jsxs("div", { className: cn("flex items-center pt-2", phase === "done" ? "justify-end" : "justify-between"), children: [phase !== "done" && (_jsx(Button, { variant: "tertiary", onClick: onBack, icon: ArrowLeft, children: "Back" })), phase === "pickingAccount" && (_jsx(Button, { onClick: () => void handleSubmit(), disabled: selectedIds.size === 0, isLoading: setup.isConnecting, children: selectedIds.size > 1
|
|
93
|
+
? `Connect ${selectedIds.size} ${copy.entityPlural}`
|
|
94
|
+
: `Connect ${copy.entitySingular}` })), phase === "done" && importNotice && _jsx(Button, { onClick: onDismiss, children: "Done" })] })] }));
|
|
95
|
+
}
|
|
96
|
+
function IdleView(props) {
|
|
97
|
+
const { copy, oauthStartPath, onOpened } = props;
|
|
98
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsxs("h2", { className: "typography-large-body-semibold text-default-foreground", children: ["Sign in with ", copy.identityProviderName] }), _jsx("p", { className: "typography-caption text-muted-foreground", children: copy.signInDescription })] }), _jsx(OAuthConnectLink, { href: oauthStartPath, label: `Continue with ${copy.identityProviderName}`, onOpened: onOpened })] }));
|
|
99
|
+
}
|
|
100
|
+
function AwaitingOAuthView(props) {
|
|
101
|
+
const { copy } = props;
|
|
102
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsxs("h2", { className: "typography-large-body-semibold text-default-foreground", children: ["Waiting for ", copy.identityProviderName, " sign-in"] }), _jsxs("p", { className: "typography-caption text-muted-foreground", children: ["Finish signing in to ", copy.identityProviderName, ". We'll pick it up automatically when you come back."] })] }), _jsx(StatusLine, { label: "Listening for the connection\u2026" })] }));
|
|
103
|
+
}
|
|
104
|
+
function LoadingEntitiesView(props) {
|
|
105
|
+
const { copy } = props;
|
|
106
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsxs("h2", { className: "typography-large-body-semibold text-default-foreground", children: ["Loading your ", copy.providerName, " ", copy.entityPlural] }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "This usually takes a few seconds." })] }), _jsx(StatusLine, { label: `Fetching ${copy.entityPlural}…` })] }));
|
|
107
|
+
}
|
|
108
|
+
function PickingEntityView(props) {
|
|
109
|
+
const { copy, items, selectedIds, onToggle, treeOptions } = props;
|
|
110
|
+
if (!isPresent(items)) {
|
|
111
|
+
return _jsx(Banner, { type: "warning", label: copy.noEntitiesLabel });
|
|
112
|
+
}
|
|
113
|
+
const selectableCount = items.filter((item) => item.selectable && item.disabled !== true).length;
|
|
114
|
+
if (selectableCount === 0) {
|
|
115
|
+
return _jsx(Banner, { type: "info", label: copy.noneConnectableLabel });
|
|
116
|
+
}
|
|
117
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsx("h2", { className: "typography-large-body-semibold text-default-foreground", children: copy.pickTitle }), _jsx("p", { className: "typography-caption text-muted-foreground", children: copy.pickDescription })] }), _jsx(TreeMultiSelect, { items: items, selectedIds: selectedIds, onToggle: onToggle, searchPlaceholder: `Search ${copy.entityPlural}...`, ...treeOptions })] }));
|
|
118
|
+
}
|
|
119
|
+
function SubmittingView(props) {
|
|
120
|
+
const { copy } = props;
|
|
121
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsxs("div", { className: "grid gap-1", children: [_jsxs("h2", { className: "typography-large-body-semibold text-default-foreground", children: ["Connecting your ", copy.entityPlural] }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "Hold tight \u2014 this usually takes a few seconds." })] }), _jsx(StatusLine, { label: "Provisioning\u2026" })] }));
|
|
122
|
+
}
|
|
123
|
+
function DoneView(props) {
|
|
124
|
+
const { copy, importNotice } = props;
|
|
125
|
+
if (importNotice)
|
|
126
|
+
return _jsx(ImportStartedNotice, { providerName: copy.providerName, notice: importNotice });
|
|
127
|
+
return (_jsxs("div", { className: "grid gap-1", children: [_jsxs("h2", { className: "typography-large-body-semibold text-default-foreground", children: [copy.providerName, " connected"] }), _jsx("p", { className: "typography-caption text-muted-foreground", children: "Closing this dialog\u2026" })] }));
|
|
128
|
+
}
|
|
129
|
+
function FailedView(props) {
|
|
130
|
+
const { copy, title, message, onRetry } = props;
|
|
131
|
+
return (_jsxs("div", { className: "grid gap-4", children: [_jsx(Banner, { type: "error", size: "loose", label: title ?? `${copy.providerName} connection failed`, description: message ?? undefined }), isPresent(copy.retryGuidance) ? (_jsx("p", { className: "typography-caption text-muted-foreground", children: copy.retryGuidance })) : (_jsx(Button, { onClick: onRetry, children: "Try again" }))] }));
|
|
132
|
+
}
|
|
133
|
+
function StatusLine(props) {
|
|
134
|
+
const { label } = props;
|
|
135
|
+
return (_jsxs("div", { className: "flex items-center gap-2 text-muted-foreground typography-caption", role: "status", "aria-live": "polite", children: [_jsx(Loader, { className: "size-4", "aria-hidden": true }), " ", label] }));
|
|
136
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type GQLIntegration } from "@manta-eu/client";
|
|
2
|
+
import type { ReactNode } from "react";
|
|
3
|
+
import type { ConnectFormProps } from "./types.js";
|
|
4
|
+
export type ConnectSuccessStep = {
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
content: ReactNode;
|
|
8
|
+
};
|
|
9
|
+
export type OAuthSingleAccountConnectFormProps = ConnectFormProps & {
|
|
10
|
+
integration: GQLIntegration;
|
|
11
|
+
startHref: string;
|
|
12
|
+
ctaLabel: string;
|
|
13
|
+
stepTitle: string;
|
|
14
|
+
stepDescription: string;
|
|
15
|
+
supportingInfo: string;
|
|
16
|
+
permissions: string[];
|
|
17
|
+
waitingLabel: string;
|
|
18
|
+
connectedToastLabel: string;
|
|
19
|
+
successStep?: ConnectSuccessStep;
|
|
20
|
+
precedingSteps?: number;
|
|
21
|
+
};
|
|
22
|
+
export declare function OAuthSingleAccountConnectForm(props: OAuthSingleAccountConnectFormProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=OAuthSingleAccountConnectForm.d.ts.map
|
package/dist/routes/integrations/components/connect-forms/OAuthSingleAccountConnectForm.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuthSingleAccountConnectForm.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/OAuthSingleAccountConnectForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6D,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAKhD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kCAAkC,GAAG,gBAAgB,GAAG;IAClE,WAAW,EAAE,cAAc,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAEjC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAQF,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,kCAAkC,2CA2ItF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useConnectedAccountsQuery } from "@manta-eu/client";
|
|
3
|
+
import { isPresent } from "@manta-eu/lib/present";
|
|
4
|
+
import { InfoIcon } from "lucide-react";
|
|
5
|
+
import { useEffect, useRef, useState } from "react";
|
|
6
|
+
import { toast } from "sonner";
|
|
7
|
+
import { ConnectWizardShell } from "./ConnectWizardShell.js";
|
|
8
|
+
import { importStartedSuccessStep } from "./ImportStartedNotice.js";
|
|
9
|
+
import { OAuthConnectLink } from "./OAuthConnectLink.js";
|
|
10
|
+
import { useWindowFocusPoll } from "./useWindowFocusPoll.js";
|
|
11
|
+
import { Button } from "#components/button/index";
|
|
12
|
+
import { useMantaClient } from "#providers/index";
|
|
13
|
+
function connectedExternalIds(data, integration) {
|
|
14
|
+
return (data?.connectedAccounts ?? [])
|
|
15
|
+
.filter((account) => account.integration === integration)
|
|
16
|
+
.map((account) => account.externalId);
|
|
17
|
+
}
|
|
18
|
+
export function OAuthSingleAccountConnectForm(props) {
|
|
19
|
+
const { onBack, onChanged, onDismiss, provider, integration, startHref, ctaLabel, stepTitle, stepDescription, supportingInfo, permissions, waitingLabel, connectedToastLabel, successStep: explicitSuccessStep, importNotice, resumedFromOAuth = false, precedingSteps = 0, } = props;
|
|
20
|
+
const successStep = explicitSuccessStep ?? (importNotice ? importStartedSuccessStep(provider.name, importNotice) : undefined);
|
|
21
|
+
const { mantaClient } = useMantaClient();
|
|
22
|
+
const hasSuccessStep = successStep !== undefined;
|
|
23
|
+
const totalSteps = precedingSteps + (hasSuccessStep ? 2 : 1);
|
|
24
|
+
const [waiting, setWaiting] = useState(resumedFromOAuth && hasSuccessStep);
|
|
25
|
+
const [connected, setConnected] = useState(false);
|
|
26
|
+
const knownExternalIds = useRef(new Set());
|
|
27
|
+
const settled = useRef(false);
|
|
28
|
+
const { data, error, refetch } = useConnectedAccountsQuery(mantaClient, undefined, { enabled: false });
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
void refetch();
|
|
31
|
+
}, [refetch]);
|
|
32
|
+
useWindowFocusPoll(refetch, { enabled: waiting });
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (!waiting || settled.current)
|
|
35
|
+
return;
|
|
36
|
+
const connected = connectedExternalIds(data, integration).some((id) => !knownExternalIds.current.has(id));
|
|
37
|
+
if (!connected)
|
|
38
|
+
return;
|
|
39
|
+
settled.current = true;
|
|
40
|
+
setWaiting(false);
|
|
41
|
+
toast.success(connectedToastLabel);
|
|
42
|
+
onChanged();
|
|
43
|
+
if (hasSuccessStep) {
|
|
44
|
+
setConnected(true);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
onDismiss();
|
|
48
|
+
}
|
|
49
|
+
}, [waiting, data, integration, connectedToastLabel, onChanged, onDismiss, hasSuccessStep]);
|
|
50
|
+
function handleOpened() {
|
|
51
|
+
knownExternalIds.current = new Set(connectedExternalIds(data, integration));
|
|
52
|
+
setWaiting(true);
|
|
53
|
+
}
|
|
54
|
+
const accountConnected = isPresent(connectedExternalIds(data, integration));
|
|
55
|
+
const resumeUnanswered = resumedFromOAuth && hasSuccessStep && data === undefined && !isPresent(error);
|
|
56
|
+
if (successStep && (connected || (resumedFromOAuth && accountConnected))) {
|
|
57
|
+
return (_jsx(ConnectWizardShell, { provider: provider, status: "Connected", totalSteps: totalSteps, currentStep: precedingSteps + 2, stepTitle: successStep.title, stepDescription: successStep.description, primaryAction: _jsx(Button, { variant: "secondary", onClick: onDismiss, children: "Done" }), children: successStep.content }));
|
|
58
|
+
}
|
|
59
|
+
if (successStep && resumeUnanswered) {
|
|
60
|
+
return (_jsx(ConnectWizardShell, { provider: provider, status: "Checking", totalSteps: totalSteps, currentStep: precedingSteps + 2, stepTitle: successStep.title, primaryAction: _jsx(Button, { variant: "secondary", disabled: true, children: "Done" }), children: _jsx("p", { className: "typography-caption text-muted-foreground", role: "status", "aria-live": "polite", children: "Confirming the connection\u2026" }) }));
|
|
61
|
+
}
|
|
62
|
+
return (_jsx(ConnectWizardShell, { provider: provider, totalSteps: totalSteps, currentStep: precedingSteps + 1, stepTitle: stepTitle, stepDescription: stepDescription, supportingInfo: _jsxs("div", { className: "rounded-xl bg-info p-3 flex items-start gap-2 typography-small", children: [_jsx(InfoIcon, { size: 20, className: "shrink-0 mt-0.5 text-info-foreground" }), _jsx("p", { className: "text-muted-foreground", children: supportingInfo })] }), onBack: onBack, primaryAction: _jsx(OAuthConnectLink, { href: startHref, label: ctaLabel, onOpened: handleOpened }), children: _jsxs("div", { className: "grid gap-2", children: [_jsx("p", { className: "typography-small text-default-foreground", children: "Manta will be able to:" }), _jsx("ul", { className: "grid gap-1.5", children: permissions.map((permission) => (_jsxs("li", { className: "flex items-start gap-2 typography-caption text-muted-foreground", children: [_jsx("span", { "aria-hidden": true, className: "mt-2 size-1.5 shrink-0 rounded-full bg-muted-foreground" }), permission] }, permission))) }), waiting && (_jsx("p", { className: "typography-caption text-muted-foreground", role: "status", "aria-live": "polite", children: waitingLabel }))] }) }));
|
|
63
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShopifyConnectForm.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/ShopifyConnectForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAWhD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,2CAezD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { GQLIntegration } from "@manta-eu/client";
|
|
3
|
+
import { OAuthSingleAccountConnectForm } from "./OAuthSingleAccountConnectForm.js";
|
|
4
|
+
const shopifyPermissions = [
|
|
5
|
+
"Read your orders, including historical ones.",
|
|
6
|
+
"Read your products, variants, and collections.",
|
|
7
|
+
"Read your customers and their contact details.",
|
|
8
|
+
"Read your inventory, locations, and sales channels.",
|
|
9
|
+
];
|
|
10
|
+
// No shop is passed: Shopify App Store requirement 2.3.1 forbids asking a merchant to type
|
|
11
|
+
// their store domain, so the start request omits it and Shopify picks the store instead.
|
|
12
|
+
export function ShopifyConnectForm(props) {
|
|
13
|
+
return (_jsx(OAuthSingleAccountConnectForm, { ...props, integration: GQLIntegration.Shopify, startHref: "/oauth/shopify/start", ctaLabel: "Continue with Shopify", stepTitle: "Connect your Shopify store", stepDescription: "Shopify will ask which store to connect, then bring you back here.", supportingInfo: "You'll be taken to Shopify to pick a store and approve access. You can revoke it any time from your Shopify admin.", permissions: shopifyPermissions, waitingLabel: "Waiting for you to finish connecting to Shopify\u2026", connectedToastLabel: "Shopify connected" }));
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SlackConnectForm.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/SlackConnectForm.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAOhD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,gBAAgB,2CAevD"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { GQLIntegration } from "@manta-eu/client";
|
|
3
|
+
import { OAuthSingleAccountConnectForm } from "./OAuthSingleAccountConnectForm.js";
|
|
4
|
+
const slackPermissions = [
|
|
5
|
+
"Read messages and channel activity you grant access to.",
|
|
6
|
+
"Post updates, reports, and alerts to the channels you choose.",
|
|
7
|
+
];
|
|
8
|
+
export function SlackConnectForm(props) {
|
|
9
|
+
return (_jsx(OAuthSingleAccountConnectForm, { ...props, integration: GQLIntegration.Slack, startHref: "/oauth/slack/start", ctaLabel: "Continue with Slack", stepTitle: "Connect your Slack workspace", stepDescription: "Manta will take you to Slack to ask for permission, then bring you back here.", supportingInfo: "You'll be taken to Slack to approve access. You can revoke it any time from your Slack workspace settings.", permissions: slackPermissions, waitingLabel: "Waiting for you to finish connecting to Slack\u2026", connectedToastLabel: "Slack connected" }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type InferalCredentialFormConfig } from "./InferalCredentialConnectForm.js";
|
|
2
|
+
import type { ConnectFormProps } from "./types.js";
|
|
3
|
+
export declare const triplewhaleConfig: InferalCredentialFormConfig<"shopId" | "apiKey">;
|
|
4
|
+
export declare function TriplewhaleConnectForm(props: ConnectFormProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
//# sourceMappingURL=TriplewhaleConnectForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TriplewhaleConnectForm.d.ts","sourceRoot":"","sources":["../../../../../src/routes/integrations/components/connect-forms/TriplewhaleConnectForm.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,2BAA2B,EAAE,MAAM,gCAAgC,CAAC;AAChH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,eAAO,MAAM,iBAAiB,EAAE,2BAA2B,CAAC,QAAQ,GAAG,QAAQ,CA6B9E,CAAC;AAEF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,gBAAgB,2CAE7D"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { InferalCredentialConnectForm } from "./InferalCredentialConnectForm.js";
|
|
3
|
+
export const triplewhaleConfig = {
|
|
4
|
+
providerName: "Triple Whale",
|
|
5
|
+
fieldIdPrefix: "triplewhale",
|
|
6
|
+
identifier: {
|
|
7
|
+
key: "shopId",
|
|
8
|
+
label: "Shop ID",
|
|
9
|
+
placeholder: "Your Triple Whale shop ID",
|
|
10
|
+
requiredMessage: "Shop ID is required",
|
|
11
|
+
stepTitle: "Find your Triple Whale shop ID",
|
|
12
|
+
stepDescription: "We use this to identify your store inside Triple Whale.",
|
|
13
|
+
},
|
|
14
|
+
secrets: {
|
|
15
|
+
title: "Generate an API key",
|
|
16
|
+
description: "Manta needs read access to Summary Page and Pixel Attribution.",
|
|
17
|
+
fields: [
|
|
18
|
+
{
|
|
19
|
+
key: "apiKey",
|
|
20
|
+
label: "API key",
|
|
21
|
+
placeholder: "Paste your API key",
|
|
22
|
+
requiredMessage: "API key is required",
|
|
23
|
+
secret: true,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
streamNamePlaceholder: "abc-store",
|
|
28
|
+
locationStepDescription: "Pick the region closest to your store for the lowest latency.",
|
|
29
|
+
buildProviderInput: (credentials) => ({
|
|
30
|
+
triplewhale: { shopId: credentials.shopId, apiKey: credentials.apiKey },
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
export function TriplewhaleConnectForm(props) {
|
|
34
|
+
return _jsx(InferalCredentialConnectForm, { ...props, config: triplewhaleConfig });
|
|
35
|
+
}
|