From 26e1c1dc4a2a4971a3e2aef48cf1a5a34ff1e28f Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Sun, 24 Apr 2022 17:12:31 +0200 Subject: [PATCH 1/3] Attachment file rename is now possible - Relates to: #2099 --- client/components/cards/attachments.jade | 8 +++++++ client/components/cards/attachments.js | 25 +++++++++++++++++++++ imports/i18n/data/en.i18n.json | 3 ++- models/attachments.js | 9 +++++++- models/lib/fileStoreStrategy.js | 28 ++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 2 deletions(-) diff --git a/client/components/cards/attachments.jade b/client/components/cards/attachments.jade index 975d21e84..cce2419bb 100644 --- a/client/components/cards/attachments.jade +++ b/client/components/cards/attachments.jade @@ -69,6 +69,9 @@ template(name="attachmentActionsPopup") else | {{_ 'add-cover'}} if currentUser.isBoardAdmin + a.js-rename + i.fa.fa-pencil-square-o + | {{_ 'rename'}} a.js-confirm-delete i.fa.fa-close | {{_ 'delete'}} @@ -85,3 +88,8 @@ template(name="attachmentActionsPopup") a.js-move-storage-gridfs i.fa.fa-arrow-right | {{_ 'attachment-move-storage-gridfs'}} + +template(name="attachmentRenamePopup") + input.js-edit-attachment-name(type='text' autofocus value=name dir="auto") + .edit-controls.clearfix + button.primary.confirm.js-submit-edit-attachment-name(type="submit") {{_ 'save'}} diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index 8c78b363d..84424cbaa 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -134,6 +134,7 @@ BlazeComponent.extendComponent({ events() { return [ { + 'click .js-rename': Popup.open('attachmentRename'), 'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() { Attachments.remove(this._id); Popup.back(2); @@ -158,3 +159,27 @@ BlazeComponent.extendComponent({ ] } }).register('attachmentActionsPopup'); + +BlazeComponent.extendComponent({ + events() { + return [ + { + 'keydown input.js-edit-attachment-name'(evt) { + // enter = save + if (evt.keyCode === 13) { + this.find('button[type=submit]').click(); + } + }, + 'click button.js-submit-edit-attachment-name'(event) { + // save button pressed + event.preventDefault(); + const name = this.$('.js-edit-attachment-name')[0] + .value + .trim(); + Meteor.call('renameAttachment', this.data()._id, name); + Popup.back(); + }, + } + ] + } +}).register('attachmentRenamePopup'); diff --git a/imports/i18n/data/en.i18n.json b/imports/i18n/data/en.i18n.json index a4f2d204c..8e706103b 100644 --- a/imports/i18n/data/en.i18n.json +++ b/imports/i18n/data/en.i18n.json @@ -1177,5 +1177,6 @@ "size": "Size", "storage": "Storage", "action": "Action", - "board-title": "Board Title" + "board-title": "Board Title", + "attachmentRenamePopup-title": "Attachment Rename" } diff --git a/models/attachments.js b/models/attachments.js index 22e3c979f..73c5f58b1 100644 --- a/models/attachments.js +++ b/models/attachments.js @@ -4,7 +4,7 @@ import { createBucket } from './lib/grid/createBucket'; import fs from 'fs'; import path from 'path'; import { AttachmentStoreStrategyFilesystem, AttachmentStoreStrategyGridFs} from '/models/lib/attachmentStoreStrategy'; -import FileStoreStrategyFactory, {moveToStorage, STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS} from '/models/lib/fileStoreStrategy'; +import FileStoreStrategyFactory, {moveToStorage, rename, STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS} from '/models/lib/fileStoreStrategy'; let attachmentBucket; let storagePath; @@ -87,6 +87,13 @@ if (Meteor.isServer) { const fileObj = Attachments.findOne({_id: fileObjId}); moveToStorage(fileObj, storageDestination, fileStoreStrategyFactory); }, + renameAttachment(fileObjId, newName) { + check(fileObjId, String); + check(newName, String); + + const fileObj = Attachments.findOne({_id: fileObjId}); + rename(fileObj, newName, fileStoreStrategyFactory); + }, }); Meteor.startup(() => { diff --git a/models/lib/fileStoreStrategy.js b/models/lib/fileStoreStrategy.js index ebfbb4c9a..e6805e9b7 100644 --- a/models/lib/fileStoreStrategy.js +++ b/models/lib/fileStoreStrategy.js @@ -114,6 +114,13 @@ class FileStoreStrategy { unlink() { } + /** rename the file (physical) + * @li at database the filename is updated after this method + * @param newFilePath the new file path + */ + rename(newFilePath) { + } + /** return the storage name * @return the storage name */ @@ -287,6 +294,14 @@ export class FileStoreStrategyFilesystem extends FileStoreStrategy { fs.unlink(filePath, () => {}); } + /** rename the file (physical) + * @li at database the filename is updated after this method + * @param newFilePath the new file path + */ + rename(newFilePath) { + fs.renameSync(this.fileObj.versions[this.versionName].path, newFilePath); + } + /** return the storage name * @return the storage name */ @@ -389,3 +404,16 @@ export const copyFile = function(fileObj, newCardId, fileStoreStrategyFactory) { readStream.pipe(writeStream); }; + +export const rename = function(fileObj, newName, fileStoreStrategyFactory) { + Object.keys(fileObj.versions).forEach(versionName => { + const strategy = fileStoreStrategyFactory.getFileStrategy(fileObj, versionName); + const newFilePath = strategy.getNewPath(fileStoreStrategyFactory.storagePath, newName); + strategy.rename(newFilePath); + + Attachments.update({ _id: fileObj._id }, { $set: { + "name": newName, + [`versions.${versionName}.path`]: newFilePath, + } }); + }); +}; From 11f8b17a05fc72bcf42a05987166adff82038958 Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Tue, 26 Apr 2022 19:27:22 +0200 Subject: [PATCH 2/3] Attachment rename now without filename extension --- client/components/cards/attachments.jade | 2 +- client/components/cards/attachments.js | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/client/components/cards/attachments.jade b/client/components/cards/attachments.jade index cce2419bb..f915e8bb5 100644 --- a/client/components/cards/attachments.jade +++ b/client/components/cards/attachments.jade @@ -90,6 +90,6 @@ template(name="attachmentActionsPopup") | {{_ 'attachment-move-storage-gridfs'}} template(name="attachmentRenamePopup") - input.js-edit-attachment-name(type='text' autofocus value=name dir="auto") + input.js-edit-attachment-name(type='text' autofocus value="{{getNameWithoutExtension}}" dir="auto") .edit-controls.clearfix button.primary.confirm.js-submit-edit-attachment-name(type="submit") {{_ 'save'}} diff --git a/client/components/cards/attachments.js b/client/components/cards/attachments.js index 84424cbaa..2279ae932 100644 --- a/client/components/cards/attachments.js +++ b/client/components/cards/attachments.js @@ -161,6 +161,10 @@ BlazeComponent.extendComponent({ }).register('attachmentActionsPopup'); BlazeComponent.extendComponent({ + getNameWithoutExtension() { + const ret = this.data().name.replace(new RegExp("\." + this.data().extension + "$"), ""); + return ret; + }, events() { return [ { @@ -175,9 +179,9 @@ BlazeComponent.extendComponent({ event.preventDefault(); const name = this.$('.js-edit-attachment-name')[0] .value - .trim(); + .trim() + this.data().extensionWithDot; Meteor.call('renameAttachment', this.data()._id, name); - Popup.back(); + Popup.back(2); }, } ] From b6374dac3dbd61072a04d85061a420c480a407ed Mon Sep 17 00:00:00 2001 From: Martin Filser Date: Tue, 26 Apr 2022 19:30:27 +0200 Subject: [PATCH 3/3] Attachment selection, simpler code logic --- models/cards.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/models/cards.js b/models/cards.js index 0b926f4b6..73b0d48a1 100644 --- a/models/cards.js +++ b/models/cards.js @@ -739,17 +739,15 @@ Cards.helpers({ }, attachments() { + let id = this._id; if (this.isLinkedCard()) { - return Attachments.find( - { 'meta.cardId': this.linkedId }, - { sort: { uploadedAt: -1 } }, - ).each(); - } else { - return Attachments.find( - { 'meta.cardId': this._id }, - { sort: { uploadedAt: -1 } }, - ).each(); + id = this.linkedId; } + let ret = Attachments.find( + { 'meta.cardId': id }, + { sort: { uploadedAt: -1 } }, + ).each(); + return ret; }, cover() {