@paris-ias/list 1.0.178 → 1.0.180
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/module.json +1 -1
- package/dist/runtime/components/events/DenseItem.vue +1 -0
- package/dist/runtime/components/events/View.vue +0 -1
- package/dist/runtime/components/fellowships/DenseItem.vue +1 -0
- package/dist/runtime/components/list/molecules/Header.vue +2 -2
- package/dist/runtime/components/list/organisms/List.vue +21 -9
- package/dist/runtime/components/list/organisms/Results.vue +57 -1
- package/dist/runtime/components/misc/atoms/ImageContainer.vue +12 -12
- package/dist/runtime/components/news/DenseItem.vue +5 -2
- package/dist/runtime/components/people/DenseItem.vue +3 -2
- package/dist/runtime/components/projects/DenseItem.vue +2 -1
- package/dist/runtime/components/publications/DenseItem.vue +2 -1
- package/dist/runtime/stores/root.js +0 -13
- package/package.json +2 -2
package/dist/module.json
CHANGED
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
import { useI18n, useNuxtApp, computed } from "#imports"
|
|
92
92
|
import { useDisplay } from "vuetify"
|
|
93
93
|
import { useRootStore } from "../../stores/root"
|
|
94
|
+
import { highlightAndTruncate } from "../../composables/useUtils"
|
|
94
95
|
const { $rootStore } = useNuxtApp()
|
|
95
96
|
const { smAndDown, mdAndUp } = useDisplay()
|
|
96
97
|
|
|
@@ -42,10 +42,10 @@ const props = defineProps({
|
|
|
42
42
|
},
|
|
43
43
|
})
|
|
44
44
|
const visible = computed(() => {
|
|
45
|
-
console.log(
|
|
45
|
+
/* console.log(
|
|
46
46
|
"SHOULD DISPLAY FILTERS:",
|
|
47
47
|
$stores[props.type]?.filtersCount && $stores[props.type]?.filtersCount > 0,
|
|
48
|
-
)
|
|
48
|
+
) */
|
|
49
49
|
return !!(
|
|
50
50
|
$stores[props.type]?.filtersCount && $stores[props.type]?.filtersCount > 0
|
|
51
51
|
)
|
|
@@ -105,7 +105,7 @@ const props = defineProps({
|
|
|
105
105
|
})
|
|
106
106
|
|
|
107
107
|
// Initialize loading state
|
|
108
|
-
console.log("start llocal loading from setup")
|
|
108
|
+
/* console.log("start llocal loading from setup") */
|
|
109
109
|
rootStore.setLoading(true, props.type)
|
|
110
110
|
|
|
111
111
|
// Initial route -> store (single source-of-truth on first load)
|
|
@@ -132,8 +132,8 @@ const itemTemplate = computed(() =>
|
|
|
132
132
|
).toString(),
|
|
133
133
|
),
|
|
134
134
|
)
|
|
135
|
-
console.log("Starting query for type: ", props.type)
|
|
136
|
-
console.log("Using variables: ", variables.value)
|
|
135
|
+
/* console.log("Starting query for type: ", props.type)
|
|
136
|
+
console.log("Using variables: ", variables.value) */
|
|
137
137
|
|
|
138
138
|
// Apollo GraphQL query with proper reactivity
|
|
139
139
|
const { data, pending, error, refresh } = await useAsyncQuery(
|
|
@@ -147,25 +147,37 @@ const { data, pending, error, refresh } = await useAsyncQuery(
|
|
|
147
147
|
if (error.value) {
|
|
148
148
|
console.error("GraphQL query error: ", error.value)
|
|
149
149
|
} else {
|
|
150
|
-
console.log("Query result data: ", data.value)
|
|
150
|
+
/* console.log("Query result data: ", data.value) */
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
// Apply data to store immediately if available
|
|
154
154
|
if (data.value) {
|
|
155
|
-
console.log("Applying data to store directly [first load scenario]")
|
|
155
|
+
/* console.log("Applying data to store directly [first load scenario]") */
|
|
156
156
|
rootStore.applyListResult(props.type, data.value)
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
// Watch for route query changes to update filters
|
|
160
|
+
watch(
|
|
161
|
+
() => route.query,
|
|
162
|
+
(newQuery, oldQuery) => {
|
|
163
|
+
if (JSON.stringify(newQuery) !== JSON.stringify(oldQuery)) {
|
|
164
|
+
/* console.log("Route query changed, reloading filters from URL") */
|
|
165
|
+
rootStore.loadRouteQuery(props.type)
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
{ deep: true },
|
|
169
|
+
)
|
|
170
|
+
|
|
159
171
|
// Watch for variable changes to refresh and apply new data
|
|
160
172
|
watch(
|
|
161
173
|
variables,
|
|
162
174
|
async (newVars, oldVars) => {
|
|
163
175
|
if (newVars && JSON.stringify(newVars) !== JSON.stringify(oldVars)) {
|
|
164
|
-
console.log("Variables changed, refreshing query, newVars: ", newVars)
|
|
176
|
+
/* console.log("Variables changed, refreshing query, newVars: ", newVars) */
|
|
165
177
|
rootStore.setLoading(true, props.type)
|
|
166
178
|
await refresh()
|
|
167
179
|
if (data.value) {
|
|
168
|
-
console.log("Applying refreshed data to store")
|
|
180
|
+
/* console.log("Applying refreshed data to store") */
|
|
169
181
|
rootStore.applyListResult(props.type, data.value)
|
|
170
182
|
}
|
|
171
183
|
rootStore.setLoading(false, props.type)
|
|
@@ -179,7 +191,7 @@ const items = computed(() => $stores[props.type]?.items || [])
|
|
|
179
191
|
|
|
180
192
|
onMounted(() => {
|
|
181
193
|
// On initial mount: clear loading state
|
|
182
|
-
console.log("STOP local loading from mounted")
|
|
194
|
+
/* console.log("STOP local loading from mounted") */
|
|
183
195
|
rootStore.setLoading(false, props.type)
|
|
184
196
|
})
|
|
185
197
|
|
|
@@ -187,7 +199,7 @@ onBeforeUnmount(() => {
|
|
|
187
199
|
rootStore.resetState(props.type, locale.value)
|
|
188
200
|
})
|
|
189
201
|
async function onPageChange(newPage) {
|
|
190
|
-
console.log("onPageChange: ", newPage)
|
|
202
|
+
/* console.log("onPageChange: ", newPage) */
|
|
191
203
|
|
|
192
204
|
// Set loading state first
|
|
193
205
|
rootStore.setLoading(true, props.type)
|
|
@@ -84,7 +84,7 @@ const { data, pending, error, refresh } = await useAsyncQuery(
|
|
|
84
84
|
if (error.value) {
|
|
85
85
|
console.error("GraphQL query error: ", error.value)
|
|
86
86
|
} else {
|
|
87
|
-
console.log("Query result data: ", data.value.items?.length)
|
|
87
|
+
/* console.log("Query result data: ", data.value.items?.length) */
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
// Apply data to store immediately if available
|
|
@@ -118,6 +118,62 @@ const updateSearch = async (newSearch) => {
|
|
|
118
118
|
onBeforeUnmount(() => {
|
|
119
119
|
/* rootStore.resetState("all", locale.value) */
|
|
120
120
|
})
|
|
121
|
+
|
|
122
|
+
const socioscope = {
|
|
123
|
+
appId: ["iea"],
|
|
124
|
+
url: "https://thesocioscope.org",
|
|
125
|
+
subtitle: {
|
|
126
|
+
en: "Seeing How Social Change Takes Shape",
|
|
127
|
+
fr: "Voir comment le changement social prend forme",
|
|
128
|
+
},
|
|
129
|
+
date: {
|
|
130
|
+
$date: "2023-03-18T00:00:00.000Z",
|
|
131
|
+
},
|
|
132
|
+
image: {
|
|
133
|
+
url: "https://cdn-yggdrasil-dev.s3.eu-west-2.amazonaws.com/iea/project/the_socioscope.svg",
|
|
134
|
+
},
|
|
135
|
+
summary: {
|
|
136
|
+
en: "Through large scale data collection around the world and LLM-driven research, the Socioscope analyses how behaviours, norms, and practices evolve within sustainable food transitions.\nWe're building a systemic way to help make complex social patterns measurable, comparable, and understandable.",
|
|
137
|
+
fr: "Grâce à la collecte de données à grande échelle dans le monde entier et à la recherche pilotée par LLM, le Socioscope analyse comment les comportements, normes et pratiques évoluent dans les transitions alimentaires durables.\nNous construisons une méthode systématique pour rendre les schémas sociaux complexes mesurables, comparables et compréhensibles.",
|
|
138
|
+
},
|
|
139
|
+
description: {
|
|
140
|
+
en: "The Socioscope is a transformative qualitative research project that maps how behaviours, norms, and communities influence the transition toward sustainable food systems.\nThe Socioscope serves as a comprehensive observatory of these efforts, making knowledge accessible to researchers, policymakers, and practitioners worldwide. Equally important is shining a light on local initiatives that lead change on the ground and drive the shift toward a more sustainable food system.",
|
|
141
|
+
fr: "Le Socioscope est un projet de recherche qualitative transformatif qui cartographie comment les comportements, normes et communautés influencent la transition vers des systèmes alimentaires durables.\nLe Socioscope sert d'observatoire complet de ces efforts, rendant les connaissances accessibles aux chercheurs, décideurs politiques et praticiens du monde entier. Tout aussi important, il met en lumière les initiatives locales qui mènent le changement sur le terrain et conduisent la transition vers un système alimentaire plus durable.",
|
|
142
|
+
},
|
|
143
|
+
name: {
|
|
144
|
+
en: "The Socioscope",
|
|
145
|
+
fr: "Le Socioscope",
|
|
146
|
+
},
|
|
147
|
+
related: {
|
|
148
|
+
people: [
|
|
149
|
+
{
|
|
150
|
+
firstname: "Antoine",
|
|
151
|
+
lastname: "Cordelois",
|
|
152
|
+
image: {
|
|
153
|
+
url: "https://cdn-yggdrasil-dev.s3.eu-west-2.amazonaws.com/iea/people/antoine_cordelois.jpg",
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
firstname: "Saadi",
|
|
158
|
+
lastname: "Lahlou",
|
|
159
|
+
image: {
|
|
160
|
+
url: "https://cdn-yggdrasil-dev.s3.eu-west-2.amazonaws.com/iea/people/lahlou_saadi.jpg",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
firstname: "Paulius",
|
|
165
|
+
lastname: "Yamin",
|
|
166
|
+
image: {
|
|
167
|
+
url: "https://cdn-yggdrasil-dev.s3.eu-west-2.amazonaws.com/iea/people/Paulius_Yamin.jpg",
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
slug: {
|
|
173
|
+
fr: "le-socioscope",
|
|
174
|
+
en: "the-socioscope",
|
|
175
|
+
},
|
|
176
|
+
}
|
|
121
177
|
</script>
|
|
122
178
|
<style scoped>
|
|
123
179
|
.results-container{display:flex;flex-direction:column;gap:8px;margin-left:8px}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<div class="overflow-hidden mw-100">
|
|
12
12
|
<!-- TODO debug why the picture is not displaying/sizing properly -->
|
|
13
13
|
<v-img
|
|
14
|
-
v-if="src"
|
|
14
|
+
v-if="src && computedSrc"
|
|
15
15
|
:aspect-ratio="ratio"
|
|
16
16
|
:class="{ 'img-animation': animate }"
|
|
17
17
|
:lazy-src="
|
|
@@ -43,7 +43,8 @@ import { computed, useImage } from "#imports"
|
|
|
43
43
|
const img = useImage()
|
|
44
44
|
|
|
45
45
|
const computedSrc = computed(() => {
|
|
46
|
-
|
|
46
|
+
if (!props.src) return null
|
|
47
|
+
return typeof props.src === "string" ? props.src : props.src?.url || null
|
|
47
48
|
})
|
|
48
49
|
const props = defineProps({
|
|
49
50
|
src: {
|
|
@@ -68,17 +69,16 @@ const props = defineProps({
|
|
|
68
69
|
animate: { type: Boolean, default: true },
|
|
69
70
|
})
|
|
70
71
|
const _srcset = computed(() => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
},
|
|
72
|
+
const srcUrl = typeof props.src === "string" ? props.src : props.src?.url
|
|
73
|
+
if (!srcUrl) return { srcset: "", sizes: "" }
|
|
74
|
+
return img.getSizes(srcUrl, {
|
|
75
|
+
sizes: "xs:100vw sm:100vw md:100vw lg:100vw xl:100vw",
|
|
76
|
+
modifiers: {
|
|
77
|
+
format: "webp",
|
|
78
|
+
quality: 70,
|
|
79
|
+
...(props.width && { width: props.width }),
|
|
80
80
|
},
|
|
81
|
-
)
|
|
81
|
+
})
|
|
82
82
|
})
|
|
83
83
|
</script>
|
|
84
84
|
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
</template>
|
|
37
37
|
<div
|
|
38
38
|
v-html="
|
|
39
|
-
|
|
39
|
+
rootStore.search.length
|
|
40
40
|
? highlightAndTruncate(
|
|
41
41
|
300,
|
|
42
42
|
item.name,
|
|
43
|
-
|
|
43
|
+
rootStore.search.split(' '),
|
|
44
44
|
)
|
|
45
45
|
: item.name
|
|
46
46
|
"
|
|
@@ -52,9 +52,12 @@
|
|
|
52
52
|
|
|
53
53
|
<script setup>
|
|
54
54
|
import { useDisplay } from "vuetify"
|
|
55
|
+
import { useRootStore } from "../../stores/root"
|
|
56
|
+
import { highlightAndTruncate } from "../../composables/useUtils"
|
|
55
57
|
import { computed } from "#imports"
|
|
56
58
|
|
|
57
59
|
const { name, mdAndUp } = useDisplay()
|
|
60
|
+
const rootStore = useRootStore()
|
|
58
61
|
|
|
59
62
|
const props = defineProps({
|
|
60
63
|
item: {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
? highlightAndTruncate(
|
|
21
21
|
300,
|
|
22
22
|
item.firstname + ' ' + item.lastname,
|
|
23
|
-
|
|
23
|
+
rootStore.search.split(' '),
|
|
24
24
|
)
|
|
25
25
|
: item.firstname + ' ' + item.lastname
|
|
26
26
|
"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
? highlightAndTruncate(
|
|
37
37
|
300,
|
|
38
38
|
item.groups.vintage[0].theme,
|
|
39
|
-
|
|
39
|
+
rootStore.search.split(' '),
|
|
40
40
|
)
|
|
41
41
|
: item.groups.vintage[0].theme
|
|
42
42
|
"
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
|
|
48
48
|
<script setup>
|
|
49
49
|
import { useRootStore } from "../../stores/root"
|
|
50
|
+
import { highlightAndTruncate } from "../../composables/useUtils"
|
|
50
51
|
import { computed } from "#imports"
|
|
51
52
|
import { useDisplay } from "vuetify"
|
|
52
53
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
v-else
|
|
18
18
|
v-html="
|
|
19
19
|
rootStore.search.length
|
|
20
|
-
? highlightAndTruncate(300, item.name,
|
|
20
|
+
? highlightAndTruncate(300, item.name, rootStore.search.split(' '))
|
|
21
21
|
: item.name
|
|
22
22
|
"
|
|
23
23
|
/>
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
<script setup>
|
|
47
47
|
import { useDisplay } from "vuetify"
|
|
48
48
|
import { useRootStore } from "../../stores/root"
|
|
49
|
+
import { highlightAndTruncate } from "../../composables/useUtils"
|
|
49
50
|
|
|
50
51
|
const { mdAndUp } = useDisplay()
|
|
51
52
|
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
? highlightAndTruncate(
|
|
49
49
|
300,
|
|
50
50
|
item.name,
|
|
51
|
-
|
|
51
|
+
rootStore.search.split(' '),
|
|
52
52
|
)
|
|
53
53
|
: item.name
|
|
54
54
|
"
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
<script setup>
|
|
72
72
|
import { useDisplay } from "vuetify"
|
|
73
73
|
import { useRootStore } from "../../stores/root"
|
|
74
|
+
import { highlightAndTruncate } from "../../composables/useUtils"
|
|
74
75
|
import { computed } from "#imports"
|
|
75
76
|
const rootStore = useRootStore()
|
|
76
77
|
|
|
@@ -26,7 +26,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
26
26
|
}),
|
|
27
27
|
actions: {
|
|
28
28
|
setLoading(value, type = "") {
|
|
29
|
-
console.log("X - setLoading", { value, type });
|
|
30
29
|
const { $stores } = useNuxtApp();
|
|
31
30
|
if (type.length && $stores[type]) {
|
|
32
31
|
$stores[type].loading = value;
|
|
@@ -40,7 +39,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
40
39
|
}
|
|
41
40
|
},
|
|
42
41
|
loadRouteQuery(type) {
|
|
43
|
-
console.log("0 - loadRouteQuery", type);
|
|
44
42
|
const { currentRoute } = useRouter();
|
|
45
43
|
const { $stores } = useNuxtApp();
|
|
46
44
|
const query = currentRoute.value.query;
|
|
@@ -60,7 +58,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
60
58
|
$stores[type].page = parseInt(query.page, 10) || 1;
|
|
61
59
|
},
|
|
62
60
|
setFiltersCount(type) {
|
|
63
|
-
console.log("6- setFiltersCount", type);
|
|
64
61
|
const { $stores } = useNuxtApp();
|
|
65
62
|
const filters = $stores[type]?.filters ?? {};
|
|
66
63
|
const count = Object.values(filters).reduce((acc, filter) => {
|
|
@@ -71,7 +68,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
71
68
|
$stores[type].filtersCount = count;
|
|
72
69
|
},
|
|
73
70
|
updateRouteQuery(type) {
|
|
74
|
-
console.log("5- updateRouteQuery", type);
|
|
75
71
|
const router = useRouter();
|
|
76
72
|
const { $stores } = useNuxtApp();
|
|
77
73
|
const routeQuery = {
|
|
@@ -93,7 +89,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
93
89
|
router.replace({ query: routeQuery });
|
|
94
90
|
},
|
|
95
91
|
resetState(type, lang = "en") {
|
|
96
|
-
console.log("Y - resetState", { type, lang });
|
|
97
92
|
const { $stores, $models } = useNuxtApp();
|
|
98
93
|
const model = structuredClone($models[type]);
|
|
99
94
|
$stores[type].filters = model?.filters;
|
|
@@ -102,10 +97,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
102
97
|
$stores[type].sortKey = null;
|
|
103
98
|
},
|
|
104
99
|
updateSort({ type, sortKey }) {
|
|
105
|
-
console.log("Z - updateSort", {
|
|
106
|
-
type,
|
|
107
|
-
sortKey
|
|
108
|
-
});
|
|
109
100
|
const { $stores } = useNuxtApp();
|
|
110
101
|
$stores[type].page = 1;
|
|
111
102
|
$stores[type].sortKey = sortKey;
|
|
@@ -116,7 +107,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
116
107
|
type,
|
|
117
108
|
lang
|
|
118
109
|
}) {
|
|
119
|
-
console.log("W - updateView", { value, type });
|
|
120
110
|
const { $stores } = useNuxtApp();
|
|
121
111
|
if ($stores[type]?.views?.[value]) {
|
|
122
112
|
$stores[type].view = {
|
|
@@ -132,7 +122,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
132
122
|
}, */
|
|
133
123
|
updateFilter(key, val, type, lang) {
|
|
134
124
|
const { $stores } = useNuxtApp();
|
|
135
|
-
console.log("R - update filter: ", { key, val, type });
|
|
136
125
|
if ($stores[type]?.filters?.[key]) {
|
|
137
126
|
$stores[type].filters[key].value = val;
|
|
138
127
|
}
|
|
@@ -146,7 +135,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
146
135
|
type,
|
|
147
136
|
lang
|
|
148
137
|
}) {
|
|
149
|
-
console.log("H - updateItemsPerPage", { value, type });
|
|
150
138
|
const { $stores } = useNuxtApp();
|
|
151
139
|
this.page = 1;
|
|
152
140
|
$stores[type].itemsPerPage = value;
|
|
@@ -158,7 +146,6 @@ export const useRootStore = defineStore("rootStore", {
|
|
|
158
146
|
type,
|
|
159
147
|
lang = "en"
|
|
160
148
|
}) {
|
|
161
|
-
console.log("update page: ", page);
|
|
162
149
|
const router = useRouter();
|
|
163
150
|
const currentQuery = router.currentRoute.value.query;
|
|
164
151
|
const newQuery = { ...currentQuery };
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"license": "AGPL-3.0-only",
|
|
3
3
|
"main": "./dist/module.mjs",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.180",
|
|
5
5
|
"name": "@paris-ias/list",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "git+https://github.com/IEA-Paris/list.git",
|
|
8
8
|
"type": "git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@paris-ias/trees": "^2.0.
|
|
11
|
+
"@paris-ias/trees": "^2.0.47"
|
|
12
12
|
},
|
|
13
13
|
"description": "Paris IAS List Module",
|
|
14
14
|
"peerDependencies": {
|