Skip to content

Commit 4346147

Browse files
committed
Implement SEO tag pages
1 parent e5d324c commit 4346147

17 files changed

+724
-160
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ The style can also be configured in the database model, then you can skip the `s
247247

248248
See the [menu seeding documentation](documentation/seeders.md) for programmatic menu creation.
249249

250+
## Settings
251+
252+
TODO how to add settings in model and resource
253+
250254
## Redirects
251255

252256
The package includes automatic redirect management: when the slug of a page changes, a redirect from the old page
@@ -360,7 +364,8 @@ If you do not want your model in menus or call-to-actions, you can extend the [S
360364

361365
### Extending the SitemapGeneratorService
362366

363-
For full customization power, you can create your own sitemap generator service by extending the base class:
367+
For full customization power, you can create your own sitemap generator service by extending the base class or completely
368+
implementing a new service by implementing [GeneratesSitemap](src/Services/Contracts/GeneratesSitemap.php):
364369

365370
```php
366371
<?php
@@ -433,7 +438,6 @@ check:
433438
menu:
434439
- caching tree model + observer to clear cache
435440
- Menu titels menu items
436-
- Ben: add menu to default page template
437441
- test global search and improve table search and ordering
438442

439443
page:
@@ -445,7 +449,6 @@ release:
445449
- policies:
446450
- note: undeletable pages
447451
- undeletable page toggle only for permission holder
448-
- redirect controller
449452
- tag controller
450453
- documentation
451454
- Kristof: screenshots + banner + packagist + slack + filament plugin store

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

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,53 @@
153153
'navigation_sort' => 5,
154154
],
155155

156+
/*
157+
|--------------------------------------------------------------------------
158+
| Tag Pages Configuration
159+
|--------------------------------------------------------------------------
160+
|
161+
| Configure how tag pages work, including which models are included
162+
| and pagination settings.
163+
*/
164+
'tag_pages' => [
165+
'models' => [
166+
/*
167+
| Which model classes should be included in tag pages.
168+
| These models must use the HasTags trait from spatie/laravel-tags.
169+
*/
170+
'enabled' => [
171+
\Statikbe\FilamentFlexibleContentBlockPages\Models\Page::class,
172+
// Add your own taggable models here:
173+
// \App\Models\Article::class,
174+
// \App\Models\Product::class,
175+
],
176+
177+
/*
178+
| Whether to group similar content types together in display.
179+
| If true, all pages will be shown before all articles, etc.
180+
| If false, content will be mixed by publication date.
181+
*/
182+
'group_by_type' => false,
183+
],
184+
/*
185+
| The prefix of the route for tag pages. The format is:
186+
| /{route_path_prefix}/{tag:slug}
187+
*/
188+
'route_path_prefix' => 'tag',
189+
'pagination' => [
190+
/*
191+
| Number of items per page for tag listings.
192+
*/
193+
'item_count' => 20,
194+
195+
/*
196+
| Show count of each content type in tag page title/description.
197+
| Example: "Laravel (5 pages, 12 articles)"
198+
*/
199+
'show_type_counts' => true,
200+
],
201+
],
202+
156203
'tags' => [
157204
'navigation_sort' => 20,
158205
],
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Extending and customisation
2+
3+
In this document, we will explain how you can change behaviour or extend functionalities to match your project requirements.
4+
5+
6+
## Routes
7+
8+
TODO explain route helpers
9+
TODO explain how to use your own (extended) controllers
10+
11+
## SEO tag pages
12+
13+
TODO explain how to extend the views & controller

resources/lang/en/filament-flexible-content-block-pages.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@
4545
'translatable_field_hint' => 'This field can be translated. You can view/change the current language in the top right.',
4646
'settings_footer_copyright' => 'Copyright message in footer',
4747
],
48+
'tag_pages' => [
49+
'no_content' => 'No published content is tagged with ":tag" at this time.',
50+
'meta_description_no_content' => 'Browse content tagged with :tag.',
51+
'meta_description_with_content' => 'Browse :count items tagged with :tag.',
52+
],
4853
'form_component' => [
4954
'name_lbl' => 'Name',
5055
'colour_lbl' => 'Color',

resources/lang/nl/filament-flexible-content-block-pages.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@
4444
'translatable_field_hint' => 'Dit veld kan vertaald worden. De huidige taal kan je rechtsbovenaan bekijken/aanpassen.',
4545
'settings_footer_copyright' => 'Copyrightboodschap in footer',
4646
],
47+
'tag_pages' => [
48+
'no_content' => 'Er is momenteel geen gepubliceerde inhoud getagd met ":tag".',
49+
'meta_description_no_content' => 'Bekijk inhoud getagd met :tag.',
50+
'meta_description_with_content' => 'Bekijk :count items getagd met :tag.',
51+
],
4752
'form_component' => [
4853
'name_lbl' => 'Naam',
4954
'colour_lbl' => 'Kleur',
@@ -95,9 +100,6 @@
95100
'menu' => [
96101
'styles' => [
97102
'default' => 'Standaard menu',
98-
'horizontal' => 'Horizontale navigatie',
99-
'vertical' => 'Zijbalk navigatie',
100-
'dropdown' => 'Dropdown menu',
101103
],
102104
'no_items' => 'Geen menu-items beschikbaar',
103105
'mobile_toggle_label' => 'Hoofdmenu openen',
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
@extends('filament-flexible-content-block-pages::tailwind.components.layouts.base')
2+
3+
@section('content')
4+
<div class="container mx-auto px-6 py-8">
5+
<div class="mb-8">
6+
<h1 class="text-3xl font-bold mb-4">
7+
{{ $tag->getTranslation('name', app()->getLocale()) }}
8+
</h1>
9+
10+
@if($tag->seo_description)
11+
<p class="text-lg text-gray-600 mb-6">
12+
{{ $tag->getTranslation('seo_description', app()->getLocale()) }}
13+
</p>
14+
@endif
15+
16+
@if($contentCounts && count($contentCounts) > 0)
17+
<div class="flex flex-wrap gap-2 mb-6">
18+
@foreach($contentCounts as $type => $count)
19+
<span class="px-3 py-1 bg-gray-100 rounded-full text-sm">
20+
{{ $count }} {{ $type }}
21+
</span>
22+
@endforeach
23+
</div>
24+
@endif
25+
</div>
26+
27+
@if($taggedContent->count() > 0)
28+
<div class="space-y-6">
29+
@foreach($taggedContent as $item)
30+
<article class="border-b border-gray-200 pb-6 last:border-b-0">
31+
<div class="flex justify-between items-start mb-2">
32+
<span class="text-sm text-blue-600 font-medium uppercase">
33+
{{ $modelLabels[$item::class] ?? class_basename($item) }}
34+
</span>
35+
@if(method_exists($item, 'publishing_begins_at') && $item->publishing_begins_at)
36+
<time class="text-sm text-gray-500">
37+
{{ $item->publishing_begins_at->format('M j, Y') }}
38+
</time>
39+
@endif
40+
</div>
41+
42+
<h2 class="text-xl font-semibold mb-2">
43+
@if(method_exists($item, 'getUrl'))
44+
<a href="{{ $item->getUrl() }}" class="hover:text-blue-600">
45+
{{ $item->title }}
46+
</a>
47+
@else
48+
{{ $item->title }}
49+
@endif
50+
</h2>
51+
52+
@if(method_exists($item, 'intro') && $item->intro)
53+
<p class="text-gray-600 mb-3">
54+
{{ Str::limit(strip_tags($item->intro), 200) }}
55+
</p>
56+
@endif
57+
58+
@if(method_exists($item, 'tags') && $item->tags->count() > 0)
59+
<div class="flex flex-wrap gap-1">
60+
@foreach($item->tags->take(5) as $itemTag)
61+
<span class="px-2 py-1 bg-gray-50 rounded text-xs text-gray-700">
62+
{{ $itemTag->getTranslation('name', app()->getLocale()) }}
63+
</span>
64+
@endforeach
65+
</div>
66+
@endif
67+
</article>
68+
@endforeach
69+
</div>
70+
71+
@if($taggedContent->hasPages())
72+
<div class="mt-8">
73+
{{ $taggedContent->links() }}
74+
</div>
75+
@endif
76+
@else
77+
<div class="text-center py-12">
78+
<p class="text-gray-600 text-lg">
79+
@lang('filament-flexible-content-block-pages::tag_pages.no_content', ['tag' => $tag->getTranslation('name', app()->getLocale())])
80+
</p>
81+
</div>
82+
@endif
83+
</div>
84+
@endsection

src/Facades/FilamentFlexibleContentBlockPages.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
/**
1111
* @method static FilamentFlexibleContentBlockPagesConfig config()
1212
* @method static void routes()
13+
* @method static void pageRoutes()
14+
* @method static void seoTagRoutes()
1315
* @method static string getUrl(Page $page, ?string $locale = null)
1416
* @method static Settings settings()
1517
*

src/FilamentFlexibleContentBlockPages.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ public function routes(): void
1717
$this->config()->getRouteHelper()->defineRoutes();
1818
}
1919

20+
public function pageRoutes(): void
21+
{
22+
$this->config()->getRouteHelper()->definePageRoutes();
23+
}
24+
25+
public function seoTagRoutes(): void
26+
{
27+
$this->config()->getRouteHelper()->defineSeoTagRoutes();
28+
}
29+
2030
public function getUrl(Page $page, ?string $locale = null): string
2131
{
2232
return $this->config()->getRouteHelper()->getUrl($page, $locale);

src/FilamentFlexibleContentBlockPagesConfig.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,36 @@ public function getTagNavigationSort(): ?int
358358
return $this->packageConfig('tags.navigation_sort');
359359
}
360360

361+
public function areTagPagesEnabled(): bool
362+
{
363+
return ! empty($this->getTagPageEnabledModels());
364+
}
365+
366+
public function getTagPageEnabledModels(): array
367+
{
368+
return $this->packageConfig('tag_pages.models.enabled', []);
369+
}
370+
371+
public function getTagPagePaginationItemCount(): int
372+
{
373+
return $this->packageConfig('tag_pages.pagination.item_count', 20);
374+
}
375+
376+
public function shouldGroupTagPagesByType(): bool
377+
{
378+
return $this->packageConfig('tag_pages.models.group_by_type', false);
379+
}
380+
381+
public function shouldShowTagPageTypeCounts(): bool
382+
{
383+
return $this->packageConfig('tag_pages.pagination.show_type_counts', true);
384+
}
385+
386+
public function getTagPageRoutePrefix(): string
387+
{
388+
return $this->packageConfig('tag_pages.route_path_prefix', 'tag');
389+
}
390+
361391
private function packageConfig(string $configKey, $default = null): mixed
362392
{
363393
return config('filament-flexible-content-block-pages.'.$configKey, $default);

0 commit comments

Comments
 (0)