Improved tree view with drag and drop

This commit is contained in:
Stefan Zermatten
2019-04-15 15:40:42 +02:00
parent 062e554629
commit fc24cf4a5b
8 changed files with 219 additions and 21 deletions

View File

@@ -28,7 +28,6 @@ logging@1.1.20
reload@1.2.0
ejson@1.1.0
check@1.3.1
wizonesolutions:canonical
standard-minifier-js@2.4.0
shell-server@0.4.0
seba:minifiers-autoprefixer

View File

@@ -124,4 +124,3 @@ underscore@1.0.10
url@1.2.0
webapp@1.7.2
webapp-hashing@1.0.9
wizonesolutions:canonical@0.0.5

View File

@@ -56,6 +56,7 @@
import SmartInput from '/imports/ui/components/global/SmartInput.Story.vue';
import SpellSlotListTile from '/imports/ui/creature/properties/attributes/SpellSlotListTile.Story.vue';
import ToolbarLayout from '/imports/ui/layouts/ToolbarLayout.vue';
import TreeNode from '/imports/ui/components/tree/TreeNode.Story.vue';
export default {
components: {
@@ -76,6 +77,7 @@
SmartInput,
SpellSlotListTile,
ToolbarLayout,
TreeNode,
},
data(){ return {
sidebar: undefined,

View File

@@ -0,0 +1,44 @@
<template lang="html">
<div>
<tree-node v-bind="node" group="cheese"/>
<samp>
{{dataString}}
</samp>
<div style="height: 200px" @drop="e => log(e.dataTransfer.getData('cow'))" @dragover.prevent></div>
</div>
</template>
<script>
import TreeNode from '/imports/ui/components/tree/TreeNode.vue';
export default {
components: {
TreeNode,
},
data(){ return {
node: {
name: 'parent',
children: [
{name: 'child 1', children:[]},
{name: 'child 2', children: [
{name: 'grandchild 1', children:[]},
{name: 'grandchild 2', children:[]},
]},
{name: 'child 3', children:[]},
],
},
drag: false,
}},
computed: {
dataString(){
return JSON.stringify(this.node, null, 2);
}
},
methods: {
log: console.log,
},
};
</script>
<style lang="css" scoped>
</style>

View File

@@ -1,21 +1,98 @@
<template lang="html">
<div class="layout row">
<v-btn @click="expand">
<v-icon>arrow-right</v-icon>
</v-btn>
</div>
<div :class="!hasChildren ? 'empty' : null">
<div class="layout row align-center">
<v-btn
small icon
:class="showExpanded ? 'rotate-90' : null"
@click="expanded = !expanded"
:disabled="!hasChildren && !showEmpty"
>
<v-icon v-if="hasChildren || showEmpty">chevron_right</v-icon>
</v-btn>
<div>{{name}}</div>
</div>
<v-expand-transition>
<div v-if="showExpanded">
<draggable
:list="children"
class="drag-area layout column"
:group="group"
:animation="200"
ghost-class="ghost"
draggable=".item"
>
<tree-node
v-for="child in children"
v-bind="child"
:group="group"
:key="child.name"
class="item"
@dragstart.native="e => e.dataTransfer.setData('cow', 'moooooo')"
/>
</draggable>
</div>
</v-expand-transition>
</div>
</template>
<script>
/**
* TreeNode's are list item views of character properties. Every property which
* can belong to the character is shown in the tree view of the character
* the tree view shows off the full character structure, and where each part of
* character comes from.
**/
export default {
}
/**
* TreeNode's are list item views of character properties. Every property which
* can belong to the character is shown in the tree view of the character
* the tree view shows off the full character structure, and where each part of
* character comes from.
**/
import draggable from 'vuedraggable';
export default {
name: 'tree-node',
components: {
draggable,
},
data(){ return {
expanded: false,
}},
props: {
name: String,
group: String,
showEmpty: Boolean,
children: {
type: Array,
required: true,
},
},
computed: {
hasChildren(){
return this.children && this.children.length;
},
showExpanded(){
return this.expanded && (this.showEmpty || this.hasChildren)
},
},
methods: {
dragstart(){
console.log(arguments);
},
}
};
</script>
<style lang="css" scoped>
.rotate-90 {
transform: rotate(90deg);
}
.drag-area {
min-height: 40px;
box-shadow: -2px 0px 0px 0px #808080, 2px 0px 0px 0px #808080;
margin-left: 23px;
}
.empty .drag-area {
box-shadow: -2px 0px 0px 0px rgb(128, 128, 128, 0.4), 2px 0px 0px 0px rgb(128, 128, 128, 0.4);
}
.empty .v-btn {
opacity: 0.4;
}
.ghost {
opacity: 0.5;
background: #c8ebfb;
}
</style>

View File

@@ -1,8 +1,9 @@
<template lang="html">
<v-treeview :items="treeItems">
<v-treeview :items="treeItems" transition>
<template slot="label" slot-scope="{ item, open }">
<em>{{item.collection}}</em>:
<span v-if="item.collection === 'attributes' || item.collection === 'skills'">
{{item.name}}: {{item.value}}
{{item.name}} {{item.value}}
</span>
<span v-else-if="item.collection === 'effects'">
{{item.name}}: {{item.stat}} {{item.operation}} {{item.result}}

83
app/package-lock.json generated
View File

@@ -104,7 +104,7 @@
},
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
"resolved": false,
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
"requires": {
"inherits": "~2.0.0"
@@ -513,7 +513,7 @@
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"resolved": false,
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"ini": {
@@ -888,7 +888,7 @@
"process": "^0.11.9",
"punycode": "^1.4.1",
"querystring-es3": "^0.2.1",
"readable-stream": "git+https://github.com/meteor/readable-stream.git#c688cdd193549919b840e8d72a86682d91961e12",
"readable-stream": "git+https://github.com/meteor/readable-stream.git",
"stream-browserify": "^2.0.1",
"stream-http": "^2.8.0",
"string_decoder": "^1.1.0",
@@ -1461,6 +1461,37 @@
"requires": {
"inherits": "~2.0.1",
"readable-stream": "^2.0.2"
},
"dependencies": {
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"stream-http": {
@@ -1473,6 +1504,37 @@
"readable-stream": "^2.3.3",
"to-arraybuffer": "^1.0.0",
"xtend": "^4.0.0"
},
"dependencies": {
"readable-stream": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
"integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
"requires": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
},
"dependencies": {
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
"string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"requires": {
"safe-buffer": "~5.1.0"
}
}
}
},
"string_decoder": {
@@ -1871,7 +1933,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"resolved": false,
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
}
}
@@ -2009,6 +2071,11 @@
"mongo-object": "^0.1.3"
}
},
"sortablejs": {
"version": "1.8.4",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.8.4.tgz",
"integrity": "sha512-Brqnzelu1AhFuc0Fn3N/qFex1tlIiuQIUsfu2J8luJ4cRgXYkWrByxa+y5mWEBlj8A0YoABukflIJwvHyrwJ6Q=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
@@ -2195,6 +2262,14 @@
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.0.2.tgz",
"integrity": "sha512-opKtsxjp9eOcFWdp6xLQPLmRGgfM932Tl56U9chYTnoWqKxQ8M20N7AkdEbM5beUh6wICoFGYugAX9vQjyJLFg=="
},
"vuedraggable": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-2.20.0.tgz",
"integrity": "sha512-mrSWGkzY40nkgLDuuoxrs6/0u+A7VwXtQRruLQYOVjwd8HcT3BZatRvzw4qVCwJczsAYPbaMubkGOEtzDOzhsQ==",
"requires": {
"sortablejs": "^1.8.4"
}
},
"vuetify": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-1.5.0.tgz",

View File

@@ -32,6 +32,7 @@
"vue": "^2.6.2",
"vue-meteor-tracker": "^2.0.0-beta.5",
"vue-router": "^3.0.2",
"vuedraggable": "^2.20.0",
"vuetify": "^1.5.0",
"vuetify-upload-button": "^1.2.2",
"vuex": "^3.1.0"