Skip to content

Commit ae91940

Browse files
committed
implement comprehensive menu system with theme support
- Add Menu and MenuItem models with nested set functionality - Create MenuResource with drag-and-drop tree builder interface - Implement style-based menu architecture with configurable themes - Add theme system for components (tailwind default, extensible for Bootstrap) - Support linkable model integration with menu label interface │ - Add complete translation support (EN/NL) for menu system - Update PageController and LanguageSwitch to use theme-based templates - Organize all view components under theme directory structure - Add menu configuration with icons, styles, and linkable models
1 parent 93155e7 commit ae91940

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3028
-7
lines changed

.claude/settings.local.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(find:*)",
5+
"Bash(ls:*)"
6+
]
7+
},
8+
"enableAllProjectMcpServers": false
9+
}

CLAUDE.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This is a Laravel package that provides a CMS system with flexible content blocks for Filament. It extends the `statikbe/laravel-filament-flexible-content-blocks` package to create a complete page management system with routing, SEO, redirects, and tagging functionality.
8+
9+
## Development Commands
10+
11+
### Testing
12+
```bash
13+
# Run tests with Pest
14+
composer test
15+
# Run tests with coverage
16+
composer test-coverage
17+
```
18+
19+
### Code Quality
20+
```bash
21+
# Run PHPStan static analysis
22+
composer analyse
23+
# Format code with Laravel Pint
24+
composer format
25+
```
26+
27+
### Package Setup
28+
```bash
29+
# Prepare/discover package after composer changes
30+
composer prepare
31+
```
32+
33+
### Seeding
34+
```bash
35+
# Seed default pages and settings
36+
php artisan flexible-content-block-pages:seed
37+
```
38+
39+
## Architecture Overview
40+
41+
### Core Models
42+
- **Page** (`src/Models/Page.php`): Main content model with flexible content blocks, multilingual support, SEO fields, and hierarchical structure (parent/child relationships up to 3 levels deep)
43+
- **Settings** (`src/Models/Settings.php`): Global CMS settings and configuration
44+
- **Redirect** (`src/Models/Redirect.php`): URL redirect management
45+
- **Tag/TagType** (`src/Models/Tag.php`, `src/Models/TagType.php`): Content tagging system
46+
- **Menu/MenuItem** (`src/Models/Menu.php`, `src/Models/MenuItem.php`): Hierarchical menu system with nested structure using kalnoy/nestedset
47+
48+
### Key Components
49+
- **Filament Resources**: Located in `src/Resources/` - provide admin interface for all models
50+
- **Route Helpers**: `src/Routes/` handles URL generation for pages, including localized URLs via `LocalisedPageRouteHelper`
51+
- **Page Controller**: `src/Http/Controllers/PageController.php` handles frontend page rendering with SEO optimization
52+
- **Flexible Content Blocks**: Integrates with the parent package for flexible content building
53+
54+
### Configuration
55+
- Main config: `config/filament-flexible-content-block-pages.php`
56+
- Key settings: models, table names, resources, panel configuration, SEO defaults, route helper selection
57+
- Template overrides can be configured via `page_templates` array
58+
59+
### Content Block System
60+
Pages use the flexible content blocks system from the parent package, allowing:
61+
- Rich content building with various block types
62+
- Multilingual content support
63+
- Hero images and overview fields
64+
- SEO meta fields and social media optimization
65+
66+
### Routing Architecture
67+
- Three-level hierarchical pages: grandparent → parent → child
68+
- Localized routing support via `mcamara/laravel-localization`
69+
- Custom route helpers for different URL patterns
70+
- Frontend routes registered via `FilamentFlexibleContentBlockPages::routes()`
71+
72+
### Caching Strategy
73+
- SEO image dimensions cached for 8 hours (`PageController::CACHE_SEO_IMAGE_TTL`)
74+
- Taggable cache implementation in `src/Cache/TaggableCache.php`
75+
76+
### Key Dependencies
77+
- Laravel Filament for admin interface
78+
- Spatie packages for tags, media library, and redirects
79+
- Laravel Localization for multilingual support
80+
- SEOTools for meta tag and OpenGraph management
81+
- kalnoy/nestedset for hierarchical menu structure
82+
83+
## Menu Builder System (In Development)
84+
85+
### Current Status
86+
The menu builder is partially implemented with the following components:
87+
88+
**✅ Completed:**
89+
- Menu and MenuItem models with kalnoy/nestedset integration
90+
- Database migrations for menus and menu_items tables
91+
- MenuResource with basic CRUD operations
92+
- ManageMenuItems page with drag-and-drop tree interface
93+
- Alpine.js + SortableJS powered tree builder component
94+
- Translation support (EN/NL)
95+
- Configuration system with max depth settings
96+
97+
**🚧 Remaining Tasks:**
98+
- MenuItem form/modal for adding and editing menu items
99+
- Linkable model integration (following call-to-action patterns)
100+
- Frontend helper methods and blade components for menu rendering
101+
- Validation and error handling
102+
- Proper nested set operations for reordering
103+
104+
### Architecture
105+
- **Menu Model**: Simple container with name, code, and description
106+
- **MenuItem Model**: Nested set structure with linkable polymorphic relationships
107+
- **ManageMenuItems Page**: Dedicated interface for menu structure management
108+
- **Tree Builder Component**: Custom Filament field with Alpine.js interactions
109+
110+
### Configuration
111+
```php
112+
'menu' => [
113+
'max_depth' => 2, // Configurable nesting level
114+
],
115+
```
116+
117+
## Common Development Patterns
118+
119+
When extending this package:
120+
1. Models extend the flexible content blocks contracts and traits
121+
2. Resources follow Filament patterns with translatable support
122+
3. Use the facade `FilamentFlexibleContentBlockPages` to access configuration
123+
4. SEO handling follows a fallback pattern: page SEO → hero image → default settings
124+
5. Route generation uses the configured route helper class
125+
6. Menu items follow the linkable pattern for polymorphic relationships

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"filament/spatie-laravel-tags-plugin": "^3.2",
2222
"guava/filament-icon-picker": "^2.0",
2323
"illuminate/contracts": "^10.0||^11.0||^12.0",
24+
"kalnoy/nestedset": "^6.0",
2425
"mcamara/laravel-localization": "^2.3",
2526
"spatie/laravel-missing-page-redirector": "^2.11",
2627
"spatie/laravel-package-tools": "^1.16",

config/filament-flexible-content-block-pages.php

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@
55
use Filament\Http\Middleware\AuthenticateSession;
66
use Filament\Http\Middleware\DisableBladeIconComponents;
77
use Filament\Http\Middleware\DispatchServingFilamentEvent;
8-
use Filament\Navigation\NavigationItem;
98
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
109
use Illuminate\Cookie\Middleware\EncryptCookies;
1110
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
1211
use Illuminate\Routing\Middleware\SubstituteBindings;
1312
use Illuminate\Session\Middleware\StartSession;
1413
use Illuminate\View\Middleware\ShareErrorsFromSession;
1514
use Statikbe\FilamentFlexibleContentBlockPages\FilamentFlexibleContentBlockPagesConfig;
16-
use Statikbe\FilamentFlexibleContentBlockPages\Models\Page;
1715

1816
return [
1917
'models' => [
@@ -22,6 +20,8 @@
2220
FilamentFlexibleContentBlockPagesConfig::TYPE_SETTINGS => \Statikbe\FilamentFlexibleContentBlockPages\Models\Settings::class,
2321
FilamentFlexibleContentBlockPagesConfig::TYPE_TAG => \Statikbe\FilamentFlexibleContentBlockPages\Models\Tag::class,
2422
FilamentFlexibleContentBlockPagesConfig::TYPE_TAG_TYPE => \Statikbe\FilamentFlexibleContentBlockPages\Models\TagType::class,
23+
FilamentFlexibleContentBlockPagesConfig::TYPE_MENU => \Statikbe\FilamentFlexibleContentBlockPages\Models\Menu::class,
24+
FilamentFlexibleContentBlockPagesConfig::TYPE_MENU_ITEM => \Statikbe\FilamentFlexibleContentBlockPages\Models\MenuItem::class,
2525
],
2626

2727
'table_names' => [
@@ -32,6 +32,8 @@
3232
FilamentFlexibleContentBlockPagesConfig::TYPE_TAG => 'tags',
3333
FilamentFlexibleContentBlockPagesConfig::TYPE_TAGGABLE => 'taggables',
3434
FilamentFlexibleContentBlockPagesConfig::TYPE_TAG_TYPE => 'tag_types',
35+
FilamentFlexibleContentBlockPagesConfig::TYPE_MENU => 'menus',
36+
FilamentFlexibleContentBlockPagesConfig::TYPE_MENU_ITEM => 'menu_items',
3537
],
3638

3739
'resources' => [
@@ -40,6 +42,7 @@
4042
FilamentFlexibleContentBlockPagesConfig::TYPE_REDIRECT => \Statikbe\FilamentFlexibleContentBlockPages\Resources\RedirectResource::class,
4143
FilamentFlexibleContentBlockPagesConfig::TYPE_TAG => \Statikbe\FilamentFlexibleContentBlockPages\Resources\TagResource::class,
4244
FilamentFlexibleContentBlockPagesConfig::TYPE_TAG_TYPE => \Statikbe\FilamentFlexibleContentBlockPages\Resources\TagTypeResource::class,
45+
FilamentFlexibleContentBlockPagesConfig::TYPE_MENU => \Statikbe\FilamentFlexibleContentBlockPages\Resources\MenuResource::class,
4346
],
4447

4548
'panel' => [
@@ -81,4 +84,51 @@
8184
'page_templates' => [
8285
// Page::HOME_PAGE => 'pages.home',
8386
],
87+
88+
'menu' => [
89+
/*
90+
|--------------------------------------------------------------------------
91+
| Menu Theme
92+
|--------------------------------------------------------------------------
93+
|
94+
| It is possible to create different themes for the menu templates.
95+
| Creating a new theme is done by publishing the views and then creating
96+
| a new directory under resources/views/components/{theme}/menu.
97+
| You should then specify the name of your theme below.
98+
|
99+
*/
100+
'theme' => 'tailwind',
101+
102+
'max_depth' => 2,
103+
'linkable_models' => [
104+
// Models that can be linked in menu items
105+
// These models must implement HasMenuLabel interface
106+
\Statikbe\FilamentFlexibleContentBlockPages\Models\Page::class,
107+
108+
// Add your own models here:
109+
// \App\Models\Category::class,
110+
// \App\Models\Product::class,
111+
],
112+
'model_icons' => [
113+
// Configure icons for different model types based on their morph class
114+
'filament-flexible-content-block-pages::page' => 'heroicon-o-document-text',
115+
116+
// Add custom icons for your models:
117+
// 'category' => 'heroicon-o-tag',
118+
// 'product' => 'heroicon-o-shopping-bag',
119+
// 'post' => 'heroicon-o-newspaper',
120+
],
121+
'styles' => [
122+
// Available menu styles (codes only - labels come from translations)
123+
'default',
124+
'horizontal',
125+
'vertical',
126+
'dropdown',
127+
128+
// Add your custom styles here:
129+
// 'mega',
130+
// 'mobile',
131+
// 'breadcrumb',
132+
],
133+
],
84134
];
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
use Kalnoy\Nestedset\NestedSet;
7+
use Statikbe\FilamentFlexibleContentBlockPages\Facades\FilamentFlexibleContentBlockPages;
8+
9+
return new class extends Migration
10+
{
11+
public function up()
12+
{
13+
Schema::create(FilamentFlexibleContentBlockPages::config()->getMenuItemsTable(), function (Blueprint $table) {
14+
$table->id();
15+
$table->foreignId('menu_id')->constrained(FilamentFlexibleContentBlockPages::config()->getMenusTable())->cascadeOnDelete();
16+
17+
// Translatable label
18+
$table->json('label');
19+
20+
// Link options
21+
$table->string('url')->nullable();
22+
$table->string('linkable_type')->nullable();
23+
$table->unsignedBigInteger('linkable_id')->nullable();
24+
25+
// Additional options
26+
$table->string('target')->default('_self');
27+
$table->string('icon')->nullable();
28+
$table->boolean('is_visible')->default(true);
29+
$table->boolean('use_model_title')->default(false);
30+
31+
// Nested set structure
32+
NestedSet::columns($table);
33+
34+
$table->timestamps();
35+
36+
// Indexes
37+
$table->index(['linkable_type', 'linkable_id']);
38+
});
39+
}
40+
41+
public function down()
42+
{
43+
Schema::dropIfExists(FilamentFlexibleContentBlockPages::config()->getMenuItemsTable());
44+
}
45+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
use Statikbe\FilamentFlexibleContentBlockPages\Facades\FilamentFlexibleContentBlockPages;
7+
8+
return new class extends Migration
9+
{
10+
public function up()
11+
{
12+
Schema::create(FilamentFlexibleContentBlockPages::config()->getMenusTable(), function (Blueprint $table) {
13+
$table->id();
14+
$table->string('name');
15+
$table->string('code')->unique();
16+
$table->text('description')->nullable();
17+
$table->string('style')->default('default');
18+
$table->timestamps();
19+
20+
// Index for code lookups
21+
$table->index('code');
22+
});
23+
}
24+
25+
public function down()
26+
{
27+
Schema::dropIfExists(FilamentFlexibleContentBlockPages::config()->getMenusTable());
28+
}
29+
};

0 commit comments

Comments
 (0)