@antelopejs/dms 0.6.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -0
- package/dist/db/models/notification-feed-filter.d.ts +0 -1
- package/dist/db/models/notification-feed-filter.js +0 -4
- package/dist/db/models/notification-feed-filter.js.map +1 -1
- package/dist/db/models/signInAttempts.model.d.ts +18 -0
- package/dist/db/models/signInAttempts.model.js +83 -12
- package/dist/db/models/signInAttempts.model.js.map +1 -1
- package/dist/db/models/userEmailChanges.model.d.ts +8 -1
- package/dist/db/models/userEmailChanges.model.js +27 -2
- package/dist/db/models/userEmailChanges.model.js.map +1 -1
- package/dist/db/models/userNotificationPreferences.model.d.ts +0 -2
- package/dist/db/models/userNotificationPreferences.model.js +0 -13
- package/dist/db/models/userNotificationPreferences.model.js.map +1 -1
- package/dist/db/models/userNotifications.model.d.ts +5 -2
- package/dist/db/models/userNotifications.model.js +19 -2
- package/dist/db/models/userNotifications.model.js.map +1 -1
- package/dist/db/tables/signInAttempts.table.d.ts +2 -1
- package/dist/db/tables/signInAttempts.table.js +4 -0
- package/dist/db/tables/signInAttempts.table.js.map +1 -1
- package/dist/db/tables/userEmailChanges.table.d.ts +2 -1
- package/dist/db/tables/userEmailChanges.table.js +6 -1
- package/dist/db/tables/userEmailChanges.table.js.map +1 -1
- package/dist/db/tables/userNotificationPreferences.table.d.ts +0 -1
- package/dist/db/tables/userNotificationPreferences.table.js +0 -4
- package/dist/db/tables/userNotificationPreferences.table.js.map +1 -1
- package/dist/implementations/dms/layout-banners.d.ts +4 -1
- package/dist/implementations/dms/layout-banners.js +33 -18
- package/dist/implementations/dms/layout-banners.js.map +1 -1
- package/dist/implementations/dms/nav-badges.d.ts +6 -4
- package/dist/implementations/dms/nav-badges.js +6 -5
- package/dist/implementations/dms/nav-badges.js.map +1 -1
- package/dist/implementations/dms/page.d.ts +1 -0
- package/dist/implementations/dms/page.js +46 -8
- package/dist/implementations/dms/page.js.map +1 -1
- package/dist/implementations/dms/permission-preview.d.ts +1 -1
- package/dist/implementations/dms/permission-preview.js +9 -4
- package/dist/implementations/dms/permission-preview.js.map +1 -1
- package/dist/implementations/dms-auth/index.d.ts +3 -2
- package/dist/implementations/dms-auth/index.js +39 -35
- package/dist/implementations/dms-auth/index.js.map +1 -1
- package/dist/implementations/dms-auth/token-session.d.ts +3 -0
- package/dist/implementations/dms-auth/token-session.js +22 -0
- package/dist/implementations/dms-auth/token-session.js.map +1 -0
- package/dist/implementations/dms-notifications/index.d.ts +0 -1
- package/dist/implementations/dms-notifications/index.js +0 -7
- package/dist/implementations/dms-notifications/index.js.map +1 -1
- package/dist/pages/settings/settings-index.js +3 -2
- package/dist/pages/settings/settings-index.js.map +1 -1
- package/dist/pages/settings/users/account-activity-feed.d.ts +1 -1
- package/dist/pages/settings/users/account-activity-feed.js +1 -1
- package/dist/pages/settings/users/account-activity-feed.js.map +1 -1
- package/dist/pages/settings/users/account-activity.d.ts +1 -1
- package/dist/pages/settings/users/account-activity.js +1 -1
- package/dist/pages/settings/users/account-activity.js.map +1 -1
- package/dist/pages/settings/users/account-credentials.d.ts +3 -0
- package/dist/pages/settings/users/account-credentials.js +2 -0
- package/dist/pages/settings/users/account-credentials.js.map +1 -1
- package/dist/pages/settings/users/current-password.d.ts +1 -1
- package/dist/pages/settings/users/current-password.js +23 -2
- package/dist/pages/settings/users/current-password.js.map +1 -1
- package/dist/pages/settings/users/email-change.d.ts +1 -1
- package/dist/pages/settings/users/email-change.js +33 -26
- package/dist/pages/settings/users/email-change.js.map +1 -1
- package/dist/pages/settings/users/invite-resend.js +0 -1
- package/dist/pages/settings/users/invite-resend.js.map +1 -1
- package/dist/pages/settings/users/invites.d.ts +1 -2
- package/dist/pages/settings/users/invites.js +21 -19
- package/dist/pages/settings/users/invites.js.map +1 -1
- package/dist/pages/settings/users/member-invite-batch.js +0 -1
- package/dist/pages/settings/users/member-invite-batch.js.map +1 -1
- package/dist/pages/settings/users/member-invite-form.js +10 -22
- package/dist/pages/settings/users/member-invite-form.js.map +1 -1
- package/dist/pages/settings/users/member-role-options.d.ts +6 -4
- package/dist/pages/settings/users/member-role-options.js +15 -4
- package/dist/pages/settings/users/member-role-options.js.map +1 -1
- package/dist/pages/settings/users/members.d.ts +2 -3
- package/dist/pages/settings/users/members.js +7 -12
- package/dist/pages/settings/users/members.js.map +1 -1
- package/dist/pages/settings/users/notifications.d.ts +1 -8
- package/dist/pages/settings/users/notifications.js +6 -38
- package/dist/pages/settings/users/notifications.js.map +1 -1
- package/dist/pages/settings/users/permission-tree-nodes.d.ts +1 -1
- package/dist/pages/settings/users/permission-tree-nodes.js +23 -9
- package/dist/pages/settings/users/permission-tree-nodes.js.map +1 -1
- package/dist/pages/settings/users/permission-warnings.d.ts +7 -0
- package/dist/pages/settings/users/permission-warnings.js +42 -0
- package/dist/pages/settings/users/permission-warnings.js.map +1 -0
- package/dist/pages/settings/users/profile-helpers.d.ts +1 -3
- package/dist/pages/settings/users/profile-helpers.js +0 -16
- package/dist/pages/settings/users/profile-helpers.js.map +1 -1
- package/dist/pages/settings/users/role-editor-store.js +6 -3
- package/dist/pages/settings/users/role-editor-store.js.map +1 -1
- package/dist/pages/settings/users/role-editor.d.ts +2 -1
- package/dist/pages/settings/users/role-editor.js +8 -4
- package/dist/pages/settings/users/role-editor.js.map +1 -1
- package/dist/pages/settings/users/role-preview.js +2 -1
- package/dist/pages/settings/users/role-preview.js.map +1 -1
- package/dist/pages/settings/users/roles.js +5 -1
- package/dist/pages/settings/users/roles.js.map +1 -1
- package/dist/pages/settings/users/security-attention.d.ts +4 -0
- package/dist/pages/settings/users/security-attention.js +23 -7
- package/dist/pages/settings/users/security-attention.js.map +1 -1
- package/dist/pages/settings/users/security.d.ts +2 -1
- package/dist/pages/settings/users/security.js +13 -2
- package/dist/pages/settings/users/security.js.map +1 -1
- package/dist/pages/settings/users/two-factor-operations.d.ts +2 -1
- package/dist/pages/settings/users/two-factor-operations.js +28 -29
- package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
- package/dist/routes/auth/forgot-password.js +3 -0
- package/dist/routes/auth/forgot-password.js.map +1 -1
- package/dist/routes/auth/index.d.ts +1 -0
- package/dist/routes/auth/index.js +1 -0
- package/dist/routes/auth/index.js.map +1 -1
- package/dist/routes/auth/invite.js +28 -4
- package/dist/routes/auth/invite.js.map +1 -1
- package/dist/routes/auth/login-throttle.d.ts +2 -0
- package/dist/routes/auth/login-throttle.js +5 -4
- package/dist/routes/auth/login-throttle.js.map +1 -1
- package/dist/routes/auth/request-2fa-email.js +6 -18
- package/dist/routes/auth/request-2fa-email.js.map +1 -1
- package/dist/routes/auth/reset-code.d.ts +3 -0
- package/dist/routes/auth/reset-code.js +37 -0
- package/dist/routes/auth/reset-code.js.map +1 -0
- package/dist/routes/auth/reset-password.d.ts +2 -2
- package/dist/routes/auth/reset-password.js +5 -10
- package/dist/routes/auth/reset-password.js.map +1 -1
- package/dist/routes/auth/signup.js +10 -32
- package/dist/routes/auth/signup.js.map +1 -1
- package/dist/routes/auth/two-factor-throttle.d.ts +5 -0
- package/dist/routes/auth/two-factor-throttle.js +81 -0
- package/dist/routes/auth/two-factor-throttle.js.map +1 -0
- package/dist/routes/auth/validate-forgot-password-token.js +2 -8
- package/dist/routes/auth/validate-forgot-password-token.js.map +1 -1
- package/dist/routes/auth/validate-invite-token.d.ts +1 -0
- package/dist/routes/auth/validate-invite-token.js +11 -0
- package/dist/routes/auth/validate-invite-token.js.map +1 -0
- package/dist/routes/auth/verify-2fa.js +10 -13
- package/dist/routes/auth/verify-2fa.js.map +1 -1
- package/dist/routes/auth.d.ts +1 -0
- package/dist/routes/auth.js +11 -1
- package/dist/routes/auth.js.map +1 -1
- package/dist/test/helpers/auth.d.ts +0 -1
- package/dist/test/helpers/auth.js +0 -1
- package/dist/test/helpers/auth.js.map +1 -1
- package/dist/test/helpers/emails.d.ts +10 -0
- package/dist/test/helpers/emails.js +36 -0
- package/dist/test/helpers/emails.js.map +1 -0
- package/dist/test/helpers/fixtures.d.ts +0 -1
- package/dist/test/helpers/fixtures.js +1 -2
- package/dist/test/helpers/fixtures.js.map +1 -1
- package/dist/test/helpers/page-access.d.ts +1 -0
- package/dist/test/helpers/page-access.js +6 -1
- package/dist/test/helpers/page-access.js.map +1 -1
- package/dist/test/integration/auth/current-password.test.d.ts +1 -0
- package/dist/test/integration/auth/current-password.test.js +65 -0
- package/dist/test/integration/auth/current-password.test.js.map +1 -0
- package/dist/test/integration/auth/password-reset.test.d.ts +1 -0
- package/dist/test/integration/auth/password-reset.test.js +126 -0
- package/dist/test/integration/auth/password-reset.test.js.map +1 -0
- package/dist/test/integration/auth/session-revocation.test.d.ts +1 -0
- package/dist/test/integration/auth/session-revocation.test.js +45 -0
- package/dist/test/integration/auth/session-revocation.test.js.map +1 -0
- package/dist/test/integration/auth/two-factor-codes.test.d.ts +1 -0
- package/dist/test/integration/auth/two-factor-codes.test.js +335 -0
- package/dist/test/integration/auth/two-factor-codes.test.js.map +1 -0
- package/dist/test/integration/auth/two-factor-password.test.js +5 -1
- package/dist/test/integration/auth/two-factor-password.test.js.map +1 -1
- package/dist/test/integration/auth/two-factor-token.test.d.ts +1 -0
- package/dist/test/integration/auth/two-factor-token.test.js +92 -0
- package/dist/test/integration/auth/two-factor-token.test.js.map +1 -0
- package/dist/test/integration/email-change.test.js +36 -0
- package/dist/test/integration/email-change.test.js.map +1 -1
- package/dist/test/integration/invite-extension-edit.test.js +0 -1
- package/dist/test/integration/invite-extension-edit.test.js.map +1 -1
- package/dist/test/integration/invite-link-status.test.d.ts +1 -0
- package/dist/test/integration/invite-link-status.test.js +110 -0
- package/dist/test/integration/invite-link-status.test.js.map +1 -0
- package/dist/test/integration/invite-resolution.test.js +0 -3
- package/dist/test/integration/invite-resolution.test.js.map +1 -1
- package/dist/test/integration/member-settings-access.test.js +17 -0
- package/dist/test/integration/member-settings-access.test.js.map +1 -1
- package/dist/test/integration/notification-unread-badge.test.d.ts +1 -0
- package/dist/test/integration/notification-unread-badge.test.js +92 -0
- package/dist/test/integration/notification-unread-badge.test.js.map +1 -0
- package/dist/test/integration/permission-warnings.test.d.ts +1 -0
- package/dist/test/integration/permission-warnings.test.js +71 -0
- package/dist/test/integration/permission-warnings.test.js.map +1 -0
- package/dist/test/integration/removed-member-notifications.test.d.ts +1 -0
- package/dist/test/integration/removed-member-notifications.test.js +80 -0
- package/dist/test/integration/removed-member-notifications.test.js.map +1 -0
- package/dist/test/integration/role-permission-ancestors.test.d.ts +1 -0
- package/dist/test/integration/role-permission-ancestors.test.js +146 -0
- package/dist/test/integration/role-permission-ancestors.test.js.map +1 -0
- package/dist/test/integration/tenant-lifecycle.test.js +0 -4
- package/dist/test/integration/tenant-lifecycle.test.js.map +1 -1
- package/dist/test/unit/auth-session-revocation.test.d.ts +1 -0
- package/dist/test/unit/auth-session-revocation.test.js +105 -0
- package/dist/test/unit/auth-session-revocation.test.js.map +1 -0
- package/dist/test/unit/db/email-normalization.test.js +0 -1
- package/dist/test/unit/db/email-normalization.test.js.map +1 -1
- package/dist/test/unit/db/notification-feed-filter.test.js +0 -16
- package/dist/test/unit/db/notification-feed-filter.test.js.map +1 -1
- package/dist/test/unit/db/notification-inbox.test.js +63 -13
- package/dist/test/unit/db/notification-inbox.test.js.map +1 -1
- package/dist/test/unit/db/notification-preferences.test.js +0 -17
- package/dist/test/unit/db/notification-preferences.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/empty-menu-group.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/empty-menu-group.test.js +133 -0
- package/dist/test/unit/implementations/dms/empty-menu-group.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/layout-banners.test.js +78 -1
- package/dist/test/unit/implementations/dms/layout-banners.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js +149 -0
- package/dist/test/unit/implementations/dms/menu-hidden-blocks.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/nav-badges.test.js +55 -4
- package/dist/test/unit/implementations/dms/nav-badges.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.d.ts +1 -0
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js +118 -0
- package/dist/test/unit/implementations/dms/page-all-components-hidden.test.js.map +1 -0
- package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js +16 -0
- package/dist/test/unit/implementations/dms/permission-preview-aggregate.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/permission-preview-cost.test.js +5 -3
- package/dist/test/unit/implementations/dms/permission-preview-cost.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/permission-preview-menu.test.js +29 -3
- package/dist/test/unit/implementations/dms/permission-preview-menu.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/quick-actions-button.test.js +4 -2
- package/dist/test/unit/implementations/dms/quick-actions-button.test.js.map +1 -1
- package/dist/test/unit/implementations/dms/user-permissions-gate.test.js +2 -1
- package/dist/test/unit/implementations/dms/user-permissions-gate.test.js.map +1 -1
- package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js +2 -1
- package/dist/test/unit/implementations/dms-base/table-view-shared-controller.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/component-children-permissions.test.js +7 -2
- package/dist/test/unit/interfaces/dms/component-children-permissions.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js +133 -0
- package/dist/test/unit/interfaces/dms/form-watch-permissions.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js +149 -0
- package/dist/test/unit/interfaces/dms/has-permission-ancestors.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/invite-extension.test.js +13 -0
- package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/member-access.test.js +27 -1
- package/dist/test/unit/interfaces/dms/member-access.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js +31 -0
- package/dist/test/unit/interfaces/dms/nav-badge-tones.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms/page-extension.test.js +4 -1
- package/dist/test/unit/interfaces/dms/page-extension.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms/permission-requirements.test.d.ts +1 -0
- package/dist/test/unit/interfaces/dms/permission-requirements.test.js +144 -0
- package/dist/test/unit/interfaces/dms/permission-requirements.test.js.map +1 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js +70 -0
- package/dist/test/unit/interfaces/dms-base/column-display.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js +38 -0
- package/dist/test/unit/interfaces/dms-base/display-blocks-catalog.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js +6 -2
- package/dist/test/unit/interfaces/dms-base/layout-header-actions.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js +1 -1
- package/dist/test/unit/interfaces/dms-base/lists-and-settings-catalog.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-export-permission.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-reduced-chrome.test.js.map +1 -1
- package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js +2 -1
- package/dist/test/unit/interfaces/dms-base/table-view-shared-controller-permissions.test.js.map +1 -1
- package/dist/test/unit/pages/settings/account-activity-feed.test.js +2 -2
- package/dist/test/unit/pages/settings/account-activity-feed.test.js.map +1 -1
- package/dist/test/unit/pages/settings/account-activity.test.js +11 -2
- package/dist/test/unit/pages/settings/account-activity.test.js.map +1 -1
- package/dist/test/unit/pages/settings/invite-email-delivery.test.js +0 -1
- package/dist/test/unit/pages/settings/invite-email-delivery.test.js.map +1 -1
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.js +33 -0
- package/dist/test/unit/pages/settings/invite-email-validation-option.test.js.map +1 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.js +22 -0
- package/dist/test/unit/pages/settings/member-lists-page-size.test.js.map +1 -0
- package/dist/test/unit/pages/settings/member-table-widths.test.js +2 -2
- package/dist/test/unit/pages/settings/member-table-widths.test.js.map +1 -1
- package/dist/test/unit/pages/settings/members-page.test.js +7 -10
- package/dist/test/unit/pages/settings/members-page.test.js.map +1 -1
- package/dist/test/unit/pages/settings/notifications-access-gate.test.js +3 -10
- package/dist/test/unit/pages/settings/notifications-access-gate.test.js.map +1 -1
- package/dist/test/unit/pages/settings/permission-tree-nodes.test.js +57 -0
- package/dist/test/unit/pages/settings/permission-tree-nodes.test.js.map +1 -1
- package/dist/test/unit/pages/settings/permission-warnings.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/permission-warnings.test.js +49 -0
- package/dist/test/unit/pages/settings/permission-warnings.test.js.map +1 -0
- package/dist/test/unit/pages/settings/role-editor.test.js +16 -0
- package/dist/test/unit/pages/settings/role-editor.test.js.map +1 -1
- package/dist/test/unit/pages/settings/role-preview.test.js +7 -0
- package/dist/test/unit/pages/settings/role-preview.test.js.map +1 -1
- package/dist/test/unit/pages/settings/security-attention.test.d.ts +1 -0
- package/dist/test/unit/pages/settings/security-attention.test.js +74 -0
- package/dist/test/unit/pages/settings/security-attention.test.js.map +1 -0
- package/dist/test/unit/sanitize-user.test.d.ts +1 -0
- package/dist/test/unit/sanitize-user.test.js +21 -0
- package/dist/test/unit/sanitize-user.test.js.map +1 -0
- package/dist/test/unit/signup-email-validation.test.d.ts +1 -0
- package/dist/test/unit/signup-email-validation.test.js +79 -0
- package/dist/test/unit/signup-email-validation.test.js.map +1 -0
- package/dist/test/unit/validation/member-invite.schema.test.js +14 -52
- package/dist/test/unit/validation/member-invite.schema.test.js.map +1 -1
- package/dist/utils/account-notifications.d.ts +5 -0
- package/dist/utils/account-notifications.js +8 -0
- package/dist/utils/account-notifications.js.map +1 -1
- package/dist/utils/notification-emitter.d.ts +1 -1
- package/dist/utils/notification-emitter.js +1 -1
- package/dist/utils/notification-emitter.js.map +1 -1
- package/dist/utils/notification-tones.d.ts +2 -1
- package/dist/utils/notification-tones.js +5 -1
- package/dist/utils/notification-tones.js.map +1 -1
- package/dist/utils/one-time-code.d.ts +3 -0
- package/dist/utils/one-time-code.js +21 -0
- package/dist/utils/one-time-code.js.map +1 -0
- package/dist/utils/sign-in-monitor.d.ts +1 -0
- package/dist/utils/sign-in-monitor.js +3 -2
- package/dist/utils/sign-in-monitor.js.map +1 -1
- package/dist/utils/two-factor-codes.d.ts +10 -0
- package/dist/utils/two-factor-codes.js +76 -0
- package/dist/utils/two-factor-codes.js.map +1 -0
- package/dist/validation/auth.schema.d.ts +17 -0
- package/dist/validation/auth.schema.js +17 -6
- package/dist/validation/auth.schema.js.map +1 -1
- package/dist/validation/issue-message.d.ts +1 -0
- package/dist/validation/issue-message.js +9 -0
- package/dist/validation/issue-message.js.map +1 -0
- package/dist/validation/member-invite.schema.d.ts +1 -25
- package/dist/validation/member-invite.schema.js +2 -23
- package/dist/validation/member-invite.schema.js.map +1 -1
- package/frontend-vue/dms.frontend.ts +2 -0
- package/frontend-vue/layers/dms-auth/app/custom-pages/auth/forgot-validation.vue +3 -0
- package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +105 -5
- package/frontend-vue/layers/dms-auth/i18n/locales/auth-en-GB.json +20 -4
- package/frontend-vue/layers/dms-auth/i18n/locales/auth-fr-FR.json +20 -4
- package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +25 -0
- package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +3 -2
- package/frontend-vue/layers/dms-core/app/types/composed-text.ts +64 -0
- package/frontend-vue/layers/dms-core/app/types/menu.ts +15 -0
- package/frontend-vue/layers/dms-core/app/utils/composedText.ts +227 -0
- package/frontend-vue/layers/dms-core/app/utils/formatter.ts +49 -0
- package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +4 -1
- package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +4 -1
- package/frontend-vue/layers/dms-layout/app/assets/css/main.css +20 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/CommandPaletteAssistantAnswer.vue +75 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +17 -3
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardFrame.vue +22 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +24 -10
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidePanel.vue +139 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +4 -2
- package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +90 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/SidePanelHost.vue +17 -0
- package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +25 -43
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/members/MemberRolePicker.vue +24 -2
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationMatrixCategory.vue +70 -25
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationPreferencesForm.vue +25 -10
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/notificationDisplay.ts +41 -5
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfilePreferencesSummary.vue +2 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/profile/ProfileSecuritySummary.vue +20 -4
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RoleEditor.vue +21 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionArea.vue +16 -2
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionBranch.vue +1 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionLeaf.vue +13 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionTree.vue +9 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/RolePermissionWarning.vue +46 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +108 -29
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-types.ts +2 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityDialogFrame.vue +6 -6
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityEmail.vue +7 -1
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecuritySessions.vue +5 -4
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityStatus.vue +4 -3
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/security/SecurityTwoFactor.vue +54 -18
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/shell/SettingsNav.vue +13 -8
- package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/assistantGroups.ts +143 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/command-palette/useCommandPaletteAssistantMode.ts +249 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/general/useGithubStarPrompt.ts +178 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/sidePanelState.ts +191 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useHeaderActionControls.ts +51 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +113 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/navigation/useCategoryNavCards.ts +17 -10
- package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +45 -0
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/profile/useProfilePreferences.ts +8 -1
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/security/useSecurityOverview.ts +50 -3
- package/frontend-vue/layers/dms-layout/app/build/composables/settings/useSettingsNavigation.ts +3 -0
- package/frontend-vue/layers/dms-layout/app/build/utils/categoryPages.ts +1 -2
- package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +5 -0
- package/frontend-vue/layers/dms-layout/app/components/layout/DashboardSearch.vue +109 -7
- package/frontend-vue/layers/dms-layout/app/components/navigation/NavigationMenu.vue +19 -9
- package/frontend-vue/layers/dms-layout/app/composables/notification/useNotifications.ts +22 -40
- package/frontend-vue/layers/dms-layout/app/composables/useAppSidePanels.ts +96 -0
- package/frontend-vue/layers/dms-layout/app/composables/useCommandPaletteAssistant.ts +129 -0
- package/frontend-vue/layers/dms-layout/app/composables/useHeaderActions.ts +33 -11
- package/frontend-vue/layers/dms-layout/app/composables/useSidePanel.ts +41 -0
- package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +15 -0
- package/frontend-vue/layers/dms-layout/app/plugins/notification-stream.client.ts +1 -7
- package/frontend-vue/layers/dms-layout/app/plugins/side-panel-host.ts +13 -0
- package/frontend-vue/layers/dms-layout/app/types/page.ts +11 -1
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +43 -13
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +43 -13
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +45 -0
- package/frontend-vue/layers/dms-ui/app/build/components/modal/ModalEscHint.vue +28 -0
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/IdentityCell.vue +36 -7
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/cellHelpers.ts +57 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +19 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +22 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +118 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +5 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/form/floatingSaveBars.ts +38 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +66 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/navigation/useNavBadges.ts +50 -9
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +7 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/chrome.ts +2 -2
- package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +14 -10
- package/frontend-vue/layers/dms-ui/app/build/utils/navBadge.ts +12 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +4 -35
- package/frontend-vue/layers/dms-ui/app/build/utils/tone.ts +22 -0
- package/frontend-vue/layers/dms-ui/app/components/activity-feed/ActivityFeed.vue +117 -82
- package/frontend-vue/layers/dms-ui/app/components/blocks/BannerBlock.vue +8 -5
- package/frontend-vue/layers/dms-ui/app/components/blocks/KeyValueListBlock.vue +38 -18
- package/frontend-vue/layers/dms-ui/app/components/blocks/NavCardGridBlock.vue +12 -1
- package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +26 -23
- package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +16 -1
- package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +7 -8
- package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +28 -6
- package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +5 -1
- package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +4 -0
- package/frontend-vue/layers/dms-ui/app/components/status-pill/StatusPill.vue +7 -2
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +7 -2
- package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +48 -34
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +13 -3
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -14
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -14
- package/frontend-vue/package.json +2 -2
- package/frontend-vue/pnpm-lock.yaml +5 -5
- package/frontend-vue/tests/activity-feed-fill-height.test.ts +107 -0
- package/frontend-vue/tests/category-nav-cards.test.ts +21 -13
- package/frontend-vue/tests/command-palette-assistant.test.ts +344 -0
- package/frontend-vue/tests/composed-text-blocks.test.ts +205 -0
- package/frontend-vue/tests/composed-text.test.ts +265 -0
- package/frontend-vue/tests/fixtures/dashboard-search-stub.ts +91 -0
- package/frontend-vue/tests/forgot-validation-resend.test.ts +234 -0
- package/frontend-vue/tests/form-display-options.test.ts +64 -0
- package/frontend-vue/tests/form-load-error.test.ts +160 -0
- package/frontend-vue/tests/form-saved-before-success.test.ts +110 -0
- package/frontend-vue/tests/github-star-prompt.test.ts +328 -0
- package/frontend-vue/tests/header-actions.test.ts +191 -0
- package/frontend-vue/tests/invites-edit-modal.test.ts +157 -0
- package/frontend-vue/tests/layout-banners.test.ts +56 -0
- package/frontend-vue/tests/member-role-picker.test.ts +26 -0
- package/frontend-vue/tests/menu-hidden-page.test.ts +93 -0
- package/frontend-vue/tests/nav-badge-tones.test.ts +274 -0
- package/frontend-vue/tests/nav-card-badge.test.ts +69 -0
- package/frontend-vue/tests/nav-card-grid-empty-category.test.ts +163 -0
- package/frontend-vue/tests/notification-popover-errors.test.ts +71 -37
- package/frontend-vue/tests/notification-preferences-groups.test.ts +268 -0
- package/frontend-vue/tests/notification-tone-contract.test.ts +70 -0
- package/frontend-vue/tests/page-fill-height.test.ts +9 -1
- package/frontend-vue/tests/page-no-visible-blocks.test.ts +202 -0
- package/frontend-vue/tests/profile-preferences-summary.test.ts +26 -2
- package/frontend-vue/tests/profile-security-summary.test.ts +121 -0
- package/frontend-vue/tests/role-permission-tree.test.ts +102 -8
- package/frontend-vue/tests/role-permissions.test.ts +178 -56
- package/frontend-vue/tests/side-panels.test.ts +470 -0
- package/frontend-vue/tests/signup-invitation-link.test.ts +71 -2
- package/frontend-vue/tests/table-actions-column-width.test.ts +51 -1
- package/frontend-vue/tests/table-cell-sublines.test.ts +466 -0
- package/frontend-vue/tests/table-metric-cells.test.ts +4 -0
- package/frontend-vue/tests/table-view-chrome.test.ts +2 -2
- package/frontend-vue/tests/vue-inventory.test.ts +1 -1
- package/package.json +2 -2
- package/skills/dms/REFERENCE.md +1 -1
- package/skills/dms/SKILL.md +7 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { NotificationEvents } from "./types/events";
|
|
2
|
+
import { unreadToneWith } from "../../build/components/pages/settings/notification/notificationDisplay";
|
|
2
3
|
|
|
3
4
|
/** Icon well colour a sender may set on a notification. */
|
|
4
5
|
export type NotificationTone =
|
|
@@ -25,13 +26,14 @@ export interface UserNotification {
|
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
/**
|
|
28
|
-
* The whole feed's totals, with
|
|
29
|
-
*
|
|
29
|
+
* The whole feed's totals, with the tone of the unread badge (the header
|
|
30
|
+
* bell, the Notifications entry): the most important unread notification's,
|
|
31
|
+
* which the server weighs as the inbox draws it.
|
|
30
32
|
*/
|
|
31
33
|
interface FeedCounts {
|
|
32
34
|
all: number;
|
|
33
35
|
unread: number;
|
|
34
|
-
|
|
36
|
+
unreadTone?: NotificationTone;
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const API_BASE = "/settings/user/notifications";
|
|
@@ -42,17 +44,14 @@ const buildListUrl = (offset: number) =>
|
|
|
42
44
|
`${API_BASE}/list?limit=${NOTIFICATIONS_PAGE_SIZE}&offset=${offset}`;
|
|
43
45
|
|
|
44
46
|
/**
|
|
45
|
-
* Shared notification state of the header bell (
|
|
46
|
-
* and of the settings navigation
|
|
47
|
+
* Shared notification state of the header bell (unread count and tone,
|
|
48
|
+
* popover feed) and of the settings navigation; the settings inbox is a
|
|
47
49
|
* table view of its own (`dms:inbox`), which lists the feed again when these
|
|
48
50
|
* counts change.
|
|
49
51
|
*
|
|
50
|
-
*
|
|
51
|
-
* unread
|
|
52
|
-
*
|
|
53
|
-
* it is opened or marked read; `unreadCount` (the whole feed's unread total)
|
|
54
|
-
* feeds the Notifications entry of the settings navigation and its overview
|
|
55
|
-
* card.
|
|
52
|
+
* The bell and the Notifications entry show the same badge: `unreadCount`,
|
|
53
|
+
* the whole feed's unread total, in `unreadTone`. Opening the bell changes
|
|
54
|
+
* neither; a notification leaves the count once opened or marked read.
|
|
56
55
|
*/
|
|
57
56
|
export const useNotifications = () => {
|
|
58
57
|
const { $authFetch } = useAuthFetch();
|
|
@@ -61,9 +60,9 @@ export const useNotifications = () => {
|
|
|
61
60
|
"notifications-unread-count",
|
|
62
61
|
() => 0,
|
|
63
62
|
);
|
|
64
|
-
const
|
|
65
|
-
"notifications-
|
|
66
|
-
() =>
|
|
63
|
+
const unreadTone = useDmsState<NotificationTone | undefined>(
|
|
64
|
+
"notifications-unread-tone",
|
|
65
|
+
() => undefined,
|
|
67
66
|
);
|
|
68
67
|
// Whether the counts have been asked once, answered or not: until then,
|
|
69
68
|
// a 0 unread is not known to be true.
|
|
@@ -125,13 +124,13 @@ export const useNotifications = () => {
|
|
|
125
124
|
);
|
|
126
125
|
};
|
|
127
126
|
|
|
128
|
-
/** Takes the whole feed's unread and
|
|
127
|
+
/** Takes the whole feed's unread total and its tone. */
|
|
129
128
|
const applyFeedCounts = (counts: FeedCounts) => {
|
|
130
129
|
unreadCount.value = counts.unread;
|
|
131
|
-
|
|
130
|
+
unreadTone.value = counts.unread > 0 ? counts.unreadTone : undefined;
|
|
132
131
|
};
|
|
133
132
|
|
|
134
|
-
/** Loads the
|
|
133
|
+
/** Loads the whole feed's unread count and tone, the bell's badge. */
|
|
135
134
|
const fetchBellCounts = async () => {
|
|
136
135
|
try {
|
|
137
136
|
const counts = await $authFetch<FeedCounts>(`${API_BASE}/counts`);
|
|
@@ -141,15 +140,6 @@ export const useNotifications = () => {
|
|
|
141
140
|
}
|
|
142
141
|
};
|
|
143
142
|
|
|
144
|
-
/**
|
|
145
|
-
* The bell was opened: its badge resets, and counts again what arrives
|
|
146
|
-
* later. The notifications stay unread.
|
|
147
|
-
*/
|
|
148
|
-
const markAllSeen = async () => {
|
|
149
|
-
unseenCount.value = 0;
|
|
150
|
-
await $authFetch(`${API_BASE}/seen`, { method: "PUT" });
|
|
151
|
-
};
|
|
152
|
-
|
|
153
143
|
const fetchUnreadPreview = async () => {
|
|
154
144
|
const data = await $authFetch<UserNotification[]>(
|
|
155
145
|
`${API_BASE}/unread-preview`,
|
|
@@ -231,14 +221,10 @@ export const useNotifications = () => {
|
|
|
231
221
|
emitCount();
|
|
232
222
|
};
|
|
233
223
|
|
|
234
|
-
/** The bell was opened in another tab: this one's badge resets too. */
|
|
235
|
-
const handleRemoteSeen = () => {
|
|
236
|
-
unseenCount.value = 0;
|
|
237
|
-
};
|
|
238
|
-
|
|
239
224
|
/**
|
|
240
|
-
* A notification pushed in real time:
|
|
241
|
-
*
|
|
225
|
+
* A notification pushed in real time: listed first, counted unread, and its
|
|
226
|
+
* tone weighed into the badge's here, without asking the server again — a
|
|
227
|
+
* broadcast would otherwise have every open tab fetch the counts at once.
|
|
242
228
|
*/
|
|
243
229
|
const handleIncomingNotification = (incoming: UserNotification) => {
|
|
244
230
|
const isAlreadyKnown = notifications.value.some(
|
|
@@ -247,10 +233,8 @@ export const useNotifications = () => {
|
|
|
247
233
|
if (isAlreadyKnown) return;
|
|
248
234
|
notifications.value = [incoming, ...notifications.value];
|
|
249
235
|
unreadPreview.value = [incoming, ...unreadPreview.value];
|
|
250
|
-
if (!incoming.isRead)
|
|
251
|
-
|
|
252
|
-
unseenCount.value += 1;
|
|
253
|
-
}
|
|
236
|
+
if (!incoming.isRead) unreadCount.value += 1;
|
|
237
|
+
unreadTone.value = unreadToneWith(unreadTone.value, incoming);
|
|
254
238
|
sendComponentEvent(
|
|
255
239
|
NotificationEvents.NOTIFICATION_RECEIVED,
|
|
256
240
|
NOTIFICATION_COMPONENT_ID,
|
|
@@ -261,7 +245,7 @@ export const useNotifications = () => {
|
|
|
261
245
|
|
|
262
246
|
return {
|
|
263
247
|
unreadCount,
|
|
264
|
-
|
|
248
|
+
unreadTone,
|
|
265
249
|
areCountsLoaded,
|
|
266
250
|
unreadPreview,
|
|
267
251
|
notifications,
|
|
@@ -271,12 +255,10 @@ export const useNotifications = () => {
|
|
|
271
255
|
fetchNotifications,
|
|
272
256
|
markAsRead,
|
|
273
257
|
markAsUnread,
|
|
274
|
-
markAllSeen,
|
|
275
258
|
deleteNotification,
|
|
276
259
|
handleIncomingNotification,
|
|
277
260
|
handleRemoteRead,
|
|
278
261
|
handleRemoteUnread,
|
|
279
262
|
handleRemoteAllRead,
|
|
280
|
-
handleRemoteSeen,
|
|
281
263
|
};
|
|
282
264
|
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A panel docked on the right of the dashboard. Unlike a free overlay (see
|
|
3
|
+
* {@link useAppOverlay}), the DMS owns the placement and the state: from `lg`
|
|
4
|
+
* the panel sits next to the page, which shrinks to make room, behind a resize
|
|
5
|
+
* handle; below `lg` it slides over the page as a sheet above a backdrop. The
|
|
6
|
+
* module only declares its component; it opens and closes the panel through
|
|
7
|
+
* {@link useSidePanel}.
|
|
8
|
+
*
|
|
9
|
+
* A registration is plain data, so it may run from a universal plugin: the
|
|
10
|
+
* server renders an open panel in place, and a reload shows it without the
|
|
11
|
+
* page jumping.
|
|
12
|
+
*/
|
|
13
|
+
export interface SidePanel {
|
|
14
|
+
/** Unique key: dedup on `register` (upsert), target of `unregister`, and the id `useSidePanel` opens. */
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* Name of a global component rendered inside the panel. It fills the panel's
|
|
18
|
+
* height and scrolls its own content.
|
|
19
|
+
*/
|
|
20
|
+
component: string;
|
|
21
|
+
/**
|
|
22
|
+
* Accessible name of the panel landmark. Resolved through the DMS i18n
|
|
23
|
+
* convention: a plain literal, or an i18n key when prefixed with "$".
|
|
24
|
+
*/
|
|
25
|
+
ariaLabel?: string;
|
|
26
|
+
/** Width in px before the user resizes the panel. Defaults to `440`. */
|
|
27
|
+
defaultWidth?: number;
|
|
28
|
+
/** Narrowest width in px the resize handle allows. Defaults to `320`. */
|
|
29
|
+
minWidth?: number;
|
|
30
|
+
/** Widest width in px the resize handle allows. Defaults to `720`. */
|
|
31
|
+
maxWidth?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The width bounds of a side panel, defaults applied. */
|
|
35
|
+
export interface SidePanelWidthBounds {
|
|
36
|
+
defaultWidth: number;
|
|
37
|
+
minWidth: number;
|
|
38
|
+
maxWidth: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface UseAppSidePanelsReturn {
|
|
42
|
+
panels: Readonly<Ref<SidePanel[]>>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const SIDE_PANELS_STATE_KEY = "dms:side-panels";
|
|
46
|
+
const DEFAULT_SIDE_PANEL_WIDTH = 440;
|
|
47
|
+
const DEFAULT_SIDE_PANEL_MIN_WIDTH = 320;
|
|
48
|
+
const DEFAULT_SIDE_PANEL_MAX_WIDTH = 720;
|
|
49
|
+
|
|
50
|
+
function useSidePanelState() {
|
|
51
|
+
return useDmsState<SidePanel[]>(SIDE_PANELS_STATE_KEY, () => []);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Registers a {@link SidePanel}, replacing any panel registered under the same
|
|
56
|
+
* `id`. Call it inside the DMS app, from a universal plugin.
|
|
57
|
+
*/
|
|
58
|
+
export function registerSidePanel(panel: SidePanel): void {
|
|
59
|
+
const panels = useSidePanelState();
|
|
60
|
+
const next = panels.value.filter((entry) => entry.id !== panel.id);
|
|
61
|
+
next.push(panel);
|
|
62
|
+
panels.value = next;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Removes the side panel registered under `id`, if any. */
|
|
66
|
+
export function unregisterSidePanel(id: string): void {
|
|
67
|
+
const panels = useSidePanelState();
|
|
68
|
+
panels.value = panels.value.filter((entry) => entry.id !== id);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Resolves the width bounds of a panel, defaults applied. A `defaultWidth`
|
|
73
|
+
* outside `[minWidth, maxWidth]` is brought back inside.
|
|
74
|
+
*/
|
|
75
|
+
export function resolveSidePanelWidthBounds(
|
|
76
|
+
panel: SidePanel,
|
|
77
|
+
): SidePanelWidthBounds {
|
|
78
|
+
const minWidth = panel.minWidth ?? DEFAULT_SIDE_PANEL_MIN_WIDTH;
|
|
79
|
+
const maxWidth = Math.max(
|
|
80
|
+
minWidth,
|
|
81
|
+
panel.maxWidth ?? DEFAULT_SIDE_PANEL_MAX_WIDTH,
|
|
82
|
+
);
|
|
83
|
+
const defaultWidth = Math.min(
|
|
84
|
+
maxWidth,
|
|
85
|
+
Math.max(minWidth, panel.defaultWidth ?? DEFAULT_SIDE_PANEL_WIDTH),
|
|
86
|
+
);
|
|
87
|
+
return { defaultWidth, minWidth, maxWidth };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The registered side panels, in registration order. Read by the dashboard;
|
|
92
|
+
* modules normally only need `registerSidePanel` and {@link useSidePanel}.
|
|
93
|
+
*/
|
|
94
|
+
export function useAppSidePanels(): UseAppSidePanelsReturn {
|
|
95
|
+
return { panels: useSidePanelState() };
|
|
96
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A prompt the assistant mode of the command palette offers before the user
|
|
3
|
+
* types anything ("Try asking").
|
|
4
|
+
*/
|
|
5
|
+
export interface CommandPaletteAssistantSuggestion {
|
|
6
|
+
/**
|
|
7
|
+
* Text shown in the list. A `$`-prefixed value resolves as an i18n key
|
|
8
|
+
* (`useTranslation().processI18n`).
|
|
9
|
+
*/
|
|
10
|
+
label: string;
|
|
11
|
+
/**
|
|
12
|
+
* Prompt submitted when the suggestion is picked. Defaults to the resolved
|
|
13
|
+
* `label`; set it when the shown text and the question differ.
|
|
14
|
+
*/
|
|
15
|
+
prompt?: string;
|
|
16
|
+
/** Icon name shown in the item's well. Defaults to the assistant's icon. */
|
|
17
|
+
icon?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The props the palette binds to an assistant's `answerComponent`, once per
|
|
22
|
+
* submitted prompt. The component is mounted afresh for every submission.
|
|
23
|
+
*/
|
|
24
|
+
export interface CommandPaletteAssistantAnswerProps {
|
|
25
|
+
/** The prompt the user submitted, trimmed. */
|
|
26
|
+
prompt: string;
|
|
27
|
+
/**
|
|
28
|
+
* Closes the palette. Call it before an action takes the user elsewhere —
|
|
29
|
+
* a navigation, or a hand-off to the module's own assistant UI.
|
|
30
|
+
*/
|
|
31
|
+
close: () => void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* An assistant mode for the command palette (Ctrl/Cmd+K), provided by a
|
|
36
|
+
* frontend module. While one is registered, Tab switches the palette between
|
|
37
|
+
* search and assistant mode, every non-empty search ends with an
|
|
38
|
+
* "Ask the assistant" item, and a submitted prompt mounts `answerComponent`
|
|
39
|
+
* inside the palette. Without one, the palette has no assistant mode at all.
|
|
40
|
+
*
|
|
41
|
+
* The palette only frames the answer: whether it is computed inline, read-only,
|
|
42
|
+
* or handed off to the module's own interface is the component's decision. An
|
|
43
|
+
* `answerComponent` with an async `setup` (a top-level `await`) shows the
|
|
44
|
+
* palette's loading skeleton until it resolves; one that renders right away
|
|
45
|
+
* draws its own progress.
|
|
46
|
+
*
|
|
47
|
+
* Like {@link CommandPaletteSource}, an assistant carries a callable
|
|
48
|
+
* (`suggestions`), so it must be registered from CLIENT context (a `.client`
|
|
49
|
+
* plugin or component setup): a server-side registration would arrive on the
|
|
50
|
+
* client stripped of it, and the palette ignores such an entry.
|
|
51
|
+
*/
|
|
52
|
+
export interface CommandPaletteAssistant {
|
|
53
|
+
/** Unique key: dedup on `register` (upsert) and target of `unregister`. */
|
|
54
|
+
id: string;
|
|
55
|
+
/**
|
|
56
|
+
* Name of the assistant, shown in the answer frame and as the header of the
|
|
57
|
+
* "Ask" items. A `$`-prefixed value resolves as an i18n key.
|
|
58
|
+
*/
|
|
59
|
+
label: string;
|
|
60
|
+
/** Icon name of the assistant mode: the input's lead icon and the items' well. */
|
|
61
|
+
icon: string;
|
|
62
|
+
/**
|
|
63
|
+
* Input placeholder in assistant mode. A `$`-prefixed value resolves as an
|
|
64
|
+
* i18n key. Defaults to the DMS's "Ask anything about your workspace…".
|
|
65
|
+
*/
|
|
66
|
+
placeholder?: string;
|
|
67
|
+
/**
|
|
68
|
+
* Builds the suggestions listed while the prompt is empty. Evaluated inside
|
|
69
|
+
* a `computed`, so reactive state read here (the current page, the user's
|
|
70
|
+
* permissions) updates the list. Return `[]` for none.
|
|
71
|
+
*/
|
|
72
|
+
suggestions: () => CommandPaletteAssistantSuggestion[];
|
|
73
|
+
/**
|
|
74
|
+
* Full registered name of the global component that answers a prompt. It
|
|
75
|
+
* receives {@link CommandPaletteAssistantAnswerProps}.
|
|
76
|
+
*/
|
|
77
|
+
answerComponent: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const COMMAND_PALETTE_ASSISTANTS_STATE_KEY = "dms:command-palette-assistants";
|
|
81
|
+
|
|
82
|
+
function isAssistantRenderable(assistant: CommandPaletteAssistant): boolean {
|
|
83
|
+
return (
|
|
84
|
+
typeof assistant.suggestions === "function" &&
|
|
85
|
+
typeof assistant.answerComponent === "string"
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function useCommandPaletteAssistantState() {
|
|
90
|
+
return useDmsState<CommandPaletteAssistant[]>(
|
|
91
|
+
COMMAND_PALETTE_ASSISTANTS_STATE_KEY,
|
|
92
|
+
() => [],
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Registers the command palette's assistant mode. Re-registering the same `id`
|
|
98
|
+
* replaces the entry. When several modules register one, the palette uses the
|
|
99
|
+
* one registered last.
|
|
100
|
+
*/
|
|
101
|
+
export function registerCommandPaletteAssistant(
|
|
102
|
+
assistant: CommandPaletteAssistant,
|
|
103
|
+
): void {
|
|
104
|
+
const assistants = useCommandPaletteAssistantState();
|
|
105
|
+
const next = assistants.value.filter((entry) => entry.id !== assistant.id);
|
|
106
|
+
next.push(assistant);
|
|
107
|
+
assistants.value = next;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Removes the assistant registered under `id`; a no-op when there is none. */
|
|
111
|
+
export function unregisterCommandPaletteAssistant(id: string): void {
|
|
112
|
+
const assistants = useCommandPaletteAssistantState();
|
|
113
|
+
assistants.value = assistants.value.filter((entry) => entry.id !== id);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* The assistant the command palette offers, or `undefined` when no module
|
|
118
|
+
* registered a usable one. Read by the DMS palette; modules normally only need
|
|
119
|
+
* {@link registerCommandPaletteAssistant}.
|
|
120
|
+
*/
|
|
121
|
+
export function useCommandPaletteAssistant() {
|
|
122
|
+
const assistants = useCommandPaletteAssistantState();
|
|
123
|
+
|
|
124
|
+
const assistant = computed<CommandPaletteAssistant | undefined>(() =>
|
|
125
|
+
assistants.value.filter(isAssistantRenderable).at(-1),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
return { assistant };
|
|
129
|
+
}
|
|
@@ -1,11 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An icon-only button in the dashboard header. Either `onSelect` runs on
|
|
3
|
+
* click, or `sidePanelId` makes the button toggle that side panel: the DMS then
|
|
4
|
+
* derives the click and the engaged state from {@link useSidePanel}, and the
|
|
5
|
+
* action is plain data that a universal plugin may register.
|
|
6
|
+
*/
|
|
1
7
|
export interface HeaderAction {
|
|
2
8
|
id: string;
|
|
3
9
|
icon: string;
|
|
10
|
+
/** Tooltip and accessible name: a plain literal, or an i18n key when prefixed with "$". */
|
|
4
11
|
label: string;
|
|
5
|
-
|
|
12
|
+
/** Run on click. Required unless `sidePanelId` is set, which it overrides. */
|
|
13
|
+
onSelect?: () => void;
|
|
14
|
+
/** The side panel this button opens and closes (see `registerSidePanel`). */
|
|
15
|
+
sidePanelId?: string;
|
|
6
16
|
order?: number;
|
|
7
17
|
isVisible?: () => boolean;
|
|
8
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Renders the button as engaged — a toggle that is currently on. Derived
|
|
20
|
+
* from the side panel when `sidePanelId` is set.
|
|
21
|
+
*/
|
|
9
22
|
isActive?: () => boolean;
|
|
10
23
|
}
|
|
11
24
|
|
|
@@ -20,13 +33,14 @@ export const BUILDER_ACTION_ID = "dms-builder-edit";
|
|
|
20
33
|
// can register an action without a build-time dependency on this layer: it just
|
|
21
34
|
// pushes to useDmsState(HEADER_ACTIONS_STATE_KEY).
|
|
22
35
|
//
|
|
23
|
-
//
|
|
24
|
-
// from CLIENT context (a `.client` plugin or component setup):
|
|
25
|
-
// are not part of the SSR payload, so a server-side
|
|
26
|
-
// the client with its callbacks stripped.
|
|
27
|
-
//
|
|
28
|
-
//
|
|
29
|
-
//
|
|
36
|
+
// An action that carries callables (onSelect/isVisible/isActive) must be
|
|
37
|
+
// registered from CLIENT context (a `.client` plugin or component setup):
|
|
38
|
+
// function values are not part of the SSR payload, so a server-side
|
|
39
|
+
// registration would arrive on the client with its callbacks stripped.
|
|
40
|
+
// `useHeaderActions` defensively drops any entry left with neither an onSelect
|
|
41
|
+
// nor a sidePanelId, so a stray server-side registration degrades to "button
|
|
42
|
+
// not shown" rather than a runtime crash. A side panel action is plain data
|
|
43
|
+
// and may be registered from a universal plugin.
|
|
30
44
|
const HEADER_ACTIONS_STATE_KEY = "dms:header-actions";
|
|
31
45
|
const DEFAULT_ORDER = 100;
|
|
32
46
|
|
|
@@ -35,8 +49,11 @@ function actionOrder(action: HeaderAction): number {
|
|
|
35
49
|
}
|
|
36
50
|
|
|
37
51
|
function isActionRenderable(action: HeaderAction): boolean {
|
|
38
|
-
|
|
39
|
-
|
|
52
|
+
const isSelectable =
|
|
53
|
+
typeof action.onSelect === "function" ||
|
|
54
|
+
typeof action.sidePanelId === "string";
|
|
55
|
+
if (!isSelectable) return false;
|
|
56
|
+
if (typeof action.isVisible !== "function") return true;
|
|
40
57
|
return action.isVisible();
|
|
41
58
|
}
|
|
42
59
|
|
|
@@ -44,6 +61,10 @@ function useHeaderActionState() {
|
|
|
44
61
|
return useDmsState<HeaderAction[]>(HEADER_ACTIONS_STATE_KEY, () => []);
|
|
45
62
|
}
|
|
46
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Registers a {@link HeaderAction}, replacing any action registered under the
|
|
66
|
+
* same `id`. Call it inside the DMS app.
|
|
67
|
+
*/
|
|
47
68
|
export function registerHeaderAction(action: HeaderAction): void {
|
|
48
69
|
const actions = useHeaderActionState();
|
|
49
70
|
const existingIndex = actions.value.findIndex(
|
|
@@ -60,6 +81,7 @@ export function registerHeaderAction(action: HeaderAction): void {
|
|
|
60
81
|
actions.value = next;
|
|
61
82
|
}
|
|
62
83
|
|
|
84
|
+
/** The visible header actions, sorted by `order`. Read by the header. */
|
|
63
85
|
export function useHeaderActions() {
|
|
64
86
|
const actions = useHeaderActionState();
|
|
65
87
|
const visibleActions = computed<HeaderAction[]>(() =>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isSidePanelOpen,
|
|
3
|
+
setOpenSidePanel,
|
|
4
|
+
toggleSidePanel,
|
|
5
|
+
useSidePanelPreferences,
|
|
6
|
+
} from "../build/composables/layout/sidePanelState";
|
|
7
|
+
|
|
8
|
+
/** The open state of one side panel, and the actions that change it. */
|
|
9
|
+
export interface SidePanelControls {
|
|
10
|
+
/** Whether this panel is the open one. */
|
|
11
|
+
isOpen: Readonly<Ref<boolean>>;
|
|
12
|
+
/** Opens this panel, closing the one that was open, if any. */
|
|
13
|
+
open: () => void;
|
|
14
|
+
/** Closes this panel; does nothing when another one is open. */
|
|
15
|
+
close: () => void;
|
|
16
|
+
/** Opens this panel when it is closed, closes it when it is open. */
|
|
17
|
+
toggle: () => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Opens and closes the side panel registered under `id` (see
|
|
22
|
+
* {@link registerSidePanel}). The DMS owns the state: one panel is open at a
|
|
23
|
+
* time, so opening one closes the other, and which one is open is remembered
|
|
24
|
+
* in a cookie, so the server renders it open on the next visit. Every caller
|
|
25
|
+
* of the same `id` shares the state, whatever component or plugin it runs in.
|
|
26
|
+
*/
|
|
27
|
+
export function useSidePanel(id: string): SidePanelControls {
|
|
28
|
+
const preferences = useSidePanelPreferences();
|
|
29
|
+
const isOpen = computed(() => isSidePanelOpen(preferences, id));
|
|
30
|
+
|
|
31
|
+
function close(): void {
|
|
32
|
+
if (isOpen.value) setOpenSidePanel(preferences, null);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
isOpen,
|
|
37
|
+
open: () => setOpenSidePanel(preferences, id),
|
|
38
|
+
close,
|
|
39
|
+
toggle: () => toggleSidePanel(preferences, id),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -358,6 +358,13 @@ const fillingComponentId = computed(() =>
|
|
|
358
358
|
fillHeight.value ? components.value.at(-1)?.id : undefined,
|
|
359
359
|
);
|
|
360
360
|
|
|
361
|
+
// The server leaves out the blocks the viewer may not see, and says when that
|
|
362
|
+
// left nothing of a page that declares some. Never while the layout loads.
|
|
363
|
+
const { t } = useI18n();
|
|
364
|
+
const hidesEveryBlock = computed(
|
|
365
|
+
() => pageLayout.value?.allComponentsHidden === true,
|
|
366
|
+
);
|
|
367
|
+
|
|
361
368
|
// --- Live-edit highlight ---------------------------------------------------
|
|
362
369
|
// When the active page's layout changes in place (DMS dev hot-reload, same
|
|
363
370
|
// route), animate the components that changed. Added/removed components are
|
|
@@ -472,7 +479,15 @@ if (import.meta.env.DEV) {
|
|
|
472
479
|
</script>
|
|
473
480
|
|
|
474
481
|
<template>
|
|
482
|
+
<div v-if="hidesEveryBlock" class="dms-card overflow-hidden">
|
|
483
|
+
<DmsEmptyState
|
|
484
|
+
variant="no-access"
|
|
485
|
+
:title="t('page.no_visible_blocks.title')"
|
|
486
|
+
:description="t('page.no_visible_blocks.description')"
|
|
487
|
+
/>
|
|
488
|
+
</div>
|
|
475
489
|
<TransitionGroup
|
|
490
|
+
v-else
|
|
476
491
|
tag="div"
|
|
477
492
|
name="dms-fresh"
|
|
478
493
|
class="dms-page-stack space-y-6"
|
|
@@ -5,7 +5,6 @@ const NOTIFICATION_NEW_TYPE = "notification:new";
|
|
|
5
5
|
const NOTIFICATION_READ_TYPE = "notification:read";
|
|
6
6
|
const NOTIFICATION_ALL_READ_TYPE = "notification:all-read";
|
|
7
7
|
const NOTIFICATION_UNREAD_TYPE = "notification:unread";
|
|
8
|
-
const NOTIFICATION_SEEN_TYPE = "notification:seen";
|
|
9
8
|
|
|
10
9
|
interface IncomingPayload {
|
|
11
10
|
notification?: UserNotification;
|
|
@@ -28,14 +27,12 @@ export default defineDmsPlugin(() => {
|
|
|
28
27
|
handleRemoteRead,
|
|
29
28
|
handleRemoteUnread,
|
|
30
29
|
handleRemoteAllRead,
|
|
31
|
-
handleRemoteSeen,
|
|
32
30
|
} = useNotifications();
|
|
33
31
|
const realtime = useUserRealtime();
|
|
34
32
|
|
|
35
33
|
const handlers: Record<string, Handler> = {
|
|
36
34
|
[NOTIFICATION_NEW_TYPE]: (payload) => {
|
|
37
|
-
if (payload?.notification)
|
|
38
|
-
handleIncomingNotification(payload.notification);
|
|
35
|
+
if (payload?.notification) handleIncomingNotification(payload.notification);
|
|
39
36
|
},
|
|
40
37
|
[NOTIFICATION_READ_TYPE]: async (payload) => {
|
|
41
38
|
if (Array.isArray(payload?.ids)) await handleRemoteRead(payload.ids);
|
|
@@ -46,9 +43,6 @@ export default defineDmsPlugin(() => {
|
|
|
46
43
|
[NOTIFICATION_ALL_READ_TYPE]: async () => {
|
|
47
44
|
await handleRemoteAllRead();
|
|
48
45
|
},
|
|
49
|
-
[NOTIFICATION_SEEN_TYPE]: () => {
|
|
50
|
-
handleRemoteSeen();
|
|
51
|
-
},
|
|
52
46
|
};
|
|
53
47
|
|
|
54
48
|
let unsubscribe: (() => void) | undefined;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useAppOverlay } from "../composables/useAppOverlay";
|
|
2
|
+
|
|
3
|
+
/** Registered name of `SidePanelHost.vue` (the layer's `Dms` prefix applied). */
|
|
4
|
+
const SIDE_PANEL_HOST_COMPONENT = "DmsSidePanelHost";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Mounts the side panel host as an app overlay, outside the routed layouts, so
|
|
8
|
+
* the open side panel survives a layout change. Universal: the server renders
|
|
9
|
+
* the open panel too.
|
|
10
|
+
*/
|
|
11
|
+
export default defineDmsPlugin(() => {
|
|
12
|
+
useAppOverlay().register(SIDE_PANEL_HOST_COMPONENT);
|
|
13
|
+
});
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { BlockText } from "#dms-core/app/types/composed-text";
|
|
2
|
+
import type { BlockAction } from "#dms-ui/app/build/components/blocks/BlockActions.vue";
|
|
3
|
+
|
|
1
4
|
export type MenuItemType = "label" | "link";
|
|
2
5
|
// MenuItemVariant / MenuItemStatus / MenuItemQuery live in dms-core, the layer
|
|
3
6
|
// that renders them: this one only consumes them.
|
|
@@ -86,6 +89,8 @@ export type SiteLayoutTree = Omit<PageInfo, "layoutUrl"> & {
|
|
|
86
89
|
childrenOrders: string[];
|
|
87
90
|
layoutUrl?: string;
|
|
88
91
|
hasAccess?: boolean;
|
|
92
|
+
/** The tone of a `badge` the server counted (`navBadge`); neutral when absent. */
|
|
93
|
+
badgeTone?: MenuItemBadgeTone;
|
|
89
94
|
};
|
|
90
95
|
// Mirror of LayoutBannerVariant from @antelopejs/interface-dms/layout-banners.
|
|
91
96
|
export type LayoutBannerVariant = "info" | "warning" | "error";
|
|
@@ -101,7 +106,10 @@ export interface LayoutBanner {
|
|
|
101
106
|
order: number;
|
|
102
107
|
dismissible: boolean;
|
|
103
108
|
icon?: string;
|
|
104
|
-
text
|
|
109
|
+
/** A string (`$` for an i18n key) or a composed text. */
|
|
110
|
+
text?: BlockText;
|
|
111
|
+
/** Link buttons after the text; the last one leads. */
|
|
112
|
+
actions?: BlockAction[];
|
|
105
113
|
component?: string;
|
|
106
114
|
props?: Record<string, unknown>;
|
|
107
115
|
}
|
|
@@ -170,4 +178,6 @@ export interface ResolvedComponentInfo<T = object> {
|
|
|
170
178
|
export interface PageLayout {
|
|
171
179
|
components: Record<string, ComponentInfo>;
|
|
172
180
|
layout: ComponentInfo;
|
|
181
|
+
/** The page declares components and the viewer may see none of them. */
|
|
182
|
+
allComponentsHidden?: boolean;
|
|
173
183
|
}
|