feat: move lists between namespaces (#1430)
Frontend implementation of https://kolaente.dev/vikunja/api/pulls/1096 I've implemented this re-using the drag and drop part of rearranging the list position in the menu. The only problem we have is there's no way to check if a namespace is read-only and disable dropping a list into it. I hope to solve this in the future on the api but for now you can drop a list into it and get an error message. I felt like properly handling the error and restoring the list and its position given this will change anyway. Co-authored-by: kolaente <k@knt.li> Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/1430 Reviewed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de> Co-authored-by: konrad <k@knt.li> Co-committed-by: konrad <k@knt.li>
This commit is contained in:
parent
f5a92d1aec
commit
c98ab42e75
2 changed files with 21 additions and 15 deletions
|
@ -90,13 +90,15 @@
|
||||||
v-bind="dragOptions"
|
v-bind="dragOptions"
|
||||||
:modelValue="activeLists[nk]"
|
:modelValue="activeLists[nk]"
|
||||||
@update:modelValue="(lists) => updateActiveLists(n, lists)"
|
@update:modelValue="(lists) => updateActiveLists(n, lists)"
|
||||||
:group="`namespace-${n.id}-lists`"
|
group="namespace-lists"
|
||||||
@start="() => drag = true"
|
@start="() => drag = true"
|
||||||
@end="e => saveListPosition(e, nk)"
|
@end="saveListPosition"
|
||||||
handle=".handle"
|
handle=".handle"
|
||||||
:disabled="n.id < 0 || null"
|
:disabled="n.id < 0 || null"
|
||||||
tag="transition-group"
|
tag="transition-group"
|
||||||
item-key="id"
|
item-key="id"
|
||||||
|
:data-namespace-id="n.id"
|
||||||
|
:data-namespace-index="nk"
|
||||||
:component-data="{
|
:component-data="{
|
||||||
type: 'transition',
|
type: 'transition',
|
||||||
tag: 'ul',
|
tag: 'ul',
|
||||||
|
@ -198,7 +200,7 @@ export default {
|
||||||
loading: state => state[LOADING] && state[LOADING_MODULE] === 'namespaces',
|
loading: state => state[LOADING] && state[LOADING_MODULE] === 'namespaces',
|
||||||
}),
|
}),
|
||||||
activeLists() {
|
activeLists() {
|
||||||
return this.namespaces.map(({lists}) => lists?.filter(item => !item.isArchived))
|
return this.namespaces.map(({lists}) => lists?.filter(item => typeof item !== 'undefined' && !item.isArchived))
|
||||||
},
|
},
|
||||||
namespaceTitles() {
|
namespaceTitles() {
|
||||||
return this.namespaces.map((namespace) => this.getNamespaceTitle(namespace))
|
return this.namespaces.map((namespace) => this.getNamespaceTitle(namespace))
|
||||||
|
@ -241,15 +243,15 @@ export default {
|
||||||
this.listsVisible[namespaceId] = !this.listsVisible[namespaceId]
|
this.listsVisible[namespaceId] = !this.listsVisible[namespaceId]
|
||||||
},
|
},
|
||||||
updateActiveLists(namespace, activeLists) {
|
updateActiveLists(namespace, activeLists) {
|
||||||
// this is a bit hacky: since we do have to filter out the archived items from the list
|
// This is a bit hacky: since we do have to filter out the archived items from the list
|
||||||
// for vue draggable updating it is not as simple as replacing it.
|
// for vue draggable updating it is not as simple as replacing it.
|
||||||
// instead we iterate over the non archived items in the old list and replace them with the ones in their new order
|
// To work around this, we merge the active lists with the archived ones. Doing so breaks the order
|
||||||
const lists = namespace.lists.map((item) => {
|
// because now all archived lists are sorted after the active ones. This is fine because they are sorted
|
||||||
if (item.isArchived) {
|
// later when showing them anyway, and it makes the merging happening here a lot easier.
|
||||||
return item
|
const lists = [
|
||||||
}
|
...activeLists,
|
||||||
return activeLists.shift()
|
...namespace.lists.filter(l => l.isArchived),
|
||||||
})
|
]
|
||||||
|
|
||||||
const newNamespace = {
|
const newNamespace = {
|
||||||
...namespace,
|
...namespace,
|
||||||
|
@ -259,8 +261,11 @@ export default {
|
||||||
this.$store.commit('namespaces/setNamespaceById', newNamespace)
|
this.$store.commit('namespaces/setNamespaceById', newNamespace)
|
||||||
},
|
},
|
||||||
|
|
||||||
async saveListPosition(e, namespaceIndex) {
|
async saveListPosition(e) {
|
||||||
const listsActive = this.activeLists[namespaceIndex]
|
const namespaceId = parseInt(e.to.dataset.namespaceId)
|
||||||
|
const newNamespaceIndex = parseInt(e.to.dataset.namespaceIndex)
|
||||||
|
|
||||||
|
const listsActive = this.activeLists[newNamespaceIndex]
|
||||||
const list = listsActive[e.newIndex]
|
const list = listsActive[e.newIndex]
|
||||||
const listBefore = listsActive[e.newIndex - 1] ?? null
|
const listBefore = listsActive[e.newIndex - 1] ?? null
|
||||||
const listAfter = listsActive[e.newIndex + 1] ?? null
|
const listAfter = listsActive[e.newIndex + 1] ?? null
|
||||||
|
@ -273,6 +278,7 @@ export default {
|
||||||
await this.$store.dispatch('lists/updateList', {
|
await this.$store.dispatch('lists/updateList', {
|
||||||
...list,
|
...list,
|
||||||
position,
|
position,
|
||||||
|
namespaceId,
|
||||||
})
|
})
|
||||||
} finally {
|
} finally {
|
||||||
this.listUpdating[list.id] = false
|
this.listUpdating[list.id] = false
|
||||||
|
|
|
@ -134,8 +134,8 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
loadNamespacesIfFavoritesDontExist(ctx) {
|
loadNamespacesIfFavoritesDontExist(ctx) {
|
||||||
// The first namespace should be the one holding all favorites
|
// The first or second namespace should be the one holding all favorites
|
||||||
if (ctx.state.namespaces[0].id !== -2) {
|
if (ctx.state.namespaces[0].id !== -2 && ctx.state.namespaces[1]?.id !== -2) {
|
||||||
return ctx.dispatch('loadNamespaces')
|
return ctx.dispatch('loadNamespaces')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue