@paris-ias/list 1.0.108 → 1.0.111
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/list/atoms/PerPage.vue +39 -0
- package/dist/runtime/components/list/atoms/SearchInput.vue +32 -95
- package/dist/runtime/components/list/molecules/GlobalSearchInput.vue +27 -4
- package/dist/runtime/components/list/molecules/Header.vue +1 -0
- package/dist/runtime/components/list/molecules/ResultsContainer.vue +8 -1
- package/dist/runtime/components/list/organisms/List.vue +2 -0
- package/dist/runtime/components/list/organisms/Results.vue +13 -8
- package/dist/runtime/components/people/DenseItem.vue +3 -3
- package/dist/runtime/components/people/View.vue +8 -1
- package/dist/runtime/translations/en.json +3 -2
- package/dist/runtime/translations/fr.json +4 -3
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-select
|
|
3
|
+
v-model="itemsPerPage"
|
|
4
|
+
class="perPageSelect"
|
|
5
|
+
density="compact"
|
|
6
|
+
variant="outlined"
|
|
7
|
+
:items="itemsPerPageArray"
|
|
8
|
+
hide-details
|
|
9
|
+
:loading="$rootStore.loading"
|
|
10
|
+
@update:model-value="
|
|
11
|
+
$rootStore.updateItemsPerPage({
|
|
12
|
+
value: $event,
|
|
13
|
+
type: type,
|
|
14
|
+
lang: locale,
|
|
15
|
+
})
|
|
16
|
+
"
|
|
17
|
+
/>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
import { useNuxtApp, useI18n } from "#imports";
|
|
22
|
+
import { useDisplay } from "vuetify";
|
|
23
|
+
import { computed, ref } from "vue";
|
|
24
|
+
const { smAndDown } = useDisplay();
|
|
25
|
+
const { $stores, $rootStore } = useNuxtApp();
|
|
26
|
+
const { locale } = useI18n();
|
|
27
|
+
const props = defineProps({
|
|
28
|
+
type: {
|
|
29
|
+
type: String,
|
|
30
|
+
required: false,
|
|
31
|
+
default: ""
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
const itemsPerPage = ref($stores[props.type].itemsPerPage);
|
|
35
|
+
const itemsPerPageArray = computed(
|
|
36
|
+
() => $stores[props.type].view.perPage.options
|
|
37
|
+
);
|
|
38
|
+
const scrolled = computed(() => $stores.scrolled);
|
|
39
|
+
</script>
|
|
@@ -1,84 +1,44 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="d-flex flex-grow-1 flex-column">
|
|
3
|
-
<
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
v-model="filterMenuOpen"
|
|
32
|
-
:close-on-content-click="false"
|
|
33
|
-
location="bottom end"
|
|
34
|
-
offset="4"
|
|
35
|
-
>
|
|
36
|
-
<template #activator="{ props: menuProps }">
|
|
37
|
-
<v-btn
|
|
38
|
-
v-bind="menuProps"
|
|
39
|
-
:rounded="0"
|
|
40
|
-
variant="outlined"
|
|
41
|
-
size="large"
|
|
42
|
-
height="56"
|
|
43
|
-
>
|
|
44
|
-
<v-icon>mdi-filter</v-icon>
|
|
45
|
-
<v-icon class="ml-1" size="small">
|
|
46
|
-
{{ filterMenuOpen ? "mdi-chevron-up" : "mdi-chevron-down" }}
|
|
47
|
-
</v-icon>
|
|
48
|
-
</v-btn>
|
|
49
|
-
</template>
|
|
50
|
-
|
|
51
|
-
<v-card min-width="200">
|
|
52
|
-
<v-list>
|
|
53
|
-
<v-list-item
|
|
54
|
-
v-for="option in filterOptions"
|
|
55
|
-
:key="option.value"
|
|
56
|
-
@click="toggleFilter(option)"
|
|
57
|
-
>
|
|
58
|
-
<template #prepend>
|
|
59
|
-
<v-checkbox
|
|
60
|
-
hide-details
|
|
61
|
-
:model-value="selectedFilters.includes(option.value)"
|
|
62
|
-
@update:model-value="toggleFilter(option)"
|
|
63
|
-
/>
|
|
64
|
-
</template>
|
|
65
|
-
<v-list-item-title>{{ option.label }}</v-list-item-title>
|
|
66
|
-
</v-list-item>
|
|
67
|
-
</v-list>
|
|
68
|
-
</v-card>
|
|
69
|
-
</v-menu>
|
|
70
|
-
</div>
|
|
3
|
+
<v-text-field
|
|
4
|
+
v-model.trim="search"
|
|
5
|
+
:placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
|
|
6
|
+
:append-icon="type === 'all' ? 'mdi-magnify' : false"
|
|
7
|
+
prepend-inner-icon="mdi-magnify"
|
|
8
|
+
single-line
|
|
9
|
+
class="transition-swing"
|
|
10
|
+
variant="outlined"
|
|
11
|
+
hide-details
|
|
12
|
+
clearable
|
|
13
|
+
tile
|
|
14
|
+
type="search"
|
|
15
|
+
:loading="rootStore.loading"
|
|
16
|
+
@keyup.enter="$router.push(localePath('/search'))"
|
|
17
|
+
@click:append="$router.push(localePath('/search'))"
|
|
18
|
+
>
|
|
19
|
+
<!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
|
|
20
|
+
$store.state.scrolled }" -->
|
|
21
|
+
<template v-if="!search" #label>
|
|
22
|
+
<div class="searchLabel">
|
|
23
|
+
{{
|
|
24
|
+
type === "all"
|
|
25
|
+
? $t("search")
|
|
26
|
+
: $t("list.search-type", [$t("items." + type, 2)])
|
|
27
|
+
}}
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
</v-text-field>
|
|
71
31
|
</div>
|
|
72
32
|
</template>
|
|
73
33
|
|
|
74
34
|
<script setup>
|
|
75
35
|
import { useDebounceFn } from "@vueuse/core";
|
|
76
36
|
import { useRootStore } from "../../../stores/root";
|
|
77
|
-
import { computed, useI18n
|
|
78
|
-
|
|
79
|
-
const
|
|
37
|
+
import { computed, useI18n } from "#imports";
|
|
38
|
+
const { $router } = useNuxtApp();
|
|
39
|
+
const localePath = useLocalePath();
|
|
40
|
+
const { locale } = useI18n();
|
|
80
41
|
const rootStore = useRootStore();
|
|
81
|
-
const emit = defineEmits(["filter-change"]);
|
|
82
42
|
const props = defineProps({
|
|
83
43
|
type: {
|
|
84
44
|
type: String,
|
|
@@ -89,29 +49,6 @@ const props = defineProps({
|
|
|
89
49
|
default: false
|
|
90
50
|
}
|
|
91
51
|
});
|
|
92
|
-
const filterMenuOpen = ref(false);
|
|
93
|
-
const selectedFilters = ref([]);
|
|
94
|
-
const filterOptions = [
|
|
95
|
-
{ value: "people", label: capitalize(t("items.people", 2)) },
|
|
96
|
-
{ value: "events", label: capitalize(t("items.events", 2)) },
|
|
97
|
-
{ value: "news", label: capitalize(t("items.news", 2)) },
|
|
98
|
-
{ value: "publications", label: capitalize(t("items.publications", 2)) },
|
|
99
|
-
{ value: "fellowships", label: capitalize(t("items.fellowships", 2)) },
|
|
100
|
-
{ value: "projects", label: capitalize(t("items.projects", 2)) }
|
|
101
|
-
];
|
|
102
|
-
const toggleFilter = (option) => {
|
|
103
|
-
const index = selectedFilters.value.indexOf(option.value);
|
|
104
|
-
if (index > -1) {
|
|
105
|
-
selectedFilters.value.splice(index, 1);
|
|
106
|
-
} else {
|
|
107
|
-
selectedFilters.value.push(option.value);
|
|
108
|
-
}
|
|
109
|
-
emit("filter-change", {
|
|
110
|
-
name: option.value,
|
|
111
|
-
value: selectedFilters.value.includes(option.value),
|
|
112
|
-
allSelected: selectedFilters.value
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
52
|
const search = computed({
|
|
116
53
|
get() {
|
|
117
54
|
return rootStore.search;
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
<div class="d-flex align-center">
|
|
4
4
|
<v-text-field
|
|
5
5
|
v-model.trim="search"
|
|
6
|
-
:placeholder="
|
|
6
|
+
:placeholder="
|
|
7
|
+
type === 'all'
|
|
8
|
+
? t('search')
|
|
9
|
+
: $t('list.search-type', [$t('items.' + type, 2)])
|
|
10
|
+
"
|
|
7
11
|
prepend-inner-icon="mdi-magnify"
|
|
8
12
|
single-line
|
|
9
13
|
class="transition-swing flex-grow-1"
|
|
@@ -13,6 +17,7 @@
|
|
|
13
17
|
tile
|
|
14
18
|
type="search"
|
|
15
19
|
:loading="rootStore.loading"
|
|
20
|
+
@keyup.enter="$router.push(localePath('/search'))"
|
|
16
21
|
>
|
|
17
22
|
<!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
|
|
18
23
|
$store.state.scrolled }" -->
|
|
@@ -37,7 +42,7 @@
|
|
|
37
42
|
<v-btn
|
|
38
43
|
v-bind="menuProps"
|
|
39
44
|
:rounded="0"
|
|
40
|
-
variant="
|
|
45
|
+
variant="text"
|
|
41
46
|
size="large"
|
|
42
47
|
height="56"
|
|
43
48
|
>
|
|
@@ -45,6 +50,9 @@
|
|
|
45
50
|
<v-icon class="ml-1" size="small">
|
|
46
51
|
{{ filterMenuOpen ? "mdi-chevron-up" : "mdi-chevron-down" }}
|
|
47
52
|
</v-icon>
|
|
53
|
+
<v-tooltip activator="parent" location="start">
|
|
54
|
+
{{ $t("filter-by-type") }}
|
|
55
|
+
</v-tooltip>
|
|
48
56
|
</v-btn>
|
|
49
57
|
</template>
|
|
50
58
|
|
|
@@ -67,6 +75,21 @@
|
|
|
67
75
|
</v-list>
|
|
68
76
|
</v-card>
|
|
69
77
|
</v-menu>
|
|
78
|
+
<v-btn
|
|
79
|
+
v-bind="attrs"
|
|
80
|
+
:rounded="0"
|
|
81
|
+
variant="test"
|
|
82
|
+
size="large"
|
|
83
|
+
height="56"
|
|
84
|
+
v-on="on"
|
|
85
|
+
@keyup.enter="$router.push(localePath('/search'))"
|
|
86
|
+
@click="$router.push(localePath('/search'))"
|
|
87
|
+
>
|
|
88
|
+
<v-icon>mdi-magnify</v-icon>
|
|
89
|
+
<v-tooltip activator="parent" location="start">{{
|
|
90
|
+
$t("click-here-to-search")
|
|
91
|
+
}}</v-tooltip>
|
|
92
|
+
</v-btn>
|
|
70
93
|
</div>
|
|
71
94
|
</div>
|
|
72
95
|
</template>
|
|
@@ -94,14 +117,14 @@ const props = defineProps({
|
|
|
94
117
|
}
|
|
95
118
|
});
|
|
96
119
|
const filterMenuOpen = ref(false);
|
|
97
|
-
const filterOptions = [
|
|
120
|
+
const filterOptions = computed(() => [
|
|
98
121
|
{ value: "people", label: capitalize(t("items.people", 2)) },
|
|
99
122
|
{ value: "events", label: capitalize(t("items.events", 2)) },
|
|
100
123
|
{ value: "news", label: capitalize(t("items.news", 2)) },
|
|
101
124
|
{ value: "publications", label: capitalize(t("items.publications", 2)) },
|
|
102
125
|
{ value: "fellowships", label: capitalize(t("items.fellowships", 2)) },
|
|
103
126
|
{ value: "projects", label: capitalize(t("items.projects", 2)) }
|
|
104
|
-
];
|
|
127
|
+
]);
|
|
105
128
|
const toggleFilter = (option) => {
|
|
106
129
|
const currentCategories = [...props.categories];
|
|
107
130
|
const index = currentCategories.indexOf(option.value);
|
|
@@ -15,7 +15,12 @@
|
|
|
15
15
|
class="d-flex flex-column cursor-pointer"
|
|
16
16
|
@click="$emit('toggle', type)"
|
|
17
17
|
>
|
|
18
|
-
<div
|
|
18
|
+
<div
|
|
19
|
+
class="text-h4"
|
|
20
|
+
:class="
|
|
21
|
+
$rootStore.results[type].total > 0 ? '' : 'text-grey darken-2'
|
|
22
|
+
"
|
|
23
|
+
>
|
|
19
24
|
{{ capitalize($t("items." + props.type, 2)) }}
|
|
20
25
|
</div>
|
|
21
26
|
<div class="text-overline">
|
|
@@ -58,7 +63,9 @@
|
|
|
58
63
|
<script setup>
|
|
59
64
|
import { useNuxtApp, useLocalePath } from "#imports";
|
|
60
65
|
const localePath = useLocalePath();
|
|
66
|
+
const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
61
67
|
const { $rootStore } = useNuxtApp();
|
|
68
|
+
defineEmits(["toggle"]);
|
|
62
69
|
const props = defineProps({
|
|
63
70
|
type: {
|
|
64
71
|
type: String,
|
|
@@ -3,17 +3,15 @@
|
|
|
3
3
|
type="all"
|
|
4
4
|
:placeholder="$t('search')"
|
|
5
5
|
variant="outlined"
|
|
6
|
+
:categories="selectedCategories"
|
|
7
|
+
@filter-change="handleFilterChange"
|
|
6
8
|
/>
|
|
7
9
|
<ListMoleculesResultsContainer
|
|
8
|
-
v-for="type in
|
|
10
|
+
v-for="type in filteredSortedModules"
|
|
9
11
|
:key="type"
|
|
10
12
|
:feminine="type === 'people'"
|
|
11
13
|
:type
|
|
12
|
-
:open="
|
|
13
|
-
open[type] !== undefined
|
|
14
|
-
? open[type]
|
|
15
|
-
: $rootStore.results[type]?.total > 0
|
|
16
|
-
"
|
|
14
|
+
:open="$rootStore.results[type]?.total > 0 || open[type]"
|
|
17
15
|
@toggle="open[$event] = !open[$event]"
|
|
18
16
|
>
|
|
19
17
|
<v-expand-transition class="results-container">
|
|
@@ -27,7 +25,6 @@
|
|
|
27
25
|
<script setup>
|
|
28
26
|
import {
|
|
29
27
|
useNuxtApp,
|
|
30
|
-
useLocalePath,
|
|
31
28
|
onBeforeUnmount,
|
|
32
29
|
onMounted,
|
|
33
30
|
useI18n,
|
|
@@ -35,7 +32,6 @@ import {
|
|
|
35
32
|
ref,
|
|
36
33
|
computed
|
|
37
34
|
} from "#imports";
|
|
38
|
-
const localePath = useLocalePath();
|
|
39
35
|
defineOptions({
|
|
40
36
|
name: "SearchResults"
|
|
41
37
|
});
|
|
@@ -43,6 +39,10 @@ const { $rootStore } = useNuxtApp();
|
|
|
43
39
|
const appConfig = useAppConfig();
|
|
44
40
|
const { locale } = useI18n();
|
|
45
41
|
const open = ref({});
|
|
42
|
+
const selectedCategories = ref([...appConfig.list.modules]);
|
|
43
|
+
const handleFilterChange = (filterData) => {
|
|
44
|
+
selectedCategories.value = filterData.categories;
|
|
45
|
+
};
|
|
46
46
|
const sortedModules = computed(() => {
|
|
47
47
|
return appConfig.list.modules.slice().sort((a, b) => {
|
|
48
48
|
const aResults = $rootStore.results[a] || { total: 0 };
|
|
@@ -50,6 +50,11 @@ const sortedModules = computed(() => {
|
|
|
50
50
|
return (bResults.total || 0) - (aResults.total || 0);
|
|
51
51
|
});
|
|
52
52
|
});
|
|
53
|
+
const filteredSortedModules = computed(() => {
|
|
54
|
+
return sortedModules.value.filter(
|
|
55
|
+
(type) => selectedCategories.value.includes(type)
|
|
56
|
+
);
|
|
57
|
+
});
|
|
53
58
|
onMounted(async () => {
|
|
54
59
|
console.log("mounted list");
|
|
55
60
|
try {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<v-row
|
|
3
3
|
v-ripple
|
|
4
4
|
no-gutters
|
|
5
|
-
class="cursor-pointer highlight-on-hover"
|
|
5
|
+
class="cursor-pointer highlight-on-hover my-3"
|
|
6
6
|
@click="
|
|
7
7
|
$router.push(
|
|
8
8
|
localePath({
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
width="80px"
|
|
25
25
|
/>
|
|
26
26
|
</v-col>
|
|
27
|
-
<v-col align-self="center" class="text-h6 dense
|
|
27
|
+
<v-col align-self="center" class="text-h6 dense px-2">
|
|
28
28
|
<v-skeleton-loader v-if="rootStore.loading" type="heading" />
|
|
29
29
|
<div v-else class="text-h5">
|
|
30
30
|
{{ item.firstname + " " + item.lastname }}
|
|
31
31
|
</div>
|
|
32
|
-
<div class="mt-2 text-body-
|
|
32
|
+
<div class="mt-2 text-body-1 font-weight-light">
|
|
33
33
|
{{ item.groups.vintage ? item.groups.vintage[0].theme : "" }}
|
|
34
34
|
</div>
|
|
35
35
|
</v-col>
|
|
@@ -125,7 +125,14 @@
|
|
|
125
125
|
:key="position.role + index"
|
|
126
126
|
class="text-body-2"
|
|
127
127
|
>
|
|
128
|
-
|
|
128
|
+
<template v-if="position.role === 'Fellow'">
|
|
129
|
+
<span class="text-caption text-uppercase">
|
|
130
|
+
{{ $t("fellow") }}
|
|
131
|
+
</span>
|
|
132
|
+
</template>
|
|
133
|
+
<template v-else>
|
|
134
|
+
{{ position.role + " " + (position.department || "") }}
|
|
135
|
+
</template>
|
|
129
136
|
<span v-if="position.start" class="">
|
|
130
137
|
<!-- TODO FIx dates display -->
|
|
131
138
|
-
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"see-more": "See more events"
|
|
14
14
|
},
|
|
15
15
|
"filters": "Filters",
|
|
16
|
-
"from {0} to {1}": "
|
|
16
|
+
"from {0} to {1}": "From {0} to {1}",
|
|
17
17
|
"gallery": "Gallery",
|
|
18
18
|
"hybrid-event": "Hybrid event",
|
|
19
19
|
"inscription-gratuite-et-obligatoire": " Free and mandatory registration",
|
|
@@ -346,5 +346,6 @@
|
|
|
346
346
|
"list.by-vintage-from-recent-to-old": "By Year, from recent to old",
|
|
347
347
|
"list.by-vintage-from-old-to-recent": "By Year, from old to recent",
|
|
348
348
|
"no-biography": "No biography available",
|
|
349
|
-
"search": "Search"
|
|
349
|
+
"search": "Search",
|
|
350
|
+
"items-per-page": "Items per page"
|
|
350
351
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"see-more": "Voir plus d'événements"
|
|
14
14
|
},
|
|
15
15
|
"filters": "filtre | filtre | Filtres",
|
|
16
|
-
"from {0} to {1}": "
|
|
16
|
+
"from {0} to {1}": "Du {0} à {1}",
|
|
17
17
|
"gallery": "Galerie",
|
|
18
18
|
"hybrid-event": "Évènement hybride",
|
|
19
19
|
"inscription-gratuite-et-obligatoire": "Enregistrement gratuit et obligatoire",
|
|
@@ -342,8 +342,9 @@
|
|
|
342
342
|
"visit-this-project-website": "Visitez le site Web du projet",
|
|
343
343
|
"visit-this-publications-website": "Visitez la page Web de cette publication",
|
|
344
344
|
"no-biography": "Aucune biographie disponible",
|
|
345
|
-
"search": "Rechercher",
|
|
346
345
|
"close-the-filter-panel": "Réduire les filtres",
|
|
347
346
|
"list.by-vintage-from-recent-to-old": "Par année, du plus récent au plus vieux",
|
|
348
|
-
"list.by-vintage-from-old-to-recent": "Par année, du plus vieux au plus récent"
|
|
347
|
+
"list.by-vintage-from-old-to-recent": "Par année, du plus vieux au plus récent",
|
|
348
|
+
"search": "Rechercher",
|
|
349
|
+
"items-per-page": "Éléments par page"
|
|
349
350
|
}
|