@antelopejs/dms 0.9.8 → 0.11.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 +171 -0
- package/README.md +1 -1
- package/data/module-store/catalog.json +2 -2
- package/dist/attachments/table-view.js +2 -2
- package/dist/attachments/table-view.js.map +1 -1
- package/dist/automation/actions.d.ts +2 -0
- package/dist/automation/actions.js +116 -71
- package/dist/automation/actions.js.map +1 -1
- package/dist/automation/i18n.d.ts +4 -0
- package/dist/automation/i18n.js +19 -0
- package/dist/automation/i18n.js.map +1 -0
- package/dist/automation/send-notification.d.ts +21 -0
- package/dist/automation/send-notification.js +163 -0
- package/dist/automation/send-notification.js.map +1 -0
- package/dist/automation/triggers.js +19 -25
- package/dist/automation/triggers.js.map +1 -1
- package/dist/client-origin-cors.d.ts +1 -0
- package/dist/client-origin-cors.js +19 -0
- package/dist/client-origin-cors.js.map +1 -0
- package/dist/config.d.ts +3 -2
- package/dist/config.js +5 -7
- package/dist/config.js.map +1 -1
- package/dist/frontend-module.d.ts +4 -0
- package/dist/frontend-module.js +37 -0
- package/dist/frontend-module.js.map +1 -0
- package/dist/implementations/dms/client-ip.js +1 -1
- package/dist/implementations/dms/client-ip.js.map +1 -1
- package/dist/implementations/dms/dev-reload.d.ts +5 -0
- package/dist/implementations/dms/dev-reload.js +23 -3
- package/dist/implementations/dms/dev-reload.js.map +1 -1
- package/dist/implementations/dms/frontend-modules.d.ts +2 -4
- package/dist/implementations/dms/frontend-modules.js +38 -94
- package/dist/implementations/dms/frontend-modules.js.map +1 -1
- package/dist/implementations/dms/frontend-ready.d.ts +12 -2
- package/dist/implementations/dms/frontend-ready.js +34 -4
- package/dist/implementations/dms/frontend-ready.js.map +1 -1
- package/dist/implementations/dms/layout-banners.d.ts +2 -1
- package/dist/implementations/dms/layout-banners.js +9 -0
- package/dist/implementations/dms/layout-banners.js.map +1 -1
- package/dist/implementations/dms/manifest.d.ts +7 -2
- package/dist/implementations/dms/manifest.js +12 -7
- package/dist/implementations/dms/manifest.js.map +1 -1
- package/dist/implementations/dms/page.d.ts +4 -3
- package/dist/implementations/dms/page.js +49 -18
- package/dist/implementations/dms/page.js.map +1 -1
- package/dist/implementations/dms/permissions-resolver.d.ts +2 -2
- package/dist/implementations/dms/permissions-resolver.js +2 -2
- package/dist/implementations/dms/permissions-resolver.js.map +1 -1
- package/dist/implementations/dms/realtime.js +1 -0
- package/dist/implementations/dms/realtime.js.map +1 -1
- package/dist/implementations/dms-base/bulk-selection.d.ts +1 -1
- package/dist/implementations/dms-base/bulk-selection.js +23 -1
- package/dist/implementations/dms-base/bulk-selection.js.map +1 -1
- package/dist/implementations/dms-base/filter-tokens.js +5 -3
- package/dist/implementations/dms-base/filter-tokens.js.map +1 -1
- package/dist/implementations/dms-base/search-route.d.ts +1 -0
- package/dist/implementations/dms-base/search-route.js +35 -13
- package/dist/implementations/dms-base/search-route.js.map +1 -1
- package/dist/implementations/dms-base/table-view.js +11 -6
- package/dist/implementations/dms-base/table-view.js.map +1 -1
- package/dist/implementations/dms-notifications/index.d.ts +2 -2
- package/dist/implementations/dms-notifications/index.js +5 -5
- package/dist/implementations/dms-notifications/index.js.map +1 -1
- package/dist/index.js +32 -55
- package/dist/index.js.map +1 -1
- package/dist/pages/modules/index.d.ts +1 -0
- package/dist/pages/modules/index.js +1 -0
- package/dist/pages/modules/index.js.map +1 -1
- package/dist/pages/modules/modules-store.d.ts +9 -0
- package/dist/pages/modules/modules-store.js +30 -0
- package/dist/pages/modules/modules-store.js.map +1 -0
- package/dist/pages/settings/users/account-credentials.js +2 -2
- package/dist/pages/settings/users/account-credentials.js.map +1 -1
- package/dist/pages/settings/users/account-data-store.js +25 -8
- package/dist/pages/settings/users/account-data-store.js.map +1 -1
- package/dist/pages/settings/users/invite-extension-routes.js +9 -3
- package/dist/pages/settings/users/invite-extension-routes.js.map +1 -1
- package/dist/pages/settings/users/member-management.js +13 -14
- package/dist/pages/settings/users/member-management.js.map +1 -1
- package/dist/pages/settings/users/profile.d.ts +1 -4
- package/dist/pages/settings/users/profile.js +0 -35
- package/dist/pages/settings/users/profile.js.map +1 -1
- package/dist/pages/settings/users/role-editor-store.js +26 -18
- package/dist/pages/settings/users/role-editor-store.js.map +1 -1
- package/dist/pages/settings/users/role-editor.d.ts +0 -1
- package/dist/pages/settings/users/role-editor.js +1 -2
- package/dist/pages/settings/users/role-editor.js.map +1 -1
- package/dist/pages/settings/users/role-preview.js +1 -2
- package/dist/pages/settings/users/role-preview.js.map +1 -1
- package/dist/pages/settings/users/roles.js +2 -2
- package/dist/pages/settings/users/roles.js.map +1 -1
- package/dist/pages/settings/users/two-factor-operations.js.map +1 -1
- package/dist/realtime/broker.d.ts +6 -0
- package/dist/realtime/broker.js +8 -1
- package/dist/realtime/broker.js.map +1 -1
- package/dist/realtime/presence.d.ts +8 -3
- package/dist/realtime/presence.js +8 -4
- package/dist/realtime/presence.js.map +1 -1
- package/dist/realtime/sessions.d.ts +11 -1
- package/dist/realtime/sessions.js +21 -3
- package/dist/realtime/sessions.js.map +1 -1
- package/dist/realtime/table-view.d.ts +2 -2
- package/dist/realtime/table-view.js +4 -3
- package/dist/realtime/table-view.js.map +1 -1
- package/dist/routes/auth/client-ip.d.ts +1 -0
- package/dist/routes/auth/client-ip.js +18 -0
- package/dist/routes/auth/client-ip.js.map +1 -1
- package/dist/routes/auth/oauth/config.d.ts +2 -1
- package/dist/routes/auth/oauth/config.js +5 -1
- package/dist/routes/auth/oauth/config.js.map +1 -1
- package/dist/routes/auth/session-handoff.d.ts +0 -1
- package/dist/routes/auth/session-handoff.js +0 -2
- package/dist/routes/auth/session-handoff.js.map +1 -1
- package/dist/routes/auth.js +3 -2
- package/dist/routes/auth.js.map +1 -1
- package/dist/routes/index.d.ts +0 -1
- package/dist/routes/index.js +0 -1
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/realtime.d.ts +13 -1
- package/dist/routes/realtime.js +114 -29
- package/dist/routes/realtime.js.map +1 -1
- package/dist/startup-config.d.ts +2 -0
- package/dist/startup-config.js +62 -0
- package/dist/startup-config.js.map +1 -0
- package/dist/store/interfaces.d.ts +3 -2
- package/dist/store/interfaces.js +16 -6
- package/dist/store/interfaces.js.map +1 -1
- package/dist/store/listing.js +25 -15
- package/dist/store/listing.js.map +1 -1
- package/dist/store/operations.js +5 -2
- package/dist/store/operations.js.map +1 -1
- package/dist/store/requirements.js +3 -2
- package/dist/store/requirements.js.map +1 -1
- package/dist/store/runtime.d.ts +10 -1
- package/dist/store/runtime.js +33 -6
- package/dist/store/runtime.js.map +1 -1
- package/dist/store/types.d.ts +10 -0
- package/dist/utils/ensure-default-tenant.d.ts +2 -1
- package/dist/utils/ensure-default-tenant.js +13 -1
- package/dist/utils/ensure-default-tenant.js.map +1 -1
- package/dist/utils/export-jobs.js +2 -1
- package/dist/utils/export-jobs.js.map +1 -1
- package/dist/validation/auth.schema.d.ts +2 -2
- package/dist/validation/member-invite.schema.d.ts +2 -10
- package/dist/validation/member-invite.schema.js +2 -15
- package/dist/validation/member-invite.schema.js.map +1 -1
- package/frontend-vue/dms.frontend.ts +24 -5
- package/frontend-vue/dms.server.ts +17 -0
- package/frontend-vue/layers/dms-auth/server/accounts.ts +3 -4
- package/frontend-vue/layers/dms-core/app/build/composables/renderNow.ts +33 -0
- package/frontend-vue/layers/dms-core/app/build/composables/user/tablePreferences.ts +5 -1
- package/frontend-vue/layers/dms-core/app/build/utils/crossTab.ts +199 -0
- package/frontend-vue/layers/dms-core/app/build/utils/sharedRealtimeConnection.ts +410 -0
- package/frontend-vue/layers/dms-core/app/composables/auth/useApiData.ts +77 -12
- package/frontend-vue/layers/dms-core/app/composables/data-types/useDataType.ts +26 -0
- package/frontend-vue/layers/dms-core/app/composables/live/livePauseSource.ts +29 -0
- package/frontend-vue/layers/dms-core/app/composables/period/compareResolvers.ts +150 -9
- package/frontend-vue/layers/dms-core/app/composables/period/usePeriod.ts +6 -4
- package/frontend-vue/layers/dms-core/app/composables/period/usePeriodScope.ts +27 -1
- package/frontend-vue/layers/dms-core/app/composables/realtime/useUserRealtime.ts +256 -119
- package/frontend-vue/layers/dms-core/app/composables/translation/useComposedText.ts +21 -8
- package/frontend-vue/layers/dms-core/app/composables/translation/useTranslation.ts +25 -5
- package/frontend-vue/layers/dms-core/app/composables/useApiError.ts +3 -5
- package/frontend-vue/layers/dms-core/app/composables/useFieldErrors.ts +61 -26
- package/frontend-vue/layers/dms-core/app/plugins/dev-error-log.ts +16 -0
- package/frontend-vue/layers/dms-core/app/types/user.ts +6 -0
- package/frontend-vue/layers/dms-core/app/utils/composedText.ts +7 -2
- package/frontend-vue/layers/dms-core/app/utils/formatter.ts +134 -35
- package/frontend-vue/layers/dms-core/app/utils/url-interpolation.ts +18 -1
- package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +136 -2
- package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +136 -2
- package/frontend-vue/layers/dms-core/shared/types/app-config.ts +0 -2
- package/frontend-vue/layers/dms-layout/app/app.config.ts +0 -1
- package/frontend-vue/layers/dms-layout/app/assets/css/main.css +11 -1
- package/frontend-vue/layers/dms-layout/app/assets/fonts/Geist-Italic-Variable.woff2 +0 -0
- package/frontend-vue/layers/dms-layout/app/assets/fonts/Geist-Variable.woff2 +0 -0
- package/frontend-vue/layers/dms-layout/app/assets/fonts/GeistMono-Italic-Variable.woff2 +0 -0
- package/frontend-vue/layers/dms-layout/app/assets/fonts/GeistMono-Variable.woff2 +0 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +3 -2
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +41 -21
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardPageBody.vue +6 -2
- package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +4 -19
- package/frontend-vue/layers/dms-layout/app/build/components/layout/Footer.vue +11 -107
- package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +18 -7
- package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +4 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/RowSidePanel.vue +43 -82
- package/frontend-vue/layers/dms-layout/app/build/components/layout/SidebarUserMenu.vue +44 -3
- package/frontend-vue/layers/dms-layout/app/build/components/layout/UserIdentity.vue +11 -3
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleCatalogTile.vue +132 -35
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleManageMenu.vue +59 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleSourceLabel.vue +25 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreBanners.vue +73 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreOperation.vue +116 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreRequirements.vue +8 -3
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleStoreTile.vue +85 -207
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTile.vue +10 -3
- package/frontend-vue/layers/dms-layout/app/build/components/pages/modules/ModuleTileSkeleton.vue +68 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxDisplay.vue +24 -8
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/notification/NotificationInboxItem.vue +8 -5
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/region/RegionTimeZoneInput.vue +1 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/role-permissions.ts +19 -0
- package/frontend-vue/layers/dms-layout/app/build/components/pages/settings/roles/useRoleEditor.ts +2 -1
- package/frontend-vue/layers/dms-layout/app/build/composables/layout/useSidePanelWidth.ts +31 -70
- package/frontend-vue/layers/dms-layout/app/build/composables/notification/useNotificationGroupsOpen.ts +11 -1
- package/frontend-vue/layers/dms-layout/app/build/utils/dev-reload-stream.ts +81 -0
- package/frontend-vue/layers/dms-layout/app/build/utils/github-repository.ts +2 -2
- package/frontend-vue/layers/dms-layout/app/build/utils/module-store-catalog.ts +232 -36
- package/frontend-vue/layers/dms-layout/app/build/utils/modules-catalog.ts +122 -14
- package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +32 -3
- package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +49 -11
- package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +3 -2
- package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +59 -4
- package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStoreActions.ts +194 -0
- package/frontend-vue/layers/dms-layout/app/composables/page/usePageComponentPreload.ts +23 -3
- package/frontend-vue/layers/dms-layout/app/composables/page/usePageLayout.ts +4 -2
- package/frontend-vue/layers/dms-layout/app/composables/page/usePageRecordDeletion.ts +162 -0
- package/frontend-vue/layers/dms-layout/app/composables/page/useSiteLayout.ts +6 -1
- package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +6 -2
- package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +6 -2
- package/frontend-vue/layers/dms-layout/app/custom-pages/modules-store.vue +291 -0
- package/frontend-vue/layers/dms-layout/app/custom-pages/modules.vue +87 -474
- package/frontend-vue/layers/dms-layout/app/middleware/module-routing.global.ts +3 -0
- package/frontend-vue/layers/dms-layout/app/pages/[...slug].vue +13 -22
- package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +11 -10
- package/frontend-vue/layers/dms-layout/app/plugins/command-palette-personal-pages.client.ts +22 -52
- package/frontend-vue/layers/dms-layout/app/plugins/command-palette-quick-actions.client.ts +7 -7
- package/frontend-vue/layers/dms-layout/app/plugins/command-palette-session.client.ts +11 -10
- package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +14 -9
- package/frontend-vue/layers/dms-layout/app/theme/actions.ts +5 -4
- package/frontend-vue/layers/dms-layout/app/theme/form-controls.ts +9 -4
- package/frontend-vue/layers/dms-layout/app/theme/surfaces.ts +22 -6
- package/frontend-vue/layers/dms-layout/app/types/module-store.ts +9 -0
- package/frontend-vue/layers/dms-layout/app/types/page.ts +15 -1
- package/frontend-vue/layers/dms-layout/app/utils/account-menu.ts +11 -0
- package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +57 -0
- package/frontend-vue/layers/dms-layout/app/utils/pageQuery.ts +26 -0
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +45 -18
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +44 -17
- package/frontend-vue/layers/dms-ui/app/build/components/containers/TargetComponentTree.vue +31 -0
- package/frontend-vue/layers/dms-ui/app/build/components/containers/constants.ts +25 -0
- package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +244 -15
- package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +42 -25
- package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowHeader.vue +153 -0
- package/frontend-vue/layers/dms-ui/app/build/components/containers/row/RowNotFound.vue +44 -0
- package/frontend-vue/layers/dms-ui/app/build/components/containers/row/drawerRowHeader.ts +35 -0
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormEntries.vue +44 -9
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormErrorSummary.vue +11 -4
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldControl.vue +38 -5
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormFieldNotes.vue +29 -5
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormLoadError.vue +5 -1
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormSectionNav.vue +3 -1
- package/frontend-vue/layers/dms-ui/app/build/components/form/FormSections.vue +106 -27
- package/frontend-vue/layers/dms-ui/app/build/components/table/Actions.vue +12 -4
- package/frontend-vue/layers/dms-ui/app/build/components/table/Empty.vue +4 -2
- package/frontend-vue/layers/dms-ui/app/build/components/table/FiltersRow.vue +48 -1
- package/frontend-vue/layers/dms-ui/app/build/components/table/Pagination.vue +55 -54
- package/frontend-vue/layers/dms-ui/app/build/components/table/RowSelection.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/build/components/table/Table.vue +396 -288
- package/frontend-vue/layers/dms-ui/app/build/components/table/Tabs.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/build/components/table/Views.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardAvatar.vue +59 -0
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardGridSkeleton.vue +19 -2
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardRowActions.vue +38 -0
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/CardsDisplay.vue +148 -104
- package/frontend-vue/layers/dms-ui/app/build/components/table-view/LiveHoldBanner.vue +17 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/bulkSelection.ts +43 -9
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowComponentOptions.ts +76 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/rowNavigation.ts +172 -27
- package/frontend-vue/layers/dms-ui/app/build/composables/actions/useActionTargets.ts +270 -46
- package/frontend-vue/layers/dms-ui/app/build/composables/confirm/actionError.ts +6 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/confirm/confirmDialogTexts.ts +2 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/containers/closingLayers.ts +186 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/containers/context.ts +14 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/containers/drawerSize.ts +229 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/containers/useResizableSize.ts +175 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/metricCells.ts +18 -35
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/numberSuffix.ts +44 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +123 -27
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerFieldTypes.ts +2 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationFilter.ts +75 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationRows.ts +92 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationValue.ts +39 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/twoLineCell.ts +3 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/useColumnValueRenderer.ts +6 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/form/createFormFields.ts +15 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldSaved.ts +40 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/fieldValueRule.ts +62 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formEntryContext.ts +5 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formFooter.ts +42 -7
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formLayout.ts +106 -4
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formRecordLoad.ts +11 -5
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formSections.ts +32 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/formValidation.ts +36 -4
- package/frontend-vue/layers/dms-ui/app/build/composables/form/readonlyValue.ts +19 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/registerFormFunctions.ts +27 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/repeaterTable.ts +78 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/serverFieldErrors.ts +49 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/toasterClearance.ts +118 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/form/useInstantForm.ts +12 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/live/currentPageLive.ts +41 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/live/livePoller.ts +10 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/live/pageReadClock.ts +28 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/live/shortcuts.ts +1 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/live/usePageLiveHost.ts +17 -3
- package/frontend-vue/layers/dms-ui/app/build/composables/live/useUpdatedLabel.ts +38 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/pageToolbarContext.ts +75 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/page-toolbar/toolbarControlHeight.ts +29 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/period/periodComparison.ts +52 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/period/periodDisplay.ts +21 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/period/periodShortLabels.ts +28 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/period/usePeriodDraft.ts +1 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useRelationFilterLabels.ts +97 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useRowScrollAnchor.ts +106 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTable.ts +9 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/useTableColumns.ts +1 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/archivedCount.ts +31 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/filterEditorValue.ts +38 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/formatFilterValue.ts +33 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/table/utils/scrollEdges.ts +31 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useCardFields.ts +33 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useMobileDisplay.ts +48 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useScrolledPastTop.ts +41 -18
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableFooter.ts +3 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLinkedVisit.ts +78 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableLiveHold.ts +135 -22
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableRows.ts +56 -25
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewRowActions.ts +90 -35
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViews.ts +86 -10
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/bulkActions.ts +14 -4
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/card.ts +127 -2
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/compareValues.ts +13 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/expandedRows.ts +28 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/groupedRows.ts +114 -1
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/linkedArrival.ts +308 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/locateRow.ts +106 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pageArrival.ts +34 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/pinnedRows.ts +17 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/quickFilters.ts +41 -33
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/recordLink.ts +24 -8
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableCounts.ts +113 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/tableQuery.ts +27 -4
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/views.ts +22 -6
- package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/writeError.ts +21 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/addressSuggestions.ts +49 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/codeHighlight.ts +67 -29
- package/frontend-vue/layers/dms-ui/app/build/utils/eyebrow.ts +12 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/fieldOptionsI18n.ts +51 -11
- package/frontend-vue/layers/dms-ui/app/build/utils/htmlGrammar.ts +79 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/inputWidth.ts +53 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/numberAdjustment.ts +6 -3
- package/frontend-vue/layers/dms-ui/app/build/utils/relativeDate.ts +19 -5
- package/frontend-vue/layers/dms-ui/app/build/utils/scrollWithin.ts +99 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/shellParser.ts +1 -1
- package/frontend-vue/layers/dms-ui/app/build/utils/streamHighlight.ts +90 -0
- package/frontend-vue/layers/dms-ui/app/build/utils/urlVariables.ts +36 -14
- package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +1 -1
- package/frontend-vue/layers/dms-ui/app/components/RecursiveComponent.vue +9 -1
- package/frontend-vue/layers/dms-ui/app/components/blocks/LiveToggleBlock.vue +80 -32
- package/frontend-vue/layers/dms-ui/app/components/blocks/PageToolbarBlock.vue +137 -0
- package/frontend-vue/layers/dms-ui/app/components/blocks/StatGroupBlock.vue +5 -0
- package/frontend-vue/layers/dms-ui/app/components/chart/ApexChartHost.vue +16 -2
- package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +24 -5
- package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +41 -23
- package/frontend-vue/layers/dms-ui/app/components/code-snippet/CodeSnippet.vue +23 -12
- package/frontend-vue/layers/dms-ui/app/components/confirm/ConfirmModal.vue +1 -1
- package/frontend-vue/layers/dms-ui/app/components/container-footer/ContainerFooter.vue +34 -0
- package/frontend-vue/layers/dms-ui/app/components/field-row/FieldRow.vue +25 -2
- package/frontend-vue/layers/dms-ui/app/components/flow-canvas/FlowCanvas.vue +2 -2
- package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +119 -36
- package/frontend-vue/layers/dms-ui/app/components/form/components/Cascader.vue +53 -22
- package/frontend-vue/layers/dms-ui/app/components/form/components/DatePicker.vue +20 -1
- package/frontend-vue/layers/dms-ui/app/components/form/components/Display.vue +13 -1
- package/frontend-vue/layers/dms-ui/app/components/form/components/Image.vue +8 -3
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputAddress.vue +53 -5
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputCode.vue +29 -5
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputNumber.vue +45 -8
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputPercentage.vue +28 -5
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputSecret.vue +5 -0
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputText.vue +19 -2
- package/frontend-vue/layers/dms-ui/app/components/form/components/InputTime.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/components/form/components/Relation.vue +226 -65
- package/frontend-vue/layers/dms-ui/app/components/form/components/Repeater.vue +80 -30
- package/frontend-vue/layers/dms-ui/app/components/form/components/RepeaterTable.vue +210 -0
- package/frontend-vue/layers/dms-ui/app/components/form/components/Select.vue +4 -2
- package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +11 -2
- package/frontend-vue/layers/dms-ui/app/components/key-value-list/KeyValueList.vue +79 -70
- package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +117 -21
- package/frontend-vue/layers/dms-ui/app/components/meter/Meter.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/components/period/PeriodSelector.vue +113 -34
- package/frontend-vue/layers/dms-ui/app/components/save-bar/SaveBar.vue +14 -2
- package/frontend-vue/layers/dms-ui/app/components/section-header/Eyebrow.vue +6 -1
- package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +13 -0
- package/frontend-vue/layers/dms-ui/app/components/stat-group/StatGroup.vue +52 -3
- package/frontend-vue/layers/dms-ui/app/components/tab/Tab.vue +2 -1
- package/frontend-vue/layers/dms-ui/app/components/table-view/CascaderPath.vue +74 -25
- package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanBoard.vue +48 -44
- package/frontend-vue/layers/dms-ui/app/components/table-view/KanbanDisplay.vue +4 -1
- package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +426 -97
- package/frontend-vue/layers/dms-ui/app/components/top-list/TopListCard.vue +33 -5
- package/frontend-vue/layers/dms-ui/app/composables/chart/apexCategoryLabels.ts +68 -0
- package/frontend-vue/layers/dms-ui/app/composables/chart/apexDatetimeBuckets.ts +306 -0
- package/frontend-vue/layers/dms-ui/app/composables/chart/formatValue.ts +4 -3
- package/frontend-vue/layers/dms-ui/app/composables/chart/heatmapColors.ts +93 -0
- package/frontend-vue/layers/dms-ui/app/composables/chart/localizeSeries.ts +62 -0
- package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.ts +116 -8
- package/frontend-vue/layers/dms-ui/app/composables/chart/useApexChart.types.ts +7 -0
- package/frontend-vue/layers/dms-ui/app/composables/containers/types.ts +84 -1
- package/frontend-vue/layers/dms-ui/app/composables/containers/useDrawer.ts +69 -8
- package/frontend-vue/layers/dms-ui/app/composables/form/types/field-saved.ts +11 -0
- package/frontend-vue/layers/dms-ui/app/composables/form/types/field.ts +16 -0
- package/frontend-vue/layers/dms-ui/app/composables/form/types/functions.ts +1 -0
- package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +189 -28
- package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +29 -12
- package/frontend-vue/layers/dms-ui/app/composables/page-toolbar/usePageToolbarSize.ts +30 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/kanban.ts +4 -2
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/action-target.ts +22 -3
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/config.ts +4 -0
- package/frontend-vue/layers/dms-ui/app/composables/table-view/types/display.ts +24 -1
- package/frontend-vue/layers/dms-ui/app/plugins/closing-layers.client.ts +10 -0
- package/frontend-vue/layers/dms-ui/app/plugins/live-pause-source.ts +15 -0
- package/frontend-vue/layers/dms-ui/app/plugins/register.ts +2 -0
- package/frontend-vue/layers/dms-ui/app/types/input-number.ts +3 -2
- package/frontend-vue/layers/dms-ui/app/types/page-toolbar.ts +7 -0
- package/frontend-vue/layers/dms-ui/app/types/row-action.ts +0 -2
- package/frontend-vue/layers/dms-ui/app/types/row-navigation.ts +17 -0
- package/frontend-vue/layers/dms-ui/app/types/table/query.ts +2 -1
- package/frontend-vue/layers/dms-ui/app/utils/blockRefresh.ts +3 -1
- package/frontend-vue/layers/dms-ui/app/utils/cascader.ts +94 -3
- package/frontend-vue/layers/dms-ui/app/utils/componentTree.ts +24 -0
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +20 -5
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +20 -5
- package/frontend-vue/package.json +6 -2
- package/package.json +11 -10
- package/skills/dms/SKILL.md +1 -1
- package/skills/dms-auth/SKILL.md +5 -3
- package/skills/dms-best-practices/REFERENCE.md +2 -0
- package/skills/dms-best-practices/SKILL.md +4 -0
- package/skills/dms-module/SKILL.md +3 -2
- package/skills/dms-pages/REFERENCE.md +129 -16
- package/skills/dms-pages/SKILL.md +1 -1
- package/skills/dms-project/DEV-SERVERS.md +23 -1
- package/skills/dms-project/REFERENCE.md +1 -1
- package/skills/dms-project/SKILL.md +4 -1
- package/skills/dms-project/scripts/dms-dev.sh +205 -17
- package/dist/hooks/tenant-instances.d.ts +0 -1
- package/dist/hooks/tenant-instances.js +0 -13
- package/dist/hooks/tenant-instances.js.map +0 -1
- package/dist/routes/startup-gate.d.ts +0 -7
- package/dist/routes/startup-gate.js +0 -39
- package/dist/routes/startup-gate.js.map +0 -1
- package/frontend-vue/layers/dms-core/app/composables/period/periodRenderNow.ts +0 -42
|
@@ -19,15 +19,29 @@ export function formatRelativeDate(
|
|
|
19
19
|
);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
const DAY_MONTH_FORMAT: Intl.DateTimeFormatOptions = {
|
|
23
|
+
month: "short",
|
|
24
|
+
day: "numeric",
|
|
25
|
+
};
|
|
26
|
+
const YEAR_FORMAT: Intl.DateTimeFormatOptions = { year: "numeric" };
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* "Sep 27": day and short month, read against `now`; a date of another year
|
|
30
|
+
* ("Apr 2, 2018") names its year as well.
|
|
31
|
+
*/
|
|
23
32
|
export function formatDayMonth(
|
|
24
33
|
date: string | number | Date,
|
|
25
34
|
locale: string,
|
|
35
|
+
now: number = Date.now(),
|
|
26
36
|
): string {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
const day = new Date(date);
|
|
38
|
+
// Years read in the reader's time zone, as the date is written.
|
|
39
|
+
const year = regionalDateTimeFormat(locale, YEAR_FORMAT);
|
|
40
|
+
const isOtherYear = year.format(day) !== year.format(now);
|
|
41
|
+
return regionalDateTimeFormat(
|
|
42
|
+
locale,
|
|
43
|
+
isOtherYear ? { ...DAY_MONTH_FORMAT, ...YEAR_FORMAT } : DAY_MONTH_FORMAT,
|
|
44
|
+
).format(day);
|
|
31
45
|
}
|
|
32
46
|
|
|
33
47
|
/** First word of a name, for "Sep 27 · by Camille". */
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// `scrollIntoView` scrolls every ancestor that can scroll, including the
|
|
2
|
+
// layout's `overflow: hidden` root: the header and breadcrumb slide out of
|
|
3
|
+
// view and nothing brings them back. These helpers scroll the one container
|
|
4
|
+
// that actually scrolls the element instead.
|
|
5
|
+
|
|
6
|
+
const SCROLLABLE_OVERFLOW = /(auto|scroll)/;
|
|
7
|
+
|
|
8
|
+
/** Where an element lands in its scroll container. */
|
|
9
|
+
export type ScrollWithinBlock = "start" | "center" | "nearest";
|
|
10
|
+
|
|
11
|
+
/** How `scrollWithin` brings an element into view. */
|
|
12
|
+
export interface ScrollWithinOptions {
|
|
13
|
+
block?: ScrollWithinBlock;
|
|
14
|
+
behavior?: ScrollBehavior;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The closest ancestor of `element` the user can scroll (`overflow-y: auto`
|
|
19
|
+
* or `scroll`, with content taller than itself), or `null` when only the
|
|
20
|
+
* window scrolls it.
|
|
21
|
+
*
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export function scrollParent(element: HTMLElement): HTMLElement | null {
|
|
25
|
+
for (let node = element.parentElement; node; node = node.parentElement) {
|
|
26
|
+
const { overflowY } = getComputedStyle(node);
|
|
27
|
+
if (
|
|
28
|
+
SCROLLABLE_OVERFLOW.test(overflowY) &&
|
|
29
|
+
node.scrollHeight > node.clientHeight
|
|
30
|
+
) {
|
|
31
|
+
return node;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
interface ScrollViewport {
|
|
38
|
+
top: number;
|
|
39
|
+
height: number;
|
|
40
|
+
scrollTop: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function viewportOf(scroller: HTMLElement | null): ScrollViewport {
|
|
44
|
+
if (scroller) {
|
|
45
|
+
return {
|
|
46
|
+
top: scroller.getBoundingClientRect().top,
|
|
47
|
+
height: scroller.clientHeight,
|
|
48
|
+
scrollTop: scroller.scrollTop,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
return { top: 0, height: window.innerHeight, scrollTop: window.scrollY };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function scrollMarginTop(element: HTMLElement): number {
|
|
55
|
+
return Number.parseFloat(getComputedStyle(element).scrollMarginTop) || 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The scroll offset that puts `rect` at `block` in `viewport`. */
|
|
59
|
+
function targetOffset(
|
|
60
|
+
rect: DOMRect,
|
|
61
|
+
margin: number,
|
|
62
|
+
viewport: ScrollViewport,
|
|
63
|
+
block: ScrollWithinBlock,
|
|
64
|
+
): number | null {
|
|
65
|
+
const top = rect.top - viewport.top - margin;
|
|
66
|
+
if (block === "start") return viewport.scrollTop + top;
|
|
67
|
+
if (block === "center") {
|
|
68
|
+
return viewport.scrollTop + top - (viewport.height - rect.height) / 2;
|
|
69
|
+
}
|
|
70
|
+
const bottom = rect.bottom - viewport.top;
|
|
71
|
+
if (top >= 0 && bottom <= viewport.height) return null;
|
|
72
|
+
return top < 0
|
|
73
|
+
? viewport.scrollTop + top
|
|
74
|
+
: viewport.scrollTop + bottom - viewport.height;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Brings `element` into view by scrolling its own scroll container only
|
|
79
|
+
* (the window when nothing closer scrolls it), honouring its
|
|
80
|
+
* `scroll-margin-top`. Unlike `scrollIntoView`, no other ancestor moves.
|
|
81
|
+
*
|
|
82
|
+
* @internal
|
|
83
|
+
*/
|
|
84
|
+
export function scrollWithin(
|
|
85
|
+
element: HTMLElement,
|
|
86
|
+
{ block = "start", behavior = "auto" }: ScrollWithinOptions = {},
|
|
87
|
+
): void {
|
|
88
|
+
const scroller = scrollParent(element);
|
|
89
|
+
const offset = targetOffset(
|
|
90
|
+
element.getBoundingClientRect(),
|
|
91
|
+
block === "start" ? scrollMarginTop(element) : 0,
|
|
92
|
+
viewportOf(scroller),
|
|
93
|
+
block,
|
|
94
|
+
);
|
|
95
|
+
if (offset === null) return;
|
|
96
|
+
const top = Math.max(0, offset);
|
|
97
|
+
if (scroller) scroller.scrollTo({ top, behavior });
|
|
98
|
+
else window.scrollTo({ top, behavior });
|
|
99
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { StreamParser, StringStream } from "@codemirror/
|
|
1
|
+
import type { StreamParser, StringStream } from "@codemirror/streamparser";
|
|
2
2
|
|
|
3
3
|
// A shell snippet as read for highlighting only: the command of each
|
|
4
4
|
// pipeline step, its flags, quoted strings, variables and comments.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// A CodeMirror stream parser (a language written as a line tokenizer, like
|
|
2
|
+
// the shell's) run for read-only highlighting. `StreamLanguage` would do it
|
|
3
|
+
// inside an editor state, and so pull CodeMirror's view and state into every
|
|
4
|
+
// page showing a snippet: this drives the parser the same way, line by line
|
|
5
|
+
// over `StringStream`, and names its tokens' tags the same way.
|
|
6
|
+
import { type StreamParser, StringStream } from "@codemirror/streamparser";
|
|
7
|
+
import { type Highlighter, type Tag, tags } from "@lezer/highlight";
|
|
8
|
+
|
|
9
|
+
/** Receives one styled range of the code: its offsets and its classes. */
|
|
10
|
+
export type HighlightedRange = (
|
|
11
|
+
from: number,
|
|
12
|
+
to: number,
|
|
13
|
+
classes: string,
|
|
14
|
+
) => void;
|
|
15
|
+
|
|
16
|
+
// CodeMirror's defaults, which `StreamLanguage` hands every stream.
|
|
17
|
+
const TAB_SIZE = 4;
|
|
18
|
+
const INDENT_UNIT = 2;
|
|
19
|
+
// Zero-length tokens a parser may return in a row (each one changing its
|
|
20
|
+
// state) before the stream moves on by itself, as `StreamLanguage` allows.
|
|
21
|
+
const MAX_EMPTY_TOKENS = 10;
|
|
22
|
+
|
|
23
|
+
type TagValue = Tag | readonly Tag[] | ((tag: Tag) => Tag);
|
|
24
|
+
const TAG_TABLE = tags as unknown as Record<string, TagValue | undefined>;
|
|
25
|
+
const tagsByName = new Map<string, Tag[]>();
|
|
26
|
+
|
|
27
|
+
// A token type names tags the way `StreamLanguage` reads them: space
|
|
28
|
+
// separated, each a tag followed by its modifiers (`variableName.special`).
|
|
29
|
+
function tagsOf(type: string): Tag[] {
|
|
30
|
+
const cached = tagsByName.get(type);
|
|
31
|
+
if (cached) return cached;
|
|
32
|
+
const resolved = type.split(" ").flatMap((name) => {
|
|
33
|
+
let found: Tag[] = [];
|
|
34
|
+
for (const part of name.split(".")) {
|
|
35
|
+
const value = TAG_TABLE[part];
|
|
36
|
+
if (typeof value === "function") found = found.map(value);
|
|
37
|
+
else if (value && !found.length)
|
|
38
|
+
found = Array.isArray(value) ? [...value] : [value as Tag];
|
|
39
|
+
}
|
|
40
|
+
return found;
|
|
41
|
+
});
|
|
42
|
+
tagsByName.set(type, resolved);
|
|
43
|
+
return resolved;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Tokenizes `code` with `parser` and calls `put` for each range its
|
|
48
|
+
* highlighter styles, adjacent ranges of one style merged, as
|
|
49
|
+
* `highlightTree` reports a parsed tree.
|
|
50
|
+
*/
|
|
51
|
+
export function highlightStream<State>(
|
|
52
|
+
parser: StreamParser<State>,
|
|
53
|
+
code: string,
|
|
54
|
+
highlighter: Highlighter,
|
|
55
|
+
put: HighlightedRange,
|
|
56
|
+
): void {
|
|
57
|
+
const state = parser.startState?.(INDENT_UNIT) ?? (true as State);
|
|
58
|
+
let pending: { from: number; to: number; classes: string } | null = null;
|
|
59
|
+
const flush = () => {
|
|
60
|
+
if (pending) put(pending.from, pending.to, pending.classes);
|
|
61
|
+
pending = null;
|
|
62
|
+
};
|
|
63
|
+
const add = (from: number, to: number, classes: string | null) => {
|
|
64
|
+
if (pending && (pending.to !== from || pending.classes !== classes))
|
|
65
|
+
flush();
|
|
66
|
+
if (!classes) return;
|
|
67
|
+
if (pending) pending.to = to;
|
|
68
|
+
else pending = { from, to, classes };
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
let lineStart = 0;
|
|
72
|
+
for (const line of code.split("\n")) {
|
|
73
|
+
if (!line) parser.blankLine?.(state, INDENT_UNIT);
|
|
74
|
+
const stream = new StringStream(line, TAB_SIZE, INDENT_UNIT);
|
|
75
|
+
let emptyTokens = 0;
|
|
76
|
+
while (!stream.eol()) {
|
|
77
|
+
stream.start = stream.pos;
|
|
78
|
+
const type = parser.token(stream, state);
|
|
79
|
+
if (stream.pos === stream.start) {
|
|
80
|
+
if (++emptyTokens < MAX_EMPTY_TOKENS) continue;
|
|
81
|
+
stream.next();
|
|
82
|
+
}
|
|
83
|
+
emptyTokens = 0;
|
|
84
|
+
const classes = type ? highlighter.style(tagsOf(type)) : null;
|
|
85
|
+
add(lineStart + stream.start, lineStart + stream.pos, classes);
|
|
86
|
+
}
|
|
87
|
+
lineStart += line.length + 1;
|
|
88
|
+
}
|
|
89
|
+
flush();
|
|
90
|
+
}
|
|
@@ -154,19 +154,32 @@ const FRAGMENT_SEPARATOR = "#";
|
|
|
154
154
|
const PAIR_SEPARATOR = "&";
|
|
155
155
|
const VALUE_SEPARATOR = "=";
|
|
156
156
|
|
|
157
|
-
/** The query of a URL without the pairs whose whole value
|
|
158
|
-
function
|
|
157
|
+
/** The query of a URL without the pairs whose whole value matches `value`. */
|
|
158
|
+
function dropPairs(search: string, value: RegExp): string {
|
|
159
159
|
return search
|
|
160
160
|
.split(PAIR_SEPARATOR)
|
|
161
161
|
.filter((pair) => {
|
|
162
|
-
const
|
|
163
|
-
return (
|
|
164
|
-
!pair.includes(VALUE_SEPARATOR) || !UNRESOLVED_ROUTE_VALUE.test(value)
|
|
165
|
-
);
|
|
162
|
+
const pairValue = pair.slice(pair.indexOf(VALUE_SEPARATOR) + 1);
|
|
163
|
+
return !pair.includes(VALUE_SEPARATOR) || !value.test(pairValue);
|
|
166
164
|
})
|
|
167
165
|
.join(PAIR_SEPARATOR);
|
|
168
166
|
}
|
|
169
167
|
|
|
168
|
+
/**
|
|
169
|
+
* A URL without its `token`s: a query pair whose whole value is one (`value`)
|
|
170
|
+
* is left out, any other is left empty.
|
|
171
|
+
*/
|
|
172
|
+
function stripTokens(url: string, token: RegExp, value: RegExp): string {
|
|
173
|
+
const [beforeFragment = "", ...fragment] = url.split(FRAGMENT_SEPARATOR);
|
|
174
|
+
const [path = "", ...search] = beforeFragment.split(QUERY_SEPARATOR);
|
|
175
|
+
const query = dropPairs(search.join(QUERY_SEPARATOR), value);
|
|
176
|
+
const rebuilt = [
|
|
177
|
+
query ? `${path}${QUERY_SEPARATOR}${query}` : path,
|
|
178
|
+
...fragment,
|
|
179
|
+
].join(FRAGMENT_SEPARATOR);
|
|
180
|
+
return rebuilt.replace(token, "");
|
|
181
|
+
}
|
|
182
|
+
|
|
170
183
|
/**
|
|
171
184
|
* A link's URL with the `{{params.X}}` / `{{query.X}}` tokens of the page it
|
|
172
185
|
* sits on filled, for a button that always leads somewhere: a query pair
|
|
@@ -180,12 +193,21 @@ export function resolveLinkVariables(
|
|
|
180
193
|
): string {
|
|
181
194
|
const filled = replaceUrlVariables(url, context);
|
|
182
195
|
if (!hasUrlVariables(filled)) return filled;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
196
|
+
return stripTokens(filled, UNRESOLVED_ROUTE_TOKEN, UNRESOLVED_ROUTE_VALUE);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// A row field, `{{row.<path>}}`, as `interpolateUrl` fills it.
|
|
200
|
+
const ROW_KEY = String.raw`row\.[^{}\s]+`;
|
|
201
|
+
const ROW_TOKEN = tokenPattern(ROW_KEY);
|
|
202
|
+
const ROW_VALUE = new RegExp(`^${tokenPattern(ROW_KEY, "").source}$`);
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* A URL sent without a row (a bulk action on the selection bar) with its
|
|
206
|
+
* `{{row.X}}` tokens taken out as a link's unresolved page tokens are: a query
|
|
207
|
+
* pair whose whole value is one is left out (`?ids={{row._id}}` gives way to
|
|
208
|
+
* the selection's `ids`), any other is left empty.
|
|
209
|
+
*/
|
|
210
|
+
export function dropRowTokens(url: string): string {
|
|
211
|
+
if (!new RegExp(ROW_TOKEN.source).test(url)) return url;
|
|
212
|
+
return stripTokens(url, ROW_TOKEN, ROW_VALUE);
|
|
191
213
|
}
|
|
@@ -20,6 +20,11 @@ interface Props {
|
|
|
20
20
|
* a role preview veil this block; without it the block is never veiled.
|
|
21
21
|
*/
|
|
22
22
|
layoutPath?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Props handed to this block only, as they are (functions included), over
|
|
25
|
+
* its options: what an action target's container gives its block.
|
|
26
|
+
*/
|
|
27
|
+
rootProps?: Record<string, unknown>;
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
const props = defineProps<Props>();
|
|
@@ -108,7 +113,10 @@ provide<GridDeclaredColumns>(GRID_DECLARED_COLUMNS, {
|
|
|
108
113
|
<Component
|
|
109
114
|
:is="component.component"
|
|
110
115
|
:ref="anchorBlock"
|
|
111
|
-
v-bind="
|
|
116
|
+
v-bind="{
|
|
117
|
+
...JSON.parse(JSON.stringify(component.options || {})),
|
|
118
|
+
...rootProps,
|
|
119
|
+
}"
|
|
112
120
|
:page-id="pageId"
|
|
113
121
|
:component-id="componentId"
|
|
114
122
|
:child-count="columnCount"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed,
|
|
2
|
+
import { computed, onMounted, ref } from "vue";
|
|
3
3
|
import DmsSegmented from "../segmented/Segmented.vue";
|
|
4
4
|
import { usePageLive } from "../../composables/live/usePageLive";
|
|
5
|
-
import {
|
|
5
|
+
import { useUpdatedLabel } from "../../build/composables/live/useUpdatedLabel";
|
|
6
6
|
import { useLiveToggleShortcut } from "../../build/composables/live/useLiveToggleShortcut";
|
|
7
7
|
import { HIDDEN_TAB_NOTE } from "../../build/composables/live/pageLiveController";
|
|
8
8
|
import type { ConfirmTranslate } from "../../build/composables/confirm/confirmDialogTexts";
|
|
@@ -10,14 +10,24 @@ import {
|
|
|
10
10
|
missedRowsText,
|
|
11
11
|
showLiveNote,
|
|
12
12
|
} from "../../build/composables/live/liveNotes";
|
|
13
|
+
import {
|
|
14
|
+
type PageToolbarSize,
|
|
15
|
+
usePageToolbar,
|
|
16
|
+
useToolbarLiveToggle,
|
|
17
|
+
} from "../../build/composables/page-toolbar/pageToolbarContext";
|
|
18
|
+
import { PAGE_TOOLBAR_CONTROL_HEIGHT_CLASSES } from "../../build/composables/page-toolbar/toolbarControlHeight";
|
|
13
19
|
import type { DefaultComponentProps } from "../../../../dms-core/app/types/component";
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
// Its ids are optional: it reads the page's live state, not its own, and a
|
|
22
|
+
// component may draw it by hand inside its own `PageToolbar`.
|
|
23
|
+
interface LiveToggleBlockProps extends Partial<DefaultComponentProps> {
|
|
16
24
|
align?: "left" | "center" | "right";
|
|
17
25
|
/** Shows "updated N s ago". */
|
|
18
26
|
showUpdatedAt?: boolean;
|
|
19
27
|
/** `segmented` (Live / Pause segments) or `pill` (a pulsing Live pill). */
|
|
20
28
|
variant?: "segmented" | "pill";
|
|
29
|
+
/** How large it is drawn; the holding `PageToolbar`'s size, else `sm`. */
|
|
30
|
+
size?: PageToolbarSize;
|
|
21
31
|
/** What the paused toggle calls the missed events, given `{count}`. */
|
|
22
32
|
missedLabel?: string;
|
|
23
33
|
}
|
|
@@ -26,12 +36,13 @@ const props = withDefaults(defineProps<LiveToggleBlockProps>(), {
|
|
|
26
36
|
align: "right",
|
|
27
37
|
showUpdatedAt: true,
|
|
28
38
|
variant: "segmented",
|
|
39
|
+
size: undefined,
|
|
29
40
|
missedLabel: undefined,
|
|
30
41
|
});
|
|
31
42
|
|
|
32
43
|
const DIRECT = "direct";
|
|
33
44
|
const PAUSE = "pause";
|
|
34
|
-
const
|
|
45
|
+
const DEFAULT_SIZE: PageToolbarSize = "sm";
|
|
35
46
|
const ALIGN_CLASSES: Record<
|
|
36
47
|
NonNullable<LiveToggleBlockProps["align"]>,
|
|
37
48
|
string
|
|
@@ -41,26 +52,53 @@ const ALIGN_CLASSES: Record<
|
|
|
41
52
|
right: "justify-end",
|
|
42
53
|
};
|
|
43
54
|
const PILL_BUTTON_CLASS =
|
|
44
|
-
"focus-visible:outline-primary flex items-center
|
|
55
|
+
"focus-visible:outline-primary flex h-full items-center rounded-[5px] font-medium transition-colors focus-visible:outline-2";
|
|
45
56
|
const PILL_IDLE_CLASS = "text-muted hover:text-default hover:bg-elevated";
|
|
46
57
|
|
|
58
|
+
/** What each size changes: the texts and the pill's buttons. */
|
|
59
|
+
interface LiveToggleSizeClasses {
|
|
60
|
+
text: string;
|
|
61
|
+
pillButton: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The pill takes the toolbar's one height (its buttons fill it), as the
|
|
65
|
+
// period selector's segments beside it and the Resume button do.
|
|
66
|
+
const SIZE_CLASSES: Record<PageToolbarSize, LiveToggleSizeClasses> = {
|
|
67
|
+
xs: {
|
|
68
|
+
text: "text-[11.5px]",
|
|
69
|
+
pillButton: "gap-1 px-1.5 text-[11px]",
|
|
70
|
+
},
|
|
71
|
+
sm: {
|
|
72
|
+
text: "text-[12.5px]",
|
|
73
|
+
pillButton: "gap-1.5 px-2 text-[12px]",
|
|
74
|
+
},
|
|
75
|
+
md: {
|
|
76
|
+
text: "text-[13px]",
|
|
77
|
+
pillButton: "gap-1.5 px-2.5 text-[13px]",
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
47
81
|
const { t } = useI18n();
|
|
48
82
|
const translate = t as ConfirmTranslate;
|
|
49
83
|
const live = usePageLive();
|
|
84
|
+
const toolbar = usePageToolbar();
|
|
85
|
+
useToolbarLiveToggle(toolbar);
|
|
86
|
+
const size = computed(() => props.size ?? toolbar?.size.value ?? DEFAULT_SIZE);
|
|
87
|
+
const sizeClasses = computed(() => SIZE_CLASSES[size.value]);
|
|
88
|
+
const heightClass = computed(
|
|
89
|
+
() => PAGE_TOOLBAR_CONTROL_HEIGHT_CLASSES[size.value],
|
|
90
|
+
);
|
|
50
91
|
|
|
51
|
-
// The
|
|
52
|
-
//
|
|
92
|
+
// The toggle is drawn from the server on, live (the remembered pause applies
|
|
93
|
+
// once mounted), so it takes its place before the page paints. Only the
|
|
94
|
+
// "updated N s ago" text waits for the browser's clock: the server's would
|
|
95
|
+
// not match the hydrating render's.
|
|
53
96
|
const isMounted = ref(false);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (props.showUpdatedAt) {
|
|
60
|
-
ticker = setInterval(() => (now.value = Date.now()), TICK_MS);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
onBeforeUnmount(() => clearInterval(ticker));
|
|
97
|
+
onMounted(() => (isMounted.value = true));
|
|
98
|
+
const updatedText = useUpdatedLabel(
|
|
99
|
+
() => live.lastUpdatedAt.value,
|
|
100
|
+
props.showUpdatedAt,
|
|
101
|
+
);
|
|
64
102
|
|
|
65
103
|
const mode = computed({
|
|
66
104
|
get: () => (live.isPaused.value ? PAUSE : DIRECT),
|
|
@@ -75,15 +113,9 @@ const items = computed(() => [
|
|
|
75
113
|
{ value: PAUSE, label: t("dms.live.pause"), icon: "i-ph-pause" },
|
|
76
114
|
]);
|
|
77
115
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const { unit, count } = formatElapsed(now.value - at);
|
|
82
|
-
const updated = t(`dms.live.updated_${unit}`, { count }, count);
|
|
83
|
-
return live.isPolling.value
|
|
84
|
-
? `${updated} · ${t("dms.live.polling")}`
|
|
85
|
-
: updated;
|
|
86
|
-
});
|
|
116
|
+
// The browser's clock only: the server's text would not match the hydrating
|
|
117
|
+
// render's.
|
|
118
|
+
const updatedLabel = computed(() => (isMounted.value ? updatedText.value : ""));
|
|
87
119
|
|
|
88
120
|
const missedText = computed(() => {
|
|
89
121
|
const count = live.missedCount.value;
|
|
@@ -122,13 +154,14 @@ useLiveToggleShortcut(() => live.toggle());
|
|
|
122
154
|
|
|
123
155
|
<template>
|
|
124
156
|
<div
|
|
125
|
-
v-if="
|
|
157
|
+
v-if="live.isEnabled.value"
|
|
126
158
|
class="dms-live-toggle flex flex-wrap items-center gap-x-2.5 gap-y-1"
|
|
127
159
|
:class="[ALIGN_CLASSES[align], `dms-live-toggle--${variant}`]"
|
|
128
160
|
>
|
|
129
161
|
<span
|
|
130
162
|
v-if="live.isPaused.value"
|
|
131
|
-
class="dms-live-toggle__status text-muted min-w-0
|
|
163
|
+
class="dms-live-toggle__status text-muted min-w-0 tabular-nums"
|
|
164
|
+
:class="sizeClasses.text"
|
|
132
165
|
aria-live="polite"
|
|
133
166
|
>
|
|
134
167
|
{{ pausedText }}
|
|
@@ -136,16 +169,28 @@ useLiveToggleShortcut(() => live.toggle());
|
|
|
136
169
|
</span>
|
|
137
170
|
<span
|
|
138
171
|
v-else-if="showUpdatedAt"
|
|
139
|
-
class="text-muted
|
|
172
|
+
class="text-muted inline-flex items-center gap-1.5 tabular-nums"
|
|
173
|
+
:class="sizeClasses.text"
|
|
140
174
|
aria-live="off"
|
|
141
175
|
>
|
|
142
176
|
{{ updatedLabel }}
|
|
177
|
+
<!-- The polling hint, its box always kept: showing it never widens the
|
|
178
|
+
toggle, which would wrap the toolbar and move the page. -->
|
|
179
|
+
<UIcon
|
|
180
|
+
name="i-ph-wifi-slash"
|
|
181
|
+
class="dms-live-toggle__polling size-3.5 shrink-0"
|
|
182
|
+
:class="!live.isPolling.value && 'invisible'"
|
|
183
|
+
:title="live.isPolling.value ? t('dms.live.polling') : undefined"
|
|
184
|
+
:aria-label="live.isPolling.value ? t('dms.live.polling') : undefined"
|
|
185
|
+
:aria-hidden="!live.isPolling.value || undefined"
|
|
186
|
+
/>
|
|
143
187
|
</span>
|
|
144
188
|
<div
|
|
145
189
|
v-if="variant === 'pill'"
|
|
146
190
|
role="group"
|
|
147
191
|
:aria-label="t('dms.live.aria_label')"
|
|
148
|
-
class="border-default bg-default inline-flex shrink-0 items-
|
|
192
|
+
class="border-default bg-default inline-flex shrink-0 items-stretch gap-0.5 rounded-md border p-0.5"
|
|
193
|
+
:class="heightClass"
|
|
149
194
|
>
|
|
150
195
|
<button
|
|
151
196
|
type="button"
|
|
@@ -153,6 +198,7 @@ useLiveToggleShortcut(() => live.toggle());
|
|
|
153
198
|
:aria-pressed="live.isLive.value"
|
|
154
199
|
:class="[
|
|
155
200
|
PILL_BUTTON_CLASS,
|
|
201
|
+
sizeClasses.pillButton,
|
|
156
202
|
live.isLive.value ? 'bg-success/10 text-success' : PILL_IDLE_CLASS,
|
|
157
203
|
]"
|
|
158
204
|
@click="live.resume()"
|
|
@@ -173,6 +219,7 @@ useLiveToggleShortcut(() => live.toggle());
|
|
|
173
219
|
:aria-pressed="live.isPaused.value"
|
|
174
220
|
:class="[
|
|
175
221
|
PILL_BUTTON_CLASS,
|
|
222
|
+
sizeClasses.pillButton,
|
|
176
223
|
live.isPaused.value
|
|
177
224
|
? 'bg-elevated text-highlighted'
|
|
178
225
|
: PILL_IDLE_CLASS,
|
|
@@ -188,12 +235,13 @@ useLiveToggleShortcut(() => live.toggle());
|
|
|
188
235
|
v-model="mode"
|
|
189
236
|
:items="items"
|
|
190
237
|
:aria-label="t('dms.live.aria_label')"
|
|
191
|
-
size="
|
|
238
|
+
:size="size"
|
|
192
239
|
/>
|
|
193
240
|
<UButton
|
|
194
241
|
v-if="variant === 'pill' && canResume"
|
|
195
242
|
data-action="resume"
|
|
196
|
-
size="
|
|
243
|
+
:size="size"
|
|
244
|
+
:class="heightClass"
|
|
197
245
|
color="neutral"
|
|
198
246
|
variant="soft"
|
|
199
247
|
icon="i-ph-play-fill"
|