added new functions

Signed-off-by: Jakob <jakob.roehrl@web.de>
This commit is contained in:
Jakob
2019-07-11 14:31:08 +02:00
committed by Julius Härtl
parent 408ea69272
commit fcabdbdc24
12 changed files with 235 additions and 45 deletions

View File

@@ -48,7 +48,7 @@
</form> </form>
</div> </div>
<div class="board-action-buttons"> <div class="board-action-buttons">
<button title="Show archived cards" class="icon icon-archive" /> <button title="Show archived cards" class="icon icon-archive" @click="toggleShowArchived" />
<button :class="[(compactMode ? 'icon-toggle-compact-collapsed' : 'icon-toggle-compact-expanded')]" title="Toggle compact mode" class="icon" <button :class="[(compactMode ? 'icon-toggle-compact-collapsed' : 'icon-toggle-compact-expanded')]" title="Toggle compact mode" class="icon"
@click="toggleCompactMode" /> @click="toggleCompactMode" />
<router-link v-tooltip="t('deck', 'Board settings')" :to="{name: 'board.details'}" class="icon-settings-dark" <router-link v-tooltip="t('deck', 'Board settings')" :to="{name: 'board.details'}" class="icon-settings-dark"
@@ -91,6 +91,9 @@ export default {
toggleCompactMode() { toggleCompactMode() {
this.$store.dispatch('toggleCompactMode') this.$store.dispatch('toggleCompactMode')
}, },
toggleShowArchived() {
this.$store.dispatch('toggleShowArchived')
},
clickAddNewStack() { clickAddNewStack() {
this.stack = { title: this.newStackTitle } this.stack = { title: this.newStackTitle }
this.$store.dispatch('createStack', this.stack) this.$store.dispatch('createStack', this.stack)

View File

@@ -27,22 +27,6 @@
<container lock-axix="y" orientation="horizontal" @drop="onDropStack"> <container lock-axix="y" orientation="horizontal" @drop="onDropStack">
<draggable v-for="stack in stacksByBoard" :key="stack.id" class="stack"> <draggable v-for="stack in stacksByBoard" :key="stack.id" class="stack">
<stack :stack="stack" /> <stack :stack="stack" />
<!-- <h3>{{ stack.title }}
<button v-tooltip="t('deck', 'Delete')" class="icon-delete"
@click="deleteStack(stack)" />
</h3>
<container :get-child-payload="payloadForCard(stack.id)" group-name="stack" @drop="($event) => onDropCard(stack.id, $event)">
<draggable v-for="card in cardsByStack(stack.id)" :key="card.id">
<card-item v-if="card" :id="card.id" />
</draggable>
</container>
<div class="card create">
<div title="Add card">
<i class="icon icon-add" />
<span class="hidden-visually">Add card</span>
</div>
</div>
-->
</draggable> </draggable>
</container> </container>
</div> </div>
@@ -59,13 +43,11 @@
import { Container, Draggable } from 'vue-smooth-dnd' import { Container, Draggable } from 'vue-smooth-dnd'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import Controls from '../Controls' import Controls from '../Controls'
/* import CardItem from '../cards/CardItem' */
import Stack from './Stack' import Stack from './Stack'
export default { export default {
name: 'Board', name: 'Board',
components: { components: {
/* CardItem, */
Controls, Controls,
Container, Container,
Draggable, Draggable,
@@ -87,7 +69,8 @@ export default {
}, },
computed: { computed: {
...mapState({ ...mapState({
board: state => state.currentBoard board: state => state.currentBoard,
showArchived: state => state.showArchived
}), }),
stacksByBoard() { stacksByBoard() {
return this.$store.getters.stacksByBoard(this.board.id) return this.$store.getters.stacksByBoard(this.board.id)
@@ -97,7 +80,11 @@ export default {
} */ } */
}, },
watch: { watch: {
'$route': 'fetchData' '$route': 'fetchData',
showArchived() {
this.fetchData()
}
}, },
created() { created() {
this.fetchData() this.fetchData()

View File

@@ -21,7 +21,7 @@
--> -->
<template> <template>
<app-sidebar <app-sidebar v-if="board != null"
:actions="[]" :actions="[]"
:title="board.title" :title="board.title"
@close="closeSidebar"> @close="closeSidebar">

View File

@@ -36,7 +36,7 @@
</li> </li>
</ul> </ul>
<collection-list v-if="board.id" :id="&quot;board.id&quot;" :name="board.title" <collection-list v-if="board.id" :id="`${board.id}`" :name="board.title"
type="deck" /> type="deck" />
</div> </div>
</template> </template>

View File

@@ -2,6 +2,7 @@
- @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
- -
- @author Julius Härtl <jus@bitgrid.net> - @author Julius Härtl <jus@bitgrid.net>
- @author Jakob Röhrl <jakob.roehrl@web.de>
- -
- @license GNU AGPL version 3 or any later version - @license GNU AGPL version 3 or any later version
- -

View File

@@ -21,17 +21,17 @@
--> -->
<template> <template>
<app-sidebar <app-sidebar v-if="currentCard != null"
:actions="[]" :actions="[]"
title="andy-yeo-1387151-unsplash.jpg" :title="currentCard.title"
subtitle="4,3 MB, last edited 19 days ago" :subtitle="subtitle"
@close="closeSidebar"> @close="closeSidebar">
<template #action /> <template #action />
<AppSidebarTab name="Description" icon="icon-description"> <AppSidebarTab name="Description" icon="icon-description">
this is the description tab {{ currentCard.description }}
</AppSidebarTab> </AppSidebarTab>
<AppSidebarTab name="Attachments" icon="icon-files-dark"> <AppSidebarTab name="Attachments" icon="icon-files-dark">
this is the files tab {{ currentCard.attachments }}
</AppSidebarTab> </AppSidebarTab>
<AppSidebarTab name="Timeline" icon="icon-activity"> <AppSidebarTab name="Timeline" icon="icon-activity">
this is the activity tab this is the activity tab
@@ -41,6 +41,7 @@
<script> <script>
import { AppSidebar, AppSidebarTab } from 'nextcloud-vue' import { AppSidebar, AppSidebarTab } from 'nextcloud-vue'
import { mapState } from 'vuex'
export default { export default {
name: 'CardSidebar', name: 'CardSidebar',
@@ -52,6 +53,17 @@ export default {
return { return {
} }
}, },
computed: {
...mapState({
currentCard: state => state.currentCard
}),
subtitle() {
let lastModified = this.currentCard.lastModified
let createdAt = this.currentCard.createdAt
return t('deck', 'Modified') + ': ' + lastModified + ' ' + t('deck', 'Created') + ': ' + createdAt
}
},
methods: { methods: {
closeSidebar() { closeSidebar() {
this.$router.push({ name: 'board' }) this.$router.push({ name: 'board' })

View File

@@ -24,11 +24,11 @@
<div :class="{'compact': compactMode}" tag="div" class="card" <div :class="{'compact': compactMode}" tag="div" class="card"
@click="openCard"> @click="openCard">
<div class="card-upper"> <div class="card-upper">
<h3 @click.stop="startEditing">{{ card.title }}</h3> <h3 @click.stop="startEditing(card)">{{ card.title }}</h3>
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<form v-if="editing"> <form v-if="editing">
<input :value="card.title" type="text" autofocus> <input v-model="copiedCard.title" type="text" autofocus>
<input type="button" class="icon-confirm" @click="clickTitleEditSave"> <input type="button" class="icon-confirm" @click="finishedEdit(card)">
</form> </form>
<action v-if="!editing" :actions="visibilityPopover" @click.stop="" /> <action v-if="!editing" :actions="visibilityPopover" @click.stop="" />
</transition> </transition>
@@ -67,12 +67,14 @@ export default {
data() { data() {
return { return {
menuOpened: false, menuOpened: false,
editing: false editing: false,
copiedCard: ''
} }
}, },
computed: { computed: {
...mapState({ ...mapState({
compactMode: state => state.compactMode compactMode: state => state.compactMode,
showArchived: state => state.showArchived
}), }),
card() { card() {
return this.$store.getters.cardById(this.id) return this.$store.getters.cardById(this.id)
@@ -97,22 +99,30 @@ export default {
visibilityPopover() { visibilityPopover() {
return [ return [
{ {
action: () => {}, action: () => {
this.assignCardToMe()
},
icon: 'icon-archive-dark', icon: 'icon-archive-dark',
text: t('deck', 'Assign to me') text: t('deck', 'Assign to me')
}, },
{ {
action: () => {}, action: () => {
icon: 'icon-archive-dark', this.archiveUnarchiveCard()
text: t('deck', 'Archive card') },
icon: 'icon-archive',
text: t('deck', (this.showArchived ? 'Unarchive card' : 'Archive card'))
}, },
{ {
action: () => {}, action: () => {
icon: 'icon-delete-dark', this.deleteCard()
},
icon: 'icon-delete',
text: t('deck', 'Delete card') text: t('deck', 'Delete card')
}, },
{ {
action: () => {}, action: () => {
this.setCurrentCard()
},
icon: 'icon-settings-dark', icon: 'icon-settings-dark',
text: t('deck', 'Card details') text: t('deck', 'Card details')
} }
@@ -121,7 +131,7 @@ export default {
}, },
methods: { methods: {
openCard() { openCard() {
this.$router.push({ name: 'card', params: { cardId: 123 } }) this.$router.push({ name: 'card', params: { cardId: this.id } })
}, },
togglePopoverMenu() { togglePopoverMenu() {
this.menuOpened = !this.menuOpened this.menuOpened = !this.menuOpened
@@ -129,13 +139,33 @@ export default {
hidePopoverMenu() { hidePopoverMenu() {
this.menuOpened = false this.menuOpened = false
}, },
startEditing() { startEditing(card) {
this.copiedCard = Object.assign({}, card)
this.editing = true this.editing = true
}, },
clickTitleEditSave() { finishedEdit(card) {
if (this.copiedCard.title !== card.title) {
this.editing = false this.$store.dispatch('updateCard', this.copiedCard)
} }
this.editing = false
},
deleteCard() {
this.$store.dispatch('deleteCard', this.card)
},
archiveUnarchiveCard() {
this.copiedCard = Object.assign({}, this.card)
this.copiedCard.archived = !this.copiedCard.archived
this.$store.dispatch('archiveUnarchiveCard', this.copiedCard)
},
assignCardToMe() {
this.copiedCard = Object.assign({}, this.card)
this.copiedCard.assignUser = this.card.owner.uid
this.$store.dispatch('assignCardToMe', this.copiedCard)
},
setCurrentCard() {
this.$store.dispatch('setCurrentCard', this.card)
}
} }
} }
</script> </script>

View File

@@ -44,4 +44,79 @@ export class CardApi {
}) })
} }
deleteCard(cardId) {
return axios.delete(this.url(`/cards/${cardId}`))
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
}
)
.catch((err) => {
return Promise.reject(err)
})
}
updateCard(card) {
return axios.put(this.url(`/cards/${card.id}`), card)
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
}
)
.catch((err) => {
return Promise.reject(err)
})
}
assignUser(card) {
return axios.put(this.url(`/cards/${card.id}/assignUser`), card.assignUser)
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
}
)
.catch((err) => {
return Promise.reject(err)
})
}
archiveCard(card) {
return axios.put(this.url(`/cards/${card.id}/archive`))
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
}
)
.catch((err) => {
return Promise.reject(err)
})
}
unArchiveCard(card) {
return axios.put(this.url(`/cards/${card.id}/unarchive`))
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
}
)
.catch((err) => {
return Promise.reject(err)
})
}
} }

View File

@@ -44,6 +44,21 @@ export class StackApi {
}) })
} }
loadArchivedStacks(boardId) {
return axios.get(this.url(`/stacks/${boardId}/archived`))
.then(
(response) => {
return Promise.resolve(response.data)
},
(err) => {
return Promise.reject(err)
}
)
.catch((err) => {
return Promise.reject(err)
})
}
/** /**
* @param {Stack} stack * @param {Stack} stack
* @returns {Promise} * @returns {Promise}

View File

@@ -21,6 +21,7 @@
*/ */
import { CardApi } from './../services/CardApi' import { CardApi } from './../services/CardApi'
import Vue from 'vue'
const apiClient = new CardApi() const apiClient = new CardApi()
@@ -37,6 +38,9 @@ export default {
} }
}, },
mutations: { mutations: {
clearCards(state) {
state.cards = []
},
addCard(state, card) { addCard(state, card) {
let existingIndex = state.cards.findIndex(_card => _card.id === card.id) let existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) { if (existingIndex !== -1) {
@@ -45,6 +49,21 @@ export default {
} else { } else {
state.cards.push(card) state.cards.push(card)
} }
},
deleteCard(state, card) {
let existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
state.cards.splice(existingIndex, 1)
}
},
updateTitle(state, card) {
let existingIndex = state.cards.findIndex(_card => _card.id === card.id)
if (existingIndex !== -1) {
state.cards[existingIndex].title = card.title
}
},
assignCardToMe(state, card) {
// let existingIndex = state.cards.findIndex(_card => _card.id === card.id)
} }
}, },
actions: { actions: {
@@ -53,6 +72,35 @@ export default {
.then((createdCard) => { .then((createdCard) => {
commit('addCard', createdCard) commit('addCard', createdCard)
}) })
},
updateCard({ commit }, card) {
apiClient.updateCard(card)
.then((updatedCard) => {
commit('updateTitle', updatedCard)
})
},
deleteCard({ commit }, card) {
apiClient.deleteCard(card.id)
.then((card) => {
commit('deleteCard', card)
})
},
archiveUnarchiveCard({ commit }, card) {
let call = 'archiveCard'
if (card.archived === false) {
call = 'unArchiveCard'
}
apiClient[call](card)
.then((card) => {
commit('deleteCard', card)
})
},
assignCardToMe({ commit }, card) {
apiClient.assignUser(card)
.then((card) => {
commit('assignCardToMe', card)
})
} }
} }
} }

View File

@@ -46,10 +46,12 @@ export default new Vuex.Store({
}, },
strict: debug, strict: debug,
state: { state: {
showArchived: false,
navShown: true, navShown: true,
compactMode: false, compactMode: false,
sidebarShown: false, sidebarShown: false,
currentBoard: null, currentBoard: null,
currentCard: null,
boards: [], boards: [],
sharees: [], sharees: [],
boardFilter: BOARD_FILTERS.ALL boardFilter: BOARD_FILTERS.ALL
@@ -90,6 +92,9 @@ export default new Vuex.Store({
} }
}, },
mutations: { mutations: {
toggleShowArchived(state) {
state.showArchived = !state.showArchived
},
/** /**
* Adds or replaces a board in the store. * Adds or replaces a board in the store.
* Matches a board by it's id. * Matches a board by it's id.
@@ -143,6 +148,9 @@ export default new Vuex.Store({
setCurrentBoard(state, board) { setCurrentBoard(state, board) {
state.currentBoard = board state.currentBoard = board
}, },
setCurrentCard(state, card) {
state.currentCard = card
},
// label mutators // label mutators
removeLabelFromCurrentBoard(state, labelId) { removeLabelFromCurrentBoard(state, labelId) {
@@ -196,6 +204,9 @@ export default new Vuex.Store({
} }
}, },
actions: { actions: {
toggleShowArchived({ commit }) {
commit('toggleShowArchived')
},
/** /**
* @param commit * @param commit
* @param state * @param state
@@ -272,6 +283,9 @@ export default new Vuex.Store({
setCurrentBoard({ commit }, board) { setCurrentBoard({ commit }, board) {
commit('setCurrentBoard', board) commit('setCurrentBoard', board)
}, },
setCurrentCard({ commit }, card) {
commit('setCurrentCard', card)
},
// label actions // label actions
removeLabelFromCurrentBoard({ commit }, label) { removeLabelFromCurrentBoard({ commit }, label) {

View File

@@ -77,7 +77,12 @@ export default {
}) })
}, },
loadStacks({ commit }, board) { loadStacks({ commit }, board) {
apiClient.loadStacks(board.id) commit('clearCards')
let call = 'loadStacks'
if (this.state.showArchived === true) {
call = 'loadArchivedStacks'
}
apiClient[call](board.id)
.then((stacks) => { .then((stacks) => {
for (let i in stacks) { for (let i in stacks) {
let stack = stacks[i] let stack = stacks[i]