fix: card move dialog auto close

Signed-off-by: Luka Trovic <luka@nextcloud.com>
This commit is contained in:
Luka Trovic
2024-01-31 19:34:11 +01:00
parent bfe2a9053f
commit 9848733ca0
3 changed files with 116 additions and 78 deletions

View File

@@ -41,6 +41,7 @@
<router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" /> <router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" />
</div> </div>
<KeyboardShortcuts /> <KeyboardShortcuts />
<CardMoveDialog />
</NcContent> </NcContent>
</template> </template>
@@ -52,12 +53,14 @@ import { NcModal, NcContent, NcAppContent } from '@nextcloud/vue'
import { BoardApi } from './services/BoardApi.js' import { BoardApi } from './services/BoardApi.js'
import { emit, subscribe } from '@nextcloud/event-bus' import { emit, subscribe } from '@nextcloud/event-bus'
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
import CardMoveDialog from './CardMoveDialog.vue'
const boardApi = new BoardApi() const boardApi = new BoardApi()
export default { export default {
name: 'App', name: 'App',
components: { components: {
CardMoveDialog,
AppNavigation, AppNavigation,
NcModal, NcModal,
NcContent, NcContent,

107
src/CardMoveDialog.vue Normal file
View File

@@ -0,0 +1,107 @@
<template>
<NcModal v-if="modalShow" :title="t('deck', 'Move card to another board')" @close="modalShow=false">
<div class="modal__content">
<h3>{{ t('deck', 'Move card to another board') }}</h3>
<NcMultiselect v-model="selectedBoard"
:placeholder="t('deck', 'Select a board')"
:options="activeBoards"
:max-height="100"
label="title"
@select="loadStacksFromBoard" />
<NcMultiselect v-model="selectedStack"
:placeholder="t('deck', 'Select a list')"
:options="stacksFromBoard"
:max-height="100"
label="title">
<span slot="noOptions">
{{ t('deck', 'List is empty') }}
</span>
</NcMultiselect>
<button :disabled="!isBoardAndStackChoosen" class="primary" @click="moveCard">
{{ t('deck', 'Move card') }}
</button>
<button @click="modalShow=false">
{{ t('deck', 'Cancel') }}
</button>
</div>
</NcModal>
</template>
<script>
import { NcModal, NcMultiselect } from '@nextcloud/vue'
import { generateUrl } from '@nextcloud/router'
import axios from '@nextcloud/axios'
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
export default {
name: 'CardMoveDialog',
components: { NcModal, NcMultiselect },
data() {
return {
card: null,
modalShow: false,
selectedBoard: '',
selectedStack: '',
stacksFromBoard: [],
}
},
computed: {
activeBoards() {
return this.$store.getters.boards.filter((item) => item.deletedAt === 0 && item.archived === false)
},
isBoardAndStackChoosen() {
return !(this.selectedBoard === '' || this.selectedStack === '')
},
},
mounted() {
subscribe('deck:card:show-move-dialog', this.openModal)
},
destroyed() {
unsubscribe('deck:card:show-move-dialog', this.openModal)
},
methods: {
openModal(card) {
this.card = card
this.modalShow = true
},
async loadStacksFromBoard(board) {
try {
const url = generateUrl('/apps/deck/stacks/' + board.id)
const response = await axios.get(url)
this.stacksFromBoard = response.data
} catch (err) {
return err
}
},
async moveCard() {
this.copiedCard = Object.assign({}, this.card)
this.copiedCard.stackId = this.selectedStack.id
this.$store.dispatch('moveCard', this.copiedCard)
if (parseInt(this.boardId) === parseInt(this.selectedStack.boardId)) {
await this.$store.commit('addNewCard', { ...this.copiedCard })
}
this.modalShow = false
},
},
}
</script>
<style lang="scss" scoped>
.modal__content {
width: 25vw;
min-width: 250px;
min-height: 120px;
text-align: center;
margin: 20px 20px 100px 20px;
.multiselect {
margin-bottom: 10px;
}
}
.modal__content button {
float: right;
margin-top: 50px;
}
</style>

View File

@@ -47,7 +47,7 @@
<NcActionButton v-if="canEdit" <NcActionButton v-if="canEdit"
icon="icon-external" icon="icon-external"
:close-after-click="true" :close-after-click="true"
@click="modalShow=true"> @click="openCardMoveDialog">
{{ t('deck', 'Move card') }} {{ t('deck', 'Move card') }}
</NcActionButton> </NcActionButton>
<NcActionButton v-for="action in cardActions" <NcActionButton v-for="action in cardActions"
@@ -69,50 +69,23 @@
@click="deleteCard()"> @click="deleteCard()">
{{ t('deck', 'Delete card') }} {{ t('deck', 'Delete card') }}
</NcActionButton> </NcActionButton>
<NcModal v-if="modalShow" :title="t('deck', 'Move card to another board')" @close="modalShow=false">
<div class="modal__content">
<h3>{{ t('deck', 'Move card to another board') }}</h3>
<NcMultiselect v-model="selectedBoard"
:placeholder="t('deck', 'Select a board')"
:options="activeBoards"
:max-height="100"
label="title"
@select="loadStacksFromBoard" />
<NcMultiselect v-model="selectedStack"
:placeholder="t('deck', 'Select a list')"
:options="stacksFromBoard"
:max-height="100"
label="title">
<span slot="noOptions">
{{ t('deck', 'List is empty') }}
</span>
</NcMultiselect>
<button :disabled="!isBoardAndStackChoosen" class="primary" @click="moveCard">
{{ t('deck', 'Move card') }}
</button>
<button @click="modalShow=false">
{{ t('deck', 'Cancel') }}
</button>
</div>
</NcModal>
</div> </div>
</template> </template>
<script> <script>
import { NcModal, NcActionButton, NcMultiselect } from '@nextcloud/vue' import { NcActionButton } from '@nextcloud/vue'
import { mapGetters, mapState } from 'vuex' import { mapGetters, mapState } from 'vuex'
import ArchiveIcon from 'vue-material-design-icons/Archive.vue' import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CardBulletedIcon from 'vue-material-design-icons/CardBulleted.vue' import CardBulletedIcon from 'vue-material-design-icons/CardBulleted.vue'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router' import { generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
import { showUndo } from '@nextcloud/dialogs' import { showUndo } from '@nextcloud/dialogs'
import '@nextcloud/dialogs/dist/index.css' import '@nextcloud/dialogs/dist/index.css'
import { emit } from '@nextcloud/event-bus'
export default { export default {
name: 'CardMenuEntries', name: 'CardMenuEntries',
components: { NcActionButton, NcModal, NcMultiselect, ArchiveIcon, CardBulletedIcon }, components: { NcActionButton, ArchiveIcon, CardBulletedIcon },
props: { props: {
card: { card: {
type: Object, type: Object,
@@ -153,23 +126,12 @@ export default {
const board = this.$store.getters.boards.find((item) => item.id === this.card.boardId) const board = this.$store.getters.boards.find((item) => item.id === this.card.boardId)
return !!board?.permissions?.PERMISSION_EDIT return !!board?.permissions?.PERMISSION_EDIT
}, },
isBoardAndStackChoosen() {
if (this.selectedBoard === '' || this.selectedStack === '') {
return false
}
return true
},
isCurrentUserAssigned() { isCurrentUserAssigned() {
return this.card.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid) return this.card.assignedUsers.find((item) => item.type === 0 && item.participant.uid === getCurrentUser()?.uid)
}, },
activeBoards() {
return this.$store.getters.boards.filter((item) => item.deletedAt === 0 && item.archived === false)
},
boardId() { boardId() {
return this.card?.boardId ? this.card.boardId : Number(this.$route.params.id) return this.card?.boardId ? this.card.boardId : Number(this.$route.params.id)
}, },
cardRichObject() { cardRichObject() {
return { return {
id: '' + this.card.id, id: '' + this.card.id,
@@ -214,43 +176,9 @@ export default {
}, },
}) })
}, },
async moveCard() { openCardMoveDialog() {
this.copiedCard = Object.assign({}, this.card) emit('deck:card:show-move-dialog', this.card)
this.copiedCard.stackId = this.selectedStack.id
this.$store.dispatch('moveCard', this.copiedCard)
if (parseInt(this.boardId) === parseInt(this.selectedStack.boardId)) {
await this.$store.commit('addNewCard', { ...this.copiedCard })
}
this.modalShow = false
},
async loadStacksFromBoard(board) {
try {
const url = generateUrl('/apps/deck/stacks/' + board.id)
const response = await axios.get(url)
this.stacksFromBoard = response.data
} catch (err) {
return err
}
}, },
}, },
} }
</script> </script>
<style lang="scss" scoped>
.modal__content {
width: 25vw;
min-width: 250px;
min-height: 120px;
text-align: center;
margin: 20px 20px 100px 20px;
.multiselect {
margin-bottom: 10px;
}
}
.modal__content button {
float: right;
margin-top: 50px;
}
</style>