From 608ab4e58883cc559ff3233b11d233ba310e3ac6 Mon Sep 17 00:00:00 2001 From: Stefan Zermatten Date: Fri, 27 Aug 2021 13:00:01 +0200 Subject: [PATCH] Added undo delete and recycle bin to library --- app/imports/api/library/LibraryNodes.js | 21 ++++++++ .../server/cron/deleteSoftRemovedDocuments.js | 6 +-- app/imports/server/publications/library.js | 22 +++++++++ app/imports/ui/library/LibraryEditDialog.vue | 49 +++++++++++++++++++ app/imports/ui/library/LibraryNodeDialog.vue | 13 ++++- 5 files changed, 107 insertions(+), 4 deletions(-) diff --git a/app/imports/api/library/LibraryNodes.js b/app/imports/api/library/LibraryNodes.js index 4f9bb401..8b8ec90c 100644 --- a/app/imports/api/library/LibraryNodes.js +++ b/app/imports/api/library/LibraryNodes.js @@ -14,6 +14,7 @@ import { storedIconsSchema } from '/imports/api/icons/Icons.js'; import '/imports/api/library/methods/index.js'; import { updateReferenceNodeWork } from '/imports/api/library/methods/updateReferenceNode.js'; import STORAGE_LIMITS from '/imports/constants/STORAGE_LIMITS.js'; +import { restore } from '/imports/api/parenting/softRemove.js'; let LibraryNodes = new Mongo.Collection('libraryNodes'); @@ -186,6 +187,25 @@ const softRemoveLibraryNode = new ValidatedMethod({ } }); +const restoreLibraryNode = new ValidatedMethod({ + name: 'libraryNodes.restore', + validate: new SimpleSchema({ + _id: SimpleSchema.RegEx.Id + }).validator(), + mixins: [RateLimiterMixin], + rateLimit: { + numRequests: 5, + timeInterval: 5000, + }, + run({_id}){ + // Permissions + let node = LibraryNodes.findOne(_id); + assertNodeEditPermission(node, this.userId); + // Do work + restore({_id, collection: LibraryNodes}); + } +}); + export default LibraryNodes; export { LibraryNodeSchema, @@ -194,4 +214,5 @@ export { pullFromLibraryNode, pushToLibraryNode, softRemoveLibraryNode, + restoreLibraryNode, }; diff --git a/app/imports/server/cron/deleteSoftRemovedDocuments.js b/app/imports/server/cron/deleteSoftRemovedDocuments.js index 779fbed4..3758aa27 100644 --- a/app/imports/server/cron/deleteSoftRemovedDocuments.js +++ b/app/imports/server/cron/deleteSoftRemovedDocuments.js @@ -10,17 +10,17 @@ Meteor.startup(() => { ]; /** - * Deletes all soft removed documents that were removed more than 30 minutes ago + * Deletes all soft removed documents that were removed more than 1 day ago * and were not restored * @return {Number} Number of documents removed */ const deleteOldSoftRemovedDocs = function(){ const now = new Date(); - const thirtyMinutesAgo = new Date(now.getTime() - 30*60000); + const yesterday = new Date(now.getTime() - (24 * 60 * 60 * 1000)); collections.forEach(collection => { collection.remove({ removed: true, - removedAt: {$lt: thirtyMinutesAgo} // dates *before* 30 minutes ago + removedAt: {$lt: yesterday} // dates *before* yesterday }, function(error){ if (error){ console.error(JSON.stringify(error, null, 2)); diff --git a/app/imports/server/publications/library.js b/app/imports/server/publications/library.js index 4f94b72b..41e2b080 100644 --- a/app/imports/server/publications/library.js +++ b/app/imports/server/publications/library.js @@ -69,6 +69,28 @@ Meteor.publish('libraryNodes', function(libraryId){ }); }); +Meteor.publish('softRemovedLibraryNodes', function(libraryId){ + if (!libraryId) return []; + libraryIdSchema.validate({libraryId}); + this.autorun(function (){ + let userId = this.userId; + let library = Libraries.findOne(libraryId); + try { assertViewPermission(library, userId) } + catch(e){ + return this.error(e); + } + return [ + LibraryNodes.find({ + 'ancestors.0.id': libraryId, + removed: true, + removedWith: {$exists: false}, + }, { + sort: {order: 1}, + }), + ]; + }); +}); + Meteor.publish('descendantLibraryNodes', function(nodeId){ let node = LibraryNodes.findOne(nodeId); let libraryId = node?.ancestors[0]?.id; diff --git a/app/imports/ui/library/LibraryEditDialog.vue b/app/imports/ui/library/LibraryEditDialog.vue index 1c65dba3..145799da 100644 --- a/app/imports/ui/library/LibraryEditDialog.vue +++ b/app/imports/ui/library/LibraryEditDialog.vue @@ -27,6 +27,35 @@ @change="updateName" /> + +