Skip to content

Commit fb249c2

Browse files
authored
Merge pull request #56974 from nextcloud/backport/56620/stable32
[stable32] fix(unified-search): prevent provider disabling on content filter apply
2 parents ba8514c + 1273fd8 commit fb249c2

File tree

3 files changed

+100
-14
lines changed

3 files changed

+100
-14
lines changed

core/src/components/UnifiedSearch/UnifiedSearchModal.vue

Lines changed: 97 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
:label="t('core', 'Search apps, files, tags, messages') + '...'"
2828
@update:value="debouncedFind" />
2929
<div class="unified-search-modal__filters" data-cy-unified-search-filters>
30-
<NcActions :menu-name="t('core', 'Places')" :open.sync="providerActionMenuIsOpen" data-cy-unified-search-filter="places">
30+
<NcActions :open.sync="providerActionMenuIsOpen" :menu-name="t('core', 'Places')" data-cy-unified-search-filter="places">
3131
<template #icon>
3232
<IconListBox :size="20" />
3333
</template>
@@ -43,7 +43,7 @@
4343
{{ provider.name }}
4444
</NcActionButton>
4545
</NcActions>
46-
<NcActions :menu-name="t('core', 'Date')" :open.sync="dateActionMenuIsOpen" data-cy-unified-search-filter="date">
46+
<NcActions :open.sync="dateActionMenuIsOpen" :menu-name="t('core', 'Date')" data-cy-unified-search-filter="date">
4747
<template #icon>
4848
<IconCalendarRange :size="20" />
4949
</template>
@@ -127,7 +127,8 @@
127127
<h3 class="hidden-visually">
128128
{{ t('core', 'Results') }}
129129
</h3>
130-
<div v-for="providerResult in results" :key="providerResult.id" class="result">
130+
<!-- Filtered results section -->
131+
<div v-for="providerResult in filteredResults" :key="providerResult.id" class="result">
131132
<h4 :id="`unified-search-result-${providerResult.id}`" class="result-title">
132133
{{ providerResult.name }}
133134
</h4>
@@ -151,6 +152,36 @@
151152
</NcButton>
152153
</div>
153154
</div>
155+
<!-- Unfiltered results section -->
156+
<template v-if="unfilteredResults.length > 0">
157+
<div class="unified-search-modal__unfiltered-header">
158+
<span class="unified-search-modal__unfiltered-label">{{ t('core', 'Partial matches') }}</span>
159+
</div>
160+
<div v-for="providerResult in unfilteredResults" :key="`unfiltered-${providerResult.id}`" class="result result--unfiltered">
161+
<h4 :id="`unified-search-result-unfiltered-${providerResult.id}`" class="result-title">
162+
{{ providerResult.name }}
163+
</h4>
164+
<ul class="result-items" :aria-labelledby="`unified-search-result-unfiltered-${providerResult.id}`">
165+
<SearchResult v-for="(result, index) in providerResult.results"
166+
:key="index"
167+
v-bind="result" />
168+
</ul>
169+
<div class="result-footer">
170+
<NcButton v-if="providerResult.results.length === providerResult.limit" variant="tertiary-no-background" @click="loadMoreResultsForProvider(providerResult)">
171+
{{ t('core', 'Load more results') }}
172+
<template #icon>
173+
<IconDotsHorizontal :size="20" />
174+
</template>
175+
</NcButton>
176+
<NcButton v-if="providerResult.inAppSearch" alignment="end-reverse" variant="tertiary-no-background">
177+
{{ t('core', 'Search in') }} {{ providerResult.name }}
178+
<template #icon>
179+
<IconArrowRight :size="20" />
180+
</template>
181+
</NcButton>
182+
</div>
183+
</div>
184+
</template>
154185
</div>
155186
</NcDialog>
156187
</template>
@@ -335,6 +366,50 @@ export default defineComponent({
335366
hasExternalResources() {
336367
return this.providers.some(provider => provider.isExternalProvider)
337368
},
369+
370+
hasContentFilters() {
371+
return this.filters.some((filter) => filter.type === 'date' || filter.type === 'person')
372+
},
373+
374+
filteredResults() {
375+
const isInFolderAtRoot = (result) => {
376+
if (result.id !== 'in-folder') {
377+
return false
378+
}
379+
const path = result.extraParams?.path
380+
return !path || path === '/' || path === ''
381+
}
382+
383+
if (!this.hasContentFilters) {
384+
return this.results.filter((result) => !isInFolderAtRoot(result))
385+
}
386+
return this.results.filter((result) => result.supportsActiveFilters === true && !isInFolderAtRoot(result))
387+
},
388+
389+
filteredResultUrls() {
390+
const urls = new Set()
391+
this.filteredResults.forEach((provider) => {
392+
provider.results.forEach((entry) => {
393+
if (entry.resourceUrl) {
394+
urls.add(entry.resourceUrl)
395+
}
396+
})
397+
})
398+
return urls
399+
},
400+
401+
unfilteredResults() {
402+
if (!this.hasContentFilters) {
403+
return []
404+
}
405+
return this.results
406+
.filter((result) => result.supportsActiveFilters === false)
407+
.map((provider) => ({
408+
...provider,
409+
results: provider.results.filter((entry) => !this.filteredResultUrls.has(entry.resourceUrl)),
410+
}))
411+
.filter((provider) => provider.results.length > 0)
412+
},
338413
},
339414
340415
watch: {
@@ -473,6 +548,7 @@ export default defineComponent({
473548
...provider,
474549
results: response.data.ocs.data.entries,
475550
limit: params.limit ?? 5,
551+
supportsActiveFilters,
476552
})
477553
478554
unifiedSearchLogger.debug('Unified search results:', { results: this.results, newResults })
@@ -553,10 +629,6 @@ export default defineComponent({
553629
this.filters[existingPersonFilter].name = person.displayName
554630
}
555631
556-
this.providers.forEach(async (provider, index) => {
557-
this.providers[index].disabled = !(await this.providerIsCompatibleWithFilters(provider, ['person']))
558-
})
559-
560632
this.debouncedFind(this.searchQuery)
561633
unifiedSearchLogger.debug('Person filter applied', { person })
562634
},
@@ -610,7 +682,6 @@ export default defineComponent({
610682
for (let i = 0; i < this.filters.length; i++) {
611683
if (this.filters[i].id === filter.id) {
612684
this.filters.splice(i, 1)
613-
this.enableAllProviders()
614685
break
615686
}
616687
}
@@ -649,9 +720,6 @@ export default defineComponent({
649720
this.filters.push(this.dateFilter)
650721
}
651722
652-
this.providers.forEach(async (provider, index) => {
653-
this.providers[index].disabled = !(await this.providerIsCompatibleWithFilters(provider, ['since', 'until']))
654-
})
655723
this.debouncedFind(this.searchQuery)
656724
},
657725
applyQuickDateRange(range) {
@@ -844,9 +912,27 @@ export default defineComponent({
844912
align-items: center;
845913
display: flex;
846914
}
915+
916+
&--unfiltered {
917+
opacity: 0.7;
918+
}
847919
}
848920
849921
}
922+
923+
&__unfiltered-header {
924+
display: flex;
925+
flex-direction: column;
926+
gap: 2px;
927+
margin-block: 16px 8px;
928+
padding-block: 12px 0;
929+
border-top: 1px solid var(--color-border);
930+
}
931+
932+
&__unfiltered-label {
933+
font-weight: bold;
934+
color: var(--color-text-maxcontrast);
935+
}
850936
}
851937
852938
.filter-button__icon {

dist/core-unified-search.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/core-unified-search.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)