@antelopejs/dms 0.6.2 → 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 +22 -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 +1 -1
- package/skills/dms/REFERENCE.md +1 -1
|
@@ -3,8 +3,13 @@ import Container from "./Container.vue";
|
|
|
3
3
|
import DashboardSidebar from "./DashboardSidebar.vue";
|
|
4
4
|
import DashboardHeader from "./DashboardHeader.vue";
|
|
5
5
|
import DashboardBanners from "./DashboardBanners.vue";
|
|
6
|
+
import GithubStarPrompt from "./GithubStarPrompt.vue";
|
|
6
7
|
import RolePreviewBar from "./RolePreviewBar.vue";
|
|
7
8
|
import { useAppWidgets } from "../../../composables/useAppWidgets";
|
|
9
|
+
import {
|
|
10
|
+
sidePanelWidthStyle,
|
|
11
|
+
useActiveSidePanel,
|
|
12
|
+
} from "../../composables/layout/sidePanelState";
|
|
8
13
|
|
|
9
14
|
// Sidebar sizes are in px (the v2 240px sidebar). The storage key changed with
|
|
10
15
|
// the unit, so a width saved in % is not read back as px.
|
|
@@ -23,6 +28,9 @@ const DOCK_CLEARANCE_CLASS =
|
|
|
23
28
|
// One 40px chip plus its 8px gap per widget, the 10px inset and a 12px margin.
|
|
24
29
|
const DOCK_CHIP_REM = 3;
|
|
25
30
|
const DOCK_EDGE_REM = 1.375;
|
|
31
|
+
// The open side panel is rendered once for the app (`SidePanelHost`), fixed on
|
|
32
|
+
// the right; from `lg` the frame keeps its width free so the page shrinks.
|
|
33
|
+
const SIDE_PANEL_ROOM_CLASS = "lg:end-[min(var(--dms-side-panel-width),60vw)]";
|
|
26
34
|
const dockHeight = (chips: number): string =>
|
|
27
35
|
`${chips * DOCK_CHIP_REM + DOCK_EDGE_REM}rem`;
|
|
28
36
|
|
|
@@ -60,6 +68,17 @@ const regionAttrs = computed(() =>
|
|
|
60
68
|
}
|
|
61
69
|
: {},
|
|
62
70
|
);
|
|
71
|
+
|
|
72
|
+
const { panel: sidePanel, width: sidePanelWidth } = useActiveSidePanel();
|
|
73
|
+
// Bound as attributes so a frame without a panel renders no empty `style`.
|
|
74
|
+
const groupAttrs = computed(() =>
|
|
75
|
+
sidePanel.value
|
|
76
|
+
? {
|
|
77
|
+
class: SIDE_PANEL_ROOM_CLASS,
|
|
78
|
+
style: sidePanelWidthStyle(sidePanelWidth.value),
|
|
79
|
+
}
|
|
80
|
+
: {},
|
|
81
|
+
);
|
|
63
82
|
</script>
|
|
64
83
|
|
|
65
84
|
<template>
|
|
@@ -67,6 +86,7 @@ const regionAttrs = computed(() =>
|
|
|
67
86
|
data-dms-persistent-shell
|
|
68
87
|
:storage-key="DASHBOARD_STORAGE_KEY"
|
|
69
88
|
:unit="DASHBOARD_SIZE_UNIT"
|
|
89
|
+
v-bind="groupAttrs"
|
|
70
90
|
>
|
|
71
91
|
<DashboardSidebar />
|
|
72
92
|
|
|
@@ -93,5 +113,7 @@ const regionAttrs = computed(() =>
|
|
|
93
113
|
<DmsAppWidgetsDock />
|
|
94
114
|
</template>
|
|
95
115
|
</UDashboardPanel>
|
|
116
|
+
|
|
117
|
+
<GithubStarPrompt />
|
|
96
118
|
</UDashboardGroup>
|
|
97
119
|
</template>
|
|
@@ -3,6 +3,7 @@ import type { BreadcrumbItem, DropdownMenuItem } from "@nuxt/ui";
|
|
|
3
3
|
import NotificationPopover from "../notification/NotificationPopover.vue";
|
|
4
4
|
import QuickActionsPopover from "./QuickActionsPopover.vue";
|
|
5
5
|
import { useSidebarState } from "./sidebarState";
|
|
6
|
+
import { useHeaderActionControls } from "../../composables/layout/useHeaderActionControls";
|
|
6
7
|
import { usePageRecordLabel } from "#dms-core/app/build/composables/page/usePageRecordLabel";
|
|
7
8
|
|
|
8
9
|
const HOME_ICON = "i-ph-house-light";
|
|
@@ -37,6 +38,11 @@ const builderAction = computed(() =>
|
|
|
37
38
|
const headerActions = computed(() =>
|
|
38
39
|
registeredActions.value.filter((action) => action.id !== BUILDER_ACTION_ID),
|
|
39
40
|
);
|
|
41
|
+
const {
|
|
42
|
+
isToggle: isActionToggle,
|
|
43
|
+
isActive: isActionActive,
|
|
44
|
+
select: selectAction,
|
|
45
|
+
} = useHeaderActionControls();
|
|
40
46
|
|
|
41
47
|
const sidebarToggleLabel = computed(() =>
|
|
42
48
|
sidebarCollapsed.value
|
|
@@ -233,36 +239,44 @@ const mobileBreadcrumb = computed(
|
|
|
233
239
|
<template #right>
|
|
234
240
|
<UTooltip
|
|
235
241
|
v-if="builderAction"
|
|
236
|
-
:text="builderAction.label"
|
|
242
|
+
:text="processI18n(builderAction.label)"
|
|
237
243
|
:content="TOOLTIP_CONTENT"
|
|
238
244
|
>
|
|
239
245
|
<UButton
|
|
240
246
|
:icon="builderAction.icon || 'i-ph-hammer-light'"
|
|
241
247
|
variant="ghost"
|
|
242
|
-
:color="builderAction
|
|
248
|
+
:color="isActionActive(builderAction) ? 'primary' : 'neutral'"
|
|
243
249
|
:class="
|
|
244
|
-
builderAction
|
|
250
|
+
isActionActive(builderAction) ? undefined : TOOLBAR_BUTTON_CLASS
|
|
251
|
+
"
|
|
252
|
+
:aria-label="processI18n(builderAction.label)"
|
|
253
|
+
:aria-pressed="
|
|
254
|
+
isActionToggle(builderAction)
|
|
255
|
+
? isActionActive(builderAction)
|
|
256
|
+
: undefined
|
|
245
257
|
"
|
|
246
|
-
:aria-label="builderAction.label"
|
|
247
258
|
:ui="{ leadingIcon: 'size-[18px]' }"
|
|
248
|
-
@click="builderAction
|
|
259
|
+
@click="selectAction(builderAction)"
|
|
249
260
|
/>
|
|
250
261
|
</UTooltip>
|
|
251
262
|
|
|
252
263
|
<UTooltip
|
|
253
264
|
v-for="action in headerActions"
|
|
254
265
|
:key="action.id"
|
|
255
|
-
:text="action.label"
|
|
266
|
+
:text="processI18n(action.label)"
|
|
256
267
|
:content="TOOLTIP_CONTENT"
|
|
257
268
|
>
|
|
258
269
|
<UButton
|
|
259
270
|
:icon="action.icon"
|
|
260
271
|
variant="ghost"
|
|
261
|
-
color="neutral"
|
|
262
|
-
:class="TOOLBAR_BUTTON_CLASS"
|
|
263
|
-
:aria-label="action.label"
|
|
272
|
+
:color="isActionActive(action) ? 'primary' : 'neutral'"
|
|
273
|
+
:class="isActionActive(action) ? undefined : TOOLBAR_BUTTON_CLASS"
|
|
274
|
+
:aria-label="processI18n(action.label)"
|
|
275
|
+
:aria-pressed="
|
|
276
|
+
isActionToggle(action) ? isActionActive(action) : undefined
|
|
277
|
+
"
|
|
264
278
|
:ui="{ leadingIcon: 'size-[18px]' }"
|
|
265
|
-
@click="action
|
|
279
|
+
@click="selectAction(action)"
|
|
266
280
|
/>
|
|
267
281
|
</UTooltip>
|
|
268
282
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* One side panel (see `useAppSidePanels`), fixed on the right of the window.
|
|
4
|
+
* From `lg` it is docked: every dashboard frame keeps that width free on its
|
|
5
|
+
* right, so the page shrinks next to it, and a resize handle sits on its inner
|
|
6
|
+
* edge. Below `lg` the same element is a sheet over the page, above a
|
|
7
|
+
* backdrop: the switch is CSS only, so crossing the breakpoint never remounts
|
|
8
|
+
* the panel's component.
|
|
9
|
+
*/
|
|
10
|
+
import { useMediaQuery } from "@vueuse/core";
|
|
11
|
+
import type { SidePanel } from "../../../composables/useAppSidePanels";
|
|
12
|
+
import { useSidePanel } from "../../../composables/useSidePanel";
|
|
13
|
+
import { sidePanelWidthStyle } from "../../composables/layout/sidePanelState";
|
|
14
|
+
import { useSidePanelWidth } from "../../composables/layout/useSidePanelWidth";
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
panel: SidePanel;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const props = defineProps<Props>();
|
|
21
|
+
|
|
22
|
+
// The panel belongs to the dashboard: a page without its shell (onboarding,
|
|
23
|
+
// an error page) hides it, and keeps it mounted for the way back.
|
|
24
|
+
const HOST_CLASS =
|
|
25
|
+
"contents [body:not(:has([data-dms-persistent-shell]))_&]:hidden";
|
|
26
|
+
const DESKTOP_QUERY = "(min-width: 1024px)";
|
|
27
|
+
const ESCAPE_KEY = "Escape";
|
|
28
|
+
const PANEL_DOM_ID_PREFIX = "dms-side-panel-";
|
|
29
|
+
|
|
30
|
+
const { t } = useI18n();
|
|
31
|
+
const { processI18n } = useTranslation();
|
|
32
|
+
const isDocked = useMediaQuery(DESKTOP_QUERY);
|
|
33
|
+
const { close } = useSidePanel(props.panel.id);
|
|
34
|
+
const panelEl = ref<HTMLElement | null>(null);
|
|
35
|
+
const {
|
|
36
|
+
width,
|
|
37
|
+
bounds,
|
|
38
|
+
isDragging,
|
|
39
|
+
startDrag,
|
|
40
|
+
drag,
|
|
41
|
+
endDrag,
|
|
42
|
+
resizeFromKey,
|
|
43
|
+
reset,
|
|
44
|
+
} = useSidePanelWidth(props.panel);
|
|
45
|
+
|
|
46
|
+
const panelDomId = `${PANEL_DOM_ID_PREFIX}${props.panel.id}`;
|
|
47
|
+
const ariaLabel = computed(() =>
|
|
48
|
+
props.panel.ariaLabel ? processI18n(props.panel.ariaLabel) : undefined,
|
|
49
|
+
);
|
|
50
|
+
const panelStyle = computed(() => sidePanelWidthStyle(width.value));
|
|
51
|
+
const panelComponent = computed(
|
|
52
|
+
() => resolveDmsComponent(props.panel.component) ?? props.panel.component,
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
// Escape dismisses the sheet only: docked, the panel is part of the page and
|
|
56
|
+
// its component may give the key a meaning of its own.
|
|
57
|
+
function closeSheetOnEscape(event: KeyboardEvent): void {
|
|
58
|
+
if (event.key !== ESCAPE_KEY || isDocked.value) return;
|
|
59
|
+
close();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function startHandleDrag(event: PointerEvent): void {
|
|
63
|
+
(event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);
|
|
64
|
+
const renderedWidth = panelEl.value?.getBoundingClientRect().width;
|
|
65
|
+
startDrag(event, renderedWidth || width.value);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let focusBeforeOpen: HTMLElement | null = null;
|
|
69
|
+
|
|
70
|
+
function isFocusInside(): boolean {
|
|
71
|
+
return panelEl.value?.contains(document.activeElement) ?? false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// The sheet covers the page, so focus moves into it unless the panel's own
|
|
75
|
+
// component already took it; closing gives focus back to where it came from.
|
|
76
|
+
onMounted(() => {
|
|
77
|
+
const active = document.activeElement;
|
|
78
|
+
focusBeforeOpen = active instanceof HTMLElement ? active : null;
|
|
79
|
+
if (isDocked.value || isFocusInside()) return;
|
|
80
|
+
panelEl.value?.focus();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
onBeforeUnmount(() => {
|
|
84
|
+
if (isFocusInside()) focusBeforeOpen?.focus();
|
|
85
|
+
});
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<template>
|
|
89
|
+
<div data-dms-side-panel-host :class="HOST_CLASS">
|
|
90
|
+
<button
|
|
91
|
+
type="button"
|
|
92
|
+
aria-hidden="true"
|
|
93
|
+
tabindex="-1"
|
|
94
|
+
data-dms-side-panel-backdrop
|
|
95
|
+
class="bg-elevated/75 fixed inset-0 z-40 lg:hidden"
|
|
96
|
+
@click="close"
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
<aside
|
|
100
|
+
:id="panelDomId"
|
|
101
|
+
ref="panelEl"
|
|
102
|
+
data-dms-side-panel
|
|
103
|
+
:data-dragging="isDragging || undefined"
|
|
104
|
+
:aria-label="ariaLabel"
|
|
105
|
+
tabindex="-1"
|
|
106
|
+
class="border-default fixed inset-y-0 end-0 flex w-(--dms-side-panel-width) max-w-full min-w-0 flex-col border-s bg-(--dms-bg-sidebar) outline-none max-lg:z-50 max-lg:shadow-xl lg:max-w-[60vw]"
|
|
107
|
+
:style="panelStyle"
|
|
108
|
+
@keydown="closeSheetOnEscape"
|
|
109
|
+
>
|
|
110
|
+
<div
|
|
111
|
+
role="separator"
|
|
112
|
+
aria-orientation="vertical"
|
|
113
|
+
tabindex="0"
|
|
114
|
+
data-dms-side-panel-handle
|
|
115
|
+
:aria-controls="panelDomId"
|
|
116
|
+
:aria-label="t('side_panel.resize')"
|
|
117
|
+
:aria-valuenow="width"
|
|
118
|
+
:aria-valuemin="bounds.minWidth"
|
|
119
|
+
:aria-valuemax="bounds.maxWidth"
|
|
120
|
+
class="group/handle absolute inset-y-0 -start-1 z-10 hidden w-2 cursor-ew-resize touch-none outline-none select-none lg:block"
|
|
121
|
+
@pointerdown="startHandleDrag"
|
|
122
|
+
@pointermove="drag"
|
|
123
|
+
@pointerup="endDrag"
|
|
124
|
+
@pointercancel="endDrag"
|
|
125
|
+
@lostpointercapture="endDrag"
|
|
126
|
+
@keydown="resizeFromKey"
|
|
127
|
+
@dblclick="reset"
|
|
128
|
+
>
|
|
129
|
+
<span
|
|
130
|
+
aria-hidden="true"
|
|
131
|
+
class="group-hover/handle:bg-primary group-focus-visible/handle:bg-primary absolute inset-y-0 start-1/2 w-0.5 -translate-x-1/2 transition-colors motion-reduce:transition-none"
|
|
132
|
+
:class="{ 'bg-primary': isDragging }"
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
|
|
136
|
+
<component :is="panelComponent" class="min-h-0 flex-1" />
|
|
137
|
+
</aside>
|
|
138
|
+
</div>
|
|
139
|
+
</template>
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { SelectItem } from "@nuxt/ui";
|
|
3
|
+
import {
|
|
4
|
+
GITHUB_REPOSITORY,
|
|
5
|
+
GITHUB_REPOSITORY_URL,
|
|
6
|
+
} from "../../utils/github-repository";
|
|
3
7
|
|
|
4
8
|
const EXTERNAL_LINK_PATTERN = /^https?:\/\//;
|
|
5
|
-
const GITHUB_REPOSITORY = "AntelopeJS/dms";
|
|
6
|
-
const GITHUB_REPOSITORY_URL = `https://github.com/${GITHUB_REPOSITORY}`;
|
|
7
9
|
const GITHUB_REPOSITORY_API = `https://api.github.com/repos/${GITHUB_REPOSITORY}`;
|
|
8
10
|
const GITHUB_STARS_CACHE_KEY = "dms-github-stars";
|
|
9
11
|
// GitHub allows 60 anonymous API calls an hour per visitor: the count is
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed } from "vue";
|
|
3
|
+
import { isFloatingSaveBarShown } from "#dms-ui/app/build/composables/form/floatingSaveBars";
|
|
4
|
+
import { useGithubStarPrompt } from "../../composables/general/useGithubStarPrompt";
|
|
5
|
+
|
|
6
|
+
const TITLE_ID = "dms-github-star-prompt-title";
|
|
7
|
+
const DESCRIPTION_ID = "dms-github-star-prompt-description";
|
|
8
|
+
|
|
9
|
+
const { t } = useI18n();
|
|
10
|
+
const { user } = useCurrentUser();
|
|
11
|
+
const toast = useToast();
|
|
12
|
+
|
|
13
|
+
// Developers only: a production build, a client's dashboard included, never
|
|
14
|
+
// counts, stores or shows anything. The same flag gates the dev reload.
|
|
15
|
+
const { isDue, snooze, star, dismiss } = useGithubStarPrompt(
|
|
16
|
+
import.meta.env.DEV,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
// The toaster stacks in the same corner, and a floating save bar sticks to
|
|
20
|
+
// the bottom of the panel: the prompt steps aside while either is up rather
|
|
21
|
+
// than cover it.
|
|
22
|
+
const isShown = computed(
|
|
23
|
+
() =>
|
|
24
|
+
isDue.value &&
|
|
25
|
+
!!user.value &&
|
|
26
|
+
toast.toasts.value.length === 0 &&
|
|
27
|
+
!isFloatingSaveBarShown.value,
|
|
28
|
+
);
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<!-- A non-modal dialog that takes no focus: it waits at the end of the tab
|
|
33
|
+
order. Toast look (theme/surfaces.ts), in the toaster's corner and
|
|
34
|
+
width, rising into place like a toast. The buttons take the card's
|
|
35
|
+
full width, so the longer French label still fits beside "Later".
|
|
36
|
+
On a phone it tightens and drops the icon, so the text runs the full
|
|
37
|
+
width and covers less of the page. From `lg` it stays clear of an
|
|
38
|
+
open side panel, whose width the dashboard frame sets. -->
|
|
39
|
+
<div
|
|
40
|
+
v-if="isShown"
|
|
41
|
+
role="dialog"
|
|
42
|
+
:aria-labelledby="TITLE_ID"
|
|
43
|
+
:aria-describedby="DESCRIPTION_ID"
|
|
44
|
+
class="bg-default ring-accented fixed inset-x-3 bottom-3 z-50 rounded-(--dms-radius-card) p-3 shadow-(--dms-shadow-pop) ring transition duration-300 ease-out motion-reduce:transition-none sm:inset-x-auto sm:right-5 sm:bottom-5 sm:w-[380px] sm:p-3.5 sm:ps-4 lg:right-[calc(min(var(--dms-side-panel-width,0px),60vw)+1.25rem)] starting:translate-y-4 starting:opacity-0"
|
|
45
|
+
>
|
|
46
|
+
<div class="flex items-start gap-3 pe-6">
|
|
47
|
+
<DmsIconWell icon="i-ph-star" size="sm" class="max-sm:hidden" />
|
|
48
|
+
<div class="min-w-0 flex-1">
|
|
49
|
+
<h2
|
|
50
|
+
:id="TITLE_ID"
|
|
51
|
+
class="text-highlighted text-[13px]/[1.35] font-semibold"
|
|
52
|
+
>
|
|
53
|
+
{{ t("github_star_prompt.title") }}
|
|
54
|
+
</h2>
|
|
55
|
+
<p :id="DESCRIPTION_ID" class="text-muted mt-0.5 text-[13px]/[1.45]">
|
|
56
|
+
{{ t("github_star_prompt.description") }}
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="mt-2.5 flex flex-wrap justify-end gap-1.5 sm:mt-3">
|
|
61
|
+
<UButton
|
|
62
|
+
size="sm"
|
|
63
|
+
color="neutral"
|
|
64
|
+
variant="outline"
|
|
65
|
+
:label="t('github_star_prompt.later')"
|
|
66
|
+
data-action="later"
|
|
67
|
+
@click="snooze"
|
|
68
|
+
/>
|
|
69
|
+
<UButton
|
|
70
|
+
size="sm"
|
|
71
|
+
icon="i-ph-star"
|
|
72
|
+
:label="t('github_star_prompt.star')"
|
|
73
|
+
data-action="star"
|
|
74
|
+
@click="star"
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
<UButton
|
|
78
|
+
size="xs"
|
|
79
|
+
color="neutral"
|
|
80
|
+
variant="ghost"
|
|
81
|
+
square
|
|
82
|
+
icon="i-ph-x"
|
|
83
|
+
class="text-dimmed hover:text-highlighted absolute top-2.5 right-2.5"
|
|
84
|
+
:aria-label="t('github_star_prompt.close')"
|
|
85
|
+
:title="t('github_star_prompt.close')"
|
|
86
|
+
data-action="close"
|
|
87
|
+
@click="dismiss"
|
|
88
|
+
/>
|
|
89
|
+
</div>
|
|
90
|
+
</template>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Renders the open side panel (see `useSidePanel`) once for the whole app,
|
|
4
|
+
* registered as an app overlay: outside the routed layouts, so moving between
|
|
5
|
+
* the default and settings layouts keeps the panel's component mounted. The
|
|
6
|
+
* server renders it from the side panel cookie, in place on the first paint.
|
|
7
|
+
* Keyed by panel id, so each panel keeps its own focus bookkeeping.
|
|
8
|
+
*/
|
|
9
|
+
import DashboardSidePanel from "./DashboardSidePanel.vue";
|
|
10
|
+
import { useActiveSidePanel } from "../../composables/layout/sidePanelState";
|
|
11
|
+
|
|
12
|
+
const { panel } = useActiveSidePanel();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<template>
|
|
16
|
+
<DashboardSidePanel v-if="panel" :key="panel.id" :panel="panel" />
|
|
17
|
+
</template>
|
package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue
CHANGED
|
@@ -5,6 +5,7 @@ import { useNavBadges } from "#dms-ui/app/build/composables/navigation/useNavBad
|
|
|
5
5
|
import { settleWidgetRequest } from "./widgetRequest";
|
|
6
6
|
import type { UserNotification } from "../../../composables/notification/useNotifications";
|
|
7
7
|
import { resolveNotificationTone } from "../pages/settings/notification/notificationDisplay";
|
|
8
|
+
import { DMS_TONE_SOLID, iconWellToneOf } from "#dms-ui/app/build/utils/tone";
|
|
8
9
|
import DmsRowSkeleton from "#dms-ui/app/build/components/skeleton/RowSkeleton.vue";
|
|
9
10
|
|
|
10
11
|
const MAX_DISPLAYED_COUNT = 99;
|
|
@@ -23,13 +24,12 @@ const { loggedIn } = useUserSession();
|
|
|
23
24
|
const { processI18n } = useTranslation();
|
|
24
25
|
const {
|
|
25
26
|
unreadCount,
|
|
26
|
-
|
|
27
|
+
unreadTone,
|
|
27
28
|
notifications,
|
|
28
29
|
hasMore,
|
|
29
30
|
fetchBellCounts,
|
|
30
31
|
fetchNotifications,
|
|
31
32
|
markAsRead,
|
|
32
|
-
markAllSeen,
|
|
33
33
|
} = useNotifications();
|
|
34
34
|
const { setNavBadge } = useNavBadges();
|
|
35
35
|
const isOpen = ref(false);
|
|
@@ -46,37 +46,36 @@ const { isLoadingMore, setupObserver, disconnectObserver } = useInfiniteScroll(
|
|
|
46
46
|
|
|
47
47
|
// The sender's tone (a warning, a success) colours the icon well, as in the
|
|
48
48
|
// inbox; untoned notifications keep the accent until read.
|
|
49
|
-
const iconWellTone = (notification: UserNotification) =>
|
|
50
|
-
|
|
51
|
-
return tone === "neutral" ? "muted" : tone;
|
|
52
|
-
};
|
|
49
|
+
const iconWellTone = (notification: UserNotification) =>
|
|
50
|
+
iconWellToneOf(resolveNotificationTone(notification));
|
|
53
51
|
|
|
54
52
|
const formatCount = (count: number) =>
|
|
55
53
|
count > MAX_DISPLAYED_COUNT ? `${MAX_DISPLAYED_COUNT}+` : String(count);
|
|
56
54
|
|
|
57
|
-
// The bell's badge counts what
|
|
58
|
-
//
|
|
59
|
-
const displayedCount = computed(() => formatCount(
|
|
55
|
+
// The bell's badge counts what is unread, in the tone of the most important
|
|
56
|
+
// unread notification; opening the bell changes neither.
|
|
57
|
+
const displayedCount = computed(() => formatCount(unreadCount.value));
|
|
58
|
+
const badgeToneClass = computed(
|
|
59
|
+
() => DMS_TONE_SOLID[unreadTone.value ?? "neutral"],
|
|
60
|
+
);
|
|
60
61
|
|
|
61
|
-
// The bell is on every page, so it keeps the
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
watch(unreadCount, (count) => {
|
|
65
|
-
setNavBadge(
|
|
62
|
+
// The bell is on every page, so it keeps the badge of the Notifications
|
|
63
|
+
// entry in the navigation current between two menu loads: the same count,
|
|
64
|
+
// in the same tone.
|
|
65
|
+
watch([unreadCount, unreadTone], ([count, tone]) => {
|
|
66
|
+
setNavBadge(
|
|
67
|
+
NOTIFICATIONS_SETTINGS_PAGE,
|
|
68
|
+
count > 0 ? formatCount(count) : "",
|
|
69
|
+
tone,
|
|
70
|
+
);
|
|
66
71
|
});
|
|
67
72
|
|
|
68
73
|
const refreshCounts = () =>
|
|
69
74
|
settleWidgetRequest(fetchBellCounts, () => {
|
|
70
75
|
unreadCount.value = 0;
|
|
71
|
-
|
|
76
|
+
unreadTone.value = undefined;
|
|
72
77
|
});
|
|
73
78
|
|
|
74
|
-
const handleNotificationEvent = async () => {
|
|
75
|
-
if (!isOpen.value) {
|
|
76
|
-
await refreshCounts();
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
|
|
80
79
|
const handleFormSubmitSuccess = async (event: Event) => {
|
|
81
80
|
const customEvent = event as CustomEvent;
|
|
82
81
|
const submitUrl = customEvent.detail?.data?.submitUrl;
|
|
@@ -88,20 +87,10 @@ const handleFormSubmitSuccess = async (event: Event) => {
|
|
|
88
87
|
}
|
|
89
88
|
};
|
|
90
89
|
|
|
91
|
-
// Seeing is not reading: the notifications stay unread until opened or
|
|
92
|
-
// marked read, in the popover or the inbox.
|
|
93
|
-
const markSeen = async () => {
|
|
94
|
-
if (unseenCount.value > 0) await settleWidgetRequest(markAllSeen);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
90
|
onMounted(async () => {
|
|
98
91
|
if (!loggedIn.value) return;
|
|
99
92
|
await refreshCounts();
|
|
100
93
|
|
|
101
|
-
window.addEventListener(
|
|
102
|
-
NotificationEvents.NOTIFICATION_RECEIVED,
|
|
103
|
-
handleNotificationEvent as EventListener,
|
|
104
|
-
);
|
|
105
94
|
window.addEventListener(
|
|
106
95
|
FormEvents.SUBMIT_SUCCESS,
|
|
107
96
|
handleFormSubmitSuccess as EventListener,
|
|
@@ -111,10 +100,6 @@ onMounted(async () => {
|
|
|
111
100
|
onUnmounted(() => {
|
|
112
101
|
disconnectObserver();
|
|
113
102
|
|
|
114
|
-
window.removeEventListener(
|
|
115
|
-
NotificationEvents.NOTIFICATION_RECEIVED,
|
|
116
|
-
handleNotificationEvent as EventListener,
|
|
117
|
-
);
|
|
118
103
|
window.removeEventListener(
|
|
119
104
|
FormEvents.SUBMIT_SUCCESS,
|
|
120
105
|
handleFormSubmitSuccess as EventListener,
|
|
@@ -124,17 +109,12 @@ onUnmounted(() => {
|
|
|
124
109
|
watch(isOpen, async (isNowOpen) => {
|
|
125
110
|
if (isNowOpen) {
|
|
126
111
|
isListLoading.value = true;
|
|
127
|
-
await
|
|
128
|
-
markSeen(),
|
|
129
|
-
settleWidgetRequest(() => fetchNotifications(true)),
|
|
130
|
-
]);
|
|
112
|
+
await settleWidgetRequest(() => fetchNotifications(true));
|
|
131
113
|
isListLoading.value = false;
|
|
132
114
|
await nextTick();
|
|
133
115
|
setupObserver();
|
|
134
116
|
} else {
|
|
135
117
|
disconnectObserver();
|
|
136
|
-
// What arrived while the list was open showed at its top: seen too.
|
|
137
|
-
await markSeen();
|
|
138
118
|
}
|
|
139
119
|
});
|
|
140
120
|
|
|
@@ -175,8 +155,10 @@ const goToNotifications = () => {
|
|
|
175
155
|
<!-- Floats over the button's corner (nothing moves) and fades in
|
|
176
156
|
(starting style) once the count, fetched after mount, is back. -->
|
|
177
157
|
<span
|
|
178
|
-
v-if="
|
|
179
|
-
|
|
158
|
+
v-if="unreadCount > 0"
|
|
159
|
+
data-bell-badge
|
|
160
|
+
:class="badgeToneClass"
|
|
161
|
+
class="absolute -top-0.5 -right-0.5 flex h-4 min-w-4 items-center justify-center rounded-full px-1 text-[10px] leading-none font-semibold ring-2 ring-(--ui-bg-muted) transition-opacity duration-200 starting:opacity-0"
|
|
180
162
|
>
|
|
181
163
|
{{ displayedCount }}
|
|
182
164
|
</span>
|
|
@@ -20,6 +20,8 @@ interface RoleOption {
|
|
|
20
20
|
_id: string;
|
|
21
21
|
name: string;
|
|
22
22
|
permissionIds: string[];
|
|
23
|
+
/** Set when what the role grants amounts to owner-level access. */
|
|
24
|
+
warnings?: string[];
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
interface RoleOptionsResponse {
|
|
@@ -77,8 +79,7 @@ const isOwner = computed(
|
|
|
77
79
|
() => !!props.ownerField && formState?.value?.[props.ownerField] === true,
|
|
78
80
|
);
|
|
79
81
|
const isInert = computed(() => props.disabled || isOwner.value);
|
|
80
|
-
// Without an owner field
|
|
81
|
-
// an owner only.
|
|
82
|
+
// Without an owner field, the form disables the roles for an owner only.
|
|
82
83
|
const showsOwnerHint = computed(() =>
|
|
83
84
|
props.ownerField ? isOwner.value : props.disabled,
|
|
84
85
|
);
|
|
@@ -102,6 +103,19 @@ const roleItems = computed<ChipGroupItem[]>(() =>
|
|
|
102
103
|
const selectedRoles = computed(() =>
|
|
103
104
|
options.value.roles.filter((role) => selectedIds.value.has(role._id)),
|
|
104
105
|
);
|
|
106
|
+
// An owner holds every permission anyway: no warning then.
|
|
107
|
+
const ownerLevelWarning = computed(() => {
|
|
108
|
+
if (isOwner.value) return undefined;
|
|
109
|
+
const names = selectedRoles.value
|
|
110
|
+
.filter((role) => (role.warnings?.length ?? 0) > 0)
|
|
111
|
+
.map((role) => role.name);
|
|
112
|
+
if (names.length === 0) return undefined;
|
|
113
|
+
return t(
|
|
114
|
+
"page.settings.members.invite.roles_owner_level",
|
|
115
|
+
{ roles: names.join(" + ") },
|
|
116
|
+
names.length,
|
|
117
|
+
);
|
|
118
|
+
});
|
|
105
119
|
const grantedCount = computed(
|
|
106
120
|
() => new Set(selectedRoles.value.flatMap((role) => role.permissionIds)).size,
|
|
107
121
|
);
|
|
@@ -180,5 +194,13 @@ function toggle(roleId: string) {
|
|
|
180
194
|
{{ t("page.settings.members.invite.compare_roles") }}
|
|
181
195
|
</ULink>
|
|
182
196
|
</p>
|
|
197
|
+
<p
|
|
198
|
+
v-if="ownerLevelWarning"
|
|
199
|
+
class="text-warning flex items-start gap-1.5 text-xs"
|
|
200
|
+
data-role-owner-level
|
|
201
|
+
>
|
|
202
|
+
<UIcon name="i-ph-warning" class="mt-px size-3.5 shrink-0" />
|
|
203
|
+
<span>{{ ownerLevelWarning }}</span>
|
|
204
|
+
</p>
|
|
183
205
|
</div>
|
|
184
206
|
</template>
|