eduardoarandah / medialibrary-dropzone-for-laravel-backpack

Adds the dropzone component to add multiple images via medialibrary backend
6 stars 2 forks source link

[Suggestion] Use Backpack operation instead of telling users to create a controller #7

Open tabacitu opened 3 years ago

tabacitu commented 3 years ago

I think we can make the package easier to use by taking advantage of custom Backpack Operations.

Basically, instead of having them create a new controller and 4 routes for each entity they want to have media, we could create an operation, say InteractWithMediaOperation, which they use on their ProductCrudController, just like they do for the ListOperation, CreateOperation, ReorderOperation, etc.

That operation could host both the routes and actions for the field. So something like this:

<?php

namespace EduardoArandaH\MediaLibraryDropzone;

use Illuminate\Support\Facades\Route;

trait InteractWithMediaOperation
{
    /**
     * Define which routes are needed for this operation.
     *
     * @param string $segment    Name of the current entity (singular). Used as first URL segment.
     * @param string $routeName  Prefix of the route name.
     * @param string $controller Name of the current CrudController.
     */
    protected function setupInteractWithMediaRoutes($segment, $routeName, $controller)
    {
        Route::get($segment.'/{id}/media', [
            'as'        => $routeName.'.listMedia',
            'uses'      => $controller.'@listMedia',
            'operation' => 'interactWithMedia',
        ]);
        Route::post($segment.'/{id}/media', [
            'as'        => $routeName.'.storeMedia',
            'uses'      => $controller.'@storeMedia',
            'operation' => 'interactWithMedia',
        ]);
        Route::delete($segment.'/{id}/media', [
            'as'        => $routeName.'.destroyMedia',
            'uses'      => $controller.'@destroyMedia',
            'operation' => 'interactWithMedia',
        ]);
        Route::post($segment.'/{id}/media/sort', [
            'as'        => $routeName.'.sortMedia',
            'uses'      => $controller.'@sortMedia',
            'operation' => 'interactWithMedia',
        ]);
    }

  public function listMedia(Product $model)
  {
    $media = $model->getMedia();
    $pictures = [];
    foreach ($media as $item) {
      $pictures[] = [
        'id' => $item->id,
        'url' => $item->getUrl(),
        'order' => $item->order_column ?? 0,
      ];
    }

    return $pictures;
  }

  public function storeMedia(Request $request, Product $model)
  {
    $media = $model->addMedia($request->file('file'))->toMediaCollection();
    return $media->getUrl();
  }

  public function destroyMedia(Product $model, Media $picture)
  {
    $picture->delete();
  }

  public function sortMedia(Request $request)
  {
    $pictures = $request->input('pictures');
    foreach ($pictures as $picture) {
      $media = Media::findOrFail($picture['id']);
      $media->order_column = $picture['order'] ?? 0;
      $media->save();
    }
  }
}

Todo:

But:

Let me know what you think @eduardoarandah . Happy to help out with this after I figure out what happens in #6 that stops the package from working for me... I'd of course be happier if you make this conversion to Operations because it'd also mean you take a look at the docs on them and can tell me what you think - I feel that's one bit of the docs that I've had zero feedback on, so I'm not sure how clear I've made it. And it's a pity, because Operations are one thing in Backpack 4.0 that I consider groundbreaking, but not many developers use them to their full potential.

Cheers!

eduardoarandah commented 3 years ago
  • We should find a way to allow developers to add MULTIPLE media types on one entity, for example "pictures", "attachments", etc. Which should be possible but I don't see how right now before I get it 100% working;

We need to add a collection name instead of using default:

https://docs.spatie.be/laravel-medialibrary/v8/working-with-media-collections/simple-media-collections/

Like this:

public function store(Request $request, MyModel $mymodel)
  {
    $media = $mymodel->addMedia($request->file('file'))->toMediaCollection('pictures');
    return $media->getUrl();
  }

Changing javacript as right now it checks for a unique id:

https://github.com/eduardoarandah/medialibrary-dropzone-for-laravel-backpack/blob/master/src/resources/views/fields/medialibrary-dropzone.blade.php#L78

And adding collection name as a parameter for the index method.

destroy and sort uses the id so that doesn't need to change.