@datagouv/components-next 0.2.0 → 1.0.0
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 +1 -1
- package/assets/main.css +56 -1
- package/dist/Control-BNCDn-8E.js +148 -0
- package/dist/{Datafair.client-x39O4yfF.js → Datafair.client-Dls5AHTE.js} +1 -1
- package/dist/Event-BOgJUhNR.js +738 -0
- package/dist/Image-BN-4XkIn.js +247 -0
- package/dist/{JsonPreview.client-BMsC5JcY.js → JsonPreview.client-DPDTs433.js} +14 -14
- package/dist/Map-BdT3i2C4.js +7609 -0
- package/dist/MapContainer.client-BdAzd7bj.js +105 -0
- package/dist/OSM-CamriM9b.js +71 -0
- package/dist/{PdfPreview.client-COOkEkRA.js → PdfPreview.client-CopqSDyt.js} +3 -3
- package/dist/{Pmtiles.client-BaiIo4VZ.js → Pmtiles.client-mF6xaOO_.js} +2 -2
- package/dist/ScaleLine-BiesrgOv.js +165 -0
- package/dist/Swagger.client-eJ7gpfZA.js +4 -0
- package/dist/Tile-DCuqwNOI.js +1206 -0
- package/dist/TileImage-CmZf8EdU.js +1067 -0
- package/dist/View-DcDc7N2K.js +2858 -0
- package/dist/{XmlPreview.client-CAdN0w_Y.js → XmlPreview.client-C0OgBkSq.js} +7 -7
- package/dist/common-C4rDcQpp.js +243 -0
- package/dist/components-next.css +1 -1
- package/dist/components-next.js +153 -117
- package/dist/components.css +1 -1
- package/dist/{MapContainer.client-DeSo8EvG.js → index-BRGqW8aQ.js} +4975 -21416
- package/dist/leaflet-src-7m1mB8LI.js +6338 -0
- package/dist/{main-Dgri3TQL.js → main-CNHxAJ8J.js} +56758 -51450
- package/dist/proj-CKwYjU38.js +1569 -0
- package/dist/tilecoord-YW3qEH_j.js +884 -0
- package/dist/{vue3-xml-viewer.common-D6skc_Ai.js → vue3-xml-viewer.common-CmAdQfIy.js} +1 -1
- package/package.json +5 -1
- package/src/components/ActivityList/ActivityList.vue +6 -2
- package/src/components/AppLink.vue +4 -1
- package/src/components/Avatar.vue +2 -2
- package/src/components/AvatarWithName.vue +8 -4
- package/src/components/BouncingDots.vue +21 -0
- package/src/components/BrandedButton.vue +2 -0
- package/src/components/CopyButton.vue +19 -7
- package/src/components/DataserviceCard.vue +83 -118
- package/src/components/DatasetCard.vue +110 -171
- package/src/components/DatasetInformation/DatasetEmbedSection.vue +43 -0
- package/src/components/DatasetInformation/DatasetInformationSection.vue +73 -0
- package/src/components/DatasetInformation/DatasetSchemaSection.vue +74 -0
- package/src/components/DatasetInformation/DatasetSpatialSection.vue +59 -0
- package/src/components/DatasetInformation/DatasetTemporalitySection.vue +45 -0
- package/src/components/DatasetInformation/index.ts +5 -0
- package/src/components/DatasetQualityTooltipContent.vue +3 -3
- package/src/components/DescriptionList.vue +1 -4
- package/src/components/DescriptionListDetails.vue +5 -0
- package/src/components/DescriptionListTerm.vue +5 -0
- package/src/components/DiscussionMessageCard.vue +63 -0
- package/src/components/ExtraAccordion.vue +4 -4
- package/src/components/Form/BadgeSelect.vue +35 -0
- package/src/components/Form/FormatSelect.vue +28 -0
- package/src/components/Form/GeozoneSelect.vue +52 -0
- package/src/components/Form/GranularitySelect.vue +29 -0
- package/src/components/Form/LicenseSelect.vue +30 -0
- package/src/components/Form/OrganizationSelect.vue +62 -0
- package/src/components/Form/OrganizationTypeSelect.vue +34 -0
- package/src/components/Form/ReuseTopicSelect.vue +29 -0
- package/src/components/Form/SchemaSelect.vue +30 -0
- package/src/components/Form/SearchableSelect.vue +334 -0
- package/src/components/Form/SelectGroup.vue +132 -0
- package/src/components/Form/TagSelect.vue +38 -0
- package/src/components/LeafletMap.vue +31 -0
- package/src/components/LicenseBadge.vue +24 -0
- package/src/components/LoadingBlock.vue +23 -2
- package/src/components/MarkdownViewer.vue +3 -1
- package/src/components/ObjectCard.vue +42 -0
- package/src/components/ObjectCardBadge.vue +22 -0
- package/src/components/ObjectCardHeader.vue +35 -0
- package/src/components/ObjectCardOwner.vue +43 -0
- package/src/components/ObjectCardShortDescription.vue +28 -0
- package/src/components/OrganizationCard.vue +35 -20
- package/src/components/OrganizationLogo.vue +1 -1
- package/src/components/OrganizationNameWithCertificate.vue +13 -7
- package/src/components/OwnerTypeIcon.vue +1 -0
- package/src/components/Pagination.vue +1 -1
- package/src/components/Placeholder.vue +5 -2
- package/src/components/PostCard.vue +62 -0
- package/src/components/RadioGroup.vue +32 -0
- package/src/components/RadioInput.vue +64 -0
- package/src/components/ResourceAccordion/EditButton.vue +2 -3
- package/src/components/ResourceAccordion/MapContainer.client.vue +20 -16
- package/src/components/ResourceAccordion/Metadata.vue +11 -24
- package/src/components/ResourceAccordion/Pmtiles.client.vue +1 -1
- package/src/components/ResourceAccordion/Preview.vue +1 -1
- package/src/components/ResourceAccordion/ResourceAccordion.vue +30 -20
- package/src/components/ResourceAccordion/ResourceIcon.vue +1 -0
- package/src/components/ResourceAccordion/SchemaBadge.vue +2 -2
- package/src/components/ResourceExplorer/ResourceExplorer.vue +243 -0
- package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +116 -0
- package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +361 -0
- package/src/components/ReuseCard.vue +8 -28
- package/src/components/ReuseHorizontalCard.vue +80 -0
- package/src/components/Search/BasicAndAdvancedFilters.vue +49 -0
- package/src/components/Search/Filter/AccessTypeFilter.vue +37 -0
- package/src/components/Search/Filter/DatasetBadgeFilter.vue +40 -0
- package/src/components/Search/Filter/FilterButtonGroup.vue +78 -0
- package/src/components/Search/Filter/FormatFamilyFilter.vue +39 -0
- package/src/components/Search/Filter/LastUpdateRangeFilter.vue +37 -0
- package/src/components/Search/Filter/ProducerTypeFilter.vue +39 -0
- package/src/components/Search/Filter/ReuseTypeFilter.vue +42 -0
- package/src/components/Search/GlobalSearch.vue +611 -0
- package/src/components/Search/SearchInput.vue +63 -0
- package/src/components/Search/Sidemenu.vue +38 -0
- package/src/components/StatBox.vue +5 -5
- package/src/components/Tag.vue +30 -0
- package/src/components/Toggletip.vue +6 -2
- package/src/components/Tooltip.vue +2 -3
- package/src/components/TopicCard.vue +134 -0
- package/src/components/radioGroupContext.ts +9 -0
- package/src/composables/useDebouncedRef.ts +31 -0
- package/src/composables/useMetrics.ts +4 -3
- package/src/composables/useResourceCapabilities.ts +118 -0
- package/src/composables/useRouteQueryBoolean.ts +10 -0
- package/src/composables/useSelectModelSync.ts +89 -0
- package/src/composables/useStableQueryParams.ts +84 -0
- package/src/config.ts +4 -0
- package/src/functions/api.ts +17 -6
- package/src/functions/api.types.ts +4 -2
- package/src/functions/datasets.ts +1 -29
- package/src/functions/description.ts +33 -0
- package/src/functions/helpers.ts +11 -0
- package/src/functions/markdown.ts +60 -16
- package/src/functions/metrics.ts +33 -0
- package/src/functions/organizations.ts +5 -5
- package/src/main.ts +89 -7
- package/src/types/dataservices.ts +14 -12
- package/src/types/datasets.ts +20 -7
- package/src/types/discussions.ts +20 -0
- package/src/types/licenses.ts +3 -3
- package/src/types/organizations.ts +13 -1
- package/src/types/owned.ts +4 -2
- package/src/types/pages.ts +70 -0
- package/src/types/posts.ts +27 -0
- package/src/types/resources.ts +6 -0
- package/src/types/reuses.ts +14 -5
- package/src/types/search.ts +379 -0
- package/src/types/users.ts +12 -3
- package/dist/Swagger.client-CpLgaLg6.js +0 -4
- package/src/components/DatasetInformationPanel.vue +0 -211
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ObjectCard>
|
|
3
|
+
<ObjectCardHeader
|
|
4
|
+
:icon="RiChat3Line"
|
|
5
|
+
:url="discussionUrl || discussion.self_web_url || '#'"
|
|
6
|
+
>
|
|
7
|
+
{{ discussion.title }}
|
|
8
|
+
</ObjectCardHeader>
|
|
9
|
+
|
|
10
|
+
<div
|
|
11
|
+
v-if="discussion.organization || discussion.user"
|
|
12
|
+
class="text-sm m-0 flex flex-wrap md:flex-nowrap gap-y-1 items-center truncate"
|
|
13
|
+
>
|
|
14
|
+
<ObjectCardOwner
|
|
15
|
+
:organization="discussion.organization"
|
|
16
|
+
:owner="discussion.user"
|
|
17
|
+
:organization-url="organizationUrl"
|
|
18
|
+
/>
|
|
19
|
+
<RiSubtractLine
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
class="size-4 flex-none fill-gray-medium"
|
|
22
|
+
/>
|
|
23
|
+
<span class="text-gray-medium whitespace-nowrap">
|
|
24
|
+
{{ t('Posté {date}', { date: formatDate(discussion.created) }) }}
|
|
25
|
+
</span>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<ObjectCardShortDescription :text="firstMessageContent" />
|
|
29
|
+
|
|
30
|
+
<slot />
|
|
31
|
+
</ObjectCard>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script setup lang="ts">
|
|
35
|
+
import { RiChat3Line, RiSubtractLine } from '@remixicon/vue'
|
|
36
|
+
import { computed } from 'vue'
|
|
37
|
+
import type { RouteLocationRaw } from 'vue-router'
|
|
38
|
+
import { useFormatDate } from '../functions/dates'
|
|
39
|
+
import { useTranslation } from '../composables/useTranslation'
|
|
40
|
+
import type { Thread } from '../types/discussions'
|
|
41
|
+
import ObjectCard from './ObjectCard.vue'
|
|
42
|
+
import ObjectCardHeader from './ObjectCardHeader.vue'
|
|
43
|
+
import ObjectCardOwner from './ObjectCardOwner.vue'
|
|
44
|
+
import ObjectCardShortDescription from './ObjectCardShortDescription.vue'
|
|
45
|
+
|
|
46
|
+
const props = defineProps<{
|
|
47
|
+
discussion: Thread
|
|
48
|
+
discussionUrl?: RouteLocationRaw
|
|
49
|
+
organizationUrl?: RouteLocationRaw
|
|
50
|
+
}>()
|
|
51
|
+
|
|
52
|
+
const { t } = useTranslation()
|
|
53
|
+
const { formatRelativeIfRecentDate } = useFormatDate()
|
|
54
|
+
|
|
55
|
+
const firstMessageContent = computed(() => props.discussion.discussion?.[0]?.content)
|
|
56
|
+
|
|
57
|
+
const formatDate = (dateString: string) => {
|
|
58
|
+
return formatRelativeIfRecentDate(dateString, {
|
|
59
|
+
dateStyle: 'long',
|
|
60
|
+
timeStyle: 'short',
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
</script>
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
as="div"
|
|
5
5
|
>
|
|
6
6
|
<header
|
|
7
|
-
class="flex flex-wrap items-center pb-6 mb-6 border-
|
|
7
|
+
class="flex flex-wrap items-center pb-6 mb-6 border-b border-gray-default"
|
|
8
8
|
>
|
|
9
9
|
<div class="fr-col">
|
|
10
10
|
<component
|
|
11
11
|
:is="titleLevel"
|
|
12
|
-
class="subtitle
|
|
12
|
+
class="subtitle uppercase m-0"
|
|
13
13
|
>
|
|
14
14
|
{{ titleText }}
|
|
15
15
|
</component>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
</div>
|
|
35
35
|
</header>
|
|
36
36
|
<DisclosurePanel :id="accordionId">
|
|
37
|
-
<div class="pb-6 mb-6 border-
|
|
37
|
+
<div class="pb-6 mb-6 border-b border-gray-default">
|
|
38
38
|
<div
|
|
39
39
|
class="fr-grid-row fr-grid-row--gutters fr-text--sm fr-m-0"
|
|
40
40
|
data-testid="extra-list"
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
:key="key"
|
|
45
45
|
class="fr-col-12 fr-col-sm-6 fr-col-md-4"
|
|
46
46
|
>
|
|
47
|
-
<h3 class="subtitle
|
|
47
|
+
<h3 class="subtitle mb-1">
|
|
48
48
|
{{ key }}
|
|
49
49
|
</h3>
|
|
50
50
|
<p class="text-sm m-0 text-gray-medium break-all">
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="badges"
|
|
5
|
+
:loading="status === 'pending'"
|
|
6
|
+
:label="t('Label de données')"
|
|
7
|
+
:placeholder="t('Tous les labels')"
|
|
8
|
+
:get-option-id="(b: TranslatedBadge) => b.kind"
|
|
9
|
+
:display-value="(b: TranslatedBadge) => b.label"
|
|
10
|
+
:multiple="false"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { computed } from 'vue'
|
|
16
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
17
|
+
import { useSelectModelSync } from '../../composables/useSelectModelSync'
|
|
18
|
+
import { useFetch } from '../../functions/api'
|
|
19
|
+
import type { TranslatedBadge } from '../../types/badges'
|
|
20
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
21
|
+
|
|
22
|
+
const model = defineModel<TranslatedBadge | null>({ default: null })
|
|
23
|
+
const id = defineModel<string | undefined>('id')
|
|
24
|
+
|
|
25
|
+
const { t } = useTranslation()
|
|
26
|
+
|
|
27
|
+
const { data: badgesRecord, status } = await useFetch<Record<string, string>>('/api/1/datasets/badges/', { lazy: true })
|
|
28
|
+
|
|
29
|
+
const badges = computed<TranslatedBadge[]>(() => {
|
|
30
|
+
if (!badgesRecord.value) return []
|
|
31
|
+
return Object.entries(badgesRecord.value).map(([kind, label]) => ({ kind, label }))
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
useSelectModelSync({ model, id, items: badges, getId: b => b.kind })
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="formats ?? []"
|
|
5
|
+
:loading="status === 'pending'"
|
|
6
|
+
:label="t('Formats')"
|
|
7
|
+
:placeholder="t('Tous les formats')"
|
|
8
|
+
:get-option-id="(f: string) => f"
|
|
9
|
+
:display-value="(f: string) => f"
|
|
10
|
+
:multiple="false"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
16
|
+
import { useStringSelectSync } from '../../composables/useSelectModelSync'
|
|
17
|
+
import { useFetch } from '../../functions/api'
|
|
18
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
19
|
+
|
|
20
|
+
const model = defineModel<string | null>({ default: null })
|
|
21
|
+
const id = defineModel<string | undefined>('id')
|
|
22
|
+
|
|
23
|
+
const { t } = useTranslation()
|
|
24
|
+
|
|
25
|
+
const { data: formats, status } = await useFetch<string[]>('/api/1/datasets/extensions/', { lazy: true })
|
|
26
|
+
|
|
27
|
+
useStringSelectSync({ model, id })
|
|
28
|
+
</script>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="[]"
|
|
5
|
+
:suggest="suggestGeozones"
|
|
6
|
+
:label="t('Couverture spatiale')"
|
|
7
|
+
:placeholder="t('Toutes les couvertures')"
|
|
8
|
+
:get-option-id="(g: SpatialZone) => g.id"
|
|
9
|
+
:display-value="(g: SpatialZone) => g.name"
|
|
10
|
+
:multiple="false"
|
|
11
|
+
:loading="fetching"
|
|
12
|
+
>
|
|
13
|
+
<template #option="{ option }">
|
|
14
|
+
<div class="flex-1">
|
|
15
|
+
{{ option.name }}
|
|
16
|
+
</div>
|
|
17
|
+
<code class="bg-gray-100 text-gray-600 p-1 text-xs rounded">{{ option.code }}</code>
|
|
18
|
+
</template>
|
|
19
|
+
</SearchableSelect>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { ofetch } from 'ofetch'
|
|
24
|
+
import { useComponentsConfig } from '../../config'
|
|
25
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
26
|
+
import { useAsyncSelectModelSync } from '../../composables/useSelectModelSync'
|
|
27
|
+
import type { SpatialZone } from '../../types/granularity'
|
|
28
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
29
|
+
|
|
30
|
+
const model = defineModel<SpatialZone | null>({ default: null })
|
|
31
|
+
const id = defineModel<string | undefined>('id')
|
|
32
|
+
|
|
33
|
+
const config = useComponentsConfig()
|
|
34
|
+
const { t } = useTranslation()
|
|
35
|
+
|
|
36
|
+
const { fetching } = useAsyncSelectModelSync({
|
|
37
|
+
model,
|
|
38
|
+
id,
|
|
39
|
+
getId: z => z.id,
|
|
40
|
+
fetchById: async (zoneId) => {
|
|
41
|
+
const zones = await suggestGeozones(zoneId)
|
|
42
|
+
return zones.find(z => z.id === zoneId) ?? null
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
async function suggestGeozones(q: string) {
|
|
47
|
+
return await ofetch<SpatialZone[]>('/api/1/spatial/zones/suggest/', {
|
|
48
|
+
baseURL: config.apiBase,
|
|
49
|
+
query: { q, size: 20 },
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
</script>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="granularities ?? []"
|
|
5
|
+
:loading="status === 'pending'"
|
|
6
|
+
:label="t('Granularité spatiale')"
|
|
7
|
+
:placeholder="t('Toutes les granularités')"
|
|
8
|
+
:get-option-id="(g: Granularity) => g.id"
|
|
9
|
+
:display-value="(g: Granularity) => g.name"
|
|
10
|
+
:multiple="false"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
16
|
+
import { useSelectModelSync } from '../../composables/useSelectModelSync'
|
|
17
|
+
import { useFetch } from '../../functions/api'
|
|
18
|
+
import type { Granularity } from '../../types/granularity'
|
|
19
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
20
|
+
|
|
21
|
+
const model = defineModel<Granularity | null>({ default: null })
|
|
22
|
+
const id = defineModel<string | undefined>('id')
|
|
23
|
+
|
|
24
|
+
const { t } = useTranslation()
|
|
25
|
+
|
|
26
|
+
const { data: granularities, status } = await useFetch<Granularity[]>('/api/1/spatial/granularities/', { lazy: true })
|
|
27
|
+
|
|
28
|
+
useSelectModelSync({ model, id, items: granularities, getId: g => g.id })
|
|
29
|
+
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="licenses ?? []"
|
|
5
|
+
:loading="status === 'pending'"
|
|
6
|
+
:label="t('Licences')"
|
|
7
|
+
:explanation="t('Les licences définissent les règles de réutilisation des jeux de données publiés.')"
|
|
8
|
+
:placeholder="t('Toutes les licences')"
|
|
9
|
+
:get-option-id="(l: License) => l.id"
|
|
10
|
+
:display-value="(l: License) => l.title"
|
|
11
|
+
:multiple="false"
|
|
12
|
+
/>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
17
|
+
import { useSelectModelSync } from '../../composables/useSelectModelSync'
|
|
18
|
+
import { useFetch } from '../../functions/api'
|
|
19
|
+
import type { License } from '../../types/licenses'
|
|
20
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
21
|
+
|
|
22
|
+
const model = defineModel<License | null>({ default: null })
|
|
23
|
+
const id = defineModel<string | undefined>('id')
|
|
24
|
+
|
|
25
|
+
const { t } = useTranslation()
|
|
26
|
+
|
|
27
|
+
const { data: licenses, status } = await useFetch<License[]>('/api/1/datasets/licenses/', { lazy: true })
|
|
28
|
+
|
|
29
|
+
useSelectModelSync({ model, id, items: licenses, getId: l => l.id })
|
|
30
|
+
</script>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="[]"
|
|
5
|
+
:suggest="suggestOrganizations"
|
|
6
|
+
:label="t('Organisations')"
|
|
7
|
+
:placeholder="t('Toutes les organisations')"
|
|
8
|
+
:get-option-id="(option) => option.id"
|
|
9
|
+
:display-value="(option) => option.name"
|
|
10
|
+
:filter="(option, query) => (option.name).toLocaleLowerCase().includes(query.toLocaleLowerCase())"
|
|
11
|
+
:multiple="false"
|
|
12
|
+
:loading="loading || fetching"
|
|
13
|
+
>
|
|
14
|
+
<template #option="{ option }">
|
|
15
|
+
<div class="flex items-center space-x-2">
|
|
16
|
+
<OrganizationLogo
|
|
17
|
+
:organization="option"
|
|
18
|
+
size-class="size-8"
|
|
19
|
+
class="flex-none"
|
|
20
|
+
/>
|
|
21
|
+
<span>{{ option.name }}</span>
|
|
22
|
+
</div>
|
|
23
|
+
</template>
|
|
24
|
+
</SearchableSelect>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup lang="ts">
|
|
28
|
+
import { ofetch } from 'ofetch'
|
|
29
|
+
import { useComponentsConfig } from '../../config'
|
|
30
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
31
|
+
import { useAsyncSelectModelSync } from '../../composables/useSelectModelSync'
|
|
32
|
+
import type { Organization, OrganizationSuggest } from '../../types/organizations'
|
|
33
|
+
import OrganizationLogo from '../OrganizationLogo.vue'
|
|
34
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
35
|
+
|
|
36
|
+
const model = defineModel<Organization | OrganizationSuggest | null>({ default: null })
|
|
37
|
+
const id = defineModel<string | undefined>('id')
|
|
38
|
+
|
|
39
|
+
defineProps<{
|
|
40
|
+
loading?: boolean
|
|
41
|
+
}>()
|
|
42
|
+
|
|
43
|
+
const config = useComponentsConfig()
|
|
44
|
+
const { t } = useTranslation()
|
|
45
|
+
|
|
46
|
+
const { fetching } = useAsyncSelectModelSync({
|
|
47
|
+
model,
|
|
48
|
+
id,
|
|
49
|
+
getId: org => org.id,
|
|
50
|
+
fetchById: orgId => ofetch<Organization>(`/api/1/organizations/${orgId}/`, { baseURL: config.apiBase }),
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
async function suggestOrganizations(q: string): Promise<Array<Organization | OrganizationSuggest>> {
|
|
54
|
+
return await ofetch<Array<OrganizationSuggest>>('/api/1/organizations/suggest/', {
|
|
55
|
+
baseURL: config.apiBase,
|
|
56
|
+
query: {
|
|
57
|
+
q,
|
|
58
|
+
size: 20,
|
|
59
|
+
},
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="selected"
|
|
4
|
+
:options="organizationTypes"
|
|
5
|
+
:label="t(`Type d'organisation`)"
|
|
6
|
+
:placeholder="t('Tous les types')"
|
|
7
|
+
:get-option-id="(opt) => opt.type"
|
|
8
|
+
:display-value="(value) => value.label"
|
|
9
|
+
:multiple="false"
|
|
10
|
+
>
|
|
11
|
+
<template #option="{ option }">
|
|
12
|
+
{{ option.label }}
|
|
13
|
+
</template>
|
|
14
|
+
</SearchableSelect>
|
|
15
|
+
</template>
|
|
16
|
+
|
|
17
|
+
<script setup lang="ts">
|
|
18
|
+
import { computed } from 'vue'
|
|
19
|
+
import { getOrganizationTypes, OTHER, USER } from '../../functions/organizations'
|
|
20
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
21
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
22
|
+
|
|
23
|
+
const model = defineModel<string | undefined>()
|
|
24
|
+
|
|
25
|
+
const { t } = useTranslation()
|
|
26
|
+
|
|
27
|
+
const organizationTypes = getOrganizationTypes()
|
|
28
|
+
.filter(t => t.type !== OTHER && t.type !== USER)
|
|
29
|
+
|
|
30
|
+
const selected = computed({
|
|
31
|
+
get: () => organizationTypes.find(t => t.type === model.value) ?? null,
|
|
32
|
+
set: (value) => { model.value = value?.type },
|
|
33
|
+
})
|
|
34
|
+
</script>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="topics ?? []"
|
|
5
|
+
:loading="status === 'pending'"
|
|
6
|
+
:label="t('Thématique')"
|
|
7
|
+
:placeholder="t('Toutes les thématiques')"
|
|
8
|
+
:get-option-id="(topic: ReuseTopic) => topic.id"
|
|
9
|
+
:display-value="(topic: ReuseTopic) => topic.label"
|
|
10
|
+
:multiple="false"
|
|
11
|
+
/>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
16
|
+
import { useSelectModelSync } from '../../composables/useSelectModelSync'
|
|
17
|
+
import { useFetch } from '../../functions/api'
|
|
18
|
+
import type { ReuseTopic } from '../../types/reuses'
|
|
19
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
20
|
+
|
|
21
|
+
const model = defineModel<ReuseTopic | null>({ default: null })
|
|
22
|
+
const id = defineModel<string | undefined>('id')
|
|
23
|
+
|
|
24
|
+
const { t } = useTranslation()
|
|
25
|
+
|
|
26
|
+
const { data: topics, status } = await useFetch<ReuseTopic[]>('/api/1/reuses/topics/', { lazy: true })
|
|
27
|
+
|
|
28
|
+
useSelectModelSync({ model, id, items: topics, getId: topic => topic.id })
|
|
29
|
+
</script>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<SearchableSelect
|
|
3
|
+
v-model="model"
|
|
4
|
+
:options="schemas ?? []"
|
|
5
|
+
:loading="status === 'pending'"
|
|
6
|
+
:label="t('Schéma')"
|
|
7
|
+
:explanation="t('Les schémas de données permettent de décrire des modèles de données.')"
|
|
8
|
+
:placeholder="t('Tous les schémas')"
|
|
9
|
+
:get-option-id="(s: RegisteredSchema) => s.name"
|
|
10
|
+
:display-value="(s: RegisteredSchema) => s.name"
|
|
11
|
+
:multiple="false"
|
|
12
|
+
/>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup lang="ts">
|
|
16
|
+
import { useTranslation } from '../../composables/useTranslation'
|
|
17
|
+
import { useSelectModelSync } from '../../composables/useSelectModelSync'
|
|
18
|
+
import { useFetch } from '../../functions/api'
|
|
19
|
+
import type { RegisteredSchema } from '../../types/schemas'
|
|
20
|
+
import SearchableSelect from './SearchableSelect.vue'
|
|
21
|
+
|
|
22
|
+
const model = defineModel<RegisteredSchema | null>({ default: null })
|
|
23
|
+
const id = defineModel<string | undefined>('id')
|
|
24
|
+
|
|
25
|
+
const { t } = useTranslation()
|
|
26
|
+
|
|
27
|
+
const { data: schemas, status } = await useFetch<RegisteredSchema[]>('/api/1/datasets/schemas/', { lazy: true })
|
|
28
|
+
|
|
29
|
+
useSelectModelSync({ model, id, items: schemas, getId: s => s.name })
|
|
30
|
+
</script>
|