@questpie/admin 3.0.3 → 3.0.5

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 (253) hide show
  1. package/README.md +34 -5
  2. package/dist/client/blocks/block-renderer.d.mts +2 -2
  3. package/dist/client/blocks/block-renderer.mjs +4 -1
  4. package/dist/client/builder/types/action-types.d.mts +31 -3
  5. package/dist/client/builder/types/collection-types.d.mts +140 -0
  6. package/dist/client/builder/types/ui-config.d.mts +16 -2
  7. package/dist/client/builder/types/views.d.mts +57 -0
  8. package/dist/client/builder/types/widget-types.d.mts +5 -0
  9. package/dist/client/components/actions/action-button.mjs +137 -199
  10. package/dist/client/components/actions/action-dialog.mjs +198 -156
  11. package/dist/client/components/actions/confirmation-dialog.mjs +2 -2
  12. package/dist/client/components/actions/header-actions.mjs +52 -53
  13. package/dist/client/components/admin-link.d.mts +2 -2
  14. package/dist/client/components/auth/auth-loading.mjs +41 -18
  15. package/dist/client/components/blocks/block-editor-layout.mjs +2 -2
  16. package/dist/client/components/blocks/block-fields-renderer.mjs +64 -28
  17. package/dist/client/components/blocks/block-insert-button.mjs +4 -4
  18. package/dist/client/components/blocks/block-item.mjs +2 -2
  19. package/dist/client/components/blocks/block-library-sidebar.mjs +91 -63
  20. package/dist/client/components/component-renderer.mjs +1 -1
  21. package/dist/client/components/fields/array-field.mjs +14 -14
  22. package/dist/client/components/fields/asset-preview-field.mjs +1 -1
  23. package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
  24. package/dist/client/components/fields/json-field.mjs +2 -2
  25. package/dist/client/components/fields/object-array-field.mjs +22 -22
  26. package/dist/client/components/fields/object-field.mjs +5 -5
  27. package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
  28. package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
  29. package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
  30. package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
  31. package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
  32. package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
  33. package/dist/client/components/fields/relation-picker.mjs +7 -6
  34. package/dist/client/components/fields/relation-select.mjs +71 -47
  35. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
  36. package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
  37. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
  38. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
  39. package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
  40. package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
  41. package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
  42. package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
  43. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
  44. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
  45. package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
  46. package/dist/client/components/fields/upload-field.mjs +45 -49
  47. package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
  48. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
  49. package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
  50. package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
  51. package/dist/client/components/history-sidebar.mjs +850 -340
  52. package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
  53. package/dist/client/components/locale-switcher.mjs +8 -8
  54. package/dist/client/components/media/media-grid.mjs +106 -86
  55. package/dist/client/components/media/media-picker-dialog.mjs +242 -230
  56. package/dist/client/components/preview/live-preview-mode.mjs +1 -1
  57. package/dist/client/components/primitives/asset-preview.mjs +37 -22
  58. package/dist/client/components/primitives/date-input.mjs +212 -249
  59. package/dist/client/components/primitives/dropzone.mjs +192 -159
  60. package/dist/client/components/primitives/field-select-control.mjs +93 -0
  61. package/dist/client/components/primitives/select-multi.mjs +406 -365
  62. package/dist/client/components/primitives/select-single.mjs +391 -323
  63. package/dist/client/components/primitives/time-input.mjs +2 -2
  64. package/dist/client/components/sheets/resource-sheet.mjs +2 -0
  65. package/dist/client/components/ui/accordion.mjs +4 -4
  66. package/dist/client/components/ui/alert.mjs +3 -3
  67. package/dist/client/components/ui/badge.mjs +4 -4
  68. package/dist/client/components/ui/button.mjs +47 -37
  69. package/dist/client/components/ui/card.mjs +2 -2
  70. package/dist/client/components/ui/checkbox.mjs +1 -1
  71. package/dist/client/components/ui/command.mjs +5 -5
  72. package/dist/client/components/ui/dialog.mjs +3 -3
  73. package/dist/client/components/ui/drawer.mjs +1 -1
  74. package/dist/client/components/ui/dropdown-menu.mjs +157 -15
  75. package/dist/client/components/ui/empty-state.mjs +88 -59
  76. package/dist/client/components/ui/field.mjs +2 -2
  77. package/dist/client/components/ui/input-group.mjs +3 -3
  78. package/dist/client/components/ui/input.mjs +1 -1
  79. package/dist/client/components/ui/kbd.mjs +1 -1
  80. package/dist/client/components/ui/label.mjs +1 -1
  81. package/dist/client/components/ui/popover.mjs +19 -11
  82. package/dist/client/components/ui/scroll-fade.mjs +170 -0
  83. package/dist/client/components/ui/search-input.mjs +1 -1
  84. package/dist/client/components/ui/select.mjs +129 -27
  85. package/dist/client/components/ui/sheet.mjs +54 -34
  86. package/dist/client/components/ui/sidebar.mjs +15 -14
  87. package/dist/client/components/ui/skeleton.mjs +28 -12
  88. package/dist/client/components/ui/switch.mjs +2 -2
  89. package/dist/client/components/ui/table.mjs +82 -74
  90. package/dist/client/components/ui/tabs.mjs +26 -31
  91. package/dist/client/components/ui/textarea.mjs +1 -1
  92. package/dist/client/components/ui/tooltip.mjs +1 -1
  93. package/dist/client/components/widgets/chart-widget.mjs +154 -100
  94. package/dist/client/components/widgets/progress-widget.mjs +63 -36
  95. package/dist/client/components/widgets/quick-actions-widget.mjs +207 -115
  96. package/dist/client/components/widgets/recent-items-widget.mjs +147 -103
  97. package/dist/client/components/widgets/stats-widget.mjs +91 -72
  98. package/dist/client/components/widgets/table-widget.mjs +161 -247
  99. package/dist/client/components/widgets/timeline-widget.mjs +119 -78
  100. package/dist/client/components/widgets/value-widget.mjs +286 -157
  101. package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
  102. package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
  103. package/dist/client/contexts/focus-context.d.mts +2 -2
  104. package/dist/client/hooks/use-action.mjs +63 -55
  105. package/dist/client/hooks/use-audit-history.mjs +1 -65
  106. package/dist/client/hooks/use-collection-validation.mjs +36 -23
  107. package/dist/client/hooks/use-collection.mjs +96 -1
  108. package/dist/client/hooks/use-saved-views.mjs +70 -49
  109. package/dist/client/hooks/use-server-actions.mjs +70 -46
  110. package/dist/client/hooks/use-server-validation.mjs +156 -41
  111. package/dist/client/hooks/use-server-widget-data.mjs +1 -1
  112. package/dist/client/hooks/use-setup-status.d.mts +3 -3
  113. package/dist/client/hooks/use-setup-status.mjs +2 -2
  114. package/dist/client/hooks/use-transition-stage.mjs +2 -10
  115. package/dist/client/hooks/use-validation-error-map.mjs +31 -13
  116. package/dist/client/hooks/use-view-state.mjs +238 -174
  117. package/dist/client/i18n/date-locale.mjs +33 -0
  118. package/dist/client/i18n/hooks.mjs +17 -1
  119. package/dist/client/lib/utils.mjs +3 -2
  120. package/dist/client/preview/block-scope-context.d.mts +2 -2
  121. package/dist/client/preview/preview-banner.d.mts +2 -2
  122. package/dist/client/preview/preview-banner.mjs +75 -46
  123. package/dist/client/preview/preview-field.d.mts +4 -4
  124. package/dist/client/preview/preview-field.mjs +2 -2
  125. package/dist/client/runtime/provider.mjs +8 -1
  126. package/dist/client/runtime/translations-provider.mjs +1 -1
  127. package/dist/client/scope/picker.d.mts +2 -2
  128. package/dist/client/scope/provider.d.mts +2 -2
  129. package/dist/client/styles/base.css +1022 -0
  130. package/dist/client/styles/index.css +3 -589
  131. package/dist/client/utils/auto-expand-fields.mjs +4 -2
  132. package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
  133. package/dist/client/utils/use-lazy-component.mjs +80 -0
  134. package/dist/client/views/auth/accept-invite-form.d.mts +2 -2
  135. package/dist/client/views/auth/auth-layout.d.mts +17 -10
  136. package/dist/client/views/auth/auth-layout.mjs +291 -80
  137. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  138. package/dist/client/views/auth/forgot-password-form.mjs +2 -2
  139. package/dist/client/views/auth/login-form.d.mts +2 -2
  140. package/dist/client/views/auth/login-form.mjs +1 -1
  141. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  142. package/dist/client/views/auth/reset-password-form.mjs +2 -2
  143. package/dist/client/views/auth/setup-form.d.mts +2 -2
  144. package/dist/client/views/collection/auto-form-fields.mjs +11 -9
  145. package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
  146. package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
  147. package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
  148. package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
  149. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
  150. package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
  151. package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
  152. package/dist/client/views/collection/columns/build-columns.mjs +29 -9
  153. package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
  154. package/dist/client/views/collection/field-renderer.mjs +50 -89
  155. package/dist/client/views/collection/form-view.mjs +237 -227
  156. package/dist/client/views/collection/table-view.mjs +1167 -234
  157. package/dist/client/views/collection/view-skeletons.mjs +222 -79
  158. package/dist/client/views/common/global-search.mjs +29 -18
  159. package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
  160. package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
  161. package/dist/client/views/dashboard/widget-card.mjs +23 -14
  162. package/dist/client/views/globals/global-form-view.mjs +634 -589
  163. package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
  164. package/dist/client/views/layout/admin-layout.d.mts +3 -6
  165. package/dist/client/views/layout/admin-layout.mjs +152 -155
  166. package/dist/client/views/layout/admin-router.mjs +936 -616
  167. package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
  168. package/dist/client/views/layout/admin-sidebar.mjs +762 -592
  169. package/dist/client/views/layout/admin-theme.d.mts +10 -0
  170. package/dist/client/views/layout/admin-theme.mjs +84 -0
  171. package/dist/client/views/layout/admin-view-layout.mjs +161 -0
  172. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  173. package/dist/client/views/pages/accept-invite-page.mjs +49 -26
  174. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  175. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  176. package/dist/client/views/pages/forgot-password-page.mjs +2 -19
  177. package/dist/client/views/pages/invite-page.d.mts +2 -2
  178. package/dist/client/views/pages/invite-page.mjs +2 -19
  179. package/dist/client/views/pages/login-page.d.mts +3 -3
  180. package/dist/client/views/pages/login-page.mjs +4 -21
  181. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  182. package/dist/client/views/pages/reset-password-page.mjs +3 -20
  183. package/dist/client/views/pages/setup-page.d.mts +2 -2
  184. package/dist/client/views/pages/setup-page.mjs +70 -71
  185. package/dist/client.d.mts +6 -2
  186. package/dist/client.mjs +2 -1
  187. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  188. package/dist/index.d.mts +6 -2
  189. package/dist/index.mjs +2 -1
  190. package/dist/server/augmentation/dashboard.d.mts +67 -3
  191. package/dist/server/augmentation/form-layout.d.mts +21 -0
  192. package/dist/server/augmentation/index.d.mts +1 -1
  193. package/dist/server/codegen/admin-client-template.mjs +4 -0
  194. package/dist/server/fields/blocks.d.mts +1 -1
  195. package/dist/server/fields/blocks.mjs +12 -0
  196. package/dist/server/fields/rich-text.d.mts +1 -1
  197. package/dist/server/fields/rich-text.mjs +8 -0
  198. package/dist/server/i18n/index.mjs +29 -7
  199. package/dist/server/i18n/messages/cs.mjs +414 -1
  200. package/dist/server/i18n/messages/de.mjs +412 -1
  201. package/dist/server/i18n/messages/en.mjs +166 -1
  202. package/dist/server/i18n/messages/es.mjs +412 -1
  203. package/dist/server/i18n/messages/fr.mjs +412 -1
  204. package/dist/server/i18n/messages/pl.mjs +416 -1
  205. package/dist/server/i18n/messages/pt.mjs +409 -1
  206. package/dist/server/i18n/messages/sk.mjs +216 -2
  207. package/dist/server/modules/admin/block/introspection.mjs +4 -1
  208. package/dist/server/modules/admin/block/prefetch.mjs +12 -2
  209. package/dist/server/modules/admin/collections/account.d.mts +2 -2
  210. package/dist/server/modules/admin/collections/admin-locks.d.mts +2 -2
  211. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  212. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  213. package/dist/server/modules/admin/collections/apikey.d.mts +42 -42
  214. package/dist/server/modules/admin/collections/assets.d.mts +20 -20
  215. package/dist/server/modules/admin/collections/assets.mjs +0 -1
  216. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  217. package/dist/server/modules/admin/collections/user.d.mts +40 -28
  218. package/dist/server/modules/admin/collections/user.mjs +40 -9
  219. package/dist/server/modules/admin/collections/verification.d.mts +36 -36
  220. package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
  221. package/dist/server/modules/admin/factories.mjs +7 -18
  222. package/dist/server/modules/admin/index.d.mts +1 -1
  223. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  224. package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
  225. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  226. package/dist/server/modules/admin/routes/execute-action.mjs +67 -28
  227. package/dist/server/modules/admin/routes/i18n-helpers.mjs +34 -0
  228. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  229. package/dist/server/modules/admin/routes/preview.mjs +25 -17
  230. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  231. package/dist/server/modules/admin/routes/route-helpers.mjs +1 -1
  232. package/dist/server/modules/admin/routes/setup.d.mts +10 -10
  233. package/dist/server/modules/admin/routes/setup.mjs +16 -13
  234. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  235. package/dist/server/modules/admin/routes/translations.mjs +5 -1
  236. package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
  237. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +2 -2
  238. package/dist/server/modules/audit/.generated/module.d.mts +1 -1
  239. package/dist/server/modules/audit/.generated/module.mjs +1 -1
  240. package/dist/server/modules/audit/collections/audit-log.d.mts +2 -2
  241. package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
  242. package/dist/server/modules/audit/config/app.mjs +99 -42
  243. package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
  244. package/dist/server/plugin.mjs +4 -2
  245. package/dist/server/proxy-factories.d.mts +4 -3
  246. package/dist/server/proxy-factories.mjs +34 -8
  247. package/dist/shared/types/saved-views.types.d.mts +2 -0
  248. package/package.json +6 -4
  249. package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
  250. package/dist/client/components/ui/spinner.mjs +0 -52
  251. package/dist/client/components/ui/toolbar.mjs +0 -136
  252. package/dist/client/contexts/breadcrumb-context.mjs +0 -60
  253. package/dist/client/views/layout/admin-topbar.mjs +0 -236
@@ -1,3 +1,4 @@
1
+ import { createActionCallbackProxy } from "../../proxy-factories.mjs";
1
2
  import { CollectionBuilder } from "questpie";
2
3
 
3
4
  //#region src/server/modules/admin/factories.ts
@@ -46,30 +47,18 @@ function _chainable(def) {
46
47
  return new Proxy(def, { get: (target, prop) => {
47
48
  if (typeof prop !== "string") return Reflect.get(target, prop);
48
49
  if (prop in target) return target[prop];
50
+ if (prop === "set") return (key, value) => _chainable({
51
+ ...target,
52
+ [key]: value
53
+ });
49
54
  return (...args) => _chainable({
50
55
  ...target,
51
56
  [prop]: args.length === 0 ? true : args[0]
52
57
  });
53
58
  } });
54
59
  }
55
- /**
56
- * Action proxy for actions context.
57
- * Supports both `a.save()` (builtin) and `a.headerAction({...})` (custom).
58
- */
59
- const _actionBuilderProxy = new Proxy({}, { get: (_, prop) => {
60
- if (typeof prop !== "string") return void 0;
61
- return (...args) => {
62
- if (args.length === 0) return prop;
63
- return {
64
- id: prop,
65
- ...args[0]
66
- };
67
- };
68
- } });
69
- const _simpleActionProxy = new Proxy({ custom: (name, config) => ({
70
- id: name,
71
- ...config
72
- }) }, { get: (target, prop) => target[prop] ?? String(prop) });
60
+ const _actionBuilderProxy = createActionCallbackProxy();
61
+ const _simpleActionProxy = createActionCallbackProxy();
73
62
  const _collExt = {
74
63
  admin: {
75
64
  stateKey: "admin",
@@ -928,7 +928,7 @@ declare const adminModule: {
928
928
  $Infer: {
929
929
  body: {
930
930
  permissions: {
931
- readonly user?: ("delete" | "list" | "create" | "set-role" | "ban" | "impersonate" | "impersonate-admins" | "set-password" | "get" | "update")[] | undefined;
931
+ readonly user?: ("delete" | "create" | "update" | "list" | "set-role" | "ban" | "impersonate" | "impersonate-admins" | "set-password" | "get")[] | undefined;
932
932
  readonly session?: ("delete" | "list" | "revoke")[] | undefined;
933
933
  };
934
934
  } & {
@@ -1,4 +1,4 @@
1
- import * as questpie458 from "questpie";
1
+ import * as questpie425 from "questpie";
2
2
 
3
3
  //#region src/server/modules/admin/routes/admin-config.d.ts
4
4
 
@@ -22,7 +22,7 @@ import * as questpie458 from "questpie";
22
22
  * Registered via module routes and exposed through the fetch handler.
23
23
  */
24
24
  declare const adminConfigFunctions: {
25
- readonly getAdminConfig: questpie458.JsonRouteDefinition<Record<string, never> | undefined, any, questpie458.JsonRouteParams>;
25
+ readonly getAdminConfig: questpie425.JsonRouteDefinition<Record<string, never> | undefined, any, questpie425.JsonRouteParams>;
26
26
  };
27
27
  //#endregion
28
28
  export { adminConfigFunctions };
@@ -316,32 +316,42 @@ function mergeDashboardContributions(contributions) {
316
316
  let title;
317
317
  let description;
318
318
  let columns;
319
+ let rowHeight;
320
+ let gap;
319
321
  let realtime;
320
322
  const allActions = [];
321
323
  const sectionOrder = [];
322
324
  const sectionDefs = /* @__PURE__ */ new Map();
323
325
  const sectionItems = /* @__PURE__ */ new Map();
326
+ const directItems = [];
324
327
  for (const contrib of contributions) {
325
328
  if (contrib.title !== void 0) title = contrib.title;
326
329
  if (contrib.description !== void 0) description = contrib.description;
327
330
  if (contrib.columns !== void 0) columns = contrib.columns;
331
+ if (contrib.rowHeight !== void 0) rowHeight = contrib.rowHeight;
332
+ if (contrib.gap !== void 0) gap = contrib.gap;
328
333
  if (contrib.realtime !== void 0) realtime = contrib.realtime;
329
334
  if (contrib.actions) allActions.push(...contrib.actions);
330
335
  if (contrib.sections) for (const sec of contrib.sections) {
336
+ const { id: _id, ...sectionMeta } = sec;
331
337
  const existingIdx = sectionOrder.indexOf(sec.id);
332
338
  if (existingIdx !== -1) sectionOrder.splice(existingIdx, 1);
333
339
  sectionOrder.push(sec.id);
334
340
  sectionDefs.set(sec.id, {
335
- label: sec.label ?? sectionDefs.get(sec.id)?.label,
336
- layout: sec.layout ?? sectionDefs.get(sec.id)?.layout,
337
- columns: sec.columns ?? sectionDefs.get(sec.id)?.columns
341
+ ...sectionDefs.get(sec.id) ?? {},
342
+ ...sectionMeta
338
343
  });
339
344
  }
340
345
  if (contrib.items) for (const item of contrib.items) {
341
- const sid = item.sectionId;
346
+ const record = item;
347
+ const sid = record.sectionId;
348
+ if (!sid) {
349
+ directItems.push(item);
350
+ continue;
351
+ }
342
352
  if (!sectionItems.has(sid)) sectionItems.set(sid, []);
343
353
  const items = sectionItems.get(sid) ?? [];
344
- if (item.position === "start") items.unshift(item);
354
+ if (record.position === "start") items.unshift(item);
345
355
  else items.push(item);
346
356
  sectionItems.set(sid, items);
347
357
  if (!sectionDefs.has(sid)) {
@@ -350,15 +360,15 @@ function mergeDashboardContributions(contributions) {
350
360
  }
351
361
  }
352
362
  }
353
- const dashboardItems = [];
363
+ const dashboardItems = [...directItems];
354
364
  for (const sectionId of sectionOrder) {
355
365
  const def = sectionDefs.get(sectionId);
356
366
  const items = sectionItems.get(sectionId) ?? [];
357
367
  if (items.length > 0 || def?.label) dashboardItems.push({
358
368
  type: "section",
359
- label: def?.label,
369
+ id: sectionId,
370
+ ...def,
360
371
  layout: def?.layout ?? "grid",
361
- columns: def?.columns,
362
372
  items: items.map(({ sectionId: _sid, position: _pos, ...rest }) => rest)
363
373
  });
364
374
  }
@@ -366,6 +376,8 @@ function mergeDashboardContributions(contributions) {
366
376
  title,
367
377
  description,
368
378
  columns,
379
+ rowHeight,
380
+ gap,
369
381
  realtime,
370
382
  actions: allActions.length > 0 ? allActions : void 0,
371
383
  items: dashboardItems.length > 0 ? dashboardItems : void 0
@@ -425,17 +437,20 @@ async function processDashboardItems(items, accessibleCollections, accessCtx) {
425
437
  }
426
438
  if (item.type === "tabs") {
427
439
  const rawTabs = rec.tabs || [];
428
- const tabs = await Promise.all(rawTabs.map(async (tab) => {
440
+ const visibleTabs = (await Promise.all(rawTabs.map(async (tab) => {
429
441
  const filtered = await processDashboardItems(tab.items || [], accessibleCollections, accessCtx);
430
442
  return {
431
443
  ...tab,
432
444
  items: filtered
433
445
  };
434
- }));
435
- result.push({
436
- ...item,
437
- tabs
438
- });
446
+ }))).filter((tab) => tab.items.length > 0);
447
+ if (visibleTabs.length > 0) {
448
+ const { variant: _variant, ...serializableTabs } = item;
449
+ result.push({
450
+ ...serializableTabs,
451
+ tabs: visibleTabs
452
+ });
453
+ }
439
454
  continue;
440
455
  }
441
456
  const widget = rec;
@@ -453,10 +468,13 @@ async function processDashboardItems(items, accessibleCollections, accessCtx) {
453
468
  if (action.action?.type === "create") return accessibleCollections.has(action.action.collection);
454
469
  return true;
455
470
  });
456
- const { loader: loader$1, access: access$1, ...serializable$1 } = widget;
471
+ const { loader: loader$1, access: access$1, filterFn: filterFn$1, ...serializable$1 } = widget;
472
+ if (loader$1) serializable$1.hasLoader = true;
473
+ if (serializable$1.label && !serializable$1.title) serializable$1.title = serializable$1.label;
457
474
  result.push({
458
475
  ...serializable$1,
459
- actions
476
+ actions,
477
+ quickActions: serializable$1.quickActions ?? actions
460
478
  });
461
479
  continue;
462
480
  }
@@ -1,7 +1,7 @@
1
1
  import { ServerActionDefinition, ServerActionResult } from "../../../augmentation/actions.mjs";
2
2
  import "../../../augmentation.mjs";
3
3
  import { App } from "./route-helpers.mjs";
4
- import * as questpie101 from "questpie";
4
+ import * as questpie117 from "questpie";
5
5
 
6
6
  //#region src/server/modules/admin/routes/execute-action.d.ts
7
7
 
@@ -56,37 +56,37 @@ declare function executeAction(app: App, request: ExecuteActionRequest, session?
56
56
  * });
57
57
  * ```
58
58
  */
59
- declare const executeActionFn: questpie101.JsonRouteDefinition<{
59
+ declare const executeActionFn: questpie117.JsonRouteDefinition<{
60
60
  collection: string;
61
61
  actionId: string;
62
62
  itemId?: string | undefined;
63
63
  itemIds?: string[] | undefined;
64
64
  data?: Record<string, unknown> | undefined;
65
65
  locale?: string | undefined;
66
- }, any, questpie101.JsonRouteParams>;
66
+ }, any, questpie117.JsonRouteParams>;
67
67
  /**
68
68
  * Get actions configuration for a collection.
69
69
  * Returns action definitions without handlers for client rendering.
70
70
  */
71
- declare const getActionsConfigFn: questpie101.JsonRouteDefinition<{
71
+ declare const getActionsConfigFn: questpie117.JsonRouteDefinition<{
72
72
  collection: string;
73
- }, any, questpie101.JsonRouteParams>;
73
+ }, any, questpie117.JsonRouteParams>;
74
74
  /**
75
75
  * QUESTPIE functions for action execution.
76
76
  * These are registered on the `adminModule`.
77
77
  */
78
78
  declare const actionFunctions: {
79
- executeAction: questpie101.JsonRouteDefinition<{
79
+ executeAction: questpie117.JsonRouteDefinition<{
80
80
  collection: string;
81
81
  actionId: string;
82
82
  itemId?: string | undefined;
83
83
  itemIds?: string[] | undefined;
84
84
  data?: Record<string, unknown> | undefined;
85
85
  locale?: string | undefined;
86
- }, any, questpie101.JsonRouteParams>;
87
- getActionsConfig: questpie101.JsonRouteDefinition<{
86
+ }, any, questpie117.JsonRouteParams>;
87
+ getActionsConfig: questpie117.JsonRouteDefinition<{
88
88
  collection: string;
89
- }, any, questpie101.JsonRouteParams>;
89
+ }, any, questpie117.JsonRouteParams>;
90
90
  };
91
91
  //#endregion
92
92
  export { ExecuteActionRequest, ExecuteActionResponse, actionFunctions, executeAction, executeActionFn, getActionsConfig, getActionsConfigFn };
@@ -1,4 +1,5 @@
1
1
  import { getApp, getAppState, getSession } from "./route-helpers.mjs";
2
+ import { translateAdminMessage } from "./i18n-helpers.mjs";
2
3
  import { z } from "zod";
3
4
  import { route } from "questpie";
4
5
 
@@ -43,6 +44,10 @@ function getActionsConfig(app, collectionSlug) {
43
44
  };
44
45
  const customWithoutHandlers = (actionsConfig.custom || []).map((action) => {
45
46
  const { handler, ...rest } = action;
47
+ if (rest.form?.fields) rest.form = {
48
+ ...rest.form,
49
+ fields: serializeActionFormFields(rest.form.fields)
50
+ };
46
51
  return rest;
47
52
  });
48
53
  return {
@@ -58,6 +63,35 @@ function getActionsConfig(app, collectionSlug) {
58
63
  custom: customWithoutHandlers
59
64
  };
60
65
  }
66
+ function serializeActionFormFields(fields) {
67
+ const result = {};
68
+ for (const [fieldName, field$1] of Object.entries(fields)) {
69
+ if (!field$1 || typeof field$1 !== "object") {
70
+ result[fieldName] = field$1;
71
+ continue;
72
+ }
73
+ if (typeof field$1.getMetadata === "function") {
74
+ const metadata = field$1.getMetadata();
75
+ const state = field$1._state ?? {};
76
+ const adminMeta = (metadata.meta && typeof metadata.meta === "object" ? metadata.meta : void 0) ?? (state.admin && typeof state.admin === "object" ? state.admin : void 0) ?? (state.extensions?.admin && typeof state.extensions.admin === "object" ? state.extensions.admin : void 0);
77
+ const options = {};
78
+ if (metadata.options) options.options = metadata.options;
79
+ if (metadata.multiple !== void 0) options.multiple = metadata.multiple;
80
+ if (adminMeta) Object.assign(options, adminMeta);
81
+ result[fieldName] = {
82
+ type: metadata.type ?? field$1.getType?.() ?? "text",
83
+ label: metadata.label,
84
+ description: metadata.description,
85
+ required: metadata.required ?? false,
86
+ default: state.defaultValue,
87
+ options
88
+ };
89
+ continue;
90
+ }
91
+ result[fieldName] = field$1;
92
+ }
93
+ return result;
94
+ }
61
95
  /**
62
96
  * Execute a collection action.
63
97
  * Handles both built-in actions and custom actions.
@@ -65,9 +99,10 @@ function getActionsConfig(app, collectionSlug) {
65
99
  async function executeAction(app, request, session) {
66
100
  const { collection: collectionSlug, actionId, itemId, itemIds, data, locale } = request;
67
101
  const collection$1 = getAppState(app).collections?.[collectionSlug];
102
+ const t = (key, params) => translateAdminMessage(locale, key, params);
68
103
  if (!collection$1) return {
69
104
  success: false,
70
- error: `Collection "${collectionSlug}" not found`
105
+ error: t("action.collectionNotFound", { collection: collectionSlug })
71
106
  };
72
107
  const actionsConfig = (collection$1.state || collection$1).adminActions;
73
108
  if ((actionsConfig?.builtin || [
@@ -91,10 +126,13 @@ async function executeAction(app, request, session) {
91
126
  const customAction = actionsConfig?.custom?.find((a) => a.id === actionId);
92
127
  if (!customAction) return {
93
128
  success: false,
94
- error: `Action "${actionId}" not found on collection "${collectionSlug}"`
129
+ error: t("action.notFound", {
130
+ action: actionId,
131
+ collection: collectionSlug
132
+ })
95
133
  };
96
134
  if (customAction.form) {
97
- const validationError = validateActionFormData(customAction.form.fields, data || {});
135
+ const validationError = validateActionFormData(customAction.form.fields, data || {}, t);
98
136
  if (validationError) return {
99
137
  success: false,
100
138
  result: {
@@ -127,7 +165,7 @@ async function executeAction(app, request, session) {
127
165
  success: false,
128
166
  result: {
129
167
  type: "error",
130
- toast: { message: error instanceof Error ? error.message : "Action execution failed" }
168
+ toast: { message: error instanceof Error ? error.message : t("action.executionFailed") }
131
169
  }
132
170
  };
133
171
  }
@@ -136,7 +174,8 @@ async function executeAction(app, request, session) {
136
174
  * Execute a built-in action.
137
175
  */
138
176
  async function executeBuiltinAction(app, params) {
139
- const { collectionSlug, actionId, itemId, itemIds, data } = params;
177
+ const { collectionSlug, actionId, itemId, itemIds, data, locale } = params;
178
+ const t = (key, messageParams) => translateAdminMessage(locale, key, messageParams);
140
179
  const appRec = app;
141
180
  const collectionCrud = appRec.api?.collections?.[collectionSlug];
142
181
  const crudContext = {
@@ -152,7 +191,7 @@ async function executeBuiltinAction(app, params) {
152
191
  success: true,
153
192
  result: {
154
193
  type: "success",
155
- toast: { message: "Item created successfully" },
194
+ toast: { message: t("action.itemCreated") },
156
195
  effects: {
157
196
  invalidate: [collectionSlug],
158
197
  redirect: `/admin/collections/${collectionSlug}/${result.id}`
@@ -165,7 +204,7 @@ async function executeBuiltinAction(app, params) {
165
204
  success: false,
166
205
  result: {
167
206
  type: "error",
168
- toast: { message: "Item ID is required for save action" }
207
+ toast: { message: t("action.itemIdRequired.save") }
169
208
  }
170
209
  };
171
210
  await appRec.update(collectionSlug, itemId, data || {});
@@ -173,7 +212,7 @@ async function executeBuiltinAction(app, params) {
173
212
  success: true,
174
213
  result: {
175
214
  type: "success",
176
- toast: { message: "Item saved successfully" },
215
+ toast: { message: t("action.itemSaved") },
177
216
  effects: { invalidate: [collectionSlug] }
178
217
  }
179
218
  };
@@ -182,7 +221,7 @@ async function executeBuiltinAction(app, params) {
182
221
  success: false,
183
222
  result: {
184
223
  type: "error",
185
- toast: { message: "Item ID is required for delete action" }
224
+ toast: { message: t("action.itemIdRequired.delete") }
186
225
  }
187
226
  };
188
227
  await appRec.delete(collectionSlug, itemId);
@@ -190,7 +229,7 @@ async function executeBuiltinAction(app, params) {
190
229
  success: true,
191
230
  result: {
192
231
  type: "success",
193
- toast: { message: "Item deleted successfully" },
232
+ toast: { message: t("action.itemDeleted") },
194
233
  effects: {
195
234
  invalidate: [collectionSlug],
196
235
  redirect: `/admin/collections/${collectionSlug}`
@@ -202,7 +241,7 @@ async function executeBuiltinAction(app, params) {
202
241
  success: false,
203
242
  result: {
204
243
  type: "error",
205
- toast: { message: "Item IDs are required for bulk delete action" }
244
+ toast: { message: t("action.itemIdsRequired.bulkDelete") }
206
245
  }
207
246
  };
208
247
  await Promise.all(itemIds.map((id) => appRec.delete(collectionSlug, id)));
@@ -210,7 +249,7 @@ async function executeBuiltinAction(app, params) {
210
249
  success: true,
211
250
  result: {
212
251
  type: "success",
213
- toast: { message: `${itemIds.length} items deleted successfully` },
252
+ toast: { message: t("action.itemsDeleted", { count: itemIds.length }) },
214
253
  effects: { invalidate: [collectionSlug] }
215
254
  }
216
255
  };
@@ -219,7 +258,7 @@ async function executeBuiltinAction(app, params) {
219
258
  success: false,
220
259
  result: {
221
260
  type: "error",
222
- toast: { message: "Item ID is required for restore action" }
261
+ toast: { message: t("action.itemIdRequired.restore") }
223
262
  }
224
263
  };
225
264
  if (typeof appRec.restore === "function") await appRec.restore(collectionSlug, itemId);
@@ -228,14 +267,14 @@ async function executeBuiltinAction(app, params) {
228
267
  success: false,
229
268
  result: {
230
269
  type: "error",
231
- toast: { message: "Restore is not supported for this collection" }
270
+ toast: { message: t("action.restoreUnsupported") }
232
271
  }
233
272
  };
234
273
  return {
235
274
  success: true,
236
275
  result: {
237
276
  type: "success",
238
- toast: { message: "Item restored successfully" },
277
+ toast: { message: t("action.itemRestored") },
239
278
  effects: {
240
279
  invalidate: [collectionSlug],
241
280
  redirect: `/admin/collections/${collectionSlug}/${itemId}`
@@ -247,7 +286,7 @@ async function executeBuiltinAction(app, params) {
247
286
  success: false,
248
287
  result: {
249
288
  type: "error",
250
- toast: { message: "Item IDs are required for bulk restore action" }
289
+ toast: { message: t("action.itemIdsRequired.bulkRestore") }
251
290
  }
252
291
  };
253
292
  if (typeof appRec.restore === "function") await Promise.all(itemIds.map((id) => appRec.restore(collectionSlug, id)));
@@ -263,7 +302,7 @@ async function executeBuiltinAction(app, params) {
263
302
  success: true,
264
303
  result: {
265
304
  type: "success",
266
- toast: { message: `${itemIds.length} items restored successfully` },
305
+ toast: { message: t("action.itemsRestored", { count: itemIds.length }) },
267
306
  effects: { invalidate: [collectionSlug] }
268
307
  }
269
308
  };
@@ -272,7 +311,7 @@ async function executeBuiltinAction(app, params) {
272
311
  success: false,
273
312
  result: {
274
313
  type: "error",
275
- toast: { message: "Item ID is required for duplicate action" }
314
+ toast: { message: t("action.itemIdRequired.duplicate") }
276
315
  }
277
316
  };
278
317
  const original = await appRec.findById(collectionSlug, itemId);
@@ -280,7 +319,7 @@ async function executeBuiltinAction(app, params) {
280
319
  success: false,
281
320
  result: {
282
321
  type: "error",
283
- toast: { message: "Item not found" }
322
+ toast: { message: t("action.itemNotFound") }
284
323
  }
285
324
  };
286
325
  const { id, createdAt, updatedAt, ...duplicateData } = original;
@@ -289,7 +328,7 @@ async function executeBuiltinAction(app, params) {
289
328
  success: true,
290
329
  result: {
291
330
  type: "success",
292
- toast: { message: "Item duplicated successfully" },
331
+ toast: { message: t("action.itemDuplicated") },
293
332
  effects: {
294
333
  invalidate: [collectionSlug],
295
334
  redirect: `/admin/collections/${collectionSlug}/${duplicated.id}`
@@ -302,7 +341,7 @@ async function executeBuiltinAction(app, params) {
302
341
  success: false,
303
342
  result: {
304
343
  type: "error",
305
- toast: { message: "Item ID is required for transition action" }
344
+ toast: { message: t("action.itemIdRequired.transition") }
306
345
  }
307
346
  };
308
347
  const stage = data?.stage;
@@ -310,7 +349,7 @@ async function executeBuiltinAction(app, params) {
310
349
  success: false,
311
350
  result: {
312
351
  type: "error",
313
- toast: { message: "Target stage is required for transition action" }
352
+ toast: { message: t("action.targetStageRequired") }
314
353
  }
315
354
  };
316
355
  if (collectionCrud?.transitionStage) {
@@ -325,14 +364,14 @@ async function executeBuiltinAction(app, params) {
325
364
  success: false,
326
365
  result: {
327
366
  type: "error",
328
- toast: { message: "Workflow transitions are not supported for this collection" }
367
+ toast: { message: t("action.workflowUnsupported") }
329
368
  }
330
369
  };
331
370
  return {
332
371
  success: true,
333
372
  result: {
334
373
  type: "success",
335
- toast: { message: `Transitioned to "${stage}" successfully` },
374
+ toast: { message: t("workflow.transitionSuccess", { stage }) },
336
375
  effects: { invalidate: [collectionSlug] }
337
376
  }
338
377
  };
@@ -341,7 +380,7 @@ async function executeBuiltinAction(app, params) {
341
380
  success: false,
342
381
  result: {
343
382
  type: "error",
344
- toast: { message: `Unknown built-in action: ${actionId}` }
383
+ toast: { message: t("action.unknownBuiltin", { action: actionId }) }
345
384
  }
346
385
  };
347
386
  }
@@ -351,7 +390,7 @@ async function executeBuiltinAction(app, params) {
351
390
  success: false,
352
391
  result: {
353
392
  type: "error",
354
- toast: { message: error instanceof Error ? error.message : "Action execution failed" }
393
+ toast: { message: error instanceof Error ? error.message : t("action.executionFailed") }
355
394
  }
356
395
  };
357
396
  }
@@ -373,8 +412,8 @@ function isFieldRequired(field$1) {
373
412
  * Validate form data against action form fields.
374
413
  * Returns error message if validation fails, null if valid.
375
414
  */
376
- function validateActionFormData(fields, data) {
377
- for (const [fieldName, fieldConfig] of Object.entries(fields)) if (isFieldRequired(fieldConfig) && !data[fieldName]) return `Field "${fieldName}" is required`;
415
+ function validateActionFormData(fields, data, t) {
416
+ for (const [fieldName, fieldConfig] of Object.entries(fields)) if (isFieldRequired(fieldConfig) && !data[fieldName]) return t("action.fieldRequired", { field: fieldName });
378
417
  return null;
379
418
  }
380
419
  const executeActionRequestSchema = z.object({
@@ -0,0 +1,34 @@
1
+ import { getAdminMessagesForLocale } from "../../../i18n/index.mjs";
2
+
3
+ //#region src/server/modules/admin/routes/i18n-helpers.ts
4
+ function getPluralCount(params) {
5
+ if (!params) return 1;
6
+ for (const key of [
7
+ "count",
8
+ "total",
9
+ "length"
10
+ ]) if (typeof params[key] === "number") return params[key];
11
+ return 1;
12
+ }
13
+ function selectMessage(value, locale, params) {
14
+ if (typeof value === "string") return value;
15
+ const count = getPluralCount(params);
16
+ try {
17
+ return value[new Intl.PluralRules(locale).select(count)] ?? value.other;
18
+ } catch {
19
+ return count === 1 ? value.one : value.other;
20
+ }
21
+ }
22
+ function interpolate(template, params) {
23
+ if (!params) return template;
24
+ return template.replace(/\{\{\s*(\w+)\s*\}\}/g, (_, key) => params[key] === void 0 ? `{{${key}}}` : String(params[key]));
25
+ }
26
+ function translateAdminMessage(locale, key, params) {
27
+ const resolvedLocale = locale ?? "en";
28
+ const message = getAdminMessagesForLocale(resolvedLocale)[key];
29
+ if (message === void 0) return key;
30
+ return interpolate(selectMessage(message, resolvedLocale, params), params);
31
+ }
32
+
33
+ //#endregion
34
+ export { translateAdminMessage };
@@ -1,4 +1,4 @@
1
- import * as questpie460 from "questpie";
1
+ import * as questpie462 from "questpie";
2
2
 
3
3
  //#region src/server/modules/admin/routes/locales.d.ts
4
4
 
@@ -12,7 +12,7 @@ import * as questpie460 from "questpie";
12
12
  * Bundle of locale-related functions.
13
13
  */
14
14
  declare const localeFunctions: {
15
- readonly getContentLocales: questpie460.JsonRouteDefinition<Record<string, never> | undefined, any, questpie460.JsonRouteParams>;
15
+ readonly getContentLocales: questpie462.JsonRouteDefinition<Record<string, never> | undefined, any, questpie462.JsonRouteParams>;
16
16
  };
17
17
  //#endregion
18
18
  export { localeFunctions };