1
0

feat: use flexsearch for all local searches (#997)

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/997
Reviewed-by: dpschen <dpschen@noreply.kolaente.de>
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
This commit is contained in:
konrad
2021-11-14 20:49:52 +00:00
parent 1fa164453c
commit 507a73e74c
11 changed files with 157 additions and 80 deletions

View File

@ -3,6 +3,9 @@ import {setLoading} from '@/store/helper'
import {success} from '@/message'
import {i18n} from '@/i18n'
import {getLabelsByIds, filterLabelsByQuery} from '@/helpers/labels'
import {createNewIndexer} from '@/indexes'
const {add, remove, update} = createNewIndexer('labels', ['title', 'description'])
async function getAllLabels(page = 1) {
const labelService = new LabelService()
@ -26,13 +29,16 @@ export default {
setLabels(state, labels) {
labels.forEach(l => {
state.labels[l.id] = l
add(l)
})
},
setLabel(state, label) {
state.labels[label.id] = label
update(label)
},
removeLabelById(state, label) {
delete state.labels[label.id]
remove(label)
},
setLoaded(state, loaded) {
state.loaded = loaded

View File

@ -1,6 +1,9 @@
import ListService from '@/services/list'
import {setLoading} from '@/store/helper'
import {removeListFromHistory} from '@/modules/listHistory.ts'
import {createNewIndexer} from '@/indexes'
const {add, remove, search, update} = createNewIndexer('lists', ['title', 'description'])
const FavoriteListsNamespace = -2
@ -11,14 +14,17 @@ export default {
mutations: {
setList(state, list) {
state[list.id] = list
update(list)
},
setLists(state, lists) {
lists.forEach(l => {
state[l.id] = l
add(l)
})
},
removeListById(state, list) {
delete state[list.id]
remove(list)
},
},
getters: {
@ -34,6 +40,13 @@ export default {
})
return typeof list === 'undefined' ? null : list
},
searchList: state => (query, includeArchived = false) => {
return search(query)
?.filter(value => value > 0)
.map(id => state[id])
.filter(list => list.isArchived === includeArchived)
|| []
},
},
actions: {
toggleListFavorite(ctx, list) {
@ -66,7 +79,7 @@ export default {
await listService.update(list)
ctx.commit('setList', list)
ctx.commit('namespaces/setListInNamespaceById', list, {root: true})
// the returned list from listService.update is the same!
// in order to not validate vuex mutations we have to create a new copy
const newList = {
@ -81,7 +94,7 @@ export default {
ctx.dispatch('namespaces/loadNamespacesIfFavoritesDontExist', null, {root: true})
ctx.dispatch('namespaces/removeFavoritesNamespaceIfEmpty', null, {root: true})
return newList
} catch(e) {
} catch (e) {
// Reset the list state to the initial one to avoid confusion for the user
ctx.commit('setList', {
...list,
@ -97,13 +110,13 @@ export default {
const cancel = setLoading(ctx, 'lists')
const listService = new ListService()
try {
try {
const response = await listService.delete(list)
ctx.commit('removeListById', list)
ctx.commit('namespaces/removeListFromNamespaceById', list, {root: true})
removeListFromHistory({id: list.id})
return response
} finally{
} finally {
cancel()
}
},

View File

@ -1,5 +1,8 @@
import NamespaceService from '../../services/namespace'
import {setLoading} from '@/store/helper'
import {createNewIndexer} from '@/indexes'
const {add, remove, search, update} = createNewIndexer('namespaces', ['title', 'description'])
export default {
namespaced: true,
@ -9,6 +12,9 @@ export default {
mutations: {
namespaces(state, namespaces) {
state.namespaces = namespaces
namespaces.forEach(n => {
add(n)
})
},
setNamespaceById(state, namespace) {
const namespaceIndex = state.namespaces.findIndex(n => n.id === namespace.id)
@ -22,8 +28,9 @@ export default {
if (!namespace.lists || namespace.lists.length === 0) {
namespace.lists = state.namespaces[namespaceIndex].lists
}
state.namespaces[namespaceIndex] = namespace
update(namespace)
},
setListInNamespaceById(state, list) {
for (const n in state.namespaces) {
@ -43,11 +50,13 @@ export default {
},
addNamespace(state, namespace) {
state.namespaces.push(namespace)
add(namespace)
},
removeNamespaceById(state, namespaceId) {
for (const n in state.namespaces) {
if (state.namespaces[n].id === namespaceId) {
state.namespaces.splice(n, 1)
remove(state.namespaces[n])
return
}
}
@ -78,11 +87,11 @@ export default {
getters: {
getListAndNamespaceById: state => (listId, ignorePseudoNamespaces = false) => {
for (const n in state.namespaces) {
if(ignorePseudoNamespaces && state.namespaces[n].id < 0) {
if (ignorePseudoNamespaces && state.namespaces[n].id < 0) {
continue
}
for (const l in state.namespaces[n].lists) {
if (state.namespaces[n].lists[l].id === listId) {
return {
@ -97,6 +106,13 @@ export default {
getNamespaceById: state => namespaceId => {
return state.namespaces.find(({id}) => id == namespaceId) || null
},
searchNamespace: (state, getters) => query => {
return search(query)
?.filter(value => value > 0)
.map(getters.getNamespaceById)
.filter(n => n !== null)
|| []
},
},
actions: {
async loadNamespaces(ctx) {
@ -107,12 +123,12 @@ export default {
// We always load all namespaces and filter them on the frontend
const namespaces = await namespaceService.getAll({}, {is_archived: true})
ctx.commit('namespaces', namespaces)
// Put all lists in the list state
const lists = namespaces.flatMap(({lists}) => lists)
ctx.commit('lists/setLists', lists, {root: true})
return namespaces
} finally {
cancel()