strapi-plugin-hubspot 0.2.1 → 0.4.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 +145 -5
- package/dist/_chunks/HubspotObjectInput-DAq_W1rA.js +91 -0
- package/dist/_chunks/HubspotObjectInput-G-A_pL2j.mjs +73 -0
- package/dist/_chunks/HubspotPropertyInput-B-Jg0x68.js +186 -0
- package/dist/_chunks/HubspotPropertyInput-Cv77QiS6.mjs +168 -0
- package/dist/_chunks/Settings-58edRL5D.mjs +1293 -0
- package/dist/_chunks/Settings-CryiUgSe.js +1311 -0
- package/dist/_chunks/en-CnQbjHs-.js +81 -0
- package/dist/_chunks/en-DHQZuRsj.mjs +81 -0
- package/dist/_chunks/fr-Bv8zsNX5.js +81 -0
- package/dist/_chunks/fr-Dxgil7RP.mjs +81 -0
- package/dist/_chunks/index-BudHTwSw.mjs +137 -0
- package/dist/_chunks/index-Tlw1p93d.js +136 -0
- package/dist/_chunks/objectLabels-CJTKZ4vT.mjs +425 -0
- package/dist/_chunks/objectLabels-GRmYGCIn.js +442 -0
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/admin/src/components/AuditSection.d.ts +5 -0
- package/dist/admin/src/components/FailuresSection.d.ts +11 -0
- package/dist/admin/src/components/HubspotObjectInput.d.ts +28 -0
- package/dist/admin/src/components/HubspotPropertyInput.d.ts +1 -0
- package/dist/admin/src/getTranslation.d.ts +3 -0
- package/dist/admin/src/index.d.ts +6 -0
- package/dist/admin/src/objectLabels.d.ts +2 -1
- package/dist/server/index.js +445 -69
- package/dist/server/index.mjs +445 -69
- package/dist/server/src/__tests__/audit.test.d.ts +1 -0
- package/dist/server/src/__tests__/checkMapping.test.d.ts +1 -0
- package/dist/server/src/__tests__/loadSchema.test.d.ts +1 -0
- package/dist/server/src/__tests__/submit.test.d.ts +1 -0
- package/dist/server/src/__tests__/validation.test.d.ts +1 -0
- package/dist/server/src/audit.d.ts +60 -0
- package/dist/server/src/content-types.d.ts +56 -0
- package/dist/server/src/index.d.ts +104 -22
- package/dist/server/src/properties.d.ts +41 -5
- package/dist/server/src/submit.d.ts +35 -0
- package/dist/server/src/validation.d.ts +37 -0
- package/package.json +5 -2
- package/dist/_chunks/HubspotPropertyInput-BVFRtt49.js +0 -124
- package/dist/_chunks/HubspotPropertyInput-C7Wcw8ee.mjs +0 -106
- package/dist/_chunks/Settings-B5w7LAsH.mjs +0 -140
- package/dist/_chunks/Settings-TGB0MOHr.js +0 -158
- package/dist/_chunks/index-BpZtcsPM.mjs +0 -42
- package/dist/_chunks/index-DgsAHPui.js +0 -41
|
@@ -0,0 +1,1293 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { u as useIntl, o as objectLabel } from "./objectLabels-CJTKZ4vT.mjs";
|
|
4
|
+
import { Flex, Divider, Typography, Button, Box, Link as Link$1, Badge, Loader, Field } from "@strapi/design-system";
|
|
5
|
+
import { useFetchClient } from "@strapi/strapi/admin";
|
|
6
|
+
import { g as getTranslation, P as PLUGIN_ID } from "./index-BudHTwSw.mjs";
|
|
7
|
+
import "react-dom";
|
|
8
|
+
/**
|
|
9
|
+
* @remix-run/router v1.23.3
|
|
10
|
+
*
|
|
11
|
+
* Copyright (c) Remix Software Inc.
|
|
12
|
+
*
|
|
13
|
+
* This source code is licensed under the MIT license found in the
|
|
14
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
15
|
+
*
|
|
16
|
+
* @license MIT
|
|
17
|
+
*/
|
|
18
|
+
function _extends$2() {
|
|
19
|
+
return _extends$2 = Object.assign ? Object.assign.bind() : function(n) {
|
|
20
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
21
|
+
var t = arguments[e];
|
|
22
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
23
|
+
}
|
|
24
|
+
return n;
|
|
25
|
+
}, _extends$2.apply(null, arguments);
|
|
26
|
+
}
|
|
27
|
+
var Action;
|
|
28
|
+
(function(Action2) {
|
|
29
|
+
Action2["Pop"] = "POP";
|
|
30
|
+
Action2["Push"] = "PUSH";
|
|
31
|
+
Action2["Replace"] = "REPLACE";
|
|
32
|
+
})(Action || (Action = {}));
|
|
33
|
+
function invariant(value, message) {
|
|
34
|
+
if (value === false || value === null || typeof value === "undefined") {
|
|
35
|
+
throw new Error(message);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function warning(cond, message) {
|
|
39
|
+
if (!cond) {
|
|
40
|
+
if (typeof console !== "undefined") console.warn(message);
|
|
41
|
+
try {
|
|
42
|
+
throw new Error(message);
|
|
43
|
+
} catch (e) {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function createPath(_ref) {
|
|
48
|
+
let {
|
|
49
|
+
pathname = "/",
|
|
50
|
+
search = "",
|
|
51
|
+
hash = ""
|
|
52
|
+
} = _ref;
|
|
53
|
+
if (search && search !== "?") pathname += search.charAt(0) === "?" ? search : "?" + search;
|
|
54
|
+
if (hash && hash !== "#") pathname += hash.charAt(0) === "#" ? hash : "#" + hash;
|
|
55
|
+
return pathname;
|
|
56
|
+
}
|
|
57
|
+
function parsePath(path) {
|
|
58
|
+
let parsedPath = {};
|
|
59
|
+
if (path) {
|
|
60
|
+
let hashIndex = path.indexOf("#");
|
|
61
|
+
if (hashIndex >= 0) {
|
|
62
|
+
parsedPath.hash = path.substr(hashIndex);
|
|
63
|
+
path = path.substr(0, hashIndex);
|
|
64
|
+
}
|
|
65
|
+
let searchIndex = path.indexOf("?");
|
|
66
|
+
if (searchIndex >= 0) {
|
|
67
|
+
parsedPath.search = path.substr(searchIndex);
|
|
68
|
+
path = path.substr(0, searchIndex);
|
|
69
|
+
}
|
|
70
|
+
if (path) {
|
|
71
|
+
parsedPath.pathname = path;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return parsedPath;
|
|
75
|
+
}
|
|
76
|
+
var ResultType;
|
|
77
|
+
(function(ResultType2) {
|
|
78
|
+
ResultType2["data"] = "data";
|
|
79
|
+
ResultType2["deferred"] = "deferred";
|
|
80
|
+
ResultType2["redirect"] = "redirect";
|
|
81
|
+
ResultType2["error"] = "error";
|
|
82
|
+
})(ResultType || (ResultType = {}));
|
|
83
|
+
function matchPath(pattern, pathname) {
|
|
84
|
+
if (typeof pattern === "string") {
|
|
85
|
+
pattern = {
|
|
86
|
+
path: pattern,
|
|
87
|
+
caseSensitive: false,
|
|
88
|
+
end: true
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
let [matcher, compiledParams] = compilePath(pattern.path, pattern.caseSensitive, pattern.end);
|
|
92
|
+
let match = pathname.match(matcher);
|
|
93
|
+
if (!match) return null;
|
|
94
|
+
let matchedPathname = match[0];
|
|
95
|
+
let pathnameBase = matchedPathname.replace(/(.)\/+$/, "$1");
|
|
96
|
+
let captureGroups = match.slice(1);
|
|
97
|
+
let params = compiledParams.reduce((memo, _ref, index) => {
|
|
98
|
+
let {
|
|
99
|
+
paramName,
|
|
100
|
+
isOptional
|
|
101
|
+
} = _ref;
|
|
102
|
+
if (paramName === "*") {
|
|
103
|
+
let splatValue = captureGroups[index] || "";
|
|
104
|
+
pathnameBase = matchedPathname.slice(0, matchedPathname.length - splatValue.length).replace(/(.)\/+$/, "$1");
|
|
105
|
+
}
|
|
106
|
+
const value = captureGroups[index];
|
|
107
|
+
if (isOptional && !value) {
|
|
108
|
+
memo[paramName] = void 0;
|
|
109
|
+
} else {
|
|
110
|
+
memo[paramName] = (value || "").replace(/%2F/g, "/");
|
|
111
|
+
}
|
|
112
|
+
return memo;
|
|
113
|
+
}, {});
|
|
114
|
+
return {
|
|
115
|
+
params,
|
|
116
|
+
pathname: matchedPathname,
|
|
117
|
+
pathnameBase,
|
|
118
|
+
pattern
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function compilePath(path, caseSensitive, end) {
|
|
122
|
+
if (caseSensitive === void 0) {
|
|
123
|
+
caseSensitive = false;
|
|
124
|
+
}
|
|
125
|
+
if (end === void 0) {
|
|
126
|
+
end = true;
|
|
127
|
+
}
|
|
128
|
+
warning(path === "*" || !path.endsWith("*") || path.endsWith("/*"), 'Route path "' + path + '" will be treated as if it were ' + ('"' + path.replace(/\*$/, "/*") + '" because the `*` character must ') + "always follow a `/` in the pattern. To get rid of this warning, " + ('please change the route path to "' + path.replace(/\*$/, "/*") + '".'));
|
|
129
|
+
let params = [];
|
|
130
|
+
let regexpSource = "^" + path.replace(/\/*\*?$/, "").replace(/^\/*/, "/").replace(/[\\.*+^${}|()[\]]/g, "\\$&").replace(/\/:([\w-]+)(\?)?/g, (_, paramName, isOptional) => {
|
|
131
|
+
params.push({
|
|
132
|
+
paramName,
|
|
133
|
+
isOptional: isOptional != null
|
|
134
|
+
});
|
|
135
|
+
return isOptional ? "/?([^\\/]+)?" : "/([^\\/]+)";
|
|
136
|
+
});
|
|
137
|
+
if (path.endsWith("*")) {
|
|
138
|
+
params.push({
|
|
139
|
+
paramName: "*"
|
|
140
|
+
});
|
|
141
|
+
regexpSource += path === "*" || path === "/*" ? "(.*)$" : "(?:\\/(.+)|\\/*)$";
|
|
142
|
+
} else if (end) {
|
|
143
|
+
regexpSource += "\\/*$";
|
|
144
|
+
} else if (path !== "" && path !== "/") {
|
|
145
|
+
regexpSource += "(?:(?=\\/|$))";
|
|
146
|
+
} else ;
|
|
147
|
+
let matcher = new RegExp(regexpSource, caseSensitive ? void 0 : "i");
|
|
148
|
+
return [matcher, params];
|
|
149
|
+
}
|
|
150
|
+
function stripBasename(pathname, basename) {
|
|
151
|
+
if (basename === "/") return pathname;
|
|
152
|
+
if (!pathname.toLowerCase().startsWith(basename.toLowerCase())) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
let startIndex = basename.endsWith("/") ? basename.length - 1 : basename.length;
|
|
156
|
+
let nextChar = pathname.charAt(startIndex);
|
|
157
|
+
if (nextChar && nextChar !== "/") {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
return pathname.slice(startIndex) || "/";
|
|
161
|
+
}
|
|
162
|
+
const ABSOLUTE_URL_REGEX$1 = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
163
|
+
const isAbsoluteUrl = (url) => ABSOLUTE_URL_REGEX$1.test(url);
|
|
164
|
+
function resolvePath(to, fromPathname) {
|
|
165
|
+
if (fromPathname === void 0) {
|
|
166
|
+
fromPathname = "/";
|
|
167
|
+
}
|
|
168
|
+
let {
|
|
169
|
+
pathname: toPathname,
|
|
170
|
+
search = "",
|
|
171
|
+
hash = ""
|
|
172
|
+
} = typeof to === "string" ? parsePath(to) : to;
|
|
173
|
+
let pathname;
|
|
174
|
+
if (toPathname) {
|
|
175
|
+
if (isAbsoluteUrl(toPathname)) {
|
|
176
|
+
pathname = toPathname;
|
|
177
|
+
} else {
|
|
178
|
+
if (toPathname.includes("//")) {
|
|
179
|
+
let oldPathname = toPathname;
|
|
180
|
+
toPathname = removeDoubleSlashes(toPathname);
|
|
181
|
+
warning(false, "Pathnames cannot have embedded double slashes - normalizing " + (oldPathname + " -> " + toPathname));
|
|
182
|
+
}
|
|
183
|
+
if (toPathname.startsWith("/")) {
|
|
184
|
+
pathname = resolvePathname(toPathname.substring(1), "/");
|
|
185
|
+
} else {
|
|
186
|
+
pathname = resolvePathname(toPathname, fromPathname);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} else {
|
|
190
|
+
pathname = fromPathname;
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
pathname,
|
|
194
|
+
search: normalizeSearch(search),
|
|
195
|
+
hash: normalizeHash(hash)
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function resolvePathname(relativePath, fromPathname) {
|
|
199
|
+
let segments = fromPathname.replace(/\/+$/, "").split("/");
|
|
200
|
+
let relativeSegments = relativePath.split("/");
|
|
201
|
+
relativeSegments.forEach((segment) => {
|
|
202
|
+
if (segment === "..") {
|
|
203
|
+
if (segments.length > 1) segments.pop();
|
|
204
|
+
} else if (segment !== ".") {
|
|
205
|
+
segments.push(segment);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
return segments.length > 1 ? segments.join("/") : "/";
|
|
209
|
+
}
|
|
210
|
+
function getInvalidPathError(char, field, dest, path) {
|
|
211
|
+
return "Cannot include a '" + char + "' character in a manually specified " + ("`to." + field + "` field [" + JSON.stringify(path) + "]. Please separate it out to the ") + ("`to." + dest + "` field. Alternatively you may provide the full path as ") + 'a string in <Link to="..."> and the router will parse it for you.';
|
|
212
|
+
}
|
|
213
|
+
function getPathContributingMatches(matches) {
|
|
214
|
+
return matches.filter((match, index) => index === 0 || match.route.path && match.route.path.length > 0);
|
|
215
|
+
}
|
|
216
|
+
function getResolveToMatches(matches, v7_relativeSplatPath) {
|
|
217
|
+
let pathMatches = getPathContributingMatches(matches);
|
|
218
|
+
if (v7_relativeSplatPath) {
|
|
219
|
+
return pathMatches.map((match, idx) => idx === pathMatches.length - 1 ? match.pathname : match.pathnameBase);
|
|
220
|
+
}
|
|
221
|
+
return pathMatches.map((match) => match.pathnameBase);
|
|
222
|
+
}
|
|
223
|
+
function resolveTo(toArg, routePathnames, locationPathname, isPathRelative) {
|
|
224
|
+
if (isPathRelative === void 0) {
|
|
225
|
+
isPathRelative = false;
|
|
226
|
+
}
|
|
227
|
+
let to;
|
|
228
|
+
if (typeof toArg === "string") {
|
|
229
|
+
to = parsePath(toArg);
|
|
230
|
+
} else {
|
|
231
|
+
to = _extends$2({}, toArg);
|
|
232
|
+
invariant(!to.pathname || !to.pathname.includes("?"), getInvalidPathError("?", "pathname", "search", to));
|
|
233
|
+
invariant(!to.pathname || !to.pathname.includes("#"), getInvalidPathError("#", "pathname", "hash", to));
|
|
234
|
+
invariant(!to.search || !to.search.includes("#"), getInvalidPathError("#", "search", "hash", to));
|
|
235
|
+
}
|
|
236
|
+
let isEmptyPath = toArg === "" || to.pathname === "";
|
|
237
|
+
let toPathname = isEmptyPath ? "/" : to.pathname;
|
|
238
|
+
let from;
|
|
239
|
+
if (toPathname == null) {
|
|
240
|
+
from = locationPathname;
|
|
241
|
+
} else {
|
|
242
|
+
let routePathnameIndex = routePathnames.length - 1;
|
|
243
|
+
if (!isPathRelative && toPathname.startsWith("..")) {
|
|
244
|
+
let toSegments = toPathname.split("/");
|
|
245
|
+
while (toSegments[0] === "..") {
|
|
246
|
+
toSegments.shift();
|
|
247
|
+
routePathnameIndex -= 1;
|
|
248
|
+
}
|
|
249
|
+
to.pathname = toSegments.join("/");
|
|
250
|
+
}
|
|
251
|
+
from = routePathnameIndex >= 0 ? routePathnames[routePathnameIndex] : "/";
|
|
252
|
+
}
|
|
253
|
+
let path = resolvePath(to, from);
|
|
254
|
+
let hasExplicitTrailingSlash = toPathname && toPathname !== "/" && toPathname.endsWith("/");
|
|
255
|
+
let hasCurrentTrailingSlash = (isEmptyPath || toPathname === ".") && locationPathname.endsWith("/");
|
|
256
|
+
if (!path.pathname.endsWith("/") && (hasExplicitTrailingSlash || hasCurrentTrailingSlash)) {
|
|
257
|
+
path.pathname += "/";
|
|
258
|
+
}
|
|
259
|
+
return path;
|
|
260
|
+
}
|
|
261
|
+
const removeDoubleSlashes = (path) => path.replace(/\/\/+/g, "/");
|
|
262
|
+
const joinPaths = (paths) => removeDoubleSlashes(paths.join("/"));
|
|
263
|
+
const normalizeSearch = (search) => !search || search === "?" ? "" : search.startsWith("?") ? search : "?" + search;
|
|
264
|
+
const normalizeHash = (hash) => !hash || hash === "#" ? "" : hash.startsWith("#") ? hash : "#" + hash;
|
|
265
|
+
const validMutationMethodsArr = ["post", "put", "patch", "delete"];
|
|
266
|
+
new Set(validMutationMethodsArr);
|
|
267
|
+
const validRequestMethodsArr = ["get", ...validMutationMethodsArr];
|
|
268
|
+
new Set(validRequestMethodsArr);
|
|
269
|
+
/**
|
|
270
|
+
* React Router v6.30.4
|
|
271
|
+
*
|
|
272
|
+
* Copyright (c) Remix Software Inc.
|
|
273
|
+
*
|
|
274
|
+
* This source code is licensed under the MIT license found in the
|
|
275
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
276
|
+
*
|
|
277
|
+
* @license MIT
|
|
278
|
+
*/
|
|
279
|
+
function _extends$1() {
|
|
280
|
+
return _extends$1 = Object.assign ? Object.assign.bind() : function(n) {
|
|
281
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
282
|
+
var t = arguments[e];
|
|
283
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
284
|
+
}
|
|
285
|
+
return n;
|
|
286
|
+
}, _extends$1.apply(null, arguments);
|
|
287
|
+
}
|
|
288
|
+
const DataRouterContext = /* @__PURE__ */ React.createContext(null);
|
|
289
|
+
if (process.env.NODE_ENV !== "production") {
|
|
290
|
+
DataRouterContext.displayName = "DataRouter";
|
|
291
|
+
}
|
|
292
|
+
const DataRouterStateContext = /* @__PURE__ */ React.createContext(null);
|
|
293
|
+
if (process.env.NODE_ENV !== "production") {
|
|
294
|
+
DataRouterStateContext.displayName = "DataRouterState";
|
|
295
|
+
}
|
|
296
|
+
const AwaitContext = /* @__PURE__ */ React.createContext(null);
|
|
297
|
+
if (process.env.NODE_ENV !== "production") {
|
|
298
|
+
AwaitContext.displayName = "Await";
|
|
299
|
+
}
|
|
300
|
+
const NavigationContext = /* @__PURE__ */ React.createContext(null);
|
|
301
|
+
if (process.env.NODE_ENV !== "production") {
|
|
302
|
+
NavigationContext.displayName = "Navigation";
|
|
303
|
+
}
|
|
304
|
+
const LocationContext = /* @__PURE__ */ React.createContext(null);
|
|
305
|
+
if (process.env.NODE_ENV !== "production") {
|
|
306
|
+
LocationContext.displayName = "Location";
|
|
307
|
+
}
|
|
308
|
+
const RouteContext = /* @__PURE__ */ React.createContext({
|
|
309
|
+
outlet: null,
|
|
310
|
+
matches: [],
|
|
311
|
+
isDataRoute: false
|
|
312
|
+
});
|
|
313
|
+
if (process.env.NODE_ENV !== "production") {
|
|
314
|
+
RouteContext.displayName = "Route";
|
|
315
|
+
}
|
|
316
|
+
const RouteErrorContext = /* @__PURE__ */ React.createContext(null);
|
|
317
|
+
if (process.env.NODE_ENV !== "production") {
|
|
318
|
+
RouteErrorContext.displayName = "RouteError";
|
|
319
|
+
}
|
|
320
|
+
function useHref(to, _temp) {
|
|
321
|
+
let {
|
|
322
|
+
relative
|
|
323
|
+
} = _temp === void 0 ? {} : _temp;
|
|
324
|
+
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(
|
|
325
|
+
false,
|
|
326
|
+
// TODO: This error is probably because they somehow have 2 versions of the
|
|
327
|
+
// router loaded. We can help them understand how to avoid that.
|
|
328
|
+
"useHref() may be used only in the context of a <Router> component."
|
|
329
|
+
) : invariant(false) : void 0;
|
|
330
|
+
let {
|
|
331
|
+
basename,
|
|
332
|
+
navigator
|
|
333
|
+
} = React.useContext(NavigationContext);
|
|
334
|
+
let {
|
|
335
|
+
hash,
|
|
336
|
+
pathname,
|
|
337
|
+
search
|
|
338
|
+
} = useResolvedPath(to, {
|
|
339
|
+
relative
|
|
340
|
+
});
|
|
341
|
+
let joinedPathname = pathname;
|
|
342
|
+
if (basename !== "/") {
|
|
343
|
+
joinedPathname = pathname === "/" ? basename : joinPaths([basename, pathname]);
|
|
344
|
+
}
|
|
345
|
+
return navigator.createHref({
|
|
346
|
+
pathname: joinedPathname,
|
|
347
|
+
search,
|
|
348
|
+
hash
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
function useInRouterContext() {
|
|
352
|
+
return React.useContext(LocationContext) != null;
|
|
353
|
+
}
|
|
354
|
+
function useLocation() {
|
|
355
|
+
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(
|
|
356
|
+
false,
|
|
357
|
+
// TODO: This error is probably because they somehow have 2 versions of the
|
|
358
|
+
// router loaded. We can help them understand how to avoid that.
|
|
359
|
+
"useLocation() may be used only in the context of a <Router> component."
|
|
360
|
+
) : invariant(false) : void 0;
|
|
361
|
+
return React.useContext(LocationContext).location;
|
|
362
|
+
}
|
|
363
|
+
const navigateEffectWarning = "You should call navigate() in a React.useEffect(), not when your component is first rendered.";
|
|
364
|
+
function useIsomorphicLayoutEffect(cb) {
|
|
365
|
+
let isStatic = React.useContext(NavigationContext).static;
|
|
366
|
+
if (!isStatic) {
|
|
367
|
+
React.useLayoutEffect(cb);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
function useNavigate() {
|
|
371
|
+
let {
|
|
372
|
+
isDataRoute
|
|
373
|
+
} = React.useContext(RouteContext);
|
|
374
|
+
return isDataRoute ? useNavigateStable() : useNavigateUnstable();
|
|
375
|
+
}
|
|
376
|
+
function useNavigateUnstable() {
|
|
377
|
+
!useInRouterContext() ? process.env.NODE_ENV !== "production" ? invariant(
|
|
378
|
+
false,
|
|
379
|
+
// TODO: This error is probably because they somehow have 2 versions of the
|
|
380
|
+
// router loaded. We can help them understand how to avoid that.
|
|
381
|
+
"useNavigate() may be used only in the context of a <Router> component."
|
|
382
|
+
) : invariant(false) : void 0;
|
|
383
|
+
let dataRouterContext = React.useContext(DataRouterContext);
|
|
384
|
+
let {
|
|
385
|
+
basename,
|
|
386
|
+
future,
|
|
387
|
+
navigator
|
|
388
|
+
} = React.useContext(NavigationContext);
|
|
389
|
+
let {
|
|
390
|
+
matches
|
|
391
|
+
} = React.useContext(RouteContext);
|
|
392
|
+
let {
|
|
393
|
+
pathname: locationPathname
|
|
394
|
+
} = useLocation();
|
|
395
|
+
let routePathnamesJson = JSON.stringify(getResolveToMatches(matches, future.v7_relativeSplatPath));
|
|
396
|
+
let activeRef = React.useRef(false);
|
|
397
|
+
useIsomorphicLayoutEffect(() => {
|
|
398
|
+
activeRef.current = true;
|
|
399
|
+
});
|
|
400
|
+
let navigate = React.useCallback(function(to, options) {
|
|
401
|
+
if (options === void 0) {
|
|
402
|
+
options = {};
|
|
403
|
+
}
|
|
404
|
+
process.env.NODE_ENV !== "production" ? warning(activeRef.current, navigateEffectWarning) : void 0;
|
|
405
|
+
if (!activeRef.current) return;
|
|
406
|
+
if (typeof to === "number") {
|
|
407
|
+
navigator.go(to);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
let path = resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, options.relative === "path");
|
|
411
|
+
if (dataRouterContext == null && basename !== "/") {
|
|
412
|
+
path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
|
|
413
|
+
}
|
|
414
|
+
(!!options.replace ? navigator.replace : navigator.push)(path, options.state, options);
|
|
415
|
+
}, [basename, navigator, routePathnamesJson, locationPathname, dataRouterContext]);
|
|
416
|
+
return navigate;
|
|
417
|
+
}
|
|
418
|
+
function useResolvedPath(to, _temp2) {
|
|
419
|
+
let {
|
|
420
|
+
relative
|
|
421
|
+
} = _temp2 === void 0 ? {} : _temp2;
|
|
422
|
+
let {
|
|
423
|
+
future
|
|
424
|
+
} = React.useContext(NavigationContext);
|
|
425
|
+
let {
|
|
426
|
+
matches
|
|
427
|
+
} = React.useContext(RouteContext);
|
|
428
|
+
let {
|
|
429
|
+
pathname: locationPathname
|
|
430
|
+
} = useLocation();
|
|
431
|
+
let routePathnamesJson = JSON.stringify(getResolveToMatches(matches, future.v7_relativeSplatPath));
|
|
432
|
+
return React.useMemo(() => resolveTo(to, JSON.parse(routePathnamesJson), locationPathname, relative === "path"), [to, routePathnamesJson, locationPathname, relative]);
|
|
433
|
+
}
|
|
434
|
+
var DataRouterHook$1 = /* @__PURE__ */ function(DataRouterHook2) {
|
|
435
|
+
DataRouterHook2["UseBlocker"] = "useBlocker";
|
|
436
|
+
DataRouterHook2["UseRevalidator"] = "useRevalidator";
|
|
437
|
+
DataRouterHook2["UseNavigateStable"] = "useNavigate";
|
|
438
|
+
return DataRouterHook2;
|
|
439
|
+
}(DataRouterHook$1 || {});
|
|
440
|
+
var DataRouterStateHook$1 = /* @__PURE__ */ function(DataRouterStateHook2) {
|
|
441
|
+
DataRouterStateHook2["UseBlocker"] = "useBlocker";
|
|
442
|
+
DataRouterStateHook2["UseLoaderData"] = "useLoaderData";
|
|
443
|
+
DataRouterStateHook2["UseActionData"] = "useActionData";
|
|
444
|
+
DataRouterStateHook2["UseRouteError"] = "useRouteError";
|
|
445
|
+
DataRouterStateHook2["UseNavigation"] = "useNavigation";
|
|
446
|
+
DataRouterStateHook2["UseRouteLoaderData"] = "useRouteLoaderData";
|
|
447
|
+
DataRouterStateHook2["UseMatches"] = "useMatches";
|
|
448
|
+
DataRouterStateHook2["UseRevalidator"] = "useRevalidator";
|
|
449
|
+
DataRouterStateHook2["UseNavigateStable"] = "useNavigate";
|
|
450
|
+
DataRouterStateHook2["UseRouteId"] = "useRouteId";
|
|
451
|
+
return DataRouterStateHook2;
|
|
452
|
+
}(DataRouterStateHook$1 || {});
|
|
453
|
+
function getDataRouterConsoleError$1(hookName) {
|
|
454
|
+
return hookName + " must be used within a data router. See https://reactrouter.com/v6/routers/picking-a-router.";
|
|
455
|
+
}
|
|
456
|
+
function useDataRouterContext$1(hookName) {
|
|
457
|
+
let ctx = React.useContext(DataRouterContext);
|
|
458
|
+
!ctx ? process.env.NODE_ENV !== "production" ? invariant(false, getDataRouterConsoleError$1(hookName)) : invariant(false) : void 0;
|
|
459
|
+
return ctx;
|
|
460
|
+
}
|
|
461
|
+
function useRouteContext(hookName) {
|
|
462
|
+
let route = React.useContext(RouteContext);
|
|
463
|
+
!route ? process.env.NODE_ENV !== "production" ? invariant(false, getDataRouterConsoleError$1(hookName)) : invariant(false) : void 0;
|
|
464
|
+
return route;
|
|
465
|
+
}
|
|
466
|
+
function useCurrentRouteId(hookName) {
|
|
467
|
+
let route = useRouteContext(hookName);
|
|
468
|
+
let thisRoute = route.matches[route.matches.length - 1];
|
|
469
|
+
!thisRoute.route.id ? process.env.NODE_ENV !== "production" ? invariant(false, hookName + ' can only be used on routes that contain a unique "id"') : invariant(false) : void 0;
|
|
470
|
+
return thisRoute.route.id;
|
|
471
|
+
}
|
|
472
|
+
function useRouteId() {
|
|
473
|
+
return useCurrentRouteId(DataRouterStateHook$1.UseRouteId);
|
|
474
|
+
}
|
|
475
|
+
function useNavigateStable() {
|
|
476
|
+
let {
|
|
477
|
+
router
|
|
478
|
+
} = useDataRouterContext$1(DataRouterHook$1.UseNavigateStable);
|
|
479
|
+
let id = useCurrentRouteId(DataRouterStateHook$1.UseNavigateStable);
|
|
480
|
+
let activeRef = React.useRef(false);
|
|
481
|
+
useIsomorphicLayoutEffect(() => {
|
|
482
|
+
activeRef.current = true;
|
|
483
|
+
});
|
|
484
|
+
let navigate = React.useCallback(function(to, options) {
|
|
485
|
+
if (options === void 0) {
|
|
486
|
+
options = {};
|
|
487
|
+
}
|
|
488
|
+
process.env.NODE_ENV !== "production" ? warning(activeRef.current, navigateEffectWarning) : void 0;
|
|
489
|
+
if (!activeRef.current) return;
|
|
490
|
+
if (typeof to === "number") {
|
|
491
|
+
router.navigate(to);
|
|
492
|
+
} else {
|
|
493
|
+
router.navigate(to, _extends$1({
|
|
494
|
+
fromRouteId: id
|
|
495
|
+
}, options));
|
|
496
|
+
}
|
|
497
|
+
}, [router, id]);
|
|
498
|
+
return navigate;
|
|
499
|
+
}
|
|
500
|
+
new Promise(() => {
|
|
501
|
+
});
|
|
502
|
+
/**
|
|
503
|
+
* React Router DOM v6.30.4
|
|
504
|
+
*
|
|
505
|
+
* Copyright (c) Remix Software Inc.
|
|
506
|
+
*
|
|
507
|
+
* This source code is licensed under the MIT license found in the
|
|
508
|
+
* LICENSE.md file in the root directory of this source tree.
|
|
509
|
+
*
|
|
510
|
+
* @license MIT
|
|
511
|
+
*/
|
|
512
|
+
function _extends() {
|
|
513
|
+
return _extends = Object.assign ? Object.assign.bind() : function(n) {
|
|
514
|
+
for (var e = 1; e < arguments.length; e++) {
|
|
515
|
+
var t = arguments[e];
|
|
516
|
+
for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
|
|
517
|
+
}
|
|
518
|
+
return n;
|
|
519
|
+
}, _extends.apply(null, arguments);
|
|
520
|
+
}
|
|
521
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
522
|
+
if (null == r) return {};
|
|
523
|
+
var t = {};
|
|
524
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
525
|
+
if (-1 !== e.indexOf(n)) continue;
|
|
526
|
+
t[n] = r[n];
|
|
527
|
+
}
|
|
528
|
+
return t;
|
|
529
|
+
}
|
|
530
|
+
const defaultMethod = "get";
|
|
531
|
+
const defaultEncType = "application/x-www-form-urlencoded";
|
|
532
|
+
function isHtmlElement(object) {
|
|
533
|
+
return object != null && typeof object.tagName === "string";
|
|
534
|
+
}
|
|
535
|
+
function isButtonElement(object) {
|
|
536
|
+
return isHtmlElement(object) && object.tagName.toLowerCase() === "button";
|
|
537
|
+
}
|
|
538
|
+
function isFormElement(object) {
|
|
539
|
+
return isHtmlElement(object) && object.tagName.toLowerCase() === "form";
|
|
540
|
+
}
|
|
541
|
+
function isInputElement(object) {
|
|
542
|
+
return isHtmlElement(object) && object.tagName.toLowerCase() === "input";
|
|
543
|
+
}
|
|
544
|
+
function isModifiedEvent(event) {
|
|
545
|
+
return !!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
|
|
546
|
+
}
|
|
547
|
+
function shouldProcessLinkClick(event, target) {
|
|
548
|
+
return event.button === 0 && // Ignore everything but left clicks
|
|
549
|
+
(!target || target === "_self") && // Let browser handle "target=_blank" etc.
|
|
550
|
+
!isModifiedEvent(event);
|
|
551
|
+
}
|
|
552
|
+
let _formDataSupportsSubmitter = null;
|
|
553
|
+
function isFormDataSubmitterSupported() {
|
|
554
|
+
if (_formDataSupportsSubmitter === null) {
|
|
555
|
+
try {
|
|
556
|
+
new FormData(
|
|
557
|
+
document.createElement("form"),
|
|
558
|
+
// @ts-expect-error if FormData supports the submitter parameter, this will throw
|
|
559
|
+
0
|
|
560
|
+
);
|
|
561
|
+
_formDataSupportsSubmitter = false;
|
|
562
|
+
} catch (e) {
|
|
563
|
+
_formDataSupportsSubmitter = true;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
return _formDataSupportsSubmitter;
|
|
567
|
+
}
|
|
568
|
+
const supportedFormEncTypes = /* @__PURE__ */ new Set(["application/x-www-form-urlencoded", "multipart/form-data", "text/plain"]);
|
|
569
|
+
function getFormEncType(encType) {
|
|
570
|
+
if (encType != null && !supportedFormEncTypes.has(encType)) {
|
|
571
|
+
process.env.NODE_ENV !== "production" ? warning(false, '"' + encType + '" is not a valid `encType` for `<Form>`/`<fetcher.Form>` ' + ('and will default to "' + defaultEncType + '"')) : void 0;
|
|
572
|
+
return null;
|
|
573
|
+
}
|
|
574
|
+
return encType;
|
|
575
|
+
}
|
|
576
|
+
function getFormSubmissionInfo(target, basename) {
|
|
577
|
+
let method;
|
|
578
|
+
let action;
|
|
579
|
+
let encType;
|
|
580
|
+
let formData;
|
|
581
|
+
let body;
|
|
582
|
+
if (isFormElement(target)) {
|
|
583
|
+
let attr = target.getAttribute("action");
|
|
584
|
+
action = attr ? stripBasename(attr, basename) : null;
|
|
585
|
+
method = target.getAttribute("method") || defaultMethod;
|
|
586
|
+
encType = getFormEncType(target.getAttribute("enctype")) || defaultEncType;
|
|
587
|
+
formData = new FormData(target);
|
|
588
|
+
} else if (isButtonElement(target) || isInputElement(target) && (target.type === "submit" || target.type === "image")) {
|
|
589
|
+
let form = target.form;
|
|
590
|
+
if (form == null) {
|
|
591
|
+
throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');
|
|
592
|
+
}
|
|
593
|
+
let attr = target.getAttribute("formaction") || form.getAttribute("action");
|
|
594
|
+
action = attr ? stripBasename(attr, basename) : null;
|
|
595
|
+
method = target.getAttribute("formmethod") || form.getAttribute("method") || defaultMethod;
|
|
596
|
+
encType = getFormEncType(target.getAttribute("formenctype")) || getFormEncType(form.getAttribute("enctype")) || defaultEncType;
|
|
597
|
+
formData = new FormData(form, target);
|
|
598
|
+
if (!isFormDataSubmitterSupported()) {
|
|
599
|
+
let {
|
|
600
|
+
name,
|
|
601
|
+
type,
|
|
602
|
+
value
|
|
603
|
+
} = target;
|
|
604
|
+
if (type === "image") {
|
|
605
|
+
let prefix = name ? name + "." : "";
|
|
606
|
+
formData.append(prefix + "x", "0");
|
|
607
|
+
formData.append(prefix + "y", "0");
|
|
608
|
+
} else if (name) {
|
|
609
|
+
formData.append(name, value);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
} else if (isHtmlElement(target)) {
|
|
613
|
+
throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');
|
|
614
|
+
} else {
|
|
615
|
+
method = defaultMethod;
|
|
616
|
+
action = null;
|
|
617
|
+
encType = defaultEncType;
|
|
618
|
+
body = target;
|
|
619
|
+
}
|
|
620
|
+
if (formData && encType === "text/plain") {
|
|
621
|
+
body = formData;
|
|
622
|
+
formData = void 0;
|
|
623
|
+
}
|
|
624
|
+
return {
|
|
625
|
+
action,
|
|
626
|
+
method: method.toLowerCase(),
|
|
627
|
+
encType,
|
|
628
|
+
formData,
|
|
629
|
+
body
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
const _excluded = ["onClick", "relative", "reloadDocument", "replace", "state", "target", "to", "preventScrollReset", "viewTransition"], _excluded2 = ["aria-current", "caseSensitive", "className", "end", "style", "to", "viewTransition", "children"], _excluded3 = ["fetcherKey", "navigate", "reloadDocument", "replace", "state", "method", "action", "onSubmit", "relative", "preventScrollReset", "viewTransition"];
|
|
633
|
+
const REACT_ROUTER_VERSION = "6";
|
|
634
|
+
try {
|
|
635
|
+
window.__reactRouterVersion = REACT_ROUTER_VERSION;
|
|
636
|
+
} catch (e) {
|
|
637
|
+
}
|
|
638
|
+
const ViewTransitionContext = /* @__PURE__ */ React.createContext({
|
|
639
|
+
isTransitioning: false
|
|
640
|
+
});
|
|
641
|
+
if (process.env.NODE_ENV !== "production") {
|
|
642
|
+
ViewTransitionContext.displayName = "ViewTransition";
|
|
643
|
+
}
|
|
644
|
+
const FetchersContext = /* @__PURE__ */ React.createContext(/* @__PURE__ */ new Map());
|
|
645
|
+
if (process.env.NODE_ENV !== "production") {
|
|
646
|
+
FetchersContext.displayName = "Fetchers";
|
|
647
|
+
}
|
|
648
|
+
if (process.env.NODE_ENV !== "production") ;
|
|
649
|
+
const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
650
|
+
const ABSOLUTE_URL_REGEX = /^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;
|
|
651
|
+
const Link = /* @__PURE__ */ React.forwardRef(function LinkWithRef(_ref7, ref) {
|
|
652
|
+
let {
|
|
653
|
+
onClick,
|
|
654
|
+
relative,
|
|
655
|
+
reloadDocument,
|
|
656
|
+
replace,
|
|
657
|
+
state,
|
|
658
|
+
target,
|
|
659
|
+
to,
|
|
660
|
+
preventScrollReset,
|
|
661
|
+
viewTransition
|
|
662
|
+
} = _ref7, rest = _objectWithoutPropertiesLoose(_ref7, _excluded);
|
|
663
|
+
let {
|
|
664
|
+
basename
|
|
665
|
+
} = React.useContext(NavigationContext);
|
|
666
|
+
let absoluteHref;
|
|
667
|
+
let isExternal = false;
|
|
668
|
+
if (typeof to === "string" && ABSOLUTE_URL_REGEX.test(to)) {
|
|
669
|
+
absoluteHref = to;
|
|
670
|
+
if (isBrowser) {
|
|
671
|
+
try {
|
|
672
|
+
let currentUrl = new URL(window.location.href);
|
|
673
|
+
let targetUrl = to.startsWith("//") ? new URL(currentUrl.protocol + to) : new URL(to);
|
|
674
|
+
let path = stripBasename(targetUrl.pathname, basename);
|
|
675
|
+
if (targetUrl.origin === currentUrl.origin && path != null) {
|
|
676
|
+
to = path + targetUrl.search + targetUrl.hash;
|
|
677
|
+
} else {
|
|
678
|
+
isExternal = true;
|
|
679
|
+
}
|
|
680
|
+
} catch (e) {
|
|
681
|
+
process.env.NODE_ENV !== "production" ? warning(false, '<Link to="' + to + '"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.') : void 0;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
let href = useHref(to, {
|
|
686
|
+
relative
|
|
687
|
+
});
|
|
688
|
+
let internalOnClick = useLinkClickHandler(to, {
|
|
689
|
+
replace,
|
|
690
|
+
state,
|
|
691
|
+
target,
|
|
692
|
+
preventScrollReset,
|
|
693
|
+
relative,
|
|
694
|
+
viewTransition
|
|
695
|
+
});
|
|
696
|
+
function handleClick(event) {
|
|
697
|
+
if (onClick) onClick(event);
|
|
698
|
+
if (!event.defaultPrevented) {
|
|
699
|
+
internalOnClick(event);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return (
|
|
703
|
+
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
|
704
|
+
/* @__PURE__ */ React.createElement("a", _extends({}, rest, {
|
|
705
|
+
href: absoluteHref || href,
|
|
706
|
+
onClick: isExternal || reloadDocument ? onClick : handleClick,
|
|
707
|
+
ref,
|
|
708
|
+
target
|
|
709
|
+
}))
|
|
710
|
+
);
|
|
711
|
+
});
|
|
712
|
+
if (process.env.NODE_ENV !== "production") {
|
|
713
|
+
Link.displayName = "Link";
|
|
714
|
+
}
|
|
715
|
+
const NavLink = /* @__PURE__ */ React.forwardRef(function NavLinkWithRef(_ref8, ref) {
|
|
716
|
+
let {
|
|
717
|
+
"aria-current": ariaCurrentProp = "page",
|
|
718
|
+
caseSensitive = false,
|
|
719
|
+
className: classNameProp = "",
|
|
720
|
+
end = false,
|
|
721
|
+
style: styleProp,
|
|
722
|
+
to,
|
|
723
|
+
viewTransition,
|
|
724
|
+
children
|
|
725
|
+
} = _ref8, rest = _objectWithoutPropertiesLoose(_ref8, _excluded2);
|
|
726
|
+
let path = useResolvedPath(to, {
|
|
727
|
+
relative: rest.relative
|
|
728
|
+
});
|
|
729
|
+
let location = useLocation();
|
|
730
|
+
let routerState = React.useContext(DataRouterStateContext);
|
|
731
|
+
let {
|
|
732
|
+
navigator,
|
|
733
|
+
basename
|
|
734
|
+
} = React.useContext(NavigationContext);
|
|
735
|
+
let isTransitioning = routerState != null && // Conditional usage is OK here because the usage of a data router is static
|
|
736
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
737
|
+
useViewTransitionState(path) && viewTransition === true;
|
|
738
|
+
let toPathname = navigator.encodeLocation ? navigator.encodeLocation(path).pathname : path.pathname;
|
|
739
|
+
let locationPathname = location.pathname;
|
|
740
|
+
let nextLocationPathname = routerState && routerState.navigation && routerState.navigation.location ? routerState.navigation.location.pathname : null;
|
|
741
|
+
if (!caseSensitive) {
|
|
742
|
+
locationPathname = locationPathname.toLowerCase();
|
|
743
|
+
nextLocationPathname = nextLocationPathname ? nextLocationPathname.toLowerCase() : null;
|
|
744
|
+
toPathname = toPathname.toLowerCase();
|
|
745
|
+
}
|
|
746
|
+
if (nextLocationPathname && basename) {
|
|
747
|
+
nextLocationPathname = stripBasename(nextLocationPathname, basename) || nextLocationPathname;
|
|
748
|
+
}
|
|
749
|
+
const endSlashPosition = toPathname !== "/" && toPathname.endsWith("/") ? toPathname.length - 1 : toPathname.length;
|
|
750
|
+
let isActive = locationPathname === toPathname || !end && locationPathname.startsWith(toPathname) && locationPathname.charAt(endSlashPosition) === "/";
|
|
751
|
+
let isPending = nextLocationPathname != null && (nextLocationPathname === toPathname || !end && nextLocationPathname.startsWith(toPathname) && nextLocationPathname.charAt(toPathname.length) === "/");
|
|
752
|
+
let renderProps = {
|
|
753
|
+
isActive,
|
|
754
|
+
isPending,
|
|
755
|
+
isTransitioning
|
|
756
|
+
};
|
|
757
|
+
let ariaCurrent = isActive ? ariaCurrentProp : void 0;
|
|
758
|
+
let className;
|
|
759
|
+
if (typeof classNameProp === "function") {
|
|
760
|
+
className = classNameProp(renderProps);
|
|
761
|
+
} else {
|
|
762
|
+
className = [classNameProp, isActive ? "active" : null, isPending ? "pending" : null, isTransitioning ? "transitioning" : null].filter(Boolean).join(" ");
|
|
763
|
+
}
|
|
764
|
+
let style = typeof styleProp === "function" ? styleProp(renderProps) : styleProp;
|
|
765
|
+
return /* @__PURE__ */ React.createElement(Link, _extends({}, rest, {
|
|
766
|
+
"aria-current": ariaCurrent,
|
|
767
|
+
className,
|
|
768
|
+
ref,
|
|
769
|
+
style,
|
|
770
|
+
to,
|
|
771
|
+
viewTransition
|
|
772
|
+
}), typeof children === "function" ? children(renderProps) : children);
|
|
773
|
+
});
|
|
774
|
+
if (process.env.NODE_ENV !== "production") {
|
|
775
|
+
NavLink.displayName = "NavLink";
|
|
776
|
+
}
|
|
777
|
+
const Form = /* @__PURE__ */ React.forwardRef((_ref9, forwardedRef) => {
|
|
778
|
+
let {
|
|
779
|
+
fetcherKey,
|
|
780
|
+
navigate,
|
|
781
|
+
reloadDocument,
|
|
782
|
+
replace,
|
|
783
|
+
state,
|
|
784
|
+
method = defaultMethod,
|
|
785
|
+
action,
|
|
786
|
+
onSubmit,
|
|
787
|
+
relative,
|
|
788
|
+
preventScrollReset,
|
|
789
|
+
viewTransition
|
|
790
|
+
} = _ref9, props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
|
|
791
|
+
let submit = useSubmit();
|
|
792
|
+
let formAction = useFormAction(action, {
|
|
793
|
+
relative
|
|
794
|
+
});
|
|
795
|
+
let formMethod = method.toLowerCase() === "get" ? "get" : "post";
|
|
796
|
+
let submitHandler = (event) => {
|
|
797
|
+
onSubmit && onSubmit(event);
|
|
798
|
+
if (event.defaultPrevented) return;
|
|
799
|
+
event.preventDefault();
|
|
800
|
+
let submitter = event.nativeEvent.submitter;
|
|
801
|
+
let submitMethod = (submitter == null ? void 0 : submitter.getAttribute("formmethod")) || method;
|
|
802
|
+
submit(submitter || event.currentTarget, {
|
|
803
|
+
fetcherKey,
|
|
804
|
+
method: submitMethod,
|
|
805
|
+
navigate,
|
|
806
|
+
replace,
|
|
807
|
+
state,
|
|
808
|
+
relative,
|
|
809
|
+
preventScrollReset,
|
|
810
|
+
viewTransition
|
|
811
|
+
});
|
|
812
|
+
};
|
|
813
|
+
return /* @__PURE__ */ React.createElement("form", _extends({
|
|
814
|
+
ref: forwardedRef,
|
|
815
|
+
method: formMethod,
|
|
816
|
+
action: formAction,
|
|
817
|
+
onSubmit: reloadDocument ? onSubmit : submitHandler
|
|
818
|
+
}, props));
|
|
819
|
+
});
|
|
820
|
+
if (process.env.NODE_ENV !== "production") {
|
|
821
|
+
Form.displayName = "Form";
|
|
822
|
+
}
|
|
823
|
+
if (process.env.NODE_ENV !== "production") ;
|
|
824
|
+
var DataRouterHook;
|
|
825
|
+
(function(DataRouterHook2) {
|
|
826
|
+
DataRouterHook2["UseScrollRestoration"] = "useScrollRestoration";
|
|
827
|
+
DataRouterHook2["UseSubmit"] = "useSubmit";
|
|
828
|
+
DataRouterHook2["UseSubmitFetcher"] = "useSubmitFetcher";
|
|
829
|
+
DataRouterHook2["UseFetcher"] = "useFetcher";
|
|
830
|
+
DataRouterHook2["useViewTransitionState"] = "useViewTransitionState";
|
|
831
|
+
})(DataRouterHook || (DataRouterHook = {}));
|
|
832
|
+
var DataRouterStateHook;
|
|
833
|
+
(function(DataRouterStateHook2) {
|
|
834
|
+
DataRouterStateHook2["UseFetcher"] = "useFetcher";
|
|
835
|
+
DataRouterStateHook2["UseFetchers"] = "useFetchers";
|
|
836
|
+
DataRouterStateHook2["UseScrollRestoration"] = "useScrollRestoration";
|
|
837
|
+
})(DataRouterStateHook || (DataRouterStateHook = {}));
|
|
838
|
+
function getDataRouterConsoleError(hookName) {
|
|
839
|
+
return hookName + " must be used within a data router. See https://reactrouter.com/v6/routers/picking-a-router.";
|
|
840
|
+
}
|
|
841
|
+
function useDataRouterContext(hookName) {
|
|
842
|
+
let ctx = React.useContext(DataRouterContext);
|
|
843
|
+
!ctx ? process.env.NODE_ENV !== "production" ? invariant(false, getDataRouterConsoleError(hookName)) : invariant(false) : void 0;
|
|
844
|
+
return ctx;
|
|
845
|
+
}
|
|
846
|
+
function useLinkClickHandler(to, _temp) {
|
|
847
|
+
let {
|
|
848
|
+
target,
|
|
849
|
+
replace: replaceProp,
|
|
850
|
+
state,
|
|
851
|
+
preventScrollReset,
|
|
852
|
+
relative,
|
|
853
|
+
viewTransition
|
|
854
|
+
} = _temp === void 0 ? {} : _temp;
|
|
855
|
+
let navigate = useNavigate();
|
|
856
|
+
let location = useLocation();
|
|
857
|
+
let path = useResolvedPath(to, {
|
|
858
|
+
relative
|
|
859
|
+
});
|
|
860
|
+
return React.useCallback((event) => {
|
|
861
|
+
if (shouldProcessLinkClick(event, target)) {
|
|
862
|
+
event.preventDefault();
|
|
863
|
+
let replace = replaceProp !== void 0 ? replaceProp : createPath(location) === createPath(path);
|
|
864
|
+
navigate(to, {
|
|
865
|
+
replace,
|
|
866
|
+
state,
|
|
867
|
+
preventScrollReset,
|
|
868
|
+
relative,
|
|
869
|
+
viewTransition
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
}, [location, navigate, path, replaceProp, state, target, to, preventScrollReset, relative, viewTransition]);
|
|
873
|
+
}
|
|
874
|
+
function validateClientSideSubmission() {
|
|
875
|
+
if (typeof document === "undefined") {
|
|
876
|
+
throw new Error("You are calling submit during the server render. Try calling submit within a `useEffect` or callback instead.");
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
let fetcherId = 0;
|
|
880
|
+
let getUniqueFetcherId = () => "__" + String(++fetcherId) + "__";
|
|
881
|
+
function useSubmit() {
|
|
882
|
+
let {
|
|
883
|
+
router
|
|
884
|
+
} = useDataRouterContext(DataRouterHook.UseSubmit);
|
|
885
|
+
let {
|
|
886
|
+
basename
|
|
887
|
+
} = React.useContext(NavigationContext);
|
|
888
|
+
let currentRouteId = useRouteId();
|
|
889
|
+
return React.useCallback(function(target, options) {
|
|
890
|
+
if (options === void 0) {
|
|
891
|
+
options = {};
|
|
892
|
+
}
|
|
893
|
+
validateClientSideSubmission();
|
|
894
|
+
let {
|
|
895
|
+
action,
|
|
896
|
+
method,
|
|
897
|
+
encType,
|
|
898
|
+
formData,
|
|
899
|
+
body
|
|
900
|
+
} = getFormSubmissionInfo(target, basename);
|
|
901
|
+
if (options.navigate === false) {
|
|
902
|
+
let key = options.fetcherKey || getUniqueFetcherId();
|
|
903
|
+
router.fetch(key, currentRouteId, options.action || action, {
|
|
904
|
+
preventScrollReset: options.preventScrollReset,
|
|
905
|
+
formData,
|
|
906
|
+
body,
|
|
907
|
+
formMethod: options.method || method,
|
|
908
|
+
formEncType: options.encType || encType,
|
|
909
|
+
flushSync: options.flushSync
|
|
910
|
+
});
|
|
911
|
+
} else {
|
|
912
|
+
router.navigate(options.action || action, {
|
|
913
|
+
preventScrollReset: options.preventScrollReset,
|
|
914
|
+
formData,
|
|
915
|
+
body,
|
|
916
|
+
formMethod: options.method || method,
|
|
917
|
+
formEncType: options.encType || encType,
|
|
918
|
+
replace: options.replace,
|
|
919
|
+
state: options.state,
|
|
920
|
+
fromRouteId: currentRouteId,
|
|
921
|
+
flushSync: options.flushSync,
|
|
922
|
+
viewTransition: options.viewTransition
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
}, [router, basename, currentRouteId]);
|
|
926
|
+
}
|
|
927
|
+
function useFormAction(action, _temp2) {
|
|
928
|
+
let {
|
|
929
|
+
relative
|
|
930
|
+
} = _temp2 === void 0 ? {} : _temp2;
|
|
931
|
+
let {
|
|
932
|
+
basename
|
|
933
|
+
} = React.useContext(NavigationContext);
|
|
934
|
+
let routeContext = React.useContext(RouteContext);
|
|
935
|
+
!routeContext ? process.env.NODE_ENV !== "production" ? invariant(false, "useFormAction must be used inside a RouteContext") : invariant(false) : void 0;
|
|
936
|
+
let [match] = routeContext.matches.slice(-1);
|
|
937
|
+
let path = _extends({}, useResolvedPath(action ? action : ".", {
|
|
938
|
+
relative
|
|
939
|
+
}));
|
|
940
|
+
let location = useLocation();
|
|
941
|
+
if (action == null) {
|
|
942
|
+
path.search = location.search;
|
|
943
|
+
let params = new URLSearchParams(path.search);
|
|
944
|
+
let indexValues = params.getAll("index");
|
|
945
|
+
let hasNakedIndexParam = indexValues.some((v) => v === "");
|
|
946
|
+
if (hasNakedIndexParam) {
|
|
947
|
+
params.delete("index");
|
|
948
|
+
indexValues.filter((v) => v).forEach((v) => params.append("index", v));
|
|
949
|
+
let qs = params.toString();
|
|
950
|
+
path.search = qs ? "?" + qs : "";
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if ((!action || action === ".") && match.route.index) {
|
|
954
|
+
path.search = path.search ? path.search.replace(/^\?/, "?index&") : "?index";
|
|
955
|
+
}
|
|
956
|
+
if (basename !== "/") {
|
|
957
|
+
path.pathname = path.pathname === "/" ? basename : joinPaths([basename, path.pathname]);
|
|
958
|
+
}
|
|
959
|
+
return createPath(path);
|
|
960
|
+
}
|
|
961
|
+
function useViewTransitionState(to, opts) {
|
|
962
|
+
if (opts === void 0) {
|
|
963
|
+
opts = {};
|
|
964
|
+
}
|
|
965
|
+
let vtContext = React.useContext(ViewTransitionContext);
|
|
966
|
+
!(vtContext != null) ? process.env.NODE_ENV !== "production" ? invariant(false, "`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?") : invariant(false) : void 0;
|
|
967
|
+
let {
|
|
968
|
+
basename
|
|
969
|
+
} = useDataRouterContext(DataRouterHook.useViewTransitionState);
|
|
970
|
+
let path = useResolvedPath(to, {
|
|
971
|
+
relative: opts.relative
|
|
972
|
+
});
|
|
973
|
+
if (!vtContext.isTransitioning) {
|
|
974
|
+
return false;
|
|
975
|
+
}
|
|
976
|
+
let currentPath = stripBasename(vtContext.currentLocation.pathname, basename) || vtContext.currentLocation.pathname;
|
|
977
|
+
let nextPath = stripBasename(vtContext.nextLocation.pathname, basename) || vtContext.nextLocation.pathname;
|
|
978
|
+
return matchPath(path.pathname, nextPath) != null || matchPath(path.pathname, currentPath) != null;
|
|
979
|
+
}
|
|
980
|
+
const AuditSection = ({ configured }) => {
|
|
981
|
+
const intl = useIntl();
|
|
982
|
+
const { formatMessage } = intl;
|
|
983
|
+
const { get } = useFetchClient();
|
|
984
|
+
const [busy, setBusy] = React.useState(false);
|
|
985
|
+
const [error, setError] = React.useState(false);
|
|
986
|
+
const [result, setResult] = React.useState(null);
|
|
987
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
988
|
+
const problemText = (p) => {
|
|
989
|
+
switch (p.code) {
|
|
990
|
+
case "unknown":
|
|
991
|
+
return t("problem.unknown", "“{property}” does not exist on {object} in this portal", {
|
|
992
|
+
property: p.property,
|
|
993
|
+
object: objectLabel(intl, p.object)
|
|
994
|
+
});
|
|
995
|
+
case "wrong-object":
|
|
996
|
+
return t("problem.wrong-object", "“{property}” exists on {actual}, not on {object}", {
|
|
997
|
+
property: p.property,
|
|
998
|
+
object: objectLabel(intl, p.object),
|
|
999
|
+
actual: objectLabel(intl, p.actualObject)
|
|
1000
|
+
});
|
|
1001
|
+
case "whitespace":
|
|
1002
|
+
return t("problem.whitespace", "“{property}” has surrounding whitespace", {
|
|
1003
|
+
property: p.property
|
|
1004
|
+
});
|
|
1005
|
+
case "bad-option":
|
|
1006
|
+
return t("problem.bad-option", "“{property}” does not accept {values}", {
|
|
1007
|
+
property: p.property,
|
|
1008
|
+
values: p.values.join(", ")
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
};
|
|
1012
|
+
const run = async () => {
|
|
1013
|
+
setBusy(true);
|
|
1014
|
+
setError(false);
|
|
1015
|
+
setResult(null);
|
|
1016
|
+
try {
|
|
1017
|
+
const { data } = await get(`/${PLUGIN_ID}/audit`);
|
|
1018
|
+
setResult(data);
|
|
1019
|
+
} catch {
|
|
1020
|
+
setError(true);
|
|
1021
|
+
} finally {
|
|
1022
|
+
setBusy(false);
|
|
1023
|
+
}
|
|
1024
|
+
};
|
|
1025
|
+
const entryLink = (uid, entry) => `/content-manager/collection-types/${uid}/${entry.documentId}` + (entry.locale ? `?plugins[i18n][locale]=${entry.locale}` : "");
|
|
1026
|
+
const totalInvalid = result?.targets.reduce((n, r) => n + r.invalid.length, 0) ?? 0;
|
|
1027
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
1028
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
1029
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
1030
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", children: t("audit.title", "Mapping audit") }),
|
|
1031
|
+
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
1032
|
+
"audit.subtitle",
|
|
1033
|
+
"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."
|
|
1034
|
+
) })
|
|
1035
|
+
] }),
|
|
1036
|
+
/* @__PURE__ */ jsx(Flex, { gap: 2, children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: run, loading: busy, disabled: !configured, children: t("audit.run", "Run the audit") }) }),
|
|
1037
|
+
error ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: t("audit.error", "Audit failed — HubSpot unreachable?") }) : null,
|
|
1038
|
+
result && !result.targets.length ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
1039
|
+
"audit.no-targets",
|
|
1040
|
+
"No content type to audit — declare them under `validate` in the plugin config."
|
|
1041
|
+
) }) : null,
|
|
1042
|
+
result && result.targets.length ? /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
1043
|
+
totalInvalid === 0 && result.targets.every((r) => !r.error) ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "success600", children: t("audit.clean", "Nothing to report — every mapping is valid.") }) : null,
|
|
1044
|
+
result.targets.map((report) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
1045
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", paddingBottom: 2, children: [
|
|
1046
|
+
/* @__PURE__ */ jsx(Typography, { variant: "delta", children: report.uid }),
|
|
1047
|
+
/* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t("audit.summary", "{entries} entries · {mappings} mappings", {
|
|
1048
|
+
entries: report.entries,
|
|
1049
|
+
mappings: report.mappings
|
|
1050
|
+
}) })
|
|
1051
|
+
] }),
|
|
1052
|
+
report.error ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", children: t("audit.target-error", "Could not scan: {error}", { error: report.error }) }) : null,
|
|
1053
|
+
/* @__PURE__ */ jsx(Flex, { direction: "column", alignItems: "stretch", gap: 2, children: report.invalid.map((entry) => /* @__PURE__ */ jsxs(
|
|
1054
|
+
Box,
|
|
1055
|
+
{
|
|
1056
|
+
padding: 3,
|
|
1057
|
+
background: "neutral100",
|
|
1058
|
+
hasRadius: true,
|
|
1059
|
+
children: [
|
|
1060
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
1061
|
+
/* @__PURE__ */ jsx(Link$1, { tag: Link, to: entryLink(report.uid, entry), children: entry.label }),
|
|
1062
|
+
entry.locale ? /* @__PURE__ */ jsx(Badge, { children: entry.locale }) : null
|
|
1063
|
+
] }),
|
|
1064
|
+
/* @__PURE__ */ jsx(Box, { paddingTop: 1, children: entry.problems.map((p, i) => /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "danger600", tag: "p", children: problemText(p) }, i)) })
|
|
1065
|
+
]
|
|
1066
|
+
},
|
|
1067
|
+
`${entry.documentId}-${entry.locale ?? ""}`
|
|
1068
|
+
)) })
|
|
1069
|
+
] }, report.uid))
|
|
1070
|
+
] }) : null
|
|
1071
|
+
] });
|
|
1072
|
+
};
|
|
1073
|
+
const FailuresSection = ({ configured }) => {
|
|
1074
|
+
const { formatMessage } = useIntl();
|
|
1075
|
+
const { get, post } = useFetchClient();
|
|
1076
|
+
const [total, setTotal] = React.useState(null);
|
|
1077
|
+
const [busy, setBusy] = React.useState(false);
|
|
1078
|
+
const [feedback, setFeedback] = React.useState(
|
|
1079
|
+
null
|
|
1080
|
+
);
|
|
1081
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
1082
|
+
const load = React.useCallback(async () => {
|
|
1083
|
+
try {
|
|
1084
|
+
const { data } = await get(`/${PLUGIN_ID}/failures`);
|
|
1085
|
+
setTotal(data.total);
|
|
1086
|
+
} catch {
|
|
1087
|
+
setTotal(null);
|
|
1088
|
+
}
|
|
1089
|
+
}, [get]);
|
|
1090
|
+
React.useEffect(() => {
|
|
1091
|
+
load();
|
|
1092
|
+
}, [load]);
|
|
1093
|
+
const retry = async () => {
|
|
1094
|
+
setBusy(true);
|
|
1095
|
+
setFeedback(null);
|
|
1096
|
+
try {
|
|
1097
|
+
const { data } = await post(
|
|
1098
|
+
`/${PLUGIN_ID}/failures/retry`
|
|
1099
|
+
);
|
|
1100
|
+
setFeedback({
|
|
1101
|
+
tone: data.failed ? "danger" : "success",
|
|
1102
|
+
text: t("failures.retried", "{succeeded} replayed, {failed} still failing.", {
|
|
1103
|
+
succeeded: data.succeeded,
|
|
1104
|
+
failed: data.failed
|
|
1105
|
+
})
|
|
1106
|
+
});
|
|
1107
|
+
await load();
|
|
1108
|
+
} catch {
|
|
1109
|
+
setFeedback({ tone: "danger", text: t("failures.error", "Replay failed.") });
|
|
1110
|
+
} finally {
|
|
1111
|
+
setBusy(false);
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
return /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
1115
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
1116
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
1117
|
+
/* @__PURE__ */ jsx(Typography, { variant: "beta", children: t("failures.title", "Failed submissions") }),
|
|
1118
|
+
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
1119
|
+
"failures.subtitle",
|
|
1120
|
+
"Submissions HubSpot couldn't take after the automatic retries. They can be inspected under Content Manager → HubSpot failed submissions."
|
|
1121
|
+
) })
|
|
1122
|
+
] }),
|
|
1123
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
1124
|
+
/* @__PURE__ */ jsx(Badge, { active: Boolean(total), children: t("failures.count", "{count} queued", { count: total ?? 0 }) }),
|
|
1125
|
+
/* @__PURE__ */ jsx(
|
|
1126
|
+
Button,
|
|
1127
|
+
{
|
|
1128
|
+
variant: "secondary",
|
|
1129
|
+
onClick: retry,
|
|
1130
|
+
loading: busy,
|
|
1131
|
+
disabled: !configured || !total,
|
|
1132
|
+
children: t("failures.retry", "Replay now")
|
|
1133
|
+
}
|
|
1134
|
+
)
|
|
1135
|
+
] }),
|
|
1136
|
+
feedback ? /* @__PURE__ */ jsx(
|
|
1137
|
+
Typography,
|
|
1138
|
+
{
|
|
1139
|
+
variant: "pi",
|
|
1140
|
+
textColor: feedback.tone === "success" ? "success600" : "danger600",
|
|
1141
|
+
children: feedback.text
|
|
1142
|
+
}
|
|
1143
|
+
) : null
|
|
1144
|
+
] });
|
|
1145
|
+
};
|
|
1146
|
+
const HubspotSettings = () => {
|
|
1147
|
+
const { formatMessage } = useIntl();
|
|
1148
|
+
const { get, put, del } = useFetchClient();
|
|
1149
|
+
const [settings, setSettings] = React.useState(null);
|
|
1150
|
+
const [apiKey, setApiKey] = React.useState("");
|
|
1151
|
+
const [busy, setBusy] = React.useState(false);
|
|
1152
|
+
const [feedback, setFeedback] = React.useState(
|
|
1153
|
+
null
|
|
1154
|
+
);
|
|
1155
|
+
const t = (id, defaultMessage, values) => formatMessage({ id: getTranslation(id), defaultMessage }, values);
|
|
1156
|
+
const load = React.useCallback(async () => {
|
|
1157
|
+
const { data } = await get(`/${PLUGIN_ID}/settings`);
|
|
1158
|
+
setSettings(data);
|
|
1159
|
+
}, [get]);
|
|
1160
|
+
React.useEffect(() => {
|
|
1161
|
+
load().catch(
|
|
1162
|
+
() => setFeedback({ tone: "danger", text: t("settings.load-error", "Could not load settings.") })
|
|
1163
|
+
);
|
|
1164
|
+
}, [load]);
|
|
1165
|
+
const save = async () => {
|
|
1166
|
+
setBusy(true);
|
|
1167
|
+
setFeedback(null);
|
|
1168
|
+
try {
|
|
1169
|
+
const { data } = await put(`/${PLUGIN_ID}/settings`, { apiKey });
|
|
1170
|
+
setSettings(data);
|
|
1171
|
+
setApiKey("");
|
|
1172
|
+
setFeedback({ tone: "success", text: t("settings.saved", "Key saved.") });
|
|
1173
|
+
} catch {
|
|
1174
|
+
setFeedback({ tone: "danger", text: t("settings.save-error", "Could not save the key.") });
|
|
1175
|
+
} finally {
|
|
1176
|
+
setBusy(false);
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
const remove = async () => {
|
|
1180
|
+
setBusy(true);
|
|
1181
|
+
setFeedback(null);
|
|
1182
|
+
try {
|
|
1183
|
+
const { data } = await del(`/${PLUGIN_ID}/settings`);
|
|
1184
|
+
setSettings(data);
|
|
1185
|
+
setApiKey("");
|
|
1186
|
+
setFeedback({ tone: "success", text: t("settings.removed", "Key removed.") });
|
|
1187
|
+
} catch {
|
|
1188
|
+
setFeedback({ tone: "danger", text: t("settings.remove-error", "Could not remove the key.") });
|
|
1189
|
+
} finally {
|
|
1190
|
+
setBusy(false);
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
const test = async () => {
|
|
1194
|
+
setBusy(true);
|
|
1195
|
+
setFeedback(null);
|
|
1196
|
+
try {
|
|
1197
|
+
const { data } = await get(
|
|
1198
|
+
`/${PLUGIN_ID}/properties?refresh=1`
|
|
1199
|
+
);
|
|
1200
|
+
setFeedback(
|
|
1201
|
+
data.configured ? {
|
|
1202
|
+
tone: "success",
|
|
1203
|
+
text: t("settings.test-ok", "Connection established — {count} readable properties.", {
|
|
1204
|
+
count: data.properties.length
|
|
1205
|
+
})
|
|
1206
|
+
} : { tone: "danger", text: t("settings.test-no-key", "No key configured.") }
|
|
1207
|
+
);
|
|
1208
|
+
} catch {
|
|
1209
|
+
setFeedback({
|
|
1210
|
+
tone: "danger",
|
|
1211
|
+
text: t("settings.test-error", "HubSpot unreachable — invalid or revoked key?")
|
|
1212
|
+
});
|
|
1213
|
+
} finally {
|
|
1214
|
+
setBusy(false);
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
if (!settings) {
|
|
1218
|
+
return /* @__PURE__ */ jsx(Box, { padding: 8, children: /* @__PURE__ */ jsx(Loader, { small: true, children: t("settings.loading", "Loading…") }) });
|
|
1219
|
+
}
|
|
1220
|
+
const sourceLabel = {
|
|
1221
|
+
settings: t("settings.source.settings", "set here"),
|
|
1222
|
+
config: t("settings.source.config", "config/plugins.ts"),
|
|
1223
|
+
env: t("settings.source.env", "environment variable")
|
|
1224
|
+
};
|
|
1225
|
+
return /* @__PURE__ */ jsx(Box, { padding: 8, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "stretch", gap: 6, children: [
|
|
1226
|
+
/* @__PURE__ */ jsxs(Flex, { direction: "column", alignItems: "flex-start", gap: 2, children: [
|
|
1227
|
+
/* @__PURE__ */ jsx(Typography, { variant: "alpha", children: "HubSpot" }),
|
|
1228
|
+
/* @__PURE__ */ jsx(Typography, { variant: "epsilon", textColor: "neutral600", children: t(
|
|
1229
|
+
"settings.subtitle",
|
|
1230
|
+
"The private app token used to read the portal's properties and validate form mappings."
|
|
1231
|
+
) })
|
|
1232
|
+
] }),
|
|
1233
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, alignItems: "center", children: [
|
|
1234
|
+
/* @__PURE__ */ jsx(Badge, { active: settings.configured, children: settings.configured ? t("settings.configured", "Configured {hint}", { hint: settings.hint }) : t("settings.not-configured", "Not configured") }),
|
|
1235
|
+
settings.keySource ? /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t("settings.source", "source: {source}", { source: sourceLabel[settings.keySource] }) }) : null
|
|
1236
|
+
] }),
|
|
1237
|
+
/* @__PURE__ */ jsx(Box, { maxWidth: "32rem", children: /* @__PURE__ */ jsxs(
|
|
1238
|
+
Field.Root,
|
|
1239
|
+
{
|
|
1240
|
+
name: "apiKey",
|
|
1241
|
+
hint: t(
|
|
1242
|
+
"settings.key.hint",
|
|
1243
|
+
"A key entered here overrides the ones from config/plugins.ts and HUBSPOT_API_KEY."
|
|
1244
|
+
),
|
|
1245
|
+
children: [
|
|
1246
|
+
/* @__PURE__ */ jsx(Field.Label, { children: t("settings.key.label", "Private app token") }),
|
|
1247
|
+
/* @__PURE__ */ jsx(
|
|
1248
|
+
Field.Input,
|
|
1249
|
+
{
|
|
1250
|
+
type: "password",
|
|
1251
|
+
value: apiKey,
|
|
1252
|
+
autoComplete: "off",
|
|
1253
|
+
placeholder: settings.configured ? t("settings.key.placeholder.set", "•••••••• (leave empty to keep)") : t("settings.key.placeholder.empty", "pat-eu1-…"),
|
|
1254
|
+
onChange: (e) => setApiKey(e.target.value)
|
|
1255
|
+
}
|
|
1256
|
+
),
|
|
1257
|
+
/* @__PURE__ */ jsx(Field.Hint, {})
|
|
1258
|
+
]
|
|
1259
|
+
}
|
|
1260
|
+
) }),
|
|
1261
|
+
/* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
|
|
1262
|
+
/* @__PURE__ */ jsx(Button, { onClick: save, loading: busy, disabled: !apiKey.trim(), children: t("settings.save", "Save") }),
|
|
1263
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: test, loading: busy, disabled: !settings.configured, children: t("settings.test", "Test connection") }),
|
|
1264
|
+
/* @__PURE__ */ jsx(
|
|
1265
|
+
Button,
|
|
1266
|
+
{
|
|
1267
|
+
variant: "danger-light",
|
|
1268
|
+
onClick: remove,
|
|
1269
|
+
loading: busy,
|
|
1270
|
+
disabled: settings.keySource !== "settings",
|
|
1271
|
+
children: t("settings.remove", "Remove")
|
|
1272
|
+
}
|
|
1273
|
+
)
|
|
1274
|
+
] }),
|
|
1275
|
+
feedback ? /* @__PURE__ */ jsx(
|
|
1276
|
+
Typography,
|
|
1277
|
+
{
|
|
1278
|
+
variant: "pi",
|
|
1279
|
+
textColor: feedback.tone === "success" ? "success600" : "danger600",
|
|
1280
|
+
children: feedback.text
|
|
1281
|
+
}
|
|
1282
|
+
) : null,
|
|
1283
|
+
/* @__PURE__ */ jsx(Box, { paddingTop: 4, children: /* @__PURE__ */ jsx(Typography, { variant: "pi", textColor: "neutral600", children: t(
|
|
1284
|
+
"settings.scopes",
|
|
1285
|
+
"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."
|
|
1286
|
+
) }) }),
|
|
1287
|
+
/* @__PURE__ */ jsx(AuditSection, { configured: settings.configured }),
|
|
1288
|
+
/* @__PURE__ */ jsx(FailuresSection, { configured: settings.configured })
|
|
1289
|
+
] }) });
|
|
1290
|
+
};
|
|
1291
|
+
export {
|
|
1292
|
+
HubspotSettings as default
|
|
1293
|
+
};
|