diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js
index bc7cdf5522..a3a3e031f2 100644
--- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js
+++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_approve_userId.test.js
@@ -58,6 +58,12 @@ describe('POST /tasks/:id/approve/:userId', () => {
let memberTasks = await member.get('/tasks/user');
let syncedTask = find(memberTasks, findAssignedTask);
+ await member.sync();
+
+ expect(member.notifications.length).to.equal(1);
+ expect(member.notifications[0].type).to.equal('GROUP');
+ expect(member.notifications[0].data.message).to.equal(t('yourTaskHasBeenApproved'));
+
expect(syncedTask.approved).to.be.true;
expect(syncedTask.approvingUser).to.equal(user._id);
expect(syncedTask.approvedDate).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
diff --git a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js
index 71eb8e8d40..89a5407091 100644
--- a/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js
+++ b/test/api/v3/integration/tasks/groups/POST-group_tasks_id_score_direction.test.js
@@ -40,7 +40,16 @@ describe('POST /tasks/:id/score/:direction', () => {
let response = await member.post(`/tasks/${syncedTask._id}/score/up`);
let updatedTask = await member.get(`/tasks/${syncedTask._id}`);
- expect(response.message).to.equal(t('taskRequiresApproval'));
+ await user.sync();
+
+ expect(user.notifications.length).to.equal(1);
+ expect(user.notifications[0].type).to.equal('GROUP');
+ expect(user.notifications[0].data.message).to.equal(t('userHasRequestedTaskApproval', {
+ user: member.auth.local.username,
+ taskName: updatedTask.text,
+ }));
+
+ expect(response.message).to.equal(t('taskApprovalHasBeenRequested'));
expect(updatedTask.approvalRequested).to.equal(true);
expect(updatedTask.approvalRequestedDate).to.be.a('string'); // date gets converted to a string as json doesn't have a Date type
});
diff --git a/website/common/locales/en/groups.json b/website/common/locales/en/groups.json
index d750b4aec8..11ea380b05 100644
--- a/website/common/locales/en/groups.json
+++ b/website/common/locales/en/groups.json
@@ -215,5 +215,7 @@
"confirmRemoveTag": "Do you really want to remove \"<%= tag %>\"?",
"assignTask": "Assign Task",
"desktopNotificationsText": "We need your permission to enable desktop notifications for new messages in party chat! Follow your browser's instructions to turn them on.
You'll receive these notifications only while you have Habitica open. If you decide you don't like them, they can be disabled in your browser's settings.
This box will close automatically when a decision is made.",
- "claim": "Claim"
+ "claim": "Claim",
+ "yourTaskHasBeenApproved": "Your task has been approved",
+ "userHasRequestedTaskApproval": "<%= user %> has requested task approval for <%= taskName %>"
}
diff --git a/website/common/locales/en/tasks.json b/website/common/locales/en/tasks.json
index e8686b7b1d..be0578c984 100644
--- a/website/common/locales/en/tasks.json
+++ b/website/common/locales/en/tasks.json
@@ -135,5 +135,6 @@
"intelligenceExample": "Relating to academic or mentally challenging pursuits",
"perceptionExample": "Relating to work or financial tasks",
"constitutionExample": "Relating to health, wellness, and social interaction",
- "taskRequiresApproval": "This task must be approved before you can complete it."
+ "taskRequiresApproval": "This task must be approved before you can complete it. Approval has already been requested",
+ "taskApprovalHasBeenRequested": "Approval has been requested"
}
diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js
index 93537a3c65..f14e2cba2c 100644
--- a/website/server/controllers/api-v3/tasks.js
+++ b/website/server/controllers/api-v3/tasks.js
@@ -7,6 +7,7 @@ import { removeFromArray } from '../../libs/collectionManipulators';
import * as Tasks from '../../models/task';
import { model as Challenge } from '../../models/challenge';
import { model as Group } from '../../models/group';
+import { model as User } from '../../models/user';
import {
NotFound,
NotAuthorized,
@@ -319,10 +320,22 @@ api.scoreTask = {
if (task.approvalRequested) {
throw new NotAuthorized(res.t('taskRequiresApproval'));
}
+
task.approvalRequested = true;
task.approvalRequestedDate = new Date();
- await task.save();
- return res.respond(200, {message: res.t('taskRequiresApproval'), task});
+
+ let group = await Group.getGroup({user, groupId: task.group.id, fields: requiredGroupFields});
+ let groupLeader = await User.findById(group.leader); //Use this method so we can get access to notifications
+ groupLeader.addNotification('GROUP', {
+ message: res.t('userHasRequestedTaskApproval', {
+ user: user.auth.local.username,
+ taskName: task.text,
+ }),
+ });
+
+ await Bluebird.all([groupLeader.save(), task.save()]);
+
+ return res.respond(200, {message: res.t('taskApprovalHasBeenRequested'), task});
}
let wasCompleted = task.completed;
diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js
index 7f160133a1..f83d8c2a68 100644
--- a/website/server/controllers/api-v3/tasks/groups.js
+++ b/website/server/controllers/api-v3/tasks/groups.js
@@ -1,5 +1,6 @@
import { authWithHeaders } from '../../../middlewares/auth';
import ensureDevelpmentMode from '../../../middlewares/ensureDevelpmentMode';
+import Bluebird from 'bluebird';
import * as Tasks from '../../../models/task';
import { model as Group } from '../../../models/group';
import { model as User } from '../../../models/user';
@@ -203,6 +204,7 @@ api.approveTask = {
let user = res.locals.user;
let assignedUserId = req.params.userId;
+ let assignedUser = await User.findById(assignedUserId);
let taskId = req.params.taskId;
let task = await Tasks.Task.findOne({
@@ -222,7 +224,10 @@ api.approveTask = {
task.approvedDate = new Date();
task.approvingUser = user._id;
task.approved = true;
- await task.save();
+
+ assignedUser.addNotification('GROUP', {message: res.t('yourTaskHasBeenApproved')});
+
+ await Bluebird.all([assignedUser.save(), task.save()]);
res.respond(200, task);
},
diff --git a/website/server/models/userNotification.js b/website/server/models/userNotification.js
index 9d72831a13..116936cb51 100644
--- a/website/server/models/userNotification.js
+++ b/website/server/models/userNotification.js
@@ -12,6 +12,7 @@ const NOTIFICATION_TYPES = [
'REBIRTH_ACHIEVEMENT',
'NEW_CONTRIBUTOR_LEVEL',
'CRON',
+ 'GROUP',
];
const Schema = mongoose.Schema;