BRACKETS-by-TRIAD / craftable

Admin panel builder / CRUD generator for Laravel.
https://getcraftable.com
MIT License
982 stars 192 forks source link

Problem with uploading Media. #295

Closed GonrasK closed 3 years ago

GonrasK commented 3 years ago

I simply have 1 model that i'd like to be able to upload a logo for it (in this case - it's name is 'Operator') The model itself looks like this -

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use Brackets\Media\HasMedia\ProcessMediaTrait;
use Brackets\Media\HasMedia\AutoProcessMediaTrait;
use Brackets\Media\HasMedia\HasMediaCollectionsTrait;
use Spatie\MediaLibrary\HasMedia;
use Brackets\Translatable\Traits\HasTranslations;

class Operator extends Model implements HasMedia
{
    use ProcessMediaTrait;
    use AutoProcessMediaTrait;
    use HasMediaCollectionsTrait;

    public function registerMediaCollections() {
        $this->addMediaCollection('gallery');
    }

    public function registerMediaConversions(Media $media = null) : void
    {
        $this->autoRegisterThumb200();
    }

    protected $fillable = [
        'name',
        'enabled',
        'rank',
        'headline',
        'description',
        'visit_url',
        'total_score',
        'text_button',
        'text_below_button',
        'review_meta_title',
        'review_meta_description',

    ];

    protected $dates = [
        'created_at',
        'updated_at',

    ];
    // these attributes are translatable
    public $translatable = [
        'headline',
        'description',
        'visit_url',
        'text_button',
        'text_below_button',
        'review_meta_title',
        'review_meta_description',

    ];

    protected $appends = ['resource_url'];

    /* ************************ ACCESSOR ************************* */

    public function getResourceUrlAttribute()
    {
        return url('/admin/operators/'.$this->getKey());
    }

}

And the controller's store method looks like this -

public function store(StoreOperator $request)
    {
        // Sanitize input
        $sanitized = $request->getSanitized();

        // Store the Operator
//        $operator = Operator::create($sanitized);
        $operator = Operator::create($request->validated());
        if ($request->ajax()) {
            return ['redirect' => url('admin/operators'), 'message' => trans('brackets/admin-ui::admin.operation.succeeded')];
        }

        return redirect('admin/operators');
    }

Inside /js/admin/operator/Form.js , I added the mediaCollections into the VueJS mixin, like this -

import AppForm from '../app-components/Form/AppForm';

Vue.component('operator-form', {
    mixins: [AppForm],
    data: function() {
        return {
            form: {
                name:  '' ,
                enabled:  false ,
                rank:  '' ,
                headline:  this.getLocalizedFormDefaults() ,
                description:  this.getLocalizedFormDefaults() ,
                visit_url:  this.getLocalizedFormDefaults() ,
                total_score:  '' ,
                text_button:  this.getLocalizedFormDefaults() ,
                text_below_button:  this.getLocalizedFormDefaults() ,
                review_meta_title:  this.getLocalizedFormDefaults() ,
                review_meta_description:  this.getLocalizedFormDefaults() ,

            },
            mediaCollections: ['gallery']
        }
    }

});

And inside the form.elements.blade.php (under /views/admin/operator/components), I added your media-uploader widget, just like it's written in the documentation -

...

<div class="form-group row align-items-center" :class="{'has-danger': errors.has('name'), 'has-success': fields.name && fields.name.valid }">
    <label for="name" class="col-form-label text-md-right" :class="isFormLocalized ? 'col-md-4' : 'col-md-2'">{{ trans('admin.operator.columns.name') }}</label>
    <div :class="isFormLocalized ? 'col-md-4' : 'col-md-9 col-xl-8'">
        <input type="text" v-model="form.name" v-validate="'required'" @input="validate($event)" class="form-control" :class="{'form-control-danger': errors.has('name'), 'form-control-success': fields.name && fields.name.valid}" id="name" name="name" placeholder="{{ trans('admin.operator.columns.name') }}">
        <div v-if="errors.has('name')" class="form-control-feedback form-text" v-cloak>@{{ errors.first('name') }}</div>
    </div>
</div>

@include('brackets/admin-ui::admin.includes.media-uploader', [
    'mediaCollection' => app(App\Models\Operator::class)->getMediaCollection('gallery'),
    'label' => 'Gallery'
])

<div class="row">
    @foreach($locales as $locale)
        <div class="col-md" v-show="shouldShowLangGroup('{{ $locale }}')" v-cloak>
            <div class="form-group row align-items-center" :class="{'has-danger': errors.has('headline_{{ $locale }}'), 'has-success': fields.headline_{{ $locale }} && fields.headline_{{ $locale }}.valid }">
                <label for="headline_{{ $locale }}" class="col-md-2 col-form-label text-md-right">{{ trans('admin.operator.columns.headline') }}</label>
                <div class="col-md-9" :class="{'col-xl-8': !isFormLocalized }">
                    <input type="text" v-model="form.headline.{{ $locale }}" v-validate="''" @input="validate($event)" class="form-control" :class="{'form-control-danger': errors.has('headline_{{ $locale }}'), 'form-control-success': fields.headline_{{ $locale }} && fields.headline_{{ $locale }}.valid }" id="headline_{{ $locale }}" name="headline_{{ $locale }}" placeholder="{{ trans('admin.operator.columns.headline') }}">
                    <div v-if="errors.has('headline_{{ $locale }}')" class="form-control-feedback form-text" v-cloak>{{'{{'}} errors.first('headline_{{ $locale }}') }}</div>
                </div>
            </div>
        </div>
    @endforeach
</div>
...

...So... The first error I'm getting is - Declaration of App\Models\Operator::registerMediaCollections() must be compatible with Spatie\MediaLibrary\HasMedia::registerMediaCollections(): void ..

Adding the " : void " part inside the model actually helped me to finally upload the view with the media upload widget ..

public function registerMediaCollections() : void {
        $this->addMediaCollection('gallery');
    }

Resulted in -

Screen Shot 2020-12-10 at 16 39 01

But, when I'm trying to hit 'Save', I get the following error -

"Error! Illuminate\Database\Grammar::parameterize(): Argument #1 ($values) must be of type array, string given, called in /Users/gonras/trusted_network/operators-project/vendor/laravel/framework/src/Illuminate/Database/Query/Grammars/Grammar.php on line 886"

And unfortunately , I am unable to debug further from this point.

palypster commented 3 years ago

Hmm, I don't see a problem. Have you solved it?

GonrasK commented 3 years ago

yes.