@antelopejs/dms 0.9.8 → 0.11.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 (451) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/README.md +1 -1
  3. package/data/module-store/catalog.json +2 -2
  4. package/dist/attachments/table-view.js +2 -2
  5. package/dist/attachments/table-view.js.map +1 -1
  6. package/dist/automation/actions.d.ts +2 -0
  7. package/dist/automation/actions.js +116 -71
  8. package/dist/automation/actions.js.map +1 -1
  9. package/dist/automation/i18n.d.ts +4 -0
  10. package/dist/automation/i18n.js +19 -0
  11. package/dist/automation/i18n.js.map +1 -0
  12. package/dist/automation/send-notification.d.ts +21 -0
  13. package/dist/automation/send-notification.js +163 -0
  14. package/dist/automation/send-notification.js.map +1 -0
  15. package/dist/automation/triggers.js +19 -25
  16. package/dist/automation/triggers.js.map +1 -1
  17. package/dist/client-origin-cors.d.ts +1 -0
  18. package/dist/client-origin-cors.js +19 -0
  19. package/dist/client-origin-cors.js.map +1 -0
  20. package/dist/config.d.ts +3 -2
  21. package/dist/config.js +5 -7
  22. package/dist/config.js.map +1 -1
  23. package/dist/frontend-module.d.ts +4 -0
  24. package/dist/frontend-module.js +37 -0
  25. package/dist/frontend-module.js.map +1 -0
  26. package/dist/implementations/dms/client-ip.js +1 -1
  27. package/dist/implementations/dms/client-ip.js.map +1 -1
  28. package/dist/implementations/dms/dev-reload.d.ts +5 -0
  29. package/dist/implementations/dms/dev-reload.js +23 -3
  30. package/dist/implementations/dms/dev-reload.js.map +1 -1
  31. package/dist/implementations/dms/frontend-modules.d.ts +2 -4
  32. package/dist/implementations/dms/frontend-modules.js +38 -94
  33. package/dist/implementations/dms/frontend-modules.js.map +1 -1
  34. package/dist/implementations/dms/frontend-ready.d.ts +12 -2
  35. package/dist/implementations/dms/frontend-ready.js +34 -4
  36. package/dist/implementations/dms/frontend-ready.js.map +1 -1
  37. package/dist/implementations/dms/layout-banners.d.ts +2 -1
  38. package/dist/implementations/dms/layout-banners.js +9 -0
  39. package/dist/implementations/dms/layout-banners.js.map +1 -1
  40. package/dist/implementations/dms/manifest.d.ts +7 -2
  41. package/dist/implementations/dms/manifest.js +12 -7
  42. package/dist/implementations/dms/manifest.js.map +1 -1
  43. package/dist/implementations/dms/page.d.ts +4 -3
  44. package/dist/implementations/dms/page.js +49 -18
  45. package/dist/implementations/dms/page.js.map +1 -1
  46. package/dist/implementations/dms/permissions-resolver.d.ts +2 -2
  47. package/dist/implementations/dms/permissions-resolver.js +2 -2
  48. package/dist/implementations/dms/permissions-resolver.js.map +1 -1
  49. package/dist/implementations/dms/realtime.js +1 -0
  50. package/dist/implementations/dms/realtime.js.map +1 -1
  51. package/dist/implementations/dms-base/bulk-selection.d.ts +1 -1
  52. package/dist/implementations/dms-base/bulk-selection.js +23 -1
  53. package/dist/implementations/dms-base/bulk-selection.js.map +1 -1
  54. package/dist/implementations/dms-base/filter-tokens.js +5 -3
  55. package/dist/implementations/dms-base/filter-tokens.js.map +1 -1
  56. package/dist/implementations/dms-base/search-route.d.ts +1 -0
  57. package/dist/implementations/dms-base/search-route.js +35 -13
  58. package/dist/implementations/dms-base/search-route.js.map +1 -1
  59. package/dist/implementations/dms-base/table-view.js +11 -6
  60. package/dist/implementations/dms-base/table-view.js.map +1 -1
  61. package/dist/implementations/dms-notifications/index.d.ts +2 -2
  62. package/dist/implementations/dms-notifications/index.js +5 -5
  63. package/dist/implementations/dms-notifications/index.js.map +1 -1
  64. package/dist/index.js +32 -55
  65. package/dist/index.js.map +1 -1
  66. package/dist/pages/modules/index.d.ts +1 -0
  67. package/dist/pages/modules/index.js +1 -0
  68. package/dist/pages/modules/index.js.map +1 -1
  69. package/dist/pages/modules/modules-store.d.ts +9 -0
  70. package/dist/pages/modules/modules-store.js +30 -0
  71. package/dist/pages/modules/modules-store.js.map +1 -0
  72. package/dist/pages/settings/users/account-credentials.js +2 -2
  73. package/dist/pages/settings/users/account-credentials.js.map +1 -1
  74. package/dist/pages/settings/users/account-data-store.js +25 -8
  75. package/dist/pages/settings/users/account-data-store.js.map +1 -1
  76. package/dist/pages/settings/users/invite-extension-routes.js +9 -3
  77. package/dist/pages/settings/users/invite-extension-routes.js.map +1 -1
  78. package/dist/pages/settings/users/member-management.js +13 -14
  79. package/dist/pages/settings/users/member-management.js.map +1 -1
  80. package/dist/pages/settings/users/profile.d.ts +1 -4
  81. package/dist/pages/settings/users/profile.js +0 -35
  82. package/dist/pages/settings/users/profile.js.map +1 -1
  83. package/dist/pages/settings/users/role-editor-store.js +26 -18
  84. package/dist/pages/settings/users/role-editor-store.js.map +1 -1
  85. package/dist/pages/settings/users/role-editor.d.ts +0 -1
  86. package/dist/pages/settings/users/role-editor.js +1 -2
  87. package/dist/pages/settings/users/role-editor.js.map +1 -1
  88. package/dist/pages/settings/users/role-preview.js +1 -2
  89. package/dist/pages/settings/users/role-preview.js.map +1 -1
  90. package/dist/pages/settings/users/roles.js +2 -2
  91. package/dist/pages/settings/users/roles.js.map +1 -1
  92. package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
  93. package/dist/realtime/broker.d.ts +6 -0
  94. package/dist/realtime/broker.js +8 -1
  95. package/dist/realtime/broker.js.map +1 -1
  96. package/dist/realtime/presence.d.ts +8 -3
  97. package/dist/realtime/presence.js +8 -4
  98. package/dist/realtime/presence.js.map +1 -1
  99. package/dist/realtime/sessions.d.ts +11 -1
  100. package/dist/realtime/sessions.js +21 -3
  101. package/dist/realtime/sessions.js.map +1 -1
  102. package/dist/realtime/table-view.d.ts +2 -2
  103. package/dist/realtime/table-view.js +4 -3
  104. package/dist/realtime/table-view.js.map +1 -1
  105. package/dist/routes/auth/client-ip.d.ts +1 -0
  106. package/dist/routes/auth/client-ip.js +18 -0
  107. package/dist/routes/auth/client-ip.js.map +1 -1
  108. package/dist/routes/auth/oauth/config.d.ts +2 -1
  109. package/dist/routes/auth/oauth/config.js +5 -1
  110. package/dist/routes/auth/oauth/config.js.map +1 -1
  111. package/dist/routes/auth/session-handoff.d.ts +0 -1
  112. package/dist/routes/auth/session-handoff.js +0 -2
  113. package/dist/routes/auth/session-handoff.js.map +1 -1
  114. package/dist/routes/auth.js +3 -2
  115. package/dist/routes/auth.js.map +1 -1
  116. package/dist/routes/index.d.ts +0 -1
  117. package/dist/routes/index.js +0 -1
  118. package/dist/routes/index.js.map +1 -1
  119. package/dist/routes/realtime.d.ts +13 -1
  120. package/dist/routes/realtime.js +114 -29
  121. package/dist/routes/realtime.js.map +1 -1
  122. package/dist/startup-config.d.ts +2 -0
  123. package/dist/startup-config.js +62 -0
  124. package/dist/startup-config.js.map +1 -0
  125. package/dist/store/interfaces.d.ts +3 -2
  126. package/dist/store/interfaces.js +16 -6
  127. package/dist/store/interfaces.js.map +1 -1
  128. package/dist/store/listing.js +25 -15
  129. package/dist/store/listing.js.map +1 -1
  130. package/dist/store/operations.js +5 -2
  131. package/dist/store/operations.js.map +1 -1
  132. package/dist/store/requirements.js +3 -2
  133. package/dist/store/requirements.js.map +1 -1
  134. package/dist/store/runtime.d.ts +10 -1
  135. package/dist/store/runtime.js +33 -6
  136. package/dist/store/runtime.js.map +1 -1
  137. package/dist/store/types.d.ts +10 -0
  138. package/dist/utils/ensure-default-tenant.d.ts +2 -1
  139. package/dist/utils/ensure-default-tenant.js +13 -1
  140. package/dist/utils/ensure-default-tenant.js.map +1 -1
  141. package/dist/utils/export-jobs.js +2 -1
  142. package/dist/utils/export-jobs.js.map +1 -1
  143. package/dist/validation/auth.schema.d.ts +2 -2
  144. package/dist/validation/member-invite.schema.d.ts +2 -10
  145. package/dist/validation/member-invite.schema.js +2 -15
  146. package/dist/validation/member-invite.schema.js.map +1 -1
  147. package/frontend-vue/dms.frontend.ts +24 -5
  148. package/frontend-vue/dms.server.ts +17 -0
  149. package/frontend-vue/layers/dms-auth/server/accounts.ts +3 -4
  150. package/frontend-vue/layers/dms-core/app/build/composables/renderNow.ts +33 -0
  151. package/frontend-vue/layers/dms-core/app/build/composables/user/tablePreferences.ts +5 -1
  152. package/frontend-vue/layers/dms-core/app/build/utils/crossTab.ts +199 -0
  153. package/frontend-vue/layers/dms-core/app/build/utils/sharedRealtimeConnection.ts +410 -0
  154. package/frontend-vue/layers/dms-core/app/composables/auth/useApiData.ts +77 -12
  155. package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +26 -0
  156. package/frontend-vue/layers/dms-core/app/composables/live/livePauseSource.ts +29 -0
  157. package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +150 -9
  158. package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +6 -4
  159. package/frontend-vue/layers/dms-core/app/composables/period/usePeriodScope.ts +27 -1
  160. package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +256 -119
  161. package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +21 -8
  162. package/frontend-vue/layers/dms-core/app/composables/translation/useTranslation.ts +25 -5
  163. package/frontend-vue/layers/dms-core/app/composables/useApiError.ts +3 -5
  164. package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +61 -26
  165. package/frontend-vue/layers/dms-core/app/plugins/dev-error-log.ts +16 -0
  166. package/frontend-vue/layers/dms-core/app/types/user.ts +6 -0
  167. package/frontend-vue/layers/dms-core/app/utils/composedText.ts +7 -2
  168. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +134 -35
  169. package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +18 -1
  170. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +136 -2
  171. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +136 -2
  172. package/frontend-vue/layers/dms-core/shared/types/app-config.ts +0 -2
  173. package/frontend-vue/layers/dms-layout/app/app.config.ts +0 -1
  174. package/frontend-vue/layers/dms-layout/app/assets/css/main.css +11 -1
  175. package/frontend-vue/layers/dms-layout/app/assets/fonts/Geist-Italic-Variable.woff2 +0 -0
  176. package/frontend-vue/layers/dms-layout/app/assets/fonts/Geist-Variable.woff2 +0 -0
  177. package/frontend-vue/layers/dms-layout/app/assets/fonts/GeistMono-Italic-Variable.woff2 +0 -0
  178. package/frontend-vue/layers/dms-layout/app/assets/fonts/GeistMono-Variable.woff2 +0 -0
  179. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +3 -2
  180. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +41 -21
  181. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +6 -2
  182. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +4 -19
  183. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +11 -107
  184. package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +18 -7
  185. package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +4 -0
  186. package/frontend-vue/layers/dms-layout/app/build/components/layout/RowSidePanel.vue +43 -82
  187. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +44 -3
  188. package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +11 -3
  189. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +132 -35
  190. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleManageMenu.vue +59 -0
  191. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleSourceLabel.vue +25 -0
  192. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreBanners.vue +73 -0
  193. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreOperation.vue +116 -0
  194. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreRequirements.vue +8 -3
  195. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +85 -207
  196. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +10 -3
  197. package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTileSkeleton.vue +68 -0
  198. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +24 -8
  199. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +8 -5
  200. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +1 -0
  201. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +19 -0
  202. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +2 -1
  203. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +31 -70
  204. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +11 -1
  205. package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +81 -0
  206. package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +2 -2
  207. package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +232 -36
  208. package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +122 -14
  209. package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +32 -3
  210. package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +49 -11
  211. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +3 -2
  212. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +59 -4
  213. package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStoreActions.ts +194 -0
  214. package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +23 -3
  215. package/frontend-vue/layers/dms-layout/app/composables/page/usePageLayout.ts +4 -2
  216. package/frontend-vue/layers/dms-layout/app/composables/page/usePageRecordDeletion.ts +162 -0
  217. package/frontend-vue/layers/dms-layout/app/composables/page/useSiteLayout.ts +6 -1
  218. package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +6 -2
  219. package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +6 -2
  220. package/frontend-vue/layers/dms-layout/app/custom-pages/modules-store.vue +291 -0
  221. package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +87 -474
  222. package/frontend-vue/layers/dms-layout/app/middleware/module-routing.global.ts +3 -0
  223. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +13 -22
  224. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +11 -10
  225. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-personal-pages.client.ts +22 -52
  226. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-quick-actions.client.ts +7 -7
  227. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-session.client.ts +11 -10
  228. package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +14 -9
  229. package/frontend-vue/layers/dms-layout/app/theme/actions.ts +5 -4
  230. package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +9 -4
  231. package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +22 -6
  232. package/frontend-vue/layers/dms-layout/app/types/module-store.ts +9 -0
  233. package/frontend-vue/layers/dms-layout/app/types/page.ts +15 -1
  234. package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +11 -0
  235. package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +57 -0
  236. package/frontend-vue/layers/dms-layout/app/utils/pageQuery.ts +26 -0
  237. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +45 -18
  238. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +44 -17
  239. package/frontend-vue/layers/dms-ui/app/build/components/containers/TargetComponentTree.vue +31 -0
  240. package/frontend-vue/layers/dms-ui/app/build/components/containers/constants.ts +25 -0
  241. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +244 -15
  242. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +42 -25
  243. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowHeader.vue +153 -0
  244. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowNotFound.vue +44 -0
  245. package/frontend-vue/layers/dms-ui/app/build/components/containers/row/drawerRowHeader.ts +35 -0
  246. package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +44 -9
  247. package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +11 -4
  248. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +38 -5
  249. package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +29 -5
  250. package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +5 -1
  251. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +3 -1
  252. package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +106 -27
  253. package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +12 -4
  254. package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +4 -2
  255. package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +48 -1
  256. package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +55 -54
  257. package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +2 -1
  258. package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +396 -288
  259. package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +2 -1
  260. package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +2 -1
  261. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardAvatar.vue +59 -0
  262. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +19 -2
  263. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardRowActions.vue +38 -0
  264. package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +148 -104
  265. package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +17 -2
  266. package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +43 -9
  267. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowComponentOptions.ts +76 -0
  268. package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +172 -27
  269. package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +270 -46
  270. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/actionError.ts +6 -1
  271. package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +2 -0
  272. package/frontend-vue/layers/dms-ui/app/build/composables/containers/closingLayers.ts +186 -0
  273. package/frontend-vue/layers/dms-ui/app/build/composables/containers/context.ts +14 -0
  274. package/frontend-vue/layers/dms-ui/app/build/composables/containers/drawerSize.ts +229 -0
  275. package/frontend-vue/layers/dms-ui/app/build/composables/containers/useResizableSize.ts +175 -0
  276. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +18 -35
  277. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/numberSuffix.ts +44 -0
  278. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +123 -27
  279. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +2 -1
  280. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationFilter.ts +75 -0
  281. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationRows.ts +92 -0
  282. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +39 -0
  283. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +3 -3
  284. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +6 -2
  285. package/frontend-vue/layers/dms-ui/app/build/composables/form/createFormFields.ts +15 -0
  286. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldSaved.ts +40 -0
  287. package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldValueRule.ts +62 -0
  288. package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +5 -0
  289. package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +42 -7
  290. package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +106 -4
  291. package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +11 -5
  292. package/frontend-vue/layers/dms-ui/app/build/composables/form/formSections.ts +32 -0
  293. package/frontend-vue/layers/dms-ui/app/build/composables/form/formValidation.ts +36 -4
  294. package/frontend-vue/layers/dms-ui/app/build/composables/form/readonlyValue.ts +19 -0
  295. package/frontend-vue/layers/dms-ui/app/build/composables/form/registerFormFunctions.ts +27 -0
  296. package/frontend-vue/layers/dms-ui/app/build/composables/form/repeaterTable.ts +78 -0
  297. package/frontend-vue/layers/dms-ui/app/build/composables/form/serverFieldErrors.ts +49 -0
  298. package/frontend-vue/layers/dms-ui/app/build/composables/form/toasterClearance.ts +118 -0
  299. package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +12 -1
  300. package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +41 -3
  301. package/frontend-vue/layers/dms-ui/app/build/composables/live/livePoller.ts +10 -2
  302. package/frontend-vue/layers/dms-ui/app/build/composables/live/pageReadClock.ts +28 -0
  303. package/frontend-vue/layers/dms-ui/app/build/composables/live/shortcuts.ts +1 -1
  304. package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +17 -3
  305. package/frontend-vue/layers/dms-ui/app/build/composables/live/useUpdatedLabel.ts +38 -0
  306. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/pageToolbarContext.ts +75 -0
  307. package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/toolbarControlHeight.ts +29 -0
  308. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodComparison.ts +52 -0
  309. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +21 -0
  310. package/frontend-vue/layers/dms-ui/app/build/composables/period/periodShortLabels.ts +28 -0
  311. package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +1 -0
  312. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRelationFilterLabels.ts +97 -0
  313. package/frontend-vue/layers/dms-ui/app/build/composables/table/useRowScrollAnchor.ts +106 -0
  314. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +9 -0
  315. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +1 -2
  316. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/archivedCount.ts +31 -0
  317. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/filterEditorValue.ts +38 -0
  318. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/formatFilterValue.ts +33 -2
  319. package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/scrollEdges.ts +31 -0
  320. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useCardFields.ts +33 -0
  321. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useMobileDisplay.ts +48 -0
  322. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useScrolledPastTop.ts +41 -18
  323. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +3 -2
  324. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLinkedVisit.ts +78 -0
  325. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +135 -22
  326. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +56 -25
  327. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +90 -35
  328. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +86 -10
  329. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +14 -4
  330. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +127 -2
  331. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/compareValues.ts +13 -0
  332. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +28 -0
  333. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +114 -1
  334. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/linkedArrival.ts +308 -0
  335. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/locateRow.ts +106 -0
  336. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pageArrival.ts +34 -0
  337. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pinnedRows.ts +17 -0
  338. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +41 -33
  339. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +24 -8
  340. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableCounts.ts +113 -0
  341. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +27 -4
  342. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +22 -6
  343. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/writeError.ts +21 -0
  344. package/frontend-vue/layers/dms-ui/app/build/utils/addressSuggestions.ts +49 -0
  345. package/frontend-vue/layers/dms-ui/app/build/utils/codeHighlight.ts +67 -29
  346. package/frontend-vue/layers/dms-ui/app/build/utils/eyebrow.ts +12 -0
  347. package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +51 -11
  348. package/frontend-vue/layers/dms-ui/app/build/utils/htmlGrammar.ts +79 -0
  349. package/frontend-vue/layers/dms-ui/app/build/utils/inputWidth.ts +53 -0
  350. package/frontend-vue/layers/dms-ui/app/build/utils/numberAdjustment.ts +6 -3
  351. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +19 -5
  352. package/frontend-vue/layers/dms-ui/app/build/utils/scrollWithin.ts +99 -0
  353. package/frontend-vue/layers/dms-ui/app/build/utils/shellParser.ts +1 -1
  354. package/frontend-vue/layers/dms-ui/app/build/utils/streamHighlight.ts +90 -0
  355. package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +36 -14
  356. package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +1 -1
  357. package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +9 -1
  358. package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +80 -32
  359. package/frontend-vue/layers/dms-ui/app/components/blocks/PageToolbarBlock.vue +137 -0
  360. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +5 -0
  361. package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +16 -2
  362. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +24 -5
  363. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +41 -23
  364. package/frontend-vue/layers/dms-ui/app/components/code-snippet/CodeSnippet.vue +23 -12
  365. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +1 -1
  366. package/frontend-vue/layers/dms-ui/app/components/container-footer/ContainerFooter.vue +34 -0
  367. package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +25 -2
  368. package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +2 -2
  369. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +119 -36
  370. package/frontend-vue/layers/dms-ui/app/components/form/components/Cascader.vue +53 -22
  371. package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +20 -1
  372. package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +13 -1
  373. package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +8 -3
  374. package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +53 -5
  375. package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +29 -5
  376. package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +45 -8
  377. package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +28 -5
  378. package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +5 -0
  379. package/frontend-vue/layers/dms-ui/app/components/form/components/InputText.vue +19 -2
  380. package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +2 -1
  381. package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +226 -65
  382. package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +80 -30
  383. package/frontend-vue/layers/dms-ui/app/components/form/components/RepeaterTable.vue +210 -0
  384. package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +4 -2
  385. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +11 -2
  386. package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +79 -70
  387. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +117 -21
  388. package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +2 -1
  389. package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +113 -34
  390. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +14 -2
  391. package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +6 -1
  392. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +13 -0
  393. package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +52 -3
  394. package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +2 -1
  395. package/frontend-vue/layers/dms-ui/app/components/table-view/CascaderPath.vue +74 -25
  396. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +48 -44
  397. package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +4 -1
  398. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +426 -97
  399. package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +33 -5
  400. package/frontend-vue/layers/dms-ui/app/composables/chart/apexCategoryLabels.ts +68 -0
  401. package/frontend-vue/layers/dms-ui/app/composables/chart/apexDatetimeBuckets.ts +306 -0
  402. package/frontend-vue/layers/dms-ui/app/composables/chart/formatValue.ts +4 -3
  403. package/frontend-vue/layers/dms-ui/app/composables/chart/heatmapColors.ts +93 -0
  404. package/frontend-vue/layers/dms-ui/app/composables/chart/localizeSeries.ts +62 -0
  405. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +116 -8
  406. package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.types.ts +7 -0
  407. package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +84 -1
  408. package/frontend-vue/layers/dms-ui/app/composables/containers/useDrawer.ts +69 -8
  409. package/frontend-vue/layers/dms-ui/app/composables/form/types/field-saved.ts +11 -0
  410. package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +16 -0
  411. package/frontend-vue/layers/dms-ui/app/composables/form/types/functions.ts +1 -0
  412. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +189 -28
  413. package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +29 -12
  414. package/frontend-vue/layers/dms-ui/app/composables/page-toolbar/usePageToolbarSize.ts +30 -0
  415. package/frontend-vue/layers/dms-ui/app/composables/table-view/kanban.ts +4 -2
  416. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +22 -3
  417. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +4 -0
  418. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +24 -1
  419. package/frontend-vue/layers/dms-ui/app/plugins/closing-layers.client.ts +10 -0
  420. package/frontend-vue/layers/dms-ui/app/plugins/live-pause-source.ts +15 -0
  421. package/frontend-vue/layers/dms-ui/app/plugins/register.ts +2 -0
  422. package/frontend-vue/layers/dms-ui/app/types/input-number.ts +3 -2
  423. package/frontend-vue/layers/dms-ui/app/types/page-toolbar.ts +7 -0
  424. package/frontend-vue/layers/dms-ui/app/types/row-action.ts +0 -2
  425. package/frontend-vue/layers/dms-ui/app/types/row-navigation.ts +17 -0
  426. package/frontend-vue/layers/dms-ui/app/types/table/query.ts +2 -1
  427. package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +3 -1
  428. package/frontend-vue/layers/dms-ui/app/utils/cascader.ts +94 -3
  429. package/frontend-vue/layers/dms-ui/app/utils/componentTree.ts +24 -0
  430. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +20 -5
  431. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +20 -5
  432. package/frontend-vue/package.json +6 -2
  433. package/package.json +11 -10
  434. package/skills/dms/SKILL.md +1 -1
  435. package/skills/dms-auth/SKILL.md +5 -3
  436. package/skills/dms-best-practices/REFERENCE.md +2 -0
  437. package/skills/dms-best-practices/SKILL.md +4 -0
  438. package/skills/dms-module/SKILL.md +3 -2
  439. package/skills/dms-pages/REFERENCE.md +129 -16
  440. package/skills/dms-pages/SKILL.md +1 -1
  441. package/skills/dms-project/DEV-SERVERS.md +23 -1
  442. package/skills/dms-project/REFERENCE.md +1 -1
  443. package/skills/dms-project/SKILL.md +4 -1
  444. package/skills/dms-project/scripts/dms-dev.sh +205 -17
  445. package/dist/hooks/tenant-instances.d.ts +0 -1
  446. package/dist/hooks/tenant-instances.js +0 -13
  447. package/dist/hooks/tenant-instances.js.map +0 -1
  448. package/dist/routes/startup-gate.d.ts +0 -7
  449. package/dist/routes/startup-gate.js +0 -39
  450. package/dist/routes/startup-gate.js.map +0 -1
  451. package/frontend-vue/layers/dms-core/app/composables/period/periodRenderNow.ts +0 -42
@@ -7,6 +7,9 @@ import type { Tone } from "../../types/tone";
7
7
 
8
8
  export type StatGroupLayout = "joined" | "cards";
9
9
 
10
+ /** A container size: `sm` 24rem, `md` 28rem, `lg` 32rem, `xl` 36rem. */
11
+ export type StatGroupColumnsFrom = "sm" | "md" | "lg" | "xl";
12
+
10
13
  export interface StatGroupItem {
11
14
  /** Stable key; the position is used without one. */
12
15
  id?: string;
@@ -42,6 +45,12 @@ interface StatGroupProps {
42
45
  * number of items.
43
46
  */
44
47
  columns?: number;
48
+ /**
49
+ * The group's own width from which all `columns` sit side by side (a
50
+ * container size); below it, one column (`joined`) or the narrow count of
51
+ * `cards`. Defaults to the usual steps for the column count.
52
+ */
53
+ columnsFrom?: StatGroupColumnsFrom;
45
54
  /**
46
55
  * Loading: with items, their well and value turn to skeletons (labels stay);
47
56
  * without, `skeletonCount` placeholder cells are drawn.
@@ -57,6 +66,7 @@ const props = withDefaults(defineProps<StatGroupProps>(), {
57
66
  items: () => [],
58
67
  layout: "joined",
59
68
  columns: undefined,
69
+ columnsFrom: undefined,
60
70
  loading: false,
61
71
  skeletonCount: 4,
62
72
  label: undefined,
@@ -87,6 +97,38 @@ const CARD_COLUMNS: Record<number, string> = {
87
97
  6: "grid-cols-2 @2xl:grid-cols-3 @5xl:grid-cols-6",
88
98
  };
89
99
 
100
+ // `columnsFrom`: every column from that container size, literal for Tailwind.
101
+ const COLUMNS_FROM: Record<StatGroupColumnsFrom, Record<number, string>> = {
102
+ sm: {
103
+ 2: "@sm:grid-cols-2",
104
+ 3: "@sm:grid-cols-3",
105
+ 4: "@sm:grid-cols-4",
106
+ 5: "@sm:grid-cols-5",
107
+ 6: "@sm:grid-cols-6",
108
+ },
109
+ md: {
110
+ 2: "@md:grid-cols-2",
111
+ 3: "@md:grid-cols-3",
112
+ 4: "@md:grid-cols-4",
113
+ 5: "@md:grid-cols-5",
114
+ 6: "@md:grid-cols-6",
115
+ },
116
+ lg: {
117
+ 2: "@lg:grid-cols-2",
118
+ 3: "@lg:grid-cols-3",
119
+ 4: "@lg:grid-cols-4",
120
+ 5: "@lg:grid-cols-5",
121
+ 6: "@lg:grid-cols-6",
122
+ },
123
+ xl: {
124
+ 2: "@xl:grid-cols-2",
125
+ 3: "@xl:grid-cols-3",
126
+ 4: "@xl:grid-cols-4",
127
+ 5: "@xl:grid-cols-5",
128
+ 6: "@xl:grid-cols-6",
129
+ },
130
+ };
131
+
90
132
  // Every joined cell draws its top and start hairlines; the grid is pulled 1px
91
133
  // up and left under the card's clipping edge, so the first row and the first
92
134
  // column lose theirs at any column count and on every breakpoint.
@@ -98,9 +140,16 @@ const columnCount = computed(() => {
98
140
  props.columns ?? (props.items.length || props.skeletonCount || MIN_COLUMNS);
99
141
  return Math.min(MAX_COLUMNS, Math.max(MIN_COLUMNS, Math.round(wanted)));
100
142
  });
101
- const columnClass = computed(
102
- () => (isJoined.value ? JOINED_COLUMNS : CARD_COLUMNS)[columnCount.value],
103
- );
143
+ const columnClass = computed(() => {
144
+ const steps = (isJoined.value ? JOINED_COLUMNS : CARD_COLUMNS)[
145
+ columnCount.value
146
+ ]!;
147
+ const from =
148
+ props.columnsFrom && COLUMNS_FROM[props.columnsFrom][columnCount.value];
149
+ if (!from) return steps;
150
+ // The narrow count of the usual steps, then every column from the size.
151
+ return `${steps.split(" ")[0]} ${from}`;
152
+ });
104
153
  const showPlaceholders = computed(
105
154
  () => props.loading && props.items.length === 0,
106
155
  );
@@ -1,4 +1,5 @@
1
1
  <script setup lang="ts">
2
+ import { readableNumberFormat } from "#dms-core/app/utils/formatter";
2
3
  import type { TabProps } from "../../composables/tab/types";
3
4
  import { type TabBadges, TabVariant } from "../../composables/tab/types/props";
4
5
  import { useChartFetch } from "../../composables/chart/useChartFetch";
@@ -41,7 +42,7 @@ const { data: fetchedBadges } = useChartFetch<TabBadges>({
41
42
  watchSource: () => JSON.stringify(watchState.value),
42
43
  });
43
44
  const { locale } = useI18n();
44
- const countFormat = computed(() => new Intl.NumberFormat(locale.value));
45
+ const countFormat = computed(() => readableNumberFormat(locale.value));
45
46
 
46
47
  // Shown like a table view's tab counts: a mono counter, tinted on the
47
48
  // active tab.
@@ -1,12 +1,15 @@
1
1
  <script setup lang="ts">
2
2
  import {
3
- CASCADER_FETCH_LIMIT,
4
3
  CASCADER_PATH_SEPARATOR,
4
+ cascaderValueId,
5
5
  cascaderValuePath,
6
+ cascaderValueReads,
7
+ readCascaderAncestry,
6
8
  resolveCascaderKeyMapping,
7
9
  type CascaderKeyMapping,
8
10
  } from "../../utils/cascader";
9
11
  import { MAX_RELATION_BADGES } from "../../build/composables/data-types/relationBadges";
12
+ import { useRelationRows } from "../../build/composables/data-types/relationRows";
10
13
 
11
14
  const DEFAULT_VALUE_KEY = "_id";
12
15
 
@@ -17,20 +20,20 @@ interface CascaderPathProps {
17
20
  keyMapping?: Partial<CascaderKeyMapping>;
18
21
  }
19
22
 
20
- /** A picked value of a multiple cascader: its name, its path on hover. */
23
+ /**
24
+ * A picked value as the cell names it: its path, or "Not found" with its id
25
+ * on hover when its row is gone or out of reach.
26
+ */
21
27
  interface CascaderBadge {
22
28
  label: string;
23
29
  title: string;
30
+ isNotFound: boolean;
24
31
  }
25
32
 
26
33
  const props = defineProps<CascaderPathProps>();
27
34
 
28
- const { $authFetch } = useAuthFetch();
29
-
30
- interface CascaderResponse {
31
- results: Record<string, unknown>[];
32
- total: number;
33
- }
35
+ const { t } = useI18n();
36
+ const { readRelationRows } = useRelationRows();
34
37
 
35
38
  const keyMapping = computed(() =>
36
39
  resolveCascaderKeyMapping({
@@ -39,33 +42,72 @@ const keyMapping = computed(() =>
39
42
  }),
40
43
  );
41
44
 
45
+ const values = computed<unknown[]>(() =>
46
+ Array.isArray(props.value) ? props.value : [props.value],
47
+ );
48
+ const reads = computed(() =>
49
+ cascaderValueReads(values.value, keyMapping.value),
50
+ );
51
+ const ids = computed(() => reads.value.idsToRead);
52
+
53
+ // The ids a list did not join (and the parents of those it did), with their
54
+ // ancestors, read by `?ids=` level by level.
42
55
  const { data } = await useDmsAsyncData(
43
- `cascader-path-${props.searchUrl}`,
56
+ () => `cascader-path-${props.searchUrl}-${ids.value.join(",")}`,
44
57
  () =>
45
- props.searchUrl
46
- ? $authFetch<CascaderResponse>(props.searchUrl, {
47
- params: { limit: CASCADER_FETCH_LIMIT },
48
- })
58
+ props.searchUrl && ids.value.length > 0
59
+ ? readCascaderAncestry(
60
+ (pending) =>
61
+ readRelationRows(
62
+ {
63
+ searchUrl: props.searchUrl!,
64
+ keyMapping: { value: keyMapping.value.value },
65
+ },
66
+ pending,
67
+ ),
68
+ keyMapping.value,
69
+ ids.value,
70
+ )
49
71
  : Promise.resolve(undefined),
50
72
  // The labels of a path, not the page's data.
51
73
  { lazy: true, refreshOnPageRefresh: false },
52
74
  );
53
75
 
54
- const pathOf = (item: unknown): string[] =>
55
- cascaderValuePath(item, keyMapping.value, data.value?.results);
76
+ const pathRows = computed(() => [
77
+ ...reads.value.joinedRows,
78
+ ...(data.value?.rows ?? []),
79
+ ]);
56
80
 
57
- const pathLabel = computed(() =>
58
- pathOf(props.value).join(CASCADER_PATH_SEPARATOR),
59
- );
81
+ const notFound = computed(() => new Set(data.value?.notFound));
82
+
83
+ function badgeOf(item: unknown): CascaderBadge | undefined {
84
+ const id = cascaderValueId(item, keyMapping.value);
85
+ if (id !== undefined && notFound.value.has(id)) {
86
+ return {
87
+ label: t("dms.form.relation.not_found"),
88
+ title: id,
89
+ isNotFound: true,
90
+ };
91
+ }
92
+ const path = cascaderValuePath(item, keyMapping.value, pathRows.value);
93
+ if (path.length === 0) return undefined;
94
+ return {
95
+ label: path.at(-1) ?? "",
96
+ title: path.join(CASCADER_PATH_SEPARATOR),
97
+ isNotFound: false,
98
+ };
99
+ }
100
+
101
+ const single = computed(() => {
102
+ const badge = badgeOf(props.value);
103
+ if (!badge || badge.isNotFound) return badge;
104
+ return { ...badge, label: badge.title };
105
+ });
60
106
 
61
107
  const badges = computed<CascaderBadge[]>(() =>
62
108
  (Array.isArray(props.value) ? props.value : [])
63
- .map(pathOf)
64
- .filter((path) => path.length > 0)
65
- .map((path) => ({
66
- label: path.at(-1) ?? "",
67
- title: path.join(CASCADER_PATH_SEPARATOR),
68
- })),
109
+ .map(badgeOf)
110
+ .filter((badge): badge is CascaderBadge => !!badge),
69
111
  );
70
112
  const visibleBadges = computed(() =>
71
113
  badges.value.slice(0, MAX_RELATION_BADGES),
@@ -82,6 +124,7 @@ const hiddenBadges = computed(() => badges.value.slice(MAX_RELATION_BADGES));
82
124
  v-for="badge in visibleBadges"
83
125
  :key="badge.title"
84
126
  :label="badge.label"
127
+ :class="badge.isNotFound && 'text-muted'"
85
128
  :title="badge.title"
86
129
  color="neutral"
87
130
  variant="subtle"
@@ -97,5 +140,11 @@ const hiddenBadges = computed(() => badges.value.slice(MAX_RELATION_BADGES));
97
140
  size="sm"
98
141
  />
99
142
  </span>
100
- <span v-else class="truncate" :title="pathLabel">{{ pathLabel }}</span>
143
+ <span
144
+ v-else-if="single"
145
+ :class="['truncate', single.isNotFound && 'text-muted']"
146
+ :title="single.title"
147
+ >
148
+ {{ single.label }}
149
+ </span>
101
150
  </template>
@@ -17,7 +17,13 @@ import type { TableViewDisplayContext } from "../../composables/table-view/types
17
17
  import {
18
18
  buildCardProps,
19
19
  cardFieldColumns,
20
+ cardIdentity,
21
+ cardSubtitle,
20
22
  } from "../../build/composables/table-view/utils/card";
23
+ import { readSubline } from "../../build/composables/data-types/cellHelpers";
24
+ import { useComposedText } from "#dms-core/app/composables/translation/useComposedText";
25
+ import { useCardFields } from "../../build/composables/table-view/useCardFields";
26
+ import { describeTableWriteError } from "../../build/composables/table-view/utils/writeError";
21
27
 
22
28
  const DEFAULT_COLUMN_PAGE_SIZE = 10;
23
29
  const DEFAULT_COLUMN_MAX_HEIGHT = "60vh";
@@ -69,14 +75,19 @@ const props = defineProps<KanbanBoardProps>();
69
75
  const emit = defineEmits<{
70
76
  "card-click": [item: T];
71
77
  "card-delete": [item: T];
78
+ /** A card moved to another column and the change was saved. */
79
+ moved: [item: T, column: KanbanColumnDef];
80
+ /** The cards shown, column by column: what a row's drawer steps through. */
81
+ "rows-shown": [items: T[]];
72
82
  }>();
73
83
 
74
84
  const groupByField = defineModel<string>("groupByField", { required: true });
75
85
 
76
86
  const { $authFetch } = useAuthFetch();
77
- const { processI18n, processApiMessage } = useTranslation();
87
+ const { processI18n } = useTranslation();
78
88
  const { getDataType } = useDataTypes();
79
- const { locale, t } = useI18n();
89
+ const { t } = useI18n();
90
+ const { processText } = useComposedText();
80
91
  const toast = useToast();
81
92
 
82
93
  const rowIdKey = computed(() => props.rowIdKey ?? DEFAULT_ROW_ID_KEY);
@@ -171,6 +182,14 @@ watch(
171
182
  { immediate: true },
172
183
  );
173
184
 
185
+ // The cards in the order the board reads, column by column and top to
186
+ // bottom in each: a card's drawer steps through them (J / K), and through the
187
+ // cards a "load more" or a drag adds or moves.
188
+ const shownRows = computed(() =>
189
+ boardColumns.value.flatMap((col) => cells.value[col.value]?.items ?? []),
190
+ );
191
+ watch(shownRows, (rows) => emit("rows-shown", rows), { immediate: true });
192
+
174
193
  const loadMore = async (col: KanbanColumnDef) => {
175
194
  const cell = cells.value[col.value];
176
195
  if (!cell || cell.loadingMore) return;
@@ -303,18 +322,11 @@ const awaitNewerMoves = async (itemId: string, current: Promise<void>) => {
303
322
  }
304
323
  };
305
324
 
306
- interface MoveErrorPayload {
307
- data?: { message?: string };
308
- message?: string;
309
- }
310
-
311
325
  const notifyMoveError = (error: unknown) => {
312
- const err = error as MoveErrorPayload;
313
- const message = err?.data?.message || err?.message;
314
326
  toast.add({
315
327
  color: Color.error,
316
328
  title: t("dms.table.kanban.move_error"),
317
- description: message ? processApiMessage(message) : undefined,
329
+ description: describeTableWriteError(error, t, props.columns, processI18n),
318
330
  });
319
331
  };
320
332
 
@@ -348,6 +360,7 @@ const onColumnChange = async (
348
360
 
349
361
  try {
350
362
  await queued;
363
+ emit("moved", item, target);
351
364
  toast.add({
352
365
  color: Color.success,
353
366
  title: t("dms.table.kanban.move_success", { column: target.label }),
@@ -384,13 +397,18 @@ const cardColumns = computed(() =>
384
397
  }),
385
398
  );
386
399
 
387
- // The id line only adds something when the title is a label, not the id.
388
- const getCardId = (item: T): string | undefined => {
389
- if (!props.labelKey) return undefined;
390
- const label = get(item, props.labelKey);
391
- if (label === undefined || label === null || label === "") return undefined;
392
- return getRowId(item);
393
- };
400
+ // The line above the title: the title column's identity subtitle, or the
401
+ // row's own id key (`rowIdKey: "code"`) under a label — never the database
402
+ // `_id`, which tells the reader nothing.
403
+ const identity = computed(() => cardIdentity(props.columns, props.labelKey));
404
+ const getCardLine = (item: T): string | undefined =>
405
+ readSubline(
406
+ cardSubtitle(item, identity.value, {
407
+ labelKey: props.labelKey,
408
+ rowIdKey: props.rowIdKey ?? DEFAULT_ROW_ID_KEY,
409
+ }),
410
+ { processText, isStringTranslated: false },
411
+ )?.text;
394
412
 
395
413
  const getCardTitle = (item: T): string => {
396
414
  if (props.labelKey) {
@@ -403,27 +421,10 @@ const getCardTitle = (item: T): string => {
403
421
  };
404
422
 
405
423
  // Renders a card field value the same way table cells do: through the
406
- // formatter registered for the column's data type.
407
- const FieldValue = (fieldProps: { column: TableViewColumn; item: T }) => {
408
- const value = get(fieldProps.item, fieldProps.column.accessorKey);
409
- const options = fieldProps.column.type.inputComponent?.options as
410
- | Record<string, unknown>
411
- | undefined;
412
-
413
- if (value === null || value === undefined) {
414
- return h("span", (options?.fallback as string) ?? "-");
415
- }
416
-
417
- const formatter = getDataType(fieldProps.column.type.id)?.formatter;
418
- const rendered = formatter
419
- ? formatter.default(value, locale.value, options)
420
- : value;
421
-
422
- if (typeof rendered === "string" || typeof rendered === "number") {
423
- return h("span", String(rendered));
424
- }
425
- return rendered as ReturnType<typeof h>;
426
- };
424
+ // column's display, else its data type.
425
+ const { renderField } = useCardFields();
426
+ const FieldValue = (fieldProps: { column: TableViewColumn; item: T }) =>
427
+ renderField(fieldProps.column, fieldProps.item);
427
428
  </script>
428
429
 
429
430
  <template>
@@ -534,7 +535,9 @@ const FieldValue = (fieldProps: { column: TableViewColumn; item: T }) => {
534
535
  @edit="emit('card-click', element)"
535
536
  @delete="emit('card-delete', element)"
536
537
  />
537
- <!-- v2 card: id line (with its delete or lock), title, fields. -->
538
+ <!-- v2 card: subtitle line (with its delete or lock), title, fields.
539
+ Each line shrinks below a long word: a UUID truncates
540
+ rather than overflowing the card. -->
538
541
  <div
539
542
  v-else
540
543
  class="border-default group hover:border-primary/35 grid cursor-pointer gap-2 rounded-lg border bg-(--dms-surface-card) px-3 pt-2.5 pb-[11px] text-[12.5px] shadow-xs transition-colors"
@@ -542,17 +545,18 @@ const FieldValue = (fieldProps: { column: TableViewColumn; item: T }) => {
542
545
  >
543
546
  <div
544
547
  v-if="
545
- getCardId(element) ||
548
+ getCardLine(element) ||
546
549
  canDeleteItem(element) ||
547
550
  isItemLocked(element)
548
551
  "
549
552
  class="-mb-0.5 flex min-h-5 items-center gap-2"
550
553
  >
551
554
  <span
552
- v-if="getCardId(element)"
553
- class="text-muted truncate font-mono text-[11.5px] font-medium"
555
+ v-if="getCardLine(element)"
556
+ class="text-muted min-w-0 truncate font-mono text-[11.5px] font-medium"
557
+ :title="getCardLine(element)"
554
558
  >
555
- #{{ getCardId(element) }}
559
+ {{ getCardLine(element) }}
556
560
  </span>
557
561
  <UIcon
558
562
  v-if="isItemLocked(element)"
@@ -573,7 +577,7 @@ const FieldValue = (fieldProps: { column: TableViewColumn; item: T }) => {
573
577
  />
574
578
  </div>
575
579
  <p
576
- class="text-highlighted truncate text-[13px] leading-[1.3] font-semibold"
580
+ class="text-highlighted min-w-0 truncate text-[13px] leading-[1.3] font-semibold"
577
581
  >
578
582
  {{ getCardTitle(element) }}
579
583
  </p>
@@ -35,7 +35,8 @@ const onCardClick = (item: T) => props.context.actions.open(item);
35
35
 
36
36
  const onCardDelete = (item: T) => {
37
37
  const id = rowId(item);
38
- if (id) props.context.actions.delete([id]);
38
+ // The card is not among the grid's rows: hand it, its dialog names it.
39
+ if (id) props.context.actions.delete([id], [item]);
39
40
  };
40
41
 
41
42
  const kanbanBoardRef = ref<{ refresh: () => Promise<void> } | null>(null);
@@ -63,5 +64,7 @@ defineExpose({ refresh: () => kanbanBoardRef.value?.refresh() });
63
64
  :delete-action="bridge?.deleteAction"
64
65
  @card-click="(item) => onCardClick(item as T)"
65
66
  @card-delete="(item) => onCardDelete(item as T)"
67
+ @moved="bridge?.onCardMoved?.()"
68
+ @rows-shown="(items) => context.setShownRows?.(items as T[])"
66
69
  />
67
70
  </template>