]> source.dussan.org Git - nextcloud-server.git/commitdiff
Replace vue-smoothdnd with vuedraggable
authorJulius Härtl <jus@bitgrid.net>
Wed, 22 Jul 2020 09:29:35 +0000 (11:29 +0200)
committerJulius Härtl <jus@bitgrid.net>
Wed, 5 Aug 2020 15:01:28 +0000 (17:01 +0200)
Signed-off-by: Julius Härtl <jus@bitgrid.net>
apps/dashboard/src/App.vue
package-lock.json
package.json

index 51296c3029f446832f6786ef7258a72ca23cb82c..3841e35c60b79ba27e013842cb779f4a71bd19ec 100644 (file)
@@ -2,23 +2,18 @@
        <div id="app-dashboard">
                <h2>{{ greeting.icon }} {{ greeting.text }}</h2>
 
-               <Container class="panels"
-                       orientation="horizontal"
-                       drag-handle-selector=".panel--header"
-                       @drop="onDrop">
-                       <Draggable v-for="panelId in layout" :key="panels[panelId].id" class="panel">
+               <Draggable class="panels" v-model="layout" @end="saveLayout">
+                       <div v-for="panelId in layout" :key="panels[panelId].id" class="panel">
                                <div class="panel--header">
-                                       <a :href="panels[panelId].url">
-                                               <h3 :class="panels[panelId].iconClass">
-                                                       {{ panels[panelId].title }}
-                                               </h3>
-                                       </a>
+                                       <h3 :class="panels[panelId].iconClass">
+                                               {{ panels[panelId].title }}
+                                       </h3>
                                </div>
                                <div class="panel--content">
                                        <div :ref="panels[panelId].id" :data-id="panels[panelId].id" />
                                </div>
-                       </Draggable>
-               </Container>
+                       </div>
+               </Draggable>
                <a class="edit-panels icon-add" @click="showModal">{{ t('dashboard', 'Edit panels') }}</a>
                <Modal v-if="modal" @close="closeModal">
                        <div class="modal__content">
                                                        class="checkbox"
                                                        :checked="isActive(panel)"
                                                        @input="updateCheckbox(panel, $event.target.checked)">
-                                               <label :for="'panel-checkbox-' + panel.id">
+                                               <label :for="'panel-checkbox-' + panel.id" :class="panel.iconClass">
                                                        {{ panel.title }}
                                                </label>
                                        </li>
                                        <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>
                                </transition-group>
                        </div>
@@ -48,35 +43,16 @@ import Vue from 'vue'
 import { loadState } from '@nextcloud/initial-state'
 import { getCurrentUser } from '@nextcloud/auth'
 import { Modal } from '@nextcloud/vue'
-import { Container, Draggable } from 'vue-smooth-dnd'
+import Draggable from 'vuedraggable'
 import axios from '@nextcloud/axios'
 import { generateUrl } from '@nextcloud/router'
 
 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 {
        name: 'App',
        components: {
                Modal,
-               Container,
                Draggable,
        },
        data() {
@@ -87,6 +63,7 @@ export default {
                        name: getCurrentUser()?.displayName,
                        layout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),
                        modal: false,
+                       appStoreUrl: generateUrl('/settings/apps'),
                }
        },
        computed: {
@@ -161,10 +138,6 @@ export default {
                                layout: this.layout.join(','),
                        })
                },
-               onDrop(dropResult) {
-                       this.layout = applyDrag(this.layout, dropResult)
-                       this.saveLayout()
-               },
                showModal() {
                        this.modal = true
                },
@@ -200,7 +173,9 @@ export default {
        }
 
        .panels {
-               width: 100%;
+               width: auto;
+               margin: auto;
+               max-width: 1500px;
                display: flex;
                justify-content: center;
                flex-direction: row;
@@ -216,6 +191,10 @@ export default {
                border-radius: var(--border-radius-large);
                border: 2px solid var(--color-border);
 
+               &.sortable-ghost {
+                        opacity: 0.1;
+               }
+
                & > .panel--header {
                        position: sticky;
                        display: flex;
@@ -229,6 +208,15 @@ export default {
                        backdrop-filter: blur(4px);
                        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 {
                                cursor: grabbing;
                        }
@@ -252,6 +240,8 @@ export default {
 
                & > .panel--content {
                        margin: 0 16px 16px 16px;
+                       height: 420px;
+                       overflow: auto;
                }
        }
 
@@ -282,6 +272,9 @@ export default {
                        padding: 10px;
                        display: block;
                        list-style-type: none;
+                       background-size: 16px;
+                       background-position: left center;
+                       padding-left: 26px;
                }
        }
 
index a4715c500eb6ccb93dc455febc775ce06b8379c3..70cc0d8d0fc39d9fa60ff41a8d6645cf9ec8d9f5 100644 (file)
         "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": {
       "version": "2.0.9",
       "resolved": "https://registry.npmjs.org/snap.js/-/snap.js-2.0.9.tgz",
         }
       }
     },
+    "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": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
       "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.3.4.tgz",
       "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": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
         "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": {
       "version": "3.5.1",
       "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.5.1.tgz",
index db2528e21f057bcd7091deea675402846e8a2eb8..37588737a2c92231a7675ee951d410c264eadfa2 100644 (file)
@@ -82,7 +82,7 @@
     "vue-material-design-icons": "^4.8.0",
     "vue-multiselect": "^2.1.6",
     "vue-router": "^3.3.4",
-    "vue-smooth-dnd": "^0.8.1",
+    "vuedraggable": "^2.24.0",
     "vuex": "^3.5.1",
     "vuex-router-sync": "^5.0.0"
   },