strapi-plugin-hubspot 0.5.0 → 0.6.0
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/CHANGELOG.md +48 -0
- package/README.md +110 -4
- package/dist/_chunks/Forms-BF4_zA-m.js +1007 -0
- package/dist/_chunks/Forms-CW1KFO9U.mjs +989 -0
- package/dist/_chunks/{HubspotObjectInput-D9r_sGFe.mjs → HubspotObjectInput-CpxeM2J0.mjs} +3 -3
- package/dist/_chunks/{HubspotObjectInput-DpXMFiPg.js → HubspotObjectInput-hjAYWtaU.js} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-av9782v6.mjs → HubspotPropertyInput-C-52Lu24.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-Dk0t0NVe.js → HubspotPropertyInput-OSeIBaRC.js} +3 -3
- package/dist/_chunks/Settings-2V7TH5CX.mjs +321 -0
- package/dist/_chunks/Settings-DcA9M5Tw.js +339 -0
- package/dist/_chunks/en-CJ9wYHgN.mjs +197 -0
- package/dist/_chunks/en-C_-N8cjv.js +197 -0
- package/dist/_chunks/fr-BHObPoUp.js +197 -0
- package/dist/_chunks/fr-DttDn-2Y.mjs +197 -0
- package/dist/_chunks/{Settings-DTzk6GWO.mjs → index-C1UJXE_o.mjs} +576 -317
- package/dist/_chunks/{index-B3c9qEYU.js → index-CMzg-x5i.js} +12 -4
- package/dist/_chunks/{Settings-CPxe6LdH.js → index-Dgbid2LK.js} +580 -322
- package/dist/_chunks/{index-C0XHwXog.mjs → index-DkGOTp8p.mjs} +12 -4
- package/dist/_chunks/{objectLabels-DwOMxLfh.mjs → objectLabels-D9UEuOGr.mjs} +1 -1
- package/dist/_chunks/{objectLabels-DksWJnOK.js → objectLabels-Th7aYW-B.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-C3vn1DuR.js → useHubspotSchema-Bgrgg8Mt.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-BGtg7Ffj.mjs → useHubspotSchema-DQkQcA_V.mjs} +1 -1
- package/dist/admin/index.js +2 -1
- package/dist/admin/index.mjs +2 -1
- package/dist/admin/src/builder/ConditionEditor.d.ts +17 -0
- package/dist/admin/src/builder/FieldPanel.d.ts +16 -0
- package/dist/admin/src/builder/types.d.ts +90 -0
- package/dist/admin/src/index.d.ts +1 -0
- package/dist/admin/src/pages/FormEditor.d.ts +9 -0
- package/dist/admin/src/pages/Forms.d.ts +4 -0
- package/dist/admin/src/pages/FormsList.d.ts +8 -0
- package/dist/server/index.js +880 -5
- package/dist/server/index.mjs +880 -5
- package/dist/server/src/__tests__/conditions.test.d.ts +1 -0
- package/dist/server/src/__tests__/forms.test.d.ts +1 -0
- package/dist/server/src/__tests__/formsSubmit.test.d.ts +1 -0
- package/dist/server/src/__tests__/importLegacy.test.d.ts +1 -0
- package/dist/server/src/conditions.d.ts +88 -0
- package/dist/server/src/content-types.d.ts +161 -9
- package/dist/server/src/forms.d.ts +81 -0
- package/dist/server/src/formsAdmin.d.ts +39 -0
- package/dist/server/src/importLegacy.d.ts +25 -0
- package/dist/server/src/index.d.ts +214 -16
- package/dist/shared/types.d.ts +103 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.mjs +2 -0
- package/package.json +23 -6
- package/dist/_chunks/en-BN5fD3ai.js +0 -83
- package/dist/_chunks/en-xeTTAUtX.mjs +0 -83
- package/dist/_chunks/fr-BKODkfPy.mjs +0 -83
- package/dist/_chunks/fr-D3-oO8Lt.js +0 -83
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const React = require("react");
|
|
5
|
+
const objectLabels = require("./objectLabels-Th7aYW-B.js");
|
|
6
|
+
const designSystem = require("@strapi/design-system");
|
|
7
|
+
const admin = require("@strapi/strapi/admin");
|
|
8
|
+
const index$1 = require("./index-CMzg-x5i.js");
|
|
9
|
+
const index = require("./index-Dgbid2LK.js");
|
|
10
|
+
function _interopNamespace(e) {
|
|
11
|
+
if (e && e.__esModule) return e;
|
|
12
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
13
|
+
if (e) {
|
|
14
|
+
for (const k in e) {
|
|
15
|
+
if (k !== "default") {
|
|
16
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
17
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
get: () => e[k]
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
n.default = e;
|
|
25
|
+
return Object.freeze(n);
|
|
26
|
+
}
|
|
27
|
+
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
28
|
+
const AuditSection = ({ configured }) => {
|
|
29
|
+
const intl = objectLabels.useIntl();
|
|
30
|
+
const { formatMessage } = intl;
|
|
31
|
+
const { get } = admin.useFetchClient();
|
|
32
|
+
const [busy, setBusy] = React__namespace.useState(false);
|
|
33
|
+
const [error, setError] = React__namespace.useState(false);
|
|
34
|
+
const [result, setResult] = React__namespace.useState(null);
|
|
35
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: index$1.getTranslation(id), defaultMessage }, values);
|
|
36
|
+
const problemText = (p) => {
|
|
37
|
+
switch (p.code) {
|
|
38
|
+
case "unknown":
|
|
39
|
+
return t("problem.unknown", "“{property}” does not exist on {object} in this portal", {
|
|
40
|
+
property: p.property,
|
|
41
|
+
object: objectLabels.objectLabel(intl, p.object)
|
|
42
|
+
});
|
|
43
|
+
case "wrong-object":
|
|
44
|
+
return t("problem.wrong-object", "“{property}” exists on {actual}, not on {object}", {
|
|
45
|
+
property: p.property,
|
|
46
|
+
object: objectLabels.objectLabel(intl, p.object),
|
|
47
|
+
actual: objectLabels.objectLabel(intl, p.actualObject)
|
|
48
|
+
});
|
|
49
|
+
case "whitespace":
|
|
50
|
+
return t("problem.whitespace", "“{property}” has surrounding whitespace", {
|
|
51
|
+
property: p.property
|
|
52
|
+
});
|
|
53
|
+
case "bad-option":
|
|
54
|
+
return t("problem.bad-option", "“{property}” does not accept {values}", {
|
|
55
|
+
property: p.property,
|
|
56
|
+
values: p.values.join(", ")
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const run = async () => {
|
|
61
|
+
setBusy(true);
|
|
62
|
+
setError(false);
|
|
63
|
+
setResult(null);
|
|
64
|
+
try {
|
|
65
|
+
const { data } = await get(`/${index$1.PLUGIN_ID}/audit`);
|
|
66
|
+
setResult(data);
|
|
67
|
+
} catch {
|
|
68
|
+
setError(true);
|
|
69
|
+
} finally {
|
|
70
|
+
setBusy(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const entryLink = (uid, entry) => `/content-manager/collection-types/${uid}/${entry.documentId}` + (entry.locale ? `?plugins[i18n][locale]=${entry.locale}` : "");
|
|
74
|
+
const totalInvalid = result?.targets.reduce((n, r) => n + r.invalid.length, 0) ?? 0;
|
|
75
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
76
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
|
|
77
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
78
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: t("audit.title", "Mapping audit") }),
|
|
79
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
80
|
+
"audit.subtitle",
|
|
81
|
+
"Scans every entry of the validated content types and lists the mappings the portal would reject today — including properties deleted in HubSpot since they were saved."
|
|
82
|
+
) })
|
|
83
|
+
] }),
|
|
84
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", onClick: run, loading: busy, disabled: !configured, children: t("audit.run", "Run the audit") }) }),
|
|
85
|
+
error ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", children: t("audit.error", "Audit failed — HubSpot unreachable?") }) : null,
|
|
86
|
+
result && !result.targets.length ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
87
|
+
"audit.no-targets",
|
|
88
|
+
"No content type to audit — declare them under `validate` in the plugin config."
|
|
89
|
+
) }) : null,
|
|
90
|
+
result && result.targets.length ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
91
|
+
totalInvalid === 0 && result.targets.every((r) => !r.error) ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "success600", children: t("audit.clean", "Nothing to report — every mapping is valid.") }) : null,
|
|
92
|
+
result.targets.map((report) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
|
|
93
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", paddingBottom: 2, children: [
|
|
94
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", children: report.uid }),
|
|
95
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("audit.summary", "{entries} entries · {mappings} mappings", {
|
|
96
|
+
entries: report.entries,
|
|
97
|
+
mappings: report.mappings
|
|
98
|
+
}) })
|
|
99
|
+
] }),
|
|
100
|
+
report.error ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", children: t("audit.target-error", "Could not scan: {error}", { error: report.error }) }) : null,
|
|
101
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 2, children: report.invalid.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
102
|
+
designSystem.Box,
|
|
103
|
+
{
|
|
104
|
+
padding: 3,
|
|
105
|
+
background: "neutral100",
|
|
106
|
+
hasRadius: true,
|
|
107
|
+
children: [
|
|
108
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
109
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { tag: index.Link, to: entryLink(report.uid, entry), children: entry.label }),
|
|
110
|
+
entry.locale ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { children: entry.locale }) : null
|
|
111
|
+
] }),
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, children: entry.problems.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "danger600", tag: "p", children: problemText(p) }, i)) })
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
`${entry.documentId}-${entry.locale ?? ""}`
|
|
116
|
+
)) })
|
|
117
|
+
] }, report.uid))
|
|
118
|
+
] }) : null
|
|
119
|
+
] });
|
|
120
|
+
};
|
|
121
|
+
const FailuresSection = ({ configured }) => {
|
|
122
|
+
const { formatMessage } = objectLabels.useIntl();
|
|
123
|
+
const { get, post } = admin.useFetchClient();
|
|
124
|
+
const [total, setTotal] = React__namespace.useState(null);
|
|
125
|
+
const [busy, setBusy] = React__namespace.useState(false);
|
|
126
|
+
const [feedback, setFeedback] = React__namespace.useState(
|
|
127
|
+
null
|
|
128
|
+
);
|
|
129
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: index$1.getTranslation(id), defaultMessage }, values);
|
|
130
|
+
const load = React__namespace.useCallback(async () => {
|
|
131
|
+
try {
|
|
132
|
+
const { data } = await get(`/${index$1.PLUGIN_ID}/failures`);
|
|
133
|
+
setTotal(data.total);
|
|
134
|
+
} catch {
|
|
135
|
+
setTotal(null);
|
|
136
|
+
}
|
|
137
|
+
}, [get]);
|
|
138
|
+
React__namespace.useEffect(() => {
|
|
139
|
+
load();
|
|
140
|
+
}, [load]);
|
|
141
|
+
const retry = async () => {
|
|
142
|
+
setBusy(true);
|
|
143
|
+
setFeedback(null);
|
|
144
|
+
try {
|
|
145
|
+
const { data } = await post(
|
|
146
|
+
`/${index$1.PLUGIN_ID}/failures/retry`
|
|
147
|
+
);
|
|
148
|
+
setFeedback({
|
|
149
|
+
tone: data.failed ? "danger" : "success",
|
|
150
|
+
text: t("failures.retried", "{succeeded} replayed, {failed} still failing.", {
|
|
151
|
+
succeeded: data.succeeded,
|
|
152
|
+
failed: data.failed
|
|
153
|
+
})
|
|
154
|
+
});
|
|
155
|
+
await load();
|
|
156
|
+
} catch {
|
|
157
|
+
setFeedback({ tone: "danger", text: t("failures.error", "Replay failed.") });
|
|
158
|
+
} finally {
|
|
159
|
+
setBusy(false);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
163
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Divider, {}),
|
|
164
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
165
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", children: t("failures.title", "Failed submissions") }),
|
|
166
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
167
|
+
"failures.subtitle",
|
|
168
|
+
"Submissions HubSpot couldn't take after the automatic retries. They can be inspected under Content Manager → HubSpot failed submissions."
|
|
169
|
+
) })
|
|
170
|
+
] }),
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
172
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { active: Boolean(total), children: t("failures.count", "{count} queued", { count: total ?? 0 }) }),
|
|
173
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
174
|
+
designSystem.Button,
|
|
175
|
+
{
|
|
176
|
+
variant: "secondary",
|
|
177
|
+
onClick: retry,
|
|
178
|
+
loading: busy,
|
|
179
|
+
disabled: !configured || !total,
|
|
180
|
+
children: t("failures.retry", "Replay now")
|
|
181
|
+
}
|
|
182
|
+
)
|
|
183
|
+
] }),
|
|
184
|
+
feedback ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
185
|
+
designSystem.Typography,
|
|
186
|
+
{
|
|
187
|
+
variant: "pi",
|
|
188
|
+
textColor: feedback.tone === "success" ? "success600" : "danger600",
|
|
189
|
+
children: feedback.text
|
|
190
|
+
}
|
|
191
|
+
) : null
|
|
192
|
+
] });
|
|
193
|
+
};
|
|
194
|
+
const HubspotSettings = () => {
|
|
195
|
+
const { formatMessage } = objectLabels.useIntl();
|
|
196
|
+
const { get, put, del } = admin.useFetchClient();
|
|
197
|
+
const [settings, setSettings] = React__namespace.useState(null);
|
|
198
|
+
const [apiKey, setApiKey] = React__namespace.useState("");
|
|
199
|
+
const [busy, setBusy] = React__namespace.useState(false);
|
|
200
|
+
const [feedback, setFeedback] = React__namespace.useState(
|
|
201
|
+
null
|
|
202
|
+
);
|
|
203
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: index$1.getTranslation(id), defaultMessage }, values);
|
|
204
|
+
const load = React__namespace.useCallback(async () => {
|
|
205
|
+
const { data } = await get(`/${index$1.PLUGIN_ID}/settings`);
|
|
206
|
+
setSettings(data);
|
|
207
|
+
}, [get]);
|
|
208
|
+
React__namespace.useEffect(() => {
|
|
209
|
+
load().catch(
|
|
210
|
+
() => setFeedback({ tone: "danger", text: t("settings.load-error", "Could not load settings.") })
|
|
211
|
+
);
|
|
212
|
+
}, [load]);
|
|
213
|
+
const save = async () => {
|
|
214
|
+
setBusy(true);
|
|
215
|
+
setFeedback(null);
|
|
216
|
+
try {
|
|
217
|
+
const { data } = await put(`/${index$1.PLUGIN_ID}/settings`, { apiKey });
|
|
218
|
+
setSettings(data);
|
|
219
|
+
setApiKey("");
|
|
220
|
+
setFeedback({ tone: "success", text: t("settings.saved", "Key saved.") });
|
|
221
|
+
} catch {
|
|
222
|
+
setFeedback({ tone: "danger", text: t("settings.save-error", "Could not save the key.") });
|
|
223
|
+
} finally {
|
|
224
|
+
setBusy(false);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
const remove = async () => {
|
|
228
|
+
setBusy(true);
|
|
229
|
+
setFeedback(null);
|
|
230
|
+
try {
|
|
231
|
+
const { data } = await del(`/${index$1.PLUGIN_ID}/settings`);
|
|
232
|
+
setSettings(data);
|
|
233
|
+
setApiKey("");
|
|
234
|
+
setFeedback({ tone: "success", text: t("settings.removed", "Key removed.") });
|
|
235
|
+
} catch {
|
|
236
|
+
setFeedback({ tone: "danger", text: t("settings.remove-error", "Could not remove the key.") });
|
|
237
|
+
} finally {
|
|
238
|
+
setBusy(false);
|
|
239
|
+
}
|
|
240
|
+
};
|
|
241
|
+
const test = async () => {
|
|
242
|
+
setBusy(true);
|
|
243
|
+
setFeedback(null);
|
|
244
|
+
try {
|
|
245
|
+
const { data } = await get(
|
|
246
|
+
`/${index$1.PLUGIN_ID}/properties?refresh=1`
|
|
247
|
+
);
|
|
248
|
+
setFeedback(
|
|
249
|
+
data.configured ? {
|
|
250
|
+
tone: "success",
|
|
251
|
+
text: t("settings.test-ok", "Connection established — {count} readable properties.", {
|
|
252
|
+
count: data.properties.length
|
|
253
|
+
})
|
|
254
|
+
} : { tone: "danger", text: t("settings.test-no-key", "No key configured.") }
|
|
255
|
+
);
|
|
256
|
+
} catch {
|
|
257
|
+
setFeedback({
|
|
258
|
+
tone: "danger",
|
|
259
|
+
text: t("settings.test-error", "HubSpot unreachable — invalid or revoked key?")
|
|
260
|
+
});
|
|
261
|
+
} finally {
|
|
262
|
+
setBusy(false);
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
if (!settings) {
|
|
266
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true, children: t("settings.loading", "Loading…") }) });
|
|
267
|
+
}
|
|
268
|
+
const sourceLabel = {
|
|
269
|
+
settings: t("settings.source.settings", "set here"),
|
|
270
|
+
config: t("settings.source.config", "config/plugins.ts"),
|
|
271
|
+
env: t("settings.source.env", "environment variable")
|
|
272
|
+
};
|
|
273
|
+
return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
274
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
275
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "alpha", children: "HubSpot" }),
|
|
276
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
277
|
+
"settings.subtitle",
|
|
278
|
+
"The private app token used to read the portal's properties and validate form mappings."
|
|
279
|
+
) })
|
|
280
|
+
] }),
|
|
281
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
|
|
282
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Badge, { active: settings.configured, children: settings.configured ? t("settings.configured", "Configured {hint}", { hint: settings.hint }) : t("settings.not-configured", "Not configured") }),
|
|
283
|
+
settings.keySource ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t("settings.source", "source: {source}", { source: sourceLabel[settings.keySource] }) }) : null
|
|
284
|
+
] }),
|
|
285
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { maxWidth: "32rem", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
286
|
+
designSystem.Field.Root,
|
|
287
|
+
{
|
|
288
|
+
name: "apiKey",
|
|
289
|
+
hint: t(
|
|
290
|
+
"settings.key.hint",
|
|
291
|
+
"A key entered here overrides the ones from config/plugins.ts and HUBSPOT_API_KEY."
|
|
292
|
+
),
|
|
293
|
+
children: [
|
|
294
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("settings.key.label", "Private app token") }),
|
|
295
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
296
|
+
designSystem.Field.Input,
|
|
297
|
+
{
|
|
298
|
+
type: "password",
|
|
299
|
+
value: apiKey,
|
|
300
|
+
autoComplete: "off",
|
|
301
|
+
placeholder: settings.configured ? t("settings.key.placeholder.set", "•••••••• (leave empty to keep)") : t("settings.key.placeholder.empty", "pat-eu1-…"),
|
|
302
|
+
onChange: (e) => setApiKey(e.target.value)
|
|
303
|
+
}
|
|
304
|
+
),
|
|
305
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
) }),
|
|
309
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
310
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: save, loading: busy, disabled: !apiKey.trim(), children: t("settings.save", "Save") }),
|
|
311
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "secondary", onClick: test, loading: busy, disabled: !settings.configured, children: t("settings.test", "Test connection") }),
|
|
312
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
313
|
+
designSystem.Button,
|
|
314
|
+
{
|
|
315
|
+
variant: "danger-light",
|
|
316
|
+
onClick: remove,
|
|
317
|
+
loading: busy,
|
|
318
|
+
disabled: settings.keySource !== "settings",
|
|
319
|
+
children: t("settings.remove", "Remove")
|
|
320
|
+
}
|
|
321
|
+
)
|
|
322
|
+
] }),
|
|
323
|
+
feedback ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
324
|
+
designSystem.Typography,
|
|
325
|
+
{
|
|
326
|
+
variant: "pi",
|
|
327
|
+
textColor: feedback.tone === "success" ? "success600" : "danger600",
|
|
328
|
+
children: feedback.text
|
|
329
|
+
}
|
|
330
|
+
) : null,
|
|
331
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
332
|
+
"settings.scopes",
|
|
333
|
+
"The token needs the crm.schemas.contacts.read and crm.schemas.companies.read scopes to list properties. It is never returned to the browser: only its existence, its source and its last four characters are."
|
|
334
|
+
) }) }),
|
|
335
|
+
/* @__PURE__ */ jsxRuntime.jsx(AuditSection, { configured: settings.configured }),
|
|
336
|
+
/* @__PURE__ */ jsxRuntime.jsx(FailuresSection, { configured: settings.configured })
|
|
337
|
+
] }) });
|
|
338
|
+
};
|
|
339
|
+
exports.default = HubspotSettings;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
const en = {
|
|
2
|
+
"property.label": "HubSpot property",
|
|
3
|
+
"property.description": "Picked from the portal's real properties",
|
|
4
|
+
"options.section": "HubSpot",
|
|
5
|
+
"options.objectField.label": "Object field",
|
|
6
|
+
"options.objectField.description": "Name of the sibling field holding the HubSpot object (e.g. hsObject). Leave empty to list every object's properties.",
|
|
7
|
+
"options.objectField.placeholder": "hsObject",
|
|
8
|
+
"options.optionsField.label": "Options field",
|
|
9
|
+
"options.optionsField.description": `Name of the sibling repeatable holding this field's choices (value/label entries), filled by the import button on enumeration properties. Defaults to "options".`,
|
|
10
|
+
"options.optionsField.placeholder": "options",
|
|
11
|
+
"object.label": "HubSpot object",
|
|
12
|
+
"object.description": "Picked from the portal's configured objects",
|
|
13
|
+
"object.loading": "Loading HubSpot objects…",
|
|
14
|
+
"object.placeholder": "Choose an object…",
|
|
15
|
+
"object.no-scope": "{object} — missing scope on the token",
|
|
16
|
+
"settings.section": "HubSpot",
|
|
17
|
+
"settings.link": "Configuration",
|
|
18
|
+
"picker.loading": "Loading HubSpot properties…",
|
|
19
|
+
"picker.placeholder": "Search a property…",
|
|
20
|
+
"picker.free-placeholder": "e.g. hs_role, numberofemployees",
|
|
21
|
+
"picker.load-error": "HubSpot properties unavailable",
|
|
22
|
+
"picker.not-configured": "No HubSpot API key — free text. Set it in Settings → HubSpot.",
|
|
23
|
+
"picker.object-unavailable": "Properties of “{object}” unreadable — missing scope on the token.",
|
|
24
|
+
"picker.belongs-to": "{property} — belongs to {object}",
|
|
25
|
+
"picker.unknown": "{property} — unknown to the portal",
|
|
26
|
+
"picker.view": "View in HubSpot",
|
|
27
|
+
"picker.no-results": "No matching property — properties are managed in HubSpot.",
|
|
28
|
+
"picker.refresh": "Refresh the properties from HubSpot",
|
|
29
|
+
"picker.import": "Import the {count} options from HubSpot",
|
|
30
|
+
"picker.imported": "Options imported — save to keep them.",
|
|
31
|
+
"settings.subtitle": "The private app token used to read the portal's properties and validate form mappings.",
|
|
32
|
+
"settings.configured": "Configured {hint}",
|
|
33
|
+
"settings.not-configured": "Not configured",
|
|
34
|
+
"settings.source": "source: {source}",
|
|
35
|
+
"settings.source.settings": "set here",
|
|
36
|
+
"settings.source.config": "config/plugins.ts",
|
|
37
|
+
"settings.source.env": "environment variable",
|
|
38
|
+
"settings.key.label": "Private app token",
|
|
39
|
+
"settings.key.hint": "A key entered here overrides the ones from config/plugins.ts and HUBSPOT_API_KEY.",
|
|
40
|
+
"settings.key.placeholder.set": "•••••••• (leave empty to keep)",
|
|
41
|
+
"settings.key.placeholder.empty": "pat-eu1-…",
|
|
42
|
+
"settings.save": "Save",
|
|
43
|
+
"settings.test": "Test connection",
|
|
44
|
+
"settings.remove": "Remove",
|
|
45
|
+
"settings.loading": "Loading…",
|
|
46
|
+
"settings.load-error": "Could not load settings.",
|
|
47
|
+
"settings.saved": "Key saved.",
|
|
48
|
+
"settings.save-error": "Could not save the key.",
|
|
49
|
+
"settings.removed": "Key removed.",
|
|
50
|
+
"settings.remove-error": "Could not remove the key.",
|
|
51
|
+
"settings.test-ok": "Connection established — {count} readable properties.",
|
|
52
|
+
"settings.test-no-key": "No key configured.",
|
|
53
|
+
"settings.test-error": "HubSpot unreachable — invalid or revoked key?",
|
|
54
|
+
"settings.scopes": "The token needs the crm.schemas.contacts.read and crm.schemas.companies.read scopes to list properties. It is never returned to the browser: only its existence, its source and its last four characters are.",
|
|
55
|
+
"audit.title": "Mapping audit",
|
|
56
|
+
"audit.subtitle": "Scans every entry of the validated content types and lists the mappings the portal would reject today — including properties deleted in HubSpot since they were saved.",
|
|
57
|
+
"audit.run": "Run the audit",
|
|
58
|
+
"audit.error": "Audit failed — HubSpot unreachable?",
|
|
59
|
+
"audit.no-targets": "No content type to audit — declare them under `validate` in the plugin config.",
|
|
60
|
+
"audit.clean": "Nothing to report — every mapping is valid.",
|
|
61
|
+
"audit.summary": "{entries} entries · {mappings} mappings",
|
|
62
|
+
"audit.target-error": "Could not scan: {error}",
|
|
63
|
+
"failures.title": "Failed submissions",
|
|
64
|
+
"failures.subtitle": "Submissions HubSpot couldn't take after the automatic retries. They can be inspected under Content Manager → HubSpot failed submissions.",
|
|
65
|
+
"failures.count": "{count} queued",
|
|
66
|
+
"failures.retry": "Replay now",
|
|
67
|
+
"failures.retried": "{succeeded} replayed, {failed} still failing.",
|
|
68
|
+
"failures.error": "Replay failed.",
|
|
69
|
+
"problem.unknown": "“{property}” does not exist on {object} in this portal",
|
|
70
|
+
"problem.wrong-object": "“{property}” exists on {actual}, not on {object}",
|
|
71
|
+
"problem.whitespace": "“{property}” has surrounding whitespace",
|
|
72
|
+
"problem.bad-option": "“{property}” does not accept {values}",
|
|
73
|
+
"objects.contact": "Contact",
|
|
74
|
+
"objects.company": "Company",
|
|
75
|
+
"objects.deal": "Deal",
|
|
76
|
+
"objects.ticket": "Ticket",
|
|
77
|
+
"objects.product": "Product",
|
|
78
|
+
"objects.line_item": "Line item",
|
|
79
|
+
"objects.quote": "Quote",
|
|
80
|
+
"menu.label": "HubSpot Forms",
|
|
81
|
+
"forms.title": "HubSpot forms",
|
|
82
|
+
"forms.subtitle": "Multi-step forms with conditional fields, mapped to your portal's real properties.",
|
|
83
|
+
"forms.name-label": "Name of the new form",
|
|
84
|
+
"forms.name-placeholder": "Name of the new form",
|
|
85
|
+
"forms.create": "Create",
|
|
86
|
+
"forms.create-error": "Could not create the form.",
|
|
87
|
+
"forms.load-error": "Could not load the forms.",
|
|
88
|
+
"forms.loading": "Loading…",
|
|
89
|
+
"forms.empty": "No form yet — name one above to open the builder.",
|
|
90
|
+
"forms.col-name": "Name",
|
|
91
|
+
"forms.col-slug": "Slug",
|
|
92
|
+
"forms.col-structure": "Structure",
|
|
93
|
+
"forms.col-status": "Status",
|
|
94
|
+
"forms.col-updated": "Updated",
|
|
95
|
+
"forms.col-actions": "",
|
|
96
|
+
"forms.structure": "{steps} steps · {fields} fields",
|
|
97
|
+
"forms.published": "Published",
|
|
98
|
+
"forms.draft": "Draft",
|
|
99
|
+
"forms.delete": "Delete",
|
|
100
|
+
"forms.delete-confirm": 'Delete "{name}" and all its locales?',
|
|
101
|
+
"forms.delete-error": "Could not delete the form.",
|
|
102
|
+
"editor.back": "Back to the list",
|
|
103
|
+
"editor.loading": "Loading…",
|
|
104
|
+
"editor.load-error": "Could not load the form.",
|
|
105
|
+
"editor.locale": "Locale",
|
|
106
|
+
"editor.locale-copied": "New locale started from the default structure — save to keep it.",
|
|
107
|
+
"editor.unsaved": "Unsaved changes",
|
|
108
|
+
"editor.save": "Save",
|
|
109
|
+
"editor.saved": "Draft saved.",
|
|
110
|
+
"editor.save-error": "Could not save the form.",
|
|
111
|
+
"editor.invalid": "The structure has problems — see the flagged cards.",
|
|
112
|
+
"editor.publish": "Publish",
|
|
113
|
+
"editor.published": "Form published.",
|
|
114
|
+
"editor.publish-blocked": "Publishing is blocked — fix the flagged mappings first.",
|
|
115
|
+
"editor.unpublish": "Unpublish",
|
|
116
|
+
"editor.unpublished": "Form unpublished.",
|
|
117
|
+
"editor.unpublish-error": "Could not unpublish.",
|
|
118
|
+
"editor.step": "Step {n}",
|
|
119
|
+
"editor.step-up": "Move the step up",
|
|
120
|
+
"editor.step-down": "Move the step down",
|
|
121
|
+
"editor.step-delete": "Delete the step and its fields",
|
|
122
|
+
"editor.step-panel": "Step",
|
|
123
|
+
"editor.step-title": "Title",
|
|
124
|
+
"editor.step-description": "Description",
|
|
125
|
+
"editor.step-condition": "Show this step only when…",
|
|
126
|
+
"editor.conditional": "Conditional",
|
|
127
|
+
"editor.flag-error": "To fix",
|
|
128
|
+
"editor.required": "required",
|
|
129
|
+
"editor.new-field": "New field",
|
|
130
|
+
"editor.add-field": "Add a field",
|
|
131
|
+
"editor.add-step": "Add a step",
|
|
132
|
+
"editor.field-up": "Move up",
|
|
133
|
+
"editor.field-down": "Move down",
|
|
134
|
+
"editor.field-delete": "Delete the field",
|
|
135
|
+
"editor.form-panel": "Form",
|
|
136
|
+
"editor.form-name": "Internal name",
|
|
137
|
+
"editor.form-title": "Title",
|
|
138
|
+
"editor.form-subtitle": "Subtitle",
|
|
139
|
+
"editor.form-next": "Next label",
|
|
140
|
+
"editor.form-submit": "Submit label",
|
|
141
|
+
"editor.form-success": "Success message",
|
|
142
|
+
"editor.form-hint": "Select a step or a field to edit it. The public endpoint serves this form at /api/hubspot/forms/{slug}.",
|
|
143
|
+
"panel.label": "Label",
|
|
144
|
+
"panel.name": "Payload key",
|
|
145
|
+
"panel.name-hint": "Key of the answer in the submission — unique in the form.",
|
|
146
|
+
"panel.type": "Type",
|
|
147
|
+
"panel.placeholder": "Placeholder",
|
|
148
|
+
"panel.width": "Width",
|
|
149
|
+
"panel.width-full": "Full",
|
|
150
|
+
"panel.width-half": "Half",
|
|
151
|
+
"panel.help": "Help text",
|
|
152
|
+
"panel.required": "Required",
|
|
153
|
+
"panel.options": "Choices",
|
|
154
|
+
"panel.option-value": "Value",
|
|
155
|
+
"panel.option-label": "Label",
|
|
156
|
+
"panel.option-remove": "Remove",
|
|
157
|
+
"panel.option-add": "Add a choice",
|
|
158
|
+
"panel.option-import": "Import the {count} options from HubSpot",
|
|
159
|
+
"panel.hubspot": "HubSpot",
|
|
160
|
+
"panel.refresh": "Refresh the portal schema",
|
|
161
|
+
"panel.object": "Object",
|
|
162
|
+
"panel.property": "Property",
|
|
163
|
+
"panel.property-placeholder": "Search a property…",
|
|
164
|
+
"panel.property-hint": "Without a property, the answer is sent under the payload key.",
|
|
165
|
+
"panel.problem-unknown": "This property is unknown to the portal.",
|
|
166
|
+
"panel.problem-wrong-object": "This property lives on another object.",
|
|
167
|
+
"panel.problem-whitespace": "The stored property has surrounding spaces.",
|
|
168
|
+
"panel.problem-bad-option": "A choice below is not accepted by the portal's enumeration.",
|
|
169
|
+
"panel.view-in-hubspot": "View in HubSpot ↗",
|
|
170
|
+
"panel.condition": "Show this field only when…",
|
|
171
|
+
"condition.no-candidates": "Conditions can only read fields placed earlier in the form.",
|
|
172
|
+
"condition.field": "Field",
|
|
173
|
+
"condition.operator": "Operator",
|
|
174
|
+
"condition.value": "Value",
|
|
175
|
+
"condition.remove-rule": "Remove this rule",
|
|
176
|
+
"condition.add-rule": "Add a rule",
|
|
177
|
+
"condition.logic": "Logic",
|
|
178
|
+
"condition.logic-and": "All rules (AND)",
|
|
179
|
+
"condition.logic-or": "At least one (OR)",
|
|
180
|
+
"condition.and": "AND",
|
|
181
|
+
"condition.or": "OR",
|
|
182
|
+
"condition.op.eq": "is",
|
|
183
|
+
"condition.op.neq": "is not",
|
|
184
|
+
"condition.op.contains": "contains",
|
|
185
|
+
"condition.op.empty": "is empty",
|
|
186
|
+
"condition.op.notEmpty": "is filled",
|
|
187
|
+
"condition.op.gt": "is greater than",
|
|
188
|
+
"condition.op.lt": "is less than",
|
|
189
|
+
"forms.import-title": "Import an existing form",
|
|
190
|
+
"forms.import-hint": "Converts a legacy content-type form (all locales) into a draft here — same slug, source untouched. Re-importing overwrites the draft.",
|
|
191
|
+
"forms.import-source": "Form to import",
|
|
192
|
+
"forms.import": "Import",
|
|
193
|
+
"forms.import-error": "Could not import the form."
|
|
194
|
+
};
|
|
195
|
+
export {
|
|
196
|
+
en as default
|
|
197
|
+
};
|