uploading new file revisions

This commit is contained in:
zadam 2019-11-09 11:58:52 +01:00
parent 7c7beb5502
commit 60ac1a04f4
11 changed files with 132 additions and 60 deletions

View File

@ -77,6 +77,19 @@ $list.on('change', async () => {
.attr("src", `data:${note.mime};base64,` + fullNoteRevision.content)
.css("width", "100%"));
}
else if (note.type === 'file') {
$content.html(
$("<table cellpadding='10'>")
.append($("<tr>").append(
$("<th>").text("MIME: "),
$("<td>").text(revisionItem.mime)
))
.append($("<tr>").append(
$("<th>").text("File size:"),
$("<td>").text(revisionItem.contentLength + " bytes")
))
);
}
else {
$content.text("Preview isn't available for this note type.");
}

View File

@ -1,5 +1,7 @@
import utils from "./utils.js";
import server from "./server.js";
import toastService from "./toast.js";
import noteDetailService from "./note_detail.js";
class NoteDetailFile {
/**
@ -16,10 +18,12 @@ class NoteDetailFile {
this.$previewContent = ctx.$tabContent.find(".file-preview-content");
this.$downloadButton = ctx.$tabContent.find(".file-download");
this.$openButton = ctx.$tabContent.find(".file-open");
this.$uploadNewRevisionButton = ctx.$tabContent.find(".file-upload-new-revision");
this.$uploadNewRevisionInput = ctx.$tabContent.find(".file-upload-new-revision-input");
this.$downloadButton.click(() => utils.download(this.getFileUrl()));
this.$downloadButton.on('click', () => utils.download(this.getFileUrl()));
this.$openButton.click(() => {
this.$openButton.on('click', () => {
if (utils.isElectron()) {
const open = require("open");
@ -29,6 +33,34 @@ class NoteDetailFile {
window.location.href = this.getFileUrl();
}
});
this.$uploadNewRevisionButton.on("click", () => {
this.$uploadNewRevisionInput.trigger("click");
});
this.$uploadNewRevisionInput.on('change', async () => {
const formData = new FormData();
formData.append('upload', this.$uploadNewRevisionInput[0].files[0]);
const result = await $.ajax({
url: baseApiUrl + 'notes/' + this.ctx.note.noteId + '/file',
headers: 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 file revision has been uploaded.");
await noteDetailService.reload();
}
else {
toastService.showError("Upload of a new file revision failed.");
}
});
}
async render() {

View File

@ -62,14 +62,14 @@ class NoteDetailImage {
});
if (result.uploaded) {
toastService.showMessage("New revision of the image has been uploaded.")
toastService.showMessage("New image revision has been uploaded.");
await utils.clearBrowserCache();
await noteDetailService.reload();
}
else {
toastService.showError("Could not upload new revision of the image: " + result.message);
toastService.showError("Upload of a new image revision failed: " + result.message);
}
});
}

View File

@ -4,30 +4,30 @@ const noteService = require('../../services/notes');
const protectedSessionService = require('../../services/protected_session');
const repository = require('../../services/repository');
const utils = require('../../services/utils');
const noteRevisionService = require('../../services/note_revisions');
async function uploadFile(req) {
const parentNoteId = req.params.parentNoteId;
async function updateFile(req) {
const {noteId} = req.params;
const file = req.file;
const originalName = file.originalname;
const size = file.size;
const mime = file.mimetype.toLowerCase();
const parentNote = await repository.getNote(parentNoteId);
const note = await repository.getNote(noteId);
if (!parentNote) {
return [404, `Note ${parentNoteId} doesn't exist.`];
if (!note) {
return [404, `Note ${noteId} doesn't exist.`];
}
const {note} = await noteService.createNote(parentNoteId, originalName, file.buffer, {
target: 'into',
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
type: mime.startsWith("image/") ? 'image' : 'file',
mime: file.mimetype,
attributes: [{ type: "label", name: "originalFileName", value: originalName }]
});
await noteRevisionService.createNoteRevision(note);
note.mime = file.mimetype.toLowerCase();
await note.setContent(file.buffer);
await note.setLabel('originalFileName', file.originalname);
await noteRevisionService.protectNoteRevisions(note);
return {
noteId: note.noteId
uploaded: true
};
}
@ -58,7 +58,7 @@ async function downloadFile(req, res) {
}
module.exports = {
uploadFile,
updateFile,
downloadFile,
downloadNoteFile
};

View File

@ -1,6 +1,6 @@
const repository = require('../services/repository');
const log = require('../services/log');
const fileUploadService = require('./api/file_upload');
const fileUploadService = require('./api/files.js');
const scriptService = require('../services/script');
function register(router) {

View File

@ -28,7 +28,7 @@ const imageRoute = require('./api/image');
const attributesRoute = require('./api/attributes');
const scriptRoute = require('./api/script');
const senderRoute = require('./api/sender');
const filesRoute = require('./api/file_upload');
const filesRoute = require('./api/files');
const searchRoute = require('./api/search');
const dateNotesRoute = require('./api/date_notes');
const linkMapRoute = require('./api/link_map');
@ -146,8 +146,8 @@ function register(app) {
route(GET, '/api/notes/:branchId/export/:type/:format/:version/:taskId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch);
route(POST, '/api/notes/:parentNoteId/import', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], importRoute.importToBranch, apiResultHandler);
route(POST, '/api/notes/:parentNoteId/upload', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware],
filesRoute.uploadFile, apiResultHandler);
route(PUT, '/api/notes/:noteId/file', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware],
filesRoute.updateFile, apiResultHandler);
route(GET, '/api/notes/:noteId/download', [auth.checkApiAuthOrElectron], filesRoute.downloadFile);
// this "hacky" path is used for easier referencing of CSS resources

View File

@ -13,6 +13,7 @@ const jimp = require('jimp');
const imageType = require('image-type');
const sanitizeFilename = require('sanitize-filename');
const dateUtils = require('./date_utils');
const noteRevisionService = require('./note_revisions.js');
const NoteRevision = require("../entities/note_revision");
async function processImage(uploadBuffer, originalName, shrinkImageSwitch) {
@ -38,22 +39,7 @@ async function updateImage(noteId, uploadBuffer, originalName) {
const note = await repository.getNote(noteId);
const noteRevision = await new NoteRevision({
noteId: note.noteId,
// title and text should be decrypted now
title: note.title,
contentLength: -1, // will be updated in .setContent()
type: note.type,
mime: note.mime,
isProtected: false, // will be fixed in the protectNoteRevisions() call
utcDateLastEdited: note.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: note.dateModified,
dateCreated: dateUtils.localNowDateTime()
}).save();
await noteRevision.setContent(await note.getContent());
await noteRevisionService.createNoteRevision(note);
note.mime = 'image/' + imageFormat.ext.toLowerCase();
@ -61,7 +47,7 @@ async function updateImage(noteId, uploadBuffer, originalName) {
await note.setLabel('originalFileName', originalName);
await noteService.protectNoteRevisions(note);
await noteRevisionService.protectNoteRevisions(note);
}
async function saveImage(parentNoteId, uploadBuffer, originalName, shrinkImageSwitch) {

View File

@ -0,0 +1,47 @@
"use strict";
const NoteRevision = require('../entities/note_revision');
const dateUtils = require('../services/date_utils');
/**
* @param {Note} note
*/
async function protectNoteRevisions(note) {
for (const revision of await note.getRevisions()) {
if (note.isProtected !== revision.isProtected) {
revision.isProtected = note.isProtected;
await revision.save();
}
}
}
/**
* @param {Note} note
* @return {NoteRevision}
*/
async function createNoteRevision(note) {
const noteRevision = await new NoteRevision({
noteId: note.noteId,
// title and text should be decrypted now
title: note.title,
contentLength: -1, // will be updated in .setContent()
type: note.type,
mime: note.mime,
isProtected: false, // will be fixed in the protectNoteRevisions() call
utcDateLastEdited: note.utcDateModified,
utcDateCreated: dateUtils.utcNowDateTime(),
utcDateModified: dateUtils.utcNowDateTime(),
dateLastEdited: note.dateModified,
dateCreated: dateUtils.localNowDateTime()
}).save();
await noteRevision.setContent(await note.getContent());
return noteRevision;
}
module.exports = {
protectNoteRevisions,
createNoteRevision
};

View File

@ -14,6 +14,7 @@ const Attribute = require('../entities/attribute');
const hoistedNoteService = require('../services/hoisted_note');
const protectedSessionService = require('../services/protected_session');
const log = require('../services/log');
const noteRevisionService = require('../services/note_revisions');
async function getNewNotePosition(parentNoteId, noteData) {
let newNotePos = 0;
@ -199,17 +200,7 @@ async function protectNote(note, protect) {
await note.save();
}
await protectNoteRevisions(note);
}
async function protectNoteRevisions(note) {
for (const revision of await note.getRevisions()) {
if (note.isProtected !== revision.isProtected) {
revision.isProtected = note.isProtected;
await revision.save();
}
}
await noteRevisionService.protectNoteRevisions(note);
}
function findImageLinks(content, foundLinks) {
@ -383,7 +374,7 @@ async function updateNote(noteId, noteUpdates) {
await triggerNoteTitleChanged(note);
}
await protectNoteRevisions(note);
await noteRevisionService.protectNoteRevisions(note);
return {
dateModified: note.dateModified,
@ -538,6 +529,5 @@ module.exports = {
deleteBranch,
protectNoteRecursively,
scanForLinks,
duplicateNote,
protectNoteRevisions
duplicateNote
};

View File

@ -24,10 +24,14 @@
</tr>
<tr>
<td colspan="2">
<button class="file-download btn btn-primary" type="button">Download</button>
<button class="file-download btn btn-sm btn-primary" type="button">Download</button>
&nbsp;
<button class="file-open btn btn-primary" type="button">Open</button>
<button class="file-open btn btn-sm btn-primary" type="button">Open</button>
&nbsp;
<button class="file-upload-new-revision btn btn-sm btn-primary">Upload new revision</button>
</td>
</tr>
</table>
<input type="file" class="file-upload-new-revision-input" style="display: none">
</div>

View File

@ -27,6 +27,6 @@
<span class="image-filesize"></span>
</span>
</div>
</div>
<input type="file" class="image-upload-new-revision-input" style="display: none">
<input type="file" class="image-upload-new-revision-input" style="display: none">
</div>