Add: fuzzy FollowList filtering

This commit is contained in:
Raphael Beer 2020-03-25 08:18:33 +01:00
parent e2b9e90b77
commit 76def5f901
No known key found for this signature in database
GPG Key ID: C1AC5E018B25EF11
2 changed files with 47 additions and 11 deletions

View File

@ -32,7 +32,7 @@ describe('FollowList.vue', () => {
}) })
describe('given a user with connections', () => { describe('given a user with connections', () => {
;['following', 'followedBy'].forEach(type => ;['following', 'followedBy'].forEach((type) =>
describe(`and type=${type}`, () => { describe(`and type=${type}`, () => {
let wrapper let wrapper
let queryMock let queryMock
@ -75,12 +75,6 @@ describe('FollowList.vue', () => {
}), }),
) )
}) })
describe('given more than 7 connections', () => {
it('displays them in an overflow container', () => {
wrapper.find('')
})
})
}) })
}) })

View File

@ -1,10 +1,20 @@
<template> <template>
<base-card style="position: relative; height: auto;"> <base-card style="position: relative; height: 424px;">
<ds-space v-if="this.connections && this.connections.length" margin="x-small"> <ds-space v-if="this.connections && this.connections.length" margin="x-small">
<ds-text tag="h5" color="soft"> <ds-text tag="h5" color="soft">
{{ userName | truncate(15) }} {{ $t(`profile.network.${type}`) }} {{ userName | truncate(15) }} {{ $t(`profile.network.${type}`) }}
</ds-text> </ds-text>
</ds-space> </ds-space>
<ds-space v-if="this.connections && this.connections.length > 7" margin="x-small">
<ds-input
ref="filter"
@input.native="setFilter"
placeholder="filter"
v-focus="true"
size="small"
icon="filter"
/>
</ds-space>
<template v-if="this.connections && this.connections.length <= 7"> <template v-if="this.connections && this.connections.length <= 7">
<ds-space v-for="follow in uniq(this.connections)" :key="follow.id" margin="x-small"> <ds-space v-for="follow in uniq(this.connections)" :key="follow.id" margin="x-small">
<!-- TODO: find better solution for rendering errors --> <!-- TODO: find better solution for rendering errors -->
@ -24,7 +34,11 @@
</template> </template>
<template v-else-if="this.connections.length > 7"> <template v-else-if="this.connections.length > 7">
<div class="overflow-container"> <div class="overflow-container">
<ds-space v-for="follow in uniq(this.connections)" :key="follow.id" margin="x-small"> <ds-space
v-for="follow in uniq(this.filteredConnections)"
:key="follow.id"
margin="x-small"
>
<client-only> <client-only>
<user-teaser :user="follow" /> <user-teaser :user="follow" />
</client-only> </client-only>
@ -32,7 +46,7 @@
</div> </div>
</template> </template>
<template v-else> <template v-else>
<p style="text-align: center; opacity: .5;"> <p style="text-align: center; opacity: 0.5;">
{{ userName }} {{ $t(`profile.network.${type}Nobody`) }} {{ userName }} {{ $t(`profile.network.${type}Nobody`) }}
</p> </p>
</template> </template>
@ -56,6 +70,7 @@ export default {
data() { data() {
return { return {
additionalConnections: [], additionalConnections: [],
filter: null,
queries: { queries: {
followedBy: followedByQuery, followedBy: followedByQuery,
following: followingQuery, following: followingQuery,
@ -70,6 +85,30 @@ export default {
connections() { connections() {
return [...this.user[this.type], ...this.additionalConnections] return [...this.user[this.type], ...this.additionalConnections]
}, },
filteredConnections() {
if (!this.filter) {
return this.connections
}
const fuzzyExpression = new RegExp(
`${this.filter.split('').reduce((part, c) => `${part}[^${c}]*${c}`)}`,
'i',
)
const fuzzyScores = this.connections
.map((user) => {
const match = user.name.match(fuzzyExpression)
return {
user,
score: match ? match[0].length * (match.index + 1) : -1,
}
})
.filter((score) => score.score !== -1)
.sort((a, b) => a.score - b.score)
return fuzzyScores.map((score) => score.user)
},
allConnectionsCount() { allConnectionsCount() {
return this.user[`${this.type}Count`] return this.user[`${this.type}Count`]
}, },
@ -86,13 +125,16 @@ export default {
}) })
this.additionalConnections = data.User[0][this.type] this.additionalConnections = data.User[0][this.type]
}, },
setFilter(evt) {
this.$set(this, 'filter', evt.target.value)
},
}, },
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.overflow-container { .overflow-container {
max-height: 350px; max-height: 300px;
overflow-y: auto; overflow-y: auto;
} }
</style> </style>