Add task filter for labels (#350)

Add task filter for labels

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/350
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
This commit is contained in:
konrad 2020-12-20 12:41:47 +00:00
parent 8c41cd54a8
commit 79335aaedf

View file

@ -131,6 +131,47 @@
</multiselect> </multiselect>
</div> </div>
</div> </div>
<div class="field">
<label class="label">Labels</label>
<div class="control">
<multiselect
:clear-on-select="true"
:close-on-select="false"
:hide-selected="true"
:internal-search="true"
:loading="labelService.loading"
:multiple="true"
:options="foundLabels"
:options-limit="300"
:searchable="true"
:showNoOptions="false"
@search-change="findLabels"
@select="label => addLabel(label)"
label="title"
placeholder="Type to search for a label..."
track-by="id"
v-model="labels"
>
<template
slot="tag"
slot-scope="{ option }">
<span
:style="{'background': option.hexColor, 'color': option.textColor}"
class="tag mr-2 mb-2">
<span>{{ option.title }}</span>
<a @click="removeLabel(option)" class="delete is-small"></a>
</span>
</template>
<template slot="clear" slot-scope="props">
<div
@mousedown.prevent.stop="clearLabels(props.search)"
class="multiselect__clear"
v-if="labels.length"></div>
</template>
</multiselect>
</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -147,7 +188,8 @@ import differenceWith from 'lodash/differenceWith'
import PrioritySelect from '@/components/tasks/partials/prioritySelect' import PrioritySelect from '@/components/tasks/partials/prioritySelect'
import PercentDoneSelect from '@/components/tasks/partials/percentDoneSelect' import PercentDoneSelect from '@/components/tasks/partials/percentDoneSelect'
import UserService from '../../../services/user' import UserService from '@/services/user'
import LabelService from '@/services/label'
export default { export default {
name: 'filters', name: 'filters',
@ -194,10 +236,15 @@ export default {
userService: UserService, userService: UserService,
foundUsers: [], foundUsers: [],
users: [], users: [],
labelService: LabelService,
foundLabels: [],
labels: [],
} }
}, },
created() { created() {
this.userService = new UserService() this.userService = new UserService()
this.labelService = new LabelService()
}, },
mounted() { mounted() {
this.params = this.value this.params = this.value
@ -459,6 +506,58 @@ export default {
this.$set(this.filters, 'assignees', userIDs.join(',')) this.$set(this.filters, 'assignees', userIDs.join(','))
this.setSingleValueFilter('assignees', 'assignees', '', 'in') this.setSingleValueFilter('assignees', 'assignees', '', 'in')
}, },
clearLabels() {
this.$set(this, 'foundLabels', [])
},
findLabels(query) {
if (query === '') {
this.clearLabels()
}
this.labelService.getAll({}, {s: query})
.then(response => {
// Filter the results to not include labels already selected
this.$set(this, 'foundLabels', differenceWith(response, this.labels, (first, second) => {
return first.id === second.id
}))
})
.catch(e => {
this.error(e, this)
})
},
addLabel() {
this.$nextTick(() => {
this.changeLabelFilter()
})
},
removeLabel(label) {
this.$nextTick(() => {
for (const l in this.labels) {
if (this.labels[l].id === label.id) {
this.labels.splice(l, 1)
}
break
}
this.changeLabelFilter()
})
},
changeLabelFilter() {
if (this.labels.length === 0) {
this.removePropertyFromFilter('labels')
this.change()
return
}
let labelIDs = []
this.labels.forEach(u => {
labelIDs.push(u.id)
})
this.$set(this.filters, 'labels', labelIDs.join(','))
this.setSingleValueFilter('labels', 'labels', '', 'in')
},
}, },
} }
</script> </script>