@paris-ias/list 1.3.3 → 1.3.5
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
|
@@ -155,7 +155,6 @@
|
|
|
155
155
|
<script setup>
|
|
156
156
|
import { useNuxtApp, ref, computed } from "#imports"
|
|
157
157
|
import { useDisplay } from "vuetify"
|
|
158
|
-
import { useRootStore } from "../../../stores/root"
|
|
159
158
|
|
|
160
159
|
const { $stores } = useNuxtApp()
|
|
161
160
|
const props = defineProps({
|
|
@@ -166,34 +165,16 @@ const props = defineProps({
|
|
|
166
165
|
})
|
|
167
166
|
const feminine = ref(["news", "publications", "people"].includes(props.type))
|
|
168
167
|
const { smAndDown: isSmAndDown } = useDisplay()
|
|
169
|
-
const rootStore = useRootStore()
|
|
170
168
|
|
|
171
|
-
|
|
169
|
+
// The skeleton must track the loading state ONLY. A previous extra clause
|
|
170
|
+
// (`isZeroTotal && (isAnySearchActive || itemsCount > 0)`) was permanently true
|
|
171
|
+
// after any search that returned zero results — so a completed empty search
|
|
172
|
+
// (e.g. "posten") stayed pinned in skeleton mode instead of showing the
|
|
173
|
+
// "0 items found searching for X" message, which is exactly the v-else branch
|
|
174
|
+
// below and the correct thing to render in that case.
|
|
175
|
+
const showSkeleton = computed(() =>
|
|
172
176
|
Boolean($stores[props.type] && $stores[props.type].loading),
|
|
173
177
|
)
|
|
174
|
-
const isTypeSearchActive = computed(() => {
|
|
175
|
-
const s = $stores[props.type]?.search
|
|
176
|
-
return Boolean(s && s.length)
|
|
177
|
-
})
|
|
178
|
-
const isGlobalSearchActive = computed(
|
|
179
|
-
() => typeof rootStore.search === "string" && rootStore.search.length > 0,
|
|
180
|
-
)
|
|
181
|
-
const isAnySearchActive = computed(
|
|
182
|
-
() => isTypeSearchActive.value || isGlobalSearchActive.value,
|
|
183
|
-
)
|
|
184
|
-
const isZeroTotal = computed(
|
|
185
|
-
() => Number($stores[props.type]?.total || 0) === 0,
|
|
186
|
-
)
|
|
187
|
-
const itemsCount = computed(() =>
|
|
188
|
-
Array.isArray($stores[props.type]?.items)
|
|
189
|
-
? $stores[props.type]?.items?.length || 0
|
|
190
|
-
: 0,
|
|
191
|
-
)
|
|
192
|
-
const showSkeleton = computed(
|
|
193
|
-
() =>
|
|
194
|
-
isLoading.value ||
|
|
195
|
-
(isZeroTotal.value && (isAnySearchActive.value || itemsCount.value > 0)),
|
|
196
|
-
)
|
|
197
178
|
</script>
|
|
198
179
|
|
|
199
180
|
<style lang="scss" scoped></style>
|
|
@@ -54,8 +54,6 @@ import {
|
|
|
54
54
|
useNuxtApp,
|
|
55
55
|
resolveComponent,
|
|
56
56
|
computed,
|
|
57
|
-
onUpdated,
|
|
58
|
-
onMounted,
|
|
59
57
|
watch,
|
|
60
58
|
onBeforeUnmount,
|
|
61
59
|
nextTick,
|
|
@@ -168,6 +166,22 @@ if (data.value) {
|
|
|
168
166
|
rootStore.applyListResult(props.type, data.value)
|
|
169
167
|
}
|
|
170
168
|
|
|
169
|
+
// Keep the store `loading` flag in lockstep with the query's real `pending`
|
|
170
|
+
// state. This is the single source of truth for every skeleton (the items view
|
|
171
|
+
// and SearchString both read `$stores[type].loading`). Deriving it from
|
|
172
|
+
// `pending` avoids the SSR/hydration race that previously left a search-on-load
|
|
173
|
+
// (e.g. ?search=posten) pinned in skeleton mode: on a hard load the manual
|
|
174
|
+
// `onMounted` reset and the `variables` watcher could fire in an order that
|
|
175
|
+
// re-set `loading: true` and never cleared it. `pending` flips to false exactly
|
|
176
|
+
// once, when the query resolves, regardless of that ordering.
|
|
177
|
+
watch(
|
|
178
|
+
pending,
|
|
179
|
+
(isPending) => {
|
|
180
|
+
rootStore.setLoading(Boolean(isPending), props.type)
|
|
181
|
+
},
|
|
182
|
+
{ immediate: true },
|
|
183
|
+
)
|
|
184
|
+
|
|
171
185
|
// Watch for route query changes to update filters
|
|
172
186
|
watch(
|
|
173
187
|
() => route.query,
|
|
@@ -186,13 +200,17 @@ watch(
|
|
|
186
200
|
async (newVars, oldVars) => {
|
|
187
201
|
if (newVars && JSON.stringify(newVars) !== JSON.stringify(oldVars)) {
|
|
188
202
|
/* console.log("Variables changed, refreshing query, newVars: ", newVars) */
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
203
|
+
// `loading` is driven by the `pending` watch above — `refresh()` toggles
|
|
204
|
+
// `pending` for us, so we only own the refetch + applying the result here.
|
|
205
|
+
try {
|
|
206
|
+
await refresh()
|
|
207
|
+
if (data.value) {
|
|
208
|
+
/* console.log("Applying refreshed data to store") */
|
|
209
|
+
rootStore.applyListResult(props.type, data.value)
|
|
210
|
+
}
|
|
211
|
+
} catch (e) {
|
|
212
|
+
console.error("List refresh failed: ", e)
|
|
194
213
|
}
|
|
195
|
-
rootStore.setLoading(false, props.type)
|
|
196
214
|
}
|
|
197
215
|
},
|
|
198
216
|
{ deep: true },
|
|
@@ -201,21 +219,12 @@ watch(
|
|
|
201
219
|
// Reactive items computed from the store (single source of truth)
|
|
202
220
|
const items = computed(() => $stores[props.type]?.items || [])
|
|
203
221
|
|
|
204
|
-
onMounted(() => {
|
|
205
|
-
// On initial mount: clear loading state
|
|
206
|
-
/* console.log("STOP local loading from mounted") */
|
|
207
|
-
rootStore.setLoading(false, props.type)
|
|
208
|
-
})
|
|
209
|
-
|
|
210
222
|
onBeforeUnmount(() => {
|
|
211
223
|
rootStore.resetState(props.type, locale.value)
|
|
212
224
|
})
|
|
213
225
|
async function onPageChange(newPage) {
|
|
214
226
|
/* console.log("onPageChange: ", newPage) */
|
|
215
227
|
|
|
216
|
-
// Set loading state first
|
|
217
|
-
rootStore.setLoading(true, props.type)
|
|
218
|
-
|
|
219
228
|
// Update the page in the store
|
|
220
229
|
rootStore.updatePage({
|
|
221
230
|
page: newPage,
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"license": "AGPL-3.0-only",
|
|
3
3
|
"main": "./dist/module.mjs",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.5",
|
|
5
5
|
"name": "@paris-ias/list",
|
|
6
6
|
"repository": {
|
|
7
7
|
"url": "git+https://github.com/IEA-Paris/list.git",
|
|
8
8
|
"type": "git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@paris-ias/trees": "^2.2.
|
|
11
|
+
"@paris-ias/trees": "^2.2.19"
|
|
12
12
|
},
|
|
13
13
|
"description": "Paris IAS List Module",
|
|
14
14
|
"peerDependencies": {
|