@paris-ias/list 1.0.111 → 1.0.113
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 +24 -15
- package/dist/runtime/components/fellowships/DenseItem.vue +1 -1
- package/dist/runtime/components/list/atoms/SearchInput.vue +4 -2
- package/dist/runtime/components/list/molecules/Pagination.vue +2 -0
- package/dist/runtime/components/list/organisms/List.vue +16 -2
- package/dist/runtime/components/list/views/Dense.vue +0 -1
- package/dist/runtime/components/news/DenseItem.vue +24 -23
- package/dist/runtime/components/people/Badges.vue +74 -0
- package/dist/runtime/components/people/DenseItem.vue +11 -8
- package/dist/runtime/components/people/RowsItem.vue +2 -2
- package/dist/runtime/components/people/View.vue +1 -1
- package/dist/runtime/components/publications/DenseItem.vue +14 -7
- package/dist/runtime/graphql/list/publications.gql +2 -0
- package/dist/runtime/runtime/components/actions/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/actions/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/actions/View.vue +20 -0
- package/dist/runtime/runtime/components/affiliations/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/affiliations/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/affiliations/View.vue +20 -0
- package/dist/runtime/runtime/components/apps/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/apps/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/apps/View.vue +20 -0
- package/dist/runtime/runtime/components/disciplines/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/disciplines/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/disciplines/View.vue +20 -0
- package/dist/runtime/runtime/components/events/Badges.vue +73 -0
- package/dist/runtime/runtime/components/events/DateTimePlace.vue +77 -0
- package/dist/runtime/runtime/components/events/DenseItem.vue +60 -0
- package/dist/runtime/runtime/components/events/ExpandedItem.vue +9 -0
- package/dist/runtime/runtime/components/events/RegisterModal.vue +50 -0
- package/dist/runtime/runtime/components/events/RelatedItem.vue +44 -0
- package/dist/runtime/runtime/components/events/RowsItem.vue +118 -0
- package/dist/runtime/runtime/components/events/SlidingItem.vue +63 -0
- package/dist/runtime/runtime/components/events/View.vue +333 -0
- package/dist/runtime/runtime/components/fellowships/Badges.vue +47 -0
- package/dist/runtime/runtime/components/fellowships/DenseItem.vue +42 -0
- package/dist/runtime/runtime/components/fellowships/ExpandedItem.vue +7 -0
- package/dist/runtime/runtime/components/fellowships/RegisterModal.vue +41 -0
- package/dist/runtime/runtime/components/fellowships/RowsItem.vue +58 -0
- package/dist/runtime/runtime/components/fellowships/View.vue +203 -0
- package/dist/runtime/runtime/components/files/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/files/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/files/View.vue +20 -0
- package/dist/runtime/runtime/components/list/atoms/FiltersMenu.vue +44 -0
- package/dist/runtime/runtime/components/list/atoms/ResetButton.vue +33 -0
- package/dist/runtime/runtime/components/list/atoms/ResultsList.vue +27 -0
- package/dist/runtime/runtime/components/list/atoms/SearchInput.vue +59 -0
- package/dist/runtime/runtime/components/list/atoms/SearchItem.vue +65 -0
- package/dist/runtime/runtime/components/list/atoms/SearchString.vue +160 -0
- package/dist/runtime/runtime/components/list/atoms/SortMenu.vue +80 -0
- package/dist/runtime/runtime/components/list/atoms/ViewMenu.vue +63 -0
- package/dist/runtime/runtime/components/list/atoms/itemsPerPage.vue +33 -0
- package/dist/runtime/runtime/components/list/inputs/AutoComplete.vue +24 -0
- package/dist/runtime/runtime/components/list/inputs/BooleanSwitch.vue +20 -0
- package/dist/runtime/runtime/components/list/inputs/Checkbox.vue +20 -0
- package/dist/runtime/runtime/components/list/inputs/Select.vue +28 -0
- package/dist/runtime/runtime/components/list/molecules/Filters.vue +98 -0
- package/dist/runtime/runtime/components/list/molecules/GlobalSearchInput.vue +131 -0
- package/dist/runtime/runtime/components/list/molecules/Header.vue +51 -0
- package/dist/runtime/runtime/components/list/molecules/Pagination.vue +194 -0
- package/dist/runtime/runtime/components/list/molecules/ResultsContainer.vue +78 -0
- package/dist/runtime/runtime/components/list/organisms/List.vue +110 -0
- package/dist/runtime/runtime/components/list/organisms/Results.vue +72 -0
- package/dist/runtime/runtime/components/list/organisms/Slider.vue +180 -0
- package/dist/runtime/runtime/components/list/views/Dense.vue +12 -0
- package/dist/runtime/runtime/components/list/views/Expanded.vue +10 -0
- package/dist/runtime/runtime/components/list/views/Grid.vue +13 -0
- package/dist/runtime/runtime/components/list/views/Rows.vue +12 -0
- package/dist/runtime/runtime/components/list/views/Slider.vue +147 -0
- package/dist/runtime/runtime/components/list/views/Table.vue +13 -0
- package/dist/runtime/runtime/components/mailing/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/mailing/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/mailing/View.vue +20 -0
- package/dist/runtime/runtime/components/misc/atoms/DateStamp.vue +101 -0
- package/dist/runtime/runtime/components/misc/atoms/ImageContainer.vue +127 -0
- package/dist/runtime/runtime/components/misc/atoms/ShareMenu.vue +61 -0
- package/dist/runtime/runtime/components/misc/atoms/Socials.vue +120 -0
- package/dist/runtime/runtime/components/misc/molecules/ChipContainer.vue +31 -0
- package/dist/runtime/runtime/components/misc/molecules/Related.vue +28 -0
- package/dist/runtime/runtime/components/misc/molecules/RelatedItems.vue +27 -0
- package/dist/runtime/runtime/components/misc/molecules/SearchItem.vue +26 -0
- package/dist/runtime/runtime/components/news/DenseItem.vue +73 -0
- package/dist/runtime/runtime/components/news/ExpandedItem.vue +145 -0
- package/dist/runtime/runtime/components/news/Header.vue +7 -0
- package/dist/runtime/runtime/components/news/RelatedItem.vue +44 -0
- package/dist/runtime/runtime/components/news/RowsItem.vue +182 -0
- package/dist/runtime/runtime/components/news/View.vue +174 -0
- package/dist/runtime/runtime/components/people/DenseItem.vue +60 -0
- package/dist/runtime/runtime/components/people/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/people/RelatedItem.vue +41 -0
- package/dist/runtime/runtime/components/people/RowsItem.vue +93 -0
- package/dist/runtime/runtime/components/people/View.vue +172 -0
- package/dist/runtime/runtime/components/projects/DenseItem.vue +77 -0
- package/dist/runtime/runtime/components/projects/ExpandedItem.vue +12 -0
- package/dist/runtime/runtime/components/projects/RelatedItem.vue +44 -0
- package/dist/runtime/runtime/components/projects/RowsItem.vue +103 -0
- package/dist/runtime/runtime/components/projects/View.vue +130 -0
- package/dist/runtime/runtime/components/publications/DenseItem.vue +89 -0
- package/dist/runtime/runtime/components/publications/RelatedItem.vue +44 -0
- package/dist/runtime/runtime/components/publications/RowsItem.vue +105 -0
- package/dist/runtime/runtime/components/publications/View.vue +132 -0
- package/dist/runtime/runtime/components/tags/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/tags/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/tags/View.vue +20 -0
- package/dist/runtime/runtime/components/users/ExpandedItem.vue +14 -0
- package/dist/runtime/runtime/components/users/RowsItem.vue +12 -0
- package/dist/runtime/runtime/components/users/View.vue +20 -0
- package/dist/runtime/runtime/composables/useFetchItem.d.ts +6 -0
- package/dist/runtime/runtime/composables/useFetchItem.js +49 -0
- package/dist/runtime/runtime/composables/useIcons.d.ts +1 -0
- package/dist/runtime/runtime/composables/useIcons.js +30 -0
- package/dist/runtime/runtime/composables/useUtils.d.ts +12 -0
- package/dist/runtime/runtime/composables/useUtils.js +48 -0
- package/dist/runtime/runtime/graphql/buildFiltersValues.gql +35 -0
- package/dist/runtime/runtime/graphql/item/action.gql +22 -0
- package/dist/runtime/runtime/graphql/item/affiliations.gql +37 -0
- package/dist/runtime/runtime/graphql/item/apps.gql +34 -0
- package/dist/runtime/runtime/graphql/item/disciplines.gql +17 -0
- package/dist/runtime/runtime/graphql/item/events.gql +120 -0
- package/dist/runtime/runtime/graphql/item/fellowships.gql +164 -0
- package/dist/runtime/runtime/graphql/item/files.gql +25 -0
- package/dist/runtime/runtime/graphql/item/mailing.gql +10 -0
- package/dist/runtime/runtime/graphql/item/news.gql +129 -0
- package/dist/runtime/runtime/graphql/item/people.gql +174 -0
- package/dist/runtime/runtime/graphql/item/projects.gql +171 -0
- package/dist/runtime/runtime/graphql/item/publications.gql +169 -0
- package/dist/runtime/runtime/graphql/item/tags.gql +13 -0
- package/dist/runtime/runtime/graphql/item/users.gql +14 -0
- package/dist/runtime/runtime/graphql/list/action.gql +31 -0
- package/dist/runtime/runtime/graphql/list/affiliations.gql +42 -0
- package/dist/runtime/runtime/graphql/list/apps.gql +42 -0
- package/dist/runtime/runtime/graphql/list/disciplines.gql +22 -0
- package/dist/runtime/runtime/graphql/list/events.gql +44 -0
- package/dist/runtime/runtime/graphql/list/fellowships.gql +53 -0
- package/dist/runtime/runtime/graphql/list/files.gql +37 -0
- package/dist/runtime/runtime/graphql/list/mailing.gql +22 -0
- package/dist/runtime/runtime/graphql/list/news.gql +40 -0
- package/dist/runtime/runtime/graphql/list/people.gql +50 -0
- package/dist/runtime/runtime/graphql/list/projects.gql +37 -0
- package/dist/runtime/runtime/graphql/list/publications.gql +38 -0
- package/dist/runtime/runtime/graphql/list/search.gql +161 -0
- package/dist/runtime/runtime/graphql/list/tags.gql +22 -0
- package/dist/runtime/runtime/graphql/list/users.gql +38 -0
- package/dist/runtime/runtime/graphql/login.gql +0 -0
- package/dist/runtime/runtime/plugins/pinia.d.ts +2 -0
- package/dist/runtime/runtime/plugins/pinia.js +134 -0
- package/dist/runtime/runtime/plugins/vuetify.d.ts +2 -0
- package/dist/runtime/runtime/plugins/vuetify.js +21 -0
- package/dist/runtime/runtime/public/default.png +0 -0
- package/dist/runtime/runtime/public/filters.json +72 -0
- package/dist/runtime/runtime/server/tsconfig.json +3 -0
- package/dist/runtime/runtime/stores/factory.d.ts +25 -0
- package/dist/runtime/runtime/stores/factory.js +19 -0
- package/dist/runtime/runtime/stores/root.d.ts +60 -0
- package/dist/runtime/runtime/stores/root.js +315 -0
- package/dist/runtime/runtime/translations/en.json +350 -0
- package/dist/runtime/runtime/translations/fr.json +349 -0
- package/dist/runtime/runtime/types/imports.d.ts +13 -0
- package/dist/runtime/runtime/types/stores.d.ts +11 -0
- package/dist/runtime/translations/en.json +1 -1
- package/package.json +2 -2
- /package/dist/runtime/{components → runtime/components}/people/GroupBadges.vue +0 -0
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-btn-toggle
|
|
3
|
+
value="currentPage"
|
|
4
|
+
role="navigation"
|
|
5
|
+
aria-label="Pagination Navigation"
|
|
6
|
+
>
|
|
7
|
+
<!-- TODO: switch to page as route param -->
|
|
8
|
+
<v-btn
|
|
9
|
+
v-if="!(hidePrevNext && firstPageSelected())"
|
|
10
|
+
:disabled="firstPageSelected()"
|
|
11
|
+
min-width="35"
|
|
12
|
+
height="35"
|
|
13
|
+
width="35"
|
|
14
|
+
:tabindex="!hidePrevNext && firstPageSelected() ? -1 : 0"
|
|
15
|
+
aria-label="Previous Page"
|
|
16
|
+
nuxt
|
|
17
|
+
@click="updatePage(currentPage - 1)"
|
|
18
|
+
@keyup.enter="updatePage(currentPage - 1)"
|
|
19
|
+
>
|
|
20
|
+
<v-icon>mdi-chevron-left</v-icon>
|
|
21
|
+
</v-btn>
|
|
22
|
+
|
|
23
|
+
<template v-for="(page, index) in renderPages" :key="page.key">
|
|
24
|
+
<v-btn
|
|
25
|
+
v-if="page.isGap"
|
|
26
|
+
min-width="35"
|
|
27
|
+
height="35"
|
|
28
|
+
width="35"
|
|
29
|
+
icon
|
|
30
|
+
nuxt
|
|
31
|
+
@keyup.enter="updatePage(getGapPage(index))"
|
|
32
|
+
@click="updatePage(getGapPage(index))"
|
|
33
|
+
>
|
|
34
|
+
...
|
|
35
|
+
</v-btn>
|
|
36
|
+
<template v-else>
|
|
37
|
+
<v-btn
|
|
38
|
+
:class="{ 'active-page': !!page.current }"
|
|
39
|
+
tabindex="0"
|
|
40
|
+
outlined
|
|
41
|
+
min-width="35"
|
|
42
|
+
height="35"
|
|
43
|
+
tile
|
|
44
|
+
nuxt
|
|
45
|
+
:active="!!page.current"
|
|
46
|
+
:color="!!page.current ? 'white' : 'black'"
|
|
47
|
+
text
|
|
48
|
+
width="35"
|
|
49
|
+
:aria-current="!!page.current ? 'true' : 'false'"
|
|
50
|
+
:aria-label="
|
|
51
|
+
page.current
|
|
52
|
+
? `Current page, Page ${page.value}`
|
|
53
|
+
: `Goto Page ${page.value}`
|
|
54
|
+
"
|
|
55
|
+
@click="updatePage(page.value)"
|
|
56
|
+
@keyup.enter="updatePage(page.value)"
|
|
57
|
+
>
|
|
58
|
+
{{ page.value }}
|
|
59
|
+
</v-btn>
|
|
60
|
+
</template>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<v-btn
|
|
64
|
+
v-if="!(hidePrevNext && lastPageSelected())"
|
|
65
|
+
:tabindex="!hidePrevNext && lastPageSelected() ? -1 : 0"
|
|
66
|
+
:disabled="lastPageSelected()"
|
|
67
|
+
aria-label="Next Page"
|
|
68
|
+
min-width="35"
|
|
69
|
+
height="35"
|
|
70
|
+
width="35"
|
|
71
|
+
nuxt
|
|
72
|
+
@click="updatePage(currentPage + 1)"
|
|
73
|
+
@keyup.enter="updatePage(currentPage + 1)"
|
|
74
|
+
>
|
|
75
|
+
<v-icon>mdi-chevron-right</v-icon>
|
|
76
|
+
</v-btn>
|
|
77
|
+
</v-btn-toggle>
|
|
78
|
+
</template>
|
|
79
|
+
|
|
80
|
+
<script setup>
|
|
81
|
+
import { useRootStore } from "../../../stores/root";
|
|
82
|
+
import { useRoute, computed, useI18n } from "#imports";
|
|
83
|
+
const { locale } = useI18n();
|
|
84
|
+
const route = useRoute();
|
|
85
|
+
const rootStore = useRootStore();
|
|
86
|
+
const props = defineProps({
|
|
87
|
+
totalPages: {
|
|
88
|
+
type: Number,
|
|
89
|
+
required: true
|
|
90
|
+
},
|
|
91
|
+
currentPage: {
|
|
92
|
+
type: Number,
|
|
93
|
+
default: 1
|
|
94
|
+
},
|
|
95
|
+
pagePadding: {
|
|
96
|
+
type: Number,
|
|
97
|
+
default: 1,
|
|
98
|
+
validator: (value) => {
|
|
99
|
+
return value > 0;
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
pageGap: {
|
|
103
|
+
type: Number,
|
|
104
|
+
default: 2,
|
|
105
|
+
validator: (value) => {
|
|
106
|
+
return value > 0;
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
hidePrevNext: {
|
|
110
|
+
type: Boolean,
|
|
111
|
+
default: false
|
|
112
|
+
},
|
|
113
|
+
type: {
|
|
114
|
+
type: String,
|
|
115
|
+
default: "",
|
|
116
|
+
required: true
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
const renderPages = computed(() => {
|
|
120
|
+
const pages = [];
|
|
121
|
+
for (let pageIndex = 1; pageIndex <= props.totalPages; pageIndex++) {
|
|
122
|
+
if (pageIndex === props.currentPage || pageIndex < props.pageGap || pageIndex > props.totalPages - props.pageGap + 1) {
|
|
123
|
+
pages.push(createPage(pageIndex));
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
let minimum;
|
|
127
|
+
let maximum;
|
|
128
|
+
if (props.currentPage <= props.pageGap + props.pagePadding) {
|
|
129
|
+
minimum = props.pageGap + 1;
|
|
130
|
+
maximum = minimum + props.pagePadding * 2;
|
|
131
|
+
} else if (props.currentPage >= props.totalPages - props.pageGap - props.pagePadding) {
|
|
132
|
+
maximum = props.totalPages - props.pageGap;
|
|
133
|
+
minimum = maximum - props.pagePadding * 2;
|
|
134
|
+
} else {
|
|
135
|
+
minimum = props.currentPage - props.pagePadding;
|
|
136
|
+
maximum = props.currentPage + props.pagePadding;
|
|
137
|
+
}
|
|
138
|
+
if (pageIndex >= minimum && pageIndex <= props.currentPage || pageIndex >= props.currentPage && pageIndex <= maximum) {
|
|
139
|
+
pages.push(createPage(pageIndex));
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
if (pageIndex === props.pageGap) {
|
|
143
|
+
if (minimum > props.pageGap + 1 && props.currentPage > props.pageGap + props.pagePadding + 1) {
|
|
144
|
+
pages.push(createGap(pageIndex));
|
|
145
|
+
} else {
|
|
146
|
+
pages.push(createPage(pageIndex));
|
|
147
|
+
}
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (pageIndex === props.totalPages - props.pageGap + 1) {
|
|
151
|
+
if (maximum < props.totalPages - props.pageGap && props.currentPage < props.totalPages - props.pageGap - props.pagePadding) {
|
|
152
|
+
pages.push(createGap(pageIndex));
|
|
153
|
+
} else {
|
|
154
|
+
pages.push(createPage(pageIndex));
|
|
155
|
+
}
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return pages;
|
|
160
|
+
});
|
|
161
|
+
const createPage = (pageIndex) => {
|
|
162
|
+
return {
|
|
163
|
+
key: pageIndex,
|
|
164
|
+
current: props.currentPage === pageIndex,
|
|
165
|
+
value: pageIndex
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
const firstPageSelected = () => {
|
|
169
|
+
return props.currentPage === 1;
|
|
170
|
+
};
|
|
171
|
+
const lastPageSelected = () => {
|
|
172
|
+
return props.currentPage === props.totalPages || props.totalPages === 0;
|
|
173
|
+
};
|
|
174
|
+
const createGap = (pageIndex) => {
|
|
175
|
+
return {
|
|
176
|
+
key: pageIndex,
|
|
177
|
+
isGap: true
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
const emit = defineEmits(["update"]);
|
|
181
|
+
const updatePage = (page) => {
|
|
182
|
+
rootStore.updatePage({ page, type: props.type, lang: locale.value });
|
|
183
|
+
emit("update", page);
|
|
184
|
+
};
|
|
185
|
+
const getGapPage = (index) => {
|
|
186
|
+
return Math.floor(
|
|
187
|
+
renderPages.value[index - 1].key + ((renderPages.value[index + 1].key || props.totalPages) - renderPages.value[index - 1].key) / 2
|
|
188
|
+
);
|
|
189
|
+
};
|
|
190
|
+
</script>
|
|
191
|
+
|
|
192
|
+
<style>
|
|
193
|
+
.active-page{background-color:#000!important;color:#f5f5f5!important}
|
|
194
|
+
</style>
|
|
@@ -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>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<ListMoleculesHeader :type="type" />
|
|
3
|
+
<component :is="view">
|
|
4
|
+
<component
|
|
5
|
+
:is="itemTemplate"
|
|
6
|
+
v-for="(item, index) in items"
|
|
7
|
+
:key="index"
|
|
8
|
+
:item="item"
|
|
9
|
+
:index="index"
|
|
10
|
+
/>
|
|
11
|
+
</component>
|
|
12
|
+
<div class="text-center">
|
|
13
|
+
<ListMoleculesPagination
|
|
14
|
+
v-if="numberOfPages > 1"
|
|
15
|
+
:type="type"
|
|
16
|
+
color="black"
|
|
17
|
+
large
|
|
18
|
+
:current-page="page"
|
|
19
|
+
:total-pages="numberOfPages"
|
|
20
|
+
:page-padding="1"
|
|
21
|
+
:page-gap="2"
|
|
22
|
+
:hide-prev-next="false"
|
|
23
|
+
@update="onPageChange"
|
|
24
|
+
/>
|
|
25
|
+
</div>
|
|
26
|
+
</template>
|
|
27
|
+
|
|
28
|
+
<script setup>
|
|
29
|
+
import { useRootStore } from "../../../stores/root";
|
|
30
|
+
import { capitalize } from "../../../composables/useUtils";
|
|
31
|
+
import {
|
|
32
|
+
useNuxtApp,
|
|
33
|
+
resolveComponent,
|
|
34
|
+
computed,
|
|
35
|
+
onBeforeUnmount,
|
|
36
|
+
onMounted,
|
|
37
|
+
useI18n,
|
|
38
|
+
useRoute
|
|
39
|
+
} from "#imports";
|
|
40
|
+
const { $stores } = useNuxtApp();
|
|
41
|
+
const { locale } = useI18n();
|
|
42
|
+
const route = useRoute();
|
|
43
|
+
const rootStore = useRootStore();
|
|
44
|
+
const props = defineProps({
|
|
45
|
+
addBtn: {
|
|
46
|
+
type: Boolean,
|
|
47
|
+
required: false,
|
|
48
|
+
default: false
|
|
49
|
+
},
|
|
50
|
+
type: {
|
|
51
|
+
type: String,
|
|
52
|
+
default: "people",
|
|
53
|
+
required: true
|
|
54
|
+
},
|
|
55
|
+
layout: {
|
|
56
|
+
type: Object,
|
|
57
|
+
required: false,
|
|
58
|
+
default: () => {
|
|
59
|
+
return {
|
|
60
|
+
cols: 12,
|
|
61
|
+
xl: 12
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
pagination: {
|
|
66
|
+
type: Object,
|
|
67
|
+
required: false,
|
|
68
|
+
default: () => {
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
addButton: {
|
|
73
|
+
type: Boolean,
|
|
74
|
+
required: false,
|
|
75
|
+
default: false
|
|
76
|
+
},
|
|
77
|
+
items: [Object]
|
|
78
|
+
});
|
|
79
|
+
const view = computed(
|
|
80
|
+
() => props.customView ? resolveComponent("ListViews" + capitalize(props.customView)) : resolveComponent("ListViews" + capitalize($stores[props.type].view.name))
|
|
81
|
+
);
|
|
82
|
+
const itemTemplate = computed(
|
|
83
|
+
() => resolveComponent(
|
|
84
|
+
(capitalize(props.type) + capitalize($stores[props.type].view.name) + "Item").toString()
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
const numberOfPages = computed(() => $stores[props.type].numberOfPages);
|
|
88
|
+
const page = computed(() => +$stores[props.type].page);
|
|
89
|
+
const items = computed(() => $stores[props.type].items);
|
|
90
|
+
console.log("setup list");
|
|
91
|
+
onMounted(() => {
|
|
92
|
+
console.log("mounted list");
|
|
93
|
+
});
|
|
94
|
+
rootStore.loadRouteQuery(props.type);
|
|
95
|
+
try {
|
|
96
|
+
await rootStore.update(props.type, locale.value);
|
|
97
|
+
} catch (error) {
|
|
98
|
+
console.log("error fetching update list: ", error);
|
|
99
|
+
}
|
|
100
|
+
onBeforeUnmount(() => {
|
|
101
|
+
rootStore.resetState(props.type, locale.value);
|
|
102
|
+
});
|
|
103
|
+
const onPageChange = (newPage) => {
|
|
104
|
+
rootStore.updatePage({ page: newPage, type: props.type, lang: locale.value });
|
|
105
|
+
window.scrollTo({
|
|
106
|
+
top: 0,
|
|
107
|
+
behavior: "smooth"
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
</script>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
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>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<script setup>
|
|
28
|
+
import {
|
|
29
|
+
useNuxtApp,
|
|
30
|
+
useLocalePath,
|
|
31
|
+
onBeforeUnmount,
|
|
32
|
+
onMounted,
|
|
33
|
+
useI18n,
|
|
34
|
+
useAppConfig,
|
|
35
|
+
ref,
|
|
36
|
+
computed
|
|
37
|
+
} from "#imports";
|
|
38
|
+
const localePath = useLocalePath();
|
|
39
|
+
defineOptions({
|
|
40
|
+
name: "SearchResults"
|
|
41
|
+
});
|
|
42
|
+
const { $rootStore } = useNuxtApp();
|
|
43
|
+
const appConfig = useAppConfig();
|
|
44
|
+
const { locale } = useI18n();
|
|
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
|
+
});
|
|
52
|
+
});
|
|
53
|
+
onMounted(async () => {
|
|
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
|
+
}
|
|
65
|
+
});
|
|
66
|
+
onBeforeUnmount(() => {
|
|
67
|
+
});
|
|
68
|
+
</script>
|
|
69
|
+
|
|
70
|
+
<style scoped>
|
|
71
|
+
.results-container{display:flex;flex-direction:column;gap:8px;margin-left:8px}
|
|
72
|
+
</style>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="slider-container">
|
|
3
|
+
<!-- Header with counter and navigation -->
|
|
4
|
+
<div class="slider-header">
|
|
5
|
+
<div class="slide-counter">
|
|
6
|
+
{{ activeSlideIndex + 1 }}/{{ items.length }}
|
|
7
|
+
</div>
|
|
8
|
+
<div class="navigation-controls">
|
|
9
|
+
<button
|
|
10
|
+
:disabled="!canGoBack"
|
|
11
|
+
class="nav-button nav-prev"
|
|
12
|
+
@click="goToSlide(activeSlideIndex - 1)"
|
|
13
|
+
>
|
|
14
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
15
|
+
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
|
|
16
|
+
</svg>
|
|
17
|
+
</button>
|
|
18
|
+
<button
|
|
19
|
+
:disabled="!canGoForward"
|
|
20
|
+
class="nav-button nav-next"
|
|
21
|
+
@click="goToSlide(activeSlideIndex + 1)"
|
|
22
|
+
>
|
|
23
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
|
24
|
+
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
|
|
25
|
+
</svg>
|
|
26
|
+
</button>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<!-- Slider container -->
|
|
31
|
+
<div ref="sliderRef" class="slider-viewport" @scroll="handleScroll">
|
|
32
|
+
<div
|
|
33
|
+
class="slider-track"
|
|
34
|
+
:style="{ transform: `translateX(${offsetX}px)` }"
|
|
35
|
+
>
|
|
36
|
+
<div
|
|
37
|
+
v-for="(item, index) in items"
|
|
38
|
+
:key="index"
|
|
39
|
+
class="slide-item"
|
|
40
|
+
:class="{
|
|
41
|
+
'slide-visible': isSlideVisible(index),
|
|
42
|
+
'slide-entering': isSlideEntering(index),
|
|
43
|
+
'slide-exiting': isSlideExiting(index),
|
|
44
|
+
}"
|
|
45
|
+
:style="getSlideStyle(index)"
|
|
46
|
+
>
|
|
47
|
+
<component :is="itemComponent" :item="item" :index="index" />
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script setup>
|
|
55
|
+
import { ref, computed, onMounted, onBeforeUnmount, nextTick, watch } from "vue";
|
|
56
|
+
import { useRootStore } from "../../../stores/root";
|
|
57
|
+
import { capitalize } from "../../../composables/useUtils";
|
|
58
|
+
import { useNuxtApp, useI18n } from "#imports";
|
|
59
|
+
defineOptions({ name: "ListOrganismsSlider" });
|
|
60
|
+
const { $stores } = useNuxtApp();
|
|
61
|
+
const { locale } = useI18n();
|
|
62
|
+
const rootStore = useRootStore();
|
|
63
|
+
const props = defineProps({
|
|
64
|
+
type: {
|
|
65
|
+
type: String,
|
|
66
|
+
required: true
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
const items = computed(() => $stores[props.type].items);
|
|
70
|
+
const sliderRef = ref(null);
|
|
71
|
+
const activeSlideIndex = ref(0);
|
|
72
|
+
const offsetX = ref(0);
|
|
73
|
+
const containerWidth = ref(0);
|
|
74
|
+
const slideWidth = ref(0);
|
|
75
|
+
const slidesPerView = ref(1);
|
|
76
|
+
const itemComponent = computed(() => {
|
|
77
|
+
return capitalize(props.type) + "SlidingItem";
|
|
78
|
+
});
|
|
79
|
+
const totalSlides = computed(() => items.value.length);
|
|
80
|
+
const canGoBack = computed(() => activeSlideIndex.value > 0);
|
|
81
|
+
const canGoForward = computed(() => {
|
|
82
|
+
const maxIndex = Math.max(0, totalSlides.value - slidesPerView.value);
|
|
83
|
+
return activeSlideIndex.value < maxIndex;
|
|
84
|
+
});
|
|
85
|
+
const visibleSlideIndices = computed(() => {
|
|
86
|
+
const start = activeSlideIndex.value;
|
|
87
|
+
const end = Math.min(start + slidesPerView.value, totalSlides.value);
|
|
88
|
+
return Array.from({ length: end - start }, (_, i) => start + i);
|
|
89
|
+
});
|
|
90
|
+
const calculateDimensions = () => {
|
|
91
|
+
if (!sliderRef.value) return;
|
|
92
|
+
containerWidth.value = sliderRef.value.offsetWidth;
|
|
93
|
+
const breakpoints = {
|
|
94
|
+
320: { slidesPerView: 1.2, spacing: 20 },
|
|
95
|
+
640: { slidesPerView: 2, spacing: 24 },
|
|
96
|
+
960: { slidesPerView: 2.5, spacing: 28 },
|
|
97
|
+
1280: { slidesPerView: 3, spacing: 32 },
|
|
98
|
+
1600: { slidesPerView: 3.5, spacing: 36 }
|
|
99
|
+
};
|
|
100
|
+
const currentBreakpoint = Object.entries(breakpoints).reverse().find(([width]) => window.innerWidth >= Number.parseInt(width));
|
|
101
|
+
const config = currentBreakpoint ? currentBreakpoint[1] : breakpoints[320];
|
|
102
|
+
slidesPerView.value = Math.floor(config.slidesPerView);
|
|
103
|
+
slideWidth.value = (containerWidth.value - config.spacing * (config.slidesPerView - 1)) / config.slidesPerView;
|
|
104
|
+
};
|
|
105
|
+
const isSlideVisible = (index) => {
|
|
106
|
+
return visibleSlideIndices.value.includes(index);
|
|
107
|
+
};
|
|
108
|
+
const isSlideEntering = (index) => {
|
|
109
|
+
const rightmostVisible = Math.max(...visibleSlideIndices.value);
|
|
110
|
+
return index === rightmostVisible && index > activeSlideIndex.value;
|
|
111
|
+
};
|
|
112
|
+
const isSlideExiting = (index) => {
|
|
113
|
+
const leftmostVisible = Math.min(...visibleSlideIndices.value);
|
|
114
|
+
return index === leftmostVisible && index < activeSlideIndex.value;
|
|
115
|
+
};
|
|
116
|
+
const getSlideStyle = (index) => {
|
|
117
|
+
const baseStyles = {
|
|
118
|
+
width: `${slideWidth.value}px`,
|
|
119
|
+
opacity: isSlideVisible(index) ? 1 : 0,
|
|
120
|
+
transform: `translateX(${index * (slideWidth.value + 24)}px)`,
|
|
121
|
+
transition: "all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94)"
|
|
122
|
+
};
|
|
123
|
+
if (isSlideEntering(index)) {
|
|
124
|
+
baseStyles.transform += " translateX(20px)";
|
|
125
|
+
baseStyles.opacity = 0.8;
|
|
126
|
+
}
|
|
127
|
+
if (isSlideExiting(index)) {
|
|
128
|
+
baseStyles.transform += " translateX(-20px)";
|
|
129
|
+
baseStyles.opacity = 0.6;
|
|
130
|
+
}
|
|
131
|
+
return baseStyles;
|
|
132
|
+
};
|
|
133
|
+
const goToSlide = (targetIndex) => {
|
|
134
|
+
const maxIndex = Math.max(0, totalSlides.value - slidesPerView.value);
|
|
135
|
+
const newIndex = Math.max(0, Math.min(targetIndex, maxIndex));
|
|
136
|
+
if (newIndex === activeSlideIndex.value) return;
|
|
137
|
+
activeSlideIndex.value = newIndex;
|
|
138
|
+
updateSliderPosition();
|
|
139
|
+
};
|
|
140
|
+
const updateSliderPosition = () => {
|
|
141
|
+
const newOffset = -(activeSlideIndex.value * (slideWidth.value + 24));
|
|
142
|
+
const visualOffset = activeSlideIndex.value > 0 ? -40 : 0;
|
|
143
|
+
offsetX.value = newOffset + visualOffset;
|
|
144
|
+
};
|
|
145
|
+
const handleScroll = () => {
|
|
146
|
+
};
|
|
147
|
+
const handleResize = () => {
|
|
148
|
+
calculateDimensions();
|
|
149
|
+
updateSliderPosition();
|
|
150
|
+
};
|
|
151
|
+
onMounted(async () => {
|
|
152
|
+
await nextTick();
|
|
153
|
+
calculateDimensions();
|
|
154
|
+
updateSliderPosition();
|
|
155
|
+
window.addEventListener("resize", handleResize);
|
|
156
|
+
});
|
|
157
|
+
onBeforeUnmount(() => {
|
|
158
|
+
window.removeEventListener("resize", handleResize);
|
|
159
|
+
rootStore.resetState(props.type, locale.value);
|
|
160
|
+
});
|
|
161
|
+
watch(
|
|
162
|
+
() => items.value,
|
|
163
|
+
() => {
|
|
164
|
+
nextTick(() => {
|
|
165
|
+
calculateDimensions();
|
|
166
|
+
updateSliderPosition();
|
|
167
|
+
});
|
|
168
|
+
},
|
|
169
|
+
{ deep: true }
|
|
170
|
+
);
|
|
171
|
+
try {
|
|
172
|
+
await rootStore.update(props.type, locale.value);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.log("error fetching update list: ", error);
|
|
175
|
+
}
|
|
176
|
+
</script>
|
|
177
|
+
|
|
178
|
+
<style scoped>
|
|
179
|
+
.slider-container{overflow:hidden;position:relative;width:100%}.slider-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:24px;padding:0 20px}.slide-counter{color:#666;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,sans-serif;font-size:14px;font-weight:500}.navigation-controls{display:flex;gap:8px}.nav-button{align-items:center;background:#fff;border:1px solid #e0e0e0;border-radius:4px;color:#333;cursor:pointer;display:flex;height:40px;justify-content:center;transition:all .2s ease;width:40px}.nav-button:hover:not(:disabled){background:#f5f5f5;border-color:#d0d0d0}.nav-button:disabled{color:#999;cursor:not-allowed;opacity:.4}.slider-viewport{overflow:hidden;padding:0 20px;position:relative;width:100%}.slider-track{display:flex;transition:transform .4s cubic-bezier(.25,.46,.45,.94);will-change:transform}.slide-item{flex-shrink:0;margin-right:24px;transform-origin:center;will-change:transform,opacity}.slide-item:last-child{margin-right:0}.slide-entering{animation:slideInFromRight .4s cubic-bezier(.25,.46,.45,.94)}.slide-exiting{animation:slideOutToLeft .4s cubic-bezier(.25,.46,.45,.94)}@keyframes slideInFromRight{0%{opacity:0;transform:translateX(40px)}to{opacity:1;transform:translateX(0)}}@keyframes slideOutToLeft{0%{opacity:1;transform:translateX(0)}to{opacity:.6;transform:translateX(-40px)}}@media (max-width:640px){.slider-header{margin-bottom:20px;padding:0 16px}.slider-viewport{padding:0 16px}.slide-item{margin-right:16px}}@media (max-width:480px){.slide-counter{font-size:12px}.nav-button{height:36px;width:36px}.nav-button svg{height:20px;width:20px}}
|
|
180
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="my-6 ml-2 pb-6">
|
|
3
|
+
<slot>
|
|
4
|
+
<!-- fallback content -->
|
|
5
|
+
Dense view
|
|
6
|
+
</slot>
|
|
7
|
+
</section>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
section{display:table;width:100%}section>*{display:table-row}section .v-col.dense{display:table-cell;vertical-align:middle}
|
|
12
|
+
</style>
|