Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a3edb07e4 | ||
|
|
fea45d2398 | ||
|
|
18aa1b2040 | ||
|
|
9afe38d043 | ||
|
|
5ddbecf97e | ||
|
|
7b573ca86e | ||
|
|
a9256fed05 | ||
|
|
8ec10e7a6a | ||
|
|
5ee1f0a169 | ||
|
|
b0652b0102 | ||
|
|
47b68c777d | ||
|
|
16feaaa6ca | ||
|
|
8a38c167c0 | ||
|
|
1835d968f3 | ||
|
|
2a9d170647 | ||
|
|
b4649d8c87 | ||
|
|
e50bcca7ce |
4739
dataSources/srd/spells.json
Normal file
4739
dataSources/srd/spells.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,3 +10,8 @@ _.each(items, (item) => {
|
|||||||
item.library = "SRDLibraryGA3XWsd"
|
item.library = "SRDLibraryGA3XWsd"
|
||||||
LibraryItems.insert(item)
|
LibraryItems.insert(item)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
_.each(spells, (spell) => {
|
||||||
|
spell.library = "SRDLibraryGA3XWsd"
|
||||||
|
LibrarySpells.insert(spell)
|
||||||
|
});
|
||||||
|
|||||||
247
dataSources/srd/tools.json
Normal file
247
dataSources/srd/tools.json
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "Alchemist’s supplies",
|
||||||
|
"plural": "Alchemist’s supplies",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 50,
|
||||||
|
"weight": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Brewer’s supplies",
|
||||||
|
"plural": "Brewer’s supplies",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 20,
|
||||||
|
"weight": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Calligrapher’s supplies",
|
||||||
|
"plural": "Calligrapher’s supplies",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 10,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Carpenter’s tools",
|
||||||
|
"plural": "Carpenter’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 8,
|
||||||
|
"weight": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cartographer’s tools",
|
||||||
|
"plural": "Cartographer’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 15,
|
||||||
|
"weight": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cobbler’s tools",
|
||||||
|
"plural": "Cobbler’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 5,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cook’s utensils",
|
||||||
|
"plural": "Cook’s utensils",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 1,
|
||||||
|
"weight": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Glassblower’s tools",
|
||||||
|
"plural": "Glassblower’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 30,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Jeweler’s tools",
|
||||||
|
"plural": "Jeweler’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 25,
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Leatherworker’s tools",
|
||||||
|
"plural": "Leatherworker’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 5,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mason’s tools",
|
||||||
|
"plural": "Mason’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 10,
|
||||||
|
"weight": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Painter’s supplies",
|
||||||
|
"plural": "Painter’s supplies",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 10,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Potter’s tools",
|
||||||
|
"plural": "Potter’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 10,
|
||||||
|
"weight": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Smith’s tools",
|
||||||
|
"plural": "Smith’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 20,
|
||||||
|
"weight": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tinker’s tools",
|
||||||
|
"plural": "Tinker’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 50,
|
||||||
|
"weight": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Weaver’s tools",
|
||||||
|
"plural": "Weaver’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 1,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Woodcarver’s tools",
|
||||||
|
"plural": "Woodcarver’s tools",
|
||||||
|
"description": "These special tools include the items needed to pursue a craft or trade. The table shows examples of the most common types of tools, each providing items related to a single craft. Proficiency with a set of artisan’s tools lets you add your proficiency bonus to any ability checks you make using the tools in your craft. Each type of artisan’s tools requires a separate proficiency.",
|
||||||
|
"value": 1,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dice set",
|
||||||
|
"plural": "Dice sets",
|
||||||
|
"description": "This item encompasses a wide range of game pieces, including dice and decks of cards (for games such as Three-Dragon Ante). A few common examples appear on the Tools table, but other kinds of gaming sets exist. If you are proficient with a gaming set, you can add your proficiency bonus to ability checks you make to play a game with that set. Each type of gaming set requires a separate proficiency.",
|
||||||
|
"value": 0.1,
|
||||||
|
"weight": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Playing card set",
|
||||||
|
"plural": "Playing card sets",
|
||||||
|
"description": "This item encompasses a wide range of game pieces, including dice and decks of cards (for games such as Three-Dragon Ante). A few common examples appear on the Tools table, but other kinds of gaming sets exist. If you are proficient with a gaming set, you can add your proficiency bonus to ability checks you make to play a game with that set. Each type of gaming set requires a separate proficiency.",
|
||||||
|
"value": 0.5,
|
||||||
|
"weight": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Bagpipes",
|
||||||
|
"plural": "Bagpipes",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 30,
|
||||||
|
"weight": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Drum",
|
||||||
|
"plural": "Drums",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 6,
|
||||||
|
"weight": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Dulcimer",
|
||||||
|
"plural": "Dulcimers",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 25,
|
||||||
|
"weight": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Flute",
|
||||||
|
"plural": "Flutes",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 2,
|
||||||
|
"weight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Lute",
|
||||||
|
"plural": "Lutes",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 35,
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Lyre",
|
||||||
|
"plural": "Lyres",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 30,
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Horn",
|
||||||
|
"plural": "Horns",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 3,
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pan flute",
|
||||||
|
"plural": "Pan flutes",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 12,
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Shawm",
|
||||||
|
"plural": "Shawms",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 2,
|
||||||
|
"weight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Viol",
|
||||||
|
"plural": "Viols",
|
||||||
|
"description": "If you have proficiency with a given musical instrument, you can add your proficiency bonus to any ability checks you make to play music with the instrument. A bard can use a musical instrument as a spellcasting focus.",
|
||||||
|
"value": 30,
|
||||||
|
"weight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Disguise Kit",
|
||||||
|
"plural": "Disguise Kits",
|
||||||
|
"description": "This pouch of cosmetics, hair dye, and small props lets you create disguises that change your physical appearance. Proficiency with this kit lets you add your proficiency bonus to any ability checks you make to create a visual disguise.",
|
||||||
|
"value": 25,
|
||||||
|
"weight": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Forgery Kit",
|
||||||
|
"plural": "Forgery Kits",
|
||||||
|
"description": "This small box contains a variety of papers and parchments, pens and inks, seals and sealing wax, gold and silver leaf, and other supplies necessary to create convincing forgeries of physical documents. Proficiency with this kit lets you add your proficiency bonus to any ability checks you make to create a physical forgery of a document.",
|
||||||
|
"value": 15,
|
||||||
|
"weight": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Herbalism Kit",
|
||||||
|
"plural": "Herbalism Kits",
|
||||||
|
"description": "This kit contains a variety of instruments such as clippers, mortar and pestle, and pouches and vials used by herbalists to create remedies and potions. Proficiency with this kit lets you add your proficiency bonus to any ability checks you make to identify or apply herbs. Also, proficiency with this kit is required to create antitoxin and potions of healing.",
|
||||||
|
"value": 5,
|
||||||
|
"weight": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Navigator’s tools",
|
||||||
|
"plural": "Navigator’s tools",
|
||||||
|
"description": "This set of instruments is used for navigation at sea. Proficiency with navigator’s tools lets you chart a ship’s course and follow navigation charts. In addition, these tools allow you to add your proficiency bonus to any ability check you make to avoid getting lost at sea.",
|
||||||
|
"value": 25,
|
||||||
|
"weight": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Thieves’ tools",
|
||||||
|
"plural": "Thieves’ tools",
|
||||||
|
"description": "This set of tools includes a small file, a set of lock picks, a small mirror mounted on a metal handle, a set of narrow-bladed scissors, and a pair of pliers. Proficiency with these tools lets you add your proficiency bonus to any ability checks you make to disarm traps or open locks.",
|
||||||
|
"value": 25,
|
||||||
|
"weight": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Poisoner's Kit",
|
||||||
|
"plural": "Poisoner's Kits",
|
||||||
|
"description": "A poisoner’s kit includes the vials, chemicals, and other equipment necessary for the creation of poisons. Proficiency with this kit lets you add your proficiency bonus to any ability checks you make to craft or use poisons.",
|
||||||
|
"value": 50,
|
||||||
|
"weight": 2
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -46,3 +46,4 @@ templates:array
|
|||||||
ecmascript@0.6.1
|
ecmascript@0.6.1
|
||||||
es5-shim@4.6.15
|
es5-shim@4.6.15
|
||||||
differential:vulcanize
|
differential:vulcanize
|
||||||
|
reactive-dict
|
||||||
|
|||||||
66
rpg-docs/Model/Library/LibrarySpells.js
Normal file
66
rpg-docs/Model/Library/LibrarySpells.js
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
LibrarySpells = new Mongo.Collection("librarySpells");
|
||||||
|
|
||||||
|
Schemas.LibrarySpells = new SimpleSchema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
trim: false,
|
||||||
|
defaultValue: "New Spell",
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
trim: false,
|
||||||
|
},
|
||||||
|
castingTime: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
defaultValue: "action",
|
||||||
|
trim: false,
|
||||||
|
},
|
||||||
|
range: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
trim: false,
|
||||||
|
},
|
||||||
|
duration: {
|
||||||
|
type: String,
|
||||||
|
optional: true,
|
||||||
|
trim: false,
|
||||||
|
defaultValue: "Instantaneous",
|
||||||
|
},
|
||||||
|
"components.verbal": {type: Boolean, defaultValue: false},
|
||||||
|
"components.somatic": {type: Boolean, defaultValue: false},
|
||||||
|
"components.concentration": {type: Boolean, defaultValue: false},
|
||||||
|
"components.material": {type: String, optional: true},
|
||||||
|
ritual: {
|
||||||
|
type: Boolean,
|
||||||
|
defaultValue: false,
|
||||||
|
},
|
||||||
|
level: {
|
||||||
|
type: Number,
|
||||||
|
defaultValue: 1,
|
||||||
|
},
|
||||||
|
school: {
|
||||||
|
type: String,
|
||||||
|
defaultValue: "Abjuration",
|
||||||
|
allowedValues: magicSchools,
|
||||||
|
},
|
||||||
|
library: {type: String, regEx: SimpleSchema.RegEx.Id, index: 1},
|
||||||
|
effects: {type: [Schemas.LibraryEffects], defaultValue: []},
|
||||||
|
attacks: {type: [Schemas.LibraryAttacks], defaultValue: []},
|
||||||
|
});
|
||||||
|
|
||||||
|
LibrarySpells.attachSchema(Schemas.LibrarySpells);
|
||||||
|
|
||||||
|
LibrarySpells.allow({
|
||||||
|
insert(userId, doc) {
|
||||||
|
return Libraries.canEdit(userId, doc.library);
|
||||||
|
},
|
||||||
|
update(userId, doc, fields, modifier) {
|
||||||
|
return Libraries.canEdit(userId, doc.library);
|
||||||
|
},
|
||||||
|
remove(userId, doc) {
|
||||||
|
return Libraries.canEdit(userId, doc.library);
|
||||||
|
},
|
||||||
|
fetch: ["library"],
|
||||||
|
});
|
||||||
@@ -10,13 +10,13 @@ Template.registerHelper("valueString", function(value) {
|
|||||||
|
|
||||||
var resultArray = [];
|
var resultArray = [];
|
||||||
if (gp > 0) {
|
if (gp > 0) {
|
||||||
resultArray.push(gp + "gp");
|
resultArray.push(gp + " gp");
|
||||||
}
|
}
|
||||||
if (sp > 0) {
|
if (sp > 0) {
|
||||||
resultArray.push(sp + "sp");
|
resultArray.push(sp + " sp");
|
||||||
}
|
}
|
||||||
if (cp > 0) {
|
if (cp > 0) {
|
||||||
resultArray.push(cp + "cp");
|
resultArray.push(cp + " cp");
|
||||||
}
|
}
|
||||||
|
|
||||||
//build string with correct spacing
|
//build string with correct spacing
|
||||||
@@ -36,18 +36,18 @@ Template.registerHelper("longValueString", function(value) {
|
|||||||
//sp
|
//sp
|
||||||
var gp = Math.floor(value);
|
var gp = Math.floor(value);
|
||||||
if (gp > 0) {
|
if (gp > 0) {
|
||||||
resultArray.push(gp + "gp");
|
resultArray.push(gp + " gp");
|
||||||
}
|
}
|
||||||
//sp
|
//sp
|
||||||
var sp = Math.floor(10 * (value % 1));
|
var sp = Math.floor(10 * (value % 1));
|
||||||
if (sp > 0 || resultArray.length) {
|
if (sp > 0 || resultArray.length) {
|
||||||
resultArray.push(sp + "sp");
|
resultArray.push(sp + " sp");
|
||||||
}
|
}
|
||||||
//cp
|
//cp
|
||||||
var cp = 10 * ((value * 10) % 1);
|
var cp = 10 * ((value * 10) % 1);
|
||||||
cp = Math.round(cp * 1000) / 1000;
|
cp = Math.round(cp * 1000) / 1000;
|
||||||
if (cp > 0 || resultArray.length) {
|
if (cp > 0 || resultArray.length) {
|
||||||
resultArray.push(cp + "cp");
|
resultArray.push(cp + " cp");
|
||||||
}
|
}
|
||||||
|
|
||||||
//build string with correct spacing
|
//build string with correct spacing
|
||||||
|
|||||||
@@ -60,8 +60,8 @@
|
|||||||
Limit uses
|
Limit uses
|
||||||
</paper-toggle-button>
|
</paper-toggle-button>
|
||||||
{{#if usesSet}}
|
{{#if usesSet}}
|
||||||
<paper-input id="usesInput" type="number" allowed-pattern="[0-9]" class="flex"
|
<paper-input id="usesInput" class="flex" label="Uses" value={{uses}} style="flex-basis: 100px; max-width: 200px">
|
||||||
label="Uses" value={{uses}} style="flex-basis: 100px; max-width: 200px">
|
{{> formulaSuffix}}
|
||||||
</paper-input>
|
</paper-input>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="flex" style="flex-basis: 100px; max-width: 200px"></div>
|
<div class="flex" style="flex-basis: 100px; max-width: 200px"></div>
|
||||||
|
|||||||
@@ -28,9 +28,9 @@
|
|||||||
<template name="containerView">
|
<template name="containerView">
|
||||||
<div class="layout horizontal wrap center justified">
|
<div class="layout horizontal wrap center justified">
|
||||||
<table class="summaryTable fullwidth">
|
<table class="summaryTable fullwidth">
|
||||||
<tr><td>Container</td><td>{{round weight}}lbs</td><td>{{longValueString value}}</td></tr>
|
<tr><td>Container</td><td>{{round weight}} lbs</td><td>{{longValueString value}}</td></tr>
|
||||||
<tr><td>Contents</td><td>{{round contentsWeight}}lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
<tr><td>Contents</td><td>{{round contentsWeight}} lbs</td><td>{{longValueString contentsValue}}</td></tr>
|
||||||
<tr class="paper-font-body2"><td>Total</td><td>{{round totalWeight}}lbs</td><td>{{longValueString totalValue}}</td></tr>
|
<tr class="paper-font-body2"><td>Total</td><td>{{round totalWeight}} lbs</td><td>{{longValueString totalValue}}</td></tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{{#if description}}
|
{{#if description}}
|
||||||
|
|||||||
@@ -18,11 +18,11 @@
|
|||||||
<div>
|
<div>
|
||||||
<paper-material class="card">
|
<paper-material class="card">
|
||||||
<div class="top green white-text weightCarried layout horizontal center">
|
<div class="top green white-text weightCarried layout horizontal center">
|
||||||
<div class="paper-font-subhead" flex>
|
<div class="paper-font-subhead flex">
|
||||||
Weight Carried
|
Weight Carried
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{round weightCarried}}lbs
|
{{round weightCarried}} lbs
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bottom green" style="padding: 0;">
|
<div class="bottom green" style="padding: 0;">
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
{{valueString equipmentValue}}
|
{{valueString equipmentValue}}
|
||||||
</div>
|
</div>
|
||||||
<div class="paper-font-caption">
|
<div class="paper-font-caption">
|
||||||
{{round equipmentWeight}}lbs
|
{{round equipmentWeight}} lbs
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div flex class="bottom list">
|
<div flex class="bottom list">
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
{{valueString carriedValue}}
|
{{valueString carriedValue}}
|
||||||
</div>
|
</div>
|
||||||
<div class="paper-font-caption">
|
<div class="paper-font-caption">
|
||||||
{{round carriedWeight}}lbs
|
{{round carriedWeight}} lbs
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div flex class="bottom list">
|
<div flex class="bottom list">
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
{{valueString totalValue}}
|
{{valueString totalValue}}
|
||||||
</div>
|
</div>
|
||||||
<div class="paper-font-caption" style="margin-right: 8px">
|
<div class="paper-font-caption" style="margin-right: 8px">
|
||||||
{{round totalWeight}}lbs
|
{{round totalWeight}} lbs
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<paper-checkbox class="carriedCheckbox"
|
<paper-checkbox class="carriedCheckbox"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<template name="itemDetails">
|
<template name="itemDetails">
|
||||||
<div class="paper-font-headline layout horizontal wrap center justified">
|
<div class="paper-font-headline layout horizontal wrap center justified">
|
||||||
{{#if weight}}<div class="sideMargin">{{round totalWeight}}lbs</div>{{/if}}
|
{{#if weight}}<div class="sideMargin">{{round totalWeight}} lbs</div>{{/if}}
|
||||||
{{#if value}}<div>{{valueString totalValue}}</div>{{/if}}
|
{{#if value}}<div>{{valueString totalValue}}</div>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="paper-font-caption layout horizontal wrap">
|
<div class="paper-font-caption layout horizontal wrap">
|
||||||
|
|||||||
@@ -2,6 +2,22 @@
|
|||||||
background-color: #e4e4e4;
|
background-color: #e4e4e4;
|
||||||
}
|
}
|
||||||
|
|
||||||
.item-library-dialog .paper-font-subhead {
|
.item-library-dialog .category-header {
|
||||||
color: rgba(0,0,0,0.54);
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-library-dialog .category-header iron-icon {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-library-dialog .category-header iron-icon.open {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-library-dialog table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-library-dialog .library-item td {
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,32 +10,46 @@
|
|||||||
</paper-input>
|
</paper-input>
|
||||||
</app-toolbar>
|
</app-toolbar>
|
||||||
<div class="flex scroll-y">
|
<div class="flex scroll-y">
|
||||||
{{#if ready}}
|
<div class="items" style="padding:8px">
|
||||||
<div class="items" style="padding:8px">
|
{{#if searchTerm}}
|
||||||
{{#if searchTerm}}
|
{{#if searchItems.count}}
|
||||||
{{#if searchItems.count}}
|
<table style="width: 100%">
|
||||||
{{#each item in searchItems}}
|
<tbody>
|
||||||
{{>libraryItem item=item selected=(isSelected item)}}
|
{{#each item in searchItems}}
|
||||||
{{/each}}
|
{{>libraryItem item=item selected=(isSelected item)}}
|
||||||
{{else}}
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{else}}{{#if searchReady}}
|
||||||
No items match "{{searchTerm}}"
|
No items match "{{searchTerm}}"
|
||||||
{{/if}}
|
{{/if}}{{/if}}
|
||||||
{{else}}
|
{{#unless searchReady}}
|
||||||
{{#each category in categories}}
|
<div class="layout vertical center" style="width: 100%; padding: 16px;">
|
||||||
<div class="paper-font-subhead">
|
<paper-spinner active></paper-spinner>
|
||||||
{{category.name}}
|
</div>
|
||||||
</div>
|
{{/unless}}
|
||||||
{{#each item in (itemsInCategory category.key)}}
|
{{else}}
|
||||||
{{>libraryItem item=item selected=(isSelected item)}}
|
{{#each categories}}
|
||||||
{{/each}}
|
<div class="paper-font-body2 category-header clickable">
|
||||||
{{/each}}
|
<iron-icon icon="chevron-right" class="{{#if isOpen key}}open{{/if}}">
|
||||||
{{/if}}
|
</iron-icon>
|
||||||
</div>
|
{{name}}
|
||||||
{{else}}
|
</div>
|
||||||
<div class="fit layout vertical center center-justified">
|
<iron-collapse opened={{isOpen key}}>
|
||||||
<paper-spinner active></paper-spinner>
|
<table style="width: 100%">
|
||||||
</div>
|
<tbody>
|
||||||
{{/if}}
|
{{#each item in (itemsInCategory key)}}
|
||||||
|
{{>libraryItem item=item selected=(isSelected item)}}
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{#unless ready key}}
|
||||||
|
<paper-spinner active></paper-spinner>
|
||||||
|
{{/unless}}
|
||||||
|
</iron-collapse>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="layout horizontal end-justified">
|
<div class="layout horizontal end-justified">
|
||||||
<paper-button class="cancelButton">Cancel</paper-button>
|
<paper-button class="cancelButton">Cancel</paper-button>
|
||||||
@@ -45,10 +59,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="libraryItem">
|
<template name="libraryItem">
|
||||||
<div class="item library-item layout horizontal center {{#if selected}}selected{{/if}}">
|
<tr class="item library-item {{#if selected}}selected{{/if}}">
|
||||||
<paper-ripple></paper-ripple>
|
<td class="itemName">
|
||||||
<div class="itemName flex">
|
|
||||||
{{item.name}}
|
{{item.name}}
|
||||||
</div>
|
<paper-ripple></paper-ripple>
|
||||||
</div>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{item.weight}} lb.
|
||||||
|
<paper-ripple></paper-ripple>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{valueString item.value}}
|
||||||
|
<paper-ripple></paper-ripple>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,41 +1,74 @@
|
|||||||
const librarySubs = new SubsManager();
|
const librarySubs = new SubsManager();
|
||||||
|
|
||||||
|
const categories = [
|
||||||
|
{name: "Weapons", key: "weapons"},
|
||||||
|
{name: "Armor", key: "armor"},
|
||||||
|
{name: "Adventuring Gear", key: "adventuringGear"},
|
||||||
|
{name: "Tools", key: "tools"},
|
||||||
|
];
|
||||||
|
|
||||||
Template.itemLibraryDialog.onCreated(function(){
|
Template.itemLibraryDialog.onCreated(function(){
|
||||||
this.selectedItem = new ReactiveVar();
|
this.selectedItem = new ReactiveVar();
|
||||||
this.searchTerm = new ReactiveVar();
|
this.searchTerm = new ReactiveVar();
|
||||||
this.ready = new ReactiveVar();
|
this.categoriesOpen = new ReactiveVar([]);
|
||||||
|
this.readyDict = new ReactiveDict();
|
||||||
|
this.searchReady = new ReactiveVar();
|
||||||
|
librarySubs.subscribe("standardLibraries");
|
||||||
this.autorun(() => {
|
this.autorun(() => {
|
||||||
var handle = librarySubs.subscribe("standardLibraries");
|
// Subscribe to all open categories
|
||||||
this.ready.set(handle.ready());
|
_.each(this.categoriesOpen.get(), (key) => {
|
||||||
|
var handle = librarySubs.subscribe("standardLibraryItems", key);
|
||||||
|
this.autorun(() => {
|
||||||
|
this.readyDict.set(key, handle.ready());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.autorun(() => {
|
||||||
|
// If we are searching, subscibe to all categories
|
||||||
|
if (this.searchTerm.get()){
|
||||||
|
let handles = _.map(categories, category =>
|
||||||
|
librarySubs.subscribe("standardLibraryItems", category.key)
|
||||||
|
);
|
||||||
|
// Ready when all handles are ready
|
||||||
|
this.autorun(() => {
|
||||||
|
this.searchReady.set(_.every(handles, h => h.ready()));
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.itemLibraryDialog.helpers({
|
Template.itemLibraryDialog.helpers({
|
||||||
ready(){
|
ready(key){
|
||||||
return Template.instance().ready.get();
|
return Template.instance().readyDict.get(key);
|
||||||
},
|
},
|
||||||
categories(){
|
categories(){
|
||||||
return [
|
return categories;
|
||||||
{name: "Weapons", key: "weapons"},
|
|
||||||
{name: "Armor", key: "armor"},
|
|
||||||
{name: "Adventuring Gear", key: "adventuringGear"},
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
itemsInCategory(categoryKey){
|
itemsInCategory(categoryKey){
|
||||||
return LibraryItems.find({
|
return LibraryItems.find({
|
||||||
library: "SRDLibraryGA3XWsd",
|
library: "SRDLibraryGA3XWsd",
|
||||||
"settings.category": categoryKey,
|
"settings.category": categoryKey,
|
||||||
|
}, {
|
||||||
|
sort: {name: 1},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
isSelected(item){
|
isSelected(item){
|
||||||
const selected = Template.instance().selectedItem.get();
|
const selected = Template.instance().selectedItem.get();
|
||||||
return selected && selected._id === item._id;
|
return selected && selected._id === item._id;
|
||||||
},
|
},
|
||||||
|
isOpen(key){
|
||||||
|
const cats = Template.instance().categoriesOpen.get();
|
||||||
|
return _.contains(cats, key);
|
||||||
|
},
|
||||||
searchTerm(){
|
searchTerm(){
|
||||||
return Template.instance().searchTerm.get();
|
return Template.instance().searchTerm.get();
|
||||||
},
|
},
|
||||||
|
searchReady(){
|
||||||
|
return Template.instance().searchReady.get();
|
||||||
|
},
|
||||||
searchItems(){
|
searchItems(){
|
||||||
const searchTerm = Template.instance().searchTerm.get();
|
const searchTerm = Template.instance().searchTerm.get();
|
||||||
|
if (!searchTerm) return;
|
||||||
return LibraryItems.find({
|
return LibraryItems.find({
|
||||||
library: "SRDLibraryGA3XWsd",
|
library: "SRDLibraryGA3XWsd",
|
||||||
name: {
|
name: {
|
||||||
@@ -58,6 +91,17 @@ Template.itemLibraryDialog.events({
|
|||||||
"click #backButton": function(event, template){
|
"click #backButton": function(event, template){
|
||||||
popDialogStack();
|
popDialogStack();
|
||||||
},
|
},
|
||||||
|
"click .category-header": function(event, template){
|
||||||
|
let cats = template.categoriesOpen.get();
|
||||||
|
const key = this.key;
|
||||||
|
// Toggle whether this key is in the array or not
|
||||||
|
if (_.contains(cats, key)){
|
||||||
|
cats = _.without(cats, key);
|
||||||
|
} else {
|
||||||
|
cats.push(key);
|
||||||
|
}
|
||||||
|
template.categoriesOpen.set(cats);
|
||||||
|
},
|
||||||
"input .search-input, change .search-input": function(event, template){
|
"input .search-input, change .search-input": function(event, template){
|
||||||
const value = event.currentTarget.value;
|
const value = event.currentTarget.value;
|
||||||
template.searchTerm.set(value);
|
template.searchTerm.set(value);
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ Template.newCharacterDialog.helpers({
|
|||||||
|
|
||||||
changeFunction = function(field){
|
changeFunction = function(field){
|
||||||
return _.debounce(function(event, instance){
|
return _.debounce(function(event, instance){
|
||||||
console.log({field, event})
|
|
||||||
instance.character[field] = event.currentTarget.value;
|
instance.character[field] = event.currentTarget.value;
|
||||||
instance.schema.clean(instance.character);
|
instance.schema.clean(instance.character);
|
||||||
instance.context.validate(instance.character);
|
instance.context.validate(instance.character);
|
||||||
|
|||||||
@@ -131,6 +131,15 @@
|
|||||||
</paper-fab>
|
</paper-fab>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<paper-tooltip position="left">
|
||||||
|
Spell library
|
||||||
|
</paper-tooltip>
|
||||||
|
<paper-fab icon="av:library-books"
|
||||||
|
class="librarySpell"
|
||||||
|
mini>
|
||||||
|
</paper-fab>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<paper-tooltip position="left">
|
<paper-tooltip position="left">
|
||||||
New spell
|
New spell
|
||||||
|
|||||||
@@ -211,8 +211,17 @@ Template.spells.events({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
"click .addSpell": function(event, instance){
|
"click .addSpell": function(event, instance){
|
||||||
var charId = this.charId;
|
var charId = this._id;
|
||||||
var listId = SpellLists.findOne({charId: this._id})._id;
|
var list = SpellLists.findOne({charId});
|
||||||
|
var listId = list && list._id
|
||||||
|
if (!listId){
|
||||||
|
listId = SpellLists.insert({
|
||||||
|
name: "New SpellList",
|
||||||
|
charId: charId,
|
||||||
|
saveDC: "8 + intelligenceMod + proficiencyBonus",
|
||||||
|
attackBonus: "intelligenceMod + proficiencyBonus",
|
||||||
|
});
|
||||||
|
}
|
||||||
var id = Spells.insert({
|
var id = Spells.insert({
|
||||||
name: "New Spell",
|
name: "New Spell",
|
||||||
charId: this._id,
|
charId: this._id,
|
||||||
@@ -229,6 +238,48 @@ Template.spells.events({
|
|||||||
returnElement: () => instance.find(`.spell[data-id='${id}']`),
|
returnElement: () => instance.find(`.spell[data-id='${id}']`),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
"click .librarySpell": function(event, instance){
|
||||||
|
var charId = this._id;
|
||||||
|
var spellId = Random.id();
|
||||||
|
var list = SpellLists.findOne({charId});
|
||||||
|
var listId = list && list._id
|
||||||
|
pushDialogStack({
|
||||||
|
template: "spellLibraryDialog",
|
||||||
|
element: event.currentTarget,
|
||||||
|
callback: (result) => {
|
||||||
|
if (!result) return;
|
||||||
|
if (!listId){
|
||||||
|
listId = SpellLists.insert({
|
||||||
|
name: "New SpellList",
|
||||||
|
charId: charId,
|
||||||
|
saveDC: "8 + intelligenceMod + proficiencyBonus",
|
||||||
|
attackBonus: "intelligenceMod + proficiencyBonus",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Make the library spell into a regular spell
|
||||||
|
let spell = _.omit(result, "library", "attacks", "effects");
|
||||||
|
spell.charId = charId;
|
||||||
|
spell.parent = {
|
||||||
|
id: listId,
|
||||||
|
collection: "SpellLists",
|
||||||
|
};
|
||||||
|
spell.prepared = "prepared";
|
||||||
|
Spells.insert(spell);
|
||||||
|
// Copy over attacks and effects
|
||||||
|
_.each(result.attacks, (attack) => {
|
||||||
|
attack.charId = charId;
|
||||||
|
attack.parent = {id: spellId, collection: "Spells"};
|
||||||
|
Attacks.insert(attack);
|
||||||
|
});
|
||||||
|
_.each(result.effects, (effect) => {
|
||||||
|
effect.charId = charId;
|
||||||
|
effect.parent = {id: spellId, collection: "Spells"};
|
||||||
|
Effects.insert(effect);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
returnElement: () => $(`[data-id='${spellId}']`).get(0),
|
||||||
|
})
|
||||||
|
},
|
||||||
"click .preparedCheckbox": function(event){
|
"click .preparedCheckbox": function(event){
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
.spell-library-dialog .spell.selected {
|
||||||
|
background-color: #e4e4e4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-library-dialog .category-header {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-library-dialog .category-header iron-icon {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-library-dialog .category-header iron-icon.open {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-library-dialog table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-library-dialog .library-spell td {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<template name="spellLibraryDialog">
|
||||||
|
<div class="fit spell-library-dialog layout vertical">
|
||||||
|
<app-toolbar class="app-grey white-text">
|
||||||
|
<paper-icon-button id="backButton"
|
||||||
|
icon="arrow-back">
|
||||||
|
</paper-icon-button>
|
||||||
|
<div main-title>Spells</div>
|
||||||
|
<paper-input label="Search" class="search-input">
|
||||||
|
<iron-icon icon="search" prefix></iron-icon>
|
||||||
|
</paper-input>
|
||||||
|
</app-toolbar>
|
||||||
|
<div class="flex scroll-y">
|
||||||
|
<div class="spells" style="padding:8px">
|
||||||
|
{{#if searchTerm}}
|
||||||
|
{{#if searchSpells.count}}
|
||||||
|
<table style="width: 100%">
|
||||||
|
<tbody>
|
||||||
|
{{#each spell in searchSpells}}
|
||||||
|
{{>librarySpell spell=spell selected=(isSelected spell)}}
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{else}}{{#if searchReady}}
|
||||||
|
No spells match "{{searchTerm}}"
|
||||||
|
{{/if}}{{/if}}
|
||||||
|
{{#unless searchReady}}
|
||||||
|
<div class="layout vertical center" style="width: 100%; padding: 16px;">
|
||||||
|
<paper-spinner active></paper-spinner>
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
{{else}}
|
||||||
|
{{#each categories}}
|
||||||
|
<div class="paper-font-body2 category-header clickable">
|
||||||
|
<iron-icon icon="chevron-right" class="{{#if isOpen key}}open{{/if}}">
|
||||||
|
</iron-icon>
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
<iron-collapse opened={{isOpen key}}>
|
||||||
|
<table style="width: 100%">
|
||||||
|
<tbody>
|
||||||
|
{{#each spell in (spellsInCategory key)}}
|
||||||
|
{{>librarySpell spell=spell selected=(isSelected spell)}}
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{#unless ready key}}
|
||||||
|
<paper-spinner active></paper-spinner>
|
||||||
|
{{/unless}}
|
||||||
|
</iron-collapse>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal end-justified">
|
||||||
|
<paper-button class="cancelButton">Cancel</paper-button>
|
||||||
|
<paper-button class="okButton">OK</paper-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="librarySpell">
|
||||||
|
<tr class="spell library-spell {{#if selected}}selected{{/if}}">
|
||||||
|
<td class="spellName">
|
||||||
|
{{spell.name}}
|
||||||
|
<paper-ripple></paper-ripple>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
const librarySubs = new SubsManager();
|
||||||
|
|
||||||
|
const categories = [
|
||||||
|
{name: "Cantrips", key: 0},
|
||||||
|
{name: "Level 1", key: 1},
|
||||||
|
{name: "Level 2", key: 2},
|
||||||
|
{name: "Level 3", key: 3},
|
||||||
|
{name: "Level 4", key: 4},
|
||||||
|
{name: "Level 5", key: 5},
|
||||||
|
{name: "Level 6", key: 6},
|
||||||
|
{name: "Level 7", key: 7},
|
||||||
|
{name: "Level 8", key: 8},
|
||||||
|
{name: "Level 9", key: 9},
|
||||||
|
];
|
||||||
|
|
||||||
|
Template.spellLibraryDialog.onCreated(function(){
|
||||||
|
this.selectedSpell = new ReactiveVar();
|
||||||
|
this.searchTerm = new ReactiveVar();
|
||||||
|
this.categoriesOpen = new ReactiveVar([]);
|
||||||
|
this.readyDict = new ReactiveDict();
|
||||||
|
this.searchReady = new ReactiveVar();
|
||||||
|
librarySubs.subscribe("standardLibraries");
|
||||||
|
this.autorun(() => {
|
||||||
|
// Subscribe to all open categories
|
||||||
|
_.each(this.categoriesOpen.get(), (key) => {
|
||||||
|
var handle = librarySubs.subscribe("standardLibrarySpells", key);
|
||||||
|
this.autorun(() => {
|
||||||
|
this.readyDict.set(key, handle.ready());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.autorun(() => {
|
||||||
|
// If we are searching, subscibe to all categories
|
||||||
|
if (this.searchTerm.get()){
|
||||||
|
let handles = _.map(categories, category =>
|
||||||
|
librarySubs.subscribe("standardLibrarySpells", category.key)
|
||||||
|
);
|
||||||
|
// Ready when all handles are ready
|
||||||
|
this.autorun(() => {
|
||||||
|
this.searchReady.set(_.every(handles, h => h.ready()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.spellLibraryDialog.helpers({
|
||||||
|
ready(key){
|
||||||
|
return Template.instance().readyDict.get(key);
|
||||||
|
},
|
||||||
|
categories(){
|
||||||
|
return categories;
|
||||||
|
},
|
||||||
|
spellsInCategory(categoryKey){
|
||||||
|
return LibrarySpells.find({
|
||||||
|
library: "SRDLibraryGA3XWsd",
|
||||||
|
level: categoryKey,
|
||||||
|
}, {
|
||||||
|
sort: {name: 1},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
isSelected(spell){
|
||||||
|
const selected = Template.instance().selectedSpell.get();
|
||||||
|
return selected && selected._id === spell._id;
|
||||||
|
},
|
||||||
|
isOpen(key){
|
||||||
|
const cats = Template.instance().categoriesOpen.get();
|
||||||
|
return _.contains(cats, key);
|
||||||
|
},
|
||||||
|
searchTerm(){
|
||||||
|
return Template.instance().searchTerm.get();
|
||||||
|
},
|
||||||
|
searchReady(){
|
||||||
|
return Template.instance().searchReady.get();
|
||||||
|
},
|
||||||
|
searchSpells(){
|
||||||
|
const searchTerm = Template.instance().searchTerm.get();
|
||||||
|
if (!searchTerm) return;
|
||||||
|
return LibrarySpells.find({
|
||||||
|
library: "SRDLibraryGA3XWsd",
|
||||||
|
name: {
|
||||||
|
$regex: new RegExp(".*" + searchTerm + ".*", "gi")
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.spellLibraryDialog.events({
|
||||||
|
"click .cancelButton": function(event, template){
|
||||||
|
popDialogStack();
|
||||||
|
},
|
||||||
|
"click .okButton": function(event, template){
|
||||||
|
popDialogStack(template.selectedSpell.get());
|
||||||
|
},
|
||||||
|
"click .library-spell": function(event, template){
|
||||||
|
template.selectedSpell.set(this.spell);
|
||||||
|
},
|
||||||
|
"click #backButton": function(event, template){
|
||||||
|
popDialogStack();
|
||||||
|
},
|
||||||
|
"click .category-header": function(event, template){
|
||||||
|
let cats = template.categoriesOpen.get();
|
||||||
|
const key = this.key;
|
||||||
|
// Toggle whether this key is in the array or not
|
||||||
|
if (_.contains(cats, key)){
|
||||||
|
cats = _.without(cats, key);
|
||||||
|
} else {
|
||||||
|
cats.push(key);
|
||||||
|
}
|
||||||
|
template.categoriesOpen.set(cats);
|
||||||
|
},
|
||||||
|
"input .search-input, change .search-input": function(event, template){
|
||||||
|
const value = event.currentTarget.value;
|
||||||
|
template.searchTerm.set(value);
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -7,10 +7,6 @@
|
|||||||
display: initial !important;
|
display: initial !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#navPanel {
|
|
||||||
padding: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#navPanel paper-icon-item {
|
#navPanel paper-icon-item {
|
||||||
background: white;
|
background: white;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|||||||
@@ -174,7 +174,7 @@ const dialogCloseAnimation = ({element, returnElement, dialog, callback}) => {
|
|||||||
const stackCompensation = dialogs._array.length ? 16 : 0;
|
const stackCompensation = dialogs._array.length ? 16 : 0;
|
||||||
|
|
||||||
// Insert clone before its progenitor so it can inherit css correctly
|
// Insert clone before its progenitor so it can inherit css correctly
|
||||||
element.parentNode.insertBefore(clone, element);
|
element.parentNode && element.parentNode.insertBefore(clone, element);
|
||||||
|
|
||||||
// Polymer messes up fixed positioning, measure and compensate
|
// Polymer messes up fixed positioning, measure and compensate
|
||||||
startingRect = clone.getBoundingClientRect();
|
startingRect = clone.getBoundingClientRect();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
"/components/app-layout/app-scroll-effects/effects/parallax-background.html",
|
"/components/app-layout/app-scroll-effects/effects/parallax-background.html",
|
||||||
"/components/app-layout/app-scroll-effects/effects/resize-title.html",
|
"/components/app-layout/app-scroll-effects/effects/resize-title.html",
|
||||||
|
|
||||||
|
"/components/iron-collapse/iron-collapse.html",
|
||||||
"/components/iron-icon/iron-icon.html",
|
"/components/iron-icon/iron-icon.html",
|
||||||
"/components/iron-icons/av-icons.html",
|
"/components/iron-icons/av-icons.html",
|
||||||
"/components/iron-icons/editor-icons.html",
|
"/components/iron-icons/editor-icons.html",
|
||||||
|
|||||||
@@ -1,9 +1,25 @@
|
|||||||
|
const standardLibraryIds = [
|
||||||
|
"SRDLibraryGA3XWsd",
|
||||||
|
];
|
||||||
|
|
||||||
Meteor.publish("standardLibraries", function(){
|
Meteor.publish("standardLibraries", function(){
|
||||||
const standardLibraryIds = [
|
return Libraries.find({_id: {$in: standardLibraryIds}});
|
||||||
"SRDLibraryGA3XWsd",
|
});
|
||||||
];
|
|
||||||
return [
|
Meteor.publish("standardLibraryItems", function(categoryKey){
|
||||||
LibraryItems.find({library: {$in: standardLibraryIds}}),
|
return LibraryItems.find({
|
||||||
Libraries.find({_id: {$in: standardLibraryIds}}),
|
library: {$in: standardLibraryIds},
|
||||||
];
|
"settings.category": categoryKey,
|
||||||
|
}, {
|
||||||
|
sort: {name: 1},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Meteor.publish("standardLibrarySpells", function(level){
|
||||||
|
return LibrarySpells.find({
|
||||||
|
library: {$in: standardLibraryIds},
|
||||||
|
level,
|
||||||
|
}, {
|
||||||
|
sort: {name: 1},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user