@paris-ias/list 1.0.4 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/module.ts +119 -0
  2. package/dist/runtime/components/events/Badges.vue +73 -0
  3. package/dist/runtime/components/events/DateTimePlace.vue +77 -0
  4. package/dist/runtime/components/events/DenseItem.vue +40 -0
  5. package/dist/runtime/components/events/ExpandedItem.vue +11 -0
  6. package/dist/runtime/components/events/ListContainer.vue +41 -0
  7. package/dist/runtime/components/events/RegisterModal.vue +51 -0
  8. package/dist/runtime/components/events/RelatedItem.vue +44 -0
  9. package/dist/runtime/components/events/RowsItem.vue +114 -0
  10. package/dist/runtime/components/events/View.vue +333 -0
  11. package/dist/runtime/components/fellowships/Badges.vue +48 -0
  12. package/dist/runtime/components/fellowships/DenseItem.vue +39 -0
  13. package/dist/runtime/components/fellowships/ExpandedItem.vue +7 -0
  14. package/dist/runtime/components/fellowships/RegisterModal.vue +41 -0
  15. package/dist/runtime/components/fellowships/RowsItem.vue +61 -0
  16. package/dist/runtime/components/fellowships/View.vue +210 -0
  17. package/dist/runtime/components/list/atoms/FiltersMenu.vue +46 -0
  18. package/dist/runtime/components/list/atoms/SearchInput.vue +129 -0
  19. package/dist/runtime/components/list/atoms/SearchItem.vue +59 -0
  20. package/dist/runtime/components/list/atoms/SearchString.vue +161 -0
  21. package/dist/runtime/components/list/atoms/SortMenu.vue +97 -0
  22. package/dist/runtime/components/list/atoms/ViewMenu.vue +71 -0
  23. package/dist/runtime/components/list/inputs/AutoComplete.vue +22 -0
  24. package/dist/runtime/components/list/inputs/BooleanSwitch.vue +18 -0
  25. package/dist/runtime/components/list/inputs/Checkbox.vue +21 -0
  26. package/dist/runtime/components/list/inputs/Select.vue +25 -0
  27. package/dist/runtime/components/list/molecules/Filters.vue +97 -0
  28. package/dist/runtime/components/list/molecules/Header.vue +47 -0
  29. package/dist/runtime/components/list/molecules/Pagination.vue +243 -0
  30. package/dist/runtime/components/list/organisms/List.vue +92 -0
  31. package/dist/runtime/components/list/views/Dense.vue +25 -0
  32. package/dist/runtime/components/list/views/Expanded.vue +10 -0
  33. package/dist/runtime/components/list/views/Grid.vue +13 -0
  34. package/dist/runtime/components/list/views/Rows.vue +13 -0
  35. package/dist/runtime/components/list/views/Table.vue +13 -0
  36. package/dist/runtime/components/misc/atoms/CountUp.vue +198 -0
  37. package/dist/runtime/components/misc/atoms/DateStamp.vue +104 -0
  38. package/dist/runtime/components/misc/atoms/ImageContainer.vue +105 -0
  39. package/dist/runtime/components/misc/atoms/ShareMenu.vue +60 -0
  40. package/dist/runtime/components/misc/atoms/Socials.vue +127 -0
  41. package/dist/runtime/components/misc/molecules/ChipContainer.vue +35 -0
  42. package/dist/runtime/components/misc/molecules/Related.vue +41 -0
  43. package/dist/runtime/components/misc/molecules/RelatedItems.vue +29 -0
  44. package/dist/runtime/components/misc/molecules/SearchItem.vue +26 -0
  45. package/dist/runtime/components/news/DenseItem.vue +62 -0
  46. package/dist/runtime/components/news/ExpandedItem.vue +153 -0
  47. package/dist/runtime/components/news/Header.vue +9 -0
  48. package/dist/runtime/components/news/RelatedItem.vue +44 -0
  49. package/dist/runtime/components/news/RowsItem.vue +160 -0
  50. package/dist/runtime/components/news/View.vue +190 -0
  51. package/dist/runtime/components/people/DenseItem.vue +37 -0
  52. package/dist/runtime/components/people/ExpandedItem.vue +16 -0
  53. package/dist/runtime/components/people/GroupBadges.vue +56 -0
  54. package/dist/runtime/components/people/RelatedItem.vue +41 -0
  55. package/dist/runtime/components/people/RowsItem.vue +95 -0
  56. package/dist/runtime/components/people/View.vue +162 -0
  57. package/dist/runtime/components/projects/ExpandedItem.vue +14 -0
  58. package/dist/runtime/components/projects/RelatedItem.vue +44 -0
  59. package/dist/runtime/components/projects/RowsItem.vue +106 -0
  60. package/dist/runtime/components/projects/View.vue +131 -0
  61. package/dist/runtime/components/publications/RelatedItem.vue +44 -0
  62. package/dist/runtime/components/publications/RowsItem.vue +105 -0
  63. package/dist/runtime/components/publications/View.vue +139 -0
  64. package/dist/runtime/composables/useFetchItem.ts +64 -0
  65. package/dist/runtime/composables/useIcons.ts +30 -0
  66. package/dist/runtime/composables/useUtils.ts +75 -0
  67. package/dist/runtime/graphql/queries/buildFiltersValues.gql +35 -0
  68. package/dist/runtime/graphql/queries/item/action.gql +0 -0
  69. package/dist/runtime/graphql/queries/item/apps.gql +0 -0
  70. package/dist/runtime/graphql/queries/item/events.gql +120 -0
  71. package/dist/runtime/graphql/queries/item/fellowships.gql +164 -0
  72. package/dist/runtime/graphql/queries/item/news.gql +129 -0
  73. package/dist/runtime/graphql/queries/item/people.gql +174 -0
  74. package/dist/runtime/graphql/queries/item/projects.gql +171 -0
  75. package/dist/runtime/graphql/queries/item/publications.gql +169 -0
  76. package/dist/runtime/graphql/queries/item/users.gql +0 -0
  77. package/dist/runtime/graphql/queries/list/action.gql +0 -0
  78. package/dist/runtime/graphql/queries/list/apps.gql +32 -0
  79. package/dist/runtime/graphql/queries/list/events.gql +44 -0
  80. package/dist/runtime/graphql/queries/list/fellowships.gql +53 -0
  81. package/dist/runtime/graphql/queries/list/news.gql +39 -0
  82. package/dist/runtime/graphql/queries/list/people.gql +49 -0
  83. package/dist/runtime/graphql/queries/list/projects.gql +37 -0
  84. package/dist/runtime/graphql/queries/list/publications.gql +37 -0
  85. package/dist/runtime/graphql/queries/list/search.gql +148 -0
  86. package/dist/runtime/graphql/queries/list/users.gql +32 -0
  87. package/dist/runtime/graphql/queries/login.gql +0 -0
  88. package/dist/runtime/plugins/pinia.ts +88 -0
  89. package/dist/runtime/plugins/vuetify.js +21 -0
  90. package/dist/runtime/stores/factory.ts +18 -0
  91. package/dist/runtime/stores/root.ts +353 -0
  92. package/dist/runtime/translations/en.json +436 -0
  93. package/dist/runtime/translations/fr.json +429 -0
  94. package/dist/runtime/types/imports.d.ts +13 -0
  95. package/dist/runtime/types/stores.d.ts +11 -0
  96. package/example/.env.example +3 -0
  97. package/example/nuxt.config.ts +19 -0
  98. package/example/pages/index.vue +27 -0
  99. package/package.json +8 -17
@@ -0,0 +1,71 @@
1
+ <template>
2
+ <v-menu>
3
+ <template #activator="{ props: menu }">
4
+ <v-tooltip location="top">
5
+ <template #activator="{ props: tooltip }">
6
+ <v-btn
7
+ x-large
8
+ tile
9
+ flat
10
+ :icon="'mdi-' + current?.icon || defaultView?.icon"
11
+ :class="{
12
+ 'mt-3': isXsDisplay,
13
+ }"
14
+ v-bind="mergeProps(menu, tooltip)"
15
+ />
16
+ </template>
17
+ <div
18
+ v-html="
19
+ $t('list.view-mode') +
20
+ $t('list.' + current.name || defaultView.name)
21
+ "
22
+ />
23
+ </v-tooltip>
24
+ </template>
25
+ <v-list density="compact">
26
+ <v-list-item
27
+ v-for="(value, key, index) in items"
28
+ :key="index"
29
+ @click="updateView(value.name || key)"
30
+ >
31
+ <template #prepend>
32
+ <v-icon>mdi-{{ value.icon }}</v-icon>
33
+ </template>
34
+ <v-list-item-title>{{
35
+ $t("list." + (value.name || key))
36
+ }}</v-list-item-title>
37
+ </v-list-item>
38
+ </v-list>
39
+ </v-menu>
40
+ </template>
41
+
42
+ <script setup>
43
+ import { useRootStore } from "../../../stores/root"
44
+ import { mergeProps } from "vue"
45
+ import { useDisplay } from "vuetify"
46
+ const { $stores } = useNuxtApp()
47
+
48
+ const props = defineProps({
49
+ type: {
50
+ type: String,
51
+ default: "articles",
52
+ required: true,
53
+ },
54
+ })
55
+ const { xs: isXsDisplay } = useDisplay()
56
+
57
+ const rootStore = useRootStore()
58
+ const items = ref($stores[props.type].views)
59
+
60
+ const current = ref($stores[props.type].view)
61
+
62
+ const updateView = async (value) => {
63
+ await rootStore.updateView({ value, type: props.type })
64
+ }
65
+
66
+ onMounted(() => {
67
+ // Add any logic needed on component mount
68
+ })
69
+ </script>
70
+
71
+ <style lang="scss"></style>
@@ -0,0 +1,22 @@
1
+ <template>
2
+ <v-autocomplete
3
+ v-model="val"
4
+ :items="props.items"
5
+ :multiple="$stores[type].filters[name]?.multiple || false"
6
+ />
7
+ </template>
8
+ <script setup>
9
+ import { useRootStore } from "../../../stores/root"
10
+ const rootStore = useRootStore()
11
+ const { $stores } = useNuxtApp()
12
+ const props = defineProps(["type", "items", "name"])
13
+ const val = computed({
14
+ get() {
15
+ return $stores[props.type].filters[props.name]?.value || []
16
+ },
17
+ set(value) {
18
+ return rootStore.updateFilter(props.name, value, props.type)
19
+ },
20
+ })
21
+ </script>
22
+ <style lang="scss"></style>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <v-switch v-model="val" />
3
+ </template>
4
+ <script setup>
5
+ import { useRootStore } from "../../../stores/root"
6
+ const rootStore = useRootStore()
7
+ const props = defineProps(["type", "items", "name"])
8
+ const { $stores } = useNuxtApp()
9
+ const val = computed({
10
+ get() {
11
+ return $stores[props.type].filters[props.name]?.value
12
+ },
13
+ set(value) {
14
+ rootStore.updateFilter(props.name, value, props.type)
15
+ },
16
+ })
17
+ </script>
18
+ <style lang="scss"></style>
@@ -0,0 +1,21 @@
1
+ <template>
2
+ <v-checkbox v-model="val" />
3
+ </template>
4
+ <script setup>
5
+ import { useRootStore } from "../../../stores/root"
6
+ const rootStore = useRootStore()
7
+ const props = defineProps(["type", "items", "name"])
8
+ const { $stores } = useNuxtApp()
9
+ const val = computed({
10
+ get() {
11
+ return $stores[props.type].filters[props.name]?.value
12
+ },
13
+ set(value) {
14
+ rootStore.updateFilter(props.name, value, props.type)
15
+ },
16
+ })
17
+ onMounted(() => {
18
+ console.log(props.data)
19
+ })
20
+ </script>
21
+ <style lang="scss"></style>
@@ -0,0 +1,25 @@
1
+ <template>
2
+ <v-select
3
+ v-model="val"
4
+ :items="props.items"
5
+ :multiple="$stores[type].filters[name]?.multiple || false"
6
+ />
7
+ </template>
8
+ <script setup>
9
+ import { useRootStore } from "../../../stores/root"
10
+ const rootStore = useRootStore()
11
+ const { $stores } = useNuxtApp()
12
+ const props = defineProps(["type", "items", "name"])
13
+ const val = computed({
14
+ get() {
15
+ return $stores[props.type].filters[props.name]?.value || []
16
+ },
17
+ set(value) {
18
+ rootStore.updateFilter(props.name, value, props.type)
19
+ },
20
+ })
21
+ onMounted(() => {
22
+ console.log(props)
23
+ })
24
+ </script>
25
+ <style lang="scss"></style>
@@ -0,0 +1,97 @@
1
+ <template>
2
+ <v-row>
3
+ <template v-for="filterItem in Object.keys($stores[type].filters)">
4
+ <v-col v-if="computeVisibility(filterItem)" cols="12" sm="6" md="4">
5
+ <component
6
+ :is="ComponentName(filterItem)"
7
+ tile
8
+ :name="filterItem"
9
+ hide-details
10
+ :filter="true"
11
+ :dense="smAndDown"
12
+ :items="getItems(filterItem)"
13
+ clearable
14
+ :label="$t('list.filters.' + type + '.' + filterItem + '.label')"
15
+ min-height="56"
16
+ variant="outlined"
17
+ :loading="$stores[type].loading"
18
+ :type="type"
19
+ color="black"
20
+ style="min-width: 150px"
21
+ class="transition-swing pb-1"
22
+ />
23
+ <!-- <template
24
+ v-else
25
+ v-for="filterItem in Object.keys(rootStore[type].list.filters).slice()"
26
+ >
27
+ <div v-if="computeVisibility(filterItem)">
28
+ {{ filterItem }}
29
+ </div>
30
+ </template> -->
31
+ </v-col>
32
+ </template></v-row
33
+ >
34
+ </template>
35
+
36
+ <script setup>
37
+ import { useRootStore } from "../../../stores/root"
38
+ import { useDisplay } from "vuetify"
39
+ const { smAndDown } = useDisplay()
40
+ const i18n = useI18n()
41
+ const { locale, messages } = useI18n()
42
+ const { $stores } = useNuxtApp()
43
+ const rootStore = useRootStore()
44
+ const props = defineProps(["type", "expanded"])
45
+
46
+ const ComponentName = (name) => {
47
+ return resolveComponent(
48
+ "ListInputs" + capitalize($stores[props.type].filters[name].type)
49
+ )
50
+ }
51
+ const getItems = (name) => {
52
+ if ($stores[props.type].filters[name].type === "Checkbox") {
53
+ return []
54
+ }
55
+ if (
56
+ messages.value[locale.value].list.filters[props.type][name] === undefined
57
+ ) {
58
+ console.log("name not found, no item for this filmter: ", name)
59
+ return []
60
+ }
61
+ // TODO replace with package based values
62
+ return Object.keys(
63
+ messages.value[locale.value].list.filters[props.type][name]
64
+ )
65
+ .filter((key) => key !== "label")
66
+ .map((item) => ({
67
+ title: i18n.t(`list.filters.${props.type}.${name}.${item}`),
68
+ value: item,
69
+ }))
70
+ }
71
+ onMounted(() => {
72
+ rootStore.loadRouteQuery(props.type)
73
+ })
74
+
75
+ const computeVisibility = (filterItem) => {
76
+ return (
77
+ // if anything is set in the visibility key
78
+ !$stores[props.type].filters[filterItem].visibility ||
79
+ $stores[props.type].filters[filterItem].visibility?.default ||
80
+ $stores[props.type].filters[filterItem].visibility?.switchIf.find(
81
+ //for each of the rules set in the switchIf key
82
+ (rule) => {
83
+ // we check if each of the condition are fulfilled
84
+ return Object.keys(rule).find((value, index, obj) => {
85
+ return $stores[props.type].filters[value].multiple
86
+ ? $stores[props.type].filters[value]?.value &&
87
+ $stores[props.type].filters[value]?.value.includes(rule[value])
88
+ : $stores[props.type].filters[value]?.value === rule[value]
89
+ })
90
+ }
91
+ )
92
+ )
93
+ return true
94
+ }
95
+ </script>
96
+
97
+ <style lang="scss" scoped></style>
@@ -0,0 +1,47 @@
1
+ <template>
2
+ <v-row no-gutters>
3
+ <v-col cols="12">
4
+ <!-- <v-btn
5
+ v-if="rootStore.addBtn"
6
+ x-large
7
+ :height="mdAndUp ? '56' : '40'"
8
+ outlined
9
+ :rounded="0"
10
+ color="primary"
11
+ :to="localePath($route.fullPath + '/create')"
12
+ >
13
+ <v-icon left>mdi-plus</v-icon>
14
+ {{ $t("new-x", { item: $tc("x-" + type, 1) }) }}
15
+ </v-btn> -->
16
+ <div class="d-flex">
17
+ <ListAtomsFiltersMenu
18
+ :open="filtersOpen"
19
+ @open="filtersOpen = $event"
20
+ />
21
+ <v-spacer />
22
+ <ListAtomsViewMenu :type="type" />
23
+ <ListAtomsSortMenu :type="type" />
24
+ </div>
25
+ <v-expand-transition>
26
+ <div v-if="filtersOpen" class="mb-7">
27
+ <ListMoleculesFilters :type="type" /></div
28
+ ></v-expand-transition>
29
+ <ListAtomsSearchInput :type="type" />
30
+ <ListAtomsSearchString :type="type" />
31
+ </v-col>
32
+ </v-row>
33
+ </template>
34
+
35
+ <script setup>
36
+ const route = useRoute()
37
+
38
+ const filtersOpen = ref(!!Object.keys(route.query)?.length)
39
+
40
+ const props = defineProps({
41
+ type: {
42
+ type: String,
43
+ required: false,
44
+ default: "",
45
+ },
46
+ })
47
+ </script>
@@ -0,0 +1,243 @@
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
+ :color="page.current ? 'white' : 'black'"
46
+ text
47
+ width="35"
48
+ :aria-current="page.current ? 'true' : 'false'"
49
+ :aria-label="
50
+ page.current
51
+ ? `Current page, Page ${page.value}`
52
+ : `Goto Page ${page.value}`
53
+ "
54
+ @click="updatePage(page.value)"
55
+ @keyup.enter="updatePage(page.value)"
56
+ >
57
+ {{ page.value }}
58
+ </v-btn>
59
+ </template>
60
+ </template>
61
+
62
+ <v-btn
63
+ v-if="!(hidePrevNext && lastPageSelected())"
64
+ :tabindex="!hidePrevNext && lastPageSelected() ? -1 : 0"
65
+ :disabled="lastPageSelected()"
66
+ aria-label="Next Page"
67
+ min-width="35"
68
+ height="35"
69
+ width="35"
70
+ nuxt
71
+ @click="updatePage(currentPage + 1)"
72
+ @keyup.enter="updatePage(currentPage + 1)"
73
+ >
74
+ <v-icon>mdi-chevron-right</v-icon>
75
+ </v-btn>
76
+ </v-btn-toggle>
77
+ </template>
78
+
79
+ <script setup>
80
+ import { computed } from "vue"
81
+ import { useRoute, useRouter } from "vue-router"
82
+ import { useRootStore } from "../../../stores/root"
83
+
84
+ const route = useRoute()
85
+ const router = useRouter()
86
+ const rootStore = useRootStore()
87
+
88
+ // THIS COMPONENT IS INITIALLY BASED ON https://github.com/ashwinkshenoy/vue-simple/tree/master/packages/vs-pagination
89
+ // AND MODIFIED TO FIT INTO OUR NEEDS (Vuetify + nuxt 3)
90
+ const props = defineProps({
91
+ totalPages: {
92
+ type: Number,
93
+ required: true,
94
+ },
95
+ currentPage: {
96
+ type: Number,
97
+ default: 1,
98
+ },
99
+ pagePadding: {
100
+ type: Number,
101
+ default: 1,
102
+ validator: (value) => {
103
+ return value > 0
104
+ },
105
+ },
106
+ pageGap: {
107
+ type: Number,
108
+ default: 2,
109
+ validator: (value) => {
110
+ return value > 0
111
+ },
112
+ },
113
+ hidePrevNext: {
114
+ type: Boolean,
115
+ default: false,
116
+ },
117
+ type: {
118
+ type: String,
119
+ default: "",
120
+ required: true,
121
+ },
122
+ })
123
+
124
+ const renderPages = computed(() => {
125
+ const pages = []
126
+ for (let pageIndex = 1; pageIndex <= props.totalPages; pageIndex++) {
127
+ if (
128
+ pageIndex === props.currentPage ||
129
+ pageIndex < props.pageGap ||
130
+ pageIndex > props.totalPages - props.pageGap + 1
131
+ ) {
132
+ pages.push(createPage(pageIndex))
133
+ continue
134
+ }
135
+
136
+ let minimum
137
+ let maximum
138
+
139
+ if (props.currentPage <= props.pageGap + props.pagePadding) {
140
+ minimum = props.pageGap + 1
141
+ maximum = minimum + props.pagePadding * 2
142
+ } else if (
143
+ props.currentPage >=
144
+ props.totalPages - props.pageGap - props.pagePadding
145
+ ) {
146
+ maximum = props.totalPages - props.pageGap
147
+ minimum = maximum - props.pagePadding * 2
148
+ } else {
149
+ minimum = props.currentPage - props.pagePadding
150
+ maximum = props.currentPage + props.pagePadding
151
+ }
152
+
153
+ if (
154
+ (pageIndex >= minimum && pageIndex <= props.currentPage) ||
155
+ (pageIndex >= props.currentPage && pageIndex <= maximum)
156
+ ) {
157
+ pages.push(createPage(pageIndex))
158
+ continue
159
+ }
160
+
161
+ if (pageIndex === props.pageGap) {
162
+ if (
163
+ minimum > props.pageGap + 1 &&
164
+ props.currentPage > props.pageGap + props.pagePadding + 1
165
+ ) {
166
+ pages.push(createGap(pageIndex))
167
+ } else {
168
+ pages.push(createPage(pageIndex))
169
+ }
170
+
171
+ continue
172
+ }
173
+
174
+ if (pageIndex === props.totalPages - props.pageGap + 1) {
175
+ if (
176
+ maximum < props.totalPages - props.pageGap &&
177
+ props.currentPage < props.totalPages - props.pageGap - props.pagePadding
178
+ ) {
179
+ pages.push(createGap(pageIndex))
180
+ } else {
181
+ pages.push(createPage(pageIndex))
182
+ }
183
+
184
+ continue
185
+ }
186
+ }
187
+
188
+ return pages
189
+ })
190
+
191
+ const createPage = (pageIndex) => {
192
+ return {
193
+ key: pageIndex,
194
+ current: props.currentPage === pageIndex,
195
+ value: pageIndex,
196
+ }
197
+ }
198
+
199
+ const firstPageSelected = () => {
200
+ return props.currentPage === 1
201
+ }
202
+
203
+ const lastPageSelected = () => {
204
+ return props.currentPage === props.totalPages || props.totalPages === 0
205
+ }
206
+
207
+ const createGap = (pageIndex) => {
208
+ return {
209
+ key: pageIndex,
210
+ isGap: true,
211
+ }
212
+ }
213
+
214
+ const updatePage = (page) => {
215
+ rootStore.updatePage({ page, type: props.type })
216
+ }
217
+
218
+ const getGapPage = (index) => {
219
+ return Math.floor(
220
+ renderPages.value[index - 1].key +
221
+ ((renderPages.value[index + 1].key || props.totalPages) -
222
+ renderPages.value[index - 1].key) /
223
+ 2
224
+ )
225
+ }
226
+ // Watch for changes in the route query and update the currentPage accordingly
227
+ watch(
228
+ () => route.query.page,
229
+ (newPage) => {
230
+ if (newPage) {
231
+ props.currentPage = parseInt(newPage, 10)
232
+ }
233
+ },
234
+ { immediate: true }
235
+ )
236
+ </script>
237
+
238
+ <style>
239
+ .active-page {
240
+ background-color: #000 !important;
241
+ color: #f5f5f5 !important;
242
+ }
243
+ </style>
@@ -0,0 +1,92 @@
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
+ />
24
+ </div>
25
+ </template>
26
+ <script setup>
27
+ import { useRootStore } from "../../../stores/root"
28
+ import { capitalize } from "../../../composables/useUtils"
29
+ const { $stores } = useNuxtApp()
30
+ const { locale } = useI18n()
31
+
32
+ const rootStore = useRootStore()
33
+ const props = defineProps({
34
+ addBtn: {
35
+ type: Boolean,
36
+ required: false,
37
+ default: false,
38
+ },
39
+ type: {
40
+ type: String,
41
+ default: "",
42
+ required: true,
43
+ },
44
+ layout: {
45
+ type: Object,
46
+ required: false,
47
+ default: () => {
48
+ return {
49
+ cols: 12,
50
+ xl: 12,
51
+ }
52
+ },
53
+ },
54
+ pagination: {
55
+ type: Object,
56
+ required: false,
57
+ default: () => {
58
+ return {}
59
+ },
60
+ },
61
+ addButton: {
62
+ type: Boolean,
63
+ required: false,
64
+ default: false,
65
+ },
66
+ items: [Object],
67
+ })
68
+
69
+ const view = computed(() =>
70
+ resolveComponent("ListViews" + capitalize($stores[props.type].view.name))
71
+ )
72
+ const itemTemplate = computed(() =>
73
+ resolveComponent(
74
+ (
75
+ capitalize(props.type) +
76
+ capitalize($stores[props.type].view.name) +
77
+ "Item"
78
+ ).toString()
79
+ )
80
+ )
81
+ const numberOfPages = computed(() => $stores[props.type].numberOfPages)
82
+
83
+ const page = computed(() => +$stores[props.type].page)
84
+
85
+ const items = computed(() => $stores[props.type].items)
86
+
87
+ try {
88
+ await rootStore.update(props.type, locale.value)
89
+ } catch (error) {
90
+ console.log("error fetching update list: ", error)
91
+ }
92
+ </script>
@@ -0,0 +1,25 @@
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
+ <script setup lang="ts"></script>
11
+ <style>
12
+ section {
13
+ display: table;
14
+ width: 100%;
15
+ }
16
+
17
+ section > * {
18
+ display: table-row;
19
+ }
20
+
21
+ section .v-col.dense {
22
+ display: table-cell;
23
+ vertical-align: middle;
24
+ }
25
+ </style>
@@ -0,0 +1,10 @@
1
+ <template>
2
+ <section>
3
+ <slot>
4
+ <!-- fallback content -->
5
+ Expanded view
6
+ </slot>
7
+ </section>
8
+ </template>
9
+
10
+ <script setup lang="ts"></script>
@@ -0,0 +1,13 @@
1
+ <template>
2
+ GRID DISPLAY
3
+ <template v-for="(item, index) in items" :key="index">
4
+ <slot name="data" :item="item" />
5
+ </template>
6
+ </template>
7
+
8
+ <script setup lang="ts">
9
+ const props = defineProps({
10
+ items: [Object],
11
+ type: String,
12
+ })
13
+ </script>