vue3-with non-local dependencies and part of the functionality

Signed-off-by: grnd-alt <git@belakkaf.net>
This commit is contained in:
grnd-alt
2025-01-28 13:35:06 +01:00
parent a2a8b1ade5
commit b708f3967b
16 changed files with 4785 additions and 781 deletions

View File

@@ -1,6 +0,0 @@
# PLACEHOLDER SCRIPT FOR GETTING DEPENDENCIES vue3 ready
npm remove @vue/vue2-jest vue-template-compiler vue-at vuex-router-sync --force
npm install vue@3 vuex@4.1.0 vue-router@4.5.0 @vue/vue3-jest ../../../../../webpack-vue-config/ ../../../../../nextcloud-dialogs @vue/compat @vue/compiler-sfc
npm ci

5274
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@
"@nextcloud/auth": "^2.4.0", "@nextcloud/auth": "^2.4.0",
"@nextcloud/axios": "^2.5.1", "@nextcloud/axios": "^2.5.1",
"@nextcloud/capabilities": "^1.2.0", "@nextcloud/capabilities": "^1.2.0",
"@nextcloud/dialogs": "file:../../../../../nextcloud-dialogs", "@nextcloud/dialogs": "github:nextcloud-libraries/nextcloud-dialogs#vue3",
"@nextcloud/event-bus": "^3.3.1", "@nextcloud/event-bus": "^3.3.1",
"@nextcloud/files": "^3.10.1", "@nextcloud/files": "^3.10.1",
"@nextcloud/initial-state": "^2.2.0", "@nextcloud/initial-state": "^2.2.0",
@@ -43,7 +43,7 @@
"@nextcloud/moment": "^1.3.2", "@nextcloud/moment": "^1.3.2",
"@nextcloud/notify_push": "^1.3.0", "@nextcloud/notify_push": "^1.3.0",
"@nextcloud/router": "^3.0.1", "@nextcloud/router": "^3.0.1",
"@nextcloud/vue": "^8.22.0", "@nextcloud/vue": "^9.0.0-alpha.6",
"@vue/compat": "^3.5.13", "@vue/compat": "^3.5.13",
"@vue/compiler-sfc": "^3.5.13", "@vue/compiler-sfc": "^3.5.13",
"@vue/vue3-jest": "^29.2.6", "@vue/vue3-jest": "^29.2.6",
@@ -57,12 +57,13 @@
"moment": "^2.30.1", "moment": "^2.30.1",
"p-queue": "^8.0.1", "p-queue": "^8.0.1",
"url-search-params-polyfill": "^8.2.5", "url-search-params-polyfill": "^8.2.5",
"v3-infinite-loading": "^1.3.2",
"vue": "^3.5.13", "vue": "^3.5.13",
"vue-click-outside": "^1.1.0", "vue-click-outside": "^1.1.0",
"vue-easymde": "^2.0.0", "vue-easymde": "^2.0.0",
"vue-material-design-icons": "^5.3.1", "vue-material-design-icons": "^5.3.1",
"vue-router": "^4.5.0", "vue-router": "^4.5.0",
"vue-smooth-dnd": "^0.8.1", "vue3-smooth-dnd": "^0.0.6",
"vuex": "^4.1.0" "vuex": "^4.1.0"
}, },
"browserslist": [ "browserslist": [
@@ -78,7 +79,7 @@
"@nextcloud/cypress": "^1.0.0-beta.12", "@nextcloud/cypress": "^1.0.0-beta.12",
"@nextcloud/eslint-config": "^8.4.1", "@nextcloud/eslint-config": "^8.4.1",
"@nextcloud/stylelint-config": "^3.0.1", "@nextcloud/stylelint-config": "^3.0.1",
"@nextcloud/webpack-vue-config": "file:../../../../../webpack-vue-config", "@nextcloud/webpack-vue-config": "github:nextcloud-libraries/webpack-vue-config#vue3",
"@relative-ci/agent": "^4.2.14", "@relative-ci/agent": "^4.2.14",
"@vue/test-utils": "^2.4.6", "@vue/test-utils": "^2.4.6",
"cypress": "^13.17.0", "cypress": "^13.17.0",

View File

@@ -1,15 +1,41 @@
<!-- <!--
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors - SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later - 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'
export default {
name: 'App',
components: {
NcContent,
AppNavigation,
NcAppContent,
KeyboardShortcuts,
CardMoveDialog,
NcModal,
},
computed: {
cardDetailsInModal() {
return this.$store.getters.config('cardDetailsInModal')
},
},
methods: {
hideModal() {
this.$router.push({ name: 'board' })
},
},
}
</script>
<template> <template>
<NcContent app-name="deck" :class="{ 'nav-hidden': !navShown, 'sidebar-hidden': !sidebarRouterView }"> <NcContent app-name="deck">
<AppNavigation /> <AppNavigation />
<NcAppContent :allow-swipe-navigation="false"> <NcAppContent :allow-swipe-navigation="false">
<router-view /> <router-view />
</NcAppContent> </NcAppContent>
<div v-if="$route.params.id || $route.params.cardId"> <div v-if="$route.params.id || $route.params.cardId">
<NcModal v-if="cardDetailsInModal && $route.params.cardId" <NcModal v-if="cardDetailsInModal && $route.params.cardId"
:name="t('deck', 'Card details')" :name="t('deck', 'Card details')"
@@ -21,179 +47,10 @@
<router-view name="sidebar" /> <router-view name="sidebar" />
</div> </div>
</NcModal> </NcModal>
<router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" /> <router-view name="sidebar" :visible="!cardDetailsInModal || !$route.params.cardId" />
</div> </div>
<KeyboardShortcuts /> <KeyboardShortcuts />
<CardMoveDialog /> <CardMoveDialog />
</NcContent> </NcContent>
</template> </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>

View File

@@ -21,7 +21,7 @@
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import ActivityEntry from './ActivityEntry.vue' import ActivityEntry from './ActivityEntry.vue'
import InfiniteLoading from 'vue-infinite-loading' // import InfiniteLoading from 'v3-infinite-loading'
const ACTIVITY_FETCH_LIMIT = 50 const ACTIVITY_FETCH_LIMIT = 50
@@ -29,7 +29,6 @@ export default {
name: 'ActivityList', name: 'ActivityList',
components: { components: {
ActivityEntry, ActivityEntry,
InfiniteLoading,
}, },
props: { props: {
filter: { filter: {

View File

@@ -82,7 +82,7 @@
</template> </template>
<script> <script>
import { Container, Draggable } from 'vue-smooth-dnd' import { Container, Draggable } from 'vue3-smooth-dnd'
import { mapState, mapGetters } from 'vuex' import { mapState, mapGetters } from 'vuex'
import Controls from '../Controls.vue' import Controls from '../Controls.vue'
import DeckIcon from '../icons/DeckIcon.vue' import DeckIcon from '../icons/DeckIcon.vue'

View File

@@ -136,7 +136,7 @@
<script> <script>
import ClickOutside from 'vue-click-outside' import ClickOutside from 'vue-click-outside'
import { mapGetters, mapState } from 'vuex' 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 ArchiveIcon from 'vue-material-design-icons/Archive.vue'
import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue' import CardPlusOutline from 'vue-material-design-icons/CardPlusOutline.vue'
import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue' import { NcActions, NcActionButton, NcModal } from '@nextcloud/vue'
@@ -362,10 +362,10 @@ export default {
@use 'sass:math'; @use 'sass:math';
@import './../../css/variables'; @use './../../css/variables';
.stack { .stack {
width: $stack-width + $stack-spacing * 3; width: variables.$stack-width + variables.$stack-spacing * 3;
} }
.stack__header { .stack__header {
@@ -373,8 +373,8 @@ export default {
position: sticky; position: sticky;
top: 0; top: 0;
z-index: 100; z-index: 100;
padding-left: $card-spacing; padding-left: variables.$card-spacing;
padding-right: $card-spacing; padding-right: variables.$card-spacing;
margin: 6px; margin: 6px;
margin-top: 0; margin-top: 0;
cursor: grab; cursor: grab;
@@ -418,7 +418,7 @@ export default {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: calc($stack-width - 60px); max-width: calc(variables.$stack-width - 60px);
border-radius: 3px; border-radius: 3px;
padding: 4px 4px; padding: 4px 4px;
font-size: var(--default-font-size); font-size: var(--default-font-size);
@@ -459,8 +459,8 @@ export default {
form { form {
display: flex; display: flex;
margin-left: $stack-spacing; margin-left: variables.$stack-spacing;
margin-right: $stack-spacing; margin-right: variables.$stack-spacing;
width: 100%; width: 100%;
border: 2px solid var(--color-border-maxcontrast); border: 2px solid var(--color-border-maxcontrast);
border-radius: var(--border-radius-large); border-radius: var(--border-radius-large);

View File

@@ -72,8 +72,7 @@
</template> </template>
<script> <script>
import { NcActionButton, NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue' import { NcActionButton, NcAppSidebar, NcAppSidebarTab, NcReferenceList } from '@nextcloud/vue'
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js'
import { getCapabilities } from '@nextcloud/capabilities' import { getCapabilities } from '@nextcloud/capabilities'
import { mapState, mapGetters } from 'vuex' import { mapState, mapGetters } from 'vuex'
import CardSidebarTabDetails from './CardSidebarTabDetails.vue' import CardSidebarTabDetails from './CardSidebarTabDetails.vue'

View File

@@ -23,11 +23,11 @@
:key="comment.id" :key="comment.id"
:comment="comment" :comment="comment"
@doReload="loadComments" /> @doReload="loadComments" />
<InfiniteLoading :identifier="card.id" @infinite="infiniteHandler"> <!-- <InfiniteLoading :identifier="card.id" @infinite="infiniteHandler">
<div slot="spinner" class="icon-loading" /> <div slot="spinner" class="icon-loading" />
<div slot="no-more" /> <div slot="no-more" />
<div slot="no-results" /> <div slot="no-results" />
</InfiniteLoading> </InfiniteLoading> -->
</ul> </ul>
<div v-else-if="isLoading" class="icon icon-loading" /> <div v-else-if="isLoading" class="icon icon-loading" />
<div v-else class="emptycontent"> <div v-else class="emptycontent">
@@ -42,7 +42,7 @@ import { mapState, mapGetters } from 'vuex'
import { NcAvatar } from '@nextcloud/vue' import { NcAvatar } from '@nextcloud/vue'
import CommentItem from './CommentItem.vue' import CommentItem from './CommentItem.vue'
import CommentForm from './CommentForm.vue' import CommentForm from './CommentForm.vue'
import InfiniteLoading from 'vue-infinite-loading' // import InfiniteLoading from 'v3-infinite-loading'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
export default { export default {
@@ -51,7 +51,7 @@ export default {
NcAvatar, NcAvatar,
CommentItem, CommentItem,
CommentForm, CommentForm,
InfiniteLoading, // InfiniteLoading,
}, },
props: { props: {
card: { card: {

View File

@@ -318,8 +318,8 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@import './../../css/animations'; @use './../../css/animations';
@import './../../css/variables'; @use './../../css/variables';
@mixin dark-card { @mixin dark-card {
border: 2px solid var(--color-border-dark); border: 2px solid var(--color-border-dark);
@@ -332,7 +332,7 @@ export default {
font-size: 100%; font-size: 100%;
background-color: var(--color-main-background); background-color: var(--color-main-background);
margin-bottom: $card-spacing; margin-bottom: $card-spacing;
padding: var(--default-grid-baseline) $card-padding; padding: var(--default-grid-baseline) variables.$card-padding;
border: 2px solid var(--color-border-dark); border: 2px solid var(--color-border-dark);
width: 100%; width: 100%;
display: flex; display: flex;

View File

@@ -4,7 +4,7 @@
--> -->
<template> <template>
<div v-if="searchQuery!==''" class="global-search"> <div v-if="searchQuery !== ''" class="global-search">
<h2> <h2>
<NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" /> <NcRichText :text="t('deck', 'Search for {searchQuery} in all boards')" :arguments="queryStringArgs" />
<div v-if="loading" class="icon-loading-small" /> <div v-if="loading" class="icon-loading-small" />
@@ -19,13 +19,13 @@
:key="card.id" :key="card.id"
:standalone="true" /> :standalone="true" />
<Placeholder v-if="loading" /> <Placeholder v-if="loading" />
<InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler"> <!-- <InfiniteLoading :identifier="searchQuery" @infinite="infiniteHandler">
<div slot="spinner" /> <div slot="spinner" />
<div slot="no-more" /> <div slot="no-more" />
<div slot="no-results"> <div slot="no-results">
{{ t('deck', 'No results found') }} {{ t('deck', 'No results found') }}
</div> </div>
</InfiniteLoading> </InfiniteLoading> -->
</div> </div>
<div v-else> <div v-else>
<p>{{ t('deck', 'No results found') }}</p> <p>{{ t('deck', 'No results found') }}</p>
@@ -39,7 +39,7 @@ import CardItem from '../cards/CardItem.vue'
import { mapState } from 'vuex' import { mapState } from 'vuex'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router' import { generateOcsUrl } from '@nextcloud/router'
import InfiniteLoading from 'vue-infinite-loading' // import InfiniteLoading from 'v3-infinite-loading'
import Placeholder from './Placeholder.vue' import Placeholder from './Placeholder.vue'
import { NcActions, NcActionButton, NcRichText } from '@nextcloud/vue' import { NcActions, NcActionButton, NcRichText } from '@nextcloud/vue'
@@ -70,7 +70,14 @@ function search({ query, cursor }) {
export default { export default {
name: 'GlobalSearchResults', name: 'GlobalSearchResults',
components: { CardItem, InfiniteLoading, NcRichText, Placeholder, NcActions, NcActionButton }, components: {
CardItem,
// InfiniteLoading,
NcRichText,
Placeholder,
NcActions,
NcActionButton,
},
data() { data() {
return { return {
results: [], results: [],
@@ -175,6 +182,7 @@ export default {
top: 10px; top: 10px;
right: 10px; right: 10px;
} }
.search-wrapper { .search-wrapper {
overflow: scroll; overflow: scroll;
height: 100%; height: 100%;
@@ -182,13 +190,14 @@ export default {
padding: 10px; padding: 10px;
} }
h2 > div { h2>div {
display: inline-block; display: inline-block;
&.icon-loading-small { &.icon-loading-small {
margin-right: 20px; margin-right: 20px;
} }
} }
h2:deep(span) { h2:deep(span) {
background-color: var(--color-background-dark); background-color: var(--color-background-dark);
padding: 3px; padding: 3px;
@@ -199,10 +208,11 @@ export default {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
& > div { &>div {
flex-grow: 0; flex-grow: 0;
} }
} }
&:deep(.card) { &:deep(.card) {
width: $stack-width; width: $stack-width;
margin-right: $stack-spacing; margin-right: $stack-spacing;

View File

@@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later * 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 { translate, translatePlural } from '@nextcloud/l10n'
import './shared-init.js' import './shared-init.js'

View File

@@ -6,7 +6,6 @@ import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
import router from './router.js' import router from './router.js'
import store from './store/main.js' import store from './store/main.js'
import { sync } from 'vuex-router-sync'
import { translate, translatePlural } from '@nextcloud/l10n' import { translate, translatePlural } from '@nextcloud/l10n'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
import { subscribe } from '@nextcloud/event-bus' import { subscribe } from '@nextcloud/event-bus'
@@ -14,12 +13,13 @@ import ClickOutside from 'vue-click-outside'
import './shared-init.js' import './shared-init.js'
import './models/index.js' import './models/index.js'
import './sessions.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 // the server snap.js conflicts with vertical scrolling so we disable it
document.body.setAttribute('data-snap-ignore', 'true') document.body.setAttribute('data-snap-ignore', 'true')
sync(store, router)
const app = createApp(App) const app = createApp(App)
app.config.globalProperties.t = translate app.config.globalProperties.t = translate

View File

@@ -13,7 +13,6 @@ import BoardSidebar from './components/board/BoardSidebar.vue'
import CardSidebar from './components/card/CardSidebar.vue' import CardSidebar from './components/card/CardSidebar.vue'
import Overview from './components/overview/Overview.vue' import Overview from './components/overview/Overview.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(generateUrl('/apps/deck/')), history: createWebHistory(generateUrl('/apps/deck/')),
linkActiveClass: 'active', linkActiveClass: 'active',

View File

@@ -28,7 +28,6 @@ export const BOARD_FILTERS = {
SHARED: 'shared', SHARED: 'shared',
} }
const store = createStore({ const store = createStore({
modules: { modules: {
actions, actions,

View File

@@ -33,7 +33,7 @@ import DeckIcon from '../components/icons/DeckIcon.vue'
import { BoardApi } from './../services/BoardApi.js' import { BoardApi } from './../services/BoardApi.js'
import store from './../store/main.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 moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router' import { generateUrl } from '@nextcloud/router'