Added color options for containers, added spell lists

This commit is contained in:
Thaum
2015-02-12 13:08:20 +00:00
parent 5e98154e8d
commit 7441f09f37
32 changed files with 226 additions and 84 deletions

View File

@@ -187,7 +187,8 @@ Schemas.Character = new SimpleSchema({
//permissions
owner: { type: String, regEx: SimpleSchema.RegEx.Id },
readers: { type: [String], regEx: SimpleSchema.RegEx.Id },
writers: { type: [String], regEx: SimpleSchema.RegEx.Id }
writers: { type: [String], regEx: SimpleSchema.RegEx.Id },
color: {type: String, allowedValues: _.keys(colorOptions), defaultValue: "grey"}
//TODO add per-character settings
});

View File

@@ -7,6 +7,7 @@ Schemas.Feature = new SimpleSchema({
uses: {type: String, optional: true, trim: false},
used: {type: Number, defaultValue: 0},
reset: {type: String, allowedValues: ["manual", "longRest", "shortRest"], defaultValue: "manual"},
color: {type: String, allowedValues: _.keys(colorOptions), defaultValue: "green"}
});
Features.attachSchema(Schemas.Feature);

View File

@@ -3,8 +3,7 @@ Spells = new Meteor.Collection("spells");
Schemas.Spell = new SimpleSchema({
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
listId: {type: String, regEx: SimpleSchema.RegEx.Id},
prepared: {type: Boolean, defaultValue: false},
prepareCost: {type: Number, defaultValue: 1}, //0 for spells that "dont count against your max number of spells prepared", 1 otherwise
prepared: {type: String, defaultValue: "unprepared", allowedValues: ["prepared","unprepared","always"]},
name: {type: String},
description: {type: String, optional: true},
castingTime: {type: String, optional: true},

View File

@@ -8,7 +8,8 @@ Schemas.Container = new SimpleSchema({
isCarried: { type: Boolean },
weight: {type: Number, min: 0, defaultValue: 0, decimal: true},
value: {type: Number, min: 0, defaultValue: 0, decimal: true},
description:{type: String, optional: true}
description:{type: String, optional: true},
color: {type: String, allowedValues: _.keys(colorOptions), defaultValue: "brown"}
});
Containers.attachSchema(Schemas.Container);

View File

@@ -25,7 +25,7 @@ Router.map( function () {
];
},
data: function() {
var data = Characters.findOne({_id: this.params._id}, {fields: {_id: 1, name: 1}});
var data = Characters.findOne({_id: this.params._id}, {fields: {_id: 1, name: 1, color: 1}});
return data;
}
});

View File

@@ -0,0 +1,3 @@
Template.registerHelper("colorClass", function(color){
return color? getColorClass(color) : getColorClass(this.color);
});

View File

@@ -1,79 +1,83 @@
.red {
html /deep/ .red {
background-color: #F44336;
}
.pink {
html /deep/ .pink {
background-color: #E91E63;
}
.purple {
html /deep/ .purple {
background-color: #9C27B0;
}
.deep-purple {
html /deep/ .deep-purple {
background-color: #673AB7;
}
.indigo {
html /deep/ .indigo {
background-color: #3F51B5;
}
.blue {
html /deep/ .blue {
background-color: #2196F3;
}
.light-blue {
html /deep/ .light-blue {
background-color: #03A9F4;
}
.cyan {
html /deep/ .cyan {
background-color: #00BCD4;
}
.teal {
html /deep/ .teal {
background-color: #009688;
}
.green {
html /deep/ .green {
background-color: #4CAF50;
}
.light-green {
html /deep/ .light-green {
background-color: #8BC34A;
}
.lime {
html /deep/ .lime {
background-color: #CDDC39;
}
.yellow {
html /deep/ .yellow {
background-color: #FFEB3B;
}
.amber {
html /deep/ .amber {
background-color: #FFC107;
}
.orange {
html /deep/ .orange {
background-color: #FF9800;
}
.deep-orange {
html /deep/ .deep-orange {
background-color: #FF5722;
}
.brown {
html /deep/ .brown {
background-color: #795548;
}
.grey {
html /deep/ .grey {
background-color: #9E9E9E;
}
.blue-grey {
html /deep/ .blue-grey {
background-color: #607D8B;
}
.white {
html /deep/ .white {
background-color: #ffffff;
}
html /deep/ .black {
background-color: #000000;
}

View File

@@ -97,6 +97,7 @@ paper-button {
.fab-buffer {
height: 88px;
width: 100%;
order: 999;
}
*[hidden] {
@@ -123,3 +124,11 @@ paper-button {
paper-fab-menu /deep/ .container {
padding: 24px !important;
}
.list-subhead {
color: rgba(0,0,0,0.54);
font-size: 14px;
height: 40px;
padding-left: 16px;
font-weight: 500;
}

View File

@@ -96,4 +96,8 @@ p, .body1, body {
.white-text .caption{
color: rgba(255,255,255,0.54);
}
}
html /deep/ .white-text{
color: #fff;
}

View File

@@ -1,6 +1,5 @@
paper-tabs, core-toolbar {
background-color: #795548;
color: #fff;
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.2);
}

View File

@@ -1,13 +1,13 @@
<template name="characterSheet">
<!--<div tool horizontal layout flex end-justified class="bottom">Title-bottom</div>-->
<core-toolbar class="medium-tall">
<core-toolbar class="medium-tall {{colorClass}}">
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
<div flex>
{{name}}
</div>
<paper-icon-button icon="more-vert" role="button"></paper-icon-button>
<div class="bottom fit" horizontal layout>
<paper-tabs flex horizontal center layout id="characterSheetTabs" selected={{selectedTab}}>
<paper-tabs flex horizontal center layout id="characterSheetTabs" selected={{selectedTab}} class="{{colorClass}}">
<paper-tab>Stats</paper-tab>
<paper-tab>Features</paper-tab>
<paper-tab>Inventory</paper-tab>

View File

@@ -30,7 +30,7 @@ Template.characterSheet.rendered = function(){
Template.characterSheet.helpers({
selectedTab: function(){
return Template.instance().selectedTab.get();
},
}
});
Template.characterSheet.events({

View File

@@ -1,7 +1,7 @@
<template name="featureDialog">
{{#with feature}}
<core-header-panel fit>
<core-toolbar hero-id="toolbar" hero>
<core-toolbar class={{colorClass}} hero-id="toolbar" hero>
<paper-icon-button id="backButton" role="button" tabindex="0" icon="arrow-back" aria-label="close"></paper-icon-button>
<div flex>{{name}}</div>
<paper-icon-button id="deleteFeature"
@@ -12,26 +12,31 @@
noink></paper-icon-button>
</core-toolbar>
<div class="detailContent">
<!--name-->
<paper-input id="featureNameInput" label="Name" floatinglabel value={{name}}></paper-input>
<!--color-->
{{> colorDropdown}}
<hr style="margin: 16px 0 16px 0;">
<!--description-->
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="featureDescriptionInput" placeholder aria-label="Description" value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<hr style="margin: 16px 0 16px 0;">
<div layout horizontal center>
<div class="caption">Limit Uses <paper-toggle-button id="limitUseCheck"
checked={{usesSet}}
role="button"
aria-pressed="false"
tabindex="0"
touch-action="pan-y">
</paper-toggle-button>
{{#if usesSet}}
<paper-input id="usesInput" label="Uses" floatinglabel value={{uses}}></paper-input>
{{/if}}
</div>
<div layout horizontal center style="height: 60px;">
<div class="caption">Limit Uses</div>
<paper-toggle-button id="limitUseCheck"
checked={{usesSet}}
role="button"
aria-pressed="false"
tabindex="0"
touch-action="pan-y"
style="margin-left: 8px; margin-right:8px;">
</paper-toggle-button>
{{#if usesSet}}
<paper-input id="usesInput" label="Uses" floatinglabel value={{uses}}></paper-input>
{{/if}}
</div>
{{#if effects}}
<hr style="margin: 16px 0 16px 0;">

View File

@@ -55,6 +55,12 @@ Template.featureDialog.events({
var featureId = this._id;
Features.update(featureId, {$set: {uses: value}});
},
"core-select .colorDropdown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var value = detail.item.getAttribute("name");
Features.update(this._id, {$set: {color: value}});
}
});
Template.featureDialog.helpers({
@@ -67,5 +73,8 @@ Template.featureDialog.helpers({
},
usesSet: function(){
return _.isString(this.uses);
},
colorClass: function(){
return getColorClass(this.color)
}
});

View File

@@ -9,9 +9,9 @@
</div>
<div class="containers">
{{#each features}}
<paper-shadow class="card container featureCard" hero-id="main" {{detailHero}}>
<div class="containerTop green white-text" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName title" hero-id="title" flex {{detailHero}}>{{name}}</div>
<paper-shadow class="card container featureCard" hero-id="main" {{detailHero}} style="order: {{featureOrder}};">
<div class="containerTop {{colorClass}}" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName subhead" hero-id="title" flex {{detailHero}}>{{name}}</div>
{{#if hasUses}}<div class="subhead" style="margin-right: 8px">{{usesLeft}}/{{usesValue}}</div>{{/if}}
<paper-ripple fit></paper-ripple>
</div>

View File

@@ -1,10 +1,16 @@
Template.features.helpers({
features: function(){
var features = Features.find({charId: this._id});
var features = Features.find({charId: this._id}, {sort: {name: 1}});
return features;
},
hasUses: function(){
return this.usesValue() > 0;
},
colorClass: function(){
return getColorClass(this.color)
},
featureOrder: function(){
return _.indexOf(_.keys(colorOptions), this.color);
}
});

View File

@@ -1,7 +1,7 @@
<template name="containerDialog">
{{#with container}}
<core-header-panel fit>
<core-toolbar hero-id="toolbar" hero>
<core-toolbar hero-id="toolbar" class={{colorClass}} hero>
<paper-icon-button id="backButton" role="button" tabindex="0" icon="arrow-back" aria-label="close"></paper-icon-button>
<div flex hero-id="title" hero>{{name}}</div>
<paper-icon-button id="deleteContainer"
@@ -14,6 +14,8 @@
<div class="detailContent">
<!--Name and plural name-->
<paper-input id="containerNameInput" label="Name" floatinglabel value={{name}}></paper-input>
<!--Color-->
{{> colorDropdown}}
<!--Weight-->
<paper-input-decorator label="Weight" floatinglabel>
<input id="weightInput" type="number" value={{weight}}>

View File

@@ -43,11 +43,20 @@ Template.containerDialog.events({
"change #containerDescriptionInput": function(event){
var description = Template.instance().find("#containerDescriptionInput").value;
Containers.update(this._id, {$set: {description: description}});
},
"core-select .colorDropdown": function(event){
var detail = event.originalEvent.detail;
if(!detail.isSelected) return;
var value = detail.item.getAttribute("name");
Containers.update(this._id, {$set: {color: value}});
}
});
Template.containerDialog.helpers({
container: function(){
return Containers.findOne(this.containerId);
},
colorClass: function(){
return getColorClass(this.color)
}
});

View File

@@ -4,7 +4,7 @@
<div class="containers">
<paper-shadow class="card container">
<div class="equipmentTop" layout horizontal center>
<div class="containerName title" flex>Equipment</div>
<div class="containerName subhead" flex>Equipment</div>
<div class="caption" style="margin-right: 8px">(net Worth)</div>
<div class="caption">(weightCarried)lbs</div>
</div>
@@ -28,9 +28,9 @@
</div>
</paper-shadow>
{{#each containers}}
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
<div class="containerTop green white-text" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName title" hero-id="title" flex {{detailHero}}>{{name}}</div>
<paper-shadow class="card container" hero-id="main" {{detailHero}} style="order: {{containerOrder}};">
<div class="containerTop {{colorClass}}" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName subhead" hero-id="title" flex {{detailHero}}>{{name}}</div>
<div class="caption" style="margin-right: 8px">{{valueString totalValue}}</div>
<div class="caption">{{round totalWeight}}lbs</div>
</div>

View File

@@ -4,7 +4,7 @@ Template.inventory.created = function(){
Template.inventory.helpers({
containers: function(){
return Containers.find({charId: this._id})
return Containers.find({charId: this._id}, {sort: {name: 1}})
},
items: function(charId, containerId){
return Items.find({charId: charId, equipped: false, container: containerId })
@@ -20,6 +20,12 @@ Template.inventory.helpers({
},
ne1: function(num){
return num !== 1;
},
colorClass: function(){
return getColorClass(this.color)
},
containerOrder: function(){
return _.indexOf(_.keys(colorOptions), this.color);
}
});

View File

@@ -1,7 +1,7 @@
<template name="itemDialog">
{{#with item}}
<core-header-panel fit>
<core-toolbar hero-id="toolbar" hero>
<core-toolbar hero-id="toolbar" hero class="brown white-text">
<paper-icon-button id="backButton" role="button" tabindex="0" icon="arrow-back" aria-label="close"></paper-icon-button>
<div flex>{{name}}</div>
<paper-icon-button id="deleteItem"

View File

@@ -22,8 +22,8 @@
<template name="containerCardHelper">
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
<div class="containerTop green white-text" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName title" hero-id="title" flex {{detailHero}}>{{title}}</div>
<div class="containerTop {{colorClass}}" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName subhead" hero-id="title" flex {{detailHero}}>{{title}}</div>
</div>
<div flex class="containerMain">{{> UI.contentBlock}}</div>
</paper-shadow>

View File

@@ -1,15 +1,26 @@
var colorMap = {
description: "indigo",
personality: "blue",
ideals: "light-blue",
bonds: "cyan",
flaws: "teal",
backstory: "green"
}
Template.persona.helpers({
characterDetails: function(){
var char = Characters.findOne(this._id, {fields: {name: 1, gender: 1, alignment: 1, race:1}})
char._id += "details";
char.title = char.name;
char.color = "deep-purple";
return char;
},
characterField: function(field, title){
var fieldSelector = {fields: {}};
fieldSelector.fields[field] = 1;
var char = Characters.findOne(this._id, fieldSelector);
return {_id: char._id + field, title: title, field: field, body: char[field]};
var color = colorMap[field];
return {_id: char._id + field, title: title, field: field, color: color, body: char[field]};
}
});
@@ -19,7 +30,7 @@ Template.persona.events({
var charId = Template.parentData()._id;
GlobalUI.setDetail({
template: "textDialog",
data: {charId: charId, field: this.field, title: this.title},
data: {charId: charId, field: this.field, title: this.title, color: this.color},
heroId: this._id
});
} else{

View File

@@ -1,6 +1,6 @@
<template name="textDialog">
<core-header-panel fit>
<core-toolbar hero-id="toolbar" hero>
<core-toolbar hero-id="toolbar" hero class={{colorClass}}>
<paper-icon-button id="backButton" role="button" tabindex="0" icon="arrow-back" aria-label="close"></paper-icon-button>
<div flex hero-id="title" hero>{{title}}</div>
<paper-icon-button id="deleteContainer"

View File

@@ -2,19 +2,24 @@
<div fit>
<div id="spells" class="scroll-y" fit>
<div class="containers">
{{#each spellLevels}}
{{#each spellLists}}
<paper-shadow class="card container" hero-id="main" {{detailHero}}>
<div class="containerTop green white-text" hero-id="toolbar" layout horizontal center {{detailHero}}>
<div class="containerName title" hero-id="title" flex {{detailHero}}>{{name}}</div>
{{#if attribute}}<div class="subhead">{{../attributeValue attribute}} / {{../attributeBase attribute}}</div>{{/if}}
<div class="containerName subhead" hero-id="title" flex {{detailHero}}>{{name}}</div>
{{#if maxPrepared}}<div class="subhead">{{numPrepared}} / {{maxPrepared}}</div>{{/if}}
</div>
<div flex class="containerMain">
{{#each spellsAtLevel}}
<div class="itemSlot">
<paper-item class="inventoryItem" hero-id="main" {{detailHero}}>
{{name}}
</paper-item>
</div>
{{#each levels}}
{{#if spellCount ../_id ../../_id}}
<div class="list-subhead" layout horizontal center>{{name}}</div>
{{/if}}
{{#each spells ../_id ../../_id}}
<div class="itemSlot">
<paper-item class="inventoryItem" hero-id="main" {{detailHero}} layout horizontal center>
<!--school icon here--><div flex>{{name}}</div><!--prepared checkbox here-->
</paper-item>
</div>
{{/each}}
{{/each}}
</div>
</paper-shadow>

View File

@@ -1,21 +1,31 @@
var spellLevels = [
{ name: "Cantrips", level: 0 },
{ name: "Level 1", level: 1, attribute: "level1SpellSlots" },
{ name: "Level 2", level: 2, attribute: "level2SpellSlots" },
{ name: "Level 3", level: 3, attribute: "level3SpellSlots" },
{ name: "Level 4", level: 4, attribute: "level4SpellSlots" },
{ name: "Level 5", level: 5, attribute: "level5SpellSlots" },
{ name: "Level 6", level: 6, attribute: "level6SpellSlots" },
{ name: "Level 7", level: 7, attribute: "level7SpellSlots" },
{ name: "Level 8", level: 8, attribute: "level8SpellSlots" },
{ name: "Level 9", level: 9, attribute: "level9SpellSlots" },
{ name: "Level 1", level: 1 },
{ name: "Level 2", level: 2 },
{ name: "Level 3", level: 3 },
{ name: "Level 4", level: 4 },
{ name: "Level 5", level: 5 },
{ name: "Level 6", level: 6 },
{ name: "Level 7", level: 7 },
{ name: "Level 8", level: 8 },
{ name: "Level 9", level: 9 },
];
Template.spells.helpers({
spellLevels: function(){
return spellLevels;
spellLists: function(){
return SpellLists.find({charId: this._id});
},
spellsAtLevel: function(){
return Spells.find( {charId: Template.parentData()._id, level: this.level} )
}
spellCount: function(listId, charId){
console.log(listId, charId);
return Spells.find( {charId: charId, listId: listId, level: this.level}, {fields: {_id: 1, level: 1}} ).count() > 0;
},
spells: function(listId, charId){
return Spells.find( {charId: charId, listId: listId, level: this.level} );
},
levels: function(){
return spellLevels;
},
numPrepared: function(){
return Spells.find({charId: Template.parentData()._id, listId: this._id, prepared: "prepared"}).count();
}
})

View File

@@ -2,7 +2,7 @@
<core-drawer-panel>
<core-header-panel drawer navigation flex mode="seamed" class="white">
<core-toolbar>Application</core-toolbar>
<core-toolbar class="grey white-text">Application</core-toolbar>
<core-menu theme="core-light-theme">
<core-item icon="settings" label="item1"></core-item>
<core-item icon="settings" label="item2"></core-item>

View File

@@ -0,0 +1,9 @@
html /deep/ .colorDropdown paper-item{
width: 150px;
}
html /deep/ .colorDropdown {
top: 18px;
padding: 0.5em 0 0.25em 16px;
width: 150px;
}

View File

@@ -0,0 +1,11 @@
<template name="colorDropdown">
<paper-dropdown-menu class="colorDropdown {{colorClass color}}" label="Color">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{color}}>
{{#each colorKeys}}
<paper-item name={{this}} class="containerMenuItem {{colorClass this}}">{{this}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
</template>

View File

@@ -0,0 +1,5 @@
Template.colorDropdown.helpers({
colorKeys: function(){
return _.keys(colorOptions);
}
});

View File

@@ -0,0 +1,33 @@
colorOptions = {
"red": {whiteText: true},
"pink": {whiteText: true},
"purple": {whiteText: true},
"deep-purple": {whiteText: true},
"indigo": {whiteText: true},
"blue": {whiteText: true},
"light-blue": {whiteText: true},
"cyan": {whiteText: true},
"teal": {whiteText: true},
"green": {whiteText: true},
"light-green": {whiteText: true},
"lime": {whiteText: false},
"yellow": {whiteText: false},
"amber": {whiteText: false},
"orange": {whiteText: false},
"deep-orange": {whiteText: true},
"brown": {whiteText: true},
"grey": {whiteText: true}, //spec says no white text
"blue-grey": {whiteText: true},
"black": {whiteText: true},
};
getColorClass = function(key){
if(!key){
return "brown white-text"
}
var colorClass = key;
if(colorOptions[key].whiteText){
colorClass += " white-text";
}
return colorClass;
}

View File

@@ -7,6 +7,6 @@ Meteor.publish("singleCharacter", function(characterId, userId){
Features.find({charId: characterId}),
Effects.find({charId: characterId}),
Spells.find({charId: characterId}),
SpellLists.find({charID: characterId})
SpellLists.find({charId: characterId})
];
});