Implement searching in tasks

This commit is contained in:
Raimund Schlüßler 2019-01-24 21:01:02 +01:00
parent 3523269c1b
commit 0aed977e3f
No known key found for this signature in database
GPG key ID: 036FA7EB1A599178
4 changed files with 104 additions and 6 deletions

View file

@ -21,7 +21,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
-->
<template>
<li :task-id="task.uri"
<li v-show="showTask"
:task-id="task.uri"
:class="{done: task.completed}"
class="task-item"
>
@ -170,7 +171,8 @@ export default {
computed: {
...mapGetters({
sortOrder: 'sortOrder',
sortDirection: 'sortDirection'
sortDirection: 'sortDirection',
searchQuery: 'searchQuery',
}),
/**
* Returns the path of the task
@ -230,6 +232,20 @@ export default {
}
return sort([...subTasks], this.sortOrder, this.sortDirection)
},
/**
* Indicates whether we show the task because it matches the search.
*
* @returns {Boolean} If the task matches
*/
showTask: function() {
// If the task directly matches the search, we show it.
if (this.task.matches(this.searchQuery)) {
return true
}
// We also have to show tasks for which one sub(sub...)task matches.
return this.searchSubTasks(this.task)
},
},
methods: {
...mapActions([
@ -246,6 +262,21 @@ export default {
*/
overdue: overdue,
/**
* Checks if one of the tasks sub(sub-...)tasks matches the search query
*
* @param {Task} task The task to search in
* @returns {Boolean} If the task matches
*/
searchSubTasks(task) {
return Object.values(task.subTasks).some((subTask) => {
if (subTask.matches(this.searchQuery)) {
return true
}
return this.searchSubTasks(subTask)
})
},
/**
* Navigates to a different route, but checks if navigation is desired
*

View file

@ -94,10 +94,10 @@ OCA.Tasks.App = new Vue({
},
methods: {
filter(query) {
this.searchString = query
this.$store.commit('setSearchQuery', query)
},
cleanSearch() {
this.searchString = ''
this.$store.commit('setSearchQuery', '')
}
},
render: h => h(App)

View file

@ -95,6 +95,9 @@ export default class Task {
this._categories = categories ? categories.getValues() : []
this._modified = this.vtodo.getFirstPropertyValue('last-modified')
this._created = this.vtodo.getFirstPropertyValue('created')
this._searchQuery = ''
this._matchesSearchQuery = true
}
/**
@ -442,4 +445,45 @@ export default class Task {
this._created = this.vtodo.getFirstPropertyValue('created')
}
/**
* Checks if the task matches the search query
*
* @param {String} searchQuery The search string
* @returns {Boolean} If the task matches
*/
matches(searchQuery) {
// If the search query maches the previous search, we don't have to search again.
if (this._searchQuery === searchQuery) {
return this._matchesSearchQuery
}
// We cache the current search query for faster future comparison.
this._searchQuery = searchQuery
// If the search query is empty, the task matches by default.
if (!searchQuery) {
this._matchesSearchQuery = true
return this._matchesSearchQuery
}
// We search in these task properties
var keys = ['summary', 'note', 'categories']
// Make search case-insensitive.
searchQuery = searchQuery.toLowerCase()
for (const key of keys) {
// For the categories search the array
if (key === 'categories') {
for (const category of this[key]) {
if (category.toLowerCase().indexOf(searchQuery) > -1) {
this._matchesSearchQuery = true
return this._matchesSearchQuery
}
}
} else {
if (this[key].toLowerCase().indexOf(searchQuery) > -1) {
this._matchesSearchQuery = true
return this._matchesSearchQuery
}
}
}
this._matchesSearchQuery = false
return this._matchesSearchQuery
}
}

View file

@ -30,7 +30,8 @@ import TaskStatus from '../models/taskStatus'
Vue.use(Vuex)
const state = {
tasks: {}
tasks: {},
searchQuery: '',
}
const getters = {
@ -183,7 +184,19 @@ const getters = {
getParentTask: () => (task) => {
let tasks = task.calendar.tasks
return Object.values(tasks).find(search => search.uid === task.related) || null
}
},
/**
* Returns the current search query
*
* @param {Object} state The store data
* @param {Object} getters The store getters
* @param {Object} rootState The store root state
* @returns {String} The current search query
*/
searchQuery: (state, getters, rootState) => {
return state.searchQuery
},
}
const mutations = {
@ -485,6 +498,16 @@ const mutations = {
console.error('Error while replacing the following task ', task)
}
},
/**
* Sets the search query
*
* @param {Object} state The store data
* @param {String} searchQuery The search query
*/
setSearchQuery(state, searchQuery) {
state.searchQuery = searchQuery
},
}
const actions = {