Implemented drag and drop on spells page
This commit is contained in:
@@ -3,7 +3,10 @@
|
||||
<column-layout wide-columns>
|
||||
<div v-if="spellsWithoutList.length">
|
||||
<v-card>
|
||||
<spell-list :spells="spellsWithoutList" />
|
||||
<spell-list
|
||||
:spells="spellsWithoutList"
|
||||
:parent-ref="{id: creatureId, collection: 'creatures'}"
|
||||
/>
|
||||
</v-card>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
{title: 'Home', icon: 'home', to: '/'},
|
||||
{title: 'Characters', icon: 'portrait', to: '/characterList', requireLogin: true},
|
||||
{title: 'Library', icon: 'book', to: '/library', requireLogin: true},
|
||||
{title: 'Tabletops', icon: 'api', to: '/tabletops', requireLogin: true},
|
||||
//{title: 'Tabletops', icon: 'api', to: '/tabletops', requireLogin: true},
|
||||
//{title: 'Friends', icon: 'people', to: '/friends', requireLogin: true},
|
||||
{title: 'Feedback', icon: 'bug_report', to: '/feedback'},
|
||||
{title: 'About', icon: 'subject', to: '/about'},
|
||||
|
||||
@@ -4,26 +4,62 @@
|
||||
dense
|
||||
class="spell-list"
|
||||
>
|
||||
<template v-for="level in levels">
|
||||
<v-subheader :key="`${level}-header`">
|
||||
{{ level === 0 ? 'Cantrips' : `Level ${level}` }}
|
||||
</v-subheader>
|
||||
<spell-list-tile
|
||||
v-for="spell in spellsByLevel[level]"
|
||||
:key="spell._id"
|
||||
:data-id="`spell-list-tile-${spell._id}`"
|
||||
:model="spell"
|
||||
@click="clickProperty(spell._id)"
|
||||
/>
|
||||
</template>
|
||||
<draggable
|
||||
v-model="computedSpells"
|
||||
:group="`spell-list`"
|
||||
ghost-class="ghost"
|
||||
draggable=".item"
|
||||
handle=".handle"
|
||||
:animation="200"
|
||||
@change="change"
|
||||
>
|
||||
<template v-for="spell in computedSpells">
|
||||
<v-subheader
|
||||
v-if="spell.isSubheader"
|
||||
:key="`${spell.level}-header`"
|
||||
class="item"
|
||||
>
|
||||
{{ spell.level === 0 ? 'Cantrips' : `Level ${spell.level}` }}
|
||||
</v-subheader>
|
||||
<spell-list-tile
|
||||
v-else
|
||||
:key="spell._id"
|
||||
class="item"
|
||||
:data-id="`spell-list-tile-${spell._id}`"
|
||||
:model="spell"
|
||||
@click="clickProperty(spell._id)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</v-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable';
|
||||
import SpellListTile from '/imports/ui/properties/components/spells/SpellListTile.vue';
|
||||
import { organizeDoc } from '/imports/api/parenting/organizeMethods.js';
|
||||
|
||||
function spellsWithSubheaders(spells = []){
|
||||
let result = [];
|
||||
let lastSpell = undefined;
|
||||
let sortedSpells = [...spells].sort((a, b) => a.level - b.level)
|
||||
sortedSpells.forEach(spell => {
|
||||
if (spell.isSubheader) return;
|
||||
if (!lastSpell || spell.level > lastSpell.level){
|
||||
result.push({
|
||||
isSubheader: true,
|
||||
level: spell.level,
|
||||
});
|
||||
}
|
||||
result.push(spell);
|
||||
lastSpell = spell;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
SpellListTile,
|
||||
},
|
||||
props: {
|
||||
@@ -31,24 +67,36 @@ export default {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
parentRef: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data(){ return {
|
||||
dataSpells: [],
|
||||
}},
|
||||
computed: {
|
||||
levels(){
|
||||
let levels = new Set();
|
||||
this.spells.forEach(spell => levels.add(spell.level));
|
||||
return levels;
|
||||
},
|
||||
spellsByLevel(){
|
||||
let spellsByLevel = {};
|
||||
this.spells.forEach(spell => {
|
||||
if (!spellsByLevel[spell.level]){
|
||||
spellsByLevel[spell.level] = [spell];
|
||||
} else {
|
||||
spellsByLevel[spell.level].push(spell);
|
||||
}
|
||||
});
|
||||
return spellsByLevel;
|
||||
},
|
||||
computedSpells: {
|
||||
get(){
|
||||
return spellsWithSubheaders(this.dataSpells);
|
||||
},
|
||||
set(value){
|
||||
this.dataSpells = value;
|
||||
},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
spells(value){
|
||||
this.dataSpells = spellsWithSubheaders(value);
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.dataSpells = spellsWithSubheaders(this.spells);
|
||||
},
|
||||
methods: {
|
||||
clickProperty(_id){
|
||||
@@ -58,6 +106,31 @@ export default {
|
||||
data: {_id},
|
||||
});
|
||||
},
|
||||
change({added, moved}){
|
||||
let event = added || moved;
|
||||
if (event){
|
||||
// If this spell is now adjacent to another, set the order accordingly
|
||||
let order;
|
||||
let before = this.dataSpells[event.newIndex - 1];
|
||||
let after = this.dataSpells[event.newIndex + 1];
|
||||
if (before && before._id){
|
||||
order = before.order + 0.5;
|
||||
} else if (after && after._id) {
|
||||
order = after.order - 0.5;
|
||||
} else {
|
||||
order = -0.5;
|
||||
}
|
||||
let doc = event.element;
|
||||
organizeDoc.call({
|
||||
docRef: {
|
||||
id: doc._id,
|
||||
collection: 'creatureProperties',
|
||||
},
|
||||
parentRef: this.parentRef,
|
||||
order,
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
</v-toolbar-title>
|
||||
<v-spacer />
|
||||
</template>
|
||||
<spell-list :spells="spells" />
|
||||
<spell-list
|
||||
:spells="spells"
|
||||
:parent-ref="{id: model._id, collection: 'creatureProperties'}"
|
||||
/>
|
||||
</toolbar-card>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
{{ components }}
|
||||
</v-list-tile-sub-title>
|
||||
</v-list-tile-content>
|
||||
<v-list-tile-action>
|
||||
<v-icon
|
||||
style="height: 100%; width: 40px; cursor: move;"
|
||||
class="handle"
|
||||
>
|
||||
drag_indicator
|
||||
</v-icon>
|
||||
</v-list-tile-action>
|
||||
</v-list-tile>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user