@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,118 @@
1
+ import { h, type VNodeChild } from "vue";
2
+ import type { DataType } from "#dms-core/app/composables/data-types/useDataType";
3
+ import { useComposedText } from "../../../../../dms-core/app/composables/translation/useComposedText";
4
+ import {
5
+ type ComposableText,
6
+ isComposedText,
7
+ } from "../../../../../dms-core/app/utils/composedText";
8
+ import { readRowField, readSubline, toneClass, type Row } from "./cellHelpers";
9
+
10
+ const EMPTY = "—";
11
+ const PRIMARY_CLASS = "text-highlighted truncate text-[13px] font-medium";
12
+ const EMPTY_PRIMARY_CLASS = "text-dimmed truncate text-[13px]";
13
+ const SUB_CLASS = "truncate text-xs";
14
+
15
+ interface TwoLineOptions {
16
+ /** Row field holding the primary line, in place of the column's value. */
17
+ primaryField?: string;
18
+ /** Row field holding the secondary line. */
19
+ subField?: string;
20
+ /** Tone of the secondary line when the row gives none. */
21
+ subTone?: string;
22
+ /** Text of an empty primary line. */
23
+ emptyLabel?: string;
24
+ /** The column's own data type, which writes its value. */
25
+ columnType?: string;
26
+ /** The column's own type options (a select's items). */
27
+ typeOptions?: unknown;
28
+ }
29
+
30
+ const isBlank = (value: unknown): boolean =>
31
+ value === null || value === undefined || value === "";
32
+
33
+ /** The column's value written by the column's own data type. */
34
+ function formatColumnValue(
35
+ value: unknown,
36
+ locale: string,
37
+ opts: TwoLineOptions,
38
+ row: Row,
39
+ ): VNodeChild {
40
+ const { getDataType } = useDataTypes();
41
+ const formatter = opts.columnType
42
+ ? getDataType(opts.columnType)?.formatter
43
+ : undefined;
44
+ const format = formatter?.cell ?? formatter?.default;
45
+ if (!format) return String(value);
46
+ return format(value, locale, opts.typeOptions, row) as VNodeChild;
47
+ }
48
+
49
+ /** The primary line, or nothing when the row has none to show. */
50
+ function readPrimary(
51
+ value: unknown,
52
+ locale: string,
53
+ opts: TwoLineOptions,
54
+ row: Row,
55
+ ): VNodeChild | undefined {
56
+ const { processText } = useComposedText();
57
+ if (opts.primaryField) {
58
+ const text = processText(
59
+ readRowField(row, opts.primaryField) as ComposableText,
60
+ );
61
+ return text || undefined;
62
+ }
63
+ if (isBlank(value)) return undefined;
64
+ if (isComposedText(value)) return processText(value);
65
+ return formatColumnValue(value, locale, opts, row);
66
+ }
67
+
68
+ /**
69
+ * `two_line`: a primary line — the column's value in its own format, or a row
70
+ * field's text — over a secondary line read off the row, in the row's tone,
71
+ * else `subTone`, else muted. No avatar.
72
+ */
73
+ function renderTwoLine(
74
+ value: unknown,
75
+ locale: string,
76
+ options: unknown,
77
+ row: Row,
78
+ ) {
79
+ const { processText } = useComposedText();
80
+ const opts = (options ?? {}) as TwoLineOptions;
81
+ const primary = readPrimary(value, locale, opts, row);
82
+ const sub = readSubline(readRowField(row, opts.subField), {
83
+ processText,
84
+ isStringTranslated: true,
85
+ });
86
+ return h("span", { class: "flex min-w-0 flex-col leading-tight" }, [
87
+ primary === undefined
88
+ ? h(
89
+ "span",
90
+ { class: EMPTY_PRIMARY_CLASS },
91
+ opts.emptyLabel ? processText(opts.emptyLabel) : EMPTY,
92
+ )
93
+ : h("span", { class: PRIMARY_CLASS }, [primary]),
94
+ sub
95
+ ? h(
96
+ "span",
97
+ {
98
+ class: [SUB_CLASS, toneClass(sub.tone ?? opts.subTone, "muted")],
99
+ title: sub.text,
100
+ },
101
+ sub.text,
102
+ )
103
+ : null,
104
+ ]);
105
+ }
106
+
107
+ /**
108
+ * The `two_line` cell data type. It draws an empty value too: its primary
109
+ * line may come from another field, and its secondary line always does.
110
+ */
111
+ export const registerTwoLineCellType = (
112
+ registerDataType: (dataType: DataType) => void,
113
+ ) => {
114
+ registerDataType({
115
+ id: "two_line",
116
+ formatter: { default: renderTwoLine, empty: renderTwoLine },
117
+ });
118
+ };
@@ -45,8 +45,10 @@ export function useColumnValueRenderer() {
45
45
  const { locale } = useI18n();
46
46
 
47
47
  // A display also reads the column's own type options (`typeOptions`): a
48
- // select's items name the values it draws. A display declared without
49
- // options reads them at the top level, as it always did.
48
+ // select's items name the values it draws; and the column's own type id
49
+ // (`columnType`), so it can write the value as the column would (an amount
50
+ // under `two_line`). A display declared without options reads the type
51
+ // options at the top level, as it always did.
50
52
  const resolveRenderer = (column: RenderableColumn) => {
51
53
  const typeOptions = column.type?.inputComponent?.options as
52
54
  | Record<string, unknown>
@@ -56,7 +58,7 @@ export function useColumnValueRenderer() {
56
58
  const displayOptions = column.display.options ?? typeOptions;
57
59
  return {
58
60
  typeId: column.display.type,
59
- options: { ...displayOptions, typeOptions },
61
+ options: { ...displayOptions, typeOptions, columnType: column.type?.id },
60
62
  };
61
63
  };
62
64
 
@@ -0,0 +1,38 @@
1
+ import {
2
+ computed,
3
+ onBeforeUnmount,
4
+ onMounted,
5
+ ref,
6
+ shallowReactive,
7
+ watch,
8
+ } from "vue";
9
+
10
+ // Only mounted bars count, so a server render never adds to it.
11
+ const shownBars = shallowReactive(new Set<symbol>());
12
+
13
+ /**
14
+ * Whether a floating save bar (the one sticking to the bottom of the panel)
15
+ * is on screen: what else sits in that corner steps aside for it.
16
+ */
17
+ export const isFloatingSaveBarShown = computed(() => shownBars.size > 0);
18
+
19
+ /** Counts the calling floating save bar while `isShown` holds. */
20
+ export function trackFloatingSaveBar(isShown: () => boolean): void {
21
+ const id = Symbol("floating-save-bar");
22
+ const isMounted = ref(false);
23
+ watch(
24
+ () => isMounted.value && isShown(),
25
+ (shown) => {
26
+ if (shown) shownBars.add(id);
27
+ else shownBars.delete(id);
28
+ },
29
+ { immediate: true },
30
+ );
31
+ onMounted(() => {
32
+ isMounted.value = true;
33
+ });
34
+ onBeforeUnmount(() => {
35
+ isMounted.value = false;
36
+ shownBars.delete(id);
37
+ });
38
+ }
@@ -0,0 +1,66 @@
1
+ import { type Ref, ref } from "vue";
2
+ import { apiErrorStatus } from "#dms-core/app/composables/useFieldErrors";
3
+ import { HTTP_FORBIDDEN } from "#dms-core/app/utils/http-status";
4
+
5
+ /**
6
+ * Why a form could not load the record it edits: `forbidden` when the server
7
+ * refused the caller the read (a role that may edit rows but not view them),
8
+ * `error` for anything else (a network failure, a server error, a row gone).
9
+ */
10
+ export type FormLoadFailure = "forbidden" | "error";
11
+
12
+ /** The cached load of a form's record (`useDmsAsyncData`), as far as it is read. */
13
+ export interface FormLoadSource<T> {
14
+ data: Ref<T | null>;
15
+ error: Ref<unknown>;
16
+ refresh(): Promise<void>;
17
+ }
18
+
19
+ /** Where a form stands with the record it loads, and how to try again. */
20
+ export interface FormRecordLoad {
21
+ /** Set while the last load failed: the form shows it instead of its fields. */
22
+ failure: Ref<FormLoadFailure | null>;
23
+ /** Set while `retry` loads the record again. */
24
+ retrying: Ref<boolean>;
25
+ /** Load the record again; the form opens on it once it arrives. */
26
+ retry(): Promise<void>;
27
+ }
28
+
29
+ /** The failure a load error stands for; `null` when there is none. */
30
+ export function formLoadFailure(error: unknown): FormLoadFailure | null {
31
+ if (!error) return null;
32
+ return apiErrorStatus(error) === HTTP_FORBIDDEN ? "forbidden" : "error";
33
+ }
34
+
35
+ /**
36
+ * Follow a form's record load: `apply` receives the record once it loaded,
37
+ * and only then. A failed load is never applied, not even the values a
38
+ * previous opening left in the cache: a form showing them, or its defaults,
39
+ * would read as the record and save over it.
40
+ */
41
+ export function trackFormRecordLoad<T>(
42
+ load: FormLoadSource<T>,
43
+ apply: (payload: T) => void,
44
+ ): FormRecordLoad {
45
+ const failure = ref<FormLoadFailure | null>(null);
46
+ const retrying = ref(false);
47
+ const settle = (): void => {
48
+ failure.value = formLoadFailure(load.error.value);
49
+ const payload = load.data.value;
50
+ if (!failure.value && payload) apply(payload);
51
+ };
52
+ settle();
53
+ return {
54
+ failure,
55
+ retrying,
56
+ async retry() {
57
+ retrying.value = true;
58
+ try {
59
+ await load.refresh();
60
+ } finally {
61
+ retrying.value = false;
62
+ }
63
+ settle();
64
+ },
65
+ };
66
+ }
@@ -1,24 +1,65 @@
1
+ import type { Tone } from "../../../types/tone";
2
+
3
+ /** A page's navigation badge: its label (`""` for none) and its tone. */
4
+ export interface NavBadge {
5
+ label: string;
6
+ /** Neutral (grey) when absent. */
7
+ tone?: Tone;
8
+ }
9
+
10
+ /** A menu entry as the server serves it, as far as its badge goes. */
11
+ export interface ServedNavBadge {
12
+ fullId?: string;
13
+ badge?: string;
14
+ /** The tone of a counted badge; neutral when absent. */
15
+ badgeTone?: Tone;
16
+ }
17
+
1
18
  /**
2
19
  * Fresh counts a page publishes for its navigation entry, by page full id
3
- * (`settings.workspace.members` → `"7"`, `""` for none). The server counts a table
4
- * view tab declared with `navBadge: true` when the menu loads; the table
5
- * publishes its own counter here once shown, which navigation surfaces draw
6
- * over the server's badge.
20
+ * (`settings.workspace.members` → `{ label: "7" }`, `""` for none), with
21
+ * their tone. The server counts a table view tab declared with `navBadge`
22
+ * when the menu loads; the table publishes its own counter here once shown,
23
+ * which navigation surfaces draw over the server's badge.
7
24
  *
8
25
  * Shared state, so a count published on one page stays shown on the others.
9
26
  */
10
27
  export const useNavBadges = () => {
11
- const badges = useDmsState<Record<string, string>>(
28
+ const badges = useDmsState<Record<string, NavBadge>>(
12
29
  "dms-nav-badges",
13
30
  () => ({}),
14
31
  );
15
32
 
16
33
  /** Sets, or with `undefined` clears, the badge of a page. */
17
- function setNavBadge(fullId: string, badge: string | undefined): void {
18
- if (badges.value[fullId] === badge) return;
34
+ function setNavBadge(
35
+ fullId: string,
36
+ label: string | undefined,
37
+ tone?: Tone,
38
+ ): void {
39
+ const current = badges.value[fullId];
40
+ if (current?.label === label && current?.tone === tone) return;
19
41
  const { [fullId]: _previous, ...rest } = badges.value;
20
- badges.value = badge === undefined ? rest : { ...rest, [fullId]: badge };
42
+ if (label === undefined) {
43
+ if (current !== undefined) badges.value = rest;
44
+ return;
45
+ }
46
+ badges.value = { ...rest, [fullId]: tone ? { label, tone } : { label } };
47
+ }
48
+
49
+ /**
50
+ * The badge `entry` shows: the one its page published, fresher, or the
51
+ * one the server served; undefined when it has none.
52
+ */
53
+ function navBadgeOf(entry: ServedNavBadge): NavBadge | undefined {
54
+ const live =
55
+ entry.fullId === undefined ? undefined : badges.value[entry.fullId];
56
+ const served: NavBadge | undefined =
57
+ entry.badge === undefined
58
+ ? undefined
59
+ : { label: entry.badge, tone: entry.badgeTone };
60
+ const badge = live ?? served;
61
+ return badge?.label ? badge : undefined;
21
62
  }
22
63
 
23
- return { badges, setNavBadge };
64
+ return { badges, setNavBadge, navBadgeOf };
24
65
  };
@@ -134,7 +134,13 @@ export const useTable = <T extends Data>(props: UseTableProps<T>) => {
134
134
 
135
135
  const tableConfig = shallowRef({
136
136
  data: tableData,
137
- columns: columns.value,
137
+ // Read on each update rather than once: labelled row actions are sized on
138
+ // the rows listed, which a table opened by client-side navigation only
139
+ // receives after it is set up. A copy taken then keeps the width of an
140
+ // empty list, and the rows' buttons are cut.
141
+ get columns() {
142
+ return columns.value;
143
+ },
138
144
 
139
145
  ...stateHandlers,
140
146
 
@@ -35,7 +35,7 @@ const LAYOUT_CHROME: Record<TableViewLayout, ResolvedTableChrome> = {
35
35
  pageSize: true,
36
36
  },
37
37
  // The list of a settings page: tabs, an open search field, quick filters,
38
- // sortable headers, the row menu and a short footer.
38
+ // sortable headers, the row menu and a footer with the page size picker.
39
39
  compact: {
40
40
  caption: false,
41
41
  search: "field",
@@ -44,7 +44,7 @@ const LAYOUT_CHROME: Record<TableViewLayout, ResolvedTableChrome> = {
44
44
  refresh: false,
45
45
  menu: false,
46
46
  columnMenus: false,
47
- pageSize: false,
47
+ pageSize: true,
48
48
  },
49
49
  };
50
50
 
@@ -53,6 +53,7 @@ function buildNavigationItem(
53
53
  variant: item.variant,
54
54
  status: item.status,
55
55
  badge: item.badge,
56
+ badgeTone: item.badgeTone,
56
57
  children: children.length > 0 ? children : undefined,
57
58
  };
58
59
  }
@@ -98,19 +99,22 @@ function convertToTreeItems(node: SiteLayoutTree): NavigationMenuItem[][] {
98
99
  }
99
100
 
100
101
  // Module roots are only ever direct children of the `modules` category, so the
101
- // same walk serves the root menu and a module's own menu.
102
+ // same walk serves the root menu and a module's own menu. A page left out of
103
+ // the menu (refused, or showing the viewer none of its blocks) hands its
104
+ // place to the pages nested under it that the viewer can open.
102
105
  function convertChildrenToItems(node: SiteLayoutTree): NavigationMenuItem[] {
103
- return node.childrenOrders
104
- .map((nodeId) => {
105
- const item = node.children[nodeId]!;
106
+ return node.childrenOrders.flatMap((nodeId): NavigationMenuItem[] => {
107
+ const item = node.children[nodeId]!;
106
108
 
107
- if (item.isModuleRoot || item.hasAccess === false) {
108
- return null;
109
- }
109
+ if (item.isModuleRoot) {
110
+ return [];
111
+ }
112
+ if (item.hasAccess === false) {
113
+ return item.layoutUrl ? convertChildrenToItems(item) : [];
114
+ }
110
115
 
111
- return buildNavigationItem(item, convertChildrenToItems(item));
112
- })
113
- .filter((item) => item !== null) as NavigationMenuItem[];
116
+ return [buildNavigationItem(item, convertChildrenToItems(item))];
117
+ });
114
118
  }
115
119
 
116
120
  const MODULE_PAGES_GROUP_ID = "module-pages";
@@ -0,0 +1,12 @@
1
+ import type { Tone } from "../../types/tone";
2
+ import { DMS_TONE_SOFT } from "./tone";
3
+
4
+ /**
5
+ * A page's navigation badge (v2 nav trail count): a small mono pill in the
6
+ * soft tint of the tone its count carries, neutral grey without one. The
7
+ * settings nav draws it after an entry, a nav card in its top corner; where
8
+ * it sits is the caller's.
9
+ */
10
+ export function navBadgeClass(tone: Tone | undefined): string {
11
+ return `rounded-full px-1.5 font-mono text-[10.5px] font-semibold tabular-nums ${DMS_TONE_SOFT[tone ?? "neutral"]}`;
12
+ }
@@ -1,29 +1,6 @@
1
+ import { formatRelativeDistance } from "#dms-core/app/utils/formatter";
1
2
  import { regionalDateTimeFormat } from "#dms-core/app/utils/regional";
2
3
 
3
- const SECOND_MS = 1000;
4
- const MINUTE_MS = 60 * SECOND_MS;
5
- const HOUR_MS = 60 * MINUTE_MS;
6
- const DAY_MS = 24 * HOUR_MS;
7
- const WEEK_MS = 7 * DAY_MS;
8
- const MONTH_MS = 30 * DAY_MS;
9
- const YEAR_MS = 365 * DAY_MS;
10
-
11
- interface RelativeUnit {
12
- unit: Intl.RelativeTimeFormatUnit;
13
- ms: number;
14
- /** The unit applies below this elapsed time. */
15
- below: number;
16
- }
17
-
18
- const RELATIVE_UNITS: RelativeUnit[] = [
19
- { unit: "minute", ms: MINUTE_MS, below: HOUR_MS },
20
- { unit: "hour", ms: HOUR_MS, below: DAY_MS },
21
- { unit: "day", ms: DAY_MS, below: WEEK_MS },
22
- { unit: "week", ms: WEEK_MS, below: MONTH_MS },
23
- { unit: "month", ms: MONTH_MS, below: YEAR_MS },
24
- { unit: "year", ms: YEAR_MS, below: Number.POSITIVE_INFINITY },
25
- ];
26
-
27
4
  function capitalize(text: string): string {
28
5
  return text ? `${text[0]!.toLocaleUpperCase()}${text.slice(1)}` : text;
29
6
  }
@@ -37,17 +14,9 @@ export function formatRelativeDate(
37
14
  locale: string,
38
15
  now: number = Date.now(),
39
16
  ): string {
40
- const deltaMs = new Date(date).getTime() - now;
41
- const distance = Math.abs(deltaMs);
42
- const unit =
43
- RELATIVE_UNITS.find((candidate) => distance < candidate.below) ??
44
- RELATIVE_UNITS[RELATIVE_UNITS.length - 1]!;
45
- const value = Math.round(deltaMs / unit.ms);
46
- const format = new Intl.RelativeTimeFormat(locale, {
47
- numeric: "auto",
48
- style: "short",
49
- });
50
- return capitalize(format.format(value, unit.unit));
17
+ return capitalize(
18
+ formatRelativeDistance(date, locale, { style: "short", now }),
19
+ );
51
20
  }
52
21
 
53
22
  /** "Sep 27": day and short month. */
@@ -43,6 +43,20 @@ export const DMS_TONE_SOFT: Record<Tone, string> = {
43
43
  info: "bg-info/12 text-info",
44
44
  };
45
45
 
46
+ /**
47
+ * The solid fills of the v2 badges (the `solid` variant's theme): a count
48
+ * floating over an icon, where a tint would let the icon show through.
49
+ */
50
+ export const DMS_TONE_SOLID: Record<Tone, string> = {
51
+ neutral: "bg-inverted text-inverted",
52
+ primary: "bg-(--dms-accent-fill) text-(--dms-accent-on-fill)",
53
+ secondary: "bg-(--ui-color-secondary-400) text-(--ui-color-secondary-950)",
54
+ success: "bg-(--ui-color-success-500) text-(--ui-color-success-950)",
55
+ warning: "bg-(--ui-color-warning-400) text-(--ui-color-warning-950)",
56
+ error: "bg-(--ui-color-error-500) text-white",
57
+ info: "bg-(--ui-color-info-400) text-(--ui-color-info-950)",
58
+ };
59
+
46
60
  /** Tone as a text color only. */
47
61
  export const DMS_TONE_TEXT: Record<Tone, string> = {
48
62
  neutral: "text-muted",
@@ -72,3 +86,11 @@ export const DMS_TONE_OUTLINE: Record<Tone, string> = {
72
86
  export function toneTextClass(tone: string | undefined): string {
73
87
  return tone && isDmsTone(tone) ? DMS_TONE_TEXT[tone] : "";
74
88
  }
89
+
90
+ /**
91
+ * A tone drawn as an icon well's: neutral, or no tone, is the quiet `muted`
92
+ * well. A summary row coloured by a navigation badge's tone reads it so.
93
+ */
94
+ export function iconWellToneOf(tone: Tone | undefined): Tone | "muted" {
95
+ return !tone || tone === "neutral" ? "muted" : tone;
96
+ }