diff --git a/core/src/components/UnifiedSearch/UnifiedSearchModal.vue b/core/src/components/UnifiedSearch/UnifiedSearchModal.vue
index 15d4098dd30..4f1c54a8b11 100644
--- a/core/src/components/UnifiedSearch/UnifiedSearchModal.vue
+++ b/core/src/components/UnifiedSearch/UnifiedSearchModal.vue
@@ -27,7 +27,7 @@
:label="t('core', 'Search apps, files, tags, messages') + '...'"
@update:value="debouncedFind" />
-
+
@@ -43,7 +43,7 @@
{{ provider.name }}
-
+
@@ -120,7 +120,8 @@
{{ t('core', 'Results') }}
-
+
+
{{ providerResult.name }}
@@ -144,6 +145,36 @@
+
+
+
+
+
+ {{ providerResult.name }}
+
+
+
+
+
@@ -321,6 +352,50 @@ export default defineComponent({
debouncedFilterContacts() {
return debounce(this.filterContacts, 300)
},
+
+ hasContentFilters() {
+ return this.filters.some((filter) => filter.type === 'date' || filter.type === 'person')
+ },
+
+ filteredResults() {
+ const isInFolderAtRoot = (result) => {
+ if (result.id !== 'in-folder') {
+ return false
+ }
+ const path = result.extraParams?.path
+ return !path || path === '/' || path === ''
+ }
+
+ if (!this.hasContentFilters) {
+ return this.results.filter((result) => !isInFolderAtRoot(result))
+ }
+ return this.results.filter((result) => result.supportsActiveFilters === true && !isInFolderAtRoot(result))
+ },
+
+ filteredResultUrls() {
+ const urls = new Set()
+ this.filteredResults.forEach((provider) => {
+ provider.results.forEach((entry) => {
+ if (entry.resourceUrl) {
+ urls.add(entry.resourceUrl)
+ }
+ })
+ })
+ return urls
+ },
+
+ unfilteredResults() {
+ if (!this.hasContentFilters) {
+ return []
+ }
+ return this.results
+ .filter((result) => result.supportsActiveFilters === false)
+ .map((provider) => ({
+ ...provider,
+ results: provider.results.filter((entry) => !this.filteredResultUrls.has(entry.resourceUrl)),
+ }))
+ .filter((provider) => provider.results.length > 0)
+ },
},
watch: {
@@ -413,20 +488,30 @@ export default defineComponent({
// This block of filter checks should be dynamic somehow and should be handled in
// nextcloud/search lib
- const activeFilters = this.filters.filter(filter => {
+ const contentFilterTypes = this.filters
+ .filter((f) => f.type !== 'provider')
+ .map((f) => f.type)
+ const supportsActiveFilters = contentFilterTypes.length === 0
+ || contentFilterTypes.every((type) => this.providerIsCompatibleWithFilters(provider, [type]))
+
+ const baseProvider = provider.searchFrom
+ ? this.providers.find((p) => p.id === provider.searchFrom) ?? provider
+ : provider
+
+ const activeFilters = this.filters.filter((filter) => {
return filter.type !== 'provider' && this.providerIsCompatibleWithFilters(provider, [filter.type])
})
- activeFilters.forEach(filter => {
+ activeFilters.forEach((filter) => {
switch (filter.type) {
case 'date':
- if (provider.filters?.since && provider.filters?.until) {
+ if (baseProvider.filters?.since && baseProvider.filters?.until) {
params.since = this.dateFilter.startFrom
params.until = this.dateFilter.endAt
}
break
case 'person':
- if (provider.filters?.person) {
+ if (baseProvider.filters?.person) {
params.person = this.personFilter.user
}
break
@@ -445,6 +530,7 @@ export default defineComponent({
...provider,
results: response.data.ocs.data.entries,
limit: params.limit ?? 5,
+ supportsActiveFilters,
})
unifiedSearchLogger.debug('Unified search results:', { results: this.results, newResults })
@@ -716,8 +802,20 @@ export default defineComponent({
return flattenedArray
},
- async providerIsCompatibleWithFilters(provider, filterIds) {
- return filterIds.every(filterId => provider.filters?.[filterId] !== undefined)
+ providerIsCompatibleWithFilters(provider, filterIds) {
+ const baseProvider = provider.searchFrom
+ ? this.providers.find((p) => p.id === provider.searchFrom) ?? provider
+ : provider
+ return filterIds.every((filterId) => {
+ switch (filterId) {
+ case 'date':
+ return baseProvider.filters?.since !== undefined && baseProvider.filters?.until !== undefined
+ case 'person':
+ return baseProvider.filters?.person !== undefined
+ default:
+ return baseProvider.filters?.[filterId] !== undefined
+ }
+ })
},
async enableAllProviders() {
this.providers.forEach(async (_, index) => {
@@ -793,9 +891,27 @@ export default defineComponent({
align-items: center;
display: flex;
}
+
+ &--unfiltered {
+ opacity: 0.7;
+ }
}
}
+
+ &__unfiltered-header {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ margin-block: 16px 8px;
+ padding-block: 12px 0;
+ border-top: 1px solid var(--color-border);
+ }
+
+ &__unfiltered-label {
+ font-weight: bold;
+ color: var(--color-text-maxcontrast);
+ }
}
.filter-button__icon {