Skip to content

Commit 4f4cec2

Browse files
committed
Use new SearchableList component for people filter
This commit migrates away from NcSelect which has a couple of accesibility and display problems currently, hence a new component `SearchableList` is now used. Signed-off-by: fenn-cs <fenn25.fn@gmail.com>
1 parent 8feacd0 commit 4f4cec2

File tree

3 files changed

+63
-59
lines changed

3 files changed

+63
-59
lines changed

core/src/components/GlobalSearch/SearchFilterChip.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ export default {
4747
display: flex;
4848
align-items: center;
4949
padding-right: 5px;
50-
filter: grayscale(100%) invert(100%);
5150
5251
img {
5352
width: 20px;

core/src/components/GlobalSearch/SearchableList.vue

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
-->
2222

2323
<template>
24-
<NcPopover>
24+
<NcPopover :shown="opened">
2525
<template #trigger>
2626
<slot name="trigger" />
2727
</template>
@@ -35,17 +35,17 @@
3535
</NcTextField>
3636
<ul v-if="filteredList.length > 0" class="searchable-list__list">
3737
<li v-for="element in filteredList"
38-
:key="element"
39-
:title="element"
38+
:key="element.id"
39+
:title="element.displayName"
4040
role="button">
4141
<NcButton alignment="start"
4242
type="tertiary"
4343
:wide="true"
44-
@click="$emit(element)">
44+
@click="itemSelected(element)">
4545
<template #icon>
46-
<NcAvatar :display-name="element" :hide-favorite="false" />
46+
<NcAvatar :user="element.user" :show-user-status="false" :hide-favorite="false" />
4747
</template>
48-
{{ element }}
48+
{{ element.displayName }}
4949
</NcButton>
5050
</li>
5151
</ul>
@@ -98,6 +98,7 @@ export default {
9898
9999
data() {
100100
return {
101+
opened: false,
101102
error: false,
102103
searchTerm: '',
103104
}
@@ -106,7 +107,10 @@ export default {
106107
computed: {
107108
filteredList() {
108109
return this.searchList.filter((element) => {
109-
return element.toLowerCase().includes(this.searchTerm.toLowerCase())
110+
if (!this.searchTerm.toLowerCase().length) {
111+
return true
112+
}
113+
return ['displayName'].some(prop => element[prop].toLowerCase().includes(this.searchTerm.toLowerCase()))
110114
})
111115
},
112116
},
@@ -115,12 +119,16 @@ export default {
115119
clearSearch() {
116120
this.searchTerm = ''
117121
},
122+
itemSelected(element) {
123+
this.$emit('item-selected', element)
124+
this.clearSearch()
125+
this.opened = false
126+
},
118127
},
119128
}
120129
</script>
121130

122131
<style lang="scss" scoped>
123-
124132
.searchable-list {
125133
&__wrapper {
126134
padding: calc(var(--default-grid-baseline) * 3);

core/src/views/GlobalSearchModal.vue

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,19 @@
5252
{{ t('core', 'Custom date range') }}
5353
</NcActionButton>
5454
</NcActions>
55-
<NcSelect v-bind="peopleSeclectProps"
56-
v-model="peopleSeclectProps.value"
57-
@search="filterContacts"
58-
@option:selected="applyPersonFilter" />
55+
<SearchableList :label-text="t('core', 'Search people')"
56+
:search-list="userContacts"
57+
:empty-content-text="t('core', 'Not found')"
58+
@item-selected="applyPersonFilter">
59+
<template #trigger>
60+
<NcButton>
61+
<template #icon>
62+
<AccountGroup :size="20" />
63+
</template>
64+
{{ t('core', 'People') }}
65+
</NcButton>
66+
</template>
67+
</SearchableList>
5968
</div>
6069
<div class="global-search-modal__filters-applied">
6170
<FilterChip v-for="filter in filters"
@@ -64,7 +73,10 @@
6473
:pretext="''"
6574
@delete="removeFilter(filter)">
6675
<template #icon>
67-
<AccountIcon v-if="filter.type === 'person'" />
76+
<NcAvatar v-if="filter.type === 'person'"
77+
:user="filter.user"
78+
:show-user-status="false"
79+
:hide-favorite="false" />
6880
<CalendarRangeIcon v-else-if="filter.type === 'date'" />
6981
<img v-else :src="filter.icon" alt="">
7082
</template>
@@ -130,44 +142,46 @@
130142

131143
<script>
132144
import ArrowRight from 'vue-material-design-icons/ArrowRight.vue'
133-
import AccountIcon from 'vue-material-design-icons/AccountCircle.vue'
145+
import AccountGroup from 'vue-material-design-icons/AccountGroup.vue'
134146
import CalendarRangeIcon from 'vue-material-design-icons/CalendarRange.vue'
135147
import CustomDateRangeModal from '../components/GlobalSearch/CustomDateRangeModal.vue'
136148
import DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'
137149
import FilterChip from '../components/GlobalSearch/SearchFilterChip.vue'
138150
import ListBox from 'vue-material-design-icons/ListBox.vue'
139151
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
140152
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
153+
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
141154
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
142155
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
143156
import NcInputField from '@nextcloud/vue/dist/Components/NcInputField.js'
144157
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
145158
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
146-
import NcSelect from '@nextcloud/vue/dist/Components/NcSelect.js'
147159
import MagnifyIcon from 'vue-material-design-icons/Magnify.vue'
160+
import SearchableList from '../components/GlobalSearch/SearchableList.vue'
148161
149162
import debounce from 'debounce'
150163
import { getProviders, search as globalSearch, getContacts } from '../services/GlobalSearchService.js'
151164
152165
export default {
153166
name: 'GlobalSearchModal',
154167
components: {
155-
AccountIcon,
156168
ArrowRight,
169+
AccountGroup,
157170
CalendarRangeIcon,
158171
CustomDateRangeModal,
159172
DotsHorizontalIcon,
160173
FilterChip,
161174
ListBox,
162175
NcActions,
163176
NcActionButton,
177+
NcAvatar,
164178
NcButton,
165179
NcEmptyContent,
166180
NcModal,
167181
NcListItem,
168-
NcSelect,
169182
NcInputField,
170183
MagnifyIcon,
184+
SearchableList,
171185
},
172186
props: {
173187
isVisible: {
@@ -182,7 +196,7 @@ export default {
182196
dateActionMenuIsOpen: false,
183197
providerResultLimit: 5,
184198
dateFilter: { id: 'date', type: 'date', text: '', startFrom: null, endAt: null },
185-
personFilter: { id: 'person', type: 'person', text: '' },
199+
personFilter: { id: 'person', type: 'person', name: '' },
186200
dateFilterIsApplied: false,
187201
personFilterIsApplied: false,
188202
filteredProviders: [],
@@ -198,17 +212,9 @@ export default {
198212
},
199213
200214
computed: {
201-
peopleSeclectProps: {
215+
userContacts: {
202216
get() {
203-
return {
204-
// inputId: getRandomId(),
205-
userSelect: true,
206-
label: t('core', 'People filter'),
207-
placeholder: t('core', 'Search people'),
208-
placement: 'top',
209-
options: this.contacts,
210-
value: null,
211-
}
217+
return this.contacts
212218
},
213219
214220
},
@@ -258,7 +264,7 @@ export default {
258264
}
259265
}
260266
261-
if (this.providerResultLimit > 5) {
267+
if (this.providerResultLimit > 5) {
262268
params.limit = this.providerResultLimit
263269
}
264270
@@ -345,7 +351,18 @@ export default {
345351
},
346352
applyPersonFilter(person) {
347353
this.personFilterIsApplied = true
348-
this.personFilter.id = person.id
354+
const existingPersonFilter = this.filters.findIndex(filter => filter.id === person.id)
355+
if (existingPersonFilter === -1) {
356+
this.personFilter.id = person.id
357+
this.personFilter.user = person.user
358+
this.personFilter.name = person.displayName
359+
this.filters.push(this.personFilter)
360+
} else {
361+
this.filters[existingPersonFilter].id = person.id
362+
this.filters[existingPersonFilter].user = person.user
363+
this.filters[existingPersonFilter].name = person.displayName
364+
}
365+
349366
this.debouncedFind(this.searchQuery)
350367
console.debug('Person filter applied', person)
351368
},
@@ -504,39 +521,19 @@ $margin: 10px;
504521
&__filters {
505522
display: flex;
506523
padding-top: 5px;
507-
align-items: center;
508524
justify-content: space-between;
509525
510-
/* Overwrite NcSelect styles */
511-
::v-deep div.v-select {
512-
min-width: 0; // reset NcSelect min width
513-
514-
div.vs__dropdown-toggle {
515-
height: 44px; // Overwrite height of NcSelect component to match button
516-
}
526+
>*:not(:last-child) {
527+
// flex: 1;
528+
margin-right: 0.5m;
517529
}
518530
519-
::v-deep>* {
520-
min-width: auto;
521-
/* Reset hard set min widths */
522-
min-height: 0;
523-
/* Reset any min heights */
524-
display: flex;
525-
align-items: center;
526-
flex: 1;
527-
528-
>* {
529-
flex: 1;
530-
min-width: auto;
531-
/* Reset hard set min widths */
532-
min-height: 0;
531+
>* {
532+
button {
533+
min-width: 160px;
533534
}
534-
535535
}
536536
537-
::v-deep>*:not(:last-child) {
538-
margin: 0 2px;
539-
}
540537
}
541538
542539
&__filters-applied {
@@ -641,9 +638,9 @@ div.v-popper__wrapper {
641638
img {
642639
width: 24px;
643640
margin: 0 4px;
644-
// filter: invert(100%) grayscale(1) contrast(100) brightness(1);
645-
filter: grayscale(100%);
641+
filter: var(--background-invert-if-bright);
646642
}
643+
647644
}
648645
}
649646
}

0 commit comments

Comments
 (0)