Compare commits

...

14 Commits

Author SHA1 Message Date
18cb9d5d80 refactor(infra) : reorganize docker config into infra/dev and infra/prod
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Align project structure with Lesstime: move docker/ to infra/dev/ and
deploy/ to infra/prod/. Update all references in docker-compose,
makefile, CI workflow, Dockerfile, .gitignore and .dockerignore.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 08:11:35 +02:00
gitea-actions
4ba134dd69 chore : bump version to v1.9.9
Some checks failed
Auto Tag Develop / tag (push) Successful in 6s
Build & Push Docker Image / build (push) Successful in 32s
Build Release Artefact / build (push) Failing after 1m27s
2026-04-01 14:18:42 +00:00
Matthieu
5e7a744151 feat : add maintenance mode toggle in admin panel
All checks were successful
Auto Tag Develop / tag (push) Successful in 8s
- Backend: MaintenanceModeListener blocks non-admin API requests when
  var/maintenance flag file exists. MaintenanceController provides
  toggle (PUT /api/admin/maintenance) and public check endpoint
  (GET /api/maintenance/check).
- Frontend: Toggle button in admin page, maintenance.vue page for
  blocked users, middleware redirects non-admins to /maintenance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 16:18:32 +02:00
gitea-actions
044b64152c chore : bump version to v1.9.8
Some checks failed
Auto Tag Develop / tag (push) Successful in 7s
Build & Push Docker Image / build (push) Successful in 36s
Build Release Artefact / build (push) Failing after 1m38s
2026-04-01 12:52:57 +00:00
Matthieu
4de3ffa0e0 chore : trigger auto-tag
All checks were successful
Auto Tag Develop / tag (push) Successful in 9s
2026-04-01 14:52:45 +02:00
Matthieu
5bdf578de9 refactor : migrate VERSION file to config/version.yaml
Some checks failed
Auto Tag Develop / tag (push) Failing after 7s
Same versioning system as SIRH/Lesstime. Updates nuxt.config.ts,
Dockerfile, deploy.sh, auto-tag CI, and release script.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:52:01 +02:00
gitea-actions
bc1b757a96 chore : bump version to v1.9.7
All checks were successful
Auto Tag Develop / tag (push) Successful in 7s
Build & Push Docker Image / build (push) Successful in 18s
Build Release Artefact / build (push) Successful in 2m53s
2026-04-01 12:47:15 +00:00
Matthieu
24b664e85b fix : update frontend/ to latest develop branch content
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
The initial merge only had master content. This replaces frontend/
with the full develop branch including reference-auto, constructeur
links, versioning, and all recent features.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:47:04 +02:00
gitea-actions
8565e68062 chore : bump version to v1.9.6
All checks were successful
Auto Tag Develop / tag (push) Successful in 9s
Build & Push Docker Image / build (push) Successful in 23s
Build Release Artefact / build (push) Successful in 2m5s
2026-04-01 12:36:42 +00:00
Matthieu
a8a95b16a9 fix : mount var/storage/documents volume instead of var/uploads
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:36:30 +02:00
gitea-actions
68b394fc14 chore : bump version to v1.9.5
All checks were successful
Auto Tag Develop / tag (push) Successful in 7s
Build & Push Docker Image / build (push) Successful in 34s
Build Release Artefact / build (push) Successful in 1m41s
2026-04-01 12:28:32 +00:00
Matthieu
2ceb49db9f fix : use REGISTRY_TOKEN instead of RELEASE_TOKEN in CI workflows
Some checks failed
Auto Tag Develop / tag (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:28:20 +02:00
Matthieu
8ad0f26249 feat : add auto-tag and release artefact CI workflows
Some checks failed
Auto Tag Develop / tag (push) Failing after 4s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:23:12 +02:00
Matthieu
be859e57db refactor : rename Inventory_frontend to frontend in docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-01 14:20:19 +02:00
51 changed files with 600 additions and 258 deletions

View File

@@ -2,10 +2,10 @@
.gitea
.env.local
.env.test
docker/
deploy/docker/docker-compose.prod.yml
deploy/docker/deploy.sh
deploy/docker/.env.example
infra/dev/
infra/prod/docker-compose.yml
infra/prod/deploy.sh
infra/prod/.env.example
frontend/node_modules
frontend/.nuxt
frontend/.output

View File

@@ -0,0 +1,65 @@
name: Auto Tag Develop
on:
push:
branches:
- develop
jobs:
tag:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.REGISTRY_TOKEN }}
persist-credentials: true
- name: Create next tag from config/version.yaml
shell: bash
run: |
set -euo pipefail
# Skip if current commit already has a vX.Y.Z tag
if git tag --points-at HEAD | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "Tag already exists on this commit. Skipping."
exit 0
fi
changed_version=false
if git diff --name-only "${{ gitea.event.before }}" "${{ gitea.event.after }}" | grep -q '^config/version\.yaml$'; then
changed_version=true
fi
read_version() {
awk -F': *' '/app\.version:/{print $2}' config/version.yaml | tr -d '[:space:]' | tr -d "'\""
}
if $changed_version; then
version="$(read_version)"
if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid version in version.yaml: $version" >&2
exit 1
fi
else
last_tag="$(git tag -l 'v*' --sort=-v:refname | head -n1 || true)"
if [ -z "$last_tag" ]; then
version="0.1.0"
else
base="${last_tag#v}"
IFS='.' read -r major minor patch <<< "$base"
version="${major}.${minor}.$((patch + 1))"
fi
printf "parameters:\\n app.version: '%s'\\n" "$version" > config/version.yaml
git config user.name "gitea-actions"
git config user.email "gitea-actions@local"
git add config/version.yaml
git commit -m "chore : bump version to v$version" || true
git push origin develop || true
fi
tag="v$version"
git tag "$tag"
git push origin "$tag"

View File

@@ -19,7 +19,7 @@ jobs:
- name: Build Docker image
run: |
docker build \
-f deploy/docker/Dockerfile.prod \
-f infra/prod/Dockerfile \
-t gitea.malio.fr/malio-dev/inventory:${{ gitea.ref_name }} \
-t gitea.malio.fr/malio-dev/inventory:latest \
.

View File

@@ -0,0 +1,67 @@
name: Build Release Artefact
on:
push:
tags:
- "v*"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
extensions: mbstring, intl, pdo_pgsql, xml, curl, zip, gd
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "lts/*"
- name: Install backend deps (prod)
env:
APP_ENV: prod
APP_DEBUG: "0"
run: composer install --no-dev --optimize-autoloader --no-interaction --no-scripts
- name: Build frontend (static)
run: |
cd frontend
npm ci
CI=1 NUXT_TELEMETRY_DISABLED=1 NUXT_PUBLIC_API_BASE_URL=/api NUXT_PUBLIC_APP_BASE=/ npm run generate
test -f .output/public/index.html
- name: Build artefact
shell: bash
run: |
set -euo pipefail
mkdir -p release
tar -czf "release/inventory-${GITHUB_REF_NAME}.tar.gz" \
.env \
bin \
config \
migrations \
public \
src \
templates \
vendor \
composer.json \
composer.lock \
symfony.lock \
VERSION \
frontend/.output
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: release/inventory-${{ github.ref_name }}.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.REGISTRY_TOKEN }}

2
.gitignore vendored
View File

@@ -20,7 +20,7 @@
###< phpunit/phpunit ###
###> docker ###
docker/.env.docker.local
infra/dev/.env.docker.local
###< docker ###
###> migration archives ###
/_archives/

View File

@@ -12,7 +12,7 @@ inventory.malio-dev.fr/api → Backend Symfony (PHP-FPM derrière Nginx)
| Composant | Technologie | Emplacement serveur |
|-----------|-------------|---------------------|
| Backend | Symfony 8 + API Platform | `/var/www/Inventory/` |
| Frontend | Nuxt 4 (site statique) | `/var/www/Inventory/Inventory_frontend/.output/public/` |
| Frontend | Nuxt 4 (site statique) | `/var/www/Inventory/frontend/.output/public/` |
| Base de données | PostgreSQL 16 | Base `inventory` |
### Schéma simplifié
@@ -117,7 +117,7 @@ php bin/console doctrine:migrations:migrate --no-interaction
### 4. Configurer le frontend Nuxt
```bash
cd /var/www/Inventory/Inventory_frontend
cd /var/www/Inventory/frontend
# Permissions
sudo chown -R malio:malio .
@@ -173,7 +173,7 @@ server {
# Frontend statique — tout le reste
location / {
root /var/www/Inventory/Inventory_frontend/.output/public;
root /var/www/Inventory/frontend/.output/public;
index index.html;
try_files $uri $uri/ /index.html; # SPA fallback
}
@@ -214,7 +214,7 @@ php bin/console cache:clear --env=prod
sudo chown -R www-data:www-data var/
# Frontend
cd Inventory_frontend
cd frontend
npm install
npx nuxi generate
```
@@ -268,7 +268,7 @@ php /var/www/Inventory/bin/console cache:clear --env=prod
Les fichiers statiques sont en cache. Rebuilder :
```bash
cd /var/www/Inventory/Inventory_frontend
cd /var/www/Inventory/frontend
rm -rf .output
npx nuxi generate
```
@@ -299,7 +299,7 @@ tail -f /var/www/Inventory/var/log/prod.log
php /var/www/Inventory/bin/console cache:clear --env=prod
# Rebuild frontend
cd /var/www/Inventory/Inventory_frontend && npx nuxi generate
cd /var/www/Inventory/frontend && npx nuxi generate
# Status des services
systemctl status php8.4-fpm

View File

@@ -57,7 +57,7 @@ make start
make install
```
> Si `make start` échoue sur le port de la BDD, modifier `POSTGRES_PORT` dans `docker/.env.docker.local`.
> Si `make start` échoue sur le port de la BDD, modifier `POSTGRES_PORT` dans `infra/dev/.env.docker.local`.
### Que fait `make install` ?
@@ -254,7 +254,7 @@ Configuration PhpStorm / VSCode :
- **Port** : `8081`
- **Path mapping** : racine du projet → `/var/www/html`
> Sous WSL, modifier `XDEBUG_CLIENT_HOST` dans `docker/.env.docker.local` avec votre IP locale.
> Sous WSL, modifier `XDEBUG_CLIENT_HOST` dans `infra/dev/.env.docker.local` avec votre IP locale.
## Git

View File

@@ -59,7 +59,7 @@ Après avoir exécuté le script :
```bash
# Pousser le frontend d'abord (si modifié)
cd Inventory_frontend && git push && git push --tags && cd ..
cd frontend && git push && git push --tags && cd ..
# Pousser le backend
git push && git push --tags
@@ -79,7 +79,7 @@ git push && git push --tags
|---------|------|
| `VERSION` | Source unique de vérité |
| `config/packages/api_platform.yaml` | Version affichée dans la doc API (Swagger) |
| `Inventory_frontend/nuxt.config.ts` | Lit `VERSION` au build pour l'afficher dans le footer |
| `frontend/nuxt.config.ts` | Lit `VERSION` au build pour l'afficher dans le footer |
| Footer de l'app | Affiche `v{{ appVersion }}` |
## Notes de release
@@ -118,5 +118,5 @@ git submodule update --init --recursive
composer install --no-dev --optimize-autoloader
php bin/console doctrine:migrations:migrate --no-interaction
php bin/console cache:clear --env=prod
cd Inventory_frontend && npm install && npx nuxi generate
cd frontend && npm install && npx nuxi generate
```

View File

@@ -1 +0,0 @@
1.9.4

View File

@@ -1,7 +1,7 @@
api_platform:
title: Inventory API
description: API de gestion d'inventaire industriel — machines, pièces, composants, produits.
version: 1.9.1
version: 1.9.6
defaults:
stateless: false
cache_headers:

View File

@@ -55,6 +55,7 @@ security:
- { path: ^/api/admin, roles: ROLE_ADMIN }
- { path: ^/api/docs, roles: PUBLIC_ACCESS }
- { path: ^/api/health$, roles: PUBLIC_ACCESS }
- { path: ^/api/maintenance/check$, roles: PUBLIC_ACCESS }
- { path: ^/_mcp, roles: ROLE_USER }
- { path: ^/docs, roles: PUBLIC_ACCESS }
- { path: ^/contexts, roles: PUBLIC_ACCESS }

2
config/version.yaml Normal file
View File

@@ -0,0 +1,2 @@
parameters:
app.version: '1.9.9'

View File

@@ -2,7 +2,7 @@ services:
web:
container_name: php-${DOCKER_APP_NAME}-apache
build:
context: ./docker/php
context: ./infra/dev
dockerfile: Dockerfile
args:
DOCKER_PHP_VERSION: ${DOCKER_PHP_VERSION}
@@ -20,9 +20,9 @@ services:
- ~/.cache:/var/www/.cache # Pour la cache de composer
- ~/.config:/var/www/.config # Pour la config de yarn
- ~/.composer:/var/www/.composer # Pour la config de composer
- ./docker/php/config/php.ini:/usr/local/etc/php/php.ini
- ./docker/php/config/vhost.conf:/etc/apache2/sites-available/000-default.conf
- ./docker/php/config/docker-php-ext-xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
- ./infra/dev/php.ini:/usr/local/etc/php/php.ini
- ./infra/dev/vhost.conf:/etc/apache2/sites-available/000-default.conf
- ./infra/dev/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
- ./LOG:/var/www/html/LOG
- ./LOG/logs_apache:/var/log/apache2/
extra_hosts:

View File

@@ -103,10 +103,10 @@ Cela securise l'integrite sans changer l'architecture. Le `resolveTarget` et les
### 3. Composables frontend geants (400-550 LOC)
**Fichiers concernes :**
- `/Inventory_frontend/app/composables/useComponentEdit.ts` (550 LOC)
- `/Inventory_frontend/app/composables/usePieceEdit.ts` (472 LOC)
- `/Inventory_frontend/app/composables/useMachineDetailData.ts` (468 LOC)
- `/Inventory_frontend/app/composables/useComponentCreate.ts` (417 LOC)
- `/frontend/app/composables/useComponentEdit.ts` (550 LOC)
- `/frontend/app/composables/usePieceEdit.ts` (472 LOC)
- `/frontend/app/composables/useMachineDetailData.ts` (468 LOC)
- `/frontend/app/composables/useComponentCreate.ts` (417 LOC)
**Probleme :** Ces composables orchestrent en un seul fichier : le chargement de donnees, la gestion de formulaire, la persistence des custom fields, la gestion des documents, l'historique, la resolution de labels, et la soumission. Chacun instancie 8-12 sous-composables.
@@ -134,9 +134,9 @@ Appliquer le meme pattern a `usePieceEdit` et `useComponentCreate`. Les blocs co
### 4. Triple duplication de la logique custom fields frontend
**Fichiers concernes :**
- `/Inventory_frontend/app/shared/utils/customFieldFormUtils.ts` (404 LOC) - pour les pages create/edit
- `/Inventory_frontend/app/shared/utils/customFieldUtils.ts` (440 LOC) - pour la page machine detail
- `/Inventory_frontend/app/shared/utils/entityCustomFieldLogic.ts` (335 LOC) - pour les composants item
- `/frontend/app/shared/utils/customFieldFormUtils.ts` (404 LOC) - pour les pages create/edit
- `/frontend/app/shared/utils/customFieldUtils.ts` (440 LOC) - pour la page machine detail
- `/frontend/app/shared/utils/entityCustomFieldLogic.ts` (335 LOC) - pour les composants item
**Probleme :** Ces 3 fichiers resolvent le meme probleme (normaliser des definitions de custom fields + merger avec des valeurs existantes) avec des implementations differentes :
- `customFieldFormUtils.ts` : `resolveFieldName()`, `resolveFieldType()`, `buildCustomFieldInputs()`
@@ -273,7 +273,7 @@ public function process(mixed $data, Operation $operation, ...): mixed
### 9. Dependance circulaire dans `useMachineDetailData`
**Fichier concerne :**
- `/Inventory_frontend/app/composables/useMachineDetailData.ts` (lignes 119-187)
- `/frontend/app/composables/useMachineDetailData.ts` (lignes 119-187)
**Probleme :** `useMachineDetailProducts` a besoin de `machineProductLinks` (venant de hierarchy), et `useMachineDetailHierarchy` a besoin de `findProductById` (venant de products). La solution actuelle utilise un `_machineProductLinksProxy` ref avec un watcher pour synchroniser.

View File

@@ -811,9 +811,9 @@ private function resolvePieceQuantity(MachinePieceLink $pieceLink): int
### Task 2.5: Update Frontend to Handle New Structure Format
**Files:**
- Modify: `Inventory_frontend/app/composables/useMachineHierarchy.ts``buildMachineHierarchyFromLinks()`
- Modify: `Inventory_frontend/app/shared/utils/structureDisplayUtils.ts`
- Modify: `Inventory_frontend/app/shared/utils/structureSelectionUtils.ts`
- Modify: `frontend/app/composables/useMachineHierarchy.ts``buildMachineHierarchyFromLinks()`
- Modify: `frontend/app/shared/utils/structureDisplayUtils.ts`
- Modify: `frontend/app/shared/utils/structureSelectionUtils.ts`
**Note:** The API response shape for `structure` stays the same (pieces/subcomponents/products arrays), so frontend changes should be minimal. The main change is that `path` fields are removed and `resolvedPiece` is now always populated inline.
@@ -950,7 +950,7 @@ ALTER TABLE pieces DROP COLUMN IF EXISTS productids;
### Task 4.1: Update Frontend Types
**Files:**
- Modify: `Inventory_frontend/app/shared/types/` (if type definitions reference structure/skeleton JSON shapes)
- Modify: `frontend/app/shared/types/` (if type definitions reference structure/skeleton JSON shapes)
- [ ] **Step 1: Search frontend for all references to `structure.pieces`, `structure.subcomponents`, `structure.products`, `skeleton`, `productIds`**

View File

@@ -274,15 +274,15 @@ git commit -m "test(piece) : add quantity tests for MachinePieceLink"
### Task 4: TypeScript Types + Sanitization + Hydration Functions
**Files:**
- Modify: `Inventory_frontend/app/shared/types/inventory.ts`
- Modify: `Inventory_frontend/app/shared/model/componentStructure.ts`
- Modify: `Inventory_frontend/app/shared/model/componentStructureSanitize.ts`
- Modify: `Inventory_frontend/app/shared/model/componentStructureHydrate.ts`
- Modify: `Inventory_frontend/app/shared/utils/structureAssignmentHelpers.ts`
- Modify: `frontend/app/shared/types/inventory.ts`
- Modify: `frontend/app/shared/model/componentStructure.ts`
- Modify: `frontend/app/shared/model/componentStructureSanitize.ts`
- Modify: `frontend/app/shared/model/componentStructureHydrate.ts`
- Modify: `frontend/app/shared/utils/structureAssignmentHelpers.ts`
- [ ] **Step 1: Add `quantity` to `ComponentModelPiece` type**
In `Inventory_frontend/app/shared/types/inventory.ts`, add `quantity` to the `ComponentModelPiece` interface (after `role`, line ~23):
In `frontend/app/shared/types/inventory.ts`, add `quantity` to the `ComponentModelPiece` interface (after `role`, line ~23):
```typescript
quantity?: number
@@ -290,7 +290,7 @@ quantity?: number
- [ ] **Step 2: Add `quantity` to `validatePiece()` in same file**
In `Inventory_frontend/app/shared/types/inventory.ts`, in `validatePiece()` (line ~144-172):
In `frontend/app/shared/types/inventory.ts`, in `validatePiece()` (line ~144-172):
After `const role = ensureString(value.role)` (line ~161), add:
@@ -306,7 +306,7 @@ And in the return object, add after the `role` spread:
- [ ] **Step 3: Update `sanitizePieces()` to preserve quantity**
In `Inventory_frontend/app/shared/model/componentStructureSanitize.ts`, in `sanitizePieces()` (~line 130-188).
In `frontend/app/shared/model/componentStructureSanitize.ts`, in `sanitizePieces()` (~line 130-188).
After the existing field extractions, add:
@@ -324,7 +324,7 @@ if (quantity !== undefined) {
- [ ] **Step 4: Update `normalizeStructureForSave()` to include quantity**
In `Inventory_frontend/app/shared/model/componentStructure.ts`, in `normalizeStructureForSave()` (~lines 164-179), add in the piece payload mapping after the `reference` check:
In `frontend/app/shared/model/componentStructure.ts`, in `normalizeStructureForSave()` (~lines 164-179), add in the piece payload mapping after the `reference` check:
```typescript
if ((piece as any).quantity !== undefined && (piece as any).quantity >= 1) {
@@ -336,7 +336,7 @@ if ((piece as any).quantity !== undefined && (piece as any).quantity >= 1) {
- [ ] **Step 5: Update `hydratePieces()` and `mapComponentPieces()` to preserve quantity**
In `Inventory_frontend/app/shared/model/componentStructureHydrate.ts`:
In `frontend/app/shared/model/componentStructureHydrate.ts`:
In `hydratePieces()` (line ~95-107), add to the mapped object:
@@ -352,7 +352,7 @@ In `mapComponentPieces()` (line ~168-179), add to the mapped object:
- [ ] **Step 6: Update `sanitizePieceDefinition()` to preserve quantity**
In `Inventory_frontend/app/shared/utils/structureAssignmentHelpers.ts`, in `sanitizePieceDefinition()` (~lines 172-180), add to the `stripNullish()` object:
In `frontend/app/shared/utils/structureAssignmentHelpers.ts`, in `sanitizePieceDefinition()` (~lines 172-180), add to the `stripNullish()` object:
```typescript
quantity: typeof (definition as any).quantity === 'number' ? (definition as any).quantity : null,
@@ -361,14 +361,14 @@ quantity: typeof (definition as any).quantity === 'number' ? (definition as any)
- [ ] **Step 7: Run lint + typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
Expected: 0 errors
- [ ] **Step 8: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/shared/types/inventory.ts app/shared/model/componentStructure.ts app/shared/model/componentStructureSanitize.ts app/shared/model/componentStructureHydrate.ts app/shared/utils/structureAssignmentHelpers.ts
git commit -m "feat(piece) : add quantity field to piece types, sanitization and hydration"
```
@@ -378,14 +378,14 @@ git commit -m "feat(piece) : add quantity field to piece types, sanitization and
### Task 5: Composant Structure Editor — Quantity Input
**Files:**
- Modify: `Inventory_frontend/app/components/StructureNodeEditor.vue` (piece section, lines ~229-299)
- Modify: `Inventory_frontend/app/composables/useStructureNodeCrud.ts` (`addPiece()`, lines ~110-118)
- Modify: `frontend/app/components/StructureNodeEditor.vue` (piece section, lines ~229-299)
- Modify: `frontend/app/composables/useStructureNodeCrud.ts` (`addPiece()`, lines ~110-118)
**Context:** `StructureNodeEditor.vue` renders the composant structure editor. The piece section (lines ~236-293) currently shows only a `select` for `typePieceId` and a delete button. The `addPiece()` function in `useStructureNodeCrud.ts` creates new piece entries with default fields.
- [ ] **Step 1: Add default quantity to `addPiece()`**
In `Inventory_frontend/app/composables/useStructureNodeCrud.ts`, in `addPiece()` (line ~110-118), add `quantity: 1` to the pushed object:
In `frontend/app/composables/useStructureNodeCrud.ts`, in `addPiece()` (line ~110-118), add `quantity: 1` to the pushed object:
```typescript
const addPiece = () => {
@@ -403,7 +403,7 @@ const addPiece = () => {
- [ ] **Step 2: Add quantity input in `StructureNodeEditor.vue`**
In `Inventory_frontend/app/components/StructureNodeEditor.vue`, in the piece item rendering section (inside the `v-for` loop for pieces, line ~256-292), add a quantity input next to the existing piece type `select`. Place it after the select and before the delete button:
In `frontend/app/components/StructureNodeEditor.vue`, in the piece item rendering section (inside the `v-for` loop for pieces, line ~256-292), add a quantity input next to the existing piece type `select`. Place it after the select and before the delete button:
```vue
<input
@@ -420,14 +420,14 @@ In `Inventory_frontend/app/components/StructureNodeEditor.vue`, in the piece ite
- [ ] **Step 3: Run lint + typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
Expected: 0 errors
- [ ] **Step 4: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/StructureNodeEditor.vue app/composables/useStructureNodeCrud.ts
git commit -m "feat(piece) : add quantity input to composant structure editor"
```
@@ -437,13 +437,13 @@ git commit -m "feat(piece) : add quantity input to composant structure editor"
### Task 6: Machine Detail Page — Display Quantity
**Files:**
- Modify: `Inventory_frontend/app/components/PieceItem.vue`
- Modify: `frontend/app/components/PieceItem.vue`
**Context:** `PieceItem.vue` renders each piece in the machine structure view. The piece name is displayed at line ~26 in an `<h3>` tag. Quantity should appear as "×N" after the name, in secondary text. For direct pieces (no parent component), it should be editable. For composant pieces, read-only.
- [ ] **Step 1: Add quantity display to PieceItem**
In `Inventory_frontend/app/components/PieceItem.vue`, after the piece name in the `<h3>` tag (line ~26), add the quantity display:
In `frontend/app/components/PieceItem.vue`, after the piece name in the `<h3>` tag (line ~26), add the quantity display:
```vue
<span
@@ -492,14 +492,14 @@ Ensure this value is included in the data emitted when saving (follow the same p
- [ ] **Step 3: Run lint + typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
Expected: 0 errors
- [ ] **Step 4: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/PieceItem.vue
git commit -m "feat(piece) : display and edit quantity on machine piece items"
```
@@ -514,14 +514,14 @@ git commit -m "feat(piece) : display and edit quantity on machine piece items"
- [ ] **Step 1: Push frontend commits**
```bash
cd Inventory_frontend && git push
cd frontend && git push
```
- [ ] **Step 2: Update submodule pointer in main repo**
```bash
cd /home/matthieu/dev_malio/Inventory
git add Inventory_frontend
git add frontend
git commit -m "chore(frontend) : update submodule — piece quantity feature"
```

View File

@@ -1346,13 +1346,13 @@ git commit -m "feat(sync) : add ModelTypeSyncController with preview and sync en
### Task 12: Delete `useCategoryEditGuard` composable and tests
**Files:**
- Delete: `Inventory_frontend/app/composables/useCategoryEditGuard.ts`
- Delete: `Inventory_frontend/tests/composables/useCategoryEditGuard.test.ts`
- Delete: `frontend/app/composables/useCategoryEditGuard.ts`
- Delete: `frontend/tests/composables/useCategoryEditGuard.test.ts`
- [ ] **Step 1: Delete files + commit**
```bash
cd Inventory_frontend
cd frontend
rm app/composables/useCategoryEditGuard.ts tests/composables/useCategoryEditGuard.test.ts
git add -A && git commit -m "refactor(sync) : remove useCategoryEditGuard composable and tests"
```
@@ -1362,25 +1362,25 @@ git add -A && git commit -m "refactor(sync) : remove useCategoryEditGuard compos
### Task 13: Remove restrictedMode from structure editors and composables
**Files:**
- Modify: `Inventory_frontend/app/components/StructureNodeEditor.vue` — remove `restrictedMode` prop, `v-if="!restrictedMode"` guards
- Modify: `Inventory_frontend/app/components/PieceModelStructureEditor.vue` — same
- Modify: `Inventory_frontend/app/components/ComponentModelStructureEditor.vue` — remove prop forwarding
- Modify: `Inventory_frontend/app/composables/useStructureNodeCrud.ts` — remove `restrictedMode` from props, remove `isExisting*` guards, remove `initial*Indices`
- Modify: `Inventory_frontend/app/composables/useStructureNodeLogic.ts` — remove from props, computed, and crud call
- Modify: `Inventory_frontend/app/composables/usePieceStructureEditorLogic.ts` — remove from props, remove `isExisting*` guards
- Modify: `frontend/app/components/StructureNodeEditor.vue` — remove `restrictedMode` prop, `v-if="!restrictedMode"` guards
- Modify: `frontend/app/components/PieceModelStructureEditor.vue` — same
- Modify: `frontend/app/components/ComponentModelStructureEditor.vue` — remove prop forwarding
- Modify: `frontend/app/composables/useStructureNodeCrud.ts` — remove `restrictedMode` from props, remove `isExisting*` guards, remove `initial*Indices`
- Modify: `frontend/app/composables/useStructureNodeLogic.ts` — remove from props, computed, and crud call
- Modify: `frontend/app/composables/usePieceStructureEditorLogic.ts` — remove from props, remove `isExisting*` guards
- [ ] **Step 1: Remove from each file** (read each file first, then edit)
- [ ] **Step 2: Run lint + typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend && git add -A && git commit -m "refactor(sync) : remove restrictedMode from structure editors and composables"
cd frontend && git add -A && git commit -m "refactor(sync) : remove restrictedMode from structure editors and composables"
```
---
@@ -1388,24 +1388,24 @@ cd Inventory_frontend && git add -A && git commit -m "refactor(sync) : remove re
### Task 14: Remove restrictedMode from ModelTypeForm and edit pages
**Files:**
- Modify: `Inventory_frontend/app/components/model-types/ModelTypeForm.vue` — remove `restrictedMode`, `disableSubmit`, `disableSubmitMessage`, `restrictedModeMessage` props and warning banner
- Modify: `Inventory_frontend/app/pages/component-category/[id]/edit.vue` — remove `useCategoryEditGuard` import/usage, guard props from `<ModelTypeForm>`
- Modify: `Inventory_frontend/app/pages/piece-category/[id]/edit.vue` — same
- Modify: `Inventory_frontend/app/pages/product-category/[id]/edit.vue` — same
- Modify: `Inventory_frontend/tests/components/PieceModelStructureEditor.test.ts` — remove `restrictedMode: true` test cases
- Modify: `frontend/app/components/model-types/ModelTypeForm.vue` — remove `restrictedMode`, `disableSubmit`, `disableSubmitMessage`, `restrictedModeMessage` props and warning banner
- Modify: `frontend/app/pages/component-category/[id]/edit.vue` — remove `useCategoryEditGuard` import/usage, guard props from `<ModelTypeForm>`
- Modify: `frontend/app/pages/piece-category/[id]/edit.vue` — same
- Modify: `frontend/app/pages/product-category/[id]/edit.vue` — same
- Modify: `frontend/tests/components/PieceModelStructureEditor.test.ts` — remove `restrictedMode: true` test cases
- [ ] **Step 1: Clean each file** (read first, then edit)
- [ ] **Step 2: Run lint + typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend && git add -A && git commit -m "refactor(sync) : remove restrictedMode from ModelTypeForm and category edit pages"
cd frontend && git add -A && git commit -m "refactor(sync) : remove restrictedMode from ModelTypeForm and category edit pages"
```
---
@@ -1415,11 +1415,11 @@ cd Inventory_frontend && git add -A && git commit -m "refactor(sync) : remove re
### Task 15: Add sync service functions
**Files:**
- Modify: `Inventory_frontend/app/services/modelTypes.ts`
- Modify: `frontend/app/services/modelTypes.ts`
- [ ] **Step 1: Add `syncPreview` and `syncExecute`**
Add to the end of `Inventory_frontend/app/services/modelTypes.ts`:
Add to the end of `frontend/app/services/modelTypes.ts`:
```typescript
export function syncPreview(id: string, structure: unknown, opts: { signal?: AbortSignal } = {}) {
@@ -1466,7 +1466,7 @@ export function syncExecute(id: string, confirmation: { confirmDeletions: boolea
- [ ] **Step 2: Run lint + typecheck + commit**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
git add -A && git commit -m "feat(sync) : add syncPreview and syncExecute service functions"
```
@@ -1475,7 +1475,7 @@ git add -A && git commit -m "feat(sync) : add syncPreview and syncExecute servic
### Task 16: Create SyncConfirmationModal component
**Files:**
- Create: `Inventory_frontend/app/components/SyncConfirmationModal.vue`
- Create: `frontend/app/components/SyncConfirmationModal.vue`
- [ ] **Step 1: Create the modal**
@@ -1487,7 +1487,7 @@ Emits: `confirm`, `cancel`
- [ ] **Step 2: Run lint + typecheck + commit**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
git add -A && git commit -m "feat(sync) : add SyncConfirmationModal component"
```
@@ -1496,9 +1496,9 @@ git add -A && git commit -m "feat(sync) : add SyncConfirmationModal component"
### Task 17: Wire sync flow into category edit pages
**Files:**
- Modify: `Inventory_frontend/app/pages/component-category/[id]/edit.vue`
- Modify: `Inventory_frontend/app/pages/piece-category/[id]/edit.vue`
- Modify: `Inventory_frontend/app/pages/product-category/[id]/edit.vue`
- Modify: `frontend/app/pages/component-category/[id]/edit.vue`
- Modify: `frontend/app/pages/piece-category/[id]/edit.vue`
- Modify: `frontend/app/pages/product-category/[id]/edit.vue`
- [ ] **Step 1: Update `component-category/[id]/edit.vue`**
@@ -1524,13 +1524,13 @@ Same flow, adapt imports and routes.
- [ ] **Step 4: Run lint + typecheck + build**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck && npm run build
cd frontend && npm run lint:fix && npx nuxi typecheck && npm run build
```
- [ ] **Step 5: Commit**
```bash
cd Inventory_frontend && git add -A && git commit -m "feat(sync) : wire sync flow into category edit pages with confirmation modal"
cd frontend && git add -A && git commit -m "feat(sync) : wire sync flow into category edit pages with confirmation modal"
```
---
@@ -1547,7 +1547,7 @@ Expected: All tests pass.
- [ ] **Step 2: Run frontend checks**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck && npm run build
cd frontend && npm run lint:fix && npx nuxi typecheck && npm run build
```
- [ ] **Step 3: Run php-cs-fixer**
@@ -1561,7 +1561,7 @@ Run: `make php-cs-fixer-allow-risky`
- [ ] **Step 1: Update frontend submodule**
```bash
git add Inventory_frontend
git add frontend
git commit -m "chore(submodule) : update frontend pointer for sync feature"
```

View File

@@ -574,7 +574,7 @@ git commit -m "test(comments) : add tests for comment creation with file attachm
### Task 6: Frontend — update useComments composable
**Files:**
- Modify: `Inventory_frontend/app/composables/useComments.ts`
- Modify: `frontend/app/composables/useComments.ts`
- [ ] **Step 1: Add document type to Comment interface**
@@ -661,12 +661,12 @@ const createComment = async (
- [ ] **Step 3: Run lint + typecheck**
Run: `cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck`
Run: `cd frontend && npm run lint:fix && npx nuxi typecheck`
- [ ] **Step 4: Commit (in frontend submodule)**
```bash
cd Inventory_frontend
cd frontend
git add app/composables/useComments.ts
git commit -m "feat(comments) : support file attachments in createComment"
```
@@ -676,7 +676,7 @@ git commit -m "feat(comments) : support file attachments in createComment"
### Task 7: Frontend — update CommentSection.vue
**Files:**
- Modify: `Inventory_frontend/app/components/CommentSection.vue`
- Modify: `frontend/app/components/CommentSection.vue`
- [ ] **Step 1: Add file input and file list display to the template**
@@ -810,12 +810,12 @@ const handleSubmit = async () => {
- [ ] **Step 3: Run lint + typecheck**
Run: `cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck`
Run: `cd frontend && npm run lint:fix && npx nuxi typecheck`
- [ ] **Step 4: Commit (in frontend submodule)**
```bash
cd Inventory_frontend
cd frontend
git add app/components/CommentSection.vue
git commit -m "feat(comments) : add file attachment UI to CommentSection"
```
@@ -848,7 +848,7 @@ git commit -m "feat(documents) : add comment ExistsFilter"
- [ ] **Step 4: Update submodule pointer**
```bash
git add Inventory_frontend
git add frontend
git commit -m "chore(submodule) : update frontend pointer (comment documents feature)"
```

View File

@@ -22,15 +22,15 @@
- `src/Controller/DocumentQueryController.php` — add `type` to `normalizeDocuments()`
### Frontend (create)
- `Inventory_frontend/app/shared/documentTypes.ts` — type constants + labels
- `Inventory_frontend/app/components/DocumentEditModal.vue` — mini-modal for editing name+type
- `frontend/app/shared/documentTypes.ts` — type constants + labels
- `frontend/app/components/DocumentEditModal.vue` — mini-modal for editing name+type
### Frontend (modify)
- `Inventory_frontend/app/composables/useDocuments.ts` — add `type` to interface + `updateDocument()` method
- `Inventory_frontend/app/components/DocumentUpload.vue` — add type select
- `Inventory_frontend/app/components/common/DocumentListInline.vue` — add type badge + edit button
- `Inventory_frontend/app/composables/useEntityDocuments.ts` — add `updateDocument` delegation
- `Inventory_frontend/app/pages/documents.vue` — add type column + edit button
- `frontend/app/composables/useDocuments.ts` — add `type` to interface + `updateDocument()` method
- `frontend/app/components/DocumentUpload.vue` — add type select
- `frontend/app/components/common/DocumentListInline.vue` — add type badge + edit button
- `frontend/app/composables/useEntityDocuments.ts` — add `updateDocument` delegation
- `frontend/app/pages/documents.vue` — add type column + edit button
---
@@ -266,13 +266,13 @@ git commit -m "feat(documents) : accept type on upload + expose in query control
### Task 4: Frontend — Type Constants + Document Interface
**Files:**
- Create: `Inventory_frontend/app/shared/documentTypes.ts`
- Modify: `Inventory_frontend/app/composables/useDocuments.ts:6-27` (Document interface), `useDocuments.ts:205-253` (upload)
- Create: `frontend/app/shared/documentTypes.ts`
- Modify: `frontend/app/composables/useDocuments.ts:6-27` (Document interface), `useDocuments.ts:205-253` (upload)
- [ ] **Step 1: Create documentTypes.ts**
```typescript
// Inventory_frontend/app/shared/documentTypes.ts
// frontend/app/shared/documentTypes.ts
export const DOCUMENT_TYPES = [
{ value: 'documentation', label: 'Documentation' },
{ value: 'devis', label: 'Devis' },
@@ -355,12 +355,12 @@ Add `updateDocument` to the return object.
- [ ] **Step 5: Run lint**
Run: `cd Inventory_frontend && npm run lint:fix`
Run: `cd frontend && npm run lint:fix`
- [ ] **Step 6: Commit frontend**
```bash
cd Inventory_frontend
cd frontend
git add app/shared/documentTypes.ts app/composables/useDocuments.ts
git commit -m "feat(documents) : add document type constants and updateDocument method"
```
@@ -370,7 +370,7 @@ git commit -m "feat(documents) : add document type constants and updateDocument
### Task 5: Frontend — DocumentUpload Type Select
**Files:**
- Modify: `Inventory_frontend/app/components/DocumentUpload.vue`
- Modify: `frontend/app/components/DocumentUpload.vue`
- [ ] **Step 1: Add type prop and select to DocumentUpload**
@@ -419,12 +419,12 @@ Note: since DocumentUpload uses `<script setup>` without `lang="ts"`, use `@chan
- [ ] **Step 2: Run lint**
Run: `cd Inventory_frontend && npm run lint:fix`
Run: `cd frontend && npm run lint:fix`
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/DocumentUpload.vue
git commit -m "feat(documents) : add type select to DocumentUpload component"
```
@@ -434,7 +434,7 @@ git commit -m "feat(documents) : add type select to DocumentUpload component"
### Task 6: Frontend — DocumentEditModal
**Files:**
- Create: `Inventory_frontend/app/components/DocumentEditModal.vue`
- Create: `frontend/app/components/DocumentEditModal.vue`
- [ ] **Step 1: Create DocumentEditModal component**
@@ -533,12 +533,12 @@ const save = () => {
- [ ] **Step 2: Run lint**
Run: `cd Inventory_frontend && npm run lint:fix`
Run: `cd frontend && npm run lint:fix`
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/DocumentEditModal.vue
git commit -m "feat(documents) : add DocumentEditModal component"
```
@@ -548,8 +548,8 @@ git commit -m "feat(documents) : add DocumentEditModal component"
### Task 7: Frontend — DocumentListInline + Type Badge + Edit Button
**Files:**
- Modify: `Inventory_frontend/app/components/common/DocumentListInline.vue`
- Modify: `Inventory_frontend/app/composables/useEntityDocuments.ts`
- Modify: `frontend/app/components/common/DocumentListInline.vue`
- Modify: `frontend/app/composables/useEntityDocuments.ts`
- [ ] **Step 1: Add type badge and edit button to DocumentListInline**
@@ -622,12 +622,12 @@ Add `editDocument` to the return object.
- [ ] **Step 3: Run lint**
Run: `cd Inventory_frontend && npm run lint:fix`
Run: `cd frontend && npm run lint:fix`
- [ ] **Step 4: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/common/DocumentListInline.vue app/composables/useEntityDocuments.ts
git commit -m "feat(documents) : add type badge and edit button to DocumentListInline"
```
@@ -637,11 +637,11 @@ git commit -m "feat(documents) : add type badge and edit button to DocumentListI
### Task 8: Frontend — Wire Edit Modal in Entity Pages
**Files:**
- Modify: `Inventory_frontend/app/components/ComponentItem.vue`
- Modify: `Inventory_frontend/app/components/PieceItem.vue`
- Modify: `Inventory_frontend/app/pages/pieces/[id]/edit.vue`
- Modify: `Inventory_frontend/app/pages/component/[id]/edit.vue`
- Modify: `Inventory_frontend/app/pages/product/[id]/edit.vue`
- Modify: `frontend/app/components/ComponentItem.vue`
- Modify: `frontend/app/components/PieceItem.vue`
- Modify: `frontend/app/pages/pieces/[id]/edit.vue`
- Modify: `frontend/app/pages/component/[id]/edit.vue`
- Modify: `frontend/app/pages/product/[id]/edit.vue`
- [ ] **Step 1: Wire in ComponentItem and PieceItem**
@@ -688,12 +688,12 @@ Pass `type: uploadDocType.value` in the upload context when calling `handleFiles
- [ ] **Step 4: Run lint + typecheck**
Run: `cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck`
Run: `cd frontend && npm run lint:fix && npx nuxi typecheck`
- [ ] **Step 5: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/ app/pages/
git commit -m "feat(documents) : wire DocumentEditModal and type select in all entity pages"
```
@@ -703,7 +703,7 @@ git commit -m "feat(documents) : wire DocumentEditModal and type select in all e
### Task 9: Frontend — Documents Global Page
**Files:**
- Modify: `Inventory_frontend/app/pages/documents.vue`
- Modify: `frontend/app/pages/documents.vue`
- [ ] **Step 1: Add type column to DataTable**
@@ -765,12 +765,12 @@ Pass `typeFilter` to `fetchDocuments` → `loadDocuments` as a new filter param,
- [ ] **Step 4: Run lint + typecheck**
Run: `cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck`
Run: `cd frontend && npm run lint:fix && npx nuxi typecheck`
- [ ] **Step 5: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/pages/documents.vue app/composables/useDocuments.ts
git commit -m "feat(documents) : add type column, filter, and edit to documents page"
```
@@ -789,7 +789,7 @@ Expected: all tests pass
- [ ] **Step 2: Run full frontend checks**
Run: `cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck && npm run build`
Run: `cd frontend && npm run lint:fix && npx nuxi typecheck && npm run build`
Expected: 0 errors
- [ ] **Step 3: Manual verification**
@@ -804,6 +804,6 @@ Expected: 0 errors
```bash
cd /home/matthieu/dev_malio/Inventory
git add Inventory_frontend
git add frontend
git commit -m "chore(submodule) : update frontend pointer (document types feature)"
```

View File

@@ -19,9 +19,9 @@
| T3 | Modify | `src/Service/ModelTypeCategoryConversionService.php:195-236` |
| T3 | Modify | `src/Service/ModelTypeCategoryConversionService.php:340-405` |
| T4 | Modify | `src/Controller/CustomFieldValueController.php:199-211` |
| T5 | Modify | `Inventory_frontend/app/composables/useComponentEdit.ts:398-405` |
| T5 | Modify | `Inventory_frontend/app/composables/usePieceEdit.ts:407-414` |
| T6 | Modify | `Inventory_frontend/app/composables/useComponentCreate.ts` (same pattern if present) |
| T5 | Modify | `frontend/app/composables/useComponentEdit.ts:398-405` |
| T5 | Modify | `frontend/app/composables/usePieceEdit.ts:407-414` |
| T6 | Modify | `frontend/app/composables/useComponentCreate.ts` (same pattern if present) |
---
@@ -347,8 +347,8 @@ git commit -m "fix(custom-fields) : prevent creation of orphan CustomField witho
Consequence : le `definitionMap` est toujours vide, les champs perso sans `customFieldId` existant ne trouvent pas leur definition et sont envoyes sans `definitionId` (fallback sur metadata = CustomField orphelin cote backend = Task 4).
**Files:**
- Modify: `Inventory_frontend/app/composables/useComponentEdit.ts:401-403`
- Modify: `Inventory_frontend/app/composables/usePieceEdit.ts:410-412`
- Modify: `frontend/app/composables/useComponentEdit.ts:401-403`
- Modify: `frontend/app/composables/usePieceEdit.ts:410-412`
- [ ] **Step 1: Fix useComponentEdit.ts**
@@ -387,13 +387,13 @@ Verifier `useComponentCreate.ts`, `pieces/create.vue`, `product/[id]/edit.vue` p
- [ ] **Step 4: Lint + typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
- [ ] **Step 5: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/composables/useComponentEdit.ts app/composables/usePieceEdit.ts
git commit -m "fix(custom-fields) : use structure.customFields path for definition lookup"
```

View File

@@ -15,7 +15,7 @@
### Task 1: Multi-select site checkboxes on Parc Machines
**Files:**
- Modify: `Inventory_frontend/app/pages/machines/index.vue`
- Modify: `frontend/app/pages/machines/index.vue`
- [ ] **Step 1: Replace `selectedSite` ref with reactive Set**
@@ -90,14 +90,14 @@ Open `http://localhost:3001/machines`. Confirm:
- [ ] **Step 7: Run frontend lint**
Run: `cd Inventory_frontend && npm run lint:fix`
Run: `cd frontend && npm run lint:fix`
---
### Task 2: Alphabetical sorting on Parc Machines
**Files:**
- Modify: `Inventory_frontend/app/pages/machines/index.vue`
- Modify: `frontend/app/pages/machines/index.vue`
- [ ] **Step 1: Add sort to `filteredMachines` computed**
@@ -140,7 +140,7 @@ Open `http://localhost:3001/machines`. Confirm machines are sorted A→Z by name
- [ ] **Step 3: Commit Tasks 1 + 2**
```bash
cd Inventory_frontend && git add app/pages/machines/index.vue && git commit -m "feat(machines) : multi-select site checkboxes + alphabetical sort"
cd frontend && git add app/pages/machines/index.vue && git commit -m "feat(machines) : multi-select site checkboxes + alphabetical sort"
```
---
@@ -342,9 +342,9 @@ git add src/Doctrine/SearchByNameOrReferenceExtension.php tests/Api/FilterTest.p
### Task 4: Frontend — Switch composables from `name` to `q`
**Files:**
- Modify: `Inventory_frontend/app/composables/usePieces.ts`
- Modify: `Inventory_frontend/app/composables/useComposants.ts`
- Modify: `Inventory_frontend/app/composables/useProducts.ts`
- Modify: `frontend/app/composables/usePieces.ts`
- Modify: `frontend/app/composables/useComposants.ts`
- Modify: `frontend/app/composables/useProducts.ts`
- [ ] **Step 1: Update `usePieces.ts`**
@@ -385,7 +385,7 @@ params.set('q', search.trim())
- [ ] **Step 4: Run frontend lint**
Run: `cd Inventory_frontend && npm run lint:fix`
Run: `cd frontend && npm run lint:fix`
- [ ] **Step 5: Verify in browser**
@@ -399,11 +399,11 @@ Confirm that searching by a reference value returns the correct results.
- [ ] **Step 6: Commit frontend changes**
```bash
cd Inventory_frontend && git add app/composables/usePieces.ts app/composables/useComposants.ts app/composables/useProducts.ts && git commit -m "feat(search) : use q param for OR search on name/reference"
cd frontend && git add app/composables/usePieces.ts app/composables/useComposants.ts app/composables/useProducts.ts && git commit -m "feat(search) : use q param for OR search on name/reference"
```
- [ ] **Step 7: Update submodule pointer in main repo**
```bash
cd /home/matthieu/dev_malio/Inventory && git add Inventory_frontend && git commit -m "chore(submodule) : update frontend pointer (OR search + site checkboxes)"
cd /home/matthieu/dev_malio/Inventory && git add frontend && git commit -m "chore(submodule) : update frontend pointer (OR search + site checkboxes)"
```

View File

@@ -1100,13 +1100,13 @@ git commit -m "feat(detail) : update catalogs and cross-links to use detail page
- [ ] **Step 1: Run lint**
```bash
cd Inventory_frontend && npm run lint:fix
cd frontend && npm run lint:fix
```
- [ ] **Step 2: Run typecheck**
```bash
cd Inventory_frontend && npx nuxi typecheck
cd frontend && npx nuxi typecheck
```
Fix any errors found.

View File

@@ -29,15 +29,15 @@
- `src/Repository/AuditLogRepository.php` — Add `findVersionHistory()` method
### Frontend — New Files
- `Inventory_frontend/app/composables/useEntityVersions.ts` — API calls for versions/preview/restore
- `Inventory_frontend/app/components/common/EntityVersionList.vue` — Version list with restore button
- `Inventory_frontend/app/components/common/VersionRestoreModal.vue` — Preview + confirm modal
- `frontend/app/composables/useEntityVersions.ts` — API calls for versions/preview/restore
- `frontend/app/components/common/EntityVersionList.vue` — Version list with restore button
- `frontend/app/components/common/VersionRestoreModal.vue` — Preview + confirm modal
### Frontend — Modified Files
- `Inventory_frontend/app/pages/machine/[id].vue` — Add Versions section
- `Inventory_frontend/app/pages/component/[id]/edit.vue` — Add Versions section
- `Inventory_frontend/app/pages/piece/[id].vue` — Add Versions section
- `Inventory_frontend/app/pages/product/[id]/edit.vue` — Add Versions section
- `frontend/app/pages/machine/[id].vue` — Add Versions section
- `frontend/app/pages/component/[id]/edit.vue` — Add Versions section
- `frontend/app/pages/piece/[id].vue` — Add Versions section
- `frontend/app/pages/product/[id]/edit.vue` — Add Versions section
---
@@ -1870,7 +1870,7 @@ git commit -m "test(versioning) : add EntityVersionTest for list, preview and re
## Task 9b: Frontend — add `restore` action label to historyDisplayUtils
**Files:**
- Modify: `Inventory_frontend/app/shared/utils/historyDisplayUtils.ts`
- Modify: `frontend/app/shared/utils/historyDisplayUtils.ts`
- [ ] **Step 1: Add `restore` case to `historyActionLabel`**
@@ -1888,7 +1888,7 @@ export const historyActionLabel = (action: string): string => {
- [ ] **Step 2: Commit in frontend repo**
```bash
cd Inventory_frontend
cd frontend
git add app/shared/utils/historyDisplayUtils.ts
git commit -m "feat(versioning) : add restore action label to historyDisplayUtils"
cd ..
@@ -1899,7 +1899,7 @@ cd ..
## Task 10: Frontend — useEntityVersions composable
**Files:**
- Create: `Inventory_frontend/app/composables/useEntityVersions.ts`
- Create: `frontend/app/composables/useEntityVersions.ts`
- [ ] **Step 1: Create the composable**
@@ -2004,16 +2004,16 @@ export function useEntityVersions(deps: Deps) {
- [ ] **Step 2: Run lint**
Run (in `Inventory_frontend/`): `npm run lint:fix`
Run (in `frontend/`): `npm run lint:fix`
- [ ] **Step 3: Run typecheck**
Run (in `Inventory_frontend/`): `npx nuxi typecheck`
Run (in `frontend/`): `npx nuxi typecheck`
- [ ] **Step 4: Commit in frontend repo**
```bash
cd Inventory_frontend
cd frontend
git add app/composables/useEntityVersions.ts
git commit -m "feat(versioning) : add useEntityVersions composable"
cd ..
@@ -2024,7 +2024,7 @@ cd ..
## Task 11: Frontend — VersionRestoreModal component
**Files:**
- Create: `Inventory_frontend/app/components/common/VersionRestoreModal.vue`
- Create: `frontend/app/components/common/VersionRestoreModal.vue`
- [ ] **Step 1: Create the modal component**
@@ -2129,12 +2129,12 @@ const formatValue = (value: unknown): string => {
- [ ] **Step 2: Run lint**
Run (in `Inventory_frontend/`): `npm run lint:fix`
Run (in `frontend/`): `npm run lint:fix`
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/common/VersionRestoreModal.vue
git commit -m "feat(versioning) : add VersionRestoreModal component"
cd ..
@@ -2145,7 +2145,7 @@ cd ..
## Task 12: Frontend — EntityVersionList component
**Files:**
- Create: `Inventory_frontend/app/components/common/EntityVersionList.vue`
- Create: `frontend/app/components/common/EntityVersionList.vue`
- [ ] **Step 1: Create the version list component**
@@ -2296,12 +2296,12 @@ onMounted(() => {
- [ ] **Step 2: Run lint**
Run (in `Inventory_frontend/`): `npm run lint:fix`
Run (in `frontend/`): `npm run lint:fix`
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend
cd frontend
git add app/components/common/EntityVersionList.vue
git commit -m "feat(versioning) : add EntityVersionList component with restore flow"
cd ..
@@ -2312,10 +2312,10 @@ cd ..
## Task 13: Frontend — Integrate EntityVersionList into detail pages
**Files:**
- Modify: `Inventory_frontend/app/pages/machine/[id].vue`
- Modify: `Inventory_frontend/app/pages/component/[id]/edit.vue`
- Modify: `Inventory_frontend/app/pages/piece/[id].vue`
- Modify: `Inventory_frontend/app/pages/product/[id]/edit.vue`
- Modify: `frontend/app/pages/machine/[id].vue`
- Modify: `frontend/app/pages/component/[id]/edit.vue`
- Modify: `frontend/app/pages/piece/[id].vue`
- Modify: `frontend/app/pages/product/[id]/edit.vue`
- [ ] **Step 1: Add EntityVersionList to machine/[id].vue**
@@ -2398,16 +2398,16 @@ import EntityVersionList from '~/components/common/EntityVersionList.vue'
- [ ] **Step 5: Run lint**
Run (in `Inventory_frontend/`): `npm run lint:fix`
Run (in `frontend/`): `npm run lint:fix`
- [ ] **Step 6: Run typecheck**
Run (in `Inventory_frontend/`): `npx nuxi typecheck`
Run (in `frontend/`): `npx nuxi typecheck`
- [ ] **Step 7: Commit in frontend repo**
```bash
cd Inventory_frontend
cd frontend
git add app/pages/machine/\[id\].vue app/pages/component/\[id\]/edit.vue app/pages/piece/\[id\].vue app/pages/product/\[id\]/edit.vue
git commit -m "feat(versioning) : integrate EntityVersionList into all detail pages"
cd ..
@@ -2416,7 +2416,7 @@ cd ..
- [ ] **Step 8: Update submodule pointer in main repo**
```bash
git add Inventory_frontend
git add frontend
git commit -m "chore(submodule) : update frontend pointer (entity versioning)"
```
@@ -2431,7 +2431,7 @@ Expected: All tests pass.
- [ ] **Step 2: Run frontend lint + typecheck**
Run (in `Inventory_frontend/`): `npm run lint:fix && npx nuxi typecheck`
Run (in `frontend/`): `npm run lint:fix && npx nuxi typecheck`
Expected: 0 errors.
- [ ] **Step 3: Manual smoke test**

View File

@@ -14,12 +14,12 @@
| Action | File | Responsibility |
|--------|------|----------------|
| Modify | `Inventory_frontend/app/components/machine/MachineInfoCard.vue` | Remove blur-triggered saves, expose saveFieldDefinitions via defineExpose |
| Modify | `Inventory_frontend/app/components/machine/MachineCustomFieldDefEditor.vue` | Remove standalone save button |
| Modify | `Inventory_frontend/app/pages/machine/[id].vue` | Add Save/Cancel buttons, wire submitEdition via template ref |
| Modify | `Inventory_frontend/app/composables/useMachineDetailData.ts` | Add submitEdition, cancelEdition, saving, canSubmit |
| Modify | `Inventory_frontend/app/composables/useMachineDetailUpdates.ts` | Remove auto-save from handleMachineConstructeurChange |
| Modify | `Inventory_frontend/app/composables/useMachineDetailCustomFields.ts` | Add saveAllMachineCustomFields batch method |
| Modify | `frontend/app/components/machine/MachineInfoCard.vue` | Remove blur-triggered saves, expose saveFieldDefinitions via defineExpose |
| Modify | `frontend/app/components/machine/MachineCustomFieldDefEditor.vue` | Remove standalone save button |
| Modify | `frontend/app/pages/machine/[id].vue` | Add Save/Cancel buttons, wire submitEdition via template ref |
| Modify | `frontend/app/composables/useMachineDetailData.ts` | Add submitEdition, cancelEdition, saving, canSubmit |
| Modify | `frontend/app/composables/useMachineDetailUpdates.ts` | Remove auto-save from handleMachineConstructeurChange |
| Modify | `frontend/app/composables/useMachineDetailCustomFields.ts` | Add saveAllMachineCustomFields batch method |
| Modify | `src/EventSubscriber/MachineAuditSubscriber.php` | Enrich snapshot with links + detect link changes in onFlush |
---
@@ -27,7 +27,7 @@
### Task 1: Remove blur-triggered saves from MachineInfoCard
**Files:**
- Modify: `Inventory_frontend/app/components/machine/MachineInfoCard.vue`
- Modify: `frontend/app/components/machine/MachineInfoCard.vue`
- [ ] **Step 1: Remove `@blur` from name input (line 17)**
@@ -143,7 +143,7 @@ defineExpose({
- [ ] **Step 7: Commit**
```bash
git add Inventory_frontend/app/components/machine/MachineInfoCard.vue
git add frontend/app/components/machine/MachineInfoCard.vue
git commit -m "refactor(machine) : remove blur-triggered auto-saves from MachineInfoCard"
```
@@ -152,7 +152,7 @@ git commit -m "refactor(machine) : remove blur-triggered auto-saves from Machine
### Task 2: Remove standalone save button from MachineCustomFieldDefEditor
**Files:**
- Modify: `Inventory_frontend/app/components/machine/MachineCustomFieldDefEditor.vue`
- Modify: `frontend/app/components/machine/MachineCustomFieldDefEditor.vue`
- [ ] **Step 1: Remove the "Enregistrer les champs" button (lines 7-15)**
@@ -201,7 +201,7 @@ defineEmits<{
- [ ] **Step 3: Commit**
```bash
git add Inventory_frontend/app/components/machine/MachineCustomFieldDefEditor.vue
git add frontend/app/components/machine/MachineCustomFieldDefEditor.vue
git commit -m "refactor(machine) : remove standalone save button from custom field def editor"
```
@@ -210,7 +210,7 @@ git commit -m "refactor(machine) : remove standalone save button from custom fie
### Task 3: Stop auto-save in handleMachineConstructeurChange
**Files:**
- Modify: `Inventory_frontend/app/composables/useMachineDetailUpdates.ts:211-214`
- Modify: `frontend/app/composables/useMachineDetailUpdates.ts:211-214`
- [ ] **Step 1: Remove the auto-save call**
@@ -231,7 +231,7 @@ With:
- [ ] **Step 2: Commit**
```bash
git add Inventory_frontend/app/composables/useMachineDetailUpdates.ts
git add frontend/app/composables/useMachineDetailUpdates.ts
git commit -m "refactor(machine) : stop auto-saving on constructeur change"
```
@@ -240,7 +240,7 @@ git commit -m "refactor(machine) : stop auto-saving on constructeur change"
### Task 4: Add batch custom field save method
**Files:**
- Modify: `Inventory_frontend/app/composables/useMachineDetailCustomFields.ts`
- Modify: `frontend/app/composables/useMachineDetailCustomFields.ts`
- [ ] **Step 1: Add `saveAllMachineCustomFields` method**
@@ -325,7 +325,7 @@ With:
- [ ] **Step 3: Commit**
```bash
git add Inventory_frontend/app/composables/useMachineDetailCustomFields.ts
git add frontend/app/composables/useMachineDetailCustomFields.ts
git commit -m "feat(machine) : add batch saveAllMachineCustomFields method"
```
@@ -334,7 +334,7 @@ git commit -m "feat(machine) : add batch saveAllMachineCustomFields method"
### Task 5: Add submitEdition, cancelEdition, saving, canSubmit to orchestrator
**Files:**
- Modify: `Inventory_frontend/app/composables/useMachineDetailData.ts`
- Modify: `frontend/app/composables/useMachineDetailData.ts`
- [ ] **Step 1: Add `saving` ref in the core state block (after line 63)**
@@ -423,7 +423,7 @@ Add to the return object:
- [ ] **Step 6: Commit**
```bash
git add Inventory_frontend/app/composables/useMachineDetailData.ts
git add frontend/app/composables/useMachineDetailData.ts
git commit -m "feat(machine) : add submitEdition, cancelEdition, saving, canSubmit"
```
@@ -432,7 +432,7 @@ git commit -m "feat(machine) : add submitEdition, cancelEdition, saving, canSubm
### Task 6: Wire Save/Cancel buttons in the page
**Files:**
- Modify: `Inventory_frontend/app/pages/machine/[id].vue`
- Modify: `frontend/app/pages/machine/[id].vue`
- [ ] **Step 1: Add template ref on MachineInfoCard (line 56)**
@@ -597,7 +597,7 @@ const historyFieldLabels = {
- [ ] **Step 7: Commit**
```bash
git add Inventory_frontend/app/pages/machine/[id].vue
git add frontend/app/pages/machine/[id].vue
git commit -m "feat(machine) : add single save button and wire cancel/submit"
```
@@ -988,13 +988,13 @@ git commit -m "feat(versioning) : detect machine link add/remove in onFlush and
- [ ] **Step 1: Run ESLint fix**
```bash
cd Inventory_frontend && npm run lint:fix
cd frontend && npm run lint:fix
```
- [ ] **Step 2: Run typecheck**
```bash
cd Inventory_frontend && npx nuxi typecheck
cd frontend && npx nuxi typecheck
```
Expected: 0 errors.
@@ -1039,7 +1039,7 @@ git add -A && git commit -m "fix(machine) : fix cs-fixer and test issues from si
```bash
make start
cd Inventory_frontend && npm run dev
cd frontend && npm run dev
```
- [ ] **Step 2: Test single save flow**

View File

@@ -94,8 +94,8 @@ git commit --no-verify -m "feat(constructeur) : add SearchFilter on Constructeur
### Task F2: Frontend — Add types + useConstructeurLinks composable
**Files:**
- Modify: `Inventory_frontend/app/shared/constructeurUtils.ts`
- Create: `Inventory_frontend/app/composables/useConstructeurLinks.ts`
- Modify: `frontend/app/shared/constructeurUtils.ts`
- Create: `frontend/app/composables/useConstructeurLinks.ts`
- [ ] **Step 1: Add ConstructeurLinkEntry type to constructeurUtils.ts**
@@ -227,7 +227,7 @@ export function useConstructeurLinks() {
- [ ] **Step 3: Commit**
```bash
cd Inventory_frontend && git add -A && git commit -m "feat(constructeur) : add ConstructeurLinkEntry type and useConstructeurLinks composable"
cd frontend && git add -A && git commit -m "feat(constructeur) : add ConstructeurLinkEntry type and useConstructeurLinks composable"
```
---
@@ -235,7 +235,7 @@ cd Inventory_frontend && git add -A && git commit -m "feat(constructeur) : add C
### Task F3: Frontend — Create ConstructeurLinksTable component
**Files:**
- Create: `Inventory_frontend/app/components/ConstructeurLinksTable.vue`
- Create: `frontend/app/components/ConstructeurLinksTable.vue`
- [ ] **Step 1: Create the component**
@@ -338,7 +338,7 @@ const removeLink = (index: number) => {
- [ ] **Step 2: Commit**
```bash
cd Inventory_frontend && git add -A && git commit -m "feat(constructeur) : add ConstructeurLinksTable component"
cd frontend && git add -A && git commit -m "feat(constructeur) : add ConstructeurLinksTable component"
```
---
@@ -346,9 +346,9 @@ cd Inventory_frontend && git add -A && git commit -m "feat(constructeur) : add C
### Task F4: Frontend — Update piece edit flow (model case)
**Files:**
- Modify: `Inventory_frontend/app/composables/usePieceEdit.ts`
- Modify: `Inventory_frontend/app/pages/piece/[id].vue`
- Modify: `Inventory_frontend/app/composables/usePieces.ts`
- Modify: `frontend/app/composables/usePieceEdit.ts`
- Modify: `frontend/app/pages/piece/[id].vue`
- Modify: `frontend/app/composables/usePieces.ts`
This task establishes the pattern for all entity types.
@@ -376,13 +376,13 @@ In `createPiece()` and `updatePieceData()`: stop wrapping payload with `buildCon
- [ ] **Step 4: Lint and typecheck**
```bash
cd Inventory_frontend && npm run lint:fix && npx nuxi typecheck
cd frontend && npm run lint:fix && npx nuxi typecheck
```
- [ ] **Step 5: Commit**
```bash
cd Inventory_frontend && git add -A && git commit -m "feat(constructeur) : update piece edit flow with supplier references"
cd frontend && git add -A && git commit -m "feat(constructeur) : update piece edit flow with supplier references"
```
---
@@ -392,11 +392,11 @@ cd Inventory_frontend && git add -A && git commit -m "feat(constructeur) : updat
Same pattern as Task F4 but for composants.
**Files:**
- Modify: `Inventory_frontend/app/composables/useComponentEdit.ts`
- Modify: `Inventory_frontend/app/pages/component/[id]/index.vue`
- Modify: `Inventory_frontend/app/pages/component/[id]/edit.vue`
- Modify: `Inventory_frontend/app/composables/useComposants.ts`
- Modify: `Inventory_frontend/app/pages/component/create.vue`
- Modify: `frontend/app/composables/useComponentEdit.ts`
- Modify: `frontend/app/pages/component/[id]/index.vue`
- Modify: `frontend/app/pages/component/[id]/edit.vue`
- Modify: `frontend/app/composables/useComposants.ts`
- Modify: `frontend/app/pages/component/create.vue`
---
@@ -406,10 +406,10 @@ Same pattern as Task F4 but for products.
**Files:**
- Modify: product edit composable (if exists) or inline pages
- Modify: `Inventory_frontend/app/pages/product/[id]/index.vue`
- Modify: `Inventory_frontend/app/pages/product/[id]/edit.vue`
- Modify: `Inventory_frontend/app/composables/useProducts.ts`
- Modify: `Inventory_frontend/app/pages/product/create.vue`
- Modify: `frontend/app/pages/product/[id]/index.vue`
- Modify: `frontend/app/pages/product/[id]/edit.vue`
- Modify: `frontend/app/composables/useProducts.ts`
- Modify: `frontend/app/pages/product/create.vue`
---
@@ -418,11 +418,11 @@ Same pattern as Task F4 but for products.
Machine uses a different architecture (MachineStructureController, useMachineDetailData/Updates).
**Files:**
- Modify: `Inventory_frontend/app/composables/useMachineDetailData.ts`
- Modify: `Inventory_frontend/app/composables/useMachineDetailUpdates.ts`
- Modify: `Inventory_frontend/app/pages/machine/[id].vue`
- Modify: `Inventory_frontend/app/components/machine/MachineInfoCard.vue`
- Modify: `Inventory_frontend/app/composables/useMachines.ts`
- Modify: `frontend/app/composables/useMachineDetailData.ts`
- Modify: `frontend/app/composables/useMachineDetailUpdates.ts`
- Modify: `frontend/app/pages/machine/[id].vue`
- Modify: `frontend/app/components/machine/MachineInfoCard.vue`
- Modify: `frontend/app/composables/useMachines.ts`
Key differences:
- Machine data comes from `/api/machines/{id}/structure` (custom controller) which already returns the new constructeur link format
@@ -434,8 +434,8 @@ Key differences:
### Task F8: Frontend — Update machine structure components (PieceItem, ComponentItem)
**Files:**
- Modify: `Inventory_frontend/app/components/PieceItem.vue`
- Modify: `Inventory_frontend/app/components/ComponentItem.vue`
- Modify: `frontend/app/components/PieceItem.vue`
- Modify: `frontend/app/components/ComponentItem.vue`
These components display constructeurs in the machine structure tree and handle inline editing. Update them to:
- Read from `constructeurLinks` format in the machine structure response
@@ -447,9 +447,9 @@ These components display constructeurs in the machine structure tree and handle
### Task F9: Frontend — Update create pages
**Files:**
- Modify: `Inventory_frontend/app/pages/pieces/create.vue`
- Modify: `Inventory_frontend/app/pages/component/create.vue`
- Modify: `Inventory_frontend/app/pages/product/create.vue`
- Modify: `frontend/app/pages/pieces/create.vue`
- Modify: `frontend/app/pages/component/create.vue`
- Modify: `frontend/app/pages/product/create.vue`
On creation pages, there are no existing links. The flow is:
1. User selects constructeurs + optionally fills supplierReference

View File

@@ -18,7 +18,7 @@ L'utilisateur veut pouvoir sélectionner plusieurs sites simultanément.
- Quand **une ou plusieurs** sont cochées → filtre sur ces sites uniquement.
### Changements techniques
**Fichier** : `Inventory_frontend/app/pages/machines/index.vue`
**Fichier** : `frontend/app/pages/machines/index.vue`
- **Réactivité** : utiliser `reactive(new Set())` (Vue 3.4+ supporte nativement les mutations `add`/`delete`/`has` sur un Set réactif). Pas de `.value` nécessaire.
- **Note** : le fichier utilise `<script setup>` sans `lang="ts"` — ne pas utiliser d'annotations TypeScript comme `Set<string>`.
@@ -36,7 +36,7 @@ Les machines s'affichent dans l'ordre retourné par l'API, sans tri. L'utilisate
Ajouter un `.sort()` avec `localeCompare('fr')` à la fin du computed `filteredMachines`.
### Changements techniques
**Fichier** : `Inventory_frontend/app/pages/machines/index.vue`
**Fichier** : `frontend/app/pages/machines/index.vue`
- Dans le computed `filteredMachines`, ajouter avant le `return` :
```js
@@ -67,9 +67,9 @@ Créer une **Extension Doctrine** (`SearchByNameOrReferenceExtension`) qui inter
- **Pas de conflit** avec le `SearchFilter` existant : le paramètre `q` n'est pas enregistré comme propriété de `SearchFilter`, donc il sera ignoré par celui-ci. Les filtres `name` et `reference` restent disponibles pour d'autres usages.
**Frontend — 3 fichiers** (dans la fonction `loadXxx`, remplacer l'appel `params.set('name', search.trim())`) :
- `Inventory_frontend/app/composables/usePieces.ts` → `params.set('q', search.trim())`
- `Inventory_frontend/app/composables/useComposants.ts` → idem
- `Inventory_frontend/app/composables/useProducts.ts` → idem
- `frontend/app/composables/usePieces.ts` → `params.set('q', search.trim())`
- `frontend/app/composables/useComposants.ts` → idem
- `frontend/app/composables/useProducts.ts` → idem
---
@@ -77,11 +77,11 @@ Créer une **Extension Doctrine** (`SearchByNameOrReferenceExtension`) qui inter
| Fichier | Changement |
|---------|-----------|
| `Inventory_frontend/app/pages/machines/index.vue` | Checkboxes sites + tri alphabétique |
| `frontend/app/pages/machines/index.vue` | Checkboxes sites + tri alphabétique |
| `src/Doctrine/SearchByNameOrReferenceExtension.php` | **Nouveau** — Extension Doctrine OR search |
| `Inventory_frontend/app/composables/usePieces.ts` | `name` → `q` |
| `Inventory_frontend/app/composables/useComposants.ts` | `name` → `q` |
| `Inventory_frontend/app/composables/useProducts.ts` | `name` → `q` |
| `frontend/app/composables/usePieces.ts` | `name` → `q` |
| `frontend/app/composables/useComposants.ts` | `name` → `q` |
| `frontend/app/composables/useProducts.ts` | `name` → `q` |
## Hors scope
- La page Parc Machines cherche **déjà** sur nom ET référence côté frontend (filtrage client-side). Pas de changement nécessaire.

View File

@@ -2,7 +2,7 @@
**Date** : 2026-03-31
**Scope** : Frontend uniquement (pas de changement backend)
**Fichier impacté** : `Inventory_frontend/app/components/model-types/ModelTypeForm.vue`
**Fichier impacté** : `frontend/app/components/model-types/ModelTypeForm.vue`
## Problème

View File

@@ -0,0 +1,30 @@
import { ref } from 'vue'
import { useApi } from './useApi'
const maintenanceEnabled = ref(false)
export function useMaintenance() {
const { apiCall } = useApi()
const loading = ref(false)
const fetchStatus = async () => {
const res = await apiCall<{ enabled: boolean }>('/admin/maintenance')
if (res.success && res.data) {
maintenanceEnabled.value = res.data.enabled
}
}
const toggle = async () => {
loading.value = true
try {
const res = await apiCall<{ enabled: boolean }>('/admin/maintenance', { method: 'PUT' })
if (res.success && res.data) {
maintenanceEnabled.value = res.data.enabled
}
} finally {
loading.value = false
}
}
return { maintenanceEnabled, loading, fetchStatus, toggle }
}

View File

@@ -1,4 +1,4 @@
import { useProfileSession, usePermissions } from "#imports";
import { useProfileSession, usePermissions, useApi } from "#imports";
export default defineNuxtRouteMiddleware(async (to) => {
const { ensureSession, activeProfile } = useProfileSession();
@@ -12,9 +12,10 @@ export default defineNuxtRouteMiddleware(async (to) => {
normalizedPath.startsWith("/profiles") ||
fullPath.startsWith("/profiles") ||
routeName.startsWith("profiles");
const isMaintenanceRoute = normalizedPath === "/maintenance";
// Redirect to login if no active profile
if (!activeProfile.value && !isProfilesRoute) {
if (!activeProfile.value && !isProfilesRoute && !isMaintenanceRoute) {
return navigateTo("/profiles");
}
@@ -29,5 +30,13 @@ export default defineNuxtRouteMiddleware(async (to) => {
}
}
// Maintenance mode check for non-admin users
if (!isAdmin.value && !isMaintenanceRoute && !isProfilesRoute) {
const { apiCall } = useApi();
const res = await apiCall<{ enabled: boolean }>('/maintenance/check');
if (res.success && res.data?.enabled) {
return navigateTo("/maintenance");
}
}
}
});

View File

@@ -1,5 +1,28 @@
<template>
<div class="container mx-auto p-6 max-w-6xl">
<!-- Maintenance Mode -->
<div class="alert mb-6" :class="maintenanceEnabled ? 'alert-warning' : 'alert-info'">
<div class="flex items-center justify-between w-full">
<div class="flex items-center gap-2">
<span class="font-medium">Mode maintenance</span>
<span v-if="maintenanceEnabled" class="badge badge-warning badge-sm">Actif</span>
<span v-else class="badge badge-ghost badge-sm">Inactif</span>
</div>
<button
class="btn btn-sm"
:class="maintenanceEnabled ? 'btn-ghost' : 'btn-warning'"
:disabled="maintenanceLoading"
@click="handleToggleMaintenance"
>
<span v-if="maintenanceLoading" class="loading loading-spinner loading-xs" />
{{ maintenanceEnabled ? 'Désactiver' : 'Activer' }}
</button>
</div>
<p class="text-sm opacity-70 mt-1">
{{ maintenanceEnabled ? 'Seuls les administrateurs peuvent accéder à l\'application.' : 'L\'application est accessible à tous les utilisateurs.' }}
</p>
</div>
<div class="flex items-center justify-between mb-6">
<h1 class="text-2xl font-bold">
Administration des profils
@@ -153,9 +176,14 @@
<script setup>
import { ref, computed, onMounted } from 'vue'
import DataTable from '~/components/common/DataTable.vue'
import { useAdminProfiles } from '#imports'
import { useAdminProfiles, useMaintenance } from '#imports'
const { profiles, loading, fetchAll, createProfile, updateRole, setPassword, deactivateProfile } = useAdminProfiles()
const { maintenanceEnabled, loading: maintenanceLoading, fetchStatus: fetchMaintenanceStatus, toggle: toggleMaintenance } = useMaintenance()
const handleToggleMaintenance = async () => {
await toggleMaintenance()
}
const loaded = ref(false)
const isLoading = computed(() => loading.value || !loaded.value)
@@ -264,7 +292,7 @@ const handleDeactivate = async (profileId) => {
}
onMounted(async () => {
await fetchAll()
await Promise.all([fetchAll(), fetchMaintenanceStatus()])
loaded.value = true
})
</script>

View File

@@ -0,0 +1,21 @@
<template>
<div class="min-h-screen flex items-center justify-center bg-base-200">
<div class="text-center max-w-md">
<h1 class="text-4xl font-bold mb-4">
Maintenance
</h1>
<p class="text-lg text-base-content/70 mb-6">
L'application est actuellement en maintenance. Veuillez réessayer ultérieurement.
</p>
<button class="btn btn-primary" @click="retry">
Réessayer
</button>
</div>
</div>
</template>
<script setup>
const retry = () => {
navigateTo('/')
}
</script>

View File

@@ -3,12 +3,14 @@ import { readFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
// Lire la version depuis le fichier VERSION à la racine du projet parent
// Lire la version depuis config/version.yaml à la racine du projet parent
const getAppVersion = (): string => {
try {
const __dirname = dirname(fileURLToPath(import.meta.url))
const versionPath = resolve(__dirname, '..', 'VERSION')
return readFileSync(versionPath, 'utf-8').trim()
const versionPath = resolve(__dirname, '..', 'config', 'version.yaml')
const content = readFileSync(versionPath, 'utf-8')
const match = content.match(/app\.version:\s*'([^']+)'/)
return match ? match[1] : '0.0.0'
} catch {
return '0.0.0'
}

View File

@@ -19,7 +19,6 @@ COPY migrations migrations/
COPY public public/
COPY src src/
COPY templates templates/
COPY VERSION VERSION
RUN composer dump-autoload --optimize --no-dev
@@ -31,6 +30,7 @@ COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ ./
COPY config/version.yaml /app/config/version.yaml
ENV CI=1 \
NUXT_TELEMETRY_DISABLED=1 \
NUXT_PUBLIC_API_BASE_URL=/api \
@@ -61,8 +61,8 @@ RUN ln -sf /dev/stdout /var/log/nginx/access.log \
RUN rm -f /etc/nginx/sites-enabled/default
# Configs
COPY deploy/docker/supervisord.conf /etc/supervisor/conf.d/app.conf
COPY deploy/docker/nginx.conf /etc/nginx/sites-enabled/inventory.conf
COPY infra/prod/supervisord.conf /etc/supervisor/conf.d/app.conf
COPY infra/prod/nginx.conf /etc/nginx/sites-enabled/inventory.conf
# Backend from stage 1
COPY --from=backend-build /app /var/www/html

View File

@@ -24,5 +24,5 @@ echo "==> Clearing cache..."
sudo docker compose exec -T -u www-data app php bin/console cache:clear --env=prod
sudo docker compose exec -T -u www-data app php bin/console cache:warmup --env=prod
VERSION=$(sudo docker compose exec -T app cat VERSION)
VERSION=$(sudo docker compose exec -T app cat config/version.yaml | grep 'app.version' | awk -F"'" '{print $2}')
echo "==> Deployed v${VERSION}"

View File

@@ -6,7 +6,7 @@ services:
ports:
- "8082:80"
volumes:
- ./uploads:/var/www/html/var/uploads
- ./storage:/var/www/html/var/storage/documents
extra_hosts:
- "host.docker.internal:host-gateway"
restart: unless-stopped

View File

@@ -1,6 +1,6 @@
# Permet d'utiliser un .env.docker.local pour override
ENV_DEFAULT = docker/.env.docker
ENV_LOCAL = docker/.env.docker.local
ENV_DEFAULT = infra/dev/.env.docker
ENV_LOCAL = infra/dev/.env.docker.local
ENV_FILE := $(if $(wildcard $(ENV_LOCAL)),$(ENV_LOCAL),$(ENV_DEFAULT))
# Permet d'avoir les variables du fichier .env.docker.local
@@ -25,13 +25,13 @@ DATA_SQL_NORM ?= data_norm.sql
#========================================================================================
env-init:
@mkdir -p docker
@mkdir -p infra/dev
@cp --update=none $(ENV_DEFAULT) $(ENV_LOCAL)
# Lance le container
start: env-init
@echo "**** START CONTAINERS ****"
@cp --update=none docker/.env.docker docker/.env.docker.local
@cp --update=none infra/dev/.env.docker infra/dev/.env.docker.local
CURRENT_UID=$(shell id -u) CURRENT_GID=$(shell id -g) $(DOCKER_COMPOSE) up -d
@echo ""
@echo "URLs disponibles:"

View File

@@ -11,11 +11,11 @@ NC='\033[0m' # No Color
# Répertoire racine du projet
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
VERSION_FILE="$PROJECT_ROOT/VERSION"
VERSION_FILE="$PROJECT_ROOT/config/version.yaml"
API_PLATFORM_FILE="$PROJECT_ROOT/config/packages/api_platform.yaml"
# Lire la version actuelle
current_version=$(cat "$VERSION_FILE" | tr -d '\n')
current_version=$(awk -F': *' '/app\.version:/{print $2}' "$VERSION_FILE" | tr -d "' \n\r")
# Fonction pour afficher l'aide
show_help() {
@@ -113,8 +113,8 @@ cd "$PROJECT_ROOT"
# ===========================================
# ÉTAPE 1 : Mettre à jour VERSION
# ===========================================
echo -e "${BLUE}[1/4]${NC} Mise à jour du fichier VERSION..."
echo "$new_version" > "$VERSION_FILE"
echo -e "${BLUE}[1/4]${NC} Mise à jour de config/version.yaml..."
printf "parameters:\\n app.version: '%s'\\n" "$new_version" > "$VERSION_FILE"
# ===========================================
# ÉTAPE 2 : Mettre à jour api_platform.yaml

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Attribute\Route;
final class MaintenanceController extends AbstractController
{
public function __construct(
private readonly KernelInterface $kernel,
) {}
#[Route('/api/maintenance/check', name: 'maintenance_check', methods: ['GET'])]
public function check(): JsonResponse
{
return new JsonResponse([
'enabled' => file_exists($this->flagPath()),
]);
}
#[Route('/api/admin/maintenance', name: 'admin_maintenance_status', methods: ['GET'])]
public function status(): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
return new JsonResponse([
'enabled' => file_exists($this->flagPath()),
]);
}
#[Route('/api/admin/maintenance', name: 'admin_maintenance_toggle', methods: ['PUT'])]
public function toggle(): JsonResponse
{
$this->denyAccessUnlessGranted('ROLE_ADMIN');
$path = $this->flagPath();
if (file_exists($path)) {
unlink($path);
$enabled = false;
} else {
file_put_contents($path, (string) time());
$enabled = true;
}
return new JsonResponse(['enabled' => $enabled]);
}
private function flagPath(): string
{
return $this->kernel->getProjectDir() . '/var/maintenance';
}
}

View File

@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace App\EventListener;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
#[AsEventListener(event: 'kernel.request', priority: 10)]
final class MaintenanceModeListener
{
public function __construct(
private readonly KernelInterface $kernel,
private readonly TokenStorageInterface $tokenStorage,
) {}
public function __invoke(RequestEvent $event): void
{
if (!$event->isMainRequest()) {
return;
}
$flagFile = $this->kernel->getProjectDir() . '/var/maintenance';
if (!file_exists($flagFile)) {
return;
}
$request = $event->getRequest();
$path = $request->getPathInfo();
// Always allow maintenance status endpoint and session endpoints
if (str_starts_with($path, '/api/admin/maintenance')
|| str_starts_with($path, '/api/maintenance/check')
|| str_starts_with($path, '/api/session')
|| str_starts_with($path, '/api/health')
|| str_starts_with($path, '/api/docs')
) {
return;
}
// Allow admin users through
$token = $this->tokenStorage->getToken();
if ($token && $token->getUser()) {
$roles = $token->getRoleNames();
if (in_array('ROLE_ADMIN', $roles, true)) {
return;
}
}
$event->setResponse(new JsonResponse(
['message' => 'Application en maintenance. Veuillez réessayer ultérieurement.'],
JsonResponse::HTTP_SERVICE_UNAVAILABLE,
));
}
}