@datagouv/components-next 1.0.2-dev.57 → 1.0.2-dev.59
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-qm_JoZUL.js → Datafair.client-f2FP7plo.js} +1 -1
- package/dist/{JsonPreview.client-BpovqdDN.js → JsonPreview.client-m3C0XIoF.js} +2 -2
- package/dist/{MapContainer.client-6Y5RJxtw.js → MapContainer.client-CUGKCZsN.js} +2 -2
- package/dist/{PdfPreview.client-Drv5EwJe.js → PdfPreview.client-deTriWNm.js} +2 -2
- package/dist/{Pmtiles.client-B3dUb4iS.js → Pmtiles.client-BQbOKcQX.js} +1 -1
- package/dist/{PreviewWrapper.vue_vue_type_script_setup_true_lang-BmRAxeK4.js → PreviewWrapper.vue_vue_type_script_setup_true_lang-bDZ3XRKG.js} +1 -1
- package/dist/{XmlPreview.client-CXF1N-AI.js → XmlPreview.client-DJL20TEn.js} +3 -3
- package/dist/components-next.js +1 -1
- package/dist/components.css +1 -1
- package/dist/{index-lCAbcwQm.js → index-Dw2SiLgu.js} +1 -1
- package/dist/{main-5ZJvZtsQ.js → main-jWuVtc9s.js} +12870 -12884
- package/dist/{vue3-xml-viewer.common-X_gxbf2s.js → vue3-xml-viewer.common-lELDJ2z7.js} +1 -1
- package/package.json +1 -1
- package/src/components/OrganizationNameWithCertificate.vue +3 -2
- package/src/components/Search/GlobalSearch.vue +110 -119
- package/src/types/search.ts +19 -0
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<component
|
|
8
8
|
:is="as"
|
|
9
9
|
class="mb-0 truncate flex-initial"
|
|
10
|
-
:class="[colorClass, { 'text-xs': size === 'xs', 'text-sm': size === 'sm', 'text-base': size === 'base' }]"
|
|
10
|
+
:class="[colorClass, { 'text-xs': size === 'xs', 'text-sm': size === 'sm', 'text-base': size === 'base', 'text-xl sm:text-2xl': size === 'xl' }]"
|
|
11
11
|
>
|
|
12
12
|
{{ organization.name }}
|
|
13
13
|
<small
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
'size-3': size === 'xs',
|
|
25
25
|
'size-4': size === 'sm',
|
|
26
26
|
'size-5': size === 'base',
|
|
27
|
+
'size-6': size === 'xl',
|
|
27
28
|
}"
|
|
28
29
|
:aria-label="t(`L'identité de ce service public est certifiée par {certifier}`, { certifier: config.name })"
|
|
29
30
|
aria-hidden="true"
|
|
@@ -53,7 +54,7 @@ withDefaults(defineProps<{
|
|
|
53
54
|
organization: Organization | OrganizationReference
|
|
54
55
|
showAcronym?: boolean
|
|
55
56
|
showType?: boolean
|
|
56
|
-
size?: 'base' | 'sm' | 'xs'
|
|
57
|
+
size?: 'xl' | 'base' | 'sm' | 'xs'
|
|
57
58
|
colorClass?: string
|
|
58
59
|
as?: string
|
|
59
60
|
}>(), {
|
|
@@ -5,13 +5,14 @@
|
|
|
5
5
|
@submit.prevent
|
|
6
6
|
>
|
|
7
7
|
<div
|
|
8
|
+
v-if="!hideSearchInput"
|
|
8
9
|
ref="search"
|
|
9
10
|
class="flex flex-wrap items-center justify-between"
|
|
10
11
|
data-cy="search"
|
|
11
12
|
>
|
|
12
13
|
<SearchInput
|
|
13
14
|
v-model="q"
|
|
14
|
-
:placeholder="placeholder ||
|
|
15
|
+
:placeholder="placeholder || strategies[currentTypeConfig?.class ?? 'datasets'].placeholder"
|
|
15
16
|
/>
|
|
16
17
|
</div>
|
|
17
18
|
<div class="grid grid-cols-12 mt-2 md:mt-5">
|
|
@@ -30,13 +31,13 @@
|
|
|
30
31
|
>
|
|
31
32
|
<RadioInput
|
|
32
33
|
v-for="typeConfig in config"
|
|
33
|
-
:key="typeConfig
|
|
34
|
-
:value="typeConfig
|
|
35
|
-
:count="
|
|
36
|
-
:loading="
|
|
37
|
-
:icon="
|
|
34
|
+
:key="configKey(typeConfig)"
|
|
35
|
+
:value="configKey(typeConfig)"
|
|
36
|
+
:count="resultsMap[configKey(typeConfig)]?.data.value?.total"
|
|
37
|
+
:loading="resultsMap[configKey(typeConfig)]?.status.value === 'pending' || resultsMap[configKey(typeConfig)]?.status.value === 'idle'"
|
|
38
|
+
:icon="strategies[typeConfig.class].icon"
|
|
38
39
|
>
|
|
39
|
-
{{ typeConfig.name ||
|
|
40
|
+
{{ typeConfig.name || strategies[typeConfig.class].name }}
|
|
40
41
|
</RadioInput>
|
|
41
42
|
</RadioGroup>
|
|
42
43
|
</Sidemenu>
|
|
@@ -127,7 +128,7 @@
|
|
|
127
128
|
v-model="producerType"
|
|
128
129
|
:facets="getFacets('producer_type')"
|
|
129
130
|
:loading="searchResultsStatus === 'pending'"
|
|
130
|
-
:exclude="
|
|
131
|
+
:exclude="currentTypeConfig?.class === 'organizations' ? ['user'] : []"
|
|
131
132
|
:style="{ order: getOrder('producer_type') }"
|
|
132
133
|
/>
|
|
133
134
|
<DatasetBadgeFilter
|
|
@@ -229,7 +230,7 @@
|
|
|
229
230
|
<transition mode="out-in">
|
|
230
231
|
<LoadingBlock
|
|
231
232
|
v-slot="{ data: results }"
|
|
232
|
-
:status="searchResultsStatus"
|
|
233
|
+
:status="searchResultsStatus!"
|
|
233
234
|
:data="searchResults"
|
|
234
235
|
>
|
|
235
236
|
<div v-if="results && results.data.length">
|
|
@@ -239,7 +240,7 @@
|
|
|
239
240
|
:key="result.id"
|
|
240
241
|
class="p-0"
|
|
241
242
|
>
|
|
242
|
-
<template v-if="
|
|
243
|
+
<template v-if="currentTypeConfig?.class === 'datasets'">
|
|
243
244
|
<slot
|
|
244
245
|
name="dataset"
|
|
245
246
|
:dataset="result"
|
|
@@ -247,7 +248,7 @@
|
|
|
247
248
|
<DatasetCard :dataset="(result as Dataset)" />
|
|
248
249
|
</slot>
|
|
249
250
|
</template>
|
|
250
|
-
<template v-else-if="
|
|
251
|
+
<template v-else-if="currentTypeConfig?.class === 'dataservices'">
|
|
251
252
|
<slot
|
|
252
253
|
name="dataservice"
|
|
253
254
|
:dataservice="result"
|
|
@@ -255,7 +256,7 @@
|
|
|
255
256
|
<DataserviceCard :dataservice="(result as Dataservice)" />
|
|
256
257
|
</slot>
|
|
257
258
|
</template>
|
|
258
|
-
<template v-else-if="
|
|
259
|
+
<template v-else-if="currentTypeConfig?.class === 'reuses'">
|
|
259
260
|
<slot
|
|
260
261
|
name="reuse"
|
|
261
262
|
:reuse="result"
|
|
@@ -263,7 +264,7 @@
|
|
|
263
264
|
<ReuseHorizontalCard :reuse="(result as Reuse)" />
|
|
264
265
|
</slot>
|
|
265
266
|
</template>
|
|
266
|
-
<template v-else-if="
|
|
267
|
+
<template v-else-if="currentTypeConfig?.class === 'organizations'">
|
|
267
268
|
<slot
|
|
268
269
|
name="organization"
|
|
269
270
|
:organization="result"
|
|
@@ -271,7 +272,7 @@
|
|
|
271
272
|
<OrganizationHorizontalCard :organization="(result as Organization)" />
|
|
272
273
|
</slot>
|
|
273
274
|
</template>
|
|
274
|
-
<template v-else-if="
|
|
275
|
+
<template v-else-if="currentTypeConfig?.class === 'topics'">
|
|
275
276
|
<slot
|
|
276
277
|
name="topic"
|
|
277
278
|
:topic="result"
|
|
@@ -348,7 +349,7 @@
|
|
|
348
349
|
</template>
|
|
349
350
|
|
|
350
351
|
<script setup lang="ts">
|
|
351
|
-
import { computed, provide, shallowReactive, useSlots, watch, useTemplateRef, type Ref } from 'vue'
|
|
352
|
+
import { computed, provide, shallowReactive, useSlots, watch, useTemplateRef, type Component, type Ref } from 'vue'
|
|
352
353
|
import { useRouteQuery } from '@vueuse/router'
|
|
353
354
|
import { RiBookShelfLine, RiBuilding2Line, RiCloseCircleLine, RiDatabase2Line, RiLightbulbLine, RiLineChartLine, RiRssLine, RiTerminalLine } from '@remixicon/vue'
|
|
354
355
|
import magnifyingGlassSrc from '../../../assets/illustrations/magnifying_glass.svg?url'
|
|
@@ -358,12 +359,13 @@ import { forEachActiveCustomFilter, isCustomFilterActive, searchFilterContextKey
|
|
|
358
359
|
import { useStableQueryParams } from '../../composables/useStableQueryParams'
|
|
359
360
|
import { useComponentsConfig } from '../../config'
|
|
360
361
|
import { useFetch } from '../../functions/api'
|
|
362
|
+
import type { AsyncDataRequestStatus } from '../../functions/api.types'
|
|
361
363
|
import type { Dataset } from '../../types/datasets'
|
|
362
364
|
import type { Dataservice } from '../../types/dataservices'
|
|
363
365
|
import type { Organization } from '../../types/organizations'
|
|
364
366
|
import type { Reuse } from '../../types/reuses'
|
|
365
367
|
import type { TopicV2 } from '../../types/topics'
|
|
366
|
-
import type { GlobalSearchConfig,
|
|
368
|
+
import type { GlobalSearchConfig, SearchResponseByClass, SearchType, SearchTypeConfig, SortOption, FacetItem } from '../../types/search'
|
|
367
369
|
import { getDefaultGlobalSearchConfig } from '../../types/search'
|
|
368
370
|
import BrandedButton from '../BrandedButton.vue'
|
|
369
371
|
import LoadingBlock from '../LoadingBlock.vue'
|
|
@@ -397,13 +399,17 @@ import ReuseTypeFilter from './Filter/ReuseTypeFilter.vue'
|
|
|
397
399
|
const props = withDefaults(defineProps<{
|
|
398
400
|
config?: GlobalSearchConfig
|
|
399
401
|
placeholder?: string
|
|
402
|
+
hideSearchInput?: boolean
|
|
400
403
|
}>(), {
|
|
401
404
|
config: getDefaultGlobalSearchConfig,
|
|
405
|
+
hideSearchInput: false,
|
|
402
406
|
})
|
|
403
407
|
|
|
408
|
+
const configKey = (c: SearchTypeConfig) => c.key ?? c.class
|
|
409
|
+
|
|
404
410
|
// defineModel's default is static and can't depend on props, so we cast and initialize manually
|
|
405
|
-
const currentType = defineModel<
|
|
406
|
-
if (!currentType.value) currentType.value = props.config[0]
|
|
411
|
+
const currentType = defineModel<string>('type') as Ref<string>
|
|
412
|
+
if (!currentType.value) currentType.value = configKey(props.config[0] ?? { class: 'datasets' })
|
|
407
413
|
|
|
408
414
|
const { t } = useTranslation()
|
|
409
415
|
const componentsConfig = useComponentsConfig()
|
|
@@ -419,7 +425,7 @@ const customFilterStops = new Map<string, () => void>()
|
|
|
419
425
|
const initialType = currentType.value
|
|
420
426
|
|
|
421
427
|
const currentTypeConfig = computed(() =>
|
|
422
|
-
props.config.find(c => c
|
|
428
|
+
props.config.find(c => configKey(c) === currentType.value),
|
|
423
429
|
)
|
|
424
430
|
|
|
425
431
|
const activeBasicFilters = computed(() =>
|
|
@@ -532,13 +538,6 @@ watch(currentType, () => {
|
|
|
532
538
|
}
|
|
533
539
|
})
|
|
534
540
|
|
|
535
|
-
// Check which types are enabled
|
|
536
|
-
const datasetsEnabled = computed(() => props.config.some(c => c.class === 'datasets'))
|
|
537
|
-
const dataservicesEnabled = computed(() => props.config.some(c => c.class === 'dataservices'))
|
|
538
|
-
const reusesEnabled = computed(() => props.config.some(c => c.class === 'reuses'))
|
|
539
|
-
const organizationsEnabled = computed(() => props.config.some(c => c.class === 'organizations'))
|
|
540
|
-
const topicsEnabled = computed(() => props.config.some(c => c.class === 'topics'))
|
|
541
|
-
|
|
542
541
|
// Create stable params for each type
|
|
543
542
|
const stableParamsOptions = {
|
|
544
543
|
allFilters,
|
|
@@ -549,33 +548,87 @@ const stableParamsOptions = {
|
|
|
549
548
|
pageSize,
|
|
550
549
|
}
|
|
551
550
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
551
|
+
// Discriminated union: each variant carries its own response type so a `class`
|
|
552
|
+
// narrow gives the precise shape of `data.value` (no cast needed).
|
|
553
|
+
type SearchEntry = {
|
|
554
|
+
[K in SearchType]: {
|
|
555
|
+
class: K
|
|
556
|
+
data: Ref<SearchResponseByClass[K] | null>
|
|
557
|
+
status: Ref<AsyncDataRequestStatus>
|
|
558
|
+
}
|
|
559
|
+
}[SearchType]
|
|
560
|
+
|
|
561
|
+
// One strategy per class consolidates everything that varies by class:
|
|
562
|
+
// metadata (icon/name/placeholder), endpoint, and a typed fetch factory.
|
|
563
|
+
type SearchStrategy<C extends SearchType> = {
|
|
564
|
+
url: string
|
|
565
|
+
icon: Component
|
|
566
|
+
name: string
|
|
567
|
+
placeholder: string
|
|
568
|
+
fetch: (
|
|
569
|
+
params: Ref<Record<string, unknown>>,
|
|
570
|
+
server: boolean,
|
|
571
|
+
) => Promise<Extract<SearchEntry, { class: C }>>
|
|
572
|
+
}
|
|
572
573
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
574
|
+
function makeStrategy<C extends SearchType>(
|
|
575
|
+
cls: C,
|
|
576
|
+
meta: Omit<SearchStrategy<C>, 'fetch'>,
|
|
577
|
+
): SearchStrategy<C> {
|
|
578
|
+
return {
|
|
579
|
+
...meta,
|
|
580
|
+
fetch: async (params, server) => {
|
|
581
|
+
const { data, status } = await useFetch<SearchResponseByClass[C]>(
|
|
582
|
+
meta.url,
|
|
583
|
+
{ params, lazy: true, server },
|
|
584
|
+
)
|
|
585
|
+
// Tautologically equivalent to Extract<SearchEntry, { class: C }>, but TS
|
|
586
|
+
// cannot prove it on a generic C, so we assert.
|
|
587
|
+
return { class: cls, data, status } as Extract<SearchEntry, { class: C }>
|
|
588
|
+
},
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
const strategies: { [K in SearchType]: SearchStrategy<K> } = {
|
|
593
|
+
datasets: makeStrategy('datasets', {
|
|
594
|
+
url: '/api/2/datasets/search/',
|
|
595
|
+
icon: RiDatabase2Line,
|
|
596
|
+
name: t('Jeux de données'),
|
|
597
|
+
placeholder: t('ex. élections présidentielles'),
|
|
598
|
+
}),
|
|
599
|
+
dataservices: makeStrategy('dataservices', {
|
|
600
|
+
url: '/api/2/dataservices/search/',
|
|
601
|
+
icon: RiTerminalLine,
|
|
602
|
+
name: t('API'),
|
|
603
|
+
placeholder: t('ex: SIRENE'),
|
|
604
|
+
}),
|
|
605
|
+
reuses: makeStrategy('reuses', {
|
|
606
|
+
url: '/api/2/reuses/search/',
|
|
607
|
+
icon: RiLineChartLine,
|
|
608
|
+
name: t('Réutilisations'),
|
|
609
|
+
placeholder: t('Rechercher une réutilisation de données'),
|
|
610
|
+
}),
|
|
611
|
+
organizations: makeStrategy('organizations', {
|
|
612
|
+
url: '/api/2/organizations/search/',
|
|
613
|
+
icon: RiBuilding2Line,
|
|
614
|
+
name: t('Organisations'),
|
|
615
|
+
placeholder: t('Rechercher une organisation'),
|
|
616
|
+
}),
|
|
617
|
+
topics: makeStrategy('topics', {
|
|
618
|
+
url: '/api/2/topics/search/',
|
|
619
|
+
icon: RiBookShelfLine,
|
|
620
|
+
name: t('Thématiques'),
|
|
621
|
+
placeholder: t('Rechercher une thématique'),
|
|
622
|
+
}),
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
// One params + fetch per config entry, keyed by configKey
|
|
626
|
+
const resultsMap: Record<string, SearchEntry> = {}
|
|
627
|
+
for (const c of props.config) {
|
|
628
|
+
const key = configKey(c)
|
|
629
|
+
const params = useStableQueryParams({ ...stableParamsOptions, typeConfig: c })
|
|
630
|
+
resultsMap[key] = await strategies[c.class].fetch(params, initialType === key)
|
|
631
|
+
}
|
|
579
632
|
|
|
580
633
|
// Reset page on filter/sort change. Custom filters (registered via
|
|
581
634
|
// useSearchFilter) have their own watchers set up in `provide`, so they're
|
|
@@ -648,80 +701,18 @@ function resetFilters() {
|
|
|
648
701
|
flushQ()
|
|
649
702
|
}
|
|
650
703
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const { data: datasetsResults, status: datasetsStatus } = await useFetch<DatasetSearchResponse<Dataset>>(
|
|
654
|
-
datasetsUrl,
|
|
655
|
-
{ params: datasetsParams, lazy: true, server: initialType === 'datasets' },
|
|
656
|
-
)
|
|
657
|
-
const { data: dataservicesResults, status: dataservicesStatus } = await useFetch<DataserviceSearchResponse<Dataservice>>(
|
|
658
|
-
dataservicesUrl,
|
|
659
|
-
{ params: dataservicesParams, lazy: true, server: initialType === 'dataservices' },
|
|
660
|
-
)
|
|
661
|
-
const { data: reusesResults, status: reusesStatus } = await useFetch<ReuseSearchResponse<Reuse>>(
|
|
662
|
-
reusesUrl,
|
|
663
|
-
{ params: reusesParams, lazy: true, server: initialType === 'reuses' },
|
|
664
|
-
)
|
|
665
|
-
const { data: organizationsResults, status: organizationsStatus } = await useFetch<OrganizationSearchResponse<Organization>>(
|
|
666
|
-
organizationsUrl,
|
|
667
|
-
{ params: organizationsParams, lazy: true, server: initialType === 'organizations' },
|
|
668
|
-
)
|
|
669
|
-
const { data: topicsResults, status: topicsStatus } = await useFetch<TopicSearchResponse<TopicV2>>(
|
|
670
|
-
topicsUrl,
|
|
671
|
-
{ params: topicsParams, lazy: true, server: initialType === 'topics' },
|
|
672
|
-
)
|
|
673
|
-
|
|
674
|
-
const typesMeta = {
|
|
675
|
-
datasets: {
|
|
676
|
-
icon: RiDatabase2Line,
|
|
677
|
-
name: t('Jeux de données'),
|
|
678
|
-
placeholder: t('ex. élections présidentielles'),
|
|
679
|
-
results: datasetsResults,
|
|
680
|
-
status: datasetsStatus,
|
|
681
|
-
},
|
|
682
|
-
dataservices: {
|
|
683
|
-
icon: RiTerminalLine,
|
|
684
|
-
name: t('API'),
|
|
685
|
-
placeholder: t('ex: SIRENE'),
|
|
686
|
-
results: dataservicesResults,
|
|
687
|
-
status: dataservicesStatus,
|
|
688
|
-
},
|
|
689
|
-
reuses: {
|
|
690
|
-
icon: RiLineChartLine,
|
|
691
|
-
name: t('Réutilisations'),
|
|
692
|
-
placeholder: t('Rechercher une réutilisation de données'),
|
|
693
|
-
results: reusesResults,
|
|
694
|
-
status: reusesStatus,
|
|
695
|
-
},
|
|
696
|
-
organizations: {
|
|
697
|
-
icon: RiBuilding2Line,
|
|
698
|
-
name: t('Organisations'),
|
|
699
|
-
placeholder: t('Rechercher une organisation'),
|
|
700
|
-
results: organizationsResults,
|
|
701
|
-
status: organizationsStatus,
|
|
702
|
-
},
|
|
703
|
-
topics: {
|
|
704
|
-
icon: RiBookShelfLine,
|
|
705
|
-
name: t('Thématiques'),
|
|
706
|
-
placeholder: t('Rechercher une thématique'),
|
|
707
|
-
results: topicsResults,
|
|
708
|
-
status: topicsStatus,
|
|
709
|
-
},
|
|
710
|
-
} as const
|
|
711
|
-
|
|
712
|
-
const searchResults = computed(() => typesMeta[currentType.value].results.value)
|
|
713
|
-
const searchResultsStatus = computed(() => typesMeta[currentType.value].status.value)
|
|
704
|
+
const searchResults = computed(() => resultsMap[currentType.value]?.data.value)
|
|
705
|
+
const searchResultsStatus = computed(() => resultsMap[currentType.value]?.status.value)
|
|
714
706
|
|
|
715
707
|
// RSS feed URL for datasets
|
|
716
708
|
const rssUrl = computed(() => {
|
|
717
|
-
if (
|
|
709
|
+
if (currentTypeConfig.value?.class !== 'datasets') return null
|
|
718
710
|
|
|
719
711
|
const params = new URLSearchParams()
|
|
720
|
-
const datasetsConfig = props.config.find(c => c.class === 'datasets')
|
|
721
712
|
|
|
722
713
|
// Add hidden filters first
|
|
723
|
-
if (
|
|
724
|
-
for (const hf of
|
|
714
|
+
if (currentTypeConfig.value?.hiddenFilters) {
|
|
715
|
+
for (const hf of currentTypeConfig.value.hiddenFilters) {
|
|
725
716
|
if (hf?.value) params.set(hf.key as string, String(hf.value))
|
|
726
717
|
}
|
|
727
718
|
}
|
package/src/types/search.ts
CHANGED
|
@@ -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,6 +296,7 @@ export type SortOption<Sort extends string> = {
|
|
|
291
296
|
|
|
292
297
|
export type DatasetSearchConfig = {
|
|
293
298
|
class: 'datasets'
|
|
299
|
+
key?: string
|
|
294
300
|
name?: string
|
|
295
301
|
hiddenFilters?: HiddenFilter<DatasetSearchFilters>[]
|
|
296
302
|
basicFilters?: (keyof DatasetSearchFilters)[]
|
|
@@ -300,6 +306,7 @@ export type DatasetSearchConfig = {
|
|
|
300
306
|
|
|
301
307
|
export type DataserviceSearchConfig = {
|
|
302
308
|
class: 'dataservices'
|
|
309
|
+
key?: string
|
|
303
310
|
name?: string
|
|
304
311
|
hiddenFilters?: HiddenFilter<DataserviceSearchFilters>[]
|
|
305
312
|
basicFilters?: (keyof DataserviceSearchFilters)[]
|
|
@@ -309,6 +316,7 @@ export type DataserviceSearchConfig = {
|
|
|
309
316
|
|
|
310
317
|
export type ReuseSearchConfig = {
|
|
311
318
|
class: 'reuses'
|
|
319
|
+
key?: string
|
|
312
320
|
name?: string
|
|
313
321
|
hiddenFilters?: HiddenFilter<ReuseSearchFilters>[]
|
|
314
322
|
basicFilters?: (keyof ReuseSearchFilters)[]
|
|
@@ -318,6 +326,7 @@ export type ReuseSearchConfig = {
|
|
|
318
326
|
|
|
319
327
|
export type OrganizationSearchConfig = {
|
|
320
328
|
class: 'organizations'
|
|
329
|
+
key?: string
|
|
321
330
|
name?: string
|
|
322
331
|
hiddenFilters?: HiddenFilter<OrganizationSearchFilters>[]
|
|
323
332
|
basicFilters?: (keyof OrganizationSearchFilters)[]
|
|
@@ -327,6 +336,7 @@ export type OrganizationSearchConfig = {
|
|
|
327
336
|
|
|
328
337
|
export type TopicSearchConfig = {
|
|
329
338
|
class: 'topics'
|
|
339
|
+
key?: string
|
|
330
340
|
name?: string
|
|
331
341
|
hiddenFilters?: HiddenFilter<TopicSearchFilters>[]
|
|
332
342
|
basicFilters?: (keyof TopicSearchFilters)[]
|
|
@@ -340,6 +350,15 @@ export type SearchType = SearchTypeConfig['class']
|
|
|
340
350
|
|
|
341
351
|
export type GlobalSearchConfig = SearchTypeConfig[]
|
|
342
352
|
|
|
353
|
+
// Maps each search class to its concrete response shape.
|
|
354
|
+
export type SearchResponseByClass = {
|
|
355
|
+
datasets: DatasetSearchResponse<Dataset>
|
|
356
|
+
dataservices: DataserviceSearchResponse<Dataservice>
|
|
357
|
+
reuses: ReuseSearchResponse<Reuse>
|
|
358
|
+
organizations: OrganizationSearchResponse<Organization>
|
|
359
|
+
topics: TopicSearchResponse<TopicV2>
|
|
360
|
+
}
|
|
361
|
+
|
|
343
362
|
// Helper functions for default configs
|
|
344
363
|
|
|
345
364
|
export const defaultDatasetSortOptions: SortOption<DatasetSearchSort>[] = [
|