@@ -1048,12 +1038,26 @@ export default {
},
teamManagerAccess () {
if (!this.isGroupTask || !this.group) return true;
+ if (!this.group.leader && !this.group.managers) return false;
return (this.group.leader._id === this.user._id || this.group.managers[this.user._id]);
},
displayNotes () {
if (this.isGroupTask && !this.isUser) return this.task.group.managerNotes;
return this.task.notes;
},
+ isOpenTask () {
+ if (!this.isGroupTask) return false;
+ if (this.task.group.assignedUsers.length > 0) return false;
+ return true;
+ },
+ showTaskLockIcon () {
+ if (this.isUser) return false;
+ if (this.isGroupTask) {
+ if (this.isOpenTask) return false;
+ if (this.task.group.assignedUsers.indexOf(this.user._id) !== -1) return false;
+ }
+ return true;
+ },
},
methods: {
...mapActions({
@@ -1121,6 +1125,8 @@ export default {
setTimeout(() => this.$root.$emit('castEnd', task, 'task', e), 0);
},
async score (direction) {
+ if (this.showTaskLockIcon) return;
+ if (this.task.type === 'habit' && !this.task[direction]) return;
if (this.isYesterdaily === true) {
await this.beforeTaskScore(this.task);
this.task.completed = !this.task.completed;
diff --git a/website/client/src/components/tasks/yesterdailyModal.vue b/website/client/src/components/tasks/yesterdailyModal.vue
index 0a24fbac8a..1c12e39fb8 100644
--- a/website/client/src/components/tasks/yesterdailyModal.vue
+++ b/website/client/src/components/tasks/yesterdailyModal.vue
@@ -84,6 +84,7 @@
import moment from 'moment';
import { mapState } from '@/libs/store';
import scoreTask from '@/mixins/scoreTask';
+import sync from '@/mixins/sync';
import Task from './task';
import LoadingSpinner from '../ui/loadingSpinner';
@@ -92,7 +93,7 @@ export default {
Task,
LoadingSpinner,
},
- mixins: [scoreTask],
+ mixins: [scoreTask, sync],
props: {
yesterDailies: {
type: Array,
@@ -180,6 +181,7 @@ export default {
this.isLoading = false;
this.$root.$emit('bv::hide::modal', 'yesterdaily');
+ if (this.$route.fullPath.indexOf('task-information') !== -1) this.sync();
},
},
};
diff --git a/website/client/src/store/getters/tasks.js b/website/client/src/store/getters/tasks.js
index 525ffbdb26..a194f385b1 100644
--- a/website/client/src/store/getters/tasks.js
+++ b/website/client/src/store/getters/tasks.js
@@ -114,15 +114,20 @@ export function canEdit (store) {
};
}
-function _nonInteractive (task) {
- return (task.group && task.group.id && !task.userId)
- || (task.challenge && task.challenge.id && !task.userId)
- || (task.group && task.group.approval && task.group.approval.requested
- && task.type !== 'habit');
+function _nonInteractive (task, userId) {
+ if (task.userId) return false;
+ if (task.challenge && task.challenge.id) return true;
+ if (
+ task.group
+ && task.group.assignedUsers.length > 0
+ && task.group.assignedUsers.indexOf(userId) === -1
+ ) return true;
+ return false;
}
export function getTaskClasses (store) {
const userPreferences = store.state.user.data.preferences;
+ const userId = store.state.user.data._id;
// Purpose can be one of the following strings:
// Edit Modal: edit-modal-bg, edit-modal-text, edit-modal-icon
@@ -171,7 +176,7 @@ export function getTaskClasses (store) {
if (type === 'todo' || type === 'daily') {
if (task.completed || (!shouldDo(dueDate, task, userPreferences) && type === 'daily')) {
return {
- bg: _nonInteractive(task) ? 'task-disabled-daily-todo-control-bg-noninteractive' : 'task-disabled-daily-todo-control-bg',
+ bg: _nonInteractive(task, userId) ? 'task-disabled-daily-todo-control-bg-noninteractive' : 'task-disabled-daily-todo-control-bg',
checkbox: 'task-disabled-daily-todo-control-checkbox',
inner: 'task-disabled-daily-todo-control-inner',
content: 'task-disabled-daily-todo-control-content',
@@ -179,28 +184,28 @@ export function getTaskClasses (store) {
}
return {
- bg: _nonInteractive(task) ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
+ bg: _nonInteractive(task, userId) ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
checkbox: `task-${color}-control-checkbox`,
inner: `task-${color}-control-inner-daily-todo`,
icon: `task-${color}-control-icon`,
};
} if (type === 'reward') {
return {
- bg: _nonInteractive(task) ? 'task-reward-control-bg-noninteractive' : 'task-reward-control-bg',
+ bg: _nonInteractive(task, userId) ? 'task-reward-control-bg-noninteractive' : 'task-reward-control-bg',
};
} if (type === 'habit') {
return {
up: task.up
? {
- bg: _nonInteractive(task) ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
- inner: _nonInteractive(task) ? `task-${color}-control-inner-habit-noninteractive` : `task-${color}-control-inner-habit`,
+ bg: _nonInteractive(task, userId) ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
+ inner: _nonInteractive(task, userId) ? `task-${color}-control-inner-habit-noninteractive` : `task-${color}-control-inner-habit`,
icon: `task-${color}-control-icon`,
}
: { bg: 'task-disabled-habit-control-bg', inner: 'task-disabled-habit-control-inner', icon: `task-${color}-control-icon` },
down: task.down
? {
- bg: _nonInteractive(task) ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
- inner: _nonInteractive(task) ? `task-${color}-control-inner-habit-noninteractive` : `task-${color}-control-inner-habit`,
+ bg: _nonInteractive(task, userId) ? `task-${color}-control-bg-noninteractive` : `task-${color}-control-bg`,
+ inner: _nonInteractive(task, userId) ? `task-${color}-control-inner-habit-noninteractive` : `task-${color}-control-inner-habit`,
icon: `task-${color}-control-icon`,
}
: { bg: 'task-disabled-habit-control-bg', inner: 'task-disabled-habit-control-inner', icon: `task-${color}-control-icon` },
diff --git a/website/common/script/ops/scoreTask.js b/website/common/script/ops/scoreTask.js
index 59645e4b71..708ce1d5f8 100644
--- a/website/common/script/ops/scoreTask.js
+++ b/website/common/script/ops/scoreTask.js
@@ -104,7 +104,7 @@ function _gainMP (user, val) {
// ===== CONSTITUTION =====
// TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point.
function _subtractPoints (user, task, stats, delta) {
- if (task.group.id && !task.userId) return stats.hp;
+ if (task.group.id && !task.userId && task.type === 'daily') return stats.hp;
let conBonus = 1 - statsComputed(user).con / 250;
if (conBonus < 0.1) conBonus = 0.1;
diff --git a/website/server/controllers/api-v3/tasks.js b/website/server/controllers/api-v3/tasks.js
index 5c20a9f4d7..d6aa1cb958 100644
--- a/website/server/controllers/api-v3/tasks.js
+++ b/website/server/controllers/api-v3/tasks.js
@@ -654,13 +654,6 @@ api.updateTask = {
// the other of the keys when using .toObject()
// see https://github.com/Automattic/mongoose/issues/2749
- task.group.approval.required = false;
- if (sanitizedObj.requiresApproval) {
- task.group.approval.required = true;
- }
- if (sanitizedObj.sharedCompletion) {
- task.group.sharedCompletion = sanitizedObj.sharedCompletion;
- }
if (sanitizedObj.managerNotes) {
task.group.managerNotes = sanitizedObj.managerNotes;
}
diff --git a/website/server/controllers/api-v3/tasks/groups.js b/website/server/controllers/api-v3/tasks/groups.js
index 98da938496..e78735e588 100644
--- a/website/server/controllers/api-v3/tasks/groups.js
+++ b/website/server/controllers/api-v3/tasks/groups.js
@@ -208,26 +208,13 @@ api.assignTask = {
const group = await Group.getGroup({ user, groupId: task.group.id, fields: groupFields });
if (!group) throw new NotFound(res.t('groupNotFound'));
- if (canNotEditTasks(group, user, assignedUserId)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks'));
+ if (canNotEditTasks(group, user)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks'));
const promises = [];
const taskText = task.text;
const userName = `@${user.auth.local.username}`;
- if (user._id === assignedUserId) {
- const managerIds = Object.keys(group.managers);
- managerIds.push(group.leader);
- const managers = await User.find({ _id: managerIds }, 'notifications preferences').exec();
- managers.forEach(manager => {
- if (manager._id === user._id) return;
- manager.addNotification('GROUP_TASK_CLAIMED', {
- message: res.t('taskClaimed', { userName, taskText }, manager.preferences.language),
- groupId: group._id,
- taskId: task._id,
- });
- promises.push(manager.save());
- });
- } else {
+ if (user._id !== assignedUserId) {
assignedUser.addNotification('GROUP_TASK_ASSIGNED', {
message: res.t('youHaveBeenAssignedTask', { managerName: userName, taskText }),
taskId: task._id,
@@ -283,7 +270,7 @@ api.unassignTask = {
const group = await Group.getGroup({ user, groupId: task.group.id, fields });
if (!group) throw new NotFound(res.t('groupNotFound'));
- if (canNotEditTasks(group, user, assignedUserId)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks'));
+ if (canNotEditTasks(group, user)) throw new NotAuthorized(res.t('onlyGroupLeaderCanEditTasks'));
await group.unlinkTask(task, assignedUser);
@@ -531,7 +518,7 @@ api.getGroupApprovals = {
if (canNotEditTasks(group, user)) {
approvals = await Tasks.Task.find({
'group.id': groupId,
- 'group.approval.approved': false,
+ 'group.approval.approved': { $ne: true },
'group.approval.requested': true,
'group.assignedUsers': user._id,
userId: user._id,
@@ -541,7 +528,7 @@ api.getGroupApprovals = {
} else {
approvals = await Tasks.Task.find({
'group.id': groupId,
- 'group.approval.approved': false,
+ 'group.approval.approved': { $ne: true },
'group.approval.requested': true,
}, 'userId group text')
.populate('userId', 'profile')
diff --git a/website/server/models/task.js b/website/server/models/task.js
index 604de20ca9..1b40940f4c 100644
--- a/website/server/models/task.js
+++ b/website/server/models/task.js
@@ -216,8 +216,6 @@ TaskSchema.statics.findMultipleByIdOrAlias = async function findByIdOrAlias (
if (!userId) throw new Error('User identifier is a required argument');
const query = _.cloneDeep(additionalQueries);
- query.userId = userId;
-
const ids = [];
const aliases = [];
@@ -229,10 +227,18 @@ TaskSchema.statics.findMultipleByIdOrAlias = async function findByIdOrAlias (
}
});
- query.$or = [
- { _id: { $in: ids } },
- { alias: { $in: aliases } },
- ];
+ if (ids.length > 0 && aliases.length > 0) {
+ query.$or = [
+ { _id: { $in: ids } },
+ { alias: { $in: aliases } },
+ ];
+ } else if (ids.length > 0) {
+ query._id = { $in: ids };
+ } else if (aliases.length > 0) {
+ query.alias = { $in: aliases };
+ } else {
+ throw new Error('No identifiers found.'); // Should be covered by the !identifiers check, but..
+ }
const tasks = await this.find(query).exec();