@mattisvensson/strapi-plugin-webatlas 0.8.0 → 0.8.2

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.
Files changed (84) hide show
  1. package/dist/_chunks/FullLoader-Cmsf8xS6.js +12 -0
  2. package/dist/_chunks/FullLoader-Cmsf8xS6.js.map +1 -0
  3. package/dist/_chunks/FullLoader-CrPED_dY.mjs +1 -0
  4. package/dist/_chunks/FullLoader-CrPED_dY.mjs.map +1 -0
  5. package/dist/_chunks/SettingTitle-BaaQ_99D.mjs +69 -0
  6. package/dist/_chunks/SettingTitle-BaaQ_99D.mjs.map +1 -0
  7. package/dist/_chunks/SettingTitle-D5oNwpzC.js +67 -0
  8. package/dist/_chunks/SettingTitle-DDZxIqee.js +68 -0
  9. package/dist/_chunks/SettingTitle-DDZxIqee.js.map +1 -0
  10. package/dist/_chunks/SettingTitle-IwvX4Kb5.mjs +68 -0
  11. package/dist/_chunks/{de-C1QgkRoj.mjs → de-B9pq-AJZ.mjs} +11 -2
  12. package/dist/_chunks/de-B9pq-AJZ.mjs.map +1 -0
  13. package/dist/_chunks/de-DlQxM8Tg.js +131 -0
  14. package/dist/_chunks/de-DlQxM8Tg.js.map +1 -0
  15. package/dist/_chunks/{en--8p5hbLP.mjs → en-Dmbcf7gp.mjs} +11 -2
  16. package/dist/_chunks/en-Dmbcf7gp.mjs.map +1 -0
  17. package/dist/_chunks/en-DrhxIwOr.js +131 -0
  18. package/dist/_chunks/en-DrhxIwOr.js.map +1 -0
  19. package/dist/_chunks/index--XAogZgv.js +247 -0
  20. package/dist/_chunks/index--XAogZgv.js.map +1 -0
  21. package/dist/_chunks/index-2lVgPz4a.js +128 -0
  22. package/dist/_chunks/index-B1dEY-gs.js +246 -0
  23. package/dist/_chunks/index-B1mbYb2_.js +293 -0
  24. package/dist/_chunks/index-B2tjc_lG.mjs +247 -0
  25. package/dist/_chunks/index-B2tjc_lG.mjs.map +1 -0
  26. package/dist/_chunks/index-BFuwbmZy.js +12241 -0
  27. package/dist/_chunks/{index-DSPh-fHL.mjs → index-D2Meknib.mjs} +11 -9
  28. package/dist/_chunks/index-D2SIGcj3.mjs +12242 -0
  29. package/dist/_chunks/index-D2SIGcj3.mjs.map +1 -0
  30. package/dist/_chunks/index-DH0mFrgH.js +129 -0
  31. package/dist/_chunks/index-DH0mFrgH.js.map +1 -0
  32. package/dist/_chunks/index-DKtlnMlv.js +12242 -0
  33. package/dist/_chunks/index-DKtlnMlv.js.map +1 -0
  34. package/dist/_chunks/index-DOMrViWi.js +4207 -0
  35. package/dist/_chunks/index-DOMrViWi.js.map +1 -0
  36. package/dist/_chunks/index-DXRtXlZW.mjs +129 -0
  37. package/dist/_chunks/index-DXRtXlZW.mjs.map +1 -0
  38. package/dist/_chunks/index-Df365kgY.js +294 -0
  39. package/dist/_chunks/index-Df365kgY.js.map +1 -0
  40. package/dist/_chunks/{index-VcxUbdMO.mjs → index-Dm_GIRd4.mjs} +35 -30
  41. package/dist/_chunks/index-Dt-mlR1F.mjs +4191 -0
  42. package/dist/_chunks/index-Dt-mlR1F.mjs.map +1 -0
  43. package/dist/_chunks/index-QFbHwlyj.mjs +294 -0
  44. package/dist/_chunks/index-QFbHwlyj.mjs.map +1 -0
  45. package/dist/_chunks/{index-7rox7tGX.mjs → index-QU9SZ_H9.mjs} +93 -52
  46. package/dist/_chunks/{index-Z3qq1ab8.mjs → index-_49Fvwqq.mjs} +47 -36
  47. package/dist/_chunks/{index-DGSjLYNl.mjs → index-aAKsnALd.mjs} +1 -1
  48. package/dist/_chunks/index-g8wz2qoC.js +4206 -0
  49. package/dist/admin/index.js +5 -0
  50. package/dist/admin/index.js.map +1 -0
  51. package/dist/admin/index.mjs +2 -1
  52. package/dist/admin/index.mjs.map +1 -0
  53. package/dist/admin/src/components/modals/NavEdit.d.ts +1 -1
  54. package/dist/admin/src/pages/Navigation/RouteItem.d.ts +1 -0
  55. package/dist/admin/src/pages/Settings/ContentBox.d.ts +5 -0
  56. package/dist/admin/src/pages/Settings/PageWrapper.d.ts +2 -1
  57. package/dist/admin/src/pages/Settings/SettingTitle.d.ts +4 -0
  58. package/dist/admin/src/pages/Settings/index.d.ts +4 -0
  59. package/dist/pluginId.d.ts +2 -1
  60. package/dist/server/index.js +63 -45
  61. package/dist/server/index.js.map +1 -0
  62. package/dist/server/index.mjs +63 -45
  63. package/dist/server/index.mjs.map +1 -0
  64. package/dist/server/src/utils/index.d.ts +6 -0
  65. package/dist/server/src/utils/navItemHandler.d.ts +1 -1
  66. package/dist/server/src/utils/reduceDepthOfOrphanedItems.d.ts +2 -0
  67. package/package.json +1 -1
  68. package/dist/_chunks/PageWrapper-B6nLPFak.mjs +0 -55
  69. package/dist/_chunks/PageWrapper-BMzPDWn4.js +0 -0
  70. package/dist/_chunks/PageWrapper-BMzPDWn4.js.map +0 -0
  71. package/dist/_chunks/de-DYxCPOdb.js +0 -0
  72. package/dist/_chunks/de-DYxCPOdb.js.map +0 -0
  73. package/dist/_chunks/en-Be-athEA.js +0 -0
  74. package/dist/_chunks/en-Be-athEA.js.map +0 -0
  75. package/dist/_chunks/index-Bu-uQ9jA.js +0 -0
  76. package/dist/_chunks/index-Bu-uQ9jA.js.map +0 -0
  77. package/dist/_chunks/index-C53yDU_z.js +0 -0
  78. package/dist/_chunks/index-C53yDU_z.js.map +0 -0
  79. package/dist/_chunks/index-CAz59RSr.js +0 -0
  80. package/dist/_chunks/index-CAz59RSr.js.map +0 -0
  81. package/dist/_chunks/index-DKfUSLPc.js +0 -0
  82. package/dist/_chunks/index-DKfUSLPc.js.map +0 -0
  83. package/dist/_chunks/index-DPMhcaxW.js +0 -0
  84. package/dist/_chunks/index-DPMhcaxW.js.map +0 -0
@@ -0,0 +1,246 @@
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-g8wz2qoC.js");
8
+ const admin = require("@strapi/strapi/admin");
9
+ require("@strapi/icons/symbols");
10
+ const FullLoader = require("./FullLoader-Cmsf8xS6.js");
11
+ const reactIntl = require("react-intl");
12
+ const reactRouterDom = require("react-router-dom");
13
+ function getRouteType(route) {
14
+ if (route.wrapper) {
15
+ return "wrapper";
16
+ } else if (!route.internal) {
17
+ return "external";
18
+ } else {
19
+ return "internal";
20
+ }
21
+ }
22
+ function TableHeader({
23
+ sortKey,
24
+ handleSort
25
+ }) {
26
+ const { formatMessage } = reactIntl.useIntl();
27
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
28
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Th, { onClick: () => handleSort("title"), cursor: "pointer", children: [
29
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
30
+ id: index.getTranslation("title"),
31
+ defaultMessage: "Title"
32
+ }) }),
33
+ sortKey === "title" && /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, {})
34
+ ] }),
35
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Th, { onClick: () => handleSort("fullPath"), cursor: "pointer", children: [
36
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
37
+ id: index.getTranslation("route"),
38
+ defaultMessage: "Route"
39
+ }) }),
40
+ sortKey === "fullPath" && /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, {})
41
+ ] }),
42
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Th, { onClick: () => handleSort("type"), cursor: "pointer", children: [
43
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
44
+ id: index.getTranslation("routes.page.column.type"),
45
+ defaultMessage: "Type"
46
+ }) }),
47
+ sortKey === "type" && /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronDown, {})
48
+ ] }),
49
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { children: formatMessage({
50
+ id: index.getTranslation("actions"),
51
+ defaultMessage: "Actions"
52
+ }) }) })
53
+ ] }) });
54
+ }
55
+ function TableRow({ route }) {
56
+ const { formatMessage } = reactIntl.useIntl();
57
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
58
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: route.title }) }),
59
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: route.fullPath }) }),
60
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: formatMessage({
61
+ id: index.getTranslation(`route.type.${getRouteType(route)}`),
62
+ defaultMessage: "-"
63
+ }) }) }),
64
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { gap: 2, justifyContent: "end", children: route.internal && /* @__PURE__ */ jsxRuntime.jsx(
65
+ designSystem.LinkButton,
66
+ {
67
+ variant: "secondary",
68
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, {}),
69
+ href: `/admin/content-manager/collection-types/${route.relatedContentType}/${route.relatedDocumentId}`,
70
+ children: formatMessage({
71
+ id: index.getTranslation("edit"),
72
+ defaultMessage: "Edit"
73
+ })
74
+ }
75
+ ) }) })
76
+ ] });
77
+ }
78
+ function PageWrapper({ children }) {
79
+ const { formatMessage } = reactIntl.useIntl();
80
+ return /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Main, { children: [
81
+ /* @__PURE__ */ jsxRuntime.jsx(
82
+ admin.Layouts.Header,
83
+ {
84
+ title: formatMessage({
85
+ id: index.getTranslation("routes.page.title"),
86
+ defaultMessage: "Routes"
87
+ }),
88
+ subtitle: formatMessage({
89
+ id: index.getTranslation("routes.page.subtitle"),
90
+ defaultMessage: "Overview of all existing routes"
91
+ })
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }) })
95
+ ] });
96
+ }
97
+ function compareBy(field, direction) {
98
+ if (!field) {
99
+ return () => 0;
100
+ }
101
+ if (field === "type") {
102
+ return (a, b) => {
103
+ const typeA = a.internal ? "internal" : "external";
104
+ const typeB = b.internal ? "internal" : "external";
105
+ return direction === "asc" ? typeA.localeCompare(typeB) : typeB.localeCompare(typeA);
106
+ };
107
+ }
108
+ return (a, b) => {
109
+ const aValue = a[field];
110
+ const bValue = b[field];
111
+ if (typeof aValue === "string" && typeof bValue === "string") {
112
+ return direction === "asc" ? aValue.localeCompare(bValue) : bValue.localeCompare(aValue);
113
+ }
114
+ return 0;
115
+ };
116
+ }
117
+ function SearchInput({
118
+ searchQuery,
119
+ handleSearchChange
120
+ }) {
121
+ const { formatMessage } = reactIntl.useIntl();
122
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { style: { marginBottom: "16px" }, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 4, s: 12, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { width: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(
123
+ designSystem.Field.Input,
124
+ {
125
+ name: "search",
126
+ placeholder: formatMessage({
127
+ id: index.getTranslation("routes.page.searchPlaceholder"),
128
+ defaultMessage: "Search routes"
129
+ }),
130
+ value: searchQuery,
131
+ onChange: handleSearchChange,
132
+ endAction: searchQuery ? /* @__PURE__ */ jsxRuntime.jsx(
133
+ "button",
134
+ {
135
+ type: "button",
136
+ onClick: () => handleSearchChange({ target: { value: "" } }),
137
+ style: { color: "inherit", background: "none", border: "none", cursor: "pointer" },
138
+ "aria-label": "Clear search",
139
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.Cross, {})
140
+ }
141
+ ) : null
142
+ }
143
+ ) }) }) }) });
144
+ }
145
+ function RouteTable({
146
+ routes,
147
+ sortKey,
148
+ handleSort
149
+ }) {
150
+ const { formatMessage } = reactIntl.useIntl();
151
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 4, rowCount: routes.length, children: [
152
+ /* @__PURE__ */ jsxRuntime.jsx(TableHeader, { sortKey, handleSort }),
153
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: routes.length > 0 ? routes.map((route) => /* @__PURE__ */ jsxRuntime.jsx(TableRow, { route }, route.id)) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
154
+ designSystem.EmptyStateLayout,
155
+ {
156
+ content: formatMessage({
157
+ id: index.getTranslation("routes.page.emptyRoutes"),
158
+ defaultMessage: "No routes found"
159
+ }),
160
+ shadow: false
161
+ }
162
+ ) }) }) })
163
+ ] });
164
+ }
165
+ const Routes = () => {
166
+ const { getRoutes } = index.useApi();
167
+ const { formatMessage } = reactIntl.useIntl();
168
+ const { toggleNotification } = admin.useNotification();
169
+ const [allRoutes, setAllRoutes] = React.useState([]);
170
+ const [routes, setRoutes] = React.useState([]);
171
+ const [loading, setLoading] = React.useState(true);
172
+ const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
173
+ const initialQuery = searchParams.get("search") || "";
174
+ const [searchQuery, setSearchQuery] = React.useState(initialQuery);
175
+ const [sortKey, setSortKey] = React.useState(void 0);
176
+ const [sortDirection, setSortDirection] = React.useState("asc");
177
+ React.useEffect(() => {
178
+ const query = searchQuery.toLowerCase();
179
+ setRoutes(
180
+ allRoutes.filter(
181
+ (route) => JSON.stringify(route.id).toLowerCase().includes(query) || route.title.toLowerCase().includes(query) || route.fullPath.toLowerCase().includes(query) || route.relatedDocumentId.toLowerCase().includes(query) || route.relatedContentType.toLowerCase().includes(query)
182
+ )
183
+ );
184
+ }, [searchQuery, allRoutes]);
185
+ const debouncedSetSearchParams = React.useMemo(
186
+ () => index.debounce((value) => {
187
+ value ? setSearchParams({ search: value }) : setSearchParams({});
188
+ }, 300),
189
+ [setSearchParams]
190
+ );
191
+ const handleSearchChange = (e) => {
192
+ const value = e.target.value;
193
+ setSearchQuery(value);
194
+ debouncedSetSearchParams(value);
195
+ };
196
+ React.useEffect(() => {
197
+ async function fetchRoutes() {
198
+ try {
199
+ const data = await getRoutes();
200
+ setAllRoutes(data);
201
+ setRoutes(data);
202
+ } catch (err) {
203
+ console.error("Failed to fetch routes:", err);
204
+ toggleNotification({
205
+ type: "danger",
206
+ message: formatMessage({
207
+ id: index.getTranslation("notification.routes.fetchFailed"),
208
+ defaultMessage: "Failed to fetch routes"
209
+ })
210
+ });
211
+ } finally {
212
+ setLoading(false);
213
+ }
214
+ }
215
+ fetchRoutes();
216
+ }, []);
217
+ const handleSort = (key) => {
218
+ setSortDirection((prev) => prev === "asc" ? "desc" : "asc");
219
+ setSortKey(key);
220
+ };
221
+ React.useEffect(() => {
222
+ const sortedRoutes = sortKey ? [...routes].sort(compareBy(sortKey, sortDirection)) : routes;
223
+ setRoutes(sortedRoutes);
224
+ }, [sortKey, sortDirection]);
225
+ if (loading) {
226
+ return /* @__PURE__ */ jsxRuntime.jsx(PageWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(FullLoader.FullLoader, {}) });
227
+ }
228
+ return /* @__PURE__ */ jsxRuntime.jsxs(PageWrapper, { children: [
229
+ /* @__PURE__ */ jsxRuntime.jsx(
230
+ SearchInput,
231
+ {
232
+ handleSearchChange,
233
+ searchQuery
234
+ }
235
+ ),
236
+ /* @__PURE__ */ jsxRuntime.jsx(
237
+ RouteTable,
238
+ {
239
+ routes,
240
+ sortKey,
241
+ handleSort
242
+ }
243
+ )
244
+ ] });
245
+ };
246
+ exports.default = Routes;
@@ -0,0 +1,293 @@
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 admin = require("@strapi/strapi/admin");
7
+ const index = require("./index-g8wz2qoC.js");
8
+ const reactIntl = require("react-intl");
9
+ require("@strapi/icons/symbols");
10
+ const FullLoader = require("./FullLoader-Cmsf8xS6.js");
11
+ const SettingTitle = require("./SettingTitle-D5oNwpzC.js");
12
+ const icons = require("@strapi/icons");
13
+ function ContentTypeAccordion({
14
+ contentType,
15
+ contentTypeSettings,
16
+ dispatch
17
+ }) {
18
+ const { formatMessage } = reactIntl.useIntl();
19
+ if (!contentType) return null;
20
+ return /* @__PURE__ */ jsxRuntime.jsx(
21
+ designSystem.Box,
22
+ {
23
+ borderColor: !contentTypeSettings.default && "danger500",
24
+ children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Accordion.Item, { value: contentType.uid, size: "S", children: [
25
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Trigger, { children: contentType?.info.displayName }) }),
26
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Content, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { padding: 3, children: [
27
+ /* @__PURE__ */ jsxRuntime.jsxs(
28
+ designSystem.Field.Root,
29
+ {
30
+ name: "selectedContentTypes",
31
+ hint: formatMessage({
32
+ id: index.getTranslation("settings.page.defaultField.hint"),
33
+ defaultMessage: 'The selected field from the content type will be used to generate the URL alias. Use a field that is unique and descriptive, such as a "title" or "name".'
34
+ }),
35
+ error: !contentTypeSettings.default && formatMessage({
36
+ id: index.getTranslation("settings.page.defaultField.error"),
37
+ defaultMessage: "Please select a default field"
38
+ }),
39
+ required: true,
40
+ children: [
41
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: formatMessage({
42
+ id: index.getTranslation("settings.page.defaultField"),
43
+ defaultMessage: "Default URL Alias field"
44
+ }) }),
45
+ /* @__PURE__ */ jsxRuntime.jsx(
46
+ designSystem.SingleSelect,
47
+ {
48
+ name: `defaultField-${contentType.uid}`,
49
+ onClear: () => dispatch({ type: "SET_DEFAULT_FIELD", payload: { ctUid: contentType.uid, field: "" } }),
50
+ value: contentTypeSettings?.default || "",
51
+ onChange: (value) => dispatch({ type: "SET_DEFAULT_FIELD", payload: { ctUid: contentType.uid, field: value } }),
52
+ children: Object.entries(contentType.attributes).map(([key], index2) => {
53
+ if (key === "id" || key === "documentId" || key === "createdAt" || key === "updatedAt" || key === "createdBy" || key === "updatedBy" || key === "webatlas_path" || key === "webatlas_override") return null;
54
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: key, children: key }, index2);
55
+ })
56
+ }
57
+ ),
58
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
59
+ ]
60
+ }
61
+ ),
62
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(
63
+ designSystem.Field.Root,
64
+ {
65
+ name: "urlAliasPattern",
66
+ hint: formatMessage({
67
+ id: index.getTranslation("settings.page.urlAliasPattern.hint"),
68
+ defaultMessage: 'The pattern to prepend to the generated URL alias. For example, if you enter "blog" and the value of default field is "My First Post", the generated URL alias will be "blog/my-first-post". Leave empty for no prefix.'
69
+ }),
70
+ children: [
71
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Label, { children: [
72
+ formatMessage({
73
+ id: index.getTranslation("settings.page.urlAliasPattern"),
74
+ defaultMessage: "URL Alias Pattern"
75
+ }),
76
+ /* @__PURE__ */ jsxRuntime.jsx(index.Tooltip, { description: formatMessage({
77
+ id: index.getTranslation("settings.page.urlAliasPattern.tooltip"),
78
+ defaultMessage: "Leading and trailing slashes will be removed. Spaces will be replaced with hyphens. Special characters will be encoded."
79
+ }) })
80
+ ] }),
81
+ /* @__PURE__ */ jsxRuntime.jsx(
82
+ designSystem.Field.Input,
83
+ {
84
+ value: contentTypeSettings.pattern,
85
+ onChange: (e) => dispatch({ type: "SET_PATTERN", payload: { ctUid: contentType.uid, pattern: e.target.value } }),
86
+ disabled: !contentTypeSettings.default,
87
+ type: "text",
88
+ placeholder: formatMessage({
89
+ id: index.getTranslation("settings.page.urlAliasPattern.placeholder"),
90
+ defaultMessage: "e.g. blog"
91
+ })
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
95
+ ]
96
+ }
97
+ ) })
98
+ ] }) })
99
+ ] }, contentType.uid)
100
+ },
101
+ contentType.uid
102
+ );
103
+ }
104
+ function reducer(newConfig, action) {
105
+ let updatedContentTypes;
106
+ switch (action.type) {
107
+ case "SET_SELECTED_CONTENT_TYPES":
108
+ if (!newConfig) return null;
109
+ updatedContentTypes = action.payload.map((ct) => {
110
+ return newConfig?.selectedContentTypes.find((cta) => cta.uid === ct.uid) || ct;
111
+ });
112
+ return { ...newConfig, selectedContentTypes: updatedContentTypes || [] };
113
+ case "SET_DEFAULT_FIELD":
114
+ if (!newConfig) return null;
115
+ updatedContentTypes = newConfig?.selectedContentTypes.map(
116
+ (ct) => ct.uid === action.payload.ctUid ? { ...ct, default: action.payload.field } : ct
117
+ );
118
+ return { ...newConfig, selectedContentTypes: updatedContentTypes || [] };
119
+ case "SET_PATTERN":
120
+ if (!newConfig) return null;
121
+ updatedContentTypes = newConfig?.selectedContentTypes.map(
122
+ (ct) => ct.uid === action.payload.ctUid ? { ...ct, pattern: index.transformToUrl(action.payload.pattern) } : ct
123
+ );
124
+ return { ...newConfig, selectedContentTypes: updatedContentTypes || [] };
125
+ case "SET_CONFIG":
126
+ return action.payload;
127
+ default:
128
+ throw new Error();
129
+ }
130
+ }
131
+ const Settings = () => {
132
+ const { config: fetchedConfig, setConfig, loading, fetchError } = index.usePluginConfig();
133
+ const [config, dispatch] = React.useReducer(reducer, fetchedConfig);
134
+ const { contentTypes: allContentTypesData } = index.useAllContentTypes();
135
+ const allContentTypes = allContentTypesData?.filter((ct) => ct.pluginOptions?.webatlas?.active === true);
136
+ const { toggleNotification } = admin.useNotification();
137
+ const { formatMessage } = reactIntl.useIntl();
138
+ const [isSaving, setIsSaving] = React.useState(false);
139
+ const initialConfig = React.useRef(fetchedConfig);
140
+ React.useEffect(() => {
141
+ initialConfig.current = fetchedConfig;
142
+ if (fetchedConfig)
143
+ dispatch({ type: "SET_CONFIG", payload: fetchedConfig });
144
+ }, [fetchedConfig]);
145
+ React.useEffect(() => {
146
+ if (fetchError) {
147
+ toggleNotification({
148
+ type: "danger",
149
+ message: formatMessage({
150
+ id: index.getTranslation("notification.error"),
151
+ defaultMessage: "An error occurred"
152
+ }) + ": " + fetchError
153
+ });
154
+ }
155
+ }, [fetchError, toggleNotification, formatMessage]);
156
+ async function save() {
157
+ if (!config || config.selectedContentTypes.find((cta) => !cta.default) !== void 0) return;
158
+ setIsSaving(true);
159
+ try {
160
+ await setConfig({ selectedContentTypes: config.selectedContentTypes });
161
+ initialConfig.current = config;
162
+ toggleNotification({
163
+ type: "success",
164
+ message: formatMessage({
165
+ id: index.getTranslation("notification.settings.saved"),
166
+ defaultMessage: "Settings saved successfully"
167
+ })
168
+ });
169
+ setIsSaving(false);
170
+ } catch (err) {
171
+ setIsSaving(false);
172
+ toggleNotification({
173
+ type: "danger",
174
+ message: formatMessage({
175
+ id: index.getTranslation("notification.error"),
176
+ defaultMessage: "An error occurred"
177
+ }) + ": " + err
178
+ });
179
+ console.error(err);
180
+ }
181
+ }
182
+ if (loading) {
183
+ return /* @__PURE__ */ jsxRuntime.jsx(
184
+ SettingTitle.PageWrapper,
185
+ {
186
+ isSaving,
187
+ subtitle: formatMessage({
188
+ id: index.getTranslation("loading"),
189
+ defaultMessage: "Loading..."
190
+ }),
191
+ disabledCondition: true,
192
+ children: /* @__PURE__ */ jsxRuntime.jsx(FullLoader.FullLoader, { height: 200 })
193
+ }
194
+ );
195
+ }
196
+ return /* @__PURE__ */ jsxRuntime.jsxs(
197
+ SettingTitle.PageWrapper,
198
+ {
199
+ save,
200
+ isSaving,
201
+ subtitle: formatMessage({
202
+ id: index.getTranslation("settings.page.general.subtitle"),
203
+ defaultMessage: "Configure general settings"
204
+ }),
205
+ disabledCondition: JSON.stringify(config) === JSON.stringify(initialConfig.current),
206
+ children: [
207
+ /* @__PURE__ */ jsxRuntime.jsxs(SettingTitle.ContentBox, { title: formatMessage({
208
+ id: index.getTranslation("settings.page.general.contentTypes"),
209
+ defaultMessage: "Content Types"
210
+ }), children: [
211
+ /* @__PURE__ */ jsxRuntime.jsxs(
212
+ designSystem.Field.Root,
213
+ {
214
+ name: "selectedContentTypes",
215
+ hint: formatMessage({
216
+ id: index.getTranslation("settings.page.enabledContentTypes.hint"),
217
+ defaultMessage: "Select the content types for which you want to enable URL aliases"
218
+ }),
219
+ children: [
220
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: /* @__PURE__ */ jsxRuntime.jsx(SettingTitle.SettingTitle, { children: formatMessage({
221
+ id: index.getTranslation("settings.page.enabledContentTypes"),
222
+ defaultMessage: "Enabled Content Types"
223
+ }) }) }),
224
+ /* @__PURE__ */ jsxRuntime.jsx(
225
+ designSystem.MultiSelect,
226
+ {
227
+ placeholder: formatMessage({
228
+ id: index.getTranslation("settings.page.enabledContentTypes.placeholder"),
229
+ defaultMessage: "Select content types..."
230
+ }),
231
+ onClear: () => dispatch({ type: "SET_SELECTED_CONTENT_TYPES", payload: [] }),
232
+ value: [...config?.selectedContentTypes.map((ct) => ct.uid) || []],
233
+ onChange: (value) => dispatch({
234
+ type: "SET_SELECTED_CONTENT_TYPES",
235
+ payload: value.map((v) => ({
236
+ uid: v,
237
+ default: "",
238
+ pattern: ""
239
+ }))
240
+ }),
241
+ withTags: true,
242
+ children: allContentTypes && allContentTypes.map(
243
+ (item) => /* @__PURE__ */ jsxRuntime.jsx(designSystem.MultiSelectOption, { value: item.uid, children: item.info.displayName }, item.uid)
244
+ )
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {})
248
+ ]
249
+ }
250
+ ),
251
+ config?.selectedContentTypes && config.selectedContentTypes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 4, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "selectedContentTypesAccordion", children: [
252
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: /* @__PURE__ */ jsxRuntime.jsx(SettingTitle.SettingTitle, { children: formatMessage({
253
+ id: index.getTranslation("settings.page.contentTypeSettings"),
254
+ defaultMessage: "Content Type settings"
255
+ }) }) }),
256
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Accordion.Root, { children: config.selectedContentTypes?.map((contentTypeSettings) => {
257
+ const ct = allContentTypes?.find((item) => item.uid === contentTypeSettings.uid);
258
+ return /* @__PURE__ */ jsxRuntime.jsx(ContentTypeAccordion, { contentType: ct, contentTypeSettings, dispatch }, contentTypeSettings.uid);
259
+ }) })
260
+ ] }) })
261
+ ] }),
262
+ /* @__PURE__ */ jsxRuntime.jsx(SettingTitle.ContentBox, { title: formatMessage({
263
+ id: index.getTranslation("settings.page.general.details"),
264
+ defaultMessage: "Details"
265
+ }), children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "selectedContentTypesAccordion", children: [
266
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: /* @__PURE__ */ jsxRuntime.jsxs(SettingTitle.SettingTitle, { children: [
267
+ index.PLUGIN_NAME,
268
+ " ",
269
+ formatMessage({
270
+ id: index.getTranslation("version"),
271
+ defaultMessage: "Version"
272
+ })
273
+ ] }) }),
274
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { children: [
275
+ "v",
276
+ index.PLUGIN_VERSION,
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ designSystem.Link,
279
+ {
280
+ href: `https://github.com/mattisvensson/strapi-plugin-webatlas/releases/tag/v${index.PLUGIN_VERSION}`,
281
+ target: "_blank",
282
+ rel: "noopener noreferrer",
283
+ style: { marginLeft: 4 },
284
+ children: /* @__PURE__ */ jsxRuntime.jsx(icons.ExternalLink, {})
285
+ }
286
+ )
287
+ ] })
288
+ ] }) })
289
+ ]
290
+ }
291
+ );
292
+ };
293
+ exports.default = Settings;