@datagouv/components-next 1.0.2-dev.20 → 1.0.2-dev.200
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/README.md +7 -6
- package/assets/main.css +4 -0
- package/dist/{Control-DuZJdKV_.js → Control-B9WQxlpJ.js} +1 -1
- package/dist/{Datafair.client-Ds3VQrRi.js → Datafair.client-CFTmBFoY.js} +9 -9
- package/dist/{Event--kp8kMdJ.js → Event-iXDrp-fy.js} +31 -31
- package/dist/{Image-34hvypZI.js → Image-mNMBOofs.js} +9 -9
- package/dist/ImagePreview.client-BvDM3qjE.js +36 -0
- package/dist/JsonPreview.client-BP6gPRxf.js +40 -0
- package/dist/{Map-BjUnLyj8.js → Map-BfqKMw0S.js} +1739 -1599
- package/dist/{MapContainer.client-B2BijMx5.js → MapContainer.client-D9N3664r.js} +41 -42
- package/dist/{OSM-s40W6sQ2.js → OSM-CcrUhItr.js} +15 -23
- package/dist/{PdfPreview.client-DJBMzrlC.js → PdfPreview.client-C6A6ZiKl.js} +835 -856
- package/dist/Pmtiles.client-B_sDZoqu.js +26333 -0
- package/dist/PreviewWrapper.vue_vue_type_script_setup_true_lang-DGLXBys_.js +60 -0
- package/dist/{ScaleLine-KW-nXqp3.js → ScaleLine-VGQ7nkMS.js} +2 -2
- package/dist/{Tile-DbNFNPfU.js → Tile-CSpn0Ca8.js} +160 -163
- package/dist/{TileImage-BsXBxMtq.js → TileImage-CpbaEFwd.js} +143 -131
- package/dist/{View-BR92hTWP.js → View-BYBpt-AU.js} +483 -422
- package/dist/XmlPreview.client-DFQ1T-LN.js +34 -0
- package/dist/{common-PJfpC179.js → common-BoeTUnDZ.js} +52 -52
- package/dist/components-next.css +1 -52
- package/dist/components-next.js +196 -150
- package/dist/components.css +2 -2
- package/dist/{index-BFQX7Ccz.js → index-B_tPYi5Z.js} +34094 -27864
- package/dist/{leaflet-src-7m1mB8LI.js → leaflet-src-PeylHk0o.js} +162 -164
- package/dist/{main-vqhkVhVS.js → main-CVOZp_Nx.js} +41939 -73132
- package/dist/{proj-DsetBcW7.js → proj-DxGbobp7.js} +662 -626
- package/dist/{text-clamp.esm-B5kW_XMt.js → text-clamp.esm-DVseBqZZ.js} +4 -4
- package/dist/{tilecoord-Db24Px13.js → tilecoord-DvX7WWiA.js} +273 -264
- package/dist/{vue3-json-viewer-BXwup7nO.js → vue3-json-viewer-CJLQFzXZ.js} +10 -16
- package/dist/{vue3-xml-viewer.common-BcNJo35o.js → vue3-xml-viewer.common-CcF3Xd23.js} +1 -1
- package/package.json +47 -38
- package/src/chart.ts +5 -0
- package/src/components/ActivityList/ActivityList.vue +24 -14
- package/src/components/AppLink.vue +3 -0
- package/src/components/BannerAction.vue +6 -2
- package/src/components/Chart/ChartViewer.vue +320 -0
- package/src/components/Chart/ChartViewerWrapper.vue +182 -0
- package/src/components/CopyButton.vue +6 -2
- package/src/components/DataserviceCard.vue +24 -5
- package/src/components/DataserviceQuality.vue +82 -0
- package/src/components/DataserviceQualityInline.vue +31 -0
- package/src/components/DataserviceQualityTooltipContent.vue +79 -0
- package/src/components/DatasetCard.vue +24 -9
- package/src/components/DatasetInformation/DatasetTemporalitySection.vue +7 -4
- package/src/components/DatasetQuality.vue +11 -11
- package/src/components/DatasetQualityInline.vue +2 -2
- package/src/components/DatasetQualityTooltipContent.vue +1 -1
- package/src/components/DiscussionMessageCard.vue +14 -15
- package/src/components/Form/Listbox.vue +101 -0
- package/src/components/Form/SchemaSelect.vue +2 -0
- package/src/components/FormattedDate.vue +81 -0
- package/src/components/InfiniteLoader.vue +53 -0
- package/src/components/LoadingBlock.vue +4 -1
- package/src/components/ObjectCardHeader.vue +11 -4
- package/src/components/OpenApiViewer/ContentTypeSelect.vue +48 -0
- package/src/components/OpenApiViewer/EndpointRequest.vue +164 -0
- package/src/components/OpenApiViewer/EndpointResponses.vue +149 -0
- package/src/components/OpenApiViewer/OpenApiViewer.vue +308 -0
- package/src/components/OpenApiViewer/SchemaPanel.vue +53 -0
- package/src/components/OpenApiViewer/SchemaTree.vue +77 -0
- package/src/components/OpenApiViewer/openapi.ts +150 -0
- package/src/components/OrganizationNameWithCertificate.vue +3 -2
- package/src/components/Pagination.vue +25 -62
- package/src/components/PostCard.vue +13 -15
- package/src/components/RadioInput.vue +7 -2
- package/src/components/ResourceAccordion/DataStructure.vue +11 -33
- package/src/components/ResourceAccordion/Datafair.client.vue +1 -1
- package/src/components/ResourceAccordion/Downloads.vue +172 -0
- package/src/components/ResourceAccordion/ImagePreview.client.vue +48 -0
- package/src/components/ResourceAccordion/JsonPreview.client.vue +23 -104
- package/src/components/ResourceAccordion/MapContainer.client.vue +2 -11
- package/src/components/ResourceAccordion/Metadata.vue +4 -6
- package/src/components/ResourceAccordion/PdfPreview.client.vue +58 -97
- package/src/components/ResourceAccordion/PdfSkeleton.vue +44 -0
- package/src/components/ResourceAccordion/Pmtiles.client.vue +28 -13
- package/src/components/ResourceAccordion/Preview.vue +19 -15
- package/src/components/ResourceAccordion/PreviewWrapper.vue +89 -0
- package/src/components/ResourceAccordion/ResourceAccordion.vue +36 -117
- package/src/components/ResourceAccordion/XmlPreview.client.vue +16 -98
- package/src/components/ResourceExplorer/ResourceExplorer.vue +105 -210
- package/src/components/ResourceExplorer/ResourceExplorerHeader.vue +79 -0
- package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +104 -71
- package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +143 -291
- package/src/components/ResourceExplorer/ResourceMainAction.vue +240 -0
- package/src/components/ResourceExplorer/ResourceSelector.vue +51 -0
- package/src/components/ResourceExplorer/ResourceViewerHeader.vue +122 -0
- package/src/components/ResourceExplorer/ResourceViewerSkeleton.vue +94 -0
- package/src/components/ResourceListItem.vue +168 -0
- package/src/components/ReuseCard.vue +28 -9
- package/src/components/ReuseDetails.vue +2 -2
- package/src/components/ReuseHorizontalCard.vue +2 -2
- package/src/components/SchemaCard.vue +10 -1
- package/src/components/Search/Filter/AccessTypeFilter.vue +2 -2
- package/src/components/Search/GlobalSearch.vue +229 -123
- package/src/components/Search/SearchInput.vue +5 -4
- package/src/components/Search/Sidemenu.vue +4 -3
- package/src/components/SmallChart.vue +11 -10
- package/src/components/StatBox.vue +13 -5
- package/src/components/TabularExplorer/TabularActiveFilters.vue +79 -0
- package/src/components/TabularExplorer/TabularCell.vue +50 -0
- package/src/components/TabularExplorer/TabularCellPopover.vue +170 -0
- package/src/components/TabularExplorer/TabularColumnsMenu.vue +112 -0
- package/src/components/TabularExplorer/TabularExplorer.vue +299 -0
- package/src/components/TabularExplorer/TabularFilterContent.vue +362 -0
- package/src/components/TabularExplorer/TabularFilterPopover.vue +106 -0
- package/src/components/TabularExplorer/TabularMobileFilterButton.vue +21 -0
- package/src/components/TabularExplorer/TabularMobileFilters.vue +150 -0
- package/src/components/TabularExplorer/TabularRowsInfo.vue +31 -0
- package/src/components/TabularExplorer/TabularSkeleton.vue +92 -0
- package/src/components/TabularExplorer/TabularTable.vue +481 -0
- package/src/components/TabularExplorer/TabularToolbar.vue +25 -0
- package/src/components/TabularExplorer/types.ts +84 -0
- package/src/components/TabularExplorer/useColumnMetadata.ts +98 -0
- package/src/components/TabularExplorer/useTabularContext.ts +82 -0
- package/src/components/TopicCard.vue +13 -14
- package/src/composables/useActiveDescendant.ts +5 -0
- package/src/composables/useDatasetResources.ts +164 -0
- package/src/composables/useHasTabularData.ts +15 -1
- package/src/composables/useMetrics.ts +1 -1
- package/src/composables/useResizable.ts +46 -0
- package/src/composables/useResourceCapabilities.ts +48 -40
- package/src/composables/useSearchFilter.ts +120 -0
- package/src/composables/useStableQueryParams.ts +38 -6
- package/src/composables/useTabularProfile.ts +70 -0
- package/src/composables/useTranslation.ts +24 -9
- package/src/config.ts +21 -3
- package/src/functions/activities.ts +3 -3
- package/src/functions/api.ts +20 -42
- package/src/functions/api.types.ts +1 -0
- package/src/functions/charts.ts +99 -0
- package/src/functions/datasets.ts +0 -17
- package/src/functions/dates.ts +6 -7
- package/src/functions/helpers.ts +15 -0
- package/src/functions/metrics.ts +63 -60
- package/src/functions/paginate.ts +46 -0
- package/src/functions/resourceCapabilities.ts +34 -0
- package/src/functions/resources.ts +136 -1
- package/src/functions/schemas.ts +27 -0
- package/src/functions/scroll.ts +20 -0
- package/src/functions/tabular.ts +214 -0
- package/src/functions/tabularApi.ts +96 -11
- package/src/main.ts +119 -14
- package/src/types/dataservices.ts +17 -0
- package/src/types/organizations.ts +10 -0
- package/src/types/pages.ts +0 -5
- package/src/types/posts.ts +2 -2
- package/src/types/reports.ts +5 -1
- package/src/types/resources.ts +0 -1
- package/src/types/reuses.ts +12 -1
- package/src/types/search.ts +63 -1
- package/src/types/site.ts +5 -3
- package/src/types/ui.ts +2 -0
- package/src/types/users.ts +2 -1
- package/src/types/visualizations.ts +93 -0
- package/assets/swagger-themes/newspaper.css +0 -1670
- package/dist/JsonPreview.client-CYxmz0yV.js +0 -72
- package/dist/Pmtiles.client-C_hvRDuy.js +0 -25185
- package/dist/Swagger.client-B4y0hXME.js +0 -4
- package/dist/XmlPreview.client-LETEfNBH.js +0 -64
- package/src/components/ResourceAccordion/Swagger.client.vue +0 -48
- package/src/functions/pagination.ts +0 -9
- /package/src/components/{DatasetQualityItem.vue → QualityItem.vue} +0 -0
- /package/src/components/{DatasetQualityItemWarning.vue → QualityItemWarning.vue} +0 -0
- /package/src/components/{DatasetQualityScore.vue → QualityScore.vue} +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import type { Component } from 'vue'
|
|
2
|
+
import {
|
|
3
|
+
RiHashtag,
|
|
4
|
+
RiPriceTag3Line,
|
|
5
|
+
RiText,
|
|
6
|
+
RiCalendarLine,
|
|
7
|
+
RiCalendarEventLine,
|
|
8
|
+
RiTimeLine,
|
|
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,
|
|
22
|
+
} from '@remixicon/vue'
|
|
23
|
+
import { useTranslation } from '../composables/useTranslation'
|
|
24
|
+
import type { TranslationFunction } from '../composables/useTranslation'
|
|
25
|
+
import type { ColumnFilters, ColumnType } from '../components/TabularExplorer/types'
|
|
26
|
+
|
|
27
|
+
export function hasFilterForColumn(filters: Record<string, ColumnFilters>, column: string): boolean {
|
|
28
|
+
const f = filters[column]
|
|
29
|
+
if (!f) return false
|
|
30
|
+
return !!(f.in?.length || f.exact != null || f.contains || f.null || f.min != null || f.max != null)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type TypeDisplay = {
|
|
34
|
+
icon: Component
|
|
35
|
+
label: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function buildTypeConfig(t: TranslationFunction): Record<ColumnType, TypeDisplay> {
|
|
39
|
+
return {
|
|
40
|
+
number: { icon: RiHashtag, label: t('Nombre') },
|
|
41
|
+
categorical: { icon: RiPriceTag3Line, label: t('Catégoriel') },
|
|
42
|
+
text: { icon: RiText, label: t('Texte') },
|
|
43
|
+
date: { icon: RiCalendarLine, label: t('Date') },
|
|
44
|
+
boolean: { icon: RiCheckboxLine, label: t('Booléen') },
|
|
45
|
+
year: { icon: RiCalendarLine, label: t('Année') },
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function resolveColumnType(colInfo: { python_type: string, format?: string }, isCategorical: boolean): ColumnType {
|
|
50
|
+
if (colInfo.format === 'year') return 'year'
|
|
51
|
+
if (['int', 'float'].includes(colInfo.python_type)) return 'number'
|
|
52
|
+
if (['date', 'datetime'].includes(colInfo.python_type)) return 'date'
|
|
53
|
+
if (colInfo.python_type === 'bool') return 'boolean'
|
|
54
|
+
if (isCategorical) return 'categorical'
|
|
55
|
+
return 'text'
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// csv-detective formats that carry no semantic meaning beyond the generic
|
|
59
|
+
// display type already resolved by `ColumnType` — these fall back to
|
|
60
|
+
// `buildTypeConfig` (Texte / Nombre / Date / Booléen) in the header.
|
|
61
|
+
export const GENERIC_FORMATS = new Set(['string', 'int', 'float', 'date', 'bool', 'booleen'])
|
|
62
|
+
|
|
63
|
+
// Semantic types detected by csv-detective (see ../../../csv-detective/csv_detective/formats).
|
|
64
|
+
// The list is intentionally exhaustive, but unknown formats are tolerated:
|
|
65
|
+
// `getColumnDisplay` humanizes any format missing from this map.
|
|
66
|
+
export function buildFormatConfig(t: TranslationFunction): Record<string, TypeDisplay> {
|
|
67
|
+
return {
|
|
68
|
+
// Geo — territories & addresses
|
|
69
|
+
adresse: { icon: RiMapPin2Line, label: t('Adresse') },
|
|
70
|
+
commune: { icon: RiMapPin2Line, label: t('Commune') },
|
|
71
|
+
code_commune: { icon: RiMapPin2Line, label: t('Code INSEE commune') },
|
|
72
|
+
code_commune_insee: { icon: RiMapPin2Line, label: t('Code INSEE commune') },
|
|
73
|
+
departement: { icon: RiMapPin2Line, label: t('Département') },
|
|
74
|
+
code_departement: { icon: RiMapPin2Line, label: t('Code département') },
|
|
75
|
+
region: { icon: RiMapPin2Line, label: t('Région') },
|
|
76
|
+
code_region: { icon: RiMapPin2Line, label: t('Code région') },
|
|
77
|
+
code_epci: { icon: RiMapPin2Line, label: t('Code EPCI') },
|
|
78
|
+
code_postal: { icon: RiMapPin2Line, label: t('Code postal') },
|
|
79
|
+
insee_canton: { icon: RiMapPin2Line, label: t('Canton') },
|
|
80
|
+
code_fantoir: { icon: RiMapPin2Line, label: t('Code FANTOIR') },
|
|
81
|
+
id_rnb: { icon: RiMapPin2Line, label: t('Identifiant RNB') },
|
|
82
|
+
// Geo — countries
|
|
83
|
+
pays: { icon: RiGlobalLine, label: t('Pays') },
|
|
84
|
+
iso_country_code_alpha2: { icon: RiGlobalLine, label: t('Code pays (ISO α-2)') },
|
|
85
|
+
iso_country_code_alpha3: { icon: RiGlobalLine, label: t('Code pays (ISO α-3)') },
|
|
86
|
+
iso_country_code_numeric: { icon: RiGlobalLine, label: t('Code pays (ISO num.)') },
|
|
87
|
+
// Geo — coordinates
|
|
88
|
+
latitude_wgs: { icon: RiFocus3Line, label: t('Latitude') },
|
|
89
|
+
latitude_wgs_fr_metropole: { icon: RiFocus3Line, label: t('Latitude') },
|
|
90
|
+
longitude_wgs: { icon: RiFocus3Line, label: t('Longitude') },
|
|
91
|
+
longitude_wgs_fr_metropole: { icon: RiFocus3Line, label: t('Longitude') },
|
|
92
|
+
latitude_l93: { icon: RiFocus3Line, label: t('Latitude (Lambert 93)') },
|
|
93
|
+
longitude_l93: { icon: RiFocus3Line, label: t('Longitude (Lambert 93)') },
|
|
94
|
+
latlon_wgs: { icon: RiFocus3Line, label: t('Latitude / longitude') },
|
|
95
|
+
lonlat_wgs: { icon: RiFocus3Line, label: t('Longitude / latitude') },
|
|
96
|
+
// Identifiers
|
|
97
|
+
siren: { icon: RiFingerprintLine, label: t('SIREN') },
|
|
98
|
+
siret: { icon: RiFingerprintLine, label: t('SIRET') },
|
|
99
|
+
code_rna: { icon: RiFingerprintLine, label: t('Identifiant RNA') },
|
|
100
|
+
code_waldec: { icon: RiFingerprintLine, label: t('Identifiant WALDEC') },
|
|
101
|
+
code_import: { icon: RiFingerprintLine, label: t('Code Import') },
|
|
102
|
+
uai: { icon: RiFingerprintLine, label: t('UAI') },
|
|
103
|
+
insee_ape700: { icon: RiFingerprintLine, label: t('Code APE') },
|
|
104
|
+
code_csp_insee: { icon: RiFingerprintLine, label: t('Code CSP') },
|
|
105
|
+
uuid: { icon: RiFingerprintLine, label: t('UUID') },
|
|
106
|
+
mongo_object_id: { icon: RiFingerprintLine, label: t('Identifiant Mongo') },
|
|
107
|
+
// Contact
|
|
108
|
+
email: { icon: RiMailLine, label: t('Email') },
|
|
109
|
+
url: { icon: RiLinksLine, label: t('URL') },
|
|
110
|
+
tel_fr: { icon: RiPhoneLine, label: t('Téléphone') },
|
|
111
|
+
username: { icon: RiUserLine, label: t('Nom d\'utilisateur') },
|
|
112
|
+
// People
|
|
113
|
+
sexe: { icon: RiUserLine, label: t('Sexe') },
|
|
114
|
+
csp_insee: { icon: RiUserLine, label: t('Catégorie socio-pro.') },
|
|
115
|
+
// Quantities
|
|
116
|
+
money: { icon: RiMoneyEuroCircleLine, label: t('Montant') },
|
|
117
|
+
percent: { icon: RiPercentLine, label: t('Pourcentage') },
|
|
118
|
+
// Temporal
|
|
119
|
+
year: { icon: RiCalendarLine, label: t('Année') },
|
|
120
|
+
date_fr: { icon: RiCalendarLine, label: t('Date') },
|
|
121
|
+
jour_de_la_semaine: { icon: RiCalendarEventLine, label: t('Jour de la semaine') },
|
|
122
|
+
mois_de_lannee: { icon: RiCalendarEventLine, label: t('Mois de l\'année') },
|
|
123
|
+
datetime_naive: { icon: RiTimeLine, label: t('Date et heure') },
|
|
124
|
+
datetime_aware: { icon: RiTimeLine, label: t('Date et heure') },
|
|
125
|
+
datetime_rfc822: { icon: RiTimeLine, label: t('Date et heure') },
|
|
126
|
+
// Structured
|
|
127
|
+
json: { icon: RiBracesLine, label: t('JSON') },
|
|
128
|
+
geojson: { icon: RiBracesLine, label: t('GeoJSON') },
|
|
129
|
+
binary: { icon: RiCodeLine, label: t('Binaire') },
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Tolerant fallback for a semantic format we don't explicitly know about:
|
|
134
|
+
// "code_truc_machin" -> "Code truc machin".
|
|
135
|
+
export function humanizeFormat(format: string): string {
|
|
136
|
+
const spaced = format.replace(/_/g, ' ').trim()
|
|
137
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function useFormatTabular() {
|
|
141
|
+
const { locale } = useTranslation()
|
|
142
|
+
|
|
143
|
+
function formatNumber(value: unknown): string {
|
|
144
|
+
const num = Number(value)
|
|
145
|
+
if (Number.isNaN(num)) return String(value)
|
|
146
|
+
return num.toLocaleString(locale)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function formatCellDate(value: unknown): string {
|
|
150
|
+
if (value == null || value === '') return '–'
|
|
151
|
+
const d = new Date(String(value))
|
|
152
|
+
if (Number.isNaN(d.getTime())) return String(value)
|
|
153
|
+
return new Intl.DateTimeFormat(locale, { day: '2-digit', month: '2-digit', year: 'numeric' }).format(d)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return { formatNumber, formatCellDate }
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const TRUTHY_VALUES = ['true', '1', 'oui', 'yes']
|
|
160
|
+
const FALSY_VALUES = ['false', '0', 'non', 'no']
|
|
161
|
+
|
|
162
|
+
// `encodeURIComponent` leaves `.`, `(` and `)` as-is, but they are the operator
|
|
163
|
+
// separator and the delimiters of the API's `or(...)` grammar: a search value
|
|
164
|
+
// containing one makes the parser reject the whole query with a 400. Wrapping
|
|
165
|
+
// the value in double quotes (as the API README suggests) does not work here —
|
|
166
|
+
// the API keeps them as part of the searched string and returns no result. It
|
|
167
|
+
// does percent-decode the value after parsing, so encoding them is enough.
|
|
168
|
+
function encodeConditionValue(value: string): string {
|
|
169
|
+
return encodeURIComponent(value)
|
|
170
|
+
.replace(/\./g, '%2E')
|
|
171
|
+
.replace(/\(/g, '%28')
|
|
172
|
+
.replace(/\)/g, '%29')
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// A decimal literal, not `Number()`: the API compares against a number column,
|
|
176
|
+
// and it answers an error for the whole `or(...)` when it is handed something it
|
|
177
|
+
// cannot parse as one — which `Number()` happily accepts (`0x10`, `1e5`, ` `).
|
|
178
|
+
const NUMBER_LITERAL_RE = /^-?\d+(\.\d+)?$/
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Builds the OR conditions for global search across all columns.
|
|
182
|
+
* Text and categorical columns get a `__contains` filter; number columns
|
|
183
|
+
* get a `__exact` filter only when the search value is numeric.
|
|
184
|
+
* Year, date and boolean columns are excluded.
|
|
185
|
+
*/
|
|
186
|
+
export function buildGlobalSearchConditions(
|
|
187
|
+
allColumns: string[],
|
|
188
|
+
getColumnType: (col: string) => ColumnType,
|
|
189
|
+
searchValue: string,
|
|
190
|
+
): string[] {
|
|
191
|
+
const conditions: string[] = []
|
|
192
|
+
for (const col of allColumns) {
|
|
193
|
+
const type = getColumnType(col)
|
|
194
|
+
if (type === 'text' || type === 'categorical') {
|
|
195
|
+
conditions.push(col + '__contains.' + encodeConditionValue(searchValue))
|
|
196
|
+
}
|
|
197
|
+
else if (type === 'number' && NUMBER_LITERAL_RE.test(searchValue)) {
|
|
198
|
+
conditions.push(col + '__exact.' + encodeConditionValue(searchValue))
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return conditions
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function isTruthy(value: unknown): boolean {
|
|
205
|
+
if (typeof value === 'boolean') return value
|
|
206
|
+
if (typeof value === 'string') return TRUTHY_VALUES.includes(value.toLowerCase())
|
|
207
|
+
return Boolean(value)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function isFalsy(value: unknown): boolean {
|
|
211
|
+
if (typeof value === 'boolean') return !value
|
|
212
|
+
if (typeof value === 'string') return FALSY_VALUES.includes(value.toLowerCase())
|
|
213
|
+
return !value
|
|
214
|
+
}
|
|
@@ -1,20 +1,105 @@
|
|
|
1
1
|
import { ofetch } from 'ofetch'
|
|
2
2
|
import { useComponentsConfig, type PluginConfig } from '../config'
|
|
3
|
+
import type { GenericFilter } from '../types/visualizations'
|
|
4
|
+
import type { SortConfig, TabularProfileResponse } from '../components/TabularExplorer/types'
|
|
3
5
|
|
|
4
|
-
export type SortConfig
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export type { SortConfig }
|
|
7
|
+
|
|
8
|
+
export type TabularDataResponse = {
|
|
9
|
+
data: Array<Record<string, unknown>>
|
|
10
|
+
links: {
|
|
11
|
+
profile: string
|
|
12
|
+
swagger: string
|
|
13
|
+
next: string
|
|
14
|
+
}
|
|
15
|
+
meta: { total: number }
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export type TabularAggregateType = 'avg' | 'sum' | 'count' | 'min' | 'max'
|
|
19
|
+
|
|
20
|
+
export type FetchTabularDataOptions = {
|
|
21
|
+
resourceId: string
|
|
22
|
+
page?: number
|
|
23
|
+
pageSize?: number
|
|
24
|
+
columns?: Array<string> | undefined
|
|
25
|
+
sort?: SortConfig
|
|
26
|
+
groupBy?: string | undefined
|
|
27
|
+
aggregation?: {
|
|
28
|
+
column: string
|
|
29
|
+
type: TabularAggregateType
|
|
30
|
+
} | undefined
|
|
31
|
+
filters?: GenericFilter | undefined
|
|
32
|
+
}
|
|
8
33
|
|
|
9
34
|
/**
|
|
10
|
-
* Call Tabular-api to get table content
|
|
35
|
+
* Call Tabular-api to get table content with options object
|
|
11
36
|
*/
|
|
12
|
-
export async function
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
37
|
+
export async function fetchTabularData(config: PluginConfig, options: FetchTabularDataOptions): Promise<TabularDataResponse> {
|
|
38
|
+
const page = options.page ?? 1
|
|
39
|
+
const pageSize = options.pageSize ?? config.tabularApiPageSize ?? 15
|
|
40
|
+
let url = `${config.tabularApiUrl}/api/resources/${options.resourceId}/data/?page=${page}&page_size=${pageSize}`
|
|
41
|
+
if (options.columns) {
|
|
42
|
+
url += `&columns=${options.columns.map(col => encodeURIComponent(col)).join(',')}`
|
|
43
|
+
}
|
|
44
|
+
if (options.sort) {
|
|
45
|
+
url += `&${encodeURIComponent(options.sort.column)}__sort=${encodeURIComponent(options.sort.direction)}`
|
|
46
|
+
}
|
|
47
|
+
if (options.groupBy && options.aggregation?.type) {
|
|
48
|
+
url += `&${encodeURIComponent(options.groupBy)}__groupby&${encodeURIComponent(options.aggregation.column)}__${encodeURIComponent(options.aggregation.type)}`
|
|
49
|
+
}
|
|
50
|
+
if (options.filters) {
|
|
51
|
+
const filterQuery = buildFilterQuery(options.filters)
|
|
52
|
+
if (filterQuery) {
|
|
53
|
+
url += `&${filterQuery}`
|
|
54
|
+
}
|
|
16
55
|
}
|
|
17
|
-
return await ofetch(url)
|
|
56
|
+
return await ofetch<TabularDataResponse>(url)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function buildFilterQuery(filters: GenericFilter): string {
|
|
60
|
+
const params: Array<string> = []
|
|
61
|
+
if ('filters' in filters) {
|
|
62
|
+
for (const filter of filters.filters) {
|
|
63
|
+
if ('filters' in filter) {
|
|
64
|
+
params.push(buildFilterQuery(filter))
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
if (filter.condition === 'is_null') {
|
|
68
|
+
params.push(`${encodeURIComponent(filter.column)}__isnull`)
|
|
69
|
+
}
|
|
70
|
+
else if (filter.condition === 'is_not_null') {
|
|
71
|
+
params.push(`${encodeURIComponent(filter.column)}__isnotnull`)
|
|
72
|
+
}
|
|
73
|
+
else if (filter.value !== null && filter.value !== undefined && filter.value !== '') {
|
|
74
|
+
params.push(`${encodeURIComponent(filter.column)}__${encodeURIComponent(filter.condition)}=${encodeURIComponent(filter.value)}`)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const filter = filters
|
|
81
|
+
if (filter.condition === 'is_null') {
|
|
82
|
+
params.push(`${encodeURIComponent(filter.column)}__isnull`)
|
|
83
|
+
}
|
|
84
|
+
else if (filter.condition === 'is_not_null') {
|
|
85
|
+
params.push(`${encodeURIComponent(filter.column)}__isnotnull`)
|
|
86
|
+
}
|
|
87
|
+
else if (filter.value !== null && filter.value !== undefined && filter.value !== '') {
|
|
88
|
+
params.push(`${encodeURIComponent(filter.column)}__${encodeURIComponent(filter.condition)}=${encodeURIComponent(filter.value)}`)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return params.join('&')
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Call Tabular-api to get table content
|
|
96
|
+
*/
|
|
97
|
+
export async function getData(config: PluginConfig, id: string, page: number, sortConfig?: SortConfig | null): Promise<TabularDataResponse> {
|
|
98
|
+
return fetchTabularData(config, {
|
|
99
|
+
resourceId: id,
|
|
100
|
+
page,
|
|
101
|
+
sort: sortConfig ?? undefined,
|
|
102
|
+
})
|
|
18
103
|
}
|
|
19
104
|
|
|
20
105
|
/**
|
|
@@ -22,5 +107,5 @@ export async function getData(config: PluginConfig, id: string, page: number, so
|
|
|
22
107
|
*/
|
|
23
108
|
export function useGetProfile() {
|
|
24
109
|
const config = useComponentsConfig()
|
|
25
|
-
return (id: string) => ofetch(`${config.tabularApiUrl}/api/resources/${id}/profile/`)
|
|
110
|
+
return (id: string) => ofetch<TabularProfileResponse>(`${config.tabularApiUrl}/api/resources/${id}/profile/`)
|
|
26
111
|
}
|
package/src/main.ts
CHANGED
|
@@ -13,9 +13,9 @@ import type { License } from './types/licenses'
|
|
|
13
13
|
import type { Member, MemberRole, NewOrganization, Organization, OrganizationOrSuggest, OrganizationReference, OrganizationSuggest } from './types/organizations'
|
|
14
14
|
import type { Owned, OwnedWithFullObject, OwnedWithId } from './types/owned'
|
|
15
15
|
import type { Comment, Thread } from './types/discussions'
|
|
16
|
-
import type {
|
|
16
|
+
import type { PageBloc, ContentBloc, BlocWithTitle, DatasetsListBloc, DataservicesListBloc, ReusesListBloc, LinkInBloc, LinksListBloc, MarkdownBloc, AccordionItemBloc, AccordionListBloc, HeroBloc } from './types/pages'
|
|
17
17
|
import type { Post } from './types/posts'
|
|
18
|
-
import type { ReuseReference, NewReuse, Reuse, ReuseTopic, ReuseType } from './types/reuses'
|
|
18
|
+
import type { ReuseReference, NewReuse, Reuse, ReuseV2, ReuseTopic, ReuseType } from './types/reuses'
|
|
19
19
|
import type { RegisteredSchema, Schema, SchemaDetails, SchemaField, SchemaPath, SchemaPublicationMode, SchemaResponseData, SchemaVersion, ValidataError } from './types/schemas'
|
|
20
20
|
import type { TopicV2, TopicElement, TopicElementClass, TopicElementRel } from './types/topics'
|
|
21
21
|
import type { CommunityResource, FileResourceFileType, RemoteResourceFileType, ResourceFileType, ResourceGroup, ResourceType, Resource } from './types/resources'
|
|
@@ -23,8 +23,12 @@ 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 {
|
|
27
|
-
import {
|
|
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 { ColumnFilters, ColumnType, TabularRow } from './components/TabularExplorer/types'
|
|
28
|
+
import type { GlobalSearchConfig, SearchType, SearchTypeConfig, SortOption, HiddenFilter, BuiltInFilterKey, DatasetSearchConfig, DatasetSearchFilters, DataserviceSearchConfig, DataserviceSearchFilters, ReuseSearchConfig, ReuseSearchFilters, OrganizationSearchConfig, OrganizationSearchFilters, TopicSearchConfig, TopicSearchFilters } from './types/search'
|
|
29
|
+
import { getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultTopicConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search'
|
|
30
|
+
import { useSearchFilter } from './composables/useSearchFilter'
|
|
31
|
+
import type { UseSearchFilterOptions } from './composables/useSearchFilter'
|
|
28
32
|
|
|
29
33
|
import ActivityList from './components/ActivityList/ActivityList.vue'
|
|
30
34
|
import UserActivityList from './components/ActivityList/UserActivityList.vue'
|
|
@@ -36,19 +40,26 @@ import BannerAction from './components/BannerAction.vue'
|
|
|
36
40
|
import BrandedButton from './components/BrandedButton.vue'
|
|
37
41
|
import CopyButton from './components/CopyButton.vue'
|
|
38
42
|
import DataserviceCard from './components/DataserviceCard.vue'
|
|
43
|
+
import DataserviceQuality from './components/DataserviceQuality.vue'
|
|
44
|
+
import DataserviceQualityInline from './components/DataserviceQualityInline.vue'
|
|
45
|
+
import DataserviceQualityTooltipContent from './components/DataserviceQualityTooltipContent.vue'
|
|
39
46
|
import DatasetCard from './components/DatasetCard.vue'
|
|
47
|
+
import DataStructure from './components/ResourceAccordion/DataStructure.vue'
|
|
48
|
+
import Downloads from './components/ResourceAccordion/Downloads.vue'
|
|
49
|
+
import Metadata from './components/ResourceAccordion/Metadata.vue'
|
|
40
50
|
import DescriptionListTerm from './components/DescriptionListTerm.vue'
|
|
41
51
|
import DescriptionListDetails from './components/DescriptionListDetails.vue'
|
|
42
52
|
import DiscussionMessageCard from './components/DiscussionMessageCard.vue'
|
|
43
53
|
import DateRangeDetails from './components/DateRangeDetails.vue'
|
|
54
|
+
import FormattedDate from './components/FormattedDate.vue'
|
|
44
55
|
import { DatasetInformationSection, DatasetTemporalitySection, DatasetSpatialSection, DatasetSchemaSection, DatasetEmbedSection } from './components/DatasetInformation'
|
|
45
56
|
import LeafletMap from './components/LeafletMap.vue'
|
|
46
57
|
import LicenseBadge from './components/LicenseBadge.vue'
|
|
47
58
|
import Tag from './components/Tag.vue'
|
|
48
59
|
import DatasetQuality from './components/DatasetQuality.vue'
|
|
49
60
|
import DatasetQualityInline from './components/DatasetQualityInline.vue'
|
|
50
|
-
import
|
|
51
|
-
import
|
|
61
|
+
import QualityItem from './components/QualityItem.vue'
|
|
62
|
+
import QualityScore from './components/QualityScore.vue'
|
|
52
63
|
import ProgressBar from './components/ProgressBar.vue'
|
|
53
64
|
import DatasetQualityTooltipContent from './components/DatasetQualityTooltipContent.vue'
|
|
54
65
|
import ExtraAccordion from './components/ExtraAccordion.vue'
|
|
@@ -57,6 +68,7 @@ import LoadingBlock from './components/LoadingBlock.vue'
|
|
|
57
68
|
import MarkdownViewer from './components/MarkdownViewer.vue'
|
|
58
69
|
import OrganizationCard from './components/OrganizationCard.vue'
|
|
59
70
|
import OrganizationHorizontalCard from './components/OrganizationHorizontalCard.vue'
|
|
71
|
+
import ObjectCardOwner from './components/ObjectCardOwner.vue'
|
|
60
72
|
import OrganizationLogo from './components/OrganizationLogo.vue'
|
|
61
73
|
import OrganizationNameWithCertificate from './components/OrganizationNameWithCertificate.vue'
|
|
62
74
|
import OwnerType from './components/OwnerType.vue'
|
|
@@ -70,16 +82,16 @@ import PostCard from './components/PostCard.vue'
|
|
|
70
82
|
import ReadMore from './components/ReadMore.vue'
|
|
71
83
|
import ResourceAccordion from './components/ResourceAccordion/ResourceAccordion.vue'
|
|
72
84
|
import ResourceIcon from './components/ResourceAccordion/ResourceIcon.vue'
|
|
85
|
+
import ResourceSelector from './components/ResourceExplorer/ResourceSelector.vue'
|
|
73
86
|
import ResourceExplorer from './components/ResourceExplorer/ResourceExplorer.vue'
|
|
74
87
|
import ResourceExplorerSidebar from './components/ResourceExplorer/ResourceExplorerSidebar.vue'
|
|
75
88
|
import ResourceExplorerViewer from './components/ResourceExplorer/ResourceExplorerViewer.vue'
|
|
76
|
-
import
|
|
89
|
+
import OpenApiViewer from './components/OpenApiViewer/OpenApiViewer.vue'
|
|
77
90
|
import ReuseCard from './components/ReuseCard.vue'
|
|
78
91
|
import ReuseHorizontalCard from './components/ReuseHorizontalCard.vue'
|
|
79
92
|
import ReuseDetails from './components/ReuseDetails.vue'
|
|
80
93
|
import SchemaCard from './components/SchemaCard.vue'
|
|
81
94
|
import SimpleBanner from './components/SimpleBanner.vue'
|
|
82
|
-
import SmallChart from './components/SmallChart.vue'
|
|
83
95
|
import StatBox from './components/StatBox.vue'
|
|
84
96
|
import Tab from './components/Tabs/Tab.vue'
|
|
85
97
|
import TabGroup from './components/Tabs/TabGroup.vue'
|
|
@@ -94,16 +106,29 @@ import GlobalSearch from './components/Search/GlobalSearch.vue'
|
|
|
94
106
|
import SearchInput from './components/Search/SearchInput.vue'
|
|
95
107
|
import SearchableSelect from './components/Form/SearchableSelect.vue'
|
|
96
108
|
import SelectGroup from './components/Form/SelectGroup.vue'
|
|
109
|
+
import Listbox from './components/Form/Listbox.vue'
|
|
110
|
+
import InfiniteLoader from './components/InfiniteLoader.vue'
|
|
111
|
+
import TabularExplorer from './components/TabularExplorer/TabularExplorer.vue'
|
|
112
|
+
import TabularMobileFilters from './components/TabularExplorer/TabularMobileFilters.vue'
|
|
113
|
+
import TabularTable from './components/TabularExplorer/TabularTable.vue'
|
|
114
|
+
import TabularToolbar from './components/TabularExplorer/TabularToolbar.vue'
|
|
97
115
|
import type { UseFetchFunction } from './functions/api.types'
|
|
98
116
|
import { configKey, useComponentsConfig, type PluginConfig } from './config.js'
|
|
117
|
+
import { ofetch } from 'ofetch'
|
|
118
|
+
import { useTranslation } from './composables/useTranslation'
|
|
99
119
|
|
|
100
120
|
export { Toaster, toast } from 'vue-sonner'
|
|
101
121
|
|
|
102
122
|
export * from './composables/useActiveDescendant'
|
|
123
|
+
export * from './composables/useDebouncedRef'
|
|
103
124
|
export * from './composables/useMetrics'
|
|
104
125
|
export * from './composables/useReuseType'
|
|
105
126
|
export * from './composables/useTranslation'
|
|
106
127
|
export * from './composables/useHasTabularData'
|
|
128
|
+
export * from './composables/useResourceCapabilities'
|
|
129
|
+
export * from './composables/useTabularProfile'
|
|
130
|
+
export * from './composables/useDatasetResources'
|
|
131
|
+
export * from './composables/useResizable'
|
|
107
132
|
|
|
108
133
|
export * from './functions/activities'
|
|
109
134
|
export * from './functions/datasets'
|
|
@@ -116,17 +141,33 @@ export * from './functions/metrics'
|
|
|
116
141
|
export * from './functions/never'
|
|
117
142
|
export * from './functions/organizations'
|
|
118
143
|
export * from './functions/owned'
|
|
119
|
-
export * from './functions/pagination'
|
|
120
144
|
export * from './functions/resources'
|
|
121
145
|
export * from './functions/reuses'
|
|
122
146
|
export * from './functions/schemas'
|
|
147
|
+
export * from './functions/tabular'
|
|
123
148
|
export * from './functions/users'
|
|
149
|
+
export * from './functions/tabularApi'
|
|
150
|
+
export * from './functions/charts'
|
|
124
151
|
export * from './types/access_types'
|
|
125
152
|
|
|
126
153
|
export type {
|
|
127
154
|
GlobalSearchConfig,
|
|
128
155
|
SearchType,
|
|
156
|
+
SearchTypeConfig,
|
|
129
157
|
SortOption,
|
|
158
|
+
HiddenFilter,
|
|
159
|
+
BuiltInFilterKey,
|
|
160
|
+
DatasetSearchConfig,
|
|
161
|
+
DatasetSearchFilters,
|
|
162
|
+
DataserviceSearchConfig,
|
|
163
|
+
DataserviceSearchFilters,
|
|
164
|
+
ReuseSearchConfig,
|
|
165
|
+
ReuseSearchFilters,
|
|
166
|
+
OrganizationSearchConfig,
|
|
167
|
+
OrganizationSearchFilters,
|
|
168
|
+
TopicSearchConfig,
|
|
169
|
+
TopicSearchFilters,
|
|
170
|
+
UseSearchFilterOptions,
|
|
130
171
|
UseFetchFunction,
|
|
131
172
|
AccessType,
|
|
132
173
|
AccessAudience,
|
|
@@ -168,7 +209,6 @@ export type {
|
|
|
168
209
|
Owned,
|
|
169
210
|
OwnedWithFullObject,
|
|
170
211
|
OwnedWithId,
|
|
171
|
-
Page,
|
|
172
212
|
PageBloc,
|
|
173
213
|
ContentBloc,
|
|
174
214
|
BlocWithTitle,
|
|
@@ -197,6 +237,7 @@ export type {
|
|
|
197
237
|
ResourceType,
|
|
198
238
|
ReuseReference,
|
|
199
239
|
Reuse,
|
|
240
|
+
ReuseV2,
|
|
200
241
|
ReuseTopic,
|
|
201
242
|
ReuseType,
|
|
202
243
|
Schema,
|
|
@@ -218,6 +259,29 @@ export type {
|
|
|
218
259
|
ValidataError,
|
|
219
260
|
Weight,
|
|
220
261
|
WellType,
|
|
262
|
+
Chart,
|
|
263
|
+
ChartForm,
|
|
264
|
+
ChartForApi,
|
|
265
|
+
CombinedSort,
|
|
266
|
+
ColumnDefinition,
|
|
267
|
+
ColumnFilters,
|
|
268
|
+
ColumnType,
|
|
269
|
+
ColumnsDefinition,
|
|
270
|
+
TabularRow,
|
|
271
|
+
FilterCondition,
|
|
272
|
+
Filter,
|
|
273
|
+
AndFilters,
|
|
274
|
+
GenericFilter,
|
|
275
|
+
XAxisType,
|
|
276
|
+
XAxisSortBy,
|
|
277
|
+
SortDirection,
|
|
278
|
+
XAxis,
|
|
279
|
+
XAxisForm,
|
|
280
|
+
UnitPosition,
|
|
281
|
+
YAxis,
|
|
282
|
+
DataSeriesType,
|
|
283
|
+
DataSeries,
|
|
284
|
+
DataSeriesForm,
|
|
221
285
|
}
|
|
222
286
|
|
|
223
287
|
export {
|
|
@@ -225,16 +289,43 @@ export {
|
|
|
225
289
|
getDefaultDataserviceConfig,
|
|
226
290
|
getDefaultReuseConfig,
|
|
227
291
|
getDefaultOrganizationConfig,
|
|
292
|
+
getDefaultTopicConfig,
|
|
228
293
|
getDefaultGlobalSearchConfig,
|
|
229
294
|
defaultDatasetSortOptions,
|
|
230
295
|
defaultDataserviceSortOptions,
|
|
231
296
|
defaultReuseSortOptions,
|
|
232
297
|
defaultOrganizationSortOptions,
|
|
298
|
+
useSearchFilter,
|
|
233
299
|
}
|
|
234
300
|
|
|
235
301
|
// Vue Plugin
|
|
236
302
|
const datagouv: Plugin<PluginConfig> = {
|
|
237
303
|
async install(app: App, options) {
|
|
304
|
+
// Default `$fetch` to an ofetch instance carrying the datagouv API specifics + the consumer's
|
|
305
|
+
// auth hooks, so everything downstream (the default `useFetch`, imperative helpers) can rely on
|
|
306
|
+
// a single configured fetch. A consumer that provides its own `$fetch` keeps full control.
|
|
307
|
+
if (!options.$fetch) {
|
|
308
|
+
options.$fetch = ofetch.create({
|
|
309
|
+
baseURL: options.apiBase,
|
|
310
|
+
onRequest(context) {
|
|
311
|
+
if (options.onRequest) {
|
|
312
|
+
if (Array.isArray(options.onRequest)) options.onRequest.forEach(hook => hook(context))
|
|
313
|
+
else options.onRequest(context)
|
|
314
|
+
}
|
|
315
|
+
context.options.headers.set('Content-Type', 'application/json')
|
|
316
|
+
context.options.headers.set('Accept', 'application/json')
|
|
317
|
+
if (options.devApiKey) context.options.headers.set('X-API-KEY', options.devApiKey)
|
|
318
|
+
const { locale } = useTranslation()
|
|
319
|
+
if (locale) {
|
|
320
|
+
context.options.params ??= {}
|
|
321
|
+
context.options.params['lang'] = locale
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
onRequestError: options.onRequestError,
|
|
325
|
+
onResponse: options.onResponse,
|
|
326
|
+
onResponseError: options.onResponseError,
|
|
327
|
+
})
|
|
328
|
+
}
|
|
238
329
|
app.provide(configKey, options)
|
|
239
330
|
if (!options.textClamp) {
|
|
240
331
|
const textClamp = await import('vue3-text-clamp')
|
|
@@ -255,7 +346,13 @@ export {
|
|
|
255
346
|
BrandedButton,
|
|
256
347
|
CopyButton,
|
|
257
348
|
DataserviceCard,
|
|
349
|
+
DataserviceQuality,
|
|
350
|
+
DataserviceQualityInline,
|
|
351
|
+
DataserviceQualityTooltipContent,
|
|
258
352
|
DatasetCard,
|
|
353
|
+
DataStructure,
|
|
354
|
+
Downloads,
|
|
355
|
+
Metadata,
|
|
259
356
|
DatasetInformationSection,
|
|
260
357
|
DatasetTemporalitySection,
|
|
261
358
|
DatasetSpatialSection,
|
|
@@ -266,10 +363,11 @@ export {
|
|
|
266
363
|
DiscussionMessageCard,
|
|
267
364
|
DatasetQuality,
|
|
268
365
|
DatasetQualityInline,
|
|
269
|
-
|
|
270
|
-
|
|
366
|
+
QualityItem,
|
|
367
|
+
QualityScore,
|
|
271
368
|
DatasetQualityTooltipContent,
|
|
272
369
|
DateRangeDetails,
|
|
370
|
+
FormattedDate,
|
|
273
371
|
ExtraAccordion,
|
|
274
372
|
LabelTag,
|
|
275
373
|
LeafletMap,
|
|
@@ -295,15 +393,16 @@ export {
|
|
|
295
393
|
ResourceExplorer,
|
|
296
394
|
ResourceExplorerSidebar,
|
|
297
395
|
ResourceExplorerViewer,
|
|
396
|
+
ObjectCardOwner,
|
|
298
397
|
ResourceIcon,
|
|
398
|
+
ResourceSelector,
|
|
299
399
|
ReuseCard,
|
|
300
400
|
ReuseDetails,
|
|
301
401
|
ReuseHorizontalCard,
|
|
302
402
|
SchemaCard,
|
|
303
403
|
SimpleBanner,
|
|
304
|
-
SmallChart,
|
|
305
404
|
StatBox,
|
|
306
|
-
|
|
405
|
+
OpenApiViewer,
|
|
307
406
|
Tab,
|
|
308
407
|
TabGroup,
|
|
309
408
|
TabList,
|
|
@@ -318,4 +417,10 @@ export {
|
|
|
318
417
|
SearchInput,
|
|
319
418
|
SearchableSelect,
|
|
320
419
|
SelectGroup,
|
|
420
|
+
Listbox,
|
|
421
|
+
InfiniteLoader,
|
|
422
|
+
TabularExplorer,
|
|
423
|
+
TabularMobileFilters,
|
|
424
|
+
TabularTable,
|
|
425
|
+
TabularToolbar,
|
|
321
426
|
}
|
|
@@ -24,12 +24,27 @@ export type BaseDataservice = Owned & WithAccessType & {
|
|
|
24
24
|
license: string | null
|
|
25
25
|
private: boolean
|
|
26
26
|
rate_limiting: string
|
|
27
|
+
rate_limiting_url: string | null
|
|
27
28
|
title: DataserviceReference['title']
|
|
28
29
|
contact_points: Array<ContactPoint>
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
export type NewDataservice = Omit<BaseDataservice, keyof OwnedWithId> & OwnedWithId
|
|
32
33
|
|
|
34
|
+
export type DataserviceQuality = {
|
|
35
|
+
has_description: boolean
|
|
36
|
+
has_machine_documentation: boolean
|
|
37
|
+
has_technical_documentation: boolean
|
|
38
|
+
has_business_documentation: boolean
|
|
39
|
+
license: boolean
|
|
40
|
+
has_contact_point: boolean
|
|
41
|
+
has_base_api_url: boolean
|
|
42
|
+
availability_documented: boolean
|
|
43
|
+
rate_limiting_documented: boolean
|
|
44
|
+
access_conditions_clear: boolean
|
|
45
|
+
score: number
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
export type Dataservice = Owned & WithAccessType & {
|
|
34
49
|
acronym: string
|
|
35
50
|
archived_at: string | null
|
|
@@ -65,9 +80,11 @@ export type Dataservice = Owned & WithAccessType & {
|
|
|
65
80
|
permissions: { edit: boolean, delete: boolean }
|
|
66
81
|
private: boolean
|
|
67
82
|
rate_limiting: string
|
|
83
|
+
rate_limiting_url: string | null
|
|
68
84
|
self_api_url: DataserviceReference['self_api_url']
|
|
69
85
|
self_web_url: DataserviceReference['self_web_url']
|
|
70
86
|
slug: string
|
|
71
87
|
tags: Array<string>
|
|
72
88
|
title: string
|
|
89
|
+
quality?: DataserviceQuality
|
|
73
90
|
}
|