@datagouv/components-next 1.0.2-dev.10 → 1.0.2-dev.100

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.
Files changed (107) hide show
  1. package/assets/main.css +4 -0
  2. package/dist/{Control-DuZJdKV_.js → Control-ZFh5ta_U.js} +1 -1
  3. package/dist/Datafair.client-C2j760M5.js +30 -0
  4. package/dist/{Event--kp8kMdJ.js → Event-DSQcW7OF.js} +24 -24
  5. package/dist/{Image-34hvypZI.js → Image-BijNEG0p.js} +6 -6
  6. package/dist/JsonPreview.client-PFfBR4J8.js +40 -0
  7. package/dist/{Map-BjUnLyj8.js → Map-BUtPf5GN.js} +756 -756
  8. package/dist/MapContainer.client-CGrS2baS.js +101 -0
  9. package/dist/{OSM-s40W6sQ2.js → OSM-D4MTdBtk.js} +2 -2
  10. package/dist/{PdfPreview.client-BVjPxlPu.js → PdfPreview.client-DU36UBGQ.js} +822 -865
  11. package/dist/{Pmtiles.client-CRJ56yX2.js → Pmtiles.client-DuTezcn5.js} +574 -579
  12. package/dist/PreviewWrapper.vue_vue_type_script_setup_true_lang-ProPRqX6.js +61 -0
  13. package/dist/{ScaleLine-KW-nXqp3.js → ScaleLine-hJQIqcZm.js} +2 -2
  14. package/dist/{Tile-DbNFNPfU.js → Tile-Dcl7oIVu.js} +35 -35
  15. package/dist/{TileImage-BsXBxMtq.js → TileImage-BJeHipMX.js} +4 -4
  16. package/dist/{View-BR92hTWP.js → View-xp_P_OHw.js} +412 -401
  17. package/dist/XmlPreview.client-Bcq2Ye14.js +34 -0
  18. package/dist/{common-PJfpC179.js → common-BjQlan3k.js} +36 -36
  19. package/dist/components-next.css +6 -6
  20. package/dist/components-next.js +175 -149
  21. package/dist/components.css +1 -1
  22. package/dist/{index-BZsAZ7iw.js → index-BJ-zwAF5.js} +32886 -27183
  23. package/dist/{main-qc4CO9Kn.js → main-TqHFAOCi.js} +92255 -76685
  24. package/dist/{proj-DsetBcW7.js → proj-CsNo9yH1.js} +532 -512
  25. package/dist/{tilecoord-Db24Px13.js → tilecoord-A0fLnBZr.js} +28 -28
  26. package/dist/{vue3-xml-viewer.common-CCOV_ohP.js → vue3-xml-viewer.common-BnJTx_B7.js} +1 -1
  27. package/package.json +18 -11
  28. package/src/components/ActivityList/ActivityList.vue +0 -2
  29. package/src/components/Chart/ChartViewer.vue +226 -0
  30. package/src/components/Chart/ChartViewerWrapper.vue +170 -0
  31. package/src/components/DataserviceCard.vue +3 -0
  32. package/src/components/DatasetCard.vue +9 -4
  33. package/src/components/Form/Listbox.vue +101 -0
  34. package/src/components/Form/SearchableSelect.vue +2 -1
  35. package/src/components/InfiniteLoader.vue +53 -0
  36. package/src/components/ObjectCardHeader.vue +11 -4
  37. package/src/components/OpenApiViewer/ContentTypeSelect.vue +48 -0
  38. package/src/components/OpenApiViewer/EndpointRequest.vue +164 -0
  39. package/src/components/OpenApiViewer/EndpointResponses.vue +149 -0
  40. package/src/components/OpenApiViewer/OpenApiViewer.vue +308 -0
  41. package/src/components/OpenApiViewer/SchemaPanel.vue +53 -0
  42. package/src/components/OpenApiViewer/SchemaTree.vue +77 -0
  43. package/src/components/OpenApiViewer/openapi.ts +150 -0
  44. package/src/components/OrganizationNameWithCertificate.vue +3 -2
  45. package/src/components/Pagination.vue +8 -5
  46. package/src/components/ReadMore.vue +1 -1
  47. package/src/components/ResourceAccordion/DataStructure.vue +11 -33
  48. package/src/components/ResourceAccordion/Datafair.client.vue +4 -10
  49. package/src/components/ResourceAccordion/Downloads.vue +160 -0
  50. package/src/components/ResourceAccordion/JsonPreview.client.vue +23 -121
  51. package/src/components/ResourceAccordion/MapContainer.client.vue +5 -14
  52. package/src/components/ResourceAccordion/Metadata.vue +1 -2
  53. package/src/components/ResourceAccordion/PdfPreview.client.vue +24 -103
  54. package/src/components/ResourceAccordion/Pmtiles.client.vue +5 -10
  55. package/src/components/ResourceAccordion/Preview.vue +16 -21
  56. package/src/components/ResourceAccordion/PreviewLoader.vue +1 -2
  57. package/src/components/ResourceAccordion/PreviewUnavailable.vue +22 -0
  58. package/src/components/ResourceAccordion/PreviewWrapper.vue +82 -0
  59. package/src/components/ResourceAccordion/ResourceAccordion.vue +10 -109
  60. package/src/components/ResourceAccordion/XmlPreview.client.vue +16 -115
  61. package/src/components/ResourceExplorer/ResourceExplorer.vue +35 -20
  62. package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +2 -2
  63. package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +56 -146
  64. package/src/components/ResourceExplorer/ResourceSelector.vue +113 -0
  65. package/src/components/ReuseCard.vue +12 -4
  66. package/src/components/Search/GlobalSearch.vue +191 -110
  67. package/src/components/Search/SearchInput.vue +5 -4
  68. package/src/components/TabularExplorer/TabularCell.vue +51 -0
  69. package/src/components/TabularExplorer/TabularCellPopover.vue +170 -0
  70. package/src/components/TabularExplorer/TabularExplorer.vue +973 -0
  71. package/src/components/TabularExplorer/TabularFilterContent.vue +351 -0
  72. package/src/components/TabularExplorer/TabularFilterPopover.vue +111 -0
  73. package/src/components/TabularExplorer/types.ts +83 -0
  74. package/src/composables/useHasTabularData.ts +13 -0
  75. package/src/composables/useMetrics.ts +1 -1
  76. package/src/composables/useResourceCapabilities.ts +1 -1
  77. package/src/composables/useSearchFilter.ts +118 -0
  78. package/src/composables/useStableQueryParams.ts +31 -3
  79. package/src/composables/useTabularProfile.ts +70 -0
  80. package/src/config.ts +20 -3
  81. package/src/functions/api.ts +9 -37
  82. package/src/functions/api.types.ts +1 -0
  83. package/src/functions/charts.ts +68 -0
  84. package/src/functions/datasets.ts +0 -17
  85. package/src/functions/metrics.ts +6 -4
  86. package/src/functions/resources.ts +56 -1
  87. package/src/functions/tabular.ts +60 -0
  88. package/src/functions/tabularApi.ts +138 -11
  89. package/src/main.ts +94 -7
  90. package/src/types/dataservices.ts +2 -0
  91. package/src/types/pages.ts +0 -5
  92. package/src/types/posts.ts +2 -2
  93. package/src/types/reports.ts +5 -1
  94. package/src/types/search.ts +52 -1
  95. package/src/types/site.ts +5 -3
  96. package/src/types/ui.ts +2 -0
  97. package/src/types/users.ts +2 -1
  98. package/src/types/visualizations.ts +89 -0
  99. package/assets/swagger-themes/newspaper.css +0 -1670
  100. package/dist/Datafair.client-0UYUu5yf.js +0 -35
  101. package/dist/JsonPreview.client-BrTMBWHZ.js +0 -87
  102. package/dist/MapContainer.client-CUmKyByc.js +0 -107
  103. package/dist/Swagger.client-2Yn7iF0A.js +0 -4
  104. package/dist/XmlPreview.client-DxqlVnKu.js +0 -79
  105. package/src/components/ResourceAccordion/Swagger.client.vue +0 -48
  106. package/src/functions/pagination.ts +0 -9
  107. /package/assets/illustrations/{_microscope.svg → microscope.svg} +0 -0
@@ -1,20 +1,147 @@
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 } from '../components/TabularExplorer/types'
3
5
 
4
- export type SortConfig = {
5
- column: string
6
- type: string
7
- } | null
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
+ }
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
+ }
8
75
 
9
76
  /**
10
- * Call Tabular-api to get table content
77
+ * Call Tabular-api to get table content with options object
11
78
  */
12
- export async function getData(config: PluginConfig, id: string, page: number, sortConfig?: SortConfig) {
13
- let url = `${config.tabularApiUrl}/api/resources/${id}/data/?page=${page}&page_size=${config.tabularApiPageSize || 15}`
14
- if (sortConfig) {
15
- url = url + `&${sortConfig.column}__sort=${sortConfig.type}`
79
+ export async function fetchTabularData(config: PluginConfig, options: FetchTabularDataOptions): Promise<TabularDataResponse> {
80
+ const page = options.page ?? 1
81
+ const pageSize = options.pageSize ?? config.tabularApiPageSize ?? 15
82
+ let url = `${config.tabularApiUrl}/api/resources/${options.resourceId}/data/?page=${page}&page_size=${pageSize}`
83
+ if (options.columns) {
84
+ url += `&columns=${options.columns.map(col => encodeURIComponent(col)).join(',')}`
85
+ }
86
+ if (options.sort) {
87
+ url += `&${encodeURIComponent(options.sort.column)}__sort=${encodeURIComponent(options.sort.direction)}`
16
88
  }
17
- return await ofetch(url)
89
+ if (options.groupBy && options.aggregation?.type) {
90
+ url += `&${encodeURIComponent(options.groupBy)}__groupby&${encodeURIComponent(options.aggregation.column)}__${encodeURIComponent(options.aggregation.type)}`
91
+ }
92
+ if (options.filters) {
93
+ const filterQuery = buildFilterQuery(options.filters)
94
+ if (filterQuery) {
95
+ url += `&${filterQuery}`
96
+ }
97
+ }
98
+ return await ofetch<TabularDataResponse>(url)
99
+ }
100
+
101
+ function buildFilterQuery(filters: GenericFilter): string {
102
+ const params: Array<string> = []
103
+ if ('filters' in filters) {
104
+ for (const filter of filters.filters) {
105
+ if ('filters' in filter) {
106
+ params.push(buildFilterQuery(filter))
107
+ }
108
+ else {
109
+ if (filter.condition === 'is_null') {
110
+ params.push(`${encodeURIComponent(filter.column)}__isnull`)
111
+ }
112
+ else if (filter.condition === 'is_not_null') {
113
+ params.push(`${encodeURIComponent(filter.column)}__isnotnull`)
114
+ }
115
+ else if (filter.value !== null && filter.value !== undefined && filter.value !== '') {
116
+ params.push(`${encodeURIComponent(filter.column)}__${encodeURIComponent(filter.condition)}=${encodeURIComponent(filter.value)}`)
117
+ }
118
+ }
119
+ }
120
+ }
121
+ else {
122
+ const filter = filters
123
+ if (filter.condition === 'is_null') {
124
+ params.push(`${encodeURIComponent(filter.column)}__isnull`)
125
+ }
126
+ else if (filter.condition === 'is_not_null') {
127
+ params.push(`${encodeURIComponent(filter.column)}__isnotnull`)
128
+ }
129
+ else if (filter.value !== null && filter.value !== undefined && filter.value !== '') {
130
+ params.push(`${encodeURIComponent(filter.column)}__${encodeURIComponent(filter.condition)}=${encodeURIComponent(filter.value)}`)
131
+ }
132
+ }
133
+ return params.join('&')
134
+ }
135
+
136
+ /**
137
+ * Call Tabular-api to get table content
138
+ */
139
+ export async function getData(config: PluginConfig, id: string, page: number, sortConfig?: SortConfig | null): Promise<TabularDataResponse> {
140
+ return fetchTabularData(config, {
141
+ resourceId: id,
142
+ page,
143
+ sort: sortConfig ?? undefined,
144
+ })
18
145
  }
19
146
 
20
147
  /**
@@ -22,5 +149,5 @@ export async function getData(config: PluginConfig, id: string, page: number, so
22
149
  */
23
150
  export function useGetProfile() {
24
151
  const config = useComponentsConfig()
25
- return (id: string) => ofetch(`${config.tabularApiUrl}/api/resources/${id}/profile/`)
152
+ return (id: string) => ofetch<TabularProfileResponse>(`${config.tabularApiUrl}/api/resources/${id}/profile/`)
26
153
  }
package/src/main.ts CHANGED
@@ -13,7 +13,7 @@ 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 { Page, PageBloc, ContentBloc, BlocWithTitle, DatasetsListBloc, DataservicesListBloc, ReusesListBloc, LinkInBloc, LinksListBloc, MarkdownBloc, AccordionItemBloc, AccordionListBloc, HeroBloc } from './types/pages'
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
18
  import type { ReuseReference, NewReuse, Reuse, ReuseTopic, ReuseType } from './types/reuses'
19
19
  import type { RegisteredSchema, Schema, SchemaDetails, SchemaField, SchemaPath, SchemaPublicationMode, SchemaResponseData, SchemaVersion, ValidataError } from './types/schemas'
@@ -23,8 +23,11 @@ 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 { GlobalSearchConfig, SearchType, SortOption } from './types/search'
27
- import { getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search'
26
+ import type { Chart, ChartForm, ChartForApi, FilterCondition, Filter, AndFilters, GenericFilter, XAxisType, XAxisSortBy, SortDirection, XAxis, XAxisForm, UnitPosition, YAxis, DataSeriesType, DataSeries, DataSeriesForm } from './types/visualizations'
27
+ import type { GlobalSearchConfig, SearchType, SearchTypeConfig, SortOption, HiddenFilter, BuiltInFilterKey, DatasetSearchConfig, DatasetSearchFilters, DataserviceSearchConfig, DataserviceSearchFilters, ReuseSearchConfig, ReuseSearchFilters, OrganizationSearchConfig, OrganizationSearchFilters, TopicSearchConfig, TopicSearchFilters } from './types/search'
28
+ import { getDefaultDatasetConfig, getDefaultDataserviceConfig, getDefaultReuseConfig, getDefaultOrganizationConfig, getDefaultTopicConfig, getDefaultGlobalSearchConfig, defaultDatasetSortOptions, defaultDataserviceSortOptions, defaultReuseSortOptions, defaultOrganizationSortOptions } from './types/search'
29
+ import { useSearchFilter } from './composables/useSearchFilter'
30
+ import type { UseSearchFilterOptions } from './composables/useSearchFilter'
28
31
 
29
32
  import ActivityList from './components/ActivityList/ActivityList.vue'
30
33
  import UserActivityList from './components/ActivityList/UserActivityList.vue'
@@ -37,6 +40,9 @@ import BrandedButton from './components/BrandedButton.vue'
37
40
  import CopyButton from './components/CopyButton.vue'
38
41
  import DataserviceCard from './components/DataserviceCard.vue'
39
42
  import DatasetCard from './components/DatasetCard.vue'
43
+ import DataStructure from './components/ResourceAccordion/DataStructure.vue'
44
+ import Downloads from './components/ResourceAccordion/Downloads.vue'
45
+ import Metadata from './components/ResourceAccordion/Metadata.vue'
40
46
  import DescriptionListTerm from './components/DescriptionListTerm.vue'
41
47
  import DescriptionListDetails from './components/DescriptionListDetails.vue'
42
48
  import DiscussionMessageCard from './components/DiscussionMessageCard.vue'
@@ -57,6 +63,7 @@ import LoadingBlock from './components/LoadingBlock.vue'
57
63
  import MarkdownViewer from './components/MarkdownViewer.vue'
58
64
  import OrganizationCard from './components/OrganizationCard.vue'
59
65
  import OrganizationHorizontalCard from './components/OrganizationHorizontalCard.vue'
66
+ import ObjectCardOwner from './components/ObjectCardOwner.vue'
60
67
  import OrganizationLogo from './components/OrganizationLogo.vue'
61
68
  import OrganizationNameWithCertificate from './components/OrganizationNameWithCertificate.vue'
62
69
  import OwnerType from './components/OwnerType.vue'
@@ -70,16 +77,19 @@ import PostCard from './components/PostCard.vue'
70
77
  import ReadMore from './components/ReadMore.vue'
71
78
  import ResourceAccordion from './components/ResourceAccordion/ResourceAccordion.vue'
72
79
  import ResourceIcon from './components/ResourceAccordion/ResourceIcon.vue'
80
+ import ResourceSelector from './components/ResourceExplorer/ResourceSelector.vue'
73
81
  import ResourceExplorer from './components/ResourceExplorer/ResourceExplorer.vue'
74
82
  import ResourceExplorerSidebar from './components/ResourceExplorer/ResourceExplorerSidebar.vue'
75
83
  import ResourceExplorerViewer from './components/ResourceExplorer/ResourceExplorerViewer.vue'
76
- import Swagger from './components/ResourceAccordion/Swagger.client.vue'
84
+ import OpenApiViewer from './components/OpenApiViewer/OpenApiViewer.vue'
77
85
  import ReuseCard from './components/ReuseCard.vue'
78
86
  import ReuseHorizontalCard from './components/ReuseHorizontalCard.vue'
79
87
  import ReuseDetails from './components/ReuseDetails.vue'
80
88
  import SchemaCard from './components/SchemaCard.vue'
81
89
  import SimpleBanner from './components/SimpleBanner.vue'
82
90
  import SmallChart from './components/SmallChart.vue'
91
+ import ChartViewer from './components/Chart/ChartViewer.vue'
92
+ import ChartViewerWrapper from './components/Chart/ChartViewerWrapper.vue'
83
93
  import StatBox from './components/StatBox.vue'
84
94
  import Tab from './components/Tabs/Tab.vue'
85
95
  import TabGroup from './components/Tabs/TabGroup.vue'
@@ -94,16 +104,24 @@ import GlobalSearch from './components/Search/GlobalSearch.vue'
94
104
  import SearchInput from './components/Search/SearchInput.vue'
95
105
  import SearchableSelect from './components/Form/SearchableSelect.vue'
96
106
  import SelectGroup from './components/Form/SelectGroup.vue'
107
+ import Listbox from './components/Form/Listbox.vue'
108
+ import InfiniteLoader from './components/InfiniteLoader.vue'
109
+ import TabularExplorer from './components/TabularExplorer/TabularExplorer.vue'
97
110
  import type { UseFetchFunction } from './functions/api.types'
98
111
  import { configKey, useComponentsConfig, type PluginConfig } from './config.js'
112
+ import { ofetch } from 'ofetch'
113
+ import { useTranslation } from './composables/useTranslation'
99
114
 
100
115
  export { Toaster, toast } from 'vue-sonner'
101
116
 
102
117
  export * from './composables/useActiveDescendant'
118
+ export * from './composables/useDebouncedRef'
103
119
  export * from './composables/useMetrics'
104
120
  export * from './composables/useReuseType'
105
121
  export * from './composables/useTranslation'
106
122
  export * from './composables/useHasTabularData'
123
+ export * from './composables/useResourceCapabilities'
124
+ export * from './composables/useTabularProfile'
107
125
 
108
126
  export * from './functions/activities'
109
127
  export * from './functions/datasets'
@@ -116,17 +134,33 @@ export * from './functions/metrics'
116
134
  export * from './functions/never'
117
135
  export * from './functions/organizations'
118
136
  export * from './functions/owned'
119
- export * from './functions/pagination'
120
137
  export * from './functions/resources'
121
138
  export * from './functions/reuses'
122
139
  export * from './functions/schemas'
140
+ export * from './functions/tabular'
123
141
  export * from './functions/users'
142
+ export * from './functions/tabularApi'
143
+ export * from './functions/charts'
124
144
  export * from './types/access_types'
125
145
 
126
146
  export type {
127
147
  GlobalSearchConfig,
128
148
  SearchType,
149
+ SearchTypeConfig,
129
150
  SortOption,
151
+ HiddenFilter,
152
+ BuiltInFilterKey,
153
+ DatasetSearchConfig,
154
+ DatasetSearchFilters,
155
+ DataserviceSearchConfig,
156
+ DataserviceSearchFilters,
157
+ ReuseSearchConfig,
158
+ ReuseSearchFilters,
159
+ OrganizationSearchConfig,
160
+ OrganizationSearchFilters,
161
+ TopicSearchConfig,
162
+ TopicSearchFilters,
163
+ UseSearchFilterOptions,
130
164
  UseFetchFunction,
131
165
  AccessType,
132
166
  AccessAudience,
@@ -168,7 +202,6 @@ export type {
168
202
  Owned,
169
203
  OwnedWithFullObject,
170
204
  OwnedWithId,
171
- Page,
172
205
  PageBloc,
173
206
  ContentBloc,
174
207
  BlocWithTitle,
@@ -218,6 +251,23 @@ export type {
218
251
  ValidataError,
219
252
  Weight,
220
253
  WellType,
254
+ Chart,
255
+ ChartForm,
256
+ ChartForApi,
257
+ FilterCondition,
258
+ Filter,
259
+ AndFilters,
260
+ GenericFilter,
261
+ XAxisType,
262
+ XAxisSortBy,
263
+ SortDirection,
264
+ XAxis,
265
+ XAxisForm,
266
+ UnitPosition,
267
+ YAxis,
268
+ DataSeriesType,
269
+ DataSeries,
270
+ DataSeriesForm,
221
271
  }
222
272
 
223
273
  export {
@@ -225,16 +275,43 @@ export {
225
275
  getDefaultDataserviceConfig,
226
276
  getDefaultReuseConfig,
227
277
  getDefaultOrganizationConfig,
278
+ getDefaultTopicConfig,
228
279
  getDefaultGlobalSearchConfig,
229
280
  defaultDatasetSortOptions,
230
281
  defaultDataserviceSortOptions,
231
282
  defaultReuseSortOptions,
232
283
  defaultOrganizationSortOptions,
284
+ useSearchFilter,
233
285
  }
234
286
 
235
287
  // Vue Plugin
236
288
  const datagouv: Plugin<PluginConfig> = {
237
289
  async install(app: App, options) {
290
+ // Default `$fetch` to an ofetch instance carrying the datagouv API specifics + the consumer's
291
+ // auth hooks, so everything downstream (the default `useFetch`, imperative helpers) can rely on
292
+ // a single configured fetch. A consumer that provides its own `$fetch` keeps full control.
293
+ if (!options.$fetch) {
294
+ options.$fetch = ofetch.create({
295
+ baseURL: options.apiBase,
296
+ onRequest(context) {
297
+ if (options.onRequest) {
298
+ if (Array.isArray(options.onRequest)) options.onRequest.forEach(hook => hook(context))
299
+ else options.onRequest(context)
300
+ }
301
+ context.options.headers.set('Content-Type', 'application/json')
302
+ context.options.headers.set('Accept', 'application/json')
303
+ if (options.devApiKey) context.options.headers.set('X-API-KEY', options.devApiKey)
304
+ const { locale } = useTranslation()
305
+ if (locale) {
306
+ context.options.params ??= {}
307
+ context.options.params['lang'] = locale
308
+ }
309
+ },
310
+ onRequestError: options.onRequestError,
311
+ onResponse: options.onResponse,
312
+ onResponseError: options.onResponseError,
313
+ })
314
+ }
238
315
  app.provide(configKey, options)
239
316
  if (!options.textClamp) {
240
317
  const textClamp = await import('vue3-text-clamp')
@@ -256,6 +333,9 @@ export {
256
333
  CopyButton,
257
334
  DataserviceCard,
258
335
  DatasetCard,
336
+ DataStructure,
337
+ Downloads,
338
+ Metadata,
259
339
  DatasetInformationSection,
260
340
  DatasetTemporalitySection,
261
341
  DatasetSpatialSection,
@@ -295,15 +375,19 @@ export {
295
375
  ResourceExplorer,
296
376
  ResourceExplorerSidebar,
297
377
  ResourceExplorerViewer,
378
+ ObjectCardOwner,
298
379
  ResourceIcon,
380
+ ResourceSelector,
299
381
  ReuseCard,
300
382
  ReuseDetails,
301
383
  ReuseHorizontalCard,
302
384
  SchemaCard,
303
385
  SimpleBanner,
304
386
  SmallChart,
387
+ ChartViewer,
388
+ ChartViewerWrapper,
305
389
  StatBox,
306
- Swagger,
390
+ OpenApiViewer,
307
391
  Tab,
308
392
  TabGroup,
309
393
  TabList,
@@ -318,4 +402,7 @@ export {
318
402
  SearchInput,
319
403
  SearchableSelect,
320
404
  SelectGroup,
405
+ Listbox,
406
+ InfiniteLoader,
407
+ TabularExplorer,
321
408
  }
@@ -24,6 +24,7 @@ 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
  }
@@ -65,6 +66,7 @@ export type Dataservice = Owned & WithAccessType & {
65
66
  permissions: { edit: boolean, delete: boolean }
66
67
  private: boolean
67
68
  rate_limiting: string
69
+ rate_limiting_url: string | null
68
70
  self_api_url: DataserviceReference['self_api_url']
69
71
  self_web_url: DataserviceReference['self_web_url']
70
72
  slug: string
@@ -2,11 +2,6 @@ import type { DatasetV2 } from './datasets'
2
2
  import type { Dataservice } from './dataservices'
3
3
  import type { Reuse } from './reuses'
4
4
 
5
- export type Page = {
6
- id: string
7
- blocs: Array<PageBloc>
8
- }
9
-
10
5
  export type BlocWithTitle = {
11
6
  title: string
12
7
  subtitle: string | null
@@ -1,12 +1,12 @@
1
1
  import type { Dataset } from './datasets'
2
- import type { Page } from './pages'
2
+ import type { PageBloc } from './pages'
3
3
  import type { Reuse } from './reuses'
4
4
  import type { User } from './users'
5
5
 
6
6
  export type Post = {
7
7
  body_type: 'markdown' | 'html' | 'blocs'
8
+ blocs: Array<PageBloc>
8
9
  content: string
9
- content_as_page: Page | null
10
10
  created_at: string
11
11
  credit_to: string
12
12
  credit_url: string
@@ -1,7 +1,7 @@
1
1
  import type { User } from './users'
2
2
 
3
3
  export type ReportSubject = {
4
- class: 'Discussion' | 'Dataservice' | 'Dataset' | 'Organization' | 'Reuse'
4
+ class: 'Discussion' | 'Dataservice' | 'Dataset' | 'Organization' | 'Reuse' | 'User'
5
5
  id: string
6
6
  }
7
7
 
@@ -16,11 +16,15 @@ export type Report = {
16
16
  id: string
17
17
  by: User | null
18
18
  subject: ReportSubject | null
19
+ subject_embed_id: string | null
19
20
  reason: ReportReasonValue
20
21
  message: string
21
22
  reported_at: string
22
23
  self_api_url: string
23
24
  subject_deleted_at: string | null
25
+ subject_deleted_by: User | null
26
+ subject_label: string | null
24
27
  dismissed_at: string | null
25
28
  dismissed_by: User | null
29
+ callbacks_count: number
26
30
  }
@@ -1,5 +1,10 @@
1
1
  import type { PaginatedArray } from './api'
2
2
  import type { AccessType } from './access_types'
3
+ import type { Dataset } from './datasets'
4
+ import type { Dataservice } from './dataservices'
5
+ import type { Organization } from './organizations'
6
+ import type { Reuse } from './reuses'
7
+ import type { TopicV2 } from './topics'
3
8
  import type {
4
9
  CERTIFIED,
5
10
  PUBLIC_SERVICE,
@@ -291,7 +296,9 @@ export type SortOption<Sort extends string> = {
291
296
 
292
297
  export type DatasetSearchConfig = {
293
298
  class: 'datasets'
299
+ key?: string
294
300
  name?: string
301
+ placeholder?: string | null
295
302
  hiddenFilters?: HiddenFilter<DatasetSearchFilters>[]
296
303
  basicFilters?: (keyof DatasetSearchFilters)[]
297
304
  advancedFilters?: (keyof DatasetSearchFilters)[]
@@ -300,7 +307,9 @@ export type DatasetSearchConfig = {
300
307
 
301
308
  export type DataserviceSearchConfig = {
302
309
  class: 'dataservices'
310
+ key?: string
303
311
  name?: string
312
+ placeholder?: string | null
304
313
  hiddenFilters?: HiddenFilter<DataserviceSearchFilters>[]
305
314
  basicFilters?: (keyof DataserviceSearchFilters)[]
306
315
  advancedFilters?: (keyof DataserviceSearchFilters)[]
@@ -309,7 +318,9 @@ export type DataserviceSearchConfig = {
309
318
 
310
319
  export type ReuseSearchConfig = {
311
320
  class: 'reuses'
321
+ key?: string
312
322
  name?: string
323
+ placeholder?: string | null
313
324
  hiddenFilters?: HiddenFilter<ReuseSearchFilters>[]
314
325
  basicFilters?: (keyof ReuseSearchFilters)[]
315
326
  advancedFilters?: (keyof ReuseSearchFilters)[]
@@ -318,19 +329,43 @@ export type ReuseSearchConfig = {
318
329
 
319
330
  export type OrganizationSearchConfig = {
320
331
  class: 'organizations'
332
+ key?: string
321
333
  name?: string
334
+ placeholder?: string | null
322
335
  hiddenFilters?: HiddenFilter<OrganizationSearchFilters>[]
323
336
  basicFilters?: (keyof OrganizationSearchFilters)[]
324
337
  advancedFilters?: (keyof OrganizationSearchFilters)[]
325
338
  sortOptions?: SortOption<OrganizationSearchSort>[]
326
339
  }
327
340
 
328
- export type SearchTypeConfig = DatasetSearchConfig | DataserviceSearchConfig | ReuseSearchConfig | OrganizationSearchConfig
341
+ export type TopicSearchConfig = {
342
+ class: 'topics'
343
+ key?: string
344
+ name?: string
345
+ placeholder?: string | null
346
+ hiddenFilters?: HiddenFilter<TopicSearchFilters>[]
347
+ basicFilters?: (keyof TopicSearchFilters)[]
348
+ advancedFilters?: (keyof TopicSearchFilters)[]
349
+ sortOptions?: SortOption<TopicSearchSort>[]
350
+ }
351
+
352
+ export type SearchTypeConfig = DatasetSearchConfig | DataserviceSearchConfig | ReuseSearchConfig | OrganizationSearchConfig | TopicSearchConfig
353
+
354
+ export type BuiltInFilterKey = keyof DatasetSearchFilters | keyof DataserviceSearchFilters | keyof ReuseSearchFilters | keyof OrganizationSearchFilters | keyof TopicSearchFilters
329
355
 
330
356
  export type SearchType = SearchTypeConfig['class']
331
357
 
332
358
  export type GlobalSearchConfig = SearchTypeConfig[]
333
359
 
360
+ // Maps each search class to its concrete response shape.
361
+ export type SearchResponseByClass = {
362
+ datasets: DatasetSearchResponse<Dataset>
363
+ dataservices: DataserviceSearchResponse<Dataservice>
364
+ reuses: ReuseSearchResponse<Reuse>
365
+ organizations: OrganizationSearchResponse<Organization>
366
+ topics: TopicSearchResponse<TopicV2>
367
+ }
368
+
334
369
  // Helper functions for default configs
335
370
 
336
371
  export const defaultDatasetSortOptions: SortOption<DatasetSearchSort>[] = [
@@ -397,11 +432,27 @@ export function getDefaultOrganizationConfig(overrides?: Partial<Omit<Organizati
397
432
  }
398
433
  }
399
434
 
435
+ export const defaultTopicSortOptions: SortOption<TopicSearchSort>[] = [
436
+ { value: '-created', label: 'Date de création' },
437
+ { value: '-last_modified', label: 'Dernière mise à jour' },
438
+ ]
439
+
440
+ export function getDefaultTopicConfig(overrides?: Partial<Omit<TopicSearchConfig, 'class'>>): TopicSearchConfig {
441
+ return {
442
+ class: 'topics',
443
+ basicFilters: ['last_update_range', 'producer_type'],
444
+ advancedFilters: ['organization', 'tag'],
445
+ sortOptions: defaultTopicSortOptions,
446
+ ...overrides,
447
+ }
448
+ }
449
+
400
450
  export function getDefaultGlobalSearchConfig(): GlobalSearchConfig {
401
451
  return [
402
452
  getDefaultDatasetConfig(),
403
453
  getDefaultDataserviceConfig(),
404
454
  getDefaultReuseConfig(),
405
455
  getDefaultOrganizationConfig(),
456
+ getDefaultTopicConfig(),
406
457
  ]
407
458
  }
package/src/types/site.ts CHANGED
@@ -1,9 +1,11 @@
1
+ import type { PageBloc } from './pages'
2
+
1
3
  export type Site = {
2
4
  id: string
3
5
  title: string
4
- datasets_page: string | null
5
- reuses_page: string | null
6
- dataservices_page: string | null
6
+ datasets_blocs: Array<PageBloc>
7
+ reuses_blocs: Array<PageBloc>
8
+ dataservices_blocs: Array<PageBloc>
7
9
  version: string
8
10
  metrics: {
9
11
  'dataservices': number
package/src/types/ui.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export type WellType = 'primary' | 'secondary'
2
2
 
3
3
  export type Weight = 'light' | 'regular' | 'semi-bold' | 'bold' | 'heavy'
4
+
5
+ export type TitleTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
@@ -21,13 +21,14 @@ export type User = {
21
21
  page: UserReference['page']
22
22
  avatar: UserReference['avatar']
23
23
  avatar_thumbnail: UserReference['avatar_thumbnail']
24
- apikey?: string
25
24
  email?: string
26
25
  about: string
27
26
  website?: string
28
27
  roles?: Array<string>
29
28
  organizations: Array<OrganizationReference>
30
29
  last_login_at: string | null
30
+ password_rotation_demanded: string | null
31
+ password_rotation_performed: string | null
31
32
  since: string | null
32
33
  metrics: {
33
34
  datasets: number