@antelopejs/dms 0.9.7 → 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 +114 -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 -45
- 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/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/frontend-vue/layers/dms-core/app/composables/period/periodRenderNow.ts +0 -42
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatDuration,
|
|
3
|
+
readableNumberFormat,
|
|
4
|
+
} from "#dms-core/app/utils/formatter";
|
|
1
5
|
import { defineAsyncComponent, h } from "vue";
|
|
2
6
|
import type { DataType } from "#dms-core/app/composables/data-types/useDataType";
|
|
3
7
|
import StatusPill from "../../../components/status-pill/StatusPill.vue";
|
|
4
8
|
import MonoCell from "../../components/table/MonoCell.vue";
|
|
5
|
-
import {
|
|
9
|
+
import { getAppComposedText } from "../../../../../dms-core/app/composables/translation/useComposedText";
|
|
6
10
|
import {
|
|
7
11
|
readRowField,
|
|
8
12
|
readRowTone,
|
|
@@ -11,6 +15,7 @@ import {
|
|
|
11
15
|
toneClass,
|
|
12
16
|
type Row,
|
|
13
17
|
} from "./cellHelpers";
|
|
18
|
+
import { getAppTranslation } from "../../../../../dms-core/app/composables/translation/useTranslation";
|
|
14
19
|
|
|
15
20
|
const Sparkline = defineAsyncComponent(
|
|
16
21
|
() => import("../../../components/chart/internal/Sparkline.vue"),
|
|
@@ -50,8 +55,8 @@ function statusPillTone(opts: StatusPillOptions, key: string, row: Row) {
|
|
|
50
55
|
* `subTone`, else the pill's.
|
|
51
56
|
*/
|
|
52
57
|
function renderStatusPill(value: unknown, options: unknown, row: Row) {
|
|
53
|
-
const { processI18n } =
|
|
54
|
-
const { processText } =
|
|
58
|
+
const { processI18n } = getAppTranslation();
|
|
59
|
+
const { processText } = getAppComposedText();
|
|
55
60
|
const opts = (options ?? {}) as StatusPillOptions;
|
|
56
61
|
const key = String(value);
|
|
57
62
|
const item = opts.typeOptions?.items?.find(
|
|
@@ -175,10 +180,6 @@ function renderSparkline(options: unknown, row: Row) {
|
|
|
175
180
|
}
|
|
176
181
|
|
|
177
182
|
const MS_PER_SECOND = 1000;
|
|
178
|
-
const SECONDS_PER_MINUTE = 60;
|
|
179
|
-
const MINUTES_PER_HOUR = 60;
|
|
180
|
-
const MS_PER_MINUTE = MS_PER_SECOND * SECONDS_PER_MINUTE;
|
|
181
|
-
const MS_PER_HOUR = MS_PER_MINUTE * MINUTES_PER_HOUR;
|
|
182
183
|
const DURATION_UNIT_MS: Record<string, number> = { ms: 1, s: MS_PER_SECOND };
|
|
183
184
|
|
|
184
185
|
// SI symbols read the same in every language; the figure follows the locale.
|
|
@@ -188,39 +189,16 @@ const withSymbol = (
|
|
|
188
189
|
symbol: string,
|
|
189
190
|
maximumFractionDigits = 0,
|
|
190
191
|
): string =>
|
|
191
|
-
`${
|
|
192
|
+
`${readableNumberFormat(locale, { maximumFractionDigits }).format(value)} ${symbol}`;
|
|
192
193
|
|
|
193
194
|
/** A duration always in milliseconds, its digits grouped: "2,149 ms". */
|
|
194
195
|
export function formatMilliseconds(ms: number, locale: string): string {
|
|
195
|
-
const figure =
|
|
196
|
+
const figure = readableNumberFormat(locale, {
|
|
196
197
|
maximumFractionDigits: 0,
|
|
197
|
-
// `true` groups a four-digit figure too, where a locale's default (es,
|
|
198
|
-
// pl) would leave "2149" against "12.149" further down the column.
|
|
199
|
-
useGrouping: true,
|
|
200
198
|
}).format(ms);
|
|
201
199
|
return `${figure} ms`;
|
|
202
200
|
}
|
|
203
201
|
|
|
204
|
-
/**
|
|
205
|
-
* A duration in its most readable unit: "910 ms", "1.8 s", "4 min 12 s",
|
|
206
|
-
* "2 h 5 min".
|
|
207
|
-
*/
|
|
208
|
-
export function formatDuration(ms: number, locale: string): string {
|
|
209
|
-
const absolute = Math.abs(ms);
|
|
210
|
-
if (absolute < MS_PER_SECOND) return withSymbol(locale, Math.round(ms), "ms");
|
|
211
|
-
if (absolute < MS_PER_MINUTE) {
|
|
212
|
-
return withSymbol(locale, ms / MS_PER_SECOND, "s", 1);
|
|
213
|
-
}
|
|
214
|
-
const [major, majorSymbol, minor, minorSymbol] =
|
|
215
|
-
absolute < MS_PER_HOUR
|
|
216
|
-
? ([MS_PER_MINUTE, "min", MS_PER_SECOND, "s"] as const)
|
|
217
|
-
: ([MS_PER_HOUR, "h", MS_PER_MINUTE, "min"] as const);
|
|
218
|
-
const whole = Math.trunc(ms / major);
|
|
219
|
-
const rest = Math.round((ms - whole * major) / minor);
|
|
220
|
-
const head = withSymbol(locale, whole, majorSymbol);
|
|
221
|
-
return rest === 0 ? head : `${head} ${withSymbol(locale, rest, minorSymbol)}`;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
202
|
const BYTE_SYMBOLS = ["B", "kB", "MB", "GB", "TB"];
|
|
225
203
|
const BYTE_STEP = 1000;
|
|
226
204
|
|
|
@@ -253,8 +231,12 @@ interface DurationOptions {
|
|
|
253
231
|
toneField?: string;
|
|
254
232
|
}
|
|
255
233
|
|
|
256
|
-
|
|
257
|
-
|
|
234
|
+
type DurationWriter = (ms: number, locale: string) => string;
|
|
235
|
+
|
|
236
|
+
// A cell is read at a glance: the readable duration is rounded there.
|
|
237
|
+
const DURATION_FORMATS: Record<string, DurationWriter> = {
|
|
238
|
+
readable: (ms, locale) =>
|
|
239
|
+
formatDuration(ms, locale, { precision: "rounded" }),
|
|
258
240
|
ms: formatMilliseconds,
|
|
259
241
|
};
|
|
260
242
|
|
|
@@ -270,7 +252,8 @@ function renderDuration(
|
|
|
270
252
|
) {
|
|
271
253
|
const opts = (options ?? {}) as DurationOptions;
|
|
272
254
|
const ms = numberOf(value) * (DURATION_UNIT_MS[opts.unit ?? "ms"] ?? 1);
|
|
273
|
-
const format =
|
|
255
|
+
const format =
|
|
256
|
+
DURATION_FORMATS[opts.format ?? "readable"] ?? DURATION_FORMATS.readable!;
|
|
274
257
|
return figure(
|
|
275
258
|
format(ms, locale),
|
|
276
259
|
rowToneTextClass(row, opts.toneField, FIGURE_TONE_CLASS),
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { DataTypeFormatter } from "#dms-core/app/composables/data-types/useDataType";
|
|
2
|
+
import {
|
|
3
|
+
getPluginI18n,
|
|
4
|
+
resolveI18nKey,
|
|
5
|
+
} from "../../../../../dms-core/app/composables/translation/useTranslation";
|
|
6
|
+
|
|
7
|
+
/** A formatter writing a number for a locale, with Intl's options. */
|
|
8
|
+
type NumberFormatter = (
|
|
9
|
+
value: unknown,
|
|
10
|
+
locale: string,
|
|
11
|
+
options?: Intl.NumberFormatOptions,
|
|
12
|
+
) => unknown;
|
|
13
|
+
|
|
14
|
+
/** The options of a numeric field a cell reads besides Intl's. */
|
|
15
|
+
interface NumberSuffixOptions {
|
|
16
|
+
/** Unit after the value ("days"): an i18n key with `$`, or a literal. */
|
|
17
|
+
suffix?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Keeps the unit on the line of its number when a cell wraps.
|
|
21
|
+
const UNIT_SEPARATOR = " ";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A numeric data type's formatter writing the field's unit after the value,
|
|
25
|
+
* as its form input does ("12.5 kWp"), wherever the type is drawn: table
|
|
26
|
+
* cells, expanded rows, cards, read-only fields. A value that is not a
|
|
27
|
+
* number is left as the formatter returns it.
|
|
28
|
+
*
|
|
29
|
+
* A formatter also runs where no component setup is active (a footer sum, a
|
|
30
|
+
* group header, an export), so the unit is translated through the
|
|
31
|
+
* application's composer, never through a composable.
|
|
32
|
+
*/
|
|
33
|
+
export function withNumberSuffix(format: NumberFormatter): DataTypeFormatter {
|
|
34
|
+
return (value, locale, options) => {
|
|
35
|
+
const formatted = format(
|
|
36
|
+
value,
|
|
37
|
+
locale,
|
|
38
|
+
options as Intl.NumberFormatOptions | undefined,
|
|
39
|
+
);
|
|
40
|
+
const suffix = (options as NumberSuffixOptions | undefined)?.suffix;
|
|
41
|
+
if (!suffix || typeof value !== "number" || typeof formatted !== "string") {
|
|
42
|
+
return formatted;
|
|
43
|
+
}
|
|
44
|
+
const unit = resolveI18nKey(getPluginI18n().translate, suffix);
|
|
45
|
+
return `${formatted}${UNIT_SEPARATOR}${unit}`;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -7,6 +7,7 @@ import UIcon from "@nuxt/ui/runtime/vue/components/Icon.vue";
|
|
|
7
7
|
import ULink from "@nuxt/ui/components/Link.vue";
|
|
8
8
|
import { buildRelationBadges } from "./relationBadges";
|
|
9
9
|
import { mapRelationBeforeState, sameRelationValue } from "./relationValue";
|
|
10
|
+
import { relationSelectSource } from "./relationRows";
|
|
10
11
|
import {
|
|
11
12
|
isSet,
|
|
12
13
|
readRowField,
|
|
@@ -17,8 +18,15 @@ import {
|
|
|
17
18
|
toneClass,
|
|
18
19
|
} from "./cellHelpers";
|
|
19
20
|
import { registerMetricCellTypes } from "./metricCells";
|
|
21
|
+
import {
|
|
22
|
+
dateFilterEditorValue,
|
|
23
|
+
numberFilterEditorValue,
|
|
24
|
+
} from "../table/utils/filterEditorValue";
|
|
25
|
+
import { formatDuration } from "#dms-core/app/utils/formatter";
|
|
26
|
+
import { withNumberSuffix } from "./numberSuffix";
|
|
20
27
|
import { registerTwoLineCellType } from "./twoLineCell";
|
|
21
|
-
import {
|
|
28
|
+
import { formatRecordLabel } from "../table-view/utils/formTexts";
|
|
29
|
+
import { getAppComposedText } from "../../../../../dms-core/app/composables/translation/useComposedText";
|
|
22
30
|
import StatusPill, {
|
|
23
31
|
type StatusPillVariant,
|
|
24
32
|
} from "../../../components/status-pill/StatusPill.vue";
|
|
@@ -29,6 +37,8 @@ import {
|
|
|
29
37
|
formatDayMonth,
|
|
30
38
|
formatRelativeDate,
|
|
31
39
|
} from "../../utils/relativeDate";
|
|
40
|
+
import { serverRenderNow } from "#dms-core/app/build/composables/renderNow";
|
|
41
|
+
import { getAppTranslation } from "../../../../../dms-core/app/composables/translation/useTranslation";
|
|
32
42
|
|
|
33
43
|
const FilePreview = defineAsyncComponent(
|
|
34
44
|
() => import("../../../components/table-view/FilePreview.vue"),
|
|
@@ -141,11 +151,57 @@ function createLinkRenderer(options: LinkRendererOptions) {
|
|
|
141
151
|
};
|
|
142
152
|
}
|
|
143
153
|
|
|
154
|
+
/** A `UrlType`'s options its read-only value reads. */
|
|
155
|
+
interface UrlOptions {
|
|
156
|
+
preview?: "avatar" | "image";
|
|
157
|
+
/**
|
|
158
|
+
* The label of the field shown, handed by the form's read-only display:
|
|
159
|
+
* the image's name when its row has none.
|
|
160
|
+
*/
|
|
161
|
+
fieldLabel?: string;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const URL_IMAGE_CLASS =
|
|
165
|
+
"border-default h-16 w-auto max-w-full rounded-md border object-cover";
|
|
166
|
+
|
|
167
|
+
// The fields that name a row, read in order for its image's text.
|
|
168
|
+
const ROW_NAME_FIELDS = ["name", "label", "title"];
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* What an image stands for to a reader who cannot see it: the name of the
|
|
172
|
+
* row it belongs to (a team member's photo is that member), or else the
|
|
173
|
+
* field's label.
|
|
174
|
+
*/
|
|
175
|
+
function imageAlt(row: Row, locale: string, options: UrlOptions): string {
|
|
176
|
+
for (const field of ROW_NAME_FIELDS) {
|
|
177
|
+
const name = formatRecordLabel(row?.[field], locale);
|
|
178
|
+
if (name) return name;
|
|
179
|
+
}
|
|
180
|
+
return options.fieldLabel ?? "";
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* A URL drawn as the image it points to, when its type asks for it
|
|
185
|
+
* (`preview`): a remote photo reads as a picture, not as its address.
|
|
186
|
+
*/
|
|
187
|
+
function renderUrl(value: unknown, locale: string, options: unknown, row: Row) {
|
|
188
|
+
const opts = (options ?? {}) as UrlOptions;
|
|
189
|
+
if (!opts.preview || !isString(value) || !value) return undefined;
|
|
190
|
+
const alt = imageAlt(row, locale, opts);
|
|
191
|
+
if (opts.preview === "avatar") return h(UAvatar, { src: value, alt });
|
|
192
|
+
return h("img", {
|
|
193
|
+
src: value,
|
|
194
|
+
alt,
|
|
195
|
+
loading: "lazy",
|
|
196
|
+
class: URL_IMAGE_CLASS,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
144
200
|
const convertToBoolean = (value: unknown): boolean =>
|
|
145
201
|
parse(String(value)) === true;
|
|
146
202
|
|
|
147
203
|
const getBooleanLabel = (value: unknown): string => {
|
|
148
|
-
const { processI18n } =
|
|
204
|
+
const { processI18n } = getAppTranslation();
|
|
149
205
|
return convertToBoolean(value)
|
|
150
206
|
? processI18n("$dms.table.filter.boolean.checked")
|
|
151
207
|
: processI18n("$dms.table.filter.boolean.unchecked");
|
|
@@ -160,7 +216,7 @@ function renderBoolean(value: unknown) {
|
|
|
160
216
|
}
|
|
161
217
|
|
|
162
218
|
function formatDateBetween(value: unknown, locale: string): string {
|
|
163
|
-
const { t } =
|
|
219
|
+
const { t } = getAppTranslation();
|
|
164
220
|
const [rawStart, rawEnd] = Array.isArray(value)
|
|
165
221
|
? value
|
|
166
222
|
: [
|
|
@@ -174,7 +230,7 @@ function formatDateBetween(value: unknown, locale: string): string {
|
|
|
174
230
|
|
|
175
231
|
// v2 .status pill, tinted with the configured online/offline color.
|
|
176
232
|
function renderStatus(value: unknown, options: unknown) {
|
|
177
|
-
const { processI18n } =
|
|
233
|
+
const { processI18n } = getAppTranslation();
|
|
178
234
|
const opts = options as StatusOptions | undefined;
|
|
179
235
|
const isOnline = Boolean(value);
|
|
180
236
|
const onlineLabel = opts?.onlineLabel || "$common.status.online";
|
|
@@ -194,7 +250,7 @@ function renderStatusPill(label: string, color: string) {
|
|
|
194
250
|
}
|
|
195
251
|
|
|
196
252
|
function renderSelectItem(item: SelectItem) {
|
|
197
|
-
const { processI18n } =
|
|
253
|
+
const { processI18n } = getAppTranslation();
|
|
198
254
|
const label = processI18n(item.label);
|
|
199
255
|
if (!item.icon && !item.iconColor && !item.textColor) return label;
|
|
200
256
|
|
|
@@ -253,7 +309,7 @@ function renderSelect(value: unknown, options?: unknown) {
|
|
|
253
309
|
function formatAddress(value: unknown): string {
|
|
254
310
|
if (!value || typeof value !== "object") return " ";
|
|
255
311
|
|
|
256
|
-
const { processI18n } =
|
|
312
|
+
const { processI18n } = getAppTranslation();
|
|
257
313
|
const addr = value as Record<string, string>;
|
|
258
314
|
const countryName = addr.countryCode
|
|
259
315
|
? processI18n(`$country.${addr.countryCode}`)
|
|
@@ -283,7 +339,7 @@ function renderRelationBadge(label: string, title?: string) {
|
|
|
283
339
|
}
|
|
284
340
|
|
|
285
341
|
function renderRelationBadges(values: unknown[], labelKey: string) {
|
|
286
|
-
const { processI18n } =
|
|
342
|
+
const { processI18n } = getAppTranslation();
|
|
287
343
|
const { visible, hidden } = buildRelationBadges(values, labelKey);
|
|
288
344
|
const badges = visible.map((label) =>
|
|
289
345
|
renderRelationBadge(processI18n(label)),
|
|
@@ -354,7 +410,7 @@ function renderImage(value: unknown, options: unknown) {
|
|
|
354
410
|
}
|
|
355
411
|
|
|
356
412
|
function renderFile(value: unknown, options: unknown) {
|
|
357
|
-
const { t } =
|
|
413
|
+
const { t } = getAppTranslation();
|
|
358
414
|
const opts = options as FileOptions | undefined;
|
|
359
415
|
|
|
360
416
|
if (opts?.multiple && Array.isArray(value)) {
|
|
@@ -408,8 +464,8 @@ const matchesBadge = (badge: IdentityBadgeOption, value: unknown): boolean =>
|
|
|
408
464
|
* `emptyIcon` stand for a row without a value.
|
|
409
465
|
*/
|
|
410
466
|
function renderIdentity(value: unknown, options: unknown, row: Row) {
|
|
411
|
-
const { processI18n } =
|
|
412
|
-
const { processText } =
|
|
467
|
+
const { processI18n } = getAppTranslation();
|
|
468
|
+
const { processText } = getAppComposedText();
|
|
413
469
|
const opts = (options ?? {}) as IdentityOptions;
|
|
414
470
|
const badges = (opts.badges ?? [])
|
|
415
471
|
.filter((badge) => matchesBadge(badge, readRowField(row, badge.field)))
|
|
@@ -526,7 +582,7 @@ function renderPill(pill: PillItem) {
|
|
|
526
582
|
* a relation could not resolve (a deleted row) is skipped.
|
|
527
583
|
*/
|
|
528
584
|
function renderPills(value: unknown, options: unknown, row: Row) {
|
|
529
|
-
const { processI18n } =
|
|
585
|
+
const { processI18n } = getAppTranslation();
|
|
530
586
|
const opts = (options ?? {}) as PillsOptions;
|
|
531
587
|
if (opts.exclusive && isSet(readRowField(row, opts.exclusive.field))) {
|
|
532
588
|
return h("span", { class: [PILL_CLASS, PILL_FILLED_CLASS] }, [
|
|
@@ -605,11 +661,14 @@ function renderRelativeDate(
|
|
|
605
661
|
options: unknown,
|
|
606
662
|
row: Row,
|
|
607
663
|
) {
|
|
608
|
-
const { processI18n } =
|
|
664
|
+
const { processI18n } = getAppTranslation();
|
|
609
665
|
const opts = (options ?? {}) as RelativeDateOptions;
|
|
610
666
|
const date = new Date(value as string);
|
|
611
667
|
if (Number.isNaN(date.getTime())) return String(value);
|
|
612
|
-
|
|
668
|
+
// Measured from the server render's instant while hydrating it: "3 min ago"
|
|
669
|
+
// written at 12:00:59 stays so in a browser hydrating at 12:01:01.
|
|
670
|
+
const now = serverRenderNow() ?? Date.now();
|
|
671
|
+
const deltaMs = date.getTime() - now;
|
|
613
672
|
const isPast = deltaMs < 0;
|
|
614
673
|
const title = formatDate(date, locale, RELATIVE_TITLE_FORMAT) ?? undefined;
|
|
615
674
|
|
|
@@ -624,8 +683,8 @@ function renderRelativeDate(
|
|
|
624
683
|
const style = (isPast ? opts.pastStyle : undefined) ?? opts.style;
|
|
625
684
|
let text =
|
|
626
685
|
style === "day"
|
|
627
|
-
? formatDayMonth(date, locale)
|
|
628
|
-
: formatRelativeDate(date, locale);
|
|
686
|
+
? formatDayMonth(date, locale, now)
|
|
687
|
+
: formatRelativeDate(date, locale, now);
|
|
629
688
|
const isSoon = !isPast && !!opts.soonWithinMs && deltaMs < opts.soonWithinMs;
|
|
630
689
|
const tone = isPast
|
|
631
690
|
? (opts.pastTone ?? opts.tone)
|
|
@@ -644,7 +703,7 @@ function renderRelativeDate(
|
|
|
644
703
|
}
|
|
645
704
|
|
|
646
705
|
function renderMissingDate(options: unknown) {
|
|
647
|
-
const { processI18n } =
|
|
706
|
+
const { processI18n } = getAppTranslation();
|
|
648
707
|
const opts = (options ?? {}) as RelativeDateOptions;
|
|
649
708
|
if (!opts.emptyLabel) return "-";
|
|
650
709
|
return h(
|
|
@@ -670,7 +729,7 @@ interface IndicatorOptions {
|
|
|
670
729
|
* on for a set flag or a non-empty list.
|
|
671
730
|
*/
|
|
672
731
|
function renderIndicator(value: unknown, options: unknown) {
|
|
673
|
-
const { processI18n } =
|
|
732
|
+
const { processI18n } = getAppTranslation();
|
|
674
733
|
const opts = (options ?? {}) as IndicatorOptions;
|
|
675
734
|
const isOn = isSet(value);
|
|
676
735
|
const icon = isOn ? opts.onIcon : opts.offIcon;
|
|
@@ -768,7 +827,8 @@ const registerPrimitiveTypes = (
|
|
|
768
827
|
) => {
|
|
769
828
|
registerDataType({
|
|
770
829
|
id: "number",
|
|
771
|
-
formatter: { default: formatNumber
|
|
830
|
+
formatter: { default: withNumberSuffix(formatNumber) },
|
|
831
|
+
filterEditorValue: numberFilterEditorValue,
|
|
772
832
|
});
|
|
773
833
|
registerDataType({
|
|
774
834
|
id: "string",
|
|
@@ -776,15 +836,24 @@ const registerPrimitiveTypes = (
|
|
|
776
836
|
});
|
|
777
837
|
registerDataType({
|
|
778
838
|
id: "price",
|
|
779
|
-
formatter: { default: formatPrice
|
|
839
|
+
formatter: { default: withNumberSuffix(formatPrice) },
|
|
840
|
+
filterEditorValue: numberFilterEditorValue,
|
|
780
841
|
});
|
|
781
842
|
registerDataType({
|
|
782
843
|
id: "percentage",
|
|
783
|
-
formatter: { default: formatPercentage
|
|
844
|
+
formatter: { default: withNumberSuffix(formatPercentage) },
|
|
845
|
+
filterEditorValue: numberFilterEditorValue,
|
|
784
846
|
});
|
|
785
847
|
registerDataType({
|
|
786
848
|
id: "string_time",
|
|
787
|
-
|
|
849
|
+
// Written as the field writes it ("7 h 30 min"), in the reader's locale,
|
|
850
|
+
// rounded as every duration cell is: the field keeps the exact value.
|
|
851
|
+
formatter: {
|
|
852
|
+
default: (value: unknown, locale: string) =>
|
|
853
|
+
isNumber(value)
|
|
854
|
+
? formatDuration(Number(value), locale, { precision: "rounded" })
|
|
855
|
+
: value,
|
|
856
|
+
},
|
|
788
857
|
});
|
|
789
858
|
};
|
|
790
859
|
|
|
@@ -801,17 +870,18 @@ const registerDateType = (registerDataType: (dataType: DataType) => void) => {
|
|
|
801
870
|
id: "date",
|
|
802
871
|
formatter: {
|
|
803
872
|
default: (value: unknown, locale: string) => {
|
|
804
|
-
const { t } =
|
|
873
|
+
const { t } = getAppTranslation();
|
|
805
874
|
return formatDate(value, locale) ?? t("dms.date.undefined");
|
|
806
875
|
},
|
|
807
876
|
cell: (value: unknown, locale: string) => {
|
|
808
|
-
const { t } =
|
|
877
|
+
const { t } = getAppTranslation();
|
|
809
878
|
return (
|
|
810
879
|
formatDate(value, locale, CELL_DATE_FORMAT) ?? t("dms.date.undefined")
|
|
811
880
|
);
|
|
812
881
|
},
|
|
813
882
|
is_between: formatDateBetween,
|
|
814
883
|
},
|
|
884
|
+
filterEditorValue: dateFilterEditorValue,
|
|
815
885
|
});
|
|
816
886
|
};
|
|
817
887
|
|
|
@@ -875,9 +945,13 @@ const registerLinkTypes = (registerDataType: (dataType: DataType) => void) => {
|
|
|
875
945
|
id: "email",
|
|
876
946
|
formatter: { default: createLinkRenderer({ hrefPrefix: "mailto:" }) },
|
|
877
947
|
});
|
|
948
|
+
const renderLink = createLinkRenderer({ target: "_blank" });
|
|
878
949
|
registerDataType({
|
|
879
950
|
id: "url",
|
|
880
|
-
formatter: {
|
|
951
|
+
formatter: {
|
|
952
|
+
default: (value: unknown, locale: string, options: unknown, row?: Row) =>
|
|
953
|
+
renderUrl(value, locale, options, row) ?? renderLink(value, locale),
|
|
954
|
+
},
|
|
881
955
|
});
|
|
882
956
|
};
|
|
883
957
|
|
|
@@ -892,6 +966,7 @@ const registerRelationType = (
|
|
|
892
966
|
},
|
|
893
967
|
beforeStateMapper: mapRelationBeforeState,
|
|
894
968
|
isSameValue: sameRelationValue,
|
|
969
|
+
selectSource: relationSelectSource,
|
|
895
970
|
});
|
|
896
971
|
};
|
|
897
972
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { h } from "vue";
|
|
2
2
|
import type { DataType } from "#dms-core/app/composables/data-types/useDataType";
|
|
3
|
+
import { getAppTranslation } from "../../../../../dms-core/app/composables/translation/useTranslation";
|
|
3
4
|
|
|
4
5
|
// How the field types made of several values read in a table cell or a
|
|
5
6
|
// read-only form: a count, a masked secret, the first line of the code,
|
|
@@ -19,7 +20,7 @@ const countOf = (value: unknown): number => {
|
|
|
19
20
|
|
|
20
21
|
function renderCount(key: string) {
|
|
21
22
|
return (value: unknown) => {
|
|
22
|
-
const { t } =
|
|
23
|
+
const { t } = getAppTranslation();
|
|
23
24
|
const count = countOf(value);
|
|
24
25
|
return t(key, { count }, count);
|
|
25
26
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { isEmptyFormValue, sameFormValue } from "../unsaved-changes/formValue";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A relation picker narrowed by another field of its form: the related
|
|
5
|
+
* table's `field` must equal the form's value of `from`.
|
|
6
|
+
*/
|
|
7
|
+
export interface RelationFilterBy {
|
|
8
|
+
field: string;
|
|
9
|
+
from: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/** The compare mode the search route matches the related `field` with. */
|
|
13
|
+
const FILTER_MODE = "is";
|
|
14
|
+
|
|
15
|
+
type FilterValue = string | number | boolean;
|
|
16
|
+
|
|
17
|
+
function isFilterValue(value: unknown): value is FilterValue {
|
|
18
|
+
if (typeof value === "string") return value !== "";
|
|
19
|
+
return typeof value === "number" || typeof value === "boolean";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The query narrowing the picker's search: the related table's filter
|
|
24
|
+
* syntax (`filter_<field>=is:<value>`), the one its funnel sends. Nothing
|
|
25
|
+
* while the source field holds no single value: every row is offered.
|
|
26
|
+
*/
|
|
27
|
+
export function relationFilterParams(
|
|
28
|
+
filterBy: RelationFilterBy | undefined,
|
|
29
|
+
sourceValue: unknown,
|
|
30
|
+
): Record<string, string> {
|
|
31
|
+
if (!filterBy || !isFilterValue(sourceValue)) return {};
|
|
32
|
+
return { [`filter_${filterBy.field}`]: `${FILTER_MODE}:${sourceValue}` };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** The source field and the pick, before and after a change of either. */
|
|
36
|
+
export interface RelationPickChange {
|
|
37
|
+
source: unknown;
|
|
38
|
+
pick: unknown;
|
|
39
|
+
previousSource: unknown;
|
|
40
|
+
previousPick: unknown;
|
|
41
|
+
/** The source value the current pick was made (or loaded) with. */
|
|
42
|
+
pickSource: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Whether to clear the pick, and the source value the pick now goes with. */
|
|
46
|
+
export interface RelationPickOutcome {
|
|
47
|
+
shouldClear: boolean;
|
|
48
|
+
pickSource: unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** Whether a picker holds a value. */
|
|
52
|
+
function hasRelationPick(value: unknown): boolean {
|
|
53
|
+
return !isEmptyFormValue(value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Whether a change of the source field voids the pick: made for another of
|
|
58
|
+
* its values. A pick changing at the same time (a record loading both
|
|
59
|
+
* values) or after goes with the current source; going back to the value the
|
|
60
|
+
* pick was made with keeps it.
|
|
61
|
+
*/
|
|
62
|
+
export function resolveRelationPick(
|
|
63
|
+
change: RelationPickChange,
|
|
64
|
+
): RelationPickOutcome {
|
|
65
|
+
const isPickChange = !sameFormValue(change.pick, change.previousPick);
|
|
66
|
+
if (isPickChange || !hasRelationPick(change.pick)) {
|
|
67
|
+
return { shouldClear: false, pickSource: change.source };
|
|
68
|
+
}
|
|
69
|
+
const isSourceChange = !sameFormValue(change.source, change.previousSource);
|
|
70
|
+
const isPickSource = sameFormValue(change.source, change.pickSource);
|
|
71
|
+
return {
|
|
72
|
+
shouldClear: isSourceChange && !isPickSource,
|
|
73
|
+
pickSource: change.pickSource,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { DataTypeSelectSource } from "#dms-core/app/composables/data-types/useDataType";
|
|
2
|
+
import { pageRequestUrl } from "../page/pageUrlValues";
|
|
3
|
+
import { relationIdsQuery } from "./relationValue";
|
|
4
|
+
|
|
5
|
+
/** The keys a `select` route's row carries its label and value under by default. */
|
|
6
|
+
export const RELATION_LABEL_KEY = "label";
|
|
7
|
+
export const RELATION_VALUE_KEY = "value";
|
|
8
|
+
|
|
9
|
+
type RelationRow = Record<string, unknown>;
|
|
10
|
+
|
|
11
|
+
interface RelationSelectResponse {
|
|
12
|
+
results?: RelationRow[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface RelationSourceOptions {
|
|
16
|
+
searchUrl?: unknown;
|
|
17
|
+
keyMapping?: DataTypeSelectSource["keyMapping"];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The `select` route a relation's control reads its rows from, and their key
|
|
22
|
+
* mapping: the relation data type's {@link DataTypeSelectSource}.
|
|
23
|
+
*/
|
|
24
|
+
export function relationSelectSource(
|
|
25
|
+
options: unknown,
|
|
26
|
+
): DataTypeSelectSource | undefined {
|
|
27
|
+
const opts = options as RelationSourceOptions | undefined;
|
|
28
|
+
if (typeof opts?.searchUrl !== "string") return undefined;
|
|
29
|
+
return { searchUrl: opts.searchUrl, keyMapping: opts.keyMapping };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** The value a row of the source is picked by. */
|
|
33
|
+
export function relationRowValue(
|
|
34
|
+
source: DataTypeSelectSource,
|
|
35
|
+
row: RelationRow,
|
|
36
|
+
): unknown {
|
|
37
|
+
return row[source.keyMapping?.value || RELATION_VALUE_KEY];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The label a row of the source is named by. */
|
|
41
|
+
export function relationRowLabel(
|
|
42
|
+
source: DataTypeSelectSource,
|
|
43
|
+
row: RelationRow,
|
|
44
|
+
): unknown {
|
|
45
|
+
return row[source.keyMapping?.label || RELATION_LABEL_KEY];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Reads the rows of a relation's ids from its `select` route, narrowed with
|
|
50
|
+
* `?ids=` to those rows alone (matched on the mapped value key), whatever the
|
|
51
|
+
* route's page size. The one way the picker, the filter chips and the
|
|
52
|
+
* read-only lists name the ids they hold. A failed read answers no rows: the
|
|
53
|
+
* ids then show as they are.
|
|
54
|
+
*/
|
|
55
|
+
export function useRelationRows() {
|
|
56
|
+
const { $authFetch } = useAuthFetch();
|
|
57
|
+
|
|
58
|
+
async function readRelationRows(
|
|
59
|
+
source: DataTypeSelectSource,
|
|
60
|
+
ids: string[],
|
|
61
|
+
): Promise<RelationRow[]> {
|
|
62
|
+
const url = pageRequestUrl(source.searchUrl);
|
|
63
|
+
if (!url || ids.length === 0) return [];
|
|
64
|
+
const response = await $authFetch<RelationSelectResponse>(url, {
|
|
65
|
+
params: relationIdsQuery(ids, source.keyMapping),
|
|
66
|
+
}).catch(() => undefined);
|
|
67
|
+
return response?.results ?? [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return { readRelationRows };
|
|
71
|
+
}
|
|
@@ -64,3 +64,42 @@ export function sameRelationValue(
|
|
|
64
64
|
};
|
|
65
65
|
return sameFormValue(comparable(left), comparable(right));
|
|
66
66
|
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* What a relation field asks its target's `select` route for to label the
|
|
70
|
+
* ids it holds: those rows alone, matched on the field's value key (the
|
|
71
|
+
* route falls back to the row id when none is mapped).
|
|
72
|
+
*/
|
|
73
|
+
export interface RelationIdsQuery {
|
|
74
|
+
ids: string[];
|
|
75
|
+
idKey?: string;
|
|
76
|
+
limit: number;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const isIdValue = (value: unknown): value is string | number =>
|
|
80
|
+
(typeof value === "string" && value !== "") || typeof value === "number";
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The ids a relation value holds that no known row labels yet — a form whose
|
|
84
|
+
* read answers the id (`"u-5"`) rather than the joined row. A joined row
|
|
85
|
+
* labels itself, so only plain ids are returned, each once.
|
|
86
|
+
*/
|
|
87
|
+
export function unlabeledRelationIds(
|
|
88
|
+
value: unknown,
|
|
89
|
+
labeledIds: ReadonlySet<string>,
|
|
90
|
+
): string[] {
|
|
91
|
+
const ids = [value].flat().filter(isIdValue).map(String);
|
|
92
|
+
return [...new Set(ids)].filter((id) => !labeledIds.has(id));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** The `select` query answering the rows of `ids`. */
|
|
96
|
+
export function relationIdsQuery(
|
|
97
|
+
ids: string[],
|
|
98
|
+
keyMapping?: RelationKeyMapping,
|
|
99
|
+
): RelationIdsQuery {
|
|
100
|
+
return {
|
|
101
|
+
ids,
|
|
102
|
+
...(keyMapping?.value ? { idKey: keyMapping.value } : {}),
|
|
103
|
+
limit: ids.length,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { h, type VNodeChild } from "vue";
|
|
2
2
|
import type { DataType } from "#dms-core/app/composables/data-types/useDataType";
|
|
3
|
-
import {
|
|
3
|
+
import { getAppComposedText } from "../../../../../dms-core/app/composables/translation/useComposedText";
|
|
4
4
|
import {
|
|
5
5
|
type ComposableText,
|
|
6
6
|
isComposedText,
|
|
@@ -53,7 +53,7 @@ function readPrimary(
|
|
|
53
53
|
opts: TwoLineOptions,
|
|
54
54
|
row: Row,
|
|
55
55
|
): VNodeChild | undefined {
|
|
56
|
-
const { processText } =
|
|
56
|
+
const { processText } = getAppComposedText();
|
|
57
57
|
if (opts.primaryField) {
|
|
58
58
|
const text = processText(
|
|
59
59
|
readRowField(row, opts.primaryField) as ComposableText,
|
|
@@ -76,7 +76,7 @@ function renderTwoLine(
|
|
|
76
76
|
options: unknown,
|
|
77
77
|
row: Row,
|
|
78
78
|
) {
|
|
79
|
-
const { processText } =
|
|
79
|
+
const { processText } = getAppComposedText();
|
|
80
80
|
const opts = (options ?? {}) as TwoLineOptions;
|
|
81
81
|
const primary = readPrimary(value, locale, opts, row);
|
|
82
82
|
const sub = readSubline(readRowField(row, opts.subField), {
|