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 @@