@iqual/nuxt-icms 1.3.1 → 1.4.1
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/assets/symbols/chevron-right.svg +1 -1
- package/components/Blokkli/HeroImage/index.vue +1 -1
- package/components/Blokkli/Teasers/icon.svg +3 -3
- package/components/DesignSystem/Atoms/Button.vue +86 -36
- package/components/DesignSystem/Atoms/Caption.vue +10 -10
- package/components/DesignSystem/Atoms/Container.vue +10 -6
- package/components/DesignSystem/Atoms/GridRow.vue +4 -3
- package/components/DesignSystem/Atoms/LinkListItem.vue +31 -8
- package/components/DesignSystem/Molecules/ButtonGroup.vue +18 -3
- package/components/DesignSystem/Molecules/Card.vue +86 -31
- package/components/DesignSystem/Molecules/IconText.vue +37 -16
- package/components/DesignSystem/Molecules/MediaLightbox.vue +213 -58
- package/components/DesignSystem/Molecules/MediaSlider.vue +88 -25
- package/components/DesignSystem/Molecules/Partnership.vue +40 -9
- package/components/DesignSystem/Molecules/Table.vue +90 -25
- package/components/DesignSystem/Molecules/TitleComposition.vue +15 -12
- package/components/DesignSystem/Organisms/ContentBlock.vue +61 -15
- package/components/DesignSystem/Organisms/FacetedListing.vue +170 -0
- package/components/DesignSystem/Organisms/FlipTeaser.vue +119 -47
- package/components/DesignSystem/Organisms/HeaderHero.vue +167 -0
- package/components/DesignSystem/Organisms/HeaderTextImage.vue +71 -0
- package/components/DesignSystem/Organisms/LogoElement.vue +33 -10
- package/components/DesignSystem/Organisms/Map.vue +11 -6
- package/components/DesignSystem/Organisms/SearchResults.vue +41 -0
- package/components/DesignSystem/Organisms/TeamElement.vue +84 -20
- package/components/DesignSystem/Organisms/TeaserCard.vue +87 -34
- package/components/DesignSystem/Organisms/Testimonial.vue +82 -12
- package/components/DesignSystem/Organisms/TimelineElement.vue +42 -12
- package/components/DesignSystem/Organisms/TwoColumnTextElement.vue +44 -9
- package/components/DesignSystem/Pages/Search.vue +39 -0
- package/components/Drupal/Breadcrumb/index.vue +16 -5
- package/components/Drupal/Messages/index.vue +16 -5
- package/components/Drupal/Webform/fragment.graphql +8 -5
- package/components/Drupal/Webform/index.vue +20 -9
- package/components/Drupal/Webform/query.graphql +18 -16
- package/components/Form/CheckboxInput.vue +6 -6
- package/components/Form/CheckboxInputs.vue +5 -5
- package/components/Form/FileUploadInput.vue +6 -6
- package/components/Form/RadioButtonsInput.vue +5 -5
- package/components/Form/SelectInput.vue +7 -7
- package/components/Form/SubmitButton.vue +1 -1
- package/components/Form/TextAreaInput.vue +2 -2
- package/components/Form/TextEmailInput.vue +2 -2
- package/components/Form/TextInput.vue +2 -2
- package/components/Form/TextPhoneInput.vue +2 -2
- package/components/Form/composables/useFormElement.ts +5 -5
- package/components/Form/utils/types.ts +8 -7
- package/components/Media/Icon/index.vue +10 -6
- package/components/Media/Image/index.vue +26 -20
- package/components/Media/RemoteVideo/index.vue +34 -21
- package/components/Media/Video/index.vue +6 -5
- package/components/Node/Icms/Page/Teaser/index.vue +6 -4
- package/components/Node/Icms/Page/index.vue +2 -2
- package/components/Paragraph/Button/Element/index.vue +9 -2
- package/components/Paragraph/CallToAction/index.vue +43 -10
- package/components/Paragraph/Card/Element/index.vue +2 -1
- package/components/Paragraph/Card/Layout/index.vue +29 -10
- package/components/Paragraph/Contact/index.vue +41 -12
- package/components/Paragraph/Downloads/index.vue +82 -33
- package/components/Paragraph/FAQ/Element/index.vue +41 -12
- package/components/Paragraph/FAQ/Layout/index.vue +47 -13
- package/components/Paragraph/FlipTeasers/index.vue +26 -6
- package/components/Paragraph/Gallery/index.vue +42 -10
- package/components/Paragraph/HeroImage/index.vue +62 -16
- package/components/Paragraph/IconText/Element/index.vue +7 -1
- package/components/Paragraph/IconText/Layout/index.vue +39 -12
- package/components/Paragraph/Introduction/index.vue +50 -15
- package/components/Paragraph/Logo/Element/fragment.graphql +1 -0
- package/components/Paragraph/Logo/Element/index.vue +7 -2
- package/components/Paragraph/Media/index.vue +32 -31
- package/components/Paragraph/Partnerships/Element/fragment.graphql +1 -0
- package/components/Paragraph/Partnerships/Element/index.vue +7 -0
- package/components/Paragraph/Partnerships/Layout/index.vue +100 -27
- package/components/Paragraph/SingleTestimonial/index.vue +58 -15
- package/components/Paragraph/Table/index.vue +32 -9
- package/components/Paragraph/Tabs/Element/index.vue +44 -10
- package/components/Paragraph/Tabs/Layout/index.vue +123 -37
- package/components/Paragraph/Team/Element/index.vue +18 -1
- package/components/Paragraph/Team/Layout/index.vue +30 -7
- package/components/Paragraph/Teasers/index.vue +33 -7
- package/components/Paragraph/Testimonial/Element/index.vue +30 -5
- package/components/Paragraph/Testimonial/Layout/index.vue +78 -24
- package/components/Paragraph/Text/index.vue +32 -10
- package/components/Paragraph/TextMedia/index.vue +44 -13
- package/components/Paragraph/Timeline/Element/index.vue +23 -7
- package/components/Paragraph/Timeline/Layout/index.vue +232 -67
- package/components/Paragraph/TwoColumnText/Element/index.vue +20 -3
- package/components/Paragraph/TwoColumnText/Layout/index.vue +8 -1
- package/components/Paragraph/iFrame/index.vue +31 -11
- package/components/Search/Facets/FacetDropdownUI.vue +351 -77
- package/components/Search/Facets/FacetedSearchUI.vue +257 -101
- package/components/Search/Facets/fragment.graphql +5 -1
- package/components/Search/Input/index.vue +78 -20
- package/components/Section/Footer/index.vue +170 -30
- package/components/Section/Header/Buttons.vue +34 -0
- package/components/Section/Header/DesktopMainMenu.vue +160 -0
- package/components/Section/Header/DesktopMainMenuDropdown.vue +170 -0
- package/components/Section/Header/LanguageDropdown.vue +95 -64
- package/components/Section/Header/LanguageLinks.vue +39 -0
- package/components/Section/Header/Logo.vue +24 -0
- package/components/Section/Header/MainButtons.vue +31 -0
- package/components/Section/Header/MenuIcon.vue +61 -49
- package/components/Section/Header/MetaButtons.vue +31 -0
- package/components/Section/Header/MetaMenu.vue +55 -53
- package/components/Section/Header/MobileMainMenu.vue +23 -0
- package/components/Section/Header/MobileMainMenuItem.vue +191 -0
- package/components/Section/Header/index.vue +183 -185
- package/composables/useMenu.ts +2 -2
- package/composables/useMobileMenuOverlayBus.ts +44 -0
- package/composables/useNavigationOffset.ts +2 -2
- package/composables/useTheme.ts +75 -0
- package/formkit.theme.ts +541 -586
- package/layouts/default.vue +7 -35
- package/layouts/error.vue +7 -32
- package/nuxt.config.ts +13 -0
- package/package.json +1 -1
- package/plugins/initData.ts +8 -5
- package/queries/query.initData.graphql +4 -2
- package/tailwind.config.ts +11 -11
- package/types/global.ts +1 -0
- package/components/Section/Header/GlobalMenu.vue +0 -335
- package/components/Section/Header/LanguageSwitcher.vue +0 -37
|
@@ -7,12 +7,19 @@
|
|
|
7
7
|
v-model="facetSelections"
|
|
8
8
|
@facets-change="onFacetsChange"
|
|
9
9
|
:total-count="totalCount"
|
|
10
|
-
:displayed-count="
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
:displayed-count="
|
|
11
|
+
props.groupResultsByFacet
|
|
12
|
+
? displayedResults?.reduce(
|
|
13
|
+
(total, group) => total + (group?.results?.length || 0),
|
|
14
|
+
0,
|
|
15
|
+
)
|
|
16
|
+
: displayedResults?.[0]?.results?.length
|
|
17
|
+
"
|
|
13
18
|
:loading="isLoading"
|
|
14
19
|
:colorScheme="colorScheme"
|
|
15
|
-
class="
|
|
20
|
+
:class="
|
|
21
|
+
themedClass('listingTypeAllSearchFacetsFacetDropdownUIClass', 'mb-6')
|
|
22
|
+
"
|
|
16
23
|
:enable-text-search="enableTextSearch"
|
|
17
24
|
:search-term="searchTerm"
|
|
18
25
|
@update:search-term="onSearchTermChange"
|
|
@@ -26,7 +33,7 @@
|
|
|
26
33
|
>{{ JSON.stringify(facetSelections, null, 2) }}</pre
|
|
27
34
|
>
|
|
28
35
|
<pre
|
|
29
|
-
class="
|
|
36
|
+
class="mt-2 whitespace-pre rounded bg-blue-50 p-3 text-xs"
|
|
30
37
|
v-if="facetData.length"
|
|
31
38
|
>
|
|
32
39
|
Facets: {{ facetData.length }} items</pre
|
|
@@ -36,43 +43,92 @@ Facets: {{ facetData.length }} items</pre
|
|
|
36
43
|
|
|
37
44
|
<template v-if="debug && listingType !== 'all'">
|
|
38
45
|
<!-- Debug info for manual/contextual filters -->
|
|
39
|
-
<pre class="
|
|
40
|
-
Active Filters ({{ listingType }}): {{
|
|
46
|
+
<pre class="mb-4 whitespace-pre rounded bg-yellow-50 p-3 text-xs">
|
|
47
|
+
Active Filters ({{ listingType }}): {{
|
|
41
48
|
JSON.stringify(activeFilters, null, 2)
|
|
42
49
|
}}</pre
|
|
43
50
|
>
|
|
44
51
|
</template>
|
|
52
|
+
|
|
45
53
|
<!-- Results Section -->
|
|
46
|
-
<div class="
|
|
54
|
+
<div :class="themedClass('resultsContainerClass')">
|
|
47
55
|
<template v-if="displayedResults?.length">
|
|
48
56
|
<div
|
|
49
57
|
v-for="(group, groupIndex) in displayedResults"
|
|
50
58
|
:key="`group-${groupIndex}`"
|
|
59
|
+
:class="themedClass('resultGroupClass')"
|
|
51
60
|
>
|
|
52
61
|
<slot name="results" :results="group" :loading="loadingMore">
|
|
53
|
-
<p
|
|
62
|
+
<p
|
|
63
|
+
v-if="
|
|
64
|
+
props.groupResultsByFacet && 'label' in group && group?.label
|
|
65
|
+
"
|
|
66
|
+
:class="themedClass('resultGroupLabelClass')"
|
|
67
|
+
>
|
|
68
|
+
{{ group?.label }}
|
|
69
|
+
<span
|
|
70
|
+
v-if="'count' in group && group?.count"
|
|
71
|
+
:class="themedClass('resultGroupCountClass')"
|
|
72
|
+
>
|
|
73
|
+
({{ group?.count }})
|
|
74
|
+
</span>
|
|
75
|
+
</p>
|
|
54
76
|
<!-- Default slot content if no slot is provided -->
|
|
55
77
|
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
|
|
56
|
-
<div
|
|
78
|
+
<div
|
|
79
|
+
v-for="(result, index) in group?.results"
|
|
57
80
|
:key="`result-${index}`"
|
|
58
81
|
>
|
|
59
|
-
<pre class="rounded bg-gray-100 p-2 text-xs
|
|
60
|
-
JSON.stringify(result, null, 2)
|
|
61
|
-
|
|
82
|
+
<pre class="overflow-hidden rounded bg-gray-100 p-2 text-xs">
|
|
83
|
+
{{ JSON.stringify(result, null, 2) }}
|
|
84
|
+
</pre>
|
|
62
85
|
</div>
|
|
63
86
|
</div>
|
|
64
87
|
</slot>
|
|
65
|
-
|
|
88
|
+
|
|
66
89
|
<!-- Group-specific Load More Section (for grouped results) -->
|
|
67
|
-
<div
|
|
68
|
-
|
|
90
|
+
<div
|
|
91
|
+
v-if="
|
|
92
|
+
props.groupResultsByFacet &&
|
|
93
|
+
'label' in group &&
|
|
94
|
+
canGroupLoadMore(group)
|
|
95
|
+
"
|
|
96
|
+
:class="
|
|
97
|
+
themedClass(
|
|
98
|
+
'groupLoadMoreButtonContainerClass',
|
|
99
|
+
'mt-6 flex justify-center',
|
|
100
|
+
)
|
|
101
|
+
"
|
|
102
|
+
>
|
|
103
|
+
<slot
|
|
104
|
+
name="group-load-more"
|
|
105
|
+
:loadMore="() => loadMoreGroup(group)"
|
|
106
|
+
:loading="isGroupLoading(group)"
|
|
107
|
+
:group="group"
|
|
108
|
+
>
|
|
69
109
|
<button
|
|
70
110
|
@click="loadMoreGroup(group)"
|
|
71
111
|
:disabled="isGroupLoading(group)"
|
|
72
|
-
:class="
|
|
112
|
+
:class="
|
|
113
|
+
cn(
|
|
114
|
+
button({ colorScheme }),
|
|
115
|
+
themedClass('groupLoadMoreButtonClass'),
|
|
116
|
+
props.loadMoreButtonClass,
|
|
117
|
+
)
|
|
118
|
+
"
|
|
73
119
|
>
|
|
74
|
-
<span
|
|
75
|
-
|
|
120
|
+
<span
|
|
121
|
+
v-if="!isGroupLoading(group)"
|
|
122
|
+
:class="themedClass('groupLoadMoreButtonLabelClass')"
|
|
123
|
+
>
|
|
124
|
+
{{ defaultLoadMoreText }}
|
|
125
|
+
</span>
|
|
126
|
+
<span
|
|
127
|
+
v-else
|
|
128
|
+
:class="themedClass('groupLoadMoreLoadingButtonLabelClass')"
|
|
129
|
+
>
|
|
130
|
+
{{ defaultLoadingText }}
|
|
131
|
+
</span>
|
|
76
132
|
</button>
|
|
77
133
|
</slot>
|
|
78
134
|
</div>
|
|
@@ -81,7 +137,14 @@ Active Filters ({{ listingType }}): {{
|
|
|
81
137
|
|
|
82
138
|
<template v-else-if="!isLoading">
|
|
83
139
|
<slot name="no-results">
|
|
84
|
-
<div
|
|
140
|
+
<div
|
|
141
|
+
:class="
|
|
142
|
+
themedClass(
|
|
143
|
+
'noResultsContainerClass',
|
|
144
|
+
'col-span-12 py-8 text-center text-gray-500',
|
|
145
|
+
)
|
|
146
|
+
"
|
|
147
|
+
>
|
|
85
148
|
{{ defaultNoResultsText }}
|
|
86
149
|
</div>
|
|
87
150
|
</slot>
|
|
@@ -89,23 +152,47 @@ Active Filters ({{ listingType }}): {{
|
|
|
89
152
|
|
|
90
153
|
<template v-if="isLoading">
|
|
91
154
|
<slot name="loading">
|
|
92
|
-
<div
|
|
93
|
-
|
|
155
|
+
<div
|
|
156
|
+
:class="
|
|
157
|
+
themedClass(
|
|
158
|
+
'loadingContainerClass',
|
|
159
|
+
'col-span-12 py-8 text-center',
|
|
160
|
+
)
|
|
161
|
+
"
|
|
162
|
+
>
|
|
163
|
+
<span :class="loadingText({ colorScheme })">
|
|
164
|
+
{{ defaultLoadingText }}
|
|
165
|
+
</span>
|
|
94
166
|
</div>
|
|
95
167
|
</slot>
|
|
96
168
|
</template>
|
|
97
169
|
</div>
|
|
98
170
|
|
|
99
171
|
<!-- Global Load More Section (for non-grouped results) -->
|
|
100
|
-
<div
|
|
172
|
+
<div
|
|
173
|
+
v-if="showLoadMore"
|
|
174
|
+
:class="
|
|
175
|
+
themedClass(
|
|
176
|
+
'globalLoadMoreButtonContainer',
|
|
177
|
+
'mt-10 flex justify-center lg:mt-20',
|
|
178
|
+
)
|
|
179
|
+
"
|
|
180
|
+
>
|
|
101
181
|
<slot name="load-more" :loadMore="loadMore" :loading="loadingMore">
|
|
102
182
|
<button
|
|
103
183
|
@click="loadMore"
|
|
104
184
|
:disabled="loadingMore"
|
|
105
|
-
:class="
|
|
185
|
+
:class="cn(button({ colorScheme }), loadMoreButtonClass)"
|
|
106
186
|
>
|
|
107
|
-
<span
|
|
108
|
-
|
|
187
|
+
<span
|
|
188
|
+
v-if="!loadingMore"
|
|
189
|
+
:class="themedClass('globalLoadMoreButtonLabel')"
|
|
190
|
+
>
|
|
191
|
+
{{ defaultLoadMoreText }}
|
|
192
|
+
</span>
|
|
193
|
+
<span v-else :class="themedClass('globalLoadMoreLoadingButtonLabel')">
|
|
194
|
+
{{ defaultLoadingText }}
|
|
195
|
+
</span>
|
|
109
196
|
</button>
|
|
110
197
|
</slot>
|
|
111
198
|
</div>
|
|
@@ -114,7 +201,11 @@ Active Filters ({{ listingType }}): {{
|
|
|
114
201
|
|
|
115
202
|
<script lang="ts" setup>
|
|
116
203
|
import { nextTick } from 'vue'
|
|
204
|
+
import type { ColorScheme } from '@iqual/nuxt-icms/types/global'
|
|
117
205
|
import type { SearchApiQueryFilterInput } from '#graphql-operations'
|
|
206
|
+
import { useTheme } from '@iqual/nuxt-icms/composables/useTheme'
|
|
207
|
+
import { tv } from 'tailwind-variants'
|
|
208
|
+
import cn from '@iqual/nuxt-icms/composables/useCn'
|
|
118
209
|
|
|
119
210
|
export interface FacetFilterItem {
|
|
120
211
|
id: string
|
|
@@ -156,7 +247,7 @@ export interface FacetedSearchUIProps {
|
|
|
156
247
|
debug?: boolean
|
|
157
248
|
|
|
158
249
|
/** Color scheme for default button styling */
|
|
159
|
-
colorScheme?:
|
|
250
|
+
colorScheme?: ColorScheme
|
|
160
251
|
|
|
161
252
|
/** Custom CSS classes for the load more button */
|
|
162
253
|
loadMoreButtonClass?: string
|
|
@@ -179,6 +270,8 @@ const props = withDefaults(defineProps<FacetedSearchUIProps>(), {
|
|
|
179
270
|
conjunction: 'AND',
|
|
180
271
|
})
|
|
181
272
|
|
|
273
|
+
const themedClass = useTheme('SearchFacetsFacetedSearchUI')
|
|
274
|
+
|
|
182
275
|
// Get the $texts function for internationalization
|
|
183
276
|
const { $texts } = useNuxtApp()
|
|
184
277
|
|
|
@@ -280,9 +373,9 @@ const buildSearchFilter = (
|
|
|
280
373
|
return { conditions: baseConditions }
|
|
281
374
|
} else if (baseConditions.length === 0) {
|
|
282
375
|
// If no base conditions, return additional conditions with conjunction
|
|
283
|
-
return {
|
|
376
|
+
return {
|
|
284
377
|
conditions: additionalConditions,
|
|
285
|
-
conjunction: props.conjunction
|
|
378
|
+
conjunction: props.conjunction,
|
|
286
379
|
}
|
|
287
380
|
} else {
|
|
288
381
|
// Create the exact structure: base group AND additional group (with specified conjunction)
|
|
@@ -290,13 +383,13 @@ const buildSearchFilter = (
|
|
|
290
383
|
conjunction: 'AND',
|
|
291
384
|
groups: [
|
|
292
385
|
{
|
|
293
|
-
conditions: baseConditions
|
|
386
|
+
conditions: baseConditions,
|
|
294
387
|
},
|
|
295
388
|
{
|
|
296
389
|
conditions: additionalConditions,
|
|
297
|
-
conjunction: props.conjunction
|
|
298
|
-
}
|
|
299
|
-
]
|
|
390
|
+
conjunction: props.conjunction,
|
|
391
|
+
},
|
|
392
|
+
],
|
|
300
393
|
}
|
|
301
394
|
}
|
|
302
395
|
}
|
|
@@ -326,34 +419,44 @@ const { data: initialResultsData, refresh: refreshResults } =
|
|
|
326
419
|
`facetedSearch-results-${props.listingType}-${JSON.stringify(props.baseFilter)}-${JSON.stringify(activeFilters.value)}`,
|
|
327
420
|
async () => {
|
|
328
421
|
const filter = buildSearchFilter()
|
|
329
|
-
|
|
422
|
+
|
|
330
423
|
// Debug: Log the initial filter structure
|
|
331
424
|
if (props.debug) {
|
|
332
|
-
console.log(
|
|
425
|
+
console.log(
|
|
426
|
+
'FacetedSearch - Initial filter being sent:',
|
|
427
|
+
JSON.stringify(filter, null, 2),
|
|
428
|
+
)
|
|
333
429
|
}
|
|
334
|
-
|
|
430
|
+
|
|
335
431
|
const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
|
|
336
432
|
filter,
|
|
337
433
|
facets: props.facets,
|
|
338
|
-
limit: props?.groupResultsByFacet
|
|
434
|
+
limit: props?.groupResultsByFacet
|
|
435
|
+
? props.itemsPerPage * 10
|
|
436
|
+
: props.itemsPerPage,
|
|
339
437
|
offset: 0,
|
|
340
438
|
keys: searchTerm.value ?? '',
|
|
341
439
|
})
|
|
342
440
|
isLoading.value = false
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
441
|
+
if (
|
|
442
|
+
props?.groupResultsByFacet &&
|
|
443
|
+
response?.data?.searchApiQuery?.facets
|
|
444
|
+
) {
|
|
445
|
+
response.data.searchApiQuery.facets =
|
|
446
|
+
response.data?.searchApiQuery?.facets?.map((f) => {
|
|
447
|
+
return {
|
|
448
|
+
count: f?.count,
|
|
449
|
+
field: f?.field,
|
|
450
|
+
label: f?.label,
|
|
451
|
+
filter: f?.filter,
|
|
452
|
+
results: f?.results?.slice(0, 4),
|
|
453
|
+
}
|
|
454
|
+
})
|
|
351
455
|
}
|
|
352
456
|
return response.data?.searchApiQuery ?? null
|
|
353
457
|
},
|
|
354
458
|
)
|
|
355
459
|
|
|
356
|
-
|
|
357
460
|
// Initialize facets from initial query (only for 'all' listing type)
|
|
358
461
|
if (initialFacetsData.value) {
|
|
359
462
|
allFacets.value = initialFacetsData.value.facets || []
|
|
@@ -368,22 +471,27 @@ async function updateSearchResults(selections: Record<string, string[]>) {
|
|
|
368
471
|
try {
|
|
369
472
|
isLoading.value = true
|
|
370
473
|
currentPage.value = 1 // Reset pagination when filters change
|
|
371
|
-
|
|
474
|
+
|
|
372
475
|
// Reset group pagination states when filters change
|
|
373
476
|
groupPagination.value = {}
|
|
374
477
|
groupLoadingMore.value = {}
|
|
375
|
-
|
|
478
|
+
|
|
376
479
|
const filter = buildSearchFilter(selections)
|
|
377
480
|
|
|
378
481
|
// Debug: Log the filter structure
|
|
379
482
|
if (props.debug) {
|
|
380
|
-
console.log(
|
|
483
|
+
console.log(
|
|
484
|
+
'FacetedSearch - Filter being sent:',
|
|
485
|
+
JSON.stringify(filter, null, 2),
|
|
486
|
+
)
|
|
381
487
|
}
|
|
382
488
|
|
|
383
489
|
const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
|
|
384
490
|
filter,
|
|
385
491
|
facets: props.facets,
|
|
386
|
-
limit: props?.groupResultsByFacet
|
|
492
|
+
limit: props?.groupResultsByFacet
|
|
493
|
+
? props.itemsPerPage * 10
|
|
494
|
+
: props.itemsPerPage,
|
|
387
495
|
offset: 0,
|
|
388
496
|
keys: searchTerm.value ?? '',
|
|
389
497
|
})
|
|
@@ -393,29 +501,27 @@ async function updateSearchResults(selections: Record<string, string[]>) {
|
|
|
393
501
|
// Apply the same transformation as in the initial query
|
|
394
502
|
let processedFacets = response?.data?.searchApiQuery?.facets
|
|
395
503
|
if (processedFacets) {
|
|
396
|
-
processedFacets = processedFacets.map(f => ({
|
|
504
|
+
processedFacets = processedFacets.map((f) => ({
|
|
397
505
|
count: f?.count,
|
|
398
506
|
field: f?.field,
|
|
399
507
|
label: f?.label,
|
|
400
508
|
filter: f?.filter,
|
|
401
|
-
results: f?.results?.slice(0, 4)
|
|
509
|
+
results: f?.results?.slice(0, 4),
|
|
402
510
|
}))
|
|
403
511
|
}
|
|
404
|
-
|
|
512
|
+
|
|
405
513
|
initialResultsData.value = {
|
|
406
514
|
...initialResultsData.value,
|
|
407
515
|
facets: processedFacets,
|
|
408
516
|
count: response?.data?.searchApiQuery?.count,
|
|
409
517
|
}
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
518
|
+
} else {
|
|
412
519
|
initialResultsData.value = {
|
|
413
520
|
...initialResultsData.value,
|
|
414
521
|
results: response?.data?.searchApiQuery?.results,
|
|
415
522
|
count: response?.data?.searchApiQuery?.count,
|
|
416
523
|
}
|
|
417
524
|
}
|
|
418
|
-
|
|
419
525
|
} catch (error) {
|
|
420
526
|
console.error('Error updating search results:', error)
|
|
421
527
|
} finally {
|
|
@@ -426,19 +532,23 @@ async function updateSearchResults(selections: Record<string, string[]>) {
|
|
|
426
532
|
// Computed properties
|
|
427
533
|
const displayedResults = computed(() => {
|
|
428
534
|
if (props?.groupResultsByFacet) {
|
|
429
|
-
return initialResultsData.value?.facets
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
535
|
+
return initialResultsData.value?.facets
|
|
536
|
+
?.filter((facet) => {
|
|
537
|
+
return facet?.field == props?.groupResultsByFacet
|
|
538
|
+
})
|
|
539
|
+
.map((facet) => {
|
|
540
|
+
return {
|
|
541
|
+
label: facet?.filter?.label,
|
|
542
|
+
count: facet?.count,
|
|
543
|
+
results: facet?.results || [],
|
|
544
|
+
}
|
|
545
|
+
})
|
|
438
546
|
}
|
|
439
|
-
return
|
|
440
|
-
|
|
441
|
-
|
|
547
|
+
return [
|
|
548
|
+
{
|
|
549
|
+
results: initialResultsData.value?.results || [],
|
|
550
|
+
},
|
|
551
|
+
]
|
|
442
552
|
})
|
|
443
553
|
|
|
444
554
|
const totalCount = computed(() => {
|
|
@@ -525,24 +635,9 @@ watch(
|
|
|
525
635
|
refreshResults()
|
|
526
636
|
}
|
|
527
637
|
},
|
|
528
|
-
{ immediate: false }
|
|
638
|
+
{ immediate: false },
|
|
529
639
|
)
|
|
530
640
|
|
|
531
|
-
// Default button styling based on color scheme
|
|
532
|
-
const defaultButtonClass = computed(() => {
|
|
533
|
-
const baseClasses =
|
|
534
|
-
'shadow-none h-auto block text-h7 font-medium py-3 px-20 rounded-full duration-300 ease-in-out w-full md:w-fit border disabled:opacity-50 disabled:cursor-not-allowed'
|
|
535
|
-
|
|
536
|
-
const colorSchemeClasses = {
|
|
537
|
-
none: 'bg-white text-black hover:bg-black hover:text-white border-black',
|
|
538
|
-
dark: 'bg-white text-black hover:bg-black hover:text-white border-black',
|
|
539
|
-
light: 'bg-gray-50 text-black hover:bg-black hover:text-white border-black',
|
|
540
|
-
accent: 'bg-white text-black hover:bg-black hover:text-white border-black',
|
|
541
|
-
}
|
|
542
|
-
|
|
543
|
-
return `${baseClasses} ${colorSchemeClasses[props.colorScheme] || colorSchemeClasses.none}`
|
|
544
|
-
})
|
|
545
|
-
|
|
546
641
|
// Load more handler
|
|
547
642
|
async function loadMore() {
|
|
548
643
|
if (loadingMore.value || isLoading.value) return
|
|
@@ -585,16 +680,19 @@ async function loadMore() {
|
|
|
585
680
|
// Load more handler for specific group
|
|
586
681
|
async function loadMoreGroup(group: any) {
|
|
587
682
|
if (!props.groupResultsByFacet || !group || !('label' in group)) return
|
|
588
|
-
|
|
683
|
+
|
|
589
684
|
const groupKey = getGroupKey(group)
|
|
590
685
|
if (groupLoadingMore.value[groupKey] || isLoading.value) return
|
|
591
|
-
|
|
686
|
+
|
|
592
687
|
groupLoadingMore.value[groupKey] = true
|
|
593
688
|
|
|
594
689
|
try {
|
|
595
690
|
// Find the facet filter value that corresponds to this group
|
|
596
|
-
const groupFacetValue = initialResultsData.value?.facets?.find(
|
|
597
|
-
f
|
|
691
|
+
const groupFacetValue = initialResultsData.value?.facets?.find(
|
|
692
|
+
(f) =>
|
|
693
|
+
f &&
|
|
694
|
+
f.field === props.groupResultsByFacet &&
|
|
695
|
+
f.filter?.label === group.label,
|
|
598
696
|
)?.filter?.id
|
|
599
697
|
|
|
600
698
|
if (!groupFacetValue) {
|
|
@@ -610,28 +708,31 @@ async function loadMoreGroup(group: any) {
|
|
|
610
708
|
// Step 1: First apply the facet filter and wait for it to complete
|
|
611
709
|
const updatedSelections = {
|
|
612
710
|
...facetSelections.value,
|
|
613
|
-
[props.groupResultsByFacet]: [groupFacetValue]
|
|
711
|
+
[props.groupResultsByFacet]: [groupFacetValue],
|
|
614
712
|
}
|
|
615
|
-
|
|
713
|
+
|
|
616
714
|
// Update facetSelections and trigger the normal facet change flow
|
|
617
715
|
facetSelections.value = updatedSelections
|
|
618
716
|
onFacetsChange(updatedSelections)
|
|
619
|
-
|
|
717
|
+
|
|
620
718
|
// Wait for the facet change to complete
|
|
621
719
|
await nextTick()
|
|
622
720
|
// Wait a bit more to ensure the search results have been updated
|
|
623
|
-
await new Promise(resolve => setTimeout(resolve, 100))
|
|
721
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
624
722
|
}
|
|
625
723
|
|
|
626
724
|
// Step 2: Now do the load more operation
|
|
627
725
|
// For grouped results, find the current results for this specific group
|
|
628
|
-
const currentGroupData = initialResultsData.value?.facets?.find(
|
|
629
|
-
f
|
|
726
|
+
const currentGroupData = initialResultsData.value?.facets?.find(
|
|
727
|
+
(f) =>
|
|
728
|
+
f &&
|
|
729
|
+
f.field === props.groupResultsByFacet &&
|
|
730
|
+
f.filter?.label === group.label,
|
|
630
731
|
)
|
|
631
|
-
|
|
732
|
+
|
|
632
733
|
const currentGroupResults = currentGroupData?.results || []
|
|
633
734
|
const currentCount = currentGroupResults.length
|
|
634
|
-
|
|
735
|
+
|
|
635
736
|
// Use the current group result count as offset to load more
|
|
636
737
|
const response = await useGraphqlQuery('layoutOverviewResultsSearch', {
|
|
637
738
|
filter: buildSearchFilter(facetSelections.value),
|
|
@@ -643,19 +744,23 @@ async function loadMoreGroup(group: any) {
|
|
|
643
744
|
if (response.data?.searchApiQuery?.results) {
|
|
644
745
|
// Append new results to the existing group results
|
|
645
746
|
const newResults = response.data.searchApiQuery.results
|
|
646
|
-
|
|
747
|
+
|
|
647
748
|
// Update the specific group's results in the facets array
|
|
648
749
|
if (initialResultsData.value?.facets && currentGroupData) {
|
|
649
|
-
const updatedFacets = initialResultsData.value.facets.map(facet => {
|
|
650
|
-
if (
|
|
750
|
+
const updatedFacets = initialResultsData.value.facets.map((facet) => {
|
|
751
|
+
if (
|
|
752
|
+
facet &&
|
|
753
|
+
facet.field === props.groupResultsByFacet &&
|
|
754
|
+
facet.filter?.label === group.label
|
|
755
|
+
) {
|
|
651
756
|
return {
|
|
652
757
|
...facet,
|
|
653
|
-
results: [...currentGroupResults, ...newResults]
|
|
758
|
+
results: [...currentGroupResults, ...newResults],
|
|
654
759
|
}
|
|
655
760
|
}
|
|
656
761
|
return facet
|
|
657
762
|
})
|
|
658
|
-
|
|
763
|
+
|
|
659
764
|
initialResultsData.value = {
|
|
660
765
|
...initialResultsData.value,
|
|
661
766
|
facets: updatedFacets,
|
|
@@ -676,6 +781,57 @@ async function loadMoreGroup(group: any) {
|
|
|
676
781
|
}
|
|
677
782
|
}
|
|
678
783
|
|
|
784
|
+
const button = tv({
|
|
785
|
+
base: themedClass(
|
|
786
|
+
'buttonBase',
|
|
787
|
+
'shadow-none h-auto block text-h7 font-medium py-3 px-20 rounded-full duration-300 ease-in-out w-full md:w-fit border disabled:opacity-50 disabled:cursor-not-allowed',
|
|
788
|
+
),
|
|
789
|
+
variants: {
|
|
790
|
+
colorScheme: {
|
|
791
|
+
none: themedClass(
|
|
792
|
+
'buttonVariantsColorSchemeNone',
|
|
793
|
+
'bg-white text-black hover:bg-black hover:text-white border-black',
|
|
794
|
+
),
|
|
795
|
+
dark: themedClass(
|
|
796
|
+
'buttonVariantsColorSchemeDark',
|
|
797
|
+
'bg-white text-black hover:bg-black hover:text-white border-black',
|
|
798
|
+
),
|
|
799
|
+
light: themedClass(
|
|
800
|
+
'buttonVariantsColorSchemeLight',
|
|
801
|
+
'bg-gray-50 text-black hover:bg-black hover:text-white border-black',
|
|
802
|
+
),
|
|
803
|
+
accent: themedClass(
|
|
804
|
+
'buttonVariantsColorSchemeAccent',
|
|
805
|
+
'bg-white text-black hover:bg-black hover:text-white border-black',
|
|
806
|
+
),
|
|
807
|
+
},
|
|
808
|
+
},
|
|
809
|
+
defaultVariants: {
|
|
810
|
+
colorScheme: 'none',
|
|
811
|
+
},
|
|
812
|
+
})
|
|
813
|
+
|
|
814
|
+
const loadingText = tv({
|
|
815
|
+
base: themedClass('loadingTextBase'),
|
|
816
|
+
variants: {
|
|
817
|
+
colorScheme: {
|
|
818
|
+
none: themedClass('loadingTextVariantsColorSchemeNone', 'text-gray-500'),
|
|
819
|
+
dark: themedClass('loadingTextVariantsColorSchemeDark', 'text-gray-500'),
|
|
820
|
+
light: themedClass(
|
|
821
|
+
'loadingTextVariantsColorSchemeLight',
|
|
822
|
+
'text-gray-500',
|
|
823
|
+
),
|
|
824
|
+
accent: themedClass(
|
|
825
|
+
'loadingTextVariantsColorSchemeAccent',
|
|
826
|
+
'text-gray-500',
|
|
827
|
+
),
|
|
828
|
+
},
|
|
829
|
+
},
|
|
830
|
+
defaultVariants: {
|
|
831
|
+
colorScheme: 'none',
|
|
832
|
+
},
|
|
833
|
+
})
|
|
834
|
+
|
|
679
835
|
// Debug logging
|
|
680
836
|
watchEffect(() => {
|
|
681
837
|
if (props.debug) {
|
|
@@ -32,10 +32,14 @@ query layoutOverviewResultsSearch(
|
|
|
32
32
|
searchApiQuery(
|
|
33
33
|
indexId: "content_search",
|
|
34
34
|
filter: $filter
|
|
35
|
-
facets: $facets
|
|
35
|
+
facets: $facets
|
|
36
36
|
limit: $limit
|
|
37
37
|
offset: $offset
|
|
38
38
|
keys: $keys
|
|
39
|
+
sort: [
|
|
40
|
+
{field: "weight", direction:DESC},
|
|
41
|
+
{field: "created", direction:DESC}
|
|
42
|
+
]
|
|
39
43
|
) {
|
|
40
44
|
count
|
|
41
45
|
results {
|