From 4046910a9d1127fd9e7830fcf278d8fb569c677e Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 28 May 2026 15:11:45 +0200 Subject: [PATCH 1/5] feat(catalog) : add admin categories page with MalioDataTable and drawer (first draft) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Page Nuxt /admin/categories : MalioDataTable + bouton Ajouter - CategoryDrawer : modes creation / consultation / edition (transition auto view -> edit a la 1re modif), validation client RG-1.02/04/05, mapping erreurs server 409 (doublon) et 422 (violations) - CategoryDeleteModal : confirmation suppression (soft delete cote API) - Types Category, CategoryType, User - i18n admin.categories.* (titre, table, form, validation, toasts) - Fix latent : ajout 'categories' a AdminLinkSlug e2e (oubli ERP-47) Logique fetch inline volontaire au M0 — extraction en composables a ERP-50 (ticket 0.8). Aucune persistance d'etat de tableau dans l'URL. --- frontend/i18n/locales/fr.json | 33 ++ .../components/CategoryDeleteModal.vue | 76 ++++ .../catalog/components/CategoryDrawer.vue | 370 ++++++++++++++++++ frontend/modules/catalog/nuxt.config.ts | 1 + .../catalog/pages/admin/categories.vue | 162 ++++++++ frontend/modules/catalog/types/category.ts | 71 ++++ .../e2e/helpers/pages/SidebarComponent.ts | 2 +- 7 files changed, 714 insertions(+), 1 deletion(-) create mode 100644 frontend/modules/catalog/components/CategoryDeleteModal.vue create mode 100644 frontend/modules/catalog/components/CategoryDrawer.vue create mode 100644 frontend/modules/catalog/nuxt.config.ts create mode 100644 frontend/modules/catalog/pages/admin/categories.vue create mode 100644 frontend/modules/catalog/types/category.ts diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index a71d4db..77849a7 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -230,6 +230,39 @@ "updated": "Site mis à jour avec succès", "deleted": "Site supprimé avec succès" } + }, + "categories": { + "title": "Gestion des catégories", + "newCategory": "Ajouter", + "editCategory": "Modifier la catégorie", + "createCategory": "Créer une catégorie", + "viewCategory": "Détail de la catégorie", + "noCategories": "Aucune catégorie pour l'instant.", + "table": { + "name": "Nom", + "type": "Type" + }, + "form": { + "name": "Nom", + "type": "Type de catégorie", + "typePlaceholder": "Sélectionner un type" + }, + "validation": { + "nameRequired": "Le nom est obligatoire.", + "nameLength": "Le nom doit faire entre 2 et 120 caractères.", + "typeRequired": "Le type de catégorie est obligatoire." + }, + "delete": { + "title": "Supprimer la catégorie", + "message": "Êtes-vous sûr de vouloir supprimer la catégorie \"{name}\" ? Cette action est irréversible." + }, + "toast": { + "created": "Catégorie créée avec succès", + "updated": "Catégorie mise à jour avec succès", + "deleted": "Catégorie supprimée avec succès", + "duplicate": "Une catégorie nommée « {name} » existe déjà pour ce type.", + "typesLoadFailed": "Impossible de charger les types de catégorie. Réessayez." + } } } } diff --git a/frontend/modules/catalog/components/CategoryDeleteModal.vue b/frontend/modules/catalog/components/CategoryDeleteModal.vue new file mode 100644 index 0000000..c03a28c --- /dev/null +++ b/frontend/modules/catalog/components/CategoryDeleteModal.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/frontend/modules/catalog/components/CategoryDrawer.vue b/frontend/modules/catalog/components/CategoryDrawer.vue new file mode 100644 index 0000000..87d3788 --- /dev/null +++ b/frontend/modules/catalog/components/CategoryDrawer.vue @@ -0,0 +1,370 @@ + + + diff --git a/frontend/modules/catalog/nuxt.config.ts b/frontend/modules/catalog/nuxt.config.ts new file mode 100644 index 0000000..268da7f --- /dev/null +++ b/frontend/modules/catalog/nuxt.config.ts @@ -0,0 +1 @@ +export default defineNuxtConfig({}) diff --git a/frontend/modules/catalog/pages/admin/categories.vue b/frontend/modules/catalog/pages/admin/categories.vue new file mode 100644 index 0000000..077d77a --- /dev/null +++ b/frontend/modules/catalog/pages/admin/categories.vue @@ -0,0 +1,162 @@ + + + diff --git a/frontend/modules/catalog/types/category.ts b/frontend/modules/catalog/types/category.ts new file mode 100644 index 0000000..acb154d --- /dev/null +++ b/frontend/modules/catalog/types/category.ts @@ -0,0 +1,71 @@ +/** + * Types front du module Catalog (M0 — Gestion des categories). + * + * Contrats API consommes : + * - GET /api/categories → HydraCollection + * - GET /api/categories/{id} → Category + * - POST /api/categories → body { name, categoryType: IRI } + * - PATCH /api/categories/{id} → body partiel { name?, categoryType?: IRI } + * - DELETE /api/categories/{id} → 204 (soft delete via CategoryProcessor) + * - GET /api/category_types → HydraCollection + * + * Notes : + * - Les IRI sont envoyes en POST/PATCH (ex. "/api/category_types/3"). + * - `categoryType` est embarque (groupe Serializer `category:read` sur les + * proprietes de CategoryType, cf. spec-back § 3.4). + * - `createdBy` / `updatedBy` peuvent etre `null` (hors contexte HTTP, + * ON DELETE SET NULL en BDD). Affichage : libelle "Systeme" si null. + */ + +/** + * Reference legere d'un user, telle qu'embarquee dans Category.createdBy / + * updatedBy. Volontairement minimaliste : on n'a besoin que de l'identifiant + * et de l'username pour l'affichage courant. + */ +export interface User { + id: number + username: string +} + +/** + * Reference du referentiel CategoryType (lecture seule au M0). + */ +export interface CategoryType { + id: number + code: string + label: string +} + +/** + * Categorie metier — telle qu'elle est lue depuis l'API. L'entite porte le + * pattern Timestampable+Blamable (cf. spec-back § 2.8). + */ +export interface Category { + id: number + name: string + categoryType: CategoryType + /** Soft delete : null = active, valeur = supprimee logiquement le {date}. */ + deletedAt: string | null + createdAt: string + updatedAt: string + createdBy: User | null + updatedBy: User | null +} + +/** + * Payload accepte en POST /api/categories. `categoryType` est envoye en + * IRI Hydra (ex. `/api/category_types/3`). + */ +export interface CategoryCreateInput { + name: string + categoryType: string +} + +/** + * Payload accepte en PATCH /api/categories/{id}. Tous les champs sont + * optionnels (modification partielle). + */ +export interface CategoryUpdateInput { + name?: string + categoryType?: string +} diff --git a/frontend/tests/e2e/helpers/pages/SidebarComponent.ts b/frontend/tests/e2e/helpers/pages/SidebarComponent.ts index 9bdae9e..9e7a130 100644 --- a/frontend/tests/e2e/helpers/pages/SidebarComponent.ts +++ b/frontend/tests/e2e/helpers/pages/SidebarComponent.ts @@ -1,6 +1,6 @@ import type { Locator, Page } from '@playwright/test' -export type AdminLinkSlug = 'users' | 'roles' | 'sites' | 'audit-log' +export type AdminLinkSlug = 'users' | 'roles' | 'sites' | 'categories' | 'audit-log' /** * Page Object de la sidebar (MalioSidebar), scope sur les items "admin". -- 2.39.5 From 216f38847be19133c7061f474e4bc6f6a0e486e1 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Thu, 28 May 2026 15:37:33 +0200 Subject: [PATCH 2/5] fix(ci) : recreer l'index partiel uq_category_name_type_active apres schema:update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit doctrine:schema:update --force drop l'index unique partiel cree par la migration M0 Catalog (LOWER(name), category_type_id) WHERE deleted_at IS NULL : Doctrine ORM ne sait pas exprimer les index fonctionnels partiels via les mappings, donc le voit comme orphelin. Resultat : en CI les tests CategoryUniqueTest::testDuplicateName* attendent un 409 (collision) et recoivent 201 — l'index unique n'existant plus, le doublon passe. Aligne le step CI sur la cible makefile test-db-setup qui recreait deja l'index manuellement apres schema:update. --- .gitea/workflows/pull-request.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitea/workflows/pull-request.yml b/.gitea/workflows/pull-request.yml index c161627..c0f9425 100644 --- a/.gitea/workflows/pull-request.yml +++ b/.gitea/workflows/pull-request.yml @@ -73,12 +73,20 @@ jobs: run: vendor/bin/php-cs-fixer fix --config=.php-cs-fixer.dist.php --allow-risky=yes --dry-run --diff - name: Bootstrap test database + # Aligne sur la cible `test-db-setup` du makefile : apres + # `schema:update --force`, on RECREE manuellement l'index unique + # partiel `uq_category_name_type_active` car Doctrine ORM ne sait + # pas exprimer les index fonctionnels partiels (LOWER(name) + WHERE + # deleted_at IS NULL) et `schema:update` les considere comme + # orphelins et les DROP — collisions non detectees, tests d'unicite + # qui attendent 409 recoivent 201. run: | php bin/console doctrine:database:create --env=test --if-not-exists --no-interaction php bin/console doctrine:migrations:migrate --env=test --no-interaction php bin/console doctrine:schema:update --env=test --force --no-interaction php bin/console doctrine:fixtures:load --env=test --no-interaction php bin/console app:sync-permissions --env=test --no-interaction + php bin/console --env=test dbal:run-sql "CREATE UNIQUE INDEX IF NOT EXISTS uq_category_name_type_active ON category (LOWER(name), category_type_id) WHERE deleted_at IS NULL" - name: Run PHPUnit run: php -d memory_limit=512M vendor/bin/phpunit -- 2.39.5 From 934a12b28e78d6600a075f7ff27c2fb7a14940aa Mon Sep 17 00:00:00 2001 From: tristan Date: Fri, 29 May 2026 08:12:03 +0200 Subject: [PATCH 3/5] fix(category): update category modal to MalioModal component --- .../components/CategoryDeleteModal.vue | 90 +++++++------------ frontend/package-lock.json | 55 +++++++----- 2 files changed, 64 insertions(+), 81 deletions(-) diff --git a/frontend/modules/catalog/components/CategoryDeleteModal.vue b/frontend/modules/catalog/components/CategoryDeleteModal.vue index c03a28c..5842904 100644 --- a/frontend/modules/catalog/components/CategoryDeleteModal.vue +++ b/frontend/modules/catalog/components/CategoryDeleteModal.vue @@ -1,37 +1,35 @@ - - diff --git a/frontend/package-lock.json b/frontend/package-lock.json index cf060ff..e3ec321 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -85,6 +85,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -582,27 +583,6 @@ "integrity": "sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ==", "license": "MIT" }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -1303,6 +1283,7 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "license": "MIT", + "peer": true, "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" @@ -2221,6 +2202,7 @@ "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.4.2.tgz", "integrity": "sha512-5+IPRNX2CjkBhuWUwz0hBuLqiaJPRoKzQ+SvcdrQDbAyE+VDeFt74VpSFr5/R0ujrK4b+XnSHUJWdS72w6hsog==", "license": "MIT", + "peer": true, "dependencies": { "c12": "^3.3.3", "consola": "^3.4.2", @@ -2323,6 +2305,7 @@ "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.4.2.tgz", "integrity": "sha512-/q6C7Qhiricgi+PKR7ovBnJlKTL0memCbA1CzRT+itCW/oeYzUfeMdQ35mGntlBoyRPNrMXbzuSUhfDbSCU57w==", "license": "MIT", + "peer": true, "dependencies": { "@vue/shared": "^3.5.30", "defu": "^6.1.4", @@ -4638,6 +4621,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.2.tgz", "integrity": "sha512-yjv2N7gaQMbIVfsSZHBMscLoybgetcTraXsSMrELAerl/jfRipg5S1dBXMFvgRy8Kh48+TGoH+5nqshxdOEGoQ==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4886,6 +4870,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.2.tgz", "integrity": "sha512-tRbbjpOPrY4ApIHtn3ctnKIhkkioewMsZa5gJzqVB47LJFNyzLXLo/aID4sJRKTIMi1wd1fA9TiBKPe6KqczPA==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4991,6 +4976,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.23.2.tgz", "integrity": "sha512-K2o1gMwn09nrd5ewftSy08U6LMC1cW3Cmml5+vHT9P/VeMtYwkbNg+9Mt1uFh7VfAZmlkj8d3u7RYqfl8xMVJA==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -5017,6 +5003,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.2.tgz", "integrity": "sha512-kRHQ3nSbAfkFdxj9FtDdr4hpREndGgWFA6ZEAwlLeGUxf8QYTpuF9zb2yxdBPBlTc5+JsbPcskNt+u1PazGKYw==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -5031,6 +5018,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.2.tgz", "integrity": "sha512-1kvsBqGNu2ZJ0P/lkxN0pAMqSyUcpkMIzE4xwGUIyAiD0pZV6dr+OCMwGWOTLllSyrn91xI5K7OLk3pYeCPKqA==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-commands": "^1.6.2", @@ -5174,6 +5162,7 @@ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~7.19.0" } @@ -5236,6 +5225,7 @@ "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", @@ -6015,6 +6005,7 @@ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", "license": "MIT", + "peer": true, "dependencies": { "@babel/parser": "^7.29.2", "@vue/compiler-core": "3.5.32", @@ -6258,6 +6249,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6645,6 +6637,7 @@ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "license": "Apache-2.0", + "peer": true, "peerDependencies": { "bare-abort-controller": "*" }, @@ -6842,6 +6835,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -6956,6 +6950,7 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=8" } @@ -7150,7 +7145,8 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz", "integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/clean-regexp": { "version": "1.0.0", @@ -8203,6 +8199,7 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9361,6 +9358,7 @@ "integrity": "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", @@ -11807,6 +11805,7 @@ "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.4.2.tgz", "integrity": "sha512-iWVFpr/YEqVU/CenqIHMnIkvb2HE/9f+q8oxZ+pj2et+60NljGRClCgnmbvGPdmNFE0F1bEhoBCYfqbDOCim3Q==", "license": "MIT", + "peer": true, "dependencies": { "@dxup/nuxt": "^0.4.0", "@nuxt/cli": "^3.34.0", @@ -12865,6 +12864,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "license": "MIT", + "peer": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -12922,6 +12922,7 @@ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.112.0.tgz", "integrity": "sha512-7rQ3QdJwobMQLMZwQaPuPYMEF2fDRZwf51lZ//V+bA37nejjKW5ifMHbbCwvA889Y4RLhT+/wLJpPRhAoBaZYw==", "license": "MIT", + "peer": true, "dependencies": { "@oxc-project/types": "^0.112.0" }, @@ -13188,6 +13189,7 @@ "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", "license": "MIT", + "peer": true, "dependencies": { "@vue/devtools-api": "^7.7.7" }, @@ -13313,6 +13315,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -13856,6 +13859,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -14646,6 +14650,7 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "license": "MIT", + "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -15549,6 +15554,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -16228,6 +16234,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -16494,6 +16501,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", "license": "MIT", + "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -17412,6 +17420,7 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", "license": "MIT", + "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/compiler-sfc": "3.5.32", @@ -17456,6 +17465,7 @@ "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0 || ^9.0.0", @@ -17492,6 +17502,7 @@ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.3.1.tgz", "integrity": "sha512-azq8fhVnCwJAw0iXW7i44h9P+Bj+snNuevBAaJ9bxn0I3YVsRU3deVFPNnTfZ2uxVJefGp83JUmL68ddCPw5Pw==", "license": "MIT", + "peer": true, "dependencies": { "@intlify/core-base": "11.3.1", "@intlify/devtools-types": "11.3.1", -- 2.39.5 From b0f379dcb8160f7b7acfaf0e36ed448bca8a0b7d Mon Sep 17 00:00:00 2001 From: tristan Date: Fri, 29 May 2026 09:11:07 +0200 Subject: [PATCH 4/5] fix(chore) : package-lock.json --- frontend/package-lock.json | 55 +++++++++++++++----------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e3ec321..cf060ff 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -85,7 +85,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -583,6 +582,27 @@ "integrity": "sha512-/B8YJGPzaYq1NbsQmwgP8EZqg40NpTw4ZB3suuI0TplbxKHeK94jeaawLmVhCv+YwUnOpiWEz9U6SeThku/8JQ==", "license": "MIT" }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emnapi/wasi-threads": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", @@ -1283,7 +1303,6 @@ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "license": "MIT", - "peer": true, "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" @@ -2202,7 +2221,6 @@ "resolved": "https://registry.npmjs.org/@nuxt/kit/-/kit-4.4.2.tgz", "integrity": "sha512-5+IPRNX2CjkBhuWUwz0hBuLqiaJPRoKzQ+SvcdrQDbAyE+VDeFt74VpSFr5/R0ujrK4b+XnSHUJWdS72w6hsog==", "license": "MIT", - "peer": true, "dependencies": { "c12": "^3.3.3", "consola": "^3.4.2", @@ -2305,7 +2323,6 @@ "resolved": "https://registry.npmjs.org/@nuxt/schema/-/schema-4.4.2.tgz", "integrity": "sha512-/q6C7Qhiricgi+PKR7ovBnJlKTL0memCbA1CzRT+itCW/oeYzUfeMdQ35mGntlBoyRPNrMXbzuSUhfDbSCU57w==", "license": "MIT", - "peer": true, "dependencies": { "@vue/shared": "^3.5.30", "defu": "^6.1.4", @@ -4621,7 +4638,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.23.2.tgz", "integrity": "sha512-yjv2N7gaQMbIVfsSZHBMscLoybgetcTraXsSMrELAerl/jfRipg5S1dBXMFvgRy8Kh48+TGoH+5nqshxdOEGoQ==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4870,7 +4886,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.23.2.tgz", "integrity": "sha512-tRbbjpOPrY4ApIHtn3ctnKIhkkioewMsZa5gJzqVB47LJFNyzLXLo/aID4sJRKTIMi1wd1fA9TiBKPe6KqczPA==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -4976,7 +4991,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.23.2.tgz", "integrity": "sha512-K2o1gMwn09nrd5ewftSy08U6LMC1cW3Cmml5+vHT9P/VeMtYwkbNg+9Mt1uFh7VfAZmlkj8d3u7RYqfl8xMVJA==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -5003,7 +5017,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.23.2.tgz", "integrity": "sha512-kRHQ3nSbAfkFdxj9FtDdr4hpREndGgWFA6ZEAwlLeGUxf8QYTpuF9zb2yxdBPBlTc5+JsbPcskNt+u1PazGKYw==", "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -5018,7 +5031,6 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.23.2.tgz", "integrity": "sha512-1kvsBqGNu2ZJ0P/lkxN0pAMqSyUcpkMIzE4xwGUIyAiD0pZV6dr+OCMwGWOTLllSyrn91xI5K7OLk3pYeCPKqA==", "license": "MIT", - "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-commands": "^1.6.2", @@ -5162,7 +5174,6 @@ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.19.0" } @@ -5225,7 +5236,6 @@ "integrity": "sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.58.2", "@typescript-eslint/types": "8.58.2", @@ -6005,7 +6015,6 @@ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", "license": "MIT", - "peer": true, "dependencies": { "@babel/parser": "^7.29.2", "@vue/compiler-core": "3.5.32", @@ -6249,7 +6258,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6637,7 +6645,6 @@ "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.8.2.tgz", "integrity": "sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==", "license": "Apache-2.0", - "peer": true, "peerDependencies": { "bare-abort-controller": "*" }, @@ -6835,7 +6842,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", @@ -6950,7 +6956,6 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=8" } @@ -7145,8 +7150,7 @@ "version": "0.2.2", "resolved": "https://registry.npmjs.org/citty/-/citty-0.2.2.tgz", "integrity": "sha512-+6vJA3L98yv+IdfKGZHBNiGW5KHn22e/JwID0Strsz8h4S/csAu/OuICwxrg44k5MRiZHWIo8XXuJgQTriRP4w==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/clean-regexp": { "version": "1.0.0", @@ -8199,7 +8203,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9358,7 +9361,6 @@ "integrity": "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", @@ -11805,7 +11807,6 @@ "resolved": "https://registry.npmjs.org/nuxt/-/nuxt-4.4.2.tgz", "integrity": "sha512-iWVFpr/YEqVU/CenqIHMnIkvb2HE/9f+q8oxZ+pj2et+60NljGRClCgnmbvGPdmNFE0F1bEhoBCYfqbDOCim3Q==", "license": "MIT", - "peer": true, "dependencies": { "@dxup/nuxt": "^0.4.0", "@nuxt/cli": "^3.34.0", @@ -12864,7 +12865,6 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "license": "MIT", - "peer": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -12922,7 +12922,6 @@ "resolved": "https://registry.npmjs.org/oxc-parser/-/oxc-parser-0.112.0.tgz", "integrity": "sha512-7rQ3QdJwobMQLMZwQaPuPYMEF2fDRZwf51lZ//V+bA37nejjKW5ifMHbbCwvA889Y4RLhT+/wLJpPRhAoBaZYw==", "license": "MIT", - "peer": true, "dependencies": { "@oxc-project/types": "^0.112.0" }, @@ -13189,7 +13188,6 @@ "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", "license": "MIT", - "peer": true, "dependencies": { "@vue/devtools-api": "^7.7.7" }, @@ -13315,7 +13313,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -13859,7 +13856,6 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz", "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==", "license": "MIT", - "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -14650,7 +14646,6 @@ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", "license": "MIT", - "peer": true, "dependencies": { "@types/estree": "1.0.8" }, @@ -15554,7 +15549,6 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", "license": "MIT", - "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -16234,7 +16228,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "napi-postinstall": "^0.3.0" }, @@ -16501,7 +16494,6 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", @@ -17420,7 +17412,6 @@ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", "license": "MIT", - "peer": true, "dependencies": { "@vue/compiler-dom": "3.5.32", "@vue/compiler-sfc": "3.5.32", @@ -17465,7 +17456,6 @@ "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.0", "eslint-scope": "^8.2.0 || ^9.0.0", @@ -17502,7 +17492,6 @@ "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.3.1.tgz", "integrity": "sha512-azq8fhVnCwJAw0iXW7i44h9P+Bj+snNuevBAaJ9bxn0I3YVsRU3deVFPNnTfZ2uxVJefGp83JUmL68ddCPw5Pw==", "license": "MIT", - "peer": true, "dependencies": { "@intlify/core-base": "11.3.1", "@intlify/devtools-types": "11.3.1", -- 2.39.5 From 71ca15e1ec8c9ec1ad20a4ef903f62fc568fc956 Mon Sep 17 00:00:00 2001 From: tristan Date: Fri, 29 May 2026 10:41:54 +0200 Subject: [PATCH 5/5] refactor(catalog) : align categories.vue comments with actual behavior + drop magic h2 size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - categories.vue : commentaires retiraient ce qui n'est pas cable (tri client en miroir, slice pagination) — alignes sur le comportement reel (tri 100% serveur, affichage exhaustif). - CategoryDrawer.vue : `text-[24px]` remplace par `text-2xl` (echelle Tailwind standard). Le retour sur la largeur 150px des boutons d'action est tracke pour ERP-70 (mise a jour @malio/layer-ui : on poussera le token la-bas). --- .../modules/catalog/components/CategoryDrawer.vue | 2 +- frontend/modules/catalog/pages/admin/categories.vue | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/frontend/modules/catalog/components/CategoryDrawer.vue b/frontend/modules/catalog/components/CategoryDrawer.vue index 87d3788..73991f0 100644 --- a/frontend/modules/catalog/components/CategoryDrawer.vue +++ b/frontend/modules/catalog/components/CategoryDrawer.vue @@ -7,7 +7,7 @@ @update:model-value="emit('update:modelValue', $event)" > diff --git a/frontend/modules/catalog/pages/admin/categories.vue b/frontend/modules/catalog/pages/admin/categories.vue index 077d77a..482bce8 100644 --- a/frontend/modules/catalog/pages/admin/categories.vue +++ b/frontend/modules/catalog/pages/admin/categories.vue @@ -13,9 +13,12 @@ - + + ) { /** * Charge la liste des categories. Le serveur exclut les soft-deleted par * defaut (RG-1.08) et trie par name ASC (RG-1.10). Pas de pagination - * serveur (RG : volumetrie ≤ 300, pagination front via MalioDataTable). + * serveur (volumetrie cible <= 300) ni de slice client — toute la liste + * est rendue d'un coup ; la barre du MalioDataTable est donc cosmetique + * jusqu'a la mise a jour layer-ui (ticket ERP-70). * * Logique inline volontaire au M0 (decision prompt ERP-49) : extraction * en composable `useCategoriesAdmin` au ticket 0.8 (ERP-50). -- 2.39.5