@datagouv/components-next 0.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.
Files changed (119) hide show
  1. package/README.md +150 -0
  2. package/assets/main.css +136 -0
  3. package/assets/placeholders/author.png +0 -0
  4. package/assets/placeholders/dataset.png +0 -0
  5. package/assets/placeholders/news.png +0 -0
  6. package/assets/placeholders/organization.png +0 -0
  7. package/assets/placeholders/reuse.png +0 -0
  8. package/assets/tailwind.config.js +24 -0
  9. package/dist/components.css +2 -0
  10. package/dist/locales/de.js +155 -0
  11. package/dist/locales/en.js +155 -0
  12. package/dist/locales/es.js +155 -0
  13. package/dist/locales/fr.js +155 -0
  14. package/dist/locales/it.js +155 -0
  15. package/dist/locales/pt.js +155 -0
  16. package/dist/locales/sr.js +155 -0
  17. package/package.json +72 -0
  18. package/src/components/AppLink.vue +51 -0
  19. package/src/components/Avatar.vue +27 -0
  20. package/src/components/AvatarWithName.vue +26 -0
  21. package/src/components/BannerAction.vue +39 -0
  22. package/src/components/BrandedButton.vue +170 -0
  23. package/src/components/CopyButton.vue +84 -0
  24. package/src/components/DataserviceCard.vue +184 -0
  25. package/src/components/DatasetCard.vue +198 -0
  26. package/src/components/DatasetInformationPanel.vue +210 -0
  27. package/src/components/DatasetQuality.vue +68 -0
  28. package/src/components/DatasetQualityInline.vue +32 -0
  29. package/src/components/DatasetQualityItem.vue +32 -0
  30. package/src/components/DatasetQualityItemWarning.vue +21 -0
  31. package/src/components/DatasetQualityScore.vue +35 -0
  32. package/src/components/DatasetQualityTooltipContent.vue +79 -0
  33. package/src/components/DescriptionDetails.vue +23 -0
  34. package/src/components/DescriptionList/DescriptionDetails.stories.ts +43 -0
  35. package/src/components/DescriptionList/DescriptionList.stories.ts +47 -0
  36. package/src/components/DescriptionList/DescriptionTerm.stories.ts +28 -0
  37. package/src/components/DescriptionList.vue +8 -0
  38. package/src/components/DescriptionTerm.vue +8 -0
  39. package/src/components/ExtraAccordion.vue +78 -0
  40. package/src/components/Icons/Archive.vue +21 -0
  41. package/src/components/Icons/Code.vue +21 -0
  42. package/src/components/Icons/Documentation.vue +21 -0
  43. package/src/components/Icons/File.vue +21 -0
  44. package/src/components/Icons/Image.vue +7 -0
  45. package/src/components/Icons/Link.vue +21 -0
  46. package/src/components/Icons/Table.vue +21 -0
  47. package/src/components/OrganizationCard.vue +68 -0
  48. package/src/components/OrganizationNameWithCertificate.vue +45 -0
  49. package/src/components/OwnerType.vue +43 -0
  50. package/src/components/OwnerTypeIcon.vue +18 -0
  51. package/src/components/Pagination.vue +205 -0
  52. package/src/components/Placeholder.vue +29 -0
  53. package/src/components/ReadMore.vue +107 -0
  54. package/src/components/ResourceAccordion/DataStructure.vue +87 -0
  55. package/src/components/ResourceAccordion/EditButton.vue +34 -0
  56. package/src/components/ResourceAccordion/Metadata.vue +171 -0
  57. package/src/components/ResourceAccordion/Preview.vue +229 -0
  58. package/src/components/ResourceAccordion/PreviewLoader.vue +148 -0
  59. package/src/components/ResourceAccordion/ResourceAccordion.vue +484 -0
  60. package/src/components/ResourceAccordion/ResourceIcon.vue +16 -0
  61. package/src/components/ResourceAccordion/SchemaBadge.vue +148 -0
  62. package/src/components/ResourceAccordion/SchemaLoader.vue +30 -0
  63. package/src/components/ResourceAccordion/Swagger.vue +46 -0
  64. package/src/components/ResourceAccordion/france.svg +1 -0
  65. package/src/components/ReuseCard.vue +106 -0
  66. package/src/components/ReuseDetails.vue +45 -0
  67. package/src/components/SimpleBanner.vue +24 -0
  68. package/src/components/SmallChart.vue +149 -0
  69. package/src/components/StatBox.vue +100 -0
  70. package/src/components/Tabs/Tab.vue +62 -0
  71. package/src/components/Tabs/TabGroup.vue +20 -0
  72. package/src/components/Tabs/TabList.vue +15 -0
  73. package/src/components/Tabs/TabPanel.vue +7 -0
  74. package/src/components/Tabs/TabPanels.vue +7 -0
  75. package/src/components/Toggletip.vue +62 -0
  76. package/src/components/ToggletipButton.vue +14 -0
  77. package/src/composables/useActiveDescendant.ts +103 -0
  78. package/src/composables/useReuseType.ts +14 -0
  79. package/src/config.ts +33 -0
  80. package/src/functions/api.ts +96 -0
  81. package/src/functions/api.types.ts +41 -0
  82. package/src/functions/config.ts +12 -0
  83. package/src/functions/datasets.ts +24 -0
  84. package/src/functions/dates.ts +85 -0
  85. package/src/functions/helpers.ts +38 -0
  86. package/src/functions/markdown.ts +47 -0
  87. package/src/functions/matomo.ts +3 -0
  88. package/src/functions/organizations.ts +85 -0
  89. package/src/functions/owned.ts +11 -0
  90. package/src/functions/resources.ts +99 -0
  91. package/src/functions/reuses.ts +28 -0
  92. package/src/functions/schemas.ts +96 -0
  93. package/src/functions/tabularApi.ts +27 -0
  94. package/src/functions/users.ts +7 -0
  95. package/src/locales/de.json +154 -0
  96. package/src/locales/en.json +154 -0
  97. package/src/locales/es.json +154 -0
  98. package/src/locales/fr.json +154 -0
  99. package/src/locales/it.json +154 -0
  100. package/src/locales/pt.json +154 -0
  101. package/src/locales/sr.json +154 -0
  102. package/src/main.ts +147 -0
  103. package/src/types/badges.ts +5 -0
  104. package/src/types/contact_point.ts +7 -0
  105. package/src/types/dataservices.ts +68 -0
  106. package/src/types/datasets.ts +80 -0
  107. package/src/types/frequency.ts +6 -0
  108. package/src/types/granularity.ts +6 -0
  109. package/src/types/harvest.ts +3 -0
  110. package/src/types/keyboard.ts +1 -0
  111. package/src/types/licenses.ts +9 -0
  112. package/src/types/organizations.ts +41 -0
  113. package/src/types/owned.ts +9 -0
  114. package/src/types/resources.ts +37 -0
  115. package/src/types/reuses.ts +49 -0
  116. package/src/types/site.ts +23 -0
  117. package/src/types/topics.ts +20 -0
  118. package/src/types/ui.ts +3 -0
  119. package/src/types/users.ts +10 -0
@@ -0,0 +1,229 @@
1
+ <template>
2
+ <div>
3
+ <div
4
+ v-if="hasError"
5
+ class="bg-warning-lightest text-warning-dark p-3 mt-8 mx-8 mb-3"
6
+ >
7
+ <p class="fr-grid-row fr-m-0">
8
+ <span
9
+ class="fr-icon-warning-line"
10
+ aria-hidden="true"
11
+ />
12
+ {{ t("The preview of this file failed to load.") }}
13
+ </p>
14
+ </div>
15
+ <PreviewLoader v-else-if="loading" />
16
+ <template v-else>
17
+ <div class="bg-blue-100 text-datagouv fr-hidden fr-unhidden-md p-4">
18
+ <div class="fr-grid-row fr-grid-row--middle fr-grid-row--gutters">
19
+ <div
20
+ class="fr-col-auto"
21
+ v-html="franceSvg"
22
+ />
23
+ <div class="fr-col">
24
+ <p class="fr-text--bold fr-m-0">
25
+ {{ t("Explore data in detail") }}
26
+ </p>
27
+ <p class="fr-text--sm fr-m-0 f-italic">
28
+ {{ t("Use our tool to get an overview of data, learn about different columns or perform filters and sorts.") }}
29
+ </p>
30
+ </div>
31
+ <p class="fr-col-auto fr-my-0">
32
+ <BrandedButton
33
+ :href="resource.preview_url"
34
+ :icon="RiExternalLinkFill"
35
+ icon-right
36
+ >
37
+ {{ t("Explore data") }}
38
+ </BrandedButton>
39
+ </p>
40
+ </div>
41
+ </div>
42
+ <div class="fr-table fr-table--no-background fr-p-0 fr-pt-0-5v fr-m-0">
43
+ <table class="fr-mb-3w">
44
+ <caption class="fr-sr-only">
45
+ {{ t('Preview of {name}', { name: resource.title }) }}
46
+ </caption>
47
+ <thead>
48
+ <tr>
49
+ <th
50
+ v-for="(col, index) in columns"
51
+ :key="index"
52
+ scope="col"
53
+ >
54
+ <div class="fr-grid-row fr-grid-row--middle col-width">
55
+ <BrandedButton
56
+ color="secondary-softer"
57
+ :icon="isSortedBy(col) && sortConfig && sortConfig.type == 'asc' ? RiArrowUpLine : RiArrowDownLine"
58
+ icon-right
59
+ size="xs"
60
+ @click="sortByField(col)"
61
+ >
62
+ {{ col }}
63
+ <span class="sr-only">{{ sortConfig && sortConfig.type == 'desc' ? t("Sort ascending") : t("Sort descending") }}</span>
64
+ </BrandedButton>
65
+ </div>
66
+ </th>
67
+ </tr>
68
+ </thead>
69
+ <tbody>
70
+ <tr
71
+ v-for="(row, rowIndex) in rows"
72
+ :key="rowIndex"
73
+ >
74
+ <td
75
+ v-for="(col, colIndex) in columns"
76
+ :key="colIndex"
77
+ class="cell-padding"
78
+ >
79
+ <div class="fr-grid-row fr-grid-row--middle fr-text--xs w-100 style-cell">
80
+ <div class="fr-my-auto">
81
+ {{ row[col] }}
82
+ </div>
83
+ </div>
84
+ </td>
85
+ </tr>
86
+ </tbody>
87
+ </table>
88
+ </div>
89
+ <Pagination
90
+ class="fr-mt-3w"
91
+ :page="currentPage"
92
+ :page-size="pageSize"
93
+ :total-results="rowCount"
94
+ @change="changePage"
95
+ />
96
+ <div class="fr-px-5v">
97
+ {{ t("Preview updated on {date}", { date: lastUpdate }) }} —
98
+ {{ t('{count} columns', columns.length) }} —
99
+ {{ t('{count} rows', rowCount) }}
100
+ </div>
101
+ </template>
102
+ </div>
103
+ </template>
104
+
105
+ <script setup lang="ts">
106
+ import { computed, onMounted, ref } from 'vue'
107
+ import { useI18n } from 'vue-i18n'
108
+ import { RiArrowDownLine, RiArrowUpLine, RiExternalLinkFill } from '@remixicon/vue'
109
+ import Pagination from '../Pagination.vue'
110
+ import { getData, type SortConfig } from '../../functions/tabularApi'
111
+ import { formatDate } from '../../functions/dates'
112
+ import type { Resource } from '../../types/resources'
113
+ import { useComponentsConfig } from '../../config'
114
+ import BrandedButton from '../BrandedButton.vue'
115
+ import franceSvg from './france.svg?raw'
116
+ import PreviewLoader from './PreviewLoader.vue'
117
+
118
+ const props = defineProps<{ resource: Resource }>()
119
+
120
+ const { t } = useI18n()
121
+
122
+ const rows = ref<Array<Record<string, unknown>>>([])
123
+ const columns = ref<Array<string>>([])
124
+ const loading = ref(true)
125
+ const hasError = ref(false)
126
+ const sortConfig = ref<SortConfig>(null)
127
+ const rowCount = ref(0)
128
+ const config = useComponentsConfig()
129
+ const pageSize = computed(() => config.tabularApiPageSize || 20)
130
+ const currentPage = ref(1)
131
+
132
+ /**
133
+ * Check if the preview is sorted by the provided column
134
+ */
135
+ function isSortedBy(col: string) {
136
+ return col === sortConfig.value?.column
137
+ }
138
+
139
+ /**
140
+ * Retrieve preview necessary infos
141
+ */
142
+ async function getTableInfos(page: number, sortConfig?: SortConfig) {
143
+ try {
144
+ // Check that this function return wanted data
145
+ const { data } = await getData(config, props.resource.id, page, sortConfig)
146
+ if ('data' in data && data.data && data.data.length > 0) {
147
+ // Update existing rows
148
+ rows.value = data.data
149
+ columns.value = Object.keys(data.data[0]).filter(item => item !== '__id')
150
+ rowCount.value = data.meta.total
151
+ currentPage.value = page
152
+ loading.value = false
153
+ }
154
+ else {
155
+ hasError.value = true
156
+ loading.value = false
157
+ }
158
+ }
159
+ catch {
160
+ hasError.value = true
161
+ loading.value = false
162
+ }
163
+ };
164
+
165
+ /**
166
+ * Change page
167
+ */
168
+ function changePage(page: number) {
169
+ getTableInfos(page, sortConfig.value)
170
+ }
171
+
172
+ /**
173
+ * Sort by a specific column
174
+ */
175
+ function sortByField(col: string) {
176
+ if (sortConfig.value && sortConfig.value.column == col) {
177
+ if (sortConfig.value.type == 'asc') {
178
+ sortConfig.value.type = 'desc'
179
+ }
180
+ else {
181
+ sortConfig.value.type = 'asc'
182
+ }
183
+ }
184
+ else {
185
+ if (!sortConfig.value) {
186
+ sortConfig.value = {
187
+ column: col,
188
+ type: 'asc',
189
+ }
190
+ }
191
+ else {
192
+ sortConfig.value.column = col
193
+ sortConfig.value.type = 'asc'
194
+ }
195
+ }
196
+ currentPage.value = 1
197
+ getTableInfos(currentPage.value, sortConfig.value)
198
+ };
199
+
200
+ const lastUpdate = formatDate(props.resource.extras['analysis:parsing:finished_at'])
201
+
202
+ onMounted(() => {
203
+ getTableInfos(currentPage.value)
204
+ })
205
+ </script>
206
+
207
+ <style scoped>
208
+ .style-cell {
209
+ height: 3rem;
210
+ overflow-y: auto;
211
+ }
212
+
213
+ .col-width {
214
+ width: 20rem;
215
+ }
216
+
217
+ .cell-padding {
218
+ padding: 0.5rem 0rem 0.5rem 1.2rem!important;
219
+ }
220
+
221
+ td {
222
+ border-right: 1px solid #CECECE;
223
+ border-bottom: 1px solid #CECECE;
224
+ }
225
+
226
+ th {
227
+ border-right: 1px solid #CECECE;
228
+ }
229
+ </style>
@@ -0,0 +1,148 @@
1
+ <template>
2
+ <ContentLoader
3
+ :width="1124"
4
+ :height="300"
5
+ :speed="2"
6
+ primary-color="#f3f3f3"
7
+ secondary-color="#ecebeb"
8
+ >
9
+ <rect
10
+ x="16"
11
+ y="16"
12
+ rx="4"
13
+ ry="4"
14
+ width="112"
15
+ height="24"
16
+ />
17
+ <rect
18
+ x="160"
19
+ y="16"
20
+ rx="4"
21
+ ry="4"
22
+ width="116"
23
+ height="24"
24
+ />
25
+ <rect
26
+ x="308"
27
+ y="16"
28
+ rx="4"
29
+ ry="4"
30
+ width="140"
31
+ height="24"
32
+ />
33
+ <rect
34
+ x="480"
35
+ y="16"
36
+ rx="4"
37
+ ry="4"
38
+ width="106"
39
+ height="24"
40
+ />
41
+ <rect
42
+ x="618"
43
+ y="16"
44
+ rx="4"
45
+ ry="4"
46
+ width="140"
47
+ height="24"
48
+ />
49
+ <rect
50
+ x="790"
51
+ y="16"
52
+ rx="4"
53
+ ry="4"
54
+ width="144"
55
+ height="24"
56
+ />
57
+ <rect
58
+ x="966"
59
+ y="16"
60
+ rx="4"
61
+ ry="4"
62
+ width="142"
63
+ height="24"
64
+ />
65
+ <rect
66
+ x="4"
67
+ y="56"
68
+ rx="4"
69
+ ry="4"
70
+ width="1116"
71
+ height="4"
72
+ />
73
+
74
+ <template
75
+ v-for="n in 5"
76
+ :key="n"
77
+ >
78
+ <rect
79
+ x="16"
80
+ :y="getY(n)"
81
+ rx="4"
82
+ ry="4"
83
+ width="112"
84
+ height="32"
85
+ />
86
+ <rect
87
+ x="160"
88
+ :y="getY(n)"
89
+ rx="4"
90
+ ry="4"
91
+ width="116"
92
+ height="32"
93
+ />
94
+ <rect
95
+ x="308"
96
+ :y="getY(n)"
97
+ rx="4"
98
+ ry="4"
99
+ width="140"
100
+ height="32"
101
+ />
102
+ <rect
103
+ x="480"
104
+ :y="getY(n)"
105
+ rx="4"
106
+ ry="4"
107
+ width="106"
108
+ height="32"
109
+ />
110
+ <rect
111
+ x="618"
112
+ :y="getY(n)"
113
+ rx="4"
114
+ ry="4"
115
+ width="140"
116
+ height="32"
117
+ />
118
+ <rect
119
+ x="790"
120
+ :y="getY(n)"
121
+ rx="4"
122
+ ry="4"
123
+ width="144"
124
+ height="32"
125
+ />
126
+ <rect
127
+ x="966"
128
+ :y="getY(n)"
129
+ rx="4"
130
+ ry="4"
131
+ width="142"
132
+ height="32"
133
+ />
134
+ </template>
135
+ </ContentLoader>
136
+ </template>
137
+
138
+ <script setup lang="ts">
139
+ import { ContentLoader } from 'vue-content-loader'
140
+
141
+ function getY(row: number) {
142
+ const topMargin = 16
143
+ const borderHeight = 4
144
+ const cellHeight = 32
145
+ const gapHeight = 24
146
+ return topMargin + borderHeight + row * (cellHeight + gapHeight)
147
+ }
148
+ </script>