@datagouv/components-next 1.0.2-dev.221 → 1.0.2-dev.222
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-BQzHk6je.js → Datafair.client-B1OKZr6h.js} +1 -1
- package/dist/{ImagePreview.client-Cld46eGd.js → ImagePreview.client-D04HNejY.js} +1 -1
- package/dist/{JsonPreview.client-BXURFXgZ.js → JsonPreview.client-B0_IvXry.js} +2 -2
- package/dist/{MapContainer.client-Dc4DB5l3.js → MapContainer.client-zzejMZGK.js} +2 -2
- package/dist/{PdfPreview.client-llrHD630.js → PdfPreview.client-yeS69omp.js} +2 -2
- package/dist/{Pmtiles.client-DFP8oK6A.js → Pmtiles.client-CxixL6Rw.js} +1 -1
- package/dist/{PreviewWrapper.vue_vue_type_script_setup_true_lang-5yjTI07B.js → PreviewWrapper.vue_vue_type_script_setup_true_lang-DunhHltO.js} +1 -1
- package/dist/{XmlPreview.client-C3OEOuUI.js → XmlPreview.client-Bi-Dtuq8.js} +3 -3
- package/dist/components-next.css +1 -1
- package/dist/components-next.js +73 -73
- package/dist/{index-5j8dwm1I.js → index-B7ZsPIob.js} +1 -1
- package/dist/{leaflet-src-CtezwTk4.js → leaflet-src-ClDGecfN.js} +1 -1
- package/dist/{main-HU94LBny.js → main-DAxkqaSe.js} +2945 -2955
- package/dist/{vue3-xml-viewer.common-C1QomD0e.js → vue3-xml-viewer.common-Dux7EzjM.js} +1 -1
- package/package.json +1 -1
- package/src/components/ResourceAccordion/EditButton.vue +4 -1
- package/src/components/ResourceAccordion/ResourceAccordion.vue +6 -1
- package/src/components/TabularExplorer/TabularCellPopover.vue +30 -4
- package/src/functions/resources.ts +4 -0
- package/src/functions/tabular.ts +0 -33
- package/src/types/resources.ts +6 -0
package/package.json
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
icon-only
|
|
5
5
|
:icon="RiPencilLine"
|
|
6
6
|
color="warning"
|
|
7
|
-
:
|
|
7
|
+
:disabled="!!disabledReason"
|
|
8
|
+
:title="disabledReason ?? t('Éditer le fichier')"
|
|
8
9
|
data-testid="edit-button"
|
|
9
10
|
/>
|
|
10
11
|
</template>
|
|
@@ -19,10 +20,12 @@ type Props = {
|
|
|
19
20
|
datasetId: string
|
|
20
21
|
isCommunityResource?: boolean
|
|
21
22
|
resourceId: string
|
|
23
|
+
disabledReason?: string | null
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const props = withDefaults(defineProps<Props>(), {
|
|
25
27
|
isCommunityResource: false,
|
|
28
|
+
disabledReason: null,
|
|
26
29
|
})
|
|
27
30
|
|
|
28
31
|
const { t } = useTranslation()
|
|
@@ -173,6 +173,7 @@
|
|
|
173
173
|
:dataset-id="dataset.id"
|
|
174
174
|
:resource-id="resource.id"
|
|
175
175
|
:is-community-resource="isCommunityResource"
|
|
176
|
+
:disabled-reason="editDisabledReason"
|
|
176
177
|
size="xs"
|
|
177
178
|
/>
|
|
178
179
|
</p>
|
|
@@ -327,7 +328,7 @@ import { trackEvent } from '../../functions/matomo'
|
|
|
327
328
|
import CopyButton from '../CopyButton.vue'
|
|
328
329
|
import { useComponentsConfig } from '../../config'
|
|
329
330
|
import { getOwnerName } from '../../functions/owned'
|
|
330
|
-
import { getResourceFormatIcon, getResourceTitleId, detectOgcService, getResourceFilesize, isImagePreviewFormat, resolveResourceExternalUrl } from '../../functions/resources'
|
|
331
|
+
import { getResourceFormatIcon, getResourceTitleId, detectOgcService, getResourceFilesize, isGeopfSynced, isImagePreviewFormat, resolveResourceExternalUrl } from '../../functions/resources'
|
|
331
332
|
import BrandedButton from '../BrandedButton.vue'
|
|
332
333
|
import { useTranslation } from '../../composables/useTranslation'
|
|
333
334
|
import { useHasTabularData } from '../../composables/useHasTabularData'
|
|
@@ -384,6 +385,10 @@ const hasPmtiles = computed(() => {
|
|
|
384
385
|
return props.resource.extras['analysis:parsing:pmtiles_url'] || props.resource.format === 'pmtiles'
|
|
385
386
|
})
|
|
386
387
|
|
|
388
|
+
const editDisabledReason = computed(() => {
|
|
389
|
+
return isGeopfSynced(props.resource) ? t('Vous ne pouvez pas modifier cette ressource car elle est synchronisée avec cartes.gouv.fr') : null
|
|
390
|
+
})
|
|
391
|
+
|
|
387
392
|
const hasDatafairPreview = computed(() => {
|
|
388
393
|
// Checks if there are the corresponding extras for a datafair preview.
|
|
389
394
|
// Limited only to datasets published by certified organizations since it will load an iframe.
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
} from '@remixicon/vue'
|
|
81
81
|
import { toast } from 'vue-sonner'
|
|
82
82
|
import { useTranslation } from '../../composables/useTranslation'
|
|
83
|
-
import {
|
|
83
|
+
import { buildTypeConfig, toIsoDay } from '../../functions/tabular'
|
|
84
84
|
import ClientOnly from '../ClientOnly.vue'
|
|
85
85
|
import type { ColumnType, ColumnFilters } from './types'
|
|
86
86
|
|
|
@@ -128,10 +128,36 @@ function close() {
|
|
|
128
128
|
|
|
129
129
|
function filterByValue() {
|
|
130
130
|
if (!cell.value) return
|
|
131
|
+
const val = String(cell.value.value ?? '')
|
|
131
132
|
const col = cell.value.column
|
|
132
|
-
filters.value
|
|
133
|
-
|
|
134
|
-
|
|
133
|
+
const existing = filters.value[col] ?? {}
|
|
134
|
+
// A date goes through the same `date` filter the column panel writes, so the
|
|
135
|
+
// calendar opens on the day that was clicked instead of on an empty month.
|
|
136
|
+
if (cell.value.columnType === 'date') {
|
|
137
|
+
const day = toIsoDay(cell.value.value)
|
|
138
|
+
if (day) {
|
|
139
|
+
filters.value = { ...filters.value, [col]: { ...existing, date: { operator: 'is', start: day } } }
|
|
140
|
+
}
|
|
141
|
+
// An empty cell has no day to select: filtering on the missing values is
|
|
142
|
+
// what "this value" means there, and the panel shows it as such.
|
|
143
|
+
else if (cell.value.value == null || cell.value.value === '') {
|
|
144
|
+
filters.value = { ...filters.value, [col]: { ...existing, null: 'only' } }
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (cell.value.columnType === 'categorical' || cell.value.columnType === 'text' || cell.value.columnType === 'year') {
|
|
148
|
+
const current = existing.in ?? []
|
|
149
|
+
if (!current.includes(val)) {
|
|
150
|
+
filters.value = { ...filters.value, [col]: { ...existing, in: [...current, val] } }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else if (cell.value.columnType === 'number') {
|
|
154
|
+
const num = Number(cell.value.value)
|
|
155
|
+
if (Number.isFinite(num)) {
|
|
156
|
+
filters.value = { ...filters.value, [col]: { ...existing, min: num, max: num } }
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else if (cell.value.columnType === 'boolean') {
|
|
160
|
+
filters.value = { ...filters.value, [col]: { ...existing, exact: val } }
|
|
135
161
|
}
|
|
136
162
|
close()
|
|
137
163
|
}
|
|
@@ -179,6 +179,10 @@ export function getResourceExternalUrl(dataset: Dataset | DatasetV2 | Omit<Datas
|
|
|
179
179
|
return `${dataset.page}${isCommunityResource(resource) ? '/community-resources' : ''}?resource_id=${resource.id}`
|
|
180
180
|
}
|
|
181
181
|
|
|
182
|
+
export function isGeopfSynced(resource: Resource | CommunityResource): boolean {
|
|
183
|
+
return resource.geopf?.push_status != null || typeof resource.geopf?.offering_id === 'string'
|
|
184
|
+
}
|
|
185
|
+
|
|
182
186
|
export function resolveResourceExternalUrl<R extends Resource | CommunityResource>(
|
|
183
187
|
dataset: Dataset | DatasetV2 | Omit<Dataset, 'resources' | 'community_resources'>,
|
|
184
188
|
resource: R,
|
package/src/functions/tabular.ts
CHANGED
|
@@ -93,39 +93,6 @@ export function buildDateFilterParams(column: string, filter: DateFilter): Recor
|
|
|
93
93
|
return params
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
/**
|
|
97
|
-
* The filter "filter by this value" sets on a column for the cell that was
|
|
98
|
-
* clicked, merged into the filters already set on that column.
|
|
99
|
-
*
|
|
100
|
-
* An empty cell holds no value to match on: whatever the column type, filtering
|
|
101
|
-
* on the missing values is what "this value" means there — and it is the filter
|
|
102
|
-
* the column panel offers for them.
|
|
103
|
-
*/
|
|
104
|
-
export function buildCellValueFilter(columnType: ColumnType, value: unknown, existing: ColumnFilters): ColumnFilters {
|
|
105
|
-
if (value == null || value === '') return { ...existing, null: 'only' }
|
|
106
|
-
switch (columnType) {
|
|
107
|
-
// A date goes through the same `date` filter the column panel writes, so the
|
|
108
|
-
// calendar opens on the day that was clicked instead of on an empty month.
|
|
109
|
-
case 'date': {
|
|
110
|
-
const day = toIsoDay(value)
|
|
111
|
-
return day ? { ...existing, date: { operator: 'is', start: day } } : existing
|
|
112
|
-
}
|
|
113
|
-
case 'number': {
|
|
114
|
-
const num = Number(value)
|
|
115
|
-
return Number.isFinite(num) ? { ...existing, min: num, max: num } : existing
|
|
116
|
-
}
|
|
117
|
-
case 'boolean':
|
|
118
|
-
return { ...existing, exact: String(value) }
|
|
119
|
-
case 'categorical':
|
|
120
|
-
case 'text':
|
|
121
|
-
case 'year': {
|
|
122
|
-
const val = String(value)
|
|
123
|
-
const selected = existing.in ?? []
|
|
124
|
-
return selected.includes(val) ? existing : { ...existing, in: [...selected, val] }
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
96
|
export type TypeDisplay = {
|
|
130
97
|
icon: Component
|
|
131
98
|
label: string
|
package/src/types/resources.ts
CHANGED
|
@@ -12,6 +12,11 @@ export type FileResourceFileType = 'file'
|
|
|
12
12
|
|
|
13
13
|
export type ResourceFileType = RemoteResourceFileType | FileResourceFileType
|
|
14
14
|
|
|
15
|
+
export type GeopfResourceMetadata = {
|
|
16
|
+
push_status?: 'pending' | 'done' | 'error' | 'timeout' | null
|
|
17
|
+
offering_id?: string | null
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export type Resource = {
|
|
16
21
|
id: string
|
|
17
22
|
title: string
|
|
@@ -22,6 +27,7 @@ export type Resource = {
|
|
|
22
27
|
extras: Record<string, unknown>
|
|
23
28
|
metrics: { views: number }
|
|
24
29
|
harvest: Harvest
|
|
30
|
+
geopf: GeopfResourceMetadata | null
|
|
25
31
|
filesize: number | null
|
|
26
32
|
filetype: ResourceFileType
|
|
27
33
|
format: string
|