mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-19 15:48:04 +01:00
rewrite & api: use mongoose populate to replace group.members array with
popualte member objects. this puts a load on the front-end, we'll need to optimize! also added some duplicates sanitization.
This commit is contained in:
@@ -4,7 +4,9 @@ habitrpg
|
|||||||
|
|
||||||
.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', '$location',
|
.controller("GroupsCtrl", ['$scope', '$rootScope', 'Groups', '$http', '$location',
|
||||||
function($scope, $rootScope, Groups) {
|
function($scope, $rootScope, Groups) {
|
||||||
$scope.groups = Groups.query();
|
$scope.groups = Groups.query(function(groups){
|
||||||
|
$scope.members = groups.members;
|
||||||
|
});
|
||||||
$scope.party = true;
|
$scope.party = true;
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -18,34 +18,23 @@ var api = module.exports;
|
|||||||
|
|
||||||
api.getGroups = function(req, res, next) {
|
api.getGroups = function(req, res, next) {
|
||||||
var user = res.locals.user;
|
var user = res.locals.user;
|
||||||
/*TODO should we support non-authenticated users? just for viewing public groups?*/
|
var usernameFields = 'auth.local.username auth.facebook.first_name auth.facebook.last_name auth.facebook.name auth.facebook.username';
|
||||||
|
|
||||||
return async.parallel({
|
// First get all groups
|
||||||
|
async.parallel({
|
||||||
party: function(cb) {
|
party: function(cb) {
|
||||||
async.waterfall([
|
Group
|
||||||
function(cb2) {
|
.findOne({type: 'party', members: {'$in': [user._id]}})
|
||||||
Group.findOne({type: 'party', members: {'$in': [user._id]}}, cb2);
|
.populate({
|
||||||
}, function(party, cb2) {
|
path: 'members',
|
||||||
var fields, query;
|
//match: {_id: {$ne: user._id}}, //fixme this causes it to hang??
|
||||||
party = party.toJSON();
|
select: 'profile preferences items stats achievements party backer ' + usernameFields
|
||||||
query = {_id: {
|
})
|
||||||
'$in': party.members,
|
.exec(cb);
|
||||||
'$nin': [user._id]
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fields = 'profile preferences items stats achievements party backer auth.local.username auth.facebook.first_name auth.facebook.last_name auth.facebook.name auth.facebook.username'.split(' ');
|
|
||||||
fields = _.reduce(fields, (function(m, k, v) {m[k] = 1;return m;}), {});
|
|
||||||
User.find(query, fields, function(err, members) {
|
|
||||||
party.members = members;
|
|
||||||
cb2(err, party);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
], function(err, members) {
|
|
||||||
cb(err, members);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
guilds: function(cb) {
|
guilds: function(cb) {
|
||||||
Group.find({type: 'guild', members: {'$in': [user._id]}}, cb);
|
Group.find({type: 'guild', members: {'$in': [user._id]}}).populate('members', usernameFields).exec(cb);
|
||||||
|
// Group.find({type: 'guild', members: {'$in': [user._id]}}, cb);
|
||||||
},
|
},
|
||||||
tavern: function(cb) {
|
tavern: function(cb) {
|
||||||
Group.findOne({_id: 'habitrpg'}, cb);
|
Group.findOne({_id: 'habitrpg'}, cb);
|
||||||
@@ -59,8 +48,13 @@ api.getGroups = function(req, res, next) {
|
|||||||
members: 1
|
members: 1
|
||||||
}, cb);
|
}, cb);
|
||||||
}
|
}
|
||||||
}, function(err, results) {
|
}, function(err, results){
|
||||||
if (err) return res.json(500, {err: err});
|
if (err) return res.json(500, {err: err});
|
||||||
|
|
||||||
|
// Remove self from party (see above failing `match` directive in `populate`
|
||||||
|
var i = _.findIndex(results.party.members, {_id:user._id});
|
||||||
|
if (~i) results.party.members.splice(i,1);
|
||||||
|
|
||||||
res.json(results);
|
res.json(results);
|
||||||
});
|
})
|
||||||
};
|
};
|
||||||
@@ -1,18 +1,10 @@
|
|||||||
var GroupSchema, Schema, helpers, mongoose, _;
|
var mongoose = require("mongoose");
|
||||||
|
var Schema = mongoose.Schema;
|
||||||
|
var helpers = require('habitrpg-shared/script/helpers');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
mongoose = require("mongoose");
|
var GroupSchema = new Schema({
|
||||||
|
_id: {type: String, 'default': helpers.uuid},
|
||||||
Schema = mongoose.Schema;
|
|
||||||
|
|
||||||
helpers = require('habitrpg-shared/script/helpers');
|
|
||||||
|
|
||||||
_ = require('lodash');
|
|
||||||
|
|
||||||
GroupSchema = new Schema({
|
|
||||||
_id: {
|
|
||||||
type: String,
|
|
||||||
'default': helpers.uuid
|
|
||||||
},
|
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
leader: {
|
leader: {
|
||||||
@@ -43,7 +35,9 @@ GroupSchema = new Schema({
|
|||||||
Number: Number,
|
Number: Number,
|
||||||
'default': 0
|
'default': 0
|
||||||
},
|
},
|
||||||
|
websites: Array,
|
||||||
chat: Array,
|
chat: Array,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
# [{
|
# [{
|
||||||
# timestamp: Date
|
# timestamp: Date
|
||||||
@@ -58,10 +52,41 @@ GroupSchema = new Schema({
|
|||||||
balance: Number,
|
balance: Number,
|
||||||
logo: String,
|
logo: String,
|
||||||
leaderMessage: String
|
leaderMessage: String
|
||||||
}, {
|
}, {strict: 'throw'});
|
||||||
strict: 'throw'
|
|
||||||
});
|
|
||||||
|
/**
|
||||||
|
* Derby duplicated stuff. This is a temporary solution, once we're completely off derby we'll run an mongo migration
|
||||||
|
* to remove duplicates, then take these fucntions out
|
||||||
|
*/
|
||||||
|
function removeDuplicates(doc){
|
||||||
|
// Remove duplicate members
|
||||||
|
if (doc.members) {
|
||||||
|
var uniqMembers = _.uniq(doc.members);
|
||||||
|
if (uniqMembers.length != doc.members.length) {
|
||||||
|
doc.members = uniqMembers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doc.websites) {
|
||||||
|
var uniqWebsites = _.uniq(doc.websites);
|
||||||
|
if (uniqWebsites.length != doc.websites.length) {
|
||||||
|
doc.websites = uniqWebsites;
|
||||||
|
}
|
||||||
|
console.log(doc.websites);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GroupSchema.pre('save', function(next){
|
||||||
|
removeDuplicates(this);
|
||||||
|
next();
|
||||||
|
})
|
||||||
|
|
||||||
|
GroupSchema.methods.toJSON = function(){
|
||||||
|
var doc = this.toObject();
|
||||||
|
removeDuplicates(doc);
|
||||||
|
return doc;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports.schema = GroupSchema;
|
module.exports.schema = GroupSchema;
|
||||||
|
|
||||||
module.exports.model = mongoose.model("Group", GroupSchema);
|
module.exports.model = mongoose.model("Group", GroupSchema);
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
var Schema, UserSchema, helpers, mongoose, _;
|
var mongoose = require("mongoose");
|
||||||
|
var Schema = mongoose.Schema;
|
||||||
|
var helpers = require('habitrpg-shared/script/helpers');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
mongoose = require("mongoose");
|
var UserSchema = new Schema({
|
||||||
|
|
||||||
Schema = mongoose.Schema;
|
|
||||||
|
|
||||||
helpers = require('habitrpg-shared/script/helpers');
|
|
||||||
|
|
||||||
_ = require('lodash');
|
|
||||||
|
|
||||||
UserSchema = new Schema({
|
|
||||||
_id: {
|
_id: {
|
||||||
type: String,
|
type: String,
|
||||||
'default': helpers.uuid
|
'default': helpers.uuid
|
||||||
@@ -274,20 +269,16 @@ UserSchema.post('init', function(doc) {
|
|||||||
|
|
||||||
|
|
||||||
UserSchema.methods.toJSON = function() {
|
UserSchema.methods.toJSON = function() {
|
||||||
var doc;
|
var doc = this.toObject();
|
||||||
doc = this.toObject();
|
|
||||||
doc.id = doc._id;
|
doc.id = doc._id;
|
||||||
_.each(['habit', 'daily', 'todo', 'reward'], function(type) {
|
_.each(['habit', 'daily', 'todo', 'reward'], function(type) {
|
||||||
/* we use _.transform instead of a simple _.where in order to maintain sort-order*/
|
// we use _.transform instead of a simple _.where in order to maintain sort-order
|
||||||
|
doc["" + type + "s"] = _.transform(doc["" + type + "Ids"], function(result, tid) {
|
||||||
return doc["" + type + "s"] = _.transform(doc["" + type + "Ids"], function(result, tid) {
|
result.push(doc.tasks[tid]);
|
||||||
return result.push(doc.tasks[tid]);
|
|
||||||
});
|
});
|
||||||
/*delete doc["#{type}Ids"]*/
|
//delete doc["#{type}Ids"]
|
||||||
|
|
||||||
});
|
});
|
||||||
/*delete doc.tasks*/
|
//delete doc.tasks
|
||||||
|
|
||||||
doc.filters = {};
|
doc.filters = {};
|
||||||
return doc;
|
return doc;
|
||||||
};
|
};
|
||||||
@@ -296,16 +287,12 @@ UserSchema.methods.toJSON = function() {
|
|||||||
# FIXME - since we're using special @post('init') above, we need to flag when the original path was modified.
|
# FIXME - since we're using special @post('init') above, we need to flag when the original path was modified.
|
||||||
# Custom setter/getter virtuals?
|
# Custom setter/getter virtuals?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
UserSchema.pre('save', function(next) {
|
UserSchema.pre('save', function(next) {
|
||||||
this.markModified('tasks');
|
this.markModified('tasks');
|
||||||
/*our own version incrementer*/
|
//our own version incrementer
|
||||||
|
|
||||||
this._v++;
|
this._v++;
|
||||||
return next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports.schema = UserSchema;
|
module.exports.schema = UserSchema;
|
||||||
|
|
||||||
module.exports.model = mongoose.model("User", UserSchema);
|
module.exports.model = mongoose.model("User", UserSchema);
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
a.pull-right.gem-wallet(ng-show='group.type=="guild" && group.id!="habitrpg"', rel='popover', data-trigger='hover', data-title='Guild Bank', data-content='Gems which your Guild leader can use for prizes in the upcoming <a target=_blank href="https://trello.com/card/challenges-individual-party-guild-public/50e5d3684fe3a7266b0036d6/58">Challenges</a> feature.', data-placement='bottom', data-html='true')
|
a.pull-right.gem-wallet(rel='popover', data-trigger='hover', data-title='Guild Bank', data-content='Gems which your Guild leader can use for prizes in the upcoming <a target=_blank href="https://trello.com/card/challenges-individual-party-guild-public/50e5d3684fe3a7266b0036d6/58">Challenges</a> feature.', data-placement='bottom', data-html='true')
|
||||||
// <span class="task-action-btn tile flush bright add-gems-btn">+</span>
|
// <span class="task-action-btn tile flush bright add-gems-btn">+</span>
|
||||||
span.task-action-btn.tile.flush.neutral
|
span.task-action-btn.tile.flush.neutral
|
||||||
.Gems
|
.Gems
|
||||||
| {{gems(group.balance)}} Guild Gems
|
| {{group.balance / 4 | number:0 }} Guild Gems
|
||||||
.row-fluid
|
.row-fluid
|
||||||
.span4
|
.span4
|
||||||
h3 {{group.name}}
|
h3 {{group.name}}
|
||||||
@@ -43,24 +43,24 @@ a.pull-right.gem-wallet(ng-show='group.type=="guild" && group.id!="habitrpg"', r
|
|||||||
|
|
||||||
accordion-group(heading='Members')
|
accordion-group(heading='Members')
|
||||||
table.table.table-striped
|
table.table.table-striped
|
||||||
tr(ng-repeat='memberId in group.members')
|
tr(ng-repeat='member in group.members')
|
||||||
td
|
td
|
||||||
// allow leaders to ban members
|
// allow leaders to ban members
|
||||||
div(ng-show='and(equal(group.leader,_user.id),not(equal(_user.id,memberId)))')
|
div(ng-show='group.leader == user.id && user.id!=member._id')
|
||||||
// {{#with group.members[$index]}}
|
// {{#with group.members[$index]}}
|
||||||
a(x-bind='click:removeAt', data-refresh='true', data-confirm='Boot this member?')
|
a(x-bind='click:removeAt', data-refresh='true', data-confirm='Boot this member?')
|
||||||
i.icon-ban-circle(rel='tooltip', title='Boot Member')
|
i.icon-ban-circle(tooltip='Boot Member')
|
||||||
// {{/}}
|
// {{/}}
|
||||||
a(data-toggle='modal', data-target='#avatar-modal-{{memberId}}')
|
a(data-toggle='modal', data-target='#avatar-modal-{{member._id}}')
|
||||||
span(ng-class='{"badge badge-info": group.leader==memberId}')
|
span(ng-class='{"badge badge-info": group.leader==member._id}')
|
||||||
| {{username(_members[memberId].auth, _members[memberId].profile.name)}}
|
| {{username(member.auth, member.profile.name)}}
|
||||||
td
|
td
|
||||||
| ({{memberId}})
|
| ({{member._id}})
|
||||||
// {#with group as :group}
|
// {#with group as :group}
|
||||||
form.form-inline(x-bind='submit:groupInvite', data-type='{group.type}')
|
form.form-inline(x-bind='submit:groupInvite', data-type='{{group.type}}')
|
||||||
.alert.alert-danger(ng-show='_groupError') {_groupError}
|
.alert.alert-danger(ng-show='_groupError') {{_groupError}}
|
||||||
.control-group
|
.control-group
|
||||||
input.input-medium(type='text', placeholder='User Id', value='{_groupInvitee}')
|
input.input-medium(type='text', placeholder='User Id', value='{{_groupInvitee}}')
|
||||||
input.btn(type='submit', value='Invite')
|
input.btn(type='submit', value='Invite')
|
||||||
// {/}
|
// {/}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ a.pull-right.gem-wallet(ng-show='group.type=="guild" && group.id!="habitrpg"', r
|
|||||||
div(ng-show='_editing.leaderMessage[group.id]')
|
div(ng-show='_editing.leaderMessage[group.id]')
|
||||||
a.pull-right(x-bind='click:toggleLeaderMessageEdit', data-gid='{{group.id}}')
|
a.pull-right(x-bind='click:toggleLeaderMessageEdit', data-gid='{{group.id}}')
|
||||||
i.icon-ok
|
i.icon-ok
|
||||||
textarea(cols='3', placeholder='Message from group leader') {group.leaderMessage}
|
textarea(cols='3', placeholder='Message from group leader') {{group.leaderMessage}}
|
||||||
div(ng-hide='_editing.leaderMessage[group.id]')
|
div(ng-hide='_editing.leaderMessage[group.id]')
|
||||||
a.btn.pull-right(x-bind='click:toggleLeaderMessageEdit', data-gid='{{group.id}}') Edit leader message
|
a.btn.pull-right(x-bind='click:toggleLeaderMessageEdit', data-gid='{{group.id}}') Edit leader message
|
||||||
table(ng-show='group.leaderMessage')
|
table(ng-show='group.leaderMessage')
|
||||||
@@ -100,7 +100,7 @@ a.pull-right.gem-wallet(ng-show='group.type=="guild" && group.id!="habitrpg"', r
|
|||||||
.popover.static-popover.fade.right.in
|
.popover.static-popover.fade.right.in
|
||||||
.arrow
|
.arrow
|
||||||
h3.popover-title {{username(_members[group.leader].auth,_members[group.leader].profile.name)}}
|
h3.popover-title {{username(_members[group.leader].auth,_members[group.leader].profile.name)}}
|
||||||
.popover-content {group.leaderMessage}
|
.popover-content {{group.leaderMessage}}
|
||||||
h3 Chat
|
h3 Chat
|
||||||
include ./chat-box
|
include ./chat-box
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ div(ng-controller='GroupsCtrl')
|
|||||||
|
|
||||||
.tab-content
|
.tab-content
|
||||||
#groups-party.tab-pane.active Party
|
#groups-party.tab-pane.active Party
|
||||||
div(ng-show='groups.party.id', ng-controller='PartyCtrl')
|
div(ng-show='group._id', ng-controller='PartyCtrl')
|
||||||
app:groups:group(group='{groups[_party.id]}')
|
include ./group
|
||||||
div(ng-hide='groups.party.id')
|
div(ng-hide='group._id')
|
||||||
div(ng-show='user.invitations.party')
|
div(ng-show='user.invitations.party')
|
||||||
// #with required for the accept/reject buttons
|
// #with required for the accept/reject buttons
|
||||||
// {#with _user.invitations.party as :party}
|
// {#with _user.invitations.party as :party}
|
||||||
|
|||||||
Reference in New Issue
Block a user