Compare commits

..

49 Commits
0.9.3 ... 1.0.1

Author SHA1 Message Date
Stefan Zermatten
2540278787 Bumped version 2017-03-09 08:40:21 +02:00
Stefan Zermatten
5ed1977082 Fixed dragging items to characters in the drawer 2017-03-09 08:40:15 +02:00
Stefan Zermatten
a750101765 Fixed app drawer appearing behind content 2017-03-09 08:39:59 +02:00
Stefan Zermatten
aa08a9b57a Fixed links not closing drawer automatically 2017-03-09 08:39:39 +02:00
Stefan Zermatten
a8960e26ec Fixed issue with health bars clamping to 100 2017-03-06 14:50:46 +02:00
Stefan Zermatten
eefb3895ad Bumped version to 1.0.0 2017-03-06 11:37:15 +02:00
Stefan Zermatten
5b1caa7e95 Merge pull request #57 from ThaumRystra/update-meteor-1.4-polymer-1.0
Update to polymer 1.0, Meteor 1.4
2017-03-06 10:36:03 +02:00
Stefan Zermatten
21fdad1054 Added resolution for webcomponentsjs 2017-02-21 09:37:32 +02:00
Stefan Zermatten
c482395426 Fixed FABs not reappearing after dialog close 2017-02-13 09:22:17 +02:00
Stefan Zermatten
cb493a9f16 Firefox now works... mostly 2017-02-13 09:21:55 +02:00
Stefan Zermatten
576c1f953b Firefox now works... barely 2017-02-10 14:01:06 +02:00
Stefan Zermatten
eb4336b3e9 Moved back to differential:vulcanize for imports 2017-01-31 15:26:05 +02:00
Stefan Zermatten
03cb32bf34 Updated color dropdown to Polymer 1 paper-swatch-picker 2017-01-31 13:36:15 +02:00
Stefan Zermatten
a869772238 Updated journal page to Polymer 1 2017-01-31 11:09:57 +02:00
Stefan Zermatten
9c61493a12 Updated persona tab to Polymer 1 2017-01-31 09:58:35 +02:00
Stefan Zermatten
7af3b8e06e Upgraded spells page to Polymer 1 2017-01-30 13:02:22 +02:00
Stefan Zermatten
fd21f4f7d7 Fixed some dialog animation edge cases 2017-01-27 15:34:59 +02:00
Stefan Zermatten
3530eefb2a Added custom tab pages animations 2017-01-27 15:34:09 +02:00
Stefan Zermatten
d710579025 Updated inventory to Polymer 1 2017-01-26 10:23:27 +02:00
Stefan Zermatten
f7a3929c05 Fixed toast 2017-01-25 08:40:30 +02:00
Stefan Zermatten
1af15eff3c Small style and event fixes 2017-01-23 15:08:19 +02:00
Stefan Zermatten
33ca60c2e6 Migrated the Feature page to Polymer 1 2017-01-20 15:45:18 +02:00
Stefan Zermatten
4261776d8c Removed SCSS, using CSS only now
SCSS wasn't being utilized enough to add much value to the build times
2017-01-20 09:06:24 +02:00
Stefan Zermatten
b44fe33b30 Finished upgrading stat tab to Polymer 1 2017-01-20 09:05:16 +02:00
Stefan Zermatten
c4a488a176 Updated useraccounts, character settings to Polymer 1 2017-01-19 15:43:48 +02:00
Stefan Zermatten
137a94f251 Began moving character sheet and related menus to Polymer 1 2017-01-18 15:04:09 +02:00
Stefan Zermatten
817020bea8 Updated hitpoint / temporary hitpoint box to Polymer 1 2017-01-18 11:19:03 +02:00
Stefan Zermatten
420de9b005 Migrated stats tab to Polymer 1.0 2017-01-17 15:01:11 +02:00
Stefan Zermatten
b8fdc27df9 Rebuilt dialog animations with cross-fade effect 2017-01-17 15:00:05 +02:00
Stefan Zermatten
bdc64dfb10 Updated the new character dialog to Polymer 1 2017-01-16 15:34:23 +02:00
Stefan Zermatten
d4bec4f5e7 Cleaned up dialogStack 2017-01-16 15:34:03 +02:00
Stefan Zermatten
041186059c Updated static pages to Polymer 1 2017-01-16 13:48:43 +02:00
Stefan Zermatten
01535a414c Updated character lists to Polymer 1 2017-01-16 13:48:18 +02:00
Stefan Zermatten
d9e180bac0 Simplified toast to just take text 2017-01-13 15:35:08 +02:00
Stefan Zermatten
235089e790 Fixed typos of the app name 2017-01-13 15:34:51 +02:00
Stefan Zermatten
c560d80c26 Updated front page to Polymer 1 2017-01-13 15:34:28 +02:00
Stefan Zermatten
a67b13f659 Updated feedback form to Polymer 1 2017-01-13 13:21:42 +02:00
Stefan Zermatten
c416adc85b Improved the dialog stack animations 2017-01-13 13:21:05 +02:00
Stefan Zermatten
dbbb3739d0 Added a new animated dialog stack
This is to replace the animated-pages hack with Blaze component built for purpose
2017-01-12 15:30:06 +02:00
Stefan Zermatten
38ea89995a Moved views out of private folder 2017-01-12 15:28:59 +02:00
Stefan Zermatten
37268495ae Got some Polymer 1.0 elements working with 1.4
Character sheets now visible, but vulcanize broke, using raw head imports instead
2016-12-22 11:15:30 +02:00
Stefan Zermatten
042b67dd77 Fixed merge conflict 2016-12-20 13:58:32 +02:00
Stefan Zermatten
07cb3859db Merge branch 'update-meteor-1.4' into update-meteor-1.4-polymer-1.0 2016-12-20 13:57:56 +02:00
Stefan Zermatten
b1fdaa726c Removed useless Kadira 2016-12-08 13:52:04 +02:00
Stefan Zermatten
a333b0bdc8 Fixed broken drawer swiping 2016-12-08 13:51:54 +02:00
Stefan Zermatten
c32680a15a Upgraded meteor 2016-12-08 13:51:35 +02:00
Stefan Zermatten
d1950b4598 Bumped changelog for webcomponentsjs update 2016-12-08 09:55:07 +02:00
Greg Williams
af20eb4f3c Updated webcomponentsjs to v0.7.23 2016-11-23 22:03:09 -08:00
Stefan Zermatten
7af2e80ec1 Removed Polymer 0.5, started implementing Polymer 1.0 2016-10-03 13:00:27 +02:00
244 changed files with 5452 additions and 5906 deletions

View File

@@ -13,7 +13,7 @@
"disallowMixedSpacesAndTabs": "smart",
"disallowTrailingWhitespace": true,
"disallowSpaceAfterPrefixUnaryOperators": true,
"disallowMultipleVarDecl": true,
"disallowMultipleVarDecl": false,
"disallowNewlineBeforeBlockStatements": true,
"disallowKeywordsOnNewLine": ["else"],
@@ -53,4 +53,4 @@
"disallowMultipleLineBreaks": true,
"disallowNewlineBeforeBlockStatements": true
}
}

1
rpg-docs/.gitignore vendored
View File

@@ -3,6 +3,7 @@
.demeteorized
settings.json
public/components
public/_imports.html
nohup.out
node_modules
dump

View File

@@ -11,3 +11,5 @@ notices-for-facebook-graph-api-2
1.2.0-cordova-changes
1.2.0-breaking-changes
1.3.0-split-minifiers-package
1.4.0-remove-old-dev-bundle-link
1.4.1-add-shell-server-package

View File

@@ -3,14 +3,13 @@
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
thaum:vulcanize@0.0.5
iron:router
accounts-password
accounts-ui
random
accounts-password@1.3.3
accounts-ui@1.1.9
random@1.0.10
dburles:collection-helpers
reactive-var
underscore
reactive-var@1.0.11
underscore@1.0.10
aldeed:collection2
matb33:collection-hooks
zimme:collection-softremovable
@@ -19,29 +18,31 @@ dburles:mongo-collection-instances
percolate:migrations
ecwyne:mathjs
useraccounts:polymer
accounts-google
accounts-google@1.0.11
splendido:accounts-meld
email
email@1.1.18
meteorhacks:subs-manager
meteorhacks:kadira
chuangbo:marked
reywood:iron-router-ga
meteor-base
mobile-experience
mongo
meteor-base@1.0.4
mobile-experience@1.0.4
mongo@1.1.14
blaze-html-templates
session
jquery
tracker
logging
reload
ejson
session@1.1.7
jquery@1.11.10
tracker@1.1.1
logging@1.1.16
reload@1.1.11
ejson@1.0.13
spacebars
check
check@1.2.4
useraccounts:iron-routing
wizonesolutions:canonical
meteorhacks:fast-render
fourseven:scss
wolves:bourbon
standard-minifier-css
standard-minifier-js
standard-minifier-js@1.2.1
shell-server@0.2.1
seba:minifiers-autoprefixer
nikogosovd:multiple-uihooks
templates:array
ecmascript@0.6.1
es5-shim@4.6.15
differential:vulcanize

View File

@@ -1 +1 @@
METEOR@1.3.2.4
METEOR@1.4.2.6

View File

@@ -1,131 +1,128 @@
accounts-base@1.2.7
accounts-google@1.0.9
accounts-oauth@1.1.12
accounts-password@1.1.8
accounts-base@1.2.14
accounts-google@1.0.11
accounts-oauth@1.1.15
accounts-password@1.3.3
accounts-ui@1.1.9
accounts-ui-unstyled@1.1.12
aldeed:collection2@2.9.1
aldeed:collection2-core@1.1.1
aldeed:schema-deny@1.0.1
aldeed:schema-index@1.0.1
accounts-ui-unstyled@1.1.13
aldeed:collection2@2.10.0
aldeed:collection2-core@1.2.0
aldeed:schema-deny@1.1.0
aldeed:schema-index@1.1.1
aldeed:simple-schema@1.5.3
allow-deny@1.0.4
autoupdate@1.2.9
babel-compiler@6.6.4
babel-runtime@0.1.8
base64@1.0.8
binary-heap@1.0.8
blaze@2.1.7
blaze-html-templates@1.0.4
blaze-tools@1.0.8
boilerplate-generator@1.0.8
caching-compiler@1.0.4
caching-html-compiler@1.0.6
callback-hook@1.0.8
check@1.2.1
chuangbo:cookie@1.1.0
allow-deny@1.0.5
autoupdate@1.3.12
babel-compiler@6.13.0
babel-runtime@1.0.1
base64@1.0.10
binary-heap@1.0.10
blaze@2.3.0
blaze-html-templates@1.1.0
blaze-tools@1.0.10
boilerplate-generator@1.0.11
caching-compiler@1.1.9
caching-html-compiler@1.1.0
callback-hook@1.0.10
check@1.2.4
chuangbo:marked@0.3.5_1
coffeescript@1.0.17
dburles:collection-helpers@1.0.4
coffeescript@1.11.1_4
dburles:collection-helpers@1.1.0
dburles:mongo-collection-instances@0.3.5
ddp@1.2.5
ddp-client@1.2.7
ddp-common@1.2.5
ddp-rate-limiter@1.0.4
ddp-server@1.2.6
ddp-client@1.3.2
ddp-common@1.2.8
ddp-rate-limiter@1.0.6
ddp-server@1.3.12
deps@1.0.12
diff-sequence@1.0.5
ecmascript@0.4.3
ecmascript-runtime@0.2.10
diff-sequence@1.0.7
differential:vulcanize@3.0.0
ecmascript@0.6.1
ecmascript-runtime@0.3.15
ecwyne:mathjs@0.25.0
ejson@1.0.11
email@1.0.12
fastclick@1.0.11
fourseven:scss@3.4.3
geojson-utils@1.0.8
google@1.1.11
ejson@1.0.13
email@1.1.18
es5-shim@4.6.15
fastclick@1.0.13
geojson-utils@1.0.10
google@1.1.15
hot-code-push@1.0.4
html-tools@1.0.9
htmljs@1.0.9
http@1.1.5
id-map@1.0.7
html-tools@1.0.11
htmljs@1.0.11
http@1.2.10
id-map@1.0.9
iron:controller@1.0.12
iron:core@1.0.11
iron:dynamic-template@1.0.12
iron:layout@1.0.12
iron:location@1.0.11
iron:middleware-stack@1.1.0
iron:router@1.0.12
iron:router@1.1.1
iron:url@1.0.11
jquery@1.11.8
jquery@1.11.10
lai:collection-extensions@0.2.1_1
launch-screen@1.0.11
less@2.6.0
launch-screen@1.1.0
less@2.7.9
livedata@1.0.18
localstorage@1.0.9
logging@1.0.12
matb33:collection-hooks@0.8.1
mdg:validation-error@0.2.0
meteor@1.1.14
localstorage@1.0.12
logging@1.1.16
matb33:collection-hooks@0.8.4
mdg:validation-error@0.5.1
meteor@1.6.0
meteor-base@1.0.4
meteorhacks:fast-render@2.14.0
meteorhacks:inject-data@2.0.0
meteorhacks:kadira@2.28.7
meteorhacks:meteorx@1.4.1
meteorhacks:picker@1.0.3
meteorhacks:subs-manager@1.6.4
minifier-css@1.1.11
minifier-js@1.1.11
minimongo@1.0.16
minifier-css@1.2.16
minifier-js@1.2.17
minimongo@1.0.19
mobile-experience@1.0.4
mobile-status-bar@1.0.12
modules@0.6.1
modules-runtime@0.6.3
momentjs:moment@2.13.1
mongo@1.1.7
mongo-id@1.0.4
mongo-livedata@1.0.12
npm-bcrypt@0.8.5
npm-mongo@1.4.43
oauth@1.1.10
oauth2@1.1.9
observe-sequence@1.0.11
ordered-dict@1.0.7
mobile-status-bar@1.0.13
modules@0.7.7
modules-runtime@0.7.8
momentjs:moment@2.17.1
mongo@1.1.14
mongo-id@1.0.6
nikogosovd:multiple-uihooks@0.1.8
npm-bcrypt@0.9.2
npm-mongo@2.2.16_1
oauth@1.1.12
oauth2@1.1.11
observe-sequence@1.0.14
ordered-dict@1.0.9
percolate:migrations@0.9.8
promise@0.6.7
promise@0.8.8
raix:eventemitter@0.1.3
random@1.0.9
rate-limit@1.0.4
reactive-dict@1.1.7
reactive-var@1.0.9
reload@1.1.8
retry@1.0.7
random@1.0.10
rate-limit@1.0.6
reactive-dict@1.1.8
reactive-var@1.0.11
reload@1.1.11
retry@1.0.9
reywood:iron-router-ga@0.7.1
routepolicy@1.0.10
service-configuration@1.0.9
session@1.1.5
sha@1.0.7
softwarerero:accounts-t9n@1.3.4
spacebars@1.0.11
spacebars-compiler@1.0.11
routepolicy@1.0.12
seba:minifiers-autoprefixer@1.0.1
service-configuration@1.0.11
session@1.1.7
sha@1.0.9
shell-server@0.2.1
softwarerero:accounts-t9n@1.3.7
spacebars@1.0.13
spacebars-compiler@1.1.0
splendido:accounts-emails-field@1.2.0
splendido:accounts-meld@1.3.1
srp@1.0.8
standard-minifier-css@1.0.6
standard-minifier-js@1.0.6
templating@1.1.9
templating-tools@1.0.4
thaum:vulcanize@0.0.5
tracker@1.0.13
ui@1.0.11
underscore@1.0.8
url@1.0.9
srp@1.0.10
standard-minifier-js@1.2.2
templates:array@1.0.3
templating@1.3.0
templating-compiler@1.3.0
templating-runtime@1.3.0
templating-tools@1.1.0
tracker@1.1.1
ui@1.0.12
underscore@1.0.10
url@1.0.11
useraccounts:core@1.14.2
useraccounts:iron-routing@1.14.2
useraccounts:polymer@1.12.3
webapp@1.2.8
useraccounts:polymer@1.14.2
webapp@1.3.12
webapp-hashing@1.0.9
wizonesolutions:canonical@0.0.5
wolves:bourbon@3.1.0
zimme:collection-behaviours@1.1.3
zimme:collection-softremovable@1.0.5

View File

@@ -443,13 +443,13 @@ Characters.calculate = {
}),
};
var depreciated = function() {
//var err = new Error("this function has been depreciated");
var deprecated = function() {
//var err = new Error("this function has been deprecated");
var name = "";
if (Template.instance()){
name = Template.instance().view.name;
}
var logString = "this function has been depreciated \n";
var logString = "this function has been deprecated \n";
if (name){
logString += "View: " + name + "\n\n";
}
@@ -464,56 +464,56 @@ Characters.helpers({
//returns the value stored in the field requested
//will set up dependencies on just that field
getField : function(fieldName){
depreciated();
deprecated();
return Characters.calculate.getField(this._id, fieldName);
},
//returns the value of a field
fieldValue : function(fieldName){
depreciated();
deprecated();
return Characters.calculate.fieldValue(this._id, fieldName);
},
attributeValue: function(attributeName){
depreciated();
deprecated();
return Characters.calculate.attributeValue(this._id, attributeName);
},
attributeBase: function(attributeName){
depreciated();
deprecated();
return Characters.calculate.attributeBase(this._id, attributeName);
},
skillMod: function(skillName){
depreciated();
deprecated();
return Characters.calculate.skillMod(this._id, skillName);
},
proficiency: function(skillName){
depreciated();
deprecated();
return Characters.calculate.proficiency(this._id, skillName);
},
passiveSkill: function(skillName){
depreciated();
deprecated();
return Characters.calculate.passiveSkill(this._id, skillName);
},
advantage: function(skillName){
depreciated();
deprecated();
return Characters.calculate.advantage(this._id, skillName);
},
abilityMod: function(attribute){
depreciated();
deprecated();
return Characters.calculate.abilityMod(this._id, attribute);
},
passiveAbility: function(attribute){
depreciated();
deprecated();
return Characters.calculate.passiveAbility(this._id, attribute);
},
xpLevel: function(){
depreciated();
deprecated();
return Characters.calculate.xpLevel(this._id);
},
level: function(){
depreciated();
deprecated();
return Characters.calculate.level(this._id);
},
experience: function(){
depreciated();
deprecated();
return Characters.calculate.experience(this._id);
},
});

View File

@@ -17,8 +17,8 @@ Schemas.Report = new SimpleSchema({
},
type: {
type: String,
allowedValues: ["bug", "change", "feature", "general"],
defaultValue: "bug",
allowedValues: ["General Feedback", "Bug", "Suggested Change", "Feature Request"],
defaultValue: "General Feedback",
},
//the immediate impact of doing this action (eg. -1 rages)
severity: {

View File

@@ -26,13 +26,8 @@ Router.map(function() {
waitOn: function(){
return subsManager.subscribe("characterList", Meteor.userId());
},
data: {
characters: function(){
return Characters.find({}, {fields: {_id: 1}, sort: {name: 1}});
}
},
onAfterAction: function() {
document.title = appName;
document.title = appName + " - Characters";
},
fastRender: true,
});

View File

@@ -15,12 +15,16 @@
"tests"
],
"dependencies": {
"polymer": "Polymer/polymer#~0.5.5",
"core-elements": "Polymer/core-elements#~0.5.5",
"paper-elements": "Polymer/paper-elements#~0.5.5",
"paper-fab-menu": "cwdoh/paper-fab-menu#~0.4.0"
"polymer": "Polymer/polymer#^1.0.0",
"iron-elements": "PolymerElements/iron-elements#^1.0.0",
"platinum-elements": "PolymerElements/platinum-elements#^1.0.1",
"neon-elements": "PolymerElements/neon-elements#^1.0.0",
"paper-elements": "PolymerElements/paper-elements#^1.0.7",
"app-elements": "PolymerElements/app-elements#^0.10.1",
"marked-element": "PolymerElements/marked-element#^1.2.0",
"paper-swatch-picker": "PolymerElements/paper-swatch-picker#~1.0.2"
},
"resolutions": {
"webcomponentsjs": "0.6.3"
"webcomponentsjs": "0.7.24"
}
}

View File

@@ -1,14 +1,17 @@
this.GlobalUI = (function() {
function GlobalUI() {}
GlobalUI.dialog = {};
var toast;
GlobalUI.toast = function(opts) {
var toast;
toast = $("[global-toast]")[0];
toast.text = opts.text;
Session.set("global.ui.toastTemplate", opts.template);
Session.set("global.ui.toastData", opts.data);
if (!toast) toast = $("#global-toast")[0];
if (_.isObject(opts)){
toast.text = opts.text;
Session.set("global.ui.toastTemplate", opts.template);
Session.set("global.ui.toastData", opts.data);
} else {
toast.text = opts;
Session.set("global.ui.toastTemplate");
Session.set("global.ui.toastData");
}
return toast.show();
};
@@ -18,147 +21,18 @@ this.GlobalUI = (function() {
template: "undoToast",
data: {
id: id,
collection: collection
}
collection: collection,
},
});
};
GlobalUI.setDialog = function(opts) {
this.dialog = $("[global-dialog]")[0];
Session.set("global.ui.dialogHeader", opts.heading);
Session.set("global.ui.dialogData", opts.data);
Session.set("global.ui.dialogTemplate", opts.template);
Session.set("global.ui.dialogFullOnMobile", opts.fullOnMobile !== null);
};
GlobalUI.showDialog = function(opts) {
this.dialog = $("[global-dialog]")[0];
Session.set("global.ui.dialogHeader", opts.heading);
Session.set("global.ui.dialogData", opts.data);
Session.set("global.ui.dialogTemplate", opts.template);
Session.set("global.ui.dialogFullOnMobile", opts.fullOnMobile !== null);
return Tracker.afterFlush((function(_this) {
return function() {
return _this.dialog.open();
};
})(this));
};
GlobalUI.closeDialog = function() {
return this.dialog.close();
};
//To show a detail, first animate the click, with raising z-depth
//then call this function with a template and data
//the element should have a hero-id of detail-main
GlobalUI.showDetail = function(opts) {
Session.set("global.ui.detailData", opts.data);
Session.set("global.ui.detailTemplate", opts.template);
Session.set("global.ui.detailHeroId", opts.heroId);
Session.set("global.ui.detailShow", true);
};
//if setting the detail rather than showing it,
//the template should contain the following in template.rendered
//
//if (!this.alreadyRendered){
// Session.set("global.ui.detailShow", true);
// this.alreadyRendered = true;
//}
GlobalUI.setDetail = function(opts) {
Session.set("global.ui.detailData", opts.data);
Session.set("global.ui.detailTemplate", opts.template);
Session.set("global.ui.detailHeroId", opts.heroId);
if (window.history && window.history.pushState) {
history.replaceState({detail: "closed", opts: opts}, "Detail Dialog");
history.pushState({detail: "opened", opts: opts}, "Detail Dialog");
}
};
var throttleBack = _.throttle(function() {
history.back();
}, 100, {trailing: false});
GlobalUI.closeDetail = function() {
if (window.history && history.pushState && history.state.detail === "opened") {
throttleBack();
} else {
Session.set("global.ui.detailShow", false);
}
};
GlobalUI.popStateHandler = function(e) {
var state = e.originalEvent.state;
if (state) {
if (state.detail === "closed") {
Session.set("global.ui.detailShow", false);
} else if (state.detail === "opened") {
var opts = state.opts;
Session.set("global.ui.detailData", opts.data);
Session.set("global.ui.detailTemplate", opts.template);
Session.set("global.ui.detailHeroId", opts.heroId);
}
}
};
return GlobalUI;
})();
Template.layout.helpers({
globalDialogTemplate: function() {
return Session.get("global.ui.dialogTemplate");
},
globalDialogData: function() {
return Session.get("global.ui.dialogData");
},
globalDialogFullOnMobile: function() {
return Session.get("global.ui.dialogFullOnMobile");
},
globalDialogHeader: function() {
return Session.get("global.ui.dialogHeader");
},
globalDetailSelected: function() {
return Session.get("global.ui.detailShow") ? 1 : 0;
},
globalDetailTemplate: function() {
return Session.get("global.ui.detailTemplate");
},
globalDetailData: function() {
return Session.get("global.ui.detailData");
},
globalToastTemplate: function() {
return Session.get("global.ui.toastTemplate");
},
globalToastData: function() {
return Session.get("global.ui.toastData");
}
});
Template.layout.events({
"core-overlay-close-completed [global-dialog]": function(e) {
Session.set("global.ui.dialogTemplate", null);
Session.set("global.ui.dialogData", null);
return Session.set("global.ui.dialogFullOnMobile", null);
},
"core-animated-pages-transition-end [detail-pages]": function(e) {
var detailOpened = Session.get("global.ui.detailShow");
if (!detailOpened) {
Session.set("global.ui.detailData", null);
Session.set("global.ui.detailTemplate", null);
Session.set("global.ui.detailHeroId", null);
}
},
"core-animated-pages-transition-prepare": function(e) {
var detailOpened = Session.get("global.ui.detailShow");
if (detailOpened) {
//set up the transition
} else {
//undo hack
$("#mainContentSection").removeClass("fake-selected");
}
},
"tap #screenDim": function(e) {
GlobalUI.closeDetail();
}
},
});

View File

@@ -23,3 +23,11 @@ Template.registerHelper("evaluateSignedSpaced", function(charId, string) {
Template.registerHelper("evaluateString", function(charId, string) {
return evaluateString(charId, string);
});
Template.registerHelper("evaluateShortString", function(charId, string) {
if (_.isString(string)){
return evaluateString(
charId, string.split(/^( *[-*_]){3,} *(?:\n+|$)/m)[0]
);
}
});

View File

@@ -1,32 +1,23 @@
openParentDialog = function(parent, charId, heroId) {
var detail;
openParentDialog = function({
parent, charId, element, returnElement, callback,
}) {
let template;
let data;
if (parent.collection === "Characters" && parent.group === "racial") {
detail = {
template: "raceDialog",
data: {charId: parent.id},
};
template = "raceDialog";
data = {charId: parent.id};
} else if (parent.collection === "Features") {
detail = {
template: "featureDialog",
data: {featureId: parent.id},
};
template = "featureDialog";
data = {featureId: parent.id};
} else if (parent.collection === "Classes") {
detail = {
template: "classDialog",
data: {classId: parent.id},
};
template = "classDialog";
data = {classId: parent.id};
} else if (parent.collection === "Items") {
detail = {
template: "itemDialog",
data: {itemId: parent.id},
};
template = "itemDialog";
data = {itemId: parent.id};
} else if (parent.collection === "Spells") {
detail = {
template: "spellDialog",
data: {spellId: parent.id},
};
template = "spellDialog";
data = {spellId: parent.id};
}
detail.heroId = heroId;
detail.charId = charId;
GlobalUI.setDetail(detail);
pushDialogStack({template, data, element, returnElement, callback});
};

View File

@@ -0,0 +1,24 @@
/**
* Take in a map like this:
* {
* "#someId": {
* proprty1() { return someReactiveValue()}
* }
* }
* and bind the properties to the DOM on autorun.
*
* Useful for polymer components where you need to set the order of property updating
* or alter properties that don't bind well to their attributes
*/
Blaze.Template.prototype.binding = function(bindingMap){
this.onRendered(function(){
_.each(bindingMap, (propertyMap, cssPattern) => {
node = this.find(cssPattern);
_.each(propertyMap, (func, property) => {
this.autorun(() => {
node[property] = func && func.call && func.call(this, node);
});
});
});
});
};

View File

@@ -0,0 +1,85 @@
/*Column layout*/
.column-container {
column-fill: balance;
column-gap: 0px;
column-width: 304px;
padding: 4px;
}
.column-container.thin-columns {
column-count: 4;
column-width: 240px;
}
.column-container > div {
padding: 4px;
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
/*Cards*/
.card {
background: white;
border-radius: 2px;
}
.card .top {
cursor: pointer;
padding: 16px;
border-radius: 2px 2px 0 0;
}
.card .top.white {
cursor: auto;
padding: 16px;
border-bottom: rgba(0,0,0,0.12) solid 1px;
}
.card .bottom {
padding: 16px;
border-radius: 0 0 2px 2px;
}
.card .bottom.list {
padding: 16px 0;
}
.card .bottom.list .paper-font-subhead {
color: rgba(0,0,0,0.54);
font-size: 14px;
font-weight: 500;
letter-spacing: 0.010em;
padding: 12px 16px 12px 16px;
}
.card .bottom.text {
white-space: pre-wrap;
}
.card .left {
padding: 16px;
border-radius: 2px 0 0 2px;
text-align: center;
min-width: 72px;
}
.card .right {
padding: 16px;
border-radius: 0 2px 2px 0;
}
.card .left paper-icon-button {
display: block;
height: 32px;
padding: 0;
width: 32px;
}
.card .left paper-icon-button[disabled] {
color: rgba(255, 255, 255, 0.2);
}
.card img, .card iron-image {
max-width: 100%;
}

View File

@@ -1,89 +0,0 @@
@import "{wolves:bourbon}/bourbon";
$thickColumnWidth: 304px;
$thinColumnWidth: 240px;
//Column layout
.column-container {
@include column-fill(balance);
@include column-gap(0px);
@include column-width($thickColumnWidth);
padding: 4px;
&.thin-columns {
@include column-count(4);
@include column-width($thinColumnWidth);
}
& > div {
padding: 4px;
//stop divs breaking over multiple columns
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
}
}
//Cards
.card {
background: white;
border-radius: 2px;
.top {
cursor: pointer;
padding: 16px;
border-radius: 2px 2px 0 0;
&.white {
cursor: auto;
padding: 16px;
border-bottom: rgba(0,0,0,0.12) solid 1px;
}
paper-checkbox::shadow #ink[checked] {
color: #ffffff;
}
paper-checkbox::shadow #ink {
color: #ffffff;
}
paper-checkbox::shadow #checkbox.checked {
background-color: #ffffff;
background-color: rgba(255,255,255,0.27);
border-color: #ffffff;
border-color: rgba(255,255,255,0.27);
}
paper-checkbox::shadow #checkbox {
border-color: #ffffff;
border-color: rgba(255,255,255,0.54);
}
}
.bottom {
padding: 16px;
border-radius: 0 0 2px 2px;
&.list {
padding: 0 0 16px 0;
.subhead {
color: rgba(0,0,0,0.54);
font-size: 14px;
font-weight: 500;
letter-spacing: 0.010em;
padding: 12px 16px 12px 16px;
}
}
&.text {
white-space: pre-wrap;
}
}
.left {
padding: 16px;
border-radius: 2px 0 0 2px;
text-align: center;
min-width: 72px;
}
.right {
padding: 16px;
border-radius: 0 2px 2px 0;
}
}
/* undo pointer cursor on detail box heading */
#globalDetail.card .top {
cursor: auto;
}

View File

@@ -70,6 +70,10 @@
background-color: #9E9E9E;
}
.blue-grey {
background-color: #607D8B;
}
.app-grey {
background-color: #424242;
}
@@ -80,4 +84,4 @@
.black {
background-color: #262626;
}
}

View File

@@ -0,0 +1,43 @@
/*
List items
*/
.item-slot {
background-color: rgb(232, 232, 232);
background-color: rgba(0, 0, 0, 0.1);
}
.item {
background: white;
cursor: pointer;
font-size: 16px;
height: 40px;
margin: 1px 0 1px 0;
padding: 0 16px 0 16px;
position: relative;
transition: box-shadow 0.3s ease, opacity 0.5s ease-in-out;
}
.item > .itemName {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.item.small {
height: 32px;
}
.item.tall {
height: 56px;
}
.item.flexible {
height: auto;
padding-top: 16px;
padding-bottom: 16px;
}
.item iron-icon, .item paper-icon-button {
color: #747474;
color: rgba(0,0,0,0.54);
}

View File

@@ -1,37 +0,0 @@
/*
List items
*/
.item-slot {
background-color: rgb(232, 232, 232);
background-color: rgba(0, 0, 0, 0.1);
}
.item {
background: white;
cursor: pointer;
font-size: 16px;
height: 40px;
margin: 1px 0 1px 0;
padding: 0 16px 0 16px;
position: relative;
transition: box-shadow 0.3s ease, opacity 0.5s ease-in-out;
&.small {
height: 32px;
}
&.tall {
height: 56px;
}
&.flexible {
height: auto;
padding-top: 16px;
padding-bottom: 16px;
}
&[hero], &:active{
box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.37);
z-index: 10;
}
core-icon, paper-icon-button {
color: #747474;
color: rgba(0,0,0,0.54);
}
}

View File

@@ -1,7 +1,4 @@
@import "{wolves:bourbon}/bourbon";
@import "colors";
//apply a natural box layout model to all elements
/*apply a natural box layout model to all elements*/
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
@@ -19,17 +16,7 @@ body {
background-color: #E0E0E0;
}
//fix tabs and core-toolbar having box shadow
core-toolbar {
box-shadow: none;
}
//give drawer panel a shadow always
core-header-panel[drawer] {
box-shadow: 2px 0px 5px 0px rgba(0,0,0,0.2);
}
//Paragraphs
/*Paragraphs*/
p {
margin-bottom: 8px;
}
@@ -46,14 +33,48 @@ hr {
text-align: center;
}
//FABs
.avatar {
display: inline-block;
box-sizing: border-box;
width: 40px;
height: 40px;
border-radius: 50%;
font-size: 26px;
font-color: rgba(255, 255, 255, 0.58) !important;
}
/*
temporary fix for https://github.com/PolymerElements/paper-item/issues/71
*/
paper-icon-item::shadow #contentIcon {
flex-shrink: 0;
}
/*FABs*/
.floatyButton {
position: fixed;
bottom: 24px;
right: 24px;
/* stop the fab from flashing during animation */
transform: scale(1) translateZ(0px);
z-index: 3;
}
//Buttons
paper-fab {
background-color: #d13b2e;
}
paper-fab.keyboard-focus {
background: #630c05;
}
.red-button:not([disabled]) {
background: #d23f31;
color: #fff;
margin-top: 16px;
}
/*Buttons*/
paper-button {
color: #000;
color: rgba(0,0,0,0.87);
@@ -63,7 +84,12 @@ paper-button {
text-transform: uppercase;
}
//Style shortcuts
dicecloud-selector paper-item {
white-space: nowrap;
overflow: hidden;
}
/*Style shortcuts*/
.scroll-y {
overflow-y: auto;
}

View File

@@ -1,24 +0,0 @@
.card .left paper-icon-button {
display: block;
height: 32px;
padding: 0;
width: 32px;
}
.card .left paper-icon-button[disabled] {
color: rgba(255, 255, 255, 0.2);
}
.card .left paper-icon-button /deep/ core-icon {
height: 32px;
width: 32px;
}
/*fix paper-dropdowns*/
body /deep/ core-menu {
overflow-x: hidden !important;
}
html /deep/ paper-dropdown {
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
}

View File

@@ -0,0 +1,15 @@
td {
padding: 8px;
}
.strengthTable{
width: 100%;
}
.strengthTable td:nth-child(2){
text-align: right;
}
.summaryTable td:nth-child(3){
text-align: right;
}

View File

@@ -1,21 +0,0 @@
td {
padding: 8px;
}
.strengthTable{
width: 100%;
td{
&:nth-child(2) {
text-align: right;
}
&:nth-child(3) {
width: 250px;
}
}
}
.summaryTable {
&:nth-child(3){
text-align: right;
}
}

View File

@@ -1,68 +0,0 @@
#detailScreenFiller {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
}
#screenDim {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: grey;
background-color: rgba(0,0,0,0.35);
}
#fadeDummy {
pointer-events: none;
}
.detailContent {
padding: 24px;
}
html /deep/ .red-button:not([disabled]) {
background: #d23f31;
color: #fff;
margin-top: 16px;
}
#globalDetail {
background-color: white;
width: 624px;
height: 500px;
border-radius: 2px;
}
#globalDetail core-toolbar {
border-radius: 2px 2px 0 0;
}
@media (max-width: 640px) {
#globalDetail core-toolbar {
border-radius: 0;
}
}
@media (max-width: 640px) {
#globalDetail {
top: 0 !important;
left: 0 !important;
width: 100%;
height: 100%;
margin: 0;
border-radius: 0;
}
}
.not-selected [hero] {
visibility: hidden;
}

View File

@@ -1,113 +1,64 @@
.display2 {
font-size: 45px;
font-weight: 400;
color: #000;
color: rgba(0,0,0,0.54);
letter-spacing: 0;
.white-text {
color: #dedede;
color: rgba(255,255,255,0.87);
}
.white-text .display2{
.white-text .paper-font-display2{
color: #8a8a8a;
color: rgba(255,255,255,0.54);
}
.display1 {
font-size: 34px;
font-weight: 400;
color: #000;
color: rgba(0,0,0,0.54);
letter-spacing: 0;
}
.white-text .display1, .white-text.display1{
.white-text .paper-font-display1, .white-text.paper-font-display1{
color: #8a8a8a;
color: rgba(255,255,255,0.54);
}
h1, .headline {
font-size: 24px;
font-weight: 400;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0;
}
.white-text h1, .white-text .headline, .white-text.headline{
.white-text h1, .white-text .paper-font-headline, .white-text.paper-font-headline{
color: #dedede;
color: rgba(255,255,255,0.87);
}
h2, .title {
font-size: 20px;
font-weight: 500;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.005em;
}
.white-text h2, .white-text .title, .white-text.title{
.white-text h2, .white-text .paper-font-title, .white-text.paper-font-title{
color: #dedede;
color: rgba(255,255,255,0.87);
}
h3, .subhead {
font-size: 16px;
font-weight: 400;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010em;
}
.white-text h3, .white-text .subhead{
.white-text h3, .white-text .paper-font-subhead{
color: #dedede;
color: rgba(255,255,255,0.87);
}
.body2 {
font-size: 14px;
font-weight: 500;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010em;
}
.white-text .body2{
.white-text .paper-font-body2{
color: #dedede;
color: rgba(255,255,255,0.87);
}
p, .body1, body {
font-size: 14px;
font-weight: 400;
margin: 0;
color: #000;
color: rgba(0,0,0,0.87);
letter-spacing: 0.010em;
}
.white-text p, .white-text .body1{
.white-text p, .white-text .paper-font-body1{
color: #dedede;
color: rgba(255,255,255,0.87);
}
.caption{
font-size: 12px;
font-weight: 400;
color: #000;
color: rgba(0,0,0,0.54);
letter-spacing: 0.020em;
}
.white-text .caption{
.white-text .paper-font-caption{
color: #8a8a8a;
color: rgba(255,255,255,0.54);
}
html /deep/ .white-text{
color: #fff;
}
.black54 {
color: #444;
color: #757575;
color: rgba(0,0,0,0.54);
}
.white54 {
color: #eee;
color: #8a8a8a;
color: rgba(255,255,255,0.54);
}
.black87 {
color: #212121;
color: rgba(0,0,0,0.87);
}
.white87 {
color: #dedede;
color: rgba(255,255,255,0.87);
}

View File

@@ -1,39 +1,33 @@
<template name="attackEdit">
<div layout horizontal>
<div layout vertical flex>
<div layout horizontal>
<div class="layout horizontal">
<div class="layout vertical flex">
<div class="layout horizontal wrap">
<!--attackBonus-->
<paper-input class="attackBonusInput"
label="Attack Bonus"
floatinglabel
value={{attackBonus}}
flex></paper-input>
<paper-input class="attackBonusInput flex" label="Attack Bonus" value={{attackBonus}}
style="flex-basis: 200px; margin-right: 16px;">
{{> formulaSuffix}}
</paper-input>
<!--details-->
<paper-input class="detailInput"
label="Details"
floatinglabel
value={{details}}></paper-input>
<paper-input class="detailInput" label="Details" value={{details}} style="flex-basis: 200px;">
</paper-input>
</div>
<div layout horizontal>
<div class="layout horizontal wrap">
<!--damageBonus-->
<paper-input class="damageInput"
label="Damage"
floatinglabel
value={{damage}}
flex></paper-input>
<paper-input class="damageInput flex" label="Damage" value={{damage}}
style="flex-basis: 200px; margin-right: 16px;">
{{> bracketSuffix}}
</paper-input>
<!--DamageType-->
<paper-dropdown-menu class="damageTypeDropdown" label="Damage Type">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{damageType}}>
{{#each damageTypes}}
<paper-item name={{this}} class="containerMenuItem">{{this}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
<paper-dropdown-menu label="Damage Type" dynamic-align>
<dicecloud-selector class="dropdown-content damageTypeDropdown" selected={{damageType}}>
{{#each damageTypes}}
<paper-item name={{this}} class="containerMenuItem">{{this}}</paper-item>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
</div>
</div>
<!--Delete Button-->
<paper-icon-button class="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
<paper-icon-button class="deleteAttack" icon="delete"></paper-icon-button>
</div>
</template>
</template>

View File

@@ -15,7 +15,7 @@ var damageTypes = [
];
Template.attackEdit.events({
"tap .deleteAttack": function(event, instance) {
"click .deleteAttack": function(event, instance) {
Attacks.softRemoveNode(this._id);
GlobalUI.deletedToast(this._id, "Attacks", "Attack");
},
@@ -31,9 +31,8 @@ Template.attackEdit.events({
var value = event.currentTarget.value;
Attacks.update(this._id, {$set: {details: value}});
},
"core-select .damageTypeDropdown": function(event) {
"iron-select .damageTypeDropdown": function(event) {
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
if (value == this.damageType) return;
Attacks.update(this._id, {$set: {damageType: value}});
@@ -44,7 +43,4 @@ Template.attackEdit.helpers({
damageTypes: function() {
return damageTypes;
},
DAMAGE_DICE: function() {
return DAMAGE_DICE;
},
});

View File

@@ -3,7 +3,7 @@
{{#if attacks.count}}
<hr style="margin: 16px 0 16px 0;">
<div id="attacks">
<h2>Attacks</h2>
<div class="paper-font-title">Attacks</div>
{{#each attacks}}
{{>attackEdit}}
{{/each}}

View File

@@ -1,14 +1,14 @@
<template name="attackView">
<div class="attackView" layout horizontal>
<div class="headline" style="margin-right: 16px;" layout horizontal center>
<div class="attackView layout horizontal">
<div class="paper-font-headline layout horizontal center" style="margin-right: 16px;">
{{evaluateSigned charId attackBonus}}
</div>
<div layout vertical>
<div class="layout vertical">
<div>
{{evaluateString charId damage}}&nbsp;{{damageType}}
</div>
{{#if details}}
<div class="caption">
<div class="paper-font-caption">
{{details}}
</div>
{{/if}}

View File

@@ -2,10 +2,10 @@
{{#if attacks.count}}
<hr style="margin: 16px 0 16px 0;">
<div class="attacks">
<h2 class="spaceAfter">Attacks</h2>
<div class="spaceAfter paper-font-title">Attacks</div>
{{#each attacks}}
{{> attackView}}
{{/each}}
</div>
{{/if}}
</template>
</template>

View File

@@ -1,27 +1,24 @@
<template name="characterSettings">
{{#with character}}
<div style="height: 100px;">
<table style="width: 100%;">
<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 class="fit layout vertical">
<app-header-layout has-scrolling-region class="feedback flex">
<app-header fixed effects="waterfall">
<app-toolbar>
<div main-title>Character Settings</div>
</app-toolbar>
</app-header>
<div class="form flex">
<paper-toggle-button id="hideSpellcasting" checked={{settings.hideSpellcasting}}>
Hide Spells tab
</paper-toggle-button>
<paper-toggle-button id="variantEncumbrance" checked={{settings.useVariantEncumbrance}}>
Use variant encumbrance
</paper-toggle-button>
</div>
</app-header-layout>
<div class="buttons layout horizontal end-justified">
<paper-button class="doneButton"> Done </paper-button>
</div>
</div>
{{/with}}
<paper-button id="doneButton" affirmative> Done </paper-button>
</template>

View File

@@ -23,4 +23,7 @@ Template.characterSettings.events({
);
}
},
"click .doneButton": function(event, instance){
popDialogStack();
},
});

View File

@@ -1,9 +1,20 @@
<template name="deleteCharacterConfirmation">
<div>
Deleting a character cannot be undone.<br>
To continue type "{{name}}" into the box below.<br>
<paper-input id="nameInput" label="type the characters's name here" style="width: 100%;"></paper-input><br>
<paper-button id="deleteButton" style={{getStyle}} disabled={{cantDelete}}>Delete Character</paper-button>
<div class="fit layout vertical">
<app-header-layout has-scrolling-region class="feedback flex">
<app-header fixed effects="waterfall">
<app-toolbar>
<div main-title>Delete Character</div>
</app-toolbar>
</app-header>
<div class="form flex">
Deleting a character cannot be undone.<br>
To continue type "{{name}}" into the box below.<br>
<paper-input id="nameInput" label="type the characters's name here" style="width: 100%;"></paper-input><br>
<paper-button id="deleteButton" style={{getStyle}} disabled={{cantDelete}}>Delete Character</paper-button>
</div>
</app-header-layout>
<div class="buttons layout horizontal end-justified">
<paper-button class="cancelButton"> Cancel </paper-button>
</div>
</div>
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
</template>
</template>

View File

@@ -18,11 +18,14 @@ Template.deleteCharacterConfirmation.events({
var canDel = instance.find("#nameInput").value === this.name;
instance.canDelete.set(canDel);
},
"tap #deleteButton": function(event, instance) {
"click #deleteButton": function(event, instance) {
if (instance.find("#nameInput").value === this.name) {
GlobalUI.closeDialog();
Router.go("/");
popDialogStack();
Router.go("/characterList");
Characters.remove(this._id);
}
}
},
"click .cancelButton": function(event, instance){
popDialogStack();
},
});

View File

@@ -1,54 +1,65 @@
<template name="shareDialog">
<div style="width: 360px;">
<div layout horizontal center>
<div>Who can view this character: </div>
<paper-dropdown-menu class="visibilityDropdown"
label="Visibility">
<paper-dropdown layered class="dropdown">
<core-menu class="menu visibilityMenu" selected={{viewPermission}}>
<paper-item name="whitelist">Only people I share with</paper-item>
<paper-item name="public">Anyone with link</paper-item>
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
<div class="fit layout vertical">
<app-header-layout has-scrolling-region class="feedback flex">
<app-header fixed effects="waterfall">
<app-toolbar>
<div main-title>Share</div>
</app-toolbar>
</app-header>
<div class="form flex">
<paper-dropdown-menu label="Who can view this character">
<dicecloud-selector class="visibilityDropdown dropdown-content" selected={{viewPermission}}>
<paper-item name="whitelist">Only people I share with</paper-item>
<paper-item name="public">Anyone with link</paper-item>
</dicecloud-selector>
</paper-dropdown-menu>
<div class="layout horizontal center wrap">
<paper-input class="flex" id="userNameOrEmailInput" label="Share with username or email" floatinglabel></paper-input>
<paper-button id="shareButton"
class="red-button"
style="width: 80px; height: 37px; margin-top: 16px;"
raised
disabled={{shareButtonDisabled}}>Share</paper-button>
<paper-radio-group id="accessLevelMenu" selected="read">
<paper-radio-button name="read">View Only</paper-radio-button>
<paper-radio-button name="write">Can Edit</paper-radio-button>
</paper-radio-group>
</div>
<p style="color: red;">{{userFindError}}</p>
<div>
{{#if readers.length}}
<div class="paper-font-subhead">
Can View
</div>
{{#each id in readers}}
<div class="layout horizontal center">
{{#with id=id}}
<paper-icon-button class="deleteShare" icon="delete">
</paper-icon-button>
{{/with}}
<div class="flex">{{username id}}</div>
</div>
{{/each}}
{{/if}}
{{#if writers.length}}
<div class="paper-font-subhead">
Can Edit
</div>
{{#each id in writers}}
<div class="layout horizontal center">
{{#with id=id}}
<paper-icon-button class="deleteShare" icon="delete">
</paper-icon-button>
{{/with}}
<div class="flex">{{username id}}</div>
</div>
{{/each}}
{{/if}}
</div>
</div>
</app-header-layout>
<div class="buttons layout horizontal end-justified">
<paper-button class="doneButton"> Done </paper-button>
</div>
<div>
{{#if readers.count}}
<div style="font-weight: 500;">
Can View
</div>
{{#each readers}}
<div layout horizontal center>
<div flex>{{getUserName}}</div>
<paper-icon-button class="deleteShare" icon="delete"></paper-icon-button>
</div>
{{/each}}
{{/if}}
{{#if writers.count}}
<div style="font-weight: 500;">
Can Edit
</div>
{{#each writers}}
<div layout horizontal center>
<div flex>{{username}}</div>
<paper-icon-button class="deleteShare" icon="delete"></paper-icon-button>
</div>
{{/each}}
{{/if}}
</div>
<div layout horizontal center>
<paper-input flex id="userNameOrEmailInput" label="Username or email" floatinglabel></paper-input>
<paper-button id="shareButton"
class="red-button"
style="width: 80px; height: 37px; margin-top: 16px;"
raised
disabled={{shareButtonDisabled}}>Share</paper-button>
</div>
<p style="color: red;">{{userFindError}}</p>
<paper-radio-group id="accessLevelMenu" selected="read">
<paper-radio-button name="read" label="View Only"></paper-radio-button>
<paper-radio-button name="write" label="Can Edit"></paper-radio-button>
</paper-radio-group>
</div>
<paper-button id="doneButton" affirmative> Done </paper-button>
</template>

View File

@@ -1,5 +1,19 @@
Template.shareDialog.onCreated(function(){
this.userId = new ReactiveVar();
this.autorun(() => {
var char = Characters.findOne(Template.currentData()._id, {
fields: {readers: 1, writers: 1}
});
if (!char) return;
this.subscribe("userNames", _.union(char.readers, char.writers));
});
});
Template.shareDialog.onRendered(function(){
// Polymer not mirroring selected attribute properly
this.$("paper-listbox").each(function(){
this.selected = this.getAttribute("selected");
});
});
Template.shareDialog.helpers({
@@ -9,11 +23,16 @@ Template.shareDialog.helpers({
},
readers: function(){
var char = Characters.findOne(this._id, {fields: {readers: 1}});
return Meteor.users.find({_id: {$in: char.readers}});
return char.readers;
},
writers: function(){
var char = Characters.findOne(this._id, {fields: {writers: 1}});
return Meteor.users.find({_id: {$in: char.writers}});
//Meteor.users.find({_id: {$in: char.writers}});
return char.writers
},
username: function(id){
const user = Meteor.users.findOne(id);
return user && user.username || "user: " + id;
},
shareButtonDisabled: function(){
return !Template.instance().userId.get();
@@ -23,15 +42,11 @@ Template.shareDialog.helpers({
return "User not found";
}
},
getUserName: function() {
return this.username || "user: " + this._id;
}
});
Template.shareDialog.events({
"core-select .visibilityDropdown": function(event){
"iron-select .visibilityDropdown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
var char = Characters.findOne(this._id, {fields: {settings: 1}});
if (value == char.settings.viewPermission) return;
@@ -50,7 +65,7 @@ Template.shareDialog.events({
}
});
},
"tap #shareButton": function(event, instance){
"click #shareButton": function(event, instance){
var self = this;
var permission = instance.find("#accessLevelMenu").selected;
if (!permission) throw "no permission set";
@@ -68,9 +83,12 @@ Template.shareDialog.events({
});
}
},
"tap .deleteShare": function(event, instance) {
"click .deleteShare": function(event, instance) {
Characters.update(instance.data._id, {
$pull: {writers: this._id, readers: this._id}
$pull: {writers: this.id, readers: this.id}
});
},
"click .doneButton": function(event, instance){
popDialogStack();
},
});

View File

@@ -1,28 +1,24 @@
paper-tabs, core-toolbar {
box-shadow: 0px 3px 2px rgba(0, 0, 0, 0.2);
}
core-toolbar paper-tabs {
box-shadow: none;
}
paper-tabs[noink][nobar] paper-tab.core-selected {
color: #fff;
}
paper-tabs /deep/ #selectionBar, #onRadio {
background-color: #d50000;
}
paper-tabs ::shadow #ink {
color: #b22 !important;
}
paper-tabs.transparent-brown {
background-color: transparent;
box-shadow: none;
}
core-toolbar.medium-tall {
app-toolbar.medium-tall {
height: 108px;
}
.character-name {
padding-left: 16px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.character-menu paper-icon-item{
cursor: pointer;
}
.character-sheet app-header {
position: relative;
z-index: 1;
}
.character-sheet iron-pages > div {
overflow-y: auto;
overflow-x: hidden;
}

View File

@@ -1,54 +1,58 @@
<template name="characterSheet">
<!--<div tool horizontal layout flex end-justified class="bottom">Title-bottom</div>-->
<core-toolbar class="medium-tall {{colorClass}}">
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
<div flex>
{{name}}
</div>
{{#if canEditCharacter _id}}
<div>
{{> colorDropdown}}
</div>
<paper-menu-button>
<paper-icon-button icon="more-vert" noink></paper-icon-button>
<paper-dropdown class="dropdown" halign="right">
<core-menu class="menu" style="color: black; color: rgba(0,0,0,0.87);">
<paper-item id="deleteCharacter">
<core-icon icon="delete"></core-icon>Delete
</paper-item>
<paper-item id="shareCharacter">
<core-icon icon="social:share"></core-icon>Share
</paper-item>
<paper-item id="characterSettings">
<core-icon icon="settings"></core-icon>Settings
</paper-item>
</core-menu>
</paper-dropdown>
</paper-menu-button>
{{/if}}
<div class="bottom fit" horizontal layout>
<paper-tabs flex horizontal center layout id="characterSheetTabs" selected={{selectedTab}} class="{{colorClass}}">
<paper-tab name="stats">Stats</paper-tab>
<paper-tab name="features">Features</paper-tab>
<paper-tab name="inventory">Inventory</paper-tab>
<div class="fit layout vertical character-sheet">
<app-header fixed effects="waterfall">
<app-toolbar class="medium-tall {{colorClass}}">
<div top-item class="layout horizontal center">
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div class="flex character-name">
{{name}}
</div>
{{#if canEditCharacter _id}}
{{> colorDropdown}}
<paper-menu-button class="character-menu" horizontal-align="right">
<paper-icon-button icon="more-vert" class="dropdown-trigger"></paper-icon-button>
<paper-menu class="dropdown-content black87">
<paper-icon-item id="deleteCharacter">
<iron-icon icon="delete" item-icon></iron-icon>
Delete
</paper-icon-item>
<paper-icon-item id="shareCharacter">
<iron-icon icon="social:share" item-icon></iron-icon>
Share
</paper-icon-item>
<paper-icon-item id="characterSettings">
<iron-icon icon="settings" item-icon></iron-icon>
Settings
</paper-icon-item>
</paper-menu>
</paper-menu-button>
{{/if}}
</div>
<div bottom-item>
<paper-tabs id="characterSheetTabs" selected={{selectedTab}} class="{{colorClass}}">
<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>
</div>
</app-toolbar>
</app-header>
<div class="flex" style="position: relative;">
<iron-pages id="tabPages" class="fit" selected={{selectedTab}}>
<div name="stats" class="tab-page fit">{{> stats}}</div>
<div name="features" class="tab-page fit">{{> features}}</div>
<div name="inventory" class="tab-page fit">{{> inventory}}</div>
{{#unless hideSpellcasting}}
<paper-tab name="spells">Spells</paper-tab>
<div name="spells" class="tab-page fit">{{> spells}}</div>
{{/unless}}
<paper-tab name="persona">Persona</paper-tab>
<paper-tab name="journal">Journal</paper-tab>
</paper-tabs>
<div name="persona" class="tab-page fit">{{> persona}}</div>
<div name="journal" class="tab-page fit">{{> journal}}</div>
</iron-pages>
</div>
</core-toolbar>
<div fit>
<core-animated-pages id="tabPages" selected={{selectedTab}} transitions="slide-from-right" fit>
<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>
</div>
</template>

View File

@@ -1,11 +1,162 @@
Template.characterSheet.onCreated(function() {
//default to the first tab
Session.setDefault(this.data._id + ".selectedTab", "stats");
let tabPages, tabSliders, tabFabs, tabFabMenus;
Template.characterSheet.onRendered(function() {
//default to the stats tab
Session.setDefault(this.data._id + ".selectedTab", "0");
// Keep the header's scroll target up to date with the currently selected tab
let header;
this.autorun(() => {
const tab = getTab(Template.currentData()._id);
header = header || this.find("app-header");
if (!header) return;
Tracker.afterFlush(() => {
header.scrollTarget = this.find("#tabPages .iron-selected");
header._scrollHandler && header._scrollHandler();
});
});
_.defer(() => {
// Store all the tab page components for use in animations
tabPages = _.times(6, (n) =>
this.$(`.tab-page:nth-child(${n + 1})`)
);
tabSliders = _.times(6, (n) =>
tabPages[n].find(".animation-slider")
);
tabFabs = _.times(6, (n) =>
tabPages[n].find(".floatyButton")
);
tabFabMenus = _.times(6, (n) =>
tabPages[n].find(".mini-holder")
);
})
//watch this character and make sure their encumbrance is updated
trackEncumbranceConditions(this.data._id, this);
//trackEncumbranceConditions(this.data._id, this);
});
/**
* Page change animations that suck less than neon-animated-pages
*/
const tabAnimation = ({oldTab, newTab, duration}) => {
if (newTab === oldTab) return;
duration = duration || 400;
const delay = (element, f) => {
element.on(
"transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd",
(event) => {
if (event.target == event.currentTarget){
f();
$(this).off(event);
}
}
);
}
const isForward = newTab > oldTab;
const entryAnimation = {
before: {
transform: isForward ? "translateX(100%)" : "translateX(-100%)",
},
during: {
transition: `transform ${duration}ms ease`,
transform: "",
},
after: {
transition: "",
transform: "",
},
}
const exitAnimation = {
before: {
transform: "translateZ(0)",
},
during: {
transition: `transform ${duration}ms ease`,
transform: isForward ? "translateX(-100%)" : "translateX(100%)",
},
after: {
transition: "",
transform: "",
display: "",
},
}
const oldPage = tabPages[oldTab];
const newPage = tabPages[newTab];
if (oldPage.length && newPage.length){
oldPage[0].style.setProperty("display", "initial", "important");
oldPage.css({zIndex: "1"});
newPage.css({zIndex: "0"});
_.defer(() => {
oldPage.css({
transition: `z-index ${duration}ms linear`,
zIndex: "0",
});
newPage.css({
transition: `z-index ${duration}ms linear`,
zIndex: "1",
});
});
delay(oldPage, () => oldPage.css({
display: "",
transition: "",
zIndex: "",
}));
delay(newPage, () => newPage.css({
transition: "",
zIndex: "",
}));
}
const oldSlider = tabSliders[oldTab];
if (oldSlider.length){
oldSlider.css(exitAnimation.before);
_.defer(() => oldSlider.css(exitAnimation.during));
delay(oldSlider, () => oldSlider.css(exitAnimation.after));
}
const newSlider = tabSliders[newTab];
if (newSlider.length){
newSlider.css(entryAnimation.before);
_.defer(() => newSlider.css(entryAnimation.during));
delay(newSlider, () => newSlider.css(entryAnimation.after));
}
slideDown = ({element, reverse}) => {
element.css({
transform: reverse ? "translateY(80px)" : "",
});
const fraction = duration / 4;
_.defer(() => element.css({
transition: reverse ?
`transform ${fraction}ms ease-out ${duration - fraction}ms` :
`transform ${fraction}ms ease-in`,
transform: reverse ? "" : "translateY(80px)",
}));
delay(element, () => element.css({
transition: "",
}));
}
const oldFab = tabFabs[oldTab];
const newFab = tabFabs[newTab];
if (oldFab.length && !newFab.length){
slideDown({element: oldFab});
}
if (newFab.length && !oldFab.length){
slideDown({element: newFab, reverse: true});
}
if (newFab.length && oldFab.length){
newFab.css({transform: ""});
}
const oldFabMenu = tabFabMenus[oldTab];
if (oldFabMenu.length) {
Blaze.getView(oldFabMenu[0]).templateInstance().active.set(false);
}
}
var setTab = function(charId, tab){
tabAnimation({
oldTab: +Session.get(charId + ".selectedTab"),
newTab: +tab,
});
return Session.set(charId + ".selectedTab", tab);
};
@@ -24,34 +175,32 @@ Template.characterSheet.helpers({
});
Template.characterSheet.events({
"core-animated-pages-transition-end #tabPages": function(event) {
event.stopPropagation();
},
"tap #characterSheetTabs paper-tab": function(event, instance){
setTab(this._id, event.currentTarget.getAttribute("name"));
"iron-select #characterSheetTabs": function(event, instance){
setTab(this._id, event.target.selected);
},
"color-change": function(event, instance){
console.log("character color change")
Characters.update(this._id, {$set: {color: event.color}});
},
"tap #deleteCharacter": function(event, instance){
GlobalUI.showDialog({
heading: "Delete " + this.name,
"click #deleteCharacter": function(event, instance){
pushDialogStack({
data: this,
template: "deleteCharacterConfirmation",
element: event.currentTarget.parentElement.parentElement,
});
},
"tap #shareCharacter": function(event, instance){
GlobalUI.showDialog({
heading: "Share " + this.name,
"click #shareCharacter": function(event, instance){
pushDialogStack({
data: this,
template: "shareDialog",
element: event.currentTarget.parentElement.parentElement,
});
},
"tap #characterSettings": function(event, instance){
GlobalUI.showDialog({
heading: this.name + " Settings",
"click #characterSettings": function(event, instance){
pushDialogStack({
data: this,
template: "characterSettings",
element: event.currentTarget.parentElement.parentElement,
});
},
});

View File

@@ -1,22 +1,15 @@
html /deep/ .operationDropDown {
.effectEdit .operationDropDown {
width: 152px;
}
html /deep/ .statDropDown {
.effectEdit .statDropDown {
width: 152px;
}
html /deep/ .damageMultiplierDropDown {
.effectEdit .damageMultiplierDropDown {
width: 152px;
}
html /deep/ .effectEdit paper-input {
position: relative;
bottom: 5px;
}
html /deep/ .effectEdit {
height: 64px;
display: flex;
align-items: flex-end;
.effectEdit .deleteEffect {
flex-shrink: 0;
}

View File

@@ -1,36 +1,30 @@
<template name="effectEdit">
<div class="effectEdit" layout horizontal center>
<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>
<div class="effectEdit layout horizontal center">
<paper-dropdown-menu label="Stat" class="statDropDown" dynamic-align>
<dicecloud-selector class="statMenu dropdown-content" selected={{stat}} selectable="paper-item">
{{#each statGroups}}
<div style="font-weight: bold; margin-top: 16px; padding-left: 8px;">
{{this}}
</div>
{{#each stats}}
<paper-item name={{stat}}>{{name}}</paper-item>
{{/each}}
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
{{#if operations}}
<paper-dropdown-menu class="operationDropDown"
label="Operation">
<paper-dropdown layered class="dropdown">
<core-menu class="menu operationMenu" selected={{operation}}>
{{#each operations}}
<paper-item name={{operation}}>{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
<paper-dropdown-menu class="operationDropDown" label="Operation" dynamic-align>
<dicecloud-selector class="dropdown-content operationMenu" selected={{operation}}>
{{#each operations}}
<paper-item name={{operation}}>{{name}}</paper-item>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
{{/if}}
{{#if effectValueTemplate}}
{{> Template.dynamic template=effectValueTemplate}}
{{else}}
<div flex></div>
<div class="flex"></div>
{{/if}}
<paper-icon-button class="deleteEffect"
icon="delete">
@@ -40,27 +34,22 @@
</template>
<template name="regularEffectValue">
<paper-input class="effectValueInput"
label="Value"
floatinglabel
value={{effectValue}}
flex
<paper-input class="effectValueInput flex"
label="Value"
floatinglabel
value={{effectValue}}
style="flex-basis: 100px;">
</paper-input>
</template>
<template name="multiplierEffectValue">
<paper-dropdown-menu class="damageMultiplierDropDown"
label="Damage Multiplier">
<paper-dropdown layered
class="dropdown">
<core-menu class="menu multiplierMenu"
<paper-dropdown-menu class="damageMultiplierDropDown" label="Damage Multiplier" dynamic-align>
<dicecloud-selector class="menu multiplierMenu dropdown-content"
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>
</dicecloud-selector>
</paper-dropdown-menu>
<div flex></div>
<div class="flex"></div>
</template>

View File

@@ -1,4 +1,5 @@
//TODO add dexterity armor
// jscs:disable maximumLineLength
var stats = [
{stat: "strength", name: "Strength", group: "Ability Scores"},
{stat: "dexterity", name: "Dexterity", group: "Ability Scores"},
@@ -68,9 +69,11 @@ var stats = [
{stat: "psychicMultiplier", name: "Psychic", group: "Weakness/Resistance"},
{stat: "radiantMultiplier", name: "Radiant", group: "Weakness/Resistance"},
{stat: "slashingMultiplier", name: "Slashing", group: "Weakness/Resistance"},
{stat: "thunderMultiplier", name: "Thunder", group: "Weakness/Resistance"}
{stat: "thunderMultiplier", name: "Thunder", group: "Weakness/Resistance"},
];
// jscs:enable maximumLineLength
var statsDict = _.indexBy(stats, "stat");
var statGroups = _.groupBy(stats, "group");
var statGroupNames = _.keys(statGroups);
@@ -80,7 +83,7 @@ var attributeOperations = [
{name: "Add", operation: "add"},
{name: "Multiply", operation: "mul"},
{name: "Min", operation: "min"},
{name: "Max", operation: "max"}
{name: "Max", operation: "max"},
];
var skillOperations = [
{name: "Add", operation: "add"},
@@ -91,7 +94,7 @@ var skillOperations = [
{name: "Disadvantage", operation: "disadvantage"},
{name: "Passive Bonus", operation: "passiveAdd"},
{name: "Automatically Fail", operation: "fail"},
{name: "Conditional Benefit", operation: "conditional"}
{name: "Conditional Benefit", operation: "conditional"},
];
Template.effectEdit.helpers({
@@ -125,7 +128,7 @@ Template.effectEdit.helpers({
//default template
return "regularEffectValue";
}
},
});
Template.regularEffectValue.helpers({
@@ -135,33 +138,30 @@ Template.regularEffectValue.helpers({
});
Template.effectEdit.events({
"tap .deleteEffect": function(event){
"click .deleteEffect": function(event){
Effects.softRemoveNode(this._id);
GlobalUI.deletedToast(this._id, "Effects", "Effect");
},
"core-select .statDropDown": function(event){
"iron-select .statDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var statName = detail.item.getAttribute("name");
if (statName == this.stat) return;
Effects.update(this._id, {$set: {stat: statName}});
},
"core-select .operationDropDown": function(event){
"iron-select .operationDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var opName = detail.item.getAttribute("name");
if (opName == this.operation) return;
Effects.update(this._id, {$set: {operation: opName}});
},
"core-select .damageMultiplierDropDown": function(event){
"iron-select .damageMultiplierDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = +detail.item.getAttribute("name");
if (value == this.value) return;
Effects.update(this._id, {$set: {
value: value,
calculation: "",
operation: "mul"
operation: "mul",
}});
},
"change .effectValueInput": function(event){
@@ -174,5 +174,5 @@ Template.effectEdit.events({
if (this.calculation === value) return;
Effects.update(this._id, {$set: {value: "", calculation: value}});
}
}
},
});

View File

@@ -1,13 +1,12 @@
<!--needs to be given charId, parentId and parentCollection-->
<template name="effectsEditList">
{{#if effects.count}}
<hr class="vertMargin">
<div id="effects">
<h2>Effects</h2>
<div class="paper-font-title">Effects</div>
{{#each effects}}
{{>effectEdit}}
{{/each}}
</div>
{{/if}}
<paper-button id="addEffectButton" class="red-button" raised>Add Effect</paper-button>
</template>
</template>

View File

@@ -1,9 +1,8 @@
<!--needs to be given charId, (parentId or stat) and type-->
<template name="effectsViewList">
{{#if effects.count}}
<hr style="margin: 16px 0 16px 0;">
<div class="effects">
<h2 class="spaceAfter">Effects</h2>
<div class="spaceAfter paper-font-title">Effects</div>
<table class="wideTable">
{{#each effects}}
{{>effectView}}

View File

@@ -10,10 +10,9 @@
<template name="featureDetails">
{{#if or canEnable hasUses}}
<div layout horizontal center justified wrap>
<div class="layout horizontal center justified wrap">
{{#if canEnable}}
<div>enabled:</div>
<paper-checkbox class="sideMargin" checked={{enabled}}></paper-checkbox>
<paper-checkbox class="sideMargin" checked={{enabled}}>enabled</paper-checkbox>
{{/if}}
{{#if hasUses}}
<div class="subhead" style="margin-right: 16px">
@@ -21,7 +20,7 @@
</div>
{{/if}}
{{#if hasUses}}
<div layout horizontal>
<div class="layout horizontal">
<paper-button class="useFeature" disabled={{noUsesLeft}}>Use</paper-button>
<paper-button class="resetFeature" disabled={{usesFull}}>Reset</paper-button>
</div>
@@ -41,44 +40,36 @@
<template name="featureEdit">
<!--name-->
<paper-input id="featureNameInput" class="fullwidth" label="Name" floatinglabel value={{name}}></paper-input>
<paper-input id="featureNameInput" class="fullwidth" label="Name" value={{name}}></paper-input>
<hr class="vertMargin">
<div layout horizontal center style="height: 60px;">
<paper-dropdown-menu id="enabledDropdown" label="Enable Feature">
<paper-dropdown layered class="dropdown">
<core-menu id="enabledMenu" class="menu" selected={{enabledSelection}} on-tap="onStatMenuTap">
<paper-item name="alwaysEnabled"> Always Enabled </paper-item>
<paper-item name="enabled"> Enabled </paper-item>
<paper-item name="disabled"> Disabled </paper-item>
</core-menu>
</paper-dropdown>
<div class="layout horizontal center wrap justified">
<paper-dropdown-menu class=flex label="Enable Feature" style="flex-basis: 150px; max-width: 200px;">
<dicecloud-selector selected={{enabledSelection}} class="dropdown-content enabled-dropdown">
<paper-item name="alwaysEnabled" style="width: 150px;">
Always Enabled
</paper-item>
<paper-item name="enabled">
Enabled
</paper-item>
<paper-item name="disabled">
Disabled
</paper-item>
</dicecloud-selector>
</paper-dropdown-menu>
<div layout horizontal center class="sideMargin">
<div>Limit Uses: </div>
<paper-toggle-button id="limitUseCheck"
class="sideMargin"
checked={{usesSet}}
role="button"
aria-pressed="false"
tabindex="0"
touch-action="pan-y">
</paper-toggle-button>
</div>
<paper-toggle-button id="limitUseCheck" checked={{usesSet}} style="margin: 0 16px; height: 62px;">
Limit uses
</paper-toggle-button>
{{#if usesSet}}
<paper-input flex id="usesInput" label="Uses" floatinglabel value={{uses}}></paper-input>
<paper-input id="usesInput" type="number" allowed-pattern="[0-9]" class="flex"
label="Uses" value={{uses}} style="flex-basis: 100px; max-width: 200px">
</paper-input>
{{else}}
<div class="flex" style="flex-basis: 100px; max-width: 200px"></div>
{{/if}}
</div>
<hr class="vertMargin">
<!--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>
<paper-textarea label="Description" id="featureDescriptionInput" value={{description}}></paper-textarea>
{{> effectsEditList parentId=_id parentCollection="Features" charId=charId name=name enabled=enabled}}
{{> proficiencyEditList parentId=_id parentCollection="Features" charId=charId enabled=enabled}}

View File

@@ -11,7 +11,7 @@ Template.featureDialog.events({
"tap #deleteButton": function(event, instance){
Features.softRemoveNode(instance.data.featureId);
GlobalUI.deletedToast(instance.data.featureId, "Features", "Feature");
GlobalUI.closeDetail();
popDialogStack();
},
});
@@ -31,11 +31,11 @@ Template.featureDetails.helpers({
});
Template.featureDetails.events({
"tap .useFeature": function(event){
"click .useFeature": function(event){
var featureId = this._id;
Features.update(featureId, {$inc: {used: 1}});
},
"tap .resetFeature": function(event){
"click .resetFeature": function(event){
var featureId = this._id;
Features.update(featureId, {$set: {used: 0}});
},
@@ -46,10 +46,6 @@ Template.featureDetails.events({
},
});
Template.featureEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.featureEdit.helpers({
usesSet: function(){
return _.isString(this.uses);
@@ -67,32 +63,60 @@ Template.featureEdit.helpers({
},
});
const debounce = (f) => _.debounce(f, 300);
Template.featureEdit.events({
"change #featureNameInput": function(event){
var name = Template.instance().find("#featureNameInput").value;
Features.update(this._id, {$set: {name: name}});
},
"change #featureDescriptionInput": function(event){
var description = Template.instance().find("#featureDescriptionInput").value;
Features.update(this._id, {$set: {description: description}});
},
"change #limitUseCheck": function(event){
"input #featureNameInput": debounce(function(event){
const input = event.currentTarget;
var name = input.value;
if (!name){
input.invalid = true;
input.errorMessage = "Name is required";
} else {
input.invalid = false;
Features.update(this._id, {
$set: {name: name}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}
}),
"input #featureDescriptionInput": debounce(function(event){
var description = event.currentTarget.value;
Features.update(this._id, {
$set: {description: description}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #limitUseCheck": debounce(function(event){
var currentUses = this.uses;
var featureId = this._id;
if (event.target.checked && !_.isString(currentUses)){
Features.update(featureId, {$set: {uses: ""}}, {removeEmptyStrings: false});
Features.update(featureId, {
$set: {uses: ""}
}, {
removeEmptyStrings: false
});
} else if (!event.target.checked && _.isString(currentUses)){
Features.update(featureId, {$unset: {uses: ""}});
Features.update(featureId, {
$unset: {uses: ""}
});
}
},
"change #usesInput, input #quantityInput": function(event){
var value = event.target.value;
}),
"input #usesInput, input #quantityInput": debounce(function(event){
var value = event.currentTarget.value;
var featureId = this._id;
Features.update(featureId, {$set: {uses: value}});
},
"core-select #enabledDropdown": function(event){
Features.update(featureId, {
$set: {uses: value}
}, {
removeEmptyStrings: false,
});
}),
"iron-select .enabled-dropdown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
var setter;
if (value === "enabled"){

View File

@@ -2,14 +2,6 @@
cursor: pointer;
}
.features {
display: flex !important;
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
padding: 4px;
}
.featureCardTop {
margin-bottom: 8px;
}
@@ -18,7 +10,7 @@
white-space: pre-line;
}
.resourceCards paper-shadow.healthCard {
.resourceCards paper-material.healthCard {
width: 100%;
}

View File

@@ -1,44 +1,41 @@
<template name="features">
<div fit>
<div class="scroll-y" fit>
<div class="column-container">
<!--expertiseDice-->
{{>resource name="expertiseDice" title="Expertise Dice" color="teal" char=this}}
<!--ki-->
{{>resource name="ki" title="Ki Points" color="teal" char=this}}
<!--rages-->
{{>resource name="rages" title="Rages" color="teal" char=this}}
<!--sorceryPoints-->
{{>resource name="sorceryPoints" title="Sorcery Points" color="teal" char=this}}
<!--superiorityDice-->
{{>resource name="superiorityDice" title="Superiority Dice" color="teal" char=this}}
<div class="features">
<div class="column-container animation-slider">
<!--expertiseDice-->
{{>resource name="expertiseDice" title="Expertise Dice" color="teal" char=this}}
<!--ki-->
{{>resource name="ki" title="Ki Points" color="teal" char=this}}
<!--rages-->
{{>resource name="rages" title="Rages" color="teal" char=this}}
<!--sorceryPoints-->
{{>resource name="sorceryPoints" title="Sorcery Points" color="teal" char=this}}
<!--superiorityDice-->
{{>resource name="superiorityDice" title="Superiority Dice" color="teal" char=this}}
<!--Attacks-->
<div>
<paper-shadow class="card">
<!--Attacks-->
<div>
<paper-material class="card">
<div class="top white">
Attacks
</div>
<div class="bottom list">
{{#each attacks}}
<div class="item-slot">
<div class="flexible attack item"
hero-id="main" {{detailHero}}>
<div layout horizontal>
<div class="headline"
style="margin-right: 16px;"
layout horizontal center>
<div class="flexible attack item">
<div class="layout horizontal">
<div class="paper-font-headline layout horizontal center"
style="margin-right: 16px;">
{{evaluateSigned ../_id attackBonus}}
</div>
<div flex layout vertical>
<div class="body2">
<div class="flex layout vertical">
<div class="paper-font-body2">
{{name}}
</div>
<div>
{{evaluateString ../_id damage}}&nbsp;{{damageType}}
</div>
{{#if details}}
<div class="caption">
<div>
{{details}}
</div>
{{/if}}
@@ -48,47 +45,44 @@
</div>
{{/each}}
</div>
</paper-shadow>
</div>
</paper-material>
</div>
<!--Proficiencies-->
<div>
<paper-shadow class="card">
<!--Proficiencies-->
<div>
<paper-material class="card">
<div class="white top">
Proficiencies
</div>
<div flex class="bottom list">
{{#if weaponProfs.count}}
<div class="subhead">Weapons</div>
<div class="paper-font-subhead">Weapons</div>
{{/if}}
{{#each weaponProfs}}
{{> proficiencyListItem}}
{{/each}}
{{#if armorProfs.count}}
<div class="subhead">Armor</div>
<div class="paper-font-subhead">Armor</div>
{{/if}}
{{#each armorProfs}}
{{> proficiencyListItem}}
{{/each}}
{{#if toolProfs.count}}
<div class="subhead">Tools</div>
<div class="paper-font-subhead">Tools</div>
{{/if}}
{{#each toolProfs}}
{{> proficiencyListItem}}
{{/each}}
</div>
</paper-shadow>
</div>
</paper-material>
</div>
<!--features-->
{{#each features}}
<div>
<paper-shadow class="card featureCard"
hero-id="main" {{detailHero}}>
<div class="top {{colorClass}} subhead"
layout horizontal
hero-id="toolbar" {{detailHero}}>
<div flex hero-id="title" {{detailHero}}>
<!--features-->
{{#each features}}
<div>
<paper-material class="card featureCard" data-id={{_id}}>
<div class="top {{colorClass}} paper-font-subhead layout horizontal">
<div class="flex">
{{name}}
</div>
{{#if hasUses}}
@@ -97,22 +91,22 @@
</div>
{{/if}}
{{#if canEnable}}
<core-tooltip label="Feature enabled"
position="left">
<div>
<paper-checkbox class="enabledCheckbox"
checked={{enabled}}
disabled={{#unless canEditCharacter charId}}true{{/unless}}>
</paper-checkbox>
</core-tooltip>
<paper-tooltip position="left">Feature enabled</paper-tooltip>
</div>
{{/if}}
</div>
{{#if description}}
<div flex class="bottom">
{{#markdown}}{{evaluateString charId shortDescription}}{{/markdown}}
<div class="bottom flex">
{{#markdown}}{{evaluateShortString charId description}}{{/markdown}}
</div>
{{/if}}
{{#if hasUses}}
<div layout horizontal center end-justified>
<div class="layout horizontal center end-justified">
<paper-button class="useFeature"
disabled={{noUsesLeft}}>
Use
@@ -123,21 +117,16 @@
</paper-button>
</div>
{{/if}}
</paper-shadow>
</div>
{{/each}}
</div>
<div class="fab-buffer"></div>
</paper-material>
</div>
{{/each}}
</div>
{{#if canEditCharacter _id}}
<paper-fab id="addFeature"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
aria-label="Add"
hero-id="main"></paper-fab>
icon="add">
<paper-tooltip position="left">Add Feature</paper-tooltip>
</paper-fab>
{{/if}}
</div>
</template>
@@ -145,12 +134,8 @@
<template name="resource">
{{#if characterCalculate "attributeBase" char._id name}}
<div>
<paper-shadow class="card"
hero-id="main" {{detailHero name char._id}}
layout horizontal>
<div class="left {{getColor}} display1 white-text"
hero-id="toolbar" {{detailHero name char._id}}
layout horizontal center>
<paper-material class="card layout horizontal">
<div class="left {{getColor}} paper-font-display1 white-text layout horizontal center">
<div style="margin-right: 8px;">
<paper-icon-button class="resourceUp"
icon="arrow-drop-up"
@@ -164,11 +149,10 @@
<div>{{characterCalculate "attributeValue" char._id name}}</div>
<!--<div>/{{char.attributeBase name}}</div>-->
</div>
<div class="right clickable"
flex layout horizontal center>
<div class="right clickable flex layout horizontal center">
{{title}}
</div>
</paper-shadow>
</paper-material>
</div>
{{/if}}
</template>

View File

@@ -3,11 +3,6 @@ Template.features.helpers({
var features = Features.find({charId: this._id}, {sort: {color: 1, name: 1}});
return features;
},
shortDescription: function() {
if (_.isString(this.description)){
return this.description.split(/^( *[-*_]){3,} *(?:\n+|$)/m)[0];
}
},
hasUses: function(){
return this.usesValue() > 0;
},
@@ -43,54 +38,45 @@ Template.features.helpers({
});
Template.features.events({
"tap #addFeature": function(event){
"click #addFeature": function(event, instance){
var featureId = Features.insert({
name: "New Feature",
charId: this._id,
enabled: true,
alwaysEnabled: true,
});
GlobalUI.setDetail({
pushDialogStack({
template: "featureDialog",
data: {featureId: featureId, charId: this._id, startEditing: true},
heroId: featureId,
element: event.currentTarget,
returnElement: () => instance.find(`.featureCard[data-id='${featureId}']`),
});
},
"tap #addAttackButton": function(event){
var charId = this._id;
Attacks.insert({
charId: charId
}, function(error, id){
if (!error){
GlobalUI.setDetail({
template: "attackDialog",
data: {attackId: id, charId: charId},
heroId: id,
});
}
});
},
"tap .featureCard .top": function(event){
"click .featureCard .top": function(event){
var featureId = this._id;
var charId = Template.parentData()._id;
GlobalUI.setDetail({
pushDialogStack({
template: "featureDialog",
data: {featureId: featureId, charId: charId},
heroId: featureId,
element: event.currentTarget.parentElement,
});
},
"tap .attack": function(event){
openParentDialog(this.parent, this.charId, this._id);
"click .attack": function(event){
openParentDialog({
parent: this.parent,
charId: this.charId,
element: event.currentTarget,
});
},
"tap .useFeature": function(event){
"click .useFeature": function(event){
var featureId = this._id;
Features.update(featureId, {$inc: {used: 1}});
},
"tap .resetFeature": function(event){
"click .resetFeature": function(event){
var featureId = this._id;
Features.update(featureId, {$set: {used: 0}});
},
"tap .enabledCheckbox": function(event){
"click .enabledCheckbox": function(event){
event.stopPropagation();
},
"change .enabledCheckbox": function(event){
@@ -122,7 +108,7 @@ Template.resource.helpers({
});
Template.resource.events({
"tap .resourceUp": function(event){
"click .resourceUp": function(event){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var base = Characters.calculate.attributeBase(this.char._id, this.name);
if (value < base){
@@ -131,7 +117,7 @@ Template.resource.events({
Characters.update(this.char._id, modifier, {validate: false});
}
},
"tap .resourceDown": function(event){
"click .resourceDown": function(event){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
if (value > 0){
var modifier = {$inc: {}};
@@ -139,11 +125,11 @@ Template.resource.events({
Characters.update(this.char._id, modifier, {validate: false});
}
},
"tap .right": function(event, instance) {
GlobalUI.setDetail({
"click .right": function(event, instance) {
pushDialogStack({
template: "attributeDialog",
data: {name: this.title, statName: this.name, charId: this.char._id},
heroId: this.char._id + this.name,
element: event.currentTarget.parentElement,
});
},
});

View File

@@ -0,0 +1,15 @@
.carryCapacityBar {
background-color: #7DC580;
background-color: rgba(255,255,255,0.27);
position: relative;
height: 4px;
}
.carryCapacityBar div{
height: 100%;
position: absolute;
}
.carryCapacityBar .tick {
border-right: solid 2px #E5E5E5;
border-right-color: rgba(255,255,255,0.54);
}

View File

@@ -1,14 +0,0 @@
.carryCapacityBar {
background-color: #7DC580;
background-color: rgba(255,255,255,0.27);
position: relative;
height: 4px;
div{
height: 100%;
position: absolute;
}
.tick {
border-right: solid 2px #E5E5E5;
border-right-color: rgba(255,255,255,0.54);
}
}

View File

@@ -1,17 +1,17 @@
<template name="carryDialog">
{{#baseDialog title="Weight Carried" class=color hideEdit=true}}
<div layout horizontal center-justified end>
<div class="display2">
<div class="layout horizontal center-justified end">
<div class="paper-font-display2">
{{round carriedWeight 1}}
</div>
<div class="display1">
<div class="paper-font-display1">
lbs
</div>
</div>
<hr class="vertMargin">
{{> carryCapacityTable}}
{{/baseDialog}}
</template>
</template>

View File

@@ -11,32 +11,26 @@
<template name="containerEdit">
<paper-input id="containerNameInput"
label="Name"
floatinglabel
value={{name}}></paper-input>
<div layout horizontal around-justified wrap>
<paper-input-decorator label="Weight" floatinglabel>
<input id="weightInput" type="number" value={{weight}}>
</paper-input-decorator>
<paper-input-decorator label="Value" floatinglabel>
<input id="valueInput" type="number" value={{value}}>
</paper-input-decorator>
<div class="layout horizontal around-justified wrap">
<paper-input id="weightInput" label="Weight" type="number" value={{weight}}>
</paper-input>
<paper-input id="valueInput" label="Value" type="number" value={{value}}>
</paper-input>
</div>
<hr class="vertMargin">
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="containerDescriptionInput" placeholder aria-label="Description" value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-textarea label="Description" id="containerDescriptionInput" value={{description}}>
</paper-textarea>
</template>
<template name="containerView">
<div layout horizontal wrap center justified>
<div class="layout horizontal wrap center justified">
<table class="summaryTable fullwidth">
<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 class="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>
</div>
{{#if description}}

View File

@@ -14,30 +14,44 @@ Template.containerDialog.events({
instance.data.containerId,
"Containers", "Container and contents"
);
GlobalUI.closeDetail();
popDialogStack();
},
});
Template.containerEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.containerEdit.events({
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
"change #containerNameInput": function(event){
"input #containerNameInput": function(event){
var name = Template.instance().find("#containerNameInput").value;
Containers.update(this._id, {$set: {name: name}});
Containers.update(this._id, {
$set: {name: name}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
},
"change #weightInput, input #weightInput": function(event){
var weight = +Template.instance().find("#weightInput").value;
Containers.update(this._id, {$set: {weight: weight}});
Containers.update(this._id, {
$set: {weight: weight}
}, {
removeEmptyStrings: false,
});
},
"change #valueInput, input #valueInput": function(event){
var value = +Template.instance().find("#valueInput").value;
Containers.update(this._id, {$set: {value: value}});
Containers.update(this._id, {
$set: {value: value}
}, {
removeEmptyStrings: false,
});
},
"change #containerDescriptionInput": function(event, instance){
"input #containerDescriptionInput": function(event, instance){
var description = instance.find("#containerDescriptionInput").value;
Containers.update(this._id, {$set: {description: description}});
Containers.update(this._id, {
$set: {description: description}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
},
});

View File

@@ -1,169 +1,160 @@
<template name="inventory">
<div fit>
<div id="inventory" class="scroll-y" fit>
<div class="column-container">
<!--Net Worth-->
<div>
<paper-shadow class="card">
<div class="white top" layout horizontal center>
<div class="subhead" flex>
Net Worth
</div>
<div>
{{valueString netWorth}}
</div>
<div id="inventory" class="animation-slider">
<div class="column-container">
<!--Net Worth-->
<div>
<paper-material class="card">
<div class="white top layout horizontal center">
<div class="paper-font-subhead flex">
Net Worth
</div>
</paper-shadow>
</div>
<!--Weight Carried-->
<div>
<paper-shadow class="card"
hero-id="main" {{detailHero "weightCarried" _id}}>
<div class="top green white-text weightCarried"
hero-id="toolbar" {{detailHero "weightCarried" _id}}
layout horizontal center>
<div class="subhead" flex>
Weight Carried
</div>
<div>
{{round weightCarried}}lbs
</div>
</div>
<div class="bottom green" style="padding: 0;">
{{> carryCapacityBar}}
</div>
{{#if encumberedBuffs.count}}
<div class="bottom list">
{{#each encumberedBuffs}}
<div class="item-slot">
<div class="item buff"
hero-id="main" {{detailHero}}
layout horizontal center>
<div flex>
<core-icon icon="work"
style="margin-right: 16px">
</core-icon>
{{name}}
</div>
</div>
</div>
{{/each}}
</div>
{{/if}}
</paper-shadow>
</div>
<!--Equipment-->
<div>
<paper-shadow class="card equipmentContainer">
<div class="white top" layout horizontal center>
<div class="subhead" flex>
Equipment
</div>
<div class="caption" style="margin-right: 8px">
{{valueString equipmentValue}}
</div>
<div class="caption">
{{round equipmentWeight}}lbs
</div>
</div>
<div flex class="bottom list">
{{#if attuned.count}}
<div class="subhead">Attuned</div>
{{/if}}
{{#each attuned}}
{{>inventoryItem}}
{{/each}}
{{#if attuned.count}}
<div class="subhead">Equipment</div>
{{/if}}
{{#each equipment}}
{{>inventoryItem}}
{{/each}}
</div>
</paper-shadow>
</div>
<!--Carried Items-->
<div>
<paper-shadow class="card carriedContainer">
<div class="white top" layout horizontal center>
<div class="subhead" flex>
Carried
</div>
<div class="caption" style="margin-right: 8px">
{{valueString carriedValue}}
</div>
<div class="caption">
{{round carriedWeight}}lbs
</div>
</div>
<div flex class="bottom list">
{{#each carriedItems}}
{{>inventoryItem}}
{{/each}}
</div>
</paper-shadow>
</div>
{{#each containers}}
<div>
<paper-shadow class="card itemContainer"
hero-id="main" {{detailHero}}>
<div class="top {{colorClass}}"
hero-id="toolbar" {{detailHero}}
layout horizontal center>
<div class="subhead" flex
hero-id="title" {{detailHero}}>
{{valueString netWorth}}
</div>
</div>
</paper-material>
</div>
<!--Weight Carried-->
<div>
<paper-material class="card">
<div class="top green white-text weightCarried layout horizontal center">
<div class="paper-font-subhead" flex>
Weight Carried
</div>
<div>
{{round weightCarried}}lbs
</div>
</div>
<div class="bottom green" style="padding: 0;">
{{> carryCapacityBar}}
</div>
{{#if encumberedBuffs.count}}
<div class="bottom list">
{{#each encumberedBuffs}}
<div class="item-slot">
<div class="item buff layout horizontal center">
<div class="flex">
<iron-icon icon="work"
style="margin-right: 16px">
</iron-icon>
{{name}}
</div>
<div class="caption" style="margin-right: 8px">
{{valueString totalValue}}
</div>
<div class="caption" style="margin-right: 8px">
{{round totalWeight}}lbs
</div>
<core-tooltip label="Container carried" position="left">
<paper-checkbox class="carriedCheckbox"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
checked={{isCarried}}>
</paper-checkbox>
</core-tooltip>
</div>
<div class="bottom list">
{{#each items ../_id _id}}
{{>inventoryItem}}
{{/each}}
</div>
</paper-shadow>
</div>
{{/each}}
{{/each}}
</div>
{{/if}}
</paper-material>
</div>
<div class="fab-buffer"></div>
<!--Equipment-->
<div>
<paper-material class="card equipmentContainer">
<div class="white top layout horizontal center">
<div class="paper-font-subhead flex">
Equipment
</div>
<div class="paper-font-caption" style="margin-right: 8px">
{{valueString equipmentValue}}
</div>
<div class="paper-font-caption">
{{round equipmentWeight}}lbs
</div>
</div>
<div flex class="bottom list">
{{#if attuned.count}}
<div class="paper-font-subhead">Attuned</div>
{{/if}}
{{#each attuned}}
{{>inventoryItem}}
{{/each}}
{{#if attuned.count}}
<div class="paper-font-subhead">Equipment</div>
{{/if}}
{{#each equipment}}
{{>inventoryItem}}
{{/each}}
</div>
</paper-material>
</div>
<!--Carried Items-->
<div>
<paper-material class="card carriedContainer">
<div class="white top layout horizontal center">
<div class="paper-font-subhead flex">
Carried
</div>
<div class="paper-font-caption" style="margin-right: 8px">
{{valueString carriedValue}}
</div>
<div class="paper-font-caption">
{{round carriedWeight}}lbs
</div>
</div>
<div flex class="bottom list">
{{#each carriedItems}}
{{>inventoryItem}}
{{/each}}
</div>
</paper-material>
</div>
{{#each containers}}
<div>
<paper-material class="card itemContainer" data-id={{_id}}>
<div class="top {{colorClass}} layout horizontal center">
<div class="paper-font-subhead flex">
{{name}}
</div>
<div class="paper-font-caption" style="margin-right: 8px">
{{valueString totalValue}}
</div>
<div class="paper-font-caption" style="margin-right: 8px">
{{round totalWeight}}lbs
</div>
<div>
<paper-checkbox class="carriedCheckbox"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
checked={{isCarried}}>
</paper-checkbox>
<paper-tooltip position="left"> Container carried</paper-tooltip>
</div>
</div>
<div class="bottom list">
{{#each items ../_id _id}}
{{>inventoryItem}}
{{/each}}
</div>
</paper-material>
</div>
{{/each}}
</div>
{{#if canEditCharacter _id}}
{{#fabMenu}}
<core-tooltip label="New container" position="left">
<paper-fab icon="work"
class="addContainer"
mini>
</paper-fab>
</core-tooltip>
<core-tooltip label="New item" position="left">
<paper-fab icon="note-add"
class="addItem"
mini>
</paper-fab>
</core-tooltip>
{{/fabMenu}}
{{/if}}
<div class="fab-buffer"></div>
</div>
{{#if canEditCharacter _id}}
{{#fabMenu}}
<div>
<paper-fab icon="work"
class="addContainer"
mini>
</paper-fab>
<paper-tooltip position="left"> New container </paper-tooltip>
</div>
<div>
<paper-fab icon="note-add"
class="addItem"
mini>
</paper-fab>
<paper-tooltip position="left"> New item </paper-tooltip>
</div>
{{/fabMenu}}
{{/if}}
</template>
<template name="inventoryItem">
<div class="item-slot">
<div class="item {{hidden}} inventoryItem"
hero-id="main" {{detailHero}}
layout horizontal center
draggable={{canEditCharacter charId}}>
<div flex class="itemName">
<div class="item {{hidden}} inventoryItem layout horizontal center"
draggable={{canEditCharacter charId}}
data-id={{_id}}>
<div class="itemName flex">
{{#if ne1 quantity}}{{quantity}}&nbsp;{{/if}}{{pluralName}}
</div>
{{#if settings.showIncrement}}{{#if canEditCharacter charId}}

View File

@@ -91,9 +91,11 @@ Template.inventory.helpers({
},
equipmentWeight: function(){
var weight = 0;
Items.find({charId: this._id, enabled: true},
{fields: {weight : 1, quantity: 1}}
).forEach(function(item){
Items.find({
charId: this._id, enabled: true,
}, {
fields: {weight : 1, quantity: 1}
}).forEach(function(item){
weight += item.totalWeight();
});
return weight;
@@ -121,101 +123,88 @@ Template.inventory.helpers({
});
Template.inventory.events({
"tap .addItem": function(event){
"click .addItem": function(event, instance){
var charId = this._id;
Items.insert({
var itemId = Items.insert({
charId: charId,
parent:{
id: charId,
collection: "Characters",
},
}, function(err, itemId){
if (err) throw err;
GlobalUI.setDetail({
template: "itemDialog",
data: {itemId: itemId, charId: charId, startEditing: true},
heroId: itemId,
});
});
pushDialogStack({
template: "itemDialog",
data: {itemId: itemId, charId: charId, startEditing: true},
element: event.currentTarget,
returnElement: () => $(`[data-id='${itemId}']`).get(0),
});
},
"tap .addContainer": function(event){
"click .addContainer": function(event, instance){
var containerId = Containers.insert({
name: "New Container",
isCarried: true,
charId: this._id,
});
GlobalUI.setDetail({
pushDialogStack({
template: "containerDialog",
data: {
containerId: containerId,
charId: this.charId,
startEditing: true,
},
heroId: containerId,
element: event.currentTarget,
returnElement: instance.find(`.itemContainer[data-id='${containerId}']`),
});
},
"tap .weightCarried": function(event) {
"click .weightCarried": function(event, instance) {
var charId = this._id;
GlobalUI.setDetail({
pushDialogStack({
template: "carryDialog",
data: {charId: charId, color: "green"},
heroId: charId + "weightCarried",
element: event.currentTarget.parentElement,
});
},
"tap .buff": function(event){
"click .buff": function(event, instance){
var buffId = this._id;
var charId = Template.parentData()._id;
GlobalUI.setDetail({
pushDialogStack({
template: "buffDialog",
data: {buffId: buffId, charId: charId},
heroId: buffId,
element: event.currentTarget,
});
},
"tap .inventoryItem": function(event){
"click .inventoryItem": function(event, instance){
var itemId = this._id;
var charId = Template.parentData()._id;
GlobalUI.setDetail({
pushDialogStack({
template: "itemDialog",
data: {itemId: itemId, charId: charId},
heroId: itemId,
element: event.currentTarget,
returnElement: () => $(`[data-id='${itemId}']`).get(0),
});
},
"hold .inventoryItem": function(event, instance) {
var itemId = this._id;
var charId = Template.parentData()._id;
var containerId = this.parent.id;
GlobalUI.showDialog({
template: "moveItemDialog",
data: {
charId: charId,
itemId: itemId,
containerId: containerId,
},
heading: "Move " + this.pluralName(),
});
},
"tap .incrementButtons": function(event) {
"click .incrementButtons": function(event, instance) {
event.stopPropagation();
},
"tap .addItemQuantity": function(event) {
"click .addItemQuantity": function(event, instance) {
var itemId = this._id;
Items.update(itemId, {$set: {quantity: this.quantity + 1}});
},
"tap .subItemQuantity": function(event) {
"click .subItemQuantity": function(event, instance) {
var itemId = this._id;
Items.update(itemId, {$set: {quantity: this.quantity - 1}});
},
"tap .itemContainer .top": function(event){
GlobalUI.setDetail({
"click .itemContainer .top": function(event, instance){
pushDialogStack({
template: "containerDialog",
data: {containerId: this._id, charId: this.charId},
heroId: this._id,
element: event.currentTarget.parentElement,
});
},
"tap .carriedCheckbox": function(event){
"click .carriedCheckbox": function(event, instance){
event.stopPropagation();
},
"change .carriedCheckbox": function(event){
"change .carriedCheckbox": function(event, instance){
var carried;
if (this.isCarried) carried = false;
else carried = true;
@@ -271,7 +260,7 @@ Template.layout.events({
var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
if (event.ctrlKey){
//split the stack to the container
GlobalUI.showDialog({
pushDialogStack({
template: "splitStackDialog",
data: {
id: itemId,
@@ -294,12 +283,11 @@ Template.layout.events({
var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
if (event.ctrlKey){
//split the stack to the container
GlobalUI.showDialog({
pushDialogStack({
template: "splitStackDialog",
data: {
id: itemId,
parentCollection: "Characters",
parentId: this._id,
},
});
} else {
@@ -312,7 +300,7 @@ Template.layout.events({
var itemId = event.originalEvent.dataTransfer.getData("dicecloud-id/items");
if (event.ctrlKey){
//split the stack to the container
GlobalUI.showDialog({
pushDialogStack({
template: "splitStackDialog",
data: {
id: itemId,

View File

@@ -9,11 +9,11 @@
</template>
<template name="itemDetails">
<div layout horizontal wrap center justified class="headline">
<div class="paper-font-headline layout horizontal wrap center justified">
{{#if weight}}<div class="sideMargin">{{round totalWeight}}lbs</div>{{/if}}
{{#if value}}<div>{{valueString totalValue}}</div>{{/if}}
</div>
<div layout horizontal wrap class="caption">
<div class="paper-font-caption layout horizontal wrap">
{{#if enabled}}<div class="vertMargin" style="margin-right: 16px">Equipped</div>{{/if}}
{{#if requiresAttunement}}<div class="vertMargin">Requires Attunement</div>{{/if}}
</div>
@@ -26,74 +26,47 @@
</template>
<template name="itemEdit">
<paper-input class="fullwidth" id="itemNameInput" label="Name" floatinglabel value={{name}}></paper-input>
<div layout horizontal wrap>
<paper-input-decorator label="Quantity"
floatinglabel
style="width: 80px">
<input id="quantityInput"
type="number"
value={{quantity}}>
</paper-input-decorator>
<paper-input class="fullwidth" id="itemNameInput" label="Name" value={{name}}></paper-input>
<div class="layout horizontal center wrap">
<paper-input id="quantityInput" type="number" label="Quantity" style="width: 80px" value={{quantity}}>
</paper-input>
{{# if ne1 quantity}}
<paper-input flex id="itemPluralInput"
label="Plural Name"
floatinglabel
value={{plural}}></paper-input>
<paper-input class="flex" id="itemPluralInput" label="Plural Name" value={{plural}} style="flex-basis: 182px;">
</paper-input>
{{else}}
<div class="flex" style="flex-basis: 182px;">
</div>
{{/if}}
</div>
<div center horizontal layout>
<div class="padded">Show increment buttons</div>
<paper-checkbox id="incrementCheckbox"
checked={{settings.showIncrement}}>
<paper-checkbox id="incrementCheckbox" checked={{settings.showIncrement}}>
Show increment buttons
</paper-checkbox>
</div>
<hr class="vertMargin">
<div layout horizontal wrap justified>
<div center horizontal layout>
<div class="padded">Container</div>
{{> containerDropdown}}
</div>
<div center horizontal layout>
<div class="padded">Equipped</div>
<paper-toggle-button id="equippedInput"
checked={{enabled}}
role="button"
aria-pressed="false"
tabindex="0"
touch-action="pan-y">
</paper-toggle-button>
</div>
<div center horizontal layout>
<div class="padded">Requires Attunement</div>
<paper-checkbox id="attunementCheckbox"
checked={{requiresAttunement}}>
</paper-checkbox>
</div>
<div class="layout horizontal center wrap justified" style="margin-top: 16px;">
{{> containerDropdown}}
<paper-toggle-button id="equippedInput" checked={{enabled}}>
Equipped
</paper-toggle-button>
<paper-checkbox id="attunementCheckbox" checked={{requiresAttunement}}>
Requires Attunement
</paper-checkbox>
</div>
<hr class="vertMargin">
<div layout horizontal around-justified>
<paper-input-decorator label="Weight Each (lbs)" floatinglabel>
<input id="weightInput" type="number" value={{weight}}>
</paper-input-decorator>
<div class="layout horizontal around-justified" style="margin-top: 16px;">
<paper-input id="weightInput" type="number" value={{weight}} label="Weight Each (lbs)">
</paper-input>
<!--Value-->
<paper-input-decorator label="Value Each (GP)" floatinglabel>
<input id="valueInput" type="number" value={{value}}>
</paper-input-decorator>
<paper-input id="valueInput" type="number" value={{value}} label="Value Each (GP)">
</paper-input>
</div>
<hr class="vertMargin">
<!--Description-->
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="itemDescriptionInput" placeholder aria-label="Description" value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-textarea id="itemDescriptionInput" label="Description" value={{description}}>
<div suffix>
<paper-tooltip position="left" animation-delay="0">This field accepts formulae in {curly brackets}</paper-tooltip>
<iron-icon icon="dicecloud:code-braces"></iron-icon>
</div>
</paper-textarea>
<!--Effects-->
{{> effectsEditList parentId=_id parentCollection="Items" charId=charId enabled=equipped name=name}}
<!--Attacks-->
@@ -101,13 +74,11 @@
</template>
<template name="containerDropdown">
<paper-dropdown-menu id="containerDropDown" label="Container">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{parent.id}}>
{{#each containers}}
<paper-item name={{_id}} class="containerMenuItem">{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
<paper-dropdown-menu label="Container">
<dicecloud-selector class="dropdown-content" id="containerDropDown" selected={{parent.id}}>
{{#each containers}}
<paper-item name={{_id}} class="containerMenuItem">{{name}}</paper-item>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
</template>

View File

@@ -27,60 +27,95 @@ Template.itemDialog.helpers({
});
Template.itemDialog.events({
"tap #editButton": function(event, instance){
"click #editButton": function(event, instance){
instance.editing.set(true);
},
"tap #doneEditingButton": function(event, instance){
"click #doneEditingButton": function(event, instance){
instance.editing.set(false);
},
"color-change": function(event, instance){
Items.update(instance.data.itemId, {$set: {color: event.color}});
},
"tap #deleteButton": function(event, instance){
"click #deleteButton": function(event, instance){
Items.softRemoveNode(instance.data.itemId);
GlobalUI.deletedToast(instance.data.itemId, "Items", "Item");
GlobalUI.closeDetail();
popDialogStack();
},
});
Template.itemEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.itemEdit.helpers({
ne1: function(num){
return num != 1;
},
});
const debounce = (f) => _.debounce(f, 200);
Template.itemEdit.events({
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
"change #itemNameInput": function(event){
var name = Template.instance().find("#itemNameInput").value;
Items.update(this._id, {$set: {name: name}});
},
"change #itemPluralInput": function(event){
var plural = Template.instance().find("#itemPluralInput").value;
Items.update(this._id, {$set: {plural: plural}});
},
"change #quantityInput": function(event){
var quantity = +Template.instance().find("#quantityInput").value;
Items.update(this._id, {$set: {quantity: quantity}});
},
"change #weightInput": function(event){
var weight = +Template.instance().find("#weightInput").value;
Items.update(this._id, {$set: {weight: weight}});
},
"change #valueInput": function(event){
var value = +Template.instance().find("#valueInput").value;
Items.update(this._id, {$set: {value: value}});
},
"change #itemDescriptionInput": function(event){
var description = Template.instance().find("#itemDescriptionInput").value;
Items.update(this._id, {$set: {description: description}});
},
"input #itemNameInput": debounce(function(event, instance){
const input = event.currentTarget;
var name = input.value;
if (!name){
input.invalid = true;
input.errorMessage = "Name is required";
} else {
input.invalid = false;
Items.update(this._id, {
$set: {name: name}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}
}),
"input #itemPluralInput": debounce(function(event, instance){
var plural = event.currentTarget.value;
Items.update(this._id, {
$set: {plural: plural}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #quantityInput": debounce(function(event, instance){
var quantity = +event.currentTarget.value;
Items.update(this._id, {
$set: {quantity: quantity}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #weightInput": debounce(function(event, instance){
var weight = +event.currentTarget.value;
Items.update(this._id, {
$set: {weight: weight}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #valueInput": debounce(function(event, instance){
var value = +event.currentTarget.value;
Items.update(this._id, {
$set: {value: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #itemDescriptionInput": debounce(function(event, instance){
var description = event.currentTarget.value;
Items.update(this._id, {
$set: {description: description}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #equippedInput": function(event){
var equipped = Template.instance().find("#equippedInput").checked;
var equipped = event.currentTarget.checked;
if (equipped){
Meteor.call("equipItem", this._id, this.charId);
} else {
@@ -104,9 +139,8 @@ Template.containerDropdown.helpers({
});
Template.containerDropdown.events({
"core-select #containerDropDown": function(event){
"iron-select #containerDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var containerId = detail.item.getAttribute("name");
Meteor.call("moveItemToContainer", Template.currentData()._id, containerId);
}

View File

@@ -21,10 +21,10 @@
{{#each containers}}
<paper-item name={{_id}}
layout horizontal center>
<core-icon icon="image:brightness-1"
<iron-icon icon="image:brightness-1"
style="color: {{hexColor color}};
margin-right: 16px;">
</core-icon>
</iron-icon>
<div>{{name}}</div>
</paper-item>
{{/each}}

View File

@@ -1,13 +1,29 @@
<!-- data needs to include id of item, parentCollection, parentId -->
<template name="splitStackDialog">
<div style="width: 300px; height: 110px;">
<paper-input-decorator label="Quantity" floatinglabel>
<input autoFocus id="quantityInput" type="number" value={{quantity}}>
</paper-input-decorator>
<paper-button id="oneButton"> One </paper-button>
<paper-button id="halfButton"> Half </paper-button>
<paper-button id="allButton"> All </paper-button>
<div class="fit layout vertical">
<app-header-layout has-scrolling-region class="feedback flex">
<app-header fixed effects="waterfall">
<app-toolbar>
Split Stack
</app-toolbar>
</app-header>
<div class="form flex">
<paper-input autoFocus label="Quantity" id="quantityInput" type="number" value={{quantity}}>
</paper-input>
<div class="layout horizontal justified">
<paper-button id="oneButton"> One </paper-button>
<paper-button id="halfButton"> Half </paper-button>
<paper-button id="allButton"> All </paper-button>
</div>
</div>
</app-header-layout>
<div class="buttons layout horizontal end-justified">
<paper-button id="cancelButton">
Cancel
</paper-button>
<paper-button id="moveButton">
move
</paper-button>
</div>
</div>
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
<paper-button id="moveButton" affirmative> Move </paper-button>
</template>

View File

@@ -1,3 +1,7 @@
Template.splitStackDialog.onRendered(function(){
this.find("#quantityInput").focus();
});
Template.splitStackDialog.helpers({
quantity: function(){
var item = Items.findOne(this.id);
@@ -6,22 +10,26 @@ Template.splitStackDialog.helpers({
});
Template.splitStackDialog.events({
"tap #moveButton": function(event, instance){
"click #moveButton": function(event, instance){
Meteor.call(
"splitItemToParent",
this.id,
+instance.find("#quantityInput").value,
{collection: this.parentCollection , id: this.parentId}
);
popDialogStack();
},
"tap #oneButton":function(event, instance){
"click #cancelButton": function(event, instance){
popDialogStack();
},
"click #oneButton":function(event, instance){
instance.find("#quantityInput").value = 1;
},
"tap #halfButton":function(event, instance){
"click #halfButton":function(event, instance){
var val = Math.round(Items.findOne(this.id).quantity / 2);
instance.find("#quantityInput").value = val;
},
"tap #allButton":function(event, instance){
"click #allButton":function(event, instance){
instance.find("#quantityInput").value = Items.findOne(this.id).quantity;
},
});

View File

@@ -1,8 +1,8 @@
<template name="classDialog">
{{#with class}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
<div layout vertical center>
<div class="display2">
<div class="layout vertical center">
<div class="paper-font-display2">
{{level}}
</div>
<div>
@@ -14,12 +14,12 @@
{{> proficiencyViewList charId=charId parentId=_id}}
{{else}}
<!--Name-->
<paper-input id="classNameInput" label="Class Name" floatinglabel value={{name}}></paper-input>
<paper-input id="classNameInput" label="Class Name" value={{name}}></paper-input>
<!--Level-->
<paper-input id="levelValueInput" label="Level" floatinglabel value={{level}}></paper-input>
<paper-input id="levelValueInput" label="Level" value={{level}}></paper-input>
<!--Effects-->
{{> effectsEditList parentId=_id parentCollection="Classes" charId=charId}}
{{> proficiencyEditList parentId=_id parentCollection="Classes" charId=charId}}
{{/baseDialog}}
{{/with}}
</template>
</template>

View File

@@ -1,28 +1,35 @@
Template.classDialog.onRendered(function(){
updatePolymerInputs(this);
});
Template.classDialog.events({
"color-change": function(event, instance){
Classes.update(instance.data.classId, {$set: {color: event.color}});
},
"tap #deleteButton": function(event, instance){
Classes.softRemoveNode(instance.data.classId);
GlobalUI.deletedToast(instance.data.classId, "Classes", "Class");
GlobalUI.closeDetail();
},
"change #classNameInput": function(event){
var value = event.currentTarget.value;
Classes.update(this._id, {$set: {name: value}});
},
"change #levelValueInput": function(event){
var value = event.currentTarget.value;
Classes.update(this._id, {$set: {level: value}});
},
});
const debounce = (f) => _.debounce(f, 300);
Template.classDialog.helpers({
class: function(){
return Classes.findOne(this.classId);
}
});
Template.classDialog.events({
"color-change": function(event, instance){
Classes.update(instance.data.classId, {$set: {color: event.color}});
},
"click #deleteButton": function(event, instance){
Classes.softRemoveNode(instance.data.classId);
GlobalUI.deletedToast(instance.data.classId, "Classes", "Class");
popDialogStack();
},
"input #classNameInput, change #classNameInput": debounce(function(event){
var value = event.currentTarget.value;
Classes.update(this._id, {
$set: {name: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #levelValueInput, change #levelValueInput": debounce(function(event){
var value = event.currentTarget.value;
Classes.update(this._id, {
$set: {level: value}
}, {
removeEmptyStrings: false,
});
}),
});

View File

@@ -1,7 +1,7 @@
<template name="experienceDialog">
{{#with experience}}
{{#baseDialog title=name class=color hideColor="true" startEditing=../startEditing}}
<div horizontal layout center-justified class= "display2">
<div class="horizontal layout center-justified paper-font-display2">
{{value}}
</div>
{{#if description}}
@@ -15,18 +15,12 @@
</template>
<template name="experienceEdit">
<div horizontal layout>
<div class="horizontal layout">
<!--Name-->
<paper-input id="experienceNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
<paper-input id="experienceNameInput" label="Name" value={{name}} class="flex"></paper-input>
<!--Value-->
<paper-input-decorator label="Value" floatinglabel>
<input id="valueInput" type="number" value={{value}}>
</paper-input-decorator>
<paper-input id="valueInput" type="number" value={{value}} label="Value"></paper-input>
</div>
<!--Description-->
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="experienceDescriptionInput" placeholder value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-textarea id="experienceDescriptionInput" label="Description" value={{description}}></paper-textarea>
</template>

View File

@@ -1,7 +1,3 @@
Template.experienceEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.experienceDialog.helpers({
experience: function(){
Experiences.findOne(this.experienceId);
@@ -20,21 +16,40 @@ Template.experienceDialog.events({
instance.data.experienceId,
"Experiences", "Experience"
);
GlobalUI.closeDetail();
popDialogStack();
},
});
const debounce = (f) => _.debounce(f, 300);
Template.experienceEdit.events({
"change #experienceNameInput": function(event){
"input #experienceNameInput, change #experienceNameInput":
debounce(function(event){
var value = event.currentTarget.value;
Experiences.update(this._id, {$set: {name: value}});
},
"change #valueInput": function(event){
Experiences.update(this._id, {
$set: {name: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #valueInput, change #valueInput":
debounce(function(event){
var value = +event.currentTarget.value;
Experiences.update(this._id, {$set: {value: value}});
},
"change #experienceDescriptionInput": function(event){
Experiences.update(this._id, {
$set: {value: value}
}, {
removeEmptyStrings: false,
});
}),
"input #experienceDescriptionInput":
debounce(function(event){
var value = event.currentTarget.value;
Experiences.update(this._id, {$set: {description: value}});
},
Experiences.update(this._id, {
$set: {description: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
});

View File

@@ -1,108 +1,91 @@
<template name="journal">
<div fit>
<div id="journal" class="scroll-y" fit>
<div class="column-container">
<!--Experience Table-->
<div><paper-shadow class="card experiencesCard"
hero-id="main" {{detailHero}}>
<div class="top white subhead"
hero-id="toolbar" {{detailHero}}
layout horizontal center>
<div flex>Experience</div>
<div >{{characterCalculate "experience" _id}} XP</div>
<paper-icon-button class="black54" id="addXP" icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}></paper-icon-button>
</div>
<div class="bottom list">
{{#each experiences}}
<div class="item-slot">
<div class="item experience"
hero-id="main" {{detailHero}}
layout horizontal center>
<div flex>{{name}}</div>
<div class="xpValue">{{value}}</div>
</div>
</div>
{{/each}}
</div>
{{#if moreExperiencesOrCollapse}}
<div layout horizontal center end-justified>
<paper-button id="moreExperiences"
disabled={{notMoreExperiences}}>
Load More
</paper-button>
<paper-button id="lessExperiences"
disabled={{cantCollapse}}>
Collapse
</paper-button>
</div>
{{/if}}
</paper-shadow></div>
<!--Class Table-->
<div><paper-shadow class="card"
hero-id="main" {{detailHero}}>
<div class="white top"
hero-id="toolbar" {{detailHero}}
layout horizontal center>
<div flex>
<div class="containerName subhead">
Level {{characterCalculate "level" _id}}
</div>
{{#if nextLevelXP}}
<div class="caption">
Next Level: {{nextLevelXP}}XP
</div>
{{/if}}
</div>
<paper-icon-button class="black54"
id="addClassButton"
icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
</paper-icon-button>
</div>
<div class="bottom list">
<div class="item-slot">
<div class="item race"
hero-id="main" {{detailHero "race" _id}}
layout horizontal center>
{{race}}
</div>
</div>
{{#each classes}}
<div class="item-slot">
<div class="item class"
hero-id="main" {{detailHero}}
layout horizontal center>
{{name}}&nbsp;{{level}}
</div>
</div>
{{/each}}
</div>
</paper-shadow></div>
<!--Notes-->
{{#each notes}}
<div>
<paper-shadow class="card" hero-id="main" {{detailHero}}>
<div class="top {{colorClass}} noteTop subhead"
hero-id="toolbar" {{detailHero}}
layout horizontal center>
{{name}}
</div>
<div class="bottom">{{#markdown}}{{description}}{{/markdown}}</div>
</paper-shadow>
<div class="column-container animation-slider">
<!--Experience Table-->
<div>
<paper-material class="card experiencesCard">
<div class="top white subhead layout horizontal center">
<div class="flex">Experience</div>
<div>{{characterCalculate "experience" _id}} XP</div>
<paper-icon-button class="black54" id="addXP" icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}></paper-icon-button>
</div>
{{/each}}
</div>
<div class="fab-buffer"></div>
<div class="bottom list">
{{#each experiences}}
<div class="item-slot">
<div class="item experience layout horizontal center" data-id={{_id}}>
<div class="flex">{{name}}</div>
<div class="xpValue">{{value}}</div>
</div>
</div>
{{/each}}
</div>
{{#if moreExperiencesOrCollapse}}
<div class="layout horizontal center end-justified">
<paper-button id="moreExperiences" disabled={{notMoreExperiences}}>
Load More
</paper-button>
<paper-button id="lessExperiences" disabled={{cantCollapse}}>
Collapse
</paper-button>
</div>
{{/if}}
</paper-material>
</div>
<!--Class Table-->
<div>
<paper-material class="card">
<div class="white top layout horizontal center">
<div class="flex">
<div class="containerName paper-font-subhead">
Level {{characterCalculate "level" _id}}
</div>
{{#if nextLevelXP}}
<div class="paper-font-caption">
Next Level: {{nextLevelXP}}XP
</div>
{{/if}}
</div>
<paper-icon-button class="black54"
id="addClassButton"
icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
</paper-icon-button>
</div>
<div class="bottom list">
<div class="item-slot">
<div class="item race layout horizontal center">
{{race}}
</div>
</div>
{{#each classes}}
<div class="item-slot">
<div class="item class layout horizontal center" data-id={{_id}}>
{{name}}&nbsp;{{level}}
</div>
</div>
{{/each}}
</div>
</paper-material>
</div>
<!--Notes-->
{{#each notes}}
<div>
<paper-material class="card note" data-id={{_id}}>
<div class="top {{colorClass}} noteTop paper-font-subhead layout horizontal center">
{{name}}
</div>
<div class="bottom">
{{#markdown}}{{evaluateShortString charId description}}{{/markdown}}
</div>
</paper-material>
</div>
{{/each}}
</div>
<div class="fab-buffer"></div>
{{#if canEditCharacter _id}}
<paper-fab id="addNote"
<paper-fab id="addNote"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
hero-id="main"></paper-fab>
title="Add"></paper-fab>
{{/if}}
</template>

View File

@@ -53,101 +53,93 @@ Template.journal.helpers({
});
Template.journal.events({
"tap .noteTop": function(event){
GlobalUI.setDetail({
"click .noteTop": function(event){
pushDialogStack({
template: "noteDialog",
data: {noteId: this._id, charId: this.charId},
heroId: this._id,
element: event.currentTarget.parentElement,
});
},
"tap .experience": function(event){
GlobalUI.setDetail({
"click .experience": function(event){
pushDialogStack({
template: "experienceDialog",
data: {experienceId: this._id, charId: this.charId},
heroId: this._id,
element: event.currentTarget,
});
},
"tap .class": function(event){
GlobalUI.setDetail({
"click .class": function(event){
pushDialogStack({
template: "classDialog",
data: {classId: this._id, charId: this.charId},
heroId: this._id,
element: event.currentTarget,
});
},
"tap .race": function(event){
GlobalUI.setDetail({
"click .race": function(event){
pushDialogStack({
template: "raceDialog",
data: {charId: this._id},
heroId: this._id + "race",
element: event.currentTarget,
});
},
"tap #addNote": function(event){
"click #addNote": function(event, instance){
var charId = this._id;
Notes.insert({
var noteId = Notes.insert({
name: "New Note",
charId: charId,
}, function(error, id){
if (!error){
GlobalUI.setDetail({
template: "noteDialog",
data: {noteId: id, charId: charId, startEditing: true},
heroId: id,
});
}
});
pushDialogStack({
template: "noteDialog",
data: {noteId: noteId, charId: charId, startEditing: true},
element: event.currentTarget,
returnElement: () => instance.find(`.note[data-id='${noteId}']`),
});
},
"tap #addXP": function(event){
"click #addXP": function(event, instance){
var charId = this._id;
Experiences.insert({
var expId = Experiences.insert({
charId: charId
}, function(error, id){
if (!error){
GlobalUI.setDetail({
template: "experienceDialog",
data: {experienceId: id, charId: charId, startEditing: true},
heroId: id,
});
}
});
pushDialogStack({
template: "experienceDialog",
data: {experienceId: expId, charId: charId, startEditing: true},
element: event.currentTarget,
returnElement: () => instance.find(`.experience[data-id='${expId}']`),
});
},
"tap #addClassButton":function(event){
"click #addClassButton":function(event, instance){
var charId = this._id;
Classes.insert({
var classId = Classes.insert({
charId: charId,
name: "new Class",
level: 1,
}, function(error, id){
if (!error){
GlobalUI.setDetail({
template: "classDialog",
data: {classId: id, charId: charId, startEditing: true},
heroId: id,
});
}
});
pushDialogStack({
template: "classDialog",
data: {classId: classId, charId: charId, startEditing: true},
element: event.currentTarget,
returnElement: () => instance.find(`.class[data-id='${classId}']`),
});
},
"tap #moreExperiences": function(event){
var inst = Template.instance();
inst.experiencesLimit.set(
inst.experiencesLimit.get() +
"click #moreExperiences": function(event, instance){
instance.experiencesLimit.set(
instance.experiencesLimit.get() +
(this.settings && this.settings.experiencesInc || 10)
);
},
"tap #lessExperiences": function(event){
var inst = Template.instance();
inst.experiencesLimit.set(
"click #lessExperiences": function(event, instance){
instance.experiencesLimit.set(
this.settings && this.settings.experiencesInc || 10
);
//scroll to the top of the div
inst.$(".scroll-y").animate({
// Scroll to the top of the div
instance.$(".scroll-y").animate({
scrollTop: (
inst.$(".scroll-y").scrollTop() +
inst.$(".experiencesCard").position().top -
instance.$(".scroll-y").scrollTop() +
instance.$(".experiencesCard").position().top -
8
)
}, 300);
//HACK giggle the columns :( to workaround chrome bug that stops .containers height from updating
var cs = inst.$(".containers").removeClass("containers");
// HACK jiggle the columns :( to workaround chrome bug that stops .containers height from updating
var cs = instance.$(".containers").removeClass("containers");
_.defer(function(){cs.addClass("containers");});
},
});

View File

@@ -1,7 +1,7 @@
<template name="noteDialog">
{{#with note}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
<div>{{#markdown}}{{description}}{{/markdown}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{else}}
{{> noteDialogEdit}}
{{/baseDialog}}
@@ -10,21 +10,13 @@
<template name="noteDialogEdit">
<!--Name-->
<div horizontal layout>
<div class="horizontal layout">
<paper-input id="noteNameInput"
label="Name"
floatinglabel
value={{name}}
flex>
class="flex">
</paper-input>
</div>
<!--Description, formatting this nicely breaks it, leave it as is-->
<paper-input-decorator label="Description"
floatinglabel
layout vertical>
<paper-autogrow-textarea>
<textarea id="noteDescriptionInput"
value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
</template>
<paper-textarea id="noteDescriptionInput" label="Description" value={{description}}></paper-textarea>
</template>

View File

@@ -11,21 +11,36 @@ Template.noteDialog.events({
"tap #deleteButton": function(event, instance){
Notes.softRemove(instance.data.noteId);
GlobalUI.deletedToast(instance.data.noteId, "Notes", "Note");
GlobalUI.closeDetail();
popDialogStack();
},
});
Template.noteDialogEdit.onRendered(function(){
updatePolymerInputs(this);
});
const debounce = (f) => _.debounce(f, 300);
Template.noteDialogEdit.events({
"change #noteNameInput, input #noteNameInput": function(event){
"change #noteNameInput, input #noteNameInput": debounce(function(event){
const input = event.currentTarget;
var name = input.value;
if (!name){
input.invalid = true;
input.errorMessage = "Name is required";
} else {
input.invalid = false;
Notes.update(this._id, {
$set: {name: name}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}
}),
"input #noteDescriptionInput": debounce(function(event){
var value = event.currentTarget.value;
Notes.update(this._id, {$set: {name: value}});
},
"change #noteDescriptionInput": function(event){
var value = event.currentTarget.value;
Notes.update(this._id, {$set: {description: value}});
},
Notes.update(this._id, {
$set: {description: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
});

View File

@@ -1,13 +1,13 @@
<template name="raceDialog">
{{#baseDialog title="Race" class=color hideColor="true" hideDelete="true" startEditing=startEditing}}
<div horizontal layout center-justified class= "display2">
<div class="horizontal layout center-justified paper-font-display2">
{{race}}
</div>
{{> effectsViewList charId=charId parentId=charId parentGroup="racial"}}
{{> proficiencyViewList charId=charId parentId=charId parentGroup="racial"}}
{{else}}
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input>
<paper-input id="raceInput" label="Race" value={{race}}></paper-input>
{{> effectsEditList parentId=charId parentCollection="Characters" charId=charId parentGroup="racial"}}
{{> proficiencyEditList parentId=charId parentCollection="Characters" charId=charId parentGroup="racial"}}
{{/baseDialog}}
</template>
</template>

View File

@@ -1,12 +1,13 @@
Template.raceDialog.onRendered(function(){
updatePolymerInputs(this);
});
Template.raceDialog.events({
"change #raceInput": function(event){
"input #raceInput, change #raceInput": _.debounce(function(event){
var value = event.currentTarget.value;
Characters.update(this.charId, {$set: {race: value}});
}
Characters.update(this.charId, {
$set: {race: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}, 300),
});
Template.raceDialog.helpers({

View File

@@ -1,40 +1,27 @@
<template name="newCharacterDialog">
<div>
<paper-input id="nameInput" label="Name"></paper-input><br>
<paper-input id="genderInput" label="Gender"></paper-input><br>
<paper-input id="raceInput" label="Race"></paper-input>
<!--
<div>
<div layout horizontal center-justified>
{{pointsUsed}}/<paper-input-decorator><input type="number" value="27"></paper-input-decorator>
</div>
<div layout horizontal wrap>
<div>Strength</div>
<paper-slider id="strSlider" min="8" max="15" value="8" secondaryProgress={{secondaryProgress}}></paper-slider>
</div>
<div layout horizontal wrap>
<div>Dexterity</div>
<paper-slider id="dexSlider" min="8" max="15" value="8" secondaryProgress={{secondaryProgress}}></paper-slider>
</div>
<div layout horizontal wrap>
<div>Constitution</div>
<paper-slider id="conSlider" min="8" max="15" value="8" secondaryProgress={{secondaryProgress}}></paper-slider>
</div>
<div layout horizontal wrap>
<div>Intelligence</div>
<paper-slider id="intSlider" min="8" max="15" value="8" secondaryProgress={{secondaryProgress}}></paper-slider>
</div>
<div layout horizontal wrap>
<div>Wisdom</div>
<paper-slider id="wisSlider" min="8" max="15" value="8" secondaryProgress={{secondaryProgress}}></paper-slider>
</div>
<div layout horizontal wrap>
<div>Charisma</div>
<paper-slider id="chaSlider" min="8" max="15" value="8" secondaryProgress={{secondaryProgress}}></paper-slider>
<div class="fit layout vertical">
<app-header-layout has-scrolling-region class="new-character-dialog flex">
<app-header fixed effects="waterfall">
<app-toolbar>
<div main-title>New Character</div>
</app-toolbar>
</app-header>
<div class="form">
<p>
Input the basics of your character, but don't worry, you can always change these values later
</p>
<paper-input class="nameInput" label="Name" {{errorAtts "name"}}></paper-input><br>
<paper-input class="genderInput" label="Gender" {{errorAtts "gender"}}></paper-input><br>
<paper-input class="raceInput" label="Race" {{errorAtts "race"}}></paper-input>
</div>
</app-header-layout>
<div class="buttons layout horizontal end-justified">
<paper-button class="cancelButton">
Cancel
</paper-button>
<paper-button class="addButton" disabled={{invalid}}>
Add
</paper-button>
</div>
-->
</div>
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
<paper-button id="addButton" affirmative> Add </paper-button>
</template>
</template>

View File

@@ -1,13 +1,50 @@
Template.newCharacterDialog.events({
"tap #addButton": function(event, instance){
Characters.insert({
name: instance.find("#nameInput").value,
gender: instance.find("#genderInput").value,
race: instance.find("#raceInput").value,
owner: Meteor.userId(),
}, function(err, id){
if (err) throw err;
Router.go("characterSheet", {_id: id});
});
}
Template.newCharacterDialog.onCreated(function(){
this.character = {};
this.schema = new SimpleSchema({
//strings
name: {type: String},
gender: {type: String, optional: true},
race: {type: String, optional: true},
});
this.context = this.schema.newContext();
this.context.runOnce = new ReactiveVar(false);
});
Template.newCharacterDialog.helpers({
invalid(){
let context = Template.instance().context;
let valid = context.isValid() && context.runOnce.get();
return !valid;
},
errorAtts(key){
let error = Template.instance().context.keyErrorMessage(key);
if (error){
return {
invalid: true,
["error-message"]: error,
}
}
},
});
changeFunction = function(field){
return _.debounce(function(event, instance){
console.log({field, event})
instance.character[field] = event.currentTarget.value;
instance.schema.clean(instance.character);
instance.context.validate(instance.character);
if (!instance.context.runOnce.get()) instance.context.runOnce.set(true);
}, 200);
};
Template.newCharacterDialog.events({
"input .nameInput": changeFunction("name"),
"input .genderInput": changeFunction("gender"),
"input .raceInput": changeFunction("race"),
"click .cancelButton": function(event, instance){
popDialogStack();
},
"click .addButton": function(event, instance){
popDialogStack(instance.character);
},
});

View File

@@ -2,10 +2,9 @@
{{#baseDialog title=name class="deep-purple white-text" hideColor="true" hideDelete="true" startEditing=startEditing}}
{{#with char}}
<div>{{alignment}} {{gender}} {{race}}</div>
<core-image style="width: 350px; height: 350px; margin-top: 8px;"
sizing="cover"
hero-id="image" hero
src={{picture}}></core-image>
<iron-image style="width: 350px; height: 350px; margin-top: 8px;"
sizing="contain"
src={{picture}}></iron-image>
{{/with}}
{{else}}
{{#with char}}
@@ -15,22 +14,21 @@
</template>
<template name="personaDetailsEdit">
<div layout horizontal center-justified>
<div flex style="max-width: 350px;" layout vertical>
<div class="layout horizontal center-justified">
<div class="flex layout vertical" style="max-width: 400px;">
<!--Name-->
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input>
<paper-input id="nameInput" label="Name" value={{name}}></paper-input>
<!--Alignment-->
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input>
<paper-input id="alignmentInput" label="Alignment" value={{alignment}}></paper-input>
<!--Gender-->
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input>
<paper-input id="genderInput" label="Gender" value={{gender}}></paper-input>
<!--Race-->
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input>
<paper-input id="raceInput" label="Race" value={{race}}></paper-input>
<!--Picture-->
<paper-input id="pictureInput" label="Picture URL" floatinglabel value={{picture}}></paper-input>
<core-image style="height:350px; width: 100%; margin-top: 8px;"
sizing="cover"
hero-id="image" hero
src={{picture}}></core-image>
<paper-input id="pictureInput" label="Picture URL" value={{picture}}></paper-input>
<iron-image style="margin-top: 8px; width: 100%; height: 400px;"
sizing="contain"
src={{picture}}></iron-image>
</div>
</div>
</template>

View File

@@ -1,7 +1,3 @@
Template.personaDetailsEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.personaDetailsDialog.helpers({
char: function() {
return Characters.findOne(
@@ -11,25 +7,20 @@ Template.personaDetailsDialog.helpers({
}
});
inputHandler = (field) => _.debounce(function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {
$set: {[field]: input}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}, 300);
Template.personaDetailsEdit.events({
"change #nameInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {name: input}});
},
"change #alignmentInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {alignment: input}});
},
"change #genderInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {gender: input}});
},
"change #raceInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {race: input}});
},
"change #pictureInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {picture: input}});
},
"input #nameInput, change #nameInput": inputHandler("name"),
"input #alignmentInput, change #alignmentInput": inputHandler("alignment"),
"input #genderInput, change #genderInput": inputHandler("gender"),
"input #raceInput, change #raceInput": inputHandler("race"),
"input #pictureInput, change #pictureInput": inputHandler("picture"),
});

View File

@@ -1,77 +1,66 @@
<template name="persona">
<div fit>
<div id="persona" class="scroll-y" fit>
<div class="column-container">
{{#with characterDetails}}
<div>
<paper-shadow class="card"
hero-id="main" {{detailHero "details" _id}}>
{{#unless picture}}
<div class="top subhead characterField {{colorClass}}"
hero-id="toolbar" {{detailHero "details" _id}}>
<div class="subhead" flex
hero-id="title" {{detailHero "details" _id}}>
{{name}}
</div>
</div>
{{else}}
<core-image class="characterField clickable"
style="height:350px; width: 100%;
background-color: #e8e8e8;"
sizing="cover"
hero-id="image" {{detailHero "details" _id}}
src={{picture}}></core-image>
{{/unless}}
<div class="bottom">
{{#if picture}}
<div class="title" hero-id="title" {{detailHero "details" _id}}>
{{name}}
</div>
{{/if}}
<div class="subhead">
{{alignment}} {{gender}} {{race}}
<div class="column-container animation-slider">
{{#with characterDetails}}
<div>
<paper-material class="card">
{{#unless picture}}
<div class="top paper-font-subhead characterField {{colorClass}}">
<div class="paper-font-subhead flex">
{{name}}
</div>
</div>
</paper-shadow>
</div>
{{/with}}
<div>{{> containerCard characterField "description" "Description"}}</div>
<div>{{> containerCard characterField "personality" "Personality Traits"}}</div>
<div>{{> containerCard characterField "ideals" "Ideals"}}</div>
<div>{{> containerCard characterField "bonds" "Bonds"}}</div>
<div>{{> containerCard characterField "flaws" "Flaws"}}</div>
<div>{{> containerCard characterField "backstory" "Background"}}</div>
<div>
<paper-shadow class="card">
<div class="white top subhead">
Languages
{{else}}
<iron-image class="characterField clickable"
style="height:350px; width: 100%;
background-color: #424242;"
sizing="contain"
src={{picture}}></iron-image>
{{/unless}}
<div class="bottom">
{{#if picture}}
<div class="paper-font-title">
{{name}}
</div>
{{/if}}
<div class="paper-font-subhead">
{{alignment}} {{gender}} {{race}}
</div>
</div>
<div class="bottom list">
{{#each languages}}
{{> proficiencyListItem}}
{{/each}}
</div>
</paper-shadow>
</div>
</paper-material>
</div>
{{/with}}
<div>{{> containerCard characterField "description" "Description"}}</div>
<div>{{> containerCard characterField "personality" "Personality Traits"}}</div>
<div>{{> containerCard characterField "ideals" "Ideals"}}</div>
<div>{{> containerCard characterField "bonds" "Bonds"}}</div>
<div>{{> containerCard characterField "flaws" "Flaws"}}</div>
<div>{{> containerCard characterField "backstory" "Background"}}</div>
<div>
<paper-material class="card">
<div class="white top paper-font-subhead">
Languages
</div>
<div class="bottom list">
{{#each languages}}
{{> proficiencyListItem}}
{{/each}}
</div>
</paper-material>
</div>
</div>
</template>
<template name="containerCard">
{{#containerCardHelper this}}{{evaluateString _id body}}{{/containerCardHelper}}
{{#containerCardHelper this}}{{evaluateShortString _id body}}{{/containerCardHelper}}
</template>
<template name="containerCardHelper">
<paper-shadow class="card {{class}}"
hero-id="main" {{detailHero field ../_id}}>
<div class="top subhead {{colorClass}} {{topClass}}"
hero-id="toolbar" {{detailHero field ../_id}}>
<div class="subhead" flex
hero-id="title" {{detailHero field ../_id}}>
<paper-material class="card {{class}}">
<div class="top paper-font-subhead {{colorClass}} {{topClass}}">
<div class="paper-font-subhead flex">
{{title}}
</div>
</div>
<div class="bottom">{{#markdown}}{{> UI.contentBlock}}{{/markdown}}</div>
</paper-shadow>
</paper-material>
</template>

View File

@@ -16,7 +16,6 @@ Template.persona.helpers({
char.field = "details";
char.title = char.name;
char.color = "d";
char.startEditing = true;
return char;
},
characterField: function(field, title){
@@ -39,28 +38,27 @@ Template.persona.helpers({
});
Template.persona.events({
"tap .characterField": function(event){
"click .characterField": function(event){
if (this.field == "details"){
this.charId = Template.parentData()._id;
GlobalUI.setDetail({
pushDialogStack({
template: "personaDetailsDialog",
data: this,
heroId: this._id + this.field,
element: event.currentTarget.parentElement,
});
} else {
var template = "textDialog";
if (this.field === "backstory") template = "backgroundDialog";
var charId = Template.parentData()._id;
GlobalUI.setDetail({
pushDialogStack({
template: template,
data: {
charId: charId,
field: this.field,
title: this.title,
color: this.color,
startEditing: true,
},
heroId: this._id + this.field,
element: event.currentTarget.parentElement,
});
}
}

View File

@@ -1,5 +1,5 @@
<template name="textDialog">
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true"}}
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
{{else}}
{{> textDialogEdit}}
@@ -7,9 +7,6 @@
</template>
<template name="textDialogEdit">
<paper-input-decorator label={{title}} floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="textInput" placeholder value={{value}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-textarea label={{title}} id="textInput" value={{value}}>
</paper-textarea>
</template>

View File

@@ -7,10 +7,6 @@ Template.textDialog.helpers({
}
});
Template.textDialogEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.textDialogEdit.helpers({
value: function(){
var fieldSelector = {fields: {}};
@@ -21,10 +17,13 @@ Template.textDialogEdit.helpers({
});
Template.textDialogEdit.events({
"change #textInput": function(event){
"input #textInput": _.debounce(function(event){
var input = event.currentTarget.value;
var setter = {$set: {}};
setter.$set[this.field] = input;
Characters.update(this.charId, setter);
}
Characters.update(this.charId, {
$set: {[this.field]: input}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}, 300),
});

View File

@@ -1,23 +1,19 @@
<template name="proficiencyEdit">
<div layout horizontal around-justified>
<paper-dropdown-menu class="typeDropDown" label="Stat Group" flex>
<paper-dropdown layered class="dropdown">
<core-menu class="menu typeMenu" selected={{type}}>
{{#each proficiencyTypes}}
<div class="layout horizontal around-justified">
<paper-dropdown-menu class="typeDropDown flex" label="Stat Group">
<dicecloud-selector class="typeMenu dropdown-content" selected={{type}}>
{{#each proficiencyTypes}}
<paper-item class="statGroupSelect" name={{type}}>{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
{{> UI.dynamic template=nameInputTemplate}}
<paper-dropdown-menu class="valueDropDown" label="Proficiency" flex>
<paper-dropdown layered class="dropdown">
<core-menu class="menu valueMenu" selected={{value}}>
<paper-item name="1">Proficient</paper-item>
<paper-item name="0.5">Half Prof. Bonus</paper-item>
<paper-item name="2">Double Prof. Bonus</paper-item>
</core-menu>
</paper-dropdown>
<paper-dropdown-menu class="valueDropDown flex" label="Proficiency">
<dicecloud-selector class="valueMenu dropdown-content" selected={{value}}>
<paper-item name="1">Proficient</paper-item>
<paper-item name="0.5">Half Prof. Bonus</paper-item>
<paper-item name="2">Double Prof. Bonus</paper-item>
</dicecloud-selector>
</paper-dropdown-menu>
<paper-icon-button class="deleteProficiency"
icon="delete">
@@ -26,14 +22,12 @@
</template>
<template name="nameDropdown">
<paper-dropdown-menu class="nameDropDown sideMargin" label="Proficiency" flex>
<paper-dropdown layered class="dropdown">
<core-menu class="menu nameMenu" selected={{name}}>
{{#each nameDropdownItems}}
<paper-item name={{stat}}>{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
<paper-dropdown-menu class="nameDropDown sideMargin flex" label="Proficiency">
<dicecloud-selector class="nameMenu dropdown-content" selected={{name}}>
{{#each nameDropdownItems}}
<paper-item name={{stat}}>{{name}}</paper-item>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
</template>

View File

@@ -51,27 +51,24 @@ Template.proficiencyEdit.helpers({
});
Template.proficiencyEdit.events({
"tap .deleteProficiency": function(event){
"click .deleteProficiency": function(event){
Proficiencies.softRemoveNode(this._id);
GlobalUI.deletedToast(this._id, "Proficiencies", "Proficiency");
},
"core-select .typeDropDown": function(event){
"iron-select .typeDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var type = detail.item.getAttribute("name");
if (type == this.type) return;
Proficiencies.update(this._id, {$set: {type: type}});
},
"core-select .valueDropDown": function(event){
"iron-select .valueDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = +detail.item.getAttribute("name");
if (value == this.value) return;
Proficiencies.update(this._id, {$set: {value: value}});
},
"core-select .nameDropDown": function(event){
"iron-select .nameDropDown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var name = detail.item.getAttribute("name");
if (name == this.name) return;
Proficiencies.update(this._id, {$set: {name: name}});

View File

@@ -1,10 +1,8 @@
<!--needs to be given charId, parentId and parentCollection-->
<template name="proficiencyEditList">
{{#if proficiencies.count}}
<hr class="vertMargin">
<div id="proficiencies">
<h2>Proficiencies</h2>
<div class="paper-font-title">Proficiencies</div>
{{#each proficiencies}}
{{>proficiencyEdit}}
{{/each}}
@@ -15,4 +13,4 @@
raised>
Add Proficiency
</paper-button>
</template>
</template>

View File

@@ -1,11 +1,8 @@
<template name="proficiencyListItem">
<div class="item-slot">
<div class="proficiency item small"
hero-id="main" {{detailHero}}
layout horizontal center>
<core-icon icon="{{profIcon}}"
style="margin-right: 16px;"></core-icon>
<div flex>{{getName}}</div>
<div class="proficiency item small layout horizontal center">
<iron-icon icon="{{profIcon}}" style="margin-right: 16px;"></iron-icon>
<div class="flex">{{getName}}</div>
</div>
</div>
</template>
</template>

View File

@@ -14,7 +14,11 @@ Template.proficiencyListItem.helpers({
});
Template.proficiencyListItem.events({
"tap .proficiency": function(event, instance){
openParentDialog(this.parent, this.charId, this._id);
"click .proficiency": function(event, instance){
openParentDialog({
parent: this.parent,
charId: this.charId,
element: event.currentTarget,
});
}
});

View File

@@ -1,10 +1,7 @@
<template name="proficiencyView">
<div class="proficiencyView item small"
style="padding: 0;"
layout horizontal center>
<core-icon icon="{{profIcon}}" style="margin-right: 16px;"></core-icon>
<div class="proficiencyView item small layout horizontal center"
style="padding: 0;">
<iron-icon icon="{{profIcon}}" style="margin-right: 16px;"></iron-icon>
<div>{{getName}}</div>
</div>
</template>

View File

@@ -1,11 +1,12 @@
<template name="proficiencyViewList">
{{#if proficiencies.count}}
<hr class="vertMargin">
<div class="proficiencies">
<h2 style="margin-bottom: 8px;">Proficiencies</h2>
<div class="paper-font-title" style="margin-bottom: 8px;">
Proficiencies
</div>
{{#each proficiencies}}
{{> proficiencyView}}
{{/each}}
</div>
{{/if}}
</template>
</template>

View File

@@ -1,3 +1,7 @@
.spellDialog paper-checkbox {
margin: 8px 16px 8px 8px;
.spell-dialog paper-checkbox {
margin: 8px;
}
.spell-dialog paper-dropdown-menu, .spell-dialog paper-input {
margin: 0 4px;
}

View File

@@ -1,36 +1,38 @@
<template name="spellDialog">
{{#with spell}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
{{> spellDetails}}
{{else}}
{{> spellEdit}}
{{/baseDialog}}
{{/with}}
<div class="spell-dialog">
{{#with spell}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
{{> spellDetails}}
{{else}}
{{> spellEdit}}
{{/baseDialog}}
{{/with}}
</div>
</template>
<template name="spellDetails">
<div class="body2">
<div class="paper-font-body2">
Level {{level}} {{school}} {{#if ritual}}ritual{{/if}}, {{preparedString}}
</div>
<div style="margin: 16px 0 16px 0;">
{{#if castingTime}}
<div>
<span class="body2">Casting Time: </span><span>{{castingTime}}</span>
<span class="paper-font-body2">Casting Time: </span><span>{{castingTime}}</span>
</div>
{{/if}}
{{#if range}}
<div>
<span class="body2">Range: </span><span>{{range}}</span>
<span class="paper-font-body2">Range: </span><span>{{range}}</span>
</div>
{{/if}}
{{#if getComponents}}
<div>
<span class="body2">Components: </span><span>{{getComponents}}</span>
<span class="paper-font-body2">Components: </span><span>{{getComponents}}</span>
</div>
{{/if}}
{{#if duration}}
<div>
<span class="body2">Duration: </span><span>{{duration}}</span>
<span class="paper-font-body2">Duration: </span><span>{{duration}}</span>
</div>
{{/if}}
</div>
@@ -39,101 +41,78 @@
</template>
<template name="spellEdit">
<div horizontal layout>
<paper-input id="spellNameInput" label="Name" floatinglabel value={{name}} flex></paper-input>
</div>
<div layout horizontal justified wrap>
<paper-dropdown-menu id="schoolDropdown" label="School">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{school}}>
{{#each magicSchools}}
<paper-item name={{this}} class="containerMenuItem">{{this}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
<paper-dropdown-menu id="levelDropdown" label="Level">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{level}}>
{{#each spellLevels}}
<paper-item name={{level}} class="containerMenuItem">{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
</paper-dropdown-menu>
<div class="horizontal layout wrap">
<paper-input id="spellNameInput" label="Name" class="flex" value={{name}}></paper-input>
<paper-dropdown-menu id="listDropdown" label="Spell List">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{parent.id}}>
{{#each spellLists}}
<dicecloud-selector class="dropdown-content" selected={{parent.id}}>
{{#each spellLists}}
<paper-item name={{_id}} class="containerMenuItem">{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
<paper-dropdown-menu id="preparedDropdown" label="School">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{prepared}}>
{{#each preparedOptions}}
</div>
<div class="layout horizontal center justified wrap">
<paper-dropdown-menu id="levelDropdown" label="Level">
<dicecloud-selector class="dropdown-content" selected={{level}}>
{{#each spellLevels}}
<paper-item name={{level}} class="containerMenuItem">{{name}}</paper-item>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
<paper-dropdown-menu id="schoolDropdown" label="School">
<dicecloud-selector class="dropdown-content" selected={{school}}>
{{#each magicSchools}}
<paper-item name={{this}} class="containerMenuItem">{{this}}</paper-item>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
<paper-dropdown-menu id="preparedDropdown" label="Prepared">
<dicecloud-selector class="dropdown-content" selected={{prepared}}>
{{#each preparedOptions}}
<paper-item name={{value}} class="containerMenuItem">{{name}}</paper-item>
{{/each}}
</core-menu>
</paper-dropdown>
{{/each}}
</dicecloud-selector>
</paper-dropdown-menu>
<paper-checkbox id="ritualCheckbox" class="sideMargin" checked={{ritual}}>
Ritual
</paper-checkbox>
</div>
<hr class="vertMargin">
<div horizontal layout center justified wrap>
<div layout horizontal center>
<span>Verbal:</span>
<paper-checkbox id="verbalCheckbox" class="sideMargin" checked={{components.verbal}}></paper-checkbox>
</div>
<div layout horizontal center>
<span>Somatic:</span>
<paper-checkbox id="somaticCheckbox" class="sideMargin" checked={{components.somatic}}></paper-checkbox>
</div>
<div layout horizontal center>
<span>Concentration:</span>
<paper-checkbox id="concentrationCheckbox" class="sideMargin" checked={{components.concentration}}></paper-checkbox>
</div>
<div layout horizontal center>
<span>Ritual: </span>
<paper-checkbox id="ritualCheckbox" class="sideMargin" checked={{ritual}}></paper-checkbox>
</div>
</div>
<div layout horizontal center>
<div>Material: </div>
<paper-input id="materialInput" class="sideMargin" label="Material Components" floatinglabel value={{components.material}} flex></paper-input>
</div>
<hr class="vertMargin">
<div layout horizontal justified wrap>
<div class="layout horizontal center justified wrap">
<paper-input id="castingTimeInput"
label="Casting Time"
value={{castingTime}}
floatinglabel
flex></paper-input>
class="flex"
></paper-input>
<paper-input id="rangeInput"
class="sideMargin"
class="sideMargin flex"
label="Range"
value={{range}}
floatinglabel
flex></paper-input>
></paper-input>
</div>
<div class="horizontal layout center justified wrap">
<paper-checkbox id="verbalCheckbox" class="sideMargin" checked={{components.verbal}}>
Verbal
</paper-checkbox>
<paper-checkbox id="somaticCheckbox" class="sideMargin" checked={{components.somatic}}>
Somatic
</paper-checkbox>
<paper-input id="materialInput" class="sideMargin flex" label="Material Components" value={{components.material}}>
</paper-input>
</div>
<div class="horizontal laout center justified wrap">
<paper-input id="durationInput"
label="Duration"
value={{duration}}
floatinglabel
flex></paper-input>
class="flex"
></paper-input>
<paper-checkbox id="concentrationCheckbox" class="sideMargin" checked={{components.concentration}}>
Concentration
</paper-checkbox>
</div>
<hr class="vertMargin">
<!--Description-->
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="descriptionInput" placeholder value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-textarea id="descriptionInput" label="Description" value="{{description}}">
</paper-textarea>
{{> attackEditList parentId=_id parentCollection="Spells" charId=charId enabled=true name=name}}
</template>

View File

@@ -24,7 +24,7 @@ Template.spellDialog.events({
"tap #deleteButton": function(event, instance){
Spells.softRemoveNode(instance.data.spellId);
GlobalUI.deletedToast(instance.data.spellId, "Spells", "Spell");
GlobalUI.closeDetail();
popDialogStack();
},
});
@@ -47,10 +47,6 @@ Template.spellDetails.helpers({
},
});
Template.spellEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.spellEdit.helpers({
spellLists: function(){
return SpellLists.find({charId: this.charId}, {fields: {name: 1}});
@@ -70,55 +66,92 @@ Template.spellEdit.helpers({
},
});
const debounce = (f) => _.debounce(f, 300);
Template.spellEdit.events({
"change #spellNameInput, input #spellNameInput": function(event){
"change #spellNameInput, input #spellNameInput": debounce(function(event){
const input = event.currentTarget;
var value = input.value;
if (!value){
input.invalid = true;
input.errorMessage = "Name is required";
} else {
input.invalid = false;
Spells.update(this._id, {
$set: {name: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}
}),
"change #castingTimeInput, input #castingTimeInput": debounce(function(event){
var value = event.currentTarget.value;
Spells.update(this._id, {$set: {name: value}});
},
"change #castingTimeInput": function(event){
Spells.update(this._id, {
$set: {castingTime: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #rangeInput, input #rangeInput": debounce(function(event){
var value = event.currentTarget.value;
Spells.update(this._id, {$set: {castingTime: value}});
},
"change #rangeInput": function(event){
Spells.update(this._id, {
$set: {range: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #durationInput, input #durationInput": debounce(function(event){
var value = event.currentTarget.value;
Spells.update(this._id, {$set: {range: value}});
},
"change #durationInput": function(event){
Spells.update(this._id, {
$set: {duration: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #materialInput, input #materialInput": debounce(function(event){
var value = event.currentTarget.value;
Spells.update(this._id, {$set: {duration: value}});
},
"change #materialInput": function(event){
Spells.update(this._id, {
$set: {"components.material": value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #descriptionInput": debounce(function(event){
var value = event.currentTarget.value;
Spells.update(this._id, {$set: {"components.material": value}});
},
"change #descriptionInput": function(event){
var value = event.currentTarget.value;
Spells.update(this._id, {$set: {"description": value}});
},
"core-select #listDropdown": function(event){
Spells.update(this._id, {
$set: {"description": value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"iron-select #listDropdown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
if (value == this.parent.id) return;
Spells.update(this._id, {$set: {"parent.id": value}});
Spells.update(this._id, {
$set: {"parent.id": value}
});
},
"core-select #levelDropdown": function(event){
"iron-select #levelDropdown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
if (value == this.level) return;
Spells.update(this._id, {$set: {level: value}});
},
"core-select #schoolDropdown": function(event){
"iron-select #schoolDropdown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
if (value == this.school) return;
Spells.update(this._id, {$set: {school: value}});
},
"core-select #preparedDropdown": function(event){
"iron-select #preparedDropdown": function(event){
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");
if (value == this.school) return;
Spells.update(this._id, {$set: {prepared: value}});

View File

@@ -2,10 +2,10 @@
{{#with spellList}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
<div>
<div layout horizontal justified wrap class="subhead">
<div class="paper-font-subhead layout horizontal justified wrap">
{{#if attackBonus}}
<div>
Attack Bonus: {{evaluate charId attackBonus}}
Attack Bonus: {{evaluateSigned charId attackBonus}}
</div>
{{/if}}
{{#if saveDC}}
@@ -15,7 +15,7 @@
{{/if}}
{{#if maxPrepared}}
<div>
Max Prepared: {{evaluateSigned charId maxPrepared}}
Max Prepared Spells: {{evaluate charId maxPrepared}}
</div>
{{/if}}
</div>
@@ -23,36 +23,26 @@
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
</div>
{{else}}
<div class="layout vertical">
<!--Name-->
<paper-input id="spellListNameInput"
class="fullwidth"
label="Name"
floatinglabel
value={{name}}></paper-input>
<paper-input id="spellListNameInput" label="Name" value={{name}}>
</paper-input>
<!--Save DC-->
<paper-input id="spellListSaveDCInput"
label="Save DC"
floatinglabel
value={{saveDC}}
style="width: 100%;"></paper-input><br>
<paper-input id="spellListSaveDCInput" label="Save DC" value={{saveDC}}>
{{> formulaSuffix}}
</paper-input>
<!--Attack Bonus-->
<paper-input id="spellListAttackBonusInput"
label="Attack Bonus"
floatinglabel
value={{attackBonus}}
style="width: 100%;"></paper-input><br>
<paper-input id="spellListAttackBonusInput" label="Attack Bonus" value={{attackBonus}}>
{{> formulaSuffix}}
</paper-input>
<!--Max Prepared-->
<paper-input id="spellListMaxPreparedInput"
label="Maximum Prepared Spells"
floatinglabel
value={{maxPrepared}}
style="width: 100%;"></paper-input><br>
<paper-input id="spellListMaxPreparedInput" label="Maximum Prepared Spells" value={{maxPrepared}}>
{{> formulaSuffix}}
</paper-input>
<!--Description-->
<paper-input-decorator label="Description" floatinglabel layout vertical>
<paper-autogrow-textarea>
<textarea id="spellListDescriptionInput" placeholder value={{description}}></textarea>
</paper-autogrow-textarea>
</paper-input-decorator>
<paper-textarea id="spellListDescriptionInput" label="Description" value={{description}}>
</paper-textarea>
</div>
{{/baseDialog}}
{{/with}}
</template>
</template>

View File

@@ -1,48 +1,80 @@
Template.spellListDialog.onRendered(function(){
updatePolymerInputs(this);
Template.spellListDialog.helpers({
spellList: function(){
return SpellLists.findOne(this.spellListId);
}
});
const debounce = (f) => _.debounce(f, 300);
Template.spellListDialog.events({
"color-change": function(event, instance){
SpellLists.update(instance.data.spellListId, {$set: {color: event.color}});
},
"tap #deleteButton": function(event, instance){
"click #deleteButton": function(event, instance){
SpellLists.softRemoveNode(instance.data.spellListId);
GlobalUI.deletedToast(
instance.data.spellListId,
"SpellLists",
"Spell list and contents"
);
GlobalUI.closeDetail();
popDialogStack();
},
//TODO clean up String -> num here so they don't need casting by Schema.clean
//TODO validate input (integer, non-negative, etc) for these inputs and give validation errors
"change #spellListNameInput, input #spellListNameInput": function(event){
"change #spellListNameInput, input #spellListNameInput":
debounce(function(event){
const input = event.currentTarget;
var value = input.value;
if (!value){
input.invalid = true;
input.errorMessage = "Name is required";
} else {
input.invalid = false;
SpellLists.update(this._id, {
$set: {name: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}
}),
"change #spellListSaveDCInput, input #spellListSaveDCInput":
debounce(function(event){
var value = event.currentTarget.value;
SpellLists.update(this._id, {$set: {name: value}});
},
"change #spellListSaveDCInput, input #spellListSaveDCInput": function(event){
var value = event.currentTarget.value;
SpellLists.update(this._id, {$set: {saveDC: value}});
},
SpellLists.update(this._id, {
$set: {saveDC: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #spellListAttackBonusInput, input #spellListAttackBonusInput":
function(event){
debounce(function(event){
var value = event.currentTarget.value;
SpellLists.update(this._id, {$set: {attackBonus: value}});
},
SpellLists.update(this._id, {
$set: {attackBonus: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"change #spellListMaxPreparedInput, input #spellListMaxPreparedInput":
function(event){
debounce(function(event){
var value = event.currentTarget.value;
SpellLists.update(this._id, {$set: {maxPrepared: value}});
},
"change #spellListDescriptionInput": function(event){
SpellLists.update(this._id, {
$set: {maxPrepared: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
"input #spellListDescriptionInput": debounce(function(event){
var value = event.currentTarget.value;
SpellLists.update(this._id, {$set: {description: value}});
},
});
Template.spellListDialog.helpers({
spellList: function(){
return SpellLists.findOne(this.spellListId);
}
SpellLists.update(this._id, {
$set: {description: value}
}, {
removeEmptyStrings: false,
trimStrings: false,
});
}),
});

View File

@@ -6,7 +6,7 @@
height: 56px;
}
#spells .inventoryItem core-icon{
#spells .inventoryItem iron-icon{
width: 32px;
height: 32px;
}
@@ -18,7 +18,7 @@
cursor: pointer !important;
}
#spells .inventoryItem[disabled] core-icon{
#spells .inventoryItem[disabled] iron-icon{
color: #ccc !important;
color: rgba(0,0,0,0.26) !important;
}
@@ -67,17 +67,15 @@
margin: 4px;
}
.spellList .containerMain {
-ms-column-width: 300px;
-webkit-column-width: 300px;
-moz-column-width: 300px;
.spellList.card .bottom.list {
column-width: 300px;
-ms-column-gap: 8px;
-webkit-column-gap: 8px;
-moz-column-gap: 8px;
column-gap: 8px;
-moz-column-fill: balance;
column-fill: balance;
padding: 16px 4px;
}
.spellList .bottom .paper-font-subhead {
margin-left: 16px;
}
.spellLevel {

View File

@@ -1,147 +1,145 @@
<template name="spells">
<div fit>
<div id="spells" class="scroll-y" fit>
<div style="padding: 4px;"
layout horizontal start wrap>
{{#if hasSlots}}
<paper-shadow class="card"
style="margin: 4px;"
hero-id="main" {{detailHero}}>
<div class="white top subhead"
layout horizontal center>
Spell Slots
</div>
<div class="bottom list">
{{#each levels}}{{#if showSlots ..}}
<div class="item-slot">
<div class="item spellSlot"
hero-id="main" {{detailHero slotStatName ../_id}}
layout horizontal center>
<div style="margin-right: 16px">
{{name}}
</div>
<div flex layout horizontal center>
{{#each slotBubbles ..}}
<paper-icon-button class="slotBubble"
icon={{icon}}
disabled={{disabled}}>
</paper-icon-button>
{{/each}}
</div>
<div id="spells" class="animation-slider">
<div style="padding: 4px;"
class="layout horizontal start wrap">
{{#if hasSlots}}
<paper-material class="card"
style="margin: 4px;">
<div class="white top subhead layout horizontal center">
Spell Slots
</div>
<div class="bottom list">
{{#each levels}}{{#if showSlots ..}}
<div class="item-slot">
<div class="item spellSlot layout horizontal center">
<div style="margin-right: 16px">
{{name}}
</div>
<div class="flex layout horizontal center">
{{#each slotBubbles ..}}
<paper-icon-button class="slotBubble"
icon={{icon}}
disabled={{disabled}}>
</paper-icon-button>
{{/each}}
</div>
</div>
{{/if}}{{/each}}
</div>
</paper-shadow>
{{/if}}
{{#each spellLists}}
<paper-shadow class="card spellList" flex
hero-id="main" {{detailHero}}
style="margin: 4px;">
<div class="top {{colorClass}}"
hero-id="toolbar" {{detailHero}}
layout horizontal center>
<div flex>
<div class="subhead">{{name}}</div>
<div class="caption">
{{#if saveDC}}
<span style="margin-right: 16px;">
Save DC: {{evaluate charId saveDC}}
</span>
{{/if}}
{{#if attackBonus}}
<span>
Attack Bonus: {{evaluateSigned charId attackBonus}}
</span>
{{/if}}
</div>
</div>
{{#if settings.showUnprepared}}
{{#if maxPrepared}}
<div class="subhead">
{{numPrepared}} / {{evaluate charId maxPrepared}}
{{/if}}{{/each}}
</div>
</paper-material>
{{/if}}
{{#each spellLists}}
<paper-material class="card spellList flex" data-id={{_id}} style="margin: 4px;">
<div class="top {{colorClass}} layout horizontal center">
<div class="flex">
<div class="paper-font-subhead">{{name}}</div>
<div class="paper-font-caption">
{{#if saveDC}}
<span style="margin-right: 16px;">
Save DC: {{evaluate charId saveDC}}
</span>
{{/if}}
{{#if attackBonus}}
<span>
Attack Bonus: {{evaluateSigned charId attackBonus}}
</span>
{{/if}}
</div>
</div>
{{#if showUnprepared _id}}
{{#if maxPrepared}}
<div class="paper-font-subhead">
{{numPrepared}} / {{evaluate charId maxPrepared}}
</div>
{{/if}}
<div>
<paper-tooltip position="left">
Done
</paper-tooltip>
<paper-icon-button class="finishPrep" icon="done">
</paper-icon-button>
</div>
{{else}}
<div>
<paper-tooltip position="left">
Change prepared spells
</paper-tooltip>
<paper-icon-button class="prepSpells"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
icon="book">
</paper-icon-button>
</div>
{{/if}}
</div>
<div class="bottom list">
{{#each levels}}
<div class="spellLevel">
{{#if spellCount .. ../../_id}}
<div class="paper-font-subhead">
{{name}}
</div>
{{/if}}
<core-tooltip label="Done"
position="left">
<paper-icon-button class="finishPrep"
icon="done">
</paper-icon-button>
</core-tooltip>
{{else}}
<core-tooltip label="Change prepared spells"
position="left">
<paper-icon-button class="prepSpells"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
icon="book">
</paper-icon-button>
</core-tooltip>
{{/if}}
</div>
<div class="bottom list column-container">
{{#each levels}}
<div class="spellLevel">
{{#if spellCount .. ../../_id}}
<div class="subhead">
{{name}}
{{#each spells ../_id ../../_id}}
{{#if showSpell ../../_id}}
<div class="item-slot">
<div class="tall spell item layout horizontal center" data-id={{_id}}>
<iron-icon icon="social:whatshot"
style="color: {{hexColor color}};
margin-right: 16px;"
></iron-icon>
<div class="flex layout vertical">
<div>{{name}}</div>
<div class="paper-font-caption">
{{school}}
{{castingTime}}
{{#if ritual}}
(ritual)
{{/if}}
{{#if spellComponents}}
- {{spellComponents}}
{{/if}}
</div>
</div>
{{#if showUnprepared ../../_id}}
<paper-checkbox class="preparedCheckbox"
checked={{isPrepared}}
disabled={{cantUnprepare}}>
</paper-checkbox>
{{/if}}
</div>
</div>
{{/if}}
{{#each spells ../_id ../../_id}}
{{#if showSpell ../../settings.showUnprepared}}
<div class="item-slot">
<div class="tall spell item"
hero-id="main" {{detailHero}}
layout horizontal center>
<core-icon icon="social:whatshot"
style="color: {{hexColor color}};
margin-right: 16px;"
></core-icon>
<div flex layout vertical>
<div>{{name}}</div>
<div class="caption">
{{school}}
{{castingTime}}
{{#if ritual}}
(ritual)
{{/if}}
{{#if spellComponents}}
- {{spellComponents}}
{{/if}}
</div>
</div>
{{#if ../../settings.showUnprepared}}
<paper-checkbox class="preparedCheckbox"
checked={{isPrepared}}
disabled={{cantUnprepare}}>
</paper-checkbox>
{{/if}}
</div>
</div>
{{/if}}
{{/each}}
</div>
{{/each}}
</div>
</paper-shadow>
{{/each}}
</div>
<div class="fab-buffer"></div>
{{/each}}
</div>
{{/each}}
</div>
</paper-material>
{{/each}}
</div>
<div class="fab-buffer"></div>
</div>
{{#if canEditCharacter _id}}
{{#fabMenu}}
<core-tooltip label="New spell list" position="left">
<div>
<paper-tooltip position="left">
New spell list
</paper-tooltip>
<paper-fab icon="work"
class="addSpellList"
mini>
</paper-fab>
</core-tooltip>
<core-tooltip label="New spell" position="left">
</div>
<div>
<paper-tooltip position="left">
New spell
</paper-tooltip>
<paper-fab icon="note-add"
class="addSpell"
mini>
class="addSpell"
mini>
</paper-fab>
</core-tooltip>
</div>
{{/fabMenu}}
{{/if}}
</template>

View File

@@ -11,13 +11,17 @@ var spellLevels = [
{name: "Level 9", level: 9},
];
const showUnprepared = (listId) => {
return Session.get(`showUnprepared.${listId}`);
}
Template.spells.helpers({
spellLists: function(){
return SpellLists.find({charId: this._id}, {sort: {color: 1, name: 1}});
},
spellCount: function(list, charId){
if (!list || !list.settings) return;
if (list.settings.showUnprepared){
if (!list) return;
if (showUnprepared(list._id)){
return Spells.find(
{charId: charId, "parent.id": list._id, level: this.level},
{fields: {_id: 1, level: 1}}
@@ -43,6 +47,9 @@ Template.spells.helpers({
levels: function(){
return spellLevels;
},
showUnprepared: function(listId){
return showUnprepared(listId);
},
numPrepared: function(){
return Spells.find({
charId: Template.parentData()._id,
@@ -72,8 +79,8 @@ Template.spells.helpers({
isPrepared: function(){
return this.prepared === "prepared" || this.prepared === "always";
},
showSpell: function(listShowPrepped){
if (listShowPrepped) {
showSpell: function(listId){
if (showUnprepared(listId)) {
return true;
} else {
return this.prepared === "prepared" || this.prepared === "always";
@@ -84,7 +91,9 @@ Template.spells.helpers({
},
cantCast: function(level, char){
for (var i = level; i <= 9; i++){
if (Characters.calculate.attributeValue(char._id, "level" + i + "SpellSlots") > 0){
if (Characters.calculate.attributeValue(
char._id, "level" + i + "SpellSlots"
) > 0){
return false;
}
}
@@ -97,21 +106,27 @@ Template.spells.helpers({
},
hasSlots: function(){
for (var i = 1; i <= 9; i += 1){
if (Characters.calculate.attributeBase(this._id, "level" + i + "SpellSlots")){
if (Characters.calculate.attributeBase(
this._id, "level" + i + "SpellSlots"
)){
return true;
}
}
return false;
},
slotBubbles: function(char){
var baseSlots = Characters.calculate.attributeBase(char._id, "level" + this.level + "SpellSlots");
var currentSlots = Characters.calculate.attributeValue(char._id, "level" + this.level + "SpellSlots");
var baseSlots = Characters.calculate.attributeBase(
char._id, "level" + this.level + "SpellSlots"
);
var currentSlots = Characters.calculate.attributeValue(
char._id, "level" + this.level + "SpellSlots"
);
var slotsUsed = baseSlots - currentSlots;
var bubbles = [];
var i;
for (i = 0; i < currentSlots; i++){
bubbles.push({
icon: "radio-button-on",
icon: "radio-button-checked",
disabled: i !== currentSlots - 1 || !canEditCharacter(char._id), //last full slot not disabled
attribute: "level" + this.level + "SpellSlots",
charId: char._id,
@@ -119,7 +134,7 @@ Template.spells.helpers({
}
for (i = 0; i < slotsUsed; i++){
bubbles.push({
icon: "radio-button-off",
icon: "radio-button-unchecked",
disabled: i !== 0 || !canEditCharacter(char._id), //first empty slot not disabled
attribute: "level" + this.level + "SpellSlots",
charId: char._id,
@@ -133,11 +148,11 @@ Template.spells.helpers({
});
Template.spells.events({
"tap .slotBubble": function(event){
"click .slotBubble": function(event){
var modifier;
if (!event.currentTarget.disabled){
var char = Characters.findOne(this.charId);
if (event.currentTarget.icon === "radio-button-off"){
if (event.currentTarget.icon === "radio-button-unchecked"){
if (
Characters.calculate.attributeValue(char._id, this.attribute) <
Characters.calculate.attributeBase(char._id, this.attribute)
@@ -156,51 +171,49 @@ Template.spells.events({
}
event.stopPropagation();
},
"tap .spellSlot": function(event, instance) {
"click .spellSlot": function(event, instance) {
var name = "Level " + this.level + " Spell Slots";
var stat = "level" + this.level + "SpellSlots";
var charId = instance.data._id;
GlobalUI.setDetail({
pushDialogStack({
template: "attributeDialog",
data: {name: name, statName: stat, charId: charId},
heroId: charId + stat,
element: event.currentTarget,
});
},
"tap .spellList .top": function(event){
GlobalUI.setDetail({
"click .spellList .top": function(event){
pushDialogStack({
template: "spellListDialog",
data: {spellListId: this._id, charId: this.charId},
heroId: this._id,
element: event.currentTarget.parentElement,
});
},
"tap .spell": function(event){
GlobalUI.setDetail({
"click .spell": function(event){
pushDialogStack({
template: "spellDialog",
data: {spellId: this._id, charId: this.charId},
heroId: this._id,
element: event.currentTarget,
});
},
"tap .addSpellList": function(event){
"click .addSpellList": function(event, instance){
var charId = this.charId;
SpellLists.insert({
var id = SpellLists.insert({
name: "New SpellList",
charId: this._id,
saveDC: "8 + intelligenceMod + proficiencyBonus",
attackBonus: "intelligenceMod + proficiencyBonus",
}, function(error, id){
if (!error){
GlobalUI.setDetail({
template: "spellListDialog",
data: {spellListId: id, charId: charId, startEditing: true},
heroId: id,
});
}
});
pushDialogStack({
template: "spellListDialog",
data: {spellListId: id, charId: charId, startEditing: true},
element: event.currentTarget,
returnElement: () => instance.find(`.spellList[data-id='${id}']`),
});
},
"tap .addSpell": function(event){
"click .addSpell": function(event, instance){
var charId = this.charId;
var listId = SpellLists.findOne({charId: this._id})._id;
Spells.insert({
var id = Spells.insert({
name: "New Spell",
charId: this._id,
parent: {
@@ -208,17 +221,15 @@ Template.spells.events({
collection: "SpellLists",
},
prepared: "prepared",
}, function(error, id){
if (!error){
GlobalUI.setDetail({
template: "spellDialog",
data: {spellId: id, charId: charId, startEditing: true},
heroId: id,
});
}
});
pushDialogStack({
template: "spellDialog",
data: {spellId: id, charId: charId, startEditing: true},
element: event.currentTarget,
returnElement: () => instance.find(`.spell[data-id='${id}']`),
});
},
"tap .preparedCheckbox": function(event){
"click .preparedCheckbox": function(event){
event.stopPropagation();
},
"change .preparedCheckbox": function(event){
@@ -228,12 +239,12 @@ Template.spells.events({
else if (this.prepared === "prepared" && !value)
Spells.update(this._id, {$set: {prepared: "unprepared"}});
},
"tap .prepSpells": function(event){
SpellLists.update(this._id, {$set: {"settings.showUnprepared": true}});
"click .prepSpells": function(event){
Session.set(`showUnprepared.${this._id}`, true);
event.stopPropagation();
},
"tap .finishPrep": function(event){
SpellLists.update(this._id, {$set: {"settings.showUnprepared": false}});
"click .finishPrep": function(event){
Session.set(`showUnprepared.${this._id}`, false);
event.stopPropagation();
},
});

View File

@@ -0,0 +1,23 @@
.ability-mini-card {
min-width: 75px;
text-align: center;
cursor: pointer;
-webkit-margin-collapse: separate;
background: #fff;
}
.ability-mini-card .title {
padding: 16px;
}
.ability-mini-card .numbers {
min-width: 72px;
padding: 16px;
}
.ability-mini-card .modifier {
font-weight: 600;
font-size: 24px;
color: #747474;
color: rgba(0,0,0,0.54);
}

View File

@@ -1,16 +1,17 @@
<template name="abilityMiniCard">
<div>
<paper-shadow class="card abilityMiniCard clickable"
hero-id="main" {{detailHero ability ../_id}}
layout horizontal>
<div class="left white-text {{color}}"
hero-id="toolbar" {{detailHero ability ../_id}}>
<div class="display1">{{characterCalculate "attributeValue" ../_id ability}}</div>
<div class="title">{{abilityMod}}</div>
</div>
<div class="right subhead" layout horizontal center>
{{title}}
</div>
</paper-shadow>
<paper-material class="ability-mini-card layout horizontal">
<div class="numbers">
<div class="paper-font-display1 stat">
{{characterCalculate "attributeValue" ../_id ability}}
</div>
<div class="paper-font-subhead modifier">
{{abilityMod}}
</div>
</div>
<div class="paper-font-subhead title flex layout horizontal center">
{{title}}
</div>
</paper-material>
</div>
</template>

View File

@@ -1,14 +1,28 @@
<!-- data just needs charId -->
<template name="addTHPDialog">
<div style="width: 200px; height: 150px;">
<paper-input id="nameInput" label="Label"></paper-input>
<paper-input-decorator label="Quantity" floatinglabel>
<input autoFocus id="quantityInput" type="number" value="10">
</paper-input-decorator>
<div layout horizontal justify-center>
Delete when zero <paper-checkbox id="deleteWhenZeroCheckbox" checked style="margin-left: 8px;"></paper-checkbox>
<div class="fit layout vertical">
<app-header-layout has-scrolling-region class="new-character-dialog flex">
<app-header fixed effects="waterfall">
<app-toolbar>
<div main-title>Add Hitpoint Slider</div>
</app-toolbar>
</app-header>
<div class="form">
<paper-input id="quantityInput" label="Hitpoint maximum" autofocus type="number" value="" min="0" allowed-pattern="[0-9]">
</paper-input>
<paper-input id="nameInput" label="Label"></paper-input>
<paper-checkbox id="deleteWhenZeroCheckbox">
Delete when zero
</paper-checkbox>
</div>
</app-header-layout>
<div class="buttons layout horizontal end-justified">
<paper-button class="cancelButton">
Cancel
</paper-button>
<paper-button class="addButton" disabled={{invalid}}>
Add
</paper-button>
</div>
</div>
<paper-button id="cancelButton" affirmative> Cancel </paper-button>
<paper-button id="addButton" affirmative> Add </paper-button>
</template>

View File

@@ -1,5 +1,10 @@
Template.addTHPDialog.onRendered(function(){
this.find("#quantityInput").focus();
});
Template.addTHPDialog.events({
"tap #addButton": function(event, instance){
"tap .addButton": function(event, instance){
popDialogStack();
var max = +instance.find("#quantityInput").value;
if (!max || max < 0) max = 0;
TemporaryHitPoints.insert({
@@ -8,5 +13,8 @@ Template.addTHPDialog.events({
maximum: max,
deleteOnZero: !!instance.find("#deleteWhenZeroCheckbox").checked,
});
}
},
"tap .cancelButton": function(event, instance){
popDialogStack();
},
});

View File

@@ -6,12 +6,12 @@
</template>
<template name="attributeDialogView">
<div layout horizontal center-justified end>
<div class="display2">
<div class="layout horizontal center-justified end">
<div class="paper-font-display2">
{{attributeValue}}
</div>
{{#if adjustment}}
<div class="display1">
<div class="paper-font-display1">
/{{attributeBase}}
</div>
{{/if}}
@@ -19,50 +19,52 @@
<hr class="vertMargin">
<table class="summaryTable">
{{#each baseEffects}}
<tr>
<td>{{sourceName}}</td>
<td>Base: {{statValue}}</td>
<div class="layout vertical center">
<table class="summaryTable">
{{#each baseEffects}}
<tr>
<td>{{sourceName}}</td>
<td>Base: {{statValue}}</td>
</tr>
{{/each}}
{{#each addEffects}}
<tr>
<td>{{sourceName}}</td>
<td>{{signedString statValue}}</td>
</tr>
{{/each}}
{{#each mulEffects}}
<tr>
<td>{{sourceName}}</td>
<td>&times; {{statValue}}</td>
</tr>
{{/each}}
{{#each minEffects}}
<tr>
<td>{{sourceName}}</td>
<td>Min: {{statValue}}</td>
</tr>
{{/each}}
{{#each maxEffects}}
<tr>
<td>{{sourceName}}</td>
<td>Max: {{statValue}}</td>
</tr>
{{/each}}
{{#if adjustment}}
<tr class="paper-font-body2">
<td>Base Value</td>
<td>{{attributeBase}}</td>
</tr>
<tr>
<td>Adjustment</td>
<td>{{signedString adjustment}}</td>
</tr>
{{/if}}
<tr class="paper-font-body2">
<td>Total</td>
<td>{{attributeValue}}</td>
</tr>
{{/each}}
{{#each addEffects}}
<tr>
<td>{{sourceName}}</td>
<td>{{signedString statValue}}</td>
</tr>
{{/each}}
{{#each mulEffects}}
<tr>
<td>{{sourceName}}</td>
<td>&times; {{statValue}}</td>
</tr>
{{/each}}
{{#each minEffects}}
<tr>
<td>{{sourceName}}</td>
<td>Min: {{statValue}}</td>
</tr>
{{/each}}
{{#each maxEffects}}
<tr>
<td>{{sourceName}}</td>
<td>Max: {{statValue}}</td>
</tr>
{{/each}}
{{#if adjustment}}
<tr class="body2">
<td>Base Value</td>
<td>{{attributeBase}}</td>
</tr>
<tr>
<td>Adjustment</td>
<td>{{signedString adjustment}}</td>
</tr>
{{/if}}
<tr class="body2">
<td>Total</td>
<td>{{attributeValue}}</td>
</tr>
</table>
</table>
</div>
</template>

View File

@@ -3,9 +3,9 @@
{{> attributeDialogView}}
<hr class="vertMargin">
<div>
<div class="title padded">Carrying</div>
<div class="paper-font-title padded">Carrying</div>
{{> carryCapacityTable}}
<div class="title padded">Jumping</div>
<div class="paper-font-title padded">Jumping</div>
<table class="strengthTable">
<tr>
<td>Running long jump</td>
@@ -18,7 +18,7 @@
<tr>
<td>Running high jump</td>
<td>{{evaluate charId "3 + strengthMod"}} feet</td>
<td class="caption">
<td>
Can reach a ledge as high as
{{evaluate charId "3 + strengthMod"}} feet
+ 1.5&times; your height
@@ -27,7 +27,7 @@
<tr>
<td>Standing high jump</td>
<td>{{evaluate charId "floor((3 + strengthMod)/2)"}} feet</td>
<td class="caption">
<td>
Can reach a ledge as high as
{{evaluate charId "floor((3 + strengthMod)/2)"}} feet
+ 1.5&times; your height

Some files were not shown because too many files have changed in this diff Show More