@datagouv/components-next 0.2.0 → 1.0.1
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 +49 -22
- package/dist/Control-BNCDn-8E.js +148 -0
- package/dist/{Datafair.client-x39O4yfF.js → Datafair.client-B5lBpOl8.js} +2 -2
- package/dist/Event-BOgJUhNR.js +738 -0
- package/dist/Image-BN-4XkIn.js +247 -0
- package/dist/{JsonPreview.client-BMsC5JcY.js → JsonPreview.client-Doz1Z0BS.js} +23 -23
- package/dist/Map-BdT3i2C4.js +7609 -0
- package/dist/MapContainer.client-oiieO8H-.js +105 -0
- package/dist/OSM-CamriM9b.js +71 -0
- package/dist/PdfPreview.client-CdAhkDFJ.js +14513 -0
- package/dist/{Pmtiles.client-BaiIo4VZ.js → Pmtiles.client-B0v8tGJQ.js} +3 -3
- package/dist/ScaleLine-BiesrgOv.js +165 -0
- package/dist/Swagger.client-CsK65JnG.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-CrjHf74q.js} +17 -17
- package/dist/common-C4rDcQpp.js +243 -0
- package/dist/components-next.css +1 -1
- package/dist/components-next.js +158 -117
- package/dist/components.css +1 -1
- package/dist/{MapContainer.client-DeSo8EvG.js → index-Bbu9rOHt.js} +4975 -21416
- package/dist/leaflet-src-7m1mB8LI.js +6338 -0
- package/dist/{main-Dgri3TQL.js → main-CiH8ZmBI.js} +56973 -51462
- 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-Bi_bsV6C.js} +1 -1
- package/package.json +6 -2
- 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 +85 -120
- 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/DatasetQuality.vue +23 -16
- package/src/components/DatasetQualityInline.vue +13 -17
- package/src/components/DatasetQualityScore.vue +12 -15
- 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/OrganizationHorizontalCard.vue +87 -0
- package/src/components/OrganizationLogo.vue +1 -1
- package/src/components/OrganizationNameWithCertificate.vue +12 -6
- 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/ProgressBar.vue +31 -0
- package/src/components/RadioGroup.vue +32 -0
- package/src/components/RadioInput.vue +64 -0
- package/src/components/ResourceAccordion/Datafair.client.vue +1 -1
- package/src/components/ResourceAccordion/EditButton.vue +2 -3
- package/src/components/ResourceAccordion/JsonPreview.client.vue +3 -3
- package/src/components/ResourceAccordion/MapContainer.client.vue +21 -17
- package/src/components/ResourceAccordion/Metadata.vue +11 -24
- package/src/components/ResourceAccordion/PdfPreview.client.vue +70 -74
- package/src/components/ResourceAccordion/Pmtiles.client.vue +2 -2
- package/src/components/ResourceAccordion/Preview.vue +2 -2
- package/src/components/ResourceAccordion/ResourceAccordion.vue +35 -28
- package/src/components/ResourceAccordion/ResourceIcon.vue +1 -0
- package/src/components/ResourceAccordion/SchemaBadge.vue +2 -2
- package/src/components/ResourceAccordion/XmlPreview.client.vue +3 -3
- package/src/components/ResourceExplorer/ResourceExplorer.vue +243 -0
- package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +116 -0
- package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +410 -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 +49 -0
- package/src/components/Search/Filter/ReuseTypeFilter.vue +42 -0
- package/src/components/Search/GlobalSearch.vue +707 -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 +11 -4
- 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/useHasTabularData.ts +15 -0
- package/src/composables/useMetrics.ts +4 -3
- package/src/composables/useResourceCapabilities.ts +131 -0
- package/src/composables/useRouteQueryBoolean.ts +10 -0
- package/src/composables/useSelectModelSync.ts +89 -0
- package/src/composables/useStableQueryParams.ts +84 -0
- package/src/composables/useTranslation.ts +2 -1
- package/src/config.ts +4 -0
- package/src/functions/api.ts +25 -6
- package/src/functions/api.types.ts +5 -3
- 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/functions/resourceCapabilities.ts +55 -0
- package/src/main.ts +96 -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 +16 -0
- package/src/types/reuses.ts +14 -5
- package/src/types/search.ts +407 -0
- package/src/types/users.ts +12 -3
- package/dist/PdfPreview.client-COOkEkRA.js +0 -107
- package/dist/Swagger.client-CpLgaLg6.js +0 -4
- package/dist/pdf-vue3-IkJO65RH.js +0 -273
- package/dist/pdf.min-f72cfa08-CdgJTooZ.js +0 -9501
- package/src/components/DatasetInformationPanel.vue +0 -211
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
2
|
+
<Toggletip
|
|
3
|
+
:styled-button="false"
|
|
4
|
+
button-class="flex flex-col gap-1 rounded-sm p-1.5 -m-1.5 border-transparent -outline-offset-2 hover:bg-gray-some transition-colors w-full text-left"
|
|
5
|
+
:button-props="{ title: t('Qualité des métadonnées') }"
|
|
6
|
+
>
|
|
7
|
+
<span class="flex items-center gap-1">
|
|
8
|
+
<RiInformationLine
|
|
9
|
+
class="size-5 shrink-0"
|
|
10
|
+
aria-hidden="true"
|
|
11
|
+
/>
|
|
12
|
+
<span class="text-sm text-gray-plain font-bold">
|
|
13
|
+
{{ t('Qualité des métadonnées:') }}
|
|
14
|
+
</span>
|
|
15
|
+
</span>
|
|
16
|
+
<DatasetQualityScore
|
|
17
|
+
:score="quality.score"
|
|
18
|
+
class="w-full"
|
|
19
|
+
/>
|
|
20
|
+
<template #toggletip>
|
|
21
|
+
<DatasetQualityTooltipContent :quality />
|
|
22
|
+
</template>
|
|
23
|
+
</Toggletip>
|
|
18
24
|
<template v-if="!hideWarnings">
|
|
19
25
|
<ul class="list-none pl-0">
|
|
20
26
|
<DatasetQualityItemWarning
|
|
@@ -54,6 +60,7 @@
|
|
|
54
60
|
</template>
|
|
55
61
|
|
|
56
62
|
<script setup lang="ts">
|
|
63
|
+
import { RiInformationLine } from '@remixicon/vue'
|
|
57
64
|
import type { Quality } from '../types/datasets'
|
|
58
65
|
import DatasetQualityItemWarning from './DatasetQualityItemWarning.vue'
|
|
59
66
|
import DatasetQualityScore from './DatasetQualityScore.vue'
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-0
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
<div class="fr-grid-row fr-grid-row--middle fr-mr-1v">
|
|
16
|
-
<DatasetQualityScore :score="quality.score" />
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
2
|
+
<div class="m-0 text-sm text-gray-medium">
|
|
3
|
+
<Toggletip
|
|
4
|
+
:styled-button="false"
|
|
5
|
+
button-class="border-transparent -outline-offset-2 inline-flex items-center justify-center hover:bg-gray-lower transition-colors"
|
|
6
|
+
:button-props="{ class: 'relative z-2 gap-1 rounded-sm px-1 -mx-1 group/quality', title: t('Qualité des métadonnées') }"
|
|
7
|
+
>
|
|
8
|
+
<RiInformationLine class="size-3.5 shrink-0" />
|
|
9
|
+
<span class="text-gray-medium text-sm group-hover/quality:underline">{{ t('Métadonnées :') }}</span>
|
|
10
|
+
<DatasetQualityScore :score="quality.score" />
|
|
11
|
+
<template #toggletip>
|
|
12
|
+
<DatasetQualityTooltipContent :quality />
|
|
13
|
+
</template>
|
|
14
|
+
</Toggletip>
|
|
19
15
|
</div>
|
|
20
16
|
</template>
|
|
21
17
|
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
class="quality-score"
|
|
4
|
-
:class="props.class"
|
|
5
|
-
min="0"
|
|
6
|
-
low="0"
|
|
7
|
-
:high="high"
|
|
8
|
-
:max="quality_max_score"
|
|
9
|
-
:optimum="quality_max_score"
|
|
2
|
+
<ProgressBar
|
|
10
3
|
:value="score"
|
|
4
|
+
:max="quality_max_score"
|
|
5
|
+
:aria-label="score >= high ? t('Bon') : t('À améliorer')"
|
|
6
|
+
:bar-class="score >= high ? 'bg-success-dark' : 'bg-gray-low'"
|
|
7
|
+
:class="props.class"
|
|
11
8
|
>
|
|
12
|
-
<
|
|
13
|
-
{{ t('Bon') }}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
</meter>
|
|
9
|
+
<span class="sr-only">
|
|
10
|
+
<template v-if="score >= high">{{ t('Bon') }}</template>
|
|
11
|
+
<template v-else>{{ t('À améliorer') }}</template>
|
|
12
|
+
({{ calculatedScore }})
|
|
13
|
+
</span>
|
|
14
|
+
</ProgressBar>
|
|
19
15
|
</template>
|
|
20
16
|
|
|
21
17
|
<script setup lang="ts">
|
|
22
18
|
import { computed } from 'vue'
|
|
23
19
|
import { useTranslation } from '../composables/useTranslation'
|
|
20
|
+
import ProgressBar from './ProgressBar.vue'
|
|
24
21
|
|
|
25
22
|
const props = withDefaults(defineProps<{
|
|
26
23
|
score: number
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
2
|
+
<p class="text-sm text-gray-plain font-bold mb-0">
|
|
3
3
|
{{ t("Qualité des métadonnées :") }}
|
|
4
|
-
</
|
|
4
|
+
</p>
|
|
5
5
|
<ul class="list-none pl-0 space-y-2">
|
|
6
6
|
<DatasetQualityItem
|
|
7
7
|
:passed="quality.dataset_description_quality"
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
class="pb-0"
|
|
53
53
|
/>
|
|
54
54
|
</ul>
|
|
55
|
-
<div class="fr-grid-row fr-grid-row--right
|
|
55
|
+
<div class="fr-grid-row fr-grid-row--right">
|
|
56
56
|
<a
|
|
57
57
|
:href="config.datasetQualityGuideUrl"
|
|
58
58
|
target="_blank"
|
|
@@ -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 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>
|