Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45e9f491ff | ||
|
|
742b26b0de | ||
|
|
164ba78c81 | ||
|
|
e27211b24d | ||
|
|
30987752cc | ||
|
|
058ee2691f | ||
|
|
f0cf7f4956 | ||
|
|
75c8720b04 | ||
|
|
f73f2f670f | ||
|
|
c6e62e1cfa | ||
|
|
4e574c0f51 | ||
|
|
80b195b7f7 | ||
|
|
67956d9a42 | ||
|
|
64b3ca6066 | ||
|
|
8349f7da9b | ||
|
|
0636042878 | ||
|
|
00a050d337 |
@@ -3,12 +3,12 @@
|
|||||||
# 'meteor add' and 'meteor remove' will edit this file for you,
|
# 'meteor add' and 'meteor remove' will edit this file for you,
|
||||||
# but you can also edit it by hand.
|
# but you can also edit it by hand.
|
||||||
|
|
||||||
accounts-password@1.4.0
|
accounts-password@1.5.0
|
||||||
accounts-ui@1.1.9
|
accounts-ui@1.2.0
|
||||||
random@1.0.10
|
random@1.0.10
|
||||||
dburles:collection-helpers
|
dburles:collection-helpers
|
||||||
reactive-var@1.0.11
|
reactive-var@1.0.11
|
||||||
underscore
|
underscore@1.0.10
|
||||||
aldeed:collection2
|
aldeed:collection2
|
||||||
matb33:collection-hooks
|
matb33:collection-hooks
|
||||||
zimme:collection-softremovable
|
zimme:collection-softremovable
|
||||||
@@ -17,40 +17,40 @@ dburles:mongo-collection-instances
|
|||||||
percolate:migrations
|
percolate:migrations
|
||||||
ecwyne:mathjs
|
ecwyne:mathjs
|
||||||
useraccounts:polymer
|
useraccounts:polymer
|
||||||
accounts-google@1.2.0
|
accounts-google@1.3.0
|
||||||
splendido:accounts-meld
|
splendido:accounts-meld
|
||||||
email@1.2.3
|
email@1.2.3
|
||||||
meteorhacks:subs-manager
|
meteorhacks:subs-manager
|
||||||
chuangbo:marked
|
chuangbo:marked
|
||||||
reywood:iron-router-ga
|
reywood:iron-router-ga
|
||||||
meteor-base@1.1.0
|
meteor-base@1.2.0
|
||||||
mobile-experience@1.0.4
|
mobile-experience@1.0.5
|
||||||
mongo@1.2.0
|
mongo@1.3.1
|
||||||
blaze-html-templates
|
blaze-html-templates
|
||||||
session@1.1.7
|
session@1.1.7
|
||||||
jquery@1.11.10
|
jquery@1.11.10
|
||||||
tracker@1.1.3
|
tracker@1.1.3
|
||||||
logging@1.1.17
|
logging@1.1.19
|
||||||
reload@1.1.11
|
reload@1.1.11
|
||||||
ejson@1.0.14
|
ejson@1.1.0
|
||||||
spacebars
|
spacebars
|
||||||
check@1.2.5
|
check@1.2.5
|
||||||
useraccounts:iron-routing
|
useraccounts:iron-routing
|
||||||
wizonesolutions:canonical
|
wizonesolutions:canonical
|
||||||
standard-minifier-js@2.1.1
|
standard-minifier-js@2.2.0
|
||||||
shell-server@0.2.4
|
shell-server@0.3.0
|
||||||
seba:minifiers-autoprefixer
|
seba:minifiers-autoprefixer
|
||||||
nikogosovd:multiple-uihooks
|
nikogosovd:multiple-uihooks
|
||||||
templates:array
|
templates:array
|
||||||
ecmascript@0.8.2
|
ecmascript@0.9.0
|
||||||
es5-shim@4.6.15
|
es5-shim@4.6.15
|
||||||
differential:vulcanize
|
differential:vulcanize
|
||||||
reactive-dict@1.1.9
|
reactive-dict@1.2.0
|
||||||
percolate:synced-cron
|
percolate:synced-cron
|
||||||
ongoworks:speakingurl
|
ongoworks:speakingurl
|
||||||
service-configuration@1.0.11
|
service-configuration@1.0.11
|
||||||
google-config-ui
|
google-config-ui@1.0.0
|
||||||
dynamic-import
|
dynamic-import@0.2.0
|
||||||
ddp-rate-limiter
|
ddp-rate-limiter@1.0.7
|
||||||
rate-limit
|
rate-limit@1.0.8
|
||||||
iron:router
|
iron:router
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
METEOR@1.6
|
METEOR@1.6.0.1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
accounts-base@1.4.0
|
accounts-base@1.4.2
|
||||||
accounts-google@1.3.0
|
accounts-google@1.3.1
|
||||||
accounts-oauth@1.1.15
|
accounts-oauth@1.1.15
|
||||||
accounts-password@1.5.0
|
accounts-password@1.5.0
|
||||||
accounts-ui@1.2.0
|
accounts-ui@1.2.0
|
||||||
@@ -19,7 +19,7 @@ blaze@2.3.2
|
|||||||
blaze-html-templates@1.1.2
|
blaze-html-templates@1.1.2
|
||||||
blaze-tools@1.0.10
|
blaze-tools@1.0.10
|
||||||
boilerplate-generator@1.3.1
|
boilerplate-generator@1.3.1
|
||||||
caching-compiler@1.1.9
|
caching-compiler@1.1.11
|
||||||
caching-html-compiler@1.1.2
|
caching-html-compiler@1.1.2
|
||||||
callback-hook@1.0.10
|
callback-hook@1.0.10
|
||||||
check@1.2.5
|
check@1.2.5
|
||||||
@@ -46,7 +46,7 @@ email@1.2.3
|
|||||||
es5-shim@4.6.15
|
es5-shim@4.6.15
|
||||||
geojson-utils@1.0.10
|
geojson-utils@1.0.10
|
||||||
google-config-ui@1.0.0
|
google-config-ui@1.0.0
|
||||||
google-oauth@1.2.4
|
google-oauth@1.2.5
|
||||||
hot-code-push@1.0.4
|
hot-code-push@1.0.4
|
||||||
html-tools@1.0.11
|
html-tools@1.0.11
|
||||||
htmljs@1.0.11
|
htmljs@1.0.11
|
||||||
@@ -63,7 +63,7 @@ iron:url@1.1.0
|
|||||||
jquery@1.11.10
|
jquery@1.11.10
|
||||||
lai:collection-extensions@0.2.1_1
|
lai:collection-extensions@0.2.1_1
|
||||||
launch-screen@1.1.1
|
launch-screen@1.1.1
|
||||||
less@2.7.11
|
less@2.7.12
|
||||||
livedata@1.0.18
|
livedata@1.0.18
|
||||||
localstorage@1.2.0
|
localstorage@1.2.0
|
||||||
logging@1.1.19
|
logging@1.1.19
|
||||||
@@ -74,26 +74,26 @@ meteor-base@1.2.0
|
|||||||
meteorhacks:subs-manager@1.6.4
|
meteorhacks:subs-manager@1.6.4
|
||||||
minifier-css@1.2.16
|
minifier-css@1.2.16
|
||||||
minifier-js@2.2.2
|
minifier-js@2.2.2
|
||||||
minimongo@1.4.2
|
minimongo@1.4.3
|
||||||
mobile-experience@1.0.5
|
mobile-experience@1.0.5
|
||||||
mobile-status-bar@1.0.14
|
mobile-status-bar@1.0.14
|
||||||
modules@0.11.0
|
modules@0.11.3
|
||||||
modules-runtime@0.9.1
|
modules-runtime@0.9.2
|
||||||
momentjs:moment@2.19.2
|
momentjs:moment@2.20.1
|
||||||
mongo@1.3.0
|
mongo@1.3.1
|
||||||
mongo-dev-server@1.1.0
|
mongo-dev-server@1.1.0
|
||||||
mongo-id@1.0.6
|
mongo-id@1.0.6
|
||||||
nikogosovd:multiple-uihooks@0.1.8
|
nikogosovd:multiple-uihooks@0.1.8
|
||||||
npm-bcrypt@0.9.3
|
npm-bcrypt@0.9.3
|
||||||
npm-mongo@2.2.33
|
npm-mongo@2.2.34
|
||||||
oauth@1.2.0
|
oauth@1.2.1
|
||||||
oauth2@1.2.0
|
oauth2@1.2.0
|
||||||
observe-sequence@1.0.16
|
observe-sequence@1.0.16
|
||||||
ongoworks:speakingurl@9.0.0
|
ongoworks:speakingurl@9.0.0
|
||||||
ordered-dict@1.0.9
|
ordered-dict@1.0.9
|
||||||
percolate:migrations@0.9.8
|
percolate:migrations@0.9.8
|
||||||
percolate:synced-cron@1.3.2
|
percolate:synced-cron@1.3.2
|
||||||
promise@0.10.0
|
promise@0.10.1
|
||||||
raix:eventemitter@0.1.3
|
raix:eventemitter@0.1.3
|
||||||
random@1.0.10
|
random@1.0.10
|
||||||
rate-limit@1.0.8
|
rate-limit@1.0.8
|
||||||
@@ -107,14 +107,14 @@ seba:minifiers-autoprefixer@1.0.1
|
|||||||
service-configuration@1.0.11
|
service-configuration@1.0.11
|
||||||
session@1.1.7
|
session@1.1.7
|
||||||
sha@1.0.9
|
sha@1.0.9
|
||||||
shell-server@0.3.0
|
shell-server@0.3.1
|
||||||
softwarerero:accounts-t9n@1.3.11
|
softwarerero:accounts-t9n@1.3.11
|
||||||
spacebars@1.0.15
|
spacebars@1.0.15
|
||||||
spacebars-compiler@1.1.3
|
spacebars-compiler@1.1.3
|
||||||
splendido:accounts-emails-field@1.2.0
|
splendido:accounts-emails-field@1.2.0
|
||||||
splendido:accounts-meld@1.3.1
|
splendido:accounts-meld@1.3.1
|
||||||
srp@1.0.10
|
srp@1.0.10
|
||||||
standard-minifier-js@2.2.2
|
standard-minifier-js@2.2.3
|
||||||
templates:array@1.0.3
|
templates:array@1.0.3
|
||||||
templating@1.3.2
|
templating@1.3.2
|
||||||
templating-compiler@1.3.3
|
templating-compiler@1.3.3
|
||||||
|
|||||||
9
rpg-docs/Model/Meta/Blacklist.js
Normal file
9
rpg-docs/Model/Meta/Blacklist.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Blacklist = new Mongo.Collection("blacklist");
|
||||||
|
|
||||||
|
Schemas.Blacklist = new SimpleSchema({
|
||||||
|
userId: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Blacklist.attachSchema(Schemas.Blacklist);
|
||||||
@@ -42,12 +42,21 @@ var ifKeyValid = function(apiKey, response, callback){
|
|||||||
};
|
};
|
||||||
|
|
||||||
var isKeyValid = function(apiKey){
|
var isKeyValid = function(apiKey){
|
||||||
return !!Meteor.users.findOne({apiKey});
|
var user = Meteor.users.findOne({apiKey});
|
||||||
|
if (!user) return false;
|
||||||
|
var blackListed = Blacklist.findOne({userId: user._id});
|
||||||
|
return !blackListed;
|
||||||
};
|
};
|
||||||
|
|
||||||
var rateLimiter = new RateLimiter();
|
var rateLimiter = new RateLimiter();
|
||||||
rateLimiter.addRule({apiKey: String}, 2, 10000);
|
rateLimiter.addRule({apiKey: String}, 2, 10000);
|
||||||
|
|
||||||
var isRateLimited = function(apiKey){
|
var isRateLimited = function(apiKey){
|
||||||
return !rateLimiter.check({apiKey}).allowed;
|
const limited = !rateLimiter.check({apiKey}).allowed
|
||||||
|
if (limited) {
|
||||||
|
console.log(`Rate limit hit by API key ${apiKey}`);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,11 @@ Router.plugin("ensureSignedIn", {
|
|||||||
|
|
||||||
Router.plugin("dataNotFound", {notFoundTemplate: "notFound"});
|
Router.plugin("dataNotFound", {notFoundTemplate: "notFound"});
|
||||||
|
|
||||||
|
var handleSubError = function(e){
|
||||||
|
Session.set("error", {reason: e.reason, href: location.href});
|
||||||
|
Router.go("/error");
|
||||||
|
};
|
||||||
|
|
||||||
Router.map(function() {
|
Router.map(function() {
|
||||||
this.route("/", {
|
this.route("/", {
|
||||||
name: "home",
|
name: "home",
|
||||||
@@ -36,7 +41,9 @@ Router.map(function() {
|
|||||||
path: "/character/:_id/",
|
path: "/character/:_id/",
|
||||||
waitOn: function(){
|
waitOn: function(){
|
||||||
return [
|
return [
|
||||||
subsManager.subscribe("singleCharacter", this.params._id),
|
subsManager.subscribe(
|
||||||
|
"singleCharacter", this.params._id, {onError: handleSubError}
|
||||||
|
),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
action: function(){
|
action: function(){
|
||||||
@@ -52,7 +59,9 @@ Router.map(function() {
|
|||||||
path: "/character/:_id/:urlName",
|
path: "/character/:_id/:urlName",
|
||||||
waitOn: function(){
|
waitOn: function(){
|
||||||
return [
|
return [
|
||||||
subsManager.subscribe("singleCharacter", this.params._id),
|
subsManager.subscribe(
|
||||||
|
"singleCharacter", this.params._id, {onError: handleSubError}
|
||||||
|
),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
data: function() {
|
data: function() {
|
||||||
@@ -78,6 +87,37 @@ Router.map(function() {
|
|||||||
fastRender: true,
|
fastRender: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route("printedCharacterSheet", {
|
||||||
|
path: "/character/:_id/:urlName/print",
|
||||||
|
waitOn: function(){
|
||||||
|
return [
|
||||||
|
subsManager.subscribe(
|
||||||
|
"singleCharacter", this.params._id, {onError: handleSubError}
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
data: function() {
|
||||||
|
var data = Characters.findOne(
|
||||||
|
{_id: this.params._id},
|
||||||
|
{fields: {_id: 1, name: 1, color: 1, writers: 1, readers: 1}}
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
},
|
||||||
|
onAfterAction: function() {
|
||||||
|
var char = Characters.findOne({_id: this.params._id}, {fields: {name: 1}});
|
||||||
|
var name = char && char.name;
|
||||||
|
if (name){
|
||||||
|
document.title = name + " - Printing";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//analytics
|
||||||
|
trackPageView: false,
|
||||||
|
onRun: function() {
|
||||||
|
window.ga && window.ga("send", "pageview", "/print-character");
|
||||||
|
this.next();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
this.route("library", {
|
this.route("library", {
|
||||||
path: "/library",
|
path: "/library",
|
||||||
waitOn: function(){
|
waitOn: function(){
|
||||||
@@ -124,4 +164,11 @@ Router.map(function() {
|
|||||||
document.title = appName;
|
document.title = appName;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.route("/error", {
|
||||||
|
name: "error",
|
||||||
|
onAfterAction: function() {
|
||||||
|
document.title = `${appName} - Error`;
|
||||||
|
},
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
174
rpg-docs/client/compatibility/jquery.quickfit.js
Normal file
174
rpg-docs/client/compatibility/jquery.quickfit.js
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
// jscs:disable
|
||||||
|
// https://github.com/chunksnbits/jquery-quickfit
|
||||||
|
(function ($) {
|
||||||
|
var Quickfit, QuickfitHelper, defaults, pluginName;
|
||||||
|
|
||||||
|
pluginName = 'quickfit';
|
||||||
|
|
||||||
|
defaults = {
|
||||||
|
min: 8,
|
||||||
|
max: 12,
|
||||||
|
tolerance: 0.02,
|
||||||
|
truncate: false,
|
||||||
|
width: null,
|
||||||
|
sampleNumberOfLetters: 10,
|
||||||
|
sampleFontSize: 12
|
||||||
|
};
|
||||||
|
QuickfitHelper = (function () {
|
||||||
|
|
||||||
|
var sharedInstance = null;
|
||||||
|
|
||||||
|
QuickfitHelper.instance = function (options) {
|
||||||
|
if (!sharedInstance) {
|
||||||
|
sharedInstance = new QuickfitHelper(options);
|
||||||
|
}
|
||||||
|
return sharedInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
function QuickfitHelper(options) {
|
||||||
|
this.options = options;
|
||||||
|
|
||||||
|
this.item = $('<span id="meassure"></span>');
|
||||||
|
this.item.css({
|
||||||
|
position: 'absolute',
|
||||||
|
left: '-1000px',
|
||||||
|
top: '-1000px',
|
||||||
|
'font-size': "" + this.options.sampleFontSize + "px"
|
||||||
|
});
|
||||||
|
$('body').append(this.item);
|
||||||
|
|
||||||
|
this.meassures = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QuickfitHelper.prototype.getMeassure = function (letter) {
|
||||||
|
var currentMeassure;
|
||||||
|
currentMeassure = this.meassures[letter];
|
||||||
|
if (!currentMeassure) {
|
||||||
|
currentMeassure = this.setMeassure(letter);
|
||||||
|
}
|
||||||
|
return currentMeassure;
|
||||||
|
};
|
||||||
|
|
||||||
|
QuickfitHelper.prototype.setMeassure = function (letter) {
|
||||||
|
var currentMeassure, index, sampleLetter, text, _ref;
|
||||||
|
|
||||||
|
text = '';
|
||||||
|
sampleLetter = letter === ' ' ? ' ' : letter;
|
||||||
|
|
||||||
|
for (index = 0, _ref = this.options.sampleNumberOfLetters - 1; 0 <= _ref ? index <= _ref : index >= _ref; 0 <= _ref ? index++ : index--) {
|
||||||
|
text += sampleLetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.item.html(text);
|
||||||
|
currentMeassure = this.item.width() / this.options.sampleNumberOfLetters / this.options.sampleFontSize;
|
||||||
|
this.meassures[letter] = currentMeassure;
|
||||||
|
|
||||||
|
return currentMeassure;
|
||||||
|
};
|
||||||
|
|
||||||
|
return QuickfitHelper;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Quickfit = (function () {
|
||||||
|
|
||||||
|
function Quickfit(element, options) {
|
||||||
|
this.$element = element;
|
||||||
|
this.options = $.extend({}, defaults, options);
|
||||||
|
this.$element = $(this.$element);
|
||||||
|
this._defaults = defaults;
|
||||||
|
this._name = pluginName;
|
||||||
|
this.quickfitHelper = QuickfitHelper.instance(this.options);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickfit.prototype.fit = function () {
|
||||||
|
var elementWidth;
|
||||||
|
if (!this.options.width) {
|
||||||
|
elementWidth = this.$element.width();
|
||||||
|
this.options.width = elementWidth - this.options.tolerance * elementWidth;
|
||||||
|
}
|
||||||
|
if (this.text = this.$element.attr('data-quickfit')) {
|
||||||
|
this.previouslyTruncated = true;
|
||||||
|
} else {
|
||||||
|
this.text = this.$element.text();
|
||||||
|
}
|
||||||
|
this.calculateFontSize();
|
||||||
|
|
||||||
|
if (this.options.truncate) this.truncate();
|
||||||
|
|
||||||
|
return {
|
||||||
|
$element: this.$element,
|
||||||
|
size: this.fontSize
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Quickfit.prototype.calculateFontSize = function () {
|
||||||
|
var letter, textWidth, i;
|
||||||
|
|
||||||
|
textWidth = 0;
|
||||||
|
for (i = 0; i < this.text.length; ++i) {
|
||||||
|
letter = this.text.charAt(i);
|
||||||
|
textWidth += this.quickfitHelper.getMeassure(letter);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.targetFontSize = parseInt(this.options.width / textWidth);
|
||||||
|
return this.fontSize = Math.max(this.options.min, Math.min(this.options.max, this.targetFontSize));
|
||||||
|
};
|
||||||
|
|
||||||
|
Quickfit.prototype.truncate = function () {
|
||||||
|
var index, lastLetter, letter, textToAdd, textWidth;
|
||||||
|
|
||||||
|
if (this.fontSize > this.targetFontSize) {
|
||||||
|
textToAdd = '';
|
||||||
|
textWidth = 3 * this.quickfitHelper.getMeassure('.') * this.fontSize;
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
while (textWidth < this.options.width && index < this.text.length) {
|
||||||
|
letter = this.text[index++];
|
||||||
|
if (lastLetter) textToAdd += lastLetter;
|
||||||
|
textWidth += this.fontSize * this.quickfitHelper.getMeassure(letter);
|
||||||
|
lastLetter = letter;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (textToAdd.length + 1 === this.text.length) {
|
||||||
|
textToAdd = this.text;
|
||||||
|
} else {
|
||||||
|
textToAdd += '...';
|
||||||
|
}
|
||||||
|
this.textWasTruncated = true;
|
||||||
|
|
||||||
|
return this.$element.attr('data-quickfit', this.text).html(textToAdd);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (this.previouslyTruncated) {
|
||||||
|
return this.$element.html(this.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Quickfit;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
return $.fn.quickfit = function (options) {
|
||||||
|
var measurements = [];
|
||||||
|
|
||||||
|
// Separate measurements from repaints
|
||||||
|
// First calculate all measurements...
|
||||||
|
var $elements = this.each(function () {
|
||||||
|
var measurement = new Quickfit(this, options).fit();
|
||||||
|
measurements.push(measurement);
|
||||||
|
return measurement.$element;
|
||||||
|
});
|
||||||
|
|
||||||
|
// ... then apply the measurements.
|
||||||
|
for (var i = 0; i < measurements.length; i++) {
|
||||||
|
var measurement = measurements[i];
|
||||||
|
|
||||||
|
measurement.$element.css({ fontSize: measurement.size + 'px' });
|
||||||
|
}
|
||||||
|
|
||||||
|
return $elements;
|
||||||
|
};
|
||||||
|
|
||||||
|
})(jQuery, window);
|
||||||
12
rpg-docs/client/lib/printing.js
Normal file
12
rpg-docs/client/lib/printing.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Session.setDefault("isPrinting", false);
|
||||||
|
if (window.matchMedia) {
|
||||||
|
var mediaQueryList = window.matchMedia("print");
|
||||||
|
mediaQueryList.addListener(function(mql) {
|
||||||
|
if (mql.matches) {
|
||||||
|
Session.set("isPrinting", true);
|
||||||
|
Tracker.flush();
|
||||||
|
} else {
|
||||||
|
Session.set("isPrinting", false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
17
rpg-docs/client/lib/removeDuplicateProficiencies.js
Normal file
17
rpg-docs/client/lib/removeDuplicateProficiencies.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
removeDuplicateProficiencies = function(proficiencies) {
|
||||||
|
dict = {};
|
||||||
|
proficiencies.forEach(function(prof) {
|
||||||
|
if (prof.name in dict) { //if we have already gone over another proficiency for the same thing
|
||||||
|
if (dict[prof.name].value < prof.value) {
|
||||||
|
dict[prof.name] = prof; //then take the new one if it's higher, otherwise leave it
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dict[prof.name] = prof; //if it wasn't already there, store it
|
||||||
|
}
|
||||||
|
});
|
||||||
|
profs = []
|
||||||
|
_.forEach(dict, function(prof) {
|
||||||
|
profs.push(prof);
|
||||||
|
})
|
||||||
|
return profs;
|
||||||
|
};
|
||||||
@@ -20,6 +20,12 @@
|
|||||||
<iron-icon icon="social:share" item-icon></iron-icon>
|
<iron-icon icon="social:share" item-icon></iron-icon>
|
||||||
Share
|
Share
|
||||||
</paper-icon-item>
|
</paper-icon-item>
|
||||||
|
<a href={{printUrl}}>
|
||||||
|
<paper-icon-item id="printButton">
|
||||||
|
<iron-icon icon="print" item-icon></iron-icon>
|
||||||
|
Print
|
||||||
|
</paper-icon-item>
|
||||||
|
</a>
|
||||||
<paper-icon-item id="characterSettings">
|
<paper-icon-item id="characterSettings">
|
||||||
<iron-icon icon="settings" item-icon></iron-icon>
|
<iron-icon icon="settings" item-icon></iron-icon>
|
||||||
Settings
|
Settings
|
||||||
|
|||||||
@@ -165,6 +165,12 @@ var getTab = function(charId){
|
|||||||
};
|
};
|
||||||
|
|
||||||
Template.characterSheet.helpers({
|
Template.characterSheet.helpers({
|
||||||
|
printing: function(){
|
||||||
|
return Session.get("isPrinting");
|
||||||
|
},
|
||||||
|
printUrl: function(){
|
||||||
|
return `/character/${this._id}/${this.urlName || "-"}/print`
|
||||||
|
},
|
||||||
selectedTab: function(){
|
selectedTab: function(){
|
||||||
return getTab(this._id);
|
return getTab(this._id);
|
||||||
},
|
},
|
||||||
@@ -181,8 +187,8 @@ Template.characterSheet.helpers({
|
|||||||
const step = Session.get("newUserExperienceStep");
|
const step = Session.get("newUserExperienceStep");
|
||||||
if (selected == tab) return false;
|
if (selected == tab) return false;
|
||||||
return (tab === 1 && step === 0) ||
|
return (tab === 1 && step === 0) ||
|
||||||
(tab === 5 && step === 1) ||
|
(tab === 5 && step === 1) ||
|
||||||
(tab === 0 && step === 2);
|
(tab === 0 && step === 2);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,12 @@
|
|||||||
<div class="right clickable flex layout horizontal center">
|
<div class="right clickable flex layout horizontal center">
|
||||||
{{title}}
|
{{title}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="layout horizontal center">
|
||||||
|
<div class="layout vertical">
|
||||||
|
<paper-button class="resourceResetMax" disabled={{cantIncrement}}>Reset</paper-button>
|
||||||
|
<paper-button class="resourceResetZero" disabled={{cantDecrement}}>Clear</paper-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</paper-material>
|
</paper-material>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@@ -1,21 +1,3 @@
|
|||||||
var removeDuplicateProficiencies = function(proficiencies) {
|
|
||||||
dict = {};
|
|
||||||
proficiencies.forEach(function(prof) {
|
|
||||||
if (prof.name in dict) { //if we have already gone over another proficiency for the same thing
|
|
||||||
if (dict[prof.name].value < prof.value) {
|
|
||||||
dict[prof.name] = prof; //then take the new one if it's higher, otherwise leave it
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dict[prof.name] = prof; //if it wasn't already there, store it
|
|
||||||
}
|
|
||||||
});
|
|
||||||
profs = []
|
|
||||||
_.forEach(dict, function(prof) {
|
|
||||||
profs.push(prof);
|
|
||||||
})
|
|
||||||
return profs;
|
|
||||||
};
|
|
||||||
|
|
||||||
Template.features.helpers({
|
Template.features.helpers({
|
||||||
features: function(){
|
features: function(){
|
||||||
var features = Features.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
var features = Features.find({charId: this._id}, {sort: {color: 1, name: 1}});
|
||||||
@@ -129,6 +111,17 @@ Template.resource.helpers({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Template.resource.events({
|
Template.resource.events({
|
||||||
|
"click .resourceResetMax": function(event){
|
||||||
|
var modifier = {$set: {}};
|
||||||
|
modifier.$set[this.name + ".adjustment"] = 0;
|
||||||
|
Characters.update(this.char._id, modifier, {validate: false});
|
||||||
|
},
|
||||||
|
"click .resourceResetZero": function(event){
|
||||||
|
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||||
|
var modifier = {$set: {}};
|
||||||
|
modifier.$set[this.name + ".adjustment"] = -base;
|
||||||
|
Characters.update(this.char._id, modifier, {validate: false});
|
||||||
|
},
|
||||||
"click .resourceUp": function(event){
|
"click .resourceUp": function(event){
|
||||||
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
var value = Characters.calculate.attributeValue(this.char._id, this.name);
|
||||||
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
var base = Characters.calculate.attributeBase(this.char._id, this.name);
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.printedAbility .title.paper-font-subhead {
|
||||||
|
font-size: 2.5mm !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<template name="printedAbility">
|
||||||
|
<div class="printedAbility layout vertical center double-border">
|
||||||
|
<div class="paper-font-subhead title flex layout horizontal center">
|
||||||
|
{{title}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-display1 stat">
|
||||||
|
{{characterCalculate "attributeValue" ../_id ability}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead modifier">
|
||||||
|
{{abilityMod}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Template.printedAbility.helpers({
|
||||||
|
abilityMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.abilityMod(
|
||||||
|
Template.parentData()._id, this.ability
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<template name="printedAttack">
|
||||||
|
<div class="printedAttack" style="margin-bottom: 2mm">
|
||||||
|
<div class="layout horizontal">
|
||||||
|
<div class="paper-font-headline layout horizontal center"
|
||||||
|
style="margin-right: 1mm; min-width: 32px; text-align: right;">
|
||||||
|
{{evaluateAttackBonus charId attack}}
|
||||||
|
</div>
|
||||||
|
<div class="flex layout vertical">
|
||||||
|
<div class="paper-font-body2">
|
||||||
|
{{attack.name}}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{evaluateDamage charId attack}} {{attack.damageType}}
|
||||||
|
</div>
|
||||||
|
{{#if attack.details}}
|
||||||
|
<div>
|
||||||
|
{{attack.details}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
Template.printedAttack.helpers({
|
||||||
|
evaluateAttackBonus: function(charId, attack) {
|
||||||
|
if (attack.parent.collection == "Spells") {
|
||||||
|
var spell = Spells.findOne(attack.parent.id);
|
||||||
|
if (spell) {
|
||||||
|
bonus = evaluate(charId, attack.attackBonus, {
|
||||||
|
"spellListId": spell.parent.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var bonus = evaluate(charId, attack.attackBonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isFinite(bonus)) {
|
||||||
|
return bonus > 0 ? "+" + bonus : "" + bonus;
|
||||||
|
} else {
|
||||||
|
return bonus;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
evaluateDamage: function(charId, attack) {
|
||||||
|
if (attack.parent.collection == "Spells") {
|
||||||
|
var spell = Spells.findOne(attack.parent.id);
|
||||||
|
if (spell) {
|
||||||
|
return evaluateSpellString(charId, spell.parent.id, attack.damage);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return evaluateString(charId, attack.damage);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,190 @@
|
|||||||
|
.printed .page {
|
||||||
|
width: 100%;
|
||||||
|
padding: 6mm;
|
||||||
|
page-break-inside: avoid;
|
||||||
|
page-break-after: always;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .shrink-to-fit {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed p {
|
||||||
|
margin-bottom: 1mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .double-border {
|
||||||
|
position: relative;
|
||||||
|
padding: 11px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .double-border > * {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .double-border:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
border: 16px solid transparent;
|
||||||
|
border-image-source: url(/png/doubleLineImageBorder.png);
|
||||||
|
border-image-slice: 110 126 fill;
|
||||||
|
border-image-repeat: stretch;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .double-border.printedAbility {
|
||||||
|
padding: 11px 6px 0;
|
||||||
|
margin-bottom: 3mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .double-border.printedAbility:last-of-type {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .printedAbility .modifier {
|
||||||
|
position: relative;
|
||||||
|
top: 4px;
|
||||||
|
z-index: 1;
|
||||||
|
padding: 2px 18px;
|
||||||
|
background-image: url(/png/upwardPointingBorder.png);
|
||||||
|
background-position: center;
|
||||||
|
background-size: contain;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .octogon-border {
|
||||||
|
position: relative;
|
||||||
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .octogon-border:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
border: 22px solid transparent;
|
||||||
|
border-image: url(/png/octogonBorder.png) 124 118 fill;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed iron-icon {
|
||||||
|
width: 16px;
|
||||||
|
min-width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
min-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .proficiencies, .printed .attacks, .printed .background {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .shield-background {
|
||||||
|
background: url(/png/shieldBorder.png);
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
padding: 4px 8px 8px;
|
||||||
|
width: 80px;
|
||||||
|
height: 91px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .shield-background .paper-font-subhead {
|
||||||
|
width: 64px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed {
|
||||||
|
font-size: 3mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .paper-font-body2 {
|
||||||
|
font-size: 3mm;
|
||||||
|
line-height: 4mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .paper-font-subhead {
|
||||||
|
font-size: 3mm !important;
|
||||||
|
line-height: 3.5mm !important;
|
||||||
|
font-weight: bold !important;
|
||||||
|
text-transform: uppercase !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .paper-font-subhead.modifier {
|
||||||
|
font-size: 4mm !important;
|
||||||
|
line-height: 6mm !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .paper-font-display1 {
|
||||||
|
font-size: 7mm !important;
|
||||||
|
line-height: 12mm !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .paper-font-headline {
|
||||||
|
font-size: 5mm !important;
|
||||||
|
line-height: 6mm !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .lined-background {
|
||||||
|
background-image: url(/png/horizontalLine.png);
|
||||||
|
background-size: 100% 4mm;
|
||||||
|
print-color-adjust: exact;
|
||||||
|
-webkit-print-color-adjust: exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen {
|
||||||
|
.printed .page {
|
||||||
|
width: 210mm;
|
||||||
|
height: 297mm;
|
||||||
|
background: white;
|
||||||
|
margin: 8px;
|
||||||
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14),
|
||||||
|
0 1px 5px 0 rgba(0, 0, 0, 0.12),
|
||||||
|
0 3px 1px -2px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .page-holder {
|
||||||
|
width: calc(210mm + 16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed {
|
||||||
|
overflow: auto;
|
||||||
|
padding-left:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
app-drawer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
app-header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.printed {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 99;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.printed .page-holder {
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .page {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
<template name="printedCharacterSheet">
|
||||||
|
<div class="fit printed-character-sheet layout vertical">
|
||||||
|
<app-header fixed effects="waterfall">
|
||||||
|
<app-toolbar class="medium {{colorClass}} layout horizontal center" style="z-index: 2;">
|
||||||
|
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
|
||||||
|
<paper-icon-button icon="arrow-back" class="backButton"></paper-icon-button>
|
||||||
|
<div class="flex character-name">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
<div style="position: relative;">
|
||||||
|
<paper-icon-button icon="print" class="printButton"></paper-icon-button>
|
||||||
|
{{#simpleTooltip}} Print {{/simpleTooltip}}
|
||||||
|
</div>
|
||||||
|
</app-toolbar>
|
||||||
|
</app-header>
|
||||||
|
<div class="printed flex">
|
||||||
|
<div class="page-holder">
|
||||||
|
<div class="page">
|
||||||
|
<div class="layout vertical" style="height: 100%;">
|
||||||
|
<div class="layout horizontal center" style="margin-bottom: 4mm">
|
||||||
|
<img src="/crown-dice-logo-cropped-transparent.png" style="width: 60px; margin-right: 2mm">
|
||||||
|
<div class="characterName paper-font-title" style="margin-right: 4mm">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-body2">
|
||||||
|
<div>
|
||||||
|
{{#each classes}}
|
||||||
|
<span style="margin-right: 2mm;">
|
||||||
|
{{name}} {{level}}
|
||||||
|
</span>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{character.alignment}} {{character.gender}} {{character.race}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex layout vertical end" style="margin-right: 2mm;">
|
||||||
|
<div class="paper-font-body2 " style="font-size: 5mm !important;">
|
||||||
|
dicecloud.com
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{{characterUrl}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<canvas id="qrCode"></canvas>
|
||||||
|
</div>
|
||||||
|
<div class="columns layout horizontal flex">
|
||||||
|
<div class="col1 flex layout vertical">
|
||||||
|
<div class="layout vertical center-justified" style="min-height: 100px; margin-bottom: 4mm;">
|
||||||
|
<div class="initiative" style="margin-bottom: 2mm;">
|
||||||
|
{{> printedLongStat stat="" name="Inspiration" prefix=""}}
|
||||||
|
</div>
|
||||||
|
<div class="proficiencyBonus">
|
||||||
|
{{> printedLongStat stat="proficiencyBonus" name="Proficiency Bonus" prefix="+"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal">
|
||||||
|
<div class="abilities layout vertical justified" style="margin-right: 4mm;">
|
||||||
|
{{> printedAbility ability="strength" title="Strength"}}
|
||||||
|
{{> printedAbility ability="dexterity" title="Dexterity"}}
|
||||||
|
{{> printedAbility ability="constitution" title="Constitution"}}
|
||||||
|
{{> printedAbility ability="intelligence" title="Intelligence"}}
|
||||||
|
{{> printedAbility ability="wisdom" title="Wisdom"}}
|
||||||
|
{{> printedAbility ability="charisma" title="Charisma"}}
|
||||||
|
</div>
|
||||||
|
<div class="flex layout vertical">
|
||||||
|
<div class="saves double-border" style="margin-bottom: 2mm">
|
||||||
|
<div>
|
||||||
|
{{> printedSkillRow name="Strength" skill="strengthSave"}}
|
||||||
|
{{> printedSkillRow name="Dexterity" skill="dexteritySave"}}
|
||||||
|
{{> printedSkillRow name="Constitution" skill="constitutionSave"}}
|
||||||
|
{{> printedSkillRow name="Intelligence" skill="intelligenceSave"}}
|
||||||
|
{{> printedSkillRow name="Wisdom" skill="wisdomSave"}}
|
||||||
|
{{> printedSkillRow name="Charisma" skill="charismaSave"}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Saving Throws
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="skills double-border">
|
||||||
|
<div>
|
||||||
|
{{> printedSkillRow name="Acrobatics" skill="acrobatics"}}
|
||||||
|
{{> printedSkillRow name="Animal Handling" skill="animalHandling"}}
|
||||||
|
{{> printedSkillRow name="Arcana" skill="arcana"}}
|
||||||
|
{{> printedSkillRow name="Athletics" skill="athletics"}}
|
||||||
|
{{> printedSkillRow name="Deception" skill="deception"}}
|
||||||
|
{{> printedSkillRow name="History" skill="history"}}
|
||||||
|
{{> printedSkillRow name="Insight" skill="insight"}}
|
||||||
|
{{> printedSkillRow name="Intimidation" skill="intimidation"}}
|
||||||
|
{{> printedSkillRow name="Investigation" skill="investigation"}}
|
||||||
|
{{> printedSkillRow name="Medicine" skill="medicine"}}
|
||||||
|
{{> printedSkillRow name="Nature" skill="nature"}}
|
||||||
|
{{> printedSkillRow name="Perception" skill="perception" showPassive="true"}}
|
||||||
|
{{> printedSkillRow name="Performance" skill="performance"}}
|
||||||
|
{{> printedSkillRow name="Persuasion" skill="persuasion"}}
|
||||||
|
{{> printedSkillRow name="Religion" skill="religion"}}
|
||||||
|
{{> printedSkillRow name="Sleight of Hand" skill="sleightOfHand"}}
|
||||||
|
{{> printedSkillRow name="Stealth" skill="stealth"}}
|
||||||
|
{{> printedSkillRow name="Survival" skill="survival"}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Skills
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="proficiencies flex double-border" style="margin-top: 4mm">
|
||||||
|
<div class="paper-font-subhead layout vertical center" style="margin-bottom: 2mm;">
|
||||||
|
Proficiencies
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal">
|
||||||
|
<div class="flex" style="margin-right: 2mm">
|
||||||
|
{{#if armorProfs.length}}
|
||||||
|
<div class="paper-font-subhead" style="margin-bottom: 1mm;">Armor</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#each armorProfs}}
|
||||||
|
{{> printedProficiency}}
|
||||||
|
{{/each}}
|
||||||
|
{{#if weaponProfs.length}}
|
||||||
|
<div class="paper-font-subhead" style="margin: 2mm 0 1mm;">Weapons</div>
|
||||||
|
{{/if}}
|
||||||
|
{{#each weaponProfs}}
|
||||||
|
{{> printedProficiency}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{#if toolProfs.length}}
|
||||||
|
<div class="flex">
|
||||||
|
<div class="paper-font-subhead" style="margin-bottom: 1mm;">Tools</div>
|
||||||
|
{{#each toolProfs}}
|
||||||
|
{{> printedProficiency}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col2 flex layout vertical" style="margin-left: 4mm; margin-right: 4mm;">
|
||||||
|
<div class="layout horizontal center justified" style="min-height: 100px; margin-bottom: 4mm;">
|
||||||
|
<div class="armor">
|
||||||
|
{{> printedSquareStat stat="armor" name="Armor Class" class="shield-background"}}
|
||||||
|
</div>
|
||||||
|
<div class="inititive">
|
||||||
|
{{> printedSquareStat stat="initiative" name="Initiative" isSkill="true" class="double-border"}}
|
||||||
|
</div>
|
||||||
|
<div class="speed">
|
||||||
|
{{> printedSquareStat stat="speed" name="Speed" class="double-border"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hitpoints layout vertical double-border" style="margin-bottom: 2mm;">
|
||||||
|
<div>
|
||||||
|
Hit point maximum:
|
||||||
|
<span class="paper-font-subhead">
|
||||||
|
{{characterCalculate "attributeBase" _id "hitPoints"}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex" style="width: 3cm; height: 2cm;">
|
||||||
|
<!-- Space for writing -->
|
||||||
|
</div>
|
||||||
|
<div class="layout vertical center paper-font-subhead">
|
||||||
|
Hit Points
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tempHitpoints layout vertical double-border" style="margin-bottom: 2mm;">
|
||||||
|
<div style="width: 3cm; height: 1.5cm;">
|
||||||
|
<!-- Space for writing -->
|
||||||
|
</div>
|
||||||
|
<div class="layout vertical center paper-font-subhead">
|
||||||
|
Temporary Hit Points
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal" style="margin-bottom: 4mm;">
|
||||||
|
<div class="hitDice double-border flex layout vertical" style="margin-right: 2mm;">
|
||||||
|
<div>
|
||||||
|
Total:
|
||||||
|
<span class="paper-font-subhead" style="text-transform: none !important;">
|
||||||
|
{{hitDiceTotal}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="flex" style="min-height: 1cm;">
|
||||||
|
<!-- Space for writing -->
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Hit Dice
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="deathSaves layout vertical center double-border">
|
||||||
|
<div class="" style="margin-bottom: 1mm;">
|
||||||
|
Successes
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal center">
|
||||||
|
<iron-icon icon="radio-button-unchecked"></iron-icon>
|
||||||
|
<iron-icon icon="radio-button-unchecked"></iron-icon>
|
||||||
|
<iron-icon icon="radio-button-unchecked"></iron-icon>
|
||||||
|
</div>
|
||||||
|
<div class="" style="margin: 1mm 0;">
|
||||||
|
Failures
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal center">
|
||||||
|
<iron-icon icon="radio-button-unchecked"></iron-icon>
|
||||||
|
<iron-icon icon="radio-button-unchecked"></iron-icon>
|
||||||
|
<iron-icon icon="radio-button-unchecked"></iron-icon>
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead layout vertical center" style="margin-top: 2mm;">
|
||||||
|
Death Saves
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="attacks double-border flex">
|
||||||
|
<div class="paper-font-subhead layout vertical center" style="margin-bottom: 2mm;">
|
||||||
|
Attacks
|
||||||
|
</div>
|
||||||
|
{{#each attack in attacks}}
|
||||||
|
{{> printedAttack attack=attack charId=_id}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col3 flex layout vertical">
|
||||||
|
<div class="Languages double-border" style="min-height: 100px; margin-bottom: 4mm;">
|
||||||
|
<div class="paper-font-subhead layout vertical center" style="margin-bottom: 2mm;">
|
||||||
|
Languages
|
||||||
|
</div>
|
||||||
|
<div class="layout horizontal">
|
||||||
|
<div class="flex" style="margin-right: 2mm;">
|
||||||
|
{{#each languageProfs.left}}
|
||||||
|
{{> printedProficiency}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{#if languageProfs.right.length}}
|
||||||
|
<div class="flex">
|
||||||
|
{{#each languageProfs.right}}
|
||||||
|
{{> printedProficiency}}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="traits double-border">
|
||||||
|
{{#markdown}}{{evaluateShortString character._id character.personality}}{{/markdown}}
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Personality traits
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ideals double-border" style="margin-top: 2mm">
|
||||||
|
{{#markdown}}{{evaluateShortString character._id character.ideals}}{{/markdown}}
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Ideals
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bonds double-border" style="margin-top: 2mm">
|
||||||
|
{{#markdown}}{{evaluateShortString character._id character.bonds}}{{/markdown}}
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Bonds
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flaws double-border" style="margin-top: 2mm">
|
||||||
|
{{#markdown}}{{evaluateShortString character._id character.flaws}}{{/markdown}}
|
||||||
|
<div class="paper-font-subhead layout vertical center">
|
||||||
|
Flaws
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="background double-border flex layout vertical" style="margin-top: 2mm">
|
||||||
|
<div class="paper-font-subhead layout vertical center" style="margin-bottom: 4mm">
|
||||||
|
Notes
|
||||||
|
</div>
|
||||||
|
<div class="flex lined-background">
|
||||||
|
<!-- lined space for writing -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import QRCode from "qrcode"
|
||||||
|
|
||||||
|
Template.printedCharacterSheet.onRendered(function(){
|
||||||
|
// Quickfit is only called once on rendering, text will not resize reactively
|
||||||
|
this.$(".shrink-to-fit").quickfit({
|
||||||
|
min: 7,
|
||||||
|
max: 36,
|
||||||
|
truncate: true,
|
||||||
|
});
|
||||||
|
let url = `https://dicecloud.com/character/${this.data._id}`;
|
||||||
|
let canvas = this.find("#qrCode");
|
||||||
|
QRCode.toCanvas(canvas, url, {
|
||||||
|
margin: 0,
|
||||||
|
width: 200,
|
||||||
|
}, function(error){
|
||||||
|
$(canvas).css("width", "60px").css("height", "60px");
|
||||||
|
if (error) console.error(error)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.printedCharacterSheet.helpers({
|
||||||
|
character(){
|
||||||
|
return Characters.findOne(this._id);
|
||||||
|
},
|
||||||
|
classes: function(){
|
||||||
|
return Classes.find({charId: this._id}, {sort: {createdAt: 1}});
|
||||||
|
},
|
||||||
|
weaponProfs: function(){
|
||||||
|
var profs = Proficiencies.find({charId: this._id, type: "weapon"});
|
||||||
|
return removeDuplicateProficiencies(profs);
|
||||||
|
},
|
||||||
|
armorProfs: function(){
|
||||||
|
var profs = Proficiencies.find({charId: this._id, type: "armor"});
|
||||||
|
return removeDuplicateProficiencies(profs);
|
||||||
|
},
|
||||||
|
toolProfs: function(){
|
||||||
|
var profs = Proficiencies.find({charId: this._id, type: "tool"});
|
||||||
|
return removeDuplicateProficiencies(profs);
|
||||||
|
},
|
||||||
|
languageProfs: function(){
|
||||||
|
var profs = Proficiencies.find({charId: this._id, type: "language"});
|
||||||
|
profs = removeDuplicateProficiencies(profs);
|
||||||
|
if (profs.length > 3){
|
||||||
|
var halfway = Math.floor(profs.length / 2);
|
||||||
|
var left = profs.slice(0, halfway);
|
||||||
|
var right = profs.slice(halfway);
|
||||||
|
return {left, right};
|
||||||
|
} else {
|
||||||
|
return {left: profs, right: []};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attacks: function(){
|
||||||
|
return Attacks.find(
|
||||||
|
{charId: this._id, enabled: true},
|
||||||
|
{sort: {color: 1, name: 1}});
|
||||||
|
},
|
||||||
|
hitDiceTotal: function(){
|
||||||
|
let d6 = Characters.calculate.attributeValue(this._id, "d6HitDice");
|
||||||
|
let d8 = Characters.calculate.attributeValue(this._id, "d8HitDice");
|
||||||
|
let d10 = Characters.calculate.attributeValue(this._id, "d10HitDice");
|
||||||
|
let d12 = Characters.calculate.attributeValue(this._id, "d12HitDice");
|
||||||
|
d6 = d6 ? d6 + "d6" : "";
|
||||||
|
d8 = d8 ? d8 + "d8" : "";
|
||||||
|
d10 = d10 ? d10 + "d10" : "";
|
||||||
|
d12 = d12 ? d12 + "d12" : "";
|
||||||
|
return [d6, d8, d10, d12].filter(Boolean).join(" ");
|
||||||
|
},
|
||||||
|
characterUrl: function(){
|
||||||
|
return `/character/${this._id}`
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.printedCharacterSheet.events({
|
||||||
|
"click .printButton": function(event, instance){
|
||||||
|
print();
|
||||||
|
},
|
||||||
|
"click .backButton": function(event, instance){
|
||||||
|
history && history.back();
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
.printedLongStat .title {
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-left: 2mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printedLongStat .numbers {
|
||||||
|
z-index: 1;
|
||||||
|
min-width: 74px;
|
||||||
|
min-height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .printedLongStat.double-border{
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printed .printedLongStat.double-border:before {
|
||||||
|
top: 4px;
|
||||||
|
bottom: 4px;
|
||||||
|
left: 33px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<template name="printedLongStat">
|
||||||
|
<div class="printedLongStat layout horizontal double-border">
|
||||||
|
<div class="numbers paper-font-display1 octogon-border">
|
||||||
|
{{#if stat}}
|
||||||
|
{{#if isSkill}}
|
||||||
|
{{prefix}}{{skillMod}}
|
||||||
|
{{else}}
|
||||||
|
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead title flex layout horizontal center">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Template.printedLongStat.helpers({
|
||||||
|
skillMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.skillMod(
|
||||||
|
Template.parentData()._id, this.stat
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.printedProficiency iron-icon {
|
||||||
|
margin-right: 2mm;
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<template name="printedProficiency">
|
||||||
|
<div class="printedProficiency layout horizontal center">
|
||||||
|
<iron-icon icon="{{profIcon}}"></iron-icon>
|
||||||
|
<div>{{getName}}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
Template.printedProficiency.helpers({
|
||||||
|
profIcon: function(){
|
||||||
|
var prof = this.value;
|
||||||
|
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||||
|
if (prof === 1) return "image:brightness-1";
|
||||||
|
if (prof > 1) return "av:album";
|
||||||
|
return "radio-button-off";
|
||||||
|
},
|
||||||
|
getName: function(){
|
||||||
|
if (this.type === "skill") return skills[this.name];
|
||||||
|
if (this.type === "save") return saves[this.name];
|
||||||
|
return this.name;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.printedProficiency.events({
|
||||||
|
"click .proficiency": function(event, instance){
|
||||||
|
if (this.parent.collection == "Characters") {
|
||||||
|
if (this.parent.group == "background") {
|
||||||
|
pushDialogStack({
|
||||||
|
template: "backgroundDialog",
|
||||||
|
data: {
|
||||||
|
"charId": this.charId,
|
||||||
|
"field":"background",
|
||||||
|
"title":"Background",
|
||||||
|
"color":"j",
|
||||||
|
},
|
||||||
|
element: event.currentTarget,
|
||||||
|
})
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
openParentDialog({
|
||||||
|
parent: this.parent,
|
||||||
|
charId: this.charId,
|
||||||
|
element: event.currentTarget,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.printedSkillRow {
|
||||||
|
height: 24px;
|
||||||
|
min-width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printedSkillRow .skill-mod {
|
||||||
|
width: 36px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 3.5mm;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<template name="printedSkillRow">
|
||||||
|
<div class="printedSkillRow layout horizontal center">
|
||||||
|
<iron-icon icon="{{profIcon}}"></iron-icon>
|
||||||
|
{{#if failSkill}}
|
||||||
|
<div class="fail skill-mod">fail</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="{{advantage}} skill-mod">
|
||||||
|
{{skillMod}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
<div flex>
|
||||||
|
{{name}}
|
||||||
|
{{#if conditionalCount}}
|
||||||
|
*
|
||||||
|
{{/if}}
|
||||||
|
{{#if showPassive}}
|
||||||
|
({{characterCalculate "passiveSkill" ../_id skill}})
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
Template.printedSkillRow.helpers({
|
||||||
|
skillMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.skillMod(
|
||||||
|
Template.parentData()._id, this.skill
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
profIcon: function(){
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
var prof = Characters.calculate.proficiency(charId, this.skill);
|
||||||
|
if (prof > 0 && prof < 1) return "image:brightness-2";
|
||||||
|
if (prof === 1) return "image:brightness-1";
|
||||||
|
if (prof > 1) return "av:album";
|
||||||
|
return "radio-button-unchecked";
|
||||||
|
},
|
||||||
|
failSkill: function(){
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
return Effects.find({
|
||||||
|
charId: charId,
|
||||||
|
stat: this.skill,
|
||||||
|
enabled: true,
|
||||||
|
operation: "fail",
|
||||||
|
}).count();
|
||||||
|
},
|
||||||
|
advantage: function(){
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
var advantage = Characters.calculate.advantage(charId, this.skill);
|
||||||
|
if (advantage > 0) return "advantage";
|
||||||
|
if (advantage < 0) return "disadvantage";
|
||||||
|
},
|
||||||
|
conditionalCount: function(){
|
||||||
|
var charId = Template.parentData()._id;
|
||||||
|
return Effects.find({
|
||||||
|
charId: charId,
|
||||||
|
stat: this.skill,
|
||||||
|
enabled: true,
|
||||||
|
operation: "conditional",
|
||||||
|
}).count();
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.printedSquareStat {
|
||||||
|
min-width: 67px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.printedSquareStat .title.paper-font-subhead {
|
||||||
|
font-size: 2.5mm !important;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<template name="printedSquareStat">
|
||||||
|
<div class="printedSquareStat layout vertical center {{class}}">
|
||||||
|
<div class="numbers paper-font-display1">
|
||||||
|
{{#if isSkill}}
|
||||||
|
{{prefix}}{{skillMod}}
|
||||||
|
{{else}}
|
||||||
|
{{prefix}}{{characterCalculate "attributeValue" ../_id stat}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
<div class="paper-font-subhead title">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
Template.printedSquareStat.helpers({
|
||||||
|
skillMod: function() {
|
||||||
|
return signedString(
|
||||||
|
Characters.calculate.skillMod(
|
||||||
|
Template.parentData()._id, this.stat
|
||||||
|
)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -23,4 +23,17 @@
|
|||||||
<meta name="msapplication-TileColor" content="#b91d1d">
|
<meta name="msapplication-TileColor" content="#b91d1d">
|
||||||
<meta name="msapplication-TileImage" content="/mstile-144x144.png?v=lk6WXp6Pmj">
|
<meta name="msapplication-TileImage" content="/mstile-144x144.png?v=lk6WXp6Pmj">
|
||||||
<meta name="theme-color" content="#d12929">
|
<meta name="theme-color" content="#d12929">
|
||||||
|
|
||||||
|
<style type="text/css" media="print">
|
||||||
|
@page {
|
||||||
|
margin: 0mm;
|
||||||
|
}
|
||||||
|
html {
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
-webkit-transition: none !important;
|
||||||
|
transition: none !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
20
rpg-docs/client/views/meta/error/error.html
Normal file
20
rpg-docs/client/views/meta/error/error.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<template name="error">
|
||||||
|
<app-header-layout has-scrolling-region fullbleed>
|
||||||
|
<app-header class="app-grey white-text" fixed>
|
||||||
|
<app-toolbar>
|
||||||
|
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
|
||||||
|
</app-toolbar>
|
||||||
|
</app-header>
|
||||||
|
<div class="fit layout vertical center center-justified">
|
||||||
|
<div class="paper-font-subhead"
|
||||||
|
style="margin-left: 16px;
|
||||||
|
margin-right: 16px;
|
||||||
|
text-align: center;">
|
||||||
|
{{#if errorMessage}}
|
||||||
|
<div>{{errorMessage}}</div>
|
||||||
|
<paper-button class="try-again">Try Again</paper-button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</app-header-layout>
|
||||||
|
</template>
|
||||||
17
rpg-docs/client/views/meta/error/error.js
Normal file
17
rpg-docs/client/views/meta/error/error.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
Template.error.onRendered(function(){
|
||||||
|
const error = Session.get("error") || {};
|
||||||
|
if (error.href) window.history.replaceState("", "", error.href);
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.error.helpers({
|
||||||
|
errorMessage: function(){
|
||||||
|
const error = Session.get("error") || {};
|
||||||
|
return error.reason;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.error.events({
|
||||||
|
"click .try-again": function(event, instance){
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
transform-origin: top left;
|
transform-origin: top left;
|
||||||
transition: top 400ms ease, left 400ms ease;
|
transition: top 400ms ease, left 400ms ease;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog-stack .dialog .testButton {
|
.dialog-stack .dialog .testButton {
|
||||||
|
|||||||
1565
rpg-docs/package-lock.json
generated
1565
rpg-docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,9 @@
|
|||||||
"@polymer/polymer": "^1.2.5-npm-test.2",
|
"@polymer/polymer": "^1.2.5-npm-test.2",
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"bcrypt": "^1.0.3",
|
"bcrypt": "^1.0.3",
|
||||||
"bower": "^1.7.9"
|
"bower": "^1.7.9",
|
||||||
|
"core-js": "^2.5.1",
|
||||||
|
"meteor-node-stubs": "^0.3.2",
|
||||||
|
"qrcode": "^1.2.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
rpg-docs/public/png/doubleLineImageBorder.png
Normal file
BIN
rpg-docs/public/png/doubleLineImageBorder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
BIN
rpg-docs/public/png/horizontalLine.png
Normal file
BIN
rpg-docs/public/png/horizontalLine.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 180 B |
BIN
rpg-docs/public/png/octogonBorder.png
Normal file
BIN
rpg-docs/public/png/octogonBorder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
rpg-docs/public/png/shieldBorder.png
Normal file
BIN
rpg-docs/public/png/shieldBorder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
BIN
rpg-docs/public/png/upwardPointingBorder.png
Normal file
BIN
rpg-docs/public/png/upwardPointingBorder.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
8
rpg-docs/server/lib/logRateError.js
Normal file
8
rpg-docs/server/lib/logRateError.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
logRateError = function(reply, ruleInput){
|
||||||
|
// reply = {allowed, timeToReset, numInvocationsLeft}
|
||||||
|
// ruleInput = {userId, clientAddress, type, name, connectionId}
|
||||||
|
console.log(
|
||||||
|
`Limit hit for ${ruleInput.type} "${ruleInput.name}" ` +
|
||||||
|
`by user ${ruleInput.userId} from ${ruleInput.clientAddress}`
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -38,9 +38,13 @@ Meteor.publish("singleCharacter", function(characterId){
|
|||||||
DDPRateLimiter.addRule({
|
DDPRateLimiter.addRule({
|
||||||
name: "singleCharacter",
|
name: "singleCharacter",
|
||||||
type: "subscription",
|
type: "subscription",
|
||||||
userId(){ return true; },
|
userId: null,
|
||||||
connectionId(){ return true; },
|
connectionId(){ return true; },
|
||||||
}, 8, 5000);
|
}, 8, 10000, function(reply, ruleInput){
|
||||||
|
if(!reply.allowed){
|
||||||
|
logRateError(reply, ruleInput);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Meteor.publish("singleCharacterName", function(characterId){
|
Meteor.publish("singleCharacterName", function(characterId){
|
||||||
userId = this.userId;
|
userId = this.userId;
|
||||||
|
|||||||
Reference in New Issue
Block a user