Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions components/Pages/EditoHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
{{ title }}
</h1>
<CdataLink
v-if="linkUrl && linkLabel"
class="bg-[#0D0C4F]/20 hover:bg-[#0D0C4F]/30 fr-raw-link text-white font-medium text-lg px-5 py-3 rounded-4xl flex justify-start items-start sm:items-center gap-2"
:href="linkUrl"
>
Expand All @@ -34,6 +35,7 @@
<div class="w-full flex rounded-t overflow-hidden">
<input
:id="id"
:value="defaultQuery"
name="q"
class="w-full text-2xl bg-white/80 border-b-4 border-white px-4 text-black placeholder:text-gray-plain"
:placeholder
Expand All @@ -58,15 +60,20 @@
<script setup lang="ts">
import { RiInformation2Line, RiSearchLine } from '@remixicon/vue'

const props = defineProps<{
const props = withDefaults(defineProps<{
color: 'primary' | 'green' | 'purple'
title: string
subtitle: string
placeholder: string
searchUrl: string
linkLabel: string
linkUrl: string
}>()
linkLabel?: string
linkUrl?: string
defaultQuery?: string
}>(), {
linkLabel: '',
linkUrl: '',
defaultQuery: '',
})

const id = useId()

Expand Down
212 changes: 132 additions & 80 deletions datagouv-components/src/components/DataserviceCard.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<template>
<article
class="my-4 p-4 bg-white hover:bg-gray-some border fr-enlarge-link"
class="p-4 bg-white hover:bg-gray-some border fr-enlarge-link relative"
:class="{
'border-tabular-api': isTabularApi,
'border-gray-default': !isTabularApi,
'mt-6': showBadge,
'mt-2': showBadge,
}"
>
<div
Expand Down Expand Up @@ -40,89 +40,125 @@
{{ t('Archivé') }}
</p>
</div>
<h4 class="text-base mb-0 flex items-center gap-1">
<slot
name="dataserviceUrl"
:dataservice="dataservice"
:dataservice-url="dataserviceUrl"
>
<RiSparklingLine
v-if="isTabularApi"
class="size-4 flex-none"
/>
<RiTerminalLine
v-else
class="size-4 flex-none"
/>
<AppLink
class="truncate"
:to="dataserviceUrl"
>
{{ dataservice.title }}
</AppLink>
</slot>
</h4>
<div
v-if="dataservice.organization || dataservice.owner"
class="text-gray-medium overflow-hidden flex items-center gap-1 mt-1 mb-0"
>
<p
v-if="dataservice.organization"
class="text-sm block overflow-hidden mb-0 relative z-[2]"
>
<AppLink
v-if="organizationUrl"
class="link text-sm overflow-hidden"
:to="organizationUrl"
<div class="flex flex-wrap md:flex-nowrap gap-4 items-start">
<div class="flex-none">
<div class="flex justify-center items-center p-2 border border-gray-lower bg-[#fff] rounded-md overflow-hidden">
<OrganizationLogo
v-if="dataservice.organization"
:organization="dataservice.organization"
size-class="size-12"
/>
<Avatar
v-else-if="dataservice.owner"
:user="dataservice.owner"
:size="48"
/>
<Placeholder
v-else
type="Dataset"
class="size-12"
/>
</div>
</div>
<div class="flex-1 overflow-hidden">
<h4 class="text-base mb-0 flex items-center gap-1">
<slot
name="dataserviceUrl"
:dataservice="dataservice"
:dataservice-url="dataserviceUrl"
>
<RiSparklingLine
v-if="isTabularApi"
class="size-4 flex-none"
/>
<RiTerminalLine
v-else
class="size-4 flex-none"
/>
<AppLink
class="truncate"
:to="dataserviceUrl"
>
{{ dataservice.title }}
</AppLink>
</slot>
</h4>
<div
v-if="dataservice.organization || dataservice.owner"
class="text-gray-medium overflow-hidden flex items-center gap-1 m-0"
>
<OrganizationNameWithCertificate :organization="dataservice.organization" />
</AppLink>
<OrganizationNameWithCertificate
v-else
:organization="dataservice.organization"
<p
v-if="dataservice.organization"
class="text-sm block overflow-hidden mb-0 relative z-[2]"
>
<AppLink
v-if="organizationUrl"
class="link text-sm overflow-hidden"
:to="organizationUrl"
>
<OrganizationNameWithCertificate :organization="dataservice.organization" />
</AppLink>
<OrganizationNameWithCertificate
v-else
:organization="dataservice.organization"
/>
</p>
<p
v-else
class="text-sm mb-0 truncate"
>
{{ ownerName }}
</p>
<RiSubtractLine class="size-4 flex-none fill-gray-medium" />
<!-- This comment is only here to fix this issue https://github.com/datagouv/cdata/issues/653, it could be empty… -->
<p class="text-sm whitespace-nowrap mb-0">
{{ t('Mis à jour {date}', { date: formatRelativeIfRecentDate(dataservice.metadata_modified_at, { dateStyle: 'medium' }) }) }}
</p>
<RiSubtractLine class="size-4 flex-none fill-gray-medium" />
<div class="flex items-center gap-1">
<p
class="text-sm mb-0 flex items-center gap-0.5"
:aria-label="t('{n} vues | {n} vue | {n} vues', dataservice.metrics.views)"
>
<RiEyeLine
aria-hidden="true"
class="size-3.5"
/>{{ summarize(dataservice.metrics.views) }}
</p>
<p
class="text-sm mb-0 flex items-center gap-0.5"
:aria-label="t('{n} abonnés | {n} abonné | {n} abonnés', dataservice.metrics.followers)"
>
<RiStarLine
aria-hidden="true"
class="size-3.5"
/>{{ summarize(dataservice.metrics.followers) }}
</p>
</div>
</div>
<component
:is="config.textClamp"
v-if="config.textClamp && description && showDescription"
class="text-sm mt-2 mb-0"
:auto-resize="true"
:text="description"
:max-lines="2"
/>
</p>
<p
v-else
class="text-sm mb-0 truncate"
>
{{ ownerName }}
</p>
<RiSubtractLine class="size-4 flex-none fill-gray-medium" />
<!-- This comment is only here to fix this issue https://github.com/datagouv/cdata/issues/653, it could be empty… -->
<p class="text-sm whitespace-nowrap mb-0">
{{ t('Mis à jour {date}', { date: formatRelativeIfRecentDate(dataservice.metadata_modified_at, { dateStyle: 'medium' }) }) }}
</p>
<RiSubtractLine class="size-4 flex-none fill-gray-medium" />
<div class="flex items-center gap-1">
<p
class="text-sm mb-0 flex items-center gap-0.5"
:aria-label="t('{n} vues | {n} vue | {n} vues', dataservice.metrics.views)"
>
<RiEyeLine
aria-hidden="true"
class="size-3.5"
/>{{ summarize(dataservice.metrics.views) }}
</p>
<p
class="text-sm mb-0 flex items-center gap-0.5"
:aria-label="t('{n} abonnés | {n} abonné | {n} abonnés', dataservice.metrics.followers)"
<div
v-if="matchingBadges.length > 0"
class="flex flex-wrap gap-2 mt-2"
>
<RiStarLine
aria-hidden="true"
class="size-3.5"
/>{{ summarize(dataservice.metrics.followers) }}
</p>
<span
v-for="badge in matchingBadges"
:key="badge.value"
class="px-2 py-1 rounded text-white text-xs font-bold"
:style="{ backgroundColor: badge.color }"
>
{{ badge.name }}
</span>
</div>
</div>
</div>
<component
:is="config.textClamp"
v-if="config.textClamp && description && showDescription"
class="text-sm mt-2 mb-0"
:auto-resize="true"
:text="description"
:max-lines="2"
/>
</article>
</template>

Expand All @@ -139,6 +175,15 @@ import type { Dataservice } from '../types/dataservices'
import { useTranslation } from '../composables/useTranslation'
import OrganizationNameWithCertificate from './OrganizationNameWithCertificate.vue'
import AppLink from './AppLink.vue'
import OrganizationLogo from './OrganizationLogo.vue'
import Avatar from './Avatar.vue'
import Placeholder from './Placeholder.vue'

type TagIntoBadge = {
name: string
value: string
color: string
}

type Props = {
dataservice: Dataservice
Expand All @@ -155,6 +200,7 @@ type Props = {
*/
organizationUrl?: RouteLocationRaw
showDescription?: boolean
tagIntoBadge?: TagIntoBadge[]
}

const props = withDefaults(defineProps<Props>(), {
Expand All @@ -178,6 +224,12 @@ const description = ref('')
watchEffect(async () => {
description.value = await removeMarkdown(props.dataservice.description)
})

const matchingBadges = computed(() => {
if (!props.tagIntoBadge || !props.dataservice.tags) return []
const dataserviceTags = new Set(props.dataservice.tags)
return props.tagIntoBadge.filter(badge => dataserviceTags.has(badge.value))
})
</script>

<style scoped>
Expand Down
43 changes: 41 additions & 2 deletions datagouv-components/src/components/DatasetCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
</div>
<div class="flex flex-wrap md:flex-nowrap gap-4 items-start">
<div class="flex-none">
<div class="flex justify-center items-center p-2 border border-gray-lower bg-[#fff]">
<div class="flex justify-center items-center p-2 border border-gray-lower bg-[#fff] rounded-md overflow-hidden">
<OrganizationLogo
v-if="dataset.organization"
:organization="dataset.organization"
Expand All @@ -54,9 +54,22 @@
>
<AppLink
:to="datasetUrl"
class="text-gray-title text-base bg-none flex w-full truncate"
class="text-gray-title text-base bg-none flex items-center w-full truncate gap-1"
:target="datasetUrlInNewTab ? '_blank' : undefined"
>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="flex-none"
>
<path
d="M3.33333 8.33333C3.33333 8.542 3.64067 8.90533 4.35333 9.262C5.276 9.72333 6.58467 10 8 10C9.41533 10 10.724 9.72333 11.6467 9.262C12.3593 8.90533 12.6667 8.542 12.6667 8.33333V6.886C11.5667 7.566 9.88467 8 8 8C6.11533 8 4.43333 7.56533 3.33333 6.886V8.33333ZM12.6667 10.2193C11.5667 10.8993 9.88467 11.3333 8 11.3333C6.11533 11.3333 4.43333 10.8987 3.33333 10.2193V11.6667C3.33333 11.8753 3.64067 12.2387 4.35333 12.5953C5.276 13.0567 6.58467 13.3333 8 13.3333C9.41533 13.3333 10.724 13.0567 11.6467 12.5953C12.3593 12.2387 12.6667 11.8753 12.6667 11.6667V10.2193ZM2 11.6667V5C2 3.34333 4.68667 2 8 2C11.3133 2 14 3.34333 14 5V11.6667C14 13.3233 11.3133 14.6667 8 14.6667C4.68667 14.6667 2 13.3233 2 11.6667ZM8 6.66667C9.41533 6.66667 10.724 6.39 11.6467 5.92867C12.3593 5.572 12.6667 5.20867 12.6667 5C12.6667 4.79133 12.3593 4.428 11.6467 4.07133C10.724 3.61 9.41533 3.33333 8 3.33333C6.58467 3.33333 5.276 3.61 4.35333 4.07133C3.64067 4.428 3.33333 4.79133 3.33333 5C3.33333 5.20867 3.64067 5.572 4.35333 5.92867C5.276 6.39 6.58467 6.66667 8 6.66667Z"
fill="#3A3A3A"
/>
</svg>
<span
class="block truncate"
:class="dataset.acronym ? 'flex-initial' : 'flex-1'"
Expand Down Expand Up @@ -150,6 +163,19 @@
:text="descriptionShort"
:max-lines="2"
/>
<div
v-if="matchingBadges.length > 0"
class="flex flex-wrap gap-2 mt-2"
>
<span
v-for="badge in matchingBadges"
:key="badge.value"
class="px-2 py-1 rounded text-white text-xs font-bold"
:style="{ backgroundColor: badge.color }"
>
{{ badge.name }}
</span>
</div>
</div>
</div>
</div>
Expand All @@ -173,6 +199,12 @@ import OrganizationNameWithCertificate from './OrganizationNameWithCertificate.v
import AppLink from './AppLink.vue'
import OrganizationLogo from './OrganizationLogo.vue'

type TagIntoBadge = {
name: string
value: string
color: string
}

type Props = {
dataset: Dataset | DatasetV2

Expand All @@ -189,6 +221,7 @@ type Props = {
*/
organizationUrl?: RouteLocationRaw
showDescriptionShort?: boolean
tagIntoBadge?: TagIntoBadge[]
}

const props = withDefaults(defineProps<Props>(), {
Expand All @@ -206,4 +239,10 @@ watchEffect(async () => {
if (!props.showDescriptionShort) return
descriptionShort.value = await getDescriptionShort(props.dataset.description, props.dataset.description_short)
})

const matchingBadges = computed(() => {
if (!props.tagIntoBadge || !props.dataset.tags) return []
const datasetTags = new Set(props.dataset.tags)
return props.tagIntoBadge.filter(badge => datasetTags.has(badge.value))
})
</script>
Loading
Loading