withlogicco / django-prose

Wonderful rich-text editing for your Django project
https://stateofprogress.blog/2023/02/01/django-prose-wonderful-rich-text-content-editing-for-django
MIT License
202 stars 13 forks source link

htmx + prose + fileupload #49

Closed onno-timmerman closed 1 year ago

onno-timmerman commented 1 year ago

Hmmm, seems if you load django-prose with a HTMX call you don't get the upload functionality. Replace your editor.js script en load it before The do a htmx:afterOnload to reinitialize the upload script

// This code goes in /static/prose/editor.js
function uploadAttachment(host, attachment) {
    uploadFile(host, attachment.file, setProgress, setAttributes);

    function setProgress(progress) {
        attachment.setUploadProgress(progress);
    }

    function setAttributes(attributes) {
        attachment.setAttributes(attributes);
    }
}

function uploadFile(host, file, progressCallback, successCallback) {
    var key = createStorageKey(file);
    var formData = createFormData(key, file);
    var xhr = new XMLHttpRequest();

    const csrfToken = document.querySelector("input[name=csrfmiddlewaretoken]").value;

    formData.append('csrfmiddlewaretoken', csrfToken);

    xhr.open("POST", host, true);

    xhr.upload.addEventListener("progress", function(event) {
        var progress = event.loaded / event.total * 100;
        progressCallback(progress);
    });

    xhr.addEventListener("load", function(event) {
        if (xhr.status == 201) {
            const data = JSON.parse(xhr.response);

            var attributes = {
                url: data.url,
                href: `${data.url}?content-disposition=attachment`
            };
            successCallback(attributes);
        }
    });

    xhr.send(formData);
}

function createStorageKey(file) {
    var date = new Date();
    var day = date.toISOString().slice(0,10);
    var name = date.getTime() + "-" + file.name;
    return [day, name].join("/");
}

function createFormData(key, file) {
    var data = new FormData();
    data.append("key", key);
    data.append("file", file);
    data.append("Content-Type", file.type);
    return data;
}

function initializeEditors() {
    const editors = document.querySelectorAll('.django-prose-editor:not(.initialized)');

    editors.forEach(editor => {
        editor.addEventListener("trix-attachment-add", function(event) {
            uploadAttachment(editor.dataset.uploadAttachmentUrl, event.attachment);
        });
        editor.classList.add('initialized');
    });
}

// When the DOM is initially loaded
document.addEventListener("DOMContentLoaded", initializeEditors);

// Export the initializeEditors function so it can be called from other scripts
window.initializeEditors = initializeEditors;`

then the other part

document.body.addEventListener('htmx:afterOnLoad', function() {
    // Call the function exported from /static/prose/editor.js
    window.initializeEditors();
});
parisk commented 1 year ago

This should be OK now after https://github.com/withlogicco/django-prose/pull/50.