Merge pull request #120 from Dumbgenius/feature-drag-drop-spells
Feature - drag and drop spells
This commit is contained in:
@@ -83,3 +83,170 @@ Spells.after.update(function (userId, spell, fieldNames) {
|
||||
|
||||
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
|
||||
Spells.deny(CHARACTER_SUBSCHEMA_DENY);
|
||||
|
||||
|
||||
|
||||
|
||||
var checkMovePermission = function(spellId, parent, destinationOnly) {
|
||||
var spell = Spells.findOne(spellId);
|
||||
if (!spell)
|
||||
throw new Meteor.Error("No such spell",
|
||||
"An spell could not be found to move");
|
||||
//handle permissions
|
||||
var permission;
|
||||
|
||||
if (!destinationOnly) { //if we're not modifying the origin, only the destination
|
||||
permission = Meteor.call("canWriteCharacter", spell.charId);
|
||||
if (!permission){
|
||||
throw new Meteor.Error("Access denied",
|
||||
"Not permitted to move spells from this character");
|
||||
}
|
||||
}
|
||||
if (parent.collection === "Characters"){
|
||||
permission = Meteor.call("canWriteCharacter", parent.id);
|
||||
if (!permission){
|
||||
throw new Meteor.Error("Access denied",
|
||||
"Not permitted to move spells to this character");
|
||||
}
|
||||
} else {
|
||||
var parentCollectionObject = global[parent.collection];
|
||||
var parentObject = null;
|
||||
if (parentCollectionObject)
|
||||
parentObject = parentCollectionObject.findOne(
|
||||
parent.id, {fields: {_id: 1, charId: 1}}
|
||||
);
|
||||
if (!parentObject) throw new Meteor.Error(
|
||||
"Invalid parent",
|
||||
"The destination parent " + parent.id +
|
||||
" does not exist in the collection " + parent.collection
|
||||
);
|
||||
if (parentObject.charId){
|
||||
permission = Meteor.call("canWriteCharacter", parentObject.charId);
|
||||
if (!permission){
|
||||
throw new Meteor.Error("Access denied",
|
||||
"Not permitted to move spells to this character");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var moveSpell = function(spellId, targetCollection, targetId) {
|
||||
var spell = Spells.findOne(spellId);
|
||||
if (!spell) return;
|
||||
targetCollection = targetCollection || spell.parent.collection;
|
||||
targetId = targetId || spell.parent.id;
|
||||
|
||||
if (Meteor.isServer) {
|
||||
checkMovePermission(spellId, {collection: targetCollection, id: targetId}, false);
|
||||
}
|
||||
|
||||
if (targetCollection == "Characters") { //then we are copying the spell to a different character.
|
||||
targetList = SpellLists.findOne({"charId": targetId});
|
||||
targetListId = targetList && targetList._id;
|
||||
if (!targetListId) {
|
||||
targetListId = SpellLists.insert({ //create a spell list if we don't already have one
|
||||
name: "New SpellList",
|
||||
charId: targetId,
|
||||
saveDC: "8 + intelligenceMod + proficiencyBonus",
|
||||
attackBonus: "intelligenceMod + proficiencyBonus",
|
||||
});
|
||||
}
|
||||
|
||||
Spells.update(
|
||||
spellId,
|
||||
{$set: {
|
||||
charId: targetId,
|
||||
"parent.collection": "SpellLists",
|
||||
"parent.id": targetListId,
|
||||
}}
|
||||
);
|
||||
}
|
||||
else { //we are moving the spell within the same character
|
||||
//update the spell provided the update will actually change something
|
||||
if (
|
||||
spell.parent.collection !== targetCollection ||
|
||||
spell.parent.id !== targetId
|
||||
){
|
||||
Spells.update(
|
||||
spellId,
|
||||
{$set: {
|
||||
"parent.collection": targetCollection,
|
||||
"parent.id": targetId,
|
||||
}}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var copySpell = function(spellId, targetCollection, targetId) {
|
||||
var spell = Spells.findOne(spellId);
|
||||
if (!spell) return;
|
||||
targetCollection = targetCollection || spell.parent.collection;
|
||||
targetId = targetId || spell.parent.id;
|
||||
|
||||
if (Meteor.isServer) {
|
||||
checkMovePermission(spellId, {collection: targetCollection, id: targetId}, true); //we're only reading from the source character
|
||||
}
|
||||
|
||||
|
||||
if (targetCollection == "Characters") { //then we are copying the spell to a different character.
|
||||
targetList = SpellLists.findOne({"charId": targetId});
|
||||
targetListId = targetList && targetList._id;
|
||||
if (!targetListId) {
|
||||
targetListId = SpellLists.insert({ //create a spell list if we don't already have one
|
||||
name: "New SpellList",
|
||||
charId: targetId,
|
||||
saveDC: "8 + intelligenceMod + proficiencyBonus",
|
||||
attackBonus: "intelligenceMod + proficiencyBonus",
|
||||
});
|
||||
}
|
||||
|
||||
newSpell = _.clone(spell);
|
||||
delete newSpell._id;
|
||||
newSpellId = Spells.insert(newSpell); //add a new copy of the spell
|
||||
Spells.update(
|
||||
newSpellId,
|
||||
{$set: {
|
||||
charId: targetId,
|
||||
"parent.collection": "SpellLists",
|
||||
"parent.id": targetListId,
|
||||
}}
|
||||
);
|
||||
}
|
||||
else { //else we are copying the spell within the same character
|
||||
newSpell = _.clone(spell);
|
||||
delete newSpell._id;
|
||||
newSpellId = Spells.insert(newSpell); //add a new copy of the spell
|
||||
Spells.update(
|
||||
newSpellId,
|
||||
{$set: {
|
||||
"parent.collection": targetCollection,
|
||||
"parent.id": targetId,
|
||||
}}
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Meteor.methods({
|
||||
moveSpellToList: function(spellId, spellListId) {
|
||||
check(spellId, String);
|
||||
check(spellListId, String);
|
||||
moveSpell(spellId, "SpellLists", spellListId);
|
||||
},
|
||||
copySpellToList: function(spellId, spellListId) {
|
||||
check(spellId, String);
|
||||
check(spellListId, String);
|
||||
copySpell(spellId, "SpellLists", spellListId);
|
||||
},
|
||||
moveSpellToCharacter: function(spellId, charId) {
|
||||
check(spellId, String);
|
||||
check(charId, String);
|
||||
moveSpell(spellId, "Characters", charId);
|
||||
},
|
||||
copySpellToCharacter: function(spellId, charId) {
|
||||
check(spellId, String);
|
||||
check(charId, String);
|
||||
copySpell(spellId, "Characters", charId);
|
||||
},
|
||||
});
|
||||
@@ -334,21 +334,23 @@ Template.layout.events({
|
||||
Session.set("inventory.dragItemId", null);
|
||||
},
|
||||
"drop .characterRepresentative": function(event, instance) {
|
||||
var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
|
||||
if (event.ctrlKey){
|
||||
//split the stack to the container
|
||||
pushDialogStack({
|
||||
template: "splitStackDialog",
|
||||
data: {
|
||||
id: itemId,
|
||||
parentCollection: "Characters",
|
||||
parentId: this._id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
//move item to the character
|
||||
Meteor.call("moveItemToCharacter", itemId, this._id);
|
||||
if (_.contains(event.originalEvent.dataTransfer.types, "dicecloud-id/items")){
|
||||
var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
|
||||
if (event.ctrlKey){
|
||||
//split the stack to the container
|
||||
pushDialogStack({
|
||||
template: "splitStackDialog",
|
||||
data: {
|
||||
id: itemId,
|
||||
parentCollection: "Characters",
|
||||
parentId: this._id,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
//move item to the character
|
||||
Meteor.call("moveItemToCharacter", itemId, this._id);
|
||||
}
|
||||
Session.set("inventory.dragItemId", null);
|
||||
}
|
||||
Session.set("inventory.dragItemId", null);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -83,7 +83,9 @@
|
||||
{{#each spells ../_id ../../_id}}
|
||||
{{#if showSpell ../../_id}}
|
||||
<div class="item-slot">
|
||||
<div class="tall spell item layout horizontal center" data-id={{_id}}>
|
||||
<div class="tall spell item layout horizontal center spellItem"
|
||||
data-id={{_id}}
|
||||
draggable={{canEditCharacter charId}}>
|
||||
<iron-icon icon="social:whatshot"
|
||||
style="color: {{hexColor color}};
|
||||
margin-right: 16px;"
|
||||
|
||||
@@ -333,3 +333,49 @@ Template.spells.events({
|
||||
event.stopPropagation();
|
||||
},
|
||||
});
|
||||
|
||||
Template.layout.events({
|
||||
"dragstart .spellItem": function(event, instance){
|
||||
event.originalEvent.dataTransfer.setData("dicecloud-id/spells", this._id);
|
||||
Session.set("spellLists.dragSpellId", this._id);
|
||||
},
|
||||
"dragend .spellItem": function(event, instance){
|
||||
Session.set("spellLists.dragSpellId", null);
|
||||
},
|
||||
|
||||
"dragover .spellList, dragenter .spellList": function(event, instance){
|
||||
if (_.contains(event.originalEvent.dataTransfer.types, "dicecloud-id/spells")){
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
"drop .spellList": function(event, instance){
|
||||
var spellId = event.originalEvent.dataTransfer.getData("dicecloud-id/spells");
|
||||
if (event.ctrlKey){
|
||||
//copy spell to new list
|
||||
Meteor.call("copySpellToList", spellId, this._id);
|
||||
} else {
|
||||
//move spell to new list
|
||||
Meteor.call("moveSpellToList", spellId, this._id);
|
||||
}
|
||||
Session.set("spellLists.dragSpellId", null);
|
||||
},
|
||||
|
||||
"dragover .characterRepresentative, dragenter .characterRepresentative": function(event, instance){
|
||||
if (_.contains(event.originalEvent.dataTransfer.types, "dicecloud-id/spells")){
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
"drop .characterRepresentative": function(event, instance) {
|
||||
if (_.contains(event.originalEvent.dataTransfer.types, "dicecloud-id/spells")){ //to prevent conflicts with item drag/drop
|
||||
var spellId = event.originalEvent.dataTransfer.getData("dicecloud-id/spells");
|
||||
if (event.ctrlKey){
|
||||
//copy spell to character
|
||||
Meteor.call("copySpellToCharacter", spellId, this._id);
|
||||
} else {
|
||||
//move spell to character
|
||||
Meteor.call("moveSpellToCharacter", spellId, this._id);
|
||||
}
|
||||
Session.set("spellLists.dragSpellId", null);
|
||||
}
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user