@ngbplatform/ui 1.3.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/LICENSE +201 -0
- package/README.md +44 -0
- package/package.json +61 -0
- package/public/favicon.svg +6 -0
- package/public/silent-check-sso.html +8 -0
- package/src/assets/ngb_logo.svg +17 -0
- package/src/assets/ngb_logo_color.svg +17 -0
- package/src/index.ts +1023 -0
- package/src/ngb/README.md +27 -0
- package/src/ngb/accounting/NgbAccountingPeriodClosingPage.vue +1157 -0
- package/src/ngb/accounting/NgbChartOfAccountEditor.vue +590 -0
- package/src/ngb/accounting/NgbChartOfAccountsPage.vue +420 -0
- package/src/ngb/accounting/NgbGeneralJournalEntryEditPage.vue +796 -0
- package/src/ngb/accounting/NgbGeneralJournalEntryLinesEditor.vue +454 -0
- package/src/ngb/accounting/NgbGeneralJournalEntryListPage.vue +186 -0
- package/src/ngb/accounting/api.ts +79 -0
- package/src/ngb/accounting/generalJournalEntry.ts +127 -0
- package/src/ngb/accounting/generalJournalEntryApi.ts +112 -0
- package/src/ngb/accounting/generalJournalEntryTypes.ts +155 -0
- package/src/ngb/accounting/navigation.ts +83 -0
- package/src/ngb/accounting/periodClosing.ts +75 -0
- package/src/ngb/accounting/periodClosingApi.ts +60 -0
- package/src/ngb/accounting/periodClosingTypes.ts +73 -0
- package/src/ngb/accounting/types.ts +57 -0
- package/src/ngb/api/audit.ts +23 -0
- package/src/ngb/api/catalogs.ts +50 -0
- package/src/ngb/api/contracts.ts +285 -0
- package/src/ngb/api/documents.ts +170 -0
- package/src/ngb/api/http.ts +446 -0
- package/src/ngb/api/lookups.ts +14 -0
- package/src/ngb/api/types.ts +6 -0
- package/src/ngb/auth/index.ts +13 -0
- package/src/ngb/auth/keycloak.ts +374 -0
- package/src/ngb/auth/router.ts +35 -0
- package/src/ngb/auth/types.ts +12 -0
- package/src/ngb/auth/useAuthStore.ts +209 -0
- package/src/ngb/command-palette/NgbCommandPaletteDialog.vue +342 -0
- package/src/ngb/command-palette/NgbCommandPaletteEmptyState.vue +55 -0
- package/src/ngb/command-palette/NgbCommandPaletteFooterHints.vue +29 -0
- package/src/ngb/command-palette/api.ts +10 -0
- package/src/ngb/command-palette/config.ts +16 -0
- package/src/ngb/command-palette/presentation.ts +85 -0
- package/src/ngb/command-palette/search.ts +130 -0
- package/src/ngb/command-palette/staticItems.ts +243 -0
- package/src/ngb/command-palette/storage.ts +45 -0
- package/src/ngb/command-palette/store.ts +716 -0
- package/src/ngb/command-palette/types.ts +120 -0
- package/src/ngb/command-palette/useCommandPaletteHotkeys.ts +27 -0
- package/src/ngb/command-palette/useCommandPalettePageContext.ts +18 -0
- package/src/ngb/components/NgbConfirmDialog.vue +63 -0
- package/src/ngb/components/NgbDialog.vue +44 -0
- package/src/ngb/components/NgbDrawer.vue +156 -0
- package/src/ngb/components/NgbHeaderActionCluster.vue +140 -0
- package/src/ngb/components/NgbModalShell.vue +99 -0
- package/src/ngb/components/NgbToolbar.vue +14 -0
- package/src/ngb/components/forms/NgbFormLayout.vue +13 -0
- package/src/ngb/components/forms/NgbFormRow.vue +21 -0
- package/src/ngb/components/forms/NgbFormSection.vue +16 -0
- package/src/ngb/components/forms/NgbValidationSummary.vue +18 -0
- package/src/ngb/components/navigation/NgbNavigationTree.vue +68 -0
- package/src/ngb/components/navigation/NgbTreeNode.vue +94 -0
- package/src/ngb/components/register/NgbColumnChooser.vue +101 -0
- package/src/ngb/components/register/NgbRegisterGrid.vue +473 -0
- package/src/ngb/components/register/registerTypes.ts +51 -0
- package/src/ngb/components/register/useRegisterColumnResize.ts +99 -0
- package/src/ngb/components/register/useRegisterColumnState.ts +220 -0
- package/src/ngb/components/register/useRegisterRows.ts +209 -0
- package/src/ngb/components/register/useRegisterViewport.ts +56 -0
- package/src/ngb/editor/NgbDocumentEffectsPage.vue +512 -0
- package/src/ngb/editor/NgbDocumentFlowPage.vue +409 -0
- package/src/ngb/editor/NgbDocumentPrintPage.vue +712 -0
- package/src/ngb/editor/NgbEditorDiscardDialog.vue +40 -0
- package/src/ngb/editor/NgbEntityAuditSidebar.vue +288 -0
- package/src/ngb/editor/NgbEntityEditor.vue +250 -0
- package/src/ngb/editor/NgbEntityEditorDrawerActions.vue +88 -0
- package/src/ngb/editor/NgbEntityEditorHeader.vue +114 -0
- package/src/ngb/editor/catalogNavigation.ts +13 -0
- package/src/ngb/editor/config.ts +252 -0
- package/src/ngb/editor/documentCopyDraft.ts +245 -0
- package/src/ngb/editor/documentEffects.ts +43 -0
- package/src/ngb/editor/documentEffectsDateFormatting.ts +18 -0
- package/src/ngb/editor/documentNavigation.ts +115 -0
- package/src/ngb/editor/documentStatus.ts +45 -0
- package/src/ngb/editor/entityEditorErrors.ts +162 -0
- package/src/ngb/editor/entityEditorPersistence.ts +241 -0
- package/src/ngb/editor/extensions.ts +40 -0
- package/src/ngb/editor/types.ts +295 -0
- package/src/ngb/editor/useConfiguredEntityEditorDocumentActions.ts +183 -0
- package/src/ngb/editor/useDocumentEditorDrawerState.ts +152 -0
- package/src/ngb/editor/useEditorDrawerState.ts +88 -0
- package/src/ngb/editor/useEntityEditorBusinessContext.ts +97 -0
- package/src/ngb/editor/useEntityEditorCapabilities.ts +190 -0
- package/src/ngb/editor/useEntityEditorCommandPalette.ts +154 -0
- package/src/ngb/editor/useEntityEditorCommitHandlers.ts +102 -0
- package/src/ngb/editor/useEntityEditorHeaderActions.ts +253 -0
- package/src/ngb/editor/useEntityEditorLeaveGuard.ts +66 -0
- package/src/ngb/editor/useEntityEditorNavigationActions.ts +235 -0
- package/src/ngb/editor/useEntityEditorOutputs.ts +59 -0
- package/src/ngb/editor/useEntityEditorPageActions.ts +57 -0
- package/src/ngb/editor/useRouteQueryEditorDrawer.ts +173 -0
- package/src/ngb/env/runtimeConfig.ts +25 -0
- package/src/ngb/lookup/config.ts +42 -0
- package/src/ngb/lookup/defaultConfig.ts +136 -0
- package/src/ngb/lookup/navigation.ts +76 -0
- package/src/ngb/lookup/prefetch.ts +40 -0
- package/src/ngb/lookup/store.ts +261 -0
- package/src/ngb/metadata/NgbDocumentListFiltersDrawer.vue +78 -0
- package/src/ngb/metadata/NgbDocumentPeriodFilter.vue +53 -0
- package/src/ngb/metadata/NgbEntityForm.vue +84 -0
- package/src/ngb/metadata/NgbEntityFormFieldsBlock.vue +110 -0
- package/src/ngb/metadata/NgbEntityListPageHeader.vue +80 -0
- package/src/ngb/metadata/NgbFilterFieldControl.vue +104 -0
- package/src/ngb/metadata/NgbMetadataCatalogEditPage.vue +42 -0
- package/src/ngb/metadata/NgbMetadataCatalogListPage.vue +269 -0
- package/src/ngb/metadata/NgbMetadataDocumentEditPage.vue +68 -0
- package/src/ngb/metadata/NgbMetadataDocumentListPage.vue +353 -0
- package/src/ngb/metadata/NgbMetadataFieldRenderer.vue +124 -0
- package/src/ngb/metadata/NgbMetadataLookupControl.vue +92 -0
- package/src/ngb/metadata/NgbRecycleBinFilter.vue +53 -0
- package/src/ngb/metadata/NgbRegisterPageLayout.vue +143 -0
- package/src/ngb/metadata/config.ts +28 -0
- package/src/ngb/metadata/dataTypes.ts +27 -0
- package/src/ngb/metadata/entityForm.ts +114 -0
- package/src/ngb/metadata/entityModel.ts +34 -0
- package/src/ngb/metadata/entityValueFormatting.ts +83 -0
- package/src/ngb/metadata/fieldRendererState.ts +84 -0
- package/src/ngb/metadata/filtering.ts +153 -0
- package/src/ngb/metadata/lookup.ts +25 -0
- package/src/ngb/metadata/monthPagedListQuery.ts +108 -0
- package/src/ngb/metadata/normalization.ts +100 -0
- package/src/ngb/metadata/referenceHydration.ts +99 -0
- package/src/ngb/metadata/register.ts +135 -0
- package/src/ngb/metadata/routePages.ts +86 -0
- package/src/ngb/metadata/store.ts +35 -0
- package/src/ngb/metadata/types.ts +276 -0
- package/src/ngb/metadata/useMetadataListFilters.ts +306 -0
- package/src/ngb/metadata/useMetadataRegisterPageData.ts +246 -0
- package/src/ngb/metadata/useValidationFocus.ts +49 -0
- package/src/ngb/primitives/NgbBadge.vue +31 -0
- package/src/ngb/primitives/NgbButton.vue +53 -0
- package/src/ngb/primitives/NgbCheckbox.vue +33 -0
- package/src/ngb/primitives/NgbDatePicker.vue +141 -0
- package/src/ngb/primitives/NgbIcon.vue +545 -0
- package/src/ngb/primitives/NgbInput.vue +57 -0
- package/src/ngb/primitives/NgbLookup.vue +264 -0
- package/src/ngb/primitives/NgbMonthPicker.vue +132 -0
- package/src/ngb/primitives/NgbMultiSelect.vue +179 -0
- package/src/ngb/primitives/NgbPeriodPicker.vue +125 -0
- package/src/ngb/primitives/NgbPickerNavButton.vue +31 -0
- package/src/ngb/primitives/NgbPickerPopover.vue +79 -0
- package/src/ngb/primitives/NgbRadioGroup.vue +53 -0
- package/src/ngb/primitives/NgbSelect.vue +108 -0
- package/src/ngb/primitives/NgbStatusIcon.vue +63 -0
- package/src/ngb/primitives/NgbSwitch.vue +42 -0
- package/src/ngb/primitives/NgbTabs.vue +116 -0
- package/src/ngb/primitives/NgbToastHost.vue +49 -0
- package/src/ngb/primitives/NgbTooltip.vue +27 -0
- package/src/ngb/primitives/iconNames.ts +83 -0
- package/src/ngb/primitives/toast.ts +66 -0
- package/src/ngb/primitives/useAsyncComboboxQuery.ts +85 -0
- package/src/ngb/primitives/useFloatingDropdownPosition.ts +129 -0
- package/src/ngb/reporting/NgbReportComposerCollectionSection.vue +106 -0
- package/src/ngb/reporting/NgbReportComposerPanel.vue +1187 -0
- package/src/ngb/reporting/NgbReportDateRangeFilter.vue +54 -0
- package/src/ngb/reporting/NgbReportPage.vue +1124 -0
- package/src/ngb/reporting/NgbReportSheet.vue +467 -0
- package/src/ngb/reporting/api.ts +35 -0
- package/src/ngb/reporting/composer.ts +904 -0
- package/src/ngb/reporting/config.ts +120 -0
- package/src/ngb/reporting/defaultConfig.ts +15 -0
- package/src/ngb/reporting/lookupFilters.ts +43 -0
- package/src/ngb/reporting/navigation.ts +181 -0
- package/src/ngb/reporting/pageHelpers.ts +73 -0
- package/src/ngb/reporting/pageSession.ts +92 -0
- package/src/ngb/reporting/paging.ts +66 -0
- package/src/ngb/reporting/types.ts +333 -0
- package/src/ngb/router/backNavigation.ts +122 -0
- package/src/ngb/router/queryParams.ts +129 -0
- package/src/ngb/router/queryState.ts +121 -0
- package/src/ngb/router/routeAliases.ts +66 -0
- package/src/ngb/router/routeParams.ts +15 -0
- package/src/ngb/router/shareLink.ts +39 -0
- package/src/ngb/security/NgbAccessAuditPanel.vue +32 -0
- package/src/ngb/security/NgbAccessDeniedState.vue +27 -0
- package/src/ngb/security/NgbEffectiveAccessPanel.vue +60 -0
- package/src/ngb/security/NgbPermissionMatrix.vue +160 -0
- package/src/ngb/security/NgbRoleEditorPage.vue +319 -0
- package/src/ngb/security/NgbRolesPage.vue +125 -0
- package/src/ngb/security/NgbUserEditorPage.vue +615 -0
- package/src/ngb/security/NgbUsersPage.vue +125 -0
- package/src/ngb/security/api.ts +91 -0
- package/src/ngb/security/audit.ts +21 -0
- package/src/ngb/security/permissions.ts +65 -0
- package/src/ngb/security/types.ts +157 -0
- package/src/ngb/security/useAccessStore.ts +69 -0
- package/src/ngb/site/NgbDashboardAsOfToolbar.vue +100 -0
- package/src/ngb/site/NgbDashboardStatusBanner.vue +91 -0
- package/src/ngb/site/NgbLogo.vue +44 -0
- package/src/ngb/site/NgbPageHeader.vue +49 -0
- package/src/ngb/site/NgbSiteShell.vue +286 -0
- package/src/ngb/site/NgbSiteSidebar.vue +270 -0
- package/src/ngb/site/NgbTopBar.vue +425 -0
- package/src/ngb/site/NgbTrendChart.vue +224 -0
- package/src/ngb/site/dashboardData.ts +324 -0
- package/src/ngb/site/mainMenuStore.ts +49 -0
- package/src/ngb/site/types.ts +31 -0
- package/src/ngb/site/useDashboardPageState.ts +98 -0
- package/src/ngb/site/useTheme.ts +95 -0
- package/src/ngb/utils/clone.ts +43 -0
- package/src/ngb/utils/dateValues.ts +107 -0
- package/src/ngb/utils/errorMessage.ts +14 -0
- package/src/ngb/utils/guid.ts +21 -0
- package/src/ngb/utils/stableValue.ts +21 -0
- package/src/ngb/utils/storage.ts +135 -0
- package/src/styles/tailwind.css +165 -0
- package/src/vite/publicAssets.ts +104 -0
- package/vite-public-assets.js +68 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import type { LookupItem, LookupSource } from '../metadata/types'
|
|
2
|
+
|
|
3
|
+
export enum ReportAggregationKind {
|
|
4
|
+
Sum = 1,
|
|
5
|
+
Min = 2,
|
|
6
|
+
Max = 3,
|
|
7
|
+
Average = 4,
|
|
8
|
+
Count = 5,
|
|
9
|
+
CountDistinct = 6,
|
|
10
|
+
First = 7,
|
|
11
|
+
Last = 8,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export enum ReportExecutionMode {
|
|
15
|
+
Canonical = 1,
|
|
16
|
+
Composable = 2,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export enum ReportFieldKind {
|
|
20
|
+
Attribute = 1,
|
|
21
|
+
Dimension = 2,
|
|
22
|
+
Time = 3,
|
|
23
|
+
Detail = 4,
|
|
24
|
+
System = 5,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export enum ReportTimeGrain {
|
|
28
|
+
Day = 1,
|
|
29
|
+
Week = 2,
|
|
30
|
+
Month = 3,
|
|
31
|
+
Quarter = 4,
|
|
32
|
+
Year = 5,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export enum ReportSortDirection {
|
|
36
|
+
Asc = 1,
|
|
37
|
+
Desc = 2,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export enum ReportRowKind {
|
|
41
|
+
Header = 1,
|
|
42
|
+
Group = 2,
|
|
43
|
+
Detail = 3,
|
|
44
|
+
Subtotal = 4,
|
|
45
|
+
Total = 5,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type ReportCapabilitiesDto = {
|
|
49
|
+
allowsFilters?: boolean
|
|
50
|
+
allowsRowGroups?: boolean
|
|
51
|
+
allowsColumnGroups?: boolean
|
|
52
|
+
allowsMeasures?: boolean
|
|
53
|
+
allowsDetailFields?: boolean
|
|
54
|
+
allowsSorting?: boolean
|
|
55
|
+
allowsShowDetails?: boolean
|
|
56
|
+
allowsSubtotals?: boolean
|
|
57
|
+
allowsSeparateRowSubtotals?: boolean
|
|
58
|
+
allowsGrandTotals?: boolean
|
|
59
|
+
allowsVariants?: boolean
|
|
60
|
+
allowsXlsxExport?: boolean
|
|
61
|
+
maxRowGroupDepth?: number | null
|
|
62
|
+
maxColumnGroupDepth?: number | null
|
|
63
|
+
maxVisibleColumns?: number | null
|
|
64
|
+
maxVisibleRows?: number | null
|
|
65
|
+
maxRenderedCells?: number | null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type ReportPresentationDto = {
|
|
69
|
+
initialPageSize?: number | null
|
|
70
|
+
rowNoun?: string | null
|
|
71
|
+
emptyStateMessage?: string | null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export type ReportFieldDto = {
|
|
75
|
+
code: string
|
|
76
|
+
label: string
|
|
77
|
+
dataType: string
|
|
78
|
+
kind: ReportFieldKind
|
|
79
|
+
isFilterable?: boolean
|
|
80
|
+
isGroupable?: boolean
|
|
81
|
+
isSortable?: boolean
|
|
82
|
+
isSelectable?: boolean
|
|
83
|
+
supportsIncludeDescendants?: boolean
|
|
84
|
+
defaultIncludeDescendants?: boolean
|
|
85
|
+
supportedTimeGrains?: ReportTimeGrain[] | null
|
|
86
|
+
lookup?: LookupSource | null
|
|
87
|
+
description?: string | null
|
|
88
|
+
format?: string | null
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export type ReportMeasureDto = {
|
|
92
|
+
code: string
|
|
93
|
+
label: string
|
|
94
|
+
dataType: string
|
|
95
|
+
supportedAggregations?: ReportAggregationKind[] | null
|
|
96
|
+
format?: string | null
|
|
97
|
+
description?: string | null
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export type ReportDatasetDto = {
|
|
101
|
+
datasetCode: string
|
|
102
|
+
fields?: ReportFieldDto[] | null
|
|
103
|
+
measures?: ReportMeasureDto[] | null
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export type ReportParameterMetadataDto = {
|
|
107
|
+
code: string
|
|
108
|
+
dataType: string
|
|
109
|
+
isRequired: boolean
|
|
110
|
+
description?: string | null
|
|
111
|
+
defaultValue?: string | null
|
|
112
|
+
label?: string | null
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type ReportFilterOptionDto = {
|
|
116
|
+
value: string
|
|
117
|
+
label: string
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type ReportFilterFieldDto = {
|
|
121
|
+
fieldCode: string
|
|
122
|
+
label: string
|
|
123
|
+
dataType: string
|
|
124
|
+
isRequired?: boolean
|
|
125
|
+
isMulti?: boolean
|
|
126
|
+
supportsIncludeDescendants?: boolean
|
|
127
|
+
defaultIncludeDescendants?: boolean
|
|
128
|
+
lookup?: LookupSource | null
|
|
129
|
+
options?: ReportFilterOptionDto[] | null
|
|
130
|
+
description?: string | null
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export type ReportGroupingDto = {
|
|
134
|
+
fieldCode: string
|
|
135
|
+
timeGrain?: ReportTimeGrain | null
|
|
136
|
+
includeDetails?: boolean
|
|
137
|
+
includeEmpty?: boolean
|
|
138
|
+
includeDescendants?: boolean
|
|
139
|
+
labelOverride?: string | null
|
|
140
|
+
groupKey?: string | null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export type ReportMeasureSelectionDto = {
|
|
144
|
+
measureCode: string
|
|
145
|
+
aggregation?: ReportAggregationKind
|
|
146
|
+
labelOverride?: string | null
|
|
147
|
+
formatOverride?: string | null
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export type ReportSortDto = {
|
|
151
|
+
fieldCode: string
|
|
152
|
+
direction?: ReportSortDirection
|
|
153
|
+
timeGrain?: ReportTimeGrain | null
|
|
154
|
+
appliesToColumnAxis?: boolean
|
|
155
|
+
groupKey?: string | null
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export type ReportLayoutDto = {
|
|
159
|
+
rowGroups?: ReportGroupingDto[] | null
|
|
160
|
+
columnGroups?: ReportGroupingDto[] | null
|
|
161
|
+
measures?: ReportMeasureSelectionDto[] | null
|
|
162
|
+
detailFields?: string[] | null
|
|
163
|
+
sorts?: ReportSortDto[] | null
|
|
164
|
+
showDetails?: boolean
|
|
165
|
+
showSubtotals?: boolean
|
|
166
|
+
showSubtotalsOnSeparateRows?: boolean
|
|
167
|
+
showGrandTotals?: boolean
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export type ReportDefinitionDto = {
|
|
171
|
+
reportCode: string
|
|
172
|
+
name: string
|
|
173
|
+
group?: string | null
|
|
174
|
+
description?: string | null
|
|
175
|
+
mode?: ReportExecutionMode
|
|
176
|
+
dataset?: ReportDatasetDto | null
|
|
177
|
+
capabilities?: ReportCapabilitiesDto | null
|
|
178
|
+
defaultLayout?: ReportLayoutDto | null
|
|
179
|
+
parameters?: ReportParameterMetadataDto[] | null
|
|
180
|
+
filters?: ReportFilterFieldDto[] | null
|
|
181
|
+
presentation?: ReportPresentationDto | null
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export type ReportFilterValueDto = {
|
|
185
|
+
value: unknown
|
|
186
|
+
includeDescendants?: boolean
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export type ReportExportRequestDto = {
|
|
190
|
+
layout?: ReportLayoutDto | null
|
|
191
|
+
filters?: Record<string, ReportFilterValueDto> | null
|
|
192
|
+
parameters?: Record<string, string> | null
|
|
193
|
+
variantCode?: string | null
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export type ReportExecutionRequestDto = {
|
|
197
|
+
layout?: ReportLayoutDto | null
|
|
198
|
+
filters?: Record<string, ReportFilterValueDto> | null
|
|
199
|
+
parameters?: Record<string, string> | null
|
|
200
|
+
variantCode?: string | null
|
|
201
|
+
offset?: number
|
|
202
|
+
limit?: number
|
|
203
|
+
cursor?: string | null
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export type ReportCellReportTargetDto = {
|
|
207
|
+
reportCode: string
|
|
208
|
+
parameters?: Record<string, string> | null
|
|
209
|
+
filters?: Record<string, ReportFilterValueDto> | null
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export type ReportCellActionDto = {
|
|
213
|
+
kind: string
|
|
214
|
+
documentType?: string | null
|
|
215
|
+
documentId?: string | null
|
|
216
|
+
accountId?: string | null
|
|
217
|
+
catalogType?: string | null
|
|
218
|
+
catalogId?: string | null
|
|
219
|
+
report?: ReportCellReportTargetDto | null
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export type ReportCellDto = {
|
|
223
|
+
value?: unknown
|
|
224
|
+
display?: string | null
|
|
225
|
+
valueType?: string | null
|
|
226
|
+
colSpan?: number
|
|
227
|
+
rowSpan?: number
|
|
228
|
+
styleKey?: string | null
|
|
229
|
+
semanticRole?: string | null
|
|
230
|
+
action?: ReportCellActionDto | null
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export type ReportSheetColumnDto = {
|
|
234
|
+
code: string
|
|
235
|
+
title: string
|
|
236
|
+
dataType: string
|
|
237
|
+
width?: number
|
|
238
|
+
isFrozen?: boolean
|
|
239
|
+
semanticRole?: string | null
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export type ReportSheetRowDto = {
|
|
243
|
+
rowKind: ReportRowKind
|
|
244
|
+
cells: ReportCellDto[]
|
|
245
|
+
outlineLevel?: number
|
|
246
|
+
isExpanded?: boolean
|
|
247
|
+
groupKey?: string | null
|
|
248
|
+
semanticRole?: string | null
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export type ReportSheetMetaDto = {
|
|
252
|
+
title?: string | null
|
|
253
|
+
subtitle?: string | null
|
|
254
|
+
isPivot?: boolean
|
|
255
|
+
hasRowOutline?: boolean
|
|
256
|
+
hasColumnGroups?: boolean
|
|
257
|
+
diagnostics?: Record<string, string> | null
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export type ReportSheetDto = {
|
|
261
|
+
columns: ReportSheetColumnDto[]
|
|
262
|
+
rows: ReportSheetRowDto[]
|
|
263
|
+
meta?: ReportSheetMetaDto | null
|
|
264
|
+
headerRows?: ReportSheetRowDto[] | null
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export type ReportExecutionResponseDto = {
|
|
268
|
+
sheet: ReportSheetDto
|
|
269
|
+
offset: number
|
|
270
|
+
limit: number
|
|
271
|
+
total?: number | null
|
|
272
|
+
hasMore: boolean
|
|
273
|
+
nextCursor?: string | null
|
|
274
|
+
diagnostics?: Record<string, string> | null
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export type ReportVariantDto = {
|
|
278
|
+
variantCode: string
|
|
279
|
+
reportCode: string
|
|
280
|
+
name: string
|
|
281
|
+
layout?: ReportLayoutDto | null
|
|
282
|
+
filters?: Record<string, ReportFilterValueDto> | null
|
|
283
|
+
parameters?: Record<string, string> | null
|
|
284
|
+
isDefault?: boolean
|
|
285
|
+
isShared?: boolean
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export type ReportComposerLookupItem = LookupItem
|
|
289
|
+
|
|
290
|
+
export type ReportComposerFilterState = {
|
|
291
|
+
raw: string
|
|
292
|
+
items: ReportComposerLookupItem[]
|
|
293
|
+
includeDescendants: boolean
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export type ReportComposerGroupingState = {
|
|
297
|
+
groupKey?: string | null
|
|
298
|
+
fieldCode: string
|
|
299
|
+
timeGrain: ReportTimeGrain | null
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export type ReportComposerMeasureState = {
|
|
303
|
+
measureCode: string
|
|
304
|
+
aggregation: ReportAggregationKind | null
|
|
305
|
+
labelOverride: string | null
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export type ReportComposerSortState = {
|
|
309
|
+
fieldCode: string
|
|
310
|
+
groupKey?: string | null
|
|
311
|
+
appliesToColumnAxis?: boolean
|
|
312
|
+
direction: ReportSortDirection
|
|
313
|
+
timeGrain: ReportTimeGrain | null
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export type ReportComposerDraft = {
|
|
317
|
+
parameters: Record<string, string>
|
|
318
|
+
filters: Record<string, ReportComposerFilterState>
|
|
319
|
+
rowGroups: ReportComposerGroupingState[]
|
|
320
|
+
columnGroups: ReportComposerGroupingState[]
|
|
321
|
+
measures: ReportComposerMeasureState[]
|
|
322
|
+
detailFields: string[]
|
|
323
|
+
sorts: ReportComposerSortState[]
|
|
324
|
+
showDetails: boolean
|
|
325
|
+
showSubtotals: boolean
|
|
326
|
+
showSubtotalsOnSeparateRows: boolean
|
|
327
|
+
showGrandTotals: boolean
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export type ReportOptionItem<T extends string | number = string | number> = {
|
|
331
|
+
value: T
|
|
332
|
+
label: string
|
|
333
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { RouteLocationNormalizedLoaded, Router } from 'vue-router';
|
|
2
|
+
|
|
3
|
+
function normalizeQueryValue(value: unknown): string | null {
|
|
4
|
+
if (Array.isArray(value)) return normalizeQueryValue(value[0] ?? null);
|
|
5
|
+
const raw = String(value ?? '').trim();
|
|
6
|
+
return raw.length > 0 ? raw : null;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function encodeBase64Url(value: string): string {
|
|
10
|
+
const bytes = new TextEncoder().encode(value);
|
|
11
|
+
let binary = '';
|
|
12
|
+
bytes.forEach((byte) => {
|
|
13
|
+
binary += String.fromCharCode(byte);
|
|
14
|
+
});
|
|
15
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function decodeBase64Url(value: string): string | null {
|
|
19
|
+
try {
|
|
20
|
+
const padded = value.replace(/-/g, '+').replace(/_/g, '/') + '==='.slice((value.length + 3) % 4);
|
|
21
|
+
const binary = atob(padded);
|
|
22
|
+
const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
|
|
23
|
+
return new TextDecoder().decode(bytes);
|
|
24
|
+
} catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function encodeBackTarget(target: string | null | undefined): string | null {
|
|
30
|
+
const normalized = String(target ?? '').trim();
|
|
31
|
+
if (!normalized) return null;
|
|
32
|
+
return encodeBase64Url(normalized);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function decodeBackTarget(value: unknown): string | null {
|
|
36
|
+
const normalized = normalizeQueryValue(value);
|
|
37
|
+
if (!normalized) return null;
|
|
38
|
+
return decodeBase64Url(normalized);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function parseRouteTarget(target: string | null | undefined): URL | null {
|
|
42
|
+
const normalized = String(target ?? '').trim();
|
|
43
|
+
if (!normalized) return null;
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// Provide a synthetic absolute base only so the URL constructor can parse app-relative routes
|
|
47
|
+
// like "/documents/...". This value is never used for network requests and should not represent
|
|
48
|
+
// a real environment or host.
|
|
49
|
+
return new URL(normalized, 'http://ngb.local');
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function resolveBackTargetFromPath(target: string | null | undefined): string | null {
|
|
56
|
+
const parsed = parseRouteTarget(target);
|
|
57
|
+
if (!parsed) return null;
|
|
58
|
+
return decodeBackTarget(parsed.searchParams.get('back'));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function routeTargetMatches(
|
|
62
|
+
candidate: string | null | undefined,
|
|
63
|
+
expected: string | null | undefined,
|
|
64
|
+
): boolean {
|
|
65
|
+
const parsedCandidate = parseRouteTarget(candidate);
|
|
66
|
+
const parsedExpected = parseRouteTarget(expected);
|
|
67
|
+
if (!parsedCandidate || !parsedExpected) return false;
|
|
68
|
+
if (parsedCandidate.pathname !== parsedExpected.pathname) return false;
|
|
69
|
+
|
|
70
|
+
for (const [key, value] of parsedExpected.searchParams.entries()) {
|
|
71
|
+
if (parsedCandidate.searchParams.get(key) !== value) return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function buildPathWithQuery(path: string, patch: Record<string, string | null | undefined>): string {
|
|
78
|
+
const [pathname, rawQuery = ''] = path.split('?', 2);
|
|
79
|
+
const query = new URLSearchParams(rawQuery);
|
|
80
|
+
|
|
81
|
+
Object.entries(patch).forEach(([key, value]) => {
|
|
82
|
+
const normalized = String(value ?? '').trim();
|
|
83
|
+
if (normalized.length === 0) query.delete(key);
|
|
84
|
+
else query.set(key, normalized);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const suffix = query.toString();
|
|
88
|
+
return suffix ? `${pathname}?${suffix}` : pathname;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function withBackTarget(path: string, backTarget: string | null | undefined): string {
|
|
92
|
+
const encoded = encodeBackTarget(backTarget);
|
|
93
|
+
return buildPathWithQuery(path, { back: encoded });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function currentRouteBackTarget(route: Pick<RouteLocationNormalizedLoaded, 'fullPath'>): string {
|
|
97
|
+
return String(route.fullPath ?? '').trim() || '/';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function resolveBackTarget(route: Pick<RouteLocationNormalizedLoaded, 'query'>): string | null {
|
|
101
|
+
return decodeBackTarget(route.query?.back);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function navigateBack(
|
|
105
|
+
router: Router,
|
|
106
|
+
route: Pick<RouteLocationNormalizedLoaded, 'query'>,
|
|
107
|
+
fallback?: string | null,
|
|
108
|
+
): Promise<void> {
|
|
109
|
+
const explicit = resolveBackTarget(route);
|
|
110
|
+
if (explicit) {
|
|
111
|
+
await router.replace(explicit);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const normalizedFallback = String(fallback ?? '').trim();
|
|
116
|
+
if (normalizedFallback.length > 0 && typeof window !== 'undefined' && window.history.length <= 1) {
|
|
117
|
+
await router.replace(normalizedFallback);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
router.back();
|
|
122
|
+
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type LocationQueryRaw,
|
|
3
|
+
type RouteLocationNormalizedLoaded,
|
|
4
|
+
type Router,
|
|
5
|
+
} from 'vue-router'
|
|
6
|
+
import {
|
|
7
|
+
normalizeDateOnlyValue as normalizeSharedDateOnlyValue,
|
|
8
|
+
normalizeMonthValue as normalizeSharedMonthValue,
|
|
9
|
+
} from '../utils/dateValues'
|
|
10
|
+
|
|
11
|
+
export type QueryTrashMode = 'active' | 'deleted' | 'all'
|
|
12
|
+
export type QueryPatch = Record<string, unknown>
|
|
13
|
+
export type QueryNavigationMode = 'push' | 'replace'
|
|
14
|
+
|
|
15
|
+
export function normalizeTrashMode(value: unknown): QueryTrashMode {
|
|
16
|
+
const normalized = String(value ?? '').toLowerCase()
|
|
17
|
+
if (normalized === 'deleted') return 'deleted'
|
|
18
|
+
if (normalized === 'all') return 'all'
|
|
19
|
+
return 'active'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function normalizeMonthValue(value: unknown): string {
|
|
23
|
+
return normalizeSharedMonthValue(value) ?? ''
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function normalizeMonthQueryValue(value: unknown): string | null {
|
|
27
|
+
const normalized = normalizeMonthValue(value)
|
|
28
|
+
return normalized || null
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function normalizeDateOnlyQueryValue(value: unknown): string | null {
|
|
32
|
+
const normalized = normalizeSingleQueryValue(value)
|
|
33
|
+
return normalizeSharedDateOnlyValue(normalized)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function normalizeYearQueryValue(value: unknown): number | null {
|
|
37
|
+
const normalized = normalizeSingleQueryValue(value)
|
|
38
|
+
const parsed = Number.parseInt(normalized, 10)
|
|
39
|
+
return Number.isInteger(parsed) && parsed >= 1900 && parsed <= 9999 ? parsed : null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function normalizeSingleQueryValue(value: unknown): string {
|
|
43
|
+
if (Array.isArray(value)) return String(value[0] ?? '').trim()
|
|
44
|
+
return String(value ?? '').trim()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function firstQueryValue(value: unknown): string | null {
|
|
48
|
+
const normalized = normalizeSingleQueryValue(value)
|
|
49
|
+
return normalized.length > 0 ? normalized : null
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function normalizeBooleanQueryFlag(value: unknown): boolean {
|
|
53
|
+
const normalized = normalizeSingleQueryValue(value).toLowerCase()
|
|
54
|
+
return normalized === '1' || normalized === 'true' || normalized === 'yes'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function normalizeAllowedQueryValue<TValue extends string>(
|
|
58
|
+
value: unknown,
|
|
59
|
+
allowedValues: readonly TValue[],
|
|
60
|
+
): TValue | null {
|
|
61
|
+
const normalized = normalizeSingleQueryValue(value)
|
|
62
|
+
if (!normalized) return null
|
|
63
|
+
|
|
64
|
+
const allowed = new Set<string>(allowedValues)
|
|
65
|
+
return allowed.has(normalized) ? normalized as TValue : null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function cleanQueryObject<T extends Record<string, unknown>>(query: T): T {
|
|
69
|
+
const next = { ...query }
|
|
70
|
+
for (const key of Object.keys(next)) {
|
|
71
|
+
if (next[key] == null || next[key] === '') delete next[key]
|
|
72
|
+
}
|
|
73
|
+
return next
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function mergeCleanQuery<TBase extends Record<string, unknown>, TPatch extends Record<string, unknown>>(
|
|
77
|
+
base: TBase,
|
|
78
|
+
patch: TPatch,
|
|
79
|
+
): TBase & TPatch {
|
|
80
|
+
return cleanQueryObject({ ...base, ...patch })
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function navigateCleanRouteQuery(
|
|
84
|
+
route: RouteLocationNormalizedLoaded,
|
|
85
|
+
router: Router,
|
|
86
|
+
patch: QueryPatch,
|
|
87
|
+
mode: QueryNavigationMode = 'replace',
|
|
88
|
+
) {
|
|
89
|
+
return setCleanRouteQuery(route, router, { ...route.query, ...patch }, mode)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function setCleanRouteQuery(
|
|
93
|
+
route: RouteLocationNormalizedLoaded,
|
|
94
|
+
router: Router,
|
|
95
|
+
query: Record<string, unknown>,
|
|
96
|
+
mode: QueryNavigationMode = 'replace',
|
|
97
|
+
) {
|
|
98
|
+
const nextQuery = cleanQueryObject({ ...query }) as LocationQueryRaw
|
|
99
|
+
return mode === 'push'
|
|
100
|
+
? router.push({ path: route.path, query: nextQuery })
|
|
101
|
+
: router.replace({ path: route.path, query: nextQuery })
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function replaceCleanRouteQuery(
|
|
105
|
+
route: RouteLocationNormalizedLoaded,
|
|
106
|
+
router: Router,
|
|
107
|
+
patch: QueryPatch,
|
|
108
|
+
) {
|
|
109
|
+
return navigateCleanRouteQuery(route, router, patch, 'replace')
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function pushCleanRouteQuery(
|
|
113
|
+
route: RouteLocationNormalizedLoaded,
|
|
114
|
+
router: Router,
|
|
115
|
+
patch: QueryPatch,
|
|
116
|
+
) {
|
|
117
|
+
return navigateCleanRouteQuery(route, router, patch, 'push')
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function omitRouteQueryKeys(
|
|
121
|
+
route: RouteLocationNormalizedLoaded,
|
|
122
|
+
router: Router,
|
|
123
|
+
keys: readonly string[],
|
|
124
|
+
mode: QueryNavigationMode = 'replace',
|
|
125
|
+
) {
|
|
126
|
+
const next = { ...route.query } as QueryPatch
|
|
127
|
+
for (const key of keys) delete next[key]
|
|
128
|
+
return setCleanRouteQuery(route, router, next, mode)
|
|
129
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { computed, ref, watch, type WatchSource } from 'vue'
|
|
2
|
+
import type { RouteLocationNormalizedLoaded, RouteLocationRaw, Router } from 'vue-router'
|
|
3
|
+
|
|
4
|
+
import type { UiLookupItem } from '../lookup/store'
|
|
5
|
+
import { isNonEmptyGuid } from '../utils/guid'
|
|
6
|
+
import {
|
|
7
|
+
firstQueryValue,
|
|
8
|
+
normalizeAllowedQueryValue,
|
|
9
|
+
normalizeBooleanQueryFlag,
|
|
10
|
+
replaceCleanRouteQuery,
|
|
11
|
+
type QueryPatch,
|
|
12
|
+
} from './queryParams'
|
|
13
|
+
|
|
14
|
+
export type UseRouteQueryMigrationArgs<TValues extends readonly unknown[]> = {
|
|
15
|
+
route: RouteLocationNormalizedLoaded
|
|
16
|
+
router: Router
|
|
17
|
+
sources: WatchSource<TValues>
|
|
18
|
+
migrate: (values: TValues) => QueryPatch | null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function useRouteQueryMigration<TValues extends readonly unknown[]>(
|
|
22
|
+
args: UseRouteQueryMigrationArgs<TValues>,
|
|
23
|
+
) {
|
|
24
|
+
watch(
|
|
25
|
+
args.sources,
|
|
26
|
+
(values) => {
|
|
27
|
+
const patch = args.migrate(values)
|
|
28
|
+
if (!patch) return
|
|
29
|
+
void replaceCleanRouteQuery(args.route, args.router, patch)
|
|
30
|
+
},
|
|
31
|
+
{ immediate: true },
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function useGuidQueryParam(
|
|
36
|
+
route: RouteLocationNormalizedLoaded,
|
|
37
|
+
key: string,
|
|
38
|
+
) {
|
|
39
|
+
return computed(() => {
|
|
40
|
+
const value = firstQueryValue(route.query[key])
|
|
41
|
+
return isNonEmptyGuid(value) ? value : null
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function useBooleanQueryFlag(
|
|
46
|
+
route: RouteLocationNormalizedLoaded,
|
|
47
|
+
key: string,
|
|
48
|
+
) {
|
|
49
|
+
return computed(() => normalizeBooleanQueryFlag(route.query[key]))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function useAllowedQueryValue<TValue extends string>(
|
|
53
|
+
route: RouteLocationNormalizedLoaded,
|
|
54
|
+
key: string,
|
|
55
|
+
allowedValues: readonly TValue[],
|
|
56
|
+
) {
|
|
57
|
+
return computed<TValue | null>(() => normalizeAllowedQueryValue(route.query[key], allowedValues))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type UseRouteLookupSelectionArgs<TItem extends UiLookupItem = UiLookupItem> = {
|
|
61
|
+
route: RouteLocationNormalizedLoaded
|
|
62
|
+
router: Router
|
|
63
|
+
queryKey: string
|
|
64
|
+
lookupById: (id: string) => Promise<string | null | undefined>
|
|
65
|
+
search: (query: string) => Promise<TItem[]>
|
|
66
|
+
openTarget: (value: TItem | null) => Promise<RouteLocationRaw | null>
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function useRouteLookupSelection<TItem extends UiLookupItem = UiLookupItem>(
|
|
70
|
+
args: UseRouteLookupSelectionArgs<TItem>,
|
|
71
|
+
) {
|
|
72
|
+
const selected = ref<TItem | null>(null)
|
|
73
|
+
const items = ref<TItem[]>([])
|
|
74
|
+
const routeId = useGuidQueryParam(args.route, args.queryKey)
|
|
75
|
+
|
|
76
|
+
async function hydrateSelected(): Promise<void> {
|
|
77
|
+
const id = routeId.value
|
|
78
|
+
if (!id) {
|
|
79
|
+
selected.value = null
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const label = await args.lookupById(id)
|
|
85
|
+
selected.value = { id, label: label ?? id } as TItem
|
|
86
|
+
} catch {
|
|
87
|
+
selected.value = { id, label: id } as TItem
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async function onQuery(queryText: string): Promise<void> {
|
|
92
|
+
const query = queryText.trim()
|
|
93
|
+
if (!query) {
|
|
94
|
+
items.value = []
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
items.value = await args.search(query)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function onSelect(value: TItem | null): void {
|
|
102
|
+
selected.value = value
|
|
103
|
+
void replaceCleanRouteQuery(args.route, args.router, { [args.queryKey]: value?.id ?? null })
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function openSelected(): Promise<void> {
|
|
107
|
+
const target = await args.openTarget(selected.value)
|
|
108
|
+
if (!target) return
|
|
109
|
+
await args.router.push(target)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
selected,
|
|
114
|
+
items,
|
|
115
|
+
routeId,
|
|
116
|
+
hydrateSelected,
|
|
117
|
+
onQuery,
|
|
118
|
+
onSelect,
|
|
119
|
+
openSelected,
|
|
120
|
+
}
|
|
121
|
+
}
|