@mattisvensson/strapi-plugin-webatlas 0.11.5 → 0.11.6

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 CHANGED
@@ -34,6 +34,7 @@ This plugin is still in the early stages of development. Many features are plann
34
34
  - **🧭 Multiple Navigations** Support for creating and managing multiple navigation structures. Whether it's a main menu, footer links, or a custom mobile drawer — organize your content into any number of navigations with drag-and-drop sorting, nested items, and visibility toggles.
35
35
  - **🧩 Composable Component Integration** Use plugin-generated slugs and navigations directly in your frontend. Fetch routes and navigation data by slug and with a consistent API response, optimized for dynamic rendering.
36
36
  - **🧠 Conflict Detection & Validation** Webatlas prevents slug collisions and helps avoid route conflicts by validating changes in real time. Get clear error messages and automatic suggestions when something doesn’t align.
37
+ - **🔗 RoutePicker Custom Field** Use the RoutePicker custom field to select routes within your content types, ensuring consistent linking and navigation throughout your application.
37
38
 
38
39
  ## ⏳ Installation
39
40
 
@@ -104,6 +105,10 @@ After selecting the source field for path generation in settings, you'll see the
104
105
 
105
106
  **UID Path (UID Path)**: A permanent identifier path that never changes, used as a backup URL.
106
107
 
108
+ ### RoutePicker Custom Field
109
+
110
+ The RoutePicker custom field allows you to select a route from the existing routes in your Strapi application. This ensures that links between content types are consistent and automatically updated when the route changes. You can use it for example in a "Button" component to link to a different page.
111
+
107
112
  ### API endpoints
108
113
 
109
114
  Webatlas provides two API endpoints. One to fetch routes and one to fetch navigations.
@@ -0,0 +1,101 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { forwardRef, useState, useEffect } from "react";
3
+ import { Field, Combobox, ComboboxOption, Box } from "@strapi/design-system";
4
+ import { ExternalLink, Link } from "@strapi/icons";
5
+ import { u as useApi } from "./index-OkabmPb4.mjs";
6
+ import "@strapi/strapi/admin";
7
+ const Input = forwardRef((props, ref) => {
8
+ const { attribute, disabled, placeholder, label, name, onChange, required, value, hint } = props;
9
+ const { getAllRoutes } = useApi();
10
+ const [routes, setRoutes] = useState([]);
11
+ const [isLoading, setIsLoading] = useState(true);
12
+ const [displayValue, setDisplayValue] = useState("");
13
+ const isDisabled = disabled || isLoading;
14
+ const handleChange = (newValue) => {
15
+ onChange({
16
+ target: { name, type: attribute.type, value: encodeURI(newValue) }
17
+ });
18
+ };
19
+ const handleOptionCreate = (inputValue) => {
20
+ const linkValue = typeof inputValue === "string" ? inputValue : inputValue?.target?.value || String(inputValue || "");
21
+ if (linkValue) {
22
+ handleChange(linkValue);
23
+ setDisplayValue(encodeURI(linkValue));
24
+ }
25
+ };
26
+ const getStartIcon = () => {
27
+ if (!value) return null;
28
+ const matchedRoute = routes.find((route) => route.documentId === value);
29
+ if (matchedRoute) {
30
+ return /* @__PURE__ */ jsx(Link, { fill: "neutral500" });
31
+ }
32
+ return /* @__PURE__ */ jsx(ExternalLink, { fill: "neutral500" });
33
+ };
34
+ useEffect(() => {
35
+ const fetchRoutes = async () => {
36
+ setIsLoading(true);
37
+ const fetchedRoutes = await getAllRoutes();
38
+ setRoutes(fetchedRoutes);
39
+ setIsLoading(false);
40
+ if (value) {
41
+ const matchedRoute = fetchedRoutes.find((route) => route.documentId === value);
42
+ if (matchedRoute) {
43
+ setDisplayValue(`${matchedRoute.title} (${matchedRoute.path})`);
44
+ } else {
45
+ setDisplayValue(value);
46
+ }
47
+ } else {
48
+ setDisplayValue("");
49
+ }
50
+ };
51
+ fetchRoutes();
52
+ }, [value]);
53
+ return /* @__PURE__ */ jsxs(Field.Root, { id: name, required, hint, disabled: isDisabled, children: [
54
+ /* @__PURE__ */ jsx(Field.Label, { children: label }),
55
+ /* @__PURE__ */ jsx(
56
+ Combobox,
57
+ {
58
+ ref,
59
+ placeholder,
60
+ "aria-label": label,
61
+ "aria-disabled": isDisabled,
62
+ value: value || "",
63
+ textValue: displayValue || "",
64
+ creatable: true,
65
+ onCreateOption: handleOptionCreate,
66
+ createMessage: (inputValue) => `Use external link: ${encodeURI(inputValue)}`,
67
+ creatableStartIcon: /* @__PURE__ */ jsx(ExternalLink, { fill: "neutral500" }),
68
+ startIcon: getStartIcon(),
69
+ onChange: (routeId) => {
70
+ if (!routeId) {
71
+ setDisplayValue("");
72
+ handleChange("");
73
+ return;
74
+ }
75
+ const selectedRoute = routes.find((r) => r.documentId === routeId);
76
+ if (selectedRoute) {
77
+ setDisplayValue(`${selectedRoute.title} (${selectedRoute.path})`);
78
+ handleChange(routeId);
79
+ }
80
+ },
81
+ onInputChange: (inputValue) => {
82
+ const textValue = typeof inputValue === "string" ? inputValue : inputValue?.target?.value || "";
83
+ setDisplayValue(textValue);
84
+ },
85
+ children: routes.map((route) => /* @__PURE__ */ jsxs(ComboboxOption, { value: route.documentId, children: [
86
+ route.title,
87
+ " (",
88
+ route.path,
89
+ ")"
90
+ ] }, route.documentId))
91
+ }
92
+ ),
93
+ /* @__PURE__ */ jsxs(Box, { children: [
94
+ /* @__PURE__ */ jsx(Field.Hint, {}),
95
+ /* @__PURE__ */ jsx(Field.Error, {})
96
+ ] })
97
+ ] });
98
+ });
99
+ export {
100
+ Input as default
101
+ };
@@ -0,0 +1,101 @@
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 designSystem = require("@strapi/design-system");
6
+ const icons = require("@strapi/icons");
7
+ const index = require("./index-ik3u6iCE.js");
8
+ require("@strapi/strapi/admin");
9
+ const Input = React.forwardRef((props, ref) => {
10
+ const { attribute, disabled, placeholder, label, name, onChange, required, value, hint } = props;
11
+ const { getAllRoutes } = index.useApi();
12
+ const [routes, setRoutes] = React.useState([]);
13
+ const [isLoading, setIsLoading] = React.useState(true);
14
+ const [displayValue, setDisplayValue] = React.useState("");
15
+ const isDisabled = disabled || isLoading;
16
+ const handleChange = (newValue) => {
17
+ onChange({
18
+ target: { name, type: attribute.type, value: encodeURI(newValue) }
19
+ });
20
+ };
21
+ const handleOptionCreate = (inputValue) => {
22
+ const linkValue = typeof inputValue === "string" ? inputValue : inputValue?.target?.value || String(inputValue || "");
23
+ if (linkValue) {
24
+ handleChange(linkValue);
25
+ setDisplayValue(encodeURI(linkValue));
26
+ }
27
+ };
28
+ const getStartIcon = () => {
29
+ if (!value) return null;
30
+ const matchedRoute = routes.find((route) => route.documentId === value);
31
+ if (matchedRoute) {
32
+ return /* @__PURE__ */ jsxRuntime.jsx(icons.Link, { fill: "neutral500" });
33
+ }
34
+ return /* @__PURE__ */ jsxRuntime.jsx(icons.ExternalLink, { fill: "neutral500" });
35
+ };
36
+ React.useEffect(() => {
37
+ const fetchRoutes = async () => {
38
+ setIsLoading(true);
39
+ const fetchedRoutes = await getAllRoutes();
40
+ setRoutes(fetchedRoutes);
41
+ setIsLoading(false);
42
+ if (value) {
43
+ const matchedRoute = fetchedRoutes.find((route) => route.documentId === value);
44
+ if (matchedRoute) {
45
+ setDisplayValue(`${matchedRoute.title} (${matchedRoute.path})`);
46
+ } else {
47
+ setDisplayValue(value);
48
+ }
49
+ } else {
50
+ setDisplayValue("");
51
+ }
52
+ };
53
+ fetchRoutes();
54
+ }, [value]);
55
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { id: name, required, hint, disabled: isDisabled, children: [
56
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: label }),
57
+ /* @__PURE__ */ jsxRuntime.jsx(
58
+ designSystem.Combobox,
59
+ {
60
+ ref,
61
+ placeholder,
62
+ "aria-label": label,
63
+ "aria-disabled": isDisabled,
64
+ value: value || "",
65
+ textValue: displayValue || "",
66
+ creatable: true,
67
+ onCreateOption: handleOptionCreate,
68
+ createMessage: (inputValue) => `Use external link: ${encodeURI(inputValue)}`,
69
+ creatableStartIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ExternalLink, { fill: "neutral500" }),
70
+ startIcon: getStartIcon(),
71
+ onChange: (routeId) => {
72
+ if (!routeId) {
73
+ setDisplayValue("");
74
+ handleChange("");
75
+ return;
76
+ }
77
+ const selectedRoute = routes.find((r) => r.documentId === routeId);
78
+ if (selectedRoute) {
79
+ setDisplayValue(`${selectedRoute.title} (${selectedRoute.path})`);
80
+ handleChange(routeId);
81
+ }
82
+ },
83
+ onInputChange: (inputValue) => {
84
+ const textValue = typeof inputValue === "string" ? inputValue : inputValue?.target?.value || "";
85
+ setDisplayValue(textValue);
86
+ },
87
+ children: routes.map((route) => /* @__PURE__ */ jsxRuntime.jsxs(designSystem.ComboboxOption, { value: route.documentId, children: [
88
+ route.title,
89
+ " (",
90
+ route.path,
91
+ ")"
92
+ ] }, route.documentId))
93
+ }
94
+ ),
95
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [
96
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}),
97
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
98
+ ] })
99
+ ] });
100
+ });
101
+ exports.default = Input;
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import { Button, Flex, Typography, Box } from "@strapi/design-system";
3
3
  import { Page, Layouts } from "@strapi/strapi/admin";
4
- import { f as PLUGIN_NAME, g as getTranslation } from "./index-Dx-EVn-t.mjs";
4
+ import { f as PLUGIN_NAME, g as getTranslation } from "./index-OkabmPb4.mjs";
5
5
  import { useIntl } from "react-intl";
6
6
  import { Check } from "@strapi/icons";
7
7
  function PageWrapper({
@@ -2,7 +2,7 @@
2
2
  const jsxRuntime = require("react/jsx-runtime");
3
3
  const designSystem = require("@strapi/design-system");
4
4
  const admin = require("@strapi/strapi/admin");
5
- const index = require("./index-Bm8lkiNL.js");
5
+ const index = require("./index-ik3u6iCE.js");
6
6
  const reactIntl = require("react-intl");
7
7
  const icons = require("@strapi/icons");
8
8
  function PageWrapper({
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { useState, useEffect, useMemo } from "react";
3
- import { g as getTranslation, u as useApi, d as debounce, p as pluginPermissions } from "./index-Dx-EVn-t.mjs";
3
+ import { g as getTranslation, u as useApi, d as debounce, p as pluginPermissions } from "./index-OkabmPb4.mjs";
4
4
  import { Page, Layouts, useNotification } from "@strapi/strapi/admin";
5
5
  import { Grid, Box, Field, Thead, Tr, Th, Typography, VisuallyHidden, Td, Flex, LinkButton, Table, Tbody, EmptyStateLayout } from "@strapi/design-system";
6
6
  import "@strapi/icons/symbols";
@@ -4,11 +4,11 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const designSystem = require("@strapi/design-system");
6
6
  const admin = require("@strapi/strapi/admin");
7
- const index = require("./index-Bm8lkiNL.js");
7
+ const index = require("./index-ik3u6iCE.js");
8
8
  const reactIntl = require("react-intl");
9
9
  require("@strapi/icons/symbols");
10
10
  const FullLoader = require("./FullLoader-Da2n70bJ.js");
11
- const SettingTitle = require("./SettingTitle-DGSkTF7e.js");
11
+ const SettingTitle = require("./SettingTitle-DcQMSkno.js");
12
12
  function reducer(newConfig, action) {
13
13
  switch (action.type) {
14
14
  case "SET_MAX_DEPTH":
@@ -7,7 +7,7 @@ const designSystem = require("@strapi/design-system");
7
7
  const React = require("react");
8
8
  const ReactDOM = require("react-dom");
9
9
  const reactIntl = require("react-intl");
10
- const index = require("./index-Bm8lkiNL.js");
10
+ const index = require("./index-ik3u6iCE.js");
11
11
  const admin = require("@strapi/strapi/admin");
12
12
  const FullLoader = require("./FullLoader-Da2n70bJ.js");
13
13
  const symbols = require("@strapi/icons/symbols");
@@ -2,11 +2,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useReducer, useState, useRef, useEffect } from "react";
3
3
  import { Field } from "@strapi/design-system";
4
4
  import { useNotification, Page } from "@strapi/strapi/admin";
5
- import { c as usePluginConfig, g as getTranslation, p as pluginPermissions } from "./index-Dx-EVn-t.mjs";
5
+ import { c as usePluginConfig, g as getTranslation, p as pluginPermissions } from "./index-OkabmPb4.mjs";
6
6
  import { useIntl } from "react-intl";
7
7
  import "@strapi/icons/symbols";
8
8
  import { F as FullLoader } from "./FullLoader-Btjb2W2p.mjs";
9
- import { P as PageWrapper, C as ContentBox, S as SettingTitle } from "./SettingTitle-UPbQCuTC.mjs";
9
+ import { P as PageWrapper, C as ContentBox, S as SettingTitle } from "./SettingTitle-Bu_8jLRE.mjs";
10
10
  function reducer(newConfig, action) {
11
11
  switch (action.type) {
12
12
  case "SET_MAX_DEPTH":
@@ -5,7 +5,7 @@ import { Box, Typography, Dialog, Button, Modal, Flex, SingleSelect, SingleSelec
5
5
  import { useState, useEffect, createContext, useRef, useContext, useMemo, useReducer, useCallback, forwardRef } from "react";
6
6
  import { createPortal } from "react-dom";
7
7
  import { useIntl } from "react-intl";
8
- import { u as useApi, g as getTranslation, P as PLUGIN_ID, d as debounce, a as duplicateCheck, T as Tooltip, b as PathInfo, c as usePluginConfig, p as pluginPermissions } from "./index-Dx-EVn-t.mjs";
8
+ import { u as useApi, g as getTranslation, P as PLUGIN_ID, d as debounce, a as duplicateCheck, T as Tooltip, b as PathInfo, c as usePluginConfig, p as pluginPermissions } from "./index-OkabmPb4.mjs";
9
9
  import { useNotification, useFetchClient, Page, Layouts } from "@strapi/strapi/admin";
10
10
  import { C as Center, F as FullLoader } from "./FullLoader-Btjb2W2p.mjs";
11
11
  import { EmptyDocuments } from "@strapi/icons/symbols";
@@ -4,11 +4,11 @@ const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const designSystem = require("@strapi/design-system");
6
6
  const admin = require("@strapi/strapi/admin");
7
- const index = require("./index-Bm8lkiNL.js");
7
+ const index = require("./index-ik3u6iCE.js");
8
8
  const reactIntl = require("react-intl");
9
9
  require("@strapi/icons/symbols");
10
10
  const FullLoader = require("./FullLoader-Da2n70bJ.js");
11
- const SettingTitle = require("./SettingTitle-DGSkTF7e.js");
11
+ const SettingTitle = require("./SettingTitle-DcQMSkno.js");
12
12
  const icons = require("@strapi/icons");
13
13
  function ContentTypeAccordion({
14
14
  contentType,
@@ -2,11 +2,11 @@ import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { useReducer, useState, useRef, useEffect } from "react";
3
3
  import { Box, Accordion, Field, SingleSelect, SingleSelectOption, Typography, Link } from "@strapi/design-system";
4
4
  import { useNotification, Page } from "@strapi/strapi/admin";
5
- import { g as getTranslation, c as usePluginConfig, e as useAllContentTypes, p as pluginPermissions, f as PLUGIN_NAME, h as PLUGIN_VERSION } from "./index-Dx-EVn-t.mjs";
5
+ import { g as getTranslation, c as usePluginConfig, e as useAllContentTypes, p as pluginPermissions, f as PLUGIN_NAME, h as PLUGIN_VERSION } from "./index-OkabmPb4.mjs";
6
6
  import { useIntl } from "react-intl";
7
7
  import "@strapi/icons/symbols";
8
8
  import { F as FullLoader } from "./FullLoader-Btjb2W2p.mjs";
9
- import { P as PageWrapper, C as ContentBox, S as SettingTitle } from "./SettingTitle-UPbQCuTC.mjs";
9
+ import { P as PageWrapper, C as ContentBox, S as SettingTitle } from "./SettingTitle-Bu_8jLRE.mjs";
10
10
  import { ExternalLink } from "@strapi/icons";
11
11
  function ContentTypeAccordion({
12
12
  contentType,
@@ -52,7 +52,7 @@ function transformToUrl(input, replaceSlash = true) {
52
52
  input = input.replace(/-+/g, "-");
53
53
  return input;
54
54
  }
55
- const version = "0.11.4";
55
+ const version = "0.11.5";
56
56
  const strapi$1 = { "name": "webatlas", "displayName": "Webatlas" };
57
57
  const pluginPkg = {
58
58
  version,
@@ -4151,7 +4151,7 @@ const index = {
4151
4151
  id: `${PLUGIN_ID}.link.paths`,
4152
4152
  defaultMessage: "Paths"
4153
4153
  },
4154
- Component: () => import("./index-b3yS9Dm7.mjs"),
4154
+ Component: () => import("./index-Bp-XFH1V.mjs"),
4155
4155
  permissions: [pluginPermissions["page.routes"][0]]
4156
4156
  });
4157
4157
  app.addMenuLink({
@@ -4161,7 +4161,7 @@ const index = {
4161
4161
  id: `${PLUGIN_ID}.link.navigation`,
4162
4162
  defaultMessage: "Navigation"
4163
4163
  },
4164
- Component: () => import("./index-DLoZpHxU.mjs"),
4164
+ Component: () => import("./index-DjLi4gIu.mjs"),
4165
4165
  permissions: [pluginPermissions["page.navigation"][0]]
4166
4166
  });
4167
4167
  app.addSettingsLink(
@@ -4179,7 +4179,7 @@ const index = {
4179
4179
  },
4180
4180
  id: `${PLUGIN_ID}-general`,
4181
4181
  to: `${PLUGIN_ID}/general`,
4182
- Component: () => import("./index-CrgTYzgl.mjs"),
4182
+ Component: () => import("./index-DqA1gNsu.mjs"),
4183
4183
  permissions: [pluginPermissions["settings.general"][0]]
4184
4184
  }
4185
4185
  );
@@ -4190,9 +4190,51 @@ const index = {
4190
4190
  },
4191
4191
  id: `${PLUGIN_ID}-navigation`,
4192
4192
  to: `${PLUGIN_ID}/navigation`,
4193
- Component: () => import("./index-D4B4s4XO.mjs"),
4193
+ Component: () => import("./index-DLMGEpc0.mjs"),
4194
4194
  permissions: [pluginPermissions["settings.navigation"][0]]
4195
4195
  });
4196
+ app.customFields.register({
4197
+ name: "route-picker",
4198
+ pluginId: PLUGIN_ID,
4199
+ type: "string",
4200
+ intlLabel: {
4201
+ id: `${PLUGIN_ID}.route-picker.label`,
4202
+ defaultMessage: "Route Picker"
4203
+ },
4204
+ intlDescription: {
4205
+ id: `${PLUGIN_ID}.route-picker.description`,
4206
+ defaultMessage: "Select a route"
4207
+ },
4208
+ components: {
4209
+ Input: async () => import("./RoutePicker-C6omysLv.mjs").then((module) => ({
4210
+ default: module.default
4211
+ }))
4212
+ },
4213
+ options: {
4214
+ advanced: [
4215
+ {
4216
+ sectionTitle: {
4217
+ id: "global.settings",
4218
+ defaultMessage: "Settings"
4219
+ },
4220
+ items: [
4221
+ {
4222
+ name: "required",
4223
+ type: "checkbox",
4224
+ intlLabel: {
4225
+ id: "content-type-builder.form.attribute.item.requiredField",
4226
+ defaultMessage: "Required field"
4227
+ },
4228
+ description: {
4229
+ id: "content-type-builder.form.attribute.item.requiredField.description",
4230
+ defaultMessage: "You won't be able to create an entry if this field is empty"
4231
+ }
4232
+ }
4233
+ ]
4234
+ }
4235
+ ]
4236
+ }
4237
+ });
4196
4238
  app.registerPlugin({
4197
4239
  id: PLUGIN_ID,
4198
4240
  initializer: Initializer,
@@ -2,7 +2,7 @@
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 index = require("./index-Bm8lkiNL.js");
5
+ const index = require("./index-ik3u6iCE.js");
6
6
  const admin = require("@strapi/strapi/admin");
7
7
  const designSystem = require("@strapi/design-system");
8
8
  require("@strapi/icons/symbols");
@@ -70,7 +70,7 @@ function transformToUrl(input, replaceSlash = true) {
70
70
  input = input.replace(/-+/g, "-");
71
71
  return input;
72
72
  }
73
- const version = "0.11.4";
73
+ const version = "0.11.5";
74
74
  const strapi$1 = { "name": "webatlas", "displayName": "Webatlas" };
75
75
  const pluginPkg = {
76
76
  version,
@@ -4169,7 +4169,7 @@ const index = {
4169
4169
  id: `${PLUGIN_ID}.link.paths`,
4170
4170
  defaultMessage: "Paths"
4171
4171
  },
4172
- Component: () => Promise.resolve().then(() => require("./index-BztvKcfc.js")),
4172
+ Component: () => Promise.resolve().then(() => require("./index-e8zVLBgW.js")),
4173
4173
  permissions: [pluginPermissions["page.routes"][0]]
4174
4174
  });
4175
4175
  app.addMenuLink({
@@ -4179,7 +4179,7 @@ const index = {
4179
4179
  id: `${PLUGIN_ID}.link.navigation`,
4180
4180
  defaultMessage: "Navigation"
4181
4181
  },
4182
- Component: () => Promise.resolve().then(() => require("./index-BiXgA5Ru.js")),
4182
+ Component: () => Promise.resolve().then(() => require("./index-CoLBgxOP.js")),
4183
4183
  permissions: [pluginPermissions["page.navigation"][0]]
4184
4184
  });
4185
4185
  app.addSettingsLink(
@@ -4197,7 +4197,7 @@ const index = {
4197
4197
  },
4198
4198
  id: `${PLUGIN_ID}-general`,
4199
4199
  to: `${PLUGIN_ID}/general`,
4200
- Component: () => Promise.resolve().then(() => require("./index-DcUmtUyp.js")),
4200
+ Component: () => Promise.resolve().then(() => require("./index-Dok2SBFT.js")),
4201
4201
  permissions: [pluginPermissions["settings.general"][0]]
4202
4202
  }
4203
4203
  );
@@ -4208,9 +4208,51 @@ const index = {
4208
4208
  },
4209
4209
  id: `${PLUGIN_ID}-navigation`,
4210
4210
  to: `${PLUGIN_ID}/navigation`,
4211
- Component: () => Promise.resolve().then(() => require("./index-CyzPvvul.js")),
4211
+ Component: () => Promise.resolve().then(() => require("./index-CbllvYIN.js")),
4212
4212
  permissions: [pluginPermissions["settings.navigation"][0]]
4213
4213
  });
4214
+ app.customFields.register({
4215
+ name: "route-picker",
4216
+ pluginId: PLUGIN_ID,
4217
+ type: "string",
4218
+ intlLabel: {
4219
+ id: `${PLUGIN_ID}.route-picker.label`,
4220
+ defaultMessage: "Route Picker"
4221
+ },
4222
+ intlDescription: {
4223
+ id: `${PLUGIN_ID}.route-picker.description`,
4224
+ defaultMessage: "Select a route"
4225
+ },
4226
+ components: {
4227
+ Input: async () => Promise.resolve().then(() => require("./RoutePicker-CZKBOemS.js")).then((module2) => ({
4228
+ default: module2.default
4229
+ }))
4230
+ },
4231
+ options: {
4232
+ advanced: [
4233
+ {
4234
+ sectionTitle: {
4235
+ id: "global.settings",
4236
+ defaultMessage: "Settings"
4237
+ },
4238
+ items: [
4239
+ {
4240
+ name: "required",
4241
+ type: "checkbox",
4242
+ intlLabel: {
4243
+ id: "content-type-builder.form.attribute.item.requiredField",
4244
+ defaultMessage: "Required field"
4245
+ },
4246
+ description: {
4247
+ id: "content-type-builder.form.attribute.item.requiredField.description",
4248
+ defaultMessage: "You won't be able to create an entry if this field is empty"
4249
+ }
4250
+ }
4251
+ ]
4252
+ }
4253
+ ]
4254
+ }
4255
+ });
4214
4256
  app.registerPlugin({
4215
4257
  id: PLUGIN_ID,
4216
4258
  initializer: Initializer,
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
- const index = require("./index-Bm8lkiNL.js");
3
+ const index = require("./index-ik3u6iCE.js");
4
4
  exports.default = index.index;
@@ -1,4 +1,4 @@
1
- import { i } from "./index-Dx-EVn-t.mjs";
1
+ import { i } from "./index-OkabmPb4.mjs";
2
2
  export {
3
3
  i as default
4
4
  };
@@ -4665,8 +4665,6 @@ function calculateParentAndOrder({
4665
4665
  };
4666
4666
  }
4667
4667
  async function enrichWebatlasData(data, contentTypeUid) {
4668
- console.log("Enriching data with webatlas fields...", { contentTypeUid });
4669
- console.log("Original data:", JSON.stringify(data, null, 2));
4670
4668
  if (!data || typeof data !== "object") return data;
4671
4669
  const collectDocumentIds = (obj, uid) => {
4672
4670
  if (!obj || typeof obj !== "object") return [];
@@ -4714,7 +4712,7 @@ async function enrichWebatlasData(data, contentTypeUid) {
4714
4712
  select: ["relatedDocumentId", "relatedContentType", "path", "canonicalPath", "slug", "uidPath"]
4715
4713
  });
4716
4714
  const routeMap = new Map(routes2?.map((route2) => [route2.relatedDocumentId, route2]) || []);
4717
- const enrichEntity = (entity, uid) => {
4715
+ const enrichEntity2 = (entity, uid) => {
4718
4716
  if (!entity || typeof entity !== "object") return entity;
4719
4717
  const ct = uid ? strapi.contentTypes[uid] : null;
4720
4718
  const isWebatlasEnabled = ct?.pluginOptions?.webatlas?.enabled === true;
@@ -4732,37 +4730,138 @@ async function enrichWebatlasData(data, contentTypeUid) {
4732
4730
  const attribute = attr;
4733
4731
  if (attribute.type === "relation" && entity[key]) {
4734
4732
  const targetUid = attribute.target;
4735
- strapi.log.debug("relation found");
4736
4733
  if (Array.isArray(entity[key])) {
4737
4734
  entity[key] = entity[key].map(
4738
- (item) => item ? enrichEntity(item, targetUid) : item
4735
+ (item) => item ? enrichEntity2(item, targetUid) : item
4739
4736
  );
4740
4737
  } else {
4741
- entity[key] = enrichEntity(entity[key], targetUid);
4738
+ entity[key] = enrichEntity2(entity[key], targetUid);
4742
4739
  }
4743
4740
  }
4744
4741
  if (attribute.type === "component" && entity[key]) {
4745
4742
  const componentUid = attribute.component;
4746
4743
  if (Array.isArray(entity[key])) {
4747
4744
  entity[key] = entity[key].map(
4748
- (item) => item ? enrichEntity(item, componentUid) : item
4745
+ (item) => item ? enrichEntity2(item, componentUid) : item
4749
4746
  );
4750
4747
  } else {
4751
- entity[key] = enrichEntity(entity[key], componentUid);
4748
+ entity[key] = enrichEntity2(entity[key], componentUid);
4752
4749
  }
4753
4750
  }
4754
4751
  if (attribute.type === "dynamiczone" && Array.isArray(entity[key])) {
4755
4752
  entity[key] = entity[key].map((item) => {
4756
4753
  if (!item || !item.__component) return item;
4757
- return enrichEntity(item, item.__component);
4754
+ return enrichEntity2(item, item.__component);
4758
4755
  });
4759
4756
  }
4760
4757
  }
4761
4758
  }
4762
- strapi.log.debug("finished - returning");
4763
4759
  return entity;
4764
4760
  };
4765
- return enrichEntity(data, contentTypeUid);
4761
+ return enrichEntity2(data, contentTypeUid);
4762
+ }
4763
+ function isExternalUrl(value) {
4764
+ return !/^[a-z0-9]+$/.test(value);
4765
+ }
4766
+ function collectRoutePickerIds(obj, uid) {
4767
+ if (!obj || typeof obj !== "object") return [];
4768
+ const ids = [];
4769
+ if (!uid) return ids;
4770
+ const ct = strapi.contentTypes[uid] || strapi.components?.[uid];
4771
+ if (!ct?.attributes) return ids;
4772
+ for (const [key, attr] of Object.entries(ct.attributes)) {
4773
+ const attribute = attr;
4774
+ if (attribute.customField === "plugin::webatlas.route-picker" && obj[key]) {
4775
+ const value = obj[key];
4776
+ if (typeof value === "string" && !isExternalUrl(value)) {
4777
+ ids.push(value);
4778
+ }
4779
+ }
4780
+ if (attribute.type === "relation" && obj[key]) {
4781
+ const targetUid = attribute.target;
4782
+ if (Array.isArray(obj[key])) {
4783
+ ids.push(...obj[key].flatMap((item) => collectRoutePickerIds(item, targetUid)));
4784
+ } else {
4785
+ ids.push(...collectRoutePickerIds(obj[key], targetUid));
4786
+ }
4787
+ }
4788
+ if (attribute.type === "component" && obj[key]) {
4789
+ const componentUid = attribute.component;
4790
+ if (Array.isArray(obj[key])) {
4791
+ ids.push(...obj[key].flatMap((item) => collectRoutePickerIds(item, componentUid)));
4792
+ } else {
4793
+ ids.push(...collectRoutePickerIds(obj[key], componentUid));
4794
+ }
4795
+ }
4796
+ if (attribute.type === "dynamiczone" && Array.isArray(obj[key])) {
4797
+ ids.push(
4798
+ ...obj[key].flatMap((item) => {
4799
+ if (!item || !item.__component) return [];
4800
+ return collectRoutePickerIds(item, item.__component);
4801
+ })
4802
+ );
4803
+ }
4804
+ }
4805
+ return ids;
4806
+ }
4807
+ function enrichEntity(entity, uid, routeMap) {
4808
+ if (!entity || typeof entity !== "object") return entity;
4809
+ const ct = strapi.contentTypes[uid] || strapi.components?.[uid];
4810
+ if (!ct?.attributes) return entity;
4811
+ for (const [key, attr] of Object.entries(ct.attributes)) {
4812
+ const attribute = attr;
4813
+ if (attribute.customField === "plugin::webatlas.route-picker" && entity[key]) {
4814
+ const value = entity[key];
4815
+ if (typeof value === "string" && !isExternalUrl(value)) {
4816
+ const route2 = routeMap.get(value);
4817
+ if (route2) {
4818
+ entity[key] = route2.canonicalPath || route2.path || value;
4819
+ }
4820
+ }
4821
+ }
4822
+ if (attribute.type === "relation" && entity[key]) {
4823
+ const targetUid = attribute.target;
4824
+ if (Array.isArray(entity[key])) {
4825
+ entity[key] = entity[key].map(
4826
+ (item) => item ? enrichEntity(item, targetUid, routeMap) : item
4827
+ );
4828
+ } else {
4829
+ entity[key] = enrichEntity(entity[key], targetUid, routeMap);
4830
+ }
4831
+ }
4832
+ if (attribute.type === "component" && entity[key]) {
4833
+ const componentUid = attribute.component;
4834
+ if (Array.isArray(entity[key])) {
4835
+ entity[key] = entity[key].map(
4836
+ (item) => item ? enrichEntity(item, componentUid, routeMap) : item
4837
+ );
4838
+ } else {
4839
+ entity[key] = enrichEntity(entity[key], componentUid, routeMap);
4840
+ }
4841
+ }
4842
+ if (attribute.type === "dynamiczone" && Array.isArray(entity[key])) {
4843
+ entity[key] = entity[key].map((item) => {
4844
+ if (!item || !item.__component) return item;
4845
+ return enrichEntity(item, item.__component, routeMap);
4846
+ });
4847
+ }
4848
+ }
4849
+ return entity;
4850
+ }
4851
+ async function enrichRoutePickerFields(data, contentTypeUid) {
4852
+ if (!data || typeof data !== "object") return data;
4853
+ const documentIds = collectRoutePickerIds(data, contentTypeUid);
4854
+ if (documentIds.length === 0) return data;
4855
+ const uniqueDocumentIds = [...new Set(documentIds)];
4856
+ const routes2 = await strapi.db?.query(waRoute).findMany({
4857
+ where: {
4858
+ documentId: { $in: uniqueDocumentIds }
4859
+ },
4860
+ select: ["documentId", "path", "canonicalPath"]
4861
+ });
4862
+ const routeMap = new Map(routes2?.map((route2) => [route2.documentId, route2]) || []);
4863
+ const enriched = enrichEntity(data, contentTypeUid, routeMap);
4864
+ return enriched;
4766
4865
  }
4767
4866
  const migration_001_canonical_path = {
4768
4867
  version: "001",
@@ -5186,7 +5285,7 @@ const addWebatlasField = ({ strapi: strapi2 }) => {
5186
5285
  ([uid, ct]) => ct.info?.pluralName === apiEndpoint
5187
5286
  );
5188
5287
  if (!contentTypeEntry) return;
5189
- const [contentTypeUid, contentType] = contentTypeEntry;
5288
+ const [contentTypeUid] = contentTypeEntry;
5190
5289
  if (ctx.body.data) {
5191
5290
  if (Array.isArray(ctx.body.data)) {
5192
5291
  ctx.body.data = await Promise.all(
@@ -5202,8 +5301,43 @@ const addWebatlasField = ({ strapi: strapi2 }) => {
5202
5301
  }
5203
5302
  };
5204
5303
  };
5304
+ const enrichRoutePicker = ({ strapi: strapi2 }) => {
5305
+ return async (ctx, next) => {
5306
+ await next();
5307
+ if (!ctx.request.url.startsWith("/api/")) {
5308
+ return;
5309
+ }
5310
+ if (!ctx.body || ctx.status !== 200) {
5311
+ return;
5312
+ }
5313
+ const urlMatch = ctx.request.url.match(/^\/api\/([^/?]+)/);
5314
+ if (!urlMatch) return;
5315
+ const apiEndpoint = urlMatch[1];
5316
+ const contentTypeEntry = Object.entries(strapi2.contentTypes).find(
5317
+ ([uid, ct]) => ct.info?.pluralName === apiEndpoint
5318
+ );
5319
+ if (!contentTypeEntry) return;
5320
+ const [contentTypeUid] = contentTypeEntry;
5321
+ if (ctx.body.data) {
5322
+ if (Array.isArray(ctx.body.data)) {
5323
+ ctx.body.data = await Promise.all(
5324
+ ctx.body.data.map((item) => enrichRoutePickerFields(item, contentTypeUid))
5325
+ );
5326
+ } else {
5327
+ ctx.body.data = await enrichRoutePickerFields(ctx.body.data, contentTypeUid);
5328
+ }
5329
+ } else if (Array.isArray(ctx.body)) {
5330
+ ctx.body = await Promise.all(
5331
+ ctx.body.map((item) => enrichRoutePickerFields(item, contentTypeUid))
5332
+ );
5333
+ } else if (typeof ctx.body === "object") {
5334
+ ctx.body = await enrichRoutePickerFields(ctx.body, contentTypeUid);
5335
+ }
5336
+ };
5337
+ };
5205
5338
  const middlewares = {
5206
- addWebatlasField
5339
+ addWebatlasField,
5340
+ enrichRoutePicker
5207
5341
  };
5208
5342
  const bootstrap = async ({ strapi: strapi2 }) => {
5209
5343
  try {
@@ -5217,6 +5351,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
5217
5351
  documentMiddleware(strapi2, enabledContentTypes, config2);
5218
5352
  webatlasMiddleware(strapi2);
5219
5353
  strapi2.server.use(middlewares.addWebatlasField({ strapi: strapi2 }));
5354
+ strapi2.server.use(middlewares.enrichRoutePicker({ strapi: strapi2 }));
5220
5355
  } catch (error) {
5221
5356
  strapi2.log.error(`Bootstrap failed. ${String(error)}`);
5222
5357
  }
@@ -5224,6 +5359,11 @@ const bootstrap = async ({ strapi: strapi2 }) => {
5224
5359
  const destroy = ({ strapi: strapi2 }) => {
5225
5360
  };
5226
5361
  const register = ({ strapi: strapi2 }) => {
5362
+ strapi2.customFields.register({
5363
+ name: "route-picker",
5364
+ plugin: PLUGIN_ID,
5365
+ type: "string"
5366
+ });
5227
5367
  };
5228
5368
  const config = {
5229
5369
  default: {
@@ -6087,6 +6227,7 @@ const client = ({ strapi: strapi2 }) => ({
6087
6227
  let cleanEntity = cleanRootKeys(entity);
6088
6228
  cleanEntity = removeWaFields(cleanEntity);
6089
6229
  cleanEntity = await enrichWebatlasData(cleanEntity, route2.relatedContentType);
6230
+ cleanEntity = await enrichRoutePickerFields(cleanEntity, contentTypeKey);
6090
6231
  return {
6091
6232
  contentType: contentType.info.singularName,
6092
6233
  ...cleanEntity
@@ -4663,8 +4663,6 @@ function calculateParentAndOrder({
4663
4663
  };
4664
4664
  }
4665
4665
  async function enrichWebatlasData(data, contentTypeUid) {
4666
- console.log("Enriching data with webatlas fields...", { contentTypeUid });
4667
- console.log("Original data:", JSON.stringify(data, null, 2));
4668
4666
  if (!data || typeof data !== "object") return data;
4669
4667
  const collectDocumentIds = (obj, uid) => {
4670
4668
  if (!obj || typeof obj !== "object") return [];
@@ -4712,7 +4710,7 @@ async function enrichWebatlasData(data, contentTypeUid) {
4712
4710
  select: ["relatedDocumentId", "relatedContentType", "path", "canonicalPath", "slug", "uidPath"]
4713
4711
  });
4714
4712
  const routeMap = new Map(routes2?.map((route2) => [route2.relatedDocumentId, route2]) || []);
4715
- const enrichEntity = (entity, uid) => {
4713
+ const enrichEntity2 = (entity, uid) => {
4716
4714
  if (!entity || typeof entity !== "object") return entity;
4717
4715
  const ct = uid ? strapi.contentTypes[uid] : null;
4718
4716
  const isWebatlasEnabled = ct?.pluginOptions?.webatlas?.enabled === true;
@@ -4730,37 +4728,138 @@ async function enrichWebatlasData(data, contentTypeUid) {
4730
4728
  const attribute = attr;
4731
4729
  if (attribute.type === "relation" && entity[key]) {
4732
4730
  const targetUid = attribute.target;
4733
- strapi.log.debug("relation found");
4734
4731
  if (Array.isArray(entity[key])) {
4735
4732
  entity[key] = entity[key].map(
4736
- (item) => item ? enrichEntity(item, targetUid) : item
4733
+ (item) => item ? enrichEntity2(item, targetUid) : item
4737
4734
  );
4738
4735
  } else {
4739
- entity[key] = enrichEntity(entity[key], targetUid);
4736
+ entity[key] = enrichEntity2(entity[key], targetUid);
4740
4737
  }
4741
4738
  }
4742
4739
  if (attribute.type === "component" && entity[key]) {
4743
4740
  const componentUid = attribute.component;
4744
4741
  if (Array.isArray(entity[key])) {
4745
4742
  entity[key] = entity[key].map(
4746
- (item) => item ? enrichEntity(item, componentUid) : item
4743
+ (item) => item ? enrichEntity2(item, componentUid) : item
4747
4744
  );
4748
4745
  } else {
4749
- entity[key] = enrichEntity(entity[key], componentUid);
4746
+ entity[key] = enrichEntity2(entity[key], componentUid);
4750
4747
  }
4751
4748
  }
4752
4749
  if (attribute.type === "dynamiczone" && Array.isArray(entity[key])) {
4753
4750
  entity[key] = entity[key].map((item) => {
4754
4751
  if (!item || !item.__component) return item;
4755
- return enrichEntity(item, item.__component);
4752
+ return enrichEntity2(item, item.__component);
4756
4753
  });
4757
4754
  }
4758
4755
  }
4759
4756
  }
4760
- strapi.log.debug("finished - returning");
4761
4757
  return entity;
4762
4758
  };
4763
- return enrichEntity(data, contentTypeUid);
4759
+ return enrichEntity2(data, contentTypeUid);
4760
+ }
4761
+ function isExternalUrl(value) {
4762
+ return !/^[a-z0-9]+$/.test(value);
4763
+ }
4764
+ function collectRoutePickerIds(obj, uid) {
4765
+ if (!obj || typeof obj !== "object") return [];
4766
+ const ids = [];
4767
+ if (!uid) return ids;
4768
+ const ct = strapi.contentTypes[uid] || strapi.components?.[uid];
4769
+ if (!ct?.attributes) return ids;
4770
+ for (const [key, attr] of Object.entries(ct.attributes)) {
4771
+ const attribute = attr;
4772
+ if (attribute.customField === "plugin::webatlas.route-picker" && obj[key]) {
4773
+ const value = obj[key];
4774
+ if (typeof value === "string" && !isExternalUrl(value)) {
4775
+ ids.push(value);
4776
+ }
4777
+ }
4778
+ if (attribute.type === "relation" && obj[key]) {
4779
+ const targetUid = attribute.target;
4780
+ if (Array.isArray(obj[key])) {
4781
+ ids.push(...obj[key].flatMap((item) => collectRoutePickerIds(item, targetUid)));
4782
+ } else {
4783
+ ids.push(...collectRoutePickerIds(obj[key], targetUid));
4784
+ }
4785
+ }
4786
+ if (attribute.type === "component" && obj[key]) {
4787
+ const componentUid = attribute.component;
4788
+ if (Array.isArray(obj[key])) {
4789
+ ids.push(...obj[key].flatMap((item) => collectRoutePickerIds(item, componentUid)));
4790
+ } else {
4791
+ ids.push(...collectRoutePickerIds(obj[key], componentUid));
4792
+ }
4793
+ }
4794
+ if (attribute.type === "dynamiczone" && Array.isArray(obj[key])) {
4795
+ ids.push(
4796
+ ...obj[key].flatMap((item) => {
4797
+ if (!item || !item.__component) return [];
4798
+ return collectRoutePickerIds(item, item.__component);
4799
+ })
4800
+ );
4801
+ }
4802
+ }
4803
+ return ids;
4804
+ }
4805
+ function enrichEntity(entity, uid, routeMap) {
4806
+ if (!entity || typeof entity !== "object") return entity;
4807
+ const ct = strapi.contentTypes[uid] || strapi.components?.[uid];
4808
+ if (!ct?.attributes) return entity;
4809
+ for (const [key, attr] of Object.entries(ct.attributes)) {
4810
+ const attribute = attr;
4811
+ if (attribute.customField === "plugin::webatlas.route-picker" && entity[key]) {
4812
+ const value = entity[key];
4813
+ if (typeof value === "string" && !isExternalUrl(value)) {
4814
+ const route2 = routeMap.get(value);
4815
+ if (route2) {
4816
+ entity[key] = route2.canonicalPath || route2.path || value;
4817
+ }
4818
+ }
4819
+ }
4820
+ if (attribute.type === "relation" && entity[key]) {
4821
+ const targetUid = attribute.target;
4822
+ if (Array.isArray(entity[key])) {
4823
+ entity[key] = entity[key].map(
4824
+ (item) => item ? enrichEntity(item, targetUid, routeMap) : item
4825
+ );
4826
+ } else {
4827
+ entity[key] = enrichEntity(entity[key], targetUid, routeMap);
4828
+ }
4829
+ }
4830
+ if (attribute.type === "component" && entity[key]) {
4831
+ const componentUid = attribute.component;
4832
+ if (Array.isArray(entity[key])) {
4833
+ entity[key] = entity[key].map(
4834
+ (item) => item ? enrichEntity(item, componentUid, routeMap) : item
4835
+ );
4836
+ } else {
4837
+ entity[key] = enrichEntity(entity[key], componentUid, routeMap);
4838
+ }
4839
+ }
4840
+ if (attribute.type === "dynamiczone" && Array.isArray(entity[key])) {
4841
+ entity[key] = entity[key].map((item) => {
4842
+ if (!item || !item.__component) return item;
4843
+ return enrichEntity(item, item.__component, routeMap);
4844
+ });
4845
+ }
4846
+ }
4847
+ return entity;
4848
+ }
4849
+ async function enrichRoutePickerFields(data, contentTypeUid) {
4850
+ if (!data || typeof data !== "object") return data;
4851
+ const documentIds = collectRoutePickerIds(data, contentTypeUid);
4852
+ if (documentIds.length === 0) return data;
4853
+ const uniqueDocumentIds = [...new Set(documentIds)];
4854
+ const routes2 = await strapi.db?.query(waRoute).findMany({
4855
+ where: {
4856
+ documentId: { $in: uniqueDocumentIds }
4857
+ },
4858
+ select: ["documentId", "path", "canonicalPath"]
4859
+ });
4860
+ const routeMap = new Map(routes2?.map((route2) => [route2.documentId, route2]) || []);
4861
+ const enriched = enrichEntity(data, contentTypeUid, routeMap);
4862
+ return enriched;
4764
4863
  }
4765
4864
  const migration_001_canonical_path = {
4766
4865
  version: "001",
@@ -5184,7 +5283,7 @@ const addWebatlasField = ({ strapi: strapi2 }) => {
5184
5283
  ([uid, ct]) => ct.info?.pluralName === apiEndpoint
5185
5284
  );
5186
5285
  if (!contentTypeEntry) return;
5187
- const [contentTypeUid, contentType] = contentTypeEntry;
5286
+ const [contentTypeUid] = contentTypeEntry;
5188
5287
  if (ctx.body.data) {
5189
5288
  if (Array.isArray(ctx.body.data)) {
5190
5289
  ctx.body.data = await Promise.all(
@@ -5200,8 +5299,43 @@ const addWebatlasField = ({ strapi: strapi2 }) => {
5200
5299
  }
5201
5300
  };
5202
5301
  };
5302
+ const enrichRoutePicker = ({ strapi: strapi2 }) => {
5303
+ return async (ctx, next) => {
5304
+ await next();
5305
+ if (!ctx.request.url.startsWith("/api/")) {
5306
+ return;
5307
+ }
5308
+ if (!ctx.body || ctx.status !== 200) {
5309
+ return;
5310
+ }
5311
+ const urlMatch = ctx.request.url.match(/^\/api\/([^/?]+)/);
5312
+ if (!urlMatch) return;
5313
+ const apiEndpoint = urlMatch[1];
5314
+ const contentTypeEntry = Object.entries(strapi2.contentTypes).find(
5315
+ ([uid, ct]) => ct.info?.pluralName === apiEndpoint
5316
+ );
5317
+ if (!contentTypeEntry) return;
5318
+ const [contentTypeUid] = contentTypeEntry;
5319
+ if (ctx.body.data) {
5320
+ if (Array.isArray(ctx.body.data)) {
5321
+ ctx.body.data = await Promise.all(
5322
+ ctx.body.data.map((item) => enrichRoutePickerFields(item, contentTypeUid))
5323
+ );
5324
+ } else {
5325
+ ctx.body.data = await enrichRoutePickerFields(ctx.body.data, contentTypeUid);
5326
+ }
5327
+ } else if (Array.isArray(ctx.body)) {
5328
+ ctx.body = await Promise.all(
5329
+ ctx.body.map((item) => enrichRoutePickerFields(item, contentTypeUid))
5330
+ );
5331
+ } else if (typeof ctx.body === "object") {
5332
+ ctx.body = await enrichRoutePickerFields(ctx.body, contentTypeUid);
5333
+ }
5334
+ };
5335
+ };
5203
5336
  const middlewares = {
5204
- addWebatlasField
5337
+ addWebatlasField,
5338
+ enrichRoutePicker
5205
5339
  };
5206
5340
  const bootstrap = async ({ strapi: strapi2 }) => {
5207
5341
  try {
@@ -5215,6 +5349,7 @@ const bootstrap = async ({ strapi: strapi2 }) => {
5215
5349
  documentMiddleware(strapi2, enabledContentTypes, config2);
5216
5350
  webatlasMiddleware(strapi2);
5217
5351
  strapi2.server.use(middlewares.addWebatlasField({ strapi: strapi2 }));
5352
+ strapi2.server.use(middlewares.enrichRoutePicker({ strapi: strapi2 }));
5218
5353
  } catch (error) {
5219
5354
  strapi2.log.error(`Bootstrap failed. ${String(error)}`);
5220
5355
  }
@@ -5222,6 +5357,11 @@ const bootstrap = async ({ strapi: strapi2 }) => {
5222
5357
  const destroy = ({ strapi: strapi2 }) => {
5223
5358
  };
5224
5359
  const register = ({ strapi: strapi2 }) => {
5360
+ strapi2.customFields.register({
5361
+ name: "route-picker",
5362
+ plugin: PLUGIN_ID,
5363
+ type: "string"
5364
+ });
5225
5365
  };
5226
5366
  const config = {
5227
5367
  default: {
@@ -6085,6 +6225,7 @@ const client = ({ strapi: strapi2 }) => ({
6085
6225
  let cleanEntity = cleanRootKeys(entity);
6086
6226
  cleanEntity = removeWaFields(cleanEntity);
6087
6227
  cleanEntity = await enrichWebatlasData(cleanEntity, route2.relatedContentType);
6228
+ cleanEntity = await enrichRoutePickerFields(cleanEntity, contentTypeKey);
6088
6229
  return {
6089
6230
  contentType: contentType.info.singularName,
6090
6231
  ...cleanEntity
@@ -300,6 +300,9 @@ declare const _default: {
300
300
  addWebatlasField: ({ strapi }: {
301
301
  strapi: import('@strapi/types/dist/core').Strapi;
302
302
  }) => (ctx: any, next: any) => Promise<void>;
303
+ enrichRoutePicker: ({ strapi }: {
304
+ strapi: import('@strapi/types/dist/core').Strapi;
305
+ }) => (ctx: any, next: any) => Promise<void>;
303
306
  };
304
307
  };
305
308
  export default _default;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@mattisvensson/strapi-plugin-webatlas",
3
3
  "description": "A strapi plugin to manage URL routes and navigations.",
4
4
  "license": "MIT",
5
- "version": "0.11.5",
5
+ "version": "0.11.6",
6
6
  "keywords": [
7
7
  "strapi",
8
8
  "plugin",