Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2a332a2965 | ||
|
|
44a1daf6f8 |
@@ -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");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -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="{{characterPath 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={{characterPath 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);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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