strapi-plugin-hubspot 0.4.2 → 0.5.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/README.md +6 -0
- package/dist/_chunks/{HubspotObjectInput-DutelVp6.mjs → HubspotObjectInput-D9r_sGFe.mjs} +4 -16
- package/dist/_chunks/{HubspotObjectInput-Br2jTFkG.js → HubspotObjectInput-DpXMFiPg.js} +4 -16
- package/dist/_chunks/HubspotPropertyInput-Dk0t0NVe.js +245 -0
- package/dist/_chunks/HubspotPropertyInput-av9782v6.mjs +227 -0
- package/dist/_chunks/{Settings-CvbKVl-t.js → Settings-CPxe6LdH.js} +2 -2
- package/dist/_chunks/{Settings-CQsB0B2T.mjs → Settings-DTzk6GWO.mjs} +2 -2
- package/dist/_chunks/{en-PBG7-vMR.js → en-BN5fD3ai.js} +1 -0
- package/dist/_chunks/{en-D4ueeUcJ.mjs → en-xeTTAUtX.mjs} +1 -0
- package/dist/_chunks/{fr-DYnxVmIO.mjs → fr-BKODkfPy.mjs} +1 -0
- package/dist/_chunks/{fr-DL4wdV8I.js → fr-D3-oO8Lt.js} +1 -0
- package/dist/_chunks/{index-BUlB1rK9.js → index-B3c9qEYU.js} +4 -4
- package/dist/_chunks/{index-CKoBcX1T.mjs → index-C0XHwXog.mjs} +4 -4
- package/dist/_chunks/{objectLabels-B76t8qqg.js → objectLabels-DksWJnOK.js} +1 -1
- package/dist/_chunks/{objectLabels-dM4o67Fz.mjs → objectLabels-DwOMxLfh.mjs} +1 -1
- package/dist/_chunks/useHubspotSchema-BGtg7Ffj.mjs +58 -0
- package/dist/_chunks/useHubspotSchema-C3vn1DuR.js +75 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/useHubspotSchema.d.ts +28 -0
- package/package.json +1 -1
- package/dist/_chunks/HubspotPropertyInput-CK6Yj9rC.mjs +0 -177
- package/dist/_chunks/HubspotPropertyInput-DIPDPRXJ.js +0 -195
package/README.md
CHANGED
|
@@ -73,6 +73,12 @@ accept — are filtered out, so the list only ever offers things that will
|
|
|
73
73
|
actually work. When the portal id is readable, each selected property gets a
|
|
74
74
|
**Voir dans HubSpot** link straight to its settings page.
|
|
75
75
|
|
|
76
|
+
The schema is fetched **once per page** whatever the number of fields, and
|
|
77
|
+
cached ten minutes server-side. A property created in HubSpot a minute ago is
|
|
78
|
+
one click away: the **↻ button** under any picker re-fetches the portal and
|
|
79
|
+
updates every picker on the page at once. And switching a field's object clears
|
|
80
|
+
a property that doesn't exist on the new one — it could only fail at save time.
|
|
81
|
+
|
|
76
82
|
### An object picker to feed it
|
|
77
83
|
|
|
78
84
|
The sibling object field doesn't have to be a hand-typed enum: the
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { u as useIntl, o as objectLabel } from "./objectLabels-
|
|
3
|
+
import { u as useIntl, o as objectLabel } from "./objectLabels-DwOMxLfh.mjs";
|
|
4
4
|
import { Field, Flex, Loader, SingleSelect, SingleSelectOption } from "@strapi/design-system";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { g as getTranslation } from "./index-C0XHwXog.mjs";
|
|
6
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-BGtg7Ffj.mjs";
|
|
7
7
|
const HubspotObjectInput = React.forwardRef(
|
|
8
8
|
({ name, value, onChange, disabled, error, required, label, hint, labelAction }, ref) => {
|
|
9
9
|
const intl = useIntl();
|
|
10
10
|
const { formatMessage } = intl;
|
|
11
|
-
const {
|
|
12
|
-
const [schema, setSchema] = React.useState(null);
|
|
13
|
-
React.useEffect(() => {
|
|
14
|
-
let cancelled = false;
|
|
15
|
-
get(`/${PLUGIN_ID}/properties`).then(({ data }) => {
|
|
16
|
-
if (!cancelled) setSchema(data);
|
|
17
|
-
}).catch(() => {
|
|
18
|
-
if (!cancelled) setSchema({ configured: false, objects: [], unavailable: [] });
|
|
19
|
-
});
|
|
20
|
-
return () => {
|
|
21
|
-
cancelled = true;
|
|
22
|
-
};
|
|
23
|
-
}, [get]);
|
|
11
|
+
const { schema } = useHubspotSchema();
|
|
24
12
|
const emit = (next) => onChange({ target: { name, value: String(next ?? ""), type: "string" } });
|
|
25
13
|
const known = [
|
|
26
14
|
...schema?.objects ?? [],
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
|
-
const objectLabels = require("./objectLabels-
|
|
5
|
+
const objectLabels = require("./objectLabels-DksWJnOK.js");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const index = require("./index-B3c9qEYU.js");
|
|
8
|
+
const useHubspotSchema = require("./useHubspotSchema-C3vn1DuR.js");
|
|
9
9
|
function _interopNamespace(e) {
|
|
10
10
|
if (e && e.__esModule) return e;
|
|
11
11
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -28,19 +28,7 @@ const HubspotObjectInput = React__namespace.forwardRef(
|
|
|
28
28
|
({ name, value, onChange, disabled, error, required, label, hint, labelAction }, ref) => {
|
|
29
29
|
const intl = objectLabels.useIntl();
|
|
30
30
|
const { formatMessage } = intl;
|
|
31
|
-
const {
|
|
32
|
-
const [schema, setSchema] = React__namespace.useState(null);
|
|
33
|
-
React__namespace.useEffect(() => {
|
|
34
|
-
let cancelled = false;
|
|
35
|
-
get(`/${index.PLUGIN_ID}/properties`).then(({ data }) => {
|
|
36
|
-
if (!cancelled) setSchema(data);
|
|
37
|
-
}).catch(() => {
|
|
38
|
-
if (!cancelled) setSchema({ configured: false, objects: [], unavailable: [] });
|
|
39
|
-
});
|
|
40
|
-
return () => {
|
|
41
|
-
cancelled = true;
|
|
42
|
-
};
|
|
43
|
-
}, [get]);
|
|
31
|
+
const { schema } = useHubspotSchema.useHubspotSchema();
|
|
44
32
|
const emit = (next) => onChange({ target: { name, value: String(next ?? ""), type: "string" } });
|
|
45
33
|
const known = [
|
|
46
34
|
...schema?.objects ?? [],
|
|
@@ -0,0 +1,245 @@
|
|
|
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-DksWJnOK.js");
|
|
6
|
+
const designSystem = require("@strapi/design-system");
|
|
7
|
+
const icons = require("@strapi/icons");
|
|
8
|
+
const admin = require("@strapi/strapi/admin");
|
|
9
|
+
const index = require("./index-B3c9qEYU.js");
|
|
10
|
+
const useHubspotSchema = require("./useHubspotSchema-C3vn1DuR.js");
|
|
11
|
+
function _interopNamespace(e) {
|
|
12
|
+
if (e && e.__esModule) return e;
|
|
13
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
14
|
+
if (e) {
|
|
15
|
+
for (const k in e) {
|
|
16
|
+
if (k !== "default") {
|
|
17
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
18
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: () => e[k]
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
n.default = e;
|
|
26
|
+
return Object.freeze(n);
|
|
27
|
+
}
|
|
28
|
+
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
29
|
+
const oneLine = {
|
|
30
|
+
display: "block",
|
|
31
|
+
whiteSpace: "nowrap",
|
|
32
|
+
overflow: "hidden",
|
|
33
|
+
textOverflow: "ellipsis"
|
|
34
|
+
};
|
|
35
|
+
const HubspotPropertyInput = React__namespace.forwardRef(
|
|
36
|
+
({
|
|
37
|
+
name,
|
|
38
|
+
value,
|
|
39
|
+
onChange,
|
|
40
|
+
attribute,
|
|
41
|
+
disabled,
|
|
42
|
+
error,
|
|
43
|
+
required,
|
|
44
|
+
label,
|
|
45
|
+
hint,
|
|
46
|
+
labelAction
|
|
47
|
+
}, ref) => {
|
|
48
|
+
const intl = objectLabels.useIntl();
|
|
49
|
+
const { formatMessage } = intl;
|
|
50
|
+
const { schema, loadError, refresh, refreshing } = useHubspotSchema.useHubspotSchema();
|
|
51
|
+
const objectFieldName = attribute?.options?.objectField || "hsObject";
|
|
52
|
+
const siblingPath = React__namespace.useMemo(
|
|
53
|
+
() => name.replace(/[^.]+$/, objectFieldName),
|
|
54
|
+
[name, objectFieldName]
|
|
55
|
+
);
|
|
56
|
+
const siblingField = admin.useField(siblingPath);
|
|
57
|
+
const selectedObject = siblingField?.value;
|
|
58
|
+
const optionsFieldName = attribute?.options?.optionsField || "options";
|
|
59
|
+
const optionsPath = React__namespace.useMemo(
|
|
60
|
+
() => name.replace(/[^.]+$/, optionsFieldName),
|
|
61
|
+
[name, optionsFieldName]
|
|
62
|
+
);
|
|
63
|
+
const optionsField = admin.useField(optionsPath);
|
|
64
|
+
const [imported, setImported] = React__namespace.useState(false);
|
|
65
|
+
const emit = (next) => onChange({ target: { name, value: next ?? "", type: "string" } });
|
|
66
|
+
const previousObject = React__namespace.useRef(selectedObject);
|
|
67
|
+
React__namespace.useEffect(() => {
|
|
68
|
+
const previous = previousObject.current;
|
|
69
|
+
previousObject.current = selectedObject;
|
|
70
|
+
if (!previous || previous === selectedObject || !selectedObject) return;
|
|
71
|
+
if (!value || !schema?.configured) return;
|
|
72
|
+
const validHere = schema.properties.some(
|
|
73
|
+
(p) => p.object === selectedObject && p.name === value
|
|
74
|
+
);
|
|
75
|
+
if (!validHere) emit("");
|
|
76
|
+
}, [selectedObject]);
|
|
77
|
+
const options = React__namespace.useMemo(() => {
|
|
78
|
+
const all = schema?.properties ?? [];
|
|
79
|
+
const scoped = selectedObject ? all.filter((p) => p.object === selectedObject) : all;
|
|
80
|
+
const sorted = selectedObject ? [...scoped].sort(
|
|
81
|
+
(a, b) => (a.group ?? "").localeCompare(b.group ?? "") || a.label.localeCompare(b.label)
|
|
82
|
+
) : scoped;
|
|
83
|
+
const shown = sorted.map((p) => ({
|
|
84
|
+
value: p.name,
|
|
85
|
+
label: selectedObject ? `${p.group ? `${p.group} • ` : ""}${p.label} (${p.name})` : `${objectLabels.objectLabel(intl, p.object)} • ${p.label} (${p.name})`
|
|
86
|
+
}));
|
|
87
|
+
if (value && !scoped.some((p) => p.name === value)) {
|
|
88
|
+
const elsewhere = all.find((p) => p.name === value);
|
|
89
|
+
shown.unshift({
|
|
90
|
+
value,
|
|
91
|
+
label: elsewhere ? formatMessage(
|
|
92
|
+
{
|
|
93
|
+
id: index.getTranslation("picker.belongs-to"),
|
|
94
|
+
defaultMessage: "{property} — belongs to {object}"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
property: value,
|
|
98
|
+
object: objectLabels.objectLabel(intl, elsewhere.object)
|
|
99
|
+
}
|
|
100
|
+
) : formatMessage(
|
|
101
|
+
{
|
|
102
|
+
id: index.getTranslation("picker.unknown"),
|
|
103
|
+
defaultMessage: "{property} — unknown to the portal"
|
|
104
|
+
},
|
|
105
|
+
{ property: value }
|
|
106
|
+
)
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return shown;
|
|
110
|
+
}, [schema, selectedObject, value, intl, formatMessage]);
|
|
111
|
+
const describe = () => {
|
|
112
|
+
if (loadError !== null) {
|
|
113
|
+
return loadError || formatMessage({
|
|
114
|
+
id: index.getTranslation("picker.load-error"),
|
|
115
|
+
defaultMessage: "HubSpot properties unavailable"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (schema && !schema.configured) {
|
|
119
|
+
return formatMessage({
|
|
120
|
+
id: index.getTranslation("picker.not-configured"),
|
|
121
|
+
defaultMessage: "No HubSpot API key — free text. Set it in Settings → HubSpot."
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (selectedObject && schema?.unavailable.some((u) => u.object === selectedObject)) {
|
|
125
|
+
return formatMessage(
|
|
126
|
+
{
|
|
127
|
+
id: index.getTranslation("picker.object-unavailable"),
|
|
128
|
+
defaultMessage: "Properties of “{object}” unreadable — missing scope on the token."
|
|
129
|
+
},
|
|
130
|
+
{ object: objectLabels.objectLabel(intl, selectedObject) }
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return hint;
|
|
134
|
+
};
|
|
135
|
+
const crmLink = schema?.portalId && value && schema.properties.some((p) => p.name === value) ? `https://${schema.uiDomain || "app.hubspot.com"}/property-settings/${schema.portalId}/properties?search=${encodeURIComponent(value)}` : null;
|
|
136
|
+
const selectedProperty = value && schema ? schema.properties.find(
|
|
137
|
+
(p) => p.name === value && (!selectedObject || p.object === selectedObject)
|
|
138
|
+
) : void 0;
|
|
139
|
+
const importable = selectedProperty?.type === "enumeration" && (selectedProperty.options?.length ?? 0) > 0;
|
|
140
|
+
React__namespace.useEffect(() => setImported(false), [value]);
|
|
141
|
+
const importOptions = () => {
|
|
142
|
+
if (!selectedProperty || !optionsField) return;
|
|
143
|
+
const rows = selectedProperty.options.map((o, i) => ({
|
|
144
|
+
__temp_key__: `a${i}`,
|
|
145
|
+
value: o.value,
|
|
146
|
+
label: o.label ?? o.value
|
|
147
|
+
}));
|
|
148
|
+
optionsField.onChange({
|
|
149
|
+
target: { name: optionsPath, value: rows, type: "json" }
|
|
150
|
+
});
|
|
151
|
+
setImported(true);
|
|
152
|
+
};
|
|
153
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
154
|
+
designSystem.Field.Root,
|
|
155
|
+
{
|
|
156
|
+
name,
|
|
157
|
+
error,
|
|
158
|
+
hint: describe(),
|
|
159
|
+
required,
|
|
160
|
+
children: [
|
|
161
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { action: labelAction, children: label }),
|
|
162
|
+
!schema ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { paddingTop: 2, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true, children: formatMessage({
|
|
163
|
+
id: index.getTranslation("picker.loading"),
|
|
164
|
+
defaultMessage: "Loading HubSpot properties…"
|
|
165
|
+
}) }) }) : schema.configured ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
166
|
+
designSystem.Combobox,
|
|
167
|
+
{
|
|
168
|
+
ref,
|
|
169
|
+
value: value || "",
|
|
170
|
+
onChange: emit,
|
|
171
|
+
onClear: () => emit(""),
|
|
172
|
+
disabled,
|
|
173
|
+
placeholder: formatMessage({
|
|
174
|
+
id: index.getTranslation("picker.placeholder"),
|
|
175
|
+
defaultMessage: "Search a property…"
|
|
176
|
+
}),
|
|
177
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
178
|
+
noOptionsMessage: () => formatMessage({
|
|
179
|
+
id: index.getTranslation("picker.no-results"),
|
|
180
|
+
defaultMessage: "No matching property — properties are managed in HubSpot."
|
|
181
|
+
}),
|
|
182
|
+
children: options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: o.value, textValue: o.label, children: /* @__PURE__ */ jsxRuntime.jsx("span", { title: o.label, style: oneLine, children: o.label }) }, o.value))
|
|
183
|
+
}
|
|
184
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
185
|
+
designSystem.Field.Input,
|
|
186
|
+
{
|
|
187
|
+
ref,
|
|
188
|
+
value: value || "",
|
|
189
|
+
onChange: (e) => emit(e.target.value),
|
|
190
|
+
disabled,
|
|
191
|
+
placeholder: formatMessage({
|
|
192
|
+
id: index.getTranslation("picker.free-placeholder"),
|
|
193
|
+
defaultMessage: "e.g. hs_role, numberofemployees"
|
|
194
|
+
})
|
|
195
|
+
}
|
|
196
|
+
),
|
|
197
|
+
schema?.configured ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 1, gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
198
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
199
|
+
designSystem.IconButton,
|
|
200
|
+
{
|
|
201
|
+
label: formatMessage({
|
|
202
|
+
id: index.getTranslation("picker.refresh"),
|
|
203
|
+
defaultMessage: "Refresh the properties from HubSpot"
|
|
204
|
+
}),
|
|
205
|
+
variant: "ghost",
|
|
206
|
+
size: "XS",
|
|
207
|
+
onClick: refresh,
|
|
208
|
+
disabled: disabled || refreshing,
|
|
209
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowClockwise, {})
|
|
210
|
+
}
|
|
211
|
+
),
|
|
212
|
+
importable ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
213
|
+
designSystem.Button,
|
|
214
|
+
{
|
|
215
|
+
variant: "tertiary",
|
|
216
|
+
size: "S",
|
|
217
|
+
onClick: importOptions,
|
|
218
|
+
disabled,
|
|
219
|
+
children: formatMessage(
|
|
220
|
+
{
|
|
221
|
+
id: index.getTranslation("picker.import"),
|
|
222
|
+
defaultMessage: "Import the {count} options from HubSpot"
|
|
223
|
+
},
|
|
224
|
+
{ count: selectedProperty?.options.length ?? 0 }
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
) : null,
|
|
228
|
+
imported ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "success600", children: formatMessage({
|
|
229
|
+
id: index.getTranslation("picker.imported"),
|
|
230
|
+
defaultMessage: "Options imported — save to keep them."
|
|
231
|
+
}) }) : null,
|
|
232
|
+
crmLink ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { href: crmLink, isExternal: true, children: formatMessage({
|
|
233
|
+
id: index.getTranslation("picker.view"),
|
|
234
|
+
defaultMessage: "View in HubSpot"
|
|
235
|
+
}) }) : null
|
|
236
|
+
] }) : null,
|
|
237
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
|
|
238
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
239
|
+
]
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
HubspotPropertyInput.displayName = "HubspotPropertyInput";
|
|
245
|
+
exports.default = HubspotPropertyInput;
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { u as useIntl, o as objectLabel } from "./objectLabels-DwOMxLfh.mjs";
|
|
4
|
+
import { Field, Flex, Loader, Combobox, ComboboxOption, IconButton, Button, Typography, Link } from "@strapi/design-system";
|
|
5
|
+
import { ArrowClockwise } from "@strapi/icons";
|
|
6
|
+
import { useField } from "@strapi/strapi/admin";
|
|
7
|
+
import { g as getTranslation } from "./index-C0XHwXog.mjs";
|
|
8
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-BGtg7Ffj.mjs";
|
|
9
|
+
const oneLine = {
|
|
10
|
+
display: "block",
|
|
11
|
+
whiteSpace: "nowrap",
|
|
12
|
+
overflow: "hidden",
|
|
13
|
+
textOverflow: "ellipsis"
|
|
14
|
+
};
|
|
15
|
+
const HubspotPropertyInput = React.forwardRef(
|
|
16
|
+
({
|
|
17
|
+
name,
|
|
18
|
+
value,
|
|
19
|
+
onChange,
|
|
20
|
+
attribute,
|
|
21
|
+
disabled,
|
|
22
|
+
error,
|
|
23
|
+
required,
|
|
24
|
+
label,
|
|
25
|
+
hint,
|
|
26
|
+
labelAction
|
|
27
|
+
}, ref) => {
|
|
28
|
+
const intl = useIntl();
|
|
29
|
+
const { formatMessage } = intl;
|
|
30
|
+
const { schema, loadError, refresh, refreshing } = useHubspotSchema();
|
|
31
|
+
const objectFieldName = attribute?.options?.objectField || "hsObject";
|
|
32
|
+
const siblingPath = React.useMemo(
|
|
33
|
+
() => name.replace(/[^.]+$/, objectFieldName),
|
|
34
|
+
[name, objectFieldName]
|
|
35
|
+
);
|
|
36
|
+
const siblingField = useField(siblingPath);
|
|
37
|
+
const selectedObject = siblingField?.value;
|
|
38
|
+
const optionsFieldName = attribute?.options?.optionsField || "options";
|
|
39
|
+
const optionsPath = React.useMemo(
|
|
40
|
+
() => name.replace(/[^.]+$/, optionsFieldName),
|
|
41
|
+
[name, optionsFieldName]
|
|
42
|
+
);
|
|
43
|
+
const optionsField = useField(optionsPath);
|
|
44
|
+
const [imported, setImported] = React.useState(false);
|
|
45
|
+
const emit = (next) => onChange({ target: { name, value: next ?? "", type: "string" } });
|
|
46
|
+
const previousObject = React.useRef(selectedObject);
|
|
47
|
+
React.useEffect(() => {
|
|
48
|
+
const previous = previousObject.current;
|
|
49
|
+
previousObject.current = selectedObject;
|
|
50
|
+
if (!previous || previous === selectedObject || !selectedObject) return;
|
|
51
|
+
if (!value || !schema?.configured) return;
|
|
52
|
+
const validHere = schema.properties.some(
|
|
53
|
+
(p) => p.object === selectedObject && p.name === value
|
|
54
|
+
);
|
|
55
|
+
if (!validHere) emit("");
|
|
56
|
+
}, [selectedObject]);
|
|
57
|
+
const options = React.useMemo(() => {
|
|
58
|
+
const all = schema?.properties ?? [];
|
|
59
|
+
const scoped = selectedObject ? all.filter((p) => p.object === selectedObject) : all;
|
|
60
|
+
const sorted = selectedObject ? [...scoped].sort(
|
|
61
|
+
(a, b) => (a.group ?? "").localeCompare(b.group ?? "") || a.label.localeCompare(b.label)
|
|
62
|
+
) : scoped;
|
|
63
|
+
const shown = sorted.map((p) => ({
|
|
64
|
+
value: p.name,
|
|
65
|
+
label: selectedObject ? `${p.group ? `${p.group} • ` : ""}${p.label} (${p.name})` : `${objectLabel(intl, p.object)} • ${p.label} (${p.name})`
|
|
66
|
+
}));
|
|
67
|
+
if (value && !scoped.some((p) => p.name === value)) {
|
|
68
|
+
const elsewhere = all.find((p) => p.name === value);
|
|
69
|
+
shown.unshift({
|
|
70
|
+
value,
|
|
71
|
+
label: elsewhere ? formatMessage(
|
|
72
|
+
{
|
|
73
|
+
id: getTranslation("picker.belongs-to"),
|
|
74
|
+
defaultMessage: "{property} — belongs to {object}"
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
property: value,
|
|
78
|
+
object: objectLabel(intl, elsewhere.object)
|
|
79
|
+
}
|
|
80
|
+
) : formatMessage(
|
|
81
|
+
{
|
|
82
|
+
id: getTranslation("picker.unknown"),
|
|
83
|
+
defaultMessage: "{property} — unknown to the portal"
|
|
84
|
+
},
|
|
85
|
+
{ property: value }
|
|
86
|
+
)
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return shown;
|
|
90
|
+
}, [schema, selectedObject, value, intl, formatMessage]);
|
|
91
|
+
const describe = () => {
|
|
92
|
+
if (loadError !== null) {
|
|
93
|
+
return loadError || formatMessage({
|
|
94
|
+
id: getTranslation("picker.load-error"),
|
|
95
|
+
defaultMessage: "HubSpot properties unavailable"
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (schema && !schema.configured) {
|
|
99
|
+
return formatMessage({
|
|
100
|
+
id: getTranslation("picker.not-configured"),
|
|
101
|
+
defaultMessage: "No HubSpot API key — free text. Set it in Settings → HubSpot."
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (selectedObject && schema?.unavailable.some((u) => u.object === selectedObject)) {
|
|
105
|
+
return formatMessage(
|
|
106
|
+
{
|
|
107
|
+
id: getTranslation("picker.object-unavailable"),
|
|
108
|
+
defaultMessage: "Properties of “{object}” unreadable — missing scope on the token."
|
|
109
|
+
},
|
|
110
|
+
{ object: objectLabel(intl, selectedObject) }
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
return hint;
|
|
114
|
+
};
|
|
115
|
+
const crmLink = schema?.portalId && value && schema.properties.some((p) => p.name === value) ? `https://${schema.uiDomain || "app.hubspot.com"}/property-settings/${schema.portalId}/properties?search=${encodeURIComponent(value)}` : null;
|
|
116
|
+
const selectedProperty = value && schema ? schema.properties.find(
|
|
117
|
+
(p) => p.name === value && (!selectedObject || p.object === selectedObject)
|
|
118
|
+
) : void 0;
|
|
119
|
+
const importable = selectedProperty?.type === "enumeration" && (selectedProperty.options?.length ?? 0) > 0;
|
|
120
|
+
React.useEffect(() => setImported(false), [value]);
|
|
121
|
+
const importOptions = () => {
|
|
122
|
+
if (!selectedProperty || !optionsField) return;
|
|
123
|
+
const rows = selectedProperty.options.map((o, i) => ({
|
|
124
|
+
__temp_key__: `a${i}`,
|
|
125
|
+
value: o.value,
|
|
126
|
+
label: o.label ?? o.value
|
|
127
|
+
}));
|
|
128
|
+
optionsField.onChange({
|
|
129
|
+
target: { name: optionsPath, value: rows, type: "json" }
|
|
130
|
+
});
|
|
131
|
+
setImported(true);
|
|
132
|
+
};
|
|
133
|
+
return /* @__PURE__ */ jsxs(
|
|
134
|
+
Field.Root,
|
|
135
|
+
{
|
|
136
|
+
name,
|
|
137
|
+
error,
|
|
138
|
+
hint: describe(),
|
|
139
|
+
required,
|
|
140
|
+
children: [
|
|
141
|
+
/* @__PURE__ */ jsx(Field.Label, { action: labelAction, children: label }),
|
|
142
|
+
!schema ? /* @__PURE__ */ jsx(Flex, { paddingTop: 2, paddingBottom: 2, children: /* @__PURE__ */ jsx(Loader, { small: true, children: formatMessage({
|
|
143
|
+
id: getTranslation("picker.loading"),
|
|
144
|
+
defaultMessage: "Loading HubSpot properties…"
|
|
145
|
+
}) }) }) : schema.configured ? /* @__PURE__ */ jsx(
|
|
146
|
+
Combobox,
|
|
147
|
+
{
|
|
148
|
+
ref,
|
|
149
|
+
value: value || "",
|
|
150
|
+
onChange: emit,
|
|
151
|
+
onClear: () => emit(""),
|
|
152
|
+
disabled,
|
|
153
|
+
placeholder: formatMessage({
|
|
154
|
+
id: getTranslation("picker.placeholder"),
|
|
155
|
+
defaultMessage: "Search a property…"
|
|
156
|
+
}),
|
|
157
|
+
autocomplete: { type: "list", filter: "contains" },
|
|
158
|
+
noOptionsMessage: () => formatMessage({
|
|
159
|
+
id: getTranslation("picker.no-results"),
|
|
160
|
+
defaultMessage: "No matching property — properties are managed in HubSpot."
|
|
161
|
+
}),
|
|
162
|
+
children: options.map((o) => /* @__PURE__ */ jsx(ComboboxOption, { value: o.value, textValue: o.label, children: /* @__PURE__ */ jsx("span", { title: o.label, style: oneLine, children: o.label }) }, o.value))
|
|
163
|
+
}
|
|
164
|
+
) : /* @__PURE__ */ jsx(
|
|
165
|
+
Field.Input,
|
|
166
|
+
{
|
|
167
|
+
ref,
|
|
168
|
+
value: value || "",
|
|
169
|
+
onChange: (e) => emit(e.target.value),
|
|
170
|
+
disabled,
|
|
171
|
+
placeholder: formatMessage({
|
|
172
|
+
id: getTranslation("picker.free-placeholder"),
|
|
173
|
+
defaultMessage: "e.g. hs_role, numberofemployees"
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
),
|
|
177
|
+
schema?.configured ? /* @__PURE__ */ jsxs(Flex, { paddingTop: 1, gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
178
|
+
/* @__PURE__ */ jsx(
|
|
179
|
+
IconButton,
|
|
180
|
+
{
|
|
181
|
+
label: formatMessage({
|
|
182
|
+
id: getTranslation("picker.refresh"),
|
|
183
|
+
defaultMessage: "Refresh the properties from HubSpot"
|
|
184
|
+
}),
|
|
185
|
+
variant: "ghost",
|
|
186
|
+
size: "XS",
|
|
187
|
+
onClick: refresh,
|
|
188
|
+
disabled: disabled || refreshing,
|
|
189
|
+
children: /* @__PURE__ */ jsx(ArrowClockwise, {})
|
|
190
|
+
}
|
|
191
|
+
),
|
|
192
|
+
importable ? /* @__PURE__ */ jsx(
|
|
193
|
+
Button,
|
|
194
|
+
{
|
|
195
|
+
variant: "tertiary",
|
|
196
|
+
size: "S",
|
|
197
|
+
onClick: importOptions,
|
|
198
|
+
disabled,
|
|
199
|
+
children: formatMessage(
|
|
200
|
+
{
|
|
201
|
+
id: getTranslation("picker.import"),
|
|
202
|
+
defaultMessage: "Import the {count} options from HubSpot"
|
|
203
|
+
},
|
|
204
|
+
{ count: selectedProperty?.options.length ?? 0 }
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
) : null,
|
|
208
|
+
imported ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "success600", children: formatMessage({
|
|
209
|
+
id: getTranslation("picker.imported"),
|
|
210
|
+
defaultMessage: "Options imported — save to keep them."
|
|
211
|
+
}) }) : null,
|
|
212
|
+
crmLink ? /* @__PURE__ */ jsx(Link, { href: crmLink, isExternal: true, children: formatMessage({
|
|
213
|
+
id: getTranslation("picker.view"),
|
|
214
|
+
defaultMessage: "View in HubSpot"
|
|
215
|
+
}) }) : null
|
|
216
|
+
] }) : null,
|
|
217
|
+
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
218
|
+
/* @__PURE__ */ jsx(Field.Error, {})
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
);
|
|
224
|
+
HubspotPropertyInput.displayName = "HubspotPropertyInput";
|
|
225
|
+
export {
|
|
226
|
+
HubspotPropertyInput as default
|
|
227
|
+
};
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const React = require("react");
|
|
5
|
-
const objectLabels = require("./objectLabels-
|
|
5
|
+
const objectLabels = require("./objectLabels-DksWJnOK.js");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
7
|
const admin = require("@strapi/strapi/admin");
|
|
8
|
-
const index = require("./index-
|
|
8
|
+
const index = require("./index-B3c9qEYU.js");
|
|
9
9
|
require("react-dom");
|
|
10
10
|
function _interopNamespace(e) {
|
|
11
11
|
if (e && e.__esModule) return e;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
|
-
import { u as useIntl, o as objectLabel } from "./objectLabels-
|
|
3
|
+
import { u as useIntl, o as objectLabel } from "./objectLabels-DwOMxLfh.mjs";
|
|
4
4
|
import { Flex, Divider, Typography, Button, Box, Link as Link$1, Badge, Loader, Field } from "@strapi/design-system";
|
|
5
5
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
6
|
-
import { g as getTranslation, P as PLUGIN_ID } from "./index-
|
|
6
|
+
import { g as getTranslation, P as PLUGIN_ID } from "./index-C0XHwXog.mjs";
|
|
7
7
|
import "react-dom";
|
|
8
8
|
/**
|
|
9
9
|
* @remix-run/router v1.23.3
|
|
@@ -27,6 +27,7 @@ const en = {
|
|
|
27
27
|
"picker.unknown": "{property} — unknown to the portal",
|
|
28
28
|
"picker.view": "View in HubSpot",
|
|
29
29
|
"picker.no-results": "No matching property — properties are managed in HubSpot.",
|
|
30
|
+
"picker.refresh": "Refresh the properties from HubSpot",
|
|
30
31
|
"picker.import": "Import the {count} options from HubSpot",
|
|
31
32
|
"picker.imported": "Options imported — save to keep them.",
|
|
32
33
|
"settings.subtitle": "The private app token used to read the portal's properties and validate form mappings.",
|
|
@@ -25,6 +25,7 @@ const en = {
|
|
|
25
25
|
"picker.unknown": "{property} — unknown to the portal",
|
|
26
26
|
"picker.view": "View in HubSpot",
|
|
27
27
|
"picker.no-results": "No matching property — properties are managed in HubSpot.",
|
|
28
|
+
"picker.refresh": "Refresh the properties from HubSpot",
|
|
28
29
|
"picker.import": "Import the {count} options from HubSpot",
|
|
29
30
|
"picker.imported": "Options imported — save to keep them.",
|
|
30
31
|
"settings.subtitle": "The private app token used to read the portal's properties and validate form mappings.",
|
|
@@ -25,6 +25,7 @@ const fr = {
|
|
|
25
25
|
"picker.unknown": "{property} — inconnue du portail",
|
|
26
26
|
"picker.view": "Voir dans HubSpot",
|
|
27
27
|
"picker.no-results": "Aucune propriété correspondante — les propriétés se gèrent dans HubSpot.",
|
|
28
|
+
"picker.refresh": "Rafraîchir les propriétés depuis HubSpot",
|
|
28
29
|
"picker.import": "Importer les {count} options depuis HubSpot",
|
|
29
30
|
"picker.imported": "Options importées — enregistrez pour les conserver.",
|
|
30
31
|
"settings.subtitle": "Le jeton d'application privée utilisé pour lire les propriétés du portail et valider les mappings de formulaires.",
|
|
@@ -27,6 +27,7 @@ const fr = {
|
|
|
27
27
|
"picker.unknown": "{property} — inconnue du portail",
|
|
28
28
|
"picker.view": "Voir dans HubSpot",
|
|
29
29
|
"picker.no-results": "Aucune propriété correspondante — les propriétés se gèrent dans HubSpot.",
|
|
30
|
+
"picker.refresh": "Rafraîchir les propriétés depuis HubSpot",
|
|
30
31
|
"picker.import": "Importer les {count} options depuis HubSpot",
|
|
31
32
|
"picker.imported": "Options importées — enregistrez pour les conserver.",
|
|
32
33
|
"settings.subtitle": "Le jeton d'application privée utilisé pour lire les propriétés du portail et valider les mappings de formulaires.",
|
|
@@ -33,7 +33,7 @@ const index = {
|
|
|
33
33
|
defaultMessage: "Picked from the portal's real properties"
|
|
34
34
|
},
|
|
35
35
|
components: {
|
|
36
|
-
Input: async () => Promise.resolve().then(() => require("./HubspotPropertyInput-
|
|
36
|
+
Input: async () => Promise.resolve().then(() => require("./HubspotPropertyInput-Dk0t0NVe.js"))
|
|
37
37
|
},
|
|
38
38
|
// Exposed in the Content-Type Builder. Without this, `objectField` could
|
|
39
39
|
// only be set by hand-editing schema.json — which is not how anyone
|
|
@@ -96,7 +96,7 @@ const index = {
|
|
|
96
96
|
defaultMessage: "Picked from the portal's configured objects"
|
|
97
97
|
},
|
|
98
98
|
components: {
|
|
99
|
-
Input: async () => Promise.resolve().then(() => require("./HubspotObjectInput-
|
|
99
|
+
Input: async () => Promise.resolve().then(() => require("./HubspotObjectInput-DpXMFiPg.js"))
|
|
100
100
|
}
|
|
101
101
|
});
|
|
102
102
|
app.createSettingSection(
|
|
@@ -112,7 +112,7 @@ const index = {
|
|
|
112
112
|
// Mirrors the RBAC action registered server-side: a role without it
|
|
113
113
|
// doesn't see the link at all — the routes refuse it anyway.
|
|
114
114
|
permissions: [{ action: `plugin::${PLUGIN_ID}.settings`, subject: null }],
|
|
115
|
-
Component: async () => (await Promise.resolve().then(() => require("./Settings-
|
|
115
|
+
Component: async () => (await Promise.resolve().then(() => require("./Settings-CPxe6LdH.js"))).default
|
|
116
116
|
}
|
|
117
117
|
]
|
|
118
118
|
);
|
|
@@ -122,7 +122,7 @@ const index = {
|
|
|
122
122
|
return Promise.all(
|
|
123
123
|
locales.map(async (locale) => {
|
|
124
124
|
try {
|
|
125
|
-
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-
|
|
125
|
+
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => Promise.resolve().then(() => require("./en-BN5fD3ai.js")), "./translations/fr.json": () => Promise.resolve().then(() => require("./fr-D3-oO8Lt.js")) }), `./translations/${locale}.json`, 3);
|
|
126
126
|
return { data: prefixPluginTranslations(data), locale };
|
|
127
127
|
} catch {
|
|
128
128
|
return { data: {}, locale };
|
|
@@ -32,7 +32,7 @@ const index = {
|
|
|
32
32
|
defaultMessage: "Picked from the portal's real properties"
|
|
33
33
|
},
|
|
34
34
|
components: {
|
|
35
|
-
Input: async () => import("./HubspotPropertyInput-
|
|
35
|
+
Input: async () => import("./HubspotPropertyInput-av9782v6.mjs")
|
|
36
36
|
},
|
|
37
37
|
// Exposed in the Content-Type Builder. Without this, `objectField` could
|
|
38
38
|
// only be set by hand-editing schema.json — which is not how anyone
|
|
@@ -95,7 +95,7 @@ const index = {
|
|
|
95
95
|
defaultMessage: "Picked from the portal's configured objects"
|
|
96
96
|
},
|
|
97
97
|
components: {
|
|
98
|
-
Input: async () => import("./HubspotObjectInput-
|
|
98
|
+
Input: async () => import("./HubspotObjectInput-D9r_sGFe.mjs")
|
|
99
99
|
}
|
|
100
100
|
});
|
|
101
101
|
app.createSettingSection(
|
|
@@ -111,7 +111,7 @@ const index = {
|
|
|
111
111
|
// Mirrors the RBAC action registered server-side: a role without it
|
|
112
112
|
// doesn't see the link at all — the routes refuse it anyway.
|
|
113
113
|
permissions: [{ action: `plugin::${PLUGIN_ID}.settings`, subject: null }],
|
|
114
|
-
Component: async () => (await import("./Settings-
|
|
114
|
+
Component: async () => (await import("./Settings-DTzk6GWO.mjs")).default
|
|
115
115
|
}
|
|
116
116
|
]
|
|
117
117
|
);
|
|
@@ -121,7 +121,7 @@ const index = {
|
|
|
121
121
|
return Promise.all(
|
|
122
122
|
locales.map(async (locale) => {
|
|
123
123
|
try {
|
|
124
|
-
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-
|
|
124
|
+
const { default: data } = await __variableDynamicImportRuntimeHelper(/* @__PURE__ */ Object.assign({ "./translations/en.json": () => import("./en-xeTTAUtX.mjs"), "./translations/fr.json": () => import("./fr-BKODkfPy.mjs") }), `./translations/${locale}.json`, 3);
|
|
125
125
|
return { data: prefixPluginTranslations(data), locale };
|
|
126
126
|
} catch {
|
|
127
127
|
return { data: {}, locale };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const React = require("react");
|
|
3
|
-
const index = require("./index-
|
|
3
|
+
const index = require("./index-B3c9qEYU.js");
|
|
4
4
|
function _interopNamespace(e) {
|
|
5
5
|
if (e && e.__esModule) return e;
|
|
6
6
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { g as getTranslation } from "./index-
|
|
2
|
+
import { g as getTranslation } from "./index-C0XHwXog.mjs";
|
|
3
3
|
var __assign = function() {
|
|
4
4
|
__assign = Object.assign || function __assign2(t) {
|
|
5
5
|
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { useFetchClient } from "@strapi/strapi/admin";
|
|
3
|
+
import { P as PLUGIN_ID } from "./index-C0XHwXog.mjs";
|
|
4
|
+
let cached = null;
|
|
5
|
+
let inFlight = null;
|
|
6
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
7
|
+
const EMPTY = {
|
|
8
|
+
configured: false,
|
|
9
|
+
properties: [],
|
|
10
|
+
objects: [],
|
|
11
|
+
unavailable: []
|
|
12
|
+
};
|
|
13
|
+
const messageOf = (err) => err?.response?.data?.error?.message;
|
|
14
|
+
function useHubspotSchema() {
|
|
15
|
+
const { get } = useFetchClient();
|
|
16
|
+
const [schema, setSchema] = React.useState(cached);
|
|
17
|
+
const [loadError, setLoadError] = React.useState(null);
|
|
18
|
+
const [refreshing, setRefreshing] = React.useState(false);
|
|
19
|
+
const load = React.useCallback(
|
|
20
|
+
async (refresh2) => {
|
|
21
|
+
if (!refresh2 && cached) return;
|
|
22
|
+
if (refresh2) setRefreshing(true);
|
|
23
|
+
if (refresh2 || !inFlight) {
|
|
24
|
+
inFlight = get(
|
|
25
|
+
`/${PLUGIN_ID}/properties${refresh2 ? "?refresh=1" : ""}`
|
|
26
|
+
).then(({ data }) => data);
|
|
27
|
+
}
|
|
28
|
+
const request = inFlight;
|
|
29
|
+
try {
|
|
30
|
+
const data = await request;
|
|
31
|
+
cached = data;
|
|
32
|
+
setLoadError(null);
|
|
33
|
+
for (const notify of listeners) notify(data);
|
|
34
|
+
} catch (err) {
|
|
35
|
+
setSchema((current) => current ?? EMPTY);
|
|
36
|
+
setLoadError(messageOf(err) ?? "");
|
|
37
|
+
} finally {
|
|
38
|
+
if (inFlight === request) inFlight = null;
|
|
39
|
+
setRefreshing(false);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
[get]
|
|
43
|
+
);
|
|
44
|
+
React.useEffect(() => {
|
|
45
|
+
const notify = (data) => setSchema(data);
|
|
46
|
+
listeners.add(notify);
|
|
47
|
+
if (cached) setSchema(cached);
|
|
48
|
+
load(false);
|
|
49
|
+
return () => {
|
|
50
|
+
listeners.delete(notify);
|
|
51
|
+
};
|
|
52
|
+
}, [load]);
|
|
53
|
+
const refresh = React.useCallback(() => load(true), [load]);
|
|
54
|
+
return { schema, loadError, refresh, refreshing };
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
useHubspotSchema as u
|
|
58
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const React = require("react");
|
|
3
|
+
const admin = require("@strapi/strapi/admin");
|
|
4
|
+
const index = require("./index-B3c9qEYU.js");
|
|
5
|
+
function _interopNamespace(e) {
|
|
6
|
+
if (e && e.__esModule) return e;
|
|
7
|
+
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
8
|
+
if (e) {
|
|
9
|
+
for (const k in e) {
|
|
10
|
+
if (k !== "default") {
|
|
11
|
+
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
12
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: () => e[k]
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
n.default = e;
|
|
20
|
+
return Object.freeze(n);
|
|
21
|
+
}
|
|
22
|
+
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
23
|
+
let cached = null;
|
|
24
|
+
let inFlight = null;
|
|
25
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
26
|
+
const EMPTY = {
|
|
27
|
+
configured: false,
|
|
28
|
+
properties: [],
|
|
29
|
+
objects: [],
|
|
30
|
+
unavailable: []
|
|
31
|
+
};
|
|
32
|
+
const messageOf = (err) => err?.response?.data?.error?.message;
|
|
33
|
+
function useHubspotSchema() {
|
|
34
|
+
const { get } = admin.useFetchClient();
|
|
35
|
+
const [schema, setSchema] = React__namespace.useState(cached);
|
|
36
|
+
const [loadError, setLoadError] = React__namespace.useState(null);
|
|
37
|
+
const [refreshing, setRefreshing] = React__namespace.useState(false);
|
|
38
|
+
const load = React__namespace.useCallback(
|
|
39
|
+
async (refresh2) => {
|
|
40
|
+
if (!refresh2 && cached) return;
|
|
41
|
+
if (refresh2) setRefreshing(true);
|
|
42
|
+
if (refresh2 || !inFlight) {
|
|
43
|
+
inFlight = get(
|
|
44
|
+
`/${index.PLUGIN_ID}/properties${refresh2 ? "?refresh=1" : ""}`
|
|
45
|
+
).then(({ data }) => data);
|
|
46
|
+
}
|
|
47
|
+
const request = inFlight;
|
|
48
|
+
try {
|
|
49
|
+
const data = await request;
|
|
50
|
+
cached = data;
|
|
51
|
+
setLoadError(null);
|
|
52
|
+
for (const notify of listeners) notify(data);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
setSchema((current) => current ?? EMPTY);
|
|
55
|
+
setLoadError(messageOf(err) ?? "");
|
|
56
|
+
} finally {
|
|
57
|
+
if (inFlight === request) inFlight = null;
|
|
58
|
+
setRefreshing(false);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
[get]
|
|
62
|
+
);
|
|
63
|
+
React__namespace.useEffect(() => {
|
|
64
|
+
const notify = (data) => setSchema(data);
|
|
65
|
+
listeners.add(notify);
|
|
66
|
+
if (cached) setSchema(cached);
|
|
67
|
+
load(false);
|
|
68
|
+
return () => {
|
|
69
|
+
listeners.delete(notify);
|
|
70
|
+
};
|
|
71
|
+
}, [load]);
|
|
72
|
+
const refresh = React__namespace.useCallback(() => load(true), [load]);
|
|
73
|
+
return { schema, loadError, refresh, refreshing };
|
|
74
|
+
}
|
|
75
|
+
exports.useHubspotSchema = useHubspotSchema;
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface HsProperty {
|
|
2
|
+
name: string;
|
|
3
|
+
label: string;
|
|
4
|
+
object: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
options: {
|
|
7
|
+
value: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
}[];
|
|
10
|
+
group?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SchemaResponse {
|
|
13
|
+
configured: boolean;
|
|
14
|
+
properties: HsProperty[];
|
|
15
|
+
objects: string[];
|
|
16
|
+
unavailable: {
|
|
17
|
+
object: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
}[];
|
|
20
|
+
portalId?: number;
|
|
21
|
+
uiDomain?: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function useHubspotSchema(): {
|
|
24
|
+
schema: SchemaResponse | null;
|
|
25
|
+
loadError: string | null;
|
|
26
|
+
refresh: () => Promise<void>;
|
|
27
|
+
refreshing: boolean;
|
|
28
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-hubspot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "HubSpot integration for Strapi — pick CRM properties from a searchable list filtered by object, and catch bad mappings before they reach the API.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"strapi",
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { u as useIntl, o as objectLabel } from "./objectLabels-dM4o67Fz.mjs";
|
|
4
|
-
import { Field, Flex, Loader, Combobox, ComboboxOption, Button, Typography, Link } from "@strapi/design-system";
|
|
5
|
-
import { useFetchClient, useField } from "@strapi/strapi/admin";
|
|
6
|
-
import { P as PLUGIN_ID, g as getTranslation } from "./index-CKoBcX1T.mjs";
|
|
7
|
-
const oneLine = {
|
|
8
|
-
display: "block",
|
|
9
|
-
whiteSpace: "nowrap",
|
|
10
|
-
overflow: "hidden",
|
|
11
|
-
textOverflow: "ellipsis"
|
|
12
|
-
};
|
|
13
|
-
const HubspotPropertyInput = React.forwardRef(
|
|
14
|
-
({ name, value, onChange, attribute, disabled, error, required, label, hint, labelAction }, ref) => {
|
|
15
|
-
const intl = useIntl();
|
|
16
|
-
const { formatMessage } = intl;
|
|
17
|
-
const { get } = useFetchClient();
|
|
18
|
-
const [schema, setSchema] = React.useState(null);
|
|
19
|
-
const [loadError, setLoadError] = React.useState("");
|
|
20
|
-
const objectFieldName = attribute?.options?.objectField || "hsObject";
|
|
21
|
-
const siblingPath = React.useMemo(
|
|
22
|
-
() => name.replace(/[^.]+$/, objectFieldName),
|
|
23
|
-
[name, objectFieldName]
|
|
24
|
-
);
|
|
25
|
-
const siblingField = useField(siblingPath);
|
|
26
|
-
const selectedObject = siblingField?.value;
|
|
27
|
-
const optionsFieldName = attribute?.options?.optionsField || "options";
|
|
28
|
-
const optionsPath = React.useMemo(
|
|
29
|
-
() => name.replace(/[^.]+$/, optionsFieldName),
|
|
30
|
-
[name, optionsFieldName]
|
|
31
|
-
);
|
|
32
|
-
const optionsField = useField(optionsPath);
|
|
33
|
-
const [imported, setImported] = React.useState(false);
|
|
34
|
-
React.useEffect(() => {
|
|
35
|
-
let cancelled = false;
|
|
36
|
-
get(`/${PLUGIN_ID}/properties`).then(({ data }) => {
|
|
37
|
-
if (!cancelled) setSchema(data);
|
|
38
|
-
}).catch((err) => {
|
|
39
|
-
if (cancelled) return;
|
|
40
|
-
setSchema({ configured: false, properties: [], objects: [], unavailable: [] });
|
|
41
|
-
setLoadError(
|
|
42
|
-
err?.response?.data?.error?.message ?? formatMessage({
|
|
43
|
-
id: getTranslation("picker.load-error"),
|
|
44
|
-
defaultMessage: "HubSpot properties unavailable"
|
|
45
|
-
})
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
return () => {
|
|
49
|
-
cancelled = true;
|
|
50
|
-
};
|
|
51
|
-
}, [get]);
|
|
52
|
-
const emit = (next) => onChange({ target: { name, value: next ?? "", type: "string" } });
|
|
53
|
-
const options = React.useMemo(() => {
|
|
54
|
-
const all = schema?.properties ?? [];
|
|
55
|
-
const scoped = selectedObject ? all.filter((p) => p.object === selectedObject) : all;
|
|
56
|
-
const sorted = selectedObject ? [...scoped].sort(
|
|
57
|
-
(a, b) => (a.group ?? "").localeCompare(b.group ?? "") || a.label.localeCompare(b.label)
|
|
58
|
-
) : scoped;
|
|
59
|
-
const shown = sorted.map((p) => ({
|
|
60
|
-
value: p.name,
|
|
61
|
-
label: selectedObject ? `${p.group ? `${p.group} · ` : ""}${p.label} (${p.name})` : `${objectLabel(intl, p.object)} · ${p.label} (${p.name})`
|
|
62
|
-
}));
|
|
63
|
-
if (value && !scoped.some((p) => p.name === value)) {
|
|
64
|
-
const elsewhere = all.find((p) => p.name === value);
|
|
65
|
-
shown.unshift({
|
|
66
|
-
value,
|
|
67
|
-
label: elsewhere ? formatMessage(
|
|
68
|
-
{ id: getTranslation("picker.belongs-to"), defaultMessage: "{property} — belongs to {object}" },
|
|
69
|
-
{ property: value, object: objectLabel(intl, elsewhere.object) }
|
|
70
|
-
) : formatMessage(
|
|
71
|
-
{ id: getTranslation("picker.unknown"), defaultMessage: "{property} — unknown to the portal" },
|
|
72
|
-
{ property: value }
|
|
73
|
-
)
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
return shown;
|
|
77
|
-
}, [schema, selectedObject, value, intl, formatMessage]);
|
|
78
|
-
const describe = () => {
|
|
79
|
-
if (loadError) return loadError;
|
|
80
|
-
if (schema && !schema.configured) {
|
|
81
|
-
return formatMessage({
|
|
82
|
-
id: getTranslation("picker.not-configured"),
|
|
83
|
-
defaultMessage: "No HubSpot API key — free text. Set it in Settings → HubSpot."
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
if (selectedObject && schema?.unavailable.some((u) => u.object === selectedObject)) {
|
|
87
|
-
return formatMessage(
|
|
88
|
-
{
|
|
89
|
-
id: getTranslation("picker.object-unavailable"),
|
|
90
|
-
defaultMessage: "Properties of “{object}” unreadable — missing scope on the token."
|
|
91
|
-
},
|
|
92
|
-
{ object: objectLabel(intl, selectedObject) }
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
return hint;
|
|
96
|
-
};
|
|
97
|
-
const crmLink = schema?.portalId && value && schema.properties.some((p) => p.name === value) ? `https://${schema.uiDomain || "app.hubspot.com"}/property-settings/${schema.portalId}/properties?search=${encodeURIComponent(value)}` : null;
|
|
98
|
-
const selectedProperty = value && schema ? schema.properties.find(
|
|
99
|
-
(p) => p.name === value && (!selectedObject || p.object === selectedObject)
|
|
100
|
-
) : void 0;
|
|
101
|
-
const importable = selectedProperty?.type === "enumeration" && (selectedProperty.options?.length ?? 0) > 0;
|
|
102
|
-
React.useEffect(() => setImported(false), [value]);
|
|
103
|
-
const importOptions = () => {
|
|
104
|
-
if (!selectedProperty || !optionsField) return;
|
|
105
|
-
const rows = selectedProperty.options.map((o, i) => ({
|
|
106
|
-
__temp_key__: `a${i}`,
|
|
107
|
-
value: o.value,
|
|
108
|
-
label: o.label ?? o.value
|
|
109
|
-
}));
|
|
110
|
-
optionsField.onChange({
|
|
111
|
-
target: { name: optionsPath, value: rows, type: "json" }
|
|
112
|
-
});
|
|
113
|
-
setImported(true);
|
|
114
|
-
};
|
|
115
|
-
return /* @__PURE__ */ jsxs(Field.Root, { name, error, hint: describe(), required, children: [
|
|
116
|
-
/* @__PURE__ */ jsx(Field.Label, { action: labelAction, children: label }),
|
|
117
|
-
!schema ? /* @__PURE__ */ jsx(Flex, { paddingTop: 2, paddingBottom: 2, children: /* @__PURE__ */ jsx(Loader, { small: true, children: formatMessage({
|
|
118
|
-
id: getTranslation("picker.loading"),
|
|
119
|
-
defaultMessage: "Loading HubSpot properties…"
|
|
120
|
-
}) }) }) : schema.configured ? /* @__PURE__ */ jsx(
|
|
121
|
-
Combobox,
|
|
122
|
-
{
|
|
123
|
-
ref,
|
|
124
|
-
value: value || "",
|
|
125
|
-
onChange: emit,
|
|
126
|
-
onClear: () => emit(""),
|
|
127
|
-
disabled,
|
|
128
|
-
placeholder: formatMessage({
|
|
129
|
-
id: getTranslation("picker.placeholder"),
|
|
130
|
-
defaultMessage: "Search a property…"
|
|
131
|
-
}),
|
|
132
|
-
autocomplete: { type: "list", filter: "contains" },
|
|
133
|
-
noOptionsMessage: () => formatMessage({
|
|
134
|
-
id: getTranslation("picker.no-results"),
|
|
135
|
-
defaultMessage: "No matching property — properties are managed in HubSpot."
|
|
136
|
-
}),
|
|
137
|
-
children: options.map((o) => /* @__PURE__ */ jsx(ComboboxOption, { value: o.value, textValue: o.label, children: /* @__PURE__ */ jsx("span", { title: o.label, style: oneLine, children: o.label }) }, o.value))
|
|
138
|
-
}
|
|
139
|
-
) : /* @__PURE__ */ jsx(
|
|
140
|
-
Field.Input,
|
|
141
|
-
{
|
|
142
|
-
ref,
|
|
143
|
-
value: value || "",
|
|
144
|
-
onChange: (e) => emit(e.target.value),
|
|
145
|
-
disabled,
|
|
146
|
-
placeholder: formatMessage({
|
|
147
|
-
id: getTranslation("picker.free-placeholder"),
|
|
148
|
-
defaultMessage: "e.g. hs_role, numberofemployees"
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
),
|
|
152
|
-
crmLink || importable ? /* @__PURE__ */ jsxs(Flex, { paddingTop: 1, gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
153
|
-
importable ? /* @__PURE__ */ jsx(Button, { variant: "tertiary", size: "S", onClick: importOptions, disabled, children: formatMessage(
|
|
154
|
-
{
|
|
155
|
-
id: getTranslation("picker.import"),
|
|
156
|
-
defaultMessage: "Import the {count} options from HubSpot"
|
|
157
|
-
},
|
|
158
|
-
{ count: selectedProperty?.options.length ?? 0 }
|
|
159
|
-
) }) : null,
|
|
160
|
-
imported ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "success600", children: formatMessage({
|
|
161
|
-
id: getTranslation("picker.imported"),
|
|
162
|
-
defaultMessage: "Options imported — save to keep them."
|
|
163
|
-
}) }) : null,
|
|
164
|
-
crmLink ? /* @__PURE__ */ jsx(Link, { href: crmLink, isExternal: true, children: formatMessage({
|
|
165
|
-
id: getTranslation("picker.view"),
|
|
166
|
-
defaultMessage: "View in HubSpot"
|
|
167
|
-
}) }) : null
|
|
168
|
-
] }) : null,
|
|
169
|
-
/* @__PURE__ */ jsx(Field.Hint, {}),
|
|
170
|
-
/* @__PURE__ */ jsx(Field.Error, {})
|
|
171
|
-
] });
|
|
172
|
-
}
|
|
173
|
-
);
|
|
174
|
-
HubspotPropertyInput.displayName = "HubspotPropertyInput";
|
|
175
|
-
export {
|
|
176
|
-
HubspotPropertyInput as default
|
|
177
|
-
};
|
|
@@ -1,195 +0,0 @@
|
|
|
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-B76t8qqg.js");
|
|
6
|
-
const designSystem = require("@strapi/design-system");
|
|
7
|
-
const admin = require("@strapi/strapi/admin");
|
|
8
|
-
const index = require("./index-BUlB1rK9.js");
|
|
9
|
-
function _interopNamespace(e) {
|
|
10
|
-
if (e && e.__esModule) return e;
|
|
11
|
-
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
12
|
-
if (e) {
|
|
13
|
-
for (const k in e) {
|
|
14
|
-
if (k !== "default") {
|
|
15
|
-
const d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
-
enumerable: true,
|
|
18
|
-
get: () => e[k]
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
n.default = e;
|
|
24
|
-
return Object.freeze(n);
|
|
25
|
-
}
|
|
26
|
-
const React__namespace = /* @__PURE__ */ _interopNamespace(React);
|
|
27
|
-
const oneLine = {
|
|
28
|
-
display: "block",
|
|
29
|
-
whiteSpace: "nowrap",
|
|
30
|
-
overflow: "hidden",
|
|
31
|
-
textOverflow: "ellipsis"
|
|
32
|
-
};
|
|
33
|
-
const HubspotPropertyInput = React__namespace.forwardRef(
|
|
34
|
-
({ name, value, onChange, attribute, disabled, error, required, label, hint, labelAction }, ref) => {
|
|
35
|
-
const intl = objectLabels.useIntl();
|
|
36
|
-
const { formatMessage } = intl;
|
|
37
|
-
const { get } = admin.useFetchClient();
|
|
38
|
-
const [schema, setSchema] = React__namespace.useState(null);
|
|
39
|
-
const [loadError, setLoadError] = React__namespace.useState("");
|
|
40
|
-
const objectFieldName = attribute?.options?.objectField || "hsObject";
|
|
41
|
-
const siblingPath = React__namespace.useMemo(
|
|
42
|
-
() => name.replace(/[^.]+$/, objectFieldName),
|
|
43
|
-
[name, objectFieldName]
|
|
44
|
-
);
|
|
45
|
-
const siblingField = admin.useField(siblingPath);
|
|
46
|
-
const selectedObject = siblingField?.value;
|
|
47
|
-
const optionsFieldName = attribute?.options?.optionsField || "options";
|
|
48
|
-
const optionsPath = React__namespace.useMemo(
|
|
49
|
-
() => name.replace(/[^.]+$/, optionsFieldName),
|
|
50
|
-
[name, optionsFieldName]
|
|
51
|
-
);
|
|
52
|
-
const optionsField = admin.useField(optionsPath);
|
|
53
|
-
const [imported, setImported] = React__namespace.useState(false);
|
|
54
|
-
React__namespace.useEffect(() => {
|
|
55
|
-
let cancelled = false;
|
|
56
|
-
get(`/${index.PLUGIN_ID}/properties`).then(({ data }) => {
|
|
57
|
-
if (!cancelled) setSchema(data);
|
|
58
|
-
}).catch((err) => {
|
|
59
|
-
if (cancelled) return;
|
|
60
|
-
setSchema({ configured: false, properties: [], objects: [], unavailable: [] });
|
|
61
|
-
setLoadError(
|
|
62
|
-
err?.response?.data?.error?.message ?? formatMessage({
|
|
63
|
-
id: index.getTranslation("picker.load-error"),
|
|
64
|
-
defaultMessage: "HubSpot properties unavailable"
|
|
65
|
-
})
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
return () => {
|
|
69
|
-
cancelled = true;
|
|
70
|
-
};
|
|
71
|
-
}, [get]);
|
|
72
|
-
const emit = (next) => onChange({ target: { name, value: next ?? "", type: "string" } });
|
|
73
|
-
const options = React__namespace.useMemo(() => {
|
|
74
|
-
const all = schema?.properties ?? [];
|
|
75
|
-
const scoped = selectedObject ? all.filter((p) => p.object === selectedObject) : all;
|
|
76
|
-
const sorted = selectedObject ? [...scoped].sort(
|
|
77
|
-
(a, b) => (a.group ?? "").localeCompare(b.group ?? "") || a.label.localeCompare(b.label)
|
|
78
|
-
) : scoped;
|
|
79
|
-
const shown = sorted.map((p) => ({
|
|
80
|
-
value: p.name,
|
|
81
|
-
label: selectedObject ? `${p.group ? `${p.group} · ` : ""}${p.label} (${p.name})` : `${objectLabels.objectLabel(intl, p.object)} · ${p.label} (${p.name})`
|
|
82
|
-
}));
|
|
83
|
-
if (value && !scoped.some((p) => p.name === value)) {
|
|
84
|
-
const elsewhere = all.find((p) => p.name === value);
|
|
85
|
-
shown.unshift({
|
|
86
|
-
value,
|
|
87
|
-
label: elsewhere ? formatMessage(
|
|
88
|
-
{ id: index.getTranslation("picker.belongs-to"), defaultMessage: "{property} — belongs to {object}" },
|
|
89
|
-
{ property: value, object: objectLabels.objectLabel(intl, elsewhere.object) }
|
|
90
|
-
) : formatMessage(
|
|
91
|
-
{ id: index.getTranslation("picker.unknown"), defaultMessage: "{property} — unknown to the portal" },
|
|
92
|
-
{ property: value }
|
|
93
|
-
)
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
return shown;
|
|
97
|
-
}, [schema, selectedObject, value, intl, formatMessage]);
|
|
98
|
-
const describe = () => {
|
|
99
|
-
if (loadError) return loadError;
|
|
100
|
-
if (schema && !schema.configured) {
|
|
101
|
-
return formatMessage({
|
|
102
|
-
id: index.getTranslation("picker.not-configured"),
|
|
103
|
-
defaultMessage: "No HubSpot API key — free text. Set it in Settings → HubSpot."
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
if (selectedObject && schema?.unavailable.some((u) => u.object === selectedObject)) {
|
|
107
|
-
return formatMessage(
|
|
108
|
-
{
|
|
109
|
-
id: index.getTranslation("picker.object-unavailable"),
|
|
110
|
-
defaultMessage: "Properties of “{object}” unreadable — missing scope on the token."
|
|
111
|
-
},
|
|
112
|
-
{ object: objectLabels.objectLabel(intl, selectedObject) }
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
return hint;
|
|
116
|
-
};
|
|
117
|
-
const crmLink = schema?.portalId && value && schema.properties.some((p) => p.name === value) ? `https://${schema.uiDomain || "app.hubspot.com"}/property-settings/${schema.portalId}/properties?search=${encodeURIComponent(value)}` : null;
|
|
118
|
-
const selectedProperty = value && schema ? schema.properties.find(
|
|
119
|
-
(p) => p.name === value && (!selectedObject || p.object === selectedObject)
|
|
120
|
-
) : void 0;
|
|
121
|
-
const importable = selectedProperty?.type === "enumeration" && (selectedProperty.options?.length ?? 0) > 0;
|
|
122
|
-
React__namespace.useEffect(() => setImported(false), [value]);
|
|
123
|
-
const importOptions = () => {
|
|
124
|
-
if (!selectedProperty || !optionsField) return;
|
|
125
|
-
const rows = selectedProperty.options.map((o, i) => ({
|
|
126
|
-
__temp_key__: `a${i}`,
|
|
127
|
-
value: o.value,
|
|
128
|
-
label: o.label ?? o.value
|
|
129
|
-
}));
|
|
130
|
-
optionsField.onChange({
|
|
131
|
-
target: { name: optionsPath, value: rows, type: "json" }
|
|
132
|
-
});
|
|
133
|
-
setImported(true);
|
|
134
|
-
};
|
|
135
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name, error, hint: describe(), required, children: [
|
|
136
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { action: labelAction, children: label }),
|
|
137
|
-
!schema ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { paddingTop: 2, paddingBottom: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Loader, { small: true, children: formatMessage({
|
|
138
|
-
id: index.getTranslation("picker.loading"),
|
|
139
|
-
defaultMessage: "Loading HubSpot properties…"
|
|
140
|
-
}) }) }) : schema.configured ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
141
|
-
designSystem.Combobox,
|
|
142
|
-
{
|
|
143
|
-
ref,
|
|
144
|
-
value: value || "",
|
|
145
|
-
onChange: emit,
|
|
146
|
-
onClear: () => emit(""),
|
|
147
|
-
disabled,
|
|
148
|
-
placeholder: formatMessage({
|
|
149
|
-
id: index.getTranslation("picker.placeholder"),
|
|
150
|
-
defaultMessage: "Search a property…"
|
|
151
|
-
}),
|
|
152
|
-
autocomplete: { type: "list", filter: "contains" },
|
|
153
|
-
noOptionsMessage: () => formatMessage({
|
|
154
|
-
id: index.getTranslation("picker.no-results"),
|
|
155
|
-
defaultMessage: "No matching property — properties are managed in HubSpot."
|
|
156
|
-
}),
|
|
157
|
-
children: options.map((o) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.ComboboxOption, { value: o.value, textValue: o.label, children: /* @__PURE__ */ jsxRuntime.jsx("span", { title: o.label, style: oneLine, children: o.label }) }, o.value))
|
|
158
|
-
}
|
|
159
|
-
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
160
|
-
designSystem.Field.Input,
|
|
161
|
-
{
|
|
162
|
-
ref,
|
|
163
|
-
value: value || "",
|
|
164
|
-
onChange: (e) => emit(e.target.value),
|
|
165
|
-
disabled,
|
|
166
|
-
placeholder: formatMessage({
|
|
167
|
-
id: index.getTranslation("picker.free-placeholder"),
|
|
168
|
-
defaultMessage: "e.g. hs_role, numberofemployees"
|
|
169
|
-
})
|
|
170
|
-
}
|
|
171
|
-
),
|
|
172
|
-
crmLink || importable ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { paddingTop: 1, gap: 3, alignItems: "center", wrap: "wrap", children: [
|
|
173
|
-
importable ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", size: "S", onClick: importOptions, disabled, children: formatMessage(
|
|
174
|
-
{
|
|
175
|
-
id: index.getTranslation("picker.import"),
|
|
176
|
-
defaultMessage: "Import the {count} options from HubSpot"
|
|
177
|
-
},
|
|
178
|
-
{ count: selectedProperty?.options.length ?? 0 }
|
|
179
|
-
) }) : null,
|
|
180
|
-
imported ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "success600", children: formatMessage({
|
|
181
|
-
id: index.getTranslation("picker.imported"),
|
|
182
|
-
defaultMessage: "Options imported — save to keep them."
|
|
183
|
-
}) }) : null,
|
|
184
|
-
crmLink ? /* @__PURE__ */ jsxRuntime.jsx(designSystem.Link, { href: crmLink, isExternal: true, children: formatMessage({
|
|
185
|
-
id: index.getTranslation("picker.view"),
|
|
186
|
-
defaultMessage: "View in HubSpot"
|
|
187
|
-
}) }) : null
|
|
188
|
-
] }) : null,
|
|
189
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
|
|
190
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
191
|
-
] });
|
|
192
|
-
}
|
|
193
|
-
);
|
|
194
|
-
HubspotPropertyInput.displayName = "HubspotPropertyInput";
|
|
195
|
-
exports.default = HubspotPropertyInput;
|