@antelopejs/dms 0.9.8 → 0.10.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 +102 -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 -0
- package/dist/config.js +5 -3
- 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 +22 -89
- 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 +1 -2
- package/dist/implementations/dms/manifest.js +2 -0
- 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 +28 -48
- 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 +24 -13
- package/dist/store/listing.js.map +1 -1
- package/dist/store/operations.js +4 -0
- 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/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 +34 -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/hydration/isHydratingComponent.ts +29 -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 +22 -5
- 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 +166 -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 +134 -2
- package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +134 -2
- 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 +9 -0
- 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 -3
- package/frontend-vue/layers/dms-layout/app/build/components/layout/GithubStarPrompt.vue +18 -7
- package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionBar.vue +8 -0
- package/frontend-vue/layers/dms-layout/app/build/components/layout/PageHeaderActionsOutlet.vue +14 -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/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/usePageRecord.ts +50 -0
- package/frontend-vue/layers/dms-layout/app/composables/layout/useServedHeaderActions.ts +25 -7
- package/frontend-vue/layers/dms-layout/app/composables/page/useModuleHistory.ts +3 -2
- package/frontend-vue/layers/dms-layout/app/composables/page/useModuleStore.ts +51 -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/useSiteLayout.ts +6 -1
- package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +9 -0
- package/frontend-vue/layers/dms-layout/app/custom-layouts/SettingsLayout.vue +9 -0
- 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 +6 -22
- package/frontend-vue/layers/dms-layout/app/plugins/command-palette-navigation.client.ts +2 -1
- package/frontend-vue/layers/dms-layout/app/plugins/command-palette-personal-pages.client.ts +14 -44
- package/frontend-vue/layers/dms-layout/app/plugins/dms-dev-reload.client.ts +14 -9
- 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/app/utils/pageRecord.ts +71 -0
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +39 -14
- package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +38 -13
- 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/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 +38 -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/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 +47 -0
- package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +99 -24
- 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 +71 -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/formSections.ts +32 -0
- 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 +65 -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 +73 -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 +77 -32
- 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/utils/addressSuggestions.ts +49 -0
- 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/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/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/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 +118 -36
- 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 +205 -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 +203 -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/KanbanBoard.vue +45 -35
- 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 +410 -96
- 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 +4 -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 +142 -21
- package/frontend-vue/layers/dms-ui/app/composables/live/usePageLive.ts +11 -4
- 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/componentTree.ts +24 -0
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +16 -4
- package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +16 -4
- package/frontend-vue/package.json +2 -2
- package/package.json +7 -6
- 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 +125 -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/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
|
@@ -20,8 +20,6 @@ const TIME_UNITS = {
|
|
|
20
20
|
ms: 1,
|
|
21
21
|
} as const;
|
|
22
22
|
|
|
23
|
-
const TIME_UNIT_ORDER = ["y", "M", "w", "d", "h", "m", "s", "ms"] as const;
|
|
24
|
-
|
|
25
23
|
type TranslateFunction = (
|
|
26
24
|
key: string,
|
|
27
25
|
params?: Record<string, unknown>,
|
|
@@ -229,9 +227,56 @@ export function formatDateTime(
|
|
|
229
227
|
});
|
|
230
228
|
}
|
|
231
229
|
|
|
230
|
+
// The narrow no-break space French (and a few other locales) groups digits
|
|
231
|
+
// with: the interface's font draws it a fraction of a digit wide, so "1 234"
|
|
232
|
+
// read as "1234" beside a column's "12 345". Groups take a full no-break space.
|
|
233
|
+
const NARROW_GROUP_SEPARATOR = " ";
|
|
234
|
+
const GROUP_SEPARATOR = " ";
|
|
235
|
+
|
|
236
|
+
/** `Intl.NumberFormat`, its digit groups always shown and visible. */
|
|
237
|
+
export interface ReadableNumberFormat {
|
|
238
|
+
format(value: number): string;
|
|
239
|
+
formatToParts(value: number): Intl.NumberFormatPart[];
|
|
240
|
+
resolvedOptions(): Intl.ResolvedNumberFormatOptions;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function readablePart(part: Intl.NumberFormatPart): Intl.NumberFormatPart {
|
|
244
|
+
return part.type === "group" && part.value === NARROW_GROUP_SEPARATOR
|
|
245
|
+
? { ...part, value: GROUP_SEPARATOR }
|
|
246
|
+
: part;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* `new Intl.NumberFormat(locale, options)` the way the interface writes a
|
|
251
|
+
* figure: a four-digit one grouped like a longer one ("1 234" next to
|
|
252
|
+
* "12 345", where Spanish or Polish would leave "1234" by default), with a
|
|
253
|
+
* group separator wide enough to see. `options.useGrouping` still decides.
|
|
254
|
+
* Throws as `Intl.NumberFormat` does on options it refuses.
|
|
255
|
+
*/
|
|
256
|
+
export function readableNumberFormat(
|
|
257
|
+
locale?: string,
|
|
258
|
+
options?: Intl.NumberFormatOptions,
|
|
259
|
+
): ReadableNumberFormat {
|
|
260
|
+
const format = new Intl.NumberFormat(locale, {
|
|
261
|
+
useGrouping: true,
|
|
262
|
+
...options,
|
|
263
|
+
});
|
|
264
|
+
const formatToParts = (value: number) =>
|
|
265
|
+
format.formatToParts(value).map(readablePart);
|
|
266
|
+
return {
|
|
267
|
+
format: (value) =>
|
|
268
|
+
formatToParts(value)
|
|
269
|
+
.map((part) => part.value)
|
|
270
|
+
.join(""),
|
|
271
|
+
formatToParts,
|
|
272
|
+
resolvedOptions: () => format.resolvedOptions(),
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
232
276
|
/**
|
|
233
|
-
* A number written for `locale
|
|
234
|
-
* is. Options Intl refuses (an unknown
|
|
277
|
+
* A number written for `locale` (see {@link readableNumberFormat}); a value
|
|
278
|
+
* that is not a number is returned as is. Options Intl refuses (an unknown
|
|
279
|
+
* currency) write the bare number.
|
|
235
280
|
*/
|
|
236
281
|
export function formatNumber(
|
|
237
282
|
value: number,
|
|
@@ -250,7 +295,7 @@ export function formatNumber(
|
|
|
250
295
|
): unknown {
|
|
251
296
|
if (!isNumber(value)) return value;
|
|
252
297
|
try {
|
|
253
|
-
return
|
|
298
|
+
return readableNumberFormat(locale, options).format(value);
|
|
254
299
|
} catch {
|
|
255
300
|
return String(value);
|
|
256
301
|
}
|
|
@@ -312,16 +357,19 @@ const TIME_SPAN_UNITS: Record<string, keyof typeof TIME_UNITS> = {
|
|
|
312
357
|
w: "w",
|
|
313
358
|
d: "d",
|
|
314
359
|
h: "h",
|
|
360
|
+
min: "m",
|
|
315
361
|
m: "m",
|
|
316
362
|
s: "s",
|
|
317
363
|
ms: "ms",
|
|
318
364
|
};
|
|
319
365
|
|
|
320
|
-
// `01:30`, `26:00:30`: hours, then minutes and seconds under 60.
|
|
366
|
+
// `01:30`, `8:15`, `26:00:30`: hours, then minutes and seconds under 60.
|
|
321
367
|
const CLOCK_SPAN = /^(\d+):([0-5]\d)(?::([0-5]\d))?$/;
|
|
322
|
-
// `
|
|
323
|
-
const
|
|
324
|
-
|
|
368
|
+
// `8h15`, `8 h 05`: hours, then bare minutes, the way a time is often written.
|
|
369
|
+
const HOUR_MINUTE_SPAN = /^(\d+)\s*h\s*([0-5]?\d)$/i;
|
|
370
|
+
// `1h30m`, `1h 30m`, `7 h 30 min`, `1h:30m` (older displays), `1.5h`.
|
|
371
|
+
const UNIT_SPAN = /^(?:\d+(?:[.,]\d+)?\s*(?:ms|mo|min|[Mmwydhs])[\s:]*)+$/;
|
|
372
|
+
const UNIT_SPAN_PART = /(\d+(?:[.,]\d+)?)\s*(ms|mo|min|[Mmwydhs])/g;
|
|
325
373
|
|
|
326
374
|
function readClockSpan(text: string): number | undefined {
|
|
327
375
|
const match = CLOCK_SPAN.exec(text);
|
|
@@ -334,24 +382,38 @@ function readClockSpan(text: string): number | undefined {
|
|
|
334
382
|
);
|
|
335
383
|
}
|
|
336
384
|
|
|
385
|
+
function readHourMinuteSpan(text: string): number | undefined {
|
|
386
|
+
const match = HOUR_MINUTE_SPAN.exec(text);
|
|
387
|
+
if (!match) return undefined;
|
|
388
|
+
const [, hours, minutes] = match;
|
|
389
|
+
return Number(hours) * TIME_UNITS.h + Number(minutes) * TIME_UNITS.m;
|
|
390
|
+
}
|
|
391
|
+
|
|
337
392
|
function readUnitSpan(text: string): number | undefined {
|
|
338
393
|
if (!UNIT_SPAN.test(text)) return undefined;
|
|
339
394
|
let total = 0;
|
|
340
395
|
for (const [, amount, unit] of text.matchAll(UNIT_SPAN_PART)) {
|
|
341
|
-
|
|
396
|
+
const value = Number.parseFloat(amount!.replace(",", "."));
|
|
397
|
+
total += value * TIME_UNITS[TIME_SPAN_UNITS[unit!]!];
|
|
342
398
|
}
|
|
343
399
|
return total;
|
|
344
400
|
}
|
|
345
401
|
|
|
346
402
|
/**
|
|
347
|
-
* A duration typed in, in milliseconds: a clock duration (`01:30`,
|
|
348
|
-
* `26:00:30`)
|
|
349
|
-
*
|
|
403
|
+
* A duration typed in, in milliseconds: a clock duration (`01:30`, `8:15`,
|
|
404
|
+
* `26:00:30`), hours then minutes (`8h15`, `8h`) or units (`1h30m`,
|
|
405
|
+
* `1h 30m`, `7 h 30 min`, `1.5h`), a `-` before any of them for a negative
|
|
406
|
+
* one, or `undefined` for a text that is neither. It reads all
|
|
407
|
+
* {@link formatDuration} writes.
|
|
350
408
|
*/
|
|
351
409
|
export function readTimeSpan(value: string): number | undefined {
|
|
352
|
-
const
|
|
410
|
+
const trimmed = value.trim();
|
|
411
|
+
const isNegative = trimmed.startsWith("-");
|
|
412
|
+
const text = isNegative ? trimmed.slice(1).trimStart() : trimmed;
|
|
353
413
|
if (!text) return undefined;
|
|
354
|
-
|
|
414
|
+
const span =
|
|
415
|
+
readClockSpan(text) ?? readHourMinuteSpan(text) ?? readUnitSpan(text);
|
|
416
|
+
return span !== undefined && isNegative ? -span : span;
|
|
355
417
|
}
|
|
356
418
|
|
|
357
419
|
export function parseTimeSpan(value: string | number): number {
|
|
@@ -359,30 +421,99 @@ export function parseTimeSpan(value: string | number): number {
|
|
|
359
421
|
return readTimeSpan(value) ?? 0;
|
|
360
422
|
}
|
|
361
423
|
|
|
362
|
-
|
|
363
|
-
|
|
424
|
+
// Durations count in hours at most: a day or a month is a calendar span, not
|
|
425
|
+
// a number of hours.
|
|
426
|
+
const DURATION_UNITS = [
|
|
427
|
+
{ symbol: "h", ms: TIME_UNITS.h, fractionDigits: 0 },
|
|
428
|
+
{ symbol: "min", ms: TIME_UNITS.m, fractionDigits: 0 },
|
|
429
|
+
// The seconds carry the milliseconds, so nothing is rounded away.
|
|
430
|
+
{ symbol: "s", ms: TIME_UNITS.s, fractionDigits: 3 },
|
|
431
|
+
] as const;
|
|
432
|
+
const MS_FRACTION_DIGITS = 3;
|
|
364
433
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
434
|
+
/**
|
|
435
|
+
* How exact a written duration is: `exact` (the default) keeps every
|
|
436
|
+
* millisecond, so a field shows the value it holds and {@link readTimeSpan}
|
|
437
|
+
* reads it back; `rounded` keeps two units at most, the smaller one rounded
|
|
438
|
+
* ("2.1 s", "4 min 12 s", "7 h 30 min"), for a cell read at a glance.
|
|
439
|
+
*/
|
|
440
|
+
export type DurationPrecision = "exact" | "rounded";
|
|
441
|
+
|
|
442
|
+
export interface DurationFormatOptions {
|
|
443
|
+
precision?: DurationPrecision;
|
|
444
|
+
}
|
|
370
445
|
|
|
371
|
-
|
|
372
|
-
if (totalMs === 0) return ZERO_MS;
|
|
446
|
+
const ROUNDED_SECONDS_FRACTION_DIGITS = 1;
|
|
373
447
|
|
|
448
|
+
function durationFigure(
|
|
449
|
+
locale: string,
|
|
450
|
+
value: number,
|
|
451
|
+
symbol: string,
|
|
452
|
+
fractionDigits: number,
|
|
453
|
+
): string {
|
|
454
|
+
const figure = readableNumberFormat(locale, {
|
|
455
|
+
maximumFractionDigits: fractionDigits,
|
|
456
|
+
useGrouping: false,
|
|
457
|
+
numberingSystem: "latn",
|
|
458
|
+
}).format(value);
|
|
459
|
+
return `${figure} ${symbol}`;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function exactDuration(ms: number, locale: string): string {
|
|
463
|
+
let remaining = ms;
|
|
464
|
+
if (remaining < TIME_UNITS.s) {
|
|
465
|
+
return durationFigure(locale, remaining, "ms", MS_FRACTION_DIGITS);
|
|
466
|
+
}
|
|
374
467
|
const parts: string[] = [];
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
parts.push(
|
|
382
|
-
remaining %= unitValue;
|
|
383
|
-
}
|
|
468
|
+
for (const { symbol, ms: unitMs, fractionDigits } of DURATION_UNITS) {
|
|
469
|
+
const amount = fractionDigits
|
|
470
|
+
? remaining / unitMs
|
|
471
|
+
: Math.floor(remaining / unitMs);
|
|
472
|
+
remaining -= amount * unitMs;
|
|
473
|
+
if (amount)
|
|
474
|
+
parts.push(durationFigure(locale, amount, symbol, fractionDigits));
|
|
384
475
|
}
|
|
476
|
+
return parts.join(" ");
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function roundedDuration(ms: number, locale: string): string {
|
|
480
|
+
if (ms < TIME_UNITS.s) return durationFigure(locale, Math.round(ms), "ms", 0);
|
|
481
|
+
if (ms < TIME_UNITS.m) {
|
|
482
|
+
return durationFigure(
|
|
483
|
+
locale,
|
|
484
|
+
ms / TIME_UNITS.s,
|
|
485
|
+
"s",
|
|
486
|
+
ROUNDED_SECONDS_FRACTION_DIGITS,
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
const [major, majorSymbol, minor, minorSymbol] =
|
|
490
|
+
ms < TIME_UNITS.h
|
|
491
|
+
? ([TIME_UNITS.m, "min", TIME_UNITS.s, "s"] as const)
|
|
492
|
+
: ([TIME_UNITS.h, "h", TIME_UNITS.m, "min"] as const);
|
|
493
|
+
// Rounded as a whole first, so 1 min 59.7 s reads "2 min", not "1 min 60 s".
|
|
494
|
+
const total = Math.round(ms / minor) * minor;
|
|
495
|
+
const whole = Math.floor(total / major);
|
|
496
|
+
const rest = (total - whole * major) / minor;
|
|
497
|
+
const head = durationFigure(locale, whole, majorSymbol, 0);
|
|
498
|
+
return rest
|
|
499
|
+
? `${head} ${durationFigure(locale, rest, minorSymbol, 0)}`
|
|
500
|
+
: head;
|
|
501
|
+
}
|
|
385
502
|
|
|
386
|
-
|
|
387
|
-
|
|
503
|
+
/**
|
|
504
|
+
* A duration in milliseconds the way people write it, its figures in the
|
|
505
|
+
* reader's locale: "910 ms", "2.149 s", "4 min 12 s", "7 h 30 min". The one
|
|
506
|
+
* writer of a duration, for a field and a cell alike. Exact by default (hours
|
|
507
|
+
* and minutes whole, the seconds carrying the milliseconds), its figures
|
|
508
|
+
* neither grouped nor in another script, so {@link readTimeSpan} reads back
|
|
509
|
+
* the very value it wrote; `precision: "rounded"` for a cell.
|
|
510
|
+
*/
|
|
511
|
+
export function formatDuration(
|
|
512
|
+
ms: number,
|
|
513
|
+
locale: string,
|
|
514
|
+
{ precision = "exact" }: DurationFormatOptions = {},
|
|
515
|
+
): string {
|
|
516
|
+
const sign = ms < 0 ? "-" : "";
|
|
517
|
+
const write = precision === "rounded" ? roundedDuration : exactDuration;
|
|
518
|
+
return sign + write(Math.abs(ms), locale);
|
|
388
519
|
}
|
|
@@ -12,8 +12,25 @@ const WHOLE_ROW_TOKEN = new RegExp(`^\\s*${ROW_TOKEN.source}\\s*$`);
|
|
|
12
12
|
export const namesRowField = (template: string): boolean =>
|
|
13
13
|
new RegExp(ROW_TOKEN.source).test(template);
|
|
14
14
|
|
|
15
|
+
// A relation field is listed as the related row (a join): it stands for that
|
|
16
|
+
// row's id, as the field stores it, rather than "[object Object]". A dotted
|
|
17
|
+
// path (`{{row.customer.name}}`) still reaches into the row.
|
|
18
|
+
const RELATED_ROW_ID_KEYS = ["_id", "id"] as const;
|
|
19
|
+
|
|
20
|
+
const isPlainObject = (value: unknown): value is Record<string, unknown> =>
|
|
21
|
+
Object.prototype.toString.call(value) === "[object Object]";
|
|
22
|
+
|
|
23
|
+
const relatedRowId = (value: Record<string, unknown>): unknown =>
|
|
24
|
+
RELATED_ROW_ID_KEYS.map((key) => value[key]).find(
|
|
25
|
+
(id) => id !== undefined && id !== null,
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const scalarOf = (value: unknown): unknown =>
|
|
29
|
+
isPlainObject(value) ? relatedRowId(value) : value;
|
|
30
|
+
|
|
15
31
|
const rowValue = (data: Record<string, unknown>, key: string): string => {
|
|
16
|
-
const
|
|
32
|
+
const field: unknown = get(data, key);
|
|
33
|
+
const value = Array.isArray(field) ? field.map(scalarOf) : scalarOf(field);
|
|
17
34
|
return value === undefined || value === null ? "" : String(value);
|
|
18
35
|
};
|
|
19
36
|
|
|
@@ -438,7 +438,8 @@
|
|
|
438
438
|
"chart": {
|
|
439
439
|
"no_data": "No data",
|
|
440
440
|
"legend_period": "Period",
|
|
441
|
-
"legend_comparison": "Comparison"
|
|
441
|
+
"legend_comparison": "Comparison",
|
|
442
|
+
"versus_value": "vs {value}"
|
|
442
443
|
},
|
|
443
444
|
"period": {
|
|
444
445
|
"aria_label": "Period selector",
|
|
@@ -463,12 +464,33 @@
|
|
|
463
464
|
"all": "All time",
|
|
464
465
|
"custom": "Custom"
|
|
465
466
|
},
|
|
467
|
+
"short_presets": {
|
|
468
|
+
"last-hour": "1H",
|
|
469
|
+
"last-24h": "24H",
|
|
470
|
+
"today": "1D",
|
|
471
|
+
"yesterday": "-1D",
|
|
472
|
+
"last-7-days": "7D",
|
|
473
|
+
"last-30-days": "30D",
|
|
474
|
+
"last-90-days": "90D",
|
|
475
|
+
"this-month": "MTD",
|
|
476
|
+
"last-month": "-1M",
|
|
477
|
+
"this-quarter": "QTD",
|
|
478
|
+
"last-quarter": "-1Q",
|
|
479
|
+
"ytd": "YTD",
|
|
480
|
+
"last-year": "-1Y",
|
|
481
|
+
"all": "ALL"
|
|
482
|
+
},
|
|
466
483
|
"comparisons": {
|
|
467
484
|
"none": "No comparison",
|
|
468
485
|
"previous-period": "vs previous period",
|
|
469
486
|
"previous-year": "vs previous year",
|
|
470
487
|
"custom": "Custom"
|
|
471
488
|
},
|
|
489
|
+
"compare_labels": {
|
|
490
|
+
"previous-period": "vs previous period",
|
|
491
|
+
"previous-year": "vs previous year",
|
|
492
|
+
"custom": "vs comparison period"
|
|
493
|
+
},
|
|
472
494
|
"compare_options": {
|
|
473
495
|
"none": "No comparison",
|
|
474
496
|
"previous-period": "Previous period",
|
|
@@ -494,7 +516,117 @@
|
|
|
494
516
|
},
|
|
495
517
|
"a11y": {
|
|
496
518
|
"breadcrumb": "Breadcrumb",
|
|
497
|
-
"
|
|
519
|
+
"close": "Close",
|
|
520
|
+
"loading": "Loading",
|
|
521
|
+
"show_options": "Show options"
|
|
522
|
+
},
|
|
523
|
+
"automation": {
|
|
524
|
+
"triggers": {
|
|
525
|
+
"memberAdded": {
|
|
526
|
+
"name": "Member added",
|
|
527
|
+
"description": "Fires when a user becomes a member of a workspace"
|
|
528
|
+
},
|
|
529
|
+
"memberRemoved": {
|
|
530
|
+
"name": "Member removed",
|
|
531
|
+
"description": "Fires when members are removed from a workspace"
|
|
532
|
+
},
|
|
533
|
+
"inviteCreated": {
|
|
534
|
+
"name": "Invite created",
|
|
535
|
+
"description": "Fires when a user invite is created on a workspace"
|
|
536
|
+
},
|
|
537
|
+
"userRegistered": {
|
|
538
|
+
"name": "User registered",
|
|
539
|
+
"description": "Fires when a new user completes signup"
|
|
540
|
+
},
|
|
541
|
+
"recordCreated": {
|
|
542
|
+
"name": "Record created",
|
|
543
|
+
"description": "Fires when rows are created in a TableView-backed table"
|
|
544
|
+
},
|
|
545
|
+
"recordUpdated": {
|
|
546
|
+
"name": "Record updated",
|
|
547
|
+
"description": "Fires when rows are updated in a TableView-backed table"
|
|
548
|
+
},
|
|
549
|
+
"recordDeleted": {
|
|
550
|
+
"name": "Record deleted",
|
|
551
|
+
"description": "Fires when rows are deleted in a TableView-backed table"
|
|
552
|
+
},
|
|
553
|
+
"record": {
|
|
554
|
+
"fields": {
|
|
555
|
+
"location": "Data controller location to watch, e.g. \"/api/tables/members\". Leave empty to fire for every table."
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
"actions": {
|
|
560
|
+
"sendEmail": {
|
|
561
|
+
"name": "Send email",
|
|
562
|
+
"description": "Send an HTML email through the configured email provider, written out or rendered from a registered HTML template",
|
|
563
|
+
"fields": {
|
|
564
|
+
"template": "Name of a registered HTML template to render instead of the HTML",
|
|
565
|
+
"props": "Props the template is rendered with",
|
|
566
|
+
"language": "Language the template is rendered in; defaults to the recipient's when the address belongs to a user"
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
"sendNotification": {
|
|
570
|
+
"name": "Send notification",
|
|
571
|
+
"description": "Send an in-app notification to specific users and/or every user holding one of the given roles",
|
|
572
|
+
"fields": {
|
|
573
|
+
"userId": "One recipient, e.g. a trigger's user ID",
|
|
574
|
+
"tenantId": "Workspace whose members receive the role notification; leave empty for the default workspace",
|
|
575
|
+
"title": "Literal text, or a \"$\" translation key",
|
|
576
|
+
"description": "Literal text, or a \"$\" translation key",
|
|
577
|
+
"params": "Interpolation params of the title and description translations",
|
|
578
|
+
"idempotencyKey": "Stable event key, e.g. a trigger's delivery ID: a replayed event is delivered once"
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
"inviteUser": {
|
|
582
|
+
"name": "Invite user",
|
|
583
|
+
"description": "Invite an email address to a workspace: existing users are added as members directly, otherwise an invite is created (and its signup email sent unless Send the email is off)",
|
|
584
|
+
"fields": {
|
|
585
|
+
"tenantId": "Workspace to invite into; defaults to the default workspace",
|
|
586
|
+
"language": "Language of the invitation email and of the account it creates; defaults to en",
|
|
587
|
+
"inviterName": "Who the invitation email says it comes from"
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
"fields": {
|
|
592
|
+
"actorId": "Actor ID",
|
|
593
|
+
"actorName": "Actor name",
|
|
594
|
+
"asTenantOwner": "Workspace owner",
|
|
595
|
+
"at": "Date",
|
|
596
|
+
"deliveryId": "Delivery ID",
|
|
597
|
+
"description": "Description",
|
|
598
|
+
"email": "Email",
|
|
599
|
+
"error": "Error",
|
|
600
|
+
"firstname": "First name",
|
|
601
|
+
"html": "HTML",
|
|
602
|
+
"icon": "Icon",
|
|
603
|
+
"idempotencyKey": "Replay key",
|
|
604
|
+
"ids": "Record IDs",
|
|
605
|
+
"inviteId": "Invite ID",
|
|
606
|
+
"inviterName": "Inviter name",
|
|
607
|
+
"isTenantOwner": "Workspace owner",
|
|
608
|
+
"kind": "Result",
|
|
609
|
+
"language": "Language",
|
|
610
|
+
"lastname": "Last name",
|
|
611
|
+
"linkTo": "Link",
|
|
612
|
+
"location": "Table",
|
|
613
|
+
"messageId": "Message ID",
|
|
614
|
+
"name": "Name",
|
|
615
|
+
"ok": "Sent",
|
|
616
|
+
"params": "Parameters",
|
|
617
|
+
"props": "Template props",
|
|
618
|
+
"roleIds": "Roles",
|
|
619
|
+
"sendEmail": "Send the email",
|
|
620
|
+
"subject": "Subject",
|
|
621
|
+
"success": "Success",
|
|
622
|
+
"template": "Template",
|
|
623
|
+
"tenantId": "Workspace",
|
|
624
|
+
"title": "Title",
|
|
625
|
+
"to": "To",
|
|
626
|
+
"tone": "Tone",
|
|
627
|
+
"userId": "User",
|
|
628
|
+
"userIds": "Users"
|
|
629
|
+
}
|
|
498
630
|
}
|
|
499
631
|
}
|
|
500
632
|
}
|
|
@@ -438,7 +438,8 @@
|
|
|
438
438
|
"chart": {
|
|
439
439
|
"no_data": "Aucune donnée",
|
|
440
440
|
"legend_period": "Période",
|
|
441
|
-
"legend_comparison": "Comparaison"
|
|
441
|
+
"legend_comparison": "Comparaison",
|
|
442
|
+
"versus_value": "vs {value}"
|
|
442
443
|
},
|
|
443
444
|
"period": {
|
|
444
445
|
"aria_label": "Sélecteur de période",
|
|
@@ -463,12 +464,33 @@
|
|
|
463
464
|
"all": "Toute la période",
|
|
464
465
|
"custom": "Personnalisé"
|
|
465
466
|
},
|
|
467
|
+
"short_presets": {
|
|
468
|
+
"last-hour": "1 h",
|
|
469
|
+
"last-24h": "24 h",
|
|
470
|
+
"today": "Auj.",
|
|
471
|
+
"yesterday": "Hier",
|
|
472
|
+
"last-7-days": "7 j",
|
|
473
|
+
"last-30-days": "30 j",
|
|
474
|
+
"last-90-days": "90 j",
|
|
475
|
+
"this-month": "Mois",
|
|
476
|
+
"last-month": "M-1",
|
|
477
|
+
"this-quarter": "Trim.",
|
|
478
|
+
"last-quarter": "T-1",
|
|
479
|
+
"ytd": "Année",
|
|
480
|
+
"last-year": "A-1",
|
|
481
|
+
"all": "Tout"
|
|
482
|
+
},
|
|
466
483
|
"comparisons": {
|
|
467
484
|
"none": "Sans comparaison",
|
|
468
485
|
"previous-period": "vs période précédente",
|
|
469
486
|
"previous-year": "vs année précédente",
|
|
470
487
|
"custom": "Personnalisé"
|
|
471
488
|
},
|
|
489
|
+
"compare_labels": {
|
|
490
|
+
"previous-period": "vs période précédente",
|
|
491
|
+
"previous-year": "vs année précédente",
|
|
492
|
+
"custom": "vs période de comparaison"
|
|
493
|
+
},
|
|
472
494
|
"compare_options": {
|
|
473
495
|
"none": "Aucune comparaison",
|
|
474
496
|
"previous-period": "Période précédente",
|
|
@@ -494,7 +516,117 @@
|
|
|
494
516
|
},
|
|
495
517
|
"a11y": {
|
|
496
518
|
"breadcrumb": "Fil d'Ariane",
|
|
497
|
-
"
|
|
519
|
+
"close": "Fermer",
|
|
520
|
+
"loading": "Chargement",
|
|
521
|
+
"show_options": "Afficher les options"
|
|
522
|
+
},
|
|
523
|
+
"automation": {
|
|
524
|
+
"triggers": {
|
|
525
|
+
"memberAdded": {
|
|
526
|
+
"name": "Membre ajouté",
|
|
527
|
+
"description": "Se déclenche quand un utilisateur devient membre d'un espace de travail"
|
|
528
|
+
},
|
|
529
|
+
"memberRemoved": {
|
|
530
|
+
"name": "Membre retiré",
|
|
531
|
+
"description": "Se déclenche quand des membres sont retirés d'un espace de travail"
|
|
532
|
+
},
|
|
533
|
+
"inviteCreated": {
|
|
534
|
+
"name": "Invitation créée",
|
|
535
|
+
"description": "Se déclenche quand une invitation est créée dans un espace de travail"
|
|
536
|
+
},
|
|
537
|
+
"userRegistered": {
|
|
538
|
+
"name": "Utilisateur inscrit",
|
|
539
|
+
"description": "Se déclenche quand un nouvel utilisateur termine son inscription"
|
|
540
|
+
},
|
|
541
|
+
"recordCreated": {
|
|
542
|
+
"name": "Enregistrement créé",
|
|
543
|
+
"description": "Se déclenche quand des lignes sont créées dans une table adossée à une TableView"
|
|
544
|
+
},
|
|
545
|
+
"recordUpdated": {
|
|
546
|
+
"name": "Enregistrement modifié",
|
|
547
|
+
"description": "Se déclenche quand des lignes sont modifiées dans une table adossée à une TableView"
|
|
548
|
+
},
|
|
549
|
+
"recordDeleted": {
|
|
550
|
+
"name": "Enregistrement supprimé",
|
|
551
|
+
"description": "Se déclenche quand des lignes sont supprimées dans une table adossée à une TableView"
|
|
552
|
+
},
|
|
553
|
+
"record": {
|
|
554
|
+
"fields": {
|
|
555
|
+
"location": "Emplacement du contrôleur de données à surveiller, par ex. \"/api/tables/members\". Laissez vide pour réagir à toutes les tables."
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
"actions": {
|
|
560
|
+
"sendEmail": {
|
|
561
|
+
"name": "Envoyer un e-mail",
|
|
562
|
+
"description": "Envoie un e-mail HTML via le fournisseur d'e-mail configuré, rédigé tel quel ou généré à partir d'un modèle HTML enregistré",
|
|
563
|
+
"fields": {
|
|
564
|
+
"template": "Nom d'un modèle HTML enregistré à générer à la place du HTML",
|
|
565
|
+
"props": "Propriétés avec lesquelles le modèle est généré",
|
|
566
|
+
"language": "Langue dans laquelle le modèle est généré ; par défaut celle du destinataire quand l'adresse appartient à un utilisateur"
|
|
567
|
+
}
|
|
568
|
+
},
|
|
569
|
+
"sendNotification": {
|
|
570
|
+
"name": "Envoyer une notification",
|
|
571
|
+
"description": "Envoie une notification dans l'application à des utilisateurs précis et/ou à tous les utilisateurs ayant l'un des rôles indiqués",
|
|
572
|
+
"fields": {
|
|
573
|
+
"userId": "Un destinataire, par ex. l'ID utilisateur d'un déclencheur",
|
|
574
|
+
"tenantId": "Espace de travail dont les membres reçoivent la notification par rôle ; laissez vide pour l'espace par défaut",
|
|
575
|
+
"title": "Texte littéral, ou clé de traduction \"$\"",
|
|
576
|
+
"description": "Texte littéral, ou clé de traduction \"$\"",
|
|
577
|
+
"params": "Paramètres d'interpolation des traductions du titre et de la description",
|
|
578
|
+
"idempotencyKey": "Clé stable de l'événement, par ex. l'ID de livraison d'un déclencheur : un événement rejoué n'est livré qu'une fois"
|
|
579
|
+
}
|
|
580
|
+
},
|
|
581
|
+
"inviteUser": {
|
|
582
|
+
"name": "Inviter un utilisateur",
|
|
583
|
+
"description": "Invite une adresse e-mail dans un espace de travail : un utilisateur existant y est ajouté directement comme membre, sinon une invitation est créée (et son e-mail d'inscription envoyé, sauf si Envoyer l'e-mail est désactivé)",
|
|
584
|
+
"fields": {
|
|
585
|
+
"tenantId": "Espace de travail où inviter ; par défaut l'espace par défaut",
|
|
586
|
+
"language": "Langue de l'e-mail d'invitation et du compte qu'il crée ; en par défaut",
|
|
587
|
+
"inviterName": "Nom de l'expéditeur indiqué dans l'e-mail d'invitation"
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
"fields": {
|
|
592
|
+
"actorId": "ID de l'auteur",
|
|
593
|
+
"actorName": "Nom de l'auteur",
|
|
594
|
+
"asTenantOwner": "Propriétaire de l'espace",
|
|
595
|
+
"at": "Date",
|
|
596
|
+
"deliveryId": "ID de livraison",
|
|
597
|
+
"description": "Description",
|
|
598
|
+
"email": "E-mail",
|
|
599
|
+
"error": "Erreur",
|
|
600
|
+
"firstname": "Prénom",
|
|
601
|
+
"html": "HTML",
|
|
602
|
+
"icon": "Icône",
|
|
603
|
+
"idempotencyKey": "Clé de rejeu",
|
|
604
|
+
"ids": "ID des enregistrements",
|
|
605
|
+
"inviteId": "ID de l'invitation",
|
|
606
|
+
"inviterName": "Nom de l'invitant",
|
|
607
|
+
"isTenantOwner": "Propriétaire de l'espace",
|
|
608
|
+
"kind": "Résultat",
|
|
609
|
+
"language": "Langue",
|
|
610
|
+
"lastname": "Nom",
|
|
611
|
+
"linkTo": "Lien",
|
|
612
|
+
"location": "Table",
|
|
613
|
+
"messageId": "ID du message",
|
|
614
|
+
"name": "Nom",
|
|
615
|
+
"ok": "Envoyée",
|
|
616
|
+
"params": "Paramètres",
|
|
617
|
+
"props": "Propriétés du modèle",
|
|
618
|
+
"roleIds": "Rôles",
|
|
619
|
+
"sendEmail": "Envoyer l'e-mail",
|
|
620
|
+
"subject": "Objet",
|
|
621
|
+
"success": "Succès",
|
|
622
|
+
"template": "Modèle",
|
|
623
|
+
"tenantId": "Espace de travail",
|
|
624
|
+
"title": "Titre",
|
|
625
|
+
"to": "Destinataire",
|
|
626
|
+
"tone": "Ton",
|
|
627
|
+
"userId": "Utilisateur",
|
|
628
|
+
"userIds": "Utilisateurs"
|
|
629
|
+
}
|
|
498
630
|
}
|
|
499
631
|
}
|
|
500
632
|
}
|
|
@@ -3,8 +3,9 @@ import DmsBlockActions from "#dms-ui/app/build/components/blocks/BlockActions.vu
|
|
|
3
3
|
import { useComposedText } from "#dms-core/app/composables/translation/useComposedText";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* Stacks the global layout banners under the dashboard header, on
|
|
7
|
-
*
|
|
6
|
+
* Stacks the global layout banners under the dashboard header, on the pages
|
|
7
|
+
* each banner's scope covers (the application's pages unless it says
|
|
8
|
+
* otherwise). Each banner carries its own live-region role, so a
|
|
8
9
|
* banner appearing after a navigation is announced as well. A text is a
|
|
9
10
|
* string or a composed text, written in the reader's language, followed by
|
|
10
11
|
* the banner's link buttons.
|