Files
DiceCloud/app/imports/api/parenting/organizeMethods.js
2024-04-12 17:05:20 +02:00

123 lines
3.5 KiB
JavaScript

import SimpleSchema from 'simpl-schema';
import { ValidatedMethod } from 'meteor/mdg:validated-method';
import { RateLimiterMixin } from 'ddp-rate-limiter-mixin';
import { RefSchema } from '/imports/api/parenting/ChildSchema';
import { assertDocEditPermission, assertEditPermission } from '/imports/api/sharing/sharingPermissions.js';
import { compact } from 'lodash';
import Creatures from '/imports/api/creature/creatures/Creatures';
import { fetchDocByRefAsync, getCollectionByName, moveDocBetweenRoots, moveDocWithinRoot } from '/imports/api/parenting/parentingFunctions';
const moveBetweenRoots = new ValidatedMethod({
name: 'organize.moveDocBetweenRoots',
validate: new SimpleSchema({
docRef: RefSchema,
newPosition: {
type: Number, // Must end in .5
},
newRootRef: RefSchema,
skipRecompute: {
type: Boolean,
optional: true,
},
skipClient: {
type: Boolean,
optional: true,
},
}).validator(),
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 5,
timeInterval: 5000,
},
async run({ docRef, newPosition, newRootRef, skipRecompute, skipClient }) {
if (skipClient && this.isSimulation) {
return;
}
let doc = await fetchDocByRefAsync(docRef);
let collection = getCollectionByName(docRef.collection);
// The user must be able to edit both the doc and its parent to move it
// successfully
assertDocEditPermission(doc, this.userId);
const newRoot = await fetchDocByRefAsync(newRootRef);
assertEditPermission(newRoot, this.userId);
// Move the doc
await moveDocBetweenRoots(doc, collection, newRootRef, newPosition);
// Figure out which creatures need to be recalculated after this move
const creatureIdsToRecalculate = compact([
getCreatureAncestorId(doc),
getCreatureAncestorId(newRoot),
]);
// Mark the creatures for recompute
if (!skipRecompute && creatureIdsToRecalculate.length) {
Creatures.updateAsync({
_id: { $in: creatureIdsToRecalculate },
}, {
$set: { dirty: true },
});
}
},
});
const moveWithinRoot = new ValidatedMethod({
name: 'organize.moveDocWithinRoot',
validate: new SimpleSchema({
docRef: RefSchema,
newPosition: {
type: Number, // Must end in .5
},
skipRecompute: {
type: Boolean,
optional: true,
},
skipClient: {
type: Boolean,
optional: true,
},
}).validator(),
mixins: [RateLimiterMixin],
rateLimit: {
numRequests: 5,
timeInterval: 5000,
},
async run({ docRef, newPosition, skipRecompute, skipClient }) {
if (skipClient && this.isSimulation) {
return;
}
let doc = await fetchDocByRefAsync(docRef);
let collection = getCollectionByName(docRef.collection);
// The user must be able to edit the doc
assertDocEditPermission(doc, this.userId);
// Move the doc
await moveDocWithinRoot(doc, collection, newPosition);
// Figure out which creature needs to be recalculated after this move
const creatureIdToRecalculate = getCreatureAncestorId(doc);
// Mark the creatures for recompute
if (!skipRecompute && creatureIdToRecalculate) {
Creatures.updateAsync({
_id: creatureIdToRecalculate,
}, {
$set: { dirty: true },
});
}
},
});
function getCreatureAncestorId(doc) {
if (doc.type === 'pc' || doc.type === 'npc' || doc.type === 'monster') {
return doc._id;
}
if (doc?.root?.collection === 'creatures') {
return doc.root.id;
}
}
export { moveBetweenRoots, moveWithinRoot };