feat(tasks): make task copy/mirror pref per-group

This commit is contained in:
SabreCat
2022-08-02 16:09:49 -05:00
parent a418752041
commit 9b9503b141
6 changed files with 51 additions and 12 deletions

View File

@@ -39,7 +39,7 @@
id="taskMirrorToggle"
class="mr-3 mb-1 ml-auto"
:label="'Copy tasks'"
:checked="user.preferences.tasks.mirrorGroupTasks"
:checked="user.preferences.tasks.mirrorGroupTasks.indexOf(group._id) !== -1"
:hover-text="'Add assigned and open tasks to your personal task board'"
@change="changeMirrorPreference"
/>
@@ -431,12 +431,16 @@ export default {
eventCategory: 'behavior',
hitType: 'event',
mirror: newVal,
group: this.group._id,
}, { trackOnClient: true });
Analytics.updateUser({
mirrorTasks: newVal,
});
const groupsToMirror = this.user.preferences.tasks.mirrorGroupTasks || [];
if (newVal) { // we're turning copy ON for this group
groupsToMirror.push(this.group._id);
} else { // we're turning copy OFF for this group
groupsToMirror.splice(groupsToMirror.indexOf(this.group._id), 1);
}
this.$store.dispatch('user:set', {
'preferences.tasks.mirrorGroupTasks': newVal,
'preferences.tasks.mirrorGroupTasks': groupsToMirror,
});
},
},

View File

@@ -385,7 +385,7 @@ api.getUserTasks = {
url: '/tasks/user',
middlewares: [authWithHeaders({
// Some fields (including _id, preferences) are always loaded (see middlewares/auth)
userFieldsToInclude: ['guilds', 'party', 'tasksOrder'],
userFieldsToInclude: ['tasksOrder'],
})],
async handler (req, res) {
const types = Tasks.tasksTypes.map(type => `${type}s`);

View File

@@ -165,10 +165,11 @@ async function getTasks (req, res, options = {}) {
} else if (group) {
query = { 'group.id': group._id };
} else {
if (user.preferences.tasks.mirrorGroupTasks) {
const groupsToMirror = user.preferences.tasks.mirrorGroupTasks;
if (groupsToMirror && groupsToMirror.length > 0) {
upgradedGroups = await Group.find(
{
_id: { $in: user.guilds.concat(user.party._id) },
_id: { $in: groupsToMirror },
'purchased.plan.customerId': { $exists: true },
$or: [
{ 'purchased.plan.dateTerminated': { $exists: false } },

View File

@@ -1,6 +1,7 @@
import _ from 'lodash';
import common from '../../../common';
import * as Tasks from '../../models/task';
import { model as Groups } from '../../models/group';
import {
BadRequest,
NotAuthorized,
@@ -132,6 +133,34 @@ export async function update (req, res, { isV3 = false }) {
await checkNewInputForProfanity(user, res, newBlurb);
}
if (req.body['preferences.tasks.mirrorGroupTasks'] !== undefined) {
const groupsToMirror = req.body['preferences.tasks.mirrorGroupTasks'];
if (!Array.isArray(groupsToMirror)) {
throw new BadRequest('Groups to copy tasks from must be an array.');
}
const memberGroups = user.guilds;
if (user.party._id) memberGroups.push(user.party._id);
for (const targetGroup of groupsToMirror) {
if (memberGroups.indexOf(targetGroup) === -1) {
throw new BadRequest(`User not a member of group ${targetGroup}.`);
}
}
const matchingGroupsCount = await Groups.countDocuments({
_id: { $in: groupsToMirror },
'purchased.plan.customerId': { $exists: true },
$or: [
{ 'purchased.plan.dateTerminated': { $exists: false } },
{ 'purchased.plan.dateTerminated': null },
{ 'purchased.plan.dateTerminated': { $gt: new Date() } },
],
}).exec();
if (matchingGroupsCount !== groupsToMirror.length) {
throw new BadRequest('Groups to copy tasks from must have subscriptions.');
}
}
_.each(req.body, (val, key) => {
const purchasable = requiresPurchase[key];
@@ -140,7 +169,7 @@ export async function update (req, res, { isV3 = false }) {
}
if (key === 'tags') {
if (!Array.isArray(val)) throw new BadRequest('mustBeArray');
if (!Array.isArray(val)) throw new BadRequest('Tag list must be an array.');
const removedTagsIds = [];

View File

@@ -1386,10 +1386,13 @@ schema.methods.leave = async function leaveGroup (user, keep = 'keep-all', keepC
const promises = user.isModified() ? [user.save()] : [];
// remove the group from the user's groups
const userUpdate = { $pull: { 'preferences.tasks.mirrorGroupTasks': group._id } };
if (group.type === 'guild') {
promises.push(User.update({ _id: user._id }, { $pull: { guilds: group._id } }).exec());
userUpdate.$pull.guilds = group._id;
promises.push(User.update({ _id: user._id }, userUpdate).exec());
} else {
promises.push(User.update({ _id: user._id }, { $set: { party: {} } }).exec());
userUpdate.$set = { party: {} };
promises.push(User.update({ _id: user._id }, userUpdate).exec());
update.$unset = { [`quest.members.${user._id}`]: 1 };
}

View File

@@ -582,7 +582,9 @@ export default new Schema({
tasks: {
groupByChallenge: { $type: Boolean, default: false }, // @TODO remove? not used
confirmScoreNotes: { $type: Boolean, default: false }, // @TODO remove? not used
mirrorGroupTasks: { $type: Boolean, default: false },
mirrorGroupTasks: [
{ $type: String, validate: [v => validator.isUUID(v), 'Invalid group UUID.'], ref: 'Group' },
],
},
improvementCategories: {
$type: Array,