Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a332a2965 | ||
|
|
44a1daf6f8 | ||
|
|
ac23afac5d | ||
|
|
a411fb2b43 | ||
|
|
35b6fe20ae |
@@ -1,8 +1,42 @@
|
|||||||
Parties = new Mongo.Collection("parties");
|
Parties = new Mongo.Collection("parties");
|
||||||
|
|
||||||
Schemas.Party = new SimpleSchema({
|
Schemas.Party = new SimpleSchema({
|
||||||
//each character/monster can only be in one party at a time
|
name: {
|
||||||
//each party can only be in a single instance at a time
|
type: String,
|
||||||
|
defaultValue: "New Party",
|
||||||
|
trim: false,
|
||||||
|
optional: true,
|
||||||
|
},
|
||||||
|
characters: {
|
||||||
|
type: [String],
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
index: 1,
|
||||||
|
defaultValue: [],
|
||||||
|
},
|
||||||
|
owner: {
|
||||||
|
type: String,
|
||||||
|
regEx: SimpleSchema.RegEx.Id,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Parties.attachSchema(Schemas.Party);
|
Parties.attachSchema(Schemas.Party);
|
||||||
|
|
||||||
|
Parties.allow({
|
||||||
|
insert: function(userId, doc) {
|
||||||
|
return userId && doc.owner === userId;
|
||||||
|
},
|
||||||
|
update: function(userId, doc, fields, modifier) {
|
||||||
|
return userId && doc.owner === userId;
|
||||||
|
},
|
||||||
|
remove: function(userId, doc) {
|
||||||
|
return userId && doc.owner === userId;
|
||||||
|
},
|
||||||
|
fetch: ["owner"],
|
||||||
|
});
|
||||||
|
|
||||||
|
Parties.deny({
|
||||||
|
update: function(userId, docs, fields, modifier) {
|
||||||
|
// can't change owners
|
||||||
|
return _.contains(fields, "owner");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Characters = new Mongo.Collection("characters");
|
|||||||
Schemas.Character = new SimpleSchema({
|
Schemas.Character = new SimpleSchema({
|
||||||
//strings
|
//strings
|
||||||
name: {type: String, defaultValue: "", trim: false, optional: true},
|
name: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
urlName: {type: String, defaultValue: "", trim: false, optional: true},
|
urlName: {type: String, defaultValue: "-", trim: false, optional: true},
|
||||||
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
alignment: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
gender: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
race: {type: String, defaultValue: "", trim: false, optional: true},
|
race: {type: String, defaultValue: "", trim: false, optional: true},
|
||||||
@@ -543,10 +543,13 @@ if (Meteor.isServer){
|
|||||||
});
|
});
|
||||||
Characters.after.update(function(userId, doc, fieldNames, modifier, options) {
|
Characters.after.update(function(userId, doc, fieldNames, modifier, options) {
|
||||||
if (_.contains(fieldNames, "name")){
|
if (_.contains(fieldNames, "name")){
|
||||||
var urlName = getSlug(doc.name, {maintainCase: true});
|
var urlName = getSlug(doc.name, {maintainCase: true}) || "-";
|
||||||
Characters.update(doc._id, {$set: {urlName}});
|
Characters.update(doc._id, {$set: {urlName}});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Characters.before.insert(function(userId, doc) {
|
||||||
|
doc.urlName = getSlug(doc.name, {maintainCase: true}) || "-";
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Characters.allow({
|
Characters.allow({
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Router.map(function() {
|
|||||||
var _id = this.params._id
|
var _id = this.params._id
|
||||||
var character = Characters.findOne(_id);
|
var character = Characters.findOne(_id);
|
||||||
var urlName = character && character.urlName;
|
var urlName = character && character.urlName;
|
||||||
var path = `\/character\/${_id}\/${urlName}`;
|
var path = `\/character\/${_id}\/${urlName || "-"}`;
|
||||||
Router.go(path,{},{replaceState:true});
|
Router.go(path,{},{replaceState:true});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
3
rpg-docs/client/globalHelpers/characterPath.js
Normal file
3
rpg-docs/client/globalHelpers/characterPath.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Template.registerHelper("characterPath", function(char) {
|
||||||
|
return `\/character\/${char._id}\/${char.urlName || "-"}`;
|
||||||
|
});
|
||||||
@@ -8,8 +8,16 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.character-card .image {
|
.partyHeader {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partyHeader iron-icon {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partyHeader:hover iron-icon{
|
||||||
|
visibility: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
.character-card .initials {
|
.character-card .initials {
|
||||||
|
|||||||
@@ -10,31 +10,27 @@
|
|||||||
{{#if currentUser}}
|
{{#if currentUser}}
|
||||||
{{#if characters.count}}
|
{{#if characters.count}}
|
||||||
<div class="character-list layout horizontal wrap">
|
<div class="character-list layout horizontal wrap">
|
||||||
{{# each characters}}
|
{{# each charactersWithNoParty}}
|
||||||
<a class="character-card flex layout vertical end-justified" href="{{pathFor route="characterSheet" data=this}}">
|
{{> characterCard}}
|
||||||
<iron-image class="fit {{colorClass}}"
|
|
||||||
sizing="cover" preload fade src={{picture}}>
|
|
||||||
</iron-image>
|
|
||||||
{{#unless picture}}
|
|
||||||
<div class="fit initials layout vertical center center-justified">
|
|
||||||
{{initials name}}
|
|
||||||
</div>
|
|
||||||
{{/unless}}
|
|
||||||
<paper-item>
|
|
||||||
<paper-item-body two-lines>
|
|
||||||
<div class="name white87">
|
|
||||||
{{name}}
|
|
||||||
</div>
|
|
||||||
<div secondary style="color: #8a8a8a; color: rgba(255,255,255,0.87);">
|
|
||||||
{{alignment}} {{gender}} {{race}}
|
|
||||||
</div>
|
|
||||||
</paper-item-body>
|
|
||||||
</paper-item>
|
|
||||||
<paper-ripple></paper-ripple>
|
|
||||||
</a>
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{> gridPadding class="character-card flex layout vertical" num=12}}
|
{{> gridPadding class="character-card flex layout vertical" num=12}}
|
||||||
</div>
|
</div>
|
||||||
|
{{# each party in parties}}
|
||||||
|
<div class="party" data-id={{party._id}}>
|
||||||
|
{{#with party}}
|
||||||
|
<div class="partyHeader clickable paper-font-title padded">
|
||||||
|
{{name}}
|
||||||
|
<iron-icon icon="create"></iron-icon>
|
||||||
|
</div>
|
||||||
|
{{/with}}
|
||||||
|
<div class="character-list layout horizontal wrap">
|
||||||
|
{{# each charactersInParty party._id}}
|
||||||
|
{{> characterCard}}
|
||||||
|
{{/each}}
|
||||||
|
{{> gridPadding class="character-card flex layout vertical" num=12}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<div layout vertical center center-justified class="padded">
|
<div layout vertical center center-justified class="padded">
|
||||||
<div>You don't seem to have any characters yet</div>
|
<div>You don't seem to have any characters yet</div>
|
||||||
@@ -47,9 +43,46 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="fab-buffer"></div>
|
<div class="fab-buffer"></div>
|
||||||
<paper-fab class="floatyButton addCharacter"
|
{{#fabMenu}}
|
||||||
icon="add"
|
<div>
|
||||||
title="Add"></paper-fab>
|
<paper-fab icon="social:group"
|
||||||
|
class="addParty"
|
||||||
|
mini>
|
||||||
|
</paper-fab>
|
||||||
|
<paper-tooltip position="left"> New Party </paper-tooltip>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<paper-fab icon="face"
|
||||||
|
class="addCharacter"
|
||||||
|
mini>
|
||||||
|
</paper-fab>
|
||||||
|
<paper-tooltip position="left"> New Character </paper-tooltip>
|
||||||
|
</div>
|
||||||
|
{{/fabMenu}}
|
||||||
</div>
|
</div>
|
||||||
</app-header-layout>
|
</app-header-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="characterCard">
|
||||||
|
<a class="character-card flex layout vertical end-justified" href="{{characterPath this}}">
|
||||||
|
<iron-image class="fit {{colorClass}}"
|
||||||
|
sizing="cover" preload fade src={{picture}}>
|
||||||
|
</iron-image>
|
||||||
|
{{#unless picture}}
|
||||||
|
<div class="fit initials layout vertical center center-justified">
|
||||||
|
{{initials name}}
|
||||||
|
</div>
|
||||||
|
{{/unless}}
|
||||||
|
<paper-item>
|
||||||
|
<paper-item-body two-lines>
|
||||||
|
<div class="name white87">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
<div secondary style="color: #8a8a8a; color: rgba(255,255,255,0.87);">
|
||||||
|
{{alignment}} {{gender}} {{race}}
|
||||||
|
</div>
|
||||||
|
</paper-item-body>
|
||||||
|
</paper-item>
|
||||||
|
<paper-ripple></paper-ripple>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
|||||||
@@ -1,35 +1,57 @@
|
|||||||
Template.characterList.helpers({
|
Template.characterList.helpers({
|
||||||
characters(){
|
characters() {
|
||||||
var userId = Meteor.userId();
|
var userId = Meteor.userId();
|
||||||
return Characters.find(
|
return Characters.find(
|
||||||
{
|
{$or: [{readers: userId}, {writers: userId}, {owner: userId}]},
|
||||||
$or: [
|
{sort: {name: 1}}
|
||||||
{readers: userId},
|
|
||||||
{writers: userId},
|
|
||||||
{owner: userId},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fields: {
|
|
||||||
name: 1,
|
|
||||||
urlName: 1,
|
|
||||||
picture: 1,
|
|
||||||
color: 1,
|
|
||||||
race: 1,
|
|
||||||
alignment: 1,
|
|
||||||
gender: 1,
|
|
||||||
},
|
|
||||||
sort: {name: 1},
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
parties() {
|
||||||
|
return Parties.find({owner: Meteor.userId()});
|
||||||
|
},
|
||||||
|
charactersInParty(partyId) {
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
var party = Parties.findOne(partyId);
|
||||||
|
return Characters.find(
|
||||||
|
{
|
||||||
|
_id: {$in: party.characters},
|
||||||
|
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
|
||||||
|
},
|
||||||
|
{sort: {name: 1}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
charactersWithNoParty() {
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
var charArrays = Parties.find({owner: userId}).map(p => p.characters);
|
||||||
|
var partyChars = _.uniq(_.flatten(charArrays));
|
||||||
|
return Characters.find(
|
||||||
|
{
|
||||||
|
_id: {$nin: partyChars},
|
||||||
|
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
|
||||||
|
},
|
||||||
|
{sort: {name: 1}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.characterCard.helpers({
|
||||||
initials(name){
|
initials(name){
|
||||||
return name.replace(/[^A-Z]/g, "");
|
return name.replace(/[^A-Z]/g, "");
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
Template.characterList.events({
|
Template.characterList.events({
|
||||||
"tap .addCharacter": function(event, template) {
|
"click .partyHeader": function(event, instance){
|
||||||
|
pushDialogStack({
|
||||||
|
template: "partyDialog",
|
||||||
|
data: {
|
||||||
|
_id: this._id,
|
||||||
|
startEditing: true,
|
||||||
|
},
|
||||||
|
element: event.currentTarget.parentElement,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"click .addCharacter": function(event, instance) {
|
||||||
pushDialogStack({
|
pushDialogStack({
|
||||||
template: "newCharacterDialog",
|
template: "newCharacterDialog",
|
||||||
element: event.currentTarget,
|
element: event.currentTarget,
|
||||||
@@ -37,8 +59,23 @@ Template.characterList.events({
|
|||||||
if (!character) return;
|
if (!character) return;
|
||||||
character.owner = Meteor.userId();
|
character.owner = Meteor.userId();
|
||||||
let _id = Characters.insert(character);
|
let _id = Characters.insert(character);
|
||||||
Router.go("characterSheet", {_id});
|
let urlName = getSlug(character.name, {maintainCase: true}) || "-"
|
||||||
|
Router.go("characterSheet", {_id, urlName});
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
"click .addParty": function(event, instance) {
|
||||||
|
var partyId = Parties.insert({
|
||||||
|
owner: Meteor.userId(),
|
||||||
|
});
|
||||||
|
pushDialogStack({
|
||||||
|
template: "partyDialog",
|
||||||
|
data: {
|
||||||
|
_id: partyId,
|
||||||
|
startEditing: true,
|
||||||
|
},
|
||||||
|
element: event.currentTarget,
|
||||||
|
returnElement: instance.find(`.party[data-id='${partyId}']`),
|
||||||
|
});
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,8 +2,21 @@
|
|||||||
prevent character names from wrapping
|
prevent character names from wrapping
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.character-name {
|
.side-list .character-name {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.side-list .partyHead {
|
||||||
|
font-weight: 500;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-list .partyHead iron-icon {
|
||||||
|
transition: transform 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.side-list .partyHead iron-icon.open {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,31 @@
|
|||||||
<template name="characterSideList">
|
<template name="characterSideList">
|
||||||
{{#if characters.count}}
|
<div class="side-list">
|
||||||
<div class="side-list">
|
{{#each charactersWithNoParty}}
|
||||||
{{#each characters}}
|
<a href={{characterPath this}} tabindex="-1" class="side-list-character characterRepresentative">
|
||||||
<a href={{pathFor route="characterSheet" data=this}} tabindex="-1" class="side-list-character characterRepresentative">
|
<paper-item class="short">
|
||||||
<paper-item class="short">
|
<div class="character-name">
|
||||||
<div class="character-name">
|
{{name}}
|
||||||
{{name}}
|
</div>
|
||||||
</div>
|
</paper-item>
|
||||||
</paper-item>
|
</a>
|
||||||
</a>
|
{{/each}}
|
||||||
{{/each}}
|
{{#each parties}}
|
||||||
</div>
|
<div class="paper-font-subhead partyHead">
|
||||||
{{/if}}
|
<iron-icon icon="chevron-right" class="{{#if isOpen _id}}open{{/if}}">
|
||||||
|
</iron-icon>
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
<iron-collapse opened={{isOpen _id}}>
|
||||||
|
{{#each charactersInParty}}
|
||||||
|
<a href={{characterPath this}} tabindex="-1" class="side-list-character characterRepresentative">
|
||||||
|
<paper-item class="short">
|
||||||
|
<div class="character-name">
|
||||||
|
{{name}}
|
||||||
|
</div>
|
||||||
|
</paper-item>
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
</iron-collapse>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,33 +1,50 @@
|
|||||||
Template.characterSideList.onCreated(function() {
|
Template.characterSideList.onCreated(function() {
|
||||||
this.subscribe("characterList");
|
this.subscribe("characterList");
|
||||||
|
this.openedParties = new ReactiveVar(new Set());
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.characterSideList.helpers({
|
Template.characterSideList.helpers({
|
||||||
characters: function() {
|
parties() {
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
return Parties.find({owner: userId});
|
||||||
|
},
|
||||||
|
charactersInParty() {
|
||||||
var userId = Meteor.userId();
|
var userId = Meteor.userId();
|
||||||
return Characters.find(
|
return Characters.find(
|
||||||
{
|
{
|
||||||
$or: [
|
_id: {$in: this.characters},
|
||||||
{readers: userId},
|
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
|
||||||
{writers: userId},
|
|
||||||
{owner: userId},
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{sort: {name: 1}}
|
||||||
fields: {name: 1, urlName: 1},
|
|
||||||
sort: {name: 1},
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
charactersWithNoParty() {
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
var charArrays = Parties.find({owner: userId}).map(p => p.characters);
|
||||||
|
var partyChars = _.uniq(_.flatten(charArrays));
|
||||||
|
return Characters.find(
|
||||||
|
{
|
||||||
|
_id: {$nin: partyChars},
|
||||||
|
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
|
||||||
|
},
|
||||||
|
{sort: {name: 1}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
isOpen(id) {
|
||||||
|
var openedParties = Template.instance().openedParties.get();
|
||||||
|
console.log(openedParties);
|
||||||
|
return openedParties.has(id);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.characterSideList.events({
|
Template.characterSideList.events({
|
||||||
"tap .singleLineItem": function(event, instance) {
|
"click .partyHead": function(event, instance){
|
||||||
//Router.go("characterSheet", {_id: this._id});
|
var openedParties = instance.openedParties.get();
|
||||||
$("core-drawer-panel").get(0).closeDrawer();
|
if (openedParties.has(this._id)){
|
||||||
},
|
openedParties.delete(this._id);
|
||||||
"tap core-item": function() {
|
} else {
|
||||||
Router.go("characterList");
|
openedParties.add(this._id);
|
||||||
$("core-drawer-panel").get(0).closeDrawer();
|
}
|
||||||
|
instance.openedParties.set(openedParties);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.partyEdit .inPartyCheckbox {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<template name="partyDialog">
|
||||||
|
{{#with party}}
|
||||||
|
{{#baseDialog title=name hideColor=true startEditing=true}}
|
||||||
|
{{> partyDetails}}
|
||||||
|
{{else}}
|
||||||
|
{{> partyEdit}}
|
||||||
|
{{/baseDialog}}
|
||||||
|
{{/with}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="partyDetails">
|
||||||
|
<div class="fit layout vertical partyDetails" style="padding: 24px;">
|
||||||
|
<div>
|
||||||
|
{{#each character in getCharacters}}
|
||||||
|
<div>{{character.name}}</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="partyEdit">
|
||||||
|
<div class="layout vertical partyEdit" style="padding: 24px;">
|
||||||
|
<paper-input class="partyNameInput" value={{name}} label="Party name">
|
||||||
|
</paper-input>
|
||||||
|
{{#each allCharacters}}
|
||||||
|
<paper-checkbox checked={{charInParty _id}}
|
||||||
|
class="inPartyCheckbox">
|
||||||
|
{{name}}
|
||||||
|
</paper-checkbox>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
Template.partyDialog.helpers({
|
||||||
|
party(){
|
||||||
|
return Parties.findOne(this._id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.partyDetails.helpers({
|
||||||
|
getCharacters (){
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
return Characters.find(
|
||||||
|
{
|
||||||
|
_id: {$in: this.characters},
|
||||||
|
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
|
||||||
|
},
|
||||||
|
{sort: {name: 1}}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.partyEdit.helpers({
|
||||||
|
allCharacters() {
|
||||||
|
var userId = Meteor.userId();
|
||||||
|
return Characters.find(
|
||||||
|
{$or: [{readers: userId}, {writers: userId}, {owner: userId}]},
|
||||||
|
{sort: {name: 1}}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
charInParty(charId) {
|
||||||
|
return _.contains(Template.parentData().characters, charId);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.partyDialog.events({
|
||||||
|
"click #deleteButton": function(event, instance){
|
||||||
|
Parties.remove(instance.data._id);
|
||||||
|
popDialogStack();
|
||||||
|
},
|
||||||
|
"click #doneEditingButton": function(event, instance){
|
||||||
|
popDialogStack();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.partyEdit.events({
|
||||||
|
"change .inPartyCheckbox": function(event, instance){
|
||||||
|
var currentCharacters = this.characters;
|
||||||
|
var checked = event.currentTarget.checked;
|
||||||
|
var charId = this._id;
|
||||||
|
var partyId = instance.data._id;
|
||||||
|
if (checked){
|
||||||
|
Parties.update(partyId, {$addToSet: {characters: charId}});
|
||||||
|
} else {
|
||||||
|
Parties.update(partyId, {$pull: {characters: charId}});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"input .partyNameInput": function(event, instance){
|
||||||
|
var name = event.currentTarget.value;
|
||||||
|
Parties.update(this._id, {$set: {name}}, {
|
||||||
|
removeEmptyStrings: false,
|
||||||
|
trimStrings: false,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -4,11 +4,13 @@ Template.baseDialog.onCreated(function(){
|
|||||||
|
|
||||||
Template.baseDialog.helpers({
|
Template.baseDialog.helpers({
|
||||||
editing: function(){
|
editing: function(){
|
||||||
|
if (!Template.parentData() || !Template.parentData().charId) return true;
|
||||||
return Template.instance().editing.get() &&
|
return Template.instance().editing.get() &&
|
||||||
canEditCharacter(Template.parentData().charId);
|
canEditCharacter(Template.parentData().charId);
|
||||||
},
|
},
|
||||||
showEdit: function() {
|
showEdit: function() {
|
||||||
if (this.hideEdit) return false;
|
if (this.hideEdit) return false;
|
||||||
|
if (!Template.parentData() || !Template.parentData().charId) return true;
|
||||||
return canEditCharacter(Template.parentData().charId);
|
return canEditCharacter(Template.parentData().charId);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,142 +23,12 @@ Meteor.methods({
|
|||||||
|
|
||||||
Migrations.add({
|
Migrations.add({
|
||||||
version: 1,
|
version: 1,
|
||||||
name: "converts effect proficiencies to proficiency objects, removes types from assets",
|
|
||||||
up: function() {
|
|
||||||
//convert proficiency effects to proficiency objects
|
|
||||||
Effects.find({operation: "proficiency"}).forEach(function(effect){
|
|
||||||
var type = "skill";
|
|
||||||
if (_.contains(SAVES, effect.stat)) type = "save";
|
|
||||||
Proficiencies.insert({
|
|
||||||
charId: effect.charId,
|
|
||||||
name: effect.stat,
|
|
||||||
value: effect.value,
|
|
||||||
parent: _.clone(effect.parent),
|
|
||||||
type: type,
|
|
||||||
enabled: effect.enabled,
|
|
||||||
}, function(err){
|
|
||||||
if (!err) Effects.remove(effect._id);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
//store type as a parent group if it's needed
|
|
||||||
Effects.find({"parent.collection": "Characters"}).forEach(function(e){
|
|
||||||
Effects.update(e._id, {$set: {"parent.group": e.type}});
|
|
||||||
});
|
|
||||||
Attacks.find({"parent.collection": "Characters"}).forEach(function(a){
|
|
||||||
Attacks.update(a._id, {$set: {"parent.group": a.type}});
|
|
||||||
});
|
|
||||||
//remove type
|
|
||||||
Effects.update({}, {$unset: {type: ""}}, {validate: false, multi: true});
|
|
||||||
Attacks.update({}, {$unset: {type: ""}}, {validate: false, multi: true});
|
|
||||||
//remove languages and proficiencies
|
|
||||||
Characters.update(
|
|
||||||
{},
|
|
||||||
{$unset: {languages: "", proficiencies: ""}},
|
|
||||||
{validate: false, multi: true}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Migrations.add({
|
|
||||||
version: 2,
|
|
||||||
name: "Converts attacks from damage dice and damage bonus to a string with curly bracket calculations, adds settings.showIncrement to items",
|
|
||||||
up: function() {
|
|
||||||
//update attacks
|
|
||||||
Attacks.find({}).forEach(function(attack) {
|
|
||||||
if (!attack.damage && attack.damageDice && attack.damageBonus){
|
|
||||||
var newDamage = attack.damageDice +
|
|
||||||
" + {" + attack.damageBonus + "}";
|
|
||||||
Attacks.update(
|
|
||||||
attack._id,
|
|
||||||
{
|
|
||||||
$unset: {
|
|
||||||
damageBonus: "",
|
|
||||||
damageDice: "",
|
|
||||||
},
|
|
||||||
$set: {
|
|
||||||
damage: newDamage
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{validate: false});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//update Items
|
|
||||||
Items.update(
|
|
||||||
{settings: undefined},
|
|
||||||
{$set: {"settings.showIncrement" : false}},
|
|
||||||
{validate: false, multi: true}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Migrations.add({
|
|
||||||
version: 3,
|
|
||||||
name: "Converts attacks from damage dice and damage bonus to a string with curly bracket calculations, adds settings.showIncrement to items",
|
|
||||||
up: function() {
|
|
||||||
//update characters
|
|
||||||
Characters.update(
|
|
||||||
{"settings.useVariantEncumbrance": undefined},
|
|
||||||
{$set: {"settings.useVariantEncumbrance" : false}},
|
|
||||||
{validate: false, multi: true}
|
|
||||||
);
|
|
||||||
Characters.update(
|
|
||||||
{"settings.useStandardEncumbrance": undefined},
|
|
||||||
{$set: {"settings.useStandardEncumbrance" : true}},
|
|
||||||
{validate: false, multi: true}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Migrations.add({
|
|
||||||
version: 4,
|
|
||||||
name: "Adds an effect to give characters a base carry capacity",
|
|
||||||
up: function() {
|
|
||||||
//update characters
|
|
||||||
|
|
||||||
Characters.find({}).forEach(function(char){
|
|
||||||
Characters.update(char._id, {
|
|
||||||
$set: {
|
|
||||||
carryMultiplier: {
|
|
||||||
adjustment: 0,
|
|
||||||
reset: "longRest",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var effect = Effects.findOne({
|
|
||||||
charId: char._id, name: "Natural Carrying Capacity",
|
|
||||||
});
|
|
||||||
if (effect) return;
|
|
||||||
Effects.insert({
|
|
||||||
charId: char._id,
|
|
||||||
name: "Natural Carrying Capacity",
|
|
||||||
stat: "carryMultiplier",
|
|
||||||
operation: "base",
|
|
||||||
value: "1",
|
|
||||||
parent: {
|
|
||||||
id: char._id,
|
|
||||||
collection: "Characters",
|
|
||||||
group: "Inate",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
effect = Effects.findOne({
|
|
||||||
charId: char._id, name: "Natural Carrying Capacity",
|
|
||||||
});
|
|
||||||
if (!effect) throw "Carry capacity effect should be set by now."
|
|
||||||
});
|
|
||||||
},
|
|
||||||
down: function(){
|
|
||||||
return;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Migrations.add({
|
|
||||||
version: 5,
|
|
||||||
name: "Gives all characters a URL name",
|
name: "Gives all characters a URL name",
|
||||||
up: function() {
|
up: function() {
|
||||||
//update characters
|
//update characters
|
||||||
Characters.find({}).forEach(function(char){
|
Characters.find({}).forEach(function(char){
|
||||||
if (char.urlName) return;
|
if (char.urlName) return;
|
||||||
var urlName = getSlug(char.name, {maintainCase: true});
|
var urlName = getSlug(char.name, {maintainCase: true}) || "-";
|
||||||
Characters.update(char._id, {$set: {urlName}});
|
Characters.update(char._id, {$set: {urlName}});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,27 +4,24 @@ Meteor.publish("characterList", function(){
|
|||||||
this.ready();
|
this.ready();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return Characters.find(
|
return [
|
||||||
{
|
Characters.find(
|
||||||
$or: [
|
{$or: [{readers: userId}, {writers: userId}, {owner: userId}]},
|
||||||
{readers: userId},
|
{
|
||||||
{writers: userId},
|
fields: {
|
||||||
{owner: userId},
|
name: 1,
|
||||||
]
|
urlName: 1,
|
||||||
},
|
race: 1,
|
||||||
{
|
alignment: 1,
|
||||||
fields: {
|
gender: 1,
|
||||||
name: 1,
|
readers: 1,
|
||||||
urlName: 1,
|
writers:1,
|
||||||
race: 1,
|
owner: 1,
|
||||||
alignment: 1,
|
color: 1,
|
||||||
gender: 1,
|
picture: 1,
|
||||||
readers: 1,
|
}
|
||||||
writers:1,
|
|
||||||
owner: 1,
|
|
||||||
color: 1,
|
|
||||||
picture: 1,
|
|
||||||
}
|
}
|
||||||
}
|
),
|
||||||
);
|
Parties.find({owner: userId}),
|
||||||
|
];
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user