add media stuff

This commit is contained in:
Benjamin Takats
2022-12-03 19:44:41 +01:00
parent 3749c3653b
commit a8fa8ecc5b
16 changed files with 219 additions and 24 deletions

View File

@@ -2,9 +2,9 @@ models:
Category: { name: string, slug: string } Category: { name: string, slug: string }
City: { country_id: biginteger, name: string, slug: string, longitude: 'float:10', latitude: 'float:10' } City: { country_id: biginteger, name: string, slug: string, longitude: 'float:10', latitude: 'float:10' }
Country: { name: string, code: string } Country: { name: string, code: string }
Course: { lecturer_id: biginteger, name: string } Course: { lecturer_id: biginteger, name: string, description: 'text nullable' }
Event: { course_id: biginteger, venue_id: biginteger, '"from"': datetime, '"to"': datetime } Event: { course_id: biginteger, venue_id: biginteger, '"from"': datetime, '"to"': datetime, link: string }
Lecturer: { team_id: biginteger, name: string, slug: string, active: 'boolean default:1' } Lecturer: { team_id: biginteger, name: string, slug: string, active: 'boolean default:1', description: 'text nullable' }
LoginKey: { k1: string, user_id: biginteger } LoginKey: { k1: string, user_id: biginteger }
Membership: { team_id: biginteger, user_id: biginteger, role: 'string nullable' } Membership: { team_id: biginteger, user_id: biginteger, role: 'string nullable' }
Participant: { first_name: string, last_name: string } Participant: { first_name: string, last_name: string }

View File

@@ -13,6 +13,10 @@ class EventTable extends DataTableComponent
protected $model = Event::class; protected $model = Event::class;
public bool $viewingModal = false;
public $currentModal;
public function configure(): void public function configure(): void
{ {
$this $this
@@ -51,6 +55,10 @@ class EventTable extends DataTableComponent
->sortable(), ->sortable(),
Column::make("Kurs", "course.name") Column::make("Kurs", "course.name")
->sortable(), ->sortable(),
Column::make("Art")
->label(
fn($row, Column $column) => view('columns.events.categories')->withRow($row)
),
Column::make("Von", "from") Column::make("Von", "from")
->format( ->format(
fn($value, $row, Column $column) => $value->asDateTime() fn($value, $row, Column $column) => $value->asDateTime()
@@ -83,4 +91,20 @@ class EventTable extends DataTableComponent
->whereHas('venue.city.country', ->whereHas('venue.city.country',
fn($query) => $query->where('countries.code', $this->country)); fn($query) => $query->where('countries.code', $this->country));
} }
public function viewHistoryModal($modelId): void
{
$this->viewingModal = true;
$this->currentModal = Event::findOrFail($modelId);
}
public function resetModal(): void
{
$this->reset('viewingModal', 'currentModal');
}
public function customView(): string
{
return 'modals.events.register';
}
} }

View File

@@ -4,10 +4,15 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Spatie\Image\Manipulations;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class Course extends Model class Course extends Model implements HasMedia
{ {
use HasFactory; use HasFactory;
use InteractsWithMedia;
/** /**
* The attributes that aren't mass assignable. * The attributes that aren't mass assignable.
@@ -26,6 +31,27 @@ class Course extends Model
'lecturer_id' => 'integer', 'lecturer_id' => 'integer',
]; ];
public function registerMediaConversions(Media $media = null): void
{
$this
->addMediaConversion('preview')
->fit(Manipulations::FIT_CROP, 300, 300)
->nonQueued();
$this->addMediaConversion('thumb')
->fit(Manipulations::FIT_CROP, 130, 130)
->width(130)
->height(130);
}
public function registerMediaCollections(): void
{
$this->addMediaCollection('logo')
->singleFile()
->useFallbackUrl(asset('img/einundzwanzig-cover-lesestunde.png'));
$this->addMediaCollection('images')
->useFallbackUrl(asset('img/einundzwanzig-cover-lesestunde.png'));
}
public function categories(): \Illuminate\Database\Eloquent\Relations\BelongsToMany public function categories(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{ {
return $this->belongsToMany(Category::class); return $this->belongsToMany(Category::class);

View File

@@ -2,11 +2,13 @@
namespace App\Nova; namespace App\Nova;
use Ebess\AdvancedNovaMediaLibrary\Fields\Images;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Laravel\Nova\Fields\BelongsTo; use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\BelongsToMany; use Laravel\Nova\Fields\BelongsToMany;
use Laravel\Nova\Fields\Field; use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\ID; use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Markdown;
use Laravel\Nova\Fields\Text; use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest; use Laravel\Nova\Http\Requests\NovaRequest;
use ZiffMedia\NovaSelectPlus\SelectPlus; use ZiffMedia\NovaSelectPlus\SelectPlus;
@@ -56,9 +58,20 @@ class Course extends Resource
ID::make() ID::make()
->sortable(), ->sortable(),
Images::make('Main picture', 'logo')
->conversionOnIndexView('thumb'),
Images::make('Images', 'images')
->conversionOnIndexView('thumb')
->help('Lade hier Bilder hoch, um sie eventuell später in der Markdown Description einzufügen. Du musst vorher aber Speichern.'),
Text::make('Name') Text::make('Name')
->rules('required', 'string'), ->rules('required', 'string'),
Markdown::make('Description')
->alwaysShow()
->help('Markdown ist erlaubt. Du kannst Bilder aus dem Feld "Images" hier einfügen. Benutze das Link Symbol der Bilder für die Urls, nach dem du auf "Aktualisieren und Weiterarbeiten" geklickt hast.'),
BelongsTo::make('Lecturer'), BelongsTo::make('Lecturer'),
SelectPlus::make('Categories', 'categories', Category::class) SelectPlus::make('Categories', 'categories', Category::class)

View File

@@ -8,6 +8,7 @@ use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\DateTime; use Laravel\Nova\Fields\DateTime;
use Laravel\Nova\Fields\Field; use Laravel\Nova\Fields\Field;
use Laravel\Nova\Fields\ID; use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\URL;
use Laravel\Nova\Http\Requests\NovaRequest; use Laravel\Nova\Http\Requests\NovaRequest;
class Event extends Resource class Event extends Resource
@@ -55,13 +56,18 @@ class Event extends Resource
ID::make() ID::make()
->sortable(), ->sortable(),
URL::make('Link')
->rules('required', 'url'),
DateTime::make('From') DateTime::make('From')
->rules('required') ->rules('required')
->step(CarbonInterval::minutes(30))->displayUsing(fn ($value) => $value->asDateTime()), ->step(CarbonInterval::minutes(30))
->displayUsing(fn($value) => $value->asDateTime()),
DateTime::make('To') DateTime::make('To')
->rules('required') ->rules('required')
->step(CarbonInterval::minutes(30))->displayUsing(fn ($value) => $value->asDateTime()), ->step(CarbonInterval::minutes(30))
->displayUsing(fn($value) => $value->asDateTime()),
BelongsTo::make('Course'), BelongsTo::make('Course'),
BelongsTo::make('Venue') BelongsTo::make('Venue')

22
composer.lock generated
View File

@@ -3132,16 +3132,16 @@
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "3.10.4", "version": "3.11.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem.git", "url": "https://github.com/thephpleague/flysystem.git",
"reference": "a7790f3dd1b27af81d380e6b2afa77c16ab7e181" "reference": "7e423e5dd240a60adfab9bde058d7668863b7731"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/a7790f3dd1b27af81d380e6b2afa77c16ab7e181", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/7e423e5dd240a60adfab9bde058d7668863b7731",
"reference": "a7790f3dd1b27af81d380e6b2afa77c16ab7e181", "reference": "7e423e5dd240a60adfab9bde058d7668863b7731",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3203,7 +3203,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem/issues", "issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.10.4" "source": "https://github.com/thephpleague/flysystem/tree/3.11.0"
}, },
"funding": [ "funding": [
{ {
@@ -3219,7 +3219,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-11-26T19:48:01+00:00" "time": "2022-12-02T14:39:57+00:00"
}, },
{ {
"name": "league/glide", "name": "league/glide",
@@ -11254,16 +11254,16 @@
}, },
{ {
"name": "laravel-lang/lang", "name": "laravel-lang/lang",
"version": "12.5.5", "version": "12.5.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/Laravel-Lang/lang.git", "url": "https://github.com/Laravel-Lang/lang.git",
"reference": "6d4f8ccd4694530f0c4c424eded37d5b1308c062" "reference": "f0503d6bb897070c906847858eab9b4d6e40a85c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/6d4f8ccd4694530f0c4c424eded37d5b1308c062", "url": "https://api.github.com/repos/Laravel-Lang/lang/zipball/f0503d6bb897070c906847858eab9b4d6e40a85c",
"reference": "6d4f8ccd4694530f0c4c424eded37d5b1308c062", "reference": "f0503d6bb897070c906847858eab9b4d6e40a85c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -11325,7 +11325,7 @@
"type": "open_collective" "type": "open_collective"
} }
], ],
"time": "2022-12-01T13:15:55+00:00" "time": "2022-12-03T12:40:40+00:00"
}, },
{ {
"name": "laravel-lang/publisher", "name": "laravel-lang/publisher",

View File

@@ -13,6 +13,7 @@ return new class extends Migration {
{ {
Schema::table('lecturers', function (Blueprint $table) { Schema::table('lecturers', function (Blueprint $table) {
$table->longText('description') $table->longText('description')
->fulltext()
->nullable(); ->nullable();
}); });
} }

View File

@@ -0,0 +1,31 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::table('courses', function (Blueprint $table) {
$table->longText('description')
->fulltext()
->nullable();
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::table('courses', function (Blueprint $table) {
//
});
}
};

View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
* @return void
*/
public function up()
{
Schema::table('events', function (Blueprint $table) {
$table->string('link');
});
}
/**
* Reverse the migrations.
* @return void
*/
public function down()
{
Schema::table('events', function (Blueprint $table) {
//
});
}
};

View File

@@ -107,6 +107,7 @@ class DatabaseSeeder extends Seeder
Event::create([ Event::create([
'course_id' => 1, 'course_id' => 1,
'venue_id' => 1, 'venue_id' => 1,
'link' => 'https://einundzwanzig.space',
'from' => now()->startOfDay(), 'from' => now()->startOfDay(),
'to' => now() 'to' => now()
->startOfDay() ->startOfDay()

View File

@@ -1,4 +1,6 @@
{ {
"Done": "Fertig",
"Registration": "Anmeldung",
"Lecturers": "Dozenten", "Lecturers": "Dozenten",
"Cities": "Städte", "Cities": "Städte",
"Venues": "Veranstaltungs-Orte", "Venues": "Veranstaltungs-Orte",

View File

@@ -1 +1 @@
<x-button amber>Anmelden</x-button> <x-button amber wire:click="viewHistoryModal({{ $row->id }})">Anmelden</x-button>

View File

@@ -0,0 +1,5 @@
<div class="flex space-x-1">
@foreach($row->course->categories as $category)
<x-badge>{{ $category->name }}</x-badge>
@endforeach
</div>

View File

@@ -0,0 +1,56 @@
<x-jet-dialog-modal wire:model="viewingModal" maxWidth="screen" bg="bg-21gray">
<x-slot name="title">
<div class="text-gray-200">
{{ __('Registration') }}
</div>
</x-slot>
<x-slot name="content">
<div class="relative py-16">
<div class="absolute inset-x-0 top-0 hidden h-1/2 lg:block" aria-hidden="true"></div>
<div class="mx-auto max-w-7xl bg-indigo-600 lg:bg-transparent lg:px-8">
<div class="lg:grid lg:grid-cols-12">
<div class="relative z-10 lg:col-span-4 lg:col-start-1 lg:row-start-1 lg:bg-transparent lg:py-16">
<div class="absolute inset-x-0 h-1/2 lg:hidden" aria-hidden="true"></div>
<div class="mx-auto max-w-md px-4 sm:max-w-3xl sm:px-6 lg:max-w-none lg:p-0 space-y-2">
<div class="aspect-w-10 aspect-h-6 sm:aspect-w-2 sm:aspect-h-1 lg:aspect-w-1">
<img class="rounded-3xl object-cover object-center shadow-2xl"
src="{{ $currentModal?->course->getFirstMediaUrl('logo') }}"
alt="{{ $currentModal?->course->name }}">
</div>
@foreach($currentModal?->course->getMedia('images') ?? [] as $image)
<div class="aspect-w-10 aspect-h-6 sm:aspect-w-2 sm:aspect-h-1 lg:aspect-w-1">
<img class="rounded-3xl object-cover object-center shadow-2xl"
src="{{ $image->getUrl() }}"
alt="{{ $currentModal?->course->name }}">
</div>
@endforeach
</div>
</div>
<div
class="relative bg-amber-600 py-4 lg:col-span-10 lg:col-start-3 lg:row-start-1 lg:grid lg:grid-cols-10 lg:items-center lg:rounded-3xl">
<div
class="relative mx-auto max-w-md space-y-6 py-12 px-4 sm:max-w-3xl sm:py-16 sm:px-6 lg:col-span-6 lg:col-start-4 lg:max-w-none lg:p-0">
<h2 class="text-3xl font-bold tracking-tight text-white"
id="join-heading">{{ $currentModal?->course->name }}</h2>
<a class="block w-full rounded-md border border-transparent bg-white py-3 px-5 text-center text-base font-medium text-amber-500 shadow-md hover:bg-gray-50 sm:inline-block sm:w-auto"
href="{{ $currentModal?->link }}" target="_blank">Link zur Anmeldung</a>
<x-markdown>
{{ $currentModal?->course->description }}
</x-markdown>
<a class="block w-full rounded-md border border-transparent bg-white py-3 px-5 text-center text-base font-medium text-amber-500 shadow-md hover:bg-gray-50 sm:inline-block sm:w-auto"
href="{{ $currentModal?->link }}" target="_blank">Link zur Anmeldung</a>
</div>
</div>
</div>
</div>
</div>
</x-slot>
<x-slot name="footer">
<x-jet-secondary-button wire:click="resetModal" wire:loading.attr="disabled">
@lang('Done')
</x-jet-secondary-button>
</x-slot>
</x-jet-dialog-modal>

View File

@@ -1,6 +1,6 @@
@props(['id' => null, 'maxWidth' => null]) @props(['id' => null, 'maxWidth' => null, 'bg' => 'bg-white'])
<x-jet-modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}> <x-jet-modal :id="$id" :maxWidth="$maxWidth" :bg="$bg" {{ $attributes }}>
<div class="px-6 py-4"> <div class="px-6 py-4">
<div class="text-lg"> <div class="text-lg">
{{ $title }} {{ $title }}
@@ -11,7 +11,7 @@
</div> </div>
</div> </div>
<div class="flex flex-row justify-end px-6 py-4 bg-gray-100 text-right"> <div class="flex flex-row justify-end px-6 py-4 {{ $bg }} text-right">
{{ $footer }} {{ $footer }}
</div> </div>
</x-jet-modal> </x-jet-modal>

View File

@@ -1,4 +1,4 @@
@props(['id', 'maxWidth']) @props(['id', 'maxWidth', 'bg'])
@php @php
$id = $id ?? md5($attributes->wire('model')); $id = $id ?? md5($attributes->wire('model'));
@@ -9,6 +9,7 @@ $maxWidth = [
'lg' => 'sm:max-w-lg', 'lg' => 'sm:max-w-lg',
'xl' => 'sm:max-w-xl', 'xl' => 'sm:max-w-xl',
'2xl' => 'sm:max-w-2xl', '2xl' => 'sm:max-w-2xl',
'screen' => 'sm:max-w-screen-lg',
][$maxWidth ?? '2xl']; ][$maxWidth ?? '2xl'];
@endphp @endphp
@@ -53,10 +54,10 @@ $maxWidth = [
x-transition:leave="ease-in duration-200" x-transition:leave="ease-in duration-200"
x-transition:leave-start="opacity-100" x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"> x-transition:leave-end="opacity-0">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div> <div class="absolute inset-0 {{ $bg }} opacity-75"></div>
</div> </div>
<div x-show="show" class="mb-6 bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto" <div x-show="show" class="mb-6 {{ $bg }} rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }} sm:mx-auto"
x-transition:enter="ease-out duration-300" x-transition:enter="ease-out duration-300"
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100" x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"