is_array($v) ? json_encode($v, JSON_UNESCAPED_UNICODE) : (string) $v; if ($isList && ! is_array($value[0])) { return [true, array_map(fn ($v) => ['_value' => $stringify($v)], $value)]; } if ($isList) { return [false, array_map(fn ($item) => is_array($item) ? array_map($stringify, $item) : ['_value' => (string) $item], $value)]; } return [false, [array_map($stringify, $value)]]; } } if (! function_exists('_cmsFieldLooksLikeImage')) { function _cmsFieldLooksLikeImage(string $fieldKey, mixed $fieldValue): bool { if (! is_string($fieldValue) || trim($fieldValue) === '') { return false; } $key = strtolower($fieldKey); if (in_array($key, ['image', 'photo', 'avatar', 'picture', 'thumbnail', 'img', 'hero_image', 'background_image', 'cover_image'], true)) { return true; } if (preg_match('/_(image|photo|avatar|picture|thumb)$/i', $fieldKey)) { return true; } return (bool) preg_match('/\.(jpe?g|png|gif|webp|svg)$/i', $fieldValue); } } layout('components.layouts.app'); title('CMS Inhalte'); state([ 'selectedGroup' => null, 'search' => '', 'editingId' => null, 'editingField' => null, 'editLocale' => 'de', 'editValue' => '', 'editMediaId' => null, 'showJsonModal' => false, 'jsonItems' => [], 'jsonIsStringArray' => false, 'jsonEditingKey' => '', 'editingFieldType' => 'text', ]); on(['media-selected' => function (string $field, ?int $mediaId, ?string $url) { if ($field === 'content_image') { $media = $mediaId ? CmsMedia::find($mediaId) : null; if ($media) { $this->editValue = $media->filename; $this->editMediaId = $mediaId; } else { $this->editValue = ''; $this->editMediaId = null; } return; } if (str_starts_with($field, 'jsonimg:')) { $parts = explode(':', $field, 3); if (count($parts) === 3 && $mediaId) { $media = CmsMedia::find($mediaId); if ($media) { $idx = (int) $parts[1]; $fname = $parts[2]; if (isset($this->jsonItems[$idx]) && is_array($this->jsonItems[$idx])) { $this->jsonItems[$idx][$fname] = $media->filename; } } } return; } }]); $groups = computed(fn () => CmsContent::query() ->selectRaw('`group`, count(*) as count') ->groupBy('group') ->orderBy('group') ->pluck('count', 'group') ->toArray()); $flatContents = computed(function () { if (! $this->selectedGroup) { return collect(); } $contents = CmsContent::forGroup($this->selectedGroup) ->orderBy('order') ->get(); $rows = []; foreach ($contents as $content) { $value = $content->getTranslation('value', $this->editLocale); if ($content->type === 'json' && is_array($value) && ! array_is_list($value)) { foreach ($value as $fieldKey => $fieldValue) { if ($this->search && ! str_contains(strtolower($content->key . '.' . $fieldKey), strtolower($this->search))) { continue; } $fieldType = 'text'; if ($this->selectedGroup === 'legal' && $fieldKey === 'content') { $fieldType = 'legal_html'; } elseif (is_array($fieldValue)) { $fieldType = 'json'; } elseif (is_string($fieldValue) && preg_match('/<[^>]+>/', $fieldValue)) { $fieldType = 'html'; } elseif (_cmsFieldLooksLikeImage($fieldKey, $fieldValue)) { $fieldType = 'image'; } $rows[] = (object) [ 'content_id' => $content->id, 'section_key' => $content->key, 'field_key' => $fieldKey, 'display_key' => $content->key . '.' . $fieldKey, 'type' => $fieldType, 'value' => $fieldValue, 'is_subfield' => true, ]; } } else { if ($this->search && ! str_contains(strtolower($content->key), strtolower($this->search))) { continue; } $rows[] = (object) [ 'content_id' => $content->id, 'section_key' => $content->key, 'field_key' => null, 'display_key' => $content->key, 'type' => $content->type ?? 'text', 'value' => $value, 'is_subfield' => false, ]; } } return collect($rows); }); $availableIcons = computed(fn () => HeroiconOutlineList::names()); $selectGroup = function (string $group) { $this->showJsonModal = false; $this->jsonItems = []; $this->jsonIsStringArray = false; $this->jsonEditingKey = ''; $this->editingId = null; $this->editingField = null; $this->editValue = ''; $this->editMediaId = null; $this->editingFieldType = 'text'; $this->selectedGroup = $group; }; $startFieldEdit = function (int $contentId, ?string $fieldKey = null) { $content = CmsContent::find($contentId); if (! $content) { return; } $fullValue = $content->getTranslation('value', $this->editLocale); if ($fieldKey !== null && is_array($fullValue)) { $fieldValue = $fullValue[$fieldKey] ?? ''; if (is_array($fieldValue)) { $this->editingId = $contentId; $this->editingField = $fieldKey; $this->editingFieldType = 'text'; $this->jsonEditingKey = $content->key . '.' . $fieldKey; $isList = array_is_list($fieldValue); if ($isList) { [$this->jsonIsStringArray, $this->jsonItems] = _cmsParseJsonItems($fieldValue); } else { $this->jsonIsStringArray = false; $this->jsonItems = [array_map( fn ($v) => is_array($v) ? json_encode($v, JSON_UNESCAPED_UNICODE) : (string) $v, $fieldValue, )]; } $this->jsonItems = CmsFluxEditorHtmlTransformer::toEditorJsonItems($this->jsonItems, $this->jsonIsStringArray); $this->showJsonModal = true; return; } $this->editingId = $contentId; $this->editingField = $fieldKey; $this->editValue = (string) $fieldValue; if (_cmsFieldLooksLikeImage($fieldKey, $fieldValue)) { $this->editingFieldType = 'image'; $this->editMediaId = CmsMedia::where('filename', $this->editValue)->first()?->id; } elseif ($content->group === 'legal' && $fieldKey === 'content') { $this->editingFieldType = 'legal_html'; $this->editMediaId = null; } else { $this->editingFieldType = is_string($fieldValue) && preg_match('/<[^>]+>/', $fieldValue) ? 'html' : 'text'; $this->editMediaId = null; } if ($this->editingFieldType === 'html') { $this->editValue = CmsFluxEditorHtmlTransformer::toEditor($this->editValue); } } else { $this->editingId = $contentId; $this->editingField = null; if ($content->type === 'json') { $this->jsonEditingKey = $content->key; if (is_array($fullValue)) { [$this->jsonIsStringArray, $this->jsonItems] = _cmsParseJsonItems($fullValue); $this->jsonItems = CmsFluxEditorHtmlTransformer::toEditorJsonItems($this->jsonItems, $this->jsonIsStringArray); } else { $this->jsonIsStringArray = false; $this->jsonItems = []; } $this->showJsonModal = true; return; } $this->editValue = is_array($fullValue) ? json_encode($fullValue, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) : ((string) ($fullValue ?? '')); if ($content->type === 'image') { $this->editingFieldType = 'image'; $this->editMediaId = CmsMedia::where('filename', $this->editValue)->first()?->id; } elseif ($content->type === 'html') { $this->editingFieldType = 'html'; $this->editMediaId = null; $this->editValue = CmsFluxEditorHtmlTransformer::toEditor($this->editValue); } else { $this->editingFieldType = 'text'; $this->editMediaId = null; } } }; $switchLocale = function (string $locale) { $this->editLocale = $locale; if ($this->editingId && $this->showJsonModal) { $content = CmsContent::find($this->editingId); if (! $content) { return; } $fullValue = $content->getTranslation('value', $locale); if ($this->editingField !== null && is_array($fullValue)) { $fieldValue = $fullValue[$this->editingField] ?? []; if (is_array($fieldValue)) { [$this->jsonIsStringArray, $this->jsonItems] = _cmsParseJsonItems($fieldValue); $this->jsonItems = CmsFluxEditorHtmlTransformer::toEditorJsonItems($this->jsonItems, $this->jsonIsStringArray); } } elseif (is_array($fullValue)) { [$this->jsonIsStringArray, $this->jsonItems] = _cmsParseJsonItems($fullValue); $this->jsonItems = CmsFluxEditorHtmlTransformer::toEditorJsonItems($this->jsonItems, $this->jsonIsStringArray); } } elseif ($this->editingId) { $content = CmsContent::find($this->editingId); if (! $content) { return; } $fullValue = $content->getTranslation('value', $locale); if ($this->editingField !== null && is_array($fullValue)) { $fieldValue = $fullValue[$this->editingField] ?? ''; $this->editValue = is_array($fieldValue) ? json_encode($fieldValue, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) : (string) $fieldValue; if (! is_array($fieldValue)) { if (_cmsFieldLooksLikeImage((string) $this->editingField, $fieldValue)) { $this->editingFieldType = 'image'; $this->editMediaId = CmsMedia::where('filename', $this->editValue)->first()?->id; } elseif ($content->group === 'legal' && $this->editingField === 'content') { $this->editingFieldType = 'legal_html'; $this->editMediaId = null; } else { $this->editingFieldType = is_string($fieldValue) && preg_match('/<[^>]+>/', $fieldValue) ? 'html' : 'text'; $this->editMediaId = null; } if ($this->editingFieldType === 'html') { $this->editValue = CmsFluxEditorHtmlTransformer::toEditor($this->editValue); } } } else { $this->editValue = is_array($fullValue) ? json_encode($fullValue, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) : (string) ($fullValue ?? ''); if ($content->type === 'image') { $this->editingFieldType = 'image'; $this->editMediaId = CmsMedia::where('filename', $this->editValue)->first()?->id; } elseif ($content->type === 'html') { $this->editingFieldType = 'html'; $this->editMediaId = null; $this->editValue = CmsFluxEditorHtmlTransformer::toEditor($this->editValue); } else { $this->editingFieldType = 'text'; $this->editMediaId = null; } } } }; $saveEdit = function () { $content = CmsContent::find($this->editingId); if (! $content) { return; } $valueToSave = $this->editValue; if ($this->editingFieldType === 'html') { $valueToSave = CmsFluxEditorHtmlTransformer::fromEditor($valueToSave); } if ($this->editingField !== null) { $fullValue = $content->getTranslation('value', $this->editLocale); if (! is_array($fullValue)) { $fullValue = []; } $fullValue[$this->editingField] = $valueToSave; $content->setTranslation('value', $this->editLocale, $fullValue); } else { $content->setTranslation('value', $this->editLocale, $valueToSave); } $content->save(); app(CmsContentService::class)->clearCache($this->selectedGroup); $this->editingId = null; $this->editingField = null; $this->editValue = ''; $this->editingFieldType = 'text'; $this->editMediaId = null; Flux::toast(variant: 'success', heading: 'Gespeichert', text: 'Inhalt wurde erfolgreich aktualisiert.'); }; $addJsonItem = function () { if ($this->jsonIsStringArray) { $this->jsonItems[] = ['_value' => '']; } elseif (! empty($this->jsonItems)) { $template = array_map(fn () => '', $this->jsonItems[0]); $this->jsonItems[] = $template; } }; $removeJsonItem = function (int $index) { unset($this->jsonItems[$index]); $this->jsonItems = array_values($this->jsonItems); }; $saveJsonModal = function () { $content = CmsContent::find($this->editingId); if (! $content) { return; } $itemsForSave = CmsFluxEditorHtmlTransformer::fromEditorJsonItems($this->jsonItems, $this->jsonIsStringArray); if ($this->jsonIsStringArray) { $newValue = array_values(array_map(fn ($item) => $item['_value'] ?? '', $itemsForSave)); } else { $newValue = array_values( array_map(function ($item) { $cleaned = []; foreach ($item as $k => $v) { if (is_string($v) && (str_starts_with($v, '[') || str_starts_with($v, '{'))) { $decoded = json_decode($v, true); $cleaned[$k] = json_last_error() === JSON_ERROR_NONE ? $decoded : $v; } else { $cleaned[$k] = $v; } } return $cleaned; }, $itemsForSave), ); } if ($this->editingField !== null) { $fullValue = $content->getTranslation('value', $this->editLocale); if (! is_array($fullValue)) { $fullValue = []; } $fullValue[$this->editingField] = $newValue; $content->setTranslation('value', $this->editLocale, $fullValue); } else { $content->setTranslation('value', $this->editLocale, $newValue); } $content->save(); app(CmsContentService::class)->clearCache($this->selectedGroup); $this->showJsonModal = false; $this->editingId = null; $this->editingField = null; $this->jsonItems = []; Flux::toast(variant: 'success', heading: 'Gespeichert', text: 'Inhalt wurde erfolgreich aktualisiert.'); }; $cancelEdit = function () { $this->editingId = null; $this->editingField = null; $this->editValue = ''; $this->editingFieldType = 'text'; $this->editMediaId = null; }; $cancelJsonModal = function () { $this->showJsonModal = false; $this->editingId = null; $this->editingField = null; $this->jsonItems = []; }; ?> @php $cmsGroupLabels = [ 'legal' => 'Rechtliches', ]; @endphp
{{ $row->field_key ?? $row->section_key }}
@php
$typeColors = ['html' => 'amber', 'legal_html' => 'blue', 'image' => 'green', 'json' => 'violet', 'link' => 'rose'];
$badgeColor = $typeColors[$row->type] ?? 'zinc';
@endphp
{{ \Illuminate\Support\Str::limit(strip_tags((string) $row->value), 200) }}
@elseif ($row->type === 'html'){{ \Illuminate\Support\Str::limit(strip_tags(is_array($row->value) ? json_encode($row->value, JSON_UNESCAPED_UNICODE) : (string) ($row->value ?? '')), 120) }}
@endif @endif