strapi-plugin-hubspot 0.13.1 → 0.15.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 +33 -0
- package/README.md +58 -32
- package/dist/_chunks/{Forms-CHB-sKem.mjs → Forms-B7eIm0Fi.mjs} +38 -3
- package/dist/_chunks/{Forms-lrzuWzoB.js → Forms-ClyI4MJ1.js} +38 -3
- package/dist/_chunks/{HubspotFormInput-Bb6it0nP.js → HubspotFormInput-Do7F83V6.js} +1 -1
- package/dist/_chunks/{HubspotFormInput-YI09keTC.mjs → HubspotFormInput-cZAiaAaq.mjs} +1 -1
- package/dist/_chunks/{HubspotObjectInput-D3A6xzb3.js → HubspotObjectInput-DWqk2C26.js} +3 -3
- package/dist/_chunks/{HubspotObjectInput-CzLKT9oj.mjs → HubspotObjectInput-ZZk_7hWq.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-DicskLcN.mjs → HubspotPropertyInput-5bkDGmGo.mjs} +3 -3
- package/dist/_chunks/{HubspotPropertyInput-Dss3eUlL.js → HubspotPropertyInput-v9B3wb1a.js} +3 -3
- package/dist/_chunks/{Settings-4CbX3SPK.mjs → Settings-QcFbm3s5.mjs} +132 -36
- package/dist/_chunks/{Settings-Ch8tPZAV.js → Settings-X3EHnTaO.js} +131 -35
- package/dist/_chunks/{en-D8DJiSxd.mjs → en-DMJeF7EN.mjs} +19 -6
- package/dist/_chunks/{en-PYFibnDc.js → en-ZHvaZLi7.js} +19 -6
- package/dist/_chunks/{fr-BMjixfXn.mjs → fr-CVAntLmc.mjs} +18 -5
- package/dist/_chunks/{fr-yHk4sSEl.js → fr-Ds_2EAzZ.js} +18 -5
- package/dist/_chunks/{index-BE2ribUL.mjs → index-BSJAhj8r.mjs} +6 -6
- package/dist/_chunks/{index-BAvedd2m.js → index-BpcilDy1.js} +6 -6
- package/dist/_chunks/{objectLabels-CycoU0zY.js → objectLabels-CYXXFpNB.js} +1 -1
- package/dist/_chunks/{objectLabels-DGJxYjKz.mjs → objectLabels-CrYRzsqe.mjs} +1 -1
- package/dist/_chunks/{useHubspotSchema-DRfaI6mF.js → useHubspotSchema-Ba6xZUCL.js} +1 -1
- package/dist/_chunks/{useHubspotSchema-e31UsYb2.mjs → useHubspotSchema-CBF4GkmK.mjs} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/builder/types.d.ts +2 -0
- package/dist/server/index.js +502 -197
- package/dist/server/index.mjs +502 -197
- package/dist/server/src/__tests__/hsforms.test.d.ts +1 -0
- package/dist/server/src/__tests__/settings.test.d.ts +1 -0
- package/dist/server/src/content-types.d.ts +8 -0
- package/dist/server/src/forms.d.ts +10 -6
- package/dist/server/src/hsforms.d.ts +75 -0
- package/dist/server/src/importHubspot.d.ts +1 -0
- package/dist/server/src/index.d.ts +17 -2
- package/dist/server/src/settings.d.ts +36 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.15.0 — 2026-09-21
|
|
6
|
+
|
|
7
|
+
### Added — account settings in the admin
|
|
8
|
+
- **Settings → HubSpot** now holds the portal id, region (`eu1` / `na1`) and
|
|
9
|
+
the default marketing form (picked from the connected portal), not just the
|
|
10
|
+
private app token. Values saved here override `config/plugins.ts` and env.
|
|
11
|
+
Switching test → production is an admin change, not a deploy.
|
|
12
|
+
|
|
13
|
+
## 0.14.0 — 2026-09-21
|
|
14
|
+
|
|
15
|
+
### Changed — native HubSpot form conversions
|
|
16
|
+
- Submissions of a built form now post to HubSpot's **Forms API**
|
|
17
|
+
(`/submissions/v3/integration/secure/submit/{portalId}/{formGuid}`) when a
|
|
18
|
+
marketing form GUID is set. That is what HubSpot counts as a conversion:
|
|
19
|
+
Original Source, workflows, lead-center notifications, reporting.
|
|
20
|
+
- The GUID is configuration, not code: pick it in the builder (or set
|
|
21
|
+
`forms.defaultFormId`), and swap `portalId` / `region` when moving from a
|
|
22
|
+
test portal to production.
|
|
23
|
+
- The visitor's `hubspotutk` (`meta.hutk`) is forwarded as `context.hutk` so
|
|
24
|
+
attribution sticks to the session.
|
|
25
|
+
- Extra fields not declared on the HubSpot form are dropped (they 400 the
|
|
26
|
+
whole submit). GDPR `legalConsentOptions` is sent when the HubSpot form
|
|
27
|
+
has a consent block.
|
|
28
|
+
- **CRM contact upsert is the fallback** when no GUID is configured. Timeline
|
|
29
|
+
notes remain available (`forms.timelineNote`, default `true`) on that
|
|
30
|
+
fallback only — they are not form conversions.
|
|
31
|
+
- Company find-or-create (SIRET / domain) still runs after a successful
|
|
32
|
+
submit, once the contact is looked up by email.
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
- Form attribute `hubspotFormId` and a picker in the builder.
|
|
36
|
+
- Plugin config `portalId`, `region` (`eu1` by default), `forms.defaultFormId`.
|
|
37
|
+
|
|
5
38
|
## 0.13.1 — 2026-09-21
|
|
6
39
|
|
|
7
40
|
### Added
|
package/README.md
CHANGED
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
Build multi-step lead forms in a dedicated admin page: fields mapped to your
|
|
6
6
|
portal's *real* CRM properties through a searchable picker, conditional fields
|
|
7
7
|
and steps (AND/OR rules re-evaluated server-side), a public API your frontend
|
|
8
|
-
renders and posts to, and a submission pipeline that
|
|
9
|
-
finds-or-creates the Company
|
|
10
|
-
|
|
8
|
+
renders and posts to, and a submission pipeline that posts a **native HubSpot
|
|
9
|
+
form conversion** (Forms API + visitor `hutk`), finds-or-creates the Company
|
|
10
|
+
by corporate domain, and stores every submission in Strapi whatever the CRM's
|
|
11
|
+
mood.
|
|
11
12
|
|
|
12
13
|
Under it, the safety net this plugin has always been: property pickers as
|
|
13
14
|
custom fields for your own content types, save-time mapping validation, a
|
|
@@ -43,20 +44,28 @@ Permissions**):
|
|
|
43
44
|
| `GET` | `/api/hubspot/forms/:slug?locale=` | The published form — meta, steps, fields, conditions. The CRM mapping is stripped: the browser never learns your property names |
|
|
44
45
|
| `POST` | `/api/hubspot/forms/:slug/submit` | Validates (bounds, conditions, required), maps server-side, syncs HubSpot, stores the submission |
|
|
45
46
|
|
|
46
|
-
The submit pipeline, in order:
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
The submit pipeline, in order: HubSpot **Forms API** (native conversion —
|
|
48
|
+
Original Source, workflows, lead-center notifications) when a marketing form
|
|
49
|
+
GUID is set on the builder form or via `forms.defaultFormId`; the visitor's
|
|
50
|
+
`hutk` is forwarded so attribution sticks. Then the contact is looked up by
|
|
51
|
+
email and, when the address is on a corporate domain, the company is
|
|
52
|
+
found-or-created and associated. A CRM contact upsert is the **fallback**
|
|
53
|
+
when no GUID is configured — it does not count as a form conversion.
|
|
54
|
+
Timeline notes are opt-in and only used on that fallback.
|
|
55
|
+
|
|
56
|
+
Portal id, region and form GUIDs are configuration. A test portal today,
|
|
57
|
+
production tomorrow: swap `portalId` / `region` / the GUID, no code change.
|
|
53
58
|
|
|
54
59
|
```ts
|
|
55
60
|
hubspot: {
|
|
56
61
|
config: {
|
|
62
|
+
apiKey: env("HUBSPOT_API_KEY"),
|
|
63
|
+
portalId: env("HUBSPOT_PORTAL_ID"), // test now, production later
|
|
64
|
+
region: env("HUBSPOT_REGION", "eu1"), // eu1 → api-eu1.hsforms.com
|
|
57
65
|
forms: {
|
|
58
66
|
companyFromDomain: true, // Company by corporate domain + association
|
|
59
|
-
timelineNote:
|
|
67
|
+
timelineNote: false, // recap note on the CRM-upsert fallback only
|
|
68
|
+
defaultFormId: env("HUBSPOT_DEFAULT_FORM_ID", ""),
|
|
60
69
|
},
|
|
61
70
|
},
|
|
62
71
|
}
|
|
@@ -69,9 +78,9 @@ lives in your database, not in HubSpot's availability.
|
|
|
69
78
|
### GDPR consent
|
|
70
79
|
|
|
71
80
|
HubSpot's native *legal consent* block is **not** a CRM field. Importing a
|
|
72
|
-
HubSpot form skips it (you'll see "rebuild it as a field")
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
HubSpot form skips it (you'll see "rebuild it as a field"). The Forms API
|
|
82
|
+
submit sends `legalConsentOptions` when the HubSpot marketing form has a
|
|
83
|
+
GDPR block and the visitor ticked consent.
|
|
75
84
|
|
|
76
85
|
To connect consent so the CRM and Strapi both keep a proof:
|
|
77
86
|
|
|
@@ -81,17 +90,19 @@ To connect consent so the CRM and Strapi both keep a proof:
|
|
|
81
90
|
**Checkbox**, name it `consent` (that name is what the site recognizes —
|
|
82
91
|
it will not inject a second box), mark it **required**.
|
|
83
92
|
3. **Map it**: Object = Contact, property = `rgpd_consent`. The visitor's tick
|
|
84
|
-
then lands on the contact
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
4. **
|
|
93
|
+
then lands on the contact (if that property is on the HubSpot form) and in
|
|
94
|
+
`legalConsentOptions`. Leave `consentedAt` unmapped; the frontend sends it
|
|
95
|
+
in `meta.consentedAt`, stored on the submission.
|
|
96
|
+
4. **Point the builder form at a HubSpot marketing form** (right-hand panel)
|
|
97
|
+
so the tick is a native conversion, not a CRM note.
|
|
98
|
+
5. **Publish** the form. The public submit pipeline already refuses a payload
|
|
88
99
|
without consent when the site is in front (Nuxt BFF). Direct calls to
|
|
89
100
|
`/api/hubspot/forms/:slug/submit` still accept a form that has no consent
|
|
90
101
|
field — add the checkbox so required-field validation covers them too.
|
|
91
102
|
|
|
92
|
-
The
|
|
93
|
-
|
|
94
|
-
|
|
103
|
+
The frontend should also send `meta.hutk` (the `hubspotutk` cookie set by
|
|
104
|
+
HubSpot's tracking script) and `meta.pageUrl` so Original Source is Organic
|
|
105
|
+
Search / Direct / etc. rather than *Offline sources*.
|
|
95
106
|
|
|
96
107
|
### Browsing submissions
|
|
97
108
|
|
|
@@ -354,10 +365,17 @@ its equivalent per object you send to).
|
|
|
354
365
|
|
|
355
366
|
### A settings screen
|
|
356
367
|
|
|
357
|
-
**Settings → HubSpot** holds the private app token
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
368
|
+
**Settings → HubSpot** holds the private app token **and** the HubSpot account
|
|
369
|
+
that receives conversions: portal id, region (`eu1` / `na1`), and the default
|
|
370
|
+
marketing form (picked from the connected portal). Values saved here override
|
|
371
|
+
`config/plugins.ts` and env — switching test → production is an admin change,
|
|
372
|
+
not a deploy.
|
|
373
|
+
|
|
374
|
+
The token is stored server-side and never returned to the browser: the UI only
|
|
375
|
+
receives whether a key exists, where it comes from, and its last four
|
|
376
|
+
characters. Portal id / region / form GUID are not secrets and round-trip so
|
|
377
|
+
they can be edited. A "Test connection" button round-trips to HubSpot and
|
|
378
|
+
reports how many properties it can read.
|
|
361
379
|
|
|
362
380
|
Access is gated by a dedicated RBAC permission — **Settings →
|
|
363
381
|
Roles → Plugins → Hubspot**. A role without it neither sees the settings link
|
|
@@ -402,6 +420,8 @@ export default ({ env }) => ({
|
|
|
402
420
|
config: {
|
|
403
421
|
// Optional — the key can also be set from Settings → HubSpot.
|
|
404
422
|
apiKey: env("HUBSPOT_API_KEY", ""),
|
|
423
|
+
portalId: env("HUBSPOT_PORTAL_ID", ""),
|
|
424
|
+
region: env("HUBSPOT_REGION", "eu1"),
|
|
405
425
|
|
|
406
426
|
// Optional — objects whose properties are offered.
|
|
407
427
|
// Defaults to ["contact", "company"]. Standard names: contact, company,
|
|
@@ -448,6 +468,10 @@ Create a **private app** in HubSpot with a read scope per object you list:
|
|
|
448
468
|
- `crm.schemas.contacts.read`
|
|
449
469
|
- `crm.schemas.companies.read`
|
|
450
470
|
- `crm.schemas.deals.read`, `crm.schemas.custom.read`… as needed
|
|
471
|
+
- `crm.objects.contacts.read` / `write`, `crm.objects.companies.read` / `write`
|
|
472
|
+
- `forms` — list portal forms (import + builder picker) and **submit** them
|
|
473
|
+
via the Forms API (native conversions). Without this scope the pipeline
|
|
474
|
+
falls back to a CRM upsert, which HubSpot treats as an offline source.
|
|
451
475
|
|
|
452
476
|
An object the token can't read is **skipped, not fatal**: the picker keeps
|
|
453
477
|
working for the others and explains which one is missing a scope. `oauth` is
|
|
@@ -457,16 +481,18 @@ turn on the *view in HubSpot* links.
|
|
|
457
481
|
### Regions
|
|
458
482
|
|
|
459
483
|
The REST API is global: `api.hubapi.com` routes by token, whatever the portal's
|
|
460
|
-
hosting region. The **web app
|
|
461
|
-
`app-eu1.hubspot.com
|
|
462
|
-
|
|
463
|
-
|
|
484
|
+
hosting region. The **web app and the Forms API are not** — an EU-hosted portal
|
|
485
|
+
lives on `app-eu1.hubspot.com` and submits to `api-eu1.hsforms.com`. Set
|
|
486
|
+
`config.region` (`eu1`, `na1`, …) to match. Deep links are built from the
|
|
487
|
+
`uiDomain` HubSpot reports for your portal rather than a hardcoded host.
|
|
464
488
|
|
|
465
|
-
The key
|
|
489
|
+
The key, portal id, region and default form GUID are resolved in this order,
|
|
490
|
+
first match wins:
|
|
466
491
|
|
|
467
492
|
1. saved from **Settings → HubSpot**
|
|
468
|
-
2. `config.apiKey`
|
|
469
|
-
3.
|
|
493
|
+
2. `config/plugins.ts` (`apiKey`, `portalId`, `region`, `forms.defaultFormId`)
|
|
494
|
+
3. environment variables (`HUBSPOT_API_KEY`, `HUBSPOT_PORTAL_ID`,
|
|
495
|
+
`HUBSPOT_REGION`, `HUBSPOT_DEFAULT_FORM_ID`)
|
|
470
496
|
|
|
471
497
|
## Migrating an existing field
|
|
472
498
|
|
|
@@ -5,12 +5,12 @@ import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
|
5
5
|
import { Typography, Flex, Box, SingleSelect, SingleSelectOption, MultiSelect, MultiSelectOption, TextInput, IconButton, Button, Combobox, ComboboxOption, Field, Textarea, Checkbox, Divider, Loader, Badge, Table, Thead, Tr, Th, Tbody, Td, Modal } from "@strapi/design-system";
|
|
6
6
|
import { Trash, Plus, ArrowClockwise, ArrowLeft, Drag, ArrowUp, ArrowDown, List, Duplicate, Download } from "@strapi/icons";
|
|
7
7
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
8
|
-
import { g as getTranslation, P as PLUGIN_ID } from "./index-
|
|
8
|
+
import { g as getTranslation, P as PLUGIN_ID } from "./index-BSJAhj8r.mjs";
|
|
9
9
|
import { useSensors, useSensor, PointerSensor, KeyboardSensor, DndContext, closestCenter } from "@dnd-kit/core";
|
|
10
10
|
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable, arrayMove } from "@dnd-kit/sortable";
|
|
11
11
|
import { CSS } from "@dnd-kit/utilities";
|
|
12
|
-
import { o as objectLabel } from "./objectLabels-
|
|
13
|
-
import { u as useHubspotSchema } from "./useHubspotSchema-
|
|
12
|
+
import { o as objectLabel } from "./objectLabels-CrYRzsqe.mjs";
|
|
13
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-CBF4GkmK.mjs";
|
|
14
14
|
const OPERATORS = [
|
|
15
15
|
"eq",
|
|
16
16
|
"neq",
|
|
@@ -637,6 +637,7 @@ const FormEditor = () => {
|
|
|
637
637
|
const [errors, setErrors] = React.useState([]);
|
|
638
638
|
const [problems, setProblems] = React.useState([]);
|
|
639
639
|
const [feedback, setFeedback] = React.useState(null);
|
|
640
|
+
const [hsForms, setHsForms] = React.useState([]);
|
|
640
641
|
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
641
642
|
const query = locale ? `?locale=${locale}` : "";
|
|
642
643
|
React.useEffect(() => {
|
|
@@ -650,6 +651,9 @@ const FormEditor = () => {
|
|
|
650
651
|
React.useEffect(() => {
|
|
651
652
|
get("/i18n/locales").then(({ data }) => Array.isArray(data) && setLocales(data)).catch(() => setLocales([]));
|
|
652
653
|
}, [get]);
|
|
654
|
+
React.useEffect(() => {
|
|
655
|
+
get(`/${PLUGIN_ID}/builder/import/hubspot`).then(({ data }) => setHsForms(Array.isArray(data.forms) ? data.forms : [])).catch(() => setHsForms([]));
|
|
656
|
+
}, [get]);
|
|
653
657
|
React.useEffect(() => {
|
|
654
658
|
let cancelled = false;
|
|
655
659
|
setEntry(null);
|
|
@@ -744,6 +748,7 @@ const FormEditor = () => {
|
|
|
744
748
|
submitLabel: entry.submitLabel,
|
|
745
749
|
successMessage: entry.successMessage,
|
|
746
750
|
class: entry.class,
|
|
751
|
+
hubspotFormId: entry.hubspotFormId ?? "",
|
|
747
752
|
definition
|
|
748
753
|
}
|
|
749
754
|
);
|
|
@@ -1175,6 +1180,36 @@ const FormEditor = () => {
|
|
|
1175
1180
|
}
|
|
1176
1181
|
)
|
|
1177
1182
|
] }),
|
|
1183
|
+
/* @__PURE__ */ jsxs(Field.Root, { children: [
|
|
1184
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("editor.hubspot-form", "HubSpot marketing form") }),
|
|
1185
|
+
hsForms.length ? /* @__PURE__ */ jsxs(
|
|
1186
|
+
SingleSelect,
|
|
1187
|
+
{
|
|
1188
|
+
value: entry.hubspotFormId ?? "",
|
|
1189
|
+
placeholder: t(
|
|
1190
|
+
"editor.hubspot-form-placeholder",
|
|
1191
|
+
"Pick a form of the connected portal"
|
|
1192
|
+
),
|
|
1193
|
+
onChange: (id) => patchEntry({ hubspotFormId: String(id) || null }),
|
|
1194
|
+
children: [
|
|
1195
|
+
/* @__PURE__ */ jsx(SingleSelectOption, { value: "", children: t("editor.hubspot-form-none", "None — CRM upsert only") }),
|
|
1196
|
+
entry.hubspotFormId && !hsForms.some((f) => f.id === entry.hubspotFormId) && /* @__PURE__ */ jsx(SingleSelectOption, { value: entry.hubspotFormId, children: entry.hubspotFormId }),
|
|
1197
|
+
hsForms.map((f) => /* @__PURE__ */ jsx(SingleSelectOption, { value: f.id, children: f.name }, f.id))
|
|
1198
|
+
]
|
|
1199
|
+
}
|
|
1200
|
+
) : /* @__PURE__ */ jsx(
|
|
1201
|
+
TextInput,
|
|
1202
|
+
{
|
|
1203
|
+
value: entry.hubspotFormId ?? "",
|
|
1204
|
+
placeholder: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
|
1205
|
+
onChange: (e) => patchEntry({ hubspotFormId: e.target.value.trim() || null })
|
|
1206
|
+
}
|
|
1207
|
+
),
|
|
1208
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
1209
|
+
"editor.hubspot-form-hint",
|
|
1210
|
+
"Submissions go through HubSpot’s Forms API so they count as conversions. Switch the connected portal (test → production) and pick the matching form — nothing is hardcoded."
|
|
1211
|
+
) })
|
|
1212
|
+
] }),
|
|
1178
1213
|
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
1179
1214
|
"editor.form-hint",
|
|
1180
1215
|
"Select a step or a field to edit it. The public endpoint serves this form at /api/hubspot/forms/{slug}.",
|
|
@@ -7,12 +7,12 @@ const index = require("./index-DkTxsEqL.js");
|
|
|
7
7
|
const designSystem = require("@strapi/design-system");
|
|
8
8
|
const icons = require("@strapi/icons");
|
|
9
9
|
const admin = require("@strapi/strapi/admin");
|
|
10
|
-
const index$1 = require("./index-
|
|
10
|
+
const index$1 = require("./index-BpcilDy1.js");
|
|
11
11
|
const core = require("@dnd-kit/core");
|
|
12
12
|
const sortable = require("@dnd-kit/sortable");
|
|
13
13
|
const utilities = require("@dnd-kit/utilities");
|
|
14
|
-
const objectLabels = require("./objectLabels-
|
|
15
|
-
const useHubspotSchema = require("./useHubspotSchema-
|
|
14
|
+
const objectLabels = require("./objectLabels-CYXXFpNB.js");
|
|
15
|
+
const useHubspotSchema = require("./useHubspotSchema-Ba6xZUCL.js");
|
|
16
16
|
function _interopNamespace(e) {
|
|
17
17
|
if (e && e.__esModule) return e;
|
|
18
18
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -657,6 +657,7 @@ const FormEditor = () => {
|
|
|
657
657
|
const [errors, setErrors] = React__namespace.useState([]);
|
|
658
658
|
const [problems, setProblems] = React__namespace.useState([]);
|
|
659
659
|
const [feedback, setFeedback] = React__namespace.useState(null);
|
|
660
|
+
const [hsForms, setHsForms] = React__namespace.useState([]);
|
|
660
661
|
const t = (id, defaultMessage, values) => formatMessage({ id: index$1.getTranslation(id), defaultMessage }, values);
|
|
661
662
|
const query = locale ? `?locale=${locale}` : "";
|
|
662
663
|
React__namespace.useEffect(() => {
|
|
@@ -670,6 +671,9 @@ const FormEditor = () => {
|
|
|
670
671
|
React__namespace.useEffect(() => {
|
|
671
672
|
get("/i18n/locales").then(({ data }) => Array.isArray(data) && setLocales(data)).catch(() => setLocales([]));
|
|
672
673
|
}, [get]);
|
|
674
|
+
React__namespace.useEffect(() => {
|
|
675
|
+
get(`/${index$1.PLUGIN_ID}/builder/import/hubspot`).then(({ data }) => setHsForms(Array.isArray(data.forms) ? data.forms : [])).catch(() => setHsForms([]));
|
|
676
|
+
}, [get]);
|
|
673
677
|
React__namespace.useEffect(() => {
|
|
674
678
|
let cancelled = false;
|
|
675
679
|
setEntry(null);
|
|
@@ -764,6 +768,7 @@ const FormEditor = () => {
|
|
|
764
768
|
submitLabel: entry.submitLabel,
|
|
765
769
|
successMessage: entry.successMessage,
|
|
766
770
|
class: entry.class,
|
|
771
|
+
hubspotFormId: entry.hubspotFormId ?? "",
|
|
767
772
|
definition
|
|
768
773
|
}
|
|
769
774
|
);
|
|
@@ -1195,6 +1200,36 @@ const FormEditor = () => {
|
|
|
1195
1200
|
}
|
|
1196
1201
|
)
|
|
1197
1202
|
] }),
|
|
1203
|
+
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { children: [
|
|
1204
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: t("editor.hubspot-form", "HubSpot marketing form") }),
|
|
1205
|
+
hsForms.length ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1206
|
+
designSystem.SingleSelect,
|
|
1207
|
+
{
|
|
1208
|
+
value: entry.hubspotFormId ?? "",
|
|
1209
|
+
placeholder: t(
|
|
1210
|
+
"editor.hubspot-form-placeholder",
|
|
1211
|
+
"Pick a form of the connected portal"
|
|
1212
|
+
),
|
|
1213
|
+
onChange: (id) => patchEntry({ hubspotFormId: String(id) || null }),
|
|
1214
|
+
children: [
|
|
1215
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "", children: t("editor.hubspot-form-none", "None — CRM upsert only") }),
|
|
1216
|
+
entry.hubspotFormId && !hsForms.some((f) => f.id === entry.hubspotFormId) && /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: entry.hubspotFormId, children: entry.hubspotFormId }),
|
|
1217
|
+
hsForms.map((f) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: f.id, children: f.name }, f.id))
|
|
1218
|
+
]
|
|
1219
|
+
}
|
|
1220
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1221
|
+
designSystem.TextInput,
|
|
1222
|
+
{
|
|
1223
|
+
value: entry.hubspotFormId ?? "",
|
|
1224
|
+
placeholder: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
|
1225
|
+
onChange: (e) => patchEntry({ hubspotFormId: e.target.value.trim() || null })
|
|
1226
|
+
}
|
|
1227
|
+
),
|
|
1228
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
1229
|
+
"editor.hubspot-form-hint",
|
|
1230
|
+
"Submissions go through HubSpot’s Forms API so they count as conversions. Switch the connected portal (test → production) and pick the matching form — nothing is hardcoded."
|
|
1231
|
+
) })
|
|
1232
|
+
] }),
|
|
1198
1233
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
1199
1234
|
"editor.form-hint",
|
|
1200
1235
|
"Select a step or a field to edit it. The public endpoint serves this form at /api/hubspot/forms/{slug}.",
|
|
@@ -5,7 +5,7 @@ const React = require("react");
|
|
|
5
5
|
const index = require("./index-DkTxsEqL.js");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
7
|
const admin = require("@strapi/strapi/admin");
|
|
8
|
-
const index$1 = require("./index-
|
|
8
|
+
const index$1 = require("./index-BpcilDy1.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" } });
|
|
@@ -3,7 +3,7 @@ import * as React from "react";
|
|
|
3
3
|
import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
4
4
|
import { Field, Flex, Loader, Combobox, ComboboxOption } from "@strapi/design-system";
|
|
5
5
|
import { useFetchClient } from "@strapi/strapi/admin";
|
|
6
|
-
import { P as PLUGIN_ID, g as getTranslation } from "./index-
|
|
6
|
+
import { P as PLUGIN_ID, g as getTranslation } from "./index-BSJAhj8r.mjs";
|
|
7
7
|
const HubspotFormInput = React.forwardRef(
|
|
8
8
|
({ name, value, onChange, disabled, error, required, label, hint, labelAction }, ref) => {
|
|
9
9
|
const { formatMessage } = useIntl();
|
|
@@ -4,9 +4,9 @@ const jsxRuntime = require("react/jsx-runtime");
|
|
|
4
4
|
const React = require("react");
|
|
5
5
|
const index = require("./index-DkTxsEqL.js");
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
|
-
const index$1 = require("./index-
|
|
8
|
-
const objectLabels = require("./objectLabels-
|
|
9
|
-
const useHubspotSchema = require("./useHubspotSchema-
|
|
7
|
+
const index$1 = require("./index-BpcilDy1.js");
|
|
8
|
+
const objectLabels = require("./objectLabels-CYXXFpNB.js");
|
|
9
|
+
const useHubspotSchema = require("./useHubspotSchema-Ba6xZUCL.js");
|
|
10
10
|
function _interopNamespace(e) {
|
|
11
11
|
if (e && e.__esModule) return e;
|
|
12
12
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|
|
@@ -2,9 +2,9 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
4
4
|
import { Field, Flex, Loader, SingleSelect, SingleSelectOption } from "@strapi/design-system";
|
|
5
|
-
import { g as getTranslation } from "./index-
|
|
6
|
-
import { o as objectLabel } from "./objectLabels-
|
|
7
|
-
import { u as useHubspotSchema } from "./useHubspotSchema-
|
|
5
|
+
import { g as getTranslation } from "./index-BSJAhj8r.mjs";
|
|
6
|
+
import { o as objectLabel } from "./objectLabels-CrYRzsqe.mjs";
|
|
7
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-CBF4GkmK.mjs";
|
|
8
8
|
const HubspotObjectInput = React.forwardRef(
|
|
9
9
|
({ name, value, onChange, disabled, error, required, label, hint, labelAction }, ref) => {
|
|
10
10
|
const intl = useIntl();
|
package/dist/_chunks/{HubspotPropertyInput-DicskLcN.mjs → HubspotPropertyInput-5bkDGmGo.mjs}
RENAMED
|
@@ -4,9 +4,9 @@ import { u as useIntl } from "./index-CEh8vkxY.mjs";
|
|
|
4
4
|
import { Field, Flex, Loader, Combobox, ComboboxOption, IconButton, Button, Typography, Link } from "@strapi/design-system";
|
|
5
5
|
import { ArrowClockwise } from "@strapi/icons";
|
|
6
6
|
import { useField } from "@strapi/strapi/admin";
|
|
7
|
-
import { g as getTranslation } from "./index-
|
|
8
|
-
import { o as objectLabel } from "./objectLabels-
|
|
9
|
-
import { u as useHubspotSchema } from "./useHubspotSchema-
|
|
7
|
+
import { g as getTranslation } from "./index-BSJAhj8r.mjs";
|
|
8
|
+
import { o as objectLabel } from "./objectLabels-CrYRzsqe.mjs";
|
|
9
|
+
import { u as useHubspotSchema } from "./useHubspotSchema-CBF4GkmK.mjs";
|
|
10
10
|
const oneLine = {
|
|
11
11
|
display: "block",
|
|
12
12
|
whiteSpace: "nowrap",
|
|
@@ -6,9 +6,9 @@ const index = require("./index-DkTxsEqL.js");
|
|
|
6
6
|
const designSystem = require("@strapi/design-system");
|
|
7
7
|
const icons = require("@strapi/icons");
|
|
8
8
|
const admin = require("@strapi/strapi/admin");
|
|
9
|
-
const index$1 = require("./index-
|
|
10
|
-
const objectLabels = require("./objectLabels-
|
|
11
|
-
const useHubspotSchema = require("./useHubspotSchema-
|
|
9
|
+
const index$1 = require("./index-BpcilDy1.js");
|
|
10
|
+
const objectLabels = require("./objectLabels-CYXXFpNB.js");
|
|
11
|
+
const useHubspotSchema = require("./useHubspotSchema-Ba6xZUCL.js");
|
|
12
12
|
function _interopNamespace(e) {
|
|
13
13
|
if (e && e.__esModule) return e;
|
|
14
14
|
const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
|