@gorgo/medusa-integration 0.0.3 → 0.0.5
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/.medusa/server/src/admin/index.js +546 -119
- package/.medusa/server/src/admin/index.mjs +549 -122
- package/.medusa/server/src/api/admin/integrations/[provider_id]/route.js +7 -2
- package/.medusa/server/src/api/admin/integrations/__tests__/helpers.unit.spec.d.ts +1 -0
- package/.medusa/server/src/api/admin/integrations/__tests__/helpers.unit.spec.js +30 -0
- package/.medusa/server/src/api/admin/integrations/_helpers.d.ts +3 -3
- package/.medusa/server/src/api/admin/integrations/_helpers.js +8 -8
- package/.medusa/server/src/api/admin/integrations/catalog/route.d.ts +3 -0
- package/.medusa/server/src/api/admin/integrations/catalog/route.js +10 -0
- package/.medusa/server/src/api/admin/integrations/middlewares.js +16 -1
- package/.medusa/server/src/api/admin/integrations/route.js +17 -3
- package/.medusa/server/src/api/admin/integrations/validators.d.ts +7 -0
- package/.medusa/server/src/api/admin/integrations/validators.js +8 -2
- package/.medusa/server/src/index.d.ts +1 -1
- package/.medusa/server/src/jobs/__tests__/test-integration-connections.unit.spec.d.ts +1 -0
- package/.medusa/server/src/jobs/__tests__/test-integration-connections.unit.spec.js +27 -0
- package/.medusa/server/src/jobs/test-integration-connections.d.ts +7 -0
- package/.medusa/server/src/jobs/test-integration-connections.js +21 -8
- package/.medusa/server/src/lib/__tests__/catalog-fallback.unit.spec.d.ts +1 -0
- package/.medusa/server/src/lib/__tests__/catalog-fallback.unit.spec.js +37 -0
- package/.medusa/server/src/lib/__tests__/catalog.unit.spec.d.ts +1 -0
- package/.medusa/server/src/lib/__tests__/catalog.unit.spec.js +71 -0
- package/.medusa/server/src/lib/catalog.d.ts +9 -0
- package/.medusa/server/src/lib/catalog.generated.d.ts +2 -0
- package/.medusa/server/src/lib/catalog.generated.js +88 -0
- package/.medusa/server/src/lib/catalog.js +55 -0
- package/.medusa/server/src/modules/integration/descriptor/__tests__/build-zod.unit.spec.js +43 -1
- package/.medusa/server/src/modules/integration/descriptor/__tests__/define.unit.spec.js +3 -3
- package/.medusa/server/src/modules/integration/descriptor/__tests__/introspect.unit.spec.js +3 -3
- package/.medusa/server/src/modules/integration/descriptor/__tests__/section-write.unit.spec.d.ts +1 -0
- package/.medusa/server/src/modules/integration/descriptor/__tests__/section-write.unit.spec.js +64 -0
- package/.medusa/server/src/modules/integration/descriptor/__tests__/validate.unit.spec.js +28 -2
- package/.medusa/server/src/modules/integration/descriptor/build-zod.js +7 -1
- package/.medusa/server/src/modules/integration/descriptor/define.d.ts +5 -5
- package/.medusa/server/src/modules/integration/descriptor/define.js +1 -1
- package/.medusa/server/src/modules/integration/descriptor/introspect.js +2 -2
- package/.medusa/server/src/modules/integration/descriptor/meta.d.ts +1 -1
- package/.medusa/server/src/modules/integration/descriptor/section-write.d.ts +10 -0
- package/.medusa/server/src/modules/integration/descriptor/section-write.js +24 -0
- package/.medusa/server/src/modules/integration/loaders/__tests__/package-meta.unit.spec.d.ts +1 -0
- package/.medusa/server/src/modules/integration/loaders/__tests__/package-meta.unit.spec.js +63 -0
- package/.medusa/server/src/modules/integration/loaders/load-providers.js +10 -38
- package/.medusa/server/src/modules/integration/loaders/package-meta.d.ts +22 -0
- package/.medusa/server/src/modules/integration/loaders/package-meta.js +45 -0
- package/.medusa/server/src/modules/integration/loaders/resolve-package-meta.d.ts +8 -0
- package/.medusa/server/src/modules/integration/loaders/resolve-package-meta.js +59 -0
- package/.medusa/server/src/modules/integration/migrations/Migration20260720130920.d.ts +5 -0
- package/.medusa/server/src/modules/integration/migrations/Migration20260720130920.js +18 -0
- package/.medusa/server/src/modules/integration/migrations/Migration20260724101525.d.ts +5 -0
- package/.medusa/server/src/modules/integration/migrations/Migration20260724101525.js +16 -0
- package/.medusa/server/src/modules/integration/models/integration.d.ts +9 -5
- package/.medusa/server/src/modules/integration/models/integration.js +3 -3
- package/.medusa/server/src/modules/integration/services/__tests__/integration-module.unit.spec.d.ts +1 -0
- package/.medusa/server/src/modules/integration/services/__tests__/integration-module.unit.spec.js +344 -0
- package/.medusa/server/src/modules/integration/services/__tests__/integration-provider.unit.spec.js +2 -2
- package/.medusa/server/src/modules/integration/services/integration-module.d.ts +48 -11
- package/.medusa/server/src/modules/integration/services/integration-module.js +56 -6
- package/.medusa/server/src/modules/integration/types/index.d.ts +11 -0
- package/.medusa/server/src/modules/integration/types/index.js +4 -2
- package/.medusa/server/src/modules/integration/utils/integration.d.ts +11 -7
- package/.medusa/server/src/modules/integration/utils/integration.js +12 -8
- package/.medusa/server/src/subscribers/__tests__/invalidate-options-cache.unit.spec.d.ts +1 -0
- package/.medusa/server/src/subscribers/__tests__/invalidate-options-cache.unit.spec.js +53 -0
- package/.medusa/server/src/types/http/integration/admin/entities.d.ts +39 -4
- package/.medusa/server/src/types/http/integration/admin/responses.d.ts +17 -2
- package/.medusa/server/src/types/integration/common.d.ts +3 -3
- package/.medusa/server/src/workflows/integration/steps/apply-integration-section.d.ts +1 -1
- package/.medusa/server/src/workflows/integration/steps/apply-integration-section.js +13 -20
- package/.medusa/server/src/workflows/integration/steps/set-integration-enabled.d.ts +1 -1
- package/.medusa/server/src/workflows/integration/steps/upsert-integration-record.d.ts +2 -2
- package/.medusa/server/src/workflows/integration/workflows/set-integration-enabled.d.ts +1 -1
- package/.medusa/server/src/workflows/integration/workflows/upsert-integration.js +2 -2
- package/README.md +41 -2
- package/README.ru.md +85 -0
- package/package.json +7 -3
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { defineRouteConfig } from "@medusajs/admin-sdk";
|
|
3
|
-
import { PuzzleSolid, CogSixTooth, Spinner, EllipsisHorizontal,
|
|
4
|
-
import { clx,
|
|
5
|
-
import { useQuery,
|
|
3
|
+
import { PuzzleSolid, CogSixTooth, Trash, Spinner, EllipsisHorizontal, PencilSquare, Plus } from "@medusajs/icons";
|
|
4
|
+
import { clx, createDataTableColumnHelper, usePrompt, toast, Text, Badge, useDataTable, Container, Heading, Button, DataTable, Tabs, StatusBadge, Label, Input, Select, Switch, Textarea, Drawer, DropdownMenu, IconButton, Copy } from "@medusajs/ui";
|
|
5
|
+
import { useQueryClient, useQuery, keepPreviousData, useMutation } from "@tanstack/react-query";
|
|
6
|
+
import React, { useState, useMemo } from "react";
|
|
6
7
|
import { useTranslation } from "react-i18next";
|
|
7
|
-
import {
|
|
8
|
+
import { useNavigate, useParams, Link } from "react-router-dom";
|
|
8
9
|
import Medusa from "@medusajs/js-sdk";
|
|
9
|
-
import React, { useState } from "react";
|
|
10
10
|
import { LayoutComposer } from "@medusajs/dashboard/components";
|
|
11
11
|
const sdk = new Medusa({
|
|
12
12
|
baseUrl: "/",
|
|
@@ -18,9 +18,23 @@ const sdk = new Medusa({
|
|
|
18
18
|
const IntegrationIcon = ({
|
|
19
19
|
src,
|
|
20
20
|
alt,
|
|
21
|
-
size = "base"
|
|
21
|
+
size = "base",
|
|
22
|
+
framed = true
|
|
22
23
|
}) => {
|
|
23
|
-
const dim = size === "small" ? "h-6 w-6" : "h-
|
|
24
|
+
const dim = size === "small" ? "h-6 w-6" : "h-10 w-10";
|
|
25
|
+
const [errored, setErrored] = useState(false);
|
|
26
|
+
const showImage = !!src && !errored;
|
|
27
|
+
if (showImage && !framed) {
|
|
28
|
+
return /* @__PURE__ */ jsx(
|
|
29
|
+
"img",
|
|
30
|
+
{
|
|
31
|
+
src,
|
|
32
|
+
alt,
|
|
33
|
+
className: clx("shrink-0 object-contain", dim),
|
|
34
|
+
onError: () => setErrored(true)
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
}
|
|
24
38
|
return /* @__PURE__ */ jsx(
|
|
25
39
|
"div",
|
|
26
40
|
{
|
|
@@ -28,50 +42,237 @@ const IntegrationIcon = ({
|
|
|
28
42
|
"bg-ui-bg-component shadow-borders-base flex shrink-0 items-center justify-center overflow-hidden rounded-md",
|
|
29
43
|
dim
|
|
30
44
|
),
|
|
31
|
-
children:
|
|
45
|
+
children: showImage ? /* @__PURE__ */ jsx(
|
|
46
|
+
"img",
|
|
47
|
+
{
|
|
48
|
+
src,
|
|
49
|
+
alt,
|
|
50
|
+
className: "h-full w-full object-cover",
|
|
51
|
+
onError: () => setErrored(true)
|
|
52
|
+
}
|
|
53
|
+
) : /* @__PURE__ */ jsx(PuzzleSolid, { className: "text-ui-fg-subtle" })
|
|
32
54
|
}
|
|
33
55
|
);
|
|
34
56
|
};
|
|
57
|
+
const PAGE_SIZE = 20;
|
|
58
|
+
const DOCS_URL = "https://docs.gorgojs.com/ru/medusa-plugins/integration-module";
|
|
59
|
+
const IntegrationCell = ({ item }) => {
|
|
60
|
+
const { t } = useTranslation();
|
|
61
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
62
|
+
/* @__PURE__ */ jsx(IntegrationIcon, { src: item.icon, alt: t(item.display_name), size: "base" }),
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
64
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
65
|
+
/* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", weight: "plus", children: t(item.display_name) }),
|
|
66
|
+
item.provider_id && /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: item.provider_id })
|
|
67
|
+
] }),
|
|
68
|
+
item.version && /* @__PURE__ */ jsxs(Text, { size: "xsmall", leading: "compact", className: "text-ui-fg-subtle", children: [
|
|
69
|
+
t("integration.meta.version", { version: item.version }),
|
|
70
|
+
item.author && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
71
|
+
" • ",
|
|
72
|
+
t("integration.meta.authorPrefix"),
|
|
73
|
+
" ",
|
|
74
|
+
item.author_url ? /* @__PURE__ */ jsx(
|
|
75
|
+
"a",
|
|
76
|
+
{
|
|
77
|
+
href: item.author_url,
|
|
78
|
+
target: "_blank",
|
|
79
|
+
rel: "noreferrer",
|
|
80
|
+
className: "text-ui-fg-interactive",
|
|
81
|
+
onClick: (e) => e.stopPropagation(),
|
|
82
|
+
children: item.author
|
|
83
|
+
}
|
|
84
|
+
) : item.author
|
|
85
|
+
] })
|
|
86
|
+
] })
|
|
87
|
+
] })
|
|
88
|
+
] });
|
|
89
|
+
};
|
|
90
|
+
const StatusCell = ({ item }) => {
|
|
91
|
+
const { t } = useTranslation();
|
|
92
|
+
const lifecycle = !item.is_configured ? { color: "grey", label: t("integration.status.notConfigured") } : !item.is_complete ? { color: "orange", label: t("integration.status.incomplete") } : item.is_enabled ? { color: "green", label: t("integration.status.enabled") } : { color: "grey", label: t("integration.status.disabled") };
|
|
93
|
+
const connection = item.has_test_connection ? item.last_test_status === "passed" ? { color: "green", label: t("integration.status.connected") } : item.last_test_status === "failed" ? { color: "red", label: t("integration.status.connectionFailed") } : null : null;
|
|
94
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-start gap-1", children: [
|
|
95
|
+
/* @__PURE__ */ jsx(StatusBadge, { color: lifecycle.color, children: lifecycle.label }),
|
|
96
|
+
connection && /* @__PURE__ */ jsx(StatusBadge, { color: connection.color, children: connection.label })
|
|
97
|
+
] });
|
|
98
|
+
};
|
|
99
|
+
const columnHelper = createDataTableColumnHelper();
|
|
35
100
|
const IntegrationsPage = () => {
|
|
36
101
|
const { t } = useTranslation();
|
|
102
|
+
const navigate = useNavigate();
|
|
103
|
+
const qc = useQueryClient();
|
|
104
|
+
const prompt = usePrompt();
|
|
105
|
+
const [activeTab, setActiveTab] = useState("all");
|
|
106
|
+
const [search, setSearch] = useState("");
|
|
107
|
+
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: PAGE_SIZE });
|
|
108
|
+
const category = activeTab === "all" ? void 0 : activeTab;
|
|
109
|
+
const queryParams = {
|
|
110
|
+
q: search || void 0,
|
|
111
|
+
category,
|
|
112
|
+
limit: pagination.pageSize,
|
|
113
|
+
offset: pagination.pageIndex * pagination.pageSize
|
|
114
|
+
};
|
|
37
115
|
const { data, isLoading } = useQuery({
|
|
38
|
-
queryKey: ["integration-overview"],
|
|
39
|
-
queryFn: () => sdk.client.fetch("/admin/integrations")
|
|
116
|
+
queryKey: ["integration-overview", queryParams],
|
|
117
|
+
queryFn: () => sdk.client.fetch("/admin/integrations", { query: queryParams }),
|
|
118
|
+
placeholderData: keepPreviousData
|
|
40
119
|
});
|
|
41
|
-
const
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
120
|
+
const integrations = (data == null ? void 0 : data.integrations) ?? [];
|
|
121
|
+
const count = (data == null ? void 0 : data.count) ?? 0;
|
|
122
|
+
const categories = (data == null ? void 0 : data.categories) ?? [];
|
|
123
|
+
const invalidate = () => qc.invalidateQueries({ queryKey: ["integration-overview"] });
|
|
124
|
+
const toggleEnabled = useMutation({
|
|
125
|
+
mutationFn: ({ providerId, next }) => sdk.client.fetch(`/admin/integrations/${providerId}/enable`, {
|
|
126
|
+
method: "POST",
|
|
127
|
+
body: { is_enabled: next }
|
|
128
|
+
}),
|
|
129
|
+
onSuccess: (_d, { next }) => {
|
|
130
|
+
toast.success(next ? t("integration.toast.enabled") : t("integration.toast.disabled"));
|
|
131
|
+
invalidate();
|
|
132
|
+
},
|
|
133
|
+
onError: (e) => toast.error((e == null ? void 0 : e.message) ?? t("integration.toast.updateFailed"))
|
|
134
|
+
});
|
|
135
|
+
const test = useMutation({
|
|
136
|
+
mutationFn: (providerId) => sdk.client.fetch(
|
|
137
|
+
`/admin/integrations/${providerId}/test-connection`,
|
|
138
|
+
{ method: "POST" }
|
|
139
|
+
),
|
|
140
|
+
onSuccess: (r) => {
|
|
141
|
+
r.status === "passed" ? toast.success(t("integration.toast.connectionOk")) : toast.warning(r.message ?? r.status);
|
|
142
|
+
invalidate();
|
|
143
|
+
},
|
|
144
|
+
onError: (e) => toast.error((e == null ? void 0 : e.message) ?? t("integration.toast.testFailed"))
|
|
145
|
+
});
|
|
146
|
+
const remove = useMutation({
|
|
147
|
+
mutationFn: (providerId) => sdk.client.fetch(`/admin/integrations/${providerId}`, { method: "DELETE" }),
|
|
148
|
+
onSuccess: () => {
|
|
149
|
+
toast.success(t("integration.toast.deleted"));
|
|
150
|
+
invalidate();
|
|
151
|
+
},
|
|
152
|
+
onError: (e) => toast.error((e == null ? void 0 : e.message) ?? t("integration.toast.deleteFailed"))
|
|
153
|
+
});
|
|
154
|
+
const onDelete = async (item) => {
|
|
155
|
+
const confirmed = await prompt({
|
|
156
|
+
title: t("integration.delete.title"),
|
|
157
|
+
description: t("integration.delete.description", { name: t(item.display_name) }),
|
|
158
|
+
confirmText: t("integration.actions.delete"),
|
|
159
|
+
cancelText: t("integration.actions.cancel")
|
|
160
|
+
});
|
|
161
|
+
if (confirmed) remove.mutate(item.provider_id);
|
|
162
|
+
};
|
|
163
|
+
const buildActions = (item) => {
|
|
164
|
+
const groups = [];
|
|
165
|
+
const primary = [];
|
|
166
|
+
if (item.is_configured) {
|
|
167
|
+
primary.push({
|
|
168
|
+
label: item.is_enabled ? t("integration.actions.disable") : t("integration.actions.enable"),
|
|
169
|
+
onClick: () => toggleEnabled.mutate({ providerId: item.provider_id, next: !item.is_enabled })
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
if (item.is_configured && item.has_test_connection && item.is_complete) {
|
|
173
|
+
primary.push({
|
|
174
|
+
label: t("integration.actions.test"),
|
|
175
|
+
onClick: () => test.mutate(item.provider_id)
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
if (primary.length) groups.push(primary);
|
|
179
|
+
if (item.is_configured) {
|
|
180
|
+
groups.push([
|
|
181
|
+
{
|
|
182
|
+
label: t("integration.actions.delete"),
|
|
183
|
+
icon: /* @__PURE__ */ jsx(Trash, {}),
|
|
184
|
+
onClick: () => onDelete(item)
|
|
185
|
+
}
|
|
186
|
+
]);
|
|
187
|
+
}
|
|
188
|
+
return groups.length > 0 ? groups : null;
|
|
189
|
+
};
|
|
190
|
+
const columns = useMemo(
|
|
191
|
+
() => [
|
|
192
|
+
columnHelper.display({
|
|
193
|
+
id: "integration",
|
|
194
|
+
header: t("integration.columns.integration"),
|
|
195
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(IntegrationCell, { item: row.original })
|
|
196
|
+
}),
|
|
197
|
+
columnHelper.display({
|
|
198
|
+
id: "description",
|
|
199
|
+
header: t("integration.columns.description"),
|
|
200
|
+
cell: ({ row }) => row.original.description ? /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle line-clamp-2", children: t(row.original.description) }) : null
|
|
201
|
+
}),
|
|
202
|
+
columnHelper.display({
|
|
203
|
+
id: "category",
|
|
204
|
+
header: t("integration.columns.category"),
|
|
205
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: t(`integration.categories.${row.original.category}`) })
|
|
206
|
+
}),
|
|
207
|
+
columnHelper.display({
|
|
208
|
+
id: "status",
|
|
209
|
+
header: t("integration.columns.status"),
|
|
210
|
+
cell: ({ row }) => /* @__PURE__ */ jsx(StatusCell, { item: row.original })
|
|
211
|
+
}),
|
|
212
|
+
columnHelper.action({
|
|
213
|
+
actions: (ctx) => buildActions(ctx.row.original)
|
|
214
|
+
})
|
|
215
|
+
],
|
|
216
|
+
// Safe to memo on [t] only: react-query keeps each mutation's `mutate` ref stable across
|
|
217
|
+
// renders (options updated internally), so the closed-over buildActions/mutations stay current.
|
|
218
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
219
|
+
[t]
|
|
220
|
+
);
|
|
221
|
+
const table = useDataTable({
|
|
222
|
+
data: integrations,
|
|
223
|
+
columns,
|
|
224
|
+
rowCount: count,
|
|
225
|
+
isLoading,
|
|
226
|
+
getRowId: (row) => row.provider_id,
|
|
227
|
+
onRowClick: (_e, row) => {
|
|
228
|
+
const item = row.original;
|
|
229
|
+
navigate(`/settings/integrations/${item.provider_id}`);
|
|
230
|
+
},
|
|
231
|
+
search: { state: search, onSearchChange: setSearch },
|
|
232
|
+
pagination: { state: pagination, onPaginationChange: setPagination }
|
|
233
|
+
});
|
|
234
|
+
const isFiltered = activeTab !== "all" || search.trim().length > 0;
|
|
47
235
|
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
48
|
-
/* @__PURE__ */
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
236
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between px-6 py-4", children: [
|
|
237
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
238
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: t("integration.list.title") }),
|
|
239
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.list.subtitle") })
|
|
240
|
+
] }),
|
|
241
|
+
/* @__PURE__ */ jsx(Button, { size: "small", variant: "primary", onClick: () => navigate("/settings/integrations/browse"), children: t("integration.list.browseIntegrations") })
|
|
242
|
+
] }),
|
|
243
|
+
/* @__PURE__ */ jsxs(DataTable, { instance: table, className: "[&_td]:py-3", children: [
|
|
244
|
+
/* @__PURE__ */ jsx(DataTable.Toolbar, { children: /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center justify-between gap-3", children: [
|
|
245
|
+
/* @__PURE__ */ jsx(
|
|
246
|
+
Tabs,
|
|
55
247
|
{
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
248
|
+
value: activeTab,
|
|
249
|
+
onValueChange: (v) => {
|
|
250
|
+
setActiveTab(v);
|
|
251
|
+
setPagination((p) => ({ ...p, pageIndex: 0 }));
|
|
252
|
+
},
|
|
253
|
+
children: /* @__PURE__ */ jsxs(Tabs.List, { children: [
|
|
254
|
+
/* @__PURE__ */ jsx(Tabs.Trigger, { value: "all", children: t("integration.list.tabs.all") }),
|
|
255
|
+
categories.map((c) => /* @__PURE__ */ jsx(Tabs.Trigger, { value: c, children: t(`integration.categories.${c}`) }, c))
|
|
256
|
+
] })
|
|
257
|
+
}
|
|
258
|
+
),
|
|
259
|
+
/* @__PURE__ */ jsx(DataTable.Search, { placeholder: t("integration.list.searchPlaceholder") })
|
|
260
|
+
] }) }),
|
|
261
|
+
/* @__PURE__ */ jsx(
|
|
262
|
+
DataTable.Table,
|
|
263
|
+
{
|
|
264
|
+
emptyState: {
|
|
265
|
+
empty: { heading: isFiltered ? t("integration.list.emptyFiltered") : t("integration.list.empty") },
|
|
266
|
+
filtered: { heading: t("integration.list.emptyFiltered") }
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
),
|
|
270
|
+
/* @__PURE__ */ jsx(DataTable.Pagination, {})
|
|
271
|
+
] }),
|
|
272
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center px-6 py-4", children: /* @__PURE__ */ jsxs("a", { href: DOCS_URL, target: "_blank", rel: "noreferrer", className: "text-ui-fg-base txt-small", children: [
|
|
273
|
+
t("integration.list.learnMore"),
|
|
274
|
+
" →"
|
|
275
|
+
] }) })
|
|
75
276
|
] });
|
|
76
277
|
};
|
|
77
278
|
const config = defineRouteConfig({
|
|
@@ -83,7 +284,7 @@ const IntegrationsBreadcrumb = () => {
|
|
|
83
284
|
const { t } = useTranslation();
|
|
84
285
|
return /* @__PURE__ */ jsx(Fragment, { children: t("integration.list.title") });
|
|
85
286
|
};
|
|
86
|
-
const handle$
|
|
287
|
+
const handle$2 = {
|
|
87
288
|
breadcrumb: () => /* @__PURE__ */ jsx(IntegrationsBreadcrumb, {})
|
|
88
289
|
};
|
|
89
290
|
const Dash = () => /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: "-" });
|
|
@@ -1679,7 +1880,7 @@ function useForm(props = {}) {
|
|
|
1679
1880
|
_formControl.current.formState = getProxyFormState(formState, control);
|
|
1680
1881
|
return _formControl.current;
|
|
1681
1882
|
}
|
|
1682
|
-
const jsonToText = (v) => v
|
|
1883
|
+
const jsonToText = (v) => v == null || v === "" ? "" : JSON.stringify(v, null, 2);
|
|
1683
1884
|
const JsonField = ({ field, f }) => {
|
|
1684
1885
|
const { t } = useTranslation();
|
|
1685
1886
|
const [raw, setRaw] = useState(() => jsonToText(f.value));
|
|
@@ -1699,7 +1900,7 @@ const JsonField = ({ field, f }) => {
|
|
|
1699
1900
|
setRaw(text);
|
|
1700
1901
|
if (text.trim() === "") {
|
|
1701
1902
|
setError(null);
|
|
1702
|
-
f.onChange(
|
|
1903
|
+
f.onChange(null);
|
|
1703
1904
|
return;
|
|
1704
1905
|
}
|
|
1705
1906
|
try {
|
|
@@ -1769,7 +1970,18 @@ function renderControl(field, f, secretConfigured, t) {
|
|
|
1769
1970
|
placeholder,
|
|
1770
1971
|
value: f.value ?? "",
|
|
1771
1972
|
disabled,
|
|
1772
|
-
onChange: (e) => f.onChange(e.target.value === "" ?
|
|
1973
|
+
onChange: (e) => f.onChange(e.target.value === "" ? null : e.target.valueAsNumber)
|
|
1974
|
+
}
|
|
1975
|
+
);
|
|
1976
|
+
case "url":
|
|
1977
|
+
return /* @__PURE__ */ jsx(
|
|
1978
|
+
Input,
|
|
1979
|
+
{
|
|
1980
|
+
type: "url",
|
|
1981
|
+
placeholder,
|
|
1982
|
+
value: f.value ?? "",
|
|
1983
|
+
disabled,
|
|
1984
|
+
onChange: f.onChange
|
|
1773
1985
|
}
|
|
1774
1986
|
);
|
|
1775
1987
|
case "secret":
|
|
@@ -1780,7 +1992,8 @@ function renderControl(field, f, secretConfigured, t) {
|
|
|
1780
1992
|
placeholder: secretConfigured ? t("integration.form.keepSecret") : placeholder ?? "",
|
|
1781
1993
|
value: f.value ?? "",
|
|
1782
1994
|
disabled,
|
|
1783
|
-
onChange: f.onChange
|
|
1995
|
+
onChange: f.onChange,
|
|
1996
|
+
className: !f.value ? "[&~div]:hidden" : void 0
|
|
1784
1997
|
}
|
|
1785
1998
|
);
|
|
1786
1999
|
case "json":
|
|
@@ -1818,10 +2031,11 @@ const EditSectionDrawer = ({
|
|
|
1818
2031
|
providerId,
|
|
1819
2032
|
section,
|
|
1820
2033
|
values,
|
|
1821
|
-
|
|
2034
|
+
configuredSecrets = []
|
|
1822
2035
|
}) => {
|
|
1823
2036
|
const { t } = useTranslation();
|
|
1824
2037
|
const qc = useQueryClient();
|
|
2038
|
+
const configured = new Set(configuredSecrets);
|
|
1825
2039
|
const [defaults] = useState(() => sectionDefaults(section, values));
|
|
1826
2040
|
const form = useForm({ values: defaults });
|
|
1827
2041
|
const current = form.watch();
|
|
@@ -1848,7 +2062,7 @@ const EditSectionDrawer = ({
|
|
|
1848
2062
|
{
|
|
1849
2063
|
field: f,
|
|
1850
2064
|
control: form.control,
|
|
1851
|
-
secretConfigured:
|
|
2065
|
+
secretConfigured: configured.has(f.name)
|
|
1852
2066
|
},
|
|
1853
2067
|
f.name
|
|
1854
2068
|
)) }),
|
|
@@ -1866,7 +2080,6 @@ const EditSectionDrawer = ({
|
|
|
1866
2080
|
] })
|
|
1867
2081
|
] }) });
|
|
1868
2082
|
};
|
|
1869
|
-
const testColor = (s) => s === "passed" ? "green" : s === "failed" ? "red" : "grey";
|
|
1870
2083
|
const Row = ({ label, children }) => /* @__PURE__ */ jsxs("div", { className: "text-ui-fg-subtle grid grid-cols-2 px-6 py-4", children: [
|
|
1871
2084
|
/* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: label }),
|
|
1872
2085
|
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-x-2", children })
|
|
@@ -1938,10 +2151,16 @@ const EditPage = () => {
|
|
|
1938
2151
|
if (!descriptor) {
|
|
1939
2152
|
return /* @__PURE__ */ jsxs(Container, { className: "p-6", children: [
|
|
1940
2153
|
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.unknown", { id: provider_id }) }),
|
|
1941
|
-
/* @__PURE__ */ jsx(Link, { to: "/settings/integrations", className: "text-ui-fg-
|
|
2154
|
+
/* @__PURE__ */ jsx(Link, { to: "/settings/integrations", className: "text-ui-fg-base", children: t("integration.back") })
|
|
1942
2155
|
] });
|
|
1943
2156
|
}
|
|
2157
|
+
const version = (data == null ? void 0 : data.version) ?? null;
|
|
2158
|
+
const author = (data == null ? void 0 : data.author) ?? null;
|
|
2159
|
+
const authorUrl = (data == null ? void 0 : data.author_url) ?? null;
|
|
2160
|
+
const lifecycle = !isConfigured ? { color: "grey", label: t("integration.status.notConfigured") } : !isComplete ? { color: "orange", label: t("integration.status.incomplete") } : record.is_enabled ? { color: "green", label: t("integration.status.enabled") } : { color: "grey", label: t("integration.status.disabled") };
|
|
2161
|
+
const connection = descriptor.hasTestConnection ? (record == null ? void 0 : record.last_test_status) === "passed" ? { color: "green", label: t("integration.status.connected") } : (record == null ? void 0 : record.last_test_status) === "failed" ? { color: "red", label: t("integration.status.connectionFailed") } : null : null;
|
|
1944
2162
|
const editing = descriptor.sections.find((s) => s.id === editingSection) ?? null;
|
|
2163
|
+
const configuredSecrets = new Set((record == null ? void 0 : record.configured_secrets) ?? []);
|
|
1945
2164
|
const sectionData = {
|
|
1946
2165
|
providerId: provider_id,
|
|
1947
2166
|
identifier: descriptor.identifier,
|
|
@@ -1966,7 +2185,7 @@ const EditPage = () => {
|
|
|
1966
2185
|
{
|
|
1967
2186
|
field: f,
|
|
1968
2187
|
value: (_a = record == null ? void 0 : record.values) == null ? void 0 : _a[f.name],
|
|
1969
|
-
secretConfigured:
|
|
2188
|
+
secretConfigured: configuredSecrets.has(f.name)
|
|
1970
2189
|
}
|
|
1971
2190
|
) }, f.name);
|
|
1972
2191
|
})
|
|
@@ -1975,40 +2194,62 @@ const EditPage = () => {
|
|
|
1975
2194
|
const sideSections = descriptor.sections.filter((s) => s.column === "side");
|
|
1976
2195
|
const main = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1977
2196
|
/* @__PURE__ */ jsx(LayoutComposer.Entry, { id: "main", children: /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
1978
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
1979
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center
|
|
1980
|
-
/* @__PURE__ */
|
|
1981
|
-
|
|
1982
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
1983
|
-
/* @__PURE__ */
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2197
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-3 px-6 py-4", children: [
|
|
2198
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2199
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
|
|
2200
|
+
/* @__PURE__ */ jsx(IntegrationIcon, { src: descriptor.icon, alt: t(descriptor.displayName) }),
|
|
2201
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
2202
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
2203
|
+
/* @__PURE__ */ jsx(Heading, { children: t(descriptor.displayName) }),
|
|
2204
|
+
provider_id && /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: provider_id })
|
|
2205
|
+
] }),
|
|
2206
|
+
version && /* @__PURE__ */ jsxs(Text, { size: "xsmall", leading: "compact", className: "text-ui-fg-subtle", children: [
|
|
2207
|
+
t("integration.meta.version", { version }),
|
|
2208
|
+
author && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2209
|
+
" • ",
|
|
2210
|
+
t("integration.meta.authorPrefix"),
|
|
2211
|
+
" ",
|
|
2212
|
+
authorUrl ? /* @__PURE__ */ jsx(
|
|
2213
|
+
"a",
|
|
2214
|
+
{
|
|
2215
|
+
href: authorUrl,
|
|
2216
|
+
target: "_blank",
|
|
2217
|
+
rel: "noreferrer",
|
|
2218
|
+
className: "text-ui-fg-interactive",
|
|
2219
|
+
children: author
|
|
2220
|
+
}
|
|
2221
|
+
) : author
|
|
2222
|
+
] })
|
|
2223
|
+
] })
|
|
2224
|
+
] })
|
|
2225
|
+
] }),
|
|
2226
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
2227
|
+
/* @__PURE__ */ jsx(StatusBadge, { color: lifecycle.color, children: lifecycle.label }),
|
|
2228
|
+
connection && /* @__PURE__ */ jsx(StatusBadge, { color: connection.color, children: connection.label }),
|
|
2229
|
+
isConfigured && /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
2230
|
+
/* @__PURE__ */ jsx(DropdownMenu.Trigger, { asChild: true, children: /* @__PURE__ */ jsx(IconButton, { size: "small", variant: "transparent", children: /* @__PURE__ */ jsx(EllipsisHorizontal, {}) }) }),
|
|
2231
|
+
/* @__PURE__ */ jsxs(DropdownMenu.Content, { children: [
|
|
2232
|
+
descriptor.hasTestConnection && record.is_enabled && isComplete && /* @__PURE__ */ jsx(DropdownMenu.Item, { disabled: test.isPending, onClick: () => test.mutate(), children: t("integration.actions.test") }),
|
|
2233
|
+
isConfigured && /* @__PURE__ */ jsx(
|
|
2234
|
+
DropdownMenu.Item,
|
|
2235
|
+
{
|
|
2236
|
+
disabled: toggleEnabled.isPending,
|
|
2237
|
+
onClick: () => toggleEnabled.mutate(!record.is_enabled),
|
|
2238
|
+
children: record.is_enabled ? t("integration.actions.disable") : t("integration.actions.enable")
|
|
2239
|
+
}
|
|
2240
|
+
),
|
|
2241
|
+
isConfigured && /* @__PURE__ */ jsx(DropdownMenu.Separator, {}),
|
|
2242
|
+
isConfigured && /* @__PURE__ */ jsxs(DropdownMenu.Item, { className: "gap-x-2", onClick: onDelete, children: [
|
|
2243
|
+
/* @__PURE__ */ jsx(Trash, { className: "text-ui-fg-subtle" }),
|
|
2244
|
+
t("integration.actions.delete")
|
|
2245
|
+
] })
|
|
2246
|
+
] })
|
|
2005
2247
|
] })
|
|
2006
2248
|
] })
|
|
2007
|
-
] })
|
|
2249
|
+
] }),
|
|
2250
|
+
descriptor.description && /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t(descriptor.description) })
|
|
2008
2251
|
] }),
|
|
2009
|
-
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.
|
|
2010
|
-
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.module"), children: /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: t(`integration.modules.${descriptor.module}`) }) }),
|
|
2011
|
-
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.lastTest"), children: (record == null ? void 0 : record.last_test_status) ? /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(StatusBadge, { color: testColor(record.last_test_status), children: t(`integration.testStatus.${record.last_test_status}`) }) }) : /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", className: "text-ui-fg-subtle", children: t("integration.labels.neverTested") }) })
|
|
2252
|
+
/* @__PURE__ */ jsx(Row, { label: t("integration.labels.category"), children: /* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: t(`integration.categories.${descriptor.category}`) }) })
|
|
2012
2253
|
] }) }),
|
|
2013
2254
|
mainSections.map(renderSection),
|
|
2014
2255
|
editing && /* @__PURE__ */ jsx(
|
|
@@ -2019,7 +2260,7 @@ const EditPage = () => {
|
|
|
2019
2260
|
providerId: provider_id,
|
|
2020
2261
|
section: editing,
|
|
2021
2262
|
values: (record == null ? void 0 : record.values) ?? {},
|
|
2022
|
-
|
|
2263
|
+
configuredSecrets: (record == null ? void 0 : record.configured_secrets) ?? []
|
|
2023
2264
|
},
|
|
2024
2265
|
editing.id
|
|
2025
2266
|
)
|
|
@@ -2045,50 +2286,199 @@ const IntegrationBreadcrumb = ({ params }) => {
|
|
|
2045
2286
|
enabled: !!providerId
|
|
2046
2287
|
});
|
|
2047
2288
|
const descriptor = data == null ? void 0 : data.descriptor;
|
|
2048
|
-
if (!descriptor) return /* @__PURE__ */ jsx(Fragment, {
|
|
2289
|
+
if (!descriptor) return /* @__PURE__ */ jsx(Fragment, {});
|
|
2049
2290
|
const name = t(descriptor.displayName);
|
|
2050
|
-
return /* @__PURE__ */
|
|
2291
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2292
|
+
name + " ",
|
|
2293
|
+
/* @__PURE__ */ jsx(Badge, { size: "2xsmall", color: "grey", children: providerId })
|
|
2294
|
+
] });
|
|
2051
2295
|
};
|
|
2052
|
-
const handle = {
|
|
2296
|
+
const handle$1 = {
|
|
2053
2297
|
breadcrumb: ({ params }) => /* @__PURE__ */ jsx(IntegrationBreadcrumb, { params })
|
|
2054
2298
|
};
|
|
2299
|
+
const PUBLISH_URL = "https://docs.gorgojs.com/integrations";
|
|
2300
|
+
const API_URL = "https://gorgojs.com";
|
|
2301
|
+
const InstallModal = ({ item, onOpenChange }) => {
|
|
2302
|
+
const { t } = useTranslation();
|
|
2303
|
+
return /* @__PURE__ */ jsx(Drawer, { open: !!item, onOpenChange, children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
|
|
2304
|
+
/* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { asChild: true, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
2305
|
+
item && /* @__PURE__ */ jsx(IntegrationIcon, { src: API_URL + item.icon, alt: item.label, size: "small" }),
|
|
2306
|
+
/* @__PURE__ */ jsx("span", { children: item == null ? void 0 : item.label })
|
|
2307
|
+
] }) }) }),
|
|
2308
|
+
/* @__PURE__ */ jsx(Drawer.Body, { className: "flex flex-1 flex-col gap-y-4 overflow-auto", children: item && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2309
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.browse.install_addToConfig") }),
|
|
2310
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle flex items-center justify-between gap-x-2 rounded-md px-3 py-2", children: [
|
|
2311
|
+
/* @__PURE__ */ jsx("code", { className: "txt-compact-small text-ui-fg-subtle", children: `npm i ${item.npm}` }),
|
|
2312
|
+
/* @__PURE__ */ jsx(Copy, { content: `npm i ${item.npm}` })
|
|
2313
|
+
] }),
|
|
2314
|
+
item.configSnippet && /* @__PURE__ */ jsxs("div", { className: "bg-ui-bg-subtle flex flex-col gap-y-2 rounded-md px-3 py-2", children: [
|
|
2315
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-2", children: [
|
|
2316
|
+
/* @__PURE__ */ jsx(Text, { size: "xsmall", weight: "plus", className: "text-ui-fg-subtle", children: "medusa-config.ts" }),
|
|
2317
|
+
/* @__PURE__ */ jsx(Copy, { content: item.configSnippet })
|
|
2318
|
+
] }),
|
|
2319
|
+
/* @__PURE__ */ jsx("pre", { className: "txt-compact-small text-ui-fg-subtle overflow-x-auto whitespace-pre", children: item.configSnippet })
|
|
2320
|
+
] }),
|
|
2321
|
+
/* @__PURE__ */ jsxs("a", { href: item.docsUrl, target: "_blank", rel: "noreferrer", className: "text-ui-fg-base txt-small", children: [
|
|
2322
|
+
t("integration.browse.install_docs"),
|
|
2323
|
+
" →"
|
|
2324
|
+
] })
|
|
2325
|
+
] }) }),
|
|
2326
|
+
/* @__PURE__ */ jsx(Drawer.Footer, { children: /* @__PURE__ */ jsx(Drawer.Close, { asChild: true, children: /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", children: t("integration.actions.cancel") }) }) })
|
|
2327
|
+
] }) });
|
|
2328
|
+
};
|
|
2329
|
+
const BrowsePage = () => {
|
|
2330
|
+
const { t } = useTranslation();
|
|
2331
|
+
const navigate = useNavigate();
|
|
2332
|
+
const [activeTab, setActiveTab] = useState("all");
|
|
2333
|
+
const [search, setSearch] = useState("");
|
|
2334
|
+
const [installItem, setInstallItem] = useState(null);
|
|
2335
|
+
const { data, isLoading } = useQuery({
|
|
2336
|
+
queryKey: ["integration-catalog"],
|
|
2337
|
+
queryFn: () => sdk.client.fetch("/admin/integrations/catalog")
|
|
2338
|
+
});
|
|
2339
|
+
const items = (data == null ? void 0 : data.integrations) ?? [];
|
|
2340
|
+
const categories = useMemo(() => [...new Set(items.map((i) => i.category))], [items]);
|
|
2341
|
+
const q = search.trim().toLowerCase();
|
|
2342
|
+
const filtered = items.filter((i) => {
|
|
2343
|
+
if (activeTab !== "all" && i.category !== activeTab) return false;
|
|
2344
|
+
if (q && ![i.label, i.shortDescription, i.npm].some((s) => s.toLowerCase().includes(q))) return false;
|
|
2345
|
+
return true;
|
|
2346
|
+
});
|
|
2347
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-3", children: [
|
|
2348
|
+
/* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
2349
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between px-6 py-4", children: [
|
|
2350
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
2351
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: t("integration.browse.title") }),
|
|
2352
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.browse.subtitle") })
|
|
2353
|
+
] }),
|
|
2354
|
+
false
|
|
2355
|
+
] }),
|
|
2356
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-6 py-4", children: [
|
|
2357
|
+
/* @__PURE__ */ jsx(Tabs, { value: activeTab, onValueChange: setActiveTab, children: /* @__PURE__ */ jsxs(Tabs.List, { children: [
|
|
2358
|
+
/* @__PURE__ */ jsx(Tabs.Trigger, { value: "all", children: t("integration.list.tabs.all") }),
|
|
2359
|
+
categories.map((c) => /* @__PURE__ */ jsx(Tabs.Trigger, { value: c, children: t(`integration.categories.${c}`) }, c))
|
|
2360
|
+
] }) }),
|
|
2361
|
+
/* @__PURE__ */ jsx("div", { className: "w-64", children: /* @__PURE__ */ jsx(
|
|
2362
|
+
Input,
|
|
2363
|
+
{
|
|
2364
|
+
placeholder: t("integration.browse.searchPlaceholder"),
|
|
2365
|
+
value: search,
|
|
2366
|
+
onChange: (e) => setSearch(e.target.value)
|
|
2367
|
+
}
|
|
2368
|
+
) })
|
|
2369
|
+
] })
|
|
2370
|
+
] }),
|
|
2371
|
+
isLoading ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(Spinner, { className: "text-ui-fg-subtle animate-spin" }) }) : filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t("integration.list.emptyFiltered") }) }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2 xl:grid-cols-4", children: filtered.map((item) => /* @__PURE__ */ jsxs("div", { className: "shadow-borders-base bg-ui-bg-base flex flex-col rounded-lg", children: [
|
|
2372
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col gap-y-3 p-4", children: [
|
|
2373
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-x-2", children: [
|
|
2374
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-3", children: [
|
|
2375
|
+
/* @__PURE__ */ jsx(IntegrationIcon, { src: API_URL + item.icon, alt: item.label }),
|
|
2376
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
2377
|
+
/* @__PURE__ */ jsx(Text, { size: "small", weight: "plus", leading: "compact", children: item.label }),
|
|
2378
|
+
/* @__PURE__ */ jsx(Text, { size: "xsmall", leading: "compact", className: "text-ui-fg-subtle", children: t("integration.browse.by", { author: item.authorLocalized }) })
|
|
2379
|
+
] })
|
|
2380
|
+
] }),
|
|
2381
|
+
/* @__PURE__ */ jsx(StatusBadge, { color: item.installed ? "green" : "grey", children: item.installed ? t("integration.browse.installed") : t("integration.browse.notInstalled") })
|
|
2382
|
+
] }),
|
|
2383
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle line-clamp-2", children: item.shortDescription })
|
|
2384
|
+
] }),
|
|
2385
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t px-4 py-3", children: [
|
|
2386
|
+
item.installed && item.provider_id ? /* @__PURE__ */ jsx(
|
|
2387
|
+
Button,
|
|
2388
|
+
{
|
|
2389
|
+
size: "small",
|
|
2390
|
+
variant: "primary",
|
|
2391
|
+
onClick: () => navigate(`/settings/integrations/${item.provider_id}`),
|
|
2392
|
+
children: t("integration.browse.settings")
|
|
2393
|
+
}
|
|
2394
|
+
) : /* @__PURE__ */ jsxs(Button, { size: "small", variant: "secondary", onClick: () => setInstallItem(item), children: [
|
|
2395
|
+
/* @__PURE__ */ jsx(Plus, {}),
|
|
2396
|
+
t("integration.browse.add")
|
|
2397
|
+
] }),
|
|
2398
|
+
/* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: t(`integration.categories.${item.category}`) })
|
|
2399
|
+
] })
|
|
2400
|
+
] }, item.integrationId)) }),
|
|
2401
|
+
/* @__PURE__ */ jsx(Container, { className: "flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs("a", { href: PUBLISH_URL, target: "_blank", rel: "noreferrer", className: "text-ui-fg-base txt-small", children: [
|
|
2402
|
+
t("integration.browse.learnMore"),
|
|
2403
|
+
" →"
|
|
2404
|
+
] }) }),
|
|
2405
|
+
/* @__PURE__ */ jsx(InstallModal, { item: installItem, onOpenChange: (open) => !open && setInstallItem(null) })
|
|
2406
|
+
] });
|
|
2407
|
+
};
|
|
2408
|
+
const BrowseBreadcrumb = () => {
|
|
2409
|
+
const { t } = useTranslation();
|
|
2410
|
+
return /* @__PURE__ */ jsx(Fragment, { children: t("integration.browse.title") });
|
|
2411
|
+
};
|
|
2412
|
+
const handle = {
|
|
2413
|
+
breadcrumb: () => /* @__PURE__ */ jsx(BrowseBreadcrumb, {})
|
|
2414
|
+
};
|
|
2055
2415
|
const integration$1 = {
|
|
2056
2416
|
list: {
|
|
2057
2417
|
title: "Integrations",
|
|
2418
|
+
subtitle: "Manage integrations settings",
|
|
2419
|
+
browseIntegrations: "Browse Integrations",
|
|
2420
|
+
learnMore: "Learn how to build integrations",
|
|
2421
|
+
searchPlaceholder: "Search integrations",
|
|
2058
2422
|
empty: "No integrations registered. Declare providers under the integration plugin's options.providers in medusa-config.",
|
|
2423
|
+
emptyFiltered: "No integrations match your filters.",
|
|
2059
2424
|
tested: "tested",
|
|
2060
|
-
testFailed: "test failed"
|
|
2425
|
+
testFailed: "test failed",
|
|
2426
|
+
tabs: {
|
|
2427
|
+
all: "All"
|
|
2428
|
+
}
|
|
2429
|
+
},
|
|
2430
|
+
browse: {
|
|
2431
|
+
title: "Browse",
|
|
2432
|
+
subtitle: "Find available integrations",
|
|
2433
|
+
publish: "Add Integration",
|
|
2434
|
+
learnMore: "Learn how to build and publish your own integration",
|
|
2435
|
+
searchPlaceholder: "Search integrations",
|
|
2436
|
+
by: "by {{author}}",
|
|
2437
|
+
installed: "Installed",
|
|
2438
|
+
notInstalled: "Not installed",
|
|
2439
|
+
add: "Add",
|
|
2440
|
+
settings: "Settings",
|
|
2441
|
+
install_addToConfig: "Add this to your medusa-config.ts and restart the server.",
|
|
2442
|
+
install_docs: "Documentation"
|
|
2443
|
+
},
|
|
2444
|
+
columns: {
|
|
2445
|
+
integration: "Integration",
|
|
2446
|
+
description: "Description",
|
|
2447
|
+
category: "Category",
|
|
2448
|
+
status: "Status"
|
|
2061
2449
|
},
|
|
2062
2450
|
status: {
|
|
2063
2451
|
notConfigured: "Not configured",
|
|
2064
2452
|
incomplete: "Incomplete",
|
|
2065
2453
|
enabled: "Enabled",
|
|
2066
2454
|
disabled: "Disabled",
|
|
2067
|
-
configured: "Configured"
|
|
2455
|
+
configured: "Configured",
|
|
2456
|
+
connected: "Connected",
|
|
2457
|
+
connectionFailed: "Connection failed"
|
|
2458
|
+
},
|
|
2459
|
+
meta: {
|
|
2460
|
+
version: "v{{version}}",
|
|
2461
|
+
authorPrefix: "by"
|
|
2068
2462
|
},
|
|
2069
2463
|
labels: {
|
|
2070
|
-
|
|
2071
|
-
module: "Module",
|
|
2072
|
-
lastTest: "Last test",
|
|
2073
|
-
neverTested: "Never tested"
|
|
2464
|
+
category: "Category"
|
|
2074
2465
|
},
|
|
2075
|
-
|
|
2466
|
+
categories: {
|
|
2076
2467
|
payment: "Payment",
|
|
2468
|
+
notification: "Notification",
|
|
2077
2469
|
fulfillment: "Fulfillment",
|
|
2078
|
-
|
|
2079
|
-
|
|
2470
|
+
search: "Search",
|
|
2471
|
+
content: "Content",
|
|
2472
|
+
analytics: "Analytics",
|
|
2473
|
+
authentication: "Authentication",
|
|
2080
2474
|
erp: "ERP",
|
|
2475
|
+
crm: "CRM",
|
|
2081
2476
|
pim: "PIM",
|
|
2082
|
-
|
|
2477
|
+
marketplace: "Marketplace",
|
|
2083
2478
|
feed: "Feed",
|
|
2084
|
-
|
|
2479
|
+
file_providers: "File providers",
|
|
2085
2480
|
other: "Other"
|
|
2086
2481
|
},
|
|
2087
|
-
testStatus: {
|
|
2088
|
-
passed: "Passed",
|
|
2089
|
-
failed: "Failed",
|
|
2090
|
-
skipped: "Skipped"
|
|
2091
|
-
},
|
|
2092
2482
|
actions: {
|
|
2093
2483
|
test: "Test connection",
|
|
2094
2484
|
enable: "Enable",
|
|
@@ -2105,7 +2495,7 @@ const integration$1 = {
|
|
|
2105
2495
|
form: {
|
|
2106
2496
|
required: "{{field}} is required",
|
|
2107
2497
|
invalidJson: "Invalid JSON",
|
|
2108
|
-
keepSecret: "••••••
|
|
2498
|
+
keepSecret: "•••••• – leave blank to keep",
|
|
2109
2499
|
items: "{{count}} items"
|
|
2110
2500
|
},
|
|
2111
2501
|
toast: {
|
|
@@ -2128,40 +2518,70 @@ const en = {
|
|
|
2128
2518
|
const integration = {
|
|
2129
2519
|
list: {
|
|
2130
2520
|
title: "Интеграции",
|
|
2521
|
+
subtitle: "Управление настройками интеграций",
|
|
2522
|
+
browseIntegrations: "Найти интеграции",
|
|
2523
|
+
learnMore: "Как создавать интеграции",
|
|
2524
|
+
searchPlaceholder: "Поиск интеграций",
|
|
2131
2525
|
empty: "Нет зарегистрированных интеграций. Объявите провайдеров в options.providers плагина интеграций в medusa-config.",
|
|
2526
|
+
emptyFiltered: "Нет интеграций по заданным фильтрам",
|
|
2132
2527
|
tested: "проверено",
|
|
2133
|
-
testFailed: "ошибка проверки"
|
|
2528
|
+
testFailed: "ошибка проверки",
|
|
2529
|
+
tabs: {
|
|
2530
|
+
all: "Все"
|
|
2531
|
+
}
|
|
2532
|
+
},
|
|
2533
|
+
browse: {
|
|
2534
|
+
title: "Каталог",
|
|
2535
|
+
subtitle: "Поиск доступных интеграций",
|
|
2536
|
+
publish: "Добавить интеграцию",
|
|
2537
|
+
learnMore: "Как создать и опубликовать свою интеграцию",
|
|
2538
|
+
searchPlaceholder: "Поиск интеграций",
|
|
2539
|
+
by: "от {{author}}",
|
|
2540
|
+
installed: "Установлено",
|
|
2541
|
+
notInstalled: "Не установлено",
|
|
2542
|
+
add: "Добавить",
|
|
2543
|
+
settings: "Настройки",
|
|
2544
|
+
install_addToConfig: "Добавьте это в medusa-config.ts и перезапустите сервер.",
|
|
2545
|
+
install_docs: "Документация"
|
|
2546
|
+
},
|
|
2547
|
+
columns: {
|
|
2548
|
+
integration: "Интеграция",
|
|
2549
|
+
description: "Описание",
|
|
2550
|
+
category: "Категория",
|
|
2551
|
+
status: "Статус"
|
|
2134
2552
|
},
|
|
2135
2553
|
status: {
|
|
2136
2554
|
notConfigured: "Не настроено",
|
|
2137
2555
|
incomplete: "Не завершено",
|
|
2138
2556
|
enabled: "Включено",
|
|
2139
2557
|
disabled: "Выключено",
|
|
2140
|
-
configured: "Настроено"
|
|
2558
|
+
configured: "Настроено",
|
|
2559
|
+
connected: "Подключено",
|
|
2560
|
+
connectionFailed: "Ошибка подключения"
|
|
2561
|
+
},
|
|
2562
|
+
meta: {
|
|
2563
|
+
version: "v{{version}}",
|
|
2564
|
+
authorPrefix: "от"
|
|
2141
2565
|
},
|
|
2142
2566
|
labels: {
|
|
2143
|
-
|
|
2144
|
-
module: "Модуль",
|
|
2145
|
-
lastTest: "Последняя проверка",
|
|
2146
|
-
neverTested: "Не проверялось"
|
|
2567
|
+
category: "Категория"
|
|
2147
2568
|
},
|
|
2148
|
-
|
|
2569
|
+
categories: {
|
|
2149
2570
|
payment: "Платежи",
|
|
2571
|
+
notification: "Уведомления",
|
|
2150
2572
|
fulfillment: "Доставка",
|
|
2151
|
-
|
|
2152
|
-
|
|
2573
|
+
search: "Поиск",
|
|
2574
|
+
content: "Контент",
|
|
2575
|
+
analytics: "Аналитика",
|
|
2576
|
+
authentication: "Аутентификация",
|
|
2153
2577
|
erp: "ERP",
|
|
2578
|
+
crm: "CRM",
|
|
2154
2579
|
pim: "PIM",
|
|
2155
|
-
|
|
2580
|
+
marketplace: "Маркетплейс",
|
|
2156
2581
|
feed: "Фиды",
|
|
2157
|
-
|
|
2582
|
+
file_providers: "Файловые провайдеры",
|
|
2158
2583
|
other: "Прочее"
|
|
2159
2584
|
},
|
|
2160
|
-
testStatus: {
|
|
2161
|
-
passed: "Пройдено",
|
|
2162
|
-
failed: "Ошибка",
|
|
2163
|
-
skipped: "Пропущено"
|
|
2164
|
-
},
|
|
2165
2585
|
actions: {
|
|
2166
2586
|
test: "Проверить соединение",
|
|
2167
2587
|
enable: "Включить",
|
|
@@ -2178,7 +2598,7 @@ const integration = {
|
|
|
2178
2598
|
form: {
|
|
2179
2599
|
required: "Поле «{{field}}» обязательно",
|
|
2180
2600
|
invalidJson: "Некорректный JSON",
|
|
2181
|
-
keepSecret: "••••••
|
|
2601
|
+
keepSecret: "•••••• – оставьте пустым, чтобы не менять",
|
|
2182
2602
|
items: "{{count}} шт."
|
|
2183
2603
|
},
|
|
2184
2604
|
toast: {
|
|
@@ -2208,11 +2628,16 @@ const routeModule = {
|
|
|
2208
2628
|
{
|
|
2209
2629
|
Component: IntegrationsPage,
|
|
2210
2630
|
path: "/settings/integrations",
|
|
2211
|
-
handle: handle$
|
|
2631
|
+
handle: { label: config.label, translationNs: config.translationNs, ...handle$2 }
|
|
2212
2632
|
},
|
|
2213
2633
|
{
|
|
2214
2634
|
Component: EditPage,
|
|
2215
2635
|
path: "/settings/integrations/:provider_id",
|
|
2636
|
+
handle: handle$1
|
|
2637
|
+
},
|
|
2638
|
+
{
|
|
2639
|
+
Component: BrowsePage,
|
|
2640
|
+
path: "/settings/integrations/browse",
|
|
2216
2641
|
handle
|
|
2217
2642
|
}
|
|
2218
2643
|
]
|
|
@@ -2234,6 +2659,7 @@ const displayModule = {
|
|
|
2234
2659
|
displays: {}
|
|
2235
2660
|
};
|
|
2236
2661
|
const i18nModule = { resources: i18nTranslations0 };
|
|
2662
|
+
const cellRendererModule = {};
|
|
2237
2663
|
const layoutModule = { layouts: [] };
|
|
2238
2664
|
const plugin = {
|
|
2239
2665
|
widgetModule,
|
|
@@ -2242,6 +2668,7 @@ const plugin = {
|
|
|
2242
2668
|
formModule,
|
|
2243
2669
|
displayModule,
|
|
2244
2670
|
i18nModule,
|
|
2671
|
+
cellRendererModule,
|
|
2245
2672
|
layoutModule
|
|
2246
2673
|
};
|
|
2247
2674
|
export {
|