Merge pull request #1944 from nextcloud/refactor/navigation

This commit is contained in:
Julius Härtl
2020-05-29 15:46:11 +02:00
committed by GitHub
10 changed files with 266 additions and 284 deletions

View File

@@ -31,7 +31,7 @@
</p> </p>
</div> </div>
<div v-if="board" class="board-actions"> <div v-if="board" class="board-actions">
<div v-if="canManage && !showArchived" <div v-if="canManage && !showArchived && !board.archived"
id="stack-add" id="stack-add"
v-click-outside="hideAddStack"> v-click-outside="hideAddStack">
<Actions v-if="!isAddStackVisible" :title="t('deck', 'Add new list')"> <Actions v-if="!isAddStackVisible" :title="t('deck', 'Add new list')">

View File

@@ -25,7 +25,7 @@
<div class="stack"> <div class="stack">
<div v-click-outside="stopCardCreation" class="stack--header"> <div v-click-outside="stopCardCreation" class="stack--header">
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<h3 v-if="!canManage"> <h3 v-if="!canManage || isArchived">
{{ stack.title }} {{ stack.title }}
</h3> </h3>
<h3 v-else-if="!editing" <h3 v-else-if="!editing"
@@ -42,12 +42,12 @@
value=""> value="">
</form> </form>
</transition> </transition>
<Actions v-if="canManage" :force-menu="true"> <Actions v-if="canManage && !isArchived" :force-menu="true">
<ActionButton icon="icon-delete" @click="deleteStack(stack)"> <ActionButton icon="icon-delete" @click="deleteStack(stack)">
{{ t('deck', 'Delete list') }} {{ t('deck', 'Delete list') }}
</ActionButton> </ActionButton>
</Actions> </Actions>
<Actions v-if="canEdit && !showArchived"> <Actions v-if="canEdit && !showArchived && !isArchived">
<ActionButton icon="icon-add" @click.stop="showAddCard=true"> <ActionButton icon="icon-add" @click.stop="showAddCard=true">
{{ t('deck', 'Add card') }} {{ t('deck', 'Add card') }}
</ActionButton> </ActionButton>
@@ -133,6 +133,7 @@ export default {
...mapGetters([ ...mapGetters([
'canManage', 'canManage',
'canEdit', 'canEdit',
'isArchived',
]), ]),
...mapState({ ...mapState({
showArchived: state => state.showArchived, showArchived: state => state.showArchived,

View File

@@ -24,11 +24,11 @@
<div :style="{ backgroundColor: `#${label.color}`, color:textColor(label.color) }" class="label-title"> <div :style="{ backgroundColor: `#${label.color}`, color:textColor(label.color) }" class="label-title">
<span>{{ label.title }}</span> <span>{{ label.title }}</span>
</div> </div>
<button v-if="canManage" <button v-if="canManage && !isArchived"
v-tooltip="t('deck', 'Edit')" v-tooltip="t('deck', 'Edit')"
class="icon-rename" class="icon-rename"
@click="clickEdit(label)" /> @click="clickEdit(label)" />
<button v-if="canManage" <button v-if="canManage && !isArchived"
v-tooltip="t('deck', 'Delete')" v-tooltip="t('deck', 'Delete')"
class="icon-delete" class="icon-delete"
@click="deleteLabel(label.id)" /> @click="deleteLabel(label.id)" />
@@ -55,7 +55,7 @@
</form> </form>
</template> </template>
</li> </li>
<button v-if="canManage" @click="clickShowAddLabel()"> <button v-if="canManage && !isArchived" @click="clickShowAddLabel()">
<span class="icon-add" />{{ t('deck', 'Add a new tag') }} <span class="icon-add" />{{ t('deck', 'Add a new tag') }}
</button> </button>
</ul> </ul>
@@ -88,6 +88,7 @@ export default {
...mapGetters({ ...mapGetters({
labels: 'currentBoardLabels', labels: 'currentBoardLabels',
canManage: 'canManage', canManage: 'canManage',
isArchived: 'isArchived',
}), }),
addLabelObjValidated() { addLabelObjValidated() {
if (this.addLabelObj.title === '') { if (this.addLabelObj.title === '') {

View File

@@ -31,7 +31,7 @@
class="card" class="card"
@click="openCard"> @click="openCard">
<div class="card-upper"> <div class="card-upper">
<h3 v-if="showArchived || !canEdit"> <h3 v-if="isArchived || showArchived || !canEdit">
{{ card.title }} {{ card.title }}
</h3> </h3>
<h3 v-else-if="!editing"> <h3 v-else-if="!editing">
@@ -47,7 +47,7 @@
<input type="button" class="icon-confirm" @click="finishedEdit(card)"> <input type="button" class="icon-confirm" @click="finishedEdit(card)">
</form> </form>
<div v-if="!editing" class="right"> <div v-if="!editing" class="duedate right">
<transition name="zoom"> <transition name="zoom">
<div v-if="card.duedate" :class="dueIcon"> <div v-if="card.duedate" :class="dueIcon">
<span>{{ relativeDate }}</span> <span>{{ relativeDate }}</span>
@@ -57,7 +57,8 @@
<CardMenu v-if="!editing && compactMode" :id="id" class="right" /> <CardMenu v-if="!editing && compactMode" :id="id" class="right" />
</div> </div>
<transition-group name="zoom" <transition-group v-if="card.labels.length"
name="zoom"
tag="ul" tag="ul"
class="labels" class="labels"
@click="openCard"> @click="openCard">
@@ -109,6 +110,7 @@ export default {
}), }),
...mapGetters([ ...mapGetters([
'canEdit', 'canEdit',
'isArchived',
]), ]),
card() { card() {
return this.$store.getters.cardById(this.id) return this.$store.getters.cardById(this.id)
@@ -189,7 +191,7 @@ export default {
.card-upper { .card-upper {
display: flex; display: flex;
min-height: 50px; min-height: 44px;
form { form {
display: flex; display: flex;
padding: 5px 7px; padding: 5px 7px;
@@ -200,7 +202,7 @@ export default {
} }
h3 { h3 {
margin: 14px $card-padding; margin: 12px $card-padding;
flex-grow: 1; flex-grow: 1;
font-size: 100%; font-size: 100%;
overflow-x: hidden; overflow-x: hidden;
@@ -257,10 +259,12 @@ export default {
} }
} }
} }
.duedate {
margin-right: 9px;
}
.right { .right {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
margin-right: 9px;
} }
.icon.due { .icon.due {
@@ -269,6 +273,7 @@ export default {
margin-top: 9px; margin-top: 9px;
margin-bottom: 9px; margin-bottom: 9px;
padding: 3px 4px; padding: 3px 4px;
padding-right: 0;
font-size: 90%; font-size: 90%;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -284,14 +289,17 @@ export default {
background-color: var(--color-error); background-color: var(--color-error);
color: var(--color-primary-text); color: var(--color-primary-text);
opacity: .7; opacity: .7;
padding: 3px 4px;
} }
&.now { &.now {
background-color: var(--color-warning); background-color: var(--color-warning);
opacity: .7; opacity: .7;
padding: 3px 4px;
} }
&.next { &.next {
background-color: var(--color-background-dark); background-color: var(--color-background-dark);
opacity: .7; opacity: .7;
padding: 3px 4px;
} }
span { span {
@@ -303,8 +311,11 @@ export default {
} }
.compact { .compact {
min-height: 50px; min-height: 44px;
.duedate {
margin-right: 0;
}
&.has-labels { &.has-labels {
padding-bottom: $card-padding; padding-bottom: $card-padding;
} }

View File

@@ -23,7 +23,7 @@
<template> <template>
<div> <div>
<div @click.stop.prevent> <div @click.stop.prevent>
<Actions v-if="canEdit"> <Actions v-if="canEdit && !isArchived">
<ActionButton v-if="showArchived === false" icon="icon-user" @click="assignCardToMe()"> <ActionButton v-if="showArchived === false" icon="icon-user" @click="assignCardToMe()">
{{ t('deck', 'Assign to me') }} {{ t('deck', 'Assign to me') }}
</ActionButton> </ActionButton>
@@ -93,6 +93,7 @@ export default {
computed: { computed: {
...mapGetters([ ...mapGetters([
'canEdit', 'canEdit',
'isArchived',
]), ]),
...mapState({ ...mapState({
showArchived: state => state.showArchived, showArchived: state => state.showArchived,

View File

@@ -22,35 +22,31 @@
<template> <template>
<div id="app-navigation" :class="{'icon-loading': loading}"> <div id="app-navigation" :class="{'icon-loading': loading}">
<ul id="deck-navigation"> <AppNavigationVue>
<ul>
<AppNavigationBoardCategory <AppNavigationBoardCategory
id="deck-navigation-all" id="deck-navigation-all"
to="/board"
:text="t('deck', 'All boards')" :text="t('deck', 'All boards')"
:boards="noneArchivedBoards" :boards="noneArchivedBoards"
:open-on-add-boards="true" :open-on-add-boards="true"
icon="icon-deck" /> icon="icon-deck" />
<AppNavigationBoardCategory <AppNavigationBoardCategory
id="deck-navigation-archived" id="deck-navigation-archived"
to="/board/archived"
:text="t('deck', 'Archived boards')" :text="t('deck', 'Archived boards')"
:boards="archivedBoards" :boards="archivedBoards"
icon="icon-archive" /> icon="icon-archive" />
<AppNavigationBoardCategory <AppNavigationBoardCategory
id="deck-navigation-shared" id="deck-navigation-shared"
:text="t('deck', 'Shared boards')" to="/board/shared"
:text="t('deck', 'Shared with you')"
:boards="sharedBoards" :boards="sharedBoards"
icon="icon-shared" /> icon="icon-shared" />
<AppNavigationAddBoard v-if="canCreate" /> <AppNavigationAddBoard v-if="canCreate" />
</ul> </ul>
<div v-if="isAdmin" <AppNavigationSettings>
id="app-settings" <div>
v-click-outside="closeMenu"
:class="{open: opened}">
<div id="app-settings-header">
<button class="settings-button" @click="toggleMenu">
{{ t('deck', 'Settings') }}
</button>
</div>
<div id="app-settings-content">
<Multiselect v-model="groupLimit" <Multiselect v-model="groupLimit"
:class="{'icon-loading-small': groupLimitDisabled}" :class="{'icon-loading-small': groupLimitDisabled}"
open-direction="bottom" open-direction="bottom"
@@ -63,6 +59,21 @@
@input="updateConfig" /> @input="updateConfig" />
<p>{{ t('deck', 'Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them.') }}</p> <p>{{ t('deck', 'Limiting Deck will block users not part of those groups from creating their own boards. Users will still be able to work on boards that have been shared with them.') }}</p>
</div> </div>
</AppNavigationSettings>
</AppNavigationVue>
<ul id="deck-navigation">
<AppNavigationAddBoard v-if="canCreate" />
</ul>
<div v-if="isAdmin"
id="app-settings"
v-click-outside="closeMenu"
:class="{open: opened}">
<div id="app-settings-header">
<button class="settings-button" @click="toggleMenu">
{{ t('deck', 'Settings') }}
</button>
</div>
</div> </div>
</div> </div>
</template> </template>
@@ -71,8 +82,7 @@
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import ClickOutside from 'vue-click-outside' import ClickOutside from 'vue-click-outside'
import { Multiselect } from '@nextcloud/vue' import { AppNavigation as AppNavigationVue, AppNavigationSettings, Multiselect } from '@nextcloud/vue'
import AppNavigationAddBoard from './AppNavigationAddBoard' import AppNavigationAddBoard from './AppNavigationAddBoard'
import AppNavigationBoardCategory from './AppNavigationBoardCategory' import AppNavigationBoardCategory from './AppNavigationBoardCategory'
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
@@ -83,6 +93,8 @@ const canCreateState = loadState('deck', 'canCreate')
export default { export default {
name: 'AppNavigation', name: 'AppNavigation',
components: { components: {
AppNavigationVue,
AppNavigationSettings,
AppNavigationAddBoard, AppNavigationAddBoard,
AppNavigationBoardCategory, AppNavigationBoardCategory,
Multiselect, Multiselect,

View File

@@ -20,38 +20,30 @@
- -
--> -->
<template> <template>
<li id="deck-navigation-add" <AppNavigationItem v-if="!editing"
:title="t('deck', 'Create new board')" :title="t('deck', 'Create new board')"
:class="[{'icon-loading-small': loading, 'editing': editing}, classes]"> icon="icon-add"
<a class="icon-add" href="#" @click.prevent.stop="startCreateBoard"> @click.prevent.stop="startCreateBoard" />
{{ t('deck', 'Create new board') }} <div v-else class="board-create">
</a>
<!-- edit entry -->
<div v-if="editing" class="app-navigation-entry-edit">
<ColorPicker v-model="color" class="app-navigation-entry-bullet-wrapper"> <ColorPicker v-model="color" class="app-navigation-entry-bullet-wrapper">
<div :style="{ backgroundColor: color }" class="color0 icon-colorpicker app-navigation-entry-bullet" /> <div :style="{ backgroundColor: color }" class="color0 icon-colorpicker app-navigation-entry-bullet" />
</ColorPicker> </ColorPicker>
<form @submit.prevent.stop="createBoard"> <form @submit.prevent.stop="createBoard">
<input :placeholder="t('deck', 'New board title')" type="text" required> <input :placeholder="t('deck', 'New board title')" type="text" required>
<input type="submit" value="" class="icon-confirm"> <input type="submit" value="" class="icon-confirm">
<input type="submit" <Actions><ActionButton icon="icon-close" @click.stop.prevent="cancelEdit" /></Actions>
value=""
class="icon-close"
@click.stop.prevent="cancelEdit">
</form> </form>
<!-- <ColorPicker v-model="color" /> -->
</div> </div>
</li>
</template> </template>
<script> <script>
import { ColorPicker } from '@nextcloud/vue' import { ColorPicker, ActionButton, Actions, AppNavigationItem } from '@nextcloud/vue'
const randomColor = () => '#' + ((1 << 24) * Math.random() | 0).toString(16)
export default { export default {
name: 'AppNavigationAddBoard', name: 'AppNavigationAddBoard',
components: { ColorPicker }, components: { ColorPicker, AppNavigationItem, ActionButton, Actions },
directives: {}, directives: {},
props: {}, props: {},
data() { data() {
@@ -59,7 +51,7 @@ export default {
classes: [], classes: [],
editing: false, editing: false,
loading: false, loading: false,
color: '#000000', color: randomColor(),
} }
}, },
computed: {}, computed: {},
@@ -76,27 +68,38 @@ export default {
color: this.color.substring(1), color: this.color.substring(1),
}) })
this.editing = false this.editing = false
this.color = randomColor()
}, },
cancelEdit(e) { cancelEdit(e) {
this.editing = false this.editing = false
this.item.edit.reset(e) this.color = randomColor()
}, },
}, },
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
#app-navigation .app-navigation-entry-edit div { .board-create {
width: auto; order: 1;
display: block; display: flex;
height: 44px;
form {
display: flex;
flex-grow: 1;
input[type="text"] {
flex-grow: 1;
} }
}
}
.app-navigation-entry-bullet-wrapper { .app-navigation-entry-bullet-wrapper {
position: absolute; width: 44px;
left: 33px;
width: 44px !important;
margin: 6px;
height: 44px; height: 44px;
.color0 { .color0 {
width: 30px !important; width: 30px !important;
margin: 5px;
margin-left: 7px;
height: 30px; height: 30px;
border-radius: 50%; border-radius: 50%;
background-size: 14px; background-size: 14px;

View File

@@ -20,75 +20,80 @@
- -
--> -->
<template> <template>
<router-link :id="`board-${board.id}`" <AppNavigationItem v-if="!editing"
:title="board.title" :title="!deleted ? board.title : undoText"
:class="[{'icon-loading-small': loading, deleted: deleted, editing: editing }, classes]" :loading="loading"
:to="routeTo" :to="routeTo"
tag="li"> :undo="deleted"
<div :style="{ backgroundColor: `#${board.color}` }" class="app-navigation-entry-bullet" /> @undo="unDelete">
<a href="#"> <AppNavigationIconBullet slot="icon" :color="board.color" />
{{ board.title }}
</a>
<div v-if="actions.length > 0" class="app-navigation-entry-utils"> <AppNavigationCounter v-if="board.acl.length"
<ul> slot="counter"
<li class="app-navigation-entry-utils-menu-button">
<button v-if="board.acl.length === 0"
v-tooltip="t('deck', 'Share')"
class="icon-shared" class="icon-shared"
style="opacity: 0.3" style="opacity: 0.5" />
@click="showSidebar" />
<button v-else
v-tooltip="t('deck', 'Share')"
class="icon-shared"
@click="showSidebar" />
</li>
<li class="app-navigation-entry-utils-menu-button">
<button v-click-outside="hideMenu" v-tooltip="t('deck', 'Options')" @click="showMenu" />
</li>
</ul>
</div>
<div :class="{ 'open': menuOpen }" class="app-navigation-entry-menu">
<PopoverMenu :menu="actions" />
</div>
<!-- undo action --> <template v-if="!deleted" slot="actions">
<div v-if="deleted" class="app-navigation-entry-deleted"> <ActionButton v-if="canManage && !board.archived"
<div class="app-navigation-entry-deleted-description"> icon="icon-rename"
{{ undoText }} :close-after-click="true"
</div> @click="actionEdit">
<button {{ t('deck', 'Edit board') }}
:title="t('settings', 'Undo')" </ActionButton>
class="app-navigation-entry-deleted-button icon-history" <ActionButton v-if="canManage && !board.archived"
@click="unDelete" /> icon="icon-clone"
</div> :close-after-click="true"
@click="actionClone">
<!-- edit entry --> {{ t('deck', 'Clone board ') }}
<div v-if="editing" class="app-navigation-entry-edit"> </ActionButton>
<ActionButton v-if="canManage && board.archived"
icon="icon-archive"
:close-after-click="true"
@click="actionUnarchive">
{{ t('deck', 'Unarchive board ') }}
</ActionButton>
<ActionButton v-if="canManage && !board.archived"
icon="icon-archive"
:close-after-click="true"
@click="actionArchive">
{{ t('deck', 'Archive board ') }}
</ActionButton>
<ActionButton v-if="canManage"
icon="icon-delete"
:close-after-click="true"
@click="actionDelete">
{{ t('deck', 'Delete board ') }}
</ActionButton>
<ActionButton icon="icon-more" :close-after-click="true" @click="actionDetails">
{{ t('deck', 'Board details') }}
</ActionButton>
</template>
</AppNavigationItem>
<div v-else-if="editing" class="board-edit">
<ColorPicker class="app-navigation-entry-bullet-wrapper" :value="`#${board.color}`" @input="updateColor"> <ColorPicker class="app-navigation-entry-bullet-wrapper" :value="`#${board.color}`" @input="updateColor">
<div :style="{ backgroundColor: getColor }" class="color0 icon-colorpicker app-navigation-entry-bullet" /> <div :style="{ backgroundColor: getColor }" class="color0 icon-colorpicker app-navigation-entry-bullet" />
</ColorPicker> </ColorPicker>
<form @submit.prevent.stop="applyEdit"> <form @submit.prevent.stop="applyEdit">
<input v-model="editTitle" type="text" required> <input v-model="editTitle" type="text" required>
<input type="submit" value="" class="icon-confirm"> <input type="submit" value="" class="icon-confirm">
<input type="submit" <Actions><ActionButton icon="icon-close" @click.stop.prevent="cancelEdit" /></Actions>
value=""
class="icon-close"
@click.stop.prevent="cancelEdit">
</form> </form>
</div> </div>
</router-link>
</template> </template>
<script> <script>
import { PopoverMenu, ColorPicker } from '@nextcloud/vue' import { AppNavigationIconBullet, AppNavigationCounter, AppNavigationItem, ColorPicker, Actions, ActionButton } from '@nextcloud/vue'
import ClickOutside from 'vue-click-outside' import ClickOutside from 'vue-click-outside'
export default { export default {
name: 'AppNavigationBoard', name: 'AppNavigationBoard',
components: { components: {
AppNavigationIconBullet,
AppNavigationCounter,
AppNavigationItem,
ColorPicker, ColorPicker,
PopoverMenu, Actions,
ActionButton,
}, },
directives: { directives: {
ClickOutside, ClickOutside,
@@ -119,8 +124,7 @@ export default {
return this.board.color return this.board.color
}, },
undoText: function() { undoText: function() {
// todo translation return t('deck', 'Board {0} deleted', [this.board.title])
return 'deleted ' + this.board.title
}, },
routeTo: function() { routeTo: function() {
return { return {
@@ -128,117 +132,8 @@ export default {
params: { id: this.board.id }, params: { id: this.board.id },
} }
}, },
actions: function() { canManage() {
/* eslint-disable vue/no-side-effects-in-computed-properties */ return this.board.permissions.PERMISSION_MANAGE
/* eslint-disable vue/no-async-in-computed-properties */
const actions = []
// do not show actions while the item is loading
if (this.loading === false) {
const canManage = this.board.permissions.PERMISSION_MANAGE
if (canManage) {
actions.push({
action: () => {
this.hideMenu()
this.editTitle = this.board.title
this.editColor = '#' + this.board.color
this.editing = true
},
icon: 'icon-rename',
text: t('deck', 'Edit board'),
})
}
if (canManage) {
actions.push({
action: async() => {
this.hideMenu()
this.loading = true
try {
const newBoard = await this.$store.dispatch('cloneBoard', this.board)
this.loading = false
const route = this.routeTo
route.params.id = newBoard.id
this.$router.push(route)
} catch (e) {
OC.Notification.showTemporary(t('deck', 'An error occurred'))
console.error(e)
}
},
icon: 'icon-clone',
text: t('deck', 'Clone board'),
})
if (!this.board.archived) {
actions.push({
action: () => {
this.hideMenu()
this.loading = true
this.$store.dispatch('archiveBoard', this.board)
},
icon: 'icon-archive',
text: t('deck', 'Archive board'),
})
} else {
actions.push({
action: () => {
this.hideMenu()
this.loading = true
this.$store.dispatch('unarchiveBoard', this.board)
},
icon: 'icon-archive',
text: t('deck', 'Unarchive board'),
})
}
actions.push({
action: () => {
OC.dialogs.confirmDestructive(
t('deck', 'Are you sure you want to delete the board {title}? This will delete all the data of this board.', { title: this.board.title }),
t('deck', 'Delete the board?'),
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('deck', 'Delete'),
confirmClasses: 'error',
cancel: t('deck', 'Cancel'),
},
(result) => {
if (result) {
this.hideMenu()
this.loading = true
this.boardApi.deleteBoard(this.board)
.then(() => {
this.loading = false
this.deleted = true
this.undoTimeoutHandle = setTimeout(() => {
this.$store.dispatch('removeBoard', this.board)
}, 7000)
})
}
},
true
)
},
icon: 'icon-delete',
text: t('deck', 'Delete board'),
})
}
actions.push({
action: () => {
const route = this.routeTo
route.name = 'board.details'
this.$router.push(route)
},
icon: 'icon-settings-dark',
text: t('deck', 'Board details'),
})
}
return actions
}, },
}, },
watch: {}, watch: {},
@@ -254,15 +149,66 @@ export default {
this.deleted = false this.deleted = false
}) })
}, },
showMenu() {
this.menuOpen = true
},
hideMenu() {
this.menuOpen = false
},
updateColor(newColor) { updateColor(newColor) {
this.editColor = newColor this.editColor = newColor
}, },
actionEdit() {
this.editTitle = this.board.title
this.editColor = '#' + this.board.color
this.editing = true
},
async actionClone() {
this.loading = true
try {
const newBoard = await this.$store.dispatch('cloneBoard', this.board)
this.loading = false
const route = this.routeTo
route.params.id = newBoard.id
this.$router.push(route)
} catch (e) {
OC.Notification.showTemporary(t('deck', 'An error occurred'))
console.error(e)
}
},
actionArchive() {
this.loading = true
this.$store.dispatch('archiveBoard', this.board)
},
actionUnarchive() {
this.loading = true
this.$store.dispatch('unarchiveBoard', this.board)
},
actionDelete() {
OC.dialogs.confirmDestructive(
t('deck', 'Are you sure you want to delete the board {title}? This will delete all the data of this board.', { title: this.board.title }),
t('deck', 'Delete the board?'),
{
type: OC.dialogs.YES_NO_BUTTONS,
confirm: t('deck', 'Delete'),
confirmClasses: 'error',
cancel: t('deck', 'Cancel'),
},
(result) => {
if (result) {
this.loading = true
this.boardApi.deleteBoard(this.board)
.then(() => {
this.loading = false
this.deleted = true
this.undoTimeoutHandle = setTimeout(() => {
this.$store.dispatch('removeBoard', this.board)
}, 7000)
})
}
},
true
)
},
actionDetails() {
const route = this.routeTo
route.name = 'board.details'
this.$router.push(route)
},
applyEdit(e) { applyEdit(e) {
this.editing = false this.editing = false
if (this.editTitle || this.editColor) { if (this.editTitle || this.editColor) {
@@ -292,17 +238,29 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
#app-navigation #deck-navigation .editing { .board-edit {
height: auto !important; margin-left: 44px;
order: 1;
display: flex;
height: 44px;
form {
display: flex;
flex-grow: 1;
input[type="text"] {
flex-grow: 1;
} }
}
}
.app-navigation-entry-bullet-wrapper { .app-navigation-entry-bullet-wrapper {
position: absolute; width: 44px;
left: 33px;
width: 44px !important;
margin: 6px;
height: 44px; height: 44px;
.color0 { .color0 {
width: 30px !important; width: 30px !important;
margin: 5px;
margin-left: 7px;
height: 30px; height: 30px;
border-radius: 50%; border-radius: 50%;
background-size: 14px; background-size: 14px;

View File

@@ -20,33 +20,31 @@
- -
--> -->
<template> <template>
<li v-if="boards.length > 0" <AppNavigationItem v-if="boards.length > 0"
:id="id"
:title="text" :title="text"
:class="{'open': opened, 'collapsible': collapsible }"> :icon="icon"
<button v-if="collapsible" class="collapse" @click.prevent.stop="toggleCollapse" /> :to="to"
<a :class="icon" href="#"> :allow-collapse="collapsible"
{{ text }} :open="opened">
</a>
<ul v-if="boards.length > 0">
<AppNavigationBoard v-for="board in boardsSorted" :key="board.id" :board="board" /> <AppNavigationBoard v-for="board in boardsSorted" :key="board.id" :board="board" />
</ul> </AppNavigationItem>
</li>
</template> </template>
<script> <script>
import ClickOutside from 'vue-click-outside'
import AppNavigationBoard from './AppNavigationBoard' import AppNavigationBoard from './AppNavigationBoard'
import { AppNavigationItem } from '@nextcloud/vue'
export default { export default {
name: 'AppNavigationBoardCategory', name: 'AppNavigationBoardCategory',
components: { components: {
AppNavigationItem,
AppNavigationBoard, AppNavigationBoard,
}, },
directives: {
ClickOutside,
},
props: { props: {
to: {
type: String,
default: '',
},
id: { id: {
type: String, type: String,
required: true, required: true,
@@ -92,11 +90,5 @@ export default {
} }
}, },
}, },
mounted() {},
methods: {
toggleCollapse() {
this.opened = !this.opened
},
},
} }
</script> </script>

View File

@@ -56,7 +56,7 @@ export default new Vuex.Store({
state: { state: {
showArchived: false, showArchived: false,
navShown: true, navShown: true,
compactMode: localStorage.getItem('deck.compactMode'), compactMode: localStorage.getItem('deck.compactMode') === 'true',
sidebarShown: false, sidebarShown: false,
currentBoard: null, currentBoard: null,
currentCard: null, currentCard: null,
@@ -122,6 +122,9 @@ export default new Vuex.Store({
canShare: state => { canShare: state => {
return state.currentBoard ? state.currentBoard.permissions.PERMISSION_SHARE : false return state.currentBoard ? state.currentBoard.permissions.PERMISSION_SHARE : false
}, },
isArchived: state => {
return state.currentBoard && state.currentBoard.archived
},
}, },
mutations: { mutations: {
setSearchQuery(state, searchQuery) { setSearchQuery(state, searchQuery) {