@antelopejs/dms 0.6.2 → 0.7.1
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 +30 -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/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 +2 -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/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/useFieldErrors.ts +3 -2
- package/frontend-vue/layers/dms-core/app/types/menu.ts +15 -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/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 +4 -0
- 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/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/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/NavCardGridBlock.vue +12 -1
- 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/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/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-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
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { Ref } from "vue";
|
|
2
|
+
import {
|
|
3
|
+
resolveSidePanelWidthBounds,
|
|
4
|
+
type SidePanel,
|
|
5
|
+
type SidePanelWidthBounds,
|
|
6
|
+
} from "../../../composables/useAppSidePanels";
|
|
7
|
+
import {
|
|
8
|
+
clampSidePanelWidth,
|
|
9
|
+
readSidePanelPreferences,
|
|
10
|
+
storedSidePanelWidth,
|
|
11
|
+
storeSidePanelWidth,
|
|
12
|
+
useSidePanelDragWidth,
|
|
13
|
+
useSidePanelPreferences,
|
|
14
|
+
} from "./sidePanelState";
|
|
15
|
+
|
|
16
|
+
/** @internal */
|
|
17
|
+
export const SIDE_PANEL_KEYBOARD_STEP_PX = 16;
|
|
18
|
+
|
|
19
|
+
type WidthStep = (width: number, bounds: SidePanelWidthBounds) => number;
|
|
20
|
+
|
|
21
|
+
// The panel sits on the right: the arrow pointing away from it widens it.
|
|
22
|
+
const KEYBOARD_STEPS: Record<string, WidthStep> = {
|
|
23
|
+
ArrowLeft: (width) => width + SIDE_PANEL_KEYBOARD_STEP_PX,
|
|
24
|
+
ArrowRight: (width) => width - SIDE_PANEL_KEYBOARD_STEP_PX,
|
|
25
|
+
Home: (_, bounds) => bounds.minWidth,
|
|
26
|
+
End: (_, bounds) => bounds.maxWidth,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
interface DragStart {
|
|
30
|
+
x: number;
|
|
31
|
+
width: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @internal */
|
|
35
|
+
export interface SidePanelWidth {
|
|
36
|
+
width: Readonly<Ref<number>>;
|
|
37
|
+
bounds: SidePanelWidthBounds;
|
|
38
|
+
isDragging: Readonly<Ref<boolean>>;
|
|
39
|
+
startDrag: (event: PointerEvent, renderedWidth: number) => void;
|
|
40
|
+
drag: (event: PointerEvent) => void;
|
|
41
|
+
endDrag: () => void;
|
|
42
|
+
resizeFromKey: (event: KeyboardEvent) => void;
|
|
43
|
+
reset: () => void;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The width of a side panel and the handlers of its resize handle: dragging,
|
|
48
|
+
* the arrow / Home / End keys, and a reset to the default width. The width is
|
|
49
|
+
* kept per panel id in the side panel cookie, written once a change settles;
|
|
50
|
+
* while the handle is dragged, the shared drag width moves the page with it.
|
|
51
|
+
*
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export function useSidePanelWidth(panel: SidePanel): SidePanelWidth {
|
|
55
|
+
const bounds = resolveSidePanelWidthBounds(panel);
|
|
56
|
+
const preferences = useSidePanelPreferences();
|
|
57
|
+
const dragWidth = useSidePanelDragWidth();
|
|
58
|
+
const width = computed(
|
|
59
|
+
() =>
|
|
60
|
+
dragWidth.value ??
|
|
61
|
+
storedSidePanelWidth(
|
|
62
|
+
readSidePanelPreferences(preferences.value),
|
|
63
|
+
panel.id,
|
|
64
|
+
bounds,
|
|
65
|
+
),
|
|
66
|
+
);
|
|
67
|
+
let dragStart: DragStart | null = null;
|
|
68
|
+
|
|
69
|
+
function commit(next: number): void {
|
|
70
|
+
storeSidePanelWidth(
|
|
71
|
+
preferences,
|
|
72
|
+
panel.id,
|
|
73
|
+
clampSidePanelWidth(next, bounds),
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function startDrag(event: PointerEvent, renderedWidth: number): void {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
dragStart = { x: event.clientX, width: renderedWidth };
|
|
80
|
+
dragWidth.value = clampSidePanelWidth(renderedWidth, bounds);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function drag(event: PointerEvent): void {
|
|
84
|
+
if (dragStart === null) return;
|
|
85
|
+
const next = dragStart.width + dragStart.x - event.clientX;
|
|
86
|
+
dragWidth.value = clampSidePanelWidth(next, bounds);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function endDrag(): void {
|
|
90
|
+
if (dragStart === null) return;
|
|
91
|
+
dragStart = null;
|
|
92
|
+
commit(width.value);
|
|
93
|
+
dragWidth.value = null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function resizeFromKey(event: KeyboardEvent): void {
|
|
97
|
+
const step = KEYBOARD_STEPS[event.key];
|
|
98
|
+
if (!step) return;
|
|
99
|
+
event.preventDefault();
|
|
100
|
+
commit(step(width.value, bounds));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
width,
|
|
105
|
+
bounds,
|
|
106
|
+
isDragging: computed(() => dragWidth.value !== null),
|
|
107
|
+
startDrag,
|
|
108
|
+
drag,
|
|
109
|
+
endDrag,
|
|
110
|
+
resizeFromKey,
|
|
111
|
+
reset: () => commit(bounds.defaultWidth),
|
|
112
|
+
};
|
|
113
|
+
}
|
package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useCategoryNavCards.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { usePermissionPreview } from "#dms-core/app/build/composables/auth/usePermissionPreview";
|
|
2
2
|
import { useNavBadges } from "#dms-ui/app/build/composables/navigation/useNavBadges";
|
|
3
|
+
import type { Tone } from "#dms-ui/app/types/tone";
|
|
3
4
|
import { findTreeNode, listCategoryPages } from "../../utils/categoryPages";
|
|
4
5
|
|
|
5
6
|
const DEFAULT_PAGE_ICON = "i-ph-file";
|
|
@@ -13,7 +14,9 @@ export interface CategoryNavCard {
|
|
|
13
14
|
icon: string;
|
|
14
15
|
to: string;
|
|
15
16
|
/** The page's navigation badge, as the menu shows it. */
|
|
16
|
-
|
|
17
|
+
badge?: string;
|
|
18
|
+
/** The badge's tone, as the menu draws it. */
|
|
19
|
+
badgeTone?: Tone;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
/**
|
|
@@ -24,21 +27,25 @@ export interface CategoryNavCard {
|
|
|
24
27
|
*/
|
|
25
28
|
export function useCategoryNavCards(categoryId: () => string | undefined) {
|
|
26
29
|
const siteLayout = useSiteLayout();
|
|
27
|
-
const {
|
|
30
|
+
const { navBadgeOf } = useNavBadges();
|
|
28
31
|
const cards = computed<CategoryNavCard[]>(() => {
|
|
29
32
|
const id = categoryId();
|
|
30
33
|
const category = id
|
|
31
34
|
? findTreeNode(siteLayout.siteLayoutTree.value, id)
|
|
32
35
|
: undefined;
|
|
33
36
|
if (!category) return [];
|
|
34
|
-
return listCategoryPages(category).map((page) =>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
return listCategoryPages(category).map((page) => {
|
|
38
|
+
const badge = navBadgeOf(page);
|
|
39
|
+
return {
|
|
40
|
+
id: page.fullId,
|
|
41
|
+
title: page.displayName,
|
|
42
|
+
description: page.description,
|
|
43
|
+
icon: page.icon || DEFAULT_PAGE_ICON,
|
|
44
|
+
to: page.fullSlug,
|
|
45
|
+
badge: badge?.label,
|
|
46
|
+
badgeTone: badge?.tone,
|
|
47
|
+
};
|
|
48
|
+
});
|
|
42
49
|
});
|
|
43
50
|
return { cards };
|
|
44
51
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/** `localStorage` key prefix of the open or folded state of each preferences group. */
|
|
2
|
+
export const NOTIFICATION_GROUP_STORAGE_PREFIX = "dms-notification-group:";
|
|
3
|
+
|
|
4
|
+
const OPEN = "open";
|
|
5
|
+
const FOLDED = "folded";
|
|
6
|
+
|
|
7
|
+
function storageKey(categoryId: string): string {
|
|
8
|
+
return `${NOTIFICATION_GROUP_STORAGE_PREFIX}${categoryId}`;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function readStorage(key: string): string | null {
|
|
12
|
+
try {
|
|
13
|
+
return localStorage.getItem(key);
|
|
14
|
+
} catch {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function writeStorage(key: string, value: string): void {
|
|
20
|
+
try {
|
|
21
|
+
localStorage.setItem(key, value);
|
|
22
|
+
} catch {
|
|
23
|
+
/* storage unavailable (private mode, quota): the group folds on reload */
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Which groups of the preferences matrix are open. A group starts folded,
|
|
29
|
+
* so the page opens short and each group row's count sums it up; the state
|
|
30
|
+
* the viewer picks is kept per group in this browser.
|
|
31
|
+
*/
|
|
32
|
+
export const useNotificationGroupsOpen = () => {
|
|
33
|
+
const picked = ref<Record<string, boolean>>({});
|
|
34
|
+
|
|
35
|
+
const isOpen = (categoryId: string): boolean =>
|
|
36
|
+
picked.value[categoryId] ?? readStorage(storageKey(categoryId)) === OPEN;
|
|
37
|
+
|
|
38
|
+
const toggleOpen = (categoryId: string) => {
|
|
39
|
+
const open = !isOpen(categoryId);
|
|
40
|
+
picked.value = { ...picked.value, [categoryId]: open };
|
|
41
|
+
writeStorage(storageKey(categoryId), open ? OPEN : FOLDED);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return { isOpen, toggleOpen };
|
|
45
|
+
};
|
|
@@ -3,6 +3,7 @@ import { computed, onMounted, ref } from "vue";
|
|
|
3
3
|
import { useUserRegionalPreferences } from "#dms-core/app/composables/user/useUserRegionalPreferences";
|
|
4
4
|
import { useUniqueLocales } from "#dms-core/app/composables/translation/useUniqueLocales";
|
|
5
5
|
import { formatDate } from "#dms-core/app/utils/formatter";
|
|
6
|
+
import { iconWellToneOf } from "#dms-ui/app/build/utils/tone";
|
|
6
7
|
import { useAccessibilityPreferences } from "../../../../composables/general/useAccessibilityPreferences";
|
|
7
8
|
import { useColorModePreference } from "../../../../composables/general/useColorModePreference";
|
|
8
9
|
import { useInterfaceScale } from "../../../../composables/general/useInterfaceScale";
|
|
@@ -118,7 +119,7 @@ export function useProfilePreferences() {
|
|
|
118
119
|
|
|
119
120
|
const notificationPreferences = useNotificationPreferences();
|
|
120
121
|
const { subjects } = useNotificationCatalog();
|
|
121
|
-
const { unreadCount, areCountsLoaded } = useNotifications();
|
|
122
|
+
const { unreadCount, unreadTone, areCountsLoaded } = useNotifications();
|
|
122
123
|
const isNotificationsLoading = computed(
|
|
123
124
|
() => notificationPreferences.isLoading.value || !areCountsLoaded.value,
|
|
124
125
|
);
|
|
@@ -132,6 +133,11 @@ export function useProfilePreferences() {
|
|
|
132
133
|
const hasUnread = computed(
|
|
133
134
|
() => !isNotificationsLoading.value && unreadCount.value > 0,
|
|
134
135
|
);
|
|
136
|
+
// The well takes the unread badge's tone, the bell's and the navigation's,
|
|
137
|
+
// which the server weighs; quiet when nothing is unread.
|
|
138
|
+
const notificationsTone = computed(() =>
|
|
139
|
+
hasUnread.value ? iconWellToneOf(unreadTone.value) : "muted",
|
|
140
|
+
);
|
|
135
141
|
|
|
136
142
|
const colorMode = useColorModePreference();
|
|
137
143
|
const scale = useInterfaceScale();
|
|
@@ -192,6 +198,7 @@ export function useProfilePreferences() {
|
|
|
192
198
|
regionSummary,
|
|
193
199
|
notificationsSummary,
|
|
194
200
|
hasUnread,
|
|
201
|
+
notificationsTone,
|
|
195
202
|
appearanceSummary,
|
|
196
203
|
placeholders,
|
|
197
204
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useNavBadges } from "#dms-ui/app/build/composables/navigation/useNavBadges";
|
|
2
|
+
import type { Tone } from "#dms-ui/app/types/tone";
|
|
2
3
|
|
|
3
4
|
/** Base URL of the Security page API. */
|
|
4
5
|
export const SECURITY_ENDPOINT = "/settings/user/security";
|
|
@@ -29,6 +30,13 @@ export interface SecurityOverview {
|
|
|
29
30
|
activeSessions: number;
|
|
30
31
|
/** What needs the user's attention, most important first. */
|
|
31
32
|
attention: SecurityAttention[];
|
|
33
|
+
/**
|
|
34
|
+
* The strongest tone of `attention`, which the navigation badge takes;
|
|
35
|
+
* null when nothing needs attention.
|
|
36
|
+
*/
|
|
37
|
+
attentionTone: Tone | null;
|
|
38
|
+
/** The tone of each item of `attention`. */
|
|
39
|
+
attentionTones: Partial<Record<SecurityAttention, Tone>>;
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
/** What the API returns to enrol an authenticator app. */
|
|
@@ -47,11 +55,23 @@ export type SecurityAttention =
|
|
|
47
55
|
| "backup_codes_unsaved"
|
|
48
56
|
| "backup_codes_low";
|
|
49
57
|
|
|
58
|
+
/** Strongest first, as the server ranks the attention tones. */
|
|
59
|
+
const ATTENTION_TONE_ORDER: Tone[] = [
|
|
60
|
+
"error",
|
|
61
|
+
"warning",
|
|
62
|
+
"primary",
|
|
63
|
+
"secondary",
|
|
64
|
+
"success",
|
|
65
|
+
"info",
|
|
66
|
+
"neutral",
|
|
67
|
+
];
|
|
68
|
+
|
|
50
69
|
/**
|
|
51
70
|
* Shared Security summary: the status strip, every Security block and the
|
|
52
71
|
* profile pointer card read the same state, and any change refreshes it for
|
|
53
72
|
* all of them. It also keeps the navigation badge of the Security page, the
|
|
54
|
-
* count of what needs attention
|
|
73
|
+
* count of what needs attention in the tone the server gives it, in sync
|
|
74
|
+
* after a change.
|
|
55
75
|
*/
|
|
56
76
|
export function useSecurityOverview() {
|
|
57
77
|
const overview = useDmsState<SecurityOverview | null>(
|
|
@@ -68,6 +88,22 @@ export function useSecurityOverview() {
|
|
|
68
88
|
const attention = computed<SecurityAttention[]>(
|
|
69
89
|
() => overview.value?.attention ?? [],
|
|
70
90
|
);
|
|
91
|
+
const attentionTone = computed<Tone | undefined>(
|
|
92
|
+
() => overview.value?.attentionTone ?? undefined,
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* The strongest tone the server gives to those of `items` that need
|
|
97
|
+
* attention; undefined when none does. A block concerned by several items
|
|
98
|
+
* (the backup codes: unsaved, running low) is drawn in it.
|
|
99
|
+
*/
|
|
100
|
+
function attentionToneOf(items: SecurityAttention[]): Tone | undefined {
|
|
101
|
+
const tones = overview.value?.attentionTones ?? {};
|
|
102
|
+
const present = items
|
|
103
|
+
.map((item) => tones[item])
|
|
104
|
+
.filter((tone): tone is Tone => !!tone);
|
|
105
|
+
return ATTENTION_TONE_ORDER.find((tone) => present.includes(tone));
|
|
106
|
+
}
|
|
71
107
|
|
|
72
108
|
async function refresh(): Promise<void> {
|
|
73
109
|
try {
|
|
@@ -78,8 +114,19 @@ export function useSecurityOverview() {
|
|
|
78
114
|
return;
|
|
79
115
|
}
|
|
80
116
|
const count = attention.value.length;
|
|
81
|
-
setNavBadge(
|
|
117
|
+
setNavBadge(
|
|
118
|
+
SECURITY_PAGE_ID,
|
|
119
|
+
count > 0 ? String(count) : "",
|
|
120
|
+
attentionTone.value,
|
|
121
|
+
);
|
|
82
122
|
}
|
|
83
123
|
|
|
84
|
-
return {
|
|
124
|
+
return {
|
|
125
|
+
overview,
|
|
126
|
+
attention,
|
|
127
|
+
attentionTone,
|
|
128
|
+
attentionToneOf,
|
|
129
|
+
isUnavailable,
|
|
130
|
+
refresh,
|
|
131
|
+
};
|
|
85
132
|
}
|
package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface SettingsNavPage {
|
|
|
17
17
|
to: string;
|
|
18
18
|
/** Badge the server counted or the page declared for its entry. */
|
|
19
19
|
badge?: string;
|
|
20
|
+
/** The tone of a counted badge; neutral when absent. */
|
|
21
|
+
badgeTone?: MenuItemBadgeTone;
|
|
20
22
|
/** Dot the page declared for its entry. */
|
|
21
23
|
status?: MenuItemStatus;
|
|
22
24
|
}
|
|
@@ -36,6 +38,7 @@ const toNavPage = (node: SiteLayoutTree): SettingsNavPage => ({
|
|
|
36
38
|
icon: node.icon || DEFAULT_SETTINGS_ICON,
|
|
37
39
|
to: node.fullSlug,
|
|
38
40
|
badge: node.badge,
|
|
41
|
+
badgeTone: node.badgeTone,
|
|
39
42
|
status: node.status,
|
|
40
43
|
});
|
|
41
44
|
|
|
@@ -24,8 +24,7 @@ const isOpenablePage = (node: SiteLayoutTree): boolean =>
|
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* The pages the viewer can open among `nodes` and under them, in menu order,
|
|
27
|
-
* each one followed by the pages nested under it
|
|
28
|
-
* Members). The page answering at `landingSlug` leads to the others rather
|
|
27
|
+
* each one followed by the pages nested under it. The page answering at `landingSlug` leads to the others rather
|
|
29
28
|
* than being one of them.
|
|
30
29
|
*/
|
|
31
30
|
export function listPagesAmong(
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The DMS repository on GitHub, as `owner/name`. */
|
|
2
|
+
export const GITHUB_REPOSITORY = "AntelopeJS/dms";
|
|
3
|
+
|
|
4
|
+
/** Opened by the auth footer's star button and by the dashboard's star prompt. */
|
|
5
|
+
export const GITHUB_REPOSITORY_URL = `https://github.com/${GITHUB_REPOSITORY}`;
|
|
@@ -1,7 +1,59 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { computed, nextTick, useTemplateRef } from "vue";
|
|
3
|
+
import CommandPaletteAssistantAnswer from "../../build/components/layout/CommandPaletteAssistantAnswer.vue";
|
|
4
|
+
import { ASSISTANT_MODE_KEY } from "../../build/composables/command-palette/assistantGroups";
|
|
5
|
+
import { useCommandPaletteAssistantMode } from "../../build/composables/command-palette/useCommandPaletteAssistantMode";
|
|
6
|
+
|
|
2
7
|
const { t } = useI18n();
|
|
3
|
-
const
|
|
8
|
+
const appConfig = useDmsAppConfig();
|
|
9
|
+
const { groups: sourceGroups } = useCommandPaletteGroups();
|
|
4
10
|
const fuse = COMMAND_PALETTE_FUSE_OPTIONS;
|
|
11
|
+
const {
|
|
12
|
+
isOpen,
|
|
13
|
+
searchTerm,
|
|
14
|
+
assistant,
|
|
15
|
+
isAssistantMode,
|
|
16
|
+
answer,
|
|
17
|
+
groups,
|
|
18
|
+
announcement,
|
|
19
|
+
setMode,
|
|
20
|
+
onInputKeydown,
|
|
21
|
+
} = useCommandPaletteAssistantMode(sourceGroups);
|
|
22
|
+
|
|
23
|
+
const footerRef = useTemplateRef<HTMLElement>("footer");
|
|
24
|
+
const input = { onKeydown: onInputKeydown };
|
|
25
|
+
// The halo eases between the accent ring and the violet assistant ring.
|
|
26
|
+
const MODAL_TRANSITION_CLASS = "transition-shadow duration-300";
|
|
27
|
+
// In assistant mode, the empty slot holds the DMS's own padded states.
|
|
28
|
+
const ASSISTANT_EMPTY_CLASS = "p-0 text-start";
|
|
29
|
+
const SEARCH_UI = { modal: MODAL_TRANSITION_CLASS };
|
|
30
|
+
const ASSISTANT_UI = {
|
|
31
|
+
modal: `${MODAL_TRANSITION_CLASS} shadow-[var(--dms-shadow-cmdk),var(--dms-assistant-halo)]`,
|
|
32
|
+
input: "[&_input]:caret-secondary [&_[data-slot=leadingIcon]]:text-secondary",
|
|
33
|
+
empty: ASSISTANT_EMPTY_CLASS,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const paletteUi = computed(() =>
|
|
37
|
+
isAssistantMode.value ? ASSISTANT_UI : SEARCH_UI,
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
/** Brings focus back to the prompt after the control that held it goes away. */
|
|
41
|
+
async function focusInput(): Promise<void> {
|
|
42
|
+
await nextTick();
|
|
43
|
+
footerRef.value
|
|
44
|
+
?.closest('[role="dialog"]')
|
|
45
|
+
?.querySelector<HTMLInputElement>("input")
|
|
46
|
+
?.focus();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function switchMode(): void {
|
|
50
|
+
setMode(isAssistantMode.value ? "search" : "assistant");
|
|
51
|
+
void focusInput();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function close(): void {
|
|
55
|
+
isOpen.value = false;
|
|
56
|
+
}
|
|
5
57
|
</script>
|
|
6
58
|
|
|
7
59
|
<template>
|
|
@@ -9,26 +61,76 @@ const fuse = COMMAND_PALETTE_FUSE_OPTIONS;
|
|
|
9
61
|
leaving these props out exposes those raw keys as the dialog's
|
|
10
62
|
accessible name. -->
|
|
11
63
|
<UDashboardSearch
|
|
64
|
+
v-model:open="isOpen"
|
|
65
|
+
v-model:search-term="searchTerm"
|
|
12
66
|
:groups="groups"
|
|
13
67
|
:fuse="fuse"
|
|
68
|
+
:color-mode="!isAssistantMode"
|
|
69
|
+
:input="input"
|
|
70
|
+
:icon="isAssistantMode ? assistant?.icon : undefined"
|
|
71
|
+
:placeholder="isAssistantMode ? assistant?.placeholder : undefined"
|
|
72
|
+
:ui="paletteUi"
|
|
14
73
|
:title="t('commandPalette.dialog.title')"
|
|
15
74
|
:description="t('commandPalette.dialog.description')"
|
|
16
75
|
>
|
|
76
|
+
<template v-if="assistant && isAssistantMode" #empty>
|
|
77
|
+
<CommandPaletteAssistantAnswer
|
|
78
|
+
v-if="answer"
|
|
79
|
+
:key="answer.id"
|
|
80
|
+
:label="assistant.label"
|
|
81
|
+
:icon="assistant.icon"
|
|
82
|
+
:component="assistant.answerComponent"
|
|
83
|
+
:prompt="answer.prompt"
|
|
84
|
+
:close="close"
|
|
85
|
+
/>
|
|
86
|
+
<p v-else class="text-muted px-6 py-8 text-center text-sm">
|
|
87
|
+
{{ t("commandPalette.assistant.emptyPrompt") }}
|
|
88
|
+
</p>
|
|
89
|
+
</template>
|
|
90
|
+
|
|
17
91
|
<!-- v2 footer band: the keys that drive the palette. -->
|
|
18
92
|
<template #footer>
|
|
19
|
-
<span class="
|
|
20
|
-
|
|
21
|
-
<UKbd value="↓" size="sm" />
|
|
22
|
-
{{ t("commandPalette.footer.navigate") }}
|
|
93
|
+
<span ref="footer" class="sr-only" aria-live="polite">
|
|
94
|
+
{{ announcement }}
|
|
23
95
|
</span>
|
|
24
|
-
<span class="inline-flex items-center gap-1.5">
|
|
96
|
+
<span v-if="isAssistantMode" class="inline-flex items-center gap-1.5">
|
|
25
97
|
<UKbd value="↵" size="sm" />
|
|
26
|
-
{{ t("commandPalette.footer.
|
|
98
|
+
{{ t("commandPalette.footer.send") }}
|
|
27
99
|
</span>
|
|
100
|
+
<template v-else>
|
|
101
|
+
<span class="inline-flex items-center gap-1.5">
|
|
102
|
+
<UKbd value="↑" size="sm" />
|
|
103
|
+
<UKbd value="↓" size="sm" />
|
|
104
|
+
{{ t("commandPalette.footer.navigate") }}
|
|
105
|
+
</span>
|
|
106
|
+
<span class="inline-flex items-center gap-1.5">
|
|
107
|
+
<UKbd value="↵" size="sm" />
|
|
108
|
+
{{ t("commandPalette.footer.open") }}
|
|
109
|
+
</span>
|
|
110
|
+
</template>
|
|
28
111
|
<span class="inline-flex items-center gap-1.5">
|
|
29
112
|
<UKbd value="Esc" size="sm" />
|
|
30
113
|
{{ t("commandPalette.footer.close") }}
|
|
31
114
|
</span>
|
|
115
|
+
<UButton
|
|
116
|
+
v-if="assistant"
|
|
117
|
+
class="text-muted hover:text-secondary ms-auto gap-1.5 px-2 py-0.5 text-xs hover:bg-(--dms-assistant-tint)"
|
|
118
|
+
color="neutral"
|
|
119
|
+
variant="ghost"
|
|
120
|
+
size="xs"
|
|
121
|
+
:icon="isAssistantMode ? appConfig.ui.icons.search : assistant.icon"
|
|
122
|
+
:ui="{ leadingIcon: isAssistantMode ? undefined : 'text-secondary' }"
|
|
123
|
+
data-slot="assistantToggle"
|
|
124
|
+
@mousedown.prevent
|
|
125
|
+
@click="switchMode"
|
|
126
|
+
>
|
|
127
|
+
{{
|
|
128
|
+
isAssistantMode
|
|
129
|
+
? t("commandPalette.footer.backToSearch")
|
|
130
|
+
: t("commandPalette.footer.askAi")
|
|
131
|
+
}}
|
|
132
|
+
<UKbd :value="ASSISTANT_MODE_KEY" size="sm" />
|
|
133
|
+
</UButton>
|
|
32
134
|
</template>
|
|
33
135
|
</UDashboardSearch>
|
|
34
136
|
</template>
|
|
@@ -50,13 +50,16 @@ const VARIANT_CLASSES: Record<MenuItemVariant, MenuVariantClasses> = {
|
|
|
50
50
|
|
|
51
51
|
const STATUS_DOT_ICON = "i-ph-circle-fill";
|
|
52
52
|
const STATUS_DOT_SIZE = "size-1.5";
|
|
53
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* v2 nav trail badge: a small soft pill with a mono count, in the tone the
|
|
55
|
+
* count carries (neutral grey without one).
|
|
56
|
+
*/
|
|
54
57
|
const MENU_BADGE_PROPS = {
|
|
55
|
-
color: "neutral",
|
|
56
58
|
variant: "soft",
|
|
57
59
|
size: "sm",
|
|
58
60
|
class: "font-mono tabular-nums",
|
|
59
61
|
} as const;
|
|
62
|
+
const DEFAULT_BADGE_TONE: MenuItemBadgeTone = "neutral";
|
|
60
63
|
|
|
61
64
|
/** The per-item slot classes Nuxt UI accepts on a navigation menu item. */
|
|
62
65
|
type MenuItemUi = NonNullable<DmsMenuItem["ui"]>;
|
|
@@ -110,11 +113,18 @@ function buildItemUi(
|
|
|
110
113
|
: undefined;
|
|
111
114
|
}
|
|
112
115
|
|
|
113
|
-
// A plain badge value (a page's `badge`) gets the v2 look; a
|
|
114
|
-
// given as props is the caller's own choice.
|
|
115
|
-
function resolveMenuBadge(
|
|
116
|
+
// A plain badge value (a page's `badge`) gets the v2 look in its tone; a
|
|
117
|
+
// badge already given as props is the caller's own choice.
|
|
118
|
+
function resolveMenuBadge(
|
|
119
|
+
badge: DmsMenuItem["badge"],
|
|
120
|
+
tone: MenuItemBadgeTone | undefined,
|
|
121
|
+
): DmsMenuItem["badge"] {
|
|
116
122
|
if (typeof badge === "string" || typeof badge === "number") {
|
|
117
|
-
return {
|
|
123
|
+
return {
|
|
124
|
+
...MENU_BADGE_PROPS,
|
|
125
|
+
color: tone ?? DEFAULT_BADGE_TONE,
|
|
126
|
+
label: String(badge),
|
|
127
|
+
};
|
|
118
128
|
}
|
|
119
129
|
return badge;
|
|
120
130
|
}
|
|
@@ -177,8 +187,8 @@ const { badges: navBadges } = useNavBadges();
|
|
|
177
187
|
function badgeOf(item: DmsMenuItem): DmsMenuItem["badge"] {
|
|
178
188
|
const live =
|
|
179
189
|
item.fullId === undefined ? undefined : navBadges.value[item.fullId];
|
|
180
|
-
if (live === undefined) return item.badge;
|
|
181
|
-
return live
|
|
190
|
+
if (live === undefined) return resolveMenuBadge(item.badge, item.badgeTone);
|
|
191
|
+
return live.label ? resolveMenuBadge(live.label, live.tone) : undefined;
|
|
182
192
|
}
|
|
183
193
|
|
|
184
194
|
// A status dot lands in the trailing slot, which a parent entry already uses for
|
|
@@ -187,7 +197,7 @@ function badgeOf(item: DmsMenuItem): DmsMenuItem["badge"] {
|
|
|
187
197
|
function decorateMenuItem(item: DmsMenuItem): DmsMenuItem {
|
|
188
198
|
const variant = VARIANT_CLASSES[item.variant ?? "default"];
|
|
189
199
|
const hasChildren = (item.children?.length ?? 0) > 0;
|
|
190
|
-
const badge =
|
|
200
|
+
const badge = badgeOf(item);
|
|
191
201
|
const statusClass =
|
|
192
202
|
item.status && !hasChildren && !badge
|
|
193
203
|
? MENU_STATUS_TEXT_CLASSES[item.status]
|