mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-18 15:17:25 +01:00
add email with optional message when kicking user from group
This commit is contained in:
1
common/dist/scripts/habitrpg-shared.js
vendored
1
common/dist/scripts/habitrpg-shared.js
vendored
@@ -7173,7 +7173,6 @@ process.browser = true;
|
|||||||
process.env = {};
|
process.env = {};
|
||||||
process.argv = [];
|
process.argv = [];
|
||||||
process.version = ''; // empty string to avoid regexp issues
|
process.version = ''; // empty string to avoid regexp issues
|
||||||
process.versions = {};
|
|
||||||
|
|
||||||
function noop() {}
|
function noop() {}
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,7 @@
|
|||||||
"inactivityEmails": "Your account is inactive",
|
"inactivityEmails": "Your account is inactive",
|
||||||
"questStarted": "Your Quest has Begun",
|
"questStarted": "Your Quest has Begun",
|
||||||
"invitedQuest": "Invited to Quest",
|
"invitedQuest": "Invited to Quest",
|
||||||
|
"kickedGroup": "Kicked from group",
|
||||||
"remindersToLogin": "Reminders to check in to HabitRPG",
|
"remindersToLogin": "Reminders to check in to HabitRPG",
|
||||||
"unsubscribeAllEmails": "Check to Unsubscribe from Emails",
|
"unsubscribeAllEmails": "Check to Unsubscribe from Emails",
|
||||||
"unsubscribeAllEmailsText": "By checking this box, I certify that I understand that by unsubscribing from all emails, HabitRPG will never be able to notify me via email about important changes to the site or my account.",
|
"unsubscribeAllEmailsText": "By checking this box, I certify that I understand that by unsubscribing from all emails, HabitRPG will never be able to notify me via email about important changes to the site or my account.",
|
||||||
|
|||||||
@@ -21,88 +21,105 @@ habitrpg.controller("GroupsCtrl", ['$scope', '$rootScope', 'Shared', 'Groups', '
|
|||||||
return ~(memberIds.indexOf(userid));
|
return ~(memberIds.indexOf(userid));
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.isMember = function(user, group){
|
$scope.isMember = function(user, group){
|
||||||
return ~(group.members.indexOf(user._id));
|
return ~(group.members.indexOf(user._id));
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.Members = Members;
|
||||||
|
$scope._editing = {group:false};
|
||||||
|
|
||||||
|
$scope.save = function(group){
|
||||||
|
if(group._newLeader && group._newLeader._id) group.leader = group._newLeader._id;
|
||||||
|
group.$save();
|
||||||
|
group._editing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.deleteAllMessages = function() {
|
||||||
|
if (confirm(window.env.t('confirmDeleteAllMessages'))) {
|
||||||
|
User.user.ops.clearPMs({});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$scope.Members = Members;
|
// ------ Modals ------
|
||||||
$scope._editing = {group:false};
|
|
||||||
|
|
||||||
$scope.save = function(group){
|
$scope.clickMember = function(uid, forceShow) {
|
||||||
if(group._newLeader && group._newLeader._id) group.leader = group._newLeader._id;
|
if (User.user._id == uid && !forceShow) {
|
||||||
group.$save();
|
if ($state.is('tasks')) {
|
||||||
group._editing = false;
|
$state.go('options.profile.avatar');
|
||||||
}
|
|
||||||
|
|
||||||
$scope.deleteAllMessages = function() {
|
|
||||||
if (confirm(window.env.t('confirmDeleteAllMessages'))) {
|
|
||||||
User.user.ops.clearPMs({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------ Modals ------
|
|
||||||
|
|
||||||
$scope.clickMember = function(uid, forceShow) {
|
|
||||||
if (User.user._id == uid && !forceShow) {
|
|
||||||
if ($state.is('tasks')) {
|
|
||||||
$state.go('options.profile.avatar');
|
|
||||||
} else {
|
|
||||||
$state.go('tasks');
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// We need the member information up top here, but then we pass it down to the modal controller
|
$state.go('tasks');
|
||||||
// down below. Better way of handling this?
|
|
||||||
Members.selectMember(uid, function(){
|
|
||||||
$rootScope.openModal('member', {controller:'MemberModalCtrl', windowClass:'profile-modal', size:'lg'});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
// We need the member information up top here, but then we pass it down to the modal controller
|
||||||
$scope.removeMember = function(group, member, isMember){
|
// down below. Better way of handling this?
|
||||||
$rootScope.openModal('remove-member');
|
|
||||||
/*var yes = confirm(window.env.t('sureKick'))
|
|
||||||
if(yes){
|
|
||||||
Groups.Group.removeMember({gid: group._id, uuid: member._id }, undefined, function(){
|
|
||||||
if(isMember){
|
|
||||||
_.pull(group.members, member);
|
|
||||||
}else{
|
|
||||||
_.pull(group.invites, member);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.openInviteModal = function(group){
|
|
||||||
$rootScope.openModal('invite-friends', {controller:'InviteToGroupCtrl', resolve:
|
|
||||||
{injectedGroup: function(){
|
|
||||||
return group;
|
|
||||||
}}});
|
|
||||||
};
|
|
||||||
|
|
||||||
//var serializeQs = function(obj, prefix){
|
|
||||||
// var str = [];
|
|
||||||
// for(var p in obj) {
|
|
||||||
// if (obj.hasOwnProperty(p)) {
|
|
||||||
// var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
|
|
||||||
// str.push(typeof v == "object" ?
|
|
||||||
// serializeQs(v, k) :
|
|
||||||
// encodeURIComponent(k) + "=" + encodeURIComponent(v));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return str.join("&");
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//$scope.inviteLink = function(obj){
|
|
||||||
// return window.env.BASE_URL + '?' + serializeQs({partyInvite: obj});
|
|
||||||
//}
|
|
||||||
|
|
||||||
$scope.quickReply = function(uid) {
|
|
||||||
Members.selectMember(uid, function(){
|
Members.selectMember(uid, function(){
|
||||||
$rootScope.openModal('private-message',{controller:'MemberModalCtrl'});
|
$rootScope.openModal('member', {controller:'MemberModalCtrl', windowClass:'profile-modal', size:'lg'});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
])
|
|
||||||
|
|
||||||
|
$scope.removeMember = function(group, member, isMember){
|
||||||
|
// TODO find a better way to do this (share data with remove member modal)
|
||||||
|
$scope.removeMemberData = {
|
||||||
|
group: group,
|
||||||
|
member: member,
|
||||||
|
isMember: isMember
|
||||||
|
};
|
||||||
|
$rootScope.openModal('remove-member', {scope: $scope});
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.confirmRemoveMember = function(confirm){
|
||||||
|
if(confirm){
|
||||||
|
Groups.Group.removeMember({
|
||||||
|
gid: $scope.removeMemberData.group._id,
|
||||||
|
uuid: $scope.removeMemberData.member._id,
|
||||||
|
message: $scope.removeMemberData.message,
|
||||||
|
}, undefined, function(){
|
||||||
|
if($scope.removeMemberData.isMember){
|
||||||
|
_.pull($scope.removeMemberData.group.members, $scope.removeMemberData.member);
|
||||||
|
}else{
|
||||||
|
_.pull($scope.removeMemberData.group.invites, $scope.removeMemberData.member);
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.removeMemberData = undefined;
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
$scope.removeMemberData = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.openInviteModal = function(group){
|
||||||
|
$rootScope.openModal('invite-friends', {controller:'InviteToGroupCtrl', resolve:
|
||||||
|
{injectedGroup: function(){
|
||||||
|
return group;
|
||||||
|
}}});
|
||||||
|
};
|
||||||
|
|
||||||
|
//var serializeQs = function(obj, prefix){
|
||||||
|
// var str = [];
|
||||||
|
// for(var p in obj) {
|
||||||
|
// if (obj.hasOwnProperty(p)) {
|
||||||
|
// var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
|
||||||
|
// str.push(typeof v == "object" ?
|
||||||
|
// serializeQs(v, k) :
|
||||||
|
// encodeURIComponent(k) + "=" + encodeURIComponent(v));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return str.join("&");
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//$scope.inviteLink = function(obj){
|
||||||
|
// return window.env.BASE_URL + '?' + serializeQs({partyInvite: obj});
|
||||||
|
//}
|
||||||
|
|
||||||
|
$scope.quickReply = function(uid) {
|
||||||
|
Members.selectMember(uid, function(){
|
||||||
|
$rootScope.openModal('private-message',{controller:'MemberModalCtrl'});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}])
|
||||||
|
|
||||||
.controller('InviteToGroupCtrl', ['$scope', 'User', 'Groups', 'injectedGroup', '$http', 'Notification', function($scope, User, Groups, injectedGroup, $http, Notification){
|
.controller('InviteToGroupCtrl', ['$scope', 'User', 'Groups', 'injectedGroup', '$http', 'Notification', function($scope, User, Groups, injectedGroup, $http, Notification){
|
||||||
$scope.group = injectedGroup;
|
$scope.group = injectedGroup;
|
||||||
|
|||||||
@@ -660,8 +660,21 @@ api.invite = function(req, res, next){
|
|||||||
api.removeMember = function(req, res, next){
|
api.removeMember = function(req, res, next){
|
||||||
var group = res.locals.group;
|
var group = res.locals.group;
|
||||||
var uuid = req.query.uuid;
|
var uuid = req.query.uuid;
|
||||||
|
var message = req.query.message;
|
||||||
var user = res.locals.user;
|
var user = res.locals.user;
|
||||||
|
|
||||||
|
// Send an email to the removed user with an optional message from the leader
|
||||||
|
var sendMessage = function(removedUser){
|
||||||
|
if(removedUser.preferences.emailNotifications.kickedGroup !== false){
|
||||||
|
utils.txnEmail(removedUser, ('kicked-from-' + group.type), [
|
||||||
|
{name: 'GROUP_NAME', content: group.name},
|
||||||
|
{name: 'MESSAGE', content: message},
|
||||||
|
{name: 'GUILDS_LINK', content: nconf.get('BASE_URL') + '/#/options/groups/guilds/public'},
|
||||||
|
{name: 'PARTY_WANTED_GUILD', content: nconf.get('BASE_URL') + '/#/options/groups/guilds/f2db2a7f-13c5-454d-b3ee-ea1f5089e601'}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(group.leader !== user._id){
|
if(group.leader !== user._id){
|
||||||
return res.json(401, {err: "Only group leader can remove a member!"});
|
return res.json(401, {err: "Only group leader can remove a member!"});
|
||||||
}
|
}
|
||||||
@@ -678,12 +691,21 @@ api.removeMember = function(req, res, next){
|
|||||||
Group.update({_id:group._id},update, function(err, saved){
|
Group.update({_id:group._id},update, function(err, saved){
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
|
|
||||||
// Sending an empty 204 because Group.update doesn't return the group
|
User.findById(uuid, function(err, removedUser){
|
||||||
// see http://mongoosejs.com/docs/api.html#model_Model.update
|
if(err) return next(err);
|
||||||
return res.send(204);
|
|
||||||
|
sendMessage(removedUser);
|
||||||
|
|
||||||
|
// Sending an empty 204 because Group.update doesn't return the group
|
||||||
|
// see http://mongoosejs.com/docs/api.html#model_Model.update
|
||||||
|
group = uuid = null;
|
||||||
|
return res.send(204);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}else if(_.contains(group.invites, uuid)){
|
}else if(_.contains(group.invites, uuid)){
|
||||||
User.findById(uuid, function(err,invited){
|
User.findById(uuid, function(err,invited){
|
||||||
|
if(err) return next(err);
|
||||||
|
|
||||||
var invitations = invited.invitations;
|
var invitations = invited.invitations;
|
||||||
if(group.type === 'guild'){
|
if(group.type === 'guild'){
|
||||||
invitations.guilds.splice(_.indexOf(invitations.guilds, group._id), 1);
|
invitations.guilds.splice(_.indexOf(invitations.guilds, group._id), 1);
|
||||||
@@ -703,8 +725,9 @@ api.removeMember = function(req, res, next){
|
|||||||
|
|
||||||
// Sending an empty 204 because Group.update doesn't return the group
|
// Sending an empty 204 because Group.update doesn't return the group
|
||||||
// see http://mongoosejs.com/docs/api.html#model_Model.update
|
// see http://mongoosejs.com/docs/api.html#model_Model.update
|
||||||
return res.send(204);
|
sendMessage(invited);
|
||||||
group = uuid = null;
|
group = uuid = null;
|
||||||
|
return res.send(204);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -308,6 +308,7 @@ var UserSchema = new Schema({
|
|||||||
emailNotifications: {
|
emailNotifications: {
|
||||||
unsubscribeFromAll: {type: Boolean, 'default': false},
|
unsubscribeFromAll: {type: Boolean, 'default': false},
|
||||||
newPM: {type: Boolean, 'default': true},
|
newPM: {type: Boolean, 'default': true},
|
||||||
|
kickedGroup: {type: Boolean, 'default': true},
|
||||||
wonChallenge: {type: Boolean, 'default': true},
|
wonChallenge: {type: Boolean, 'default': true},
|
||||||
giftedGems: {type: Boolean, 'default': true},
|
giftedGems: {type: Boolean, 'default': true},
|
||||||
giftedSubscription: {type: Boolean, 'default': true},
|
giftedSubscription: {type: Boolean, 'default': true},
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ module.exports.txnEmail = function(mailingInfoArray, emailType, variables){
|
|||||||
// When only one recipient send his info as variables
|
// When only one recipient send his info as variables
|
||||||
if(mailingInfoArray.length === 1 && mailingInfoArray[0].name){
|
if(mailingInfoArray.length === 1 && mailingInfoArray[0].name){
|
||||||
variables.push({name: 'RECIPIENT_NAME', content: mailingInfoArray[0].name});
|
variables.push({name: 'RECIPIENT_NAME', content: mailingInfoArray[0].name});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isProd && mailingInfoArray.length > 0){
|
if(isProd && mailingInfoArray.length > 0){
|
||||||
request({
|
request({
|
||||||
|
|||||||
@@ -305,6 +305,11 @@ script(id='partials/options.settings.notifications.html', type="text/ng-template
|
|||||||
input(type='checkbox', ng-disabled='user.preferences.emailNotifications.unsubscribeFromAll === true', ng-model='user.preferences.emailNotifications.invitedGuild', ng-change='set({"preferences.emailNotifications.invitedGuild": user.preferences.emailNotifications.invitedGuild ? true: false})')
|
input(type='checkbox', ng-disabled='user.preferences.emailNotifications.unsubscribeFromAll === true', ng-model='user.preferences.emailNotifications.invitedGuild', ng-change='set({"preferences.emailNotifications.invitedGuild": user.preferences.emailNotifications.invitedGuild ? true: false})')
|
||||||
span=env.t('invitedGuild')
|
span=env.t('invitedGuild')
|
||||||
|
|
||||||
|
.checkbox
|
||||||
|
label
|
||||||
|
input(type='checkbox', ng-disabled='user.preferences.emailNotifications.unsubscribeFromAll === true', ng-model='user.preferences.emailNotifications.kickedGroup', ng-change='set({"preferences.emailNotifications.kickedGroup": user.preferences.emailNotifications.kickedGroup ? true: false})')
|
||||||
|
span=env.t('kickedGroup')
|
||||||
|
|
||||||
.checkbox
|
.checkbox
|
||||||
label
|
label
|
||||||
input(type='checkbox', ng-disabled='user.preferences.emailNotifications.unsubscribeFromAll === true', ng-model='user.preferences.emailNotifications.questStarted', ng-change='set({"preferences.emailNotifications.questStarted": user.preferences.emailNotifications.questStarted ? true: false})')
|
input(type='checkbox', ng-disabled='user.preferences.emailNotifications.unsubscribeFromAll === true', ng-model='user.preferences.emailNotifications.questStarted', ng-change='set({"preferences.emailNotifications.questStarted": user.preferences.emailNotifications.questStarted ? true: false})')
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ script(type='text/ng-template', id='modals/remove-member.html')
|
|||||||
.modal-header
|
.modal-header
|
||||||
h4=env.t('sureKick')
|
h4=env.t('sureKick')
|
||||||
.modal-body
|
.modal-body
|
||||||
textarea.form-control(type='text',rows='5', placeholder=env.t('optionalMessage'))
|
textarea.form-control(type='text',rows='5',placeholder=env.t('optionalMessage'),ng-model='removeMemberData.message')
|
||||||
.modal-footer
|
.modal-footer
|
||||||
button.pull-left.btn.btn-danger(ng-click='')=env.t('yesRemove')
|
button.pull-left.btn.btn-danger(ng-click='confirmRemoveMember(true); $close()')=env.t('yesRemove')
|
||||||
button.btn.btn-default(ng-click='$close()')=env.t('cancel')
|
button.btn.btn-default(ng-click='confirmRemoveMember(false); $close()')=env.t('cancel')
|
||||||
Reference in New Issue
Block a user