@paris-ias/list 1.0.106 → 1.0.108

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@paris-ias/list",
3
3
  "configKey": "list",
4
- "version": "1.0.106",
4
+ "version": "1.0.108",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.0",
7
7
  "unbuild": "3.5.0"
@@ -1,32 +1,50 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="$router.push(localePath('/activities/events/' + item.slug[locale]))"
6
7
  >
7
- <v-col align-self="center" cols="auto">
8
- {{
9
- new Date(item.start).toLocaleDateString(locale, {
10
- year: "numeric",
11
- month: "numeric",
12
- day: "numeric",
13
- })
14
- }}
8
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
9
+ <MiscAtomsImageContainer
10
+ cover
11
+ :loading="$stores.events.loading"
12
+ :src="item.image.url ? item.image : '/default.png'"
13
+ :ratio="1 / 1"
14
+ :name="item.name"
15
+ :slug="item.slug"
16
+ link="events-slug"
17
+ width="80px"
18
+ />
15
19
  </v-col>
16
- <v-col align-self="center" class="text-h6 dense">
17
- <div class="mt-2 text-h6 text-overline font-weight-black">
18
- {{ $t("list.filters.events.category." + item.category) }}
20
+
21
+ <v-col align-self="center" class="pl-2">
22
+ <div class="text-h5 dense text-overline font-weight-black">
23
+ {{
24
+ $t("list.filters.events.category." + item.category) +
25
+ " / " +
26
+ new Date(item.start).toLocaleDateString(locale, {
27
+ year: "numeric",
28
+ month: "numeric",
29
+ day: "numeric",
30
+ })
31
+ }}
32
+ </div>
33
+ <div class="text-h5 dense">
34
+ {{ item.name }}
19
35
  </div>
20
- {{ item.name }}
21
36
  </v-col>
22
- <v-col align-self="center">
23
- <!-- <EventsBadges :item /> -->
37
+
38
+ <v-col align-self="center" cols="auto">
39
+ <EventsBadges :item />
24
40
  </v-col>
25
41
  </v-row>
26
42
  </template>
27
43
 
28
44
  <script setup>
29
45
  import { useLocalePath, useI18n } from "#imports";
46
+ import { useDisplay } from "vuetify";
47
+ const { mdAndUp } = useDisplay();
30
48
  const { locale } = useI18n();
31
49
  const localePath = useLocalePath();
32
50
  const props = defineProps({
@@ -1,12 +1,13 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="
6
7
  $router.push(localePath('/activities/fellowships' + item.slug[locale]))
7
8
  "
8
9
  >
9
- <v-col align-self="center" cols="8" class="text-h6">
10
+ <v-col align-self="center" cols="8" class="text-h5 dense">
10
11
  {{ item.name }}
11
12
  <FellowshipsBadges :item="item" />
12
13
  </v-col>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <component
3
+ :is="itemTemplate"
4
+ v-for="(item, index) in $rootStore.results[type].items"
5
+ :key="index"
6
+ :item="item"
7
+ :index="index"
8
+ />
9
+ </template>
10
+
11
+ <script setup>
12
+ import { capitalize } from "../../../composables/useUtils";
13
+ import { useNuxtApp, resolveComponent, computed } from "#imports";
14
+ const { $stores, $rootStore } = useNuxtApp();
15
+ console.log("rootStore: ", $rootStore);
16
+ const props = defineProps({
17
+ type: {
18
+ type: String,
19
+ default: "people"
20
+ }
21
+ });
22
+ const itemTemplate = computed(
23
+ () => resolveComponent(
24
+ (capitalize(props.type) + capitalize($stores[props.type].view.name) + "Item").toString()
25
+ )
26
+ );
27
+ </script>
@@ -1,80 +1,84 @@
1
1
  <template>
2
2
  <div class="d-flex flex-grow-1 flex-column">
3
- <v-text-field
4
- v-model.trim="search"
5
- :placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
6
- prepend-inner-icon="mdi-magnify"
7
- single-line
8
- class="transition-swing"
9
- variant="outlined"
10
- hide-details
11
- clearable
12
- tile
13
- type="search"
14
- :loading="rootStore.loading"
15
- >
16
- <!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
17
- $store.state.scrolled }" -->
18
- <template v-if="!search" #label>
19
- <div class="searchLabel">
20
- {{
21
- type === "all"
22
- ? $t("search")
23
- : $t("list.search-type", [$t("items." + type, 2)])
24
- }}
25
- </div>
26
- </template>
27
- </v-text-field>
28
- <v-expand-transition v-if="type === 'all'">
29
- <v-list
30
- v-show="search.length"
31
- lines="three"
32
- item-props
33
- style="max-height: 300px"
34
- class="overflow-y-auto"
3
+ <div class="d-flex align-center">
4
+ <v-text-field
5
+ v-model.trim="search"
6
+ :placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
7
+ prepend-inner-icon="mdi-magnify"
8
+ single-line
9
+ class="transition-swing flex-grow-1"
10
+ variant="outlined"
11
+ hide-details
12
+ clearable
13
+ tile
14
+ type="search"
15
+ :loading="rootStore.loading"
35
16
  >
36
- <div v-if="rootStore.loading" class="d-flex justify-center py-6">
37
- <v-progress-circular color="black" size="64" indeterminate />
38
- </div>
39
- <template v-for="(item, index) in results">
40
- <v-list-subheader
41
- v-if="item.type && item.type === 'subheader'"
42
- :key="'subheader-' + index"
43
- >
44
- {{ $t(item.name) }}
45
- </v-list-subheader>
46
- <div
47
- v-else-if="item.type && item.type === 'no-result'"
48
- :key="'no-result-' + index"
49
- class="mx-6"
50
- >
51
- {{ $t("no-result") }}
17
+ <!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
18
+ $store.state.scrolled }" -->
19
+ <template v-if="!search" #label>
20
+ <div class="searchLabel">
21
+ {{
22
+ type === "all"
23
+ ? $t("search")
24
+ : $t("list.search-type", [$t("items." + type, 2)])
25
+ }}
52
26
  </div>
53
- <v-divider
54
- v-else-if="item.type && item.type === 'divider'"
55
- :key="'divider-' + index"
56
- inset
57
- />
58
- <ListAtomsSearchItem
59
- v-else
60
- :key="'item- ' + index"
61
- :index
62
- :item
63
- :type="item.type"
64
- />
65
27
  </template>
66
- </v-list>
67
- </v-expand-transition>
28
+ </v-text-field>
29
+
30
+ <v-menu
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>
68
71
  </div>
69
72
  </template>
70
73
 
71
74
  <script setup>
72
75
  import { useDebounceFn } from "@vueuse/core";
73
76
  import { useRootStore } from "../../../stores/root";
74
- import { useNuxtApp, computed, useI18n } from "#imports";
77
+ import { computed, useI18n, ref } from "#imports";
78
+ import { capitalize } from "../../../composables/useUtils";
75
79
  const { locale, t } = useI18n();
76
80
  const rootStore = useRootStore();
77
- const { $stores } = useNuxtApp();
81
+ const emit = defineEmits(["filter-change"]);
78
82
  const props = defineProps({
79
83
  type: {
80
84
  type: String,
@@ -85,34 +89,29 @@ const props = defineProps({
85
89
  default: false
86
90
  }
87
91
  });
88
- const results = computed(() => {
89
- const storeRst = rootStore.results;
90
- const rst = Object.keys(storeRst).length && Object.keys(storeRst).sort((a, b) => {
91
- return storeRst[b]?.items?.length - storeRst[a]?.items?.length;
92
- }).reduce((acc, key, index) => {
93
- const items = storeRst[key]?.items;
94
- const total = storeRst[key]?.total;
95
- if (total === 0 && index === 0) {
96
- acc.push({ type: "no-result" });
97
- return acc;
98
- }
99
- if (items?.length) {
100
- acc.push({ type: "subheader", name: t("items." + key, 2) });
101
- acc.push(
102
- ...items.map((item) => ({
103
- prependAvatar: item?.image?.url || "mdi-square",
104
- title: item.name || item.firstname + " " + item.lastname,
105
- subtitle: item.summary || item.biography,
106
- id: item.id,
107
- type: key
108
- }))
109
- );
110
- }
111
- acc.push({ type: "divider" });
112
- return acc;
113
- }, []) || {};
114
- return rst;
115
- });
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
+ };
116
115
  const search = computed({
117
116
  get() {
118
117
  return rootStore.search;
@@ -14,7 +14,7 @@
14
14
  $stores[type].total,
15
15
  $t("items." + props.type, $stores[type].total),
16
16
  ],
17
- $stores[type].total
17
+ $stores[type].total,
18
18
  )
19
19
  : $t(
20
20
  "list.0-items-found",
@@ -22,7 +22,7 @@
22
22
  $stores[type].total,
23
23
  $t("items." + props.type, $stores[type].total),
24
24
  ],
25
- $stores[type].total
25
+ $stores[type].total,
26
26
  )
27
27
  }}
28
28
  </template>
@@ -42,11 +42,11 @@
42
42
  $t(
43
43
  "items." + props.type,
44
44
  $stores[type].total,
45
- $stores[type].total
45
+ $stores[type].total,
46
46
  ),
47
47
  $stores[type].search,
48
48
  ],
49
- $stores[type].total
49
+ $stores[type].total,
50
50
  )
51
51
  : $t(
52
52
  "list.0-items-found-searching-for",
@@ -55,11 +55,11 @@
55
55
  $t(
56
56
  "items." + props.type,
57
57
  $stores[type].total,
58
- $stores[type].total
58
+ $stores[type].total,
59
59
  ),
60
60
  $stores[type].search,
61
61
  ],
62
- $stores[type].total
62
+ $stores[type].total,
63
63
  )
64
64
  }}
65
65
  </template>
@@ -79,12 +79,12 @@
79
79
  $t(
80
80
  "items." + props.type,
81
81
  $stores[type].total,
82
- $stores[type].total
82
+ $stores[type].total,
83
83
  ),
84
84
  $stores[type].filtersCount,
85
85
  $t("filters", $stores[type].filtersCount),
86
86
  ],
87
- $stores[type].total
87
+ $stores[type].total,
88
88
  )
89
89
  : $t(
90
90
  "list.0-items-found-with-1-filter",
@@ -94,7 +94,7 @@
94
94
  $stores[type].filtersCount,
95
95
  $t("filters", $stores[type].filtersCount),
96
96
  ],
97
- $stores[type].total
97
+ $stores[type].total,
98
98
  )
99
99
  }}
100
100
  </template>
@@ -117,7 +117,7 @@
117
117
  $stores[type].filtersCount,
118
118
  $t("filters", $stores[type].filtersCount),
119
119
  ],
120
- $stores[type].total
120
+ $stores[type].total,
121
121
  )
122
122
  : $t(
123
123
  "list.0-items-found-searching-for-with-1-filter",
@@ -128,7 +128,7 @@
128
128
  $stores[type].filtersCount,
129
129
  $t("filters", $stores[type].filtersCount),
130
130
  ],
131
- $stores[type].total
131
+ $stores[type].total,
132
132
  )
133
133
  }}
134
134
  </template>
@@ -0,0 +1,131 @@
1
+ <template>
2
+ <div class="d-flex flex-grow-1 flex-column">
3
+ <div class="d-flex align-center">
4
+ <v-text-field
5
+ v-model.trim="search"
6
+ :placeholder="$t('list.search-type', [$t('items.' + type, 2)])"
7
+ prepend-inner-icon="mdi-magnify"
8
+ single-line
9
+ class="transition-swing flex-grow-1"
10
+ variant="outlined"
11
+ hide-details
12
+ clearable
13
+ tile
14
+ type="search"
15
+ :loading="rootStore.loading"
16
+ >
17
+ <!-- :loading="$nuxt.loading || $store.state.loading" :class="{ 'mt-3':
18
+ $store.state.scrolled }" -->
19
+ <template v-if="!search" #label>
20
+ <div class="searchLabel">
21
+ {{
22
+ type === "all"
23
+ ? $t("search")
24
+ : $t("list.search-type", [$t("items." + type, 2)])
25
+ }}
26
+ </div>
27
+ </template>
28
+ </v-text-field>
29
+
30
+ <v-menu
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 density="compact">
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="categories.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>
71
+ </div>
72
+ </template>
73
+
74
+ <script setup>
75
+ import { useDebounceFn } from "@vueuse/core";
76
+ import { useRootStore } from "../../../stores/root";
77
+ import { computed, useI18n, ref } from "#imports";
78
+ const { locale, t } = useI18n();
79
+ const rootStore = useRootStore();
80
+ const capitalize = (str) => str.charAt(0).toUpperCase() + str.slice(1);
81
+ const emit = defineEmits(["filter-change"]);
82
+ const props = defineProps({
83
+ type: {
84
+ type: String,
85
+ required: true
86
+ },
87
+ loading: {
88
+ type: Boolean,
89
+ default: false
90
+ },
91
+ categories: {
92
+ type: Array,
93
+ default: () => []
94
+ }
95
+ });
96
+ const filterMenuOpen = ref(false);
97
+ const filterOptions = [
98
+ { value: "people", label: capitalize(t("items.people", 2)) },
99
+ { value: "events", label: capitalize(t("items.events", 2)) },
100
+ { value: "news", label: capitalize(t("items.news", 2)) },
101
+ { value: "publications", label: capitalize(t("items.publications", 2)) },
102
+ { value: "fellowships", label: capitalize(t("items.fellowships", 2)) },
103
+ { value: "projects", label: capitalize(t("items.projects", 2)) }
104
+ ];
105
+ const toggleFilter = (option) => {
106
+ const currentCategories = [...props.categories];
107
+ const index = currentCategories.indexOf(option.value);
108
+ if (index > -1) {
109
+ currentCategories.splice(index, 1);
110
+ } else {
111
+ currentCategories.push(option.value);
112
+ }
113
+ emit("filter-change", {
114
+ name: option.value,
115
+ value: currentCategories.includes(option.value),
116
+ categories: currentCategories
117
+ });
118
+ };
119
+ const search = computed({
120
+ get() {
121
+ return rootStore.search;
122
+ },
123
+ set: await useDebounceFn(async function(v) {
124
+ await rootStore.updateSearch({
125
+ type: props.type,
126
+ search: v || "",
127
+ lang: locale.value
128
+ });
129
+ }, 300)
130
+ });
131
+ </script>
@@ -0,0 +1,78 @@
1
+ <template>
2
+ <div>
3
+ <div class="d-flex align-center justify-space-between my-6">
4
+ <v-btn
5
+ variant="text"
6
+ size="large"
7
+ class=""
8
+ @click="$emit('toggle', type)"
9
+ >
10
+ <v-icon size="large">{{
11
+ open ? "mdi-chevron-down" : "mdi-chevron-right"
12
+ }}</v-icon>
13
+ </v-btn>
14
+ <div
15
+ class="d-flex flex-column cursor-pointer"
16
+ @click="$emit('toggle', type)"
17
+ >
18
+ <div class="text-h4">
19
+ {{ capitalize($t("items." + props.type, 2)) }}
20
+ </div>
21
+ <div class="text-overline">
22
+ {{
23
+ feminine
24
+ ? $t(
25
+ "list.0-items-found-f",
26
+ [
27
+ $rootStore.results[type].total,
28
+ $t("items." + props.type, $rootStore.results[type].total),
29
+ ],
30
+ $rootStore.results[type].total,
31
+ )
32
+ : $t(
33
+ "list.0-items-found",
34
+ [
35
+ $rootStore.results[type].total,
36
+ $t("items." + props.type, $rootStore.results[type].total),
37
+ ],
38
+ $rootStore.results[type].total,
39
+ )
40
+ }}
41
+ </div>
42
+ </div>
43
+ <v-spacer />
44
+ </div>
45
+ <slot />
46
+ <v-btn
47
+ class="ma-2 float-right"
48
+ color="default"
49
+ variant="text"
50
+ rounded="0"
51
+ :to="localePath(type === 'people' ? '/people' : '/activities/' + type)"
52
+ >
53
+ {{ $t("list.pls-x-more", [$rootStore.results[type].total]) }}
54
+ </v-btn>
55
+ </div>
56
+ </template>
57
+
58
+ <script setup>
59
+ import { useNuxtApp, useLocalePath } from "#imports";
60
+ const localePath = useLocalePath();
61
+ const { $rootStore } = useNuxtApp();
62
+ const props = defineProps({
63
+ type: {
64
+ type: String,
65
+ required: true
66
+ },
67
+ feminine: {
68
+ type: Boolean,
69
+ required: false,
70
+ default: false
71
+ },
72
+ open: {
73
+ type: Boolean,
74
+ required: false,
75
+ default: true
76
+ }
77
+ });
78
+ </script>
@@ -85,10 +85,10 @@ const numberOfPages = computed(() => $stores[props.type].numberOfPages);
85
85
  const page = computed(() => +$stores[props.type].page);
86
86
  const items = computed(() => $stores[props.type].items);
87
87
  console.log("setup list");
88
- rootStore.loadRouteQuery(props.type);
89
88
  onMounted(() => {
90
89
  console.log("mounted list");
91
90
  });
91
+ rootStore.loadRouteQuery(props.type);
92
92
  try {
93
93
  await rootStore.update(props.type, locale.value);
94
94
  } catch (error) {
@@ -1,54 +1,69 @@
1
1
  <template>
2
- <ListMoleculesResultsHeader :type="props.type" />
3
- <div class="results-container">
4
- <component
5
- :is="itemTemplate"
6
- v-for="(item, index) in items"
7
- :key="index"
8
- :item="item"
9
- :index="index"
10
- />
11
- </div>
2
+ <ListMoleculesGlobalSearchInput
3
+ type="all"
4
+ :placeholder="$t('search')"
5
+ variant="outlined"
6
+ />
7
+ <ListMoleculesResultsContainer
8
+ v-for="type in sortedModules"
9
+ :key="type"
10
+ :feminine="type === 'people'"
11
+ :type
12
+ :open="
13
+ open[type] !== undefined
14
+ ? open[type]
15
+ : $rootStore.results[type]?.total > 0
16
+ "
17
+ @toggle="open[$event] = !open[$event]"
18
+ >
19
+ <v-expand-transition class="results-container">
20
+ <div v-show="open[type]">
21
+ <ListAtomsResultsList :type />
22
+ </div>
23
+ </v-expand-transition>
24
+ </ListMoleculesResultsContainer>
12
25
  </template>
13
26
 
14
27
  <script setup>
15
- import { useRootStore } from "../../../stores/root";
16
- import { capitalize } from "../../../composables/useUtils";
17
28
  import {
18
29
  useNuxtApp,
19
- resolveComponent,
20
- computed,
30
+ useLocalePath,
21
31
  onBeforeUnmount,
22
32
  onMounted,
23
- useI18n
33
+ useI18n,
34
+ useAppConfig,
35
+ ref,
36
+ computed
24
37
  } from "#imports";
25
- const { $stores } = useNuxtApp();
38
+ const localePath = useLocalePath();
39
+ defineOptions({
40
+ name: "SearchResults"
41
+ });
42
+ const { $rootStore } = useNuxtApp();
43
+ const appConfig = useAppConfig();
26
44
  const { locale } = useI18n();
27
- const rootStore = useRootStore();
28
- const props = defineProps({
29
- type: {
30
- type: String,
31
- default: "people",
32
- required: true
33
- },
34
- items: [Object]
45
+ const open = ref({});
46
+ const sortedModules = computed(() => {
47
+ return appConfig.list.modules.slice().sort((a, b) => {
48
+ const aResults = $rootStore.results[a] || { total: 0 };
49
+ const bResults = $rootStore.results[b] || { total: 0 };
50
+ return (bResults.total || 0) - (aResults.total || 0);
51
+ });
35
52
  });
36
- const itemTemplate = computed(
37
- () => resolveComponent(
38
- (capitalize(props.type) + capitalize($stores[props.type].view.name) + "Item").toString()
39
- )
40
- );
41
- const items = computed(() => $stores[props.type].items);
42
- onMounted(() => {
53
+ onMounted(async () => {
43
54
  console.log("mounted list");
55
+ try {
56
+ await $rootStore.update("all", locale.value);
57
+ appConfig.list.modules.forEach((type) => {
58
+ if ($rootStore.results[type]?.total > 0) {
59
+ open.value[type] = true;
60
+ }
61
+ });
62
+ } catch (error) {
63
+ console.log("error fetching update list: ", error);
64
+ }
44
65
  });
45
- try {
46
- await rootStore.update(props.type, locale.value);
47
- } catch (error) {
48
- console.log("error fetching update list: ", error);
49
- }
50
66
  onBeforeUnmount(() => {
51
- rootStore.resetState(props.type, locale.value);
52
67
  });
53
68
  </script>
54
69
 
@@ -1,17 +1,30 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
6
  @click="$router.push(localePath('/activities/news/' + item.slug[locale]))"
6
7
  >
7
- <v-col align-self="center" cols="7" class="text-h6 dense">
8
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
9
+ <MiscAtomsImageContainer
10
+ cover
11
+ :loading="$stores.people.loading"
12
+ :src="item.image.url ? item.image : '/default.png'"
13
+ :ratio="1 / 1"
14
+ :name="item.lastname + ' ' + item.firstname"
15
+ :slug="item.slug"
16
+ link="people-slug"
17
+ width="80px"
18
+ />
19
+ </v-col>
20
+ <v-col align-self="center" class="text-h5 dense pl-2">
8
21
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
9
22
  <template v-else>
10
23
  {{ item.name }}
11
24
  </template>
12
25
  </v-col>
13
26
 
14
- <v-col align-self="center" cols="5" class="dense">
27
+ <v-col align-self="center">
15
28
  <v-skeleton-loader
16
29
  v-if="rootStore.loading"
17
30
  :type="
@@ -36,7 +49,7 @@ import { useDisplay } from "vuetify";
36
49
  import { useRootStore } from "../../stores/root";
37
50
  import { computed, useNuxtApp, useI18n, useLocalePath } from "#imports";
38
51
  const { $stores } = useNuxtApp();
39
- const { name } = useDisplay();
52
+ const { name, mdAndUp } = useDisplay();
40
53
  const localePath = useLocalePath();
41
54
  const { locale } = useI18n();
42
55
  const rootStore = useRootStore();
@@ -3,7 +3,14 @@
3
3
  v-ripple
4
4
  no-gutters
5
5
  class="cursor-pointer highlight-on-hover"
6
- @click="$router.push(localePath('/people/' + item.slug))"
6
+ @click="
7
+ $router.push(
8
+ localePath({
9
+ name: 'people-slug',
10
+ params: { slug: item.slug },
11
+ }),
12
+ )
13
+ "
7
14
  >
8
15
  <v-col v-if="mdAndUp" align-self="center" cols="1">
9
16
  <MiscAtomsImageContainer
@@ -14,10 +21,10 @@
14
21
  :name="item.lastname + ' ' + item.firstname"
15
22
  :slug="item.slug"
16
23
  link="people-slug"
17
- width="50"
24
+ width="80px"
18
25
  />
19
26
  </v-col>
20
- <v-col align-self="center" class="text-h6 pl-2">
27
+ <v-col align-self="center" class="text-h6 dense pl-2">
21
28
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
22
29
  <div v-else class="text-h5">
23
30
  {{ item.firstname + " " + item.lastname }}
@@ -26,7 +33,7 @@
26
33
  {{ item.groups.vintage ? item.groups.vintage[0].theme : "" }}
27
34
  </div>
28
35
  </v-col>
29
- <v-col align-self="center">
36
+ <v-col align-self="center" cols="auto">
30
37
  <PeopleGroupBadges :item="item" />
31
38
  </v-col>
32
39
  </v-row>
@@ -1,10 +1,30 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
+ no-gutters
4
5
  class="cursor-pointer highlight-on-hover"
5
- @click="$router.push(localePath('/projects/' + item.slug[locale]))"
6
+ @click="
7
+ $router.push(
8
+ localePath({
9
+ name: 'activities-projects-slug',
10
+ params: { slug: item.slug[locale] },
11
+ }),
12
+ )
13
+ "
6
14
  >
7
- <v-col align-self="center" cols="7" class="text-h6 dense">
15
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
16
+ <MiscAtomsImageContainer
17
+ cover
18
+ :loading="$stores.projects.loading"
19
+ :src="item.image.url ? item.image : '/default.png'"
20
+ :ratio="1 / 1"
21
+ :name="item.name"
22
+ :slug="item.slug[locale]"
23
+ link="activities-projects-slug"
24
+ width="50"
25
+ />
26
+ </v-col>
27
+ <v-col align-self="center" class="text-h5 dense pl-2">
8
28
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
9
29
  <template v-else>
10
30
  {{ item.name }}
@@ -33,7 +53,7 @@ import { useDisplay } from "vuetify";
33
53
  import { useRootStore } from "../../stores/root";
34
54
  import { computed, useNuxtApp, useI18n, useLocalePath } from "#imports";
35
55
  const { $stores } = useNuxtApp();
36
- const { name } = useDisplay();
56
+ const { name, mdAndUp } = useDisplay();
37
57
  const localePath = useLocalePath();
38
58
  const { locale } = useI18n();
39
59
  const rootStore = useRootStore();
@@ -1,19 +1,35 @@
1
1
  <template>
2
2
  <v-row
3
3
  v-ripple
4
- class="cursor-pointer highlight-on-hover"
4
+ no-gutters
5
+ class="cursor-pointer highlight-on-hover my-2"
5
6
  @click="
6
7
  $router.push(localePath('/activities/publications/' + item.slug[locale]))
7
8
  "
8
9
  >
9
- <v-col align-self="center" cols="7" class="text-h6 dense">
10
+ <v-col v-if="mdAndUp" align-self="center" cols="1">
11
+ <MiscAtomsImageContainer
12
+ cover
13
+ :loading="$stores.people.loading"
14
+ :src="item.image.url ? item.image : '/default.png'"
15
+ :ratio="1 / 1"
16
+ :name="item.lastname + ' ' + item.firstname"
17
+ :slug="item.slug[locale]"
18
+ link="activities-publications-slug"
19
+ width="80px"
20
+ />
21
+ </v-col>
22
+ <v-col align-self="center" class="text-h5 dense pl-2">
10
23
  <v-skeleton-loader v-if="rootStore.loading" type="heading" />
11
24
  <template v-else>
12
25
  {{ item.name }}
26
+ <div class="text-body-2">
27
+ {{ item.summary }}
28
+ </div>
13
29
  </template>
14
30
  </v-col>
15
31
 
16
- <v-col align-self="center" cols="5" class="dense">
32
+ <v-col align-self="center">
17
33
  <v-skeleton-loader
18
34
  v-if="rootStore.loading"
19
35
  :type="
@@ -25,7 +41,9 @@
25
41
 
26
42
  <template v-else>
27
43
  <v-chip class="ma-2" style="background-color: white; color: black">
28
- {{ $t(eventCategory) }}
44
+ {{ $t(eventCategory) }} </v-chip
45
+ ><v-chip class="ma-2" style="background-color: white; color: black">
46
+ {{ $t(eventType) }}
29
47
  </v-chip>
30
48
  <MiscMoleculesChipContainer :items="item.tags" size="small" />
31
49
  </template>
@@ -38,7 +56,7 @@ import { useDisplay } from "vuetify";
38
56
  import { useRootStore } from "../../stores/root";
39
57
  import { computed, useNuxtApp, useI18n, useLocalePath } from "#imports";
40
58
  const { $stores } = useNuxtApp();
41
- const { name } = useDisplay();
59
+ const { name, mdAndUp } = useDisplay();
42
60
  const localePath = useLocalePath();
43
61
  const { locale } = useI18n();
44
62
  const rootStore = useRootStore();
@@ -54,9 +72,18 @@ const props = defineProps({
54
72
  });
55
73
  const eventCategory = computed(() => {
56
74
  if (props.item.category) {
57
- return "list.filters.news.category." + props.item.category;
75
+ console.log("props.item.category: ", props.item.category);
76
+ return "list.filters.publications.category." + props.item.category;
77
+ } else {
78
+ return "list.filters.publications.category.OTHERS";
79
+ }
80
+ });
81
+ const eventType = computed(() => {
82
+ if (props.item.type) {
83
+ console.log("props.item.type: ", props.item.type);
84
+ return "list.filters.publications.type." + props.item.type;
58
85
  } else {
59
- return "list.filters.news.category.others";
86
+ return "list.filters.publications.type.OTHERS";
60
87
  }
61
88
  });
62
89
  </script>
@@ -4,6 +4,19 @@ query search($appId: ID = "", $search: String = "", $lang: String = "en") {
4
4
  items {
5
5
  firstname
6
6
  id
7
+ groups {
8
+ board
9
+ fellows
10
+ sab
11
+ sponsor
12
+ team
13
+ vintage {
14
+ name
15
+ theme
16
+ url
17
+ year
18
+ }
19
+ }
7
20
  image {
8
21
  alt
9
22
  backgroundColor
@@ -20,6 +20,8 @@
20
20
  "inscription-ouverte": "Registration Open",
21
21
  "items": {
22
22
  "all": "all | all | all",
23
+ "activities": "activity | activity | activities",
24
+ "about": "about | about | about",
23
25
  "events": "event | event | events",
24
26
  "fellow": "fellow | fellow | fellows",
25
27
  "fellowships": "fellowship | fellowship | fellowships",
@@ -62,7 +64,8 @@
62
64
  "SYMPOSIUM": "Symposium",
63
65
  "EXHIBITION": "Exhibition",
64
66
  "WEBINAR": "Webinar",
65
- "WORKSHOP": "Workshop"
67
+ "WORKSHOP": "Workshop",
68
+ "CALL": "Call to propositions"
66
69
  },
67
70
  "fellowship": {
68
71
  "cat": "Constructive Advanced Thinking",
@@ -149,7 +152,8 @@
149
152
  "REPORT": "Report",
150
153
  "SOFTWARE": "Software",
151
154
  "TOOL": "Tool",
152
- "VIDEO": "Video"
155
+ "VIDEO": "Video",
156
+ "OTHER": "Other"
153
157
  },
154
158
  "tags": {
155
159
  "label": "Tags",
@@ -228,7 +232,8 @@
228
232
  "SEMINAR": "Seminar",
229
233
  "SYMPOSIUM": "Symposium",
230
234
  "WEBINAR": "Webinar",
231
- "WORKSHOP": "Workshop"
235
+ "WORKSHOP": "Workshop",
236
+ "OTHERS": "Others"
232
237
  },
233
238
  "type": {
234
239
  "label": "Type",
@@ -242,7 +247,8 @@
242
247
  "REPORT": "Report",
243
248
  "SOFTWARE": "Software",
244
249
  "THESIS": "Thesis",
245
- "VIDEO": "Video"
250
+ "VIDEO": "Video",
251
+ "OTHERS": "Others"
246
252
  }
247
253
  }
248
254
  },
@@ -62,7 +62,8 @@
62
62
  "SYMPOSIUM": "Symposium",
63
63
  "EXHIBITION": "Exposition",
64
64
  "WEBINAR": "Webinaire",
65
- "WORKSHOP": "Atelier"
65
+ "WORKSHOP": "Atelier",
66
+ "CALL": "Appel à propositions"
66
67
  },
67
68
  "fellowship": {
68
69
  "label": "Programme d'accueil",
@@ -150,7 +151,8 @@
150
151
  "REPORT": "Rapport",
151
152
  "SOFTWARE": "Logiciel",
152
153
  "TOOL": "Outil",
153
- "VIDEO": "Vidéo"
154
+ "VIDEO": "Vidéo",
155
+ "OTHER": "Autres"
154
156
  },
155
157
  "tags": {
156
158
  "label": "Tags",
@@ -229,7 +231,8 @@
229
231
  "SEMINAR": "Séminaire",
230
232
  "SYMPOSIUM": "Symposium",
231
233
  "WEBINAR": "Webinaire",
232
- "WORKSHOP": "Atelier"
234
+ "WORKSHOP": "Atelier",
235
+ "OTHERS": "Autres"
233
236
  },
234
237
  "type": {
235
238
  "label": "Type",
@@ -243,7 +246,8 @@
243
246
  "REPORT": "Rapport",
244
247
  "SOFTWARE": "Logiciel",
245
248
  "THESIS": "Thèse",
246
- "VIDEO": "Vidéo"
249
+ "VIDEO": "Vidéo",
250
+ "OTHERS": "Autres"
247
251
  }
248
252
  }
249
253
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "license": "AGPL-3.0-only",
3
3
  "main": "./dist/module.mjs",
4
- "version": "1.0.106",
4
+ "version": "1.0.108",
5
5
  "name": "@paris-ias/list",
6
6
  "repository": {
7
7
  "url": "git+https://github.com/IEA-Paris/list.git",
@@ -24,7 +24,7 @@
24
24
  "@nuxtjs/apollo": "^5.0.0-alpha.14",
25
25
  "@nuxtjs/i18n": "^9.5.2",
26
26
  "@nuxtjs/mdc": "0.16.1",
27
- "@paris-ias/data": "^1.8.25",
27
+ "@paris-ias/data": "^1.8.27",
28
28
  "@pinia/nuxt": "^0.5.4",
29
29
  "@types/node": "latest",
30
30
  "@urql/exchange-execute": "2.3.1",
@@ -1,59 +0,0 @@
1
- <template>
2
- <v-divider />
3
- <div class="d-flex align-center justify-space-between my-6">
4
- <div class="d-flex flex-column">
5
- <div class="text-h4">
6
- {{ capitalize($t("items." + props.type, 2)) }}
7
- </div>
8
- <div class="text-overline">
9
- {{
10
- feminine
11
- ? $t(
12
- "list.0-items-found-f",
13
- [
14
- $stores[type].total,
15
- $t("items." + props.type, $stores[type].total),
16
- ],
17
- $stores[type].total,
18
- )
19
- : $t(
20
- "list.0-items-found",
21
- [
22
- $stores[type].total,
23
- $t("items." + props.type, $stores[type].total),
24
- ],
25
- $stores[type].total,
26
- )
27
- }}
28
- </div>
29
- </div>
30
- <v-spacer />
31
- <v-btn
32
- class="ma-2"
33
- color="default"
34
- variant="outlined"
35
- rounded="0"
36
- :to="localePath(type === 'people' ? '/people' : '/activities/' + type)"
37
- @click="$emit('add')"
38
- >
39
- {{ $t("list.pls-x-more", [$stores[type].total]) }}
40
- </v-btn>
41
- </div>
42
- </template>
43
-
44
- <script setup>
45
- import { useNuxtApp, useLocalePath } from "#imports";
46
- const localePath = useLocalePath();
47
- const { $stores } = useNuxtApp();
48
- const props = defineProps({
49
- type: {
50
- type: String,
51
- required: true
52
- },
53
- feminine: {
54
- type: Boolean,
55
- required: false,
56
- default: false
57
- }
58
- });
59
- </script>