diff --git a/.eslintrc.js b/.eslintrc.js index 9ed9faf1f..12f8725da 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -75,7 +75,6 @@ module.exports = { glob: true, log: true, EditorWatchdog: true, - baseApiUrl: true, // \src\share\canvas_share.js React: true, appState: true, diff --git a/src/public/app/services/import.js b/src/public/app/services/import.js index 7e5fc43b6..08a44920f 100644 --- a/src/public/app/services/import.js +++ b/src/public/app/services/import.js @@ -25,7 +25,7 @@ export async function uploadFiles(parentNoteId, files, options) { } await $.ajax({ - url: `${baseApiUrl}notes/${parentNoteId}/import`, + url: `${window.glob.baseApiUrl}notes/${parentNoteId}/import`, headers: await server.getHeaders(), data: formData, dataType: 'json', diff --git a/src/public/app/services/server.js b/src/public/app/services/server.js index d23b1e90d..476c153bf 100644 --- a/src/public/app/services/server.js +++ b/src/public/app/services/server.js @@ -79,7 +79,7 @@ async function call(method, url, data, headers = {}) { requestId: requestId, headers: headers, method: method, - url: `/${baseApiUrl}${url}`, + url: `/${window.glob.baseApiUrl}${url}`, data: data }); }); @@ -128,7 +128,7 @@ async function reportError(method, url, statusCode, response) { function ajax(url, method, data, headers) { return new Promise((res, rej) => { const options = { - url: baseApiUrl + url, + url: window.glob.baseApiUrl + url, type: method, headers: headers, timeout: 60000, diff --git a/src/public/app/services/utils.js b/src/public/app/services/utils.js index 41a8f0023..f4eb4371f 100644 --- a/src/public/app/services/utils.js +++ b/src/public/app/services/utils.js @@ -182,15 +182,15 @@ function randomString(len) { } function isMobile() { - return window.device === "mobile" - // window.device is not available in setup - || (!window.device && /Mobi/.test(navigator.userAgent)); + return window.glob?.device === "mobile" + // window.glob.device is not available in setup + || (!window.glob?.device && /Mobi/.test(navigator.userAgent)); } function isDesktop() { - return window.device === "desktop" - // window.device is not available in setup - || (!window.device && !/Mobi/.test(navigator.userAgent)); + return window.glob?.device === "desktop" + // window.glob.device is not available in setup + || (!window.glob?.device && !/Mobi/.test(navigator.userAgent)); } // cookie code below works for simple use cases only - ASCII only diff --git a/src/public/app/widgets/buttons/attachments_actions.js b/src/public/app/widgets/buttons/attachments_actions.js index 745fb8d1d..1e8240e78 100644 --- a/src/public/app/widgets/buttons/attachments_actions.js +++ b/src/public/app/widgets/buttons/attachments_actions.js @@ -39,6 +39,8 @@ const TPL = ` Convert attachment into note Delete attachment + + `; export default class AttachmentActionsWidget extends BasicWidget { @@ -56,6 +58,31 @@ export default class AttachmentActionsWidget extends BasicWidget { this.$widget = $(TPL); this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle')); this.$widget.find("[data-trigger-command='copyAttachmentReferenceToClipboard']").toggle(this.attachment.role === 'image'); + + this.$uploadNewRevisionInput = this.$widget.find(".attachment-upload-new-revision-input"); + this.$uploadNewRevisionInput.on('change', async () => { + const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below + this.$uploadNewRevisionInput.val(''); + + const formData = new FormData(); + formData.append('upload', fileToUpload); + + const result = await $.ajax({ + url: `${window.glob.baseApiUrl}attachments/${this.attachmentId}/file`, + headers: await server.getHeaders(), + data: formData, + type: 'PUT', + timeout: 60 * 60 * 1000, + contentType: false, // NEEDED, DON'T REMOVE THIS + processData: false, // NEEDED, DON'T REMOVE THIS + }); + + if (result.uploaded) { + toastService.showMessage("New attachment revision has been uploaded."); + } else { + toastService.showError("Upload of a new attachment revision failed."); + } + }); } async openAttachmentCommand() { @@ -66,6 +93,10 @@ export default class AttachmentActionsWidget extends BasicWidget { await openService.downloadAttachment(this.attachmentId); } + async uploadNewAttachmentRevisionCommand() { + this.$uploadNewRevisionInput.trigger('click'); + } + async copyAttachmentReferenceToClipboardCommand() { this.parent.copyAttachmentReferenceToClipboard(); } diff --git a/src/public/app/widgets/ribbon_widgets/file_properties.js b/src/public/app/widgets/ribbon_widgets/file_properties.js index 454c73f1d..a7e4e06df 100644 --- a/src/public/app/widgets/ribbon_widgets/file_properties.js +++ b/src/public/app/widgets/ribbon_widgets/file_properties.js @@ -104,7 +104,7 @@ export default class FilePropertiesWidget extends NoteContextAwareWidget { formData.append('upload', fileToUpload); const result = await $.ajax({ - url: `${baseApiUrl}notes/${this.noteId}/file`, + url: `${window.glob.baseApiUrl}notes/${this.noteId}/file`, headers: await server.getHeaders(), data: formData, type: 'PUT', diff --git a/src/public/app/widgets/ribbon_widgets/image_properties.js b/src/public/app/widgets/ribbon_widgets/image_properties.js index 9032d0d39..22fd5f9a6 100644 --- a/src/public/app/widgets/ribbon_widgets/image_properties.js +++ b/src/public/app/widgets/ribbon_widgets/image_properties.js @@ -88,7 +88,7 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget { formData.append('upload', fileToUpload); const result = await $.ajax({ - url: `${baseApiUrl}images/${this.noteId}`, + url: `${window.glob.baseApiUrl}images/${this.noteId}`, headers: await server.getHeaders(), data: formData, type: 'PUT', diff --git a/src/routes/api/files.js b/src/routes/api/files.js index 90faba559..1046baeda 100644 --- a/src/routes/api/files.js +++ b/src/routes/api/files.js @@ -14,15 +14,12 @@ const NotFoundError = require("../../errors/not_found_error"); const ValidationError = require("../../errors/validation_error.js"); function updateFile(req) { - const {noteId} = req.params; - const file = req.file; - - const note = becca.getNote(noteId); - + const note = becca.getNote(req.params.noteId); if (!note) { - throw new NotFoundError(`Note '${noteId}' doesn't exist.`); + throw new NotFoundError(`Note '${req.params.noteId}' doesn't exist.`); } + const file = req.file; note.saveNoteRevision(); note.mime = file.mimetype.toLowerCase(); @@ -39,6 +36,23 @@ function updateFile(req) { }; } +function updateAttachment(req) { + const attachment = becca.getAttachment(req.params.attachmentId); + if (!attachment) { + throw new NotFoundError(`Attachment '${req.params.attachmentId}' doesn't exist.`); + } + + const file = req.file; + attachment.getNote().saveNoteRevision(); + + attachment.mime = file.mimetype.toLowerCase(); + attachment.setContent(file.buffer, {forceSave: true}); + + return { + uploaded: true + }; +} + /** * @param {BNote|BAttachment} noteOrAttachment * @param res @@ -234,6 +248,7 @@ function uploadModifiedFileToAttachment(req) { module.exports = { updateFile, + updateAttachment, openFile, fileContentProvider, downloadFile, diff --git a/src/routes/routes.js b/src/routes/routes.js index ff9ab57be..0ac273a00 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -164,6 +164,8 @@ function register(app) { route(GET, '/api/attachments/download/:attachmentId', [auth.checkApiAuthOrElectron], filesRoute.downloadAttachment); apiRoute(PST, '/api/attachments/:attachmentId/save-to-tmp-dir', filesRoute.saveAttachmentToTmpDir); apiRoute(PST, '/api/attachments/:attachmentId/upload-modified-file', filesRoute.uploadModifiedFileToAttachment); + route(PUT, '/api/attachments/:attachmentId/file', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], + filesRoute.updateAttachment, apiResultHandler); apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions); apiRoute(DEL, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions); diff --git a/src/views/desktop.ejs b/src/views/desktop.ejs index d4635c6c1..0f2ee750a 100644 --- a/src/views/desktop.ejs +++ b/src/views/desktop.ejs @@ -21,9 +21,9 @@