diff --git a/src/init-reference.js b/src/init-reference.js index 2b63245460..9a511cfbdd 100644 --- a/src/init-reference.js +++ b/src/init-reference.js @@ -21,6 +21,7 @@ import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue/dist/Functions/registerReference.js' import { translate, translatePlural } from '@nextcloud/l10n' +import storeFactory from './store/main.js' import './shared-init.js' @@ -67,6 +68,7 @@ registerWidget('deck-board', async (el, { richObjectType, richObject, accessible const { default: BoardReferenceWidget } = await import('./views/BoardReferenceWidget.vue') const Widget = await prepareVue(BoardReferenceWidget) boardWidgets[el] = new Widget({ + store: storeFactory(), propsData: { richObjectType, richObject, diff --git a/src/main.js b/src/main.js index 3fbafb9e73..f2797aa487 100644 --- a/src/main.js +++ b/src/main.js @@ -22,7 +22,7 @@ import Vue from 'vue' import App from './App.vue' import router from './router.js' -import store from './store/main.js' +import storeFactory from './store/main.js' import { sync } from 'vuex-router-sync' import { translate, translatePlural } from '@nextcloud/l10n' import { showError } from '@nextcloud/dialogs' @@ -30,12 +30,14 @@ import { subscribe } from '@nextcloud/event-bus' import ClickOutside from 'vue-click-outside' import './shared-init.js' import './models/index.js' -import './sessions.js' +import { initSessions } from './sessions.js' // the server snap.js conflicts with vertical scrolling so we disable it document.body.setAttribute('data-snap-ignore', 'true') +const store = storeFactory() sync(store, router) +initSessions(store) Vue.prototype.t = translate Vue.prototype.n = translatePlural diff --git a/src/sessions.js b/src/sessions.js index 0a7844f005..f23e711869 100644 --- a/src/sessions.js +++ b/src/sessions.js @@ -20,7 +20,6 @@ import { listen } from '@nextcloud/notify_push' import { sessionApi } from './services/SessionApi.js' -import store from './store/main.js' import axios from '@nextcloud/axios' const SESSION_INTERVAL = 90 // in seconds @@ -29,6 +28,8 @@ let hasPush = false let syncRunning = false +let store = null + /** * used to verify, whether an event is originated by ourselves * @@ -43,28 +44,35 @@ function isOurSessionToken(token) { } } -hasPush = listen('deck_board_update', (name, body) => { - // ignore update events which we have triggered ourselves - if (isOurSessionToken(body._causingSessionToken)) return +/** + * + * @param storeInstance + */ +export function initSessions(storeInstance) { + store = storeInstance + hasPush = listen('deck_board_update', (name, body) => { + // ignore update events which we have triggered ourselves + if (isOurSessionToken(body._causingSessionToken)) return - // only handle update events for the currently open board - const currentBoardId = store.state.currentBoard?.id - if (body.id !== currentBoardId) return + // only handle update events for the currently open board + const currentBoardId = store.state.currentBoard?.id + if (body.id !== currentBoardId) return - store.dispatch('refreshBoard', currentBoardId) -}) + store.dispatch('refreshBoard', currentBoardId) + }) -listen('deck_card_update', (name, body) => { + listen('deck_card_update', (name, body) => { - // ignore update events which we have triggered ourselves - if (isOurSessionToken(body._causingSessionToken)) return + // ignore update events which we have triggered ourselves + if (isOurSessionToken(body._causingSessionToken)) return - // only handle update events for the currently open board - const currentBoardId = store.state.currentBoard?.id - if (body.boardId !== currentBoardId) return + // only handle update events for the currently open board + const currentBoardId = store.state.currentBoard?.id + if (body.boardId !== currentBoardId) return - store.dispatch('loadStacks', currentBoardId) -}) + store.dispatch('loadStacks', currentBoardId) + }) +} /** * is the notify_push app active and can diff --git a/src/store/card.js b/src/store/card.js index fb4df408ce..b81c0eeb2d 100644 --- a/src/store/card.js +++ b/src/store/card.js @@ -26,358 +26,364 @@ import Vue from 'vue' const apiClient = new CardApi() -export default { - state: { - cards: [], - }, - getters: { - cardsByStack: (state, getters, rootState) => (id) => { - return state.cards.filter((card) => { - const { tags, users, due, unassigned, completed } = rootState.filter - - if (completed === 'open' && card.done !== null) { return false } - if (completed === 'completed' && card.done == null) { return false } - let allTagsMatch = true - let allUsersMatch = true +export default function cardModuleFactory() { + return { + state: { + cards: [], + }, + getters: { + cardsByStack: (state, getters, rootState) => (id) => { + return state.cards.filter((card) => { + const { tags, users, due, unassigned, completed } = rootState.filter - if (tags.length > 0) { - tags.forEach((tag) => { - if (card.labels.findIndex((l) => l.id === tag) === -1) { - allTagsMatch = false - } - }) - if (!allTagsMatch) { + if (completed === 'open' && card.done !== null) { return false } - } - - if (users.length > 0) { - users.forEach((user) => { - if (!card?.assignedUsers || card.assignedUsers.findIndex((u) => u.participant.uid === user) === -1) { - allUsersMatch = false - } - }) - if (!allUsersMatch) { + if (completed === 'completed' && card.done == null) { return false } - } - - if (unassigned && card.assignedUsers.length > 0) { - return false - } + let allTagsMatch = true + let allUsersMatch = true - if (due !== '') { - const datediffHour = ((new Date(card.duedate) - new Date()) / 3600 / 1000) - switch (due) { - case 'noDue': - return (card.duedate === null) - case 'overdue': - return (card.overdue === 3) - case 'dueToday': - return (card.overdue >= 2) - case 'dueWeek': - return (datediffHour <= 7 * 24 && card.duedate !== null) - case 'dueMonth': - return (datediffHour <= 30 * 24 && card.duedate !== null) + if (tags.length > 0) { + tags.forEach((tag) => { + if (card.labels.findIndex((l) => l.id === tag) === -1) { + allTagsMatch = false + } + }) + if (!allTagsMatch) { + return false + } } - } - return true - }) - .filter((card) => card.stackId === id) - .filter((card) => { - if (getters.getSearchQuery === '') { - return true + if (users.length > 0) { + users.forEach((user) => { + if (!card?.assignedUsers || card.assignedUsers.findIndex((u) => u.participant.uid === user) === -1) { + allUsersMatch = false + } + }) + if (!allUsersMatch) { + return false + } } - let hasMatch = true - const matches = getters.getSearchQuery.match(/(?:[^\s"]+|"[^"]*")+/g) + if (unassigned && card.assignedUsers.length > 0) { + return false + } - const filterOutQuotes = (q) => { - if (q[0] === '"' && q[q.length - 1] === '"') { - return q.slice(1, -1) + if (due !== '') { + const datediffHour = ((new Date(card.duedate) - new Date()) / 3600 / 1000) + switch (due) { + case 'noDue': + return (card.duedate === null) + case 'overdue': + return (card.overdue === 3) + case 'dueToday': + return (card.overdue >= 2) + case 'dueWeek': + return (datediffHour <= 7 * 24 && card.duedate !== null) + case 'dueMonth': + return (datediffHour <= 30 * 24 && card.duedate !== null) } - return q } - for (const match of matches) { - let [filter, query] = match.indexOf(':') !== -1 ? match.split(/:(.*)/) : [null, match] - const isEmptyQuery = typeof query === 'undefined' || filterOutQuotes(query) === '' - if (filter === 'title') { - if (isEmptyQuery) { - continue - } - hasMatch = hasMatch && card.title.toLowerCase().includes(filterOutQuotes(query).toLowerCase()) - } else if (filter === 'description') { - if (isEmptyQuery) { - hasMatch = hasMatch && !!card.description - continue - } - hasMatch = hasMatch && card.description.toLowerCase().includes(filterOutQuotes(query).toLowerCase()) - } else if (filter === 'list') { - if (isEmptyQuery) { - continue - } - const stack = getters.stackById(card.stackId) - if (!stack) { - return false - } - hasMatch = hasMatch && stack.title.toLowerCase().includes(filterOutQuotes(query).toLowerCase()) - } else if (filter === 'tag') { - if (isEmptyQuery) { - hasMatch = hasMatch && card.labels.length > 0 - continue - } - hasMatch = hasMatch && card.labels.findIndex((label) => label.title.toLowerCase().includes(filterOutQuotes(query).toLowerCase())) !== -1 - } else if (filter === 'date') { - const datediffHour = ((new Date(card.duedate) - new Date()) / 3600 / 1000) - query = filterOutQuotes(query) - switch (query) { - case 'overdue': - hasMatch = hasMatch && (card.overdue === 3) - break - case 'today': - hasMatch = hasMatch && (datediffHour > 0 && datediffHour <= 24 && card.duedate !== null) - break - case 'week': - hasMatch = hasMatch && (datediffHour > 0 && datediffHour <= 7 * 24 && card.duedate !== null) - break - case 'month': - hasMatch = hasMatch && (datediffHour > 0 && datediffHour <= 30 * 24 && card.duedate !== null) - break - case 'none': - hasMatch = hasMatch && (card.duedate === null) - break - } + return true + }) + .filter((card) => card.stackId === id) + .filter((card) => { + if (getters.getSearchQuery === '') { + return true + } - if (card.duedate === null || !hasMatch) { - return false - } - const comparator = query[0] + (query[1] === '=' ? '=' : '') - const isValidComparator = ['<', '<=', '>', '>='].indexOf(comparator) !== -1 - const parsedCardDate = moment(card.duedate) - const parsedDate = moment(query.slice(isValidComparator ? comparator.length : 0)) - switch (comparator) { - case '<': - hasMatch = hasMatch && parsedCardDate.isBefore(parsedDate) - break - case '<=': - hasMatch = hasMatch && parsedCardDate.isSameOrBefore(parsedDate) - break - case '>': - hasMatch = hasMatch && parsedCardDate.isAfter(parsedDate) - break - case '>=': - hasMatch = hasMatch && parsedCardDate.isSameOrAfter(parsedDate) - break - default: - hasMatch = hasMatch && parsedCardDate.isSame(parsedDate) - break - } + let hasMatch = true + const matches = getters.getSearchQuery.match(/(?:[^\s"]+|"[^"]*")+/g) - } else if (filter === 'assigned') { - if (isEmptyQuery) { - hasMatch = hasMatch && card.assignedUsers.length > 0 - continue + const filterOutQuotes = (q) => { + if (q[0] === '"' && q[q.length - 1] === '"') { + return q.slice(1, -1) } - hasMatch = hasMatch && card.assignedUsers.findIndex((assignment) => { - return assignment.participant.primaryKey.toLowerCase() === filterOutQuotes(query).toLowerCase() - || assignment.participant.displayname.toLowerCase() === filterOutQuotes(query).toLowerCase() - }) !== -1 - } else { - hasMatch = hasMatch && (card.title.toLowerCase().includes(filterOutQuotes(match).toLowerCase()) - || card.description.toLowerCase().includes(filterOutQuotes(match).toLowerCase()) || card.id === parseInt(filterOutQuotes(match))) + return q } - if (!hasMatch) { - return false + for (const match of matches) { + let [filter, query] = match.indexOf(':') !== -1 ? match.split(/:(.*)/) : [null, match] + const isEmptyQuery = typeof query === 'undefined' || filterOutQuotes(query) === '' + + if (filter === 'title') { + if (isEmptyQuery) { + continue + } + hasMatch = hasMatch && card.title.toLowerCase().includes(filterOutQuotes(query).toLowerCase()) + } else if (filter === 'description') { + if (isEmptyQuery) { + hasMatch = hasMatch && !!card.description + continue + } + hasMatch = hasMatch && card.description.toLowerCase().includes(filterOutQuotes(query).toLowerCase()) + } else if (filter === 'list') { + if (isEmptyQuery) { + continue + } + const stack = getters.stackById(card.stackId) + if (!stack) { + return false + } + hasMatch = hasMatch && stack.title.toLowerCase().includes(filterOutQuotes(query).toLowerCase()) + } else if (filter === 'tag') { + if (isEmptyQuery) { + hasMatch = hasMatch && card.labels.length > 0 + continue + } + hasMatch = hasMatch && card.labels.findIndex((label) => label.title.toLowerCase().includes(filterOutQuotes(query).toLowerCase())) !== -1 + } else if (filter === 'date') { + const datediffHour = ((new Date(card.duedate) - new Date()) / 3600 / 1000) + query = filterOutQuotes(query) + switch (query) { + case 'overdue': + hasMatch = hasMatch && (card.overdue === 3) + break + case 'today': + hasMatch = hasMatch && (datediffHour > 0 && datediffHour <= 24 && card.duedate !== null) + break + case 'week': + hasMatch = hasMatch && (datediffHour > 0 && datediffHour <= 7 * 24 && card.duedate !== null) + break + case 'month': + hasMatch = hasMatch && (datediffHour > 0 && datediffHour <= 30 * 24 && card.duedate !== null) + break + case 'none': + hasMatch = hasMatch && (card.duedate === null) + break + } + + if (card.duedate === null || !hasMatch) { + return false + } + const comparator = query[0] + (query[1] === '=' ? '=' : '') + const isValidComparator = ['<', '<=', '>', '>='].indexOf(comparator) !== -1 + const parsedCardDate = moment(card.duedate) + const parsedDate = moment(query.slice(isValidComparator ? comparator.length : 0)) + switch (comparator) { + case '<': + hasMatch = hasMatch && parsedCardDate.isBefore(parsedDate) + break + case '<=': + hasMatch = hasMatch && parsedCardDate.isSameOrBefore(parsedDate) + break + case '>': + hasMatch = hasMatch && parsedCardDate.isAfter(parsedDate) + break + case '>=': + hasMatch = hasMatch && parsedCardDate.isSameOrAfter(parsedDate) + break + default: + hasMatch = hasMatch && parsedCardDate.isSame(parsedDate) + break + } + + } else if (filter === 'assigned') { + if (isEmptyQuery) { + hasMatch = hasMatch && card.assignedUsers.length > 0 + continue + } + hasMatch = hasMatch && card.assignedUsers.findIndex((assignment) => { + return assignment.participant.primaryKey.toLowerCase() === filterOutQuotes(query).toLowerCase() + || assignment.participant.displayname.toLowerCase() === filterOutQuotes(query).toLowerCase() + }) !== -1 + } else { + hasMatch = hasMatch && (card.title.toLowerCase().includes(filterOutQuotes(match).toLowerCase()) + || card.description.toLowerCase().includes(filterOutQuotes(match).toLowerCase()) || card.id === parseInt(filterOutQuotes(match))) + } + if (!hasMatch) { + return false + } } - } - return true - }) - .sort((a, b) => a.order - b.order || a.createdAt - b.createdAt) - }, - cardById: state => (id) => { - return state.cards.find((card) => card.id === id) - }, - }, - mutations: { - addCard(state, card) { - card.labels = card.labels || [] - card.assignedUsers = card.assignedUsers || [] - const existingIndex = state.cards.findIndex(_card => _card.id === card.id) - if (existingIndex !== -1) { - const existingCard = state.cards.find(_card => _card.id === card.id) - Vue.set(state.cards, existingIndex, Object.assign({}, existingCard, card)) - } else { - state.cards.push(card) - } - }, - deleteCard(state, card) { - const existingIndex = state.cards.findIndex(_card => _card.id === card.id) - if (existingIndex !== -1) { - state.cards.splice(existingIndex, 1) - } - }, - updateCard(state, card) { - const existingIndex = state.cards.findIndex(_card => _card.id === card.id) - if (existingIndex !== -1) { - Vue.set(state.cards, existingIndex, Object.assign({}, state.cards[existingIndex], card)) - } + return true + }) + .sort((a, b) => a.order - b.order || a.createdAt - b.createdAt) + }, + cardById: state => (id) => { + return state.cards.find((card) => card.id === id) + }, }, - updateCardsReorder(state, cards) { - for (const newCard of cards) { - const existingIndex = state.cards.findIndex(_card => _card.id === newCard.id) + mutations: { + addCard(state, card) { + card.labels = card.labels || [] + card.assignedUsers = card.assignedUsers || [] + const existingIndex = state.cards.findIndex(_card => _card.id === card.id) if (existingIndex !== -1) { - Vue.set(state.cards[existingIndex], 'order', newCard.order) - Vue.set(state.cards[existingIndex], 'stackId', newCard.stackId) + const existingCard = state.cards.find(_card => _card.id === card.id) + Vue.set(state.cards, existingIndex, Object.assign({}, existingCard, card)) + } else { + state.cards.push(card) } - } - }, - assignCardToUser(state, user) { - const existingIndex = state.cards.findIndex(_card => _card.id === user.cardId) - if (existingIndex !== -1) { - state.cards[existingIndex].assignedUsers.push(user) - } - }, - removeUserFromCard(state, user) { - const existingIndex = state.cards.findIndex(_card => _card.id === user.cardId) - if (existingIndex !== -1) { - const foundIndex = state.cards[existingIndex].assignedUsers.findIndex(_user => _user.id === user.id) - if (foundIndex !== -1) { - state.cards[existingIndex].assignedUsers.splice(foundIndex, 1) + }, + deleteCard(state, card) { + const existingIndex = state.cards.findIndex(_card => _card.id === card.id) + if (existingIndex !== -1) { + state.cards.splice(existingIndex, 1) } - } - }, - updateCardProperty(state, { card, property }) { - const existingIndex = state.cards.findIndex(_card => _card.id === card.id) - if (existingIndex !== -1) { - Vue.set(state.cards[existingIndex], property, card[property]) - Vue.set(state.cards[existingIndex], 'lastModified', Date.now() / 1000) - } - }, - cardSetAttachmentCount(state, { cardId, count }) { - const existingIndex = state.cards.findIndex(_card => _card.id === cardId) - if (existingIndex !== -1) { - Vue.set(state.cards[existingIndex], 'attachmentCount', count) - } - }, - cardIncreaseAttachmentCount(state, cardId) { - const existingIndex = state.cards.findIndex(_card => _card.id === cardId) - if (existingIndex !== -1) { - Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount + 1) - } - }, - cardDecreaseAttachmentCount(state, cardId) { - const existingIndex = state.cards.findIndex(_card => _card.id === cardId) - if (existingIndex !== -1) { - Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount - 1) - } - }, - addNewCard(state, card) { - state.cards.push(card) - }, - setCards(state, cards) { - const deletedCards = state.cards.filter(_card => { - return cards.findIndex(c => _card.id === c.id) === -1 - }) - for (const card of deletedCards) { - this.commit('deleteCard', card) - } - for (const card of cards) { - this.commit('addCard', card) - } - }, - }, - actions: { - async addCard({ commit }, card) { - const createdCard = await apiClient.addCard(card) - commit('addCard', createdCard) - return createdCard - }, - async updateCardTitle({ commit }, card) { - const updatedCard = await apiClient.updateCard(card) - commit('updateCardProperty', { property: 'title', card: updatedCard }) - }, - async moveCard({ commit }, card) { - const updatedCard = await apiClient.updateCard(card) - commit('deleteCard', updatedCard) - }, - async reorderCard({ commit, getters }, card) { - let i = 0 - const newCards = [] - for (const c of getters.cardsByStack(card.stackId)) { - if (c.id === card.id) { - newCards.push(card) + }, + updateCard(state, card) { + const existingIndex = state.cards.findIndex(_card => _card.id === card.id) + if (existingIndex !== -1) { + Vue.set(state.cards, existingIndex, Object.assign({}, state.cards[existingIndex], card)) } - if (i === card.order) { - i++ + }, + updateCardsReorder(state, cards) { + for (const newCard of cards) { + const existingIndex = state.cards.findIndex(_card => _card.id === newCard.id) + if (existingIndex !== -1) { + Vue.set(state.cards[existingIndex], 'order', newCard.order) + Vue.set(state.cards[existingIndex], 'stackId', newCard.stackId) + } } - if (c.id !== card.id) { - newCards.push({ ...c, order: i++ }) + }, + assignCardToUser(state, user) { + const existingIndex = state.cards.findIndex(_card => _card.id === user.cardId) + if (existingIndex !== -1) { + state.cards[existingIndex].assignedUsers.push(user) } - } - newCards.push(card) - await commit('updateCardsReorder', newCards) - - apiClient.reorderCard(card).then((cards) => { - commit('updateCardsReorder', Object.values(cards)) - }) - }, - async deleteCard({ commit }, card) { - await apiClient.deleteCard(card.id) - commit('deleteCard', card) - commit('moveCardToTrash', card) + }, + removeUserFromCard(state, user) { + const existingIndex = state.cards.findIndex(_card => _card.id === user.cardId) + if (existingIndex !== -1) { + const foundIndex = state.cards[existingIndex].assignedUsers.findIndex(_user => _user.id === user.id) + if (foundIndex !== -1) { + state.cards[existingIndex].assignedUsers.splice(foundIndex, 1) + } + } + }, + updateCardProperty(state, { card, property }) { + const existingIndex = state.cards.findIndex(_card => _card.id === card.id) + if (existingIndex !== -1) { + Vue.set(state.cards[existingIndex], property, card[property]) + Vue.set(state.cards[existingIndex], 'lastModified', Date.now() / 1000) + } + }, + cardSetAttachmentCount(state, { cardId, count }) { + const existingIndex = state.cards.findIndex(_card => _card.id === cardId) + if (existingIndex !== -1) { + Vue.set(state.cards[existingIndex], 'attachmentCount', count) + } + }, + cardIncreaseAttachmentCount(state, cardId) { + const existingIndex = state.cards.findIndex(_card => _card.id === cardId) + if (existingIndex !== -1) { + Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount + 1) + } + }, + cardDecreaseAttachmentCount(state, cardId) { + const existingIndex = state.cards.findIndex(_card => _card.id === cardId) + if (existingIndex !== -1) { + Vue.set(state.cards[existingIndex], 'attachmentCount', state.cards[existingIndex].attachmentCount - 1) + } + }, + addNewCard(state, card) { + state.cards.push(card) + }, + setCards(state, cards) { + const deletedCards = state.cards.filter(_card => { + return cards.findIndex(c => _card.id === c.id) === -1 + }) + for (const card of deletedCards) { + this.commit('deleteCard', card) + } + for (const card of cards) { + this.commit('addCard', card) + } + }, }, - async archiveUnarchiveCard({ commit }, card) { - let call = 'archiveCard' - if (card.archived === false) { - call = 'unArchiveCard' - } + actions: { + async addCard({ commit }, card) { + const createdCard = await apiClient.addCard(card) + commit('addCard', createdCard) + return createdCard + }, + async updateCardTitle({ commit }, card) { + const updatedCard = await apiClient.updateCard(card) + commit('updateCardProperty', { property: 'title', card: updatedCard }) + }, + async moveCard({ commit }, card) { + const updatedCard = await apiClient.updateCard(card) + commit('deleteCard', updatedCard) + }, + async reorderCard({ commit, getters }, card) { + let i = 0 + const newCards = [] + for (const c of getters.cardsByStack(card.stackId)) { + if (c.id === card.id) { + newCards.push(card) + } + if (i === card.order) { + i++ + } + if (c.id !== card.id) { + newCards.push({ ...c, order: i++ }) + } + } + newCards.push(card) + await commit('updateCardsReorder', newCards) - const updatedCard = await apiClient[call](card) - commit('updateCard', updatedCard) - }, - async changeCardDoneStatus({ commit }, card) { - let call = 'markCardAsDone' - if (card.done === false) { - call = 'markCardAsUndone' - } + apiClient.reorderCard(card).then((cards) => { + commit('updateCardsReorder', Object.values(cards)) + }) + }, + async deleteCard({ commit }, card) { + await apiClient.deleteCard(card.id) + commit('deleteCard', card) + commit('moveCardToTrash', card) + }, + async archiveUnarchiveCard({ commit }, card) { + let call = 'archiveCard' + if (card.archived === false) { + call = 'unArchiveCard' + } - const updatedCard = await apiClient[call](card) - commit('updateCardProperty', { property: 'done', card: updatedCard }) - }, - async assignCardToUser({ commit }, { card, assignee }) { - const user = await apiClient.assignUser(card.id, assignee.userId, assignee.type) - commit('assignCardToUser', user) - }, - async removeUserFromCard({ commit }, { card, assignee }) { - const user = await apiClient.removeUser(card.id, assignee.userId, assignee.type) - commit('removeUserFromCard', user) - }, - async addLabel({ commit }, data) { - await apiClient.assignLabelToCard(data) - commit('updateCardProperty', { property: 'labels', card: data.card }) - }, - async removeLabel({ commit }, data) { - await apiClient.removeLabelFromCard(data) - commit('updateCardProperty', { property: 'labels', card: data.card }) - }, - async updateCardDesc({ commit }, card) { - const updatedCard = await apiClient.updateCard(card) - commit('updateCardProperty', { property: 'description', card: updatedCard }) - }, - async updateCardDue({ commit }, card) { - const updatedCard = await apiClient.updateCard(card) - commit('updateCardProperty', { property: 'duedate', card: updatedCard }) - }, + const updatedCard = await apiClient[call](card) + commit('updateCard', updatedCard) + }, + async changeCardDoneStatus({ commit }, card) { + let call = 'markCardAsDone' + if (card.done === false) { + call = 'markCardAsUndone' + } + + const updatedCard = await apiClient[call](card) + commit('updateCardProperty', { property: 'done', card: updatedCard }) + }, + async assignCardToUser({ commit }, { card, assignee }) { + const user = await apiClient.assignUser(card.id, assignee.userId, assignee.type) + commit('assignCardToUser', user) + }, + async removeUserFromCard({ commit }, { card, assignee }) { + const user = await apiClient.removeUser(card.id, assignee.userId, assignee.type) + commit('removeUserFromCard', user) + }, + async addLabel({ commit }, data) { + await apiClient.assignLabelToCard(data) + commit('updateCardProperty', { property: 'labels', card: data.card }) + }, + async removeLabel({ commit }, data) { + await apiClient.removeLabelFromCard(data) + commit('updateCardProperty', { property: 'labels', card: data.card }) + }, + async updateCardDesc({ commit }, card) { + const updatedCard = await apiClient.updateCard(card) + commit('updateCardProperty', { property: 'description', card: updatedCard }) + }, + async updateCardDue({ commit }, card) { + const updatedCard = await apiClient.updateCard(card) + commit('updateCardProperty', { property: 'duedate', card: updatedCard }) + }, - addCardData({ commit }, cardData) { - const card = { ...cardData } - commit('addStack', card.relatedStack) - commit('addBoard', card.relatedBoard) - delete card.relatedStack - delete card.relatedBoard - commit('addCard', card) + addCardData({ commit }, cardData) { + const card = { ...cardData } + commit('addStack', card.relatedStack) + commit('addBoard', card.relatedBoard) + delete card.relatedStack + delete card.relatedBoard + commit('addCard', card) + }, }, - }, + } } diff --git a/src/store/main.js b/src/store/main.js index 87b2aab2bf..8a92e8036a 100644 --- a/src/store/main.js +++ b/src/store/main.js @@ -29,8 +29,8 @@ import axios from '@nextcloud/axios' import { generateOcsUrl, generateUrl } from '@nextcloud/router' import { BoardApi } from '../services/BoardApi.js' import actions from './actions.js' -import stack from './stack.js' -import card from './card.js' +import stackModuleFactory from './stack.js' +import cardModuleFactory from './card.js' import comment from './comment.js' import trashbin from './trashbin.js' import attachment from './attachment.js' @@ -46,495 +46,503 @@ export const BOARD_FILTERS = { SHARED: 'shared', } -export default new Vuex.Store({ - modules: { - actions, - stack, - card, - comment, - trashbin, - attachment, - overview, - }, - strict: debug, - state: { - isFullApp: true, - config: loadState('deck', 'config', {}), - showArchived: false, - navShown: localStorage.getItem('deck.navShown') === null || localStorage.getItem('deck.navShown') === 'true', - compactMode: localStorage.getItem('deck.compactMode') === 'true', - showCardCover: localStorage.getItem('deck.showCardCover') === 'true', - sidebarShown: false, - currentBoard: null, - currentCard: null, - hasCardSaveError: false, - boards: loadState('deck', 'initialBoards', []), - sharees: [], - assignableUsers: [], - boardFilter: BOARD_FILTERS.ALL, - searchQuery: '', - activity: [], - activityLoadMore: true, - filter: { tags: [], users: [], due: '', completed: 'both' }, - shortcutLock: false, - }, - getters: { - config: state => (key) => { - if (!state.isFullApp && key === 'cardDetailsInModal') { - return true - } +export default function storeFactory() { + return new Vuex.Store({ + modules: { + actions, + stack: stackModuleFactory(), + card: cardModuleFactory(), + comment, + trashbin, + attachment, + overview, + }, + strict: debug, + state: { + isFullApp: true, + config: loadState('deck', 'config', {}), + showArchived: false, + navShown: localStorage.getItem('deck.navShown') === null || localStorage.getItem('deck.navShown') === 'true', + compactMode: localStorage.getItem('deck.compactMode') === 'true', + showCardCover: localStorage.getItem('deck.showCardCover') === 'true', + sidebarShown: false, + currentBoard: null, + currentCard: null, + hasCardSaveError: false, + boards: loadState('deck', 'initialBoards', []), + sharees: [], + assignableUsers: [], + boardFilter: BOARD_FILTERS.ALL, + searchQuery: '', + activity: [], + activityLoadMore: true, + filter: { tags: [], users: [], due: '', completed: 'both' }, + shortcutLock: false, + }, + getters: { + config: state => (key) => { + if (!state.isFullApp && key === 'cardDetailsInModal') { + return true + } - return state.config[key] - }, - getSearchQuery: state => { - return state.searchQuery - }, - getFilter: state => { - return state.filter - }, - boards: state => { - return state.boards - }, - boardById: state => (id) => { - return state.boards.find((board) => board.id === id) - }, - assignables: state => { - return [ - ...state.assignableUsers.map((user) => ({ ...user, type: 0 })), - ...state.currentBoard.acl.filter((acl) => acl.type === 1 && typeof acl.participant === 'object').map((group) => ({ ...group.participant, type: 1 })), - ...state.currentBoard.acl.filter((acl) => acl.type === 7 && typeof acl.participant === 'object').map((circle) => ({ ...circle.participant, type: 7 })), - ] - }, - noneArchivedBoards: state => { - return state.boards.filter(board => { - return board.archived === false && !board.deletedAt - }) - }, - archivedBoards: state => { - return state.boards.filter(board => { - return board.archived === true && !board.deletedAt - }) - }, - sharedBoards: state => { - return state.boards.filter(board => { - return board.shared && !board.deletedAt - }) - }, - filteredBoards: state => { - // filters the boards depending on the active filter - const boards = state.boards.filter(board => { - return (state.boardFilter === BOARD_FILTERS.ALL && board.archived === false) - || (state.boardFilter === BOARD_FILTERS.ARCHIVED && board.archived === true) - || (state.boardFilter === BOARD_FILTERS.SHARED && board.shared === 1) - }) - return boards - }, - currentBoardLabels: state => { - return state.currentBoard ? state.currentBoard.labels : [] - }, - canEdit: state => { - return state.currentBoard ? state.currentBoard.permissions.PERMISSION_EDIT : false - }, - canManage: state => { - return state.currentBoard ? state.currentBoard.permissions.PERMISSION_MANAGE : false - }, - canShare: state => { - return state.currentBoard ? state.currentBoard.permissions.PERMISSION_SHARE : false - }, - isArchived: state => { - return state.currentBoard && state.currentBoard.archived - }, - }, - mutations: { - setFullApp(state, isFullApp) { - Vue.set(state, 'isFullApp', isFullApp) - }, - setHasCardSaveError(state, hasCardSaveError) { - Vue.set(state, 'hasCardSaveError', hasCardSaveError) - }, - SET_CONFIG(state, { key, value }) { - const [scope, id, configKey] = key.split(':', 3) - let indexExisting = -1 - switch (scope) { - case 'board': - indexExisting = state.boards.findIndex((b) => { - return id === '' + b.id + return state.config[key] + }, + getSearchQuery: state => { + return state.searchQuery + }, + getFilter: state => { + return state.filter + }, + boards: state => { + return state.boards + }, + boardById: state => (id) => { + return state.boards.find((board) => board.id === id) + }, + assignables: state => { + return [ + ...state.assignableUsers.map((user) => ({ ...user, type: 0 })), + ...state.currentBoard.acl.filter((acl) => acl.type === 1 && typeof acl.participant === 'object').map((group) => ({ + ...group.participant, + type: 1, + })), + ...state.currentBoard.acl.filter((acl) => acl.type === 7 && typeof acl.participant === 'object').map((circle) => ({ + ...circle.participant, + type: 7, + })), + ] + }, + noneArchivedBoards: state => { + return state.boards.filter(board => { + return board.archived === false && !board.deletedAt + }) + }, + archivedBoards: state => { + return state.boards.filter(board => { + return board.archived === true && !board.deletedAt }) + }, + sharedBoards: state => { + return state.boards.filter(board => { + return board.shared && !board.deletedAt + }) + }, + filteredBoards: state => { + // filters the boards depending on the active filter + const boards = state.boards.filter(board => { + return (state.boardFilter === BOARD_FILTERS.ALL && board.archived === false) + || (state.boardFilter === BOARD_FILTERS.ARCHIVED && board.archived === true) + || (state.boardFilter === BOARD_FILTERS.SHARED && board.shared === 1) + }) + return boards + }, + currentBoardLabels: state => { + return state.currentBoard ? state.currentBoard.labels : [] + }, + canEdit: state => { + return state.currentBoard ? state.currentBoard.permissions.PERMISSION_EDIT : false + }, + canManage: state => { + return state.currentBoard ? state.currentBoard.permissions.PERMISSION_MANAGE : false + }, + canShare: state => { + return state.currentBoard ? state.currentBoard.permissions.PERMISSION_SHARE : false + }, + isArchived: state => { + return state.currentBoard && state.currentBoard.archived + }, + }, + mutations: { + setFullApp(state, isFullApp) { + Vue.set(state, 'isFullApp', isFullApp) + }, + setHasCardSaveError(state, hasCardSaveError) { + Vue.set(state, 'hasCardSaveError', hasCardSaveError) + }, + SET_CONFIG(state, { key, value }) { + const [scope, id, configKey] = key.split(':', 3) + let indexExisting = -1 + switch (scope) { + case 'board': + indexExisting = state.boards.findIndex((b) => { + return id === '' + b.id + }) - if (indexExisting > -1) { - Vue.set(state.boards[indexExisting].settings, configKey, value) - } - break - default: - Vue.set(state.config, key, value) - } - }, - setSearchQuery(state, searchQuery) { - state.searchQuery = searchQuery - }, - SET_FILTER(state, filter) { - Object.assign(state.filter, filter) - }, - TOGGLE_FILTER(state, filter) { - Object.keys(filter).forEach((key) => { - switch (key) { - case 'due': - Vue.set(state.filter, key, filter.due) + if (indexExisting > -1) { + Vue.set(state.boards[indexExisting].settings, configKey, value) + } break default: - filter[key].forEach((item) => { - if (state.filter[key].indexOf(item) === -1) { - state.filter[key].push(item) - } else { - state.filter[key].splice(state.filter[key].indexOf(item), 1) - } - }) - break + Vue.set(state.config, key, value) } - }) - }, - toggleShowArchived(state, newState = undefined) { - state.showArchived = newState !== undefined ? newState : !state.showArchived - }, - /* - * Adds or replaces a board in the store. - * Matches a board by it's id. - */ - addBoard(state, board) { - const indexExisting = state.boards.findIndex((b) => { - return board.id === b.id - }) + }, + setSearchQuery(state, searchQuery) { + state.searchQuery = searchQuery + }, + SET_FILTER(state, filter) { + Object.assign(state.filter, filter) + }, + TOGGLE_FILTER(state, filter) { + Object.keys(filter).forEach((key) => { + switch (key) { + case 'due': + Vue.set(state.filter, key, filter.due) + break + default: + filter[key].forEach((item) => { + if (state.filter[key].indexOf(item) === -1) { + state.filter[key].push(item) + } else { + state.filter[key].splice(state.filter[key].indexOf(item), 1) + } + }) + break + } + }) + }, + toggleShowArchived(state, newState = undefined) { + state.showArchived = newState !== undefined ? newState : !state.showArchived + }, + /* + * Adds or replaces a board in the store. + * Matches a board by it's id. + */ + addBoard(state, board) { + const indexExisting = state.boards.findIndex((b) => { + return board.id === b.id + }) - if (indexExisting > -1) { - Vue.set(state.boards, indexExisting, board) - } else { - state.boards.push(board) - } - }, + if (indexExisting > -1) { + Vue.set(state.boards, indexExisting, board) + } else { + state.boards.push(board) + } + }, - cloneBoard(state, board) { - const indexExisting = state.boards.findIndex((b) => { - return board.id === b.id - }) + cloneBoard(state, board) { + const indexExisting = state.boards.findIndex((b) => { + return board.id === b.id + }) - if (indexExisting > -1) { - Vue.set(state.boards, indexExisting, board) - } else { - state.boards.push(board) - } - }, + if (indexExisting > -1) { + Vue.set(state.boards, indexExisting, board) + } else { + state.boards.push(board) + } + }, - /* - * Removes the board from the store. - */ - removeBoard(state, board) { - state.boards = state.boards.filter((b) => { - return board.id !== b.id - }) - }, - toggleNav(state, navState) { - state.navShown = navState - localStorage.setItem('deck.navShown', navState) - }, - toggleSidebar(state) { - state.sidebarShown = !state.sidebarShown - }, - toggleCompactMode(state) { - state.compactMode = !state.compactMode - localStorage.setItem('deck.compactMode', state.compactMode) - }, - toggleShowCardCover(state) { - state.showCardCover = !state.showCardCover - localStorage.setItem('deck.showCardCover', state.showCardCover) - }, - setBoards(state, boards) { - state.boards = boards - }, - setSharees(state, shareesUsersAndGroups) { - Vue.set(state, 'sharees', shareesUsersAndGroups.exact.users) - state.sharees.push(...shareesUsersAndGroups.exact.groups) - state.sharees.push(...shareesUsersAndGroups.exact.circles) + /* + * Removes the board from the store. + */ + removeBoard(state, board) { + state.boards = state.boards.filter((b) => { + return board.id !== b.id + }) + }, + toggleNav(state, navState) { + state.navShown = navState + localStorage.setItem('deck.navShown', navState) + }, + toggleSidebar(state) { + state.sidebarShown = !state.sidebarShown + }, + toggleCompactMode(state) { + state.compactMode = !state.compactMode + localStorage.setItem('deck.compactMode', state.compactMode) + }, + toggleShowCardCover(state) { + state.showCardCover = !state.showCardCover + localStorage.setItem('deck.showCardCover', state.showCardCover) + }, + setBoards(state, boards) { + state.boards = boards + }, + setSharees(state, shareesUsersAndGroups) { + Vue.set(state, 'sharees', shareesUsersAndGroups.exact.users) + state.sharees.push(...shareesUsersAndGroups.exact.groups) + state.sharees.push(...shareesUsersAndGroups.exact.circles) - state.sharees.push(...shareesUsersAndGroups.users) - state.sharees.push(...shareesUsersAndGroups.groups) - state.sharees.push(...shareesUsersAndGroups.circles) - }, - setAssignableUsers(state, users) { - state.assignableUsers = users - }, - setBoardFilter(state, filter) { - state.boardFilter = filter - }, - setCurrentBoard(state, board) { - state.currentBoard = board - }, - setCurrentCard(state, card) { - state.currentCard = card - }, + state.sharees.push(...shareesUsersAndGroups.users) + state.sharees.push(...shareesUsersAndGroups.groups) + state.sharees.push(...shareesUsersAndGroups.circles) + }, + setAssignableUsers(state, users) { + state.assignableUsers = users + }, + setBoardFilter(state, filter) { + state.boardFilter = filter + }, + setCurrentBoard(state, board) { + state.currentBoard = board + }, + setCurrentCard(state, card) { + state.currentCard = card + }, - // label mutators - removeLabelFromCurrentBoard(state, labelId) { - const removeIndex = state.currentBoard.labels.findIndex((l) => { - return labelId === l.id - }) + // label mutators + removeLabelFromCurrentBoard(state, labelId) { + const removeIndex = state.currentBoard.labels.findIndex((l) => { + return labelId === l.id + }) - if (removeIndex > -1) { - state.currentBoard.labels.splice(removeIndex, 1) - } - }, - updateLabelFromCurrentBoard(state, newLabel) { - const labelToUpdate = state.currentBoard.labels.find((l) => { - return newLabel.id === l.id - }) + if (removeIndex > -1) { + state.currentBoard.labels.splice(removeIndex, 1) + } + }, + updateLabelFromCurrentBoard(state, newLabel) { + const labelToUpdate = state.currentBoard.labels.find((l) => { + return newLabel.id === l.id + }) - labelToUpdate.title = newLabel.title - labelToUpdate.color = newLabel.color - }, - addLabelToCurrentBoard(state, newLabel) { - state.currentBoard.labels.push(newLabel) - }, + labelToUpdate.title = newLabel.title + labelToUpdate.color = newLabel.color + }, + addLabelToCurrentBoard(state, newLabel) { + state.currentBoard.labels.push(newLabel) + }, - // acl mutators - addAclToCurrentBoard(state, createdAcl) { - state.currentBoard.acl.push(createdAcl) - }, - updateAclFromCurrentBoard(state, acl) { - for (const acl_ in state.currentBoard.acl) { - if (state.currentBoard.acl[acl_].participant.uid === acl.participant.uid) { - Vue.set(state.currentBoard.acl, acl_, acl) - break + // acl mutators + addAclToCurrentBoard(state, createdAcl) { + state.currentBoard.acl.push(createdAcl) + }, + updateAclFromCurrentBoard(state, acl) { + for (const acl_ in state.currentBoard.acl) { + if (state.currentBoard.acl[acl_].participant.uid === acl.participant.uid) { + Vue.set(state.currentBoard.acl, acl_, acl) + break + } } - } - }, - deleteAclFromCurrentBoard(state, acl) { - let removeIndex = -1 - for (const index in state.currentBoard.acl) { - const attr = state.currentBoard.acl[index] - if (acl.id === attr.id) { - removeIndex = index - break + }, + deleteAclFromCurrentBoard(state, acl) { + let removeIndex = -1 + for (const index in state.currentBoard.acl) { + const attr = state.currentBoard.acl[index] + if (acl.id === attr.id) { + removeIndex = index + break + } } - } - if (removeIndex > -1) { - Vue.delete(state.currentBoard.acl, removeIndex) - } - }, - TOGGLE_SHORTCUT_LOCK(state, lock) { - state.shortcutLock = lock - }, - }, - actions: { - setFullApp({ commit }, isFullApp) { - commit('setFullApp', isFullApp) - }, - async setConfig({ commit }, config) { - for (const key in config) { - try { - await axios.post(generateOcsUrl(`apps/deck/api/v1.0/config/${key}`), { - value: config[key], - }) - commit('SET_CONFIG', { key, value: config[key] }) - } catch (e) { - console.error(`Error while saving ${key}`, e.response) - throw e + if (removeIndex > -1) { + Vue.delete(state.currentBoard.acl, removeIndex) } - } - }, - setFilter({ commit }, filter) { - commit('SET_FILTER', filter) - }, - toggleFilter({ commit }, filter) { - commit('TOGGLE_FILTER', filter) - }, - async loadBoardById({ commit, dispatch }, boardId) { - const filterReset = { tags: [], users: [], due: '' } - dispatch('setFilter', filterReset) - commit('setCurrentBoard', null) - const board = await apiClient.loadById(boardId) - commit('setCurrentBoard', board) - commit('setAssignableUsers', board.users) - }, + }, + TOGGLE_SHORTCUT_LOCK(state, lock) { + state.shortcutLock = lock + }, + }, + actions: { + setFullApp({ commit }, isFullApp) { + commit('setFullApp', isFullApp) + }, + async setConfig({ commit }, config) { + for (const key in config) { + try { + await axios.post(generateOcsUrl(`apps/deck/api/v1.0/config/${key}`), { + value: config[key], + }) + commit('SET_CONFIG', { key, value: config[key] }) + } catch (e) { + console.error(`Error while saving ${key}`, e.response) + throw e + } + } + }, + setFilter({ commit }, filter) { + commit('SET_FILTER', filter) + }, + toggleFilter({ commit }, filter) { + commit('TOGGLE_FILTER', filter) + }, + async loadBoardById({ commit, dispatch }, boardId) { + const filterReset = { tags: [], users: [], due: '' } + dispatch('setFilter', filterReset) + commit('setCurrentBoard', null) + const board = await apiClient.loadById(boardId) + commit('setCurrentBoard', board) + commit('setAssignableUsers', board.users) + }, - async refreshBoard({ commit, dispatch }, boardId) { - const board = await apiClient.loadById(boardId) - const etagHasChanged = board.ETag !== this.state.currentBoard.ETag - commit('setCurrentBoard', board) - commit('setAssignableUsers', board.users) + async refreshBoard({ commit, dispatch }, boardId) { + const board = await apiClient.loadById(boardId) + const etagHasChanged = board.ETag !== this.state.currentBoard.ETag + commit('setCurrentBoard', board) + commit('setAssignableUsers', board.users) - if (etagHasChanged) { - dispatch('loadStacks', boardId) - } - }, + if (etagHasChanged) { + dispatch('loadStacks', boardId) + } + }, - toggleShowArchived({ commit }) { - commit('toggleShowArchived') - }, + toggleShowArchived({ commit }) { + commit('toggleShowArchived') + }, - /** - * @param commit.commit - * @param commit - * @param state - * @param {Board} board - */ - archiveBoard({ commit }, board) { - const boardCopy = JSON.parse(JSON.stringify(board)) - boardCopy.archived = true - apiClient.updateBoard(boardCopy) - .then((board) => { - commit('addBoard', board) - }) - }, - /** - * @param commit.commit - * @param commit - * @param state - * @param {Board} board - */ - unarchiveBoard({ commit }, board) { - const boardCopy = JSON.parse(JSON.stringify(board)) - boardCopy.archived = false - apiClient.updateBoard(boardCopy) - .then((board) => { + /** + * @param commit.commit + * @param commit + * @param state + * @param {Board} board + */ + archiveBoard({ commit }, board) { + const boardCopy = JSON.parse(JSON.stringify(board)) + boardCopy.archived = true + apiClient.updateBoard(boardCopy) + .then((board) => { + commit('addBoard', board) + }) + }, + /** + * @param commit.commit + * @param commit + * @param state + * @param {Board} board + */ + unarchiveBoard({ commit }, board) { + const boardCopy = JSON.parse(JSON.stringify(board)) + boardCopy.archived = false + apiClient.updateBoard(boardCopy) + .then((board) => { + commit('addBoard', board) + }) + }, + /** + * Updates a board API side. + * + * @param commit.commit + * @param commit + * @param board The board to update. + * @return {Promise} + */ + async updateBoard({ commit }, board) { + const storedBoard = await apiClient.updateBoard(board) + commit('addBoard', storedBoard) + }, + async createBoard({ commit }, boardData) { + try { + const board = await apiClient.createBoard(boardData) commit('addBoard', board) - }) - }, - /** - * Updates a board API side. - * - * @param commit.commit - * @param commit - * @param board The board to update. - * @return {Promise} - */ - async updateBoard({ commit }, board) { - const storedBoard = await apiClient.updateBoard(board) - commit('addBoard', storedBoard) - }, - async createBoard({ commit }, boardData) { - try { - const board = await apiClient.createBoard(boardData) - commit('addBoard', board) - } catch (err) { - return err - } - }, - async cloneBoard({ commit }, boardData) { - try { - const newBoard = await apiClient.cloneBoard(boardData) - commit('cloneBoard', newBoard) - return newBoard - } catch (err) { - return err - } - }, - removeBoard({ commit }, board) { - commit('removeBoard', board) - }, - async loadBoards({ commit }) { - const boards = await apiClient.loadBoards() - commit('setBoards', boards) - }, - async loadSharees({ commit }, query) { - const params = new URLSearchParams() - if (typeof query === 'undefined') { - return - } - params.append('search', query) - params.append('format', 'json') - params.append('perPage', 20) - params.append('itemType', [0, 1, 4, 7]) - params.append('lookup', false) + } catch (err) { + return err + } + }, + async cloneBoard({ commit }, boardData) { + try { + const newBoard = await apiClient.cloneBoard(boardData) + commit('cloneBoard', newBoard) + return newBoard + } catch (err) { + return err + } + }, + removeBoard({ commit }, board) { + commit('removeBoard', board) + }, + async loadBoards({ commit }) { + const boards = await apiClient.loadBoards() + commit('setBoards', boards) + }, + async loadSharees({ commit }, query) { + const params = new URLSearchParams() + if (typeof query === 'undefined') { + return + } + params.append('search', query) + params.append('format', 'json') + params.append('perPage', 20) + params.append('itemType', [0, 1, 4, 7]) + params.append('lookup', false) - const response = await axios.get(generateOcsUrl('apps/files_sharing/api/v1/sharees'), { params }) - commit('setSharees', response.data.ocs.data) - }, + const response = await axios.get(generateOcsUrl('apps/files_sharing/api/v1/sharees'), { params }) + commit('setSharees', response.data.ocs.data) + }, - setBoardFilter({ commmit }, filter) { - commmit('setBoardFilter', filter) - }, - toggleNav({ commit }, navState) { - commit('toggleNav', navState) - }, - toggleSidebar({ commit }) { - commit('toggleSidebar') - }, - toggleCompactMode({ commit }) { - commit('toggleCompactMode') - }, - toggleShowCardCover({ commit }) { - commit('toggleShowCardCover') - }, - setCurrentBoard({ commit }, board) { - commit('setCurrentBoard', board) - }, - setAssignableUsers({ commit }, board) { - commit('setAssignableUsers', board) - }, - setCurrentCard({ commit }, card) { - commit('setCurrentCard', card) - }, + setBoardFilter({ commmit }, filter) { + commmit('setBoardFilter', filter) + }, + toggleNav({ commit }, navState) { + commit('toggleNav', navState) + }, + toggleSidebar({ commit }) { + commit('toggleSidebar') + }, + toggleCompactMode({ commit }) { + commit('toggleCompactMode') + }, + toggleShowCardCover({ commit }) { + commit('toggleShowCardCover') + }, + setCurrentBoard({ commit }, board) { + commit('setCurrentBoard', board) + }, + setAssignableUsers({ commit }, board) { + commit('setAssignableUsers', board) + }, + setCurrentCard({ commit }, card) { + commit('setCurrentCard', card) + }, - // label actions - removeLabelFromCurrentBoard({ commit }, label) { - apiClient.deleteLabel(label) - .then((label) => { - commit('removeLabelFromCurrentBoard', label.id) - }) - }, - updateLabelFromCurrentBoard({ commit }, newLabel) { - apiClient.updateLabel(newLabel) - .then((newLabel) => { - commit('updateLabelFromCurrentBoard', newLabel) - }) - }, - addLabelToCurrentBoard({ commit }, newLabel) { - newLabel.boardId = this.state.currentBoard.id - apiClient.createLabel(newLabel) - .then((newLabel) => { - commit('addLabelToCurrentBoard', newLabel) + // label actions + removeLabelFromCurrentBoard({ commit }, label) { + apiClient.deleteLabel(label) + .then((label) => { + commit('removeLabelFromCurrentBoard', label.id) + }) + }, + updateLabelFromCurrentBoard({ commit }, newLabel) { + apiClient.updateLabel(newLabel) + .then((newLabel) => { + commit('updateLabelFromCurrentBoard', newLabel) + }) + }, + addLabelToCurrentBoard({ commit }, newLabel) { + newLabel.boardId = this.state.currentBoard.id + apiClient.createLabel(newLabel) + .then((newLabel) => { + commit('addLabelToCurrentBoard', newLabel) + }) + }, + async addLabelToCurrentBoardAndCard({ dispatch, commit }, { newLabel, card }) { + newLabel.boardId = this.state.currentBoard.id + const label = await apiClient.createLabel(newLabel) + commit('addLabelToCurrentBoard', label) + dispatch('addLabel', { + card, + labelId: label.id, }) - }, - async addLabelToCurrentBoardAndCard({ dispatch, commit }, { newLabel, card }) { - newLabel.boardId = this.state.currentBoard.id - const label = await apiClient.createLabel(newLabel) - commit('addLabelToCurrentBoard', label) - dispatch('addLabel', { - card, - labelId: label.id, - }) - return label - }, + return label + }, - // acl actions - async addAclToCurrentBoard({ dispatch, commit }, newAcl) { - newAcl.boardId = this.state.currentBoard.id - const result = await apiClient.addAcl(newAcl) - commit('addAclToCurrentBoard', result) - dispatch('refreshBoard', newAcl.boardId) - }, - updateAclFromCurrentBoard({ commit }, acl) { - acl.boardId = this.state.currentBoard.id - apiClient.updateAcl(acl) - .then((acl) => { - commit('updateAclFromCurrentBoard', acl) - }) - }, - deleteAclFromCurrentBoard({ dispatch, commit }, acl) { - acl.boardId = this.state.currentBoard.id - apiClient.deleteAcl(acl) - .then((acl) => { - commit('deleteAclFromCurrentBoard', acl) - dispatch('loadBoardById', acl.boardId) + // acl actions + async addAclToCurrentBoard({ dispatch, commit }, newAcl) { + newAcl.boardId = this.state.currentBoard.id + const result = await apiClient.addAcl(newAcl) + commit('addAclToCurrentBoard', result) + dispatch('refreshBoard', newAcl.boardId) + }, + updateAclFromCurrentBoard({ commit }, acl) { + acl.boardId = this.state.currentBoard.id + apiClient.updateAcl(acl) + .then((acl) => { + commit('updateAclFromCurrentBoard', acl) + }) + }, + deleteAclFromCurrentBoard({ dispatch, commit }, acl) { + acl.boardId = this.state.currentBoard.id + apiClient.deleteAcl(acl) + .then((acl) => { + commit('deleteAclFromCurrentBoard', acl) + dispatch('loadBoardById', acl.boardId) + }) + }, + async transferOwnership({ commit }, { boardId, newOwner }) { + await axios.put(generateUrl(`apps/deck/boards/${boardId}/transferOwner`), { + newOwner, }) + }, + toggleShortcutLock({ commit }, lock) { + commit('TOGGLE_SHORTCUT_LOCK', lock) + }, }, - async transferOwnership({ commit }, { boardId, newOwner }) { - await axios.put(generateUrl(`apps/deck/boards/${boardId}/transferOwner`), { - newOwner, - }) - }, - toggleShortcutLock({ commit }, lock) { - commit('TOGGLE_SHORTCUT_LOCK', lock) - }, - }, -}) + }) +} diff --git a/src/store/stack.js b/src/store/stack.js index 8b522f200e..e677a6efdf 100644 --- a/src/store/stack.js +++ b/src/store/stack.js @@ -26,109 +26,111 @@ import applyOrderToArray from './../helpers/applyOrderToArray.js' const apiClient = new StackApi() -export default { - state: { - stacks: [], - }, - getters: { - stacksByBoard: state => (id) => { - return state.stacks.filter((stack) => stack.boardId === id).sort((a, b) => a.order - b.order) +export default function stackModuleFactory() { + return { + state: { + stacks: [], }, - stackById: state => (id) => { - return state.stacks.find((stack) => stack.id === id) + getters: { + stacksByBoard: state => (id) => { + return state.stacks.filter((stack) => stack.boardId === id).sort((a, b) => a.order - b.order) + }, + stackById: state => (id) => { + return state.stacks.find((stack) => stack.id === id) + }, }, - }, - mutations: { - addStack(state, stack) { - const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) - if (existingIndex !== -1) { - const existingStack = state.stacks.find(_stack => _stack.id === stack.id) - Vue.set(state.stacks, existingIndex, Object.assign({}, existingStack, stack)) - } else { - state.stacks.push(stack) - } - }, - orderStack(state, { stack, removedIndex, addedIndex }) { - const currentOrder = state.stacks.filter((_stack) => _stack.boardId === stack.boardId).sort((a, b) => a.order - b.order) - const newOrder = applyOrderToArray(currentOrder, removedIndex, addedIndex) - for (let i = 0; i < newOrder.length; i++) { - newOrder[i].order = parseInt(i) - } - }, - deleteStack(state, stack) { - const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) - if (existingIndex !== -1) { - state.stacks.splice(existingIndex, 1) - } - }, - updateStack(state, stack) { - const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) - if (existingIndex !== -1) { - state.stacks[existingIndex].title = stack.title - } - }, - }, - actions: { - orderStack({ commit }, { stack, removedIndex, addedIndex }) { - commit('orderStack', { stack, removedIndex, addedIndex }) - apiClient.reorderStack(stack.id, addedIndex) - .catch((err) => { - OC.Notification.showTemporary('Failed to change order') - console.error(err.response.data.message) - commit('orderStack', { stack, addedIndex, removedIndex }) - }) - }, - async loadStacks({ commit }, boardId) { - let call = 'loadStacks' - if (this.state.showArchived === true) { - call = 'loadArchivedStacks' - } - const stacks = await apiClient[call](boardId) - const cards = [] - for (const i in stacks) { - const stack = stacks[i] - for (const j in stack.cards) { - cards.push(stack.cards[j]) + mutations: { + addStack(state, stack) { + const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) + if (existingIndex !== -1) { + const existingStack = state.stacks.find(_stack => _stack.id === stack.id) + Vue.set(state.stacks, existingIndex, Object.assign({}, existingStack, stack)) + } else { + state.stacks.push(stack) + } + }, + orderStack(state, { stack, removedIndex, addedIndex }) { + const currentOrder = state.stacks.filter((_stack) => _stack.boardId === stack.boardId).sort((a, b) => a.order - b.order) + const newOrder = applyOrderToArray(currentOrder, removedIndex, addedIndex) + for (let i = 0; i < newOrder.length; i++) { + newOrder[i].order = parseInt(i) } - delete stack.cards - commit('addStack', stack) - } - commit('setCards', cards) + }, + deleteStack(state, stack) { + const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) + if (existingIndex !== -1) { + state.stacks.splice(existingIndex, 1) + } + }, + updateStack(state, stack) { + const existingIndex = state.stacks.findIndex(_stack => _stack.id === stack.id) + if (existingIndex !== -1) { + state.stacks[existingIndex].title = stack.title + } + }, }, - async loadArchivedStacks({ commit, getters }, boardId) { - const archivedStacks = await apiClient.loadArchivedStacks(boardId) - const cards = [] - for (const i in archivedStacks) { - const stack = archivedStacks[i] - for (const j in stack.cards) { - cards.push(stack.cards[j]) + actions: { + orderStack({ commit }, { stack, removedIndex, addedIndex }) { + commit('orderStack', { stack, removedIndex, addedIndex }) + apiClient.reorderStack(stack.id, addedIndex) + .catch((err) => { + OC.Notification.showTemporary('Failed to change order') + console.error(err.response.data.message) + commit('orderStack', { stack, addedIndex, removedIndex }) + }) + }, + async loadStacks({ commit }, boardId) { + let call = 'loadStacks' + if (this.state.showArchived === true) { + call = 'loadArchivedStacks' } - delete stack.cards - if (!getters.stackById(stack.id)) { + const stacks = await apiClient[call](boardId) + const cards = [] + for (const i in stacks) { + const stack = stacks[i] + for (const j in stack.cards) { + cards.push(stack.cards[j]) + } + delete stack.cards commit('addStack', stack) } - } - commit('setCards', cards) - }, - createStack({ commit }, stack) { - stack.boardId = this.state.currentBoard.id - apiClient.createStack(stack) - .then((createdStack) => { - commit('addStack', createdStack) - }) - }, - deleteStack({ commit }, stack) { - apiClient.deleteStack(stack.id) - .then((stack) => { - commit('deleteStack', stack) - commit('moveStackToTrash', stack) - }) - }, - updateStack({ commit }, stack) { - apiClient.updateStack(stack) - .then((stack) => { - commit('updateStack', stack) - }) + commit('setCards', cards) + }, + async loadArchivedStacks({ commit, getters }, boardId) { + const archivedStacks = await apiClient.loadArchivedStacks(boardId) + const cards = [] + for (const i in archivedStacks) { + const stack = archivedStacks[i] + for (const j in stack.cards) { + cards.push(stack.cards[j]) + } + delete stack.cards + if (!getters.stackById(stack.id)) { + commit('addStack', stack) + } + } + commit('setCards', cards) + }, + createStack({ commit }, stack) { + stack.boardId = this.state.currentBoard.id + apiClient.createStack(stack) + .then((createdStack) => { + commit('addStack', createdStack) + }) + }, + deleteStack({ commit }, stack) { + apiClient.deleteStack(stack.id) + .then((stack) => { + commit('deleteStack', stack) + commit('moveStackToTrash', stack) + }) + }, + updateStack({ commit }, stack) { + apiClient.updateStack(stack) + .then((stack) => { + commit('updateStack', stack) + }) + }, }, - }, + } } diff --git a/src/views/BoardReferenceWidget.vue b/src/views/BoardReferenceWidget.vue index 12c9965ba1..88c7e7d82e 100644 --- a/src/views/BoardReferenceWidget.vue +++ b/src/views/BoardReferenceWidget.vue @@ -47,7 +47,7 @@ import Board from '../components/board/Board.vue' import DeckIcon from '../components/icons/DeckIcon.vue' import { BoardApi } from './../services/BoardApi.js' -import store from './../store/main.js' +import storeFactory from './../store/main.js' import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js' @@ -59,7 +59,7 @@ const boardApi = new BoardApi() export default { name: 'BoardReferenceWidget', - store, + store: storeFactory(), components: { DeckIcon,