rename /rpg-docs to /app

This commit is contained in:
Andrew Zhu
2018-06-07 01:07:49 -07:00
parent de93636c7c
commit c099e3173b
420 changed files with 12 additions and 25 deletions

View File

@@ -0,0 +1,43 @@
.character-card{
background-color: #fff;
height: 300px;
min-width: 250px;
max-width: 500px;
flex-basis: 300px;
margin: 4px;
position: relative;
}
.partyHeader {
display: inline-block;
}
.partyHeader iron-icon {
visibility: hidden;
}
.partyHeader:hover iron-icon{
visibility: initial;
}
.character-card .initials {
font-size: 100px;
color: rgba(255,255,255,0.1);
background: linear-gradient(-8deg, rgba(0,0,0,0.7), rgba(0,0,0,0));
}
.character-card paper-item {
padding-top: 16px;
padding-bottom: 16px;
height: 76px;
background-color: #545454;
background-color: rgba(0,0,0,0.3);
}
.character-card .name {
font-weight: 500;
}
.character-card paper-ripple {
color: #fff ;
}

View File

@@ -0,0 +1,88 @@
<template name="characterList">
<app-header-layout has-scrolling-region fullbleed>
<app-header class="app-grey white-text" fixed effects="waterfall">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div style="font-weight: 300;">Characters</div>
</app-toolbar>
</app-header>
<div class="padded">
{{#if currentUser}}
{{#if characters.count}}
<div class="character-list layout horizontal wrap">
{{# each charactersWithNoParty}}
{{> characterCard}}
{{/each}}
{{> gridPadding class="character-card flex layout vertical" num=12}}
</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}}
<div layout vertical center center-justified class="padded">
<div>You don't seem to have any characters yet</div>
<paper-button class="addCharacter red-button" raised>Add Character</paper-button>
</div>
{{/if}}
{{else}}
<div layout vertical center center-justified class="padded">
<div>You must sign in to view your characters</div>
</div>
{{/if}}
<div class="fab-buffer"></div>
{{#fabMenu}}
<div>
<paper-fab icon="social:group"
class="addParty"
mini>
</paper-fab>
{{#simpleTooltip class="always"}} New Party {{/simpleTooltip}}
</div>
<div>
<paper-fab icon="face"
class="addCharacter"
mini>
</paper-fab>
{{#simpleTooltip class="always"}} New Character {{/simpleTooltip}}
</div>
{{/fabMenu}}
</div>
</app-header-layout>
</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>

View File

@@ -0,0 +1,84 @@
Template.characterList.helpers({
characters() {
var userId = Meteor.userId();
return Characters.find(
{$or: [{readers: userId}, {writers: userId}, {owner: userId}]},
{sort: {name: 1}}
);
},
parties() {
return Parties.find(
{owner: Meteor.userId()},
{sort: {name: 1}},
);
},
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){
return name.replace(/[^A-Z]/g, "");
},
});
Template.characterList.events({
"click .partyHeader": function(event, instance){
pushDialogStack({
template: "partyDialog",
data: {
_id: this._id,
startEditing: true,
},
element: event.currentTarget.parentElement,
});
},
"click .addCharacter": function(event, instance) {
pushDialogStack({
template: "newCharacterDialog",
element: event.currentTarget,
callback(character){
if (!character) return;
character.owner = Meteor.userId();
let _id = Characters.insert(character);
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}']`),
});
},
});

View File

@@ -0,0 +1,17 @@
.characterPicker .character-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.characterPicker .partyHead {
font-weight: 500;
}
.characterPicker .partyHead iron-icon {
transition: transform 0.3s ease;
}
.characterPicker .partyHead iron-icon.open {
transform: rotate(90deg);
}

View File

@@ -0,0 +1,34 @@
<template name="characterPicker">
<dicecloud-selector class="characterPicker" selected={{selected}} selectable="paper-item" style="height: 100%; overflow-y: auto;">
{{#if selfId}}{{#if includeSelf}}
<paper-item class="short clickable" name={{selfId}}>
<div class="character-name">
Self
</div>
</paper-item>
{{/if}}{{/if}}
{{#each charactersWithNoParty}}
<paper-item class="short clickable" name={{_id}}>
<div class="character-name">
{{name}}
</div>
</paper-item>
{{/each}}
{{#each parties}}
<div class="paper-font-subhead partyHead clickable">
<iron-icon icon="chevron-right" class="{{#if isOpen _id}}open{{/if}}">
</iron-icon>
{{name}}
</div>
<iron-collapse opened={{isOpen _id}}>
{{#each charactersInParty}}
<paper-item class="short clickable" name={{_id}}>
<div class="character-name">
{{name}}
</div>
</paper-item>
{{/each}}
</iron-collapse>
{{/each}}
</dicecloud-selector>
</template>

View File

@@ -0,0 +1,53 @@
Template.characterPicker.onCreated(function() {
this.subscribe("characterList");
this.openedParties = new ReactiveVar(new Set());
});
Template.characterPicker.helpers({
parties() {
return Parties.find(
{owner: Meteor.userId()},
{sort: {name: 1}},
);
},
charactersInParty() {
var userId = Meteor.userId();
var selector = {
_id: {$in: this.characters, $ne: this.selfId},
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
};
if (this.writableOnly) {
selector.$or = [{writers: userId}, {owner: userId}];
}
return Characters.find(selector,{sort: {name: 1}});
},
charactersWithNoParty() {
var userId = Meteor.userId();
var charArrays = Parties.find({owner: userId}).map(p => p.characters);
var partyChars = _.uniq(_.flatten(charArrays));
var selector = {
_id: {$nin: partyChars, $ne: this.selfId},
$or: [{readers: userId}, {writers: userId}, {owner: userId}],
};
if (this.writableOnly) {
selector.$or = [{writers: userId}, {owner: userId}];
}
return Characters.find(selector, {sort: {name: 1}});
},
isOpen(id) {
var openedParties = Template.instance().openedParties.get();
return openedParties.has(id);
},
});
Template.characterPicker.events({
"click .partyHead": function(event, instance){
var openedParties = instance.openedParties.get();
if (openedParties.has(this._id)){
openedParties.delete(this._id);
} else {
openedParties.add(this._id);
}
instance.openedParties.set(openedParties);
},
});

View File

@@ -0,0 +1,22 @@
/*
prevent character names from wrapping
*/
.side-list .character-name {
white-space: nowrap;
overflow: hidden;
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);
}

View File

@@ -0,0 +1,31 @@
<template name="characterSideList">
<div class="side-list">
{{#each charactersWithNoParty}}
<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}}
{{#each parties}}
<div class="paper-font-subhead partyHead">
<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>

View File

@@ -0,0 +1,51 @@
Template.characterSideList.onCreated(function() {
this.subscribe("characterList");
this.openedParties = new ReactiveVar(new Set());
});
Template.characterSideList.helpers({
parties() {
return Parties.find(
{owner: Meteor.userId()},
{sort: {name: 1}},
);
},
charactersInParty() {
var userId = Meteor.userId();
return Characters.find(
{
_id: {$in: this.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}}
);
},
isOpen(id) {
var openedParties = Template.instance().openedParties.get();
return openedParties.has(id);
},
});
Template.characterSideList.events({
"click .partyHead": function(event, instance){
var openedParties = instance.openedParties.get();
if (openedParties.has(this._id)){
openedParties.delete(this._id);
} else {
openedParties.add(this._id);
}
instance.openedParties.set(openedParties);
},
});

View File

@@ -0,0 +1,3 @@
.partyEdit .inPartyCheckbox {
margin-bottom: 8px;
}

View File

@@ -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>

View File

@@ -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,
});
},
});