Replace vue-smoothdnd with vuedraggable

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl 2020-07-22 11:29:35 +02:00
parent 0135eed7da
commit 90f56dd2b0
No known key found for this signature in database
GPG Key ID: 4C614C6ED2CDE6DF
3 changed files with 46 additions and 53 deletions

View File

@ -2,23 +2,18 @@
<div id="app-dashboard"> <div id="app-dashboard">
<h2>{{ greeting.icon }} {{ greeting.text }}</h2> <h2>{{ greeting.icon }} {{ greeting.text }}</h2>
<Container class="panels" <Draggable class="panels" v-model="layout" @end="saveLayout">
orientation="horizontal" <div v-for="panelId in layout" :key="panels[panelId].id" class="panel">
drag-handle-selector=".panel--header"
@drop="onDrop">
<Draggable v-for="panelId in layout" :key="panels[panelId].id" class="panel">
<div class="panel--header"> <div class="panel--header">
<a :href="panels[panelId].url"> <h3 :class="panels[panelId].iconClass">
<h3 :class="panels[panelId].iconClass"> {{ panels[panelId].title }}
{{ panels[panelId].title }} </h3>
</h3>
</a>
</div> </div>
<div class="panel--content"> <div class="panel--content">
<div :ref="panels[panelId].id" :data-id="panels[panelId].id" /> <div :ref="panels[panelId].id" :data-id="panels[panelId].id" />
</div> </div>
</Draggable> </div>
</Container> </Draggable>
<a class="edit-panels icon-add" @click="showModal">{{ t('dashboard', 'Edit panels') }}</a> <a class="edit-panels icon-add" @click="showModal">{{ t('dashboard', 'Edit panels') }}</a>
<Modal v-if="modal" @close="closeModal"> <Modal v-if="modal" @close="closeModal">
<div class="modal__content"> <div class="modal__content">
@ -30,12 +25,12 @@
class="checkbox" class="checkbox"
:checked="isActive(panel)" :checked="isActive(panel)"
@input="updateCheckbox(panel, $event.target.checked)"> @input="updateCheckbox(panel, $event.target.checked)">
<label :for="'panel-checkbox-' + panel.id"> <label :for="'panel-checkbox-' + panel.id" :class="panel.iconClass">
{{ panel.title }} {{ panel.title }}
</label> </label>
</li> </li>
<li key="appstore"> <li key="appstore">
<a href="generateUrl('/apps/settings')" class="button">{{ t('dashboard', 'Get more panels from the app store') }}</a> <a :href="appStoreUrl" class="button">{{ t('dashboard', 'Get more panels from the app store') }}</a>
</li> </li>
</transition-group> </transition-group>
</div> </div>
@ -48,35 +43,16 @@ import Vue from 'vue'
import { loadState } from '@nextcloud/initial-state' import { loadState } from '@nextcloud/initial-state'
import { getCurrentUser } from '@nextcloud/auth' import { getCurrentUser } from '@nextcloud/auth'
import { Modal } from '@nextcloud/vue' import { Modal } from '@nextcloud/vue'
import { Container, Draggable } from 'vue-smooth-dnd' import Draggable from 'vuedraggable'
import axios from '@nextcloud/axios' import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router' import { generateUrl } from '@nextcloud/router'
const panels = loadState('dashboard', 'panels') const panels = loadState('dashboard', 'panels')
const applyDrag = (arr, dragResult) => {
const { removedIndex, addedIndex, payload } = dragResult
if (removedIndex === null && addedIndex === null) return arr
const result = [...arr]
let itemToAdd = payload
if (removedIndex !== null) {
itemToAdd = result.splice(removedIndex, 1)[0]
}
if (addedIndex !== null) {
result.splice(addedIndex, 0, itemToAdd)
}
return result
}
export default { export default {
name: 'App', name: 'App',
components: { components: {
Modal, Modal,
Container,
Draggable, Draggable,
}, },
data() { data() {
@ -87,6 +63,7 @@ export default {
name: getCurrentUser()?.displayName, name: getCurrentUser()?.displayName,
layout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]), layout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),
modal: false, modal: false,
appStoreUrl: generateUrl('/settings/apps'),
} }
}, },
computed: { computed: {
@ -161,10 +138,6 @@ export default {
layout: this.layout.join(','), layout: this.layout.join(','),
}) })
}, },
onDrop(dropResult) {
this.layout = applyDrag(this.layout, dropResult)
this.saveLayout()
},
showModal() { showModal() {
this.modal = true this.modal = true
}, },
@ -200,7 +173,9 @@ export default {
} }
.panels { .panels {
width: 100%; width: auto;
margin: auto;
max-width: 1500px;
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-direction: row; flex-direction: row;
@ -216,6 +191,10 @@ export default {
border-radius: var(--border-radius-large); border-radius: var(--border-radius-large);
border: 2px solid var(--color-border); border: 2px solid var(--color-border);
&.sortable-ghost {
opacity: 0.1;
}
& > .panel--header { & > .panel--header {
position: sticky; position: sticky;
display: flex; display: flex;
@ -229,6 +208,15 @@ export default {
backdrop-filter: blur(4px); backdrop-filter: blur(4px);
cursor: grab; cursor: grab;
&, ::v-deep * {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
&:active { &:active {
cursor: grabbing; cursor: grabbing;
} }
@ -252,6 +240,8 @@ export default {
& > .panel--content { & > .panel--content {
margin: 0 16px 16px 16px; margin: 0 16px 16px 16px;
height: 420px;
overflow: auto;
} }
} }
@ -282,6 +272,9 @@ export default {
padding: 10px; padding: 10px;
display: block; display: block;
list-style-type: none; list-style-type: none;
background-size: 16px;
background-position: left center;
padding-left: 26px;
} }
} }

26
package-lock.json generated
View File

@ -8798,11 +8798,6 @@
"is-fullwidth-code-point": "^2.0.0" "is-fullwidth-code-point": "^2.0.0"
} }
}, },
"smooth-dnd": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/smooth-dnd/-/smooth-dnd-0.12.1.tgz",
"integrity": "sha512-Dndj/MOG7VP83mvzfGCLGzV2HuK1lWachMtWl/Iuk6zV7noDycIBnflwaPuDzoaapEl3Pc4+ybJArkkx9sxPZg=="
},
"snap.js": { "snap.js": {
"version": "2.0.9", "version": "2.0.9",
"resolved": "https://registry.npmjs.org/snap.js/-/snap.js-2.0.9.tgz", "resolved": "https://registry.npmjs.org/snap.js/-/snap.js-2.0.9.tgz",
@ -8905,6 +8900,11 @@
} }
} }
}, },
"sortablejs": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.10.2.tgz",
"integrity": "sha512-YkPGufevysvfwn5rfdlGyrGjt7/CRHwvRPogD/lC+TnvcN29jDpCifKP+rBqf+LRldfXSTh+0CGLcSg0VIxq3A=="
},
"source-list-map": { "source-list-map": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
@ -9918,14 +9918,6 @@
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.3.4.tgz", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.3.4.tgz",
"integrity": "sha512-SdKRBeoXUjaZ9R/8AyxsdTqkOfMcI5tWxPZOUX5Ie1BTL5rPSZ0O++pbiZCeYeythiZIdLEfkDiQPKIaWk5hDg==" "integrity": "sha512-SdKRBeoXUjaZ9R/8AyxsdTqkOfMcI5tWxPZOUX5Ie1BTL5rPSZ0O++pbiZCeYeythiZIdLEfkDiQPKIaWk5hDg=="
}, },
"vue-smooth-dnd": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/vue-smooth-dnd/-/vue-smooth-dnd-0.8.1.tgz",
"integrity": "sha512-eZVVPTwz4A1cs0+CjXx/ihV+gAl3QBoWQnU6+23Gp59t0WBU99z7ducBQ4FvjBamqOlg8SDOE5eFHQedxwB4Wg==",
"requires": {
"smooth-dnd": "0.12.1"
}
},
"vue-style-loader": { "vue-style-loader": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz", "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
@ -9976,6 +9968,14 @@
"date-format-parse": "^0.2.5" "date-format-parse": "^0.2.5"
} }
}, },
"vuedraggable": {
"version": "2.24.0",
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.24.0.tgz",
"integrity": "sha512-IlslPpc+iZ2zPNSJbydFZIDrE+don5u+Nc/bjT2YaF+Azidc+wxxJKfKT0NwE68AKk0syb0YbZneAcnynqREZQ==",
"requires": {
"sortablejs": "^1.10.1"
}
},
"vuex": { "vuex": {
"version": "3.5.1", "version": "3.5.1",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz", "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",

View File

@ -82,7 +82,7 @@
"vue-material-design-icons": "^4.8.0", "vue-material-design-icons": "^4.8.0",
"vue-multiselect": "^2.1.6", "vue-multiselect": "^2.1.6",
"vue-router": "^3.3.4", "vue-router": "^3.3.4",
"vue-smooth-dnd": "^0.8.1", "vuedraggable": "^2.24.0",
"vuex": "^3.5.1", "vuex": "^3.5.1",
"vuex-router-sync": "^5.0.0" "vuex-router-sync": "^5.0.0"
}, },