@datagouv/components-next 1.0.2-dev.127 → 1.0.2-dev.129
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-B1CFLBVW.js → Datafair.client-CFl7MKdB.js} +1 -1
- package/dist/{JsonPreview.client-DMal7Zvi.js → JsonPreview.client-CowJU7XP.js} +2 -2
- package/dist/{MapContainer.client-D4TU557F.js → MapContainer.client-CgdBWq2S.js} +2 -2
- package/dist/{PdfPreview.client-BPKxdMlu.js → PdfPreview.client-Dm4l4fyb.js} +2 -2
- package/dist/{Pmtiles.client-DW9JBIOy.js → Pmtiles.client-DsjzH41p.js} +1 -1
- package/dist/{PreviewWrapper.vue_vue_type_script_setup_true_lang-B54_WCDL.js → PreviewWrapper.vue_vue_type_script_setup_true_lang-BgFVrfFi.js} +1 -1
- package/dist/{XmlPreview.client-DfIA3_I8.js → XmlPreview.client-DBceFnA1.js} +3 -3
- package/dist/components-next.js +158 -153
- package/dist/components.css +1 -1
- package/dist/{index-CtZYQyKo.js → index-DWmJJEjk.js} +1 -1
- package/dist/{leaflet-src-DcM2vBl8.js → leaflet-src-CGmV0V-K.js} +1 -1
- package/dist/{main-BOGKXwyT.js → main-CQREzlRN.js} +12210 -12030
- package/dist/{vue3-xml-viewer.common-DuOzEGKy.js → vue3-xml-viewer.common-d08lX8ER.js} +1 -1
- package/package.json +1 -1
- package/src/components/Chart/ChartViewer.vue +10 -9
- package/src/components/Chart/ChartViewerWrapper.vue +20 -16
- package/src/components/TabularExplorer/TabularCellPopover.vue +2 -2
- package/src/components/TabularExplorer/TabularExplorer.vue +215 -82
- package/src/components/TabularExplorer/TabularFilterContent.vue +15 -13
- package/src/components/TabularExplorer/TabularFilterPopover.vue +21 -26
- package/src/components/TabularExplorer/types.ts +14 -11
- package/src/functions/charts.ts +12 -1
- package/src/functions/tabular.ts +112 -1
- package/src/functions/tabularApi.ts +1 -43
- package/src/main.ts +6 -1
- package/src/types/visualizations.ts +4 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Response from /api/resources/{rid}/data/ */
|
|
2
|
-
export
|
|
2
|
+
export type TabularDataResponse = {
|
|
3
3
|
data: TabularRow[]
|
|
4
4
|
meta: {
|
|
5
5
|
page: number
|
|
@@ -17,11 +17,14 @@ export interface TabularDataResponse {
|
|
|
17
17
|
export type TabularRow = Record<string, unknown> & { __id: number }
|
|
18
18
|
|
|
19
19
|
/** Response from /api/resources/{rid}/profile/ */
|
|
20
|
-
export
|
|
20
|
+
export type TabularProfileResponse = {
|
|
21
21
|
profile: TabularProfile
|
|
22
|
+
deleted_at: string | null
|
|
23
|
+
dataset_id: string
|
|
24
|
+
indexes: null
|
|
22
25
|
}
|
|
23
26
|
|
|
24
|
-
export
|
|
27
|
+
export type TabularProfile = {
|
|
25
28
|
header: string[]
|
|
26
29
|
columns: Record<string, TabularColumnInfo>
|
|
27
30
|
formats: Record<string, string[]>
|
|
@@ -31,20 +34,20 @@ export interface TabularProfile {
|
|
|
31
34
|
categorical: string[]
|
|
32
35
|
total_lines: number
|
|
33
36
|
nb_duplicates: number
|
|
34
|
-
columns_fields:
|
|
35
|
-
columns_labels:
|
|
37
|
+
columns_fields: Record<string, TabularColumnInfo>
|
|
38
|
+
columns_labels: Record<string, TabularColumnInfo>
|
|
36
39
|
header_row_idx: number
|
|
37
40
|
heading_columns: number
|
|
38
41
|
trailing_columns: number
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
export
|
|
44
|
+
export type TabularColumnInfo = {
|
|
42
45
|
score: number
|
|
43
46
|
format: string
|
|
44
47
|
python_type: string
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
export
|
|
50
|
+
export type TabularColumnProfile = {
|
|
48
51
|
tops: TabularTopValue[]
|
|
49
52
|
nb_distinct: number
|
|
50
53
|
nb_missing_values: number
|
|
@@ -54,14 +57,14 @@ export interface TabularColumnProfile {
|
|
|
54
57
|
mean?: number
|
|
55
58
|
}
|
|
56
59
|
|
|
57
|
-
export
|
|
60
|
+
export type TabularTopValue = {
|
|
58
61
|
value: string
|
|
59
62
|
count: number
|
|
60
63
|
}
|
|
61
64
|
|
|
62
65
|
export type ColumnType = 'number' | 'categorical' | 'text' | 'date' | 'boolean'
|
|
63
66
|
|
|
64
|
-
export
|
|
67
|
+
export type ColumnFilters = {
|
|
65
68
|
in?: string[]
|
|
66
69
|
exact?: string
|
|
67
70
|
min?: number
|
|
@@ -72,12 +75,12 @@ export interface ColumnFilters {
|
|
|
72
75
|
|
|
73
76
|
export type SortDirection = 'asc' | 'desc'
|
|
74
77
|
|
|
75
|
-
export
|
|
78
|
+
export type SortConfig = {
|
|
76
79
|
column: string
|
|
77
80
|
direction: SortDirection
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
export
|
|
83
|
+
export type BadgeStyle = {
|
|
81
84
|
backgroundColor: string
|
|
82
85
|
color: string
|
|
83
86
|
}
|
package/src/functions/charts.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { Chart, ChartForm, ChartForApi, Filter } from '../types/visualizations'
|
|
1
|
+
import type { Chart, ChartForm, ChartForApi, Filter, ColumnDefinition } from '../types/visualizations'
|
|
2
|
+
import type { TabularProfile } from '../components/TabularExplorer/types'
|
|
3
|
+
import { resolveColumnType } from './tabular'
|
|
2
4
|
|
|
3
5
|
export function toChartForm(chart: Chart) {
|
|
4
6
|
const seriesFilter = chart.series[0]?.filters as Filter | null
|
|
@@ -66,3 +68,12 @@ export function toChartApi(chartForm: ChartForm): ChartForApi {
|
|
|
66
68
|
extras: chartForm.extras,
|
|
67
69
|
}
|
|
68
70
|
}
|
|
71
|
+
|
|
72
|
+
export function buildColumnsFromProfile(profile: { profile: TabularProfile }): Array<ColumnDefinition> {
|
|
73
|
+
return profile.profile.header.map((name) => {
|
|
74
|
+
const colInfo = profile.profile.columns[name]
|
|
75
|
+
const isCategorical = profile.profile.categorical.includes(name)
|
|
76
|
+
const colType = resolveColumnType(colInfo ?? { python_type: 'unknown', format: undefined }, isCategorical)
|
|
77
|
+
return { name, type: colType }
|
|
78
|
+
})
|
|
79
|
+
}
|
package/src/functions/tabular.ts
CHANGED
|
@@ -4,9 +4,24 @@ import {
|
|
|
4
4
|
RiPriceTag3Line,
|
|
5
5
|
RiText,
|
|
6
6
|
RiCalendarLine,
|
|
7
|
+
RiCalendarEventLine,
|
|
8
|
+
RiTimeLine,
|
|
7
9
|
RiCheckboxLine,
|
|
10
|
+
RiMapPin2Line,
|
|
11
|
+
RiGlobalLine,
|
|
12
|
+
RiFocus3Line,
|
|
13
|
+
RiFingerprintLine,
|
|
14
|
+
RiMailLine,
|
|
15
|
+
RiLinksLine,
|
|
16
|
+
RiPhoneLine,
|
|
17
|
+
RiUserLine,
|
|
18
|
+
RiMoneyEuroCircleLine,
|
|
19
|
+
RiPercentLine,
|
|
20
|
+
RiBracesLine,
|
|
21
|
+
RiCodeLine,
|
|
8
22
|
} from '@remixicon/vue'
|
|
9
23
|
import { useTranslation } from '../composables/useTranslation'
|
|
24
|
+
import type { TranslationFunction } from '../composables/useTranslation'
|
|
10
25
|
import type { ColumnFilters, ColumnType } from '../components/TabularExplorer/types'
|
|
11
26
|
|
|
12
27
|
export function hasFilterForColumn(filters: Record<string, ColumnFilters>, column: string): boolean {
|
|
@@ -15,7 +30,12 @@ export function hasFilterForColumn(filters: Record<string, ColumnFilters>, colum
|
|
|
15
30
|
return !!(f.in?.length || f.exact != null || f.contains || f.null || f.min != null || f.max != null)
|
|
16
31
|
}
|
|
17
32
|
|
|
18
|
-
export
|
|
33
|
+
export type TypeDisplay = {
|
|
34
|
+
icon: Component
|
|
35
|
+
label: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function buildTypeConfig(t: TranslationFunction): Record<ColumnType, TypeDisplay> {
|
|
19
39
|
return {
|
|
20
40
|
number: { icon: RiHashtag, label: t('Nombre') },
|
|
21
41
|
categorical: { icon: RiPriceTag3Line, label: t('Catégoriel') },
|
|
@@ -25,6 +45,97 @@ export function buildTypeConfig(t: (s: string) => string): Record<ColumnType, {
|
|
|
25
45
|
}
|
|
26
46
|
}
|
|
27
47
|
|
|
48
|
+
export function resolveColumnType(colInfo: { python_type: string, format?: string }, isCategorical: boolean): ColumnType {
|
|
49
|
+
if (['int', 'float'].includes(colInfo.python_type)) return 'number'
|
|
50
|
+
if (colInfo.format === 'year') return 'date'
|
|
51
|
+
if (['date', 'datetime'].includes(colInfo.python_type)) return 'date'
|
|
52
|
+
if (colInfo.python_type === 'bool') return 'boolean'
|
|
53
|
+
if (isCategorical) return 'categorical'
|
|
54
|
+
return 'text'
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// csv-detective formats that carry no semantic meaning beyond the generic
|
|
58
|
+
// display type already resolved by `ColumnType` — these fall back to
|
|
59
|
+
// `buildTypeConfig` (Texte / Nombre / Date / Booléen) in the header.
|
|
60
|
+
export const GENERIC_FORMATS = new Set(['string', 'int', 'float', 'date', 'bool', 'booleen'])
|
|
61
|
+
|
|
62
|
+
// Semantic types detected by csv-detective (see ../../../csv-detective/csv_detective/formats).
|
|
63
|
+
// The list is intentionally exhaustive, but unknown formats are tolerated:
|
|
64
|
+
// `getColumnDisplay` humanizes any format missing from this map.
|
|
65
|
+
export function buildFormatConfig(t: TranslationFunction): Record<string, TypeDisplay> {
|
|
66
|
+
return {
|
|
67
|
+
// Geo — territories & addresses
|
|
68
|
+
adresse: { icon: RiMapPin2Line, label: t('Adresse') },
|
|
69
|
+
commune: { icon: RiMapPin2Line, label: t('Commune') },
|
|
70
|
+
code_commune: { icon: RiMapPin2Line, label: t('Code INSEE commune') },
|
|
71
|
+
code_commune_insee: { icon: RiMapPin2Line, label: t('Code INSEE commune') },
|
|
72
|
+
departement: { icon: RiMapPin2Line, label: t('Département') },
|
|
73
|
+
code_departement: { icon: RiMapPin2Line, label: t('Code département') },
|
|
74
|
+
region: { icon: RiMapPin2Line, label: t('Région') },
|
|
75
|
+
code_region: { icon: RiMapPin2Line, label: t('Code région') },
|
|
76
|
+
code_epci: { icon: RiMapPin2Line, label: t('Code EPCI') },
|
|
77
|
+
code_postal: { icon: RiMapPin2Line, label: t('Code postal') },
|
|
78
|
+
insee_canton: { icon: RiMapPin2Line, label: t('Canton') },
|
|
79
|
+
code_fantoir: { icon: RiMapPin2Line, label: t('Code FANTOIR') },
|
|
80
|
+
id_rnb: { icon: RiMapPin2Line, label: t('Identifiant RNB') },
|
|
81
|
+
// Geo — countries
|
|
82
|
+
pays: { icon: RiGlobalLine, label: t('Pays') },
|
|
83
|
+
iso_country_code_alpha2: { icon: RiGlobalLine, label: t('Code pays (ISO α-2)') },
|
|
84
|
+
iso_country_code_alpha3: { icon: RiGlobalLine, label: t('Code pays (ISO α-3)') },
|
|
85
|
+
iso_country_code_numeric: { icon: RiGlobalLine, label: t('Code pays (ISO num.)') },
|
|
86
|
+
// Geo — coordinates
|
|
87
|
+
latitude_wgs: { icon: RiFocus3Line, label: t('Latitude') },
|
|
88
|
+
latitude_wgs_fr_metropole: { icon: RiFocus3Line, label: t('Latitude') },
|
|
89
|
+
longitude_wgs: { icon: RiFocus3Line, label: t('Longitude') },
|
|
90
|
+
longitude_wgs_fr_metropole: { icon: RiFocus3Line, label: t('Longitude') },
|
|
91
|
+
latitude_l93: { icon: RiFocus3Line, label: t('Latitude (Lambert 93)') },
|
|
92
|
+
longitude_l93: { icon: RiFocus3Line, label: t('Longitude (Lambert 93)') },
|
|
93
|
+
latlon_wgs: { icon: RiFocus3Line, label: t('Latitude / longitude') },
|
|
94
|
+
lonlat_wgs: { icon: RiFocus3Line, label: t('Longitude / latitude') },
|
|
95
|
+
// Identifiers
|
|
96
|
+
siren: { icon: RiFingerprintLine, label: t('SIREN') },
|
|
97
|
+
siret: { icon: RiFingerprintLine, label: t('SIRET') },
|
|
98
|
+
code_rna: { icon: RiFingerprintLine, label: t('Identifiant RNA') },
|
|
99
|
+
code_waldec: { icon: RiFingerprintLine, label: t('Identifiant WALDEC') },
|
|
100
|
+
code_import: { icon: RiFingerprintLine, label: t('Code Import') },
|
|
101
|
+
uai: { icon: RiFingerprintLine, label: t('UAI') },
|
|
102
|
+
insee_ape700: { icon: RiFingerprintLine, label: t('Code APE') },
|
|
103
|
+
code_csp_insee: { icon: RiFingerprintLine, label: t('Code CSP') },
|
|
104
|
+
uuid: { icon: RiFingerprintLine, label: t('UUID') },
|
|
105
|
+
mongo_object_id: { icon: RiFingerprintLine, label: t('Identifiant Mongo') },
|
|
106
|
+
// Contact
|
|
107
|
+
email: { icon: RiMailLine, label: t('Email') },
|
|
108
|
+
url: { icon: RiLinksLine, label: t('URL') },
|
|
109
|
+
tel_fr: { icon: RiPhoneLine, label: t('Téléphone') },
|
|
110
|
+
username: { icon: RiUserLine, label: t('Nom d\'utilisateur') },
|
|
111
|
+
// People
|
|
112
|
+
sexe: { icon: RiUserLine, label: t('Sexe') },
|
|
113
|
+
csp_insee: { icon: RiUserLine, label: t('Catégorie socio-pro.') },
|
|
114
|
+
// Quantities
|
|
115
|
+
money: { icon: RiMoneyEuroCircleLine, label: t('Montant') },
|
|
116
|
+
percent: { icon: RiPercentLine, label: t('Pourcentage') },
|
|
117
|
+
// Temporal
|
|
118
|
+
year: { icon: RiCalendarLine, label: t('Année') },
|
|
119
|
+
date_fr: { icon: RiCalendarLine, label: t('Date') },
|
|
120
|
+
jour_de_la_semaine: { icon: RiCalendarEventLine, label: t('Jour de la semaine') },
|
|
121
|
+
mois_de_lannee: { icon: RiCalendarEventLine, label: t('Mois de l\'année') },
|
|
122
|
+
datetime_naive: { icon: RiTimeLine, label: t('Date et heure') },
|
|
123
|
+
datetime_aware: { icon: RiTimeLine, label: t('Date et heure') },
|
|
124
|
+
datetime_rfc822: { icon: RiTimeLine, label: t('Date et heure') },
|
|
125
|
+
// Structured
|
|
126
|
+
json: { icon: RiBracesLine, label: t('JSON') },
|
|
127
|
+
geojson: { icon: RiBracesLine, label: t('GeoJSON') },
|
|
128
|
+
binary: { icon: RiCodeLine, label: t('Binaire') },
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Tolerant fallback for a semantic format we don't explicitly know about:
|
|
133
|
+
// "code_truc_machin" -> "Code truc machin".
|
|
134
|
+
export function humanizeFormat(format: string): string {
|
|
135
|
+
const spaced = format.replace(/_/g, ' ').trim()
|
|
136
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1)
|
|
137
|
+
}
|
|
138
|
+
|
|
28
139
|
export function useFormatTabular() {
|
|
29
140
|
const { locale } = useTranslation()
|
|
30
141
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ofetch } from 'ofetch'
|
|
2
2
|
import { useComponentsConfig, type PluginConfig } from '../config'
|
|
3
3
|
import type { GenericFilter } from '../types/visualizations'
|
|
4
|
-
import type { SortConfig } from '../components/TabularExplorer/types'
|
|
4
|
+
import type { SortConfig, TabularProfileResponse } from '../components/TabularExplorer/types'
|
|
5
5
|
|
|
6
6
|
export type { SortConfig }
|
|
7
7
|
|
|
@@ -31,48 +31,6 @@ export type FetchTabularDataOptions = {
|
|
|
31
31
|
filters?: GenericFilter | undefined
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
export type TabularProfileResponse = {
|
|
35
|
-
profile: {
|
|
36
|
-
header: Array<string>
|
|
37
|
-
columns: Record<string, {
|
|
38
|
-
score: number
|
|
39
|
-
format: string
|
|
40
|
-
python_type: string
|
|
41
|
-
}>
|
|
42
|
-
formats: Record<string, Array<string>>
|
|
43
|
-
profile: Record<string, {
|
|
44
|
-
tops: Array<{ count: number, value: string }>
|
|
45
|
-
nb_distinct: number
|
|
46
|
-
nb_missing_values: number
|
|
47
|
-
min?: number
|
|
48
|
-
max?: number
|
|
49
|
-
std?: number
|
|
50
|
-
mean?: number
|
|
51
|
-
}>
|
|
52
|
-
encoding: string
|
|
53
|
-
separator: string
|
|
54
|
-
categorical: Array<string>
|
|
55
|
-
total_lines: number
|
|
56
|
-
nb_duplicates: number
|
|
57
|
-
columns_fields: Record<string, {
|
|
58
|
-
score: number
|
|
59
|
-
format: string
|
|
60
|
-
python_type: string
|
|
61
|
-
}>
|
|
62
|
-
columns_labels: Record<string, {
|
|
63
|
-
score: number
|
|
64
|
-
format: string
|
|
65
|
-
python_type: string
|
|
66
|
-
}>
|
|
67
|
-
header_row_idx: number
|
|
68
|
-
heading_columns: number
|
|
69
|
-
trailing_columns: number
|
|
70
|
-
}
|
|
71
|
-
deleted_at: string | null
|
|
72
|
-
dataset_id: string
|
|
73
|
-
indexes: null
|
|
74
|
-
}
|
|
75
|
-
|
|
76
34
|
/**
|
|
77
35
|
* Call Tabular-api to get table content with options object
|
|
78
36
|
*/
|
package/src/main.ts
CHANGED
|
@@ -23,7 +23,8 @@ 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
|
+
import type { Chart, ChartForm, ChartForApi, FilterCondition, Filter, AndFilters, GenericFilter, XAxisType, XAxisSortBy, SortDirection, XAxis, XAxisForm, UnitPosition, YAxis, DataSeriesType, DataSeries, DataSeriesForm, CombinedSort, ColumnDefinition, ColumnsDefinition } from './types/visualizations'
|
|
27
|
+
import type { ColumnType } from './components/TabularExplorer/types'
|
|
27
28
|
import type { GlobalSearchConfig, SearchType, SearchTypeConfig, SortOption, HiddenFilter, BuiltInFilterKey, DatasetSearchConfig, DatasetSearchFilters, DataserviceSearchConfig, DataserviceSearchFilters, ReuseSearchConfig, ReuseSearchFilters, OrganizationSearchConfig, OrganizationSearchFilters, TopicSearchConfig, TopicSearchFilters } from './types/search'
|
|
28
29
|
import { getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultTopicConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search'
|
|
29
30
|
import { useSearchFilter } from './composables/useSearchFilter'
|
|
@@ -251,6 +252,10 @@ export type {
|
|
|
251
252
|
Chart,
|
|
252
253
|
ChartForm,
|
|
253
254
|
ChartForApi,
|
|
255
|
+
CombinedSort,
|
|
256
|
+
ColumnDefinition,
|
|
257
|
+
ColumnType,
|
|
258
|
+
ColumnsDefinition,
|
|
254
259
|
FilterCondition,
|
|
255
260
|
Filter,
|
|
256
261
|
AndFilters,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { TabularAggregateType } from '../functions/tabularApi'
|
|
2
2
|
import type { Owned, OwnedWithId } from './owned'
|
|
3
|
+
import type { ColumnType } from '../components/TabularExplorer/types'
|
|
3
4
|
|
|
4
5
|
export type FilterCondition = 'exact' | 'differs' | 'is_null' | 'is_not_null' | 'greater' | 'less' | 'strictly_greater' | 'strictly_less'
|
|
5
6
|
export type Filter = {
|
|
@@ -87,3 +88,6 @@ export type ChartForm = Omit<ChartForApi, 'x_axis' | 'series' | 'owner' | 'organ
|
|
|
87
88
|
chart_type?: DataSeriesType | null
|
|
88
89
|
filter: GenericFilter | null
|
|
89
90
|
}
|
|
91
|
+
|
|
92
|
+
export type ColumnDefinition = { name: string, type: ColumnType }
|
|
93
|
+
export type ColumnsDefinition = Record<string, Array<ColumnDefinition>>
|