@datagouv/components-next 1.0.2-dev.50 → 1.0.2-dev.52
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/dist/{Datafair.client-hLoIoNbP.js → Datafair.client-CBE0uebV.js} +1 -1
- package/dist/{JsonPreview.client-BUCeeFKz.js → JsonPreview.client-B-kw70ep.js} +2 -2
- package/dist/{MapContainer.client-DrQRSrq_.js → MapContainer.client-dUUInlHa.js} +2 -2
- package/dist/{PdfPreview.client-vQ4bfJx3.js → PdfPreview.client-Y2qTpKFd.js} +2 -2
- package/dist/{Pmtiles.client-DWtu_UNl.js → Pmtiles.client-BOPJ59Cq.js} +1 -1
- package/dist/{PreviewWrapper.vue_vue_type_script_setup_true_lang-4Ufr2Kmw.js → PreviewWrapper.vue_vue_type_script_setup_true_lang-DtgGpKmM.js} +1 -1
- package/dist/{XmlPreview.client-CEEHnAFF.js → XmlPreview.client-CtW1m4O8.js} +3 -3
- package/dist/components-next.css +1 -1
- package/dist/components-next.js +160 -151
- package/dist/components.css +1 -1
- package/dist/{index-CsOZmih1.js → index-B8siUkxs.js} +1 -1
- package/dist/{main-7DRSPyNj.js → main-DaWGX8hL.js} +51503 -28228
- package/dist/{vue3-xml-viewer.common-DOIGuzsk.js → vue3-xml-viewer.common-S9Mg9vGE.js} +1 -1
- package/package.json +3 -1
- package/src/components/Chart/ChartViewer.vue +147 -0
- package/src/components/Chart/ChartViewerWrapper.vue +224 -0
- package/src/components/Form/Listbox.vue +101 -0
- package/src/components/ResourceAccordion/Preview.vue +1 -1
- package/src/composables/useHasTabularData.ts +9 -1
- package/src/functions/charts.ts +68 -0
- package/src/functions/tabularApi.ts +133 -7
- package/src/main.ts +27 -0
- package/src/types/visualizations.ts +89 -0
|
@@ -1,20 +1,146 @@
|
|
|
1
1
|
import { ofetch } from 'ofetch'
|
|
2
2
|
import { useComponentsConfig, type PluginConfig } from '../config'
|
|
3
|
+
import type { GenericFilter } from '../types/visualizations'
|
|
3
4
|
|
|
4
5
|
export type SortConfig = {
|
|
5
6
|
column: string
|
|
6
7
|
type: string
|
|
7
8
|
} | null
|
|
8
9
|
|
|
10
|
+
export type TabularDataResponse = {
|
|
11
|
+
data: Array<Record<string, unknown>>
|
|
12
|
+
links: {
|
|
13
|
+
profile: string
|
|
14
|
+
swagger: string
|
|
15
|
+
next: string
|
|
16
|
+
}
|
|
17
|
+
meta: { total: number }
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type TabularAggregateType = 'avg' | 'sum' | 'count' | 'min' | 'max'
|
|
21
|
+
|
|
22
|
+
export type FetchTabularDataOptions = {
|
|
23
|
+
resourceId: string
|
|
24
|
+
page?: number
|
|
25
|
+
pageSize?: number
|
|
26
|
+
columns?: Array<string> | undefined
|
|
27
|
+
sort?: SortConfig
|
|
28
|
+
groupBy?: string | undefined
|
|
29
|
+
aggregation?: {
|
|
30
|
+
column: string
|
|
31
|
+
type: TabularAggregateType
|
|
32
|
+
} | undefined
|
|
33
|
+
filters?: GenericFilter | undefined
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type TabularProfileResponse = {
|
|
37
|
+
profile: {
|
|
38
|
+
header: Array<string>
|
|
39
|
+
columns: Record<string, {
|
|
40
|
+
score: number
|
|
41
|
+
format: string
|
|
42
|
+
python_type: string
|
|
43
|
+
}>
|
|
44
|
+
formats: Record<string, Array<string>>
|
|
45
|
+
profile: Record<string, {
|
|
46
|
+
tops: Array<{ count: number, value: string }>
|
|
47
|
+
nb_distinct: number
|
|
48
|
+
nb_missing_values: number
|
|
49
|
+
min?: number
|
|
50
|
+
max?: number
|
|
51
|
+
std?: number
|
|
52
|
+
mean?: number
|
|
53
|
+
}>
|
|
54
|
+
encoding: string
|
|
55
|
+
separator: string
|
|
56
|
+
categorical: Array<string>
|
|
57
|
+
total_lines: number
|
|
58
|
+
nb_duplicates: number
|
|
59
|
+
columns_fields: Record<string, {
|
|
60
|
+
score: number
|
|
61
|
+
format: string
|
|
62
|
+
python_type: string
|
|
63
|
+
}>
|
|
64
|
+
columns_labels: Record<string, {
|
|
65
|
+
score: number
|
|
66
|
+
format: string
|
|
67
|
+
python_type: string
|
|
68
|
+
}>
|
|
69
|
+
header_row_idx: number
|
|
70
|
+
heading_columns: number
|
|
71
|
+
trailing_columns: number
|
|
72
|
+
}
|
|
73
|
+
deleted_at: string | null
|
|
74
|
+
dataset_id: string
|
|
75
|
+
indexes: null
|
|
76
|
+
}
|
|
77
|
+
|
|
9
78
|
/**
|
|
10
|
-
* Call Tabular-api to get table content
|
|
79
|
+
* Call Tabular-api to get table content with options object
|
|
11
80
|
*/
|
|
12
|
-
export async function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
81
|
+
export async function fetchTabularData(config: PluginConfig, options: FetchTabularDataOptions): Promise<TabularDataResponse> {
|
|
82
|
+
const page = options.page ?? 1
|
|
83
|
+
const pageSize = options.pageSize ?? config.tabularApiPageSize ?? 15
|
|
84
|
+
console.log(options)
|
|
85
|
+
let url = `${config.tabularApiUrl}/api/resources/${options.resourceId}/data/?page=${page}&page_size=${pageSize}`
|
|
86
|
+
if (options.columns) {
|
|
87
|
+
url += `&columns=${options.columns.join(',')}`
|
|
88
|
+
}
|
|
89
|
+
if (options.sort) {
|
|
90
|
+
url += `&${options.sort.column}__sort=${options.sort.type}`
|
|
16
91
|
}
|
|
17
|
-
|
|
92
|
+
if (options.groupBy && options.aggregation?.type) {
|
|
93
|
+
url += `&${options.groupBy}__groupby&${options.aggregation.column}__${options.aggregation.type}`
|
|
94
|
+
}
|
|
95
|
+
if (options.filters) {
|
|
96
|
+
const filterQuery = buildFilterQuery(options.filters)
|
|
97
|
+
if (filterQuery) {
|
|
98
|
+
url += `&${filterQuery}`
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return await ofetch<TabularDataResponse>(url)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function buildFilterQuery(filters: GenericFilter): string {
|
|
105
|
+
const params: Array<string> = []
|
|
106
|
+
if ('filters' in filters) {
|
|
107
|
+
for (const filter of filters.filters) {
|
|
108
|
+
if ('filters' in filter) {
|
|
109
|
+
params.push(buildFilterQuery(filter))
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
if (filter.condition === 'is_null') {
|
|
113
|
+
params.push(`${filter.column}__isnull`)
|
|
114
|
+
}
|
|
115
|
+
else if (filter.condition === 'is_not_null') {
|
|
116
|
+
params.push(`${filter.column}__isnotnull`)
|
|
117
|
+
}
|
|
118
|
+
else if (filter.value !== null && filter.value !== undefined && filter.value !== '') {
|
|
119
|
+
params.push(`${filter.column}__${filter.condition}=${encodeURIComponent(filter.value)}`)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
const filter = filters
|
|
126
|
+
if (filter.condition === 'is_null') {
|
|
127
|
+
params.push(`${filter.column}__isnull`)
|
|
128
|
+
}
|
|
129
|
+
else if (filter.condition === 'is_not_null') {
|
|
130
|
+
params.push(`${filter.column}__isnotnull`)
|
|
131
|
+
}
|
|
132
|
+
else if (filter.value !== null && filter.value !== undefined && filter.value !== '') {
|
|
133
|
+
params.push(`${filter.column}__${filter.condition}=${encodeURIComponent(filter.value)}`)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return params.join('&')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Call Tabular-api to get table content
|
|
141
|
+
*/
|
|
142
|
+
export function getData(config: PluginConfig, id: string, page: number, sortConfig?: SortConfig) {
|
|
143
|
+
return fetchTabularData(config, { resourceId: id, page, sort: sortConfig })
|
|
18
144
|
}
|
|
19
145
|
|
|
20
146
|
/**
|
|
@@ -22,5 +148,5 @@ export async function getData(config: PluginConfig, id: string, page: number, so
|
|
|
22
148
|
*/
|
|
23
149
|
export function useGetProfile() {
|
|
24
150
|
const config = useComponentsConfig()
|
|
25
|
-
return (id: string) => ofetch(`${config.tabularApiUrl}/api/resources/${id}/profile/`)
|
|
151
|
+
return (id: string) => ofetch<TabularProfileResponse>(`${config.tabularApiUrl}/api/resources/${id}/profile/`)
|
|
26
152
|
}
|
package/src/main.ts
CHANGED
|
@@ -23,6 +23,7 @@ import type { Site } from './types/site'
|
|
|
23
23
|
import type { Weight, WellType } from './types/ui'
|
|
24
24
|
import type { User, UserReference } from './types/users'
|
|
25
25
|
import type { Report, ReportSubject, ReportReason } from './types/reports'
|
|
26
|
+
import type { Chart, ChartForm, ChartForApi, FilterCondition, Filter, AndFilters, GenericFilter, XAxisType, XAxisSortBy, SortDirection, XAxis, XAxisForm, UnitPosition, YAxis, DataSeriesType, DataSeries, DataSeriesForm } from './types/visualizations'
|
|
26
27
|
import type { GlobalSearchConfig, SearchType, SortOption } from './types/search'
|
|
27
28
|
import { getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultTopicConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search'
|
|
28
29
|
|
|
@@ -80,6 +81,8 @@ import ReuseDetails from './components/ReuseDetails.vue'
|
|
|
80
81
|
import SchemaCard from './components/SchemaCard.vue'
|
|
81
82
|
import SimpleBanner from './components/SimpleBanner.vue'
|
|
82
83
|
import SmallChart from './components/SmallChart.vue'
|
|
84
|
+
import ChartViewer from './components/Chart/ChartViewer.vue'
|
|
85
|
+
import ChartViewerWrapper from './components/Chart/ChartViewerWrapper.vue'
|
|
83
86
|
import StatBox from './components/StatBox.vue'
|
|
84
87
|
import Tab from './components/Tabs/Tab.vue'
|
|
85
88
|
import TabGroup from './components/Tabs/TabGroup.vue'
|
|
@@ -94,12 +97,14 @@ import GlobalSearch from './components/Search/GlobalSearch.vue'
|
|
|
94
97
|
import SearchInput from './components/Search/SearchInput.vue'
|
|
95
98
|
import SearchableSelect from './components/Form/SearchableSelect.vue'
|
|
96
99
|
import SelectGroup from './components/Form/SelectGroup.vue'
|
|
100
|
+
import Listbox from './components/Form/Listbox.vue'
|
|
97
101
|
import type { UseFetchFunction } from './functions/api.types'
|
|
98
102
|
import { configKey, useComponentsConfig, type PluginConfig } from './config.js'
|
|
99
103
|
|
|
100
104
|
export { Toaster, toast } from 'vue-sonner'
|
|
101
105
|
|
|
102
106
|
export * from './composables/useActiveDescendant'
|
|
107
|
+
export * from './composables/useDebouncedRef'
|
|
103
108
|
export * from './composables/useMetrics'
|
|
104
109
|
export * from './composables/useReuseType'
|
|
105
110
|
export * from './composables/useTranslation'
|
|
@@ -120,6 +125,8 @@ export * from './functions/resources'
|
|
|
120
125
|
export * from './functions/reuses'
|
|
121
126
|
export * from './functions/schemas'
|
|
122
127
|
export * from './functions/users'
|
|
128
|
+
export * from './functions/tabularApi'
|
|
129
|
+
export * from './functions/charts'
|
|
123
130
|
export * from './types/access_types'
|
|
124
131
|
|
|
125
132
|
export type {
|
|
@@ -216,6 +223,23 @@ export type {
|
|
|
216
223
|
ValidataError,
|
|
217
224
|
Weight,
|
|
218
225
|
WellType,
|
|
226
|
+
Chart,
|
|
227
|
+
ChartForm,
|
|
228
|
+
ChartForApi,
|
|
229
|
+
FilterCondition,
|
|
230
|
+
Filter,
|
|
231
|
+
AndFilters,
|
|
232
|
+
GenericFilter,
|
|
233
|
+
XAxisType,
|
|
234
|
+
XAxisSortBy,
|
|
235
|
+
SortDirection,
|
|
236
|
+
XAxis,
|
|
237
|
+
XAxisForm,
|
|
238
|
+
UnitPosition,
|
|
239
|
+
YAxis,
|
|
240
|
+
DataSeriesType,
|
|
241
|
+
DataSeries,
|
|
242
|
+
DataSeriesForm,
|
|
219
243
|
}
|
|
220
244
|
|
|
221
245
|
export {
|
|
@@ -301,6 +325,8 @@ export {
|
|
|
301
325
|
SchemaCard,
|
|
302
326
|
SimpleBanner,
|
|
303
327
|
SmallChart,
|
|
328
|
+
ChartViewer,
|
|
329
|
+
ChartViewerWrapper,
|
|
304
330
|
StatBox,
|
|
305
331
|
OpenApiViewer,
|
|
306
332
|
Tab,
|
|
@@ -317,4 +343,5 @@ export {
|
|
|
317
343
|
SearchInput,
|
|
318
344
|
SearchableSelect,
|
|
319
345
|
SelectGroup,
|
|
346
|
+
Listbox,
|
|
320
347
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { TabularAggregateType } from '../functions/tabularApi'
|
|
2
|
+
import type { Owned, OwnedWithId } from './owned'
|
|
3
|
+
|
|
4
|
+
export type FilterCondition = 'exact' | 'differs' | 'is_null' | 'is_not_null' | 'greater' | 'less' | 'strictly_greater' | 'strictly_less'
|
|
5
|
+
export type Filter = {
|
|
6
|
+
_cls: 'Filter'
|
|
7
|
+
column: string
|
|
8
|
+
condition: FilterCondition
|
|
9
|
+
value: string | null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type AndFilters = {
|
|
13
|
+
_cls: 'AndFilters'
|
|
14
|
+
filters: Array<Filter | AndFilters>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type GenericFilter = Filter | AndFilters
|
|
18
|
+
|
|
19
|
+
export type XAxisType = 'discrete' | 'continuous'
|
|
20
|
+
|
|
21
|
+
export type XAxisSortBy = 'axis_x' | 'axis_y'
|
|
22
|
+
|
|
23
|
+
export type SortDirection = 'asc' | 'desc'
|
|
24
|
+
|
|
25
|
+
export type XAxis = {
|
|
26
|
+
column_x: string
|
|
27
|
+
sort_x_by: XAxisSortBy | null
|
|
28
|
+
sort_x_direction: SortDirection | null
|
|
29
|
+
type: XAxisType
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type CombinedSort = '' | 'axis_x-asc' | 'axis_x-desc' | 'axis_y-asc' | 'axis_y-desc'
|
|
33
|
+
|
|
34
|
+
export type XAxisForm = Omit<XAxis, 'sort_x_by' | 'sort_x_direction'> & { sort_combined: CombinedSort }
|
|
35
|
+
|
|
36
|
+
export type UnitPosition = 'prefix' | 'suffix'
|
|
37
|
+
|
|
38
|
+
export type YAxis = {
|
|
39
|
+
min: number | null
|
|
40
|
+
max: number | null
|
|
41
|
+
label: string | null
|
|
42
|
+
unit: string | null
|
|
43
|
+
unit_position: UnitPosition | null
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type DataSeriesType = 'line' | 'histogram'
|
|
47
|
+
|
|
48
|
+
export type DataSeries = {
|
|
49
|
+
type: DataSeriesType
|
|
50
|
+
column_y: string
|
|
51
|
+
aggregate_y: TabularAggregateType | null
|
|
52
|
+
resource_id: string
|
|
53
|
+
column_x_name_override: string | null
|
|
54
|
+
filters: GenericFilter | null
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Type for form where aggregate_y can be empty string for select binding
|
|
58
|
+
export type DataSeriesForm = Omit<DataSeries, 'aggregate_y'> & { aggregate_y: TabularAggregateType | '' | null }
|
|
59
|
+
|
|
60
|
+
export type Chart = Owned & {
|
|
61
|
+
id: string
|
|
62
|
+
title: string
|
|
63
|
+
slug: string
|
|
64
|
+
description: string
|
|
65
|
+
private: boolean
|
|
66
|
+
created_at: string
|
|
67
|
+
last_modified: string
|
|
68
|
+
deleted_at: string | null
|
|
69
|
+
uri: string
|
|
70
|
+
page: string
|
|
71
|
+
x_axis: XAxis
|
|
72
|
+
y_axis: YAxis
|
|
73
|
+
series: Array<DataSeries>
|
|
74
|
+
extras: Record<string, unknown>
|
|
75
|
+
permissions: { delete: boolean, edit: boolean, read: boolean }
|
|
76
|
+
metrics: {
|
|
77
|
+
views: number
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type ChartForApi = OwnedWithId & Pick<Chart, 'title' | 'description' | 'private' | 'x_axis' | 'y_axis' | 'series' | 'extras'>
|
|
82
|
+
|
|
83
|
+
export type ChartForm = Omit<ChartForApi, 'x_axis' | 'series' | 'owner' | 'organization'> & {
|
|
84
|
+
owned: OwnedWithId
|
|
85
|
+
x_axis: XAxisForm
|
|
86
|
+
series: Array<DataSeriesForm>
|
|
87
|
+
chart_type?: DataSeriesType | null
|
|
88
|
+
filter: GenericFilter | null
|
|
89
|
+
}
|