Compare commits

...

13 Commits
0.5.2 ... 0.5.5

Author SHA1 Message Date
Stefan Zermatten
89f03c7601 Merge branch 'hotfix-gmail-report' 2015-06-12 08:04:23 +02:00
Stefan Zermatten
9d2eb14c0c Change logs 2015-06-12 08:03:46 +02:00
Stefan Zermatten
7b3cb54983 Added gmail email address senders to the report emails 2015-06-12 08:02:33 +02:00
Stefan Zermatten
a09bad2fed Change logs 2015-06-10 11:13:58 +02:00
Stefan Zermatten
afd897edfe Merge branch 'Hotfix' 2015-06-10 11:05:01 +02:00
Stefan Zermatten
efc79cb6e7 Fixed net value calculation to avoid rounding errors 2015-06-10 11:00:42 +02:00
Stefan Zermatten
35efe39ea7 Made feedback reports send emails "from" their creator's address 2015-06-10 11:00:19 +02:00
Stefan Zermatten
4f1376a666 Change log 2015-06-04 09:57:49 +02:00
Stefan Zermatten
78b1d71b9d Overhauled how effects are edited 2015-05-27 13:13:51 +02:00
Stefan Zermatten
1323d8006c Made feedback not sendable without title & description 2015-05-27 09:18:34 +02:00
Stefan Zermatten
87d722adaf Now send emails to myself when feedback gets reported 2015-05-27 08:33:24 +02:00
Stefan Zermatten
90e511eb00 Added the ability to hide the spells tab for a character 2015-05-27 08:10:14 +02:00
Stefan Zermatten
5b8c25f5de Fixed a harmless error with un-set effect views 2015-05-27 08:04:39 +02:00
14 changed files with 207 additions and 117 deletions

View File

@@ -159,6 +159,7 @@ Schemas.Character = new SimpleSchema({
deathSave: {type: Schemas.DeathSave},
//permissions
party: {type: String, regEx: SimpleSchema.RegEx.Id, optional: true},
owner: {type: String, regEx: SimpleSchema.RegEx.Id},
readers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
writers: {type: [String], regEx: SimpleSchema.RegEx.Id, defaultValue: []},
@@ -173,6 +174,8 @@ Schemas.Character = new SimpleSchema({
//slowed down by carrying too much?
"settings.useVariantEncumbrance": {type: Boolean, defaultValue: false},
"settings.useStandardEncumbrance": {type: Boolean, defaultValue: true},
//hide spellcasting
"settings.hideSpellcasting": {type: Boolean, defaultValue: false},
});
Characters.attachSchema(Schemas.Character);

View File

@@ -45,7 +45,26 @@ Meteor.methods({
metaData: Object,
});
report.owner = this.userId;
Reports.insert(report);
var id = Reports.insert(report);
var user = Meteor.users.findOne(this.userId);
var sender = user &&
user.emails &&
user.emails[0] &&
user.emails[0].address ||
user.services &&
user.services.google &&
user.services.google.email ||
"reports@dicecloud.com";
var bodyText = "Report ID: " + id +
"\nSeverity: " + report.severity +
"\nType: " + report.type +
"\n\n" + report.description;
Email.send({
from: sender,
to: "stefan.zermatten@gmail.com",
subject: "DiceCloud feedback - " + report.title,
text: bodyText,
});
},
deleteReport: function(id) {
var user = Meteor.users.findOne(this.userId);

View File

@@ -1,25 +1,27 @@
Template.registerHelper("valueString", function(value) {
var intValue = Math.round(value * 100);
var cp = intValue % 10;
intValue -= cp;
cp = Math.round(cp);
sp = intValue % 100;
intValue -= sp;
sp = Math.round(sp / 10)
gp = Math.floor(value);
var resultArray = [];
//sp
var gp = Math.floor(value);
if (gp > 0) {
resultArray.push(gp + "gp");
}
//sp
var sp = Math.floor(10 * (value % 1));
if (sp > 0) {
resultArray.push(sp + "sp");
}
//cp
var cp = 10 * ((value * 10) % 1);
cp = Math.round(cp * 1000) / 1000;
if (cp > 0) {
resultArray.push(cp + "cp");
}
//build string with correct spacing
var result = "";
for (var i = 0; i < resultArray.length; i++) {
for (var i = 0, l = resultArray.length; i < l; i++) {
//add a space between values
if (i !== 0) {
result += " ";

View File

@@ -1,13 +1,26 @@
<template name="characterSettings">
{{#with character}}
<div>
<div layout horizontal>
<div>Use variant encumbrance </div>
<paper-toggle-button id="variantEncumbrance"
checked={{settings.useVariantEncumbrance}}
touch-action="pan-y">
</paper-toggle-button>
</div>
<table>
<tr>
<td>Hide Spells tab</td>
<td>
<paper-toggle-button id="hideSpellcasting"
checked={{settings.hideSpellcasting}}
touch-action="pan-y">
</paper-toggle-button>
</td>
</tr>
<tr>
<td>Use variant encumbrance</td>
<td>
<paper-toggle-button id="variantEncumbrance"
checked={{settings.useVariantEncumbrance}}
touch-action="pan-y">
</paper-toggle-button>
</td>
</tr>
</table>
</div>
{{/with}}
</template>

View File

@@ -14,4 +14,13 @@ Template.characterSettings.events({
);
}
},
"change #hideSpellcasting": function(event, instance){
var value = instance.find("#hideSpellcasting").checked;
if (this.settings.hideSpellcasting !== value){
Characters.update(
this._id,
{$set: {"settings.hideSpellcasting": value}}
);
}
},
});

View File

@@ -31,7 +31,9 @@
<paper-tab name="stats">Stats</paper-tab>
<paper-tab name="features">Features</paper-tab>
<paper-tab name="inventory">Inventory</paper-tab>
{{#unless hideSpellcasting}}
<paper-tab name="spells">Spells</paper-tab>
{{/unless}}
<paper-tab name="persona">Persona</paper-tab>
<paper-tab name="journal">Journal</paper-tab>
</paper-tabs>
@@ -42,7 +44,9 @@
<section flex name="stats">{{> stats}}</section>
<section flex name="features">{{> features}}</section>
<section flex name="inventory">{{> inventory}}</section>
{{#unless hideSpellcasting}}
<section flex name="spells">{{> spells}}</section>
{{/unless}}
<section flex name="persona">{{> persona}}</section>
<section flex name="journal">{{> journal}}</section>
</core-animated-pages>

View File

@@ -17,6 +17,10 @@ Template.characterSheet.helpers({
selectedTab: function(){
return getTab(this._id);
},
hideSpellcasting: function() {
var char = Characters.findOne(this._id);
return char && char.settings.hideSpellcasting;
}
});
Template.characterSheet.events({

View File

@@ -1,21 +1,13 @@
body /deep/ #statGroupDropDown {
width: 120px;
html /deep/ .operationDropDown {
width: 152px;
}
body /deep/ #statDropDown {
width: 120px;
html /deep/ .statDropDown {
width: 152px;
}
body /deep/ #operationDropDown {
width: 100px;
}
body /deep/ #damageMultiplierDropDown {
width: 120px;
}
body /deep/ #proficiencyDropDown {
width: 120px;
html /deep/ .damageMultiplierDropDown {
width: 152px;
}
html /deep/ .effectEdit paper-input {
@@ -24,6 +16,7 @@ html /deep/ .effectEdit paper-input {
}
html /deep/ .effectEdit {
height: 64px;
display: flex;
align-items: flex-end;
}

View File

@@ -1,27 +1,23 @@
<template name="effectEdit">
<div class="effectEdit" layout horizontal center>
<paper-dropdown-menu class="statGroupDropDown" label="Stat Group" flex>
<paper-dropdown layered class="dropdown">
<core-menu class="menu statGroupMenu" selected={{selectedStatGroup}}>
{{#each statGroups}}
<paper-item class="statGroupSelect" name={{this}}>{{this}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
{{#if stats}}
<paper-dropdown-menu class="statDropDown" label="Stat" flex>
<paper-dropdown layered class="dropdown">
<core-menu class="menu statMenu" selected={{stat}} on-tap="onStatMenuTap">
{{#each stats}}
<paper-item name={{stat}}>{{name}}</paper-item>
<paper-dropdown-menu class="statDropDown"
label="Stat">
<paper-dropdown layered
class="dropdown">
<core-menu class="menu statMenu" selected={{stat}}>
{{#each statGroups}}
<div style="font-weight: bold;
margin-top: 16px;">{{this}}</div>
{{#each stats}}
<paper-item name={{stat}}>{{name}}</paper-item>
{{/each}}
{{/each}}
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
{{/if}}
</paper-dropdown>
</paper-dropdown-menu>
{{#if operations}}
<paper-dropdown-menu class="operationDropDown" label="Operation" flex>
<paper-dropdown-menu class="operationDropDown"
label="Operation">
<paper-dropdown layered class="dropdown">
<core-menu class="menu operationMenu" selected={{operation}}>
{{#each operations}}
@@ -31,24 +27,39 @@
</paper-dropdown>
</paper-dropdown-menu>
{{/if}}
{{> Template.dynamic template=effectValueTemplate}}
<paper-icon-button class="deleteEffect" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
{{#if effectValueTemplate}}
{{> Template.dynamic template=effectValueTemplate}}
{{else}}
<div flex></div>
{{/if}}
<paper-icon-button class="deleteEffect"
icon="delete">
</paper-icon-button>
<br>
</div>
</template>
<template name="regularEffectValue">
<paper-input class="effectValueInput" label="Value" floatinglabel value={{effectValue}} flex></paper-input>
<paper-input class="effectValueInput"
label="Value"
floatinglabel
value={{effectValue}}
flex>
</paper-input>
</template>
<template name="multiplierEffectValue">
<paper-dropdown-menu class="damageMultiplierDropDown" label="Damage Multiplier" flex>
<paper-dropdown layered class="dropdown">
<core-menu class="menu multiplierMenu" selected={{value}}>
<paper-dropdown-menu class="damageMultiplierDropDown"
label="Damage Multiplier">
<paper-dropdown layered
class="dropdown">
<core-menu class="menu multiplierMenu"
selected={{value}}>
<paper-item name="0.5">Resistance</paper-item>
<paper-item name="2">Vulnerability</paper-item>
<paper-item name="0">Immunity</paper-item>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
<div flex></div>
</template>

View File

@@ -93,24 +93,17 @@ var skillOperations = [
{name: "Conditional Benefit", operation: "conditional"}
];
Template.effectEdit.created = function(){
var statGroup = statsDict[this.data.stat] && statsDict[this.data.stat].group;
this.selectedStatGroup = new ReactiveVar(statGroup);
};
Template.effectEdit.helpers({
selectedStatGroup: function(){
return Template.instance().selectedStatGroup.get();
},
statGroups: function(){
return statGroupNames;
},
stats: function(){
var group = Template.instance().selectedStatGroup.get();
var group = this;
return statGroups[group];
},
operations: function(){
var group = Template.instance().selectedStatGroup.get();
var stat = statsDict[this.stat];
var group = stat && stat.group;
if (group === "Weakness/Resistance") return null;
if (group === "Saving Throws" || group === "Skills"){
return skillOperations;
@@ -120,7 +113,8 @@ Template.effectEdit.helpers({
},
effectValueTemplate: function(){
//resistance/vulnerability template
var group = Template.instance().selectedStatGroup.get();
var stat = statsDict[this.stat];
var group = stat && stat.group;
if (group === "Weakness/Resistance") return "multiplierEffectValue";
var op = this.operation;
@@ -144,25 +138,6 @@ Template.effectEdit.events({
Effects.softRemoveNode(this._id);
GlobalUI.deletedToast(this._id, "Effects", "Effect");
},
"core-select .statGroupDropDown": function(event, instance){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var groupName = detail.item.getAttribute("name");
var oldName = Template.instance().selectedStatGroup.get();
if (oldName != groupName){
instance.selectedStatGroup.set(groupName);
if (groupName === "Weakness/Resistance"){
Effects.update(this._id, {$set: {
value: 0.5,
calculation: "",
operation: "mul"}, $unset: {stat: ""}});
} else {
Effects.update(this._id,
{$set: {operation: "add"},
$unset: {stat: "", value: "", calculation: ""}});
}
}
},
"core-select .statDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;

View File

@@ -57,40 +57,40 @@ var stats = {
"d12HitDice":{"name":"d12 Hit Dice"},
"acidMultiplier":{"name":"Acid damage", "group": "Weakness/Resistance"},
"bludgeoningMultiplier":{
"name":"Bludgeoning damage", "group": "Weakness/Resistance"
"name":"Bludgeoning damage", "group": "Weakness/Resistance",
},
"coldMultiplier":{
"name":"Cold damage", "group": "Weakness/Resistance"
"name":"Cold damage", "group": "Weakness/Resistance",
},
"fireMultiplier":{
"name":"Fire damage", "group": "Weakness/Resistance"
"name":"Fire damage", "group": "Weakness/Resistance",
},
"forceMultiplier":{
"name":"Force damage", "group": "Weakness/Resistance"
"name":"Force damage", "group": "Weakness/Resistance",
},
"lightningMultiplier":{
"name":"Lightning damage", "group": "Weakness/Resistance"
"name":"Lightning damage", "group": "Weakness/Resistance",
},
"necroticMultiplier":{
"name":"Necrotic damage", "group": "Weakness/Resistance"
"name":"Necrotic damage", "group": "Weakness/Resistance",
},
"piercingMultiplier":{
"name":"Piercing damage", "group": "Weakness/Resistance"
"name":"Piercing damage", "group": "Weakness/Resistance",
},
"poisonMultiplier":{
"name":"Poison damage", "group": "Weakness/Resistance"
"name":"Poison damage", "group": "Weakness/Resistance",
},
"psychicMultiplier":{
"name":"Psychic damage", "group": "Weakness/Resistance"
"name":"Psychic damage", "group": "Weakness/Resistance",
},
"radiantMultiplier":{
"name":"Radiant damage", "group": "Weakness/Resistance"
"name":"Radiant damage", "group": "Weakness/Resistance",
},
"slashingMultiplier":{
"name":"Slashing damage", "group": "Weakness/Resistance"
"name":"Slashing damage", "group": "Weakness/Resistance",
},
"thunderMultiplier":{
"name":"Thunder damage", "group": "Weakness/Resistance"
"name":"Thunder damage", "group": "Weakness/Resistance",
},
};
@@ -110,8 +110,8 @@ var operations = {
Template.effectView.helpers({
sourceName: function(){
var id = this.parent.id;
if(!id) return;
switch(this.parent.collection){
if (!id) return;
switch (this.parent.collection){
case "Features":
return "Feature - " + Features.findOne(id, {fields: {name: 1}}).name;
case "Classes":
@@ -130,33 +130,39 @@ Template.effectView.helpers({
return stats[this.stat] && stats[this.stat].name || "No Stat";
},
operationName: function(){
if(this.operation === "proficiency" ||
if (this.operation === "proficiency" ||
this.operation === "conditional") return null;
if(stats[this.stat].group === "Weakness/Resistance") return null;
if(this.operation === "add" && evaluateEffect(this.charId, this) < 0) return null;
return operations[this.operation] && operations[this.operation].name || "No Operation";
if (stats[this.stat] && stats[this.stat].group === "Weakness/Resistance")
return null;
if (this.operation === "add" && evaluateEffect(this.charId, this) < 0)
return null;
return operations[this.operation] &&
operations[this.operation].name || "No Operation";
},
statValue: function(){
if(this.operation === "advantage" ||
if (this.operation === "advantage" ||
this.operation === "disadvantage" ||
this.operation === "fail"){
return null;
}
if(this.operation === "proficiency"){
if(this.value == 0.5 || this.calculation == 0.5) return "Half Proficiency";
if(this.value == 1 || this.calculation == 1) return "Proficiency";
if(this.value == 2 || this.calculation == 2) return "Double Proficiency";
if (this.operation === "proficiency"){
if (this.value == 0.5 || this.calculation == 0.5)
return "Half Proficiency";
if (this.value == 1 || this.calculation == 1)
return "Proficiency";
if (this.value == 2 || this.calculation == 2)
return "Double Proficiency";
}
if(this.operation === "conditional"){
if (this.operation === "conditional"){
return this.calculation || this.value;
}
if(stats[this.stat].group === "Weakness/Resistance"){
if(this.value === 0.5) return "Resistance";
if(this.value === 2) return "Vulnerability";
if(this.value === 0) return "Immunity";
if (stats[this.stat] && stats[this.stat].group === "Weakness/Resistance"){
if (this.value === 0.5) return "Resistance";
if (this.value === 2) return "Vulnerability";
if (this.value === 0) return "Immunity";
}
var value = evaluateEffect(this.charId, this);
if(_.isNumber(value)) return value;
if (_.isNumber(value)) return value;
return this.calculation || this.value;
}
},
});

View File

@@ -25,6 +25,13 @@
</paper-autogrow-textarea>
</paper-input-decorator>
</div>
<paper-button id="cancelButton" affirmative>Cancel</paper-button>
<paper-button id="sendButton" affirmative>Send </paper-button>
<paper-button id="cancelButton"
affirmative>
Cancel
</paper-button>
<paper-button id="sendButton"
affirmative
disabled={{invalid}}>
Send
</paper-button>
</template>

View File

@@ -1,4 +1,23 @@
Template.feedback.onCreated(function() {
this.title = new ReactiveVar("");
this.description = new ReactiveVar("");
});
Template.feedback.helpers({
invalid: function() {
var inst = Template.instance();
return !inst.title.get() ||
!inst.description.get();
}
});
Template.feedback.events({
"input #feedbackTitle": function(event, instance) {
instance.title.set(instance.find("#feedbackTitle").value);
},
"input #feedbackDescription": function(event, instance) {
instance.description.set(instance.find("#feedbackDescription").value);
},
"tap #sendButton": function(event, instance) {
var report = {};
report.title = instance.find("#feedbackTitle").value;

View File

@@ -133,3 +133,28 @@ ChangeLogs.insert({
"Added performance monitoring",
],
});
ChangeLogs.insert({
version: "0.5.3",
changes: [
"Prevented a harmless error caused by effects which have no stat set",
"Added the ability to hide the spells tab",
"Feedback forms now give me push notifications",
"Feedback forms now won't send unless properly filled out",
"Overhauled how effects' stats are chosen",
],
});
ChangeLogs.insert({
version: "0.5.4",
changes: [
"Fixed rounding error on net worth calculation",
],
});
ChangeLogs.insert({
version: "0.5.5",
changes: [
"Fixed reports from google users not correctly storing the reply-to email address",
],
});