@vicacha-devs/strapi-plugin-seo 0.0.0-stage → 2.1.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.
Files changed (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -2
  3. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/AlternativeTextCheck/index.d.ts +9 -0
  4. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/CanonicalUrlCheck/index.d.ts +7 -0
  5. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/KeywordDensityCheck/index.d.ts +7 -0
  6. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/LastUpdatedAtCheck/index.d.ts +7 -0
  7. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/MetaDescriptionCheck/index.d.ts +7 -0
  8. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/MetaRobotCheck/index.d.ts +7 -0
  9. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/MetaTitleCheck/index.d.ts +7 -0
  10. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/OpenGraphCheck/index.d.ts +7 -0
  11. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/SEOAccordion/index.d.ts +10 -0
  12. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/StructuredDataCheck/index.d.ts +7 -0
  13. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/WordCountCheck/index.d.ts +7 -0
  14. package/dist/admin/components/CMEditView/RightLinksCompo/SeoChecks/index.d.ts +10 -0
  15. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/KeywordCheck/index.d.ts +7 -0
  16. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/MetaChecks/index.d.ts +8 -0
  17. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/Serp/index.d.ts +6 -0
  18. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/BrowserPreview/index.d.ts +6 -0
  19. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/OpenGraphPreview/Facebook/index.d.ts +8 -0
  20. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/OpenGraphPreview/LinkedIn/index.d.ts +8 -0
  21. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/OpenGraphPreview/X/index.d.ts +8 -0
  22. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/OpenGraphPreview/index.d.ts +6 -0
  23. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/PreviewChecks/index.d.ts +6 -0
  24. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/index.d.ts +4 -0
  25. package/dist/admin/components/CMEditView/RightLinksCompo/Summary/reducer.d.ts +2 -0
  26. package/dist/admin/components/CMEditView/RightLinksCompo/index.d.ts +1 -0
  27. package/dist/admin/components/CMEditView/utils/checks.d.ts +14 -0
  28. package/dist/admin/components/CMEditView/utils/getRegularImageAltTexts.d.ts +5 -0
  29. package/dist/admin/components/CMEditView/utils/getRichTextAndBlocksFields.d.ts +10 -0
  30. package/dist/admin/components/CMEditView/utils/getRichTextData.d.ts +2 -0
  31. package/dist/admin/components/HomePage/Header/index.d.ts +5 -0
  32. package/dist/admin/components/HomePage/Main/EmptyComponentLayout/illo.d.ts +1 -0
  33. package/dist/admin/components/HomePage/Main/SettingsModal/index.d.ts +8 -0
  34. package/dist/admin/components/HomePage/Main/index.d.ts +6 -0
  35. package/dist/admin/components/Initializer.d.ts +5 -0
  36. package/dist/admin/hooks/useSettingsApi.d.ts +5 -0
  37. package/dist/admin/index-C8tiCtgn.cjs +3490 -0
  38. package/dist/admin/index-CJ64dp6B.js +3473 -0
  39. package/dist/admin/index-CZ4VBOGS.cjs +589 -0
  40. package/dist/admin/index-DgvE6ytW.js +571 -0
  41. package/dist/admin/index.cjs +5 -0
  42. package/dist/admin/index.d.ts +18 -0
  43. package/dist/admin/index.js +5 -0
  44. package/dist/admin/index.mjs +5 -0
  45. package/dist/admin/pages/App/index.d.ts +2 -0
  46. package/dist/admin/pages/HomePage/index.d.ts +2 -0
  47. package/dist/admin/permissions.d.ts +10 -0
  48. package/dist/admin/pluginId.d.ts +1 -0
  49. package/dist/admin/translations/ar.json.d.ts +133 -0
  50. package/dist/admin/translations/en.json.d.ts +133 -0
  51. package/dist/admin/translations/es.json.d.ts +133 -0
  52. package/dist/admin/translations/fr.json.d.ts +133 -0
  53. package/dist/admin/translations/pt-BR.json.d.ts +133 -0
  54. package/dist/admin/translations/tr.json.d.ts +133 -0
  55. package/dist/admin/utils/getTrad.d.ts +1 -0
  56. package/dist/admin/utils/prefixPluginTranslations.d.ts +1 -0
  57. package/dist/package.json +3 -0
  58. package/dist/server/bootstrap.d.ts +5 -0
  59. package/dist/server/components/open-graph.json.d.ts +36 -0
  60. package/dist/server/components/seo.json.d.ts +52 -0
  61. package/dist/server/config/index.d.ts +5 -0
  62. package/dist/server/controllers/index.d.ts +16 -0
  63. package/dist/server/controllers/seo.d.ts +13 -0
  64. package/dist/server/controllers/settings.d.ts +16 -0
  65. package/dist/server/destroy.d.ts +5 -0
  66. package/dist/server/index.cjs +416 -0
  67. package/dist/server/index.d.ts +83 -0
  68. package/dist/server/index.js +416 -0
  69. package/dist/server/index.mjs +416 -0
  70. package/dist/server/register.d.ts +5 -0
  71. package/dist/server/routes/index.d.ts +35 -0
  72. package/dist/server/routes/seo.d.ts +16 -0
  73. package/dist/server/routes/settings.d.ts +16 -0
  74. package/dist/server/services/index.d.ts +19 -0
  75. package/dist/server/services/seo.d.ts +12 -0
  76. package/dist/server/services/settings.d.ts +10 -0
  77. package/dist/shared/index.cjs +17 -0
  78. package/dist/shared/index.d.ts +1 -0
  79. package/dist/shared/index.js +17 -0
  80. package/dist/shared/index.mjs +17 -0
  81. package/package.json +100 -3
@@ -0,0 +1,589 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const admin = require("@strapi/strapi/admin");
5
+ const reactRouterDom = require("react-router-dom");
6
+ const index = require("./index-C8tiCtgn.cjs");
7
+ const designSystem = require("@strapi/design-system");
8
+ const icons = require("@strapi/icons");
9
+ const React = require("react");
10
+ const reactIntl = require("react-intl");
11
+ function _interopNamespace(e) {
12
+ if (e && e.__esModule) return e;
13
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
14
+ if (e) {
15
+ for (const k in e) {
16
+ if (k !== "default") {
17
+ const d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: () => e[k]
21
+ });
22
+ }
23
+ }
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+ const React__namespace = /* @__PURE__ */ _interopNamespace(React);
29
+ const SEO_COMPONENT_PATH = "/plugins/content-type-builder/component-categories/shared/shared.seo";
30
+ const Header = ({ seoComponent }) => {
31
+ const { formatMessage } = reactIntl.useIntl();
32
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { background: "neutral100", children: /* @__PURE__ */ jsxRuntime.jsx(
33
+ admin.Layouts.Header,
34
+ {
35
+ primaryAction: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, alignItems: "center", children: [
36
+ seoComponent ? /* @__PURE__ */ jsxRuntime.jsx(
37
+ designSystem.LinkButton,
38
+ {
39
+ variant: "secondary",
40
+ tag: reactRouterDom.NavLink,
41
+ to: SEO_COMPONENT_PATH,
42
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, {}),
43
+ children: formatMessage({
44
+ id: index.getTrad("SEOPage.header.button.edit-component"),
45
+ defaultMessage: "Edit SEO component"
46
+ })
47
+ }
48
+ ) : null,
49
+ /* @__PURE__ */ jsxRuntime.jsx(
50
+ designSystem.LinkButton,
51
+ {
52
+ tag: reactRouterDom.NavLink,
53
+ variant: "tertiary",
54
+ to: "/",
55
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.ArrowLeft, {}),
56
+ children: formatMessage({
57
+ id: index.getTrad("SEOPage.header.button.back"),
58
+ defaultMessage: "Back"
59
+ })
60
+ }
61
+ )
62
+ ] }),
63
+ title: formatMessage({
64
+ id: index.getTrad("SEOPage.header.title"),
65
+ defaultMessage: "SEO"
66
+ }),
67
+ subtitle: formatMessage({
68
+ id: index.getTrad("SEOPage.header.subtitle"),
69
+ defaultMessage: "Optimize your content to be SEO friendly"
70
+ }),
71
+ as: "h2"
72
+ }
73
+ ) });
74
+ };
75
+ const SettingsModal = ({
76
+ item,
77
+ defaultSettings: sharedSettings = null,
78
+ onSettingsUpdated
79
+ }) => {
80
+ const { toggleNotification } = admin.useNotification();
81
+ const { formatMessage } = reactIntl.useIntl();
82
+ const { getSettings, setSettings } = index.useSettingsApi();
83
+ const [isOpen, setIsOpen] = React__namespace.useState(false);
84
+ const [metaTitle, setMetaTitle] = React__namespace.useState(true);
85
+ const [metaDescription, setMetaDescription] = React__namespace.useState(true);
86
+ const [metaRobots, setMetaRobots] = React__namespace.useState(true);
87
+ const [openGraph, setOpenGraph] = React__namespace.useState(true);
88
+ const [wordCount, setWordCount] = React__namespace.useState(true);
89
+ const [canonicalUrl, setCanonicalUrl] = React__namespace.useState(true);
90
+ const [keywordDensity, setKeywordDensity] = React__namespace.useState(true);
91
+ const [structuredData, setStructuredData] = React__namespace.useState(true);
92
+ const [alternativeText, setAlternativeText] = React__namespace.useState(true);
93
+ const [lastUpdatedAt, setLastUpdatedAt] = React__namespace.useState(true);
94
+ const [localSettings, setLocalSettings] = React__namespace.useState(sharedSettings);
95
+ const activeSettings = sharedSettings ?? localSettings;
96
+ const applyChecksToState = (settingsMap) => {
97
+ const seoChecks = settingsMap?.[item?.uid]?.seoChecks;
98
+ if (!seoChecks) {
99
+ return;
100
+ }
101
+ setMetaTitle(seoChecks.metaTitle);
102
+ setMetaDescription(seoChecks.metaDescription);
103
+ setMetaRobots(seoChecks.metaRobots);
104
+ setOpenGraph(seoChecks.openGraph);
105
+ setWordCount(seoChecks.wordCount);
106
+ setCanonicalUrl(seoChecks.canonicalUrl);
107
+ setKeywordDensity(seoChecks.keywordDensity);
108
+ setStructuredData(seoChecks.structuredData);
109
+ setAlternativeText(seoChecks.alternativeText);
110
+ setLastUpdatedAt(seoChecks.lastUpdatedAt);
111
+ };
112
+ const setupModalSettings = async () => {
113
+ if (activeSettings) {
114
+ applyChecksToState(activeSettings);
115
+ return;
116
+ }
117
+ try {
118
+ const { data } = await getSettings();
119
+ setLocalSettings(data);
120
+ onSettingsUpdated?.(data);
121
+ applyChecksToState(data);
122
+ } catch {
123
+ }
124
+ };
125
+ const handleSavingSettingsModal = async () => {
126
+ const baseSettings = activeSettings ?? {};
127
+ const collectionName = baseSettings?.[item?.uid]?.collectionName ?? item?.globalId ?? item?.uid;
128
+ const newSettings = {
129
+ ...baseSettings,
130
+ [item?.uid]: {
131
+ collectionName,
132
+ seoChecks: {
133
+ metaTitle,
134
+ metaDescription,
135
+ metaRobots,
136
+ openGraph,
137
+ wordCount,
138
+ canonicalUrl,
139
+ keywordDensity,
140
+ structuredData,
141
+ alternativeText,
142
+ lastUpdatedAt
143
+ }
144
+ }
145
+ };
146
+ try {
147
+ const { data: savedSettings } = await setSettings(newSettings);
148
+ const resolvedSettings = savedSettings ?? newSettings;
149
+ setLocalSettings(resolvedSettings);
150
+ onSettingsUpdated?.(resolvedSettings);
151
+ setIsOpen(false);
152
+ toggleNotification({
153
+ type: "success",
154
+ message: formatMessage(
155
+ {
156
+ id: index.getTrad("notification.success.settings"),
157
+ defaultMessage: "Settings saved for {collectionName} content-type."
158
+ },
159
+ { collectionName }
160
+ )
161
+ });
162
+ } catch {
163
+ toggleNotification({
164
+ type: "danger",
165
+ message: formatMessage({
166
+ id: index.getTrad("notification.error.settings"),
167
+ defaultMessage: "Failed to save SEO settings."
168
+ })
169
+ });
170
+ }
171
+ };
172
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Root, { open: isOpen, onOpenChange: setIsOpen, children: [
173
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(
174
+ designSystem.Button,
175
+ {
176
+ variant: "tertiary",
177
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Cog, {}),
178
+ onClick: () => void setupModalSettings(),
179
+ children: formatMessage({
180
+ id: index.getTrad("SEOPage.info.settings"),
181
+ defaultMessage: "Settings"
182
+ })
183
+ }
184
+ ) }),
185
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Content, { labelledBy: "title", children: [
186
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(
187
+ designSystem.Typography,
188
+ {
189
+ fontWeight: "bold",
190
+ textColor: "neutral800",
191
+ tag: "h2",
192
+ id: "title",
193
+ children: formatMessage({
194
+ id: index.getTrad("SEOPage.info.settings"),
195
+ defaultMessage: "Settings"
196
+ })
197
+ }
198
+ ) }),
199
+ /* @__PURE__ */ jsxRuntime.jsxs(
200
+ "form",
201
+ {
202
+ onSubmit: (event) => {
203
+ event.preventDefault();
204
+ void handleSavingSettingsModal();
205
+ },
206
+ children: [
207
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Body, { children: [
208
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(
209
+ admin.ContentBox,
210
+ {
211
+ title: formatMessage({
212
+ id: index.getTrad("Information"),
213
+ defaultMessage: "Information"
214
+ }),
215
+ subtitle: formatMessage({
216
+ id: index.getTrad("SEOPage.info.settings.information"),
217
+ defaultMessage: "Disable SEO checks for this specific content-type."
218
+ }),
219
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Information, {}),
220
+ iconBackground: "primary100"
221
+ }
222
+ ) }),
223
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Root, { gap: 4, children: [
224
+ {
225
+ state: metaTitle,
226
+ stateSetter: setMetaTitle,
227
+ id: "SEOPage.info.settings.meta-title-check",
228
+ defaultMessage: "Meta Title"
229
+ },
230
+ {
231
+ state: metaDescription,
232
+ stateSetter: setMetaDescription,
233
+ id: "SEOPage.info.settings.meta-description-check",
234
+ defaultMessage: "Meta Description"
235
+ },
236
+ {
237
+ state: metaRobots,
238
+ stateSetter: setMetaRobots,
239
+ id: "SEOPage.info.settings.meta-robots-check",
240
+ defaultMessage: "Meta Robots"
241
+ },
242
+ {
243
+ state: openGraph,
244
+ stateSetter: setOpenGraph,
245
+ id: "SEOPage.info.settings.open-graph-check",
246
+ defaultMessage: "Open Graph"
247
+ },
248
+ {
249
+ state: wordCount,
250
+ stateSetter: setWordCount,
251
+ id: "SEOPage.info.settings.word-count-check",
252
+ defaultMessage: "Word Count"
253
+ },
254
+ {
255
+ state: canonicalUrl,
256
+ stateSetter: setCanonicalUrl,
257
+ id: "SEOPage.info.settings.canonical-url-check",
258
+ defaultMessage: "Canonical URL"
259
+ },
260
+ {
261
+ state: keywordDensity,
262
+ stateSetter: setKeywordDensity,
263
+ id: "SEOPage.info.settings.keyword-density-check",
264
+ defaultMessage: "Keyword Density"
265
+ },
266
+ {
267
+ state: structuredData,
268
+ stateSetter: setStructuredData,
269
+ id: "SEOPage.info.settings.structured-data-check",
270
+ defaultMessage: "Structured Data"
271
+ },
272
+ {
273
+ state: alternativeText,
274
+ stateSetter: setAlternativeText,
275
+ id: "SEOPage.info.settings.alternative-text-check",
276
+ defaultMessage: "Alt Text"
277
+ },
278
+ {
279
+ state: lastUpdatedAt,
280
+ stateSetter: setLastUpdatedAt,
281
+ id: "SEOPage.info.settings.last-updated-at-check",
282
+ defaultMessage: "Last Updated At"
283
+ }
284
+ ].map(({ state, stateSetter, id, defaultMessage }) => {
285
+ return /* @__PURE__ */ jsxRuntime.jsxs(
286
+ designSystem.Grid.Item,
287
+ {
288
+ col: 6,
289
+ s: 6,
290
+ gap: 2,
291
+ padding: 4,
292
+ background: "neutral0",
293
+ borderWidth: "2px",
294
+ shadow: "filterShadow",
295
+ children: [
296
+ /* @__PURE__ */ jsxRuntime.jsx(
297
+ designSystem.Switch,
298
+ {
299
+ checked: state,
300
+ onCheckedChange: () => stateSetter((isChecked) => !isChecked)
301
+ }
302
+ ),
303
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", children: formatMessage({
304
+ id: index.getTrad(id),
305
+ defaultMessage
306
+ }) })
307
+ ]
308
+ },
309
+ id
310
+ );
311
+ }) })
312
+ ] }),
313
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Modal.Footer, { children: [
314
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Modal.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "tertiary", children: formatMessage({
315
+ id: index.getTrad("SEOPage.info.settings.cancel.button"),
316
+ defaultMessage: "Cancel"
317
+ }) }) }),
318
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { type: "submit", children: formatMessage({
319
+ id: index.getTrad("SEOPage.info.settings.save.button"),
320
+ defaultMessage: "Save"
321
+ }) })
322
+ ] })
323
+ ]
324
+ }
325
+ )
326
+ ] })
327
+ ] });
328
+ };
329
+ const ContentTypeRow = ({
330
+ item,
331
+ defaultSettings,
332
+ onSettingsUpdated
333
+ }) => {
334
+ const { formatMessage } = reactIntl.useIntl();
335
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
336
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: item.globalId }) }),
337
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { justifyContent: "flex-end", alignItems: "center", children: item.seo ? /* @__PURE__ */ jsxRuntime.jsx(
338
+ SettingsModal,
339
+ {
340
+ item,
341
+ defaultSettings,
342
+ onSettingsUpdated
343
+ }
344
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
345
+ designSystem.LinkButton,
346
+ {
347
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
348
+ variant: "secondary",
349
+ tag: reactRouterDom.NavLink,
350
+ to: `/plugins/content-type-builder/content-types/${item.uid}`,
351
+ children: formatMessage({
352
+ id: index.getTrad("SEOPage.info.add"),
353
+ defaultMessage: "Add component"
354
+ })
355
+ }
356
+ ) }) })
357
+ ] }, item.uid);
358
+ };
359
+ const ContentTypeTabTable = ({
360
+ items,
361
+ emptyMessageId,
362
+ emptyDefaultMessage,
363
+ createLinkTo,
364
+ createButtonId,
365
+ createButtonDefaultMessage,
366
+ defaultSettings,
367
+ onSettingsUpdated
368
+ }) => {
369
+ const { formatMessage } = reactIntl.useIntl();
370
+ const safeItems = Array.isArray(items) ? items : [];
371
+ const createAction = createLinkTo && createButtonId ? /* @__PURE__ */ jsxRuntime.jsx(
372
+ designSystem.LinkButton,
373
+ {
374
+ tag: reactRouterDom.NavLink,
375
+ to: createLinkTo,
376
+ variant: "secondary",
377
+ startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
378
+ children: formatMessage({
379
+ id: index.getTrad(createButtonId),
380
+ defaultMessage: createButtonDefaultMessage
381
+ })
382
+ }
383
+ ) : void 0;
384
+ return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: 2, rowCount: Math.max(safeItems.length, 1), children: [
385
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
386
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: formatMessage({
387
+ id: index.getTrad("SEOPage.tab-panel.column-name"),
388
+ defaultMessage: "Name"
389
+ }) }) }),
390
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, {})
391
+ ] }) }),
392
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: safeItems.length > 0 ? safeItems.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
393
+ ContentTypeRow,
394
+ {
395
+ item,
396
+ defaultSettings,
397
+ onSettingsUpdated
398
+ },
399
+ item.uid
400
+ )) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tr, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { colSpan: 2, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, background: "neutral0", children: /* @__PURE__ */ jsxRuntime.jsx(
401
+ designSystem.EmptyStateLayout,
402
+ {
403
+ icon: /* @__PURE__ */ jsxRuntime.jsx(index.Illo, {}),
404
+ content: formatMessage({
405
+ id: index.getTrad(emptyMessageId),
406
+ defaultMessage: emptyDefaultMessage
407
+ }),
408
+ action: createAction
409
+ }
410
+ ) }) }) }) })
411
+ ] });
412
+ };
413
+ const Main = ({ contentTypes }) => {
414
+ const { formatMessage } = reactIntl.useIntl();
415
+ const { getSettings } = index.useSettingsApi();
416
+ const [defaultSettings, setDefaultSettings] = React__namespace.useState(null);
417
+ React__namespace.useEffect(() => {
418
+ let isMounted = true;
419
+ void getSettings().then(({ data }) => {
420
+ if (isMounted && data) {
421
+ setDefaultSettings(data);
422
+ }
423
+ }).catch(() => {
424
+ });
425
+ return () => {
426
+ isMounted = false;
427
+ };
428
+ }, []);
429
+ const TabValues = {
430
+ collectionTypes: "collection-types",
431
+ singleTypes: "single-types",
432
+ plugins: "plugins"
433
+ };
434
+ return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 8, children: /* @__PURE__ */ jsxRuntime.jsxs(
435
+ designSystem.Tabs.Root,
436
+ {
437
+ id: "tabs",
438
+ variant: "simple",
439
+ defaultValue: TabValues.collectionTypes,
440
+ children: [
441
+ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.List, { children: [
442
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: TabValues.collectionTypes, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { children: formatMessage({
443
+ id: index.getTrad("SEOPage.tab.collection-type-title"),
444
+ defaultMessage: "Collection Types"
445
+ }) }) }),
446
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: TabValues.singleTypes, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
447
+ id: index.getTrad("SEOPage.tab.single-type-title"),
448
+ defaultMessage: "Single Types"
449
+ }) }) }),
450
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: TabValues.plugins, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: formatMessage({
451
+ id: index.getTrad("SEOPage.tab.plugin-title"),
452
+ defaultMessage: "Plugins"
453
+ }) }) })
454
+ ] }),
455
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: TabValues.collectionTypes, children: /* @__PURE__ */ jsxRuntime.jsx(
456
+ ContentTypeTabTable,
457
+ {
458
+ items: contentTypes?.collectionTypes,
459
+ emptyMessageId: "SEOPage.info.no-collection-types",
460
+ emptyDefaultMessage: "You don't have any collection-types yet...",
461
+ createLinkTo: "/plugins/content-type-builder",
462
+ createButtonId: "SEOPage.info.create-collection-type",
463
+ createButtonDefaultMessage: "Create your first collection-type",
464
+ defaultSettings,
465
+ onSettingsUpdated: setDefaultSettings
466
+ }
467
+ ) }),
468
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: TabValues.singleTypes, children: /* @__PURE__ */ jsxRuntime.jsx(
469
+ ContentTypeTabTable,
470
+ {
471
+ items: contentTypes?.singleTypes,
472
+ emptyMessageId: "SEOPage.info.no-single-types",
473
+ emptyDefaultMessage: "You don't have any single-types yet...",
474
+ createLinkTo: "/plugins/content-type-builder",
475
+ createButtonId: "SEOPage.info.create-single-type",
476
+ createButtonDefaultMessage: "Create your first single-type",
477
+ defaultSettings,
478
+ onSettingsUpdated: setDefaultSettings
479
+ }
480
+ ) }),
481
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: TabValues.plugins, children: /* @__PURE__ */ jsxRuntime.jsx(
482
+ ContentTypeTabTable,
483
+ {
484
+ items: contentTypes?.plugins,
485
+ emptyMessageId: "SEOPage.info.no-plugin-content-type",
486
+ emptyDefaultMessage: "You don't have any plugin content-type yet...",
487
+ defaultSettings,
488
+ onSettingsUpdated: setDefaultSettings
489
+ }
490
+ ) })
491
+ ]
492
+ }
493
+ ) });
494
+ };
495
+ const HomePage = React__namespace.memo(() => {
496
+ const { get, post } = admin.useFetchClient();
497
+ const { lockAppWithAutoreload, unlockAppWithAutoreload } = admin.private_useAutoReloadOverlayBlocker();
498
+ const { formatMessage } = reactIntl.useIntl();
499
+ const [isLoading, setIsLoading] = React__namespace.useState(true);
500
+ const [seoComponent, setSeoComponent] = React__namespace.useState(null);
501
+ const [contentTypes, setContentTypes] = React__namespace.useState(null);
502
+ React__namespace.useEffect(() => {
503
+ let isMounted = true;
504
+ const fetchSeoComponent = async () => {
505
+ try {
506
+ const { data } = await get(
507
+ `/${index.pluginId}/component`
508
+ );
509
+ return data;
510
+ } catch {
511
+ return null;
512
+ }
513
+ };
514
+ const fetchContentTypes = async () => {
515
+ try {
516
+ const { data } = await get(
517
+ `/${index.pluginId}/content-types`
518
+ );
519
+ return data;
520
+ } catch {
521
+ return null;
522
+ }
523
+ };
524
+ const createSeoComponent = async () => {
525
+ try {
526
+ const { data } = await post(
527
+ `/${index.pluginId}/component`
528
+ );
529
+ return data;
530
+ } catch {
531
+ return null;
532
+ }
533
+ };
534
+ const fetchData = async () => {
535
+ let currentComponent = await fetchSeoComponent();
536
+ let currentContentTypes = await fetchContentTypes();
537
+ const hasNoSeoComponent = !currentComponent || Object.keys(currentComponent).length === 0;
538
+ if (hasNoSeoComponent) {
539
+ try {
540
+ lockAppWithAutoreload();
541
+ await createSeoComponent();
542
+ } catch {
543
+ } finally {
544
+ unlockAppWithAutoreload();
545
+ }
546
+ currentComponent = await fetchSeoComponent();
547
+ currentContentTypes = await fetchContentTypes();
548
+ }
549
+ if (isMounted) {
550
+ setSeoComponent(currentComponent);
551
+ setContentTypes(currentContentTypes);
552
+ setIsLoading(false);
553
+ }
554
+ };
555
+ void fetchData();
556
+ return () => {
557
+ isMounted = false;
558
+ };
559
+ }, []);
560
+ if (isLoading) {
561
+ return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Loading, {});
562
+ }
563
+ return /* @__PURE__ */ jsxRuntime.jsxs(React__namespace.Fragment, { children: [
564
+ /* @__PURE__ */ jsxRuntime.jsx(Header, { seoComponent }),
565
+ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingLeft: 8, paddingRight: 8, children: /* @__PURE__ */ jsxRuntime.jsx(
566
+ admin.ContentBox,
567
+ {
568
+ title: formatMessage({
569
+ id: index.getTrad("Information"),
570
+ defaultMessage: "Information"
571
+ }),
572
+ subtitle: formatMessage({
573
+ id: index.getTrad("SEOPage.info.information"),
574
+ defaultMessage: "When adding your SEO component, make sure to name it 'seo' and to include it in the root of your Content-Type."
575
+ }),
576
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.Information, {}),
577
+ iconBackground: "primary100"
578
+ }
579
+ ) }),
580
+ /* @__PURE__ */ jsxRuntime.jsx(Main, { contentTypes })
581
+ ] });
582
+ });
583
+ const App = () => {
584
+ return /* @__PURE__ */ jsxRuntime.jsx(admin.private_AutoReloadOverlayBlockerProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: index.pluginPermissions.main, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [
585
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) }),
586
+ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) })
587
+ ] }) }) });
588
+ };
589
+ exports.default = App;