Compare commits

...

68 Commits

Author SHA1 Message Date
Stefan Zermatten
8b3f11603a Update Meteor to 1.2
This requires local copies of packages that are broken or not Polymer 0.5
2015-10-03 22:38:25 +02:00
Stefan Zermatten
d05874ed13 Bumped version 2015-10-01 08:06:29 +02:00
Stefan Zermatten
df2521e69c Merge pull request #5 from ThaumRystra/bugfix-unprepared-spell-attacks
Spell child attacks now set their enabled state to match the parent spell prepared state
2015-10-01 08:03:30 +02:00
Stefan Zermatten
3c6a685fe8 Fixed reference to parentId which should be parent.id 2015-10-01 07:45:38 +02:00
Connor Petersen
a77e560284 Spell attacks correctly enable based on preparedness, Model correction with collection hooks 2015-09-30 13:30:59 -07:00
Stefan Zermatten
4cec83918f Updated README.md to remove out of date info 2015-09-28 07:35:10 +02:00
Stefan Zermatten
fec95c51c6 Rolled back changes to spells tab, It wasn't a column-layout 2015-09-25 13:03:14 +02:00
Stefan Zermatten
425c42d049 Bumped version 2015-09-25 12:52:28 +02:00
Stefan Zermatten
ab6f0c4f5b Merge branch 'fix-columns' 2015-09-25 12:51:04 +02:00
Stefan Zermatten
5d6e57b896 Wrap cards in padded divs to make columns behave 2015-09-25 12:49:48 +02:00
Stefan Zermatten
7c0a8125f2 Merge branch 'fix-carry-capacity-effectView' 2015-09-04 13:56:06 +02:00
Stefan Zermatten
7481ef08a8 Carry capacity effects no longer show up as "no stat" when viewed 2015-09-04 13:55:42 +02:00
Stefan Zermatten
b578dd5fb0 Merge branch 'feature-carry-capacity-modifier' 2015-09-03 14:09:51 +02:00
Stefan Zermatten
5d6f934d88 Bumped version 2015-09-03 14:09:23 +02:00
Stefan Zermatten
337f0bfa8a Made sure migration touches every character 2015-09-03 14:09:17 +02:00
Stefan Zermatten
c62784894b Made sure encumbered conditions respect carry capacity 2015-09-03 13:53:00 +02:00
Stefan Zermatten
75fff43d7d Gave an effect menu option for carry capacity 2015-09-03 13:52:40 +02:00
Stefan Zermatten
a9eeeac0df Fixed carry capacity bar 2015-09-03 13:52:22 +02:00
Stefan Zermatten
c8af0ff0a9 Fixed carry capacity table 2015-09-03 13:52:06 +02:00
Stefan Zermatten
9e200db7b9 Made carry capacity an attribute, migrations need testing 2015-08-31 15:51:52 +02:00
Stefan Zermatten
c08cf83096 Bumped version 2015-08-27 12:21:23 +02:00
Stefan Zermatten
d9368b06d0 Merge branch 'bugfix-0.6.8' 2015-08-27 12:07:42 +02:00
Stefan Zermatten
2703367681 Proficiencies now get disabled when their features are disabled 2015-08-27 12:05:56 +02:00
Stefan Zermatten
d419442549 Fixed share dialog not finding usernames or email addresses 2015-08-27 11:59:38 +02:00
Stefan Zermatten
99df01c950 Prevented negative temporary hitpoints being added 2015-08-27 11:43:34 +02:00
Stefan Zermatten
d76349b3bb Merge branch 'release-0.6.7a' 2015-07-29 09:57:06 +02:00
Stefan Zermatten
39c061f4e8 Fixed formatting of not found page, now has a toolbar and centered text 2015-07-29 09:55:22 +02:00
Stefan Zermatten
6d167ddb22 Fixed formatting of loading page, more padding 2015-07-29 09:55:01 +02:00
Stefan Zermatten
037acbd459 Added Starter Set Wizard to the front page 2015-07-29 09:54:43 +02:00
Stefan Zermatten
4d3fc3bb09 Fixed accidental back() requests when closing detail dialogs 2015-07-29 09:54:18 +02:00
Stefan Zermatten
4b984d4fac Made analytics show all characters as the same page 2015-07-29 09:53:46 +02:00
Stefan Zermatten
58843613ba Merge branch 'release-0.6.7' 2015-07-27 13:12:42 +02:00
Stefan Zermatten
39b549b24b Bumped version 2015-07-27 13:12:28 +02:00
Stefan Zermatten
c79177de72 Added Google Analytics 2015-07-27 13:10:33 +02:00
Stefan Zermatten
11d09b1487 Fixed effect values not being visible on mobile 2015-07-27 12:16:02 +02:00
Stefan Zermatten
0e4918d57d Merge branch 'hotfix-style' 2015-07-27 12:08:22 +02:00
Stefan Zermatten
949f313af2 removed 1st column of all tables being 100px 2015-07-27 12:08:15 +02:00
Stefan Zermatten
85b63f152f Merge branch 'release-0.6.6' into develop 2015-07-27 11:23:12 +02:00
Stefan Zermatten
2141d52a7a Merge branch 'release-0.6.6' 2015-07-27 11:22:41 +02:00
Stefan Zermatten
4c84235064 Bumped version 2015-07-27 11:22:26 +02:00
Stefan Zermatten
0e194a5408 Added markdown to text areas 2015-07-27 10:21:26 +02:00
Stefan Zermatten
4b60eac330 Fixed typo on change log 2015-07-24 11:52:46 +02:00
Stefan Zermatten
cb017c359d Merge branch 'release-0.6.5' into develop 2015-07-24 11:31:05 +02:00
Stefan Zermatten
15aaaa5c14 Merge branch 'release-0.6.5' 2015-07-24 11:29:50 +02:00
Stefan Zermatten
290bee83b4 Bumped version 2015-07-24 11:29:03 +02:00
Stefan Zermatten
fcd2461205 Merge branch 'master' into release-0.6.5 2015-07-24 11:26:46 +02:00
Stefan Zermatten
52198d0249 Disabled edit buttons for read-only viewers 2015-07-23 15:07:39 +02:00
Stefan Zermatten
ba7ccfdfa0 Added support for character profile pictures 2015-07-23 15:04:43 +02:00
Stefan Zermatten
92d3b086fa net worth calculations now take into account your containers' values 2015-07-23 09:14:55 +02:00
Stefan Zermatten
e180595dcd Merge branch 'release-0.6.4' 2015-07-06 13:37:02 +02:00
Stefan Zermatten
ed708bdde0 bumped version 2015-07-06 13:36:50 +02:00
Stefan Zermatten
d7852d640f Fixed Math using min and max incorrectly in skills 2015-07-03 13:21:26 +02:00
Stefan Zermatten
a2fdee88b6 Ordered Character lists 2015-06-29 14:00:55 +02:00
Stefan Zermatten
af070b1578 Attacks inherit spell names correctly 2015-06-29 13:55:27 +02:00
Stefan Zermatten
83a8eeef0f Fixed editing of multiple attacks 2015-06-29 13:55:15 +02:00
Stefan Zermatten
34f8e7402b Hit dice constitution now has a + sign when positive 2015-06-29 10:21:49 +02:00
Stefan Zermatten
1b7e2cd850 Merge branch 'hotfix-rounding' into develop 2015-06-29 10:04:45 +02:00
Stefan Zermatten
463b7f0fc9 Merge branch 'hotfix-rounding' 2015-06-29 09:45:38 +02:00
Stefan Zermatten
266495abc8 Bumped version 2015-06-29 09:44:57 +02:00
Stefan Zermatten
453d4365d3 Prevent memoized values being used in dependency loops 2015-06-29 09:41:01 +02:00
Stefan Zermatten
e0ce6275bf Floor character attribute values 2015-06-29 09:40:37 +02:00
Stefan Zermatten
16b16ce6c6 Merge branch 'hotfix-minmax' into develop 2015-06-26 10:49:10 +02:00
Stefan Zermatten
80c72a274e Merge branch 'hotfix-minmax' 2015-06-26 10:48:43 +02:00
Stefan Zermatten
91f0f7954c Bumped version 2015-06-26 10:48:33 +02:00
Stefan Zermatten
c74abcb608 Fixed min and max error 2015-06-26 10:48:04 +02:00
Stefan Zermatten
da8b91594e Removed reference to character helper 2015-06-25 14:22:07 +02:00
Stefan Zermatten
fc26f5a73e Merge branch 'hotfix-experience-inputs' into develop 2015-06-25 14:20:54 +02:00
Stefan Zermatten
d2cc2833a9 Merge branch 'release-0.6.0' into develop 2015-06-25 13:48:32 +02:00
119 changed files with 1885 additions and 373 deletions

View File

@@ -1,58 +1,4 @@
TODO
====
RPG Docs
========
* Get Polymer installed using bower.
* Install Vulcanize package listed below
* Copy the differential polymer demo to get polymer implemented nicely
* Update Meteor
* Install and use LESS
Packages used
=============
* meteor-platform
* Base Meteor.
* [Docs](http://docs.meteor.com/#/full/)
* autopublish
* Publishes everything to the client.
* Must be removed before release
* insecure
* Allows the client the freedom to modify any colleciton.
* Must be removed before release
* iron:router
* Enables pagination and URL's to direct to specific templates.
* [Tutorial](http://www.manuel-schoebel.com/blog/iron-router-tutorial)
* accounts-password
* Lets users create accounts with a simple password
* accounts-ui
* Adds simple UI for logging in
* random
* Somewhat decent cryptographically strong psuedo random number generation.
* [readme](https://atmospherejs.com/meteor/random)
* dburles:collection-helpers
* Adds template-style helpers to collections. [github page](https://github.com/dburles/meteor-collection-helpers)
* reactive-var
* Friendly reactive variables
* [Meteor Docs](http://docs.meteor.com/#/full/reactivevar_pkg)
* cw4gn3r:jquery-event-drag
* Adds jquery drag events
* underscore
* Handy javascript utilities
* [Docs](http://underscorejs.org/)
* aldeed:collection2
* Extends collections with Schemas
* [(gitHub page)](https://github.com/aldeed/meteor-collection2)
* uses [SimpleSchema](https://github.com/aldeed/meteor-simple-schema)
* aldeed:autoform
* Automatically generates bootstrap forms for collection2 Schemas.
* [github](https://github.com/aldeed/meteor-autoform)
* differential:vulcanize
* Bakes all the polymer imports into one file
* [github](https://github.com/Differential/meteor-vulcanize)
************
Resources
=========
[differential's polymer demo](https://github.com/Differential/polymer-demo)
This is the repo for [DiceCloud](dicecloud.com). The currently deployed version should always be the head of the master branch.

1
rpg-docs/.gitignore vendored
View File

@@ -1,5 +1,6 @@
.meteor/local
.meteor/meteorite
settings.json
public/components
nohup.out
dump

View File

@@ -6,3 +6,7 @@ notices-for-0.9.0
notices-for-0.9.1
0.9.4-platform-file
notices-for-facebook-graph-api-2
1.2.0-standard-minifiers-package
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes

View File

@@ -1 +0,0 @@

View File

@@ -3,7 +3,6 @@
# 'meteor add' and 'meteor remove' will edit this file for you,
# but you can also edit it by hand.
meteor-platform
iron:router
accounts-password
accounts-ui
@@ -27,3 +26,19 @@ fourseven:scss@2.1.1
wolves:bourbon
meteorhacks:subs-manager
meteorhacks:kadira
chuangbo:marked
reywood:iron-router-ga
standard-minifiers
meteor-base
mobile-experience
mongo
blaze-html-templates
session
jquery
tracker
logging
reload
ejson
spacebars
check
useraccounts:iron-routing

View File

@@ -1 +1 @@
METEOR@1.1.0.2
METEOR@1.2.0.2

View File

@@ -1,94 +1,116 @@
accounts-base@1.2.0
accounts-google@1.0.4
accounts-oauth@1.1.5
accounts-password@1.1.1
accounts-ui@1.1.5
accounts-ui-unstyled@1.1.7
aldeed:collection2@2.3.3
accounts-base@1.2.1
accounts-google@1.0.6
accounts-oauth@1.1.7
accounts-password@1.1.3
accounts-ui@1.1.6
accounts-ui-unstyled@1.1.8
aldeed:collection2@2.5.0
aldeed:simple-schema@1.3.3
autoupdate@1.2.1
base64@1.0.3
binary-heap@1.0.3
blaze@2.1.2
blaze-tools@1.0.3
boilerplate-generator@1.0.3
callback-hook@1.0.3
check@1.0.5
coffeescript@1.0.6
autoupdate@1.2.3
babel-compiler@5.8.24_1
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.2
callback-hook@1.0.4
check@1.0.6
chuangbo:marked@0.3.5_1
coffeescript@1.0.10
dburles:collection-helpers@1.0.3
dburles:mongo-collection-instances@0.3.3
ddp@1.1.0
deps@1.0.7
differential:vulcanize@0.0.5
dburles:mongo-collection-instances@0.3.4
ddp@1.2.2
ddp-client@1.2.1
ddp-common@1.2.1
ddp-rate-limiter@1.0.0
ddp-server@1.2.1
deps@1.0.9
diff-sequence@1.0.1
differential:vulcanize@2.0.1
ecmascript@0.1.5
ecmascript-collections@0.1.6
ecwyne:mathjs@0.25.0
ejson@1.0.6
email@1.0.6
fastclick@1.0.3
ejson@1.0.7
email@1.0.7
fastclick@1.0.7
fourseven:scss@2.1.1
geojson-utils@1.0.3
google@1.1.5
html-tools@1.0.4
htmljs@1.0.4
http@1.1.0
id-map@1.0.3
iron:controller@1.0.7
iron:core@1.0.7
iron:dynamic-template@1.0.7
iron:layout@1.0.7
iron:location@1.0.7
iron:middleware-stack@1.0.7
iron:router@1.0.7
iron:url@1.0.7
jquery@1.11.3_2
json@1.0.3
lai:collection-extensions@0.1.3
launch-screen@1.0.2
less@1.0.14
livedata@1.0.13
localstorage@1.0.3
logging@1.0.7
matb33:collection-hooks@0.7.13
meteor@1.1.6
meteor-platform@1.2.2
meteorhacks:kadira@2.21.0
geojson-utils@1.0.4
google@1.1.6
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
id-map@1.0.4
iron:controller@1.0.8
iron:core@1.0.8
iron:dynamic-template@1.0.8
iron:layout@1.0.8
iron:location@1.0.9
iron:middleware-stack@1.0.9
iron:router@1.0.9
iron:url@1.0.9
jquery@1.11.4
lai:collection-extensions@0.1.4
launch-screen@1.0.4
less@2.5.0_3
livedata@1.0.15
localstorage@1.0.5
logging@1.0.8
matb33:collection-hooks@0.8.1
meteor@1.1.9
meteor-base@1.0.1
meteorhacks:kadira@2.23.4
meteorhacks:meteorx@1.3.1
meteorhacks:subs-manager@1.3.0
minifiers@1.1.5
minimongo@1.0.8
mobile-status-bar@1.0.3
momentjs:moment@2.10.3
mongo@1.1.0
mongo-livedata@1.0.8
meteorhacks:subs-manager@1.6.2
minifiers@1.1.7
minimongo@1.0.10
mobile-experience@1.0.1
mobile-status-bar@1.0.6
momentjs:moment@2.10.6
mongo@1.1.2
mongo-id@1.0.1
mongo-livedata@1.0.9
npm-bcrypt@0.7.8_2
oauth@1.1.4
oauth2@1.1.3
observe-sequence@1.0.6
ordered-dict@1.0.3
percolate:migrations@0.7.5
random@1.0.3
reactive-dict@1.1.0
reactive-var@1.0.5
reload@1.1.3
retry@1.0.3
routepolicy@1.0.5
service-configuration@1.0.4
session@1.1.0
sha@1.0.3
npm-mongo@1.4.39_1
oauth@1.1.6
oauth2@1.1.5
observe-sequence@1.0.7
ordered-dict@1.0.4
percolate:migrations@0.9.6
promise@0.5.0
random@1.0.4
rate-limit@1.0.0
reactive-dict@1.1.2
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
reywood:iron-router-ga@0.7.1
routepolicy@1.0.6
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
softwarerero:accounts-t9n@1.0.9
spacebars@1.0.6
spacebars-compiler@1.0.6
spacebars@1.0.7
spacebars-compiler@1.0.7
splendido:accounts-emails-field@1.2.0
splendido:accounts-meld@1.3.0
srp@1.0.3
templating@1.1.1
tracker@1.0.7
ui@1.0.6
underscore@1.0.3
url@1.0.4
useraccounts:core@1.9.1
useraccounts:polymer@1.9.1
webapp@1.2.0
webapp-hashing@1.0.3
wolves:bourbon@1.0.0
zimme:collection-behaviours@1.0.4
splendido:accounts-meld@1.3.1
srp@1.0.4
standard-minifiers@1.0.1
templating@1.1.4
templating-tools@1.0.0
tracker@1.0.9
ui@1.0.8
underscore@1.0.4
url@1.0.5
useraccounts:core@1.12.3
useraccounts:iron-routing@1.12.3
useraccounts:polymer@1.12.3
webapp@1.2.2
webapp-hashing@1.0.5
wolves:bourbon@1.2.0
zimme:collection-behaviours@1.1.3
zimme:collection-softremovable@1.0.4

View File

@@ -69,5 +69,17 @@ Attacks.attachSchema(Schemas.Attack);
Attacks.attachBehaviour("softRemovable");
makeChild(Attacks, ["name", "enabled"]); //children of lots of things
Attacks.after.insert(function (userId, attack) {
//Check to see if this attack's parent is a spell, if so, mirror prepared state to enabled
if (attack.parent.collection === "Spells") {
var parentSpell = Spells.findOne(attack.parent.id);
if (parentSpell.prepared === "unprepared") {
Attacks.update(attack._id, {$set: {enabled: false}});
} else if (parentSpell.prepared === "prepared" || "always") {
Attacks.update(attack._id, {$set: {enabled: true}});
}
}
});
Attacks.allow(CHARACTER_SUBSCHEMA_ALLOW);
Attacks.deny(CHARACTER_SUBSCHEMA_DENY);

View File

@@ -7,6 +7,7 @@ Schemas.Character = new SimpleSchema({
alignment: {type: String, defaultValue: "", trim: false, optional: true},
gender: {type: String, defaultValue: "", trim: false, optional: true},
race: {type: String, defaultValue: "", trim: false, optional: true},
picture: {type: String, defaultValue: "", trim: true, optional: true},
description: {type: String, defaultValue: "", trim: false, optional: true},
personality: {type: String, defaultValue: "", trim: false, optional: true},
ideals: {type: String, defaultValue: "", trim: false, optional: true},
@@ -32,6 +33,7 @@ Schemas.Character = new SimpleSchema({
age: {type: Schemas.Attribute},
ageRate: {type: Schemas.Attribute},
armor: {type: Schemas.Attribute},
carryMultiplier: {type: Schemas.Attribute},
//resources
level1SpellSlots: {type: Schemas.Attribute},
@@ -186,7 +188,7 @@ Schemas.Character = new SimpleSchema({
Characters.attachSchema(Schemas.Character);
var attributeBase = function(charId, statName){
var attributeBase = preventLoop(function(charId, statName){
check(statName, String);
//if it's a damage multiplier, we treat it specially
if (_.contains(DAMAGE_MULTIPLIERS, statName)){
@@ -226,8 +228,8 @@ var attributeBase = function(charId, statName){
var base = 0;
var add = 0;
var mul = 1;
var min = Math.NEGATIVE_INFINITY;
var max = Math.POSITIVE_INFINITY;
var min = Number.NEGATIVE_INFINITY;
var max = Number.POSITIVE_INFINITY;
Effects.find({
charId: charId,
@@ -253,8 +255,8 @@ var attributeBase = function(charId, statName){
if (result < min) result = min;
if (result > max) result = max;
return result;
};
return Math.floor(result);
});
if (Meteor.isClient) {
Template.registerHelper("characterCalculate", function(func, charId, input) {
@@ -324,9 +326,9 @@ Characters.calculate = {
value += attribute.adjustment;
return value;
}),
attributeBase: memoize(preventLoop(function(charId, attributeName){
attributeBase: memoize(function(charId, attributeName){
return attributeBase(charId, attributeName);
})),
}),
skillMod: memoize(preventLoop(function(charId, skillName){
var skill = Characters.calculate.getField(charId, skillName);
//get the final value of the ability score
@@ -345,8 +347,8 @@ Characters.calculate = {
var value;
var add = 0;
var mul = 1;
var min = Math.NEGATIVE_INFINITY;
var max = Math.POSITIVE_INFINITY;
var min = Number.NEGATIVE_INFINITY;
var max = Number.POSITIVE_INFINITY;
Effects.find({
charId: charId,
@@ -369,7 +371,7 @@ Characters.calculate = {
if (result < min) result = min;
if (result > max) result = max;
return result;
return Math.floor(result);
})),
proficiency: memoize(function(charId, skillName){
//return largest value in proficiency array
@@ -390,7 +392,7 @@ Characters.calculate = {
});
var advantage = Characters.calculate.advantage(charId, skillName);
value += 5 * advantage;
return value;
return Math.floor(value);
}),
advantage: memoize(function(charId, skillName){
var advantage = Effects.find(

View File

@@ -107,6 +107,18 @@ if (Meteor.isServer) Characters.after.insert(function(userId, char) {
group: "Inate",
},
});
Effects.insert({
charId: char._id,
name: "Natural Carrying Capacity",
stat: "carryMultiplier",
operation: "base",
value: "1",
parent: {
id: char._id,
collection: "Characters",
group: "Inate",
},
});
});
Effects.attachBehaviour("softRemovable");

View File

@@ -30,7 +30,7 @@ Schemas.Proficiency = new SimpleSchema({
Proficiencies.attachSchema(Schemas.Proficiency);
Proficiencies.attachBehaviour("softRemovable");
makeChild(Proficiencies);
makeChild(Proficiencies, ["enabled"]);
Proficiencies.allow(CHARACTER_SUBSCHEMA_ALLOW);
Proficiencies.deny(CHARACTER_SUBSCHEMA_DENY);

View File

@@ -62,6 +62,23 @@ Spells.attachSchema(Schemas.Spell);
Spells.attachBehaviour("softRemovable");
makeChild(Spells); //children of spell lists
makeParent(Spells, ["name", "enabled"]); //parents of attacks
Spells.after.update(function (userId, spell, fieldNames) {
//Update prepared state of spell and child attacks to be enabled or not
if (_.contains(fieldNames, "prepared")) {
var childAttacks = Attacks.find({"parent.id": spell._id}).fetch();
if (spell.prepared === "unprepared") {
_.each(childAttacks, function(attack){
Attacks.update(attack._id, {$set: {enabled: false}});
});
} else if (spell.prepared === "prepared" || "always") {
_.each(childAttacks, function(attack){
Attacks.update(attack._id, {$set: {enabled: true}});
});
}
}
});
Spells.allow(CHARACTER_SUBSCHEMA_ALLOW);
Spells.deny(CHARACTER_SUBSCHEMA_DENY);

View File

@@ -3,9 +3,9 @@ TemporaryHitPoints = new Mongo.Collection("temporaryHitPoints");
Schemas.TemporaryHitPoints = new SimpleSchema({
charId: {type: String, regEx: SimpleSchema.RegEx.Id},
name: {type: String, optional: true},
maximum: {type: Number, defaultValue: 0},
used: {type: Number, defaultValue: 0},
deleteOnZero:{type: Boolean, defaultValue: true},
maximum: {type: Number, defaultValue: 0, min: 0, max: 500},
used: {type: Number, defaultValue: 0, min: 0, max: 500},
deleteOnZero:{type: Boolean, defaultValue: false},
dateAdded: {
type: Date,
autoValue: function() {

View File

@@ -1,6 +1,7 @@
Router.configure({
loadingTemplate: "loading",
layoutTemplate: "layout",
trackPageView: true,
});
Router.plugin("ensureSignedIn", {
@@ -27,7 +28,7 @@ Router.map(function() {
},
data: {
characters: function(){
return Characters.find({}, {fields: {_id: 1}});
return Characters.find({}, {fields: {_id: 1}, sort: {name: 1}});
}
},
onAfterAction: function() {
@@ -56,6 +57,12 @@ Router.map(function() {
document.title = name;
}
},
//analytics
trackPageView: false,
onRun: function() {
window.ga && window.ga("send", "pageview", "/character");
this.next();
},
});
this.route("loading", {

View File

@@ -77,10 +77,10 @@ this.GlobalUI = (function() {
var throttleBack = _.throttle(function() {
history.back();
}, 800, {trailing: false});
}, 100, {trailing: false});
GlobalUI.closeDetail = function() {
if (!!(window.history && window.history.pushState)) {
if (window.history && history.pushState && history.state.detail === "opened") {
throttleBack();
} else {
Session.set("global.ui.detailShow", false);

View File

@@ -1,6 +1,10 @@
Template.registerHelper("canEditCharacter", function(charId) {
return canEditCharacter(charId);
});
canEditCharacter = function(charId) {
var char = Characters.findOne(charId)
var userId = Meteor.userId();
return char.owner === userId ||
_.contains(char.writers, userId);
});
};

View File

@@ -3,17 +3,24 @@
$thickColumnWidth: 304px;
$thinColumnWidth: 240px;
//Column layouts of cards
//Column layout
.column-container {
@include column-fill(balance);
@include column-gap(8px);
@include column-gap(0px);
@include column-width($thickColumnWidth);
padding: 8px;
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
@@ -21,20 +28,6 @@ $thinColumnWidth: 240px;
background: white;
border-radius: 2px;
.column-container & {
margin-bottom: 8px;
width: 100%;
//hack to stop flickering
-webkit-backface-visibility: hidden;
-webkit-transform: translateX(0);
//stop breaking over column divide
-webkit-column-break-inside: avoid;
page-break-inside: avoid;
break-inside: avoid;
//Fixes extra margin at top of columns
display: inline-block;
}
.top {
cursor: pointer;
padding: 16px;

View File

@@ -29,6 +29,11 @@ core-header-panel[drawer] {
box-shadow: 2px 0px 5px 0px rgba(0,0,0,0.2);
}
//Paragraphs
p {
margin-bottom: 8px;
}
//Horizontal rule
hr {
background-color: #444;
@@ -37,7 +42,7 @@ hr {
color: #444;
height: 1px;
line-height: 0;
margin: 16px -16px;
margin: 16px 0;
text-align: center;
}

View File

@@ -1,8 +1,5 @@
td {
padding: 8px;
&:nth-child(1) {
min-width: 100px;
}
}
.strengthTable{

View File

@@ -3,26 +3,26 @@
<div layout vertical flex>
<div layout horizontal>
<!--attackBonus-->
<paper-input id="attackBonusInput"
<paper-input class="attackBonusInput"
label="Attack Bonus"
floatinglabel
value={{attackBonus}}
flex></paper-input>
<!--details-->
<paper-input id="detailInput"
<paper-input class="detailInput"
label="Details"
floatinglabel
value={{details}}></paper-input>
</div>
<div layout horizontal>
<!--damageBonus-->
<paper-input id="damageInput"
<paper-input class="damageInput"
label="Damage"
floatinglabel
value={{damage}}
flex></paper-input>
<!--DamageType-->
<paper-dropdown-menu id="damageTypeDropdown" label="Damage Type">
<paper-dropdown-menu class="damageTypeDropdown" label="Damage Type">
<paper-dropdown layered class="dropdown">
<core-menu class="menu" selected={{damageType}}>
{{#each damageTypes}}
@@ -34,6 +34,6 @@
</div>
</div>
<!--Delete Button-->
<paper-icon-button id="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
<paper-icon-button class="deleteAttack" role="button" tabindex="0" icon="delete" aria-label="Delete"></paper-icon-button>
</div>
</template>

View File

@@ -15,23 +15,23 @@ var damageTypes = [
];
Template.attackEdit.events({
"tap #deleteAttack": function(event, instance) {
"tap .deleteAttack": function(event, instance) {
Attacks.softRemoveNode(this._id);
GlobalUI.deletedToast(this._id, "Attacks", "Attack");
},
"change #attackBonusInput": function(event) {
"change .attackBonusInput": function(event) {
var value = event.currentTarget.value;
Attacks.update(this._id, {$set: {attackBonus: value}});
},
"change #damageInput": function(event) {
"change .damageInput": function(event) {
var value = event.currentTarget.value;
Attacks.update(this._id, {$set: {damage: value}});
},
"change #detailInput": function(event) {
"change .detailInput": function(event) {
var value = event.currentTarget.value;
Attacks.update(this._id, {$set: {details: value}});
},
"core-select #damageTypeDropdown": function(event) {
"core-select .damageTypeDropdown": function(event) {
var detail = event.originalEvent.detail;
if (!detail.isSelected) return;
var value = detail.item.getAttribute("name");

View File

@@ -44,7 +44,8 @@
label="Value"
floatinglabel
value={{effectValue}}
flex>
flex
style="flex-basis: 100px;">
</paper-input>
</template>

View File

@@ -42,6 +42,7 @@ var stats = [
{stat: "rageDamage", name: "Rage Damage", group: "Stats"},
{stat: "expertiseDice", name: "Expertise Dice", group: "Stats"},
{stat: "superiorityDice", name: "Superiority Dice", group: "Stats"},
{stat: "carryMultiplier", name: "Carry Capacity Multiplier", group: "Stats"},
{stat: "level1SpellSlots", name: "level 1", group: "Spell Slots"},
{stat: "level2SpellSlots", name: "level 2", group: "Spell Slots"},
{stat: "level3SpellSlots", name: "level 3", group: "Spell Slots"},

View File

@@ -42,6 +42,7 @@ var stats = {
"rageDamage":{"name":"Rage Damage"},
"expertiseDice":{"name":"Expertise Dice"},
"superiorityDice":{"name":"Superiority Dice"},
"carryMultiplier": {"name": "Carry Capacity Multiplier"},
"level1SpellSlots":{"name":"level 1 Spell Slots"},
"level2SpellSlots":{"name":"level 2 Spell Slots"},
"level3SpellSlots":{"name":"level 3 Spell Slots"},

View File

@@ -32,7 +32,7 @@
{{/if}}
{{#if description}}
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{/if}}
{{> effectsViewList charId=charId parentId=_id}}

View File

@@ -12,8 +12,9 @@
{{>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">
<div class="top white">
Attacks
@@ -48,8 +49,10 @@
{{/each}}
</div>
</paper-shadow>
</div>
<!--Proficiencies-->
<div>
<paper-shadow class="card">
<div class="white top">
Proficiencies
@@ -75,13 +78,15 @@
{{/each}}
</div>
</paper-shadow>
</div>
<!--features-->
{{#each features}}
<div>
<paper-shadow class="card featureCard"
hero-id="main" {{detailHero}}>
<div class="top {{colorClass}} subhead"
layout horizontal
<div class="top {{colorClass}} subhead"
layout horizontal
hero-id="toolbar" {{detailHero}}>
<div flex hero-id="title" {{detailHero}}>
{{name}}
@@ -94,41 +99,44 @@
{{#if canEnable}}
<core-tooltip label="Feature enabled"
position="left">
<paper-checkbox class="enabledCheckbox"
checked={{enabled}}>
<paper-checkbox class="enabledCheckbox"
checked={{enabled}}
disabled={{#unless canEditCharacter charId}}true{{/unless}}>
</paper-checkbox>
</core-tooltip>
{{/if}}
</div>
{{#if description}}
<div flex class="bottom text"
>{{evaluateString charId description}}</div>
<div flex class="bottom">
{{#markdown}}{{evaluateString charId shortDescription}}{{/markdown}}
</div>
{{/if}}
{{#if hasUses}}
<div layout horizontal center end-justified>
<paper-button class="useFeature"
<paper-button class="useFeature"
disabled={{noUsesLeft}}>
Use
</paper-button>
<paper-button class="resetFeature"
<paper-button class="resetFeature"
disabled={{usesFull}}>
Reset
</paper-button>
</div>
{{/if}}
</paper-shadow>
</div>
{{/each}}
</div>
<div class="fab-buffer"></div>
</div>
{{#if canEditCharacter _id}}
<paper-fab id="addFeature"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
aria-label="Add"
<paper-fab id="addFeature"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
aria-label="Add"
hero-id="main"></paper-fab>
{{/if}}
</div>
@@ -136,15 +144,16 @@
<template name="resource">
{{#if characterCalculate "attributeBase" char._id name}}
<paper-shadow class="card"
<div>
<paper-shadow class="card"
hero-id="main" {{detailHero name char._id}}
layout horizontal>
<div class="left {{getColor}} display1 white-text"
<div class="left {{getColor}} display1 white-text"
hero-id="toolbar" {{detailHero name char._id}}
layout horizontal center>
<div style="margin-right: 8px;">
<paper-icon-button class="resourceUp"
icon="arrow-drop-up"
<paper-icon-button class="resourceUp"
icon="arrow-drop-up"
disabled={{cantIncrement}}>
</paper-icon-button>
<paper-icon-button class="resourceDown"
@@ -155,10 +164,11 @@
<div>{{characterCalculate "attributeValue" char._id name}}</div>
<!--<div>/{{char.attributeBase name}}</div>-->
</div>
<div class="right clickable"
<div class="right clickable"
flex layout horizontal center>
{{title}}
</div>
</paper-shadow>
</div>
{{/if}}
</template>

View File

@@ -3,14 +3,19 @@ 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;
},
noUsesLeft: function(){
return this.usesLeft() <= 0;
return this.usesLeft() <= 0 || !canEditCharacter(this.charId);
},
usesFull: function(){
return this.usesLeft() >= this.usesValue();
return this.usesLeft() >= this.usesValue() || !canEditCharacter(this.charId);
},
colorClass: function(){
return getColorClass(this.color);
@@ -99,15 +104,16 @@ Template.resource.helpers({
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var base = Characters.calculate.attributeBase(this.char._id, this.name);
var baseBigger = value < base;
return !baseBigger;
return !baseBigger || !canEditCharacter(this.char._id);
},
cantDecrement: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var valuePositive = value > 0;
return !valuePositive;
return !valuePositive || !canEditCharacter(this.char._id);
},
getColor: function(){
if (this.char.attributeValue(this.name) > 0){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
if (value > 0){
return this.color;
} else {
return "grey";

View File

@@ -14,7 +14,9 @@ var getFractionCarried = function(char) {
});
//get strength
var strength = Characters.calculate.attributeValue(char._id, "strength");
var capacity = strength * 15;
var carryMultiplier = Characters.calculate
.attributeValue(char._id, "carryMultiplier");
var capacity = strength * 15 * carryMultiplier;
return weight / capacity;
};

View File

@@ -41,6 +41,6 @@
</div>
{{#if description}}
<hr class="vertMargin">
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{/if}}
</template>

View File

@@ -3,6 +3,7 @@
<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>
@@ -13,7 +14,9 @@
</div>
</div>
</paper-shadow>
</div>
<!--Weight Carried-->
<div>
<paper-shadow class="card"
hero-id="main" {{detailHero "weightCarried" _id}}>
<div class="top green white-text weightCarried"
@@ -35,8 +38,7 @@
<div class="item-slot">
<div class="item buff"
hero-id="main" {{detailHero}}
layout horizontal center
draggable="true">
layout horizontal center>
<div flex>
<core-icon icon="work"
style="margin-right: 16px">
@@ -49,7 +51,9 @@
</div>
{{/if}}
</paper-shadow>
</div>
<!--Equipment-->
<div>
<paper-shadow class="card equipmentContainer">
<div class="white top" layout horizontal center>
<div class="subhead" flex>
@@ -77,7 +81,9 @@
{{/each}}
</div>
</paper-shadow>
</div>
<!--Carried Items-->
<div>
<paper-shadow class="card carriedContainer">
<div class="white top" layout horizontal center>
<div class="subhead" flex>
@@ -96,8 +102,10 @@
{{/each}}
</div>
</paper-shadow>
</div>
{{#each containers}}
<paper-shadow class="card itemContainer"
<div>
<paper-shadow class="card itemContainer"
hero-id="main" {{detailHero}}>
<div class="top {{colorClass}}"
hero-id="toolbar" {{detailHero}}
@@ -114,6 +122,7 @@
</div>
<core-tooltip label="Container carried" position="left">
<paper-checkbox class="carriedCheckbox"
disabled={{#unless canEditCharacter charId}}true{{/unless}}
checked={{isCarried}}>
</paper-checkbox>
</core-tooltip>
@@ -124,6 +133,7 @@
{{/each}}
</div>
</paper-shadow>
</div>
{{/each}}
</div>
<div class="fab-buffer"></div>
@@ -152,11 +162,11 @@
<div class="item {{hidden}} inventoryItem"
hero-id="main" {{detailHero}}
layout horizontal center
draggable="true">
draggable={{canEditCharacter charId}}>
<div flex class="itemName">
{{#if ne1 quantity}}{{quantity}}&nbsp;{{/if}}{{pluralName}}
</div>
{{#if settings.showIncrement}}
{{#if settings.showIncrement}}{{#if canEditCharacter charId}}
<div class="incrementButtons">
<paper-icon-button class="addItemQuantity"
icon="add"
@@ -166,7 +176,7 @@
icon="remove"
style="margin-right: -8px"></paper-icon-button>
</div>
{{/if}}
{{/if}}{{/if}}
</div>
</div>
</template>

View File

@@ -44,6 +44,12 @@ Template.inventory.helpers({
).forEach(function(item){
worth += item.totalValue();
});
Containers.find(
{charId: this._id},
{fields: {value : 1}}
).forEach(function(container) {
if (container.value) worth += container.value;
});
return worth;
},
weightCarried: function(){

View File

@@ -18,8 +18,8 @@
{{#if requiresAttunement}}<div class="vertMargin">Requires Attunement</div>{{/if}}
</div>
{{#if description}}
<hr class="vertMargin">
<div class="pre-wrap">{{evaluateString charId description}}</div>
<hr style="margin: 16px 0 16px 0;">
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{/if}}
{{> effectsViewList charId=charId parentId=_id}}
{{> attacksViewList charId=charId parentId=_id}}

View File

@@ -6,7 +6,7 @@
</div>
{{#if description}}
<hr class="vertMargin">
<div class="pre-wrap">{{description}}</div>
<div>{{#markdown}}{{description}}{{/markdown}}</div>
{{/if}}
{{else}}
{{> experienceEdit}}

View File

@@ -3,14 +3,15 @@
<div id="journal" class="scroll-y" fit>
<div class="column-container">
<!--Experience Table-->
<paper-shadow class="card experiencesCard"
<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"></paper-icon-button>
<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}}
@@ -36,9 +37,9 @@
</paper-button>
</div>
{{/if}}
</paper-shadow>
</paper-shadow></div>
<!--Class Table-->
<paper-shadow class="card"
<div><paper-shadow class="card"
hero-id="main" {{detailHero}}>
<div class="white top"
hero-id="toolbar" {{detailHero}}
@@ -55,7 +56,8 @@
</div>
<paper-icon-button class="black54"
id="addClassButton"
icon="add">
icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
</paper-icon-button>
</div>
<div class="bottom list">
@@ -76,29 +78,31 @@
</div>
{{/each}}
</div>
</paper-shadow>
</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 text">{{description}}</div>
<div class="bottom">{{#markdown}}{{description}}{{/markdown}}</div>
</paper-shadow>
</div>
{{/each}}
</div>
<div class="fab-buffer"></div>
</div>
</div>
{{#if canEditCharacter _id}}
<paper-fab id="addNote"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
<paper-fab id="addNote"
class="floatyButton"
icon="add"
title="Add"
role="button"
tabindex="0"
hero-id="main"></paper-fab>
{{/if}}
</template>
</template>

View File

@@ -1,7 +1,7 @@
<template name="noteDialog">
{{#with note}}
{{#baseDialog title=name class=colorClass startEditing=../startEditing}}
<div class="pre-wrap">{{description}}</div>
<div>{{#markdown}}{{description}}{{/markdown}}</div>
{{else}}
{{> noteDialogEdit}}
{{/baseDialog}}

View File

@@ -1,6 +1,6 @@
<template name="backgroundDialog">
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
<div class="pre-wrap">{{evaluateString charId value}}</div>
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true"}}
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
{{> proficiencyViewList charId=charId parentId=charId parentGroup="background"}}
{{else}}
{{> textDialogEdit}}

View File

@@ -1,18 +1,36 @@
<template name="personaDetailsDialog">
{{#baseDialog title=name class="deep-purple white-text" hideColor="true" hideDelete="true" startEditing=startEditing}}
{{alignment}} {{gender}} {{race}}
{{#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>
{{/with}}
{{else}}
{{> personaDetailsEdit}}
{{#with char}}
{{> personaDetailsEdit}}
{{/with}}
{{/baseDialog}}
</template>
<template name="personaDetailsEdit">
<!--Name-->
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input><br>
<!--Alignment-->
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input><br>
<!--Gender-->
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input><br>
<!--Race-->
<paper-input id="raceInput" label="Race" floatinglabel value={{race}}></paper-input><br>
<div layout horizontal center-justified>
<div flex style="max-width: 350px;" layout vertical>
<!--Name-->
<paper-input id="nameInput" label="Name" floatinglabel value={{name}}></paper-input>
<!--Alignment-->
<paper-input id="alignmentInput" label="Alignment" floatinglabel value={{alignment}}></paper-input>
<!--Gender-->
<paper-input id="genderInput" label="Gender" floatinglabel value={{gender}}></paper-input>
<!--Race-->
<paper-input id="raceInput" label="Race" floatinglabel 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>
</div>
</div>
</template>

View File

@@ -2,21 +2,34 @@ Template.personaDetailsEdit.onRendered(function(){
updatePolymerInputs(this);
});
Template.personaDetailsDialog.helpers({
char: function() {
return Characters.findOne(
this._id,
{fields: {name: 1, alignment: 1, gender: 1, race: 1, picture: 1}}
);
}
});
Template.personaDetailsEdit.events({
"change #nameInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {name: input}});
Characters.update(this._id, {$set: {name: input}});
},
"change #alignmentInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {alignment: input}});
Characters.update(this._id, {$set: {alignment: input}});
},
"change #genderInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {gender: input}});
Characters.update(this._id, {$set: {gender: input}});
},
"change #raceInput": function(event){
var input = event.currentTarget.value;
Characters.update(this.charId, {$set: {race: input}});
Characters.update(this._id, {$set: {race: input}});
},
"change #pictureInput": function(event){
var input = event.currentTarget.value;
Characters.update(this._id, {$set: {picture: input}});
},
});

View File

@@ -3,14 +3,45 @@
<div id="persona" class="scroll-y" fit>
<div class="column-container">
{{#with characterDetails}}
{{#containerCardHelper this}}{{alignment}} {{gender}} {{race}}{{/containerCardHelper}}
<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>
</div>
</paper-shadow>
</div>
{{/with}}
{{> containerCard characterField "description" "Description"}}
{{> containerCard characterField "personality" "Personality Traits"}}
{{> containerCard characterField "ideals" "Ideals"}}
{{> containerCard characterField "bonds" "Bonds"}}
{{> containerCard characterField "flaws" "Flaws"}}
{{> containerCard characterField "backstory" "Background"}}
<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
@@ -21,6 +52,7 @@
{{/each}}
</div>
</paper-shadow>
</div>
</div>
</div>
</div>
@@ -40,6 +72,6 @@
{{title}}
</div>
</div>
<div class="bottom text">{{> UI.contentBlock}}</div>
<div class="bottom">{{#markdown}}{{> UI.contentBlock}}{{/markdown}}</div>
</paper-shadow>
</template>
</template>

View File

@@ -11,12 +11,12 @@ Template.persona.helpers({
characterDetails: function(){
var char = Characters.findOne(
this._id,
{fields: {name: 1, gender: 1, alignment: 1, race:1}}
{fields: {name: 1, gender: 1, alignment: 1, race:1, picture: 1}}
);
char.field = "details";
char.title = char.name;
char.color = "d";
char.topClass = "characterField";
char.startEditing = true;
return char;
},
characterField: function(field, title){
@@ -40,7 +40,7 @@ Template.persona.helpers({
Template.persona.events({
"tap .characterField": function(event){
if (this.field === "details"){
if (this.field == "details"){
this.charId = Template.parentData()._id;
GlobalUI.setDetail({
template: "personaDetailsDialog",
@@ -58,6 +58,7 @@ Template.persona.events({
field: this.field,
title: this.title,
color: this.color,
startEditing: true,
},
heroId: this._id + this.field,
});

View File

@@ -1,6 +1,6 @@
<template name="textDialog">
{{#baseDialog title=title class=colorClass hideColor="true" hideDelete="true" startEditing=startEditing}}
<div class="pre-wrap">{{evaluateString charId value}}</div>
<div>{{#markdown}}{{evaluateString charId value}}{{/markdown}}</div>
{{else}}
{{> textDialogEdit}}
{{/baseDialog}}

View File

@@ -34,7 +34,7 @@
</div>
{{/if}}
</div>
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
{{> attacksViewList charId=charId parentId=_id}}
</template>

View File

@@ -20,7 +20,7 @@
{{/if}}
</div>
<hr class="vertMargin">
<div class="pre-wrap">{{evaluateString charId description}}</div>
<div>{{#markdown}}{{evaluateString charId description}}{{/markdown}}</div>
</div>
{{else}}
<!--Name-->

View File

@@ -1,7 +1,7 @@
<template name="spells">
<div fit>
<div id="spells" class="scroll-y" fit>
<div style="padding: 4px;"
<div style="padding: 4px;"
layout horizontal start wrap>
{{#if hasSlots}}
<paper-shadow class="card"
@@ -72,6 +72,7 @@
<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>
@@ -91,7 +92,7 @@
<div class="tall spell item"
hero-id="main" {{detailHero}}
layout horizontal center>
<core-icon icon="social:whatshot"
<core-icon icon="social:whatshot"
style="color: {{hexColor color}};
margin-right: 16px;"
></core-icon>
@@ -143,4 +144,4 @@
</core-tooltip>
{{/fabMenu}}
{{/if}}
</template>
</template>

View File

@@ -112,7 +112,7 @@ Template.spells.helpers({
for (i = 0; i < currentSlots; i++){
bubbles.push({
icon: "radio-button-on",
disabled: i !== currentSlots - 1, //last full slot not disabled
disabled: i !== currentSlots - 1 || !canEditCharacter(char._id), //last full slot not disabled
attribute: "level" + this.level + "SpellSlots",
charId: char._id,
});
@@ -120,7 +120,7 @@ Template.spells.helpers({
for (i = 0; i < slotsUsed; i++){
bubbles.push({
icon: "radio-button-off",
disabled: i !== 0, //first empty slot not disabled
disabled: i !== 0 || !canEditCharacter(char._id), //first empty slot not disabled
attribute: "level" + this.level + "SpellSlots",
charId: char._id,
});

View File

@@ -1,5 +1,6 @@
<template name="abilityMiniCard">
<paper-shadow class="card abilityMiniCard clickable"
<div>
<paper-shadow class="card abilityMiniCard clickable"
hero-id="main" {{detailHero ability ../_id}}
layout horizontal>
<div class="left white-text {{color}}"
@@ -11,4 +12,5 @@
{{title}}
</div>
</paper-shadow>
</div>
</template>

View File

@@ -1,9 +1,11 @@
Template.addTHPDialog.events({
"tap #addButton": function(event, instance){
var max = +instance.find("#quantityInput").value;
if (!max || max < 0) max = 0;
TemporaryHitPoints.insert({
charId: this.charId,
name: instance.find("#nameInput").value,
maximum: +instance.find("#quantityInput").value,
maximum: max,
deleteOnZero: !!instance.find("#deleteWhenZeroCheckbox").checked,
});
}

View File

@@ -2,27 +2,27 @@
<table class="carryCapacityTable strengthTable">
<tr>
<td>Encumbered</td>
<td>&gt;{{evaluate charId "strength * 5"}}lbs</td>
<td>&gt;{{evaluate charId "strength * 5 * carryMultiplier"}}lbs</td>
<td class="caption">Variant rule, encumbered characters move 10 feet slower</td>
</tr>
<tr>
<td>Heavily encumbered</td>
<td>&gt;{{evaluate charId "strength * 10"}}lbs</td>
<td>&gt;{{evaluate charId "strength * 10 * carryMultiplier"}}lbs</td>
<td class="caption">
Variant rule, heavily encumbered characters move 20 feet slower and have disadvantage on ability checks, attack rolls, and saving thows that use Strength, Dexterity, or Constitution
</td>
</tr>
<tr>
<td>Over Encumbered</td>
<td>&gt;{{evaluate charId "strength * 15"}}lbs</td>
<td>&gt;{{evaluate charId "strength * 15 * carryMultiplier"}}lbs</td>
<td class="caption">
Characters that can only just lift, push or drag their current load can only move at 5 feet.
</td>
</tr>
<tr>
<td>Push, drag or lift maximum</td>
<td>{{evaluate charId "strength * 30"}}lbs</td>
<td>{{evaluate charId "strength * 30 * carryMultiplier"}}lbs</td>
<td class="caption"></td>
</tr>
</table>
</template>
</template>

View File

@@ -1,12 +1,16 @@
<template name="healthCard">
<paper-shadow class="card container healthCard"
hero-id="main" {{detailHero "hitPoints" _id}}
<paper-shadow class="card container healthCard"
hero-id="main" {{detailHero "hitPoints" _id}}
layout horizontal wrap>
<div class="green white-text subhead left"
<div class="green white-text subhead left"
hero-id="toolbar" {{detailHero "hitPoints" _id}}
layout vertical center center-justified>
<div class="hitPointTitle clickable">Hit Points</div>
<paper-icon-button class="white54" id="addTempHP" icon="add"></paper-icon-button>
<paper-icon-button class="white54"
id="addTempHP"
icon="add"
disabled={{#unless canEditCharacter _id}}true{{/unless}}>
</paper-icon-button>
</div>
<div class="right" flex layout vertical center-justified style="min-width: 180px;">
<div layout horizontal>
@@ -14,6 +18,7 @@
value={{characterCalculate "attributeValue" _id "hitPoints"}}
max={{characterCalculate "attributeBase" _id "hitPoints"}}
editable pin
disabled={{#unless canEditCharacter _id}}true{{/unless}}
role="slider">
</paper-diff-slider>
</div>
@@ -28,14 +33,14 @@
role="slider"
flex
></paper-diff-slider>
{{#unless left}}{{#unless deleteOnZero}}
{{#unless left}}
<paper-icon-button class="deleteTHP" icon="delete"></paper-icon-button>
{{/unless}}{{/unless}}
{{/unless}}
</div>
</div>
{{/each}}
<div class="caption">
{{#if multipliers.immunities.length}}
{{#if multipliers.immunities.length}}
<div>
Immune: {{#each multipliers.immunities}} {{name}} {{/each}}
</div>

View File

@@ -1,14 +1,15 @@
<template name="hitDice">
{{#if characterCalculate "attributeBase" ../_id name}}
<paper-shadow class="card hit-dice" hero-id="main"
{{detailHero name ../_id}}
<div>
<paper-shadow class="card hit-dice" hero-id="main"
{{detailHero name ../_id}}
layout horizontal>
<div class="left green display1 white-text"
<div class="left green display1 white-text"
hero-id="toolbar" {{detailHero name ../_id}}
layout horizontal>
<div>
<paper-icon-button class="resourceUp"
icon="arrow-drop-up"
<paper-icon-button class="resourceUp"
icon="arrow-drop-up"
disabled={{cantIncrement}}>
</paper-icon-button>
<paper-icon-button class="resourceDown"
@@ -21,7 +22,7 @@
{{characterCalculate "attributeValue" ../_id name}}
</div>
<div class="title white-text">
d{{diceNum}} {{characterCalculate "abilityMod" ../_id "constitution"}}
d{{diceNum}} {{conMod}}
</div>
</div>
</div>
@@ -29,5 +30,6 @@
Hit Dice
</div>
</paper-shadow>
</div>
{{/if}}
</template>

View File

@@ -2,11 +2,16 @@ Template.hitDice.helpers({
cantIncrement: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
var base = Characters.calculate.attributeBase(this.char._id, this.name);
return value >= base;
return value >= base || !canEditCharacter(this.char._id);
},
cantDecrement: function(){
var value = Characters.calculate.attributeValue(this.char._id, this.name);
return value <= 0;
return value <= 0 || !canEditCharacter(this.char._id);
},
conMod: function(){
return signedString(
Characters.calculate.abilityMod(this.char._id, "constitution")
);
},
});

View File

@@ -27,6 +27,7 @@
{{>hitDice name="d10HitDice" diceNum="10" char=this}}
{{>hitDice name="d12HitDice" diceNum="12" char=this}}
<!--Saving Throws-->
<div>
<paper-shadow class="card">
<div class="top white subhead">
Saving Throws
@@ -40,7 +41,9 @@
{{> skillRow name="Charisma" skill="charismaSave"}}
</div>
</paper-shadow>
</div>
<!--Skills-->
<div>
<paper-shadow class="card">
<div class="top white subhead">
Skills
@@ -66,11 +69,13 @@
{{> skillRow name="Survival" skill="survival"}}
</div>
</paper-shadow>
</div>
</div>
</div>
</template>
<template name="statCard">
<div>
<paper-shadow class="card statCard clickable" hero-id="main" {{detailHero stat ../_id}} layout horizontal>
<div class="left display1 white-text {{color}}"
hero-id="toolbar" {{detailHero stat ../_id}}>
@@ -84,4 +89,5 @@
{{name}}
</div>
</paper-shadow>
</div>
</template>

View File

@@ -13,7 +13,10 @@ Template.characterSideList.helpers({
{owner: userId},
]
},
{fields: {name: 1}}
{
fields: {name: 1},
sort: {name: 1},
}
);
}
});

View File

@@ -45,6 +45,15 @@
</div>
<div class="bottom text">Lawful Good Human</div>
</paper-shadow>
<paper-shadow class="card characterCard ssWizard clickable"
z="2">
<div class="top subhead deep-purple white-text">
<div class="subhead" flex>
Starter Set Wizard
</div>
</div>
<div class="bottom text">Chaotic Good High Elf</div>
</paper-shadow>
</div>
</div>
</div>

View File

@@ -8,6 +8,9 @@ Template.intro.events({
"tap .ssArcher": function() {
Router.go("/character/yBWwt5XQTTHZiRQxq");
},
"tap .ssWizard": function() {
Router.go("/character/KxHKskm22fS2Xogah");
},
"tap .guideButton": function() {
Router.go("/guide");
},

View File

@@ -1,44 +0,0 @@
<!--core components-->
<link rel="import" href="/components/core-animated-pages/core-animated-pages.html">
<link rel="import" href="/components/core-animated-pages/transitions/cross-fade.html">
<link rel="import" href="/components/core-animated-pages/transitions/hero-transition.html">
<link rel="import" href="/components/core-animated-pages/transitions/slide-from-right.html">
<link rel="import" href="/components/core-icons/av-icons.html">
<link rel="import" href="/components/core-icons/core-icons.html">
<link rel="import" href="/components/core-icons/editor-icons.html">
<link rel="import" href="/components/core-icons/image-icons.html">
<link rel="import" href="/components/core-icons/social-icons.html">
<link rel="import" href="/components/core-image/core-image.html">
<link rel="import" href="/components/core-item/core-item.html">
<link rel="import" href="/components/core-menu/core-menu.html">
<link rel="import" href="/components/core-scaffold/core-scaffold.html">
<link rel="import" href="/components/core-transition/core-transition.html">
<!--paper components-->
<link rel="import" href="/components/paper-button/paper-button.html">
<link rel="import" href="/components/paper-checkbox/paper-checkbox.html">
<link rel="import" href="/components/paper-dialog/paper-action-dialog.html">
<link rel="import" href="/components/paper-dialog/paper-dialog.html">
<link rel="import" href="/components/paper-dialog/paper-dialog-transition.html">
<link rel="import" href="/components/paper-dropdown/paper-dropdown.html">
<link rel="import" href="/components/paper-fab/paper-fab.html">
<link rel="import" href="/components/paper-fab-menu/paper-fab-menu.html">
<link rel="import" href="/components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="/components/paper-input/paper-autogrow-textarea.html">
<link rel="import" href="/components/paper-input/paper-input.html">
<link rel="import" href="/components/paper-input/paper-input-decorator.html">
<link rel="import" href="/components/paper-item/paper-item.html">
<link rel="import" href="/components/paper-menu-button/paper-menu-button.html">
<link rel="import" href="/components/paper-radio-button/paper-radio-button.html">
<link rel="import" href="/components/paper-radio-group/paper-radio-group.html">
<link rel="import" href="/components/paper-shadow/paper-shadow.html">
<link rel="import" href="/components/paper-spinner/paper-spinner.html">
<link rel="import" href="/components/paper-slider/paper-slider.html">
<link rel="import" href="/components/paper-tabs/paper-tabs.html">
<link rel="import" href="/components/paper-toast/paper-toast.html">
<link rel="import" href="/components/paper-toggle-button/paper-toggle-button.html">
<!--custom components-->
<link rel="import" href="/custom_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="/custom_components/paper-diff-slider/paper-diff-slider.html">
<link rel="import" href="/custom_components/swipe-detect/swipe-detect.html">

View File

@@ -4,6 +4,9 @@
</core-toolbar>
<div fit layout vertical center center-justified>
<paper-spinner class="bigSpinner" active></paper-spinner>
<div class="subhead">{{randomHint}}</div>
<div class="subhead"
style="margin-left: 16px;
margin-right: 16px;
text-align: center;">{{randomHint}}</div>
</div>
</template>

View File

@@ -1,10 +1,14 @@
<template name="notFound">
<div layout vertical center center-justified fit>
<h2>The data for the page you requested could not be found.</h2>
<core-toolbar class="app-grey white-text">
<core-icon-button icon="menu" core-drawer-toggle></core-icon-button>
</core-toolbar>
<div layout vertical center center-justified fit
style="padding: 16px; text-align: center;">
<h2 style="margin-bottom: 12px;">The data for the page you requested could not be found.</h2>
{{#if currentUser}}
<h2>It might not exist, or you might not have permission to view it.</h2>
<h3>It might not exist, or you might not have permission to view it.</h3>
{{else}}
<h2>Perhaps you need to sign in first:</h2>
<h3>Perhaps you need to sign in first:</h3>
{{atForm}}
{{/if}}
</div>

View File

@@ -9,20 +9,11 @@ Template.baseDialog.onRendered(function(){
Template.baseDialog.helpers({
editing: function(){
return Template.instance().editing.get();
return Template.instance().editing.get() && canEditCharacter(Template.parentData().charId);
},
showEdit: function() {
if (this.hideEdit) return false;
var charId = Template.parentData().charId;
var userId = Meteor.userId();
if (!userId) return false;
if (charId){
var char = Characters.findOne(charId);
if (char)
return char.owner === userId ||
_.contains(char.writers, userId);
}
return true;
return canEditCharacter(Template.parentData().charId);
},
});

45
rpg-docs/config.vulcanize Normal file
View File

@@ -0,0 +1,45 @@
{
"imports": [
"/components/core-animated-pages/core-animated-pages.html",
"/components/core-animated-pages/transitions/cross-fade.html",
"/components/core-animated-pages/transitions/hero-transition.html",
"/components/core-animated-pages/transitions/slide-from-right.html",
"/components/core-icons/av-icons.html",
"/components/core-icons/core-icons.html",
"/components/core-icons/editor-icons.html",
"/components/core-icons/image-icons.html",
"/components/core-icons/social-icons.html",
"/components/core-image/core-image.html",
"/components/core-item/core-item.html",
"/components/core-menu/core-menu.html",
"/components/core-scaffold/core-scaffold.html",
"/components/core-transition/core-transition.html",
"/components/paper-button/paper-button.html",
"/components/paper-checkbox/paper-checkbox.html",
"/components/paper-dialog/paper-action-dialog.html",
"/components/paper-dialog/paper-dialog.html",
"/components/paper-dialog/paper-dialog-transition.html",
"/components/paper-dropdown/paper-dropdown.html",
"/components/paper-fab/paper-fab.html",
"/components/paper-fab-menu/paper-fab-menu.html",
"/components/paper-icon-button/paper-icon-button.html",
"/components/paper-input/paper-autogrow-textarea.html",
"/components/paper-input/paper-input.html",
"/components/paper-input/paper-input-decorator.html",
"/components/paper-item/paper-item.html",
"/components/paper-menu-button/paper-menu-button.html",
"/components/paper-radio-button/paper-radio-button.html",
"/components/paper-radio-group/paper-radio-group.html",
"/components/paper-shadow/paper-shadow.html",
"/components/paper-spinner/paper-spinner.html",
"/components/paper-slider/paper-slider.html",
"/components/paper-tabs/paper-tabs.html",
"/components/paper-toast/paper-toast.html",
"/components/paper-toggle-button/paper-toggle-button.html",
"/custom_components/paper-dropdown-menu/paper-dropdown-menu.html",
"/custom_components/paper-diff-slider/paper-diff-slider.html",
"/custom_components/swipe-detect/swipe-detect.html"
]
}

View File

@@ -1,8 +1,13 @@
Meteor.methods({
"getUserId": function(username){
if (!username) return;
regex = new RegExp("^" + username + "$", "i")
var user = Meteor.users.findOne(
{$or: [{username: username}, {"emails.address": username}]}
{$or: [
{username: username},
{"emails.address": regex},
{"services.google.email": regex},
]}
);
return user && user._id;
}

View File

@@ -15,6 +15,7 @@ function CacheObject(func, address, args, cache, context){
var self = this;
self.currentValue = null;
self.dep = new Tracker.Dependency();
self.numRun = 0;
//spawn a new autorun that keeps the value up-to-date
Tracker.nonreactive(function() {
@@ -26,8 +27,22 @@ function CacheObject(func, address, args, cache, context){
delete cache[address];
return;
}
//if we haven't run this before this flush, reset the counter after the flush
if(self.numRun === 0){
Tracker.afterFlush(function(){
self.numRun = 0;
});
}
self.numRun++;
//call the expensive function
//even if we don't use its value, we need to track its dependencies
var newValue = func.apply(context, args);
//prevent dependency loops, the memoized function shouldn't re-run
//more than once per flush
if (self.numRun > 1){
newValue = NaN;
if(_.isNaN(self.currentValue)) return;
}
//if the value changed, store the new value
if (self.currentValue !== newValue){
self.currentValue = newValue;

View File

@@ -101,6 +101,8 @@ trackEncumbranceConditions = function(charId, templateInstance) {
{fields: {"settings": 1}}
);
var strength = Characters.calculate.attributeValue(charId, "strength");
var carryMultiplier = Characters.calculate
.attributeValue(charId, "carryMultiplier");
var give = function(condition) {
Meteor.call("giveCondition", charId, condition);
};
@@ -108,11 +110,11 @@ trackEncumbranceConditions = function(charId, templateInstance) {
Meteor.call("removeCondition", charId, condition);
};
//variant encumbrance rules
if (weight > strength * 10 &&
if (weight > strength * 10 * carryMultiplier &&
character.settings.useVariantEncumbrance) {
give("encumbered2");
remove("encumbered");
} else if (weight > strength * 5 &&
} else if (weight > strength * 5 * carryMultiplier &&
character.settings.useVariantEncumbrance){
give("encumbered");
remove("encumbered2");
@@ -121,11 +123,11 @@ trackEncumbranceConditions = function(charId, templateInstance) {
remove("encumbered2");
}
//normal encumbrance rules
if (weight > strength * 30 &&
if (weight > strength * 30 * carryMultiplier &&
character.settings.useStandardEncumbrance){
give("encumbered4");
remove("encumbered3");
} else if (weight > strength * 15 &&
} else if (weight > strength * 15 * carryMultiplier &&
character.settings.useStandardEncumbrance) {
give("encumbered3");
remove("encumbered4");

View File

@@ -0,0 +1 @@
.build*

View File

@@ -0,0 +1 @@
node_modules

View File

@@ -0,0 +1,7 @@
This directory and the files immediately inside it are automatically generated
when you change this package's NPM dependencies. Commit the files in this
directory (npm-shrinkwrap.json, .gitignore, and this README) to source control
so that others run the same versions of sub-dependencies.
You should NOT check in the node_modules directory that Meteor automatically
creates; if you are using git, the .gitignore file tells git to ignore it.

View File

@@ -0,0 +1,272 @@
{
"dependencies": {
"vulcanize": {
"version": "1.9.1",
"dependencies": {
"dom5": {
"version": "1.1.0",
"dependencies": {
"parse5": {
"version": "1.4.2"
}
}
},
"es6-promise": {
"version": "2.2.0"
},
"hydrolysis": {
"version": "1.13.1",
"dependencies": {
"espree": {
"version": "2.0.3"
},
"estraverse": {
"version": "3.1.0"
},
"setimmediate": {
"version": "1.0.2"
}
}
},
"nopt": {
"version": "3.0.2",
"dependencies": {
"abbrev": {
"version": "1.0.7"
}
}
},
"path-posix": {
"version": "1.0.0"
},
"update-notifier": {
"version": "0.5.0",
"dependencies": {
"chalk": {
"version": "1.0.0",
"dependencies": {
"ansi-styles": {
"version": "2.0.1"
},
"escape-string-regexp": {
"version": "1.0.3"
},
"has-ansi": {
"version": "1.0.3",
"dependencies": {
"ansi-regex": {
"version": "1.1.1"
},
"get-stdin": {
"version": "4.0.1"
}
}
},
"strip-ansi": {
"version": "2.0.1",
"dependencies": {
"ansi-regex": {
"version": "1.1.1"
}
}
},
"supports-color": {
"version": "1.3.1"
}
}
},
"configstore": {
"version": "1.1.0",
"dependencies": {
"graceful-fs": {
"version": "3.0.8"
},
"mkdirp": {
"version": "0.5.1",
"dependencies": {
"minimist": {
"version": "0.0.8"
}
}
},
"object-assign": {
"version": "2.1.1"
},
"os-tmpdir": {
"version": "1.0.1"
},
"osenv": {
"version": "0.1.1"
},
"user-home": {
"version": "1.1.1"
},
"uuid": {
"version": "2.0.1"
},
"xdg-basedir": {
"version": "1.0.1"
}
}
},
"is-npm": {
"version": "1.0.0"
},
"latest-version": {
"version": "1.0.0",
"dependencies": {
"package-json": {
"version": "1.2.0",
"dependencies": {
"got": {
"version": "3.2.0",
"dependencies": {
"duplexify": {
"version": "3.4.1",
"dependencies": {
"end-of-stream": {
"version": "1.0.0",
"dependencies": {
"once": {
"version": "1.3.2",
"dependencies": {
"wrappy": {
"version": "1.0.1"
}
}
}
}
},
"readable-stream": {
"version": "1.1.13",
"dependencies": {
"core-util-is": {
"version": "1.0.1"
},
"isarray": {
"version": "0.0.1"
},
"string_decoder": {
"version": "0.10.31"
},
"inherits": {
"version": "2.0.1"
}
}
}
}
},
"infinity-agent": {
"version": "2.0.3"
},
"is-stream": {
"version": "1.0.1"
},
"lowercase-keys": {
"version": "1.0.0"
},
"nested-error-stacks": {
"version": "1.0.0"
},
"object-assign": {
"version": "2.1.1"
},
"prepend-http": {
"version": "1.0.1"
},
"read-all-stream": {
"version": "2.1.2",
"dependencies": {
"readable-stream": {
"version": "1.1.13",
"dependencies": {
"core-util-is": {
"version": "1.0.1"
},
"isarray": {
"version": "0.0.1"
},
"string_decoder": {
"version": "0.10.31"
},
"inherits": {
"version": "2.0.1"
}
}
}
}
},
"statuses": {
"version": "1.2.1"
},
"timed-out": {
"version": "2.0.0"
}
}
},
"registry-url": {
"version": "3.0.3",
"dependencies": {
"rc": {
"version": "1.0.3",
"dependencies": {
"minimist": {
"version": "0.0.10"
},
"deep-extend": {
"version": "0.2.11"
},
"strip-json-comments": {
"version": "0.1.3"
},
"ini": {
"version": "1.3.4"
}
}
}
}
}
}
}
}
},
"repeating": {
"version": "1.1.3",
"dependencies": {
"is-finite": {
"version": "1.0.1",
"dependencies": {
"number-is-nan": {
"version": "1.0.0"
}
}
}
}
},
"semver-diff": {
"version": "2.0.0",
"dependencies": {
"semver": {
"version": "4.3.6"
}
}
},
"string-length": {
"version": "1.0.0",
"dependencies": {
"strip-ansi": {
"version": "2.0.1",
"dependencies": {
"ansi-regex": {
"version": "1.1.1"
}
}
}
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,3 @@
differential:vulcanize@2.0.0
meteor@1.1.6
underscore@1.0.3

View File

@@ -0,0 +1,29 @@
Vulcanize
==============================================================================
Warning: API Change for version 1.0.0.
This package a meteor build plugin that wraps the [vulcanize](https://www.npmjs.com/package/vulcanize) npm package, which is used to process web components into a single output file.
### Usage
1. Ensure all your components are located somewhere under your public directory. (via bower, zip, etc)
2. Include a `config.vulcanize` file in the root of your project. This file will optionally define a path to the polyfill and paths to html imports for your components. For Example:
````
{
"polyfill": "/bower_components/webcomponentsjs/webcomponents.min.js",
"useShadowDom": true, // optional, defaults to shady dom (polymer default)
"imports": [
"/bower_components/paper-button/paper-button.html",
"/bower_components/paper-checkbox/paper-checkbox.html"
]
}
````
- By specifying a path to the polyfill we can ensure that it is injected into the bundle before any imports.
- By setting `useShadowDom` to true, we configure polymer to opt out of shady dom and use full shadow dom. This is pretty much required at the moment unless you only use polymer elements as leaf nodes. Any light dom (child elements) that gets rendered by blaze, react, etc will not be accounted for otherwise.
- Running your app in development as usual will result in individual imports being added to your `<head>` tag, resulting in multiple subsequent HTTP requests (good in development - debugging).
- Running `meteor`, `meteor build`, `modulus deploy`, etc with the `VULCANIZE=true` environment variable set will result in all your html imports being vulcanized or concatenated into a single html import (good in production). The resulting file will be called `vulcanized-{md5}.html`, which will be automatically added to your `<head>` tag. For example, `VULCANIZE=true meteor`, `VULCANIZE=true modulus deploy`.
- Setting the `CDN_PREFIX` environment variable will prepend the string to the beginning of the file path that is inserted into your HTML's `<head>` tag.

View File

@@ -0,0 +1,17 @@
Package.describe({
name: 'differential:vulcanize',
summary: 'Vulcanize',
version: '2.0.1',
git: 'https://github.com/Differential/meteor-vulcanize'
});
Package.registerBuildPlugin({
name: 'vulcanize',
use: [
"underscore@1.0.3"
],
sources: [
'vulcanize.js'
],
npmDependencies: {'vulcanize': '1.9.1'}
});

View File

@@ -0,0 +1,20 @@
{
"dependencies": [
[
"meteor",
"1.1.3"
],
[
"underscore",
"1.0.1"
]
],
"pluginDependencies": [
[
"vulcanize",
{}
]
],
"toolVersion": "meteor-tool@1.0.35",
"format": "1.0"
}

View File

@@ -0,0 +1,5 @@
// Write your tests here!
// Here is an example.
Tinytest.add('example', function (test) {
test.equal(true, true);
});

View File

@@ -0,0 +1,141 @@
var vulcan = Npm.require('vulcanize');
var crypto = Npm.require('crypto');
var url = Npm.require('url');
var fs = Npm.require('fs');
/**
* Vulcanize now requires a target input file.
* We need to create a temp file located within the same
* 'abspath' as the actual imports. Otherwise, vulcanize
* gets confused during the process.
*/
var tmpFile = '_imports.html';
var tmpDir = 'public';
var tmpPath = tmpDir + '/' + tmpFile;
/**
* Log
*/
function log() {
args = _.values(arguments);
args.unshift("=> Vulcanize:");
console.log.apply(this, args);
}
/**
* Get script tag with specified path.
*/
function scriptTag(path) {
return '<script src="' + path + '"></script>';
}
/**
* Get link tag with specified path.
*/
function linkTag(path) {
return '<link rel="import" href="' + path + '">';
}
/**
* Add config for dom mode to head.
*/
function addShadowDomConfig(compileStep) {
compileStep.addHtml({
section: 'head',
data: '<script> window.Polymer = {dom: "shadow"}; </script>'
});
}
/**
* Add webcomponentsjs script to head.
* @todo read first line and check for script tag
*/
function addPolyfillTag(compileStep, path) {
compileStep.addHtml({
section: 'head',
data: scriptTag(path)
});
}
/**
* Add imports to head.
*/
function addImportTag(compileStep, path) {
compileStep.addHtml({
section: 'head',
data: linkTag(path)
});
}
/**
* Vulcanize all files and add output file to head.
*/
function vulcanizeImports(compileStep, imports) {
var tags = _.map(imports, function(path) {
return linkTag(path);
});
fs.writeFileSync(tmpPath, tags.join("\n"));
vulcan.setOptions({ abspath: tmpDir });
vulcan.process(tmpFile, function(err, html) {
fs.unlinkSync(tmpPath);
var filenameHash = crypto.createHash('md5').update(html).digest('hex');
var filePath = '/vulcanized-' + filenameHash + '.html';
compileStep.addAsset({
path: filePath,
data: html
});
if (_.isString(process.env.CDN_PREFIX)) {
filePath = url.resolve(process.env.CDN_PREFIX, filePath);
}
addImportTag(compileStep, filePath);
});
}
/**
* Add individual import tags
*/
function individualImports(compileStep, imports) {
_.each(imports, function(path) {
addImportTag(compileStep, path);
});
}
/**
* Register appropriate plugin.
*/
Plugin.registerSourceHandler("vulcanize", function(compileStep) {
if (compileStep.inputPath === "config.vulcanize"
&& compileStep.arch === "web.browser") {
// Get JSON file.
var json = JSON.parse(compileStep.read().toString('utf8'));
// Add polyfill to html if defined.
if (_.isString(json.polyfill)) {
addPolyfillTag(compileStep, json.polyfill);
}
// Optionally opt into shadow dom, rather than shady dom.
if (json.useShadowDom) {
addShadowDomConfig(compileStep);
}
// Add imports if defined.
if (process.env.VULCANIZE && _.isArray(json.imports)) {
log("Importing vulcanized file...");
vulcanizeImports(compileStep, json.imports);
} else {
log("Importing individual files...");
individualImports(compileStep, json.imports);
}
} else if (compileStep.arch === "web.browser") {
log("File "+compileStep.inputPath+" ignored");
}
});

View File

@@ -0,0 +1,3 @@
.build*
versions.json
.versions

View File

@@ -0,0 +1,8 @@
sudo: required
language: node_js
node_js:
- "0.10"
before_install:
- "curl -L http://git.io/ejPSng | /bin/sh"
env:
- TEST_COMMAND=meteor

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 splendido
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,48 @@
[![Build Status](https://travis-ci.org/meteor-useraccounts/polymer.svg?branch=master)](https://travis-ci.org/meteor-useraccounts/polymer)
useraccounts:polymer
=====================================
WORK IN PROGRESS - let us know about any problem you might encounter ;)
## TODOs
Add the following input types:
- checkbox input
- select input
- radio input
Find the proper solution for inheriting AT events for paper-button elements
This package depends on [useraccounts:core](https://atmospherejs.com/useraccounts/core)
Learn more [here](http://useraccounts.meteor.com) or have a look at the full [documentation](https://github.com/meteor-useraccounts/core).
## Bring Your Own Polymer
Adding this package with `meteor add useraccounts:polymer` does not add any other packages providing Polymer .This is to let you choose the flavour you prefer! Or using an Atmosphere package, or straight up with bower!
## ADD theses imports manually
This package does not automatically add the imports for the elements needed. If you don't have them imported already you should copy/paste these imports :
```HTML
<link rel="import" href="bower_components/paper-input/paper-input.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<link rel="import" href="bower_components/paper-checkbox/paper-checkbox.html">
```
## Contributing
Anyone is welcome to contribute. Fork, make your changes, and then submit a pull request.
Thanks to all those who have contributed code changes to [this package](https://github.com/meteor-useraccounts/unstyled/graphs/contributors) as well as to the [core package](https://github.com/meteor-useraccounts/core/graphs/contributors) and all who have helped by submitting bug reports and feature ideas.

View File

@@ -0,0 +1,7 @@
<template name="atError">
<div class="at-error" horizontal center-justified layout>
{{#each error}}
<p>{{errorText}}</p>
{{/each}}
</div>
</template>

View File

@@ -0,0 +1,2 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atError.helpers(AccountsTemplates.atErrorHelpers);

View File

@@ -0,0 +1,39 @@
<template name="atForm">
{{#unless hide}}
<div class="at-form">
{{#if showTitle}}
{{> atTitle}}
{{/if}}
{{#if showOauthServices}}
{{> atOauth}}
{{/if}}
{{#if showServicesSeparator}}
{{> atSep}}
{{/if}}
{{#if showError}}
{{> atError}}
{{/if}}
{{#if showResult}}
{{> atResult}}
{{/if}}
{{#if showMessage}}
{{> atMessage}}
{{/if}}
{{#if showPwdForm}}
{{> atPwdForm}}
{{/if}}
{{#if showTermsLink}}
{{> atTermsLink}}
{{/if}}
{{#if showSignInLink}}
{{> atSigninLink}}
{{/if}}
{{#if showSignUpLink}}
{{> atSignupLink}}
{{/if}}
{{#if showResendVerificationEmailLink}}
{{> atResendVerificationEmailLink}}
{{/if}}
</div>
{{/unless}}
</template>

View File

@@ -0,0 +1,2 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atForm.helpers(AccountsTemplates.atFormHelpers);

View File

@@ -0,0 +1,81 @@
<template name="atInput">
{{> Template.dynamic template=templateName}}
</template>
<template name="atTextInput">
<div class="at-input pure-control-group{{#if isValidating}}validating{{/if}} {{#if hasError}}has-error{{/if}} {{#if hasSuccess}}has-success{{/if}} {{#if feedback}}has-feedback{{/if}}">
<!-- {{#if showLabels}}
<label for="at-field-{{_id}}">
{{displayName}} {{#unless required}}{{optionalText}}{{/unless}}
</label>
{{/if}}
<input type="{{type}}" id="at-field-{{_id}}" name="at-field-{{_id}}" placeholder="{{placeholder}}" autocapitalize="none" autocorrect="off">
{{#if hasIcon}}
<span class="{{iconClass}}"></span>
{{/if}}
{{#if hasError}}
<span>{{errorText}}</span>
{{/if}}
</div> -->
{{#if showLabels}}
<paper-input-decorator label=" {{displayName}} {{#unless required}}{{optionalText}}{{/unless}}" error="{{errorText}}" floatinglabel="" layout="" vertical="" isInvalid="{{#if hasError}} true {{/if}}">
<input type="{{type}}" id="at-field-{{_id}}" is="core-input" name="at-field-{{_id}}" placeholder="{{placeholder}}" autocapitalize="none" autocorrect="off">
</paper-input-decorator>
{{else}}
<paper-input-decorator error="{{errorText}}" isInvalid="{{#if hasError}} true {{/if}}">
<input type="{{type}}" id="at-field-{{_id}}" is="core-input" name="at-field-{{_id}}" placeholder="{{placeholder}}" autocapitalize="none" autocorrect="off">
</paper-input-decorator>
{{/if}}
{{#if hasIcon}}
<core-icon icon="{{iconClass}}"></core-icon>
{{/if}}
</div>
</template>
<template name="atCheckboxInput">
<div class="at-input">
<core-label horizontal layout>
<div flex>{{displayName}}</div>
<paper-checkbox type="{{type}}" id="at-field-{{_id}}" name="at-field-{{_id}}" {{disabled}} for></paper-checkbox>
</core-label>
</div>
</template>
<template name="atSelectInput">
<div class="at-input">
<core-label>
<div for="at-field-{{_id}}">{{displayName}}</div>
<core-selector id="at-field-{{_id}}" name="at-field-{{_id}}" valueattr="value" for horizontal layout center justified>
{{#each values}}
<div value="{{value}}">{{text}}</div>
{{/each}}
</core-selector>
</core-label>
</div>
</template>
<template name="atRadioInput">
<div class="at-input">
<label>{{displayName}}</label>
</div>
<paper-radio-group role="radiogroup" vertical layout>
{{#each values}}
<paper-radio-button id="at-field-{{id}}-choice-{{value}}" name="t-field-{{id}}" label="{{text}}" value={{value}} toggles role="radio" tabindex="0" aria-checked="true" aria-label="{{text}}" class="core-selected"></paper-radio-button>
{{/each}}
</paper-radio-group>
</template>
<template name="atHiddenInput">
<input type="hidden" id="at-field-{{_id}}" name="at-field-{{_id}}">
</template>

View File

@@ -0,0 +1,25 @@
_.each(AccountsTemplates.atInputRendered, function(callback){
Template.atInput.onRendered(callback);
Template.atHiddenInput.onRendered(callback);
});
// Simply 'inherites' helpers from AccountsTemplates
Template.atInput.helpers(AccountsTemplates.atInputHelpers);
// Simply 'inherites' events from AccountsTemplates
Template.atInput.events(AccountsTemplates.atInputEvents);
// Simply 'inherites' helpers from AccountsTemplates
Template.atTextInput.helpers(AccountsTemplates.atInputHelpers);
// Simply 'inherites' helpers from AccountsTemplates
Template.atCheckboxInput.helpers(AccountsTemplates.atInputHelpers);
// Simply 'inherites' helpers from AccountsTemplates
Template.atSelectInput.helpers(AccountsTemplates.atInputHelpers);
// Simply 'inherites' helpers from AccountsTemplates
Template.atRadioInput.helpers(AccountsTemplates.atInputHelpers);
// Simply 'inherites' helpers from AccountsTemplates
Template.atHiddenInput.helpers(AccountsTemplates.atInputHelpers);

View File

@@ -0,0 +1,5 @@
<template name="atMessage">
<div class="at-message">
{{message}}
</div>
</template>

View File

@@ -0,0 +1,2 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atMessage.helpers(AccountsTemplates.atMessageHelpers);

View File

@@ -0,0 +1,4 @@
<template name="atNavButton">
<!-- <a id="at-nav-button">{{text}}</a> -->
<paper-button id="at-nav-button" raised>{{text}}</paper-button>
</template>

View File

@@ -0,0 +1,5 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atNavButton.helpers(AccountsTemplates.atNavButtonHelpers);
// Simply 'inherites' events from AccountsTemplates
Template.atNavButton.events(AccountsTemplates.atNavButtonEvents);

View File

@@ -0,0 +1,7 @@
<template name="atOauth">
<div class="at-oauth" horizontal center-justified layout>
{{#each oauthService}}
{{> atSocial}}
{{/each}}
</div>
</template>

View File

@@ -0,0 +1,2 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atOauth.helpers(AccountsTemplates.atOauthHelpers);

View File

@@ -0,0 +1,168 @@
.fullPageAtForm {
margin: 0 auto;
}
.at-form {
float: none;
margin: auto;
overflow: auto;
margin-top: 20px;
margin-bottom: 20px;
border-radius: 10px;
padding: 15px;
}
.at-form p {
font-size: 15px;
line-height: 20px;
}
.at-title h3 {
margin-top: 0px;
margin-bottom: 10px;
font-size: 18px;
font-weight: 800;
text-align: center;
}
.at-link.disabled {
color: #444;
}
.at-signin-link {
margin-top: 20px;
margin-bottom: 30px;
text-align: center;
}
.at-error,
.at-result {
text-align: center;
}
.at-error {
background-color: #FFF0F0;
}
.at-error p {
width: 100%;
color: #A94442;
}
.at-oauth {
margin-top: 10px;
}
.at-btn {
display: block;
width: 100%;
}
paper-button.at-social-btn {
display: block;
width: 100%;
margin: auto;
margin-bottom: 10px;
padding: 8px 10px;
border-radius: 5px;
font-size: 16px;
}
paper-button.at-social-btn core-icon {
float: left;
width: 40px;
font-size: 20px;
margin-top: 1px;
padding-right: 15px;
padding-left: 5px;
border-right: 1px solid rgba(0, 0, 0, 0.2);
}
paper-button.at-social-btn#at-facebook {
background: #3B5998;
color: #fff;
}
paper-button.at-social-btn#at-facebook.disabled {
color: #ddd;
background: #666666;
}
paper-button.at-social-btn#at-facebook:hover {
background: #2C4780;
}
paper-button.at-social-btn#at-linkedin {
background: #338AB0;
color: #fff;
}
paper-button.at-social-btn#at-linkedin.disabled {
color: #ddd;
background: #666666;
}
paper-button.at-social-btn#at-linkedin:hover {
background: #0571A6;
}
paper-button.at-social-btn#at-twitter {
background: #4099FF;
color: #fff;
}
paper-button.at-social-btn#at-twitter.disabled {
color: #ddd;
background: #666666;
}
paper-button.at-social-btn#at-twitter:hover {
background: #3288EB;
}
paper-button.at-social-btn#at-google {
background: #db5a3c;
color: #fff;
}
paper-button.at-social-btn#at-google.disabled {
color: #ddd;
background: #666666;
}
paper-button.at-social-btn#at-google:hover {
background: #CA4C2E;
}
paper-button.at-social-btn#at-github {
background: #666;
color: #fff;
}
paper-button.at-social-btn#at-github.disabled {
color: #ddd;
background: #666666;
}
paper-button.at-social-btn#at-github:hover {
background: #555;
}
.at-sep {
text-align: center;
position: relative;
overflow: hidden;
margin-bottom: 15px;
}
.at-sep:before,
.at-sep:after {
display: block;
content: " ";
border-bottom: 1px solid #ddd;
width: 100%;
position: absolute;
top: 48%;
}
.at-sep:before {
left: -60%;
}
.at-sep:after {
right: -60%;
}
.at-input.validating * {
cursor: progress;
}
.at-pwd-form > form {
margin-top: 20px;
}
.at-pwd-form > form label {
margin-bottom: 5px;
font-weight: 500;
font-size: 14px;
}
#at-btn {
font-size: 16px;
padding: 10px 12px;
margin-top: 30px;
}
.at-signup-link {
margin-top: 20px;
margin-bottom: 30px;
}
.at-terms-link {
text-align: center;
margin-top: 20px;
font-size: 16px;
}

View File

@@ -0,0 +1,16 @@
<template name="atPwdForm">
<div class="at-pwd-form">
<form role="form" id="at-pwd-form" class="{{disabled}} pure-form pure-form-aligned" novalidate action="#" method="POST">
{{#each fields}}
{{> atInput}}
{{/each}}
{{#if showReCaptcha}}
{{> atReCaptcha}}
{{/if}}
{{#if showForgotPasswordLink}}
{{> atPwdLink}}
{{/if}}
{{> atPwdFormBtn}}
</form>
</div>
</template>

View File

@@ -0,0 +1,5 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atPwdForm.helpers(AccountsTemplates.atPwdFormHelpers);
// Simply 'inherites' events from AccountsTemplates
Template.atPwdForm.events(AccountsTemplates.atPwdFormEvents);

View File

@@ -0,0 +1,8 @@
<template name="atPwdFormBtn">
<div horizontal layout center-justified>
<button type="submit" id="at-btn" hidden></button>
<paper-button class="at-btn submit {{submitDisabled}}" role="button" id="at-btn-polymer" raised>
{{buttonText}}
</paper-button>
</div>
</template>

View File

@@ -0,0 +1,10 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atPwdFormBtn.helpers(AccountsTemplates.atPwdFormBtnHelpers);
Template.atPwdFormBtn.events = {
'click #at-btn-polymer': function(event,template) {
event.preventDefault();
template.find('button[type=submit]').click();
}
};

View File

@@ -0,0 +1,9 @@
<template name="atPwdLink">
<div class="at-pwd-link" horizontal layout center-justified>
<p>
{{preText}}
<a href="{{forgotPwdLink}}" id="at-forgotPwd" class="at-link at-pwd {{disabled}}">{{linkText}}</a>
{{suffText}}
</p>
</div>
</template>

View File

@@ -0,0 +1,5 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atPwdLink.helpers(AccountsTemplates.atPwdLinkHelpers);
// Simply 'inherites' events from AccountsTemplates
Template.atPwdLink.events(AccountsTemplates.atPwdLinkEvents);

View File

@@ -0,0 +1,3 @@
<template name="atReCaptcha">
<div class="g-recaptcha" data-sitekey='{{key}}' data-theme='{{theme}}' data-type='{{data_type}}'></div>
</template>

View File

@@ -0,0 +1,5 @@
// Simply 'inherites' rendered callback from AccountsTemplates
Template.atReCaptcha.rendered = AccountsTemplates.atReCaptchaRendered;
// Simply 'inherites' helpers from AccountsTemplates
Template.atReCaptcha.helpers(AccountsTemplates.atReCaptchaHelpers);

View File

@@ -0,0 +1,8 @@
<template name="atResendVerificationEmailLink">
<div class="at-resend-verification-email-link at-wrap" horizontal center-justified layout>
<p>
<a href="{{resendVerificationEmailLink}}" id="at-resend-verification-email" class="at-link at-resend-verification-email {{disabled}}">{{linkText}}</a>
{{suffText}}
</p>
</div>
</template>

View File

@@ -0,0 +1,5 @@
// Simply 'inherites' helpers from AccountsTemplates
Template.atResendVerificationEmailLink.helpers(AccountsTemplates.atResendVerificationEmailLinkHelpers);
// Simply 'inherites' events from AccountsTemplates
Template.atResendVerificationEmailLink.events(AccountsTemplates.atResendVerificationEmailLinkEvents);

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