Compare commits
1 commit
develop
...
issue-42-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e194311bb |
13 changed files with 237 additions and 6 deletions
|
|
@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
|
||||||
|
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||||
|
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property string $seo_title Utilisé pour la balise title de la page.
|
* @property string $seo_title Utilisé pour la balise title de la page.
|
||||||
|
|
@ -25,10 +28,11 @@ use Illuminate\Support\Str;
|
||||||
* @property-read \Carbon\Carbon $created_at Created date.
|
* @property-read \Carbon\Carbon $created_at Created date.
|
||||||
* @property-read \Carbon\Carbon $updated_at Updated date.
|
* @property-read \Carbon\Carbon $updated_at Updated date.
|
||||||
*/
|
*/
|
||||||
class News extends Model
|
class News extends Model implements SeoInterface
|
||||||
{
|
{
|
||||||
use ActivityLog;
|
use ActivityLog;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use SeoTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|
@ -163,4 +167,22 @@ class News extends Model
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * SEO TRAIT OVERLOAD
|
||||||
|
/**
|
||||||
|
* Transform to seoModel
|
||||||
|
*
|
||||||
|
* @return \App\Objects\SeoItem
|
||||||
|
*/
|
||||||
|
public function toSeoItem(): SeoItem
|
||||||
|
{
|
||||||
|
return new SeoItem(
|
||||||
|
\trans('models.classes.' . $this->getTable()),
|
||||||
|
$this->seo_title,
|
||||||
|
$this->seo_description,
|
||||||
|
$this->published ?? false,
|
||||||
|
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||||
|
$this->published ? \route('fo.' . Str::singular($this->getTable()) . '.show', $this) : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
|
||||||
|
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||||
|
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property string $seo_title Utilisé pour la balise title de la page.
|
* @property string $seo_title Utilisé pour la balise title de la page.
|
||||||
|
|
@ -36,10 +39,11 @@ use Illuminate\Support\Str;
|
||||||
* @property-read \App\Models\Picto $pictos Pictos Many-to-many relationship.
|
* @property-read \App\Models\Picto $pictos Pictos Many-to-many relationship.
|
||||||
* @property-read \App\Models\Range $range Range Belongs to relationship.
|
* @property-read \App\Models\Range $range Range Belongs to relationship.
|
||||||
*/
|
*/
|
||||||
class Product extends Model
|
class Product extends Model implements SeoInterface
|
||||||
{
|
{
|
||||||
use ActivityLog;
|
use ActivityLog;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use SeoTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|
@ -168,4 +172,22 @@ class Product extends Model
|
||||||
{
|
{
|
||||||
return $this->belongsToMany(Picto::class);
|
return $this->belongsToMany(Picto::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * SEO TRAIT OVERLOAD
|
||||||
|
/**
|
||||||
|
* Transform to seoModel
|
||||||
|
*
|
||||||
|
* @return \App\Objects\SeoItem
|
||||||
|
*/
|
||||||
|
public function toSeoItem(): SeoItem
|
||||||
|
{
|
||||||
|
return new SeoItem(
|
||||||
|
\trans('models.classes.' . Str::singular($this->getTable())),
|
||||||
|
$this->seo_title,
|
||||||
|
$this->seo_description,
|
||||||
|
$this->published ?? false,
|
||||||
|
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||||
|
$this->published ? \route('fo.' . $this->getTable() . '.show', $this) : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ use App\Traits\Models\ActivityLog;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Uwil\Seo\Laravel\Interfaces\SeoInterface;
|
||||||
|
use Uwil\Seo\Laravel\Objects\SeoItem;
|
||||||
|
use Uwil\Seo\Laravel\Traits\SeoTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property \App\Enums\StaticPageType $type Page type (StaticPageEnum).
|
* @property \App\Enums\StaticPageType $type Page type (StaticPageEnum).
|
||||||
|
|
@ -19,10 +22,11 @@ use Illuminate\Support\Str;
|
||||||
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
* @property-read \Illuminate\Support\Carbon $created_at Created date.
|
||||||
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
|
||||||
*/
|
*/
|
||||||
class StaticPage extends Model
|
class StaticPage extends Model implements SeoInterface
|
||||||
{
|
{
|
||||||
use ActivityLog;
|
use ActivityLog;
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use SeoTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|
@ -109,4 +113,22 @@ class StaticPage extends Model
|
||||||
ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id);
|
ToolboxHelper::assertFieldIsUnique($table, 'title', $title, $id);
|
||||||
ToolboxHelper::assertFieldIsUnique($table, 'slug', Str::slug($title), $id);
|
ToolboxHelper::assertFieldIsUnique($table, 'slug', Str::slug($title), $id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// * SEO TRAIT OVERLOAD
|
||||||
|
/**
|
||||||
|
* Transform to seoModel
|
||||||
|
*
|
||||||
|
* @return \App\Objects\SeoItem
|
||||||
|
*/
|
||||||
|
public function toSeoItem(): SeoItem
|
||||||
|
{
|
||||||
|
return new SeoItem(
|
||||||
|
\trans_choice('models.classes.' . Str::singular($this->getTable()), 1),
|
||||||
|
$this->seo_title,
|
||||||
|
$this->seo_description,
|
||||||
|
false,
|
||||||
|
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
|
||||||
|
''
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,11 @@ class ViewServiceProvider extends ServiceProvider
|
||||||
|
|
||||||
// * FORCE BOOTSTRAP PAGINATOR (or custom if in front)
|
// * FORCE BOOTSTRAP PAGINATOR (or custom if in front)
|
||||||
// Early boot, request wont be filled as expected.
|
// Early boot, request wont be filled as expected.
|
||||||
if (collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo') {
|
// For the moment, we exclude the seo page because the new pagination system doesn't work in the package.
|
||||||
|
if (
|
||||||
|
collect(explode('/', \request()->getPathInfo()))->get(1) === 'bo' &&
|
||||||
|
collect(explode('/', \request()->getPathInfo()))->last() !== 'seo'
|
||||||
|
) {
|
||||||
Paginator::defaultView('bo.modules.pagination');
|
Paginator::defaultView('bo.modules.pagination');
|
||||||
} else {
|
} else {
|
||||||
Paginator::useBootstrapFive();
|
Paginator::useBootstrapFive();
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@
|
||||||
"mews/purifier": "^3.4",
|
"mews/purifier": "^3.4",
|
||||||
"propaganistas/laravel-phone": "^5.0",
|
"propaganistas/laravel-phone": "^5.0",
|
||||||
"sentry/sentry-laravel": "*",
|
"sentry/sentry-laravel": "*",
|
||||||
"uwil/k8s-laravel": "*"
|
"uwil/k8s-laravel": "*",
|
||||||
|
"uwil/seo-laravel": "^2.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.9.1",
|
"fakerphp/faker": "^1.9.1",
|
||||||
|
|
|
||||||
49
composer.lock
generated
49
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "b72fd73d510285ac10b0b17fe78928c9",
|
"content-hash": "2231f3e8a4eba50d8cab64366c6dcfb1",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "axlon/laravel-postal-code-validation",
|
"name": "axlon/laravel-postal-code-validation",
|
||||||
|
|
@ -8811,6 +8811,53 @@
|
||||||
],
|
],
|
||||||
"description": "Laravel requirements for k8s"
|
"description": "Laravel requirements for k8s"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "uwil/seo-laravel",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://lab.s-web.fr/ldc-web/projets/seo-laravel.git",
|
||||||
|
"reference": "518918847ada3a75dceda343ca074d7cdf8d0458"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://lab.s-web.fr/api/v4/projects/96/packages/composer/archives/uwil/seo-laravel.zip?sha=518918847ada3a75dceda343ca074d7cdf8d0458",
|
||||||
|
"reference": "518918847ada3a75dceda343ca074d7cdf8d0458",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"illuminate/support": "~8|~9|~10",
|
||||||
|
"laravel/framework": "~8|~9|~10",
|
||||||
|
"php": "~7.4|~8"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"slevomat/coding-standard": "^8.3",
|
||||||
|
"squizlabs/php_codesniffer": "^3.7"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Uwil\\Seo\\Laravel\\SeoServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Uwil\\Seo\\Laravel\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolas Demangeat",
|
||||||
|
"email": "nicolas.demangeat@ldc.fr"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Find Seo title and seo description of a model"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "vlucas/phpdotenv",
|
"name": "vlucas/phpdotenv",
|
||||||
"version": "v5.5.0",
|
"version": "v5.5.0",
|
||||||
|
|
|
||||||
12
config/seo.php
Normal file
12
config/seo.php
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'bo_route_prefix' => 'bo.',
|
||||||
|
'blade' => 'bo.pages.seo.index',
|
||||||
|
'middlewares' => [
|
||||||
|
'web',
|
||||||
|
'admin-secure',
|
||||||
|
'auth:backend'
|
||||||
|
],
|
||||||
|
'guard' => 'backend'
|
||||||
|
];
|
||||||
|
|
@ -14,5 +14,6 @@ return [
|
||||||
'game' => 'jeu|jeux',
|
'game' => 'jeu|jeux',
|
||||||
'klub_bloc' => 'bloc klub',
|
'klub_bloc' => 'bloc klub',
|
||||||
'historicalMilestone' => 'jalon historique',
|
'historicalMilestone' => 'jalon historique',
|
||||||
|
'seo' => 'contenu SEO|contenus SEO'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,7 @@ return [
|
||||||
'third_image' => 'troisième image',
|
'third_image' => 'troisième image',
|
||||||
'title_line1' => 'première ligne du titre',
|
'title_line1' => 'première ligne du titre',
|
||||||
'title_line2' => 'deuxième ligne du titre',
|
'title_line2' => 'deuxième ligne du titre',
|
||||||
|
'type' => 'type',
|
||||||
'unpublish_at' => 'date de fin de publication',
|
'unpublish_at' => 'date de fin de publication',
|
||||||
'url' => 'url',
|
'url' => 'url',
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,12 @@
|
||||||
{{ __('Accueil') }}
|
{{ __('Accueil') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link @if (Route::is('bo.seo.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.seo.index') }}"
|
||||||
|
title="{{ __('Show the SEO informations') }}" role="button">
|
||||||
|
{{ __('SEO') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<a class="nav-link dropdown-toggle @if (request()->routeIs('bo.static_pages.*') || request()->routeIs('bo.commitmentpages.*') || request()->routeIs('bo.klubblocs.*')) active @endif" data-bs-toggle="dropdown" type="button"
|
<a class="nav-link dropdown-toggle @if (request()->routeIs('bo.static_pages.*') || request()->routeIs('bo.commitmentpages.*') || request()->routeIs('bo.klubblocs.*')) active @endif" data-bs-toggle="dropdown" type="button"
|
||||||
|
|
|
||||||
50
resources/views/bo/pages/seo/index-list.blade.php
Normal file
50
resources/views/bo/pages/seo/index-list.blade.php
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<table class="table-hover table-fix-action m-0 table">
|
||||||
|
@if (count($seoItemList) > 0)
|
||||||
|
<thead>
|
||||||
|
<tr class="border-start-0 border-end-0 border-top-0 border-dark border border-2">
|
||||||
|
<th scope="col">{{ str(__('validation.custom.type'))->ucfirst() }}</th>
|
||||||
|
<th scope="col">{{ str(__('validation.custom.seo_title'))->ucfirst() }}</th>
|
||||||
|
<th scope="col">{{ str(__('validation.custom.seo_description'))->ucfirst() }}</th>
|
||||||
|
<th scope="col">{{ str(__('validation.custom.published'))->ucfirst() }}</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($seoItemList as $seoItem)
|
||||||
|
<tr class="border-bottom list-item">
|
||||||
|
<th scope="row">{{ str($seoItem->type)->ucfirst() }}</th>
|
||||||
|
<td>{{ $seoItem->seo_title }}</td>
|
||||||
|
<td>{{ $seoItem->seo_description }}</td>
|
||||||
|
<td class="text-center align-middle">
|
||||||
|
@if ($seoItem->status)
|
||||||
|
<i class="fs-6 text-success fa-solid fa-circle-check"></i>
|
||||||
|
@else
|
||||||
|
<i class="fs-6 text-danger fa-regular fa-circle-xmark"></i>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td class="text-end align-middle">
|
||||||
|
<div class="btn-group">
|
||||||
|
@if ($seoItem->status && $seoItem->fo_url !== '#')
|
||||||
|
<a class="btn btn-sm btn-warning" data-bs-toggle="tooltip" href="{{ $seoItem->fo_url }}"
|
||||||
|
title="{{ __('Show') }}" target="_blank">
|
||||||
|
<i class="fa-solid fa-eye"></i>
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
<a class="btn btn-sm btn-primary" data-bs-toggle="tooltip" href="{{ $seoItem->bo_url }}"
|
||||||
|
title="{{ Str::ucfirst(__('crud.actions.update')) }}">
|
||||||
|
<i class="fa-solid fa-pencil"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
@else
|
||||||
|
<tr>
|
||||||
|
<td class="border-0">{{ __('crud.other.no_model_found', ['model' => __('models.classes.range')]) }}</td>
|
||||||
|
</tr>
|
||||||
|
@endif
|
||||||
|
</table>
|
||||||
|
<div class="mt-4">
|
||||||
|
{{ $seoItemList->withQueryString()->onEachSide(1)->links() }}
|
||||||
|
</div>
|
||||||
35
resources/views/bo/pages/seo/index.blade.php
Normal file
35
resources/views/bo/pages/seo/index.blade.php
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
@extends('bo.layout')
|
||||||
|
|
||||||
|
@section('title', Str::ucfirst(trans_choice('models.classes.seo', '*')))
|
||||||
|
@section('description', trans_choice('crud.meta.description.index', 1, ['model' => trans_choice('models.classes.seo', '*')]))
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
|
||||||
|
@include('modules.breadcrumbs.breadcrumb-body')
|
||||||
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col">
|
||||||
|
<form class="float-start" action="{{ route('bo.seo.index') }}">
|
||||||
|
<select class="form-select" id="type-filter" name="type">
|
||||||
|
<option value="" @if (!request()->type) selected @endif>{{ __('Filtrer par type') }}</option>
|
||||||
|
@foreach (\Uwil\Seo\Laravel\Http\Controllers\SeoController::slugifiedSeoModels() as $slugifiedSeoModel => $className)
|
||||||
|
<option value="{{ $slugifiedSeoModel }}" @if (request()->type === $slugifiedSeoModel) selected @endif>
|
||||||
|
{{ str($className)->ucfirst() }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@push('scripts')
|
||||||
|
<script nonce="{{ $nonce }}">
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
let typeFilter = document.getElementById('type-filter')
|
||||||
|
typeFilter.addEventListener('change', () => typeFilter.parentElement.submit())
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
<div class="table-responsive my-3">
|
||||||
|
@include('bo.pages.seo.index-list')
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -216,3 +216,11 @@ Breadcrumbs::for('bo.historicalmilestones.duplicate', function (Generator $trail
|
||||||
$trail->parent('bo.historicalmilestones.index');
|
$trail->parent('bo.historicalmilestones.index');
|
||||||
$trail->push(Str::ucfirst(trans('crud.actions.duplicate')));
|
$trail->push(Str::ucfirst(trans('crud.actions.duplicate')));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// * SEO
|
||||||
|
Breadcrumbs::for('bo.seo.index', function (Generator $trail) {
|
||||||
|
$trail->push(
|
||||||
|
Str::of(trans_choice('models.classes.seo', '*'))->ucfirst(),
|
||||||
|
route('bo.seo.index')
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue