Implement searching in tasks
This commit is contained in:
parent
3523269c1b
commit
0aed977e3f
4 changed files with 104 additions and 6 deletions
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
|
|
Loading…
Reference in a new issue