Seiten-Sitemap mit Vorschaubild-Verwaltung im CRM ergänzen.
Der Nested-Set-Baum zeigt box_image_url, box_body und Reiseprogramm-Bilder inklusive Bearbeitung per Modal und Mediathek, damit fehlende Kachelbilder schneller gefunden und korrigiert werden können. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
6df9c401af
commit
c39d86f80b
6 changed files with 1305 additions and 136 deletions
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Page;
|
||||
use App\Services\NavigationTreeService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use IqContent\LaravelFilemanager\Lfm;
|
||||
|
||||
class NavigationTreeController extends Controller
|
||||
{
|
||||
|
|
@ -22,7 +24,9 @@ class NavigationTreeController extends Controller
|
|||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('navigation.index');
|
||||
return view('navigation.index', [
|
||||
'lfm_helper' => app(Lfm::class),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -34,7 +38,25 @@ class NavigationTreeController extends Controller
|
|||
public function getData(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
$includeHidden = $request->get('include_hidden', true);
|
||||
$mode = $request->get('mode', 'sitemap');
|
||||
$includeHidden = $request->get('include_hidden', false);
|
||||
$onlyActive = !$includeHidden;
|
||||
|
||||
if ($mode === 'sitemap') {
|
||||
$tree = $this->navigationService->getSitemapTree($onlyActive);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'data' => $tree,
|
||||
'meta' => [
|
||||
'total_nodes' => $this->navigationService->countNodes($tree),
|
||||
'missing_preview_images' => $this->navigationService->countMissingPreviewImages($tree),
|
||||
'include_hidden' => $includeHidden,
|
||||
'structure' => 'sitemap',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$tree = $this->navigationService->getFrontendNavigationTree($includeHidden);
|
||||
|
||||
return response()->json([
|
||||
|
|
@ -43,8 +65,8 @@ class NavigationTreeController extends Controller
|
|||
'meta' => [
|
||||
'total_nodes' => $this->navigationService->countNodes($tree),
|
||||
'include_hidden' => $includeHidden,
|
||||
'structure' => 'frontend'
|
||||
]
|
||||
'structure' => 'header',
|
||||
],
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
|
|
@ -98,10 +120,17 @@ class NavigationTreeController extends Controller
|
|||
public function export(Request $request)
|
||||
{
|
||||
try {
|
||||
$includeHidden = $request->get('include_hidden', true);
|
||||
$tree = $this->navigationService->getFrontendNavigationTree($includeHidden);
|
||||
$mode = $request->get('mode', 'sitemap');
|
||||
$includeHidden = $request->get('include_hidden', false);
|
||||
$onlyActive = !$includeHidden;
|
||||
|
||||
$filename = 'navigation-tree-frontend-' . date('Y-m-d-His') . '.json';
|
||||
if ($mode === 'sitemap') {
|
||||
$tree = $this->navigationService->getSitemapTree($onlyActive);
|
||||
$filename = 'sitemap-tree-' . date('Y-m-d-His') . '.json';
|
||||
} else {
|
||||
$tree = $this->navigationService->getFrontendNavigationTree($includeHidden);
|
||||
$filename = 'navigation-tree-frontend-' . date('Y-m-d-His') . '.json';
|
||||
}
|
||||
$json = json_encode($tree, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
return response($json)
|
||||
|
|
@ -117,12 +146,21 @@ class NavigationTreeController extends Controller
|
|||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function clearCache()
|
||||
public function clearCache(Request $request)
|
||||
{
|
||||
try {
|
||||
$this->navigationService->clearCache();
|
||||
|
||||
if ($request->expectsJson() || $request->ajax()) {
|
||||
return response()->json(['success' => true]);
|
||||
}
|
||||
|
||||
return back()->with('success', 'Navigation-Cache erfolgreich gelöscht');
|
||||
} catch (\Exception $e) {
|
||||
if ($request->expectsJson() || $request->ajax()) {
|
||||
return response()->json(['success' => false, 'error' => $e->getMessage()], 500);
|
||||
}
|
||||
|
||||
return back()->with('error', 'Cache-Löschung fehlgeschlagen: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
|
@ -149,6 +187,9 @@ class NavigationTreeController extends Controller
|
|||
'travel_programs' => count(array_filter($flatList, fn($n) => $n['is_travel_program'])),
|
||||
'fewo_lodgings' => count(array_filter($flatList, fn($n) => $n['is_fewo_lodging'])),
|
||||
'country_pages' => count(array_filter($flatList, fn($n) => $n['is_country_page'])),
|
||||
'missing_preview_images' => $this->navigationService->countMissingPreviewImages(
|
||||
$this->navigationService->getSitemapTree(false)
|
||||
),
|
||||
];
|
||||
|
||||
return response()->json([
|
||||
|
|
@ -162,4 +203,76 @@ class NavigationTreeController extends Controller
|
|||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt oder löscht box_image_url einer Seite.
|
||||
*/
|
||||
public function updateBoxImage(Request $request, int $id): JsonResponse
|
||||
{
|
||||
try {
|
||||
$page = Page::findOrFail($id);
|
||||
$action = $request->input('action');
|
||||
|
||||
if ($action === 'clear') {
|
||||
if (empty($page->box_image_url)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Für diese Seite ist kein verknüpftes Seitenbild (box_image_url) hinterlegt.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
if (!$this->navigationService->pageCanClearBoxImage($page)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Das Seitenbild kann hier nicht entfernt werden, weil kein Reiseprogramm-Bild als Ersatz vorhanden ist.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$page->box_image_url = null;
|
||||
$page->save();
|
||||
} elseif ($action === 'clear_box_body') {
|
||||
if (!$this->navigationService->pageHasBoxBodyPreview($page)) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Für diese Seite ist kein Legacy-Bild (box_body) hinterlegt.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$page->box_body = null;
|
||||
$page->save();
|
||||
} elseif ($action === 'set') {
|
||||
$url = trim((string) $request->input('box_image_url', ''));
|
||||
if ($url === '') {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Bitte wählen Sie zuerst ein Bild aus der Mediathek.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$page->box_image_url = $url;
|
||||
$page->save();
|
||||
} else {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => 'Ungültige Aktion.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$this->navigationService->clearCache();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => match ($action) {
|
||||
'clear' => 'Das verknüpfte Seitenbild wurde entfernt.',
|
||||
'clear_box_body' => 'Das Legacy-Bild (box_body) wurde entfernt.',
|
||||
default => 'Das neue Seitenbild wurde gespeichert.',
|
||||
},
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'error' => $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue