import SimpleSchema from 'simpl-schema'; import { ValidatedMethod } from 'meteor/mdg:validated-method'; import { RateLimiterMixin } from 'ddp-rate-limiter-mixin'; import CreatureProperties from '/imports/api/creature/creatureProperties/CreatureProperties'; import { assertEditPermission } from '/imports/api/sharing/sharingPermissions'; import getRootCreatureAncestor from '/imports/api/creature/creatureProperties/getRootCreatureAncestor'; import { getFilter, renewDocIds } from '/imports/api/parenting/parentingFunctions'; import { rebuildNestedSets } from '/imports/api/parenting/parentingFunctions'; var snackbar; if (Meteor.isClient) { snackbar = require( '/imports/client/ui/components/snackbars/SnackbarQueue' ).snackbar } const DUPLICATE_CHILDREN_LIMIT = 50; const duplicateProperty = new ValidatedMethod({ name: 'creatureProperties.duplicate', validate: new SimpleSchema({ _id: { type: String, regEx: SimpleSchema.RegEx.Id, } }).validator(), mixins: [RateLimiterMixin], rateLimit: { numRequests: 5, timeInterval: 5000, }, run({ _id }) { let property = CreatureProperties.findOne(_id); if (!property) throw new Meteor.Error('not-found', 'The source property was not found'); let creature = getRootCreatureAncestor(property); assertEditPermission(creature, this.userId); // Renew the doc ID let randomSrc = DDP.randomStream('duplicateProperty'); let propertyId = randomSrc.id(); property._id = propertyId; // Change the variableName so it isn't immediately overridden if (property.variableName) { property.variableName += 'Copy' } // Get all the descendants let nodes = CreatureProperties.find({ ...getFilter.descendants(property), removed: { $ne: true }, }, { limit: DUPLICATE_CHILDREN_LIMIT + 1, sort: { left: 1 }, }).fetch(); // Alert the user if the limit was hit if (nodes.length > DUPLICATE_CHILDREN_LIMIT) { nodes.pop(); if (Meteor.isClient) { snackbar({ text: `Only the first ${DUPLICATE_CHILDREN_LIMIT} children were duplicated`, }); } } // Give the docs new IDs without breaking internal references const allNodes = [property, ...nodes]; renewDocIds({ docArray: allNodes }); // Order the root node property.left = Number.MAX_SAFE_INTEGER - 1; property.right = Number.MAX_SAFE_INTEGER; // Mark the sheet as needing recompute property.dirty = true; // Insert the properties CreatureProperties.batchInsert(allNodes); // Tree structure changed by inserts, reorder the tree rebuildNestedSets(CreatureProperties, property.root.id); return propertyId; }, }); export default duplicateProperty;