Display CMS Optimierungen 29-05-2026
- Mediathek: Video-Vorschaubilder statt Icons (FFmpeg-Thumbnails + Backfill-Command), Kategorie "Sonstiges" - B2in Media-Picker zeigt alle Medientypen, Typ wird automatisch erkannt; Thumbnail-Preview vor allen Medien-URL-Feldern - B2in Marke/Footer: Footer ein/aus, Logo+Claim frei positionierbar (Ecken) mit Constraints, separate Anzeige-Schalter - Angebote-Modul dynamisch: kein Slide-Typ mehr, einheitliches Detail-Layout mit ein-/ausblendbaren Bloecken, Logo/Brand pro Slide, Streichpreis-Option - Player: leere Module stoppen Endlosschleife, dynamische Layout-Anpassung bei verstecktem Footer/Header - Fix: Script-Ladereihenfolge (Livewire vor Flux), entfernte stale public/flux/flux.js, Modal-Crash beim Aktualisieren behoben Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
9262132325
commit
6c6d683b9a
42 changed files with 2267 additions and 13905 deletions
|
|
@ -6,11 +6,12 @@ use Flux\Flux;
|
|||
use Illuminate\Support\Facades\Storage;
|
||||
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||
use Livewire\WithFileUploads;
|
||||
use Livewire\WithPagination;
|
||||
use function Livewire\Volt\{layout, title, state, computed, on, uses};
|
||||
|
||||
layout('components.layouts.app');
|
||||
title('Display-Mediathek');
|
||||
uses([WithFileUploads::class]);
|
||||
uses([WithFileUploads::class, WithPagination::class]);
|
||||
|
||||
state([
|
||||
'search' => '',
|
||||
|
|
@ -47,12 +48,16 @@ $media = computed(
|
|||
default => $q,
|
||||
})
|
||||
->when($this->filterCollection, fn ($q) => $q->inCollection($this->filterCollection))
|
||||
->when($this->search, fn ($q) => $q->where('filename', 'like', "%{$this->search}%")
|
||||
->orWhere('title', 'like', "%{$this->search}%"))
|
||||
->when($this->search, fn ($q) => $q->search($this->search))
|
||||
->orderByDesc('created_at')
|
||||
->paginate(48),
|
||||
);
|
||||
|
||||
$updatedSearch = fn () => $this->resetPage();
|
||||
$updatedFilterType = fn () => $this->resetPage();
|
||||
$updatedFilterSource = fn () => $this->resetPage();
|
||||
$updatedFilterCollection = fn () => $this->resetPage();
|
||||
|
||||
$collections = computed(fn () => DisplayMedia::query()
|
||||
->whereNotNull('collection')
|
||||
->where('collection', '!=', '')
|
||||
|
|
@ -283,27 +288,37 @@ $closeDetail = function () {
|
|||
class="group relative cursor-pointer overflow-hidden rounded-lg border transition-all
|
||||
{{ $editingId === $item->id ? 'border-blue-500 ring-2 ring-blue-200 dark:ring-blue-800' : 'border-zinc-200 hover:border-zinc-400 dark:border-zinc-700' }}"
|
||||
wire:click="startEdit({{ $item->id }})">
|
||||
<div class="aspect-square bg-zinc-100 dark:bg-zinc-800">
|
||||
@if ($item->isImage() && $item->isUpload())
|
||||
<img src="{{ $item->getThumbnailUrl() }}"
|
||||
@php
|
||||
$thumbSrc = $item->getThumbnailUrl() ?? ($item->isImage() && $item->isExternal() ? $item->external_url : null);
|
||||
$videoFrameSrc = (! $thumbSrc && $item->isVideo() && $item->isUpload()) ? $item->getUrl() : null;
|
||||
@endphp
|
||||
<div class="relative aspect-square bg-zinc-100 dark:bg-zinc-800">
|
||||
@if ($thumbSrc)
|
||||
<img src="{{ $thumbSrc }}"
|
||||
alt="{{ $item->alt_text ?? $item->filename }}"
|
||||
class="h-full w-full object-cover" loading="lazy" />
|
||||
@elseif ($videoFrameSrc)
|
||||
<video class="h-full w-full object-cover" preload="metadata" muted playsinline>
|
||||
<source src="{{ $videoFrameSrc }}#t=1" type="{{ $item->mime_type }}">
|
||||
</video>
|
||||
@elseif ($item->isVideo())
|
||||
<div class="flex h-full w-full flex-col items-center justify-center gap-2 text-purple-400">
|
||||
<x-heroicon-o-film class="h-10 w-10" />
|
||||
<span class="text-xs">Video</span>
|
||||
</div>
|
||||
@elseif ($item->isExternal() && $item->isImage())
|
||||
<div class="flex h-full w-full flex-col items-center justify-center gap-2 text-blue-400">
|
||||
<x-heroicon-o-photo class="h-10 w-10" />
|
||||
<span class="text-xs">Extern</span>
|
||||
</div>
|
||||
@else
|
||||
<div class="flex h-full w-full flex-col items-center justify-center gap-2 text-zinc-400">
|
||||
<x-heroicon-o-link class="h-10 w-10" />
|
||||
<span class="text-xs">Link</span>
|
||||
</div>
|
||||
@endif
|
||||
@if ($item->isVideo() && ($thumbSrc || $videoFrameSrc))
|
||||
<div class="pointer-events-none absolute inset-0 flex items-center justify-center">
|
||||
<span class="flex h-10 w-10 items-center justify-center rounded-full bg-black/45 text-white ring-1 ring-white/30 backdrop-blur-sm">
|
||||
<x-heroicon-s-play class="h-5 w-5" />
|
||||
</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5 p-2">
|
||||
@if ($item->isVideo())
|
||||
|
|
@ -352,9 +367,17 @@ $closeDetail = function () {
|
|||
class="cursor-pointer transition {{ $editingId === $item->id ? 'bg-blue-50 dark:bg-blue-900/20' : 'hover:bg-zinc-50 dark:hover:bg-zinc-800/50' }}"
|
||||
wire:click="startEdit({{ $item->id }})">
|
||||
<td class="px-3 py-1.5">
|
||||
<div class="flex h-8 w-8 items-center justify-center overflow-hidden rounded border border-zinc-200 bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800">
|
||||
@if ($item->isImage() && $item->isUpload())
|
||||
<img src="{{ $item->getThumbnailUrl() }}" class="h-full w-full object-cover" loading="lazy" />
|
||||
@php
|
||||
$rowThumb = $item->getThumbnailUrl() ?? ($item->isImage() && $item->isExternal() ? $item->external_url : null);
|
||||
$rowVideoFrame = (! $rowThumb && $item->isVideo() && $item->isUpload()) ? $item->getUrl() : null;
|
||||
@endphp
|
||||
<div class="relative flex h-8 w-8 items-center justify-center overflow-hidden rounded border border-zinc-200 bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800">
|
||||
@if ($rowThumb)
|
||||
<img src="{{ $rowThumb }}" class="h-full w-full object-cover" loading="lazy" />
|
||||
@elseif ($rowVideoFrame)
|
||||
<video class="h-full w-full object-cover" preload="metadata" muted playsinline>
|
||||
<source src="{{ $rowVideoFrame }}#t=1" type="{{ $item->mime_type }}">
|
||||
</video>
|
||||
@elseif ($item->isVideo())
|
||||
<x-heroicon-s-film class="h-4 w-4 text-purple-500" />
|
||||
@else
|
||||
|
|
@ -418,17 +441,18 @@ $closeDetail = function () {
|
|||
|
||||
{{-- Preview --}}
|
||||
<div class="mb-4 overflow-hidden rounded-lg border border-zinc-200 bg-zinc-50 dark:border-zinc-700 dark:bg-zinc-800">
|
||||
@if ($editMedia->isImage() && $editMedia->isUpload())
|
||||
@if ($editMedia->isImage())
|
||||
<img src="{{ $editMedia->getUrl() }}" alt="{{ $editMedia->filename }}"
|
||||
class="w-full object-contain" style="max-height: 300px;" />
|
||||
@elseif ($editMedia->isVideo() && $editMedia->isUpload())
|
||||
<video controls class="w-full" style="max-height: 300px;">
|
||||
<video controls preload="metadata" class="w-full" style="max-height: 300px;"
|
||||
@if ($editMedia->getThumbnailUrl()) poster="{{ $editMedia->getThumbnailUrl() }}" @endif>
|
||||
<source src="{{ $editMedia->getUrl() }}" type="{{ $editMedia->mime_type }}">
|
||||
</video>
|
||||
@elseif ($editMedia->isExternal())
|
||||
<div class="flex flex-col items-center justify-center gap-3 py-8">
|
||||
<x-heroicon-o-link class="h-12 w-12 text-blue-400" />
|
||||
<span class="text-sm text-zinc-500">Externe Ressource</span>
|
||||
<span class="text-sm text-zinc-500">Externe Ressource (Vorschau nicht einbettbar)</span>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue