Compare commits
8 Commits
dependabot
...
vue3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
042792bfd7 | ||
|
|
5f65d14cbd | ||
|
|
f3545dd677 | ||
|
|
a7d34360b1 | ||
|
|
de907d69c5 | ||
|
|
438376b20a | ||
|
|
b708f3967b | ||
|
|
a2a8b1ade5 |
12418
package-lock.json
generated
12418
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -35,7 +35,7 @@
|
||||
"@nextcloud/auth": "^2.4.0",
|
||||
"@nextcloud/axios": "^2.5.1",
|
||||
"@nextcloud/capabilities": "^1.2.0",
|
||||
"@nextcloud/dialogs": "^6.0.1",
|
||||
"@nextcloud/dialogs": "github:nextcloud-libraries/nextcloud-dialogs#vue3",
|
||||
"@nextcloud/event-bus": "^3.3.2",
|
||||
"@nextcloud/files": "^3.10.1",
|
||||
"@nextcloud/initial-state": "^2.2.0",
|
||||
@@ -43,7 +43,11 @@
|
||||
"@nextcloud/moment": "^1.3.2",
|
||||
"@nextcloud/notify_push": "^1.3.0",
|
||||
"@nextcloud/router": "^3.0.1",
|
||||
"@nextcloud/vue": "^8.22.0",
|
||||
"@nextcloud/vue": "^9.0.0-alpha.7",
|
||||
"@vue/compat": "^3.5.13",
|
||||
"@vue/compiler-sfc": "^3.5.13",
|
||||
"@vue/vue3-jest": "^29.2.6",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"blueimp-md5": "^2.19.0",
|
||||
"chroma-js": "^3.1.2",
|
||||
"dompurify": "^3.2.4",
|
||||
@@ -54,16 +58,14 @@
|
||||
"moment": "^2.30.1",
|
||||
"p-queue": "^8.0.1",
|
||||
"url-search-params-polyfill": "^8.2.5",
|
||||
"vue": "^2.7.15",
|
||||
"vue-at": "^2.5.1",
|
||||
"v3-infinite-loading": "^1.3.2",
|
||||
"vue": "^3.5.13",
|
||||
"vue-click-outside": "^1.1.0",
|
||||
"vue-easymde": "^2.0.0",
|
||||
"vue-infinite-loading": "^2.4.5",
|
||||
"vue-material-design-icons": "^5.3.1",
|
||||
"vue-router": "^3.6.5",
|
||||
"vue-smooth-dnd": "^0.8.1",
|
||||
"vuex": "^3.6.2",
|
||||
"vuex-router-sync": "^5.0.0"
|
||||
"vue-router": "^4.5.0",
|
||||
"vue3-smooth-dnd": "^0.0.6",
|
||||
"vuex": "^4.1.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"extends @nextcloud/browserslist-config"
|
||||
@@ -78,17 +80,15 @@
|
||||
"@nextcloud/cypress": "^1.0.0-beta.13",
|
||||
"@nextcloud/eslint-config": "^8.4.2",
|
||||
"@nextcloud/stylelint-config": "^3.0.1",
|
||||
"@nextcloud/webpack-vue-config": "^6.2.0",
|
||||
"@nextcloud/webpack-vue-config": "github:nextcloud-libraries/webpack-vue-config#vue3",
|
||||
"@relative-ci/agent": "^4.2.14",
|
||||
"@vue/test-utils": "^2.4.6",
|
||||
"@vue/vue2-jest": "^29.2.6",
|
||||
"cypress": "^13.17.0",
|
||||
"eslint-plugin-cypress": "^3.6.0",
|
||||
"eslint-webpack-plugin": "^4.2.0",
|
||||
"jest": "^29.7.0",
|
||||
"jest-serializer-vue": "^3.1.0",
|
||||
"stylelint-webpack-plugin": "^5.0.1",
|
||||
"vue-template-compiler": "^2.7.16"
|
||||
"stylelint-webpack-plugin": "^5.0.1"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
|
||||
213
src/App.vue
213
src/App.vue
@@ -1,15 +1,51 @@
|
||||
<!--
|
||||
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
<script>
|
||||
import { NcAppContent, NcContent, NcModal } from '@nextcloud/vue'
|
||||
import CardMoveDialog from './CardMoveDialog.vue'
|
||||
import AppNavigation from './components/navigation/AppNavigation.vue'
|
||||
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
|
||||
import {BoardApi} from './services/BoardApi.js'
|
||||
|
||||
const boardApi = new BoardApi()
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
NcContent,
|
||||
AppNavigation,
|
||||
NcAppContent,
|
||||
KeyboardShortcuts,
|
||||
CardMoveDialog,
|
||||
NcModal,
|
||||
},
|
||||
computed: {
|
||||
cardDetailsInModal() {
|
||||
return this.$store.getters.config('cardDetailsInModal')
|
||||
},
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
boardApi,
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
hideModal() {
|
||||
this.$router.push({ name: 'board' })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NcContent app-name="deck" :class="{ 'nav-hidden': !navShown, 'sidebar-hidden': !sidebarRouterView }">
|
||||
<NcContent app-name="deck">
|
||||
<AppNavigation />
|
||||
<NcAppContent :allow-swipe-navigation="false">
|
||||
<router-view />
|
||||
</NcAppContent>
|
||||
|
||||
<div v-if="$route.params.id || $route.params.cardId">
|
||||
<NcModal v-if="cardDetailsInModal && $route.params.cardId"
|
||||
:name="t('deck', 'Card details')"
|
||||
@@ -21,179 +57,10 @@
|
||||
<router-view name="sidebar" />
|
||||
</div>
|
||||
</NcModal>
|
||||
|
||||
<router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" />
|
||||
</div>
|
||||
|
||||
<KeyboardShortcuts />
|
||||
<CardMoveDialog />
|
||||
</NcContent>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
import AppNavigation from './components/navigation/AppNavigation.vue'
|
||||
import KeyboardShortcuts from './components/KeyboardShortcuts.vue'
|
||||
import { NcModal, NcContent, NcAppContent, isMobile } from '@nextcloud/vue'
|
||||
import { BoardApi } from './services/BoardApi.js'
|
||||
import { emit, subscribe } from '@nextcloud/event-bus'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import CardMoveDialog from './CardMoveDialog.vue'
|
||||
|
||||
const boardApi = new BoardApi()
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
CardMoveDialog,
|
||||
AppNavigation,
|
||||
NcModal,
|
||||
NcContent,
|
||||
NcAppContent,
|
||||
KeyboardShortcuts,
|
||||
},
|
||||
mixins: [isMobile],
|
||||
provide() {
|
||||
return {
|
||||
boardApi,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addButton: {
|
||||
icon: 'icon-add',
|
||||
classes: [],
|
||||
text: t('deck', 'Add board'),
|
||||
edit: {
|
||||
text: t('deck', 'Add board'),
|
||||
action: () => {
|
||||
},
|
||||
reset: () => {
|
||||
},
|
||||
},
|
||||
action: () => {
|
||||
this.addButton.classes.push('editing')
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
navShown: state => state.navShown,
|
||||
sidebarShownState: state => state.sidebarShown,
|
||||
currentBoard: state => state.currentBoard,
|
||||
}),
|
||||
// TODO: properly handle sidebar showing for route subview and board sidebar
|
||||
sidebarRouterView() {
|
||||
// console.log(this.$route)
|
||||
return this.$route.name === 'card' || this.$route.name === 'board.details'
|
||||
},
|
||||
sidebarShown() {
|
||||
return this.sidebarRouterView || this.sidebarShownState
|
||||
},
|
||||
cardDetailsInModal: {
|
||||
get() {
|
||||
return this.$store.getters.config('cardDetailsInModal')
|
||||
},
|
||||
set(newValue) {
|
||||
this.$store.dispatch('setConfig', { cardDetailsInModal: newValue })
|
||||
},
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const initialState = loadState('deck', 'initialBoards', null)
|
||||
if (initialState !== null) {
|
||||
this.$store.dispatch('loadBoards')
|
||||
}
|
||||
this.$store.dispatch('loadSharees')
|
||||
},
|
||||
mounted() {
|
||||
// Set navigation to initial state and update in case it gets toggled
|
||||
emit('toggle-navigation', { open: !this.isMobile && this.navShown, _initial: true })
|
||||
this.$nextTick(() => {
|
||||
subscribe('navigation-toggled', (navState) => {
|
||||
this.$store.dispatch('toggleNav', navState.open)
|
||||
})
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
hideModal() {
|
||||
this.$router.push({ name: 'board' })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
#content-vue {
|
||||
#app-content {
|
||||
transition: margin-left 100ms ease;
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
#app-sidebar {
|
||||
transition: max-width 100ms ease;
|
||||
}
|
||||
|
||||
&.nav-hidden {
|
||||
#app-content {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.sidebar-hidden {
|
||||
#app-sidebar {
|
||||
max-width: 0;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../css/print';
|
||||
|
||||
.icon-activity {
|
||||
background-image: url(../img/activity-dark.svg);
|
||||
|
||||
body[data-theme-dark] & {
|
||||
background-image: url(../img/activity.svg);
|
||||
}
|
||||
}
|
||||
|
||||
.avatardiv.circles {
|
||||
background: var(--color-primary-element);
|
||||
}
|
||||
|
||||
.icon-circles {
|
||||
background-image: url(../img/circles-dark.svg);
|
||||
opacity: 1;
|
||||
background-size: 20px;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.icon-circles-white, .icon-circles.icon-white {
|
||||
background-image: url(../img/circles.svg);
|
||||
opacity: 1;
|
||||
background-size: 20px;
|
||||
background-position: center center;
|
||||
}
|
||||
|
||||
.icon-colorpicker {
|
||||
background-image: url('../img/color_picker.svg');
|
||||
}
|
||||
|
||||
.v-select {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.modal__card {
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
height: calc(100% - 20px);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -62,7 +62,7 @@ export default {
|
||||
mounted() {
|
||||
subscribe('deck:card:show-move-dialog', this.openModal)
|
||||
},
|
||||
destroyed() {
|
||||
unmounted() {
|
||||
unsubscribe('deck:card:show-move-dialog', this.openModal)
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -10,9 +10,15 @@
|
||||
:key="activity.activity_id"
|
||||
:activity="activity" />
|
||||
<InfiniteLoading :identifier="objectId" @infinite="infiniteHandler" @change="changeObject">
|
||||
<div slot="spinner" class="icon-loading" />
|
||||
<div slot="no-more" />
|
||||
<div slot="no-results" />
|
||||
<template #spinner>
|
||||
<div class="icon-loading" />
|
||||
</template>
|
||||
<template #no-more>
|
||||
<div />
|
||||
</template>
|
||||
<template #no-results>
|
||||
<div />
|
||||
</template>
|
||||
</InfiniteLoading>
|
||||
</div>
|
||||
</template>
|
||||
@@ -21,7 +27,7 @@
|
||||
import axios from '@nextcloud/axios'
|
||||
import { generateOcsUrl } from '@nextcloud/router'
|
||||
import ActivityEntry from './ActivityEntry.vue'
|
||||
import InfiniteLoading from 'vue-infinite-loading'
|
||||
// import InfiniteLoading from 'v3-infinite-loading'
|
||||
|
||||
const ACTIVITY_FETCH_LIMIT = 50
|
||||
|
||||
@@ -29,7 +35,6 @@ export default {
|
||||
name: 'ActivityList',
|
||||
components: {
|
||||
ActivityEntry,
|
||||
InfiniteLoading,
|
||||
},
|
||||
props: {
|
||||
filter: {
|
||||
|
||||
@@ -231,12 +231,16 @@
|
||||
</NcActionButton>
|
||||
<NcActionButton v-if="compactMode"
|
||||
@click="toggleCompactMode">
|
||||
<ArrowExpandVerticalIcon slot="icon" :size="20" decorative />
|
||||
<template #icon>
|
||||
<ArrowExpandVerticalIcon :size="20" decorative />
|
||||
</template>
|
||||
{{ t('deck', 'Toggle compact mode') }}
|
||||
</NcActionButton>
|
||||
<NcActionButton v-else
|
||||
@click="toggleCompactMode">
|
||||
<ArrowCollapseVerticalIcon slot="icon" :size="20" decorative />
|
||||
<template #icon>
|
||||
<ArrowCollapseVerticalIcon :size="20" decorative />
|
||||
</template>
|
||||
{{ t('deck', 'Toggle compact mode') }}
|
||||
</NcActionButton>
|
||||
<NcActionButton @click="toggleShowCardCover">
|
||||
@@ -274,6 +278,7 @@ import SessionList from './SessionList.vue'
|
||||
import { isNotifyPushEnabled } from '../sessions.js'
|
||||
import CreateNewCardCustomPicker from '../views/CreateNewCardCustomPicker.vue'
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
|
||||
export default {
|
||||
name: 'Controls',
|
||||
@@ -359,6 +364,11 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
onClickOutside(() => {
|
||||
this.hideAddStack()
|
||||
})
|
||||
},
|
||||
beforeMount() {
|
||||
subscribe('deck:board:show-new-card', this.clickShowAddCardModel)
|
||||
subscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
|
||||
@@ -366,7 +376,7 @@ export default {
|
||||
subscribe('deck:board:toggle-filter-by-me', this.triggerFilterByMe)
|
||||
|
||||
},
|
||||
beforeDestroy() {
|
||||
beforeUnmount() {
|
||||
unsubscribe('deck:board:show-new-card', this.clickShowAddCardModel)
|
||||
unsubscribe('deck:board:toggle-filter-popover', this.triggerOpenFilters)
|
||||
unsubscribe('deck:board:clear-filter', this.triggerClearFilter)
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
<!-- :style="{top:cardTop, left:cardLeft}" -->
|
||||
<div v-if="card && selector"
|
||||
ref="shortcutModal"
|
||||
v-click-outside="close"
|
||||
class="keyboard-shortcuts__modal"
|
||||
tabindex="0"
|
||||
@keydown.esc="close">
|
||||
@@ -18,6 +17,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import DueDateSelector from './card/DueDateSelector.vue'
|
||||
import { onClickOutside } from '@vueuse/core'
|
||||
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
|
||||
import { mapState } from 'vuex'
|
||||
import TagSelector from './card/TagSelector.vue'
|
||||
@@ -50,8 +50,9 @@ export default {
|
||||
subscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
|
||||
subscribe('deck:card:show-due-date-selector', this.handleShowDueDate)
|
||||
subscribe('deck:card:show-label-selector', this.handleShowLabel)
|
||||
onClickOutside(this.close)
|
||||
},
|
||||
destroyed() {
|
||||
unmounted() {
|
||||
document.removeEventListener('keydown', this.onKeydown)
|
||||
unsubscribe('deck:card:show-assignment-selector', this.handleShowAssignemnt)
|
||||
unsubscribe('deck:card:show-due-date-selector', this.handleShowDueDate)
|
||||
@@ -259,6 +260,7 @@ export default {
|
||||
this.$refs.shortcutModal?.focus()
|
||||
},
|
||||
close() {
|
||||
console.log("HHHHH")
|
||||
this.card = null
|
||||
this.selector = null
|
||||
},
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
{{ t('deck', 'Create a new list to add cards to this board') }}
|
||||
<form @submit.prevent="addNewStack()">
|
||||
<NcTextField ref="newStackInput"
|
||||
v-model="newStackTitle"
|
||||
:disable="loading"
|
||||
:value.sync="newStackTitle"
|
||||
:placeholder="t('deck', 'List name')"
|
||||
type="text" />
|
||||
<NcButton type="secondary"
|
||||
@@ -63,7 +63,10 @@
|
||||
data-click-closes-sidebar="true"
|
||||
data-dragscroll-enabled
|
||||
class="stack-draggable-wrapper">
|
||||
<Stack :stack="stack" :dragging="draggingStack" data-click-closes-sidebar="true" />
|
||||
<Stack :stack="stack"
|
||||
:dragging="draggingStack"
|
||||
data-click-closes-sidebar="true"
|
||||
@open-card="openCard" />
|
||||
</Draggable>
|
||||
</Container>
|
||||
</div>
|
||||
@@ -82,7 +85,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Container, Draggable } from 'vue-smooth-dnd'
|
||||
import { Container, Draggable } from 'vue3-smooth-dnd'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import Controls from '../Controls.vue'
|
||||
import DeckIcon from '../icons/DeckIcon.vue'
|
||||
@@ -165,14 +168,14 @@ export default {
|
||||
created() {
|
||||
this.session = createSession(this.id)
|
||||
this.fetchData()
|
||||
this.$root.$on('open-card', (cardId) => {
|
||||
this.localModal = cardId
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
beforeUnmount() {
|
||||
this.session.close()
|
||||
},
|
||||
methods: {
|
||||
openCard(cardId) {
|
||||
|
||||
},
|
||||
async fetchData() {
|
||||
this.loading = true
|
||||
try {
|
||||
@@ -253,8 +256,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../css/animations';
|
||||
@import '../../css/variables';
|
||||
@use '../../css/animations';
|
||||
@use '../../css/variables';
|
||||
|
||||
form {
|
||||
text-align: center;
|
||||
@@ -282,7 +285,7 @@ export default {
|
||||
}
|
||||
|
||||
.board {
|
||||
padding-left: $board-spacing;
|
||||
padding-left: variables.$board-spacing;
|
||||
position: relative;
|
||||
max-height: calc(100% - var(--default-clickable-area));
|
||||
overflow: hidden;
|
||||
@@ -313,8 +316,8 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// Margin left instead of padidng to avoid jumps on dropping a card
|
||||
margin-left: $stack-spacing;
|
||||
padding-right: $stack-spacing;
|
||||
margin-left: variables.$stack-spacing;
|
||||
padding-right: variables.$stack-spacing;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
padding-top: 15px;
|
||||
|
||||
@@ -102,7 +102,10 @@
|
||||
<transition :appear="animate && !card.animated && (card.animated=true)"
|
||||
:appear-class="'zoom-appear-class'"
|
||||
:appear-active-class="'zoom-appear-active-class'">
|
||||
<CardItem :id="card.id" ref="card" :dragging="draggingCard" />
|
||||
<CardItem :id="card.id"
|
||||
ref="card"
|
||||
:dragging="draggingCard"
|
||||
@open-card="openCard" />
|
||||
</transition>
|
||||
</Draggable>
|
||||
</Container>
|
||||
@@ -136,7 +139,7 @@
|
||||
<script>
|
||||
import ClickOutside from 'vue-click-outside'
|
||||
import { mapGetters, mapState } from 'vuex'
|
||||
import { Container, Draggable } from 'vue-smooth-dnd'
|
||||
import { Container, Draggable } from 'vue3-smooth-dnd'
|
||||
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
|
||||
import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue'
|
||||
import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue'
|
||||
@@ -171,6 +174,9 @@ export default {
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'open-card',
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
editing: false,
|
||||
@@ -233,6 +239,9 @@ export default {
|
||||
},
|
||||
|
||||
methods: {
|
||||
openCard(cardId) {
|
||||
this.$emit('open-card', cardId)
|
||||
},
|
||||
stopCardCreation(e) {
|
||||
// For some reason the submit event triggers a MouseEvent that is bubbling to the outside
|
||||
// so we have to ignore it
|
||||
@@ -362,10 +371,10 @@ export default {
|
||||
|
||||
@use 'sass:math';
|
||||
|
||||
@import './../../css/variables';
|
||||
@use './../../css/variables';
|
||||
|
||||
.stack {
|
||||
width: $stack-width + $stack-spacing * 3;
|
||||
width: variables.$stack-width + variables.$stack-spacing * 3;
|
||||
}
|
||||
|
||||
.stack__header {
|
||||
@@ -373,8 +382,8 @@ export default {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
padding-left: $card-spacing;
|
||||
padding-right: $card-spacing;
|
||||
padding-left: variables.$card-spacing;
|
||||
padding-right: variables.$card-spacing;
|
||||
margin: 6px;
|
||||
margin-top: 0;
|
||||
cursor: grab;
|
||||
@@ -418,7 +427,7 @@ export default {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: calc($stack-width - 60px);
|
||||
max-width: calc(variables.$stack-width - 60px);
|
||||
border-radius: 3px;
|
||||
padding: 4px 4px;
|
||||
font-size: var(--default-font-size);
|
||||
@@ -459,8 +468,8 @@ export default {
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
margin-left: $stack-spacing;
|
||||
margin-right: $stack-spacing;
|
||||
margin-left: variables.$stack-spacing;
|
||||
margin-right: variables.$stack-spacing;
|
||||
width: 100%;
|
||||
border: 2px solid var(--color-border-maxcontrast);
|
||||
border-radius: var(--border-radius-large);
|
||||
|
||||
@@ -72,8 +72,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NcActionButton, NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'
|
||||
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js'
|
||||
import { NcActionButton, NcAppSidebar, NcAppSidebarTab, NcReferenceList } from '@nextcloud/vue'
|
||||
import { getCapabilities } from '@nextcloud/capabilities'
|
||||
import { mapState, mapGetters } from 'vuex'
|
||||
import CardSidebarTabDetails from './CardSidebarTabDetails.vue'
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
:key="comment.id"
|
||||
:comment="comment"
|
||||
@doReload="loadComments" />
|
||||
<InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
|
||||
<!-- <InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
|
||||
<div slot="spinner" class="icon-loading" />
|
||||
<div slot="no-more" />
|
||||
<div slot="no-results" />
|
||||
</InfiniteLoading>
|
||||
</InfiniteLoading> -->
|
||||
</ul>
|
||||
<div v-else-if="isLoading" class="icon icon-loading" />
|
||||
<div v-else class="emptycontent">
|
||||
@@ -42,7 +42,7 @@ import { mapState, mapGetters } from 'vuex'
|
||||
import { NcAvatar } from '@nextcloud/vue'
|
||||
import CommentItem from './CommentItem.vue'
|
||||
import CommentForm from './CommentForm.vue'
|
||||
import InfiniteLoading from 'vue-infinite-loading'
|
||||
// import InfiniteLoading from 'v3-infinite-loading'
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
|
||||
export default {
|
||||
@@ -51,7 +51,7 @@ export default {
|
||||
NcAvatar,
|
||||
CommentItem,
|
||||
CommentForm,
|
||||
InfiniteLoading,
|
||||
// InfiniteLoading,
|
||||
},
|
||||
props: {
|
||||
card: {
|
||||
|
||||
@@ -2,8 +2,13 @@
|
||||
- SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div>
|
||||
THIS HAS AT
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <template>
|
||||
<div class="comment-form">
|
||||
<form @submit.prevent="submit">
|
||||
<At ref="at"
|
||||
@@ -191,4 +196,4 @@ export default {
|
||||
.atwho-li--avatar {
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
</style> -->
|
||||
|
||||
@@ -170,7 +170,7 @@ export default {
|
||||
mounted() {
|
||||
this.setupEditor()
|
||||
},
|
||||
async beforeDestroy() {
|
||||
async beforeUnmount() {
|
||||
await this.destroyEditor()
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
-->
|
||||
<template>
|
||||
<CardDetailEntry :label="t('deck', 'Assign a due date to this card…')" data-test="due-date-selector">
|
||||
<Calendar v-if="!card.done" slot="icon" :size="20" />
|
||||
<CalendarCheck v-else slot="icon" :size="20" />
|
||||
<template v-if="!card.done" #icon>
|
||||
<Calendar :size="20" />
|
||||
</template>
|
||||
<template v-else #icon>
|
||||
<CalendarCheck :size="20" />
|
||||
</template>
|
||||
<template v-if="!card.done && !card.archived">
|
||||
<NcDateTimePickerNative v-if="duedate"
|
||||
id="card-duedate-picker"
|
||||
|
||||
@@ -72,7 +72,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../css/variables';
|
||||
@use '../../css/variables';
|
||||
|
||||
.card-cover {
|
||||
height: 90px;
|
||||
|
||||
@@ -88,6 +88,7 @@ import CardMenu from './CardMenu.vue'
|
||||
import CardCover from './CardCover.vue'
|
||||
import DueDate from './badges/DueDate.vue'
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
|
||||
const TITLE_EDITING_STATE = {
|
||||
OFF: 0,
|
||||
@@ -120,6 +121,7 @@ export default {
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: ['open-card'],
|
||||
data() {
|
||||
return {
|
||||
highlight: false,
|
||||
@@ -226,8 +228,9 @@ export default {
|
||||
this.$router.push({ name: 'card', params: { id: boardId, cardId: this.card.id } }).catch(() => {})
|
||||
return
|
||||
}
|
||||
|
||||
this.$root.$emit('open-card', this.card.id)
|
||||
emit('open-card', {
|
||||
cardId: this.card.id,
|
||||
})
|
||||
},
|
||||
triggerEditTitle() {
|
||||
this.editingTitle = TITLE_EDITING_STATE.PENDING
|
||||
@@ -318,8 +321,8 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './../../css/animations';
|
||||
@import './../../css/variables';
|
||||
@use './../../css/animations';
|
||||
@use './../../css/variables';
|
||||
|
||||
@mixin dark-card {
|
||||
border: 2px solid var(--color-border-dark);
|
||||
@@ -331,8 +334,8 @@ export default {
|
||||
border-radius: var(--border-radius-large);
|
||||
font-size: 100%;
|
||||
background-color: var(--color-main-background);
|
||||
margin-bottom: $card-spacing;
|
||||
padding: var(--default-grid-baseline) $card-padding;
|
||||
margin-bottom: variables.$card-spacing;
|
||||
padding: var(--default-grid-baseline) variables.$card-padding;
|
||||
border: 2px solid var(--color-border-dark);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -470,7 +473,7 @@ export default {
|
||||
width: 32px;
|
||||
}
|
||||
&.has-labels {
|
||||
padding-bottom: $card-padding;
|
||||
padding-bottom: variables.$card-padding;
|
||||
}
|
||||
.labels {
|
||||
height: 6px;
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<NcActionButton v-if="!hideDetailsEntry" :close-after-click="true" @click="openCard">
|
||||
<CardBulletedIcon slot="icon" :size="20" decorative />
|
||||
<template #icon>
|
||||
<CardBulletedIcon icon :size="20" decorative />
|
||||
</template>
|
||||
{{ t('deck', 'Card details') }}
|
||||
</NcActionButton>
|
||||
<NcActionButton v-if="canEdit" :close-after-click="true" @click="editTitle">
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
</NcColorPicker>
|
||||
<form @submit.prevent.stop="createBoard">
|
||||
<NcTextField ref="inputField"
|
||||
v-model="value"
|
||||
:disable="loading"
|
||||
:value.sync="value"
|
||||
:placeholder="t('deck', 'Board name')"
|
||||
type="text"
|
||||
required />
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<AccountIcon v-if="board.acl.length > 0" />
|
||||
</template>
|
||||
|
||||
<template v-if="!deleted" slot="actions">
|
||||
<template v-if="!deleted" #actions>
|
||||
<template v-if="!isDueSubmenuActive">
|
||||
<NcActionButton icon="icon-info"
|
||||
:close-after-click="true"
|
||||
@@ -148,7 +148,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton } from '@nextcloud/vue'
|
||||
import { NcAppNavigationIconBullet, NcAppNavigationItem, NcColorPicker, NcButton, NcTextField, NcActionButton, NcLoadingIcon } from '@nextcloud/vue'
|
||||
import ClickOutside from 'vue-click-outside'
|
||||
import ArchiveIcon from 'vue-material-design-icons/Archive.vue'
|
||||
import CloneIcon from 'vue-material-design-icons/ContentDuplicate.vue'
|
||||
@@ -179,6 +179,7 @@ export default {
|
||||
CloseIcon,
|
||||
CheckIcon,
|
||||
BoardCloneModal,
|
||||
NcLoadingIcon,
|
||||
},
|
||||
directives: {
|
||||
ClickOutside,
|
||||
|
||||
@@ -145,7 +145,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import './../../css/variables';
|
||||
@use './../../css/variables';
|
||||
|
||||
.overview-wrapper {
|
||||
position: relative;
|
||||
@@ -162,16 +162,16 @@ export default {
|
||||
overflow-x: scroll;
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
padding-left: $board-spacing;
|
||||
padding-right: $board-spacing;
|
||||
padding-left: variables.$board-spacing;
|
||||
padding-right: variables.$board-spacing;
|
||||
|
||||
.dashboard-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: $stack-width;
|
||||
width: $stack-width;
|
||||
margin-left: $stack-spacing;
|
||||
margin-right: $stack-spacing;
|
||||
min-width: variables.$stack-width;
|
||||
width: variables.$stack-width;
|
||||
margin-left: variables.$stack-spacing;
|
||||
margin-right: variables.$stack-spacing;
|
||||
|
||||
h3 {
|
||||
font-size: var(--default-font-size);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div v-if="searchQuery!==''" class="global-search">
|
||||
<div v-if="searchQuery !== ''" class="global-search">
|
||||
<h2>
|
||||
<NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" />
|
||||
<div v-if="loading" class="icon-loading-small" />
|
||||
@@ -19,13 +19,13 @@
|
||||
:key="card.id"
|
||||
:standalone="true" />
|
||||
<Placeholder v-if="loading" />
|
||||
<InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler">
|
||||
<!-- <InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler">
|
||||
<div slot="spinner" />
|
||||
<div slot="no-more" />
|
||||
<div slot="no-results">
|
||||
{{ t('deck', 'No results found') }}
|
||||
</div>
|
||||
</InfiniteLoading>
|
||||
</InfiniteLoading> -->
|
||||
</div>
|
||||
<div v-else>
|
||||
<p>{{ t('deck', 'No results found') }}</p>
|
||||
@@ -39,7 +39,7 @@ import CardItem from '../cards/CardItem.vue'
|
||||
import { mapState } from 'vuex'
|
||||
import axios from '@nextcloud/axios'
|
||||
import { generateOcsUrl } from '@nextcloud/router'
|
||||
import InfiniteLoading from 'vue-infinite-loading'
|
||||
// import InfiniteLoading from 'v3-infinite-loading'
|
||||
import Placeholder from './Placeholder.vue'
|
||||
import { NcActions, NcActionButton, NcRichText } from '@nextcloud/vue'
|
||||
|
||||
@@ -70,7 +70,14 @@ function search({ query, cursor }) {
|
||||
|
||||
export default {
|
||||
name: 'GlobalSearchResults',
|
||||
components: { CardItem, InfiniteLoading, NcRichText, Placeholder, NcActions, NcActionButton },
|
||||
components: {
|
||||
CardItem,
|
||||
// InfiniteLoading,
|
||||
NcRichText,
|
||||
Placeholder,
|
||||
NcActions,
|
||||
NcActionButton,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
results: [],
|
||||
@@ -155,11 +162,11 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../css/variables';
|
||||
@use '../../css/variables';
|
||||
|
||||
.global-search {
|
||||
width: 100%;
|
||||
padding: $board-spacing + $stack-spacing;
|
||||
padding: variables.$board-spacing + variables.$stack-spacing;
|
||||
padding-bottom: 0;
|
||||
overflow: hidden;
|
||||
min-height: 35vh;
|
||||
@@ -175,6 +182,7 @@ export default {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
|
||||
.search-wrapper {
|
||||
overflow: scroll;
|
||||
height: 100%;
|
||||
@@ -182,13 +190,14 @@ export default {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
h2 > div {
|
||||
h2>div {
|
||||
display: inline-block;
|
||||
|
||||
&.icon-loading-small {
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
h2:deep(span) {
|
||||
background-color: var(--color-background-dark);
|
||||
padding: 3px;
|
||||
@@ -199,13 +208,14 @@ export default {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
& > div {
|
||||
&>div {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:deep(.card) {
|
||||
width: $stack-width;
|
||||
margin-right: $stack-spacing;
|
||||
width: variables.$stack-width;
|
||||
margin-right: variables.$stack-spacing;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -58,18 +58,18 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../css/variables';
|
||||
@use '../../css/variables';
|
||||
$clickable-area: var(--default-clickable-area);
|
||||
|
||||
.card--placeholder {
|
||||
width: $stack-width;
|
||||
margin-right: $stack-spacing;
|
||||
padding: $card-padding;
|
||||
width: variables.$stack-width;
|
||||
margin-right: variables.$stack-spacing;
|
||||
padding: variables.$card-padding;
|
||||
transition: box-shadow 0.1s ease-in-out;
|
||||
box-shadow: 0 0 2px 0 var(--color-box-shadow);
|
||||
border-radius: var(--border-radius-large);
|
||||
font-size: 100%;
|
||||
margin-bottom: $card-spacing;
|
||||
margin-bottom: variables.$card-spacing;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue/dist/Functions/registerReference.js'
|
||||
import { registerWidget, registerCustomPickerElement, NcCustomPickerRenderResult } from '@nextcloud/vue'
|
||||
import { translate, translatePlural } from '@nextcloud/l10n'
|
||||
|
||||
import './shared-init.js'
|
||||
|
||||
47
src/main.js
47
src/main.js
@@ -2,11 +2,10 @@
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
import Vue from 'vue'
|
||||
import { createApp } from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router.js'
|
||||
import store from './store/main.js'
|
||||
import { sync } from 'vuex-router-sync'
|
||||
import { translate, translatePlural } from '@nextcloud/l10n'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
import { subscribe } from '@nextcloud/event-bus'
|
||||
@@ -14,27 +13,32 @@ import ClickOutside from 'vue-click-outside'
|
||||
import './shared-init.js'
|
||||
import './models/index.js'
|
||||
import './sessions.js'
|
||||
import { configureCompat } from '@vue/compat'
|
||||
|
||||
configureCompat({ MODE: 3, INSTANCE_SCOPED_SLOTS: false, ATTR_ENUMERATED_COERCION: true, INSTANCE_EVENT_EMITTER: true, OPTIONS_BEFORE_DESTROY: true, CUSTOM_DIR: true, OPTIONS_DESTROYED: true, INSTANCE_LISTENERS: true, GLOBAL_SET: true })
|
||||
|
||||
// the server snap.js conflicts with vertical scrolling so we disable it
|
||||
document.body.setAttribute('data-snap-ignore', 'true')
|
||||
|
||||
sync(store, router)
|
||||
const app = createApp(App)
|
||||
|
||||
Vue.prototype.t = translate
|
||||
Vue.prototype.n = translatePlural
|
||||
app.config.globalProperties.t = translate
|
||||
app.config.globalProperties.n = translatePlural
|
||||
|
||||
Vue.directive('click-outside', ClickOutside)
|
||||
app.directive('click-outside', ClickOutside)
|
||||
|
||||
Vue.directive('focus', {
|
||||
inserted(el) {
|
||||
app.directive('focus', {
|
||||
mounted(el) {
|
||||
el.focus()
|
||||
},
|
||||
})
|
||||
|
||||
Vue.config.errorHandler = (err, vm, info) => {
|
||||
app.config.errorHandler = (err, vm, info) => {
|
||||
if (err.response && err.response.data.message) {
|
||||
const errorMessage = t('deck', 'Something went wrong')
|
||||
showError(`${errorMessage}: ${err.response.data.status} ${err.response.data.message}`)
|
||||
const errorMessage = translate('deck', 'Something went wrong')
|
||||
showError(
|
||||
`${errorMessage}: ${err.response.data.status} ${err.response.data.message}`,
|
||||
)
|
||||
}
|
||||
console.error(err)
|
||||
}
|
||||
@@ -47,16 +51,14 @@ window.addEventListener('DOMContentLoaded', () => {
|
||||
window.OCA.Files = {}
|
||||
}
|
||||
// register unused client for the sidebar to have access to its parser methods
|
||||
Object.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files)
|
||||
Object.assign(
|
||||
window.OCA.Files,
|
||||
{ App: { fileList: { filesClient: OC.Files.getClient() } } },
|
||||
window.OCA.Files,
|
||||
)
|
||||
})
|
||||
|
||||
/* eslint-disable-next-line no-new */
|
||||
new Vue({
|
||||
el: '#content',
|
||||
// eslint-disable-next-line vue/match-component-file-name
|
||||
name: 'Deck',
|
||||
router,
|
||||
store,
|
||||
app.mixin({
|
||||
data() {
|
||||
return {
|
||||
time: Date.now(),
|
||||
@@ -75,7 +77,7 @@ new Vue({
|
||||
this.time = Date.now()
|
||||
}, 1000)
|
||||
},
|
||||
beforeDestroy() {
|
||||
beforeUnmount() {
|
||||
clearInterval(this.interval)
|
||||
},
|
||||
methods: {
|
||||
@@ -86,9 +88,12 @@ new Vue({
|
||||
this.$store.commit('setSearchQuery', '')
|
||||
},
|
||||
},
|
||||
render: h => h(App),
|
||||
})
|
||||
|
||||
app.use(router)
|
||||
app.use(store)
|
||||
app.mount('#content')
|
||||
|
||||
if (!window.OCA.Deck) {
|
||||
window.OCA.Deck = {}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import Router, { createRouter, createWebHistory } from 'vue-router'
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import { generateUrl, getRootUrl } from '@nextcloud/router'
|
||||
import { BOARD_FILTERS } from './store/main.js'
|
||||
import Boards from './components/boards/Boards.vue'
|
||||
@@ -22,8 +22,8 @@ const webRootWithIndexPHP = getRootUrl() + '/index.php'
|
||||
const doesURLContainIndexPHP = window.location.pathname.startsWith(webRootWithIndexPHP)
|
||||
const currentBaseUrl = doesURLContainIndexPHP ? baseUrl : baseUrl.replace('/index.php/', '/')
|
||||
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
const router = createRouter({
|
||||
history: createWebHistory(generateUrl('/apps/deck/')),
|
||||
base: currentBaseUrl,
|
||||
linkActiveClass: 'active',
|
||||
routes: [
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'url-search-params-polyfill'
|
||||
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import { createStore } from 'vuex'
|
||||
import axios from '@nextcloud/axios'
|
||||
import { generateOcsUrl, generateUrl } from '@nextcloud/router'
|
||||
import { BoardApi } from '../services/BoardApi.js'
|
||||
@@ -18,7 +18,6 @@ import comment from './comment.js'
|
||||
import trashbin from './trashbin.js'
|
||||
import attachment from './attachment.js'
|
||||
import overview from './overview.js'
|
||||
Vue.use(Vuex)
|
||||
|
||||
const apiClient = new BoardApi()
|
||||
const debug = process.env.NODE_ENV !== 'production'
|
||||
@@ -29,7 +28,7 @@ export const BOARD_FILTERS = {
|
||||
SHARED: 'shared',
|
||||
}
|
||||
|
||||
export default new Vuex.Store({
|
||||
const store = createStore({
|
||||
modules: {
|
||||
actions,
|
||||
stack,
|
||||
@@ -519,3 +518,5 @@ export default new Vuex.Store({
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
export default store
|
||||
|
||||
@@ -33,7 +33,7 @@ import DeckIcon from '../components/icons/DeckIcon.vue'
|
||||
import { BoardApi } from './../services/BoardApi.js'
|
||||
import store from './../store/main.js'
|
||||
|
||||
import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'
|
||||
import { NcUserBubble } from '@nextcloud/vue'
|
||||
|
||||
import moment from '@nextcloud/moment'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
|
||||
@@ -31,6 +31,6 @@ if (isDevServer) {
|
||||
}
|
||||
}
|
||||
// Workaround for https://github.com/nextcloud/webpack-vue-config/pull/432 causing problems with nextcloud-vue-collections
|
||||
webpackConfig.resolve.alias = {}
|
||||
webpackConfig.resolve.alias = { vue: '@vue/compat' }
|
||||
|
||||
module.exports = webpackConfig
|
||||
|
||||
Reference in New Issue
Block a user