From c58c07b765f2d242828221fe1dd57361630dff81 Mon Sep 17 00:00:00 2001 From: K Muller Date: Thu, 18 Dec 2025 14:33:44 +0100 Subject: [PATCH] feat: :sparkles: Document->exercice nullable / Add slug in Tags and Categories / 2pivot table are now one --- .../StoreDocumentCategoryRequest.php | 3 +- .../DocumentTag/StoreDocumentTagRequest.php | 3 +- app/Models/Company.php | 5 +-- app/Models/Document.php | 18 ++++++-- app/Models/DocumentCategory.php | 10 ++++- app/Models/DocumentTag.php | 10 ++++- ...91619_create_document_categories_table.php | 1 + ...2_01_094142_create_document_tags_table.php | 1 + ...94143_document_document_category_table.php | 35 ---------------- ..._12_094131_create_documentables_table.php} | 15 +++---- resources/ts/back/Pages/Document/Form.tsx | 5 ++- .../ts/back/Pages/DocumentCategory/Form.tsx | 41 +++++++++++-------- .../ts/back/Pages/DocumentCategory/Show.tsx | 7 ++++ resources/ts/back/Pages/DocumentTag/Form.tsx | 41 +++++++++++-------- resources/ts/back/Pages/DocumentTag/Show.tsx | 7 ++++ resources/ts/back/types/global.d.ts | 2 + 16 files changed, 118 insertions(+), 86 deletions(-) delete mode 100644 database/migrations/2025_12_01_094143_document_document_category_table.php rename database/migrations/{2025_12_01_094143_document_document_tag_table.php => 2025_12_12_094131_create_documentables_table.php} (58%) diff --git a/app/Http/Requests/Back/DocumentCategory/StoreDocumentCategoryRequest.php b/app/Http/Requests/Back/DocumentCategory/StoreDocumentCategoryRequest.php index 254799f3..9833f71e 100644 --- a/app/Http/Requests/Back/DocumentCategory/StoreDocumentCategoryRequest.php +++ b/app/Http/Requests/Back/DocumentCategory/StoreDocumentCategoryRequest.php @@ -24,7 +24,8 @@ class StoreDocumentCategoryRequest extends FormRequest public function rules(): array { return [ - 'name' => 'required|string|between:3,255' + 'name' => 'required|string|between:3,255', + 'slug' => 'required|string|between:3,255' ]; } } diff --git a/app/Http/Requests/Back/DocumentTag/StoreDocumentTagRequest.php b/app/Http/Requests/Back/DocumentTag/StoreDocumentTagRequest.php index a5d9a8f0..e57787b6 100644 --- a/app/Http/Requests/Back/DocumentTag/StoreDocumentTagRequest.php +++ b/app/Http/Requests/Back/DocumentTag/StoreDocumentTagRequest.php @@ -24,7 +24,8 @@ class StoreDocumentTagRequest extends FormRequest public function rules(): array { return [ - 'name' => 'required|string|between:3,255' + 'name' => 'required|string|between:3,255', + 'slug' => 'required|string|between:3,255' ]; } } diff --git a/app/Models/Company.php b/app/Models/Company.php index 1d7f789d..585d807b 100644 --- a/app/Models/Company.php +++ b/app/Models/Company.php @@ -9,7 +9,6 @@ use App\Traits\Models\HasUwilImages; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Support\Facades\Cache; use Uwil\LaravelActivityLogs\Traits\ActivityLog; /** @@ -64,7 +63,7 @@ class Company extends Model protected $casts = [ 'published' => 'boolean', ]; - + /** * Relations should be included in the cache. * @@ -95,4 +94,4 @@ class Company extends Model { return $this->belongsTo(CompanySector::class, 'sector_id'); } -} \ No newline at end of file +} diff --git a/app/Models/Document.php b/app/Models/Document.php index 5bbb43a4..37df56f6 100644 --- a/app/Models/Document.php +++ b/app/Models/Document.php @@ -188,7 +188,7 @@ class Document extends Model implements TranslatableModel /** * Get the url to access a specific resource. - * + * * @param integer $id Id field of the target model. * @return string */ @@ -210,7 +210,13 @@ class Document extends Model implements TranslatableModel */ public function tags(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { - return $this->belongsToMany(DocumentTag::class); + return $this->morphedByMany( + DocumentTag::class, + 'documentable', + 'documentables', + 'document_id', + 'documentable_id' + )->withTimestamps(); } /** @@ -220,7 +226,13 @@ class Document extends Model implements TranslatableModel */ public function categories(): \Illuminate\Database\Eloquent\Relations\BelongsToMany { - return $this->belongsToMany(DocumentCategory::class); + return $this->morphedByMany( + DocumentCategory::class, + 'documentable', + 'documentables', + 'document_id', + 'documentable_id' + )->withTimestamps(); } public function inertiaFill(array $attributes) diff --git a/app/Models/DocumentCategory.php b/app/Models/DocumentCategory.php index e8e92767..b378a105 100644 --- a/app/Models/DocumentCategory.php +++ b/app/Models/DocumentCategory.php @@ -24,6 +24,7 @@ class DocumentCategory extends Model implements TranslatableModel */ protected $fillable = [ 'name', + 'slug' ]; /** @@ -33,6 +34,7 @@ class DocumentCategory extends Model implements TranslatableModel */ public $translatable = [ 'name', + 'slug' ]; /** @@ -42,6 +44,12 @@ class DocumentCategory extends Model implements TranslatableModel */ public function documents(): BelongsToMany { - return $this->belongsToMany(Document::class); + return $this->morphToMany( + Document::class, + 'documentable', + 'documentables', + 'documentable_id', + 'document_id' + ); } } diff --git a/app/Models/DocumentTag.php b/app/Models/DocumentTag.php index 32264ec8..d11c5ef9 100644 --- a/app/Models/DocumentTag.php +++ b/app/Models/DocumentTag.php @@ -24,6 +24,7 @@ class DocumentTag extends Model implements TranslatableModel */ protected $fillable = [ 'name', + 'slug' ]; /** @@ -33,6 +34,7 @@ class DocumentTag extends Model implements TranslatableModel */ public $translatable = [ 'name', + 'slug' ]; /** @@ -42,6 +44,12 @@ class DocumentTag extends Model implements TranslatableModel */ public function documents(): BelongsToMany { - return $this->belongsToMany(Document::class); + return $this->morphToMany( + Document::class, + 'documentable', + 'documentables', + 'documentable_id', + 'document_id' + ); } } diff --git a/database/migrations/2025_11_08_091619_create_document_categories_table.php b/database/migrations/2025_11_08_091619_create_document_categories_table.php index 674aa402..f1b0ee63 100644 --- a/database/migrations/2025_11_08_091619_create_document_categories_table.php +++ b/database/migrations/2025_11_08_091619_create_document_categories_table.php @@ -14,6 +14,7 @@ return new class extends Migration Schema::create('document_categories', function (Blueprint $table) { $table->id(); $table->text('name')->comment('Name of the category'); + $table->text('slug')->comment('Slug of the category'); $table->timestamps(); }); } diff --git a/database/migrations/2025_12_01_094142_create_document_tags_table.php b/database/migrations/2025_12_01_094142_create_document_tags_table.php index 964846a7..e21f553a 100644 --- a/database/migrations/2025_12_01_094142_create_document_tags_table.php +++ b/database/migrations/2025_12_01_094142_create_document_tags_table.php @@ -14,6 +14,7 @@ return new class extends Migration Schema::create('document_tags', function (Blueprint $table) { $table->id(); $table->text('name')->comment('Name of the tag'); + $table->text('slug')->comment('Slug of the tag'); $table->timestamps(); }); } diff --git a/database/migrations/2025_12_01_094143_document_document_category_table.php b/database/migrations/2025_12_01_094143_document_document_category_table.php deleted file mode 100644 index 1bf28f2e..00000000 --- a/database/migrations/2025_12_01_094143_document_document_category_table.php +++ /dev/null @@ -1,35 +0,0 @@ -id(); - $table->unsignedBigInteger('document_id'); - $table->unsignedBigInteger('document_category_id'); - $table->foreign('document_id', 'dcfd_document_fk') - ->references('id')->on('documents') - ->onDelete('cascade'); - $table->foreign('document_category_id', 'dcfd_document_category_fk') - ->references('id')->on('document_categories') - ->onDelete('cascade'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('document_document_category'); - } -}; diff --git a/database/migrations/2025_12_01_094143_document_document_tag_table.php b/database/migrations/2025_12_12_094131_create_documentables_table.php similarity index 58% rename from database/migrations/2025_12_01_094143_document_document_tag_table.php rename to database/migrations/2025_12_12_094131_create_documentables_table.php index 90bf2bf8..318563c1 100644 --- a/database/migrations/2025_12_01_094143_document_document_tag_table.php +++ b/database/migrations/2025_12_12_094131_create_documentables_table.php @@ -11,17 +11,18 @@ return new class extends Migration */ public function up() { - Schema::create('document_document_tag', function (Blueprint $table) { + Schema::create('documentables', function (Blueprint $table) { $table->id(); + $table->unsignedBigInteger('document_id'); - $table->unsignedBigInteger('document_tag_id'); - $table->foreign('document_id', 'd_pivot_d_fk') + $table->unsignedBigInteger('documentable_id'); + $table->string('documentable_type'); + $table->foreign('document_id') ->references('id')->on('documents') ->onDelete('cascade'); - $table->foreign('document_tag_id', 'd_pivot_tag_fk') - ->references('id')->on('document_tags') - ->onDelete('cascade'); $table->timestamps(); + + $table->index(['documentable_id', 'documentable_type']); }); } @@ -30,6 +31,6 @@ return new class extends Migration */ public function down(): void { - Schema::dropIfExists('document_document_tag'); + Schema::dropIfExists('documentables'); } }; diff --git a/resources/ts/back/Pages/Document/Form.tsx b/resources/ts/back/Pages/Document/Form.tsx index 5ef837d0..762cc091 100644 --- a/resources/ts/back/Pages/Document/Form.tsx +++ b/resources/ts/back/Pages/Document/Form.tsx @@ -38,7 +38,7 @@ export default function Form({ const categories = usePage().props.categories as DocumentCategoryModel[]; const { options, defaultValue } = mapPivotOptions(tags, model?.tags, "name", locale); const { options: categoriesOptions, defaultValue: categoryDefaultValue } = mapPivotOptions(categories, model?.categories, "name", locale); - + console.log(model) /** Form section */ const { post, setData, data, reset } = useForm({ _method: method === Methods.POST ? 'post' : 'put', @@ -47,7 +47,7 @@ export default function Form({ status: model?.status ?? enumDocStatus.unpublished.value, path: model?.path ? model?.path[locale] : "", tags: model?.tags ? defaultValue : [], - categories: model?.categories ? defaultValue : [], + categories: model?.categories ? categoryDefaultValue : [], published_at: model?.published_at ? model?.published_at : null, unpublished_at: model?.unpublished_at ? model?.unpublished_at : null }); @@ -228,6 +228,7 @@ export default function Form({ choice: 1 }), ).ucFirst().value()} + required={false} placeholder={str( useTrans("back.document.exercice.placeholder") ).ucFirst().value()} diff --git a/resources/ts/back/Pages/DocumentCategory/Form.tsx b/resources/ts/back/Pages/DocumentCategory/Form.tsx index ffd307d4..4ddf33b3 100644 --- a/resources/ts/back/Pages/DocumentCategory/Form.tsx +++ b/resources/ts/back/Pages/DocumentCategory/Form.tsx @@ -11,6 +11,7 @@ import useTrans from "@/hooks/use-translations"; import str from "@/hooks/use-string"; import { useCrudSubmit } from "@/hooks/use-crud-submit"; import SubmitButton from "@/back/Components/SubmitButton"; +import Slugifycator from "@/back/Components/Inputs/Slugifycator"; export default function Form({ model, @@ -31,7 +32,8 @@ export default function Form({ /** Form section */ const { post, setData, data } = useForm({ _method: method === Methods.POST ? 'post' : 'put', - name: model?.name ? model?.name[locale] : "" + name: model?.name ? model?.name[locale] : "", + slug: model?.slug ? model?.slug[locale] : "" }); const submit = useCrudSubmit({ @@ -51,21 +53,28 @@ export default function Form({ icon={} description={useTrans("back.form_subtitle_global")} > - +
+ + +
{useTrans('back.table_not_known')}

), }, + { + accessorKey: "slug", + header: str(useTrans("validation.custom.slug")).ucFirst().value(), + cell: ({ value }: { value: TranslationField }) => value[appEnv.locale] + ? value[appEnv.locale] + : (

{useTrans('back.table_not_known')}

), + }, { accessorKey: "created_at", header: str(useTrans("validation.attributes.created_at")).ucFirst().value(), diff --git a/resources/ts/back/Pages/DocumentTag/Form.tsx b/resources/ts/back/Pages/DocumentTag/Form.tsx index ffd307d4..4ddf33b3 100644 --- a/resources/ts/back/Pages/DocumentTag/Form.tsx +++ b/resources/ts/back/Pages/DocumentTag/Form.tsx @@ -11,6 +11,7 @@ import useTrans from "@/hooks/use-translations"; import str from "@/hooks/use-string"; import { useCrudSubmit } from "@/hooks/use-crud-submit"; import SubmitButton from "@/back/Components/SubmitButton"; +import Slugifycator from "@/back/Components/Inputs/Slugifycator"; export default function Form({ model, @@ -31,7 +32,8 @@ export default function Form({ /** Form section */ const { post, setData, data } = useForm({ _method: method === Methods.POST ? 'post' : 'put', - name: model?.name ? model?.name[locale] : "" + name: model?.name ? model?.name[locale] : "", + slug: model?.slug ? model?.slug[locale] : "" }); const submit = useCrudSubmit({ @@ -51,21 +53,28 @@ export default function Form({ icon={} description={useTrans("back.form_subtitle_global")} > - +
+ + +
{useTrans('back.table_not_known')}

), }, + { + accessorKey: "slug", + header: str(useTrans("validation.custom.slug")).ucFirst().value(), + cell: ({ value }: { value: TranslationField }) => value[appEnv.locale] + ? value[appEnv.locale] + : (

{useTrans('back.table_not_known')}

), + }, { accessorKey: "created_at", header: str(useTrans("validation.attributes.created_at")).ucFirst().value(), diff --git a/resources/ts/back/types/global.d.ts b/resources/ts/back/types/global.d.ts index d1310378..03b887da 100644 --- a/resources/ts/back/types/global.d.ts +++ b/resources/ts/back/types/global.d.ts @@ -192,6 +192,7 @@ type DocumentModel = { type DocumentTagModel = { id: number; name: TranslationField; + slug: TranslationField; documents_count?: number; created_at: Date; updated_at: Date; @@ -200,6 +201,7 @@ type DocumentTagModel = { type DocumentCategoryModel = { id: number; name: TranslationField; + slug: TranslationField; documents_count?: number; created_at: Date; updated_at: Date;