@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
@@ -8,6 +8,10 @@ interface DisplayProps {
8
8
  }
9
9
 
10
10
  const props = defineProps<DisplayProps>();
11
+ // The field's options, spread on the display as on its input: the
12
+ // formatter reads them as a table cell does (a status' labels and tones,
13
+ // a select's items).
14
+ const options = useAttrs();
11
15
 
12
16
  const { getDataType } = useDataTypes();
13
17
  const { locale, t } = useI18n();
@@ -29,7 +33,7 @@ const formattedValue = computed(() => {
29
33
  if (isEmptyValue(props.modelValue)) return EMPTY_FALLBACK;
30
34
  const formatter = dataType.value?.formatter?.default;
31
35
  if (!formatter) return String(props.modelValue);
32
- return formatter(props.modelValue, locale.value, props);
36
+ return formatter(props.modelValue, locale.value, options);
33
37
  });
34
38
 
35
39
  const isVNodeValue = computed(() => isVNode(formattedValue.value));
@@ -5,6 +5,7 @@ import {
5
5
  type FormKind,
6
6
  saveBarState,
7
7
  } from "../../build/composables/form/formFooter";
8
+ import { trackFloatingSaveBar } from "../../build/composables/form/floatingSaveBars";
8
9
  import DmsUnsavedStatus from "../../build/components/form/UnsavedStatus.vue";
9
10
 
10
11
  /**
@@ -107,6 +108,9 @@ const ui = computed(() =>
107
108
  theme({ variant: props.variant, hidden: state.value.isHidden }),
108
109
  );
109
110
  const buttons = computed(() => BUTTONS[props.variant]);
111
+ trackFloatingSaveBar(
112
+ () => props.variant === "floating" && !state.value.isHidden,
113
+ );
110
114
 
111
115
  // Empty while there is nothing to save: the hidden bar keeps its line.
112
116
  const statusText = computed(() => {
@@ -70,8 +70,13 @@ const theme = tv({
70
70
  },
71
71
  variants: {
72
72
  variant: {
73
- soft: { root: "rounded-full" },
74
- outline: { root: "rounded-full border bg-transparent" },
73
+ // A pill wider than its cell keeps its shape: the label gives way
74
+ // with an ellipsis instead of the pill being cut at the cell's edge.
75
+ soft: { root: "max-w-full rounded-full", label: "min-w-0 truncate" },
76
+ outline: {
77
+ root: "max-w-full rounded-full border bg-transparent",
78
+ label: "min-w-0 truncate",
79
+ },
75
80
  // A state line may run long: it wraps like text instead of a pill.
76
81
  text: { root: "whitespace-normal" },
77
82
  },
@@ -33,6 +33,7 @@ import type {
33
33
  TableViewPaginationMode,
34
34
  TableViewSourceConfig,
35
35
  TableViewReorderConfig,
36
+ TableViewTab,
36
37
  } from "../../composables/table-view/types";
37
38
  import {
38
39
  TABLE_DISPLAY_ID,
@@ -563,7 +564,7 @@ interface ResolvedTab {
563
564
  to?: string;
564
565
  toPage?: string;
565
566
  countFrom?: string;
566
- navBadge?: boolean;
567
+ navBadge?: TableViewTab["navBadge"];
567
568
  }
568
569
 
569
570
  // A configured "all" tab stands in for the implicit one, at its own place.
@@ -1175,7 +1176,11 @@ watch(
1175
1176
  const source = resolvedTabs.value.find((entry) => entry.id === tab.id);
1176
1177
  if (!source?.navBadge || tab.count === undefined) continue;
1177
1178
  const fullId = source.to ? source.toPage : pageId;
1178
- if (fullId) setNavBadge(fullId, tab.count > 0 ? String(tab.count) : "");
1179
+ const tone =
1180
+ typeof source.navBadge === "object" ? source.navBadge.tone : undefined;
1181
+ if (fullId) {
1182
+ setNavBadge(fullId, tab.count > 0 ? String(tab.count) : "", tone);
1183
+ }
1179
1184
  }
1180
1185
  },
1181
1186
  { immediate: true },
@@ -1,6 +1,6 @@
1
1
  import type { FormSubmitEvent } from "@nuxt/ui";
2
2
  import { z } from "zod";
3
- import { unref } from "vue";
3
+ import { onMounted, unref } from "vue";
4
4
  import type { FormProps, FormFetchResponse, FormSubmitResponse } from "./types";
5
5
  import { jsonSchemaToZod } from "json-schema-to-zod";
6
6
  import { FormEvents } from "./types/events";
@@ -62,8 +62,8 @@ export interface UseFormOptions {
62
62
  showFieldErrors?: (errors: FormServerFieldError[]) => boolean;
63
63
  /**
64
64
  * Called once a submit succeeded and the values are the saved ones (or
65
- * back to the opening ones for an `action` form), before any redirect:
66
- * the form has nothing unsaved from there on.
65
+ * back to the opening ones for an `action` form), before the success event
66
+ * goes out and any redirect: the form has nothing unsaved from there on.
67
67
  */
68
68
  onSaved?: () => void;
69
69
  }
@@ -458,32 +458,35 @@ function watchFieldChanges(
458
458
  ) => void,
459
459
  ): void {
460
460
  if (!componentId) return;
461
+ const id = componentId;
461
462
  const previousValuesJson: Record<string, string> = {};
462
463
 
463
- watch(
464
- () => state.value,
465
- (newState) => {
466
- for (const fieldId of Object.keys(newState)) {
467
- if (INTERNAL_STATE_KEYS.has(fieldId)) continue;
468
-
469
- let newJson: string;
470
- try {
471
- newJson = JSON.stringify(newState[fieldId]);
472
- } catch {
473
- newJson = String(newState[fieldId]);
474
- }
475
- if (newJson !== previousValuesJson[fieldId]) {
476
- sendComponentEvent(FormEvents.FIELD_CHANGE, componentId, {
477
- fieldId,
478
- value: newState[fieldId],
479
- formValues: newState,
480
- });
481
- previousValuesJson[fieldId] = newJson;
482
- }
464
+ // From mount, once `useWatch` listens: the values the form starts from
465
+ // (defaults, loaded row) reach the watch rules too, not only later edits.
466
+ onMounted(() => {
467
+ watch(() => state.value, sendChanges, { deep: true, immediate: true });
468
+ });
469
+
470
+ function sendChanges(newState: Record<string, unknown>): void {
471
+ for (const fieldId of Object.keys(newState)) {
472
+ if (INTERNAL_STATE_KEYS.has(fieldId)) continue;
473
+
474
+ let newJson: string;
475
+ try {
476
+ newJson = JSON.stringify(newState[fieldId]);
477
+ } catch {
478
+ newJson = String(newState[fieldId]);
483
479
  }
484
- },
485
- { deep: true },
486
- );
480
+ if (newJson !== previousValuesJson[fieldId]) {
481
+ sendComponentEvent(FormEvents.FIELD_CHANGE, id, {
482
+ fieldId,
483
+ value: newState[fieldId],
484
+ formValues: newState,
485
+ });
486
+ previousValuesJson[fieldId] = newJson;
487
+ }
488
+ }
489
+ }
487
490
  }
488
491
 
489
492
  /**
@@ -748,6 +751,16 @@ export const useForm = (props: FormProps, options: UseFormOptions = {}) => {
748
751
  );
749
752
  };
750
753
 
754
+ /** A submit the server accepted: nothing is left unsaved. */
755
+ const markSubmitSaved = (): void => {
756
+ submitSucceeded.value = true;
757
+ // A form sending something new each time starts over from the values it
758
+ // opened with; any other keeps what it saved as its new starting point.
759
+ if (props.kind === "action") restoreInitialValues();
760
+ else initialValues.value = snapshotFormState(state.value);
761
+ options.onSaved?.();
762
+ };
763
+
751
764
  const handleSubmitSuccess = async (
752
765
  response: FormSubmitResponse | undefined,
753
766
  plainData: FormData,
@@ -755,11 +768,6 @@ export const useForm = (props: FormProps, options: UseFormOptions = {}) => {
755
768
  showSubmitSuccessToast(response);
756
769
  showSubmitNotice(response);
757
770
  props.onSuccessCallback?.(response, plainData);
758
- // A form sending something new each time starts over from the values it
759
- // opened with; any other keeps what it saved as its new starting point.
760
- if (props.kind === "action") restoreInitialValues();
761
- else initialValues.value = snapshotFormState(state.value);
762
- options.onSaved?.();
763
771
  if (props.redirectOnSuccess) {
764
772
  const target = replaceUrlVariables(
765
773
  props.redirectOnSuccess,
@@ -777,10 +785,16 @@ export const useForm = (props: FormProps, options: UseFormOptions = {}) => {
777
785
  });
778
786
  };
779
787
 
780
- /** Sends a body to the submit URL, through the form's submit events. */
788
+ /**
789
+ * Sends a body to the submit URL, through the form's submit events.
790
+ * `onAccepted` runs once the server took it, before the success event goes
791
+ * out: what watches that event (a form page's way back to its list) finds
792
+ * the form with nothing unsaved, and leaves it without asking.
793
+ */
781
794
  const sendSubmit = async (
782
795
  submitUrl: string,
783
796
  body: FormData,
797
+ onAccepted?: () => void,
784
798
  ): Promise<FormSubmitResponse | undefined> => {
785
799
  let submitResponse: FormSubmitResponse | undefined;
786
800
  await executeSubmit(
@@ -791,6 +805,7 @@ export const useForm = (props: FormProps, options: UseFormOptions = {}) => {
791
805
  headers: { [CONTENT_LANGUAGE_HEADER]: "*" },
792
806
  }).then((res) => {
793
807
  submitResponse = res;
808
+ onAccepted?.();
794
809
  return res;
795
810
  }),
796
811
  {
@@ -831,8 +846,7 @@ export const useForm = (props: FormProps, options: UseFormOptions = {}) => {
831
846
 
832
847
  loading.value = true;
833
848
  try {
834
- const response = await sendSubmit(target.url, plainData);
835
- submitSucceeded.value = true;
849
+ const response = await sendSubmit(target.url, plainData, markSubmitSaved);
836
850
  await handleSubmitSuccess(response, plainData);
837
851
  } catch (error) {
838
852
  reportSubmitError(error);
@@ -7,6 +7,7 @@ import type { TableViewDisplayCapabilities } from "./display";
7
7
  import type { CustomButton } from "./custom-button";
8
8
  import type { FormProps } from "../../form/types";
9
9
  import type { TableProps, TableFilter } from "../../../types/table";
10
+ import type { Tone } from "../../../types/tone";
10
11
  import type { BlockAction } from "../../../build/components/blocks/BlockActions.vue";
11
12
 
12
13
  export interface QueryParamFilter {
@@ -37,13 +38,22 @@ export interface TableViewTab {
37
38
  toPage?: string;
38
39
  /** Data API location whose row total a link tab shows. */
39
40
  countFrom?: string;
40
- /** Keeps the nav badge of the page it stands for up to date. */
41
- navBadge?: boolean;
41
+ /**
42
+ * Keeps the nav badge of the page it stands for up to date; `{ tone }`
43
+ * draws it in that tone.
44
+ */
45
+ navBadge?: boolean | TableViewTabNavBadge;
46
+ }
47
+
48
+ /** A tab's nav badge drawn in a tone (interface-dms `TableViewTabNavBadge`). */
49
+ export interface TableViewTabNavBadge {
50
+ tone?: Tone;
42
51
  }
43
52
 
44
53
  /**
45
54
  * How much a table draws around its rows (backend `layout`): the full
46
- * dashboard grid, or the compact list of a settings page.
55
+ * dashboard grid, or the compact list of a settings page (no caption,
56
+ * refresh, ⋯ menu nor column menus; the footer keeps the page size picker).
47
57
  */
48
58
  export type TableViewLayout = "full" | "compact";
49
59
 
@@ -276,6 +276,13 @@
276
276
  "unsaved_changes": "Unsaved changes",
277
277
  "fetch_error_title": "Failed to fetch data",
278
278
  "fetch_error_unknown": "An unexpected error occurred. Please try again later.",
279
+ "load_error": {
280
+ "error_title": "Couldn't load this entry",
281
+ "error_description": "Check your connection, then try again. Nothing can be saved until the entry loads.",
282
+ "forbidden_title": "You can't view this entry",
283
+ "forbidden_description": "Your role doesn't let you view this entry, so the form can't open on its current values. Ask an administrator for access.",
284
+ "retry": "Try again"
285
+ },
279
286
  "select_date": "Select date",
280
287
  "relation": {
281
288
  "selected_count": "{count} selected",
@@ -489,11 +496,7 @@
489
496
  "notifications": {
490
497
  "categories": {
491
498
  "system": "System",
492
- "system_desc": "Core system notifications and security alerts",
493
- "module_one": "Security",
494
- "module_one_desc": "Security monitoring and threat detection",
495
- "module_two": "Logistics",
496
- "module_two_desc": "Shipping, inventory and supply chain updates"
499
+ "system_desc": "Core system notifications and security alerts"
497
500
  },
498
501
  "subjects": {
499
502
  "general": "General",
@@ -508,12 +511,6 @@
508
511
  "automation_desc": "Notifications sent by automation procedures",
509
512
  "updates": "Module updates",
510
513
  "updates_desc": "Available updates for the project's Antelope modules (development mode)",
511
- "module_one_alerts": "Security alerts",
512
- "module_one_alerts_desc": "Critical security events requiring immediate attention",
513
- "module_one_updates": "Threat reports",
514
- "module_one_updates_desc": "Updates on security threats and vulnerabilities",
515
- "module_two_notifications": "Shipment updates",
516
- "module_two_notifications_desc": "Updates on shipping and inventory",
517
514
  "updates_badge": "Developer mode"
518
515
  },
519
516
  "preferences": {
@@ -544,8 +541,8 @@
544
541
  "description": "You can now sign in with {provider}. Not you? Change your password and review your sign-in methods in Security."
545
542
  },
546
543
  "password_reset": {
547
- "title": "Password reset with an email link",
548
- "description": "The link was sent to {email}. Not you? Someone can read that mailbox: secure it first, then reset your password again."
544
+ "title": "Password reset with an email code",
545
+ "description": "The code was sent to {email}. Not you? Someone can read that mailbox: secure it first, then reset your password again."
549
546
  },
550
547
  "email_changed": {
551
548
  "title": "Sign-in email changed to {email}",
@@ -599,6 +596,10 @@
599
596
  "description": "Someone entered a wrong password in the last {minutes} minutes. Don't recognise this? Change your password and turn on two-factor authentication in Security.",
600
597
  "description_two_factor": "Someone entered a wrong password in the last {minutes} minutes; two-factor authentication still stood in the way. Don't recognise this? Change your password in Security."
601
598
  },
599
+ "two_factor_lockout": {
600
+ "title": "{count} wrong two-factor codes on your account",
601
+ "description": "Someone gave your password, then {count} wrong two-factor codes within {minutes} minutes; codes are refused for a while. Don't recognise this? Your password is known: change it in Security."
602
+ },
602
603
  "roles_changed": {
603
604
  "title": "Your roles are now {roles}",
604
605
  "title_one": "Your role is now {roles}",
@@ -678,7 +679,8 @@
678
679
  "empty_title": "No activity yet",
679
680
  "error_title": "Activity could not be loaded",
680
681
  "error_description": "Check your connection, then try again.",
681
- "retry": "Try again"
682
+ "retry": "Try again",
683
+ "list_label": "Activity"
682
684
  },
683
685
  "leave_guard": {
684
686
  "title": "Discard unsaved changes?",
@@ -277,6 +277,13 @@
277
277
  "error_not_submitted": "Le formulaire n'a pas été soumis",
278
278
  "fetch_error_title": "Échec de la récupération des données",
279
279
  "fetch_error_unknown": "Une erreur inattendue s'est produite. Veuillez réessayer plus tard.",
280
+ "load_error": {
281
+ "error_title": "Impossible de charger cet élément",
282
+ "error_description": "Vérifiez votre connexion, puis réessayez. Rien ne peut être enregistré tant que l'élément n'est pas chargé.",
283
+ "forbidden_title": "Vous ne pouvez pas voir cet élément",
284
+ "forbidden_description": "Votre rôle ne vous permet pas de voir cet élément, le formulaire ne peut donc pas s'ouvrir sur ses valeurs actuelles. Demandez l'accès à un administrateur.",
285
+ "retry": "Réessayer"
286
+ },
280
287
  "select_date": "Sélectionner une date",
281
288
  "relation": {
282
289
  "selected_count": "{count} sélectionné(s)",
@@ -490,11 +497,7 @@
490
497
  "notifications": {
491
498
  "categories": {
492
499
  "system": "Système",
493
- "system_desc": "Notifications système et alertes de sécurité",
494
- "module_one": "Sécurité",
495
- "module_one_desc": "Surveillance et détection des menaces",
496
- "module_two": "Logistique",
497
- "module_two_desc": "Expéditions, inventaire et chaîne d'approvisionnement"
500
+ "system_desc": "Notifications système et alertes de sécurité"
498
501
  },
499
502
  "subjects": {
500
503
  "general": "Général",
@@ -509,12 +512,6 @@
509
512
  "automation_desc": "Notifications envoyées par les procédures d'automatisation",
510
513
  "updates": "Mises à jour des modules",
511
514
  "updates_desc": "Mises à jour disponibles des modules Antelope du projet (mode développement)",
512
- "module_one_alerts": "Alertes de sécurité",
513
- "module_one_alerts_desc": "Événements critiques nécessitant une attention immédiate",
514
- "module_one_updates": "Rapports de menaces",
515
- "module_one_updates_desc": "Mises à jour sur les menaces et vulnérabilités de sécurité",
516
- "module_two_notifications": "Suivi des expéditions",
517
- "module_two_notifications_desc": "Mises à jour sur les expéditions et l'inventaire",
518
515
  "updates_badge": "Mode développeur"
519
516
  },
520
517
  "preferences": {
@@ -545,8 +542,8 @@
545
542
  "description": "Vous pouvez désormais vous connecter avec {provider}. Ce n'était pas vous ? Changez votre mot de passe et vérifiez vos méthodes de connexion dans Sécurité."
546
543
  },
547
544
  "password_reset": {
548
- "title": "Mot de passe réinitialisé par lien e-mail",
549
- "description": "Le lien a été envoyé à {email}. Ce n'était pas vous ? Quelqu'un a accès à cette boîte mail : sécurisez-la d'abord, puis réinitialisez à nouveau votre mot de passe."
545
+ "title": "Mot de passe réinitialisé par code e-mail",
546
+ "description": "Le code a été envoyé à {email}. Ce n'était pas vous ? Quelqu'un a accès à cette boîte mail : sécurisez-la d'abord, puis réinitialisez à nouveau votre mot de passe."
550
547
  },
551
548
  "email_changed": {
552
549
  "title": "E-mail de connexion changé pour {email}",
@@ -600,6 +597,10 @@
600
597
  "description": "Quelqu'un a saisi un mauvais mot de passe ces {minutes} dernières minutes. Vous ne reconnaissez pas ces tentatives ? Changez votre mot de passe et activez la double authentification dans Sécurité.",
601
598
  "description_two_factor": "Quelqu'un a saisi un mauvais mot de passe ces {minutes} dernières minutes ; la double authentification a tout de même barré la route. Vous ne reconnaissez pas ces tentatives ? Changez votre mot de passe dans Sécurité."
602
599
  },
600
+ "two_factor_lockout": {
601
+ "title": "{count} codes de double authentification erronés sur votre compte",
602
+ "description": "Quelqu'un a saisi votre mot de passe, puis {count} codes de double authentification erronés en moins de {minutes} minutes ; les codes sont refusés pour un temps. Vous ne reconnaissez pas ces tentatives ? Votre mot de passe est connu : changez-le dans Sécurité."
603
+ },
603
604
  "roles_changed": {
604
605
  "title": "Vos rôles sont désormais : {roles}",
605
606
  "title_one": "Votre rôle est désormais : {roles}",
@@ -679,7 +680,8 @@
679
680
  "empty_title": "Aucune activité pour l'instant",
680
681
  "error_title": "Impossible de charger l'activité",
681
682
  "error_description": "Vérifiez votre connexion, puis réessayez.",
682
- "retry": "Réessayer"
683
+ "retry": "Réessayer",
684
+ "list_label": "Activité"
683
685
  },
684
686
  "leave_guard": {
685
687
  "title": "Abandonner les modifications non enregistrées ?",
@@ -11,7 +11,7 @@
11
11
  "license": "Apache-2.0",
12
12
  "packageManager": "pnpm@10.6.5",
13
13
  "engines": {
14
- "@antelopejs/dms-frontend": ">=0.5.0 <0.6.0"
14
+ "@antelopejs/dms-frontend": ">=0.5.1 <0.6.0"
15
15
  },
16
16
  "scripts": {
17
17
  "typecheck": "ajs dms verify-source --layer \"$PWD\" --local-package @antelopejs/dms=.. --local-package @antelopejs/interface-dms=../../interface-dms",
@@ -73,7 +73,7 @@
73
73
  },
74
74
  "devDependencies": {
75
75
  "@antelopejs/core": ">=1.13.4 <2",
76
- "@antelopejs/dms-frontend": ">=0.5.0 <0.6.0",
76
+ "@antelopejs/dms-frontend": ">=0.5.1 <0.6.0",
77
77
  "@eslint/js": "^8.57.0",
78
78
  "@inertiajs/vue3": "^3.7.0",
79
79
  "@nuxt/ui": "4.10.0",
@@ -157,8 +157,8 @@ importers:
157
157
  specifier: '>=1.13.4 <2'
158
158
  version: 1.13.5
159
159
  '@antelopejs/dms-frontend':
160
- specifier: '>=0.5.0 <0.6.0'
161
- version: 0.5.0(@antelopejs/core@1.13.5)
160
+ specifier: '>=0.5.1 <0.6.0'
161
+ version: 0.5.1(@antelopejs/core@1.13.5)
162
162
  '@eslint/js':
163
163
  specifier: ^8.57.0
164
164
  version: 8.57.0
@@ -234,8 +234,8 @@ packages:
234
234
  engines: {node: '>=20.19'}
235
235
  hasBin: true
236
236
 
237
- '@antelopejs/dms-frontend@0.5.0':
238
- resolution: {integrity: sha512-pwoE21xA5H3AqwHgLdMJN9F8K7uo9VLzBp97JbPm3cXo10TGVCwWSgoEBJ/1+2mgS9HlWmwUDzkAqwhG0YtktA==}
237
+ '@antelopejs/dms-frontend@0.5.1':
238
+ resolution: {integrity: sha512-ykrqlHfYF+BqNy+h4FuZBbqAW6UjviauCiI8cQCW1M55MzIxk2Ar3ZnMH1VKH8QsfDBBNapDik5rd/AMLQ33dw==}
239
239
  engines: {node: '>=20.12.0'}
240
240
  hasBin: true
241
241
  peerDependencies:
@@ -4205,7 +4205,7 @@ snapshots:
4205
4205
  semver: 7.8.5
4206
4206
  typescript: 5.9.3
4207
4207
 
4208
- '@antelopejs/dms-frontend@0.5.0(@antelopejs/core@1.13.5)':
4208
+ '@antelopejs/dms-frontend@0.5.1(@antelopejs/core@1.13.5)':
4209
4209
  dependencies:
4210
4210
  '@antelopejs/core': 1.13.5
4211
4211
  chokidar: 4.0.3
@@ -0,0 +1,107 @@
1
+ import { computed, createSSRApp, defineComponent, h, ref } from "vue";
2
+ import { renderToString } from "vue/server-renderer";
3
+ import { afterEach, beforeEach, expect, it, vi } from "vitest";
4
+ import ActivityFeed from "../layers/dms-ui/app/components/activity-feed/ActivityFeed.vue";
5
+
6
+ const items = ref<Array<Record<string, unknown>>>([]);
7
+
8
+ vi.mock("../layers/dms-ui/app/build/composables/blocks/useBlockItems", () => ({
9
+ useBlockItems: () => ({
10
+ items: computed(() => items.value),
11
+ isPending: computed(() => false),
12
+ hasError: computed(() => false),
13
+ refresh: async () => {},
14
+ }),
15
+ }));
16
+
17
+ const Slot = defineComponent({
18
+ props: { title: { type: String, default: undefined } },
19
+ setup:
20
+ (props, { slots, attrs }) =>
21
+ () =>
22
+ h("div", attrs, [props.title, slots.default?.()]),
23
+ });
24
+
25
+ async function render(props: Record<string, unknown>): Promise<string> {
26
+ const app = createSSRApp({
27
+ render: () =>
28
+ h(ActivityFeed, {
29
+ componentId: "activity",
30
+ pageId: "settings",
31
+ title: "Recent account activity",
32
+ fetchUrl: "/settings/activity",
33
+ ...props,
34
+ }),
35
+ });
36
+ for (const name of [
37
+ "DmsCard",
38
+ "UIcon",
39
+ "USkeleton",
40
+ "UButton",
41
+ "ULink",
42
+ "NuxtLink",
43
+ ]) {
44
+ app.component(name, Slot);
45
+ }
46
+ return renderToString(app);
47
+ }
48
+
49
+ /** The opening tag of the feed's scroll area, if it has one. */
50
+ function scrollArea(html: string): string | undefined {
51
+ return html.match(/<div[^>]*role="region"[^>]*>/)?.[0];
52
+ }
53
+
54
+ beforeEach(() => {
55
+ items.value = Array.from({ length: 25 }, (_, index) => ({
56
+ id: `e${index}`,
57
+ title: `Entry ${index}`,
58
+ date: new Date(Date.UTC(2026, 9, 9, 23 - index)).toISOString(),
59
+ }));
60
+ vi.stubGlobal("useI18n", () => ({ locale: ref("en-GB"), t: String }));
61
+ vi.stubGlobal("useTranslation", () => ({ processI18n: String }));
62
+ });
63
+
64
+ afterEach(() => vi.unstubAllGlobals());
65
+
66
+ it("filling its cell, scrolls the entries in a focusable region sized to nothing", async () => {
67
+ const area = scrollArea(await render({ fillHeight: true }));
68
+ expect(area).toBeDefined();
69
+ expect(area).toContain('tabindex="0"');
70
+ expect(area).toContain('aria-label="Recent account activity"');
71
+ // Sized to nothing, it leaves the row's height to the cards beside it…
72
+ expect(area).toMatch(/\bcontain-size\b/);
73
+ expect(area).toMatch(/\boverflow-y-auto\b/);
74
+ expect(area).toMatch(/\bh-full\b/);
75
+ // …and once the grid stacks its cells, takes its own height, capped.
76
+ expect(area).toContain(
77
+ "[@container_style(--dms-grid-tracks:1)]:max-h-[24rem]",
78
+ );
79
+ expect(area).toContain(
80
+ "[@container_style(--dms-grid-tracks:1)]:contain-none",
81
+ );
82
+ });
83
+
84
+ it("keeps each day's separator on top of the scrolled entries", async () => {
85
+ const html = await render({ fillHeight: true });
86
+ expect(html).toMatch(/<div[^>]*class="[^"]*\bsticky top-0\b[^"]*"[^>]*><h3/);
87
+ });
88
+
89
+ it("names the region after the feed when it has no title", async () => {
90
+ const area = scrollArea(await render({ fillHeight: true, title: undefined }));
91
+ expect(area).toContain('aria-label="dms.activity_feed.list_label"');
92
+ });
93
+
94
+ it("grows with its entries by default, without a scroll area", async () => {
95
+ const html = await render({});
96
+ expect(scrollArea(html)).toBeUndefined();
97
+ expect(html).not.toContain("contain-size");
98
+ expect(html).not.toContain("sticky");
99
+ });
100
+
101
+ it("shows only the latest `maxItems` entries", async () => {
102
+ const html = await render({ fillHeight: true, maxItems: 20 });
103
+ expect(html).toContain("Entry 0");
104
+ expect(html).toContain("Entry 19");
105
+ expect(html).not.toContain("Entry 20");
106
+ expect(new Set(html.match(/Entry \d+/g)).size).toBe(20);
107
+ });
@@ -1,15 +1,9 @@
1
1
  import { afterEach, beforeEach, expect, it, vi } from "vitest";
2
2
  import { computed, ref } from "vue";
3
3
  import { useCategoryNavCards } from "../layers/dms-layout/app/build/composables/navigation/useCategoryNavCards";
4
+ import type { NavBadge } from "../layers/dms-ui/app/build/composables/navigation/useNavBadges";
4
5
 
5
- const badges = ref<Record<string, string>>({});
6
-
7
- vi.mock(
8
- "../layers/dms-ui/app/build/composables/navigation/useNavBadges",
9
- () => ({
10
- useNavBadges: () => ({ badges }),
11
- }),
12
- );
6
+ const badges = ref<Record<string, NavBadge>>({});
13
7
  vi.mock(
14
8
  "../layers/dms-core/app/build/composables/auth/usePermissionPreview",
15
9
  () => ({
@@ -40,7 +34,10 @@ const tree = ref({
40
34
  children: {
41
35
  profile: node("settings.user.profile", { icon: "i-ph-user" }),
42
36
  security: node("settings.user.security", { badge: "1" }),
43
- notifications: node("settings.user.notifications", { badge: "4" }),
37
+ notifications: node("settings.user.notifications", {
38
+ badge: "4",
39
+ badgeTone: "warning",
40
+ }),
44
41
  locked: node("settings.user.locked", { hasAccess: false }),
45
42
  },
46
43
  childrenOrders: ["profile", "security", "notifications", "locked"],
@@ -57,6 +54,7 @@ beforeEach(() => {
57
54
  vi.stubGlobal("computed", computed);
58
55
  vi.stubGlobal("useI18n", () => ({ t: (key: string) => key }));
59
56
  vi.stubGlobal("useSiteLayout", () => ({ siteLayoutTree: tree }));
57
+ vi.stubGlobal("useDmsState", () => badges);
60
58
  });
61
59
 
62
60
  afterEach(() => {
@@ -74,21 +72,31 @@ it("makes a card of each page the viewer can open, in menu order", () => {
74
72
  title: "$settings.user.profile",
75
73
  icon: "i-ph-user",
76
74
  to: "/settings/user/profile",
77
- state: undefined,
75
+ badge: undefined,
78
76
  });
79
77
  });
80
78
 
81
79
  it("shows the navigation badge, a fresher count first", () => {
82
80
  badges.value = {
83
- "settings.user.notifications": "",
84
- "settings.user.security": "2",
81
+ "settings.user.notifications": { label: "" },
82
+ "settings.user.security": { label: "2", tone: "error" },
85
83
  };
86
84
  const { cards } = useCategoryNavCards(() => "settings.user");
87
- expect(cards.value.map((card) => card.state)).toEqual([
85
+ expect(cards.value.map((card) => card.badge)).toEqual([
88
86
  undefined,
89
87
  "2",
90
88
  undefined,
91
89
  ]);
90
+ expect(cards.value[1]?.badgeTone).toBe("error");
91
+ });
92
+
93
+ it("draws the served badge in the tone the server gave it", () => {
94
+ const { cards } = useCategoryNavCards(() => "settings.user");
95
+ expect(cards.value[2]).toMatchObject({ badge: "4", badgeTone: "warning" });
96
+ expect(cards.value[1]).toMatchObject({ badge: "1", badgeTone: undefined });
97
+ // The badge is the card's corner pill, not the live state line under the
98
+ // description that a fetched card closes on.
99
+ expect(cards.value[2]).not.toHaveProperty("state");
92
100
  });
93
101
 
94
102
  it("lists nothing for a category the site layout does not hold", () => {