mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 14:47:53 +01:00
Merge branch 'develop' into common-convert
This commit is contained in:
@@ -65,15 +65,12 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------ Invites ------
|
$scope.openInviteModal = function(group){
|
||||||
|
$rootScope.openModal('invite-friends', {controller:'InviteToGroupCtrl', resolve:
|
||||||
$scope.invite = function(group){
|
{injectedGroup: function(){
|
||||||
Groups.Group.invite({gid: group._id, uuid: group.invitee}, undefined, function(){
|
return group;
|
||||||
group.invitee = '';
|
}}});
|
||||||
}, function(){
|
};
|
||||||
group.invitee = '';
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//var serializeQs = function(obj, prefix){
|
//var serializeQs = function(obj, prefix){
|
||||||
// var str = [];
|
// var str = [];
|
||||||
@@ -91,14 +88,6 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
//$scope.inviteLink = function(obj){
|
//$scope.inviteLink = function(obj){
|
||||||
// return window.env.BASE_URL + '?' + serializeQs({partyInvite: obj});
|
// return window.env.BASE_URL + '?' + serializeQs({partyInvite: obj});
|
||||||
//}
|
//}
|
||||||
$scope.emails = [{name:"",email:""},{name:"",email:""}];
|
|
||||||
$scope.inviter = User.user.profile.name;
|
|
||||||
$scope.inviteEmails = function(inviter, emails){
|
|
||||||
$http.post('/api/v2/user/social/invite-friends', {inviter:inviter, emails:emails}).success(function(){
|
|
||||||
Notification.text("Invitations sent!");
|
|
||||||
$scope.emails = [{name:'',email:''},{name:'',email:''}];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.quickReply = function(uid) {
|
$scope.quickReply = function(uid) {
|
||||||
Members.selectMember(uid, function(){
|
Members.selectMember(uid, function(){
|
||||||
@@ -108,6 +97,31 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
.controller('InviteToGroupCtrl', ['$scope', 'User', 'Groups', 'injectedGroup', '$http', 'Notification', function($scope, User, Groups, injectedGroup, $http, Notification){
|
||||||
|
$scope.group = injectedGroup;
|
||||||
|
|
||||||
|
$scope.inviter = User.user.profile.name;
|
||||||
|
$scope.emails = [{name:"",email:""},{name:"",email:""}];
|
||||||
|
|
||||||
|
$scope.inviteEmails = function(){
|
||||||
|
Groups.Group.invite({gid: $scope.group._id}, {inviter: $scope.inviter, emails: $scope.emails}, function(){
|
||||||
|
Notification.text("Invitation(s) sent!");
|
||||||
|
$scope.emails = [{name:'',email:''},{name:'',email:''}];
|
||||||
|
}, function(){
|
||||||
|
$scope.emails = [{name:'',email:''},{name:'',email:''}];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.invite = function(){
|
||||||
|
Groups.Group.invite({gid: $scope.group._id}, {uuids: [$scope.invitee]}, function(){
|
||||||
|
Notification.text("Invitation(s) sent!");
|
||||||
|
$scope.invitee = '';
|
||||||
|
}, function(){
|
||||||
|
$scope.invitee = '';
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}])
|
||||||
|
|
||||||
.controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members', 'Shared', '$http', 'Notification', 'Groups',
|
.controller("MemberModalCtrl", ['$scope', '$rootScope', 'Members', 'Shared', '$http', 'Notification', 'Groups',
|
||||||
function($scope, $rootScope, Members, Shared, $http, Notification, Groups) {
|
function($scope, $rootScope, Members, Shared, $http, Notification, Groups) {
|
||||||
$scope.timestamp = function(timestamp){
|
$scope.timestamp = function(timestamp){
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$
|
|||||||
templateUrl: 'modals/' + template + '.html',
|
templateUrl: 'modals/' + template + '.html',
|
||||||
controller: options.controller, // optional
|
controller: options.controller, // optional
|
||||||
scope: options.scope, // optional
|
scope: options.scope, // optional
|
||||||
|
resolve: options.resolve, // optional
|
||||||
keyboard: (options.keyboard === undefined ? true : options.keyboard), // optional
|
keyboard: (options.keyboard === undefined ? true : options.keyboard), // optional
|
||||||
backdrop: (options.backdrop === undefined ? true : options.backdrop), // optional
|
backdrop: (options.backdrop === undefined ? true : options.backdrop), // optional
|
||||||
size: options.size, // optional, 'sm' or 'lg'
|
size: options.size, // optional, 'sm' or 'lg'
|
||||||
|
|||||||
@@ -508,80 +508,148 @@ api.leave = function(req, res, next) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
api.invite = function(req, res, next) {
|
var inviteByUUIDs = function(uuids, group, req, res, next){
|
||||||
var group = res.locals.group;
|
async.each(uuids, function(uuid, cb){
|
||||||
var uuid = req.query.uuid;
|
User.findById(uuid, function(err,invite){
|
||||||
|
if (err) return cb(err);
|
||||||
User.findById(uuid, function(err,invite){
|
if (!invite)
|
||||||
if (err) return next(err);
|
return cb({code:400,err:'User with id "' + uuid + '" not found'});
|
||||||
if (!invite)
|
if (group.type == 'guild') {
|
||||||
return res.json(400,{err:'User with id "' + uuid + '" not found'});
|
if (_.contains(group.members,uuid))
|
||||||
if (group.type == 'guild') {
|
return cb({code:400,err: "User already in that group"});
|
||||||
if (_.contains(group.members,uuid))
|
if (invite.invitations && invite.invitations.guilds && _.find(invite.invitations.guilds, {id:group._id}))
|
||||||
return res.json(400,{err: "User already in that group"});
|
return cb({code:400,err:"User already invited to that group"});
|
||||||
if (invite.invitations && invite.invitations.guilds && _.find(invite.invitations.guilds, {id:group._id}))
|
|
||||||
return res.json(400, {err:"User already invited to that group"});
|
|
||||||
sendInvite();
|
|
||||||
} else if (group.type == 'party') {
|
|
||||||
if (invite.invitations && !_.isEmpty(invite.invitations.party))
|
|
||||||
return res.json(400,{err:"User already pending invitation."});
|
|
||||||
Group.find({type:'party', members:{$in:[uuid]}}, function(err, groups){
|
|
||||||
if (err) return next(err);
|
|
||||||
if (!_.isEmpty(groups))
|
|
||||||
return res.json(400,{err:"User already in a party."})
|
|
||||||
sendInvite();
|
sendInvite();
|
||||||
});
|
} else if (group.type == 'party') {
|
||||||
}
|
if (invite.invitations && !_.isEmpty(invite.invitations.party))
|
||||||
|
return cb({code:400,err:"User already pending invitation."});
|
||||||
function sendInvite (){
|
Group.find({type:'party', members:{$in:[uuid]}}, function(err, groups){
|
||||||
if(group.type === 'guild'){
|
if (err) return cb(err);
|
||||||
invite.invitations.guilds.push({id: group._id, name: group.name, inviter:res.locals.user._id});
|
if (!_.isEmpty(groups))
|
||||||
}else{
|
return cb({code:400,err:"User already in a party."})
|
||||||
//req.body.type in 'guild', 'party'
|
sendInvite();
|
||||||
invite.invitations.party = {id: group._id, name: group.name, inviter:res.locals.user._id};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
group.invites.push(invite._id);
|
function sendInvite (){
|
||||||
|
if(group.type === 'guild'){
|
||||||
async.series([
|
invite.invitations.guilds.push({id: group._id, name: group.name, inviter:res.locals.user._id});
|
||||||
function(cb){
|
}else{
|
||||||
invite.save(cb);
|
//req.body.type in 'guild', 'party'
|
||||||
},
|
invite.invitations.party = {id: group._id, name: group.name, inviter:res.locals.user._id};
|
||||||
function(cb){
|
|
||||||
group.save(cb);
|
|
||||||
},
|
|
||||||
function(cb){
|
|
||||||
populateQuery(group.type, Group.findById(group._id)).exec(cb);
|
|
||||||
}
|
}
|
||||||
], function(err, results){
|
|
||||||
if (err) return next(err);
|
|
||||||
|
|
||||||
if(invite.preferences.emailNotifications['invited' + (group.type == 'guild' ? 'Guild' : 'Party')] !== false){
|
group.invites.push(invite._id);
|
||||||
var emailVars = [
|
|
||||||
{name: 'INVITER', content: utils.getUserInfo(res.locals.user, ['name']).name}
|
async.series([
|
||||||
|
function(cb){
|
||||||
|
invite.save(cb);
|
||||||
|
},
|
||||||
|
function(cb){
|
||||||
|
group.save(cb);
|
||||||
|
}
|
||||||
|
], function(err, results){
|
||||||
|
if (err) return cb(err);
|
||||||
|
|
||||||
|
if(invite.preferences.emailNotifications['invited' + (group.type == 'guild' ? 'Guild' : 'Party')] !== false){
|
||||||
|
var emailVars = [
|
||||||
|
{name: 'INVITER', content: utils.getUserInfo(res.locals.user, ['name']).name}
|
||||||
|
];
|
||||||
|
|
||||||
|
if(group.type == 'guild'){
|
||||||
|
emailVars.push(
|
||||||
|
{name: 'GUILD_NAME', content: group.name},
|
||||||
|
{name: 'GUILD_URL', content: nconf.get('BASE_URL') + '/#/options/groups/guilds/public'}
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
emailVars.push(
|
||||||
|
{name: 'PARTY_NAME', content: group.name},
|
||||||
|
{name: 'PARTY_URL', content: nconf.get('BASE_URL') + '/#/options/groups/party'}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
utils.txnEmail(invite, ('invited-' + (group.type == 'guild' ? 'guild' : 'party')), emailVars);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, function(err){
|
||||||
|
if(err) return err.code ? res.json(err.code, {err: err.err}) : next(err);
|
||||||
|
|
||||||
|
// TODO pass group from save above don't find it again, or you have to find it again in order to run populate?
|
||||||
|
populateQuery(group.type, Group.findById(group._id)).exec(function(err, populatedGroup){
|
||||||
|
if(err) return next(err);
|
||||||
|
|
||||||
|
res.json(populatedGroup);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var inviteByEmails = function(invites, group, req, res, next){
|
||||||
|
var usersAlreadyRegistered = [];
|
||||||
|
|
||||||
|
async.each(invites, function(invite, cb){
|
||||||
|
if (invite.email) {
|
||||||
|
User.findOne({$or: [
|
||||||
|
{'auth.local.email': invite.email},
|
||||||
|
{'auth.facebook.emails.value': invite.email}
|
||||||
|
]}).select({_id: true, 'preferences.emailNotifications': true})
|
||||||
|
.exec(function(err, userToContact){
|
||||||
|
if(err) return next(err);
|
||||||
|
|
||||||
|
if(userToContact){
|
||||||
|
usersAlreadyRegistered.push(userToContact._id);
|
||||||
|
return cb();
|
||||||
|
}
|
||||||
|
|
||||||
|
// yeah, it supports guild too but for backward compatibility we'll use partyInvite as query
|
||||||
|
var link = nconf.get('BASE_URL')+'?partyInvite='+ utils.encrypt(JSON.stringify({id:group._id, inviter:res.locals.user._id, name:group.name}));
|
||||||
|
|
||||||
|
var variables = [
|
||||||
|
{name: 'LINK', content: link},
|
||||||
|
{name: 'INVITER', content: req.body.inviter || utils.getUserInfo(res.locals.user, ['name']).name}
|
||||||
];
|
];
|
||||||
|
|
||||||
if(group.type == 'guild'){
|
if(group.type == 'guild'){
|
||||||
emailVars.push(
|
variables.push({name: 'GUILD_NAME', content: group.name});
|
||||||
{name: 'GUILD_NAME', content: group.name},
|
|
||||||
{name: 'GUILD_URL', content: nconf.get('BASE_URL') + '/#/options/groups/guilds/public'}
|
|
||||||
);
|
|
||||||
}else{
|
|
||||||
emailVars.push(
|
|
||||||
{name: 'PARTY_NAME', content: group.name},
|
|
||||||
{name: 'PARTY_URL', content: nconf.get('BASE_URL') + '/#/options/groups/party'}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
utils.txnEmail(invite, ('invited-' + (group.type == 'guild' ? 'guild' : 'party')), emailVars);
|
// TODO implement "users can only be invited once"
|
||||||
}
|
invite.canSend = true; // Requested by utils.txnEmail
|
||||||
|
utils.txnEmail(invite, ('invite-friend' + (group.type == 'guild' ? '-guild' : '')), variables);
|
||||||
|
|
||||||
// Have to return whole group and its members for angular to show the invited user
|
cb();
|
||||||
res.json(results[2]);
|
});
|
||||||
group = uuid = null;
|
}else{
|
||||||
});
|
cb();
|
||||||
|
}
|
||||||
|
}, function(err){
|
||||||
|
if(err) return err.code ? res.json(err.code, {err: err.err}) : next(err);
|
||||||
|
|
||||||
|
if(usersAlreadyRegistered.length > 0){
|
||||||
|
inviteByUUIDs(usersAlreadyRegistered, group, req, res, next);
|
||||||
|
}else{
|
||||||
|
|
||||||
|
// Send only status code down the line because it doesn't need
|
||||||
|
// info on invited users since they are not yet registered
|
||||||
|
res.send(200);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
api.invite = function(req, res, next){
|
||||||
|
var group = res.locals.group;
|
||||||
|
|
||||||
|
if(req.body.uuids){
|
||||||
|
inviteByUUIDs(req.body.uuids, group, req, res, next);
|
||||||
|
}else if(req.body.emails){
|
||||||
|
inviteByEmails(req.body.emails, group, req, res, next)
|
||||||
|
}else{
|
||||||
|
return res.json(400,{err: "Can invite only by email or uuid"});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.removeMember = function(req, res, next){
|
api.removeMember = function(req, res, next){
|
||||||
|
|||||||
@@ -409,54 +409,15 @@ api.cast = function(req, res, next) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// It supports guild too now but we'll stick to partyInvite for backward compatibility
|
||||||
* POST /user/invite-friends
|
|
||||||
*/
|
|
||||||
api.inviteFriends = function(req, res, next) {
|
|
||||||
Group.findOne({type:'party', members:{'$in': [res.locals.user._id]}}).select('_id name').exec(function(err,party){
|
|
||||||
if (err) return next(err);
|
|
||||||
|
|
||||||
_.each(req.body.emails, function(invite){
|
|
||||||
if (invite.email) {
|
|
||||||
|
|
||||||
User.findOne({$or: [
|
|
||||||
{'auth.local.email': invite.email},
|
|
||||||
{'auth.facebook.emails.value': invite.email}
|
|
||||||
]}).select({_id: true, 'preferences.emailNotifications': true})
|
|
||||||
.exec(function(err, userToContact){
|
|
||||||
if(err) return next(err);
|
|
||||||
|
|
||||||
var link = nconf.get('BASE_URL')+'?partyInvite='+ utils.encrypt(JSON.stringify({id:party._id, inviter:res.locals.user._id, name:party.name}));
|
|
||||||
|
|
||||||
var variables = [
|
|
||||||
{name: 'LINK', content: link},
|
|
||||||
{name: 'INVITER', content: req.body.inviter || utils.getUserInfo(res.locals.user, ['name']).name}
|
|
||||||
];
|
|
||||||
|
|
||||||
invite.canSend = true;
|
|
||||||
|
|
||||||
// We check for unsubscribeFromAll here because don't pass through utils.getUserInfo
|
|
||||||
if(!userToContact || (userToContact.preferences.emailNotifications.invitedParty !== false &&
|
|
||||||
userToContact.preferences.emailNotifications.unsubscribeFromAll !== true)){
|
|
||||||
// TODO implement "users can only be invited once"
|
|
||||||
utils.txnEmail(invite, 'invite-friend', variables);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
res.send(200);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
api.sessionPartyInvite = function(req,res,next){
|
api.sessionPartyInvite = function(req,res,next){
|
||||||
if (!req.session.partyInvite) return next();
|
if (!req.session.partyInvite) return next();
|
||||||
var inv = res.locals.user.invitations;
|
var inv = res.locals.user.invitations;
|
||||||
if (inv.party && inv.party.id) return next(); // already invited to a party
|
if (inv.party && inv.party.id) return next(); // already invited to a party
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
function(cb){
|
function(cb){
|
||||||
Group.findOne({_id:req.session.partyInvite.id, type:'party', members:{$in:[req.session.partyInvite.inviter]}})
|
Group.findOne({_id:req.session.partyInvite.id, members:{$in:[req.session.partyInvite.inviter]}})
|
||||||
.select('invites members').exec(cb);
|
.select('invites members type').exec(cb);
|
||||||
},
|
},
|
||||||
function(group, cb){
|
function(group, cb){
|
||||||
if (!group){
|
if (!group){
|
||||||
@@ -464,6 +425,13 @@ api.sessionPartyInvite = function(req,res,next){
|
|||||||
delete req.session.partyInvite;
|
delete req.session.partyInvite;
|
||||||
return cb();
|
return cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(group.type == 'guild'){
|
||||||
|
inv.guilds.push(req.session.partyInvite);
|
||||||
|
}else{
|
||||||
|
//req.body.type in 'guild', 'party'
|
||||||
|
inv.party = req.session.partyInvite;
|
||||||
|
}
|
||||||
inv.party = req.session.partyInvite;
|
inv.party = req.session.partyInvite;
|
||||||
delete req.session.partyInvite;
|
delete req.session.partyInvite;
|
||||||
if (!~group.invites.indexOf(res.locals.user._id))
|
if (!~group.invites.indexOf(res.locals.user._id))
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ module.exports.locals = function(req, res, next) {
|
|||||||
worldDmg: (tavern && tavern.quest && tavern.quest.extra && tavern.quest.extra.worldDmg) || {}
|
worldDmg: (tavern && tavern.quest && tavern.quest.extra && tavern.quest.extra.worldDmg) || {}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Put query-string party invitations into session to be handled later
|
// Put query-string party (& guild but use partyInvite for backward compatibility)
|
||||||
|
// invitations into session to be handled later
|
||||||
try{
|
try{
|
||||||
req.session.partyInvite = JSON.parse(utils.decrypt(req.query.partyInvite))
|
req.session.partyInvite = JSON.parse(utils.decrypt(req.query.partyInvite))
|
||||||
} catch(e){}
|
} catch(e){}
|
||||||
|
|||||||
@@ -365,15 +365,6 @@ module.exports = (swagger, v2) ->
|
|||||||
]
|
]
|
||||||
action: user.deleteTag
|
action: user.deleteTag
|
||||||
|
|
||||||
"/user/social/invite-friends":
|
|
||||||
spec:
|
|
||||||
method: 'POST'
|
|
||||||
description: 'Invite friends via email'
|
|
||||||
parameters: [
|
|
||||||
body 'invites','Array of [{name:"Friend\'s Name", email:"friends@email.com"}] to invite to play in your party','object'
|
|
||||||
]
|
|
||||||
action: user.inviteFriends
|
|
||||||
|
|
||||||
# Webhooks
|
# Webhooks
|
||||||
"/user/webhooks":
|
"/user/webhooks":
|
||||||
spec:
|
spec:
|
||||||
@@ -469,7 +460,7 @@ module.exports = (swagger, v2) ->
|
|||||||
description: "Invite a user to a group"
|
description: "Invite a user to a group"
|
||||||
parameters: [
|
parameters: [
|
||||||
path 'gid','Group id','string'
|
path 'gid','Group id','string'
|
||||||
query 'uuid','User id to invite','string'
|
body '','a payload of invites either under body.uuids or body.emails, only one of them!','object'
|
||||||
]
|
]
|
||||||
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
middleware: [auth.auth, i18n.getUserLanguage, groups.attachGroup]
|
||||||
action:groups.invite
|
action:groups.invite
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
.panel-heading
|
.panel-heading
|
||||||
h3.panel-title
|
h3.panel-title
|
||||||
=env.t('members')
|
=env.t('members')
|
||||||
button.pull-right.btn.btn-primary(ng-click="openModal('invite-friends', {controller:'GroupsCtrl'})", ng-if='::group.type=="party"') Invite Friends
|
button.pull-right.btn.btn-primary(ng-click="openInviteModal(group)") Invite Friends
|
||||||
.panel-body.modal-fixed-height
|
.panel-body.modal-fixed-height
|
||||||
div.form-group(ng-if='::group.type=="party"')
|
div.form-group(ng-if='::group.type=="party"')
|
||||||
p=env.t('partyList')
|
p=env.t('partyList')
|
||||||
@@ -99,14 +99,6 @@ a.pull-right.gem-wallet(ng-if='group.type!="party"', popover-trigger='mouseenter
|
|||||||
a.media-body
|
a.media-body
|
||||||
span(ng-click='clickMember(invite._id, true)')
|
span(ng-click='clickMember(invite._id, true)')
|
||||||
| {{invite.profile.name}}
|
| {{invite.profile.name}}
|
||||||
.panel-footer(ng-if='::group.type!="party"')
|
|
||||||
form.form-inline(ng-submit='invite(group)')
|
|
||||||
//.alert.alert-danger(ng-show='_groupError') {{_groupError}}
|
|
||||||
.input-group
|
|
||||||
input.form-control(type='text', placeholder=env.t('userId'), ng-model='group.invitee')
|
|
||||||
span.input-group-btn
|
|
||||||
input.btn.btn-default(type='submit', value=env.t('invite'))
|
|
||||||
|
|
||||||
|
|
||||||
a.btn.btn-danger(data-id='{{group.id}}', ng-click='clickLeave(group, $event)')=env.t('leave')
|
a.btn.btn-danger(data-id='{{group.id}}', ng-click='clickLeave(group, $event)')=env.t('leave')
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ script(type='text/ng-template', id='modals/invite-friends.html')
|
|||||||
.modal-body
|
.modal-body
|
||||||
p.alert.alert-info Invite friends by <a href='http://habitrpg.wikia.com/wiki/API_Options' target='_blank'>User ID</a> here.
|
p.alert.alert-info Invite friends by <a href='http://habitrpg.wikia.com/wiki/API_Options' target='_blank'>User ID</a> here.
|
||||||
|
|
||||||
form.form-inline(ng-submit='invite(party)')
|
form.form-inline(ng-submit='invite()')
|
||||||
//-.alert.alert-danger(ng-show='_groupError') {{_groupError}}
|
//-.alert.alert-danger(ng-show='_groupError') {{_groupError}}
|
||||||
.form-group
|
.form-group
|
||||||
input.form-control(type='text', placeholder=env.t('userId'), ng-model='party.invitee')
|
input.form-control(type='text', placeholder=env.t('userId'), ng-model='invitee')
|
||||||
|
|
|
|
||||||
button.btn.btn-primary(type='submit') Invite Existing User
|
button.btn.btn-primary(type='submit') Invite Existing User
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ script(type='text/ng-template', id='modals/invite-friends.html')
|
|||||||
|
|
||||||
p.alert.alert-info Invite friends by email. If they join via your email, they'll automatically be invited to your party.
|
p.alert.alert-info Invite friends by email. If they join via your email, they'll automatically be invited to your party.
|
||||||
|
|
||||||
form.form-horizontal(ng-submit='inviteEmails(inviter, emails)')
|
form.form-horizontal(ng-submit='inviteEmails()')
|
||||||
table.table.table-striped
|
table.table.table-striped
|
||||||
thead
|
thead
|
||||||
tr
|
tr
|
||||||
|
|||||||
Reference in New Issue
Block a user