576 lines
22 KiB
Markdown
576 lines
22 KiB
Markdown
# Flux CMS — Content Management für Laravel + Livewire + Flux UI
|
|
|
|
## Überblick
|
|
|
|
Flux CMS ist ein modulares, mehrsprachiges Content-Management-System für Laravel-Anwendungen. Es nutzt Livewire Volt (Functional API) und Flux UI Pro als Admin-Oberfläche und speichert alle Inhalte übersetzbar in der Datenbank (`spatie/laravel-translatable`).
|
|
|
|
**Kernkonzept:** Bestehende Inhalte aus Laravel `lang/`-Dateien werden in die Datenbank migriert. Ein `cms()` Helper mit Fallback auf `__()` sorgt für nahtlose Migration — Seiten funktionieren sofort, auch wenn noch nicht alle Inhalte in der DB sind.
|
|
|
|
### Tech-Stack
|
|
|
|
- Laravel 12, Livewire 3, Volt (Functional API)
|
|
- Flux UI Pro v2 (Komponenten-Bibliothek)
|
|
- Tailwind CSS v4
|
|
- `spatie/laravel-translatable` für Mehrsprachigkeit
|
|
- `intervention/image` v3 für Bildverarbeitung
|
|
- Pest v4 für Tests
|
|
|
|
---
|
|
|
|
## Architektur
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Frontend (Blade/Livewire Views) │
|
|
│ {{ cms('welcome.hero.heading') }} │
|
|
│ {{ cms_media_url('welcome.hero.image') }} │
|
|
│ {{ media_url('keyvisual.webp', 'hero') }} │
|
|
└──────────────┬───────────────────────────────────────┘
|
|
│
|
|
┌──────────────▼───────────────────────────────────────┐
|
|
│ Helper-Funktionen │
|
|
│ cms() → CmsContentService (DB + Cache) │
|
|
│ cms_media_url() → CmsContent → CmsMedia → URL │
|
|
│ media_url() → CmsMedia → URL (mit Cache) │
|
|
└──────────────┬───────────────────────────────────────┘
|
|
│
|
|
┌──────────────▼───────────────────────────────────────┐
|
|
│ Datenbank (flux_cms_* Tabellen) │
|
|
│ CmsContent, CmsMedia, CmsNewsItem, CmsIndustry, │
|
|
│ CmsFaq, CmsLinkedinPost, CmsDownload │
|
|
└──────────────┬───────────────────────────────────────┘
|
|
│
|
|
┌──────────────▼───────────────────────────────────────┐
|
|
│ Media Library (Storage / public disk) │
|
|
│ cms/media/originals/ → Original-Uploads │
|
|
│ cms/media/conversions/ → Generierte Bildgrößen │
|
|
│ cms/media/thumbnails/ → Auto-generierte Thumbnails │
|
|
└──────────────┬───────────────────────────────────────┘
|
|
│
|
|
┌──────────────▼───────────────────────────────────────┐
|
|
│ Admin UI (/admin/cms/*) │
|
|
│ Livewire Volt + Flux UI Pro │
|
|
│ Content-Editor, Medienbibliothek, Downloads, │
|
|
│ Team, News, LinkedIn, FAQs, Industries │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Datenbankmodelle
|
|
|
|
### CmsContent (Kern)
|
|
Flexibler Key-Value-Store für alle Seiteninhalte.
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `group` | string | Seiten-/Dateiname (z.B. `welcome`, `about`, `footer`) |
|
|
| `key` | string | Dot-Notation-Pfad (z.B. `hero.heading`, `cta.description`) |
|
|
| `type` | enum | `text`, `html`, `image`, `json`, `link` |
|
|
| `value` | JSON | Übersetzbar: `{"de": "...", "en": "..."}` |
|
|
| `order` | int | Sortierung (chronologisch nach Dateistruktur) |
|
|
|
|
### CmsMedia (Medienbibliothek)
|
|
Zentrale Verwaltung aller Bilder und PDFs.
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `filename` | string | Original-Dateiname (z.B. `keyvisual.webp`) |
|
|
| `path` | string | Storage-Pfad (z.B. `cms/media/originals/abc123.webp`) |
|
|
| `type` | string | `image`, `pdf`, `document` |
|
|
| `mime_type` | string | MIME-Typ |
|
|
| `file_size` | int | Dateigröße in Bytes |
|
|
| `original_width` | int | Breite bei Bildern |
|
|
| `original_height` | int | Höhe bei Bildern |
|
|
| `disk` | string | Storage-Disk (default: `public`) |
|
|
| `collection` | string | Optionale Sammlung/Ordner |
|
|
| `conversions` | JSON | Generierte Bildgrößen-Pfade |
|
|
| `title` | JSON | Übersetzbar |
|
|
| `alt_text` | JSON | Übersetzbar |
|
|
| `is_published` | bool | Veröffentlichungsstatus |
|
|
|
|
### CmsDownload (Case Studies, Capabilities, Success Stories)
|
|
Vollständiges Download-Management mit sprachspezifischen PDFs.
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `title` | JSON | Übersetzbar |
|
|
| `description` | JSON | Übersetzbar |
|
|
| `category` | string | `case_study`, `capability`, `success_story` |
|
|
| `icon` | string | Heroicon-Name |
|
|
| `sub_category` | string | Detail-Kategorie (z.B. "R&D Product Support") |
|
|
| `type_label` | JSON | Übersetzbar (z.B. "Case Study" / "Capability") |
|
|
| `alt` | JSON | Übersetzbar: Alt-Text für Vorschaubild |
|
|
| `file_path` | JSON | Übersetzbar: PDF-Dateiname pro Sprache (DE/EN) |
|
|
| `thumbnail` | string | Vorschaubild-Dateiname (CmsMedia) |
|
|
| `open_text` | JSON | Übersetzbar: Button-Text "PDF öffnen" |
|
|
| `download_text` | JSON | Übersetzbar: Button-Text "PDF downloaden" |
|
|
| `highlights` | JSON | Kennzahlen `[{"value": "100%", "label": "..."}]` |
|
|
| `checkpoints` | JSON | Checkpunkte `[{"value": "..."}]` |
|
|
|
|
### Weitere Modelle
|
|
|
|
| Modell | Tabelle | Zweck |
|
|
|--------|---------|-------|
|
|
| `CmsNewsItem` | `flux_cms_news_items` | News-Band mit Icon, PDF, Datum, Bild (via CmsMedia) |
|
|
| `CmsIndustry` | `flux_cms_industries` | Industries-Band mit Sortierung |
|
|
| `CmsFaq` | `flux_cms_faqs` | FAQ-Einträge mit Kategorie und Hilfe-Text |
|
|
| `CmsLinkedinPost` | `flux_cms_linkedin_posts` | LinkedIn-Posts mit Bild (via CmsMedia) |
|
|
| `CmsSearchIndex` | `flux_cms_search_index` | Seitensuche: Keywords, Titel, Beschreibungen pro Route |
|
|
|
|
Alle Modelle nutzen `Spatie\Translatable\HasTranslations` für DE/EN (erweiterbar).
|
|
|
|
### CmsSearchIndex (Seitensuche)
|
|
Zentrales Index-Modell für die Frontend-Suche. Jeder Eintrag repräsentiert eine Seite/Route.
|
|
|
|
| Feld | Typ | Beschreibung |
|
|
|------|-----|-------------|
|
|
| `item_id` | string | Eindeutige ID (z.B. `home`, `leistungen`) |
|
|
| `route` | string | Laravel Named Route (z.B. `home`, `leistungen`) |
|
|
| `route_params` | JSON | Route-Parameter als Array |
|
|
| `category` | JSON | Übersetzbar: Kategorie (z.B. `Startseite`, `Leistungen`) |
|
|
| `title_key` | string | CMS-Key für Titel (löst via `cms()` auf) |
|
|
| `title_fallback` | JSON | Übersetzbar: Statischer Fallback-Titel |
|
|
| `description_key` | string | CMS-Key für Beschreibung |
|
|
| `description_fallback_key` | string | Sekundärer CMS-Key als Fallback |
|
|
| `description_fallback_text` | JSON | Übersetzbar: Statischer Fallback-Text |
|
|
| `keywords` | JSON | Übersetzbar: Array aus Keywords oder CMS-Keys (Dot-Notation) |
|
|
| `is_published` | bool | Veröffentlichungsstatus |
|
|
|
|
**Keywords:** Können direkte Texte oder CMS-Keys (mit Punkt) sein. CMS-Keys werden automatisch aufgelöst.
|
|
|
|
```php
|
|
// toFrontendArray() löst alle Keys auf
|
|
$entries = CmsSearchIndex::published()->ordered()->get()
|
|
->map(fn ($entry) => $entry->toFrontendArray())
|
|
->toArray();
|
|
```
|
|
|
|
---
|
|
|
|
## Medienbibliothek
|
|
|
|
### Konzept
|
|
|
|
Alle Bilder und PDFs werden zentral in einer Medienbibliothek verwaltet. Anstatt Dateien direkt an Inhalte hochzuladen, werden sie aus der Bibliothek ausgewählt. Vorteile:
|
|
|
|
- Zentrale Verwaltung aller Assets
|
|
- Automatische Bildoptimierung (Resize, Kompression, Formatkonvertierung)
|
|
- Wiederverwendung von Medien über verschiedene Inhalte hinweg
|
|
- Sprachunabhängige Bilder, sprachspezifische PDFs
|
|
|
|
### Bildprofile (Conversions)
|
|
|
|
Definiert in `config/flux-cms.php`:
|
|
|
|
```php
|
|
'media' => [
|
|
'profiles' => [
|
|
'hero' => ['width' => 1920, 'height' => 800, 'format' => 'webp', 'quality' => 85],
|
|
'card' => ['width' => 768, 'height' => 512, 'format' => 'webp', 'quality' => 80],
|
|
'thumbnail' => ['width' => 400, 'height' => 300, 'format' => 'webp', 'quality' => 75],
|
|
'avatar' => ['width' => 400, 'height' => 400, 'format' => 'webp', 'quality' => 80],
|
|
'news' => ['width' => 1200, 'height' => 630, 'format' => 'webp', 'quality' => 80],
|
|
'thumb' => ['width' => 200, 'height' => 200, 'format' => 'webp', 'quality' => 70],
|
|
],
|
|
],
|
|
```
|
|
|
|
Conversions werden automatisch beim Upload (Thumbnail) oder on-demand im Admin generiert.
|
|
|
|
### MediaConversionService
|
|
|
|
```php
|
|
$service = app(MediaConversionService::class);
|
|
|
|
// Einzelne Conversion
|
|
$service->convert($media, 'hero');
|
|
|
|
// Alle Conversions
|
|
$service->generateAllConversions($media);
|
|
|
|
// Thumbnail automatisch
|
|
$service->generateThumbnail($media);
|
|
```
|
|
|
|
### Komponenten
|
|
|
|
| Komponente | Typ | Beschreibung |
|
|
|------------|-----|-------------|
|
|
| `MediaLibraryUploader` | Class-based Livewire | Multi-File Drag&Drop Upload via `flux:file-upload` |
|
|
| `MediaPicker` | Class-based Livewire | Wiederverwendbares Modal zur Medienauswahl |
|
|
|
|
**MediaPicker-Verwendung:**
|
|
|
|
```blade
|
|
<livewire:admin.cms.media-picker
|
|
:value="$imageMediaId"
|
|
field="news_image"
|
|
type="image"
|
|
profile="news"
|
|
label="Bild wählen"
|
|
:key="'img-' . $editingId" />
|
|
```
|
|
|
|
Feuert `media-selected` Event mit `field`, `mediaId`, `url`:
|
|
|
|
```php
|
|
on(['media-selected' => function (string $field, ?int $mediaId, ?string $url) {
|
|
if ($field === 'news_image') {
|
|
$this->imageMediaId = $mediaId;
|
|
$media = $mediaId ? CmsMedia::find($mediaId) : null;
|
|
$this->image = $media ? $media->filename : '';
|
|
}
|
|
}]);
|
|
```
|
|
|
|
---
|
|
|
|
## Helper-Funktionen
|
|
|
|
### `cms()` — Content abrufen
|
|
|
|
```php
|
|
$value = cms('welcome.hero.heading');
|
|
$value = cms('key', ['highlight' => '<span>...</span>']);
|
|
$value = cms('key', locale: 'en');
|
|
```
|
|
|
|
**Fallback-Kette:** DB (mit Cache) → `__()` (Laravel-Translation)
|
|
|
|
### `cms_media_url()` — Bild über CmsContent-Key
|
|
|
|
```php
|
|
// Holt Dateiname aus CmsContent, löst über CmsMedia auf
|
|
$url = cms_media_url('welcome.hero.image');
|
|
$url = cms_media_url('welcome.hero.image', 'hero'); // mit Conversion-Profil
|
|
```
|
|
|
|
### `media_url()` — Bild über Dateiname
|
|
|
|
```php
|
|
// Löst CmsMedia-Dateiname direkt auf (mit In-Memory-Cache)
|
|
$url = media_url('keyvisual.webp');
|
|
$url = media_url('keyvisual.webp', 'hero'); // mit Conversion-Profil
|
|
```
|
|
|
|
**Fallback:** `asset('assets/images/' . $filename)` wenn nicht in CmsMedia.
|
|
|
|
### `tcms()` — Content mit Tooltip-Verarbeitung
|
|
|
|
```php
|
|
$text = tcms('welcome.hero.heading');
|
|
```
|
|
|
|
---
|
|
|
|
## Dateien-Übersicht
|
|
|
|
### Package-Kern (`package/flux-cms/core/`)
|
|
|
|
```
|
|
src/
|
|
├── Models/
|
|
│ ├── CmsContent.php # Key-Value Content-Store
|
|
│ ├── CmsMedia.php # Medienbibliothek-Einträge
|
|
│ ├── CmsNewsItem.php # News (mit toFrontendArray())
|
|
│ ├── CmsDownload.php # Downloads (mit toFrontendArray())
|
|
│ ├── CmsIndustry.php # Industries
|
|
│ ├── CmsFaq.php # FAQs
|
|
│ └── CmsLinkedinPost.php # LinkedIn-Posts
|
|
├── Services/
|
|
│ ├── CmsContentService.php # Content-Abruf mit Caching + Fallback
|
|
│ └── MediaConversionService.php # Bildverarbeitung (intervention/image)
|
|
├── Helpers/
|
|
│ ├── cms_helpers.php # cms() und tcms() Helper
|
|
│ ├── MediaLibraryUploader.php # Multi-File Upload Komponente
|
|
│ └── MediaPicker.php # Medienauswahl-Modal
|
|
└── FluxCmsServiceProvider.php # Package-Registrierung
|
|
|
|
database/
|
|
├── migrations/
|
|
│ ├── ..._create_flux_cms_contents_table.php
|
|
│ ├── ..._create_flux_cms_downloads_table.php
|
|
│ ├── ..._create_flux_cms_linkedin_posts_table.php
|
|
│ ├── ..._create_flux_cms_faqs_table.php
|
|
│ ├── ..._create_flux_cms_news_items_table.php
|
|
│ ├── ..._create_flux_cms_industries_table.php
|
|
│ └── ..._create_flux_cms_media_table.php
|
|
└── seeders-reference/
|
|
|
|
config/
|
|
└── flux-cms.php # Locales, Cache, Media-Profiles, Auth
|
|
```
|
|
|
|
### Projekt-Integration (Host-App)
|
|
|
|
```
|
|
app/
|
|
├── helpers.php # cms(), tcms(), cms_media_url(), media_url()
|
|
└── Livewire/Admin/Cms/
|
|
├── MediaLibraryUploader.php # Multi-File Upload
|
|
└── MediaPicker.php # Medienauswahl-Modal
|
|
|
|
resources/views/
|
|
├── livewire/admin/cms/ # Volt-Admin-Komponenten
|
|
│ ├── content-index.blade.php # Inhalte-Editor (text/html/image/json)
|
|
│ ├── news-index.blade.php # News-Verwaltung
|
|
│ ├── downloads-index.blade.php # Downloads (Case Studies/Capabilities/Stories)
|
|
│ ├── team-index.blade.php # Team-Verwaltung
|
|
│ ├── linkedin-index.blade.php # LinkedIn-Posts
|
|
│ ├── industries-index.blade.php # Industries
|
|
│ ├── faqs-index.blade.php # FAQ-Verwaltung
|
|
│ ├── media-index.blade.php # Medienbibliothek
|
|
│ ├── media-library-uploader.blade.php
|
|
│ ├── media-picker.blade.php
|
|
│ └── dashboard-index.blade.php # CMS-Dashboard
|
|
└── components/layouts/
|
|
└── cms.blade.php # CMS-Admin-Layout mit Sidebar
|
|
|
|
database/
|
|
├── migrations/
|
|
│ ├── ..._add_detail_columns_to_flux_cms_downloads_table.php
|
|
│ └── ..._change_file_path_to_json_on_flux_cms_downloads_table.php
|
|
└── seeders/
|
|
├── CmsContentSeeder.php # Lang → DB Migration
|
|
├── CmsMediaSeeder.php # Medien-Einträge + CmsContent image-Typen
|
|
├── CmsDownloadSeeder.php # Case Studies, Capabilities, Success Stories
|
|
├── CmsNewsItemSeeder.php # News-Band (mit Media-Filename-Mapping)
|
|
├── CmsLinkedinPostSeeder.php # LinkedIn-Posts (mit Media-Filenames)
|
|
├── CmsIndustrySeeder.php
|
|
└── CmsFaqSeeder.php
|
|
|
|
routes/web.php # CMS-Routes unter /admin/cms/*
|
|
```
|
|
|
|
---
|
|
|
|
## Admin-Bereiche
|
|
|
|
### Inhalte (`/admin/cms/content`)
|
|
- Alle `CmsContent`-Einträge nach Gruppen
|
|
- **Text/HTML**: Inline-Editor (Flux Editor) mit konfigurierbaren Toolbars
|
|
- **Image**: MediaPicker mit Vorschau
|
|
- **JSON**: Modal-Editor mit strukturierter Bearbeitung (Icons, Editor, Inputs)
|
|
- Sprachumschaltung DE/EN
|
|
|
|
### Medienbibliothek (`/admin/cms/media`)
|
|
- Grid- und Listenansicht (Toggle)
|
|
- Filter nach Typ (Bilder/PDFs/Dokumente), Sammlung, Dateiname
|
|
- Multi-File Drag&Drop Upload
|
|
- Detail-Sidebar: Metadaten, Alt-Text, Titel, Sammlung
|
|
- Bildgrößen-Management: Einzelne oder alle Conversions generieren
|
|
- **PDF-Vorschau**: Eingebettete PDF-Darstellung via iframe
|
|
- **Typ-Icons**: Farbige Icons (blau=Bild, rot=PDF) neben Dateinamen
|
|
|
|
### Downloads (`/admin/cms/downloads`)
|
|
- **Drei Kategorien**: Case Studies, Capabilities, Success Stories
|
|
- Kategoriefilter-Buttons
|
|
- Vollständige Bearbeitung: Titel, Unterkategorie, Typ-Label, Alt-Text, Icon, Beschreibung
|
|
- **Vorschaubild**: MediaPicker mit Bildvorschau
|
|
- **Sprachspezifische PDFs**: Separater PDF-Upload pro Sprache (DE/EN) mit Vorschau
|
|
- **Highlights-Editor** (Case Studies/Success Stories): Dynamische Kennzahl-Paare
|
|
- **Checkpoints-Editor** (Capabilities): Dynamische Checkpunkte
|
|
- Sortierung mit Pfeiltasten
|
|
- `toFrontendArray()` für nahtlose Frontend-Integration
|
|
|
|
### News-Band (`/admin/cms/news`)
|
|
- CRUD mit Icon (Heroicon-Select + Vorschau), Datum, Autor
|
|
- **Bild**: MediaPicker mit Vorschau in Liste und Formular
|
|
- **PDF**: MediaPicker mit eingebetteter PDF-Vorschau
|
|
- Rich-Text-Editor für Kurztext und Inhalt
|
|
- Sprachumschaltung
|
|
|
|
### Team (`/admin/cms/team`)
|
|
- CRUD für Teammitglieder (JSON in CmsContent)
|
|
- **Profilbild**: MediaPicker mit Vorschau (rund)
|
|
- Name, Position, Kürzel, LinkedIn-URL, Kurzvorstellung
|
|
- Profil-Text mit Rich-Text-Editor
|
|
|
|
### LinkedIn-Posts (`/admin/cms/linkedin`)
|
|
- CRUD mit **Bild über MediaPicker** (nicht mehr Text-Input)
|
|
- Titel, Autor, Datum, URL, Tags
|
|
- Rich-Text-Editor für Kurztext und Inhalt
|
|
- Bildvorschau in Liste und Formular
|
|
|
|
### Industries (`/admin/cms/industries`)
|
|
- CRUD mit Sortierung (Pfeiltasten + numerisches Order-Feld)
|
|
|
|
### FAQs (`/admin/cms/faqs`)
|
|
- CRUD nach Kategorien
|
|
- Rich-Text-Editor für Frage und Antwort
|
|
|
|
### Suchindex (`/admin/cms/search-index`)
|
|
- Zwei-Spalten-Layout: Liste links, Editor rechts
|
|
- Jeder Eintrag = eine Seite/Route (z.B. `home`, `leistungen`)
|
|
- **Keywords** können direkte Texte oder CMS-Keys (Dot-Notation) sein
|
|
- **Reindexieren**-Button löst `search:extract-keywords` Artisan-Befehl aus
|
|
- Vorschau zeigt aufgelöste Titel/Beschreibung/Keywords pro Sprache
|
|
- Sprachumschaltung DE/EN
|
|
|
|
---
|
|
|
|
## Content-Typen & Editor-Konfiguration
|
|
|
|
### Text-Felder
|
|
Standard-Editor mit `bold italic` Toolbar. Im Admin automatisch erkannt.
|
|
|
|
### HTML-Felder (Datenschutz, Impressum)
|
|
Voller Editor mit `heading | bold italic underline strike | bullet ordered blockquote | link`.
|
|
|
|
### Image-Felder
|
|
MediaPicker mit Vorschau. Speichert CmsMedia-Dateiname als Wert.
|
|
|
|
### JSON-Felder
|
|
Öffnen ein Modal mit strukturierter Bearbeitung:
|
|
- Erkennung ob String-Array oder Objekt-Array
|
|
- Icon-Felder → Searchable Heroicon-Select (nur Vorschau des gewählten Icons)
|
|
- Text-Felder (description, content, quote) → Rich-Text-Editor
|
|
- Verschachtelte JSON → Textarea
|
|
- Standard-Felder → Input
|
|
|
|
### :highlight Pattern
|
|
Für gradient-gestylte Textteile in Headings:
|
|
|
|
```php
|
|
// Template
|
|
{!! cms('welcome.solutions.heading', [
|
|
'highlight' => '<span class="text-gradient-premium">' . cms('welcome.solutions.heading_highlight') . '</span>',
|
|
]) !!}
|
|
```
|
|
|
|
---
|
|
|
|
## Medien-Integration im Frontend
|
|
|
|
### Bilder über CmsContent-Keys (dynamisch austauschbar)
|
|
|
|
```blade
|
|
<img src="{{ cms_media_url('welcome.hero.image') }}" />
|
|
<img src="{{ cms_media_url('welcome.hero.image', 'hero') }}" /> {{-- mit Conversion --}}
|
|
```
|
|
|
|
### Bilder über Dateiname (direkt)
|
|
|
|
```blade
|
|
<img src="{{ media_url('keyvisual.webp') }}" />
|
|
<img src="{{ media_url($profile['image']) }}" /> {{-- z.B. Team-Profil --}}
|
|
```
|
|
|
|
### Downloads (toFrontendArray)
|
|
|
|
```blade
|
|
@foreach (CmsDownload::published()->byCategory('case_study')->ordered()->get() as $dl)
|
|
<x-download-article-card :article="$dl->toFrontendArray()" :index="$loop->index" />
|
|
@endforeach
|
|
```
|
|
|
|
### News-Band (toFrontendArray)
|
|
|
|
```blade
|
|
@php
|
|
$newsItems = CmsNewsItem::published()->ordered()->get()
|
|
->map(fn ($item) => $item->toFrontendArray())
|
|
->toArray();
|
|
@endphp
|
|
```
|
|
|
|
Die `toFrontendArray()` Methoden lösen `media_url()` automatisch auf — Bilder und PDFs sind sofort verlinkt.
|
|
|
|
---
|
|
|
|
## Seeders
|
|
|
|
### Ausführungsreihenfolge
|
|
|
|
```php
|
|
$this->call([
|
|
CmsContentSeeder::class, // Hauptinhalte aus lang/ Dateien
|
|
CmsMediaSeeder::class, // Medien-Einträge + Image-Content
|
|
CmsNewsItemSeeder::class, // News-Band
|
|
CmsIndustrySeeder::class, // Industries
|
|
CmsFaqSeeder::class, // FAQs
|
|
CmsLinkedinPostSeeder::class, // LinkedIn-Posts
|
|
CmsDownloadSeeder::class, // Case Studies, Capabilities, Stories
|
|
]);
|
|
```
|
|
|
|
### Medien-Seeder
|
|
|
|
Der `CmsMediaSeeder` erfüllt zwei Aufgaben:
|
|
1. Erstellt `CmsMedia`-Einträge für alle hochgeladenen Dateien (Bilder + PDFs)
|
|
2. Erstellt `CmsContent`-Einträge vom Typ `image` (z.B. `welcome.hero.image` → `keyvisual-small.webp`)
|
|
|
|
### Download-Seeder
|
|
|
|
Enthält inline alle 12 Einträge (4 Case Studies, 5 Capabilities, 3 Success Stories) mit:
|
|
- Bilingualen Texten (DE/EN)
|
|
- Sprachspezifischen PDF-Dateinamen (DE/EN)
|
|
- Media-Dateinamen (statt alter Pfade)
|
|
- Highlights / Checkpoints
|
|
|
|
### Dateiname-Mapping
|
|
|
|
Die Seeder für News und LinkedIn mappen alte Pfade auf Media-Dateinamen:
|
|
|
|
```php
|
|
// Alt: '/assets/images/capability-global-player.jpg'
|
|
// Neu: 'capability-global-player.webp' (CmsMedia-Dateiname)
|
|
```
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
→ Siehe [SETUP.md](SETUP.md) für eine vollständige Schritt-für-Schritt-Anleitung. Für die Migration in ein bestehendes Projekt: [MIGRATION.md](MIGRATION.md).
|
|
|
|
### Kurzfassung
|
|
|
|
1. Package einbinden (`composer.json` Repository + require)
|
|
2. `composer update flux-cms/core`
|
|
3. `php artisan vendor:publish --tag=flux-cms-config`
|
|
4. `php artisan migrate`
|
|
5. Helper-Funktionen in `app/helpers.php` + `composer.json` autoload
|
|
6. Admin-Views aus `admin-reference/` kopieren
|
|
7. Seeders kopieren & ausführen
|
|
8. Routes registrieren
|
|
9. `intervention/image` installieren: `composer require intervention/image`
|
|
|
|
---
|
|
|
|
## Features-Übersicht
|
|
|
|
| Feature | Status | Beschreibung |
|
|
|---------|--------|-------------|
|
|
| Mehrsprachige Inhalte | ✅ | DE/EN, erweiterbar |
|
|
| Content-Editor (Text/HTML/Image) | ✅ | Flux Editor mit konfigurierbaren Toolbars + MediaPicker |
|
|
| JSON-Modal-Editor | ✅ | Strukturierte Bearbeitung von Arrays |
|
|
| Heroicon-Select | ✅ | Searchable mit Vorschau (performant) |
|
|
| **Medienbibliothek** | ✅ | Zentrale Bild/PDF-Verwaltung mit Grid+Listenansicht |
|
|
| **Bildoptimierung** | ✅ | Automatische Conversions (Resize/Format/Qualität) |
|
|
| **MediaPicker** | ✅ | Wiederverwendbares Modal für Medienauswahl |
|
|
| **PDF-Vorschau** | ✅ | Eingebettete PDF-Darstellung im Admin |
|
|
| **Downloads (erweitert)** | ✅ | Case Studies, Capabilities, Success Stories mit Highlights/Checkpoints |
|
|
| **Sprachspezifische PDFs** | ✅ | Separate DE/EN PDFs pro Download |
|
|
| News-Verwaltung | ✅ | CRUD mit MediaPicker für Bild + PDF |
|
|
| Team-Verwaltung | ✅ | CRUD mit MediaPicker für Profilbilder |
|
|
| LinkedIn-Posts | ✅ | CRUD mit MediaPicker für Bilder |
|
|
| Industries-Verwaltung | ✅ | CRUD mit Sortierung |
|
|
| FAQ-Verwaltung | ✅ | CRUD nach Kategorien |
|
|
| Toast-Benachrichtigungen | ✅ | Flux Toast bei allen Aktionen |
|
|
| Fallback auf lang/ | ✅ | cms() → __() wenn nicht in DB |
|
|
| Cache | ✅ | Pro Gruppe, auto-invalidiert |
|
|
| Seeder mit cleanHtml() | ✅ | Automatische HTML-Bereinigung |
|
|
| **Media-Seeder** | ✅ | Wiederherstellung aller Medien nach DB-Reset |
|
|
| **Suchindex** | ✅ | Keywords, Titel, Beschreibungen pro Route mit CMS-Key-Auflösung |
|
|
|
|
---
|
|
|
|
## Offene Punkte / Roadmap
|
|
|
|
- [ ] Drag & Drop Sortierung (Alternative zu Pfeilen)
|
|
- [ ] Versionierung von Content-Änderungen
|
|
- [ ] Rollen-basierter Zugriff auf CMS-Bereiche
|
|
- [ ] Import/Export von Inhalten
|
|
- [ ] Automatischer LinkedIn-API-Import
|
|
- [ ] Bildbearbeitung (Crop/Rotate) im Admin
|