mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	attachment revision upload
This commit is contained in:
		@@ -75,7 +75,6 @@ module.exports = {
 | 
			
		||||
        glob: true,
 | 
			
		||||
        log: true,
 | 
			
		||||
        EditorWatchdog: true,
 | 
			
		||||
        baseApiUrl: true,
 | 
			
		||||
        // \src\share\canvas_share.js
 | 
			
		||||
        React: true,
 | 
			
		||||
        appState: true,
 | 
			
		||||
 
 | 
			
		||||
@@ -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',
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,8 @@ const TPL = `
 | 
			
		||||
        <a data-trigger-command="convertAttachmentIntoNote" class="dropdown-item">Convert attachment into note</a>
 | 
			
		||||
        <a data-trigger-command="deleteAttachment" class="dropdown-item">Delete attachment</a>
 | 
			
		||||
    </div>
 | 
			
		||||
    
 | 
			
		||||
    <input type="file" class="attachment-upload-new-revision-input" style="display: none">
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
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();
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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',
 | 
			
		||||
 
 | 
			
		||||
@@ -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',
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -21,9 +21,9 @@
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */
 | 
			
		||||
 | 
			
		||||
    window.baseApiUrl = 'api/';
 | 
			
		||||
    window.device = "desktop";
 | 
			
		||||
    window.glob = {
 | 
			
		||||
        device: "desktop",
 | 
			
		||||
        baseApiUrl: 'api/',
 | 
			
		||||
        activeDialog: null,
 | 
			
		||||
        maxEntityChangeIdAtLoad: <%= maxEntityChangeIdAtLoad %>,
 | 
			
		||||
        maxEntityChangeSyncIdAtLoad: <%= maxEntityChangeSyncIdAtLoad %>,
 | 
			
		||||
 
 | 
			
		||||
@@ -105,9 +105,9 @@
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
    global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */
 | 
			
		||||
 | 
			
		||||
    window.baseApiUrl = 'api/';
 | 
			
		||||
    window.device = "mobile";
 | 
			
		||||
    window.glob = {
 | 
			
		||||
        device: "mobile",
 | 
			
		||||
        baseApiUrl: 'api/',
 | 
			
		||||
        activeDialog: null,
 | 
			
		||||
        maxEntityChangeIdAtLoad: <%= maxEntityChangeIdAtLoad %>,
 | 
			
		||||
        maxEntityChangeSyncIdAtLoad: <%= maxEntityChangeSyncIdAtLoad %>,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user