@questpie/admin 3.0.2 → 3.0.4

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 (249) 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-fields-renderer.mjs +64 -28
  16. package/dist/client/components/blocks/block-insert-button.mjs +4 -4
  17. package/dist/client/components/blocks/block-item.mjs +2 -2
  18. package/dist/client/components/blocks/block-library-sidebar.mjs +2 -2
  19. package/dist/client/components/component-renderer.mjs +1 -1
  20. package/dist/client/components/fields/array-field.mjs +14 -14
  21. package/dist/client/components/fields/asset-preview-field.mjs +1 -1
  22. package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
  23. package/dist/client/components/fields/json-field.mjs +2 -2
  24. package/dist/client/components/fields/object-array-field.mjs +22 -22
  25. package/dist/client/components/fields/object-field.mjs +5 -5
  26. package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
  27. package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
  28. package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
  29. package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
  30. package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
  31. package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
  32. package/dist/client/components/fields/relation-picker.mjs +7 -6
  33. package/dist/client/components/fields/relation-select.mjs +71 -47
  34. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
  35. package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
  36. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
  37. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
  38. package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
  39. package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
  40. package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
  41. package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
  42. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
  43. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
  44. package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
  45. package/dist/client/components/fields/upload-field.mjs +45 -49
  46. package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
  47. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
  48. package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
  49. package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
  50. package/dist/client/components/history-sidebar.mjs +850 -340
  51. package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
  52. package/dist/client/components/locale-switcher.mjs +8 -8
  53. package/dist/client/components/media/media-grid.mjs +12 -9
  54. package/dist/client/components/media/media-picker-dialog.mjs +242 -230
  55. package/dist/client/components/preview/live-preview-mode.mjs +1 -1
  56. package/dist/client/components/primitives/asset-preview.mjs +37 -22
  57. package/dist/client/components/primitives/date-input.mjs +212 -249
  58. package/dist/client/components/primitives/dropzone.mjs +192 -159
  59. package/dist/client/components/primitives/field-select-control.mjs +93 -0
  60. package/dist/client/components/primitives/select-multi.mjs +251 -230
  61. package/dist/client/components/primitives/select-single.mjs +345 -290
  62. package/dist/client/components/primitives/time-input.mjs +2 -2
  63. package/dist/client/components/sheets/resource-sheet.mjs +2 -0
  64. package/dist/client/components/ui/accordion.mjs +4 -4
  65. package/dist/client/components/ui/alert.mjs +3 -3
  66. package/dist/client/components/ui/badge.mjs +4 -4
  67. package/dist/client/components/ui/button.mjs +47 -37
  68. package/dist/client/components/ui/card.mjs +2 -2
  69. package/dist/client/components/ui/checkbox.mjs +1 -1
  70. package/dist/client/components/ui/command.mjs +5 -5
  71. package/dist/client/components/ui/dialog.mjs +3 -3
  72. package/dist/client/components/ui/drawer.mjs +1 -1
  73. package/dist/client/components/ui/dropdown-menu.mjs +157 -15
  74. package/dist/client/components/ui/empty-state.mjs +88 -59
  75. package/dist/client/components/ui/field.mjs +2 -2
  76. package/dist/client/components/ui/input-group.mjs +3 -3
  77. package/dist/client/components/ui/input.mjs +1 -1
  78. package/dist/client/components/ui/kbd.mjs +1 -1
  79. package/dist/client/components/ui/label.mjs +1 -1
  80. package/dist/client/components/ui/popover.mjs +19 -11
  81. package/dist/client/components/ui/scroll-fade.mjs +170 -0
  82. package/dist/client/components/ui/search-input.mjs +1 -1
  83. package/dist/client/components/ui/select.mjs +129 -27
  84. package/dist/client/components/ui/sheet.mjs +54 -34
  85. package/dist/client/components/ui/sidebar.mjs +15 -14
  86. package/dist/client/components/ui/skeleton.mjs +28 -12
  87. package/dist/client/components/ui/switch.mjs +2 -2
  88. package/dist/client/components/ui/table.mjs +82 -74
  89. package/dist/client/components/ui/tabs.mjs +26 -31
  90. package/dist/client/components/ui/textarea.mjs +1 -1
  91. package/dist/client/components/ui/tooltip.mjs +1 -1
  92. package/dist/client/components/widgets/chart-widget.mjs +134 -96
  93. package/dist/client/components/widgets/progress-widget.mjs +59 -34
  94. package/dist/client/components/widgets/quick-actions-widget.mjs +184 -113
  95. package/dist/client/components/widgets/recent-items-widget.mjs +144 -102
  96. package/dist/client/components/widgets/stats-widget.mjs +91 -72
  97. package/dist/client/components/widgets/table-widget.mjs +159 -246
  98. package/dist/client/components/widgets/timeline-widget.mjs +66 -43
  99. package/dist/client/components/widgets/value-widget.mjs +261 -152
  100. package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
  101. package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
  102. package/dist/client/contexts/focus-context.d.mts +2 -2
  103. package/dist/client/hooks/use-action.mjs +63 -55
  104. package/dist/client/hooks/use-audit-history.mjs +1 -65
  105. package/dist/client/hooks/use-collection-validation.mjs +36 -23
  106. package/dist/client/hooks/use-collection.mjs +96 -1
  107. package/dist/client/hooks/use-saved-views.mjs +70 -49
  108. package/dist/client/hooks/use-server-actions.mjs +59 -40
  109. package/dist/client/hooks/use-server-validation.mjs +156 -41
  110. package/dist/client/hooks/use-server-widget-data.mjs +1 -1
  111. package/dist/client/hooks/use-setup-status.d.mts +3 -3
  112. package/dist/client/hooks/use-setup-status.mjs +2 -2
  113. package/dist/client/hooks/use-transition-stage.mjs +2 -10
  114. package/dist/client/hooks/use-validation-error-map.mjs +31 -13
  115. package/dist/client/hooks/use-view-state.mjs +238 -174
  116. package/dist/client/i18n/date-locale.mjs +33 -0
  117. package/dist/client/i18n/hooks.mjs +17 -1
  118. package/dist/client/lib/utils.mjs +3 -2
  119. package/dist/client/preview/block-scope-context.d.mts +2 -2
  120. package/dist/client/preview/preview-banner.d.mts +2 -2
  121. package/dist/client/preview/preview-field.d.mts +4 -4
  122. package/dist/client/preview/preview-field.mjs +2 -2
  123. package/dist/client/runtime/provider.mjs +8 -1
  124. package/dist/client/runtime/translations-provider.mjs +1 -1
  125. package/dist/client/scope/picker.d.mts +2 -2
  126. package/dist/client/scope/provider.d.mts +2 -2
  127. package/dist/client/styles/base.css +1022 -0
  128. package/dist/client/styles/index.css +3 -589
  129. package/dist/client/utils/auto-expand-fields.mjs +4 -2
  130. package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
  131. package/dist/client/utils/use-lazy-component.mjs +80 -0
  132. package/dist/client/views/auth/auth-layout.d.mts +18 -11
  133. package/dist/client/views/auth/auth-layout.mjs +291 -80
  134. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  135. package/dist/client/views/auth/forgot-password-form.mjs +2 -2
  136. package/dist/client/views/auth/login-form.d.mts +2 -2
  137. package/dist/client/views/auth/login-form.mjs +1 -1
  138. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  139. package/dist/client/views/auth/reset-password-form.mjs +2 -2
  140. package/dist/client/views/auth/setup-form.d.mts +2 -2
  141. package/dist/client/views/collection/auto-form-fields.mjs +11 -9
  142. package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
  143. package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
  144. package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
  145. package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
  146. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
  147. package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
  148. package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
  149. package/dist/client/views/collection/columns/build-columns.mjs +29 -9
  150. package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
  151. package/dist/client/views/collection/field-renderer.mjs +50 -89
  152. package/dist/client/views/collection/form-view.mjs +237 -227
  153. package/dist/client/views/collection/table-view.mjs +1162 -229
  154. package/dist/client/views/collection/view-skeletons.mjs +222 -79
  155. package/dist/client/views/common/global-search.mjs +29 -18
  156. package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
  157. package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
  158. package/dist/client/views/dashboard/widget-card.mjs +23 -14
  159. package/dist/client/views/globals/global-form-view.mjs +634 -589
  160. package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
  161. package/dist/client/views/layout/admin-layout.d.mts +3 -6
  162. package/dist/client/views/layout/admin-layout.mjs +149 -172
  163. package/dist/client/views/layout/admin-router.mjs +747 -544
  164. package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
  165. package/dist/client/views/layout/admin-sidebar.mjs +751 -591
  166. package/dist/client/views/layout/admin-theme.d.mts +10 -0
  167. package/dist/client/views/layout/admin-theme.mjs +84 -0
  168. package/dist/client/views/layout/admin-view-layout.mjs +161 -0
  169. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  170. package/dist/client/views/pages/accept-invite-page.mjs +49 -26
  171. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  172. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  173. package/dist/client/views/pages/forgot-password-page.mjs +2 -19
  174. package/dist/client/views/pages/invite-page.d.mts +2 -2
  175. package/dist/client/views/pages/invite-page.mjs +2 -19
  176. package/dist/client/views/pages/login-page.d.mts +3 -3
  177. package/dist/client/views/pages/login-page.mjs +4 -21
  178. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  179. package/dist/client/views/pages/reset-password-page.mjs +3 -20
  180. package/dist/client/views/pages/setup-page.d.mts +2 -2
  181. package/dist/client/views/pages/setup-page.mjs +3 -20
  182. package/dist/client.d.mts +6 -2
  183. package/dist/client.mjs +2 -1
  184. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  185. package/dist/index.d.mts +6 -2
  186. package/dist/index.mjs +2 -1
  187. package/dist/server/augmentation/dashboard.d.mts +67 -3
  188. package/dist/server/augmentation/form-layout.d.mts +21 -0
  189. package/dist/server/augmentation/index.d.mts +1 -1
  190. package/dist/server/codegen/admin-client-template.mjs +4 -0
  191. package/dist/server/fields/blocks.d.mts +1 -1
  192. package/dist/server/fields/blocks.mjs +12 -0
  193. package/dist/server/fields/rich-text.d.mts +1 -1
  194. package/dist/server/fields/rich-text.mjs +8 -0
  195. package/dist/server/i18n/index.mjs +17 -1
  196. package/dist/server/i18n/messages/cs.mjs +23 -0
  197. package/dist/server/i18n/messages/de.mjs +23 -0
  198. package/dist/server/i18n/messages/en.mjs +64 -1
  199. package/dist/server/i18n/messages/es.mjs +23 -0
  200. package/dist/server/i18n/messages/fr.mjs +23 -0
  201. package/dist/server/i18n/messages/pl.mjs +23 -0
  202. package/dist/server/i18n/messages/pt.mjs +23 -0
  203. package/dist/server/i18n/messages/sk.mjs +83 -1
  204. package/dist/server/modules/admin/block/introspection.mjs +4 -1
  205. package/dist/server/modules/admin/block/prefetch.mjs +12 -2
  206. package/dist/server/modules/admin/collections/account.d.mts +50 -50
  207. package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
  208. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  209. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  210. package/dist/server/modules/admin/collections/apikey.d.mts +64 -64
  211. package/dist/server/modules/admin/collections/assets.d.mts +20 -20
  212. package/dist/server/modules/admin/collections/assets.mjs +0 -1
  213. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  214. package/dist/server/modules/admin/collections/user.d.mts +40 -28
  215. package/dist/server/modules/admin/collections/user.mjs +40 -9
  216. package/dist/server/modules/admin/collections/verification.d.mts +36 -36
  217. package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
  218. package/dist/server/modules/admin/factories.mjs +7 -18
  219. package/dist/server/modules/admin/index.d.mts +1 -1
  220. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  221. package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
  222. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  223. package/dist/server/modules/admin/routes/execute-action.mjs +33 -0
  224. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  225. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  226. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  227. package/dist/server/modules/admin/routes/setup.d.mts +10 -10
  228. package/dist/server/modules/admin/routes/setup.mjs +7 -7
  229. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  230. package/dist/server/modules/admin/routes/translations.mjs +5 -1
  231. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  232. package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
  233. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +25 -25
  234. package/dist/server/modules/audit/.generated/module.d.mts +7 -7
  235. package/dist/server/modules/audit/.generated/module.mjs +1 -1
  236. package/dist/server/modules/audit/collections/audit-log.d.mts +39 -39
  237. package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
  238. package/dist/server/modules/audit/config/app.mjs +99 -42
  239. package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
  240. package/dist/server/plugin.mjs +4 -2
  241. package/dist/server/proxy-factories.d.mts +4 -3
  242. package/dist/server/proxy-factories.mjs +34 -8
  243. package/dist/shared/types/saved-views.types.d.mts +2 -0
  244. package/package.json +6 -4
  245. package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
  246. package/dist/client/components/ui/spinner.mjs +0 -52
  247. package/dist/client/components/ui/toolbar.mjs +0 -136
  248. package/dist/client/contexts/breadcrumb-context.mjs +0 -60
  249. package/dist/client/views/layout/admin-topbar.mjs +0 -236
@@ -1,97 +1,57 @@
1
1
  import { useResolveText } from "../../i18n/hooks.mjs";
2
2
  import { cn, formatLabel } from "../../lib/utils.mjs";
3
- import { DefaultCell } from "../../views/collection/cells/primitive-cells.mjs";
3
+ import { useCollectionFields } from "../../hooks/use-collection-fields.mjs";
4
+ import { useCollectionMeta } from "../../hooks/use-collection-meta.mjs";
4
5
  import { useCollectionList } from "../../hooks/use-collection.mjs";
6
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../ui/table.mjs";
5
7
  import { WidgetCard } from "../../views/dashboard/widget-card.mjs";
8
+ import { useServerWidgetData } from "../../hooks/use-server-widget-data.mjs";
9
+ import { WidgetEmptyState } from "./widget-empty-state.mjs";
6
10
  import { TableWidgetSkeleton } from "./widget-skeletons.mjs";
7
- import { c } from "react/compiler-runtime";
11
+ import { autoExpandFields, hasFieldsToExpand } from "../../utils/auto-expand-fields.mjs";
12
+ import { buildColumns } from "../../views/collection/columns/build-columns.mjs";
13
+ import * as React from "react";
8
14
  import { jsx, jsxs } from "react/jsx-runtime";
15
+ import { flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table";
9
16
 
10
17
  //#region src/client/components/widgets/table-widget.tsx
11
18
  /**
12
- * Field types that need fieldDef passed to their cell component
13
- */
14
- const FIELD_TYPES_NEEDING_FIELD_DEF = new Set([
15
- "object",
16
- "array",
17
- "relation",
18
- "reverseRelation"
19
- ]);
20
- /**
21
- * Normalize column config - converts string to object format
19
+ * Table Widget
20
+ *
21
+ * Displays a mini table with collection data.
22
+ * Automatically uses field definitions from collection config for:
23
+ * - Column labels (from field.label)
24
+ * - Cell rendering (from field.cell)
25
+ *
26
+ * Columns can be simple field keys or objects with overrides.
22
27
  */
23
- function normalizeColumn(column) {
24
- if (typeof column === "string") return { key: column };
25
- return column;
28
+ function normalizeWidgetColumn(column) {
29
+ return typeof column === "string" ? { key: column } : column;
26
30
  }
27
- /**
28
- * Get column label from field definition or column config
29
- */
30
- function getColumnLabel(column, fieldDef) {
31
- if (column.label) return column.label;
32
- const fieldOptions = fieldDef?.["~options"];
33
- if (fieldOptions?.label) return fieldOptions.label;
34
- return formatLabel(column.key);
31
+ function toListColumnConfig(column) {
32
+ const normalized = normalizeWidgetColumn(column);
33
+ const CustomCell = normalized.render ? function TableWidgetCustomCell({ value, row }) {
34
+ return normalized.render?.(value, row?.original ?? row);
35
+ } : void 0;
36
+ return {
37
+ field: normalized.key,
38
+ header: normalized.label,
39
+ width: normalized.width,
40
+ align: normalized.align,
41
+ cell: CustomCell
42
+ };
35
43
  }
36
- /**
37
- * Resolve cell component from field definition
38
- */
39
- function resolveCellComponent(fieldDef) {
40
- if (fieldDef?.cell) return fieldDef.cell;
41
- return DefaultCell;
44
+ function getColumnSizeStyle(column) {
45
+ const size = typeof column?.getSize === "function" ? column.getSize() : 120;
46
+ return {
47
+ width: size,
48
+ minWidth: size,
49
+ maxWidth: size
50
+ };
42
51
  }
43
- /**
44
- * Renders a single table cell value using field definitions or custom renderers
45
- */
46
- function TableCellRenderer(t0) {
47
- const $ = c(14);
48
- const { item, column, fields } = t0;
49
- const value = item[column.key];
50
- if (column.render) {
51
- let t1$1;
52
- if ($[0] !== column || $[1] !== item || $[2] !== value) {
53
- t1$1 = column.render(value, item);
54
- $[0] = column;
55
- $[1] = item;
56
- $[2] = value;
57
- $[3] = t1$1;
58
- } else t1$1 = $[3];
59
- return t1$1;
60
- }
61
- const fieldDef = fields?.[column.key];
62
- let t1;
63
- if ($[4] !== fieldDef) {
64
- t1 = resolveCellComponent(fieldDef);
65
- $[4] = fieldDef;
66
- $[5] = t1;
67
- } else t1 = $[5];
68
- const CellComponent = t1;
69
- const fieldType = fieldDef?.name ?? "text";
70
- let t2;
71
- if ($[6] !== fieldType) {
72
- t2 = FIELD_TYPES_NEEDING_FIELD_DEF.has(fieldType);
73
- $[6] = fieldType;
74
- $[7] = t2;
75
- } else t2 = $[7];
76
- const needsFieldDef = t2;
77
- let t3;
78
- if ($[8] !== CellComponent || $[9] !== fieldDef || $[10] !== item || $[11] !== needsFieldDef || $[12] !== value) {
79
- t3 = needsFieldDef ? /* @__PURE__ */ jsx(CellComponent, {
80
- value,
81
- row: item,
82
- fieldDef
83
- }) : /* @__PURE__ */ jsx(CellComponent, {
84
- value,
85
- row: item
86
- });
87
- $[8] = CellComponent;
88
- $[9] = fieldDef;
89
- $[10] = item;
90
- $[11] = needsFieldDef;
91
- $[12] = value;
92
- $[13] = t3;
93
- } else t3 = $[13];
94
- return t3;
52
+ function getAlignClass(align) {
53
+ if (align === "center") return "text-center";
54
+ if (align === "right") return "text-right";
95
55
  }
96
56
  /**
97
57
  * Table Widget Component
@@ -99,174 +59,127 @@ function TableCellRenderer(t0) {
99
59
  * Displays a mini table of collection items.
100
60
  * Uses field definitions from admin config for labels and cell rendering.
101
61
  */
102
- function TableWidget(t0) {
103
- const $ = c(37);
104
- const { config, basePath: t1, navigate } = t0;
105
- const basePath = t1 === void 0 ? "/admin" : t1;
62
+ function TableWidget({ config, basePath = "/admin", navigate }) {
106
63
  const resolveText = useResolveText();
107
- const { collection, columns: rawColumns, limit: t2, sortBy, sortOrder: t3, filter, linkToDetail, emptyMessage, realtime } = config;
108
- const limit = t2 === void 0 ? 5 : t2;
109
- const sortOrder = t3 === void 0 ? "desc" : t3;
110
- const columns = rawColumns.map(normalizeColumn);
111
- const fields = void 0;
112
- let queryOptions;
113
- if ($[0] !== filter || $[1] !== limit || $[2] !== sortBy || $[3] !== sortOrder) {
114
- queryOptions = { limit };
115
- if (sortBy) {
116
- let t4$1;
117
- if ($[5] !== sortBy || $[6] !== sortOrder) {
118
- t4$1 = { [sortBy]: sortOrder };
119
- $[5] = sortBy;
120
- $[6] = sortOrder;
121
- $[7] = t4$1;
122
- } else t4$1 = $[7];
123
- queryOptions.orderBy = t4$1;
124
- }
125
- if (filter) queryOptions.where = filter;
126
- $[0] = filter;
127
- $[1] = limit;
128
- $[2] = sortBy;
129
- $[3] = sortOrder;
130
- $[4] = queryOptions;
131
- } else queryOptions = $[4];
132
- let t4;
133
- if ($[8] !== realtime) {
134
- t4 = { realtime };
135
- $[8] = realtime;
136
- $[9] = t4;
137
- } else t4 = $[9];
138
- const { data, isLoading, error, refetch } = useCollectionList(collection, queryOptions, void 0, t4);
139
- const items = Array.isArray(data?.docs) ? data.docs : [];
140
- let t5;
141
- if ($[10] !== config.title || $[11] !== resolveText) {
142
- t5 = config.title ? resolveText(config.title) : void 0;
143
- $[10] = config.title;
144
- $[11] = resolveText;
145
- $[12] = t5;
146
- } else t5 = $[12];
147
- const title = t5;
148
- let t6;
149
- if ($[13] !== basePath || $[14] !== collection || $[15] !== linkToDetail || $[16] !== navigate) {
150
- t6 = (item) => {
151
- if (linkToDetail && navigate) navigate(`${basePath}/collections/${collection}/${item.id}`);
152
- };
153
- $[13] = basePath;
154
- $[14] = collection;
155
- $[15] = linkToDetail;
156
- $[16] = navigate;
157
- $[17] = t6;
158
- } else t6 = $[17];
159
- const handleRowClick = t6;
160
- let t7;
161
- if ($[18] !== emptyMessage || $[19] !== resolveText) {
162
- t7 = emptyMessage ? resolveText(emptyMessage) : "No data available";
163
- $[18] = emptyMessage;
164
- $[19] = resolveText;
165
- $[20] = t7;
166
- } else t7 = $[20];
167
- let t8;
168
- if ($[21] !== t7) {
169
- t8 = /* @__PURE__ */ jsx("div", {
170
- className: "text-muted-foreground flex h-24 items-center justify-center",
171
- children: /* @__PURE__ */ jsx("p", {
172
- className: "text-sm",
173
- children: t7
174
- })
175
- });
176
- $[21] = t7;
177
- $[22] = t8;
178
- } else t8 = $[22];
179
- const emptyContent = t8;
180
- const tableContent = items.length === 0 ? emptyContent : /* @__PURE__ */ jsxs("div", {
181
- className: "-mx-5 -mb-1",
182
- children: [/* @__PURE__ */ jsx("div", {
183
- className: "border-border text-muted-foreground bg-muted flex items-center gap-2 border-b px-5 py-2 text-[10px] font-medium tracking-wider uppercase",
184
- children: columns.map((column) => {
185
- const fieldDef = fields?.[column.key];
186
- const label = getColumnLabel(column, fieldDef);
187
- return /* @__PURE__ */ jsx("div", {
188
- className: cn("min-w-0 flex-1", column.align === "center" && "text-center", column.align === "right" && "text-right"),
189
- style: column.width ? {
190
- width: column.width,
191
- flex: "none"
192
- } : void 0,
193
- children: resolveText(label)
194
- }, column.key);
195
- })
196
- }), items.map((item_0) => linkToDetail ? /* @__PURE__ */ jsx("button", {
197
- type: "button",
198
- className: "border-border hover:bg-muted flex w-full cursor-pointer items-center gap-2 border-b px-5 py-2.5 text-left transition-all last:border-0",
199
- onClick: () => handleRowClick(item_0),
200
- children: columns.map((column_0) => /* @__PURE__ */ jsx("div", {
201
- className: cn("min-w-0 flex-1 truncate text-sm", column_0.align === "center" && "text-center", column_0.align === "right" && "text-right"),
202
- style: column_0.width ? {
203
- width: column_0.width,
204
- flex: "none"
205
- } : void 0,
206
- children: /* @__PURE__ */ jsx(TableCellRenderer, {
207
- item: item_0,
208
- column: column_0,
209
- fields
210
- })
211
- }, column_0.key))
212
- }, item_0.id) : /* @__PURE__ */ jsx("div", {
213
- className: "border-border flex items-center gap-2 border-b px-5 py-2.5 last:border-0",
214
- children: columns.map((column_1) => /* @__PURE__ */ jsx("div", {
215
- className: cn("min-w-0 flex-1 truncate text-sm", column_1.align === "center" && "text-center", column_1.align === "right" && "text-right"),
216
- style: column_1.width ? {
217
- width: column_1.width,
218
- flex: "none"
219
- } : void 0,
220
- children: /* @__PURE__ */ jsx(TableCellRenderer, {
221
- item: item_0,
222
- column: column_1,
223
- fields
224
- })
225
- }, column_1.key))
226
- }, item_0.id))]
64
+ const { collection, columns: rawColumns, limit = 5, sortBy, sortOrder = "desc", filter, linkToDetail, emptyMessage, realtime } = config;
65
+ const useServerData = !!config.hasLoader;
66
+ const serverQuery = useServerWidgetData(config.id, {
67
+ enabled: useServerData,
68
+ refreshInterval: config.refreshInterval
69
+ });
70
+ const listColumns = React.useMemo(() => rawColumns.map(toListColumnConfig), [rawColumns]);
71
+ const listConfig = React.useMemo(() => ({ columns: listColumns }), [listColumns]);
72
+ const { fields, isLoading: fieldsLoading, error: fieldsError } = useCollectionFields(collection, { schemaQueryOptions: { enabled: !!collection } });
73
+ const { data: collectionMeta, isLoading: metaLoading, error: metaError } = useCollectionMeta(collection, { enabled: !!collection });
74
+ const expandedFields = React.useMemo(() => autoExpandFields({
75
+ fields,
76
+ list: listConfig,
77
+ relations: collectionMeta?.relations
78
+ }), [
79
+ fields,
80
+ listConfig,
81
+ collectionMeta?.relations
82
+ ]);
83
+ const queryOptions = { limit };
84
+ if (sortBy) queryOptions.orderBy = { [sortBy]: sortOrder };
85
+ if (filter) queryOptions.where = filter;
86
+ if (hasFieldsToExpand(expandedFields)) queryOptions.with = expandedFields;
87
+ const collectionQuery = useCollectionList(collection, queryOptions, { enabled: !useServerData }, { realtime });
88
+ const { data, isLoading, error, refetch, isFetching } = useServerData ? serverQuery : collectionQuery;
89
+ const items = Array.isArray(data) ? data : Array.isArray(data?.docs) ? data.docs : [];
90
+ const title = config.title ? resolveText(config.title) : void 0;
91
+ const table = useReactTable({
92
+ data: items,
93
+ columns: React.useMemo(() => buildColumns({
94
+ config: {
95
+ fields,
96
+ list: listConfig
97
+ },
98
+ fallbackColumns: listColumns.map((column) => typeof column === "string" ? column : column.field),
99
+ meta: collectionMeta
100
+ }), [
101
+ fields,
102
+ listConfig,
103
+ listColumns,
104
+ collectionMeta
105
+ ]),
106
+ getCoreRowModel: getCoreRowModel(),
107
+ getRowId: (row, index) => String(row.id ?? row._id ?? index)
227
108
  });
228
- let t9;
229
- if ($[23] !== columns.length || $[24] !== limit) {
230
- t9 = /* @__PURE__ */ jsx(TableWidgetSkeleton, {
109
+ const visibleColumns = table.getVisibleLeafColumns();
110
+ const rows = table.getRowModel().rows;
111
+ const isWidgetLoading = isLoading || fieldsLoading && !fieldsError || metaLoading && !metaError;
112
+ const handleRowClick = (item) => {
113
+ if (linkToDetail && navigate) navigate(`${basePath}/collections/${collection}/${item.id}`);
114
+ };
115
+ const resolvedEmptyMessage = emptyMessage ? resolveText(emptyMessage) : void 0;
116
+ const emptyContent = /* @__PURE__ */ jsx(WidgetEmptyState, {
117
+ iconName: "ph:table",
118
+ title: resolvedEmptyMessage ?? "No rows to show",
119
+ description: resolvedEmptyMessage ? void 0 : "There are no records for the current criteria.",
120
+ className: "min-h-32"
121
+ });
122
+ const tableContent = items.length === 0 ? emptyContent : /* @__PURE__ */ jsx("div", {
123
+ className: "qa-table-widget__table -mx-4 -mb-4 min-h-0 min-w-0",
124
+ children: /* @__PURE__ */ jsxs(Table, {
125
+ "aria-label": title ?? `${formatLabel(collection)} table`,
126
+ className: "min-w-full table-fixed",
127
+ style: { minWidth: table.getTotalSize() },
128
+ children: [
129
+ /* @__PURE__ */ jsx("colgroup", { children: visibleColumns.map((column_0) => /* @__PURE__ */ jsx("col", { style: { width: column_0.getSize() } }, column_0.id)) }),
130
+ /* @__PURE__ */ jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, {
131
+ className: "hover:bg-transparent",
132
+ children: headerGroup.headers.map((header) => {
133
+ const meta = header.column.columnDef.meta;
134
+ return /* @__PURE__ */ jsx(TableHead, {
135
+ className: getAlignClass(meta?.align),
136
+ style: getColumnSizeStyle(header.column),
137
+ children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())
138
+ }, header.id);
139
+ })
140
+ }, headerGroup.id)) }),
141
+ /* @__PURE__ */ jsx(TableBody, { children: rows.map((row_0) => {
142
+ const canNavigate = !!linkToDetail && !!navigate && !!row_0.original?.id;
143
+ return /* @__PURE__ */ jsx(TableRow, {
144
+ role: canNavigate ? "link" : void 0,
145
+ tabIndex: canNavigate ? 0 : void 0,
146
+ className: cn(canNavigate && "cursor-pointer"),
147
+ onClick: canNavigate ? () => handleRowClick(row_0.original) : void 0,
148
+ onKeyDown: canNavigate ? (event) => {
149
+ if (event.key === "Enter" || event.key === " ") {
150
+ event.preventDefault();
151
+ handleRowClick(row_0.original);
152
+ }
153
+ } : void 0,
154
+ children: row_0.getVisibleCells().map((cell) => {
155
+ const meta_0 = cell.column.columnDef.meta;
156
+ return /* @__PURE__ */ jsx(TableCell, {
157
+ className: cn(getAlignClass(meta_0?.align), meta_0?.className),
158
+ style: getColumnSizeStyle(cell.column),
159
+ children: flexRender(cell.column.columnDef.cell, cell.getContext())
160
+ }, cell.id);
161
+ })
162
+ }, row_0.id);
163
+ }) })
164
+ ]
165
+ })
166
+ });
167
+ return /* @__PURE__ */ jsx(WidgetCard, {
168
+ title,
169
+ description: config.description ? resolveText(config.description) : void 0,
170
+ variant: config.cardVariant,
171
+ isLoading: isWidgetLoading,
172
+ isRefreshing: isFetching && !isWidgetLoading,
173
+ className: cn("qa-table-widget", config.className),
174
+ loadingSkeleton: /* @__PURE__ */ jsx(TableWidgetSkeleton, {
231
175
  rows: limit,
232
- columns: columns.length
233
- });
234
- $[23] = columns.length;
235
- $[24] = limit;
236
- $[25] = t9;
237
- } else t9 = $[25];
238
- let t10;
239
- if ($[26] !== error) {
240
- t10 = error instanceof Error ? error : error ? new Error(String(error)) : null;
241
- $[26] = error;
242
- $[27] = t10;
243
- } else t10 = $[27];
244
- let t11;
245
- if ($[28] !== refetch) {
246
- t11 = () => refetch();
247
- $[28] = refetch;
248
- $[29] = t11;
249
- } else t11 = $[29];
250
- let t12;
251
- if ($[30] !== isLoading || $[31] !== t10 || $[32] !== t11 || $[33] !== t9 || $[34] !== tableContent || $[35] !== title) {
252
- t12 = /* @__PURE__ */ jsx(WidgetCard, {
253
- title,
254
- isLoading,
255
- className: "qa-table-widget",
256
- loadingSkeleton: t9,
257
- error: t10,
258
- onRefresh: t11,
259
- children: tableContent
260
- });
261
- $[30] = isLoading;
262
- $[31] = t10;
263
- $[32] = t11;
264
- $[33] = t9;
265
- $[34] = tableContent;
266
- $[35] = title;
267
- $[36] = t12;
268
- } else t12 = $[36];
269
- return t12;
176
+ columns: rawColumns.length
177
+ }),
178
+ error: error instanceof Error ? error : error ? new Error(String(error)) : null,
179
+ onRefresh: () => refetch(),
180
+ actions: config.actions,
181
+ children: tableContent
182
+ });
270
183
  }
271
184
 
272
185
  //#endregion
@@ -4,6 +4,7 @@ import { selectClient, useAdminStore } from "../../runtime/provider.mjs";
4
4
  import { resolveIconElement } from "../component-renderer.mjs";
5
5
  import { WidgetCard } from "../../views/dashboard/widget-card.mjs";
6
6
  import { useServerWidgetData } from "../../hooks/use-server-widget-data.mjs";
7
+ import { WidgetEmptyState } from "./widget-empty-state.mjs";
7
8
  import { TimelineWidgetSkeleton } from "./widget-skeletons.mjs";
8
9
  import { c } from "react/compiler-runtime";
9
10
  import { Icon } from "@iconify/react";
@@ -77,7 +78,7 @@ function formatTimestamp(date, format = "relative") {
77
78
  * ```
78
79
  */
79
80
  function TimelineWidget(t0) {
80
- const $ = c(46);
81
+ const $ = c(56);
81
82
  const { config, navigate } = t0;
82
83
  const client = useAdminStore(selectClient);
83
84
  const resolveText = useResolveText();
@@ -130,7 +131,7 @@ function TimelineWidget(t0) {
130
131
  $[12] = t8;
131
132
  } else t8 = $[12];
132
133
  const clientQuery = useQuery(t8);
133
- const { data, isLoading, error, refetch } = useServerData ? serverQuery : clientQuery;
134
+ const { data, isLoading, error, refetch, isFetching } = useServerData ? serverQuery : clientQuery;
134
135
  let t9;
135
136
  let title;
136
137
  if ($[13] !== config.title || $[14] !== data || $[15] !== emptyMessage || $[16] !== maxItems || $[17] !== navigate || $[18] !== resolveText || $[19] !== showTimestamps || $[20] !== timestampFormat) {
@@ -154,24 +155,26 @@ function TimelineWidget(t0) {
154
155
  const handleItemClick = t11$1;
155
156
  let t12$1;
156
157
  if ($[28] !== emptyMessage || $[29] !== resolveText) {
157
- t12$1 = emptyMessage ? resolveText(emptyMessage) : "No activity yet";
158
+ t12$1 = emptyMessage ? resolveText(emptyMessage) : void 0;
158
159
  $[28] = emptyMessage;
159
160
  $[29] = resolveText;
160
161
  $[30] = t12$1;
161
162
  } else t12$1 = $[30];
162
- let t13$1;
163
- if ($[31] !== t12$1) {
164
- t13$1 = /* @__PURE__ */ jsx("div", {
165
- className: "text-muted-foreground flex h-24 items-center justify-center",
166
- children: /* @__PURE__ */ jsx("p", {
167
- className: "text-sm",
168
- children: t12$1
169
- })
163
+ const resolvedEmptyMessage = t12$1;
164
+ const t13$1 = resolvedEmptyMessage ?? "No activity yet";
165
+ const t14$1 = resolvedEmptyMessage ? void 0 : "There are no events to display.";
166
+ let t15$1;
167
+ if ($[31] !== t13$1 || $[32] !== t14$1) {
168
+ t15$1 = /* @__PURE__ */ jsx(WidgetEmptyState, {
169
+ iconName: "ph:clock-counter-clockwise",
170
+ title: t13$1,
171
+ description: t14$1
170
172
  });
171
- $[31] = t12$1;
172
- $[32] = t13$1;
173
- } else t13$1 = $[32];
174
- const emptyContent = t13$1;
173
+ $[31] = t13$1;
174
+ $[32] = t14$1;
175
+ $[33] = t15$1;
176
+ } else t15$1 = $[33];
177
+ const emptyContent = t15$1;
175
178
  t9 = items.length === 0 ? emptyContent : /* @__PURE__ */ jsx("div", {
176
179
  className: "space-y-0",
177
180
  children: items.map((item_0, index) => {
@@ -237,42 +240,62 @@ function TimelineWidget(t0) {
237
240
  }
238
241
  const timelineContent = t9;
239
242
  let t10;
240
- if ($[33] !== maxItems) {
241
- t10 = /* @__PURE__ */ jsx(TimelineWidgetSkeleton, { count: maxItems });
242
- $[33] = maxItems;
243
- $[34] = t10;
244
- } else t10 = $[34];
245
- let t11;
246
- if ($[35] !== error) {
247
- t11 = error instanceof Error ? error : error ? new Error(String(error)) : null;
248
- $[35] = error;
249
- $[36] = t11;
250
- } else t11 = $[36];
243
+ if ($[34] !== config.description || $[35] !== resolveText) {
244
+ t10 = config.description ? resolveText(config.description) : void 0;
245
+ $[34] = config.description;
246
+ $[35] = resolveText;
247
+ $[36] = t10;
248
+ } else t10 = $[36];
249
+ const t11 = isFetching && !isLoading;
251
250
  let t12;
252
- if ($[37] !== refetch) {
253
- t12 = () => refetch();
254
- $[37] = refetch;
251
+ if ($[37] !== maxItems) {
252
+ t12 = /* @__PURE__ */ jsx(TimelineWidgetSkeleton, { count: maxItems });
253
+ $[37] = maxItems;
255
254
  $[38] = t12;
256
255
  } else t12 = $[38];
257
256
  let t13;
258
- if ($[39] !== isLoading || $[40] !== t10 || $[41] !== t11 || $[42] !== t12 || $[43] !== timelineContent || $[44] !== title) {
259
- t13 = /* @__PURE__ */ jsx(WidgetCard, {
257
+ if ($[39] !== error) {
258
+ t13 = error instanceof Error ? error : error ? new Error(String(error)) : null;
259
+ $[39] = error;
260
+ $[40] = t13;
261
+ } else t13 = $[40];
262
+ let t14;
263
+ if ($[41] !== refetch) {
264
+ t14 = () => refetch();
265
+ $[41] = refetch;
266
+ $[42] = t14;
267
+ } else t14 = $[42];
268
+ let t15;
269
+ if ($[43] !== config.actions || $[44] !== config.cardVariant || $[45] !== config.className || $[46] !== config.icon || $[47] !== isLoading || $[48] !== t10 || $[49] !== t11 || $[50] !== t12 || $[51] !== t13 || $[52] !== t14 || $[53] !== timelineContent || $[54] !== title) {
270
+ t15 = /* @__PURE__ */ jsx(WidgetCard, {
260
271
  title,
272
+ description: t10,
273
+ icon: config.icon,
274
+ variant: config.cardVariant,
261
275
  isLoading,
262
- loadingSkeleton: t10,
263
- error: t11,
264
- onRefresh: t12,
276
+ isRefreshing: t11,
277
+ loadingSkeleton: t12,
278
+ error: t13,
279
+ onRefresh: t14,
280
+ actions: config.actions,
281
+ className: config.className,
265
282
  children: timelineContent
266
283
  });
267
- $[39] = isLoading;
268
- $[40] = t10;
269
- $[41] = t11;
270
- $[42] = t12;
271
- $[43] = timelineContent;
272
- $[44] = title;
273
- $[45] = t13;
274
- } else t13 = $[45];
275
- return t13;
284
+ $[43] = config.actions;
285
+ $[44] = config.cardVariant;
286
+ $[45] = config.className;
287
+ $[46] = config.icon;
288
+ $[47] = isLoading;
289
+ $[48] = t10;
290
+ $[49] = t11;
291
+ $[50] = t12;
292
+ $[51] = t13;
293
+ $[52] = t14;
294
+ $[53] = timelineContent;
295
+ $[54] = title;
296
+ $[55] = t15;
297
+ } else t15 = $[55];
298
+ return t15;
276
299
  }
277
300
 
278
301
  //#endregion