@antelopejs/dms 0.6.1 → 0.7.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 (472) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/dist/db/models/notification-feed-filter.d.ts +0 -1
  3. package/dist/db/models/notification-feed-filter.js +0 -4
  4. package/dist/db/models/notification-feed-filter.js.map +1 -1
  5. package/dist/db/models/signInAttempts.model.d.ts +18 -0
  6. package/dist/db/models/signInAttempts.model.js +83 -12
  7. package/dist/db/models/signInAttempts.model.js.map +1 -1
  8. package/dist/db/models/userEmailChanges.model.d.ts +8 -1
  9. package/dist/db/models/userEmailChanges.model.js +27 -2
  10. package/dist/db/models/userEmailChanges.model.js.map +1 -1
  11. package/dist/db/models/userNotificationPreferences.model.d.ts +0 -2
  12. package/dist/db/models/userNotificationPreferences.model.js +0 -13
  13. package/dist/db/models/userNotificationPreferences.model.js.map +1 -1
  14. package/dist/db/models/userNotifications.model.d.ts +5 -2
  15. package/dist/db/models/userNotifications.model.js +19 -2
  16. package/dist/db/models/userNotifications.model.js.map +1 -1
  17. package/dist/db/tables/signInAttempts.table.d.ts +2 -1
  18. package/dist/db/tables/signInAttempts.table.js +4 -0
  19. package/dist/db/tables/signInAttempts.table.js.map +1 -1
  20. package/dist/db/tables/userEmailChanges.table.d.ts +2 -1
  21. package/dist/db/tables/userEmailChanges.table.js +6 -1
  22. package/dist/db/tables/userEmailChanges.table.js.map +1 -1
  23. package/dist/db/tables/userNotificationPreferences.table.d.ts +0 -1
  24. package/dist/db/tables/userNotificationPreferences.table.js +0 -4
  25. package/dist/db/tables/userNotificationPreferences.table.js.map +1 -1
  26. package/dist/implementations/dms/layout-banners.d.ts +4 -1
  27. package/dist/implementations/dms/layout-banners.js +33 -18
  28. package/dist/implementations/dms/layout-banners.js.map +1 -1
  29. package/dist/implementations/dms/nav-badges.d.ts +6 -4
  30. package/dist/implementations/dms/nav-badges.js +6 -5
  31. package/dist/implementations/dms/nav-badges.js.map +1 -1
  32. package/dist/implementations/dms/page.d.ts +1 -0
  33. package/dist/implementations/dms/page.js +46 -8
  34. package/dist/implementations/dms/page.js.map +1 -1
  35. package/dist/implementations/dms/permission-preview.d.ts +1 -1
  36. package/dist/implementations/dms/permission-preview.js +9 -4
  37. package/dist/implementations/dms/permission-preview.js.map +1 -1
  38. package/dist/implementations/dms-auth/index.d.ts +3 -2
  39. package/dist/implementations/dms-auth/index.js +39 -35
  40. package/dist/implementations/dms-auth/index.js.map +1 -1
  41. package/dist/implementations/dms-auth/token-session.d.ts +3 -0
  42. package/dist/implementations/dms-auth/token-session.js +22 -0
  43. package/dist/implementations/dms-auth/token-session.js.map +1 -0
  44. package/dist/implementations/dms-notifications/index.d.ts +0 -1
  45. package/dist/implementations/dms-notifications/index.js +0 -7
  46. package/dist/implementations/dms-notifications/index.js.map +1 -1
  47. package/dist/pages/settings/settings-index.js +3 -2
  48. package/dist/pages/settings/settings-index.js.map +1 -1
  49. package/dist/pages/settings/users/account-activity-feed.d.ts +1 -1
  50. package/dist/pages/settings/users/account-activity-feed.js +1 -1
  51. package/dist/pages/settings/users/account-activity-feed.js.map +1 -1
  52. package/dist/pages/settings/users/account-activity.d.ts +1 -1
  53. package/dist/pages/settings/users/account-activity.js +1 -1
  54. package/dist/pages/settings/users/account-activity.js.map +1 -1
  55. package/dist/pages/settings/users/account-credentials.d.ts +3 -0
  56. package/dist/pages/settings/users/account-credentials.js +2 -0
  57. package/dist/pages/settings/users/account-credentials.js.map +1 -1
  58. package/dist/pages/settings/users/current-password.d.ts +1 -1
  59. package/dist/pages/settings/users/current-password.js +23 -2
  60. package/dist/pages/settings/users/current-password.js.map +1 -1
  61. package/dist/pages/settings/users/email-change.d.ts +1 -1
  62. package/dist/pages/settings/users/email-change.js +33 -26
  63. package/dist/pages/settings/users/email-change.js.map +1 -1
  64. package/dist/pages/settings/users/invite-resend.js +0 -1
  65. package/dist/pages/settings/users/invite-resend.js.map +1 -1
  66. package/dist/pages/settings/users/invites.d.ts +1 -2
  67. package/dist/pages/settings/users/invites.js +21 -19
  68. package/dist/pages/settings/users/invites.js.map +1 -1
  69. package/dist/pages/settings/users/member-invite-batch.js +0 -1
  70. package/dist/pages/settings/users/member-invite-batch.js.map +1 -1
  71. package/dist/pages/settings/users/member-invite-form.js +10 -22
  72. package/dist/pages/settings/users/member-invite-form.js.map +1 -1
  73. package/dist/pages/settings/users/member-role-options.d.ts +6 -4
  74. package/dist/pages/settings/users/member-role-options.js +15 -4
  75. package/dist/pages/settings/users/member-role-options.js.map +1 -1
  76. package/dist/pages/settings/users/members.d.ts +2 -3
  77. package/dist/pages/settings/users/members.js +7 -12
  78. package/dist/pages/settings/users/members.js.map +1 -1
  79. package/dist/pages/settings/users/notifications.d.ts +1 -8
  80. package/dist/pages/settings/users/notifications.js +6 -38
  81. package/dist/pages/settings/users/notifications.js.map +1 -1
  82. package/dist/pages/settings/users/permission-tree-nodes.d.ts +1 -1
  83. package/dist/pages/settings/users/permission-tree-nodes.js +23 -9
  84. package/dist/pages/settings/users/permission-tree-nodes.js.map +1 -1
  85. package/dist/pages/settings/users/permission-warnings.d.ts +7 -0
  86. package/dist/pages/settings/users/permission-warnings.js +42 -0
  87. package/dist/pages/settings/users/permission-warnings.js.map +1 -0
  88. package/dist/pages/settings/users/profile-helpers.d.ts +1 -3
  89. package/dist/pages/settings/users/profile-helpers.js +0 -16
  90. package/dist/pages/settings/users/profile-helpers.js.map +1 -1
  91. package/dist/pages/settings/users/role-editor-store.js +6 -3
  92. package/dist/pages/settings/users/role-editor-store.js.map +1 -1
  93. package/dist/pages/settings/users/role-editor.d.ts +2 -1
  94. package/dist/pages/settings/users/role-editor.js +8 -4
  95. package/dist/pages/settings/users/role-editor.js.map +1 -1
  96. package/dist/pages/settings/users/role-preview.js +2 -1
  97. package/dist/pages/settings/users/role-preview.js.map +1 -1
  98. package/dist/pages/settings/users/roles.js +5 -1
  99. package/dist/pages/settings/users/roles.js.map +1 -1
  100. package/dist/pages/settings/users/security-attention.d.ts +4 -0
  101. package/dist/pages/settings/users/security-attention.js +23 -7
  102. package/dist/pages/settings/users/security-attention.js.map +1 -1
  103. package/dist/pages/settings/users/security.d.ts +2 -1
  104. package/dist/pages/settings/users/security.js +13 -2
  105. package/dist/pages/settings/users/security.js.map +1 -1
  106. package/dist/pages/settings/users/two-factor-operations.d.ts +2 -1
  107. package/dist/pages/settings/users/two-factor-operations.js +28 -29
  108. package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
  109. package/dist/routes/auth/forgot-password.js +3 -0
  110. package/dist/routes/auth/forgot-password.js.map +1 -1
  111. package/dist/routes/auth/index.d.ts +1 -0
  112. package/dist/routes/auth/index.js +1 -0
  113. package/dist/routes/auth/index.js.map +1 -1
  114. package/dist/routes/auth/invite.js +28 -4
  115. package/dist/routes/auth/invite.js.map +1 -1
  116. package/dist/routes/auth/login-throttle.d.ts +2 -0
  117. package/dist/routes/auth/login-throttle.js +5 -4
  118. package/dist/routes/auth/login-throttle.js.map +1 -1
  119. package/dist/routes/auth/request-2fa-email.js +6 -18
  120. package/dist/routes/auth/request-2fa-email.js.map +1 -1
  121. package/dist/routes/auth/reset-code.d.ts +3 -0
  122. package/dist/routes/auth/reset-code.js +37 -0
  123. package/dist/routes/auth/reset-code.js.map +1 -0
  124. package/dist/routes/auth/reset-password.d.ts +2 -2
  125. package/dist/routes/auth/reset-password.js +5 -10
  126. package/dist/routes/auth/reset-password.js.map +1 -1
  127. package/dist/routes/auth/signup.js +10 -32
  128. package/dist/routes/auth/signup.js.map +1 -1
  129. package/dist/routes/auth/two-factor-throttle.d.ts +5 -0
  130. package/dist/routes/auth/two-factor-throttle.js +81 -0
  131. package/dist/routes/auth/two-factor-throttle.js.map +1 -0
  132. package/dist/routes/auth/validate-forgot-password-token.js +2 -8
  133. package/dist/routes/auth/validate-forgot-password-token.js.map +1 -1
  134. package/dist/routes/auth/validate-invite-token.d.ts +1 -0
  135. package/dist/routes/auth/validate-invite-token.js +11 -0
  136. package/dist/routes/auth/validate-invite-token.js.map +1 -0
  137. package/dist/routes/auth/verify-2fa.js +10 -13
  138. package/dist/routes/auth/verify-2fa.js.map +1 -1
  139. package/dist/routes/auth.d.ts +1 -0
  140. package/dist/routes/auth.js +11 -1
  141. package/dist/routes/auth.js.map +1 -1
  142. package/dist/test/helpers/auth.d.ts +0 -1
  143. package/dist/test/helpers/auth.js +0 -1
  144. package/dist/test/helpers/auth.js.map +1 -1
  145. package/dist/test/helpers/emails.d.ts +10 -0
  146. package/dist/test/helpers/emails.js +36 -0
  147. package/dist/test/helpers/emails.js.map +1 -0
  148. package/dist/test/helpers/fixtures.d.ts +0 -1
  149. package/dist/test/helpers/fixtures.js +1 -2
  150. package/dist/test/helpers/fixtures.js.map +1 -1
  151. package/dist/test/helpers/page-access.d.ts +1 -0
  152. package/dist/test/helpers/page-access.js +6 -1
  153. package/dist/test/helpers/page-access.js.map +1 -1
  154. package/dist/test/integration/auth/current-password.test.d.ts +1 -0
  155. package/dist/test/integration/auth/current-password.test.js +65 -0
  156. package/dist/test/integration/auth/current-password.test.js.map +1 -0
  157. package/dist/test/integration/auth/password-reset.test.d.ts +1 -0
  158. package/dist/test/integration/auth/password-reset.test.js +126 -0
  159. package/dist/test/integration/auth/password-reset.test.js.map +1 -0
  160. package/dist/test/integration/auth/session-revocation.test.d.ts +1 -0
  161. package/dist/test/integration/auth/session-revocation.test.js +45 -0
  162. package/dist/test/integration/auth/session-revocation.test.js.map +1 -0
  163. package/dist/test/integration/auth/two-factor-codes.test.d.ts +1 -0
  164. package/dist/test/integration/auth/two-factor-codes.test.js +335 -0
  165. package/dist/test/integration/auth/two-factor-codes.test.js.map +1 -0
  166. package/dist/test/integration/auth/two-factor-password.test.js +5 -1
  167. package/dist/test/integration/auth/two-factor-password.test.js.map +1 -1
  168. package/dist/test/integration/auth/two-factor-token.test.d.ts +1 -0
  169. package/dist/test/integration/auth/two-factor-token.test.js +92 -0
  170. package/dist/test/integration/auth/two-factor-token.test.js.map +1 -0
  171. package/dist/test/integration/email-change.test.js +36 -0
  172. package/dist/test/integration/email-change.test.js.map +1 -1
  173. package/dist/test/integration/invite-extension-edit.test.js +0 -1
  174. package/dist/test/integration/invite-extension-edit.test.js.map +1 -1
  175. package/dist/test/integration/invite-link-status.test.d.ts +1 -0
  176. package/dist/test/integration/invite-link-status.test.js +110 -0
  177. package/dist/test/integration/invite-link-status.test.js.map +1 -0
  178. package/dist/test/integration/invite-resolution.test.js +0 -3
  179. package/dist/test/integration/invite-resolution.test.js.map +1 -1
  180. package/dist/test/integration/member-settings-access.test.js +17 -0
  181. package/dist/test/integration/member-settings-access.test.js.map +1 -1
  182. package/dist/test/integration/notification-unread-badge.test.d.ts +1 -0
  183. package/dist/test/integration/notification-unread-badge.test.js +92 -0
  184. package/dist/test/integration/notification-unread-badge.test.js.map +1 -0
  185. package/dist/test/integration/permission-warnings.test.d.ts +1 -0
  186. package/dist/test/integration/permission-warnings.test.js +71 -0
  187. package/dist/test/integration/permission-warnings.test.js.map +1 -0
  188. package/dist/test/integration/removed-member-notifications.test.d.ts +1 -0
  189. package/dist/test/integration/removed-member-notifications.test.js +80 -0
  190. package/dist/test/integration/removed-member-notifications.test.js.map +1 -0
  191. package/dist/test/integration/role-permission-ancestors.test.d.ts +1 -0
  192. package/dist/test/integration/role-permission-ancestors.test.js +146 -0
  193. package/dist/test/integration/role-permission-ancestors.test.js.map +1 -0
  194. package/dist/test/integration/tenant-lifecycle.test.js +0 -4
  195. package/dist/test/integration/tenant-lifecycle.test.js.map +1 -1
  196. package/dist/test/unit/auth-session-revocation.test.d.ts +1 -0
  197. package/dist/test/unit/auth-session-revocation.test.js +105 -0
  198. package/dist/test/unit/auth-session-revocation.test.js.map +1 -0
  199. package/dist/test/unit/db/email-normalization.test.js +0 -1
  200. package/dist/test/unit/db/email-normalization.test.js.map +1 -1
  201. package/dist/test/unit/db/notification-feed-filter.test.js +0 -16
  202. package/dist/test/unit/db/notification-feed-filter.test.js.map +1 -1
  203. package/dist/test/unit/db/notification-inbox.test.js +63 -13
  204. package/dist/test/unit/db/notification-inbox.test.js.map +1 -1
  205. package/dist/test/unit/db/notification-preferences.test.js +0 -17
  206. package/dist/test/unit/db/notification-preferences.test.js.map +1 -1
  207. package/dist/test/unit/implementations/dms/empty-menu-group.test.d.ts +1 -0
  208. package/dist/test/unit/implementations/dms/empty-menu-group.test.js +133 -0
  209. package/dist/test/unit/implementations/dms/empty-menu-group.test.js.map +1 -0
  210. package/dist/test/unit/implementations/dms/layout-banners.test.js +78 -1
  211. package/dist/test/unit/implementations/dms/layout-banners.test.js.map +1 -1
  212. package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.d.ts +1 -0
  213. package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js +149 -0
  214. package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js.map +1 -0
  215. package/dist/test/unit/implementations/dms/nav-badges.test.js +55 -4
  216. package/dist/test/unit/implementations/dms/nav-badges.test.js.map +1 -1
  217. package/dist/test/unit/implementations/dms/page-all-components-hidden.test.d.ts +1 -0
  218. package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js +118 -0
  219. package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js.map +1 -0
  220. package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js +16 -0
  221. package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js.map +1 -1
  222. package/dist/test/unit/implementations/dms/permission-preview-cost.test.js +5 -3
  223. package/dist/test/unit/implementations/dms/permission-preview-cost.test.js.map +1 -1
  224. package/dist/test/unit/implementations/dms/permission-preview-menu.test.js +29 -3
  225. package/dist/test/unit/implementations/dms/permission-preview-menu.test.js.map +1 -1
  226. package/dist/test/unit/implementations/dms/quick-actions-button.test.js +4 -2
  227. package/dist/test/unit/implementations/dms/quick-actions-button.test.js.map +1 -1
  228. package/dist/test/unit/implementations/dms/user-permissions-gate.test.js +2 -1
  229. package/dist/test/unit/implementations/dms/user-permissions-gate.test.js.map +1 -1
  230. package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js +2 -1
  231. package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js.map +1 -1
  232. package/dist/test/unit/interfaces/dms/component-children-permissions.test.js +7 -2
  233. package/dist/test/unit/interfaces/dms/component-children-permissions.test.js.map +1 -1
  234. package/dist/test/unit/interfaces/dms/form-watch-permissions.test.d.ts +1 -0
  235. package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js +133 -0
  236. package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js.map +1 -0
  237. package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.d.ts +1 -0
  238. package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js +149 -0
  239. package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js.map +1 -0
  240. package/dist/test/unit/interfaces/dms/invite-extension.test.js +13 -0
  241. package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
  242. package/dist/test/unit/interfaces/dms/member-access.test.js +27 -1
  243. package/dist/test/unit/interfaces/dms/member-access.test.js.map +1 -1
  244. package/dist/test/unit/interfaces/dms/nav-badge-tones.test.d.ts +1 -0
  245. package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js +31 -0
  246. package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js.map +1 -0
  247. package/dist/test/unit/interfaces/dms/page-extension.test.js +4 -1
  248. package/dist/test/unit/interfaces/dms/page-extension.test.js.map +1 -1
  249. package/dist/test/unit/interfaces/dms/permission-requirements.test.d.ts +1 -0
  250. package/dist/test/unit/interfaces/dms/permission-requirements.test.js +144 -0
  251. package/dist/test/unit/interfaces/dms/permission-requirements.test.js.map +1 -0
  252. package/dist/test/unit/interfaces/dms-base/column-display.test.js +70 -0
  253. package/dist/test/unit/interfaces/dms-base/column-display.test.js.map +1 -1
  254. package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js +38 -0
  255. package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js.map +1 -1
  256. package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js +6 -2
  257. package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js.map +1 -1
  258. package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js +1 -1
  259. package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js.map +1 -1
  260. package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js +2 -1
  261. package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js.map +1 -1
  262. package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js +2 -1
  263. package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js.map +1 -1
  264. package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js +2 -1
  265. package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js.map +1 -1
  266. package/dist/test/unit/pages/settings/account-activity-feed.test.js +2 -2
  267. package/dist/test/unit/pages/settings/account-activity-feed.test.js.map +1 -1
  268. package/dist/test/unit/pages/settings/account-activity.test.js +11 -2
  269. package/dist/test/unit/pages/settings/account-activity.test.js.map +1 -1
  270. package/dist/test/unit/pages/settings/invite-email-delivery.test.js +0 -1
  271. package/dist/test/unit/pages/settings/invite-email-delivery.test.js.map +1 -1
  272. package/dist/test/unit/pages/settings/invite-email-validation-option.test.d.ts +1 -0
  273. package/dist/test/unit/pages/settings/invite-email-validation-option.test.js +33 -0
  274. package/dist/test/unit/pages/settings/invite-email-validation-option.test.js.map +1 -0
  275. package/dist/test/unit/pages/settings/member-lists-page-size.test.d.ts +1 -0
  276. package/dist/test/unit/pages/settings/member-lists-page-size.test.js +22 -0
  277. package/dist/test/unit/pages/settings/member-lists-page-size.test.js.map +1 -0
  278. package/dist/test/unit/pages/settings/member-table-widths.test.js +2 -2
  279. package/dist/test/unit/pages/settings/member-table-widths.test.js.map +1 -1
  280. package/dist/test/unit/pages/settings/members-page.test.js +7 -10
  281. package/dist/test/unit/pages/settings/members-page.test.js.map +1 -1
  282. package/dist/test/unit/pages/settings/notifications-access-gate.test.js +3 -10
  283. package/dist/test/unit/pages/settings/notifications-access-gate.test.js.map +1 -1
  284. package/dist/test/unit/pages/settings/permission-tree-nodes.test.js +57 -0
  285. package/dist/test/unit/pages/settings/permission-tree-nodes.test.js.map +1 -1
  286. package/dist/test/unit/pages/settings/permission-warnings.test.d.ts +1 -0
  287. package/dist/test/unit/pages/settings/permission-warnings.test.js +49 -0
  288. package/dist/test/unit/pages/settings/permission-warnings.test.js.map +1 -0
  289. package/dist/test/unit/pages/settings/role-editor.test.js +16 -0
  290. package/dist/test/unit/pages/settings/role-editor.test.js.map +1 -1
  291. package/dist/test/unit/pages/settings/role-preview.test.js +7 -0
  292. package/dist/test/unit/pages/settings/role-preview.test.js.map +1 -1
  293. package/dist/test/unit/pages/settings/security-attention.test.d.ts +1 -0
  294. package/dist/test/unit/pages/settings/security-attention.test.js +74 -0
  295. package/dist/test/unit/pages/settings/security-attention.test.js.map +1 -0
  296. package/dist/test/unit/sanitize-user.test.d.ts +1 -0
  297. package/dist/test/unit/sanitize-user.test.js +21 -0
  298. package/dist/test/unit/sanitize-user.test.js.map +1 -0
  299. package/dist/test/unit/signup-email-validation.test.d.ts +1 -0
  300. package/dist/test/unit/signup-email-validation.test.js +79 -0
  301. package/dist/test/unit/signup-email-validation.test.js.map +1 -0
  302. package/dist/test/unit/validation/member-invite.schema.test.js +14 -52
  303. package/dist/test/unit/validation/member-invite.schema.test.js.map +1 -1
  304. package/dist/utils/account-notifications.d.ts +5 -0
  305. package/dist/utils/account-notifications.js +8 -0
  306. package/dist/utils/account-notifications.js.map +1 -1
  307. package/dist/utils/notification-emitter.d.ts +1 -1
  308. package/dist/utils/notification-emitter.js +1 -1
  309. package/dist/utils/notification-emitter.js.map +1 -1
  310. package/dist/utils/notification-tones.d.ts +2 -1
  311. package/dist/utils/notification-tones.js +5 -1
  312. package/dist/utils/notification-tones.js.map +1 -1
  313. package/dist/utils/one-time-code.d.ts +3 -0
  314. package/dist/utils/one-time-code.js +21 -0
  315. package/dist/utils/one-time-code.js.map +1 -0
  316. package/dist/utils/sign-in-monitor.d.ts +1 -0
  317. package/dist/utils/sign-in-monitor.js +3 -2
  318. package/dist/utils/sign-in-monitor.js.map +1 -1
  319. package/dist/utils/two-factor-codes.d.ts +10 -0
  320. package/dist/utils/two-factor-codes.js +76 -0
  321. package/dist/utils/two-factor-codes.js.map +1 -0
  322. package/dist/validation/auth.schema.d.ts +17 -0
  323. package/dist/validation/auth.schema.js +17 -6
  324. package/dist/validation/auth.schema.js.map +1 -1
  325. package/dist/validation/issue-message.d.ts +1 -0
  326. package/dist/validation/issue-message.js +9 -0
  327. package/dist/validation/issue-message.js.map +1 -0
  328. package/dist/validation/member-invite.schema.d.ts +1 -25
  329. package/dist/validation/member-invite.schema.js +2 -23
  330. package/dist/validation/member-invite.schema.js.map +1 -1
  331. package/frontend-vue/dms.frontend.ts +2 -0
  332. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot-validation.vue +3 -0
  333. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +105 -5
  334. package/frontend-vue/layers/dms-auth/i18n/locales/auth-en-GB.json +20 -4
  335. package/frontend-vue/layers/dms-auth/i18n/locales/auth-fr-FR.json +20 -4
  336. package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +25 -0
  337. package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +3 -2
  338. package/frontend-vue/layers/dms-core/app/types/composed-text.ts +64 -0
  339. package/frontend-vue/layers/dms-core/app/types/menu.ts +15 -0
  340. package/frontend-vue/layers/dms-core/app/utils/composedText.ts +227 -0
  341. package/frontend-vue/layers/dms-core/app/utils/formatter.ts +49 -0
  342. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +4 -1
  343. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +4 -1
  344. package/frontend-vue/layers/dms-layout/app/assets/css/main.css +20 -0
  345. package/frontend-vue/layers/dms-layout/app/build/components/layout/CommandPaletteAssistantAnswer.vue +75 -0
  346. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +17 -3
  347. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardFrame.vue +22 -0
  348. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +24 -10
  349. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidePanel.vue +139 -0
  350. package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +4 -2
  351. package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +90 -0
  352. package/frontend-vue/layers/dms-layout/app/build/components/layout/SidePanelHost.vue +17 -0
  353. package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +25 -43
  354. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/members/MemberRolePicker.vue +24 -2
  355. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixCategory.vue +70 -25
  356. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationPreferencesForm.vue +25 -10
  357. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/notificationDisplay.ts +41 -5
  358. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePreferencesSummary.vue +2 -1
  359. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue +20 -4
  360. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleEditor.vue +21 -0
  361. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionArea.vue +16 -2
  362. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionBranch.vue +1 -0
  363. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionLeaf.vue +13 -1
  364. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionTree.vue +9 -0
  365. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionWarning.vue +46 -0
  366. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +108 -29
  367. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-types.ts +2 -0
  368. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityDialogFrame.vue +6 -6
  369. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEmail.vue +7 -1
  370. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecuritySessions.vue +5 -4
  371. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityStatus.vue +4 -3
  372. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTwoFactor.vue +54 -18
  373. package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsNav.vue +13 -8
  374. package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/assistantGroups.ts +143 -0
  375. package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/useCommandPaletteAssistantMode.ts +249 -0
  376. package/frontend-vue/layers/dms-layout/app/build/composables/general/useGithubStarPrompt.ts +178 -0
  377. package/frontend-vue/layers/dms-layout/app/build/composables/layout/sidePanelState.ts +191 -0
  378. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useHeaderActionControls.ts +51 -0
  379. package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +113 -0
  380. package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useCategoryNavCards.ts +17 -10
  381. package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +45 -0
  382. package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfilePreferences.ts +8 -1
  383. package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityOverview.ts +50 -3
  384. package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts +3 -0
  385. package/frontend-vue/layers/dms-layout/app/build/utils/categoryPages.ts +1 -2
  386. package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +5 -0
  387. package/frontend-vue/layers/dms-layout/app/components/layout/DashboardSearch.vue +109 -7
  388. package/frontend-vue/layers/dms-layout/app/components/navigation/NavigationMenu.vue +19 -9
  389. package/frontend-vue/layers/dms-layout/app/composables/notification/useNotifications.ts +22 -40
  390. package/frontend-vue/layers/dms-layout/app/composables/useAppSidePanels.ts +96 -0
  391. package/frontend-vue/layers/dms-layout/app/composables/useCommandPaletteAssistant.ts +129 -0
  392. package/frontend-vue/layers/dms-layout/app/composables/useHeaderActions.ts +33 -11
  393. package/frontend-vue/layers/dms-layout/app/composables/useSidePanel.ts +41 -0
  394. package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +15 -0
  395. package/frontend-vue/layers/dms-layout/app/plugins/notification-stream.client.ts +1 -7
  396. package/frontend-vue/layers/dms-layout/app/plugins/side-panel-host.ts +13 -0
  397. package/frontend-vue/layers/dms-layout/app/types/page.ts +11 -1
  398. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +43 -13
  399. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +43 -13
  400. package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +45 -0
  401. package/frontend-vue/layers/dms-ui/app/build/components/modal/ModalEscHint.vue +28 -0
  402. package/frontend-vue/layers/dms-ui/app/build/components/table-view/IdentityCell.vue +36 -7
  403. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +57 -0
  404. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +19 -5
  405. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +22 -2
  406. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +118 -0
  407. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +5 -3
  408. package/frontend-vue/layers/dms-ui/app/build/composables/form/floatingSaveBars.ts +38 -0
  409. package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +66 -0
  410. package/frontend-vue/layers/dms-ui/app/build/composables/navigation/useNavBadges.ts +50 -9
  411. package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +7 -1
  412. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/chrome.ts +2 -2
  413. package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +14 -10
  414. package/frontend-vue/layers/dms-ui/app/build/utils/navBadge.ts +12 -0
  415. package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +4 -35
  416. package/frontend-vue/layers/dms-ui/app/build/utils/tone.ts +22 -0
  417. package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +117 -82
  418. package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +8 -5
  419. package/frontend-vue/layers/dms-ui/app/components/blocks/KeyValueListBlock.vue +38 -18
  420. package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +12 -1
  421. package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +26 -23
  422. package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +16 -1
  423. package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +7 -8
  424. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +28 -6
  425. package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +5 -1
  426. package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +4 -0
  427. package/frontend-vue/layers/dms-ui/app/components/status-pill/StatusPill.vue +7 -2
  428. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +7 -2
  429. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +48 -34
  430. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +13 -3
  431. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -14
  432. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -14
  433. package/frontend-vue/package.json +2 -2
  434. package/frontend-vue/pnpm-lock.yaml +5 -5
  435. package/frontend-vue/tests/activity-feed-fill-height.test.ts +107 -0
  436. package/frontend-vue/tests/category-nav-cards.test.ts +21 -13
  437. package/frontend-vue/tests/command-palette-assistant.test.ts +344 -0
  438. package/frontend-vue/tests/composed-text-blocks.test.ts +205 -0
  439. package/frontend-vue/tests/composed-text.test.ts +265 -0
  440. package/frontend-vue/tests/fixtures/dashboard-search-stub.ts +91 -0
  441. package/frontend-vue/tests/forgot-validation-resend.test.ts +234 -0
  442. package/frontend-vue/tests/form-display-options.test.ts +64 -0
  443. package/frontend-vue/tests/form-load-error.test.ts +160 -0
  444. package/frontend-vue/tests/form-saved-before-success.test.ts +110 -0
  445. package/frontend-vue/tests/github-star-prompt.test.ts +328 -0
  446. package/frontend-vue/tests/header-actions.test.ts +191 -0
  447. package/frontend-vue/tests/invites-edit-modal.test.ts +157 -0
  448. package/frontend-vue/tests/layout-banners.test.ts +56 -0
  449. package/frontend-vue/tests/member-role-picker.test.ts +26 -0
  450. package/frontend-vue/tests/menu-hidden-page.test.ts +93 -0
  451. package/frontend-vue/tests/nav-badge-tones.test.ts +274 -0
  452. package/frontend-vue/tests/nav-card-badge.test.ts +69 -0
  453. package/frontend-vue/tests/nav-card-grid-empty-category.test.ts +163 -0
  454. package/frontend-vue/tests/notification-popover-errors.test.ts +71 -37
  455. package/frontend-vue/tests/notification-preferences-groups.test.ts +268 -0
  456. package/frontend-vue/tests/notification-tone-contract.test.ts +70 -0
  457. package/frontend-vue/tests/page-fill-height.test.ts +9 -1
  458. package/frontend-vue/tests/page-no-visible-blocks.test.ts +202 -0
  459. package/frontend-vue/tests/profile-preferences-summary.test.ts +26 -2
  460. package/frontend-vue/tests/profile-security-summary.test.ts +121 -0
  461. package/frontend-vue/tests/role-permission-tree.test.ts +102 -8
  462. package/frontend-vue/tests/role-permissions.test.ts +178 -56
  463. package/frontend-vue/tests/side-panels.test.ts +470 -0
  464. package/frontend-vue/tests/signup-invitation-link.test.ts +71 -2
  465. package/frontend-vue/tests/table-actions-column-width.test.ts +51 -1
  466. package/frontend-vue/tests/table-cell-sublines.test.ts +466 -0
  467. package/frontend-vue/tests/table-metric-cells.test.ts +4 -0
  468. package/frontend-vue/tests/table-view-chrome.test.ts +2 -2
  469. package/frontend-vue/tests/vue-inventory.test.ts +1 -1
  470. package/package.json +2 -2
  471. package/skills/dms/REFERENCE.md +1 -1
  472. package/skills/dms/SKILL.md +7 -0
@@ -0,0 +1,466 @@
1
+ // @vitest-environment jsdom
2
+ /**
3
+ * The secondary lines of the table cells — under a status pill, under an
4
+ * identity's name, under a `two_line` primary — draw a composed text from the
5
+ * row in the reader's language and in the tone the row gives it; an identity
6
+ * without a value stands as its empty label and icon.
7
+ */
8
+ import {
9
+ createApp,
10
+ defineComponent,
11
+ h,
12
+ ref,
13
+ type App,
14
+ type VNodeChild,
15
+ } from "vue";
16
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
17
+ import { createI18n } from "vue-i18n";
18
+ import type { DataType } from "../layers/dms-core/app/composables/data-types/useDataType";
19
+ import { setRegionalPreferencesSource } from "../layers/dms-core/app/utils/regional";
20
+ import { readSubline } from "../layers/dms-ui/app/build/composables/data-types/cellHelpers";
21
+ import { registerMetricCellTypes } from "../layers/dms-ui/app/build/composables/data-types/metricCells";
22
+ import { registerTwoLineCellType } from "../layers/dms-ui/app/build/composables/data-types/twoLineCell";
23
+
24
+ // The renderers registerDefaults imports beside the identity's.
25
+ const stub = { default: { render: () => null } };
26
+ vi.mock("@nuxt/ui/components/Avatar.vue", () => stub);
27
+ vi.mock("@nuxt/ui/components/Badge.vue", () => stub);
28
+ vi.mock("@nuxt/ui/components/Link.vue", () => stub);
29
+ vi.mock("@nuxt/ui/runtime/vue/components/Icon.vue", () => stub);
30
+
31
+ vi.mock("../layers/dms-ui/app/composables/useFileReadUrls", () => ({
32
+ useFileReadUrls: () => ({ getUrl: () => undefined, resolve: () => {} }),
33
+ }));
34
+
35
+ const IdentityCell = (
36
+ await import(
37
+ "../layers/dms-ui/app/build/components/table-view/IdentityCell.vue"
38
+ )
39
+ ).default;
40
+
41
+ const i18n = createI18n({
42
+ legacy: false,
43
+ locale: "en",
44
+ fallbackLocale: "en",
45
+ missingWarn: false,
46
+ fallbackWarn: false,
47
+ messages: {
48
+ en: {
49
+ saas: {
50
+ invoice: {
51
+ open: "Open",
52
+ retry: "Payment failed · retry {date}",
53
+ due: "Due {date}",
54
+ },
55
+ plan_seats:
56
+ "{price} × {count} seat / {interval} | {price} × {count} seats / {interval}",
57
+ month: "month",
58
+ at_risk: "At risk",
59
+ renews_in: "Renews tomorrow | Renews in {count} days",
60
+ automatic: "Automatic",
61
+ joined: "Joined",
62
+ },
63
+ },
64
+ fr: {
65
+ saas: {
66
+ invoice: { retry: "Paiement refusé · nouvel essai le {date}" },
67
+ },
68
+ },
69
+ },
70
+ });
71
+
72
+ type Formatter = (
73
+ value: unknown,
74
+ locale: string,
75
+ options?: unknown,
76
+ row?: Record<string, unknown>,
77
+ ) => VNodeChild;
78
+
79
+ const formatters = new Map<string, DataType["formatter"]>();
80
+ const register = (dataType: DataType) =>
81
+ formatters.set(dataType.id, dataType.formatter);
82
+ registerMetricCellTypes(register);
83
+ registerTwoLineCellType(register);
84
+ // The column types a two-line primary is written by.
85
+ register({
86
+ id: "price",
87
+ formatter: {
88
+ default: (value) => `€${Number(value).toFixed(2)}`,
89
+ },
90
+ });
91
+ register({
92
+ id: "select",
93
+ formatter: {
94
+ default: (value, _locale, options) =>
95
+ (
96
+ options as { items: Array<{ value: string; label: string }> }
97
+ ).items.find((item) => item.value === value)?.label,
98
+ },
99
+ });
100
+
101
+ const format = (id: string, kind: "default" | "empty" = "default") =>
102
+ formatters.get(id)![kind] as Formatter;
103
+
104
+ let app: App | undefined;
105
+
106
+ const render = (content: () => VNodeChild): HTMLElement => {
107
+ const container = document.createElement("div");
108
+ app = createApp(defineComponent({ setup: () => content }));
109
+ app.component(
110
+ "UIcon",
111
+ defineComponent({
112
+ props: { name: { type: String, default: "" } },
113
+ setup: (props) => () => h("i", { "data-icon": props.name }),
114
+ }),
115
+ );
116
+ app.component(
117
+ "UAvatar",
118
+ defineComponent({
119
+ props: { text: { type: String, default: "" } },
120
+ setup: (props) => () => h("span", { "data-avatar": "" }, props.text),
121
+ }),
122
+ );
123
+ app.component("UBadge", defineComponent({ setup: () => () => h("b") }));
124
+ app.mount(container);
125
+ return container;
126
+ };
127
+
128
+ const text = (element: Element | null | undefined) =>
129
+ element?.textContent?.replace(/[\u00a0\u202f]/g, " ");
130
+
131
+ const retry = {
132
+ key: "$saas.invoice.retry",
133
+ params: { date: { type: "date", value: "2026-10-10", format: "day" } },
134
+ };
135
+
136
+ beforeEach(() => {
137
+ i18n.global.locale.value = "en";
138
+ setRegionalPreferencesSource(() => ({ timeZone: "UTC" }));
139
+ vi.stubGlobal("useI18n", () => ({
140
+ t: i18n.global.t,
141
+ locale: i18n.global.locale,
142
+ }));
143
+ vi.stubGlobal("useTranslation", () => ({
144
+ processI18n: (value: string) =>
145
+ value.startsWith("$") ? i18n.global.t(value.slice(1)) : value,
146
+ }));
147
+ vi.stubGlobal("useDataTypes", () => ({
148
+ getDataType: (id: string) => ({ id, formatter: formatters.get(id) }),
149
+ }));
150
+ vi.stubGlobal("useCurrentUser", () => ({ user: ref(null) }));
151
+ });
152
+
153
+ afterEach(() => {
154
+ app?.unmount();
155
+ app = undefined;
156
+ vi.unstubAllGlobals();
157
+ setRegionalPreferencesSource(() => ({}));
158
+ });
159
+
160
+ describe("readSubline", () => {
161
+ const processText = (value: unknown) =>
162
+ typeof value === "string" ? value.replace(/^\$/, "i18n:") : "composed";
163
+
164
+ it("reads a text with its tone, a composed text, a string, or nothing", () => {
165
+ const reading = { processText, isStringTranslated: true };
166
+ expect(readSubline({ text: retry, tone: "error" }, reading)).toEqual({
167
+ text: "composed",
168
+ tone: "error",
169
+ });
170
+ expect(readSubline(retry, reading)).toEqual({ text: "composed" });
171
+ expect(readSubline("$saas.due", reading)).toEqual({
172
+ text: "i18n:saas.due",
173
+ });
174
+ expect(readSubline(null, reading)).toBeUndefined();
175
+ expect(readSubline({ text: "" }, reading)).toBeUndefined();
176
+ });
177
+
178
+ it("keeps a data string as written when strings are not texts", () => {
179
+ expect(
180
+ readSubline("$29 a month", { processText, isStringTranslated: false }),
181
+ ).toEqual({ text: "$29 a month" });
182
+ });
183
+ });
184
+
185
+ describe("status_pill sub-line", () => {
186
+ const options = {
187
+ tones: { open: "info" },
188
+ subField: "statusDetail",
189
+ typeOptions: { items: [{ value: "open", label: "$saas.invoice.open" }] },
190
+ };
191
+
192
+ it("composes the row's sub-line in the reader's language, in the row's tone", () => {
193
+ const cell = render(() =>
194
+ format("status_pill")("open", "en", options, {
195
+ statusDetail: { text: retry, tone: "error" },
196
+ }),
197
+ );
198
+ const sub = cell.querySelector("span.text-xs");
199
+ expect(text(sub)).toBe("Payment failed · retry Oct 10");
200
+ expect(sub?.className).toContain("text-error");
201
+ });
202
+
203
+ it("follows a language switch", () => {
204
+ i18n.global.locale.value = "fr";
205
+ const cell = render(() =>
206
+ format("status_pill")("open", "fr", options, { statusDetail: retry }),
207
+ );
208
+ expect(text(cell.querySelector("span.text-xs"))).toBe(
209
+ "Paiement refusé · nouvel essai le 10 oct.",
210
+ );
211
+ });
212
+
213
+ it("draws a sub-line without a tone in subTone, else in the pill's", () => {
214
+ const due = {
215
+ key: "saas.invoice.due",
216
+ params: { date: { type: "date", value: "2026-10-28", format: "day" } },
217
+ };
218
+ const muted = render(() =>
219
+ format("status_pill")(
220
+ "open",
221
+ "en",
222
+ { ...options, subTone: "muted" },
223
+ {
224
+ statusDetail: due,
225
+ },
226
+ ),
227
+ );
228
+ expect(muted.querySelector("span.text-xs")?.className).toContain(
229
+ "text-muted",
230
+ );
231
+ app?.unmount();
232
+ const pillTone = render(() =>
233
+ format("status_pill")("open", "en", options, { statusDetail: due }),
234
+ );
235
+ expect(text(pillTone.querySelector("span.text-xs"))).toBe("Due Oct 28");
236
+ expect(pillTone.querySelector("span.text-xs")?.className).toContain(
237
+ "text-info",
238
+ );
239
+ });
240
+ });
241
+
242
+ describe("two_line", () => {
243
+ it("writes the primary line with the column's type, the plan's price under it", () => {
244
+ const cell = render(() =>
245
+ format("two_line")(
246
+ "pro",
247
+ "en",
248
+ {
249
+ subField: "planDetail",
250
+ columnType: "select",
251
+ typeOptions: { items: [{ value: "pro", label: "Business" }] },
252
+ },
253
+ {
254
+ planDetail: {
255
+ key: "saas.plan_seats",
256
+ params: {
257
+ price: { type: "money", value: 2900, currency: "EUR" },
258
+ count: { type: "count", value: 23 },
259
+ interval: { key: "saas.month" },
260
+ },
261
+ },
262
+ },
263
+ ),
264
+ );
265
+ const [primary, sub] = cell.querySelectorAll("span > span");
266
+ expect(text(primary)).toBe("Business");
267
+ expect(text(sub)).toBe("€29.00 × 23 seats / month");
268
+ expect(sub?.className).toContain("text-muted");
269
+ });
270
+
271
+ it("keeps an amount in its column format, what it means in the row's tone", () => {
272
+ const cell = render(() =>
273
+ format("two_line")(
274
+ 49,
275
+ "en",
276
+ { subField: "mrrNote", columnType: "price" },
277
+ { mrrNote: { text: "$saas.at_risk", tone: "error" } },
278
+ ),
279
+ );
280
+ const [primary, sub] = cell.querySelectorAll("span > span");
281
+ expect(text(primary)).toBe("€49.00");
282
+ expect(text(sub)).toBe("At risk");
283
+ expect(sub?.className).toContain("text-error");
284
+ });
285
+
286
+ it("reads its primary line off another field, even when the value is empty", () => {
287
+ const cell = render(() =>
288
+ format("two_line", "empty")(
289
+ null,
290
+ "en",
291
+ {
292
+ primaryField: "renewal",
293
+ subField: "renewalDate",
294
+ subTone: "warning",
295
+ },
296
+ {
297
+ renewal: {
298
+ key: "saas.renews_in",
299
+ params: { count: { type: "count", value: 3 } },
300
+ },
301
+ renewalDate: {
302
+ key: "saas.invoice.due",
303
+ params: { date: { type: "date", value: "2026-10-12" } },
304
+ },
305
+ },
306
+ ),
307
+ );
308
+ const [primary, sub] = cell.querySelectorAll("span > span");
309
+ expect(text(primary)).toBe("Renews in 3 days");
310
+ expect(text(sub)).toBe("Due Oct 12, 2026");
311
+ expect(sub?.className).toContain("text-warning");
312
+ });
313
+
314
+ it("draws its empty label for an empty primary line, and no sub-line for none", () => {
315
+ const cell = render(() =>
316
+ format("two_line", "empty")(
317
+ undefined,
318
+ "en",
319
+ { subField: "note", emptyLabel: "$saas.automatic" },
320
+ {},
321
+ ),
322
+ );
323
+ expect(text(cell)).toBe("Automatic");
324
+ expect(cell.querySelectorAll("span > span")).toHaveLength(1);
325
+ app?.unmount();
326
+ expect(
327
+ text(render(() => format("two_line", "empty")(null, "en", {}, {}))),
328
+ ).toBe("—");
329
+ });
330
+
331
+ it("composes a value that is itself a composed text", () => {
332
+ const cell = render(() =>
333
+ format("two_line")(
334
+ {
335
+ key: "saas.renews_in",
336
+ params: { count: { type: "count", value: 1 } },
337
+ },
338
+ "en",
339
+ {},
340
+ {},
341
+ ),
342
+ );
343
+ expect(text(cell)).toBe("Renews tomorrow");
344
+ });
345
+ });
346
+
347
+ describe("IdentityCell", () => {
348
+ const mountIdentity = (props: Record<string, unknown>) =>
349
+ render(() => h(IdentityCell, props));
350
+
351
+ it("stands an empty row as its muted label and icon tile", () => {
352
+ const cell = mountIdentity({
353
+ title: "",
354
+ emptyLabel: "Automatic",
355
+ emptyIcon: "i-ph-robot",
356
+ });
357
+ expect(text(cell)).toBe("Automatic");
358
+ expect(cell.querySelector("[data-icon]")?.getAttribute("data-icon")).toBe(
359
+ "i-ph-robot",
360
+ );
361
+ expect(cell.querySelector("[data-avatar]")).toBeNull();
362
+ expect(cell.querySelector(".text-muted")).not.toBeNull();
363
+ });
364
+
365
+ it("keeps the avatar and the name of a row with a value", () => {
366
+ const cell = mountIdentity({
367
+ title: "Camille Martin",
368
+ emptyLabel: "Automatic",
369
+ emptyIcon: "i-ph-robot",
370
+ });
371
+ expect(text(cell)).toContain("Camille Martin");
372
+ expect(text(cell.querySelector("[data-avatar]"))).toBe("CM");
373
+ expect(cell.querySelector("[data-icon]")).toBeNull();
374
+ });
375
+
376
+ it("draws the subtitle under the empty label, in its tone", () => {
377
+ const cell = mountIdentity({
378
+ title: "",
379
+ subtitle: "Refund · duplicate charge",
380
+ subtitleClass: "text-warning",
381
+ emptyLabel: "Automatic",
382
+ });
383
+ const sub = cell.querySelector(".text-xs");
384
+ expect(text(sub)).toBe("Refund · duplicate charge");
385
+ expect(sub?.className).toContain("text-warning");
386
+ });
387
+
388
+ it("lets the subtitle stand as the name without an empty label, as before", () => {
389
+ const cell = mountIdentity({ title: "", subtitle: "ada@example.com" });
390
+ expect(text(cell.querySelector(".truncate"))).toBe("ada@example.com");
391
+ expect(cell.querySelector(".text-xs")).toBeNull();
392
+ });
393
+ });
394
+
395
+ describe("identity sub-line", () => {
396
+ const identityFormatter = async () => {
397
+ const registered = new Map<string, DataType["formatter"]>();
398
+ // Auto-imports of the layer the other default types are registered with.
399
+ vi.stubGlobal("h", h);
400
+ for (const name of [
401
+ "formatNumber",
402
+ "formatPrice",
403
+ "formatPercentage",
404
+ "formatTimeSpan",
405
+ "formatDate",
406
+ "getBooleanLabel",
407
+ ]) {
408
+ vi.stubGlobal(name, () => "");
409
+ }
410
+ vi.stubGlobal("useDataTypes", () => ({
411
+ registerDataType: (dataType: DataType) =>
412
+ registered.set(dataType.id, dataType.formatter),
413
+ }));
414
+ const { registerDefaultDataTypes } = await import(
415
+ "../layers/dms-ui/app/build/composables/data-types/registerDefaults"
416
+ );
417
+ registerDefaultDataTypes();
418
+ return registered.get("identity")!;
419
+ };
420
+
421
+ it("composes a subtitle the row gives as a composed text, in its tone", async () => {
422
+ const identity = await identityFormatter();
423
+ const cell = render(() =>
424
+ (identity.default as Formatter)(
425
+ "Camille Martin",
426
+ "en",
427
+ { subtitleField: "ownerState" },
428
+ { ownerState: { text: "$saas.joined", tone: "success" } },
429
+ ),
430
+ );
431
+ const sub = cell.querySelector(".text-xs");
432
+ expect(text(sub)).toBe("Joined");
433
+ expect(sub?.className).toContain("text-success");
434
+ });
435
+
436
+ it("keeps a plain subtitle as written, in subtitleTone", async () => {
437
+ const identity = await identityFormatter();
438
+ const cell = render(() =>
439
+ (identity.default as Formatter)(
440
+ "Acme",
441
+ "en",
442
+ { subtitleField: "price", subtitleTone: "muted" },
443
+ { price: "$29 a month" },
444
+ ),
445
+ );
446
+ const sub = cell.querySelector(".text-xs");
447
+ expect(text(sub)).toBe("$29 a month");
448
+ expect(sub?.className).toContain("text-muted");
449
+ });
450
+
451
+ it("draws an empty issuer as its translated empty label and icon", async () => {
452
+ const identity = await identityFormatter();
453
+ const cell = render(() =>
454
+ (identity.empty as Formatter)(
455
+ null,
456
+ "en",
457
+ { emptyLabel: "$saas.automatic", emptyIcon: "i-ph-robot" },
458
+ {},
459
+ ),
460
+ );
461
+ expect(text(cell)).toBe("Automatic");
462
+ expect(cell.querySelector("[data-icon]")?.getAttribute("data-icon")).toBe(
463
+ "i-ph-robot",
464
+ );
465
+ });
466
+ });
@@ -71,6 +71,10 @@ describe("metric cells", () => {
71
71
  vi.stubGlobal("useTranslation", () => ({
72
72
  processI18n: (text: string) => text.replace(/^\$/, "i18n:"),
73
73
  }));
74
+ vi.stubGlobal("useI18n", () => ({
75
+ t: (key: string) => `i18n:${key}`,
76
+ locale: { value: "en-GB" },
77
+ }));
74
78
  });
75
79
 
76
80
  afterEach(() => {
@@ -40,7 +40,7 @@ describe("TableView layout", () => {
40
40
  expect(resolveTableChrome("full", everything).search).toBe("toggle");
41
41
  });
42
42
 
43
- it("reduces the compact layout to an open search field", () => {
43
+ it("reduces the compact layout to an open search field and the page size picker", () => {
44
44
  expect(resolveTableChrome("compact", everything)).toEqual({
45
45
  caption: false,
46
46
  search: "field",
@@ -49,7 +49,7 @@ describe("TableView layout", () => {
49
49
  refresh: false,
50
50
  menu: false,
51
51
  columnMenus: false,
52
- pageSize: false,
52
+ pageSize: true,
53
53
  });
54
54
  });
55
55
 
@@ -2,7 +2,7 @@ import { readFileSync, readdirSync, statSync } from "node:fs";
2
2
  import { join, relative } from "node:path";
3
3
  import { describe, expect, it } from "vitest";
4
4
 
5
- const EXPECTED_VUE_FILES = 264;
5
+ const EXPECTED_VUE_FILES = 271;
6
6
 
7
7
  function walk(directory: string): string[] {
8
8
  return readdirSync(directory).flatMap((name) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms",
3
- "version": "0.6.1",
3
+ "version": "0.7.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/AntelopeJS/dms.git"
@@ -37,7 +37,7 @@
37
37
  "@antelopejs/interface-data-api": ">=0.2.0 <1.0.0",
38
38
  "@antelopejs/interface-database": ">=0.1.8 <1.0.0",
39
39
  "@antelopejs/interface-database-decorators": ">=0.1.7 <1.0.0",
40
- "@antelopejs/interface-dms": ">=0.4.1 <0.5.0",
40
+ "@antelopejs/interface-dms": ">=0.4.2 <0.5.0",
41
41
  "@antelopejs/interface-email": ">=0.0.5 <1.0.0",
42
42
  "@antelopejs/interface-file-storage": ">=0.1.3 <1.0.0",
43
43
  "archiver": "^7.0.1",
@@ -13,7 +13,7 @@ List a section to see its files:
13
13
  | `docs/02.building/` | Project setup (**the common case**), every config key, pages & components, navigation, actions, backend services (hooks, notifications, realtime, replayable jobs, HTML/email rendering, export jobs), localization, frontend layer & `ajs dms` CLI, distributable modules, deployment, troubleshooting |
14
14
  | `docs/03.auth-and-tenancy/` | Auth flows (JWT, 2FA, invites), decorators & RBAC, multi-tenant data, SaaS mode |
15
15
  | `docs/04.components/` | Component catalog: charts/widgets, layout, forms, tables, DataTypes, DataController, file storage |
16
- | `docs/05.extending-the-dashboard/` | Dashboard chrome, theming, custom DataTypes (frontend side), table-view displays, component events, period filtering |
16
+ | `docs/05.extending-the-dashboard/` | Dashboard chrome (header actions, command-palette sources and assistant mode, widgets, overlays), theming, custom DataTypes (frontend side), table-view displays, component events, period filtering |
17
17
  | `docs/06.frontend-composables/` | Composables a custom frontend module's Vue calls: auth'd requests, realtime, page context, UI toolkit |
18
18
  | `docs/07.interfaces/` | The contract reference for `@antelopejs/interface-dms`, one folder per domain: `core`, `auth`, `base`, `notifications`, `html-render` |
19
19
 
@@ -35,6 +35,13 @@ For the framework underneath (the core, `ajs` CLI, interfaces as versioned contr
35
35
  A URL names the record of its page with `{{params.id}}` / `{{query.X}}` (filled from the page URL;
36
36
  nothing is fetched while one is unresolved), and `.watch(FormEvents.SUBMIT_SUCCESS,
37
37
  BlockFunctions.REFRESH_PAGE)` makes the page's data blocks re-fetch after a form saves.
38
+ A text naming values (an amount, a date, a count) is sent as a `ComposedText` —
39
+ `{ key, params: { amount: { type: "money", value: 92200, currency: "EUR" } } }` — that the
40
+ browser writes in the reader's language: StatGroup / KeyValueList / Banner texts and layout
41
+ banners (`RegisterLayoutBanner({ resolve })` → `{ text, actions }`) take it; never format text server-side.
42
+ A table cell's secondary line is a row field holding one (or `{ text, tone }`), named by
43
+ `StatusPillDisplay({ subField })`, `IdentityDisplay({ subtitleField })` or
44
+ `TwoLineDisplay({ subField })`; `IdentityDisplay({ emptyLabel, emptyIcon })` draws an empty row.
38
45
  - **It's interfaces all the way down.** Everything you consume from the DMS is an AntelopeJS
39
46
  interface imported as an `@antelopejs/interface-dms/...` subpath (see the imports below);
40
47
  a distributable module exposes its own from a companion `@antelopejs/interface-<name>` package listed in `antelopeJs.implements`.