sitero 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/export/cms/client/components/index.js +1 -0
  2. package/dist/export/core/server/index.js +1 -0
  3. package/dist/prisma/generated/internal/class.js +4 -4
  4. package/dist/src/cms/client/infrastructure/i18n/messages/en-US/resources/file.js +17 -0
  5. package/dist/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/file.js +17 -0
  6. package/dist/src/cms/client/interfaces/components/create-components.js +1 -0
  7. package/dist/src/cms/client/interfaces/components/create-post-contents.js +7 -4
  8. package/dist/src/cms/client/interfaces/components/resources/admin/author-fields.js +5 -0
  9. package/dist/src/cms/client/interfaces/components/resources/file/file-card.js +1 -1
  10. package/dist/src/cms/client/interfaces/components/resources/post/content/post-create-content.js +24 -6
  11. package/dist/src/cms/client/interfaces/components/resources/post/content/post-edit-content.js +27 -7
  12. package/dist/src/cms/client/interfaces/components/resources/post/content/post-show-content.js +13 -5
  13. package/dist/src/cms/client/interfaces/components/resources/post/content/resolve-control-field-label.js +9 -0
  14. package/dist/src/cms/client/interfaces/components/resources/post/post-list.js +5 -7
  15. package/dist/src/cms/client/interfaces/components/resources/post/search/control-field-filter-state.js +20 -0
  16. package/dist/src/cms/client/interfaces/components/resources/post/search/control-fields-filters.js +28 -14
  17. package/dist/src/cms/client/interfaces/components/ui/form/containers/side-fields.js +1 -1
  18. package/dist/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-display.js +19 -9
  19. package/dist/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-input.js +22 -11
  20. package/dist/src/cms/client/interfaces/components/ui/form/control-fields/control-fields.js +6 -1
  21. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/_topicSlug_/page.js +2 -0
  22. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/page.js +4 -0
  23. package/dist/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/page.js +4 -0
  24. package/dist/src/cms/client/interfaces/pages/dashboard/system/access/admin/_id_/edit/page.js +12 -11
  25. package/dist/src/cms/client/interfaces/pages/dashboard/system/access/admin/_id_/page.js +12 -11
  26. package/dist/src/cms/client/interfaces/pages/dashboard/system/access/admin/create/page.js +12 -11
  27. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/file/delete-many/page.js +36 -5
  28. package/dist/src/cms/client/interfaces/pages/dashboard/system/storage/trash/page.js +54 -5
  29. package/dist/src/cms/server/resources/file/actions.js +15 -31
  30. package/dist/src/config/author.js +13 -0
  31. package/dist/src/config/post.js +14 -0
  32. package/dist/src/core/infrastructure/prisma/admin/admin-prisma-ports.js +44 -28
  33. package/dist/src/core/infrastructure/prisma/config/config-prisma-ports.js +48 -31
  34. package/dist/src/core/infrastructure/prisma/file/file-prisma-ports.js +79 -34
  35. package/dist/src/core/infrastructure/prisma/file/include.js +32 -33
  36. package/dist/src/core/infrastructure/prisma/helpers/active-file-references.js +20 -0
  37. package/dist/src/core/infrastructure/prisma/post/post-prisma-ports.js +126 -95
  38. package/dist/src/core/sitero-server/create-sitero-server.js +1 -0
  39. package/dist/types/export/cms/client/components/index.d.ts +2 -1
  40. package/dist/types/export/cms/client/components/index.d.ts.map +1 -1
  41. package/dist/types/export/index.d.ts +1 -1
  42. package/dist/types/export/index.d.ts.map +1 -1
  43. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/index.d.ts +45 -0
  44. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/index.d.ts.map +1 -1
  45. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/file.d.ts +45 -0
  46. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/file.d.ts.map +1 -1
  47. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/index.d.ts +45 -0
  48. package/dist/types/src/cms/client/infrastructure/i18n/messages/en-US/resources/index.d.ts.map +1 -1
  49. package/dist/types/src/cms/client/infrastructure/i18n/messages/index.d.ts +90 -0
  50. package/dist/types/src/cms/client/infrastructure/i18n/messages/index.d.ts.map +1 -1
  51. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/index.d.ts +45 -0
  52. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/index.d.ts.map +1 -1
  53. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/file.d.ts +45 -0
  54. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/file.d.ts.map +1 -1
  55. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/index.d.ts +45 -0
  56. package/dist/types/src/cms/client/infrastructure/i18n/messages/zh-TW/resources/index.d.ts.map +1 -1
  57. package/dist/types/src/cms/client/interfaces/components/create-components.d.ts +2 -3
  58. package/dist/types/src/cms/client/interfaces/components/create-components.d.ts.map +1 -1
  59. package/dist/types/src/cms/client/interfaces/components/create-post-contents.d.ts +3 -1
  60. package/dist/types/src/cms/client/interfaces/components/create-post-contents.d.ts.map +1 -1
  61. package/dist/types/src/cms/client/interfaces/components/resources/admin/author-fields.d.ts +7 -0
  62. package/dist/types/src/cms/client/interfaces/components/resources/admin/author-fields.d.ts.map +1 -0
  63. package/dist/types/src/cms/client/interfaces/components/resources/admin/index.d.ts +1 -0
  64. package/dist/types/src/cms/client/interfaces/components/resources/admin/index.d.ts.map +1 -1
  65. package/dist/types/src/cms/client/interfaces/components/resources/file/file-card.d.ts.map +1 -1
  66. package/dist/types/src/cms/client/interfaces/components/resources/index.d.ts +1 -1
  67. package/dist/types/src/cms/client/interfaces/components/resources/index.d.ts.map +1 -1
  68. package/dist/types/src/cms/client/interfaces/components/resources/post/content/index.d.ts +1 -1
  69. package/dist/types/src/cms/client/interfaces/components/resources/post/content/index.d.ts.map +1 -1
  70. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-create-content.d.ts +5 -3
  71. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-create-content.d.ts.map +1 -1
  72. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-edit-content.d.ts +5 -3
  73. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-edit-content.d.ts.map +1 -1
  74. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-show-content.d.ts +5 -3
  75. package/dist/types/src/cms/client/interfaces/components/resources/post/content/post-show-content.d.ts.map +1 -1
  76. package/dist/types/src/cms/client/interfaces/components/resources/post/content/resolve-control-field-label.d.ts +3 -0
  77. package/dist/types/src/cms/client/interfaces/components/resources/post/content/resolve-control-field-label.d.ts.map +1 -0
  78. package/dist/types/src/cms/client/interfaces/components/resources/post/content/types.d.ts +9 -0
  79. package/dist/types/src/cms/client/interfaces/components/resources/post/content/types.d.ts.map +1 -1
  80. package/dist/types/src/cms/client/interfaces/components/resources/post/index.d.ts +1 -1
  81. package/dist/types/src/cms/client/interfaces/components/resources/post/index.d.ts.map +1 -1
  82. package/dist/types/src/cms/client/interfaces/components/resources/post/post-list.d.ts +5 -2
  83. package/dist/types/src/cms/client/interfaces/components/resources/post/post-list.d.ts.map +1 -1
  84. package/dist/types/src/cms/client/interfaces/components/resources/post/search/control-field-filter-state.d.ts +7 -0
  85. package/dist/types/src/cms/client/interfaces/components/resources/post/search/control-field-filter-state.d.ts.map +1 -0
  86. package/dist/types/src/cms/client/interfaces/components/resources/post/search/control-fields-filters.d.ts +4 -23
  87. package/dist/types/src/cms/client/interfaces/components/resources/post/search/control-fields-filters.d.ts.map +1 -1
  88. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-display.d.ts +2 -0
  89. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-display.d.ts.map +1 -1
  90. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-input.d.ts +2 -0
  91. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields-input.d.ts.map +1 -1
  92. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields.d.ts +2 -0
  93. package/dist/types/src/cms/client/interfaces/components/ui/form/control-fields/control-fields.d.ts.map +1 -1
  94. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/[topicSlug]/page.d.ts.map +1 -1
  95. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/tag/page.d.ts.map +1 -1
  96. package/dist/types/src/cms/client/interfaces/pages/dashboard/content/content-management/topic/page.d.ts.map +1 -1
  97. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/[id]/edit/page.d.ts +3 -2
  98. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/[id]/edit/page.d.ts.map +1 -1
  99. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/[id]/page.d.ts +3 -2
  100. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/[id]/page.d.ts.map +1 -1
  101. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/create/page.d.ts +3 -2
  102. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/access/admin/create/page.d.ts.map +1 -1
  103. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/storage/file/delete-many/page.d.ts.map +1 -1
  104. package/dist/types/src/cms/client/interfaces/pages/dashboard/system/storage/trash/page.d.ts.map +1 -1
  105. package/dist/types/src/cms/contracts/resources/file/actions.d.ts +16 -4
  106. package/dist/types/src/cms/contracts/resources/file/actions.d.ts.map +1 -1
  107. package/dist/types/src/cms/server/resources/file/actions.d.ts.map +1 -1
  108. package/dist/types/src/config/author.d.ts +4 -0
  109. package/dist/types/src/config/author.d.ts.map +1 -0
  110. package/dist/types/src/config/index.d.ts +2 -1
  111. package/dist/types/src/config/index.d.ts.map +1 -1
  112. package/dist/types/src/config/post.d.ts +3 -1
  113. package/dist/types/src/config/post.d.ts.map +1 -1
  114. package/dist/types/src/constants/cms-locale.d.ts +1 -0
  115. package/dist/types/src/constants/cms-locale.d.ts.map +1 -1
  116. package/dist/types/src/constants/index.d.ts +1 -1
  117. package/dist/types/src/constants/index.d.ts.map +1 -1
  118. package/dist/types/src/core/infrastructure/prisma/admin/admin-prisma-ports.d.ts.map +1 -1
  119. package/dist/types/src/core/infrastructure/prisma/config/config-prisma-ports.d.ts.map +1 -1
  120. package/dist/types/src/core/infrastructure/prisma/config/types.d.ts +1 -1
  121. package/dist/types/src/core/infrastructure/prisma/config/types.d.ts.map +1 -1
  122. package/dist/types/src/core/infrastructure/prisma/file/file-prisma-ports.d.ts +2 -1
  123. package/dist/types/src/core/infrastructure/prisma/file/file-prisma-ports.d.ts.map +1 -1
  124. package/dist/types/src/core/infrastructure/prisma/file/include.d.ts +32 -168
  125. package/dist/types/src/core/infrastructure/prisma/file/include.d.ts.map +1 -1
  126. package/dist/types/src/core/infrastructure/prisma/helpers/active-file-references.d.ts +9 -0
  127. package/dist/types/src/core/infrastructure/prisma/helpers/active-file-references.d.ts.map +1 -0
  128. package/dist/types/src/core/infrastructure/prisma/post/post-prisma-ports.d.ts.map +1 -1
  129. package/dist/types/src/core/sitero-server/create-sitero-server.d.ts.map +1 -1
  130. package/dist/types/src/web/server/resources/post/actions.d.ts +1 -1
  131. package/package.json +4 -3
@@ -1,4 +1,21 @@
1
1
  const file = {
2
+ "delete-completed": { text: "Moved to trash" },
3
+ "delete-skipped": { text: "Skipped" },
4
+ "delete-failed": { text: "Delete failed, retry available" },
5
+ "delete-not-found": { text: "The file no longer exists." },
6
+ "delete-already-deleted": { text: "The file is already in the trash." },
7
+ "restore-completed": { text: "Restored" },
8
+ "restore-skipped": { text: "Skipped" },
9
+ "restore-failed": { text: "Restore failed, retry available" },
10
+ "restore-not-found": { text: "The file no longer exists." },
11
+ "restore-not-deleted": { text: "The file is no longer in the trash." },
12
+ "purge-pending": { text: "Purge incomplete" },
13
+ "restore-purge-started": {
14
+ text: "This file cannot be restored because permanent deletion has started."
15
+ },
16
+ "purge-completed": { text: "Permanently deleted" },
17
+ "purge-skipped": { text: "Skipped" },
18
+ "purge-failed": { text: "Failed, retry available" },
2
19
  "lock-filter": {
3
20
  label: { text: "Lock status" }
4
21
  },
@@ -1,4 +1,21 @@
1
1
  const file = {
2
+ "delete-completed": { text: "\u5DF2\u79FB\u81F3\u5783\u573E\u6876" },
3
+ "delete-skipped": { text: "\u5DF2\u7565\u904E" },
4
+ "delete-failed": { text: "\u522A\u9664\u5931\u6557\uFF0C\u53EF\u91CD\u8A66" },
5
+ "delete-not-found": { text: "\u6A94\u6848\u5DF2\u4E0D\u5B58\u5728\u3002" },
6
+ "delete-already-deleted": { text: "\u6A94\u6848\u5DF2\u5728\u5783\u573E\u6876\u3002" },
7
+ "restore-completed": { text: "\u5DF2\u9084\u539F" },
8
+ "restore-skipped": { text: "\u5DF2\u7565\u904E" },
9
+ "restore-failed": { text: "\u9084\u539F\u5931\u6557\uFF0C\u53EF\u91CD\u8A66" },
10
+ "restore-not-found": { text: "\u6A94\u6848\u5DF2\u4E0D\u5B58\u5728\u3002" },
11
+ "restore-not-deleted": { text: "\u6A94\u6848\u5DF2\u4E0D\u5728\u5783\u573E\u6876\u3002" },
12
+ "purge-pending": { text: "\u6E05\u9664\u672A\u5B8C\u6210" },
13
+ "restore-purge-started": {
14
+ text: "\u6A94\u6848\u5DF2\u958B\u59CB\u6C38\u4E45\u522A\u9664\uFF0C\u7121\u6CD5\u9084\u539F\u3002"
15
+ },
16
+ "purge-completed": { text: "\u5DF2\u6C38\u4E45\u522A\u9664" },
17
+ "purge-skipped": { text: "\u672A\u57F7\u884C" },
18
+ "purge-failed": { text: "\u6E05\u9664\u5931\u6557\uFF0C\u53EF\u91CD\u8A66" },
2
19
  "lock-filter": {
3
20
  label: { text: "\u9396\u5B9A\u72C0\u614B" }
4
21
  },
@@ -81,6 +81,7 @@ function createComponents(input) {
81
81
  strategies: constants.post.strategies
82
82
  });
83
83
  const PostList = createPostList({
84
+ customControlFields: constants.post.customControlFields,
84
85
  defaultWebLocale: constants.defaultWebLocale,
85
86
  postFindListCardsAction: actions.resources.post.findListCards,
86
87
  PostCard,
@@ -42,7 +42,7 @@ import { createPostEditContent } from './resources/post/content/post-edit-conten
42
42
  import { createPostShowContent } from './resources/post/content/post-show-content.js';
43
43
 
44
44
  function createPostContents(input) {
45
- const { actions, applications, constants, components } = input;
45
+ const { actions, applications, constants, components, customControlFields } = input;
46
46
  const PostCreateContent = createPostCreateContent({
47
47
  AdminCard: components.resources.AdminCard,
48
48
  AdminList: components.resources.AdminList,
@@ -56,7 +56,8 @@ function createPostContents(input) {
56
56
  TagCard: components.resources.TagCard,
57
57
  Uploader: components.blobFile.Uploader,
58
58
  usePostCreateFormData: applications.resources.post.create,
59
- webLocales: constants.webLocales
59
+ webLocales: constants.webLocales,
60
+ customControlFields
60
61
  });
61
62
  const PostEditContent = createPostEditContent({
62
63
  AdminCard: components.resources.AdminCard,
@@ -71,7 +72,8 @@ function createPostContents(input) {
71
72
  TagCard: components.resources.TagCard,
72
73
  Uploader: components.blobFile.Uploader,
73
74
  usePostUpdateFormData: applications.resources.post.update,
74
- webLocales: constants.webLocales
75
+ webLocales: constants.webLocales,
76
+ customControlFields
75
77
  });
76
78
  const PostShowContent = createPostShowContent({
77
79
  AdminCard: components.resources.AdminCard,
@@ -80,7 +82,8 @@ function createPostContents(input) {
80
82
  PostCard: components.resources.PostCard,
81
83
  TagCard: components.resources.TagCard,
82
84
  contentMaxWidth: constants.contentMaxWidth,
83
- webLocales: constants.webLocales
85
+ webLocales: constants.webLocales,
86
+ customControlFields
84
87
  });
85
88
  return {
86
89
  resources: {
@@ -0,0 +1,5 @@
1
+ function createAllowAuthorField(fields) {
2
+ return ({ field }) => fields.includes(field);
3
+ }
4
+
5
+ export { createAllowAuthorField };
@@ -79,7 +79,7 @@ function createFileCard({
79
79
  )
80
80
  },
81
81
  state: /* @__PURE__ */ jsx(FileStateIcons, { file }),
82
- media: /* @__PURE__ */ jsx("div", { className: cn("flex-center size-full", "overflow-hidden"), children: isImage ? /* @__PURE__ */ jsx(SmartImage, { fileKey: file.key, width: 160, height: 160 }) : isVideo ? /* @__PURE__ */ jsx("video", { src: joinUrl(storageUrl, file.key), autoPlay: true, loop: true, muted: true }) : /* @__PURE__ */ jsx("span", { className: cn("scale-[2]"), children: "\u{1F4C4}" }) }),
82
+ media: /* @__PURE__ */ jsx("div", { className: cn("flex-center size-full", "overflow-hidden"), children: file?.purgeStartedAt ? /* @__PURE__ */ jsx("span", { className: "text-destructive px-3 text-center text-sm", children: t("resources.file.purge-pending.text") }) : isImage ? /* @__PURE__ */ jsx(SmartImage, { fileKey: file.key, width: 160, height: 160 }) : isVideo ? /* @__PURE__ */ jsx("video", { src: joinUrl(storageUrl, file.key), autoPlay: true, loop: true, muted: true }) : /* @__PURE__ */ jsx("span", { className: cn("scale-[2]"), children: "\u{1F4C4}" }) }),
83
83
  title: fileT.name || /* @__PURE__ */ jsx(NoData, {}),
84
84
  className,
85
85
  style: { width: WIDTH, height: HEIGHT }
@@ -3,6 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { useTranslator } from 'intor/react';
4
4
  import { useRouter } from 'next/navigation';
5
5
  import { POST_TYPES } from 'sitero-domain';
6
+ import { POST_CUSTOM_STATE_FIELDS } from '../../../../../../../config/post.js';
6
7
  import 'mime-types';
7
8
  import 'react';
8
9
  import 'ua-parser-js';
@@ -62,8 +63,10 @@ import 'intor/next';
62
63
  import { ContentContainer } from '../../../ui/layouts/content-container.js';
63
64
  import { CategoryTable } from '../category/category-table.js';
64
65
  import { TagTable } from '../tag/tag-table.js';
66
+ import { resolveControlFieldLabel } from './resolve-control-field-label.js';
65
67
 
66
68
  function createPostCreateContent({
69
+ customControlFields: defaultCustomControlFields = [],
67
70
  usePostCreateFormData,
68
71
  postCreateAction,
69
72
  AdminCard,
@@ -91,6 +94,7 @@ function createPostCreateContent({
91
94
  controlMeta,
92
95
  isFetching,
93
96
  allowField,
97
+ customControlFields = defaultCustomControlFields,
94
98
  cancelButtonHref
95
99
  }) {
96
100
  const { t, locale: cmsLocale } = useTranslator();
@@ -197,7 +201,10 @@ function createPostCreateContent({
197
201
  ...isFieldAllowed(parentType, "isIndexActive") ? ["isIndexActive"] : [],
198
202
  ...isFieldAllowed(parentType, "isSlugActive") ? ["isSlugActive"] : [],
199
203
  ...isFieldAllowed(parentType, "isFeatured") ? ["isFeatured"] : [],
200
- ...isFieldAllowed(parentType, "isShownOnHome") ? ["isShownOnHome"] : []
204
+ ...isFieldAllowed(parentType, "isShownOnHome") ? ["isShownOnHome"] : [],
205
+ ...POST_CUSTOM_STATE_FIELDS.filter(
206
+ (key) => isFieldAllowed(parentType, key)
207
+ )
201
208
  ],
202
209
  type: parentType,
203
210
  topicId: topic?.id,
@@ -254,7 +261,10 @@ function createPostCreateContent({
254
261
  ...isFieldAllowed(tagType, "isIndexActive") ? ["isIndexActive"] : [],
255
262
  ...isFieldAllowed(tagType, "isSlugActive") ? ["isSlugActive"] : [],
256
263
  ...isFieldAllowed(tagType, "isFeatured") ? ["isFeatured"] : [],
257
- ...isFieldAllowed(tagType, "isShownOnHome") ? ["isShownOnHome"] : []
264
+ ...isFieldAllowed(tagType, "isShownOnHome") ? ["isShownOnHome"] : [],
265
+ ...POST_CUSTOM_STATE_FIELDS.filter(
266
+ (key) => isFieldAllowed(tagType, key)
267
+ )
258
268
  ],
259
269
  type: tagType,
260
270
  Card: TagCard,
@@ -555,7 +565,10 @@ function createPostCreateContent({
555
565
  ...isFieldAllowed(postType, "isIndexActive") ? ["isIndexActive"] : [],
556
566
  ...isFieldAllowed(postType, "isSlugActive") ? ["isSlugActive"] : [],
557
567
  ...isFieldAllowed(postType, "isFeatured") ? ["isFeatured"] : [],
558
- ...isFieldAllowed(postType, "isShownOnHome") ? ["isShownOnHome"] : []
568
+ ...isFieldAllowed(postType, "isShownOnHome") ? ["isShownOnHome"] : [],
569
+ ...POST_CUSTOM_STATE_FIELDS.filter(
570
+ (key) => isFieldAllowed(postType, key)
571
+ )
559
572
  ],
560
573
  type: postType,
561
574
  topicId: topic?.id
@@ -576,8 +589,8 @@ function createPostCreateContent({
576
589
  )
577
590
  ] })
578
591
  ] }),
579
- /* @__PURE__ */ jsxs(SideFields, { children: [
580
- /* @__PURE__ */ jsx("div", { className: "max-lg:hidden", children: /* @__PURE__ */ jsx(
592
+ /* @__PURE__ */ jsxs(SideFields, { className: "lg:max-h-[calc(100dvh-7rem)]", children: [
593
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 max-lg:hidden", children: /* @__PURE__ */ jsx(
581
594
  ActionButtonsCard,
582
595
  {
583
596
  isInitializing: isFetching,
@@ -594,7 +607,12 @@ function createPostCreateContent({
594
607
  ...isFieldAllowed(postType, "isIndexActive") ? [{ key: "isIndexActive" }] : [],
595
608
  ...isFieldAllowed(postType, "isSlugActive") ? [{ key: "isSlugActive" }] : [],
596
609
  ...isFieldAllowed(postType, "isFeatured") ? [{ key: "isFeatured" }] : [],
597
- ...isFieldAllowed(postType, "isShownOnHome") ? [{ key: "isShownOnHome" }] : []
610
+ ...isFieldAllowed(postType, "isShownOnHome") ? [{ key: "isShownOnHome" }] : [],
611
+ ...customControlFields.filter(({ key }) => isFieldAllowed(postType, key)).map(({ key, icon, label }) => ({
612
+ key,
613
+ icon,
614
+ label: resolveControlFieldLabel(label, cmsLocale)
615
+ }))
598
616
  ],
599
617
  controlMeta,
600
618
  formData,
@@ -3,6 +3,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
3
  import { useTranslator } from 'intor/react';
4
4
  import { useRouter } from 'next/navigation';
5
5
  import { POST_TYPES } from 'sitero-domain';
6
+ import { POST_CUSTOM_STATE_FIELDS } from '../../../../../../../config/post.js';
6
7
  import 'mime-types';
7
8
  import 'react';
8
9
  import 'ua-parser-js';
@@ -61,8 +62,10 @@ import 'intor/next';
61
62
  import { ContentContainer } from '../../../ui/layouts/content-container.js';
62
63
  import { CategoryTable } from '../category/category-table.js';
63
64
  import { TagTable } from '../tag/tag-table.js';
65
+ import { resolveControlFieldLabel } from './resolve-control-field-label.js';
64
66
 
65
67
  function createPostEditContent({
68
+ customControlFields: defaultCustomControlFields = [],
66
69
  usePostUpdateFormData,
67
70
  postUpdateAction,
68
71
  AdminCard,
@@ -89,7 +92,8 @@ function createPostEditContent({
89
92
  controlMeta,
90
93
  isFetching,
91
94
  isNotFound,
92
- allowField
95
+ allowField,
96
+ customControlFields = defaultCustomControlFields
93
97
  }) {
94
98
  const { t, locale: cmsLocale } = useTranslator();
95
99
  const router = useRouter();
@@ -195,7 +199,10 @@ function createPostEditContent({
195
199
  ...isFieldAllowed(parentType, "isIndexActive") ? ["isIndexActive"] : [],
196
200
  ...isFieldAllowed(parentType, "isSlugActive") ? ["isSlugActive"] : [],
197
201
  ...isFieldAllowed(parentType, "isFeatured") ? ["isFeatured"] : [],
198
- ...isFieldAllowed(parentType, "isShownOnHome") ? ["isShownOnHome"] : []
202
+ ...isFieldAllowed(parentType, "isShownOnHome") ? ["isShownOnHome"] : [],
203
+ ...POST_CUSTOM_STATE_FIELDS.filter(
204
+ (key) => isFieldAllowed(parentType, key)
205
+ )
199
206
  ],
200
207
  type: parentType,
201
208
  topicId: topic?.id,
@@ -252,7 +259,10 @@ function createPostEditContent({
252
259
  ...isFieldAllowed(tagType, "isIndexActive") ? ["isIndexActive"] : [],
253
260
  ...isFieldAllowed(tagType, "isSlugActive") ? ["isSlugActive"] : [],
254
261
  ...isFieldAllowed(tagType, "isFeatured") ? ["isFeatured"] : [],
255
- ...isFieldAllowed(tagType, "isShownOnHome") ? ["isShownOnHome"] : []
262
+ ...isFieldAllowed(tagType, "isShownOnHome") ? ["isShownOnHome"] : [],
263
+ ...POST_CUSTOM_STATE_FIELDS.filter(
264
+ (key) => isFieldAllowed(tagType, key)
265
+ )
256
266
  ],
257
267
  type: tagType,
258
268
  Card: TagCard,
@@ -553,7 +563,10 @@ function createPostEditContent({
553
563
  ...isFieldAllowed(postType, "isIndexActive") ? ["isIndexActive"] : [],
554
564
  ...isFieldAllowed(postType, "isSlugActive") ? ["isSlugActive"] : [],
555
565
  ...isFieldAllowed(postType, "isFeatured") ? ["isFeatured"] : [],
556
- ...isFieldAllowed(postType, "isShownOnHome") ? ["isShownOnHome"] : []
566
+ ...isFieldAllowed(postType, "isShownOnHome") ? ["isShownOnHome"] : [],
567
+ ...POST_CUSTOM_STATE_FIELDS.filter(
568
+ (key) => isFieldAllowed(postType, key)
569
+ )
557
570
  ],
558
571
  type: postType,
559
572
  topicId: topic?.id,
@@ -575,8 +588,8 @@ function createPostEditContent({
575
588
  )
576
589
  ] })
577
590
  ] }),
578
- /* @__PURE__ */ jsxs(SideFields, { children: [
579
- /* @__PURE__ */ jsx("div", { className: "max-lg:hidden", children: /* @__PURE__ */ jsx(
591
+ /* @__PURE__ */ jsxs(SideFields, { className: "lg:max-h-[calc(100dvh-7rem)]", children: [
592
+ /* @__PURE__ */ jsx("div", { className: "shrink-0 max-lg:hidden", children: /* @__PURE__ */ jsx(
580
593
  ActionButtonsCard,
581
594
  {
582
595
  action: "update",
@@ -593,7 +606,14 @@ function createPostEditContent({
593
606
  ...isFieldAllowed(postType, "isIndexActive", post?.slug) ? [{ key: "isIndexActive" }] : [],
594
607
  ...isFieldAllowed(postType, "isSlugActive", post?.slug) ? [{ key: "isSlugActive" }] : [],
595
608
  ...isFieldAllowed(postType, "isFeatured", post?.slug) ? [{ key: "isFeatured" }] : [],
596
- ...isFieldAllowed(postType, "isShownOnHome", post?.slug) ? [{ key: "isShownOnHome" }] : []
609
+ ...isFieldAllowed(postType, "isShownOnHome", post?.slug) ? [{ key: "isShownOnHome" }] : [],
610
+ ...customControlFields.filter(
611
+ ({ key }) => isFieldAllowed(postType, key, post?.slug)
612
+ ).map(({ key, icon, label }) => ({
613
+ key,
614
+ icon,
615
+ label: resolveControlFieldLabel(label, cmsLocale)
616
+ }))
597
617
  ],
598
618
  controlMeta,
599
619
  formData,
@@ -47,8 +47,10 @@ import 'next/navigation';
47
47
  import 'intor/next';
48
48
  import 'zod';
49
49
  import { ContentContainer } from '../../../ui/layouts/content-container.js';
50
+ import { resolveControlFieldLabel } from './resolve-control-field-label.js';
50
51
 
51
52
  function createPostShowContent({
53
+ customControlFields: defaultCustomControlFields = [],
52
54
  contentMaxWidth,
53
55
  AdminCard,
54
56
  PostCard,
@@ -65,9 +67,10 @@ function createPostShowContent({
65
67
  topChildren,
66
68
  subcategoryType,
67
69
  CategoryCard = DefaultCategoryCard,
68
- allowField
70
+ allowField,
71
+ customControlFields = defaultCustomControlFields
69
72
  }) {
70
- const { t, format } = useTranslator();
73
+ const { t, format, locale: cmsLocale } = useTranslator();
71
74
  const type = post?.type;
72
75
  const topicSlug = post?.topic?.slug;
73
76
  const categories = post?.parents;
@@ -280,12 +283,12 @@ function createPostShowContent({
280
283
  ] }),
281
284
  children
282
285
  ] }),
283
- /* @__PURE__ */ jsxs(SideFields, { children: [
286
+ /* @__PURE__ */ jsxs(SideFields, { className: "lg:max-h-[calc(100dvh-7rem)]", children: [
284
287
  /* @__PURE__ */ jsx(
285
288
  Field,
286
289
  {
287
290
  label: t("resources.post.created-at.text"),
288
- wrapperClassName: "max-lg:hidden",
291
+ wrapperClassName: "shrink-0 max-lg:hidden",
289
292
  children: /* @__PURE__ */ jsx(FieldBody, { isLoading: isFetching, children: post?.createdAt && format.date(new Date(post?.createdAt), DATE_FORMAT_OPTIONS) })
290
293
  }
291
294
  ),
@@ -298,7 +301,12 @@ function createPostShowContent({
298
301
  ...isFieldAllowed(type, "isIndexActive", post?.slug) ? [{ key: "isIndexActive" }] : [],
299
302
  ...isFieldAllowed(type, "isSlugActive", post?.slug) ? [{ key: "isSlugActive" }] : [],
300
303
  ...isFieldAllowed(type, "isFeatured", post?.slug) ? [{ key: "isFeatured" }] : [],
301
- ...isFieldAllowed(type, "isShownOnHome", post?.slug) ? [{ key: "isShownOnHome" }] : []
304
+ ...isFieldAllowed(type, "isShownOnHome", post?.slug) ? [{ key: "isShownOnHome" }] : [],
305
+ ...customControlFields.filter(({ key }) => isFieldAllowed(type, key, post?.slug)).map(({ key, icon, label }) => ({
306
+ key,
307
+ icon,
308
+ label: resolveControlFieldLabel(label, cmsLocale)
309
+ }))
302
310
  ],
303
311
  formData: { ...post },
304
312
  isDisplay: true,
@@ -0,0 +1,9 @@
1
+ import { CMS_LOCALES_ARRAY, CMS_DEFAULT_LOCALE } from '../../../../../../../constants/cms-locale.js';
2
+
3
+ function resolveControlFieldLabel(label, locale) {
4
+ if (typeof label === "string") return label;
5
+ const cmsLocale = CMS_LOCALES_ARRAY.find((supported) => supported === locale) ?? CMS_DEFAULT_LOCALE;
6
+ return label[cmsLocale] ?? label[CMS_DEFAULT_LOCALE];
7
+ }
8
+
9
+ export { resolveControlFieldLabel };
@@ -36,22 +36,18 @@ import '../../../../../../constants/paths/redirect.js';
36
36
  import '../../../../../../constants/cms-locale.js';
37
37
  import { ListContainer } from '../../ui/blocks/list-container/list-container.js';
38
38
  import { PostTable } from './post-table.js';
39
+ import { toActiveControlFieldFilters } from './search/control-field-filter-state.js';
39
40
  import { ControlFieldsFilters } from './search/control-fields-filters.js';
40
41
 
41
- function toActiveControlFieldFilters(controlFields, usableFields) {
42
- return Object.fromEntries(
43
- Object.entries(controlFields).flatMap(
44
- ([key, value]) => value !== null && (!usableFields || usableFields.includes(key)) ? [[key, value]] : []
45
- )
46
- );
47
- }
48
42
  function createPostList({
43
+ customControlFields: defaultCustomControlFields = [],
49
44
  postFindListCardsAction,
50
45
  PostCard,
51
46
  defaultWebLocale,
52
47
  strategies
53
48
  }) {
54
49
  return function PostList({
50
+ customControlFields = defaultCustomControlFields,
55
51
  enabled = true,
56
52
  usableFields,
57
53
  // search
@@ -94,6 +90,7 @@ function createPostList({
94
90
  };
95
91
  const activeControlFieldFilters = toActiveControlFieldFilters(
96
92
  controlFields,
93
+ customControlFields,
97
94
  usableFields
98
95
  );
99
96
  const { data, isFetching } = useQuery(
@@ -150,6 +147,7 @@ function createPostList({
150
147
  filters: /* @__PURE__ */ jsx(
151
148
  ControlFieldsFilters,
152
149
  {
150
+ customControlFields,
153
151
  usableFields,
154
152
  controlFields,
155
153
  setControlFields: setControlFieldsWithPageReset
@@ -0,0 +1,20 @@
1
+ const BUILT_IN_KEYS = [
2
+ "isActive",
3
+ "isIndexActive",
4
+ "isSlugActive",
5
+ "isFeatured",
6
+ "isShownOnHome"
7
+ ];
8
+ function toActiveControlFieldFilters(controlFields, customControlFields, usableFields) {
9
+ const result = {};
10
+ const keys = [...BUILT_IN_KEYS, ...customControlFields.map(({ key }) => key)];
11
+ for (const key of keys) {
12
+ const value = controlFields[key];
13
+ if (typeof value === "boolean" && (!usableFields || usableFields.includes(key))) {
14
+ result[key] = value;
15
+ }
16
+ }
17
+ return result;
18
+ }
19
+
20
+ export { toActiveControlFieldFilters };
@@ -1,7 +1,8 @@
1
- import { jsx } from 'react/jsx-runtime';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { useTranslator } from 'intor/react';
3
3
  import { Eye, Binary, MapPinCheckInside, Star, House } from 'lucide-react';
4
4
  import { BooleanFilter } from '../../../ui/features/boolean-filter.js';
5
+ import { resolveControlFieldLabel } from '../content/resolve-control-field-label.js';
5
6
 
6
7
  const CONTROL_FIELDS = [
7
8
  {
@@ -32,22 +33,35 @@ const CONTROL_FIELDS = [
32
33
  ];
33
34
  function ControlFieldsFilters({
34
35
  usableFields,
36
+ customControlFields = [],
35
37
  controlFields,
36
38
  setControlFields
37
39
  }) {
38
- const { t } = useTranslator();
39
- return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-3", children: CONTROL_FIELDS.filter(
40
- ({ key }) => !usableFields || usableFields.includes(key)
41
- ).map(({ key, label, icon: Icon }) => /* @__PURE__ */ jsx(
42
- BooleanFilter,
43
- {
44
- value: controlFields[key],
45
- onChange: (value) => setControlFields((previous) => ({ ...previous, [key]: value })),
46
- label: t(label),
47
- icon: Icon
48
- },
49
- key
50
- )) });
40
+ const { t, locale } = useTranslator();
41
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3", children: [
42
+ CONTROL_FIELDS.filter(
43
+ ({ key }) => !usableFields || usableFields.includes(key)
44
+ ).map(({ key, label, icon: Icon }) => /* @__PURE__ */ jsx(
45
+ BooleanFilter,
46
+ {
47
+ value: controlFields[key] ?? null,
48
+ onChange: (value) => setControlFields((previous) => ({ ...previous, [key]: value })),
49
+ label: t(label),
50
+ icon: Icon
51
+ },
52
+ key
53
+ )),
54
+ customControlFields.filter(({ key }) => !usableFields || usableFields.includes(key)).map(({ key, label, icon }) => /* @__PURE__ */ jsx(
55
+ BooleanFilter,
56
+ {
57
+ value: controlFields[key] ?? null,
58
+ onChange: (value) => setControlFields((previous) => ({ ...previous, [key]: value })),
59
+ label: resolveControlFieldLabel(label, locale),
60
+ icon
61
+ },
62
+ key
63
+ ))
64
+ ] });
51
65
  }
52
66
 
53
67
  export { ControlFieldsFilters };
@@ -22,7 +22,7 @@ function SideFields({
22
22
  className: cn("relative", "lg:min-h-full", wrapperClassName),
23
23
  style: { width: isMobile ? "100%" : `${CMS_FORM_SIDE_FIELDS_WIDTH}px` },
24
24
  ...props,
25
- children: /* @__PURE__ */ jsx("div", { className: cn("top-24 lg:sticky", "flex flex-col gap-6", className), children })
25
+ children: /* @__PURE__ */ jsx("div", { className: cn("top-22 lg:sticky", "flex flex-col gap-6", className), children })
26
26
  }
27
27
  );
28
28
  }
@@ -95,16 +95,26 @@ function ControlFieldsDisplay({
95
95
  )
96
96
  }
97
97
  ),
98
- notBuiltInFields.map(({ key, label }) => {
99
- return /* @__PURE__ */ jsx(Field, { label, children: /* @__PURE__ */ jsx(
100
- Checkbox,
98
+ notBuiltInFields.map(({ key, icon: Icon, label }) => {
99
+ return /* @__PURE__ */ jsx(
100
+ Field,
101
101
  {
102
- fieldName: key,
103
- formData,
104
- isLoading,
105
- isDisplay: true
106
- }
107
- ) }, key);
102
+ label: Icon ? /* @__PURE__ */ jsxs("span", { className: "flex-center gap-2", children: [
103
+ /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
104
+ label
105
+ ] }) : label,
106
+ children: /* @__PURE__ */ jsx(
107
+ Checkbox,
108
+ {
109
+ fieldName: key,
110
+ formData,
111
+ isLoading,
112
+ isDisplay: true
113
+ }
114
+ )
115
+ },
116
+ key
117
+ );
108
118
  })
109
119
  ] });
110
120
  }
@@ -139,18 +139,29 @@ function ControlFieldsInput({
139
139
  )
140
140
  }
141
141
  ),
142
- notBuiltInFields.map(({ key, label }) => {
143
- return /* @__PURE__ */ jsx(Field, { htmlFor: key, label, children: /* @__PURE__ */ jsx(
144
- Checkbox,
142
+ notBuiltInFields.map(({ key, icon: Icon, label }) => {
143
+ return /* @__PURE__ */ jsx(
144
+ Field,
145
145
  {
146
- id: key,
147
- fieldName: key,
148
- formData,
149
- setFormData,
150
- isLoading,
151
- isDisabled
152
- }
153
- ) }, key);
146
+ htmlFor: key,
147
+ label: Icon ? /* @__PURE__ */ jsxs("span", { className: "flex-center gap-2", children: [
148
+ /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
149
+ label
150
+ ] }) : label,
151
+ children: /* @__PURE__ */ jsx(
152
+ Checkbox,
153
+ {
154
+ id: key,
155
+ fieldName: key,
156
+ formData,
157
+ setFormData,
158
+ isLoading,
159
+ isDisabled
160
+ }
161
+ )
162
+ },
163
+ key
164
+ );
154
165
  })
155
166
  ] });
156
167
  }
@@ -45,7 +45,12 @@ function ControlFields({
45
45
  return /* @__PURE__ */ jsx(
46
46
  Card,
47
47
  {
48
- className: cn("flex flex-col gap-6", "bg-base-100 p-4", "[&_svg]:size-4"),
48
+ className: cn(
49
+ "flex flex-col gap-6",
50
+ "bg-base-100 p-4",
51
+ "lg:min-h-0 lg:overflow-y-auto",
52
+ "*:shrink-0 [&_svg]:size-4"
53
+ ),
49
54
  ...props,
50
55
  children: !isDisplay ? /* @__PURE__ */ jsx(
51
56
  ControlFieldsInput,
@@ -12,6 +12,7 @@ import '../../../../../../../../shared/client/react-query/client.js';
12
12
  import '@tanstack/react-query';
13
13
  import { useCmsQuery } from '../../../../../../infrastructure/operation-result/use-cms-query.js';
14
14
  import { isContentTopic, hasTopicRole } from '../../../../../../../../config/topics.js';
15
+ import { POST_CUSTOM_STATE_FIELDS } from '../../../../../../../../config/post.js';
15
16
  import { CMS_PATHS } from '../../../../../../../../constants/paths/cms-paths.js';
16
17
  import '../../../../../../../../constants/paths/redirect.js';
17
18
  import '../../../../../../../../constants/cms-locale.js';
@@ -94,6 +95,7 @@ function createTopicScopePage({
94
95
  {}
95
96
  );
96
97
  const getUsableFields = (type) => [
98
+ ...POST_CUSTOM_STATE_FIELDS.filter((key) => isFieldAllowed(type, key)),
97
99
  ...isFieldAllowed(type, "isActive") ? ["isActive"] : [],
98
100
  ...isFieldAllowed(type, "isIndexActive") ? ["isIndexActive"] : [],
99
101
  ...isFieldAllowed(type, "isSlugActive") ? ["isSlugActive"] : [],
@@ -3,6 +3,7 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
3
  import { useTranslator } from 'intor/react';
4
4
  import { Tag, Plus } from 'lucide-react';
5
5
  import { POST_TYPES } from 'sitero-domain';
6
+ import { POST_CUSTOM_STATE_FIELDS } from '../../../../../../../../config/post.js';
6
7
  import { CMS_PATHS } from '../../../../../../../../constants/paths/cms-paths.js';
7
8
  import '../../../../../../../../constants/paths/redirect.js';
8
9
  import '../../../../../../../../constants/cms-locale.js';
@@ -80,6 +81,9 @@ function createTagIndexPage({
80
81
  PostList,
81
82
  {
82
83
  usableFields: [
84
+ ...POST_CUSTOM_STATE_FIELDS.filter(
85
+ (field) => allowField({ type, field })
86
+ ),
83
87
  ...allowField({ type, field: "isActive" }) ? ["isActive"] : [],
84
88
  ...allowField({ type, field: "isIndexActive" }) ? ["isIndexActive"] : [],
85
89
  ...allowField({ type, field: "isSlugActive" }) ? ["isSlugActive"] : [],
@@ -5,6 +5,7 @@ import { SquareLibrary } from 'lucide-react';
5
5
  import { useMemo } from 'react';
6
6
  import { POST_TYPES } from 'sitero-domain';
7
7
  import { isContentTopic } from '../../../../../../../../config/topics.js';
8
+ import { POST_CUSTOM_STATE_FIELDS } from '../../../../../../../../config/post.js';
8
9
  import 'mime-types';
9
10
  import 'ua-parser-js';
10
11
  import '../../../../../../../../shared/client/react-query/client.js';
@@ -79,6 +80,9 @@ function createTopicIndexPage({
79
80
  {
80
81
  enabled: !isFetching,
81
82
  usableFields: [
83
+ ...POST_CUSTOM_STATE_FIELDS.filter(
84
+ (field) => allowField({ type: POST_TYPES.TOPIC, field })
85
+ ),
82
86
  ...allowField({ type: POST_TYPES.TOPIC, field: "isActive" }) ? ["isActive"] : [],
83
87
  ...allowField({ type: POST_TYPES.TOPIC, field: "isIndexActive" }) ? ["isIndexActive"] : [],
84
88
  ...allowField({ type: POST_TYPES.TOPIC, field: "isSlugActive" }) ? ["isSlugActive"] : [],