@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.
- package/CHANGELOG.md +39 -0
- package/dist/db/models/notification-feed-filter.d.ts +0 -1
- package/dist/db/models/notification-feed-filter.js +0 -4
- package/dist/db/models/notification-feed-filter.js.map +1 -1
- package/dist/db/models/signInAttempts.model.d.ts +18 -0
- package/dist/db/models/signInAttempts.model.js +83 -12
- package/dist/db/models/signInAttempts.model.js.map +1 -1
- package/dist/db/models/userEmailChanges.model.d.ts +8 -1
- package/dist/db/models/userEmailChanges.model.js +27 -2
- package/dist/db/models/userEmailChanges.model.js.map +1 -1
- package/dist/db/models/userNotificationPreferences.model.d.ts +0 -2
- package/dist/db/models/userNotificationPreferences.model.js +0 -13
- package/dist/db/models/userNotificationPreferences.model.js.map +1 -1
- package/dist/db/models/userNotifications.model.d.ts +5 -2
- package/dist/db/models/userNotifications.model.js +19 -2
- package/dist/db/models/userNotifications.model.js.map +1 -1
- package/dist/db/tables/signInAttempts.table.d.ts +2 -1
- package/dist/db/tables/signInAttempts.table.js +4 -0
- package/dist/db/tables/signInAttempts.table.js.map +1 -1
- package/dist/db/tables/userEmailChanges.table.d.ts +2 -1
- package/dist/db/tables/userEmailChanges.table.js +6 -1
- package/dist/db/tables/userEmailChanges.table.js.map +1 -1
- package/dist/db/tables/userNotificationPreferences.table.d.ts +0 -1
- package/dist/db/tables/userNotificationPreferences.table.js +0 -4
- package/dist/db/tables/userNotificationPreferences.table.js.map +1 -1
- package/dist/implementations/dms/layout-banners.d.ts +4 -1
- package/dist/implementations/dms/layout-banners.js +33 -18
- package/dist/implementations/dms/layout-banners.js.map +1 -1
- package/dist/implementations/dms/nav-badges.d.ts +6 -4
- package/dist/implementations/dms/nav-badges.js +6 -5
- package/dist/implementations/dms/nav-badges.js.map +1 -1
- package/dist/implementations/dms/page.d.ts +1 -0
- package/dist/implementations/dms/page.js +46 -8
- package/dist/implementations/dms/page.js.map +1 -1
- package/dist/implementations/dms/permission-preview.d.ts +1 -1
- package/dist/implementations/dms/permission-preview.js +9 -4
- package/dist/implementations/dms/permission-preview.js.map +1 -1
- package/dist/implementations/dms-auth/index.d.ts +3 -2
- package/dist/implementations/dms-auth/index.js +39 -35
- package/dist/implementations/dms-auth/index.js.map +1 -1
- package/dist/implementations/dms-auth/token-session.d.ts +3 -0
- package/dist/implementations/dms-auth/token-session.js +22 -0
- package/dist/implementations/dms-auth/token-session.js.map +1 -0
- package/dist/implementations/dms-notifications/index.d.ts +0 -1
- package/dist/implementations/dms-notifications/index.js +0 -7
- package/dist/implementations/dms-notifications/index.js.map +1 -1
- package/dist/pages/settings/settings-index.js +3 -2
- package/dist/pages/settings/settings-index.js.map +1 -1
- package/dist/pages/settings/users/account-activity-feed.d.ts +1 -1
- package/dist/pages/settings/users/account-activity-feed.js +1 -1
- package/dist/pages/settings/users/account-activity-feed.js.map +1 -1
- package/dist/pages/settings/users/account-activity.d.ts +1 -1
- package/dist/pages/settings/users/account-activity.js +1 -1
- package/dist/pages/settings/users/account-activity.js.map +1 -1
- package/dist/pages/settings/users/account-credentials.d.ts +3 -0
- package/dist/pages/settings/users/account-credentials.js +2 -0
- package/dist/pages/settings/users/account-credentials.js.map +1 -1
- package/dist/pages/settings/users/current-password.d.ts +1 -1
- package/dist/pages/settings/users/current-password.js +23 -2
- package/dist/pages/settings/users/current-password.js.map +1 -1
- package/dist/pages/settings/users/email-change.d.ts +1 -1
- package/dist/pages/settings/users/email-change.js +33 -26
- package/dist/pages/settings/users/email-change.js.map +1 -1
- package/dist/pages/settings/users/invite-resend.js +0 -1
- package/dist/pages/settings/users/invite-resend.js.map +1 -1
- package/dist/pages/settings/users/invites.d.ts +1 -2
- package/dist/pages/settings/users/invites.js +21 -19
- package/dist/pages/settings/users/invites.js.map +1 -1
- package/dist/pages/settings/users/member-invite-batch.js +0 -1
- package/dist/pages/settings/users/member-invite-batch.js.map +1 -1
- package/dist/pages/settings/users/member-invite-form.js +10 -22
- package/dist/pages/settings/users/member-invite-form.js.map +1 -1
- package/dist/pages/settings/users/member-role-options.d.ts +6 -4
- package/dist/pages/settings/users/member-role-options.js +15 -4
- package/dist/pages/settings/users/member-role-options.js.map +1 -1
- package/dist/pages/settings/users/members.d.ts +2 -3
- package/dist/pages/settings/users/members.js +7 -12
- package/dist/pages/settings/users/members.js.map +1 -1
- package/dist/pages/settings/users/notifications.d.ts +1 -8
- package/dist/pages/settings/users/notifications.js +6 -38
- package/dist/pages/settings/users/notifications.js.map +1 -1
- package/dist/pages/settings/users/permission-tree-nodes.d.ts +1 -1
- package/dist/pages/settings/users/permission-tree-nodes.js +23 -9
- package/dist/pages/settings/users/permission-tree-nodes.js.map +1 -1
- package/dist/pages/settings/users/permission-warnings.d.ts +7 -0
- package/dist/pages/settings/users/permission-warnings.js +42 -0
- package/dist/pages/settings/users/permission-warnings.js.map +1 -0
- package/dist/pages/settings/users/profile-helpers.d.ts +1 -3
- package/dist/pages/settings/users/profile-helpers.js +0 -16
- package/dist/pages/settings/users/profile-helpers.js.map +1 -1
- package/dist/pages/settings/users/role-editor-store.js +6 -3
- package/dist/pages/settings/users/role-editor-store.js.map +1 -1
- package/dist/pages/settings/users/role-editor.d.ts +2 -1
- package/dist/pages/settings/users/role-editor.js +8 -4
- package/dist/pages/settings/users/role-editor.js.map +1 -1
- package/dist/pages/settings/users/role-preview.js +2 -1
- package/dist/pages/settings/users/role-preview.js.map +1 -1
- package/dist/pages/settings/users/roles.js +5 -1
- package/dist/pages/settings/users/roles.js.map +1 -1
- package/dist/pages/settings/users/security-attention.d.ts +4 -0
- package/dist/pages/settings/users/security-attention.js +23 -7
- package/dist/pages/settings/users/security-attention.js.map +1 -1
- package/dist/pages/settings/users/security.d.ts +2 -1
- package/dist/pages/settings/users/security.js +13 -2
- package/dist/pages/settings/users/security.js.map +1 -1
- package/dist/pages/settings/users/two-factor-operations.d.ts +2 -1
- package/dist/pages/settings/users/two-factor-operations.js +28 -29
- package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
- package/dist/routes/auth/forgot-password.js +3 -0
- package/dist/routes/auth/forgot-password.js.map +1 -1
- package/dist/routes/auth/index.d.ts +1 -0
- package/dist/routes/auth/index.js +1 -0
- package/dist/routes/auth/index.js.map +1 -1
- package/dist/routes/auth/invite.js +28 -4
- package/dist/routes/auth/invite.js.map +1 -1
- package/dist/routes/auth/login-throttle.d.ts +2 -0
- package/dist/routes/auth/login-throttle.js +5 -4
- package/dist/routes/auth/login-throttle.js.map +1 -1
- package/dist/routes/auth/request-2fa-email.js +6 -18
- package/dist/routes/auth/request-2fa-email.js.map +1 -1
- package/dist/routes/auth/reset-code.d.ts +3 -0
- package/dist/routes/auth/reset-code.js +37 -0
- package/dist/routes/auth/reset-code.js.map +1 -0
- package/dist/routes/auth/reset-password.d.ts +2 -2
- package/dist/routes/auth/reset-password.js +5 -10
- package/dist/routes/auth/reset-password.js.map +1 -1
- package/dist/routes/auth/signup.js +10 -32
- package/dist/routes/auth/signup.js.map +1 -1
- package/dist/routes/auth/two-factor-throttle.d.ts +5 -0
- package/dist/routes/auth/two-factor-throttle.js +81 -0
- package/dist/routes/auth/two-factor-throttle.js.map +1 -0
- package/dist/routes/auth/validate-forgot-password-token.js +2 -8
- package/dist/routes/auth/validate-forgot-password-token.js.map +1 -1
- package/dist/routes/auth/validate-invite-token.d.ts +1 -0
- package/dist/routes/auth/validate-invite-token.js +11 -0
- package/dist/routes/auth/validate-invite-token.js.map +1 -0
- package/dist/routes/auth/verify-2fa.js +10 -13
- package/dist/routes/auth/verify-2fa.js.map +1 -1
- package/dist/routes/auth.d.ts +1 -0
- package/dist/routes/auth.js +11 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/test/helpers/auth.d.ts +0 -1
- package/dist/test/helpers/auth.js +0 -1
- package/dist/test/helpers/auth.js.map +1 -1
- package/dist/test/helpers/emails.d.ts +10 -0
- package/dist/test/helpers/emails.js +36 -0
- package/dist/test/helpers/emails.js.map +1 -0
- package/dist/test/helpers/fixtures.d.ts +0 -1
- package/dist/test/helpers/fixtures.js +1 -2
- package/dist/test/helpers/fixtures.js.map +1 -1
- package/dist/test/helpers/page-access.d.ts +1 -0
- package/dist/test/helpers/page-access.js +6 -1
- package/dist/test/helpers/page-access.js.map +1 -1
- package/dist/test/integration/auth/current-password.test.d.ts +1 -0
- package/dist/test/integration/auth/current-password.test.js +65 -0
- package/dist/test/integration/auth/current-password.test.js.map +1 -0
- package/dist/test/integration/auth/password-reset.test.d.ts +1 -0
- package/dist/test/integration/auth/password-reset.test.js +126 -0
- package/dist/test/integration/auth/password-reset.test.js.map +1 -0
- package/dist/test/integration/auth/session-revocation.test.d.ts +1 -0
- package/dist/test/integration/auth/session-revocation.test.js +45 -0
- package/dist/test/integration/auth/session-revocation.test.js.map +1 -0
- package/dist/test/integration/auth/two-factor-codes.test.d.ts +1 -0
- package/dist/test/integration/auth/two-factor-codes.test.js +335 -0
- package/dist/test/integration/auth/two-factor-codes.test.js.map +1 -0
- package/dist/test/integration/auth/two-factor-password.test.js +5 -1
- package/dist/test/integration/auth/two-factor-password.test.js.map +1 -1
- package/dist/test/integration/auth/two-factor-token.test.d.ts +1 -0
- package/dist/test/integration/auth/two-factor-token.test.js +92 -0
- package/dist/test/integration/auth/two-factor-token.test.js.map +1 -0
- package/dist/test/integration/email-change.test.js +36 -0
- package/dist/test/integration/email-change.test.js.map +1 -1
- package/dist/test/integration/invite-extension-edit.test.js +0 -1
- package/dist/test/integration/invite-extension-edit.test.js.map +1 -1
- package/dist/test/integration/invite-link-status.test.d.ts +1 -0
- package/dist/test/integration/invite-link-status.test.js +110 -0
- package/dist/test/integration/invite-link-status.test.js.map +1 -0
- package/dist/test/integration/invite-resolution.test.js +0 -3
- package/dist/test/integration/invite-resolution.test.js.map +1 -1
- package/dist/test/integration/member-settings-access.test.js +17 -0
- package/dist/test/integration/member-settings-access.test.js.map +1 -1
- package/dist/test/integration/notification-unread-badge.test.d.ts +1 -0
- package/dist/test/integration/notification-unread-badge.test.js +92 -0
- package/dist/test/integration/notification-unread-badge.test.js.map +1 -0
- package/dist/test/integration/permission-warnings.test.d.ts +1 -0
- package/dist/test/integration/permission-warnings.test.js +71 -0
- package/dist/test/integration/permission-warnings.test.js.map +1 -0
- package/dist/test/integration/removed-member-notifications.test.d.ts +1 -0
- package/dist/test/integration/removed-member-notifications.test.js +80 -0
- package/dist/test/integration/removed-member-notifications.test.js.map +1 -0
- package/dist/test/integration/role-permission-ancestors.test.d.ts +1 -0
- package/dist/test/integration/role-permission-ancestors.test.js +146 -0
- package/dist/test/integration/role-permission-ancestors.test.js.map +1 -0
- package/dist/test/integration/tenant-lifecycle.test.js +0 -4
- package/dist/test/integration/tenant-lifecycle.test.js.map +1 -1
- package/dist/test/unit/auth-session-revocation.test.d.ts +1 -0
- package/dist/test/unit/auth-session-revocation.test.js +105 -0
- package/dist/test/unit/auth-session-revocation.test.js.map +1 -0
- package/dist/test/unit/db/email-normalization.test.js +0 -1
- package/dist/test/unit/db/email-normalization.test.js.map +1 -1
- package/dist/test/unit/db/notification-feed-filter.test.js +0 -16
- package/dist/test/unit/db/notification-feed-filter.test.js.map +1 -1
- package/dist/test/unit/db/notification-inbox.test.js +63 -13
- package/dist/test/unit/db/notification-inbox.test.js.map +1 -1
- package/dist/test/unit/db/notification-preferences.test.js +0 -17
- package/dist/test/unit/db/notification-preferences.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/empty-menu-group.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/empty-menu-group.test.js +133 -0
- package/dist/test/unit/implementations/dms/empty-menu-group.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/layout-banners.test.js +78 -1
- package/dist/test/unit/implementations/dms/layout-banners.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js +149 -0
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/nav-badges.test.js +55 -4
- package/dist/test/unit/implementations/dms/nav-badges.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js +118 -0
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js +16 -0
- package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/permission-preview-cost.test.js +5 -3
- package/dist/test/unit/implementations/dms/permission-preview-cost.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/permission-preview-menu.test.js +29 -3
- package/dist/test/unit/implementations/dms/permission-preview-menu.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/quick-actions-button.test.js +4 -2
- package/dist/test/unit/implementations/dms/quick-actions-button.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/user-permissions-gate.test.js +2 -1
- package/dist/test/unit/implementations/dms/user-permissions-gate.test.js.map +1 -1
- package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js +2 -1
- package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/component-children-permissions.test.js +7 -2
- package/dist/test/unit/interfaces/dms/component-children-permissions.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js +133 -0
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js +149 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/invite-extension.test.js +13 -0
- package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/member-access.test.js +27 -1
- package/dist/test/unit/interfaces/dms/member-access.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js +31 -0
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/page-extension.test.js +4 -1
- package/dist/test/unit/interfaces/dms/page-extension.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/permission-requirements.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/permission-requirements.test.js +144 -0
- package/dist/test/unit/interfaces/dms/permission-requirements.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js +70 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js +38 -0
- package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js +6 -2
- package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js +1 -1
- package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js.map +1 -1
- package/dist/test/unit/pages/settings/account-activity-feed.test.js +2 -2
- package/dist/test/unit/pages/settings/account-activity-feed.test.js.map +1 -1
- package/dist/test/unit/pages/settings/account-activity.test.js +11 -2
- package/dist/test/unit/pages/settings/account-activity.test.js.map +1 -1
- package/dist/test/unit/pages/settings/invite-email-delivery.test.js +0 -1
- package/dist/test/unit/pages/settings/invite-email-delivery.test.js.map +1 -1
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.js +33 -0
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.js.map +1 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.js +22 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.js.map +1 -0
- package/dist/test/unit/pages/settings/member-table-widths.test.js +2 -2
- package/dist/test/unit/pages/settings/member-table-widths.test.js.map +1 -1
- package/dist/test/unit/pages/settings/members-page.test.js +7 -10
- package/dist/test/unit/pages/settings/members-page.test.js.map +1 -1
- package/dist/test/unit/pages/settings/notifications-access-gate.test.js +3 -10
- package/dist/test/unit/pages/settings/notifications-access-gate.test.js.map +1 -1
- package/dist/test/unit/pages/settings/permission-tree-nodes.test.js +57 -0
- package/dist/test/unit/pages/settings/permission-tree-nodes.test.js.map +1 -1
- package/dist/test/unit/pages/settings/permission-warnings.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/permission-warnings.test.js +49 -0
- package/dist/test/unit/pages/settings/permission-warnings.test.js.map +1 -0
- package/dist/test/unit/pages/settings/role-editor.test.js +16 -0
- package/dist/test/unit/pages/settings/role-editor.test.js.map +1 -1
- package/dist/test/unit/pages/settings/role-preview.test.js +7 -0
- package/dist/test/unit/pages/settings/role-preview.test.js.map +1 -1
- package/dist/test/unit/pages/settings/security-attention.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/security-attention.test.js +74 -0
- package/dist/test/unit/pages/settings/security-attention.test.js.map +1 -0
- package/dist/test/unit/sanitize-user.test.d.ts +1 -0
- package/dist/test/unit/sanitize-user.test.js +21 -0
- package/dist/test/unit/sanitize-user.test.js.map +1 -0
- package/dist/test/unit/signup-email-validation.test.d.ts +1 -0
- package/dist/test/unit/signup-email-validation.test.js +79 -0
- package/dist/test/unit/signup-email-validation.test.js.map +1 -0
- package/dist/test/unit/validation/member-invite.schema.test.js +14 -52
- package/dist/test/unit/validation/member-invite.schema.test.js.map +1 -1
- package/dist/utils/account-notifications.d.ts +5 -0
- package/dist/utils/account-notifications.js +8 -0
- package/dist/utils/account-notifications.js.map +1 -1
- package/dist/utils/notification-emitter.d.ts +1 -1
- package/dist/utils/notification-emitter.js +1 -1
- package/dist/utils/notification-emitter.js.map +1 -1
- package/dist/utils/notification-tones.d.ts +2 -1
- package/dist/utils/notification-tones.js +5 -1
- package/dist/utils/notification-tones.js.map +1 -1
- package/dist/utils/one-time-code.d.ts +3 -0
- package/dist/utils/one-time-code.js +21 -0
- package/dist/utils/one-time-code.js.map +1 -0
- package/dist/utils/sign-in-monitor.d.ts +1 -0
- package/dist/utils/sign-in-monitor.js +3 -2
- package/dist/utils/sign-in-monitor.js.map +1 -1
- package/dist/utils/two-factor-codes.d.ts +10 -0
- package/dist/utils/two-factor-codes.js +76 -0
- package/dist/utils/two-factor-codes.js.map +1 -0
- package/dist/validation/auth.schema.d.ts +17 -0
- package/dist/validation/auth.schema.js +17 -6
- package/dist/validation/auth.schema.js.map +1 -1
- package/dist/validation/issue-message.d.ts +1 -0
- package/dist/validation/issue-message.js +9 -0
- package/dist/validation/issue-message.js.map +1 -0
- package/dist/validation/member-invite.schema.d.ts +1 -25
- package/dist/validation/member-invite.schema.js +2 -23
- package/dist/validation/member-invite.schema.js.map +1 -1
- package/frontend-vue/dms.frontend.ts +2 -0
- package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot-validation.vue +3 -0
- package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +105 -5
- package/frontend-vue/layers/dms-auth/i18n/locales/auth-en-GB.json +20 -4
- package/frontend-vue/layers/dms-auth/i18n/locales/auth-fr-FR.json +20 -4
- package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +25 -0
- package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +3 -2
- package/frontend-vue/layers/dms-core/app/types/composed-text.ts +64 -0
- package/frontend-vue/layers/dms-core/app/types/menu.ts +15 -0
- package/frontend-vue/layers/dms-core/app/utils/composedText.ts +227 -0
- package/frontend-vue/layers/dms-core/app/utils/formatter.ts +49 -0
- package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +4 -1
- package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +4 -1
- package/frontend-vue/layers/dms-layout/app/assets/css/main.css +20 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/CommandPaletteAssistantAnswer.vue +75 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +17 -3
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardFrame.vue +22 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +24 -10
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidePanel.vue +139 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +4 -2
- package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +90 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/SidePanelHost.vue +17 -0
- package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +25 -43
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/members/MemberRolePicker.vue +24 -2
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixCategory.vue +70 -25
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationPreferencesForm.vue +25 -10
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/notificationDisplay.ts +41 -5
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePreferencesSummary.vue +2 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue +20 -4
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleEditor.vue +21 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionArea.vue +16 -2
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionBranch.vue +1 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionLeaf.vue +13 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionTree.vue +9 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionWarning.vue +46 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +108 -29
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-types.ts +2 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityDialogFrame.vue +6 -6
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEmail.vue +7 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecuritySessions.vue +5 -4
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityStatus.vue +4 -3
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTwoFactor.vue +54 -18
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsNav.vue +13 -8
- package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/assistantGroups.ts +143 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/useCommandPaletteAssistantMode.ts +249 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/general/useGithubStarPrompt.ts +178 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/sidePanelState.ts +191 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useHeaderActionControls.ts +51 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +113 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useCategoryNavCards.ts +17 -10
- package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +45 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfilePreferences.ts +8 -1
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityOverview.ts +50 -3
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts +3 -0
- package/frontend-vue/layers/dms-layout/app/build/utils/categoryPages.ts +1 -2
- package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +5 -0
- package/frontend-vue/layers/dms-layout/app/components/layout/DashboardSearch.vue +109 -7
- package/frontend-vue/layers/dms-layout/app/components/navigation/NavigationMenu.vue +19 -9
- package/frontend-vue/layers/dms-layout/app/composables/notification/useNotifications.ts +22 -40
- package/frontend-vue/layers/dms-layout/app/composables/useAppSidePanels.ts +96 -0
- package/frontend-vue/layers/dms-layout/app/composables/useCommandPaletteAssistant.ts +129 -0
- package/frontend-vue/layers/dms-layout/app/composables/useHeaderActions.ts +33 -11
- package/frontend-vue/layers/dms-layout/app/composables/useSidePanel.ts +41 -0
- package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +15 -0
- package/frontend-vue/layers/dms-layout/app/plugins/notification-stream.client.ts +1 -7
- package/frontend-vue/layers/dms-layout/app/plugins/side-panel-host.ts +13 -0
- package/frontend-vue/layers/dms-layout/app/types/page.ts +11 -1
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +43 -13
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +43 -13
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +45 -0
- package/frontend-vue/layers/dms-ui/app/build/components/modal/ModalEscHint.vue +28 -0
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/IdentityCell.vue +36 -7
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +57 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +19 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +22 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +118 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +5 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/form/floatingSaveBars.ts +38 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +66 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/navigation/useNavBadges.ts +50 -9
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +7 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/chrome.ts +2 -2
- package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +14 -10
- package/frontend-vue/layers/dms-ui/app/build/utils/navBadge.ts +12 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +4 -35
- package/frontend-vue/layers/dms-ui/app/build/utils/tone.ts +22 -0
- package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +117 -82
- package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +8 -5
- package/frontend-vue/layers/dms-ui/app/components/blocks/KeyValueListBlock.vue +38 -18
- package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +12 -1
- package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +26 -23
- package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +16 -1
- package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +7 -8
- package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +28 -6
- package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +5 -1
- package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +4 -0
- package/frontend-vue/layers/dms-ui/app/components/status-pill/StatusPill.vue +7 -2
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +7 -2
- package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +48 -34
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +13 -3
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -14
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -14
- package/frontend-vue/package.json +2 -2
- package/frontend-vue/pnpm-lock.yaml +5 -5
- package/frontend-vue/tests/activity-feed-fill-height.test.ts +107 -0
- package/frontend-vue/tests/category-nav-cards.test.ts +21 -13
- package/frontend-vue/tests/command-palette-assistant.test.ts +344 -0
- package/frontend-vue/tests/composed-text-blocks.test.ts +205 -0
- package/frontend-vue/tests/composed-text.test.ts +265 -0
- package/frontend-vue/tests/fixtures/dashboard-search-stub.ts +91 -0
- package/frontend-vue/tests/forgot-validation-resend.test.ts +234 -0
- package/frontend-vue/tests/form-display-options.test.ts +64 -0
- package/frontend-vue/tests/form-load-error.test.ts +160 -0
- package/frontend-vue/tests/form-saved-before-success.test.ts +110 -0
- package/frontend-vue/tests/github-star-prompt.test.ts +328 -0
- package/frontend-vue/tests/header-actions.test.ts +191 -0
- package/frontend-vue/tests/invites-edit-modal.test.ts +157 -0
- package/frontend-vue/tests/layout-banners.test.ts +56 -0
- package/frontend-vue/tests/member-role-picker.test.ts +26 -0
- package/frontend-vue/tests/menu-hidden-page.test.ts +93 -0
- package/frontend-vue/tests/nav-badge-tones.test.ts +274 -0
- package/frontend-vue/tests/nav-card-badge.test.ts +69 -0
- package/frontend-vue/tests/nav-card-grid-empty-category.test.ts +163 -0
- package/frontend-vue/tests/notification-popover-errors.test.ts +71 -37
- package/frontend-vue/tests/notification-preferences-groups.test.ts +268 -0
- package/frontend-vue/tests/notification-tone-contract.test.ts +70 -0
- package/frontend-vue/tests/page-fill-height.test.ts +9 -1
- package/frontend-vue/tests/page-no-visible-blocks.test.ts +202 -0
- package/frontend-vue/tests/profile-preferences-summary.test.ts +26 -2
- package/frontend-vue/tests/profile-security-summary.test.ts +121 -0
- package/frontend-vue/tests/role-permission-tree.test.ts +102 -8
- package/frontend-vue/tests/role-permissions.test.ts +178 -56
- package/frontend-vue/tests/side-panels.test.ts +470 -0
- package/frontend-vue/tests/signup-invitation-link.test.ts +71 -2
- package/frontend-vue/tests/table-actions-column-width.test.ts +51 -1
- package/frontend-vue/tests/table-cell-sublines.test.ts +466 -0
- package/frontend-vue/tests/table-metric-cells.test.ts +4 -0
- package/frontend-vue/tests/table-view-chrome.test.ts +2 -2
- package/frontend-vue/tests/vue-inventory.test.ts +1 -1
- package/package.json +2 -2
- package/skills/dms/REFERENCE.md +1 -1
- 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
|
+
};
|
package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts
CHANGED
|
@@ -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
|
|
49
|
-
//
|
|
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)
|
|
4
|
-
* view tab declared with `navBadge
|
|
5
|
-
* publishes its own counter here once shown,
|
|
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,
|
|
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(
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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:
|
|
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
|
-
.
|
|
105
|
-
const item = node.children[nodeId]!;
|
|
106
|
+
return node.childrenOrders.flatMap((nodeId): NavigationMenuItem[] => {
|
|
107
|
+
const item = node.children[nodeId]!;
|
|
106
108
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
109
|
+
if (item.isModuleRoot) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
if (item.hasAccess === false) {
|
|
113
|
+
return item.layoutUrl ? convertChildrenToItems(item) : [];
|
|
114
|
+
}
|
|
110
115
|
|
|
111
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
+
}
|