VanOns / laraberg

A Gutenberg implementation for Laravel
GNU General Public License v3.0
1.33k stars 144 forks source link

v2 - mediaUpload #158

Closed Stuart92 closed 2 years ago

Stuart92 commented 2 years ago

Hi Maurice,

Thanks so much for releasing V2 - really appreciate your work on it! It seems to be a big step forward in terms of being cleanly integrated.

I was using Laravel File Manager with V1, and I see you have noted "This can be solved by implementing your own mediaUpload function and passing it as an editor setting." - would you be able to provide a bit more documentation there? Any suggestions on what media library / file manager to integrate with?

Thanks, Stuart

Stuart92 commented 2 years ago

So sorry - I just saw the example directory and see what you mean. Sorry to bother you.

For those interested, there is a basic sample here: https://github.com/VanOns/laraberg/blob/main/example/resources/js/app.js The upload of the image would need to be handled appropriately in the sample mediaupload function.

Stuart92 commented 2 years ago

On second thought - can you please clarify whether passing the file object to an ajax function is sufficient data to save the uploaded image in an application?

mauricewijnia commented 2 years ago

Hi!

That depends on the Ajax function you're using. Laraberg itself does not do anything for handling file uploads, our laraberg-nova package has an implementation that's suitable for the most common situations: https://github.com/VanOns/laraberg-nova/blob/main/resources/js/media-upload.js

Hope that helps!

Stuart92 commented 2 years ago

Hi Maurice - Thank you for the quick reply. This looks very helpful - I will give it a try. Cheers.

Stuart92 commented 2 years ago

For those that are interested, here's how I went about this. Note that my JS is quite poor, so there may be a better way to go about this:

Initializing Laraberg:

import uuidv4 from './uuidv4';
import mediaUpload from './media-upload';
const settings = {}
settings.mediaUpload = mediaUpload(
    uuidv4(),
    (e) => {
        console.log(e);
    }
);
Laraberg.init('#laraberg-content', settings);

uuidv4.js comes from https://github.com/VanOns/laraberg-nova/blob/main/resources/js/uuidv4.js

In media-upload.js

import uuidv4 from './uuidv4';

const mediaUpload = (draftId, onError = () => {}) => {
    const endpoint = '/upload-attachment';
    return async({filesList, onFileChange}) => {
        const promises = Array.from(filesList).map(async (file) => {
            const data = new FormData();
            data.append('Content-Type', file.type);
            data.append('attachment', file);
            try {
                var ajaxData;
                $.ajaxSetup({
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    }
                });
                $.ajax({
                    url: endpoint,
                    async: false,
                    data: data,
                    processData: false,
                    contentType: false,
                    type: 'POST',
                    success: function(data){
                        if(data.uploaded == true) {
                            ajaxCallBack(data);
                        }
                    },
                    error: function(err){
                        console.log(err);
                    }
                });
                function ajaxCallBack(data){
                    ajaxData = data;
                }
                return {
                    id: uuidv4(),
                    name: ajaxData.fileName,
                    url: ajaxData.url
                }
            }
            catch (e) {
                onError(e)
            }
        });
        const uploadedFiles = await Promise.all(promises);
        onFileChange(uploadedFiles);
    }
};

export default mediaUpload;

You'll need to define a POST route for /upload-attachment, and handle the file upload in a controller method. The controller method should return the filename, path to file, and uploaded boolean (success/fail).

Stuart92 commented 2 years ago

And, to Maurice - thank you again for your help. I noticed that the "Image" and "Gallery" blocks work nicely, but the "Cover" (adding a background image) and "Media & Content" blocks do nothing when uploading an image. I'll keep the issue open in case you'd like to address that here (though, I appreciate that you're possibly very busy and won't be able to address the issue). Thanks!

dennisnienhuis commented 2 years ago

A tip if you still want to use the Laravel File Manager package in v2 like v1:

Use the old code from v1.0: https://github.com/VanOns/laraberg/blob/v1.x/src/resources/js/laravel-filemanager/index.js

Load the required assets like the documentation has stated.

Register the component LaravelFilemanager like v1:

Laraberg.wordpress.hooks.addFilter( 'editor.MediaUpload', 'core/edit-post/components/media-upload/replace-media-upload', () => LaravelFilemanager )


Disable the old media button like v1: 
- https://github.com/VanOns/laraberg/blob/v1.x/src/resources/js/lib/element-ready.js
- https://github.com/VanOns/laraberg/blob/v1.x/src/resources/js/lib/configure-editor.js

elementRendered('.components-form-file-upload button', element => element.remove())

function elementRendered (selector, callback) { const renderedElements = [] const observer = new MutationObserver((mutations) => { const elements = document.querySelectorAll(selector) elements.forEach(element => { if (!renderedElements.includes(element)) { renderedElements.push(element) callback(element) } }) }) observer.observe(document.documentElement, { childList: true, subtree: true }) return observer }


Load Laraberg with a empty mediupload:

const mediaUpload = ({filesList, onFileChange}) => {} Laraberg.init('content-gutenberg', { mediaUpload });

Stuart92 commented 2 years ago

@dennisnienhuis - Thank you so very much for this - I would not have figured that out in a million years! Your code was plug-and-play.

The only oddity is that depending on the block type, a different LFM folder is opened for me. I.e. adding an image to a "Cover" or "Media & Text" block opens the folder I'd expect to see for the user, and "Image" and "Gallery" open a different folder. I can't quite figure out the reason for that.

dennisnienhuis commented 2 years ago

@Stuart92 Glad that it worked! Thats because a filter is used on the openModal function:

let type = 'file'
if (this.props.allowedTypes.length === 1 && this.props.allowedTypes[0] === 'image') {
    type = 'image'
}

See URL for example for the gallery block: image

and for "Media & Text": image

To show all file types use: window.open(routePrefix, 'FileManager', 'width=900,height=600')

This will prevent opening different types, like stated on the github page of laravel filemanager. "Supports two categories: files and images. Each type works in different directory."

I don't know the impact of this if an user is uploading for example documents and non image files.

Stuart92 commented 2 years ago

Ah, I see - thank you for clarifying. I have opted to always open the "file" directory, and it seems like most block elements appropriately throw an error when the wrong file type is selected. Thanks again, @mauricewijnia and @dennisnienhuis