From 5e78e67fc8a76117345db823611e4448607ab80e Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 8 Oct 2025 15:34:53 +0200 Subject: [PATCH 01/44] remove cache busting --- public/site/snippets/header.php | 4 +-- vite.config.js | 58 ++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/public/site/snippets/header.php b/public/site/snippets/header.php index f8e4f54..a35fc34 100644 --- a/public/site/snippets/header.php +++ b/public/site/snippets/header.php @@ -25,8 +25,8 @@ - - + + diff --git a/vite.config.js b/vite.config.js index 53268a1..154116f 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,33 +1,37 @@ import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; -export default defineConfig({ - plugins: [vue()], - base: '/', - build: { - outDir: 'dist', - rollupOptions: { - output: { - entryFileNames: 'assets/dist/[name].js', - assetFileNames: 'assets/dist/[name].[ext]', +export default defineConfig(({ mode }) => { + return { + plugins: [vue()], + base: '/', + build: { + outDir: 'dist', + rollupOptions: { + output: { + entryFileNames: 'assets/dist/[name].js', + assetFileNames: 'assets/dist/[name].[ext]', + }, + }, + sourcemap: mode === 'staging', + minify: mode === 'production', + }, + server: { + watch: { + ignored: [ + '**/node_modules/**', + '**/.git/**', + '**/.cache/**', + '**/.vite/**', + '**/dist/**', + '**/*.log', + '**/.idea/**', + '**/.vscode/**', + '**/public/assets/**', + '**/local/**', + '/public/**', + ], }, }, - }, - server: { - watch: { - ignored: [ - '**/node_modules/**', - '**/.git/**', - '**/.cache/**', - '**/.vite/**', - '**/dist/**', - '**/*.log', - '**/.idea/**', - '**/.vscode/**', - '**/public/assets/**', - '**/local/**', - '/public/**', - ], - }, - }, + }; }); From 95bdf4615d149635d13f6ae7f6ac41184d7763a2 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 8 Oct 2025 15:47:45 +0200 Subject: [PATCH 02/44] fix CI --- .gitlab-ci.yml | 79 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8617d19..c5d58cb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,12 +1,13 @@ stages: - build - deploy - variables: COMPOSER_ALLOW_SUPERUSER: '1' -build: +build_prod: stage: build + only: + - prod image: composer:2 script: - apk add --no-cache nodejs npm @@ -23,7 +24,27 @@ build: paths: - node_modules/ -deploy: +build_preprod: + stage: build + only: + - preprod + image: composer:2 + script: + - apk add --no-cache nodejs npm + - npm install + - npm run build:preprod + - cd dist - + composer install --no-dev --optimize-autoloader --ignore-platform-req=ext-gd + - cd .. + artifacts: + paths: + - dist/ + cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - node_modules/ + +deploy_prod: stage: deploy image: node:latest only: @@ -33,18 +54,44 @@ deploy: script: - cd dist - | - rsync_deploy() { - local src=$1 - local dst=$2 - local exclude=$3 - cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" - [[ -n $exclude ]] && cmd="$cmd $exclude" - cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" - echo "$cmd" - eval $cmd - } + rsync_deploy() { + local src=$1 + local dst=$2 + local exclude=$3 + cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" + [[ -n $exclude ]] && cmd="$cmd $exclude" + cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" + echo "$cmd" + eval $cmd + } - rsync_deploy site/ "$PROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" - rsync_deploy vendor/ "$PROD_PATH/vendor/" - rsync_deploy kirby/ "$PROD_PATH/kirby/" + rsync_deploy site/ "$PROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" + rsync_deploy vendor/ "$PROD_PATH/vendor/" + rsync_deploy kirby/ "$PROD_PATH/kirby/" rsync_deploy assets/ "$PROD_PATH/assets/" "--exclude 'tiles/'" + +deploy_preprod: + stage: deploy + image: node:latest + only: + - preprod + before_script: + - apt-get update -qq && apt-get install -y rsync sshpass + script: + - cd dist + - | + rsync_deploy() { + local src=$1 + local dst=$2 + local exclude=$3 + cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" + [[ -n $exclude ]] && cmd="$cmd $exclude" + cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" + echo "$cmd" + eval $cmd + } + + rsync_deploy site/ "$PREPROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" + rsync_deploy vendor/ "$PREPROD_PATH/vendor/" + rsync_deploy kirby/ "$PREPROD_PATH/kirby/" + rsync_deploy assets/ "$PREPROD_PATH/assets/" "--exclude 'tiles/'" From 729d72e18a473804f0ee82b75fecacb1a1630d87 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 8 Oct 2025 15:48:35 +0200 Subject: [PATCH 03/44] fix CI --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c5d58cb..5fa295d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -39,10 +39,10 @@ build_preprod: artifacts: paths: - dist/ - cache: - key: ${CI_COMMIT_REF_SLUG} - paths: - - node_modules/ + cache: + key: ${CI_COMMIT_REF_SLUG} + paths: + - node_modules/ deploy_prod: stage: deploy From 186f7b80ba3bc5af1f81b6497a612a1aeab38915 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 8 Oct 2025 15:56:15 +0200 Subject: [PATCH 04/44] fix CI --- .gitlab-ci.yml | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 3d6fd61..aa30802 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,7 @@ stages: - build - deploy + variables: COMPOSER_ALLOW_SUPERUSER: '1' @@ -82,18 +83,18 @@ deploy_prod: script: - cd dist - | - rsync_deploy() { - local src=$1 - local dst=$2 - local exclude=$3 - cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" - [[ -n $exclude ]] && cmd="$cmd $exclude" - cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" - echo "$cmd" - eval $cmd - } + rsync_deploy() { + local src=$1 + local dst=$2 + local exclude=$3 + cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" + [[ -n $exclude ]] && cmd="$cmd $exclude" + cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" + echo "$cmd" + eval $cmd + } - rsync_deploy site/ "$PROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" - rsync_deploy vendor/ "$PROD_PATH/vendor/" - rsync_deploy kirby/ "$PROD_PATH/kirby/" + rsync_deploy site/ "$PROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" + rsync_deploy vendor/ "$PROD_PATH/vendor/" + rsync_deploy kirby/ "$PROD_PATH/kirby/" rsync_deploy assets/ "$PROD_PATH/assets/" "--exclude 'tiles/'" From d590c9ac458bcc17bb7d68b9003d7e6c688554b5 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 8 Oct 2025 15:58:25 +0200 Subject: [PATCH 05/44] fix CI --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aa30802..6e95c05 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -56,7 +56,7 @@ deploy_preprod: build_prod: stage: build only: - - prod + - main image: composer:2 script: - apk add --no-cache nodejs npm From c9aefe7ecfcdb9b9988176f3f0a9dd4290b3a7f6 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 15 Oct 2025 16:17:30 +0200 Subject: [PATCH 06/44] #179 --- public/site/models/project.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/site/models/project.php b/public/site/models/project.php index 1152945..df39ff1 100644 --- a/public/site/models/project.php +++ b/public/site/models/project.php @@ -159,7 +159,7 @@ class ProjectPage extends NotificationsPage { "physicalSample" => "échantillon physique", ]; - return $stepsLabel[$this->currentStep()->value()]; + return $stepsLabel[$this->currentStep()->value()] ?? "brief"; } // public function printManagers() { From 9ce8135a3b8e6cd48ade0fc4fadc95fd842261d8 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Thu, 15 Jan 2026 14:10:20 +0100 Subject: [PATCH 07/44] Rename to CLAUDE.md and add code preferences section Renamed from CLAUDE_PROJECT_OVERVIEW.md to follow standard naming convention for automatic recognition. Added section documenting code standards and work preferences. Co-Authored-By: Claude Sonnet 4.5 --- CLAUDE_PROJECT_OVERVIEW.md => CLAUDE.md | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) rename CLAUDE_PROJECT_OVERVIEW.md => CLAUDE.md (91%) diff --git a/CLAUDE_PROJECT_OVERVIEW.md b/CLAUDE.md similarity index 91% rename from CLAUDE_PROJECT_OVERVIEW.md rename to CLAUDE.md index 4657285..7fe2bf4 100644 --- a/CLAUDE_PROJECT_OVERVIEW.md +++ b/CLAUDE.md @@ -309,3 +309,36 @@ npm run build:preprod # Staging (avec sourcemaps) 3. **Commentaires**: Positionnés en % (x, y) + pageIndex pour les PDFs multi-pages. 4. **Notifications**: Stockées par projet, trackées par user UUID dans `readby[]`. 5. **Virtual Sample**: Pistes dynamiques = pages enfants, pistes statiques = fichiers. + +--- + +## Préférences de code et standards + +### Principes généraux + +**Clarté avant tout** +- Privilégier des noms de variables et fonctions explicites +- Éviter les commentaires sauf en cas de nécessité absolue +- Le code doit être auto-documenté par des noms clairs + +**Organisation du code** +- Factoriser le code en petites fonctions bien nommées +- Éviter les blocs de code longs et complexes dans les hooks de lifecycle +- Une fonction = une responsabilité claire + +**Ce qui est considéré comme "bricolage" (à éviter)** +- Paramètres d'URL pour gérer des états applicatifs +- Commentaires qui expliquent ce que fait le code au lieu de nommer correctement +- Abstractions prématurées ou sur-ingénierie + +### Style de communication + +**Feedback direct** +- Pas de politesses inutiles +- Dire immédiatement si quelque chose ne va pas +- Tester tout de suite et signaler les problèmes + +**Qualité attendue** +- Standards élevés sur la qualité du code +- Pas de code médiocre accepté +- Exigence de clarté et d'explicité constante From c2a5bd7a85e054fda1ae6ef10a0dc4de5b5e5118 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Thu, 15 Jan 2026 14:55:27 +0100 Subject: [PATCH 08/44] Migrate to Forgejo --- .forgejo/workflows/deploy-preprod.yml | 58 +++++++++++++++++++++++++++ .forgejo/workflows/deploy-prod.yml | 58 +++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 .forgejo/workflows/deploy-preprod.yml create mode 100644 .forgejo/workflows/deploy-prod.yml diff --git a/.forgejo/workflows/deploy-preprod.yml b/.forgejo/workflows/deploy-preprod.yml new file mode 100644 index 0000000..441c01b --- /dev/null +++ b/.forgejo/workflows/deploy-preprod.yml @@ -0,0 +1,58 @@ +name: Deploy Preprod + +on: + push: + branches: + - preprod + +jobs: + build-and-deploy: + name: Build and Deploy to Preprod + runs-on: docker + container: + image: forgejo-ci-node:latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Cache node modules + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + + - name: Install npm dependencies + run: npm install + + - name: Build frontend (preprod) + run: npm run build:preprod + + - name: Install composer dependencies + run: | + cd dist + composer install --no-dev --optimize-autoloader --ignore-platform-req=ext-gd + + - name: Deploy via rsync + env: + USERNAME: ${{ secrets.USERNAME }} + PASSWORD: ${{ secrets.PASSWORD }} + HOST: ${{ secrets.HOST }} + PREPROD_PATH: ${{ secrets.PREPROD_PATH }} + run: | + cd dist + + rsync_deploy() { + local src=$1 + local dst=$2 + local exclude=$3 + cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" + [[ -n $exclude ]] && cmd="$cmd $exclude" + cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" + echo "Deploying $src to $dst" + eval $cmd + } + + rsync_deploy site/ "$PREPROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" + rsync_deploy vendor/ "$PREPROD_PATH/vendor/" + rsync_deploy kirby/ "$PREPROD_PATH/kirby/" + rsync_deploy assets/ "$PREPROD_PATH/assets/" "--exclude 'tiles/'" diff --git a/.forgejo/workflows/deploy-prod.yml b/.forgejo/workflows/deploy-prod.yml new file mode 100644 index 0000000..4943bb2 --- /dev/null +++ b/.forgejo/workflows/deploy-prod.yml @@ -0,0 +1,58 @@ +name: Deploy Production + +on: + push: + branches: + - main + +jobs: + build-and-deploy: + name: Build and Deploy to Production + runs-on: docker + container: + image: forgejo-ci-node:latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Cache node modules + uses: actions/cache@v4 + with: + path: node_modules + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + + - name: Install npm dependencies + run: npm install + + - name: Build frontend (production) + run: npm run build + + - name: Install composer dependencies + run: | + cd dist + composer install --no-dev --optimize-autoloader --ignore-platform-req=ext-gd + + - name: Deploy via rsync + env: + USERNAME: ${{ secrets.USERNAME }} + PASSWORD: ${{ secrets.PASSWORD }} + HOST: ${{ secrets.HOST }} + PROD_PATH: ${{ secrets.PROD_PATH }} + run: | + cd dist + + rsync_deploy() { + local src=$1 + local dst=$2 + local exclude=$3 + cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" + [[ -n $exclude ]] && cmd="$cmd $exclude" + cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" + echo "Deploying $src to $dst" + eval $cmd + } + + rsync_deploy site/ "$PROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" + rsync_deploy vendor/ "$PROD_PATH/vendor/" + rsync_deploy kirby/ "$PROD_PATH/kirby/" + rsync_deploy assets/ "$PROD_PATH/assets/" "--exclude 'tiles/'" From 2186e33b2929f36db83b943a50853ff87bff1865 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Thu, 15 Jan 2026 14:59:54 +0100 Subject: [PATCH 09/44] fix forgejo ci --- .forgejo/workflows/deploy-preprod.yml | 10 +++------- .forgejo/workflows/deploy-prod.yml | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.forgejo/workflows/deploy-preprod.yml b/.forgejo/workflows/deploy-preprod.yml index 441c01b..3a842dc 100644 --- a/.forgejo/workflows/deploy-preprod.yml +++ b/.forgejo/workflows/deploy-preprod.yml @@ -13,13 +13,9 @@ jobs: image: forgejo-ci-node:latest steps: - name: Checkout code - uses: actions/checkout@v4 - - - name: Cache node modules - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + run: | + git clone --depth 1 --branch preprod https://forge.studio-variable.com/${{ github.repository }}.git . + ls -la - name: Install npm dependencies run: npm install diff --git a/.forgejo/workflows/deploy-prod.yml b/.forgejo/workflows/deploy-prod.yml index 4943bb2..e4084d6 100644 --- a/.forgejo/workflows/deploy-prod.yml +++ b/.forgejo/workflows/deploy-prod.yml @@ -13,13 +13,9 @@ jobs: image: forgejo-ci-node:latest steps: - name: Checkout code - uses: actions/checkout@v4 - - - name: Cache node modules - uses: actions/cache@v4 - with: - path: node_modules - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + run: | + git clone --depth 1 --branch main https://forge.studio-variable.com/${{ github.repository }}.git . + ls -la - name: Install npm dependencies run: npm install From 5f214629ef354049dc38f8d3f323bf0978217896 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Thu, 15 Jan 2026 15:10:50 +0100 Subject: [PATCH 10/44] CI : update --- .forgejo/workflows/deploy-preprod.yml | 2 +- .forgejo/workflows/deploy-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.forgejo/workflows/deploy-preprod.yml b/.forgejo/workflows/deploy-preprod.yml index 3a842dc..771af75 100644 --- a/.forgejo/workflows/deploy-preprod.yml +++ b/.forgejo/workflows/deploy-preprod.yml @@ -26,7 +26,7 @@ jobs: - name: Install composer dependencies run: | cd dist - composer install --no-dev --optimize-autoloader --ignore-platform-req=ext-gd + composer install --no-dev --optimize-autoloader - name: Deploy via rsync env: diff --git a/.forgejo/workflows/deploy-prod.yml b/.forgejo/workflows/deploy-prod.yml index e4084d6..59f3937 100644 --- a/.forgejo/workflows/deploy-prod.yml +++ b/.forgejo/workflows/deploy-prod.yml @@ -26,7 +26,7 @@ jobs: - name: Install composer dependencies run: | cd dist - composer install --no-dev --optimize-autoloader --ignore-platform-req=ext-gd + composer install --no-dev --optimize-autoloader - name: Deploy via rsync env: From f994b1c9828d63e0b7444cca13b77cf30c129f06 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Thu, 15 Jan 2026 15:39:50 +0100 Subject: [PATCH 11/44] Fix Forgejo CI workflows and add .gitkeep files - Fix rsync exclusions to properly preserve accounts, cache, and sessions - Remove tiles exclusion (not used in this project) - Add .gitkeep files to track empty directories structure - Update .gitignore to allow .gitkeep files Co-Authored-By: Claude Sonnet 4.5 --- .forgejo/workflows/deploy-preprod.yml | 38 +++++++++++++++++---------- .forgejo/workflows/deploy-prod.yml | 38 +++++++++++++++++---------- .gitignore | 3 +++ public/site/accounts/.gitkeep | 0 public/site/cache/.gitkeep | 0 public/site/sessions/.gitkeep | 0 6 files changed, 51 insertions(+), 28 deletions(-) create mode 100644 public/site/accounts/.gitkeep create mode 100644 public/site/cache/.gitkeep create mode 100644 public/site/sessions/.gitkeep diff --git a/.forgejo/workflows/deploy-preprod.yml b/.forgejo/workflows/deploy-preprod.yml index 771af75..df6b075 100644 --- a/.forgejo/workflows/deploy-preprod.yml +++ b/.forgejo/workflows/deploy-preprod.yml @@ -37,18 +37,28 @@ jobs: run: | cd dist - rsync_deploy() { - local src=$1 - local dst=$2 - local exclude=$3 - cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" - [[ -n $exclude ]] && cmd="$cmd $exclude" - cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" - echo "Deploying $src to $dst" - eval $cmd - } + echo "Deploying site/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + --exclude 'accounts/*' \ + --exclude 'cache/*' \ + --exclude 'sessions/*' \ + --include 'accounts/' \ + --include 'cache/' \ + --include 'sessions/' \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + site/ $USERNAME@$HOST:$PREPROD_PATH/site/ - rsync_deploy site/ "$PREPROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" - rsync_deploy vendor/ "$PREPROD_PATH/vendor/" - rsync_deploy kirby/ "$PREPROD_PATH/kirby/" - rsync_deploy assets/ "$PREPROD_PATH/assets/" "--exclude 'tiles/'" + echo "Deploying vendor/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + vendor/ $USERNAME@$HOST:$PREPROD_PATH/vendor/ + + echo "Deploying kirby/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + kirby/ $USERNAME@$HOST:$PREPROD_PATH/kirby/ + + echo "Deploying assets/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + assets/ $USERNAME@$HOST:$PREPROD_PATH/assets/ diff --git a/.forgejo/workflows/deploy-prod.yml b/.forgejo/workflows/deploy-prod.yml index 59f3937..d407912 100644 --- a/.forgejo/workflows/deploy-prod.yml +++ b/.forgejo/workflows/deploy-prod.yml @@ -37,18 +37,28 @@ jobs: run: | cd dist - rsync_deploy() { - local src=$1 - local dst=$2 - local exclude=$3 - cmd="sshpass -p \"$PASSWORD\" rsync -az --delete -O" - [[ -n $exclude ]] && cmd="$cmd $exclude" - cmd="$cmd -e 'ssh -p 2244 -o StrictHostKeyChecking=no' $src $USERNAME@$HOST:$dst" - echo "Deploying $src to $dst" - eval $cmd - } + echo "Deploying site/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + --exclude 'accounts/*' \ + --exclude 'cache/*' \ + --exclude 'sessions/*' \ + --include 'accounts/' \ + --include 'cache/' \ + --include 'sessions/' \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + site/ $USERNAME@$HOST:$PROD_PATH/site/ - rsync_deploy site/ "$PROD_PATH/site/" "--exclude 'accounts/' --exclude 'cache/' --exclude 'sessions/'" - rsync_deploy vendor/ "$PROD_PATH/vendor/" - rsync_deploy kirby/ "$PROD_PATH/kirby/" - rsync_deploy assets/ "$PROD_PATH/assets/" "--exclude 'tiles/'" + echo "Deploying vendor/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + vendor/ $USERNAME@$HOST:$PROD_PATH/vendor/ + + echo "Deploying kirby/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + kirby/ $USERNAME@$HOST:$PROD_PATH/kirby/ + + echo "Deploying assets/" + sshpass -p "$PASSWORD" rsync -az --delete -O \ + -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ + assets/ $USERNAME@$HOST:$PROD_PATH/assets/ diff --git a/.gitignore b/.gitignore index bb14856..15c0a18 100644 --- a/.gitignore +++ b/.gitignore @@ -62,18 +62,21 @@ public/.idea public/site/cache/* !public/site/cache/index.html +!public/site/cache/.gitkeep # Accounts # --------------- public/site/accounts/* !public/site/accounts/index.html +!public/site/accounts/.gitkeep # Sessions # --------------- public/site/sessions/* !public/site/sessions/index.html +!public/site/sessions/.gitkeep # License # --------------- diff --git a/public/site/accounts/.gitkeep b/public/site/accounts/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/site/cache/.gitkeep b/public/site/cache/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/site/sessions/.gitkeep b/public/site/sessions/.gitkeep new file mode 100644 index 0000000..e69de29 From 78ac0940d070755f5ba23e8c353ea675bb84a8ff Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 30 Jan 2026 08:02:50 +0100 Subject: [PATCH 12/44] config : enable panel install on production --- .forgejo/workflows/deploy-preprod.yml | 8 ++++---- public/site/config/config.php | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.forgejo/workflows/deploy-preprod.yml b/.forgejo/workflows/deploy-preprod.yml index df6b075..190e138 100644 --- a/.forgejo/workflows/deploy-preprod.yml +++ b/.forgejo/workflows/deploy-preprod.yml @@ -39,12 +39,12 @@ jobs: echo "Deploying site/" sshpass -p "$PASSWORD" rsync -az --delete -O \ - --exclude 'accounts/*' \ - --exclude 'cache/*' \ - --exclude 'sessions/*' \ --include 'accounts/' \ - --include 'cache/' \ + --exclude 'accounts/*' \ --include 'sessions/' \ + --exclude 'sessions/*' \ + --include 'cache/' \ + --exclude 'cache/*' \ -e 'ssh -p 2244 -o StrictHostKeyChecking=no' \ site/ $USERNAME@$HOST:$PREPROD_PATH/site/ diff --git a/public/site/config/config.php b/public/site/config/config.php index 37f3a33..97ceb2c 100644 --- a/public/site/config/config.php +++ b/public/site/config/config.php @@ -25,6 +25,7 @@ return [ 'css' => 'assets/css/panel.css', 'favicon' => 'favicon.svg', 'menu' => require(__DIR__ . '/menu.php'), + 'install' => 'true' ], 'routes' => [ require(__DIR__ . '/routes/logout.php'), From f9be7fa0255c466111658a97f889dce92330b618 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 30 Jan 2026 08:10:23 +0100 Subject: [PATCH 13/44] fix CI --- .forgejo/workflows/deploy-preprod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/deploy-preprod.yml b/.forgejo/workflows/deploy-preprod.yml index 190e138..cbe2808 100644 --- a/.forgejo/workflows/deploy-preprod.yml +++ b/.forgejo/workflows/deploy-preprod.yml @@ -38,7 +38,7 @@ jobs: cd dist echo "Deploying site/" - sshpass -p "$PASSWORD" rsync -az --delete -O \ + sshpass -p "$PASSWORD" rsync -az --delete -O --no-perms --no-owner --no-group \ --include 'accounts/' \ --exclude 'accounts/*' \ --include 'sessions/' \ From 2b5175900cbd0e92c72d1fc3ec67c6aebfa93a27 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 30 Jan 2026 08:29:14 +0100 Subject: [PATCH 14/44] Fix ordre des pistes dans virtual sample MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Respect de l'ordre des groupes défini dans le champ groups du panel. Co-Authored-By: Claude Sonnet 4.5 --- public/site/models/project.php | 36 ++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/public/site/models/project.php b/public/site/models/project.php index 583bfeb..de53a50 100644 --- a/public/site/models/project.php +++ b/public/site/models/project.php @@ -142,19 +142,19 @@ class ProjectPage extends NotificationsPage { if ($child->hasChildren()) { $files['dynamic'] = []; - + foreach ($child->children() as $key => $track) { $trackData = [ 'title' => (string) $track->title(), 'slug' => (string) $track->slug(), 'backgroundColor' => (string) $track->backgroundColor(), 'files' => [], - ]; - + ]; + foreach ($track->views()->toFiles() as $view) { $trackData['files'][] = getFileData($view, true); } - + if ($track->group()->isNotEmpty()) { $files['dynamic'][$track->group()->value()][] = $trackData; } else { @@ -162,12 +162,36 @@ class ProjectPage extends NotificationsPage { } } + // Récupérer l'ordre des groupes depuis le champ groups + $orderedGroups = $child->groups()->split(); + + // Réorganiser $files['dynamic'] selon l'ordre défini + if (!empty($orderedGroups)) { + $orderedDynamic = []; + + foreach ($orderedGroups as $group) { + if (isset($files['dynamic'][$group])) { + $orderedDynamic[$group] = $files['dynamic'][$group]; + } + } + + // Ajouter les groupes non définis dans le champ à la fin + foreach ($files['dynamic'] as $group => $tracks) { + if (!isset($orderedDynamic[$group])) { + $orderedDynamic[$group] = $tracks; + } + } + + $files['dynamic'] = $orderedDynamic; + } + + // Toujours mettre "Autres pistes" à la fin if (isset($files['dynamic']['Autres pistes'])) { $others = $files['dynamic']['Autres pistes']; unset($files['dynamic']['Autres pistes']); $files['dynamic']['Autres pistes'] = $others; } - + } if ($child->rawGlass()->isNotEmpty() || $child->finishedGlass()->isNotEmpty()) { @@ -177,7 +201,7 @@ class ProjectPage extends NotificationsPage { if ($child->rawGlass()->isNotEmpty()) { $files['static']['rawGlass'] = getFileData($child->rawGlass()->toFile()); } - + if ($child->finishedGlass()->isNotEmpty()) { $files['static']['finishedGlass'] = getFileData($child->finishedGlass()->toFile()); } From 7ca72c6d82617dfbaea730e46e5e3f34fe366394 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Fri, 30 Jan 2026 09:13:31 +0100 Subject: [PATCH 15/44] Extended-brief supporte maintenant images + PDF comme client-brief MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Blueprint : ajout champs moodboard et description - Kanban : utilise ClientBrief au lieu de SimpleDocument - Validation : support extended-brief depuis PDF et page images - Navigation : paths dynamiques basés sur step.slug Co-Authored-By: Claude Sonnet 4.5 --- public/site/blueprints/pages/extended-brief.yml | 10 ++++++++++ src/components/project/ProjectStep.vue | 2 +- src/components/project/TitledPdfWrapper.vue | 4 ++-- src/components/project/cards/ClientBrief.vue | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/public/site/blueprints/pages/extended-brief.yml b/public/site/blueprints/pages/extended-brief.yml index 5c96ee2..88ce3b2 100644 --- a/public/site/blueprints/pages/extended-brief.yml +++ b/public/site/blueprints/pages/extended-brief.yml @@ -42,4 +42,14 @@ tabs: type: files multiple: false uploads: pdf + description: + type: textarea + size: tiny + buttons: false + moodboard: + label: Images + type: files + template: image + layout: cards + size: medium files: tabs/files diff --git a/src/components/project/ProjectStep.vue b/src/components/project/ProjectStep.vue index f9718bb..5fa68a1 100644 --- a/src/components/project/ProjectStep.vue +++ b/src/components/project/ProjectStep.vue @@ -37,7 +37,7 @@ const { step } = defineProps({ const cardsMap = { clientBrief: ClientBrief, proposal: MultipleDocuments, - extendedBrief: SimpleDocument, + extendedBrief: ClientBrief, industrialIdeation: SimpleDocument, virtualSample: VirtualSample, physicalSample: PhysicalSample, diff --git a/src/components/project/TitledPdfWrapper.vue b/src/components/project/TitledPdfWrapper.vue index a1e6fbf..8793a2c 100644 --- a/src/components/project/TitledPdfWrapper.vue +++ b/src/components/project/TitledPdfWrapper.vue @@ -16,7 +16,7 @@ @@ -11,6 +11,9 @@ diff --git a/src/components/project/virtual-sample/DynamicView.vue b/src/components/project/virtual-sample/DynamicView.vue index ad3c65e..a725334 100644 --- a/src/components/project/virtual-sample/DynamicView.vue +++ b/src/components/project/virtual-sample/DynamicView.vue @@ -87,7 +87,7 @@ const tracks = computed(() => { for (const key in raw) { list.push({ - title: key, + title: key === 'Autres pistes' ? t('virtualSample.otherTracks') : key, slug: slugify(key), variations: raw[key] || [], }); diff --git a/src/locales/en.json b/src/locales/en.json index 0ddf7d5..12c6e26 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -70,7 +70,8 @@ "loopAnimation": "Loop animation", "stopAnimation": "Stop animation", "compareTracks": "Compare tracks", - "exitCompare": "Exit compare mode" + "exitCompare": "Exit compare mode", + "addSelectedImages": "Add selected images" }, "forms": { "email": "Email", @@ -94,7 +95,8 @@ "tags": "Tags", "selectVariation": "Select a variation", "uploadedFiles": "Uploaded files", - "addImages": "Add one or more images" + "addImages": "Add one or more images", + "selectTags": "Select one or more tags" }, "auth": { "login": "Login", @@ -184,7 +186,8 @@ "dynamicPresentation": "Dynamic presentation", "staticView": "Static view", "noContent": "Content not available for this track", - "selectToCompare": "Select the track you want to compare" + "selectToCompare": "Select the track you want to compare", + "otherTracks": "Other tracks" }, "errors": { "saveFailed": "Save failed", diff --git a/src/locales/fr.json b/src/locales/fr.json index b155bcb..df53b21 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -70,7 +70,8 @@ "loopAnimation": "Animation en boucle", "stopAnimation": "Arrêter l'animation", "compareTracks": "Comparer les pistes", - "exitCompare": "Quitter le mode comparer" + "exitCompare": "Quitter le mode comparer", + "addSelectedImages": "Ajouter les images sélectionnées" }, "forms": { "email": "Email", @@ -94,7 +95,8 @@ "tags": "Tags", "selectVariation": "Sélectionnez une déclinaison", "uploadedFiles": "Fichiers importés", - "addImages": "Ajouter une ou plusieurs images" + "addImages": "Ajouter une ou plusieurs images", + "selectTags": "Sélectionner un ou plusieurs tags" }, "auth": { "login": "Connexion", @@ -184,7 +186,8 @@ "dynamicPresentation": "Présentation dynamique", "staticView": "Vue statique", "noContent": "Contenu non disponible pour cette piste", - "selectToCompare": "Sélectionnez sur la piste que vous souhaitez comparer" + "selectToCompare": "Sélectionnez sur la piste que vous souhaitez comparer", + "otherTracks": "Autres pistes" }, "errors": { "saveFailed": "Erreur lors de la sauvegarde", From cd1b374d103697d794d53da0322c0b6989e925b6 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 4 Mar 2026 13:48:33 +0100 Subject: [PATCH 36/44] fix: corriger les erreurs sur la route /login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Échapper le @ dans les placeholders email (vue-i18n v9 interprète @ comme message linking) - Gérer l'erreur silencieusement quand projects.json est inaccessible (user non connecté) Co-Authored-By: Claude Sonnet 4.6 --- src/locales/en.json | 2 +- src/locales/fr.json | 2 +- src/stores/projects.js | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index 12c6e26..78442ce 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -75,7 +75,7 @@ }, "forms": { "email": "Email", - "emailPlaceholder": "email@example.com", + "emailPlaceholder": "email{'@'}example.com", "password": "Password", "passwordPlaceholder": "Minimum 8 characters", "newPassword": "New password", diff --git a/src/locales/fr.json b/src/locales/fr.json index df53b21..5f6cd69 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -75,7 +75,7 @@ }, "forms": { "email": "Email", - "emailPlaceholder": "mail@exemple.com", + "emailPlaceholder": "mail{'@'}exemple.com", "password": "Mot de passe", "passwordPlaceholder": "Minimum 8 caractères", "newPassword": "Nouveau mot de passe", diff --git a/src/stores/projects.js b/src/stores/projects.js index 870a543..be62742 100644 --- a/src/stores/projects.js +++ b/src/stores/projects.js @@ -52,6 +52,8 @@ export const useProjectsStore = defineStore('projects', () => { isProjectsLoading.value = false; projects.value = json.page.children; // }, 3000); + }).catch(() => { + isProjectsLoading.value = false; }); // Functions From 7425a1493dc9f4cc03544515aa67f52a82bdcf5e Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 4 Mar 2026 14:44:00 +0100 Subject: [PATCH 37/44] =?UTF-8?q?feat:=20admin=20voit=20tous=20les=20proje?= =?UTF-8?q?ts=20seulement=20si=20aucun=20ne=20lui=20est=20assign=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Si un admin a au moins un projet assigné, il ne voit que ses projets. S'il n'en a aucun, il voit tous les projets (comportement précédent). Co-Authored-By: Claude Sonnet 4.6 --- public/site/plugins/user-projects/index.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/public/site/plugins/user-projects/index.php b/public/site/plugins/user-projects/index.php index 733a9b3..c1a4f3f 100644 --- a/public/site/plugins/user-projects/index.php +++ b/public/site/plugins/user-projects/index.php @@ -3,20 +3,21 @@ Kirby::plugin('adrienpayet/pdc-authorized-projects', [ 'userMethods' => [ 'currentProjects' => function() { - if ($this->role() == 'admin') { - return page('projects')->children()->listed(); + $listed = page('projects')->children()->listed(); + if ($this->role() == 'admin' && $this->hasNoAssignedProjects()) { + return $listed; } - return page('projects')->children()->listed()->filter(function($project) { - return $project->users()->toUsers()->has($this); - }); + return $listed->filter(fn($project) => $project->users()->toUsers()->has($this)); }, 'archivedProjects' => function() { - if ($this->role() == 'admin') { - return page('projects')->children()->unlisted(); + $unlisted = page('projects')->children()->unlisted(); + if ($this->role() == 'admin' && $this->hasNoAssignedProjects()) { + return $unlisted; } - return page('projects')->children()->unlisted()->filter(function($project) { - return $project->users()->toUsers()->has($this); - }); + return $unlisted->filter(fn($project) => $project->users()->toUsers()->has($this)); + }, + 'hasNoAssignedProjects' => function() { + return page('projects')->children()->filter(fn($p) => $p->users()->toUsers()->has($this))->isEmpty(); }, ] ]); From aceb8c7fdb46fc753ac68718c6f100aa8ec90b4b Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 4 Mar 2026 15:07:04 +0100 Subject: [PATCH 38/44] fix: appliquer le filtre d'assignation admin dans projects.json.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le template bypassait currentProjects() pour les admins. Maintenant : - Admin sans projets assignés → tous les projets (comportement d'origine) - Admin avec projets assignés → uniquement ses projets (listed + unlisted) - Autres rôles → inchangé Co-Authored-By: Claude Sonnet 4.6 --- public/site/templates/projects.json.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/public/site/templates/projects.json.php b/public/site/templates/projects.json.php index 542ee7e..6f589eb 100644 --- a/public/site/templates/projects.json.php +++ b/public/site/templates/projects.json.php @@ -44,9 +44,12 @@ function getProjectData($project, $user) $currentUser = $kirby->user(); try { - $children = $currentUser->role() == 'admin' - ? $page->childrenAndDrafts()->map(fn($project) => getProjectData($project, $currentUser))->values() - : $currentUser->currentProjects()->map(fn($project) => getProjectData($project, $currentUser))->values(); + if ($currentUser->role() == 'admin' && $currentUser->hasNoAssignedProjects()) { + $projectCollection = $page->childrenAndDrafts(); + } else { + $projectCollection = $currentUser->currentProjects()->merge($currentUser->archivedProjects()); + } + $children = $projectCollection->map(fn($project) => getProjectData($project, $currentUser))->values(); } catch (\Throwable $th) { throw new Exception($th->getMessage() . ' line ' . $th->getLine() . ' in file ' . $th->getFile(), 1); $children = []; From 86d48e415cf98f12a4101b885c4af219a0bdb543 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Sun, 8 Mar 2026 17:46:55 +0100 Subject: [PATCH 39/44] fix: ajuster le style du plugin analytics et corriger le nom du toggle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Supprime le doublon de séparateur dans le menu - Retire les box-shadow/padding superflus, ajuste les marges - Corrige le name du toggle topPages en kebab-case (top-pages) Co-Authored-By: Claude Sonnet 4.6 --- public/site/config/menu.php | 1 - public/site/plugins/analytics/index.css | 18 ++++----------- public/site/plugins/analytics/index.js | 2 +- .../src/components/AnalyticsDashboard.vue | 22 +++++-------------- 4 files changed, 11 insertions(+), 32 deletions(-) diff --git a/public/site/config/menu.php b/public/site/config/menu.php index dc00b7e..8198cbd 100644 --- a/public/site/config/menu.php +++ b/public/site/config/menu.php @@ -59,7 +59,6 @@ $menu = [ } ], '-', - '-', 'analytics' => [ 'label' => 'Analytics', 'icon' => 'chart', diff --git a/public/site/plugins/analytics/index.css b/public/site/plugins/analytics/index.css index a0dd05a..67f9106 100644 --- a/public/site/plugins/analytics/index.css +++ b/public/site/plugins/analytics/index.css @@ -1,18 +1,13 @@ -.k-analytics-dashboard { - padding: 1.5rem 0; -} .k-analytics-filters { display: flex; gap: 1rem; - margin-bottom: 1.5rem; } .k-analytics-filters label { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; - color: var(--color-text-light); } .k-date-inputs-wrapper { display: flex; @@ -29,33 +24,32 @@ display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; - margin-bottom: 1.5rem; + margin: 3rem 0; } .k-analytics-user-filter { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; - color: var(--color-text-light); margin-left: 2rem; } .k-field-name-user, .k-field-name-page { min-width: 15rem; } +.k-field-name-top-pages { + margin-left: 1rem; +} .k-analytics-page-filter { display: flex; align-items: center; gap: 0.5rem; font-size: 0.875rem; - color: var(--color-text-light); margin-left: 2rem; } .k-analytics-card { background: var(--color-background); border-radius: var(--rounded); - padding: 1.5rem; - box-shadow: var(--shadow); } .k-analytics-card h3 { font-size: 0.75rem; @@ -74,13 +68,10 @@ .k-analytics-chart-container { background: var(--color-background); border-radius: var(--rounded); - padding: 1.5rem; margin-bottom: 1.5rem; - box-shadow: var(--shadow); } .k-analytics-chart-header { display: flex; - justify-content: space-between; align-items: center; margin-bottom: 1rem; } @@ -98,7 +89,6 @@ border-radius: var(--rounded); padding: 3rem; text-align: center; - box-shadow: var(--shadow); } .k-analytics-empty p { margin: 0; diff --git a/public/site/plugins/analytics/index.js b/public/site/plugins/analytics/index.js index 3253af0..51f7aa4 100644 --- a/public/site/plugins/analytics/index.js +++ b/public/site/plugins/analytics/index.js @@ -11679,7 +11679,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy } } })]), _c("label", [_vm._v(" Au "), _c("input", { directives: [{ name: "model", rawName: "v-model", value: _vm.endDate, expression: "endDate" }], attrs: { "type": "date" }, domProps: { "value": _vm.endDate }, on: { "change": _vm.fetchData, "input": function($event) { if ($event.target.composing) return; _vm.endDate = $event.target.value; - } } })])])]), _c("div", { staticClass: "k-analytics-user-filter" }, [_c("k-multiselect-field", { attrs: { "options": _vm.userOptions, "value": _vm.selectedEmails, "label": "Filtrer par utilisateur(s)", "search": "true", "name": "user" }, on: { "input": _vm.onUserSelectionChange } })], 1), _c("div", { staticClass: "k-analytics-page-filter" }, [_c("k-multiselect-field", { attrs: { "options": _vm.pageOptions, "value": _vm.selectedPages, "label": "Filtrer par page(s)", "search": "true", "name": "page" }, on: { "input": _vm.onPageSelectionChange } })], 1)]), !_vm.hasData ? _c("div", { staticClass: "k-analytics-empty" }, [_c("p", [_vm._v("Aucune donnée à afficher")])]) : [_c("div", { staticClass: "k-analytics-grid" }, [_c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Sessions uniques")]), _c("div", { staticClass: "k-analytics-metric" }, [_vm._v(_vm._s(_vm.data.uniqueSessions))])]), _c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Pages vues")]), _c("div", { staticClass: "k-analytics-metric" }, [_vm._v(_vm._s(_vm.data.totalVisits))])]), _c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Pages / session")]), _c("div", { staticClass: "k-analytics-metric" }, [_vm._v(_vm._s(_vm.pagesPerSession))])])]), _c("div", { staticClass: "k-analytics-chart-container" }, [_c("div", { staticClass: "k-analytics-chart-header" }, [_c("h3", [_vm._v("Visites par jour")]), _vm.selectedPages.length === 0 ? _c("k-toggle-field", { attrs: { "value": _vm.showTopPagesOnly, "before": "Moyenne", "after": "Pages les + visitées", "text": " ", "name": "topPages" }, on: { "input": _vm.onToggleTopPages } }) : _vm._e()], 1), _c("canvas", { ref: "chartCanvas" })]), _vm.data.visitsByPage && Object.keys(_vm.data.visitsByPage).length ? _c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Pages les plus visitées")]), _c("ul", { staticClass: "k-analytics-list" }, _vm._l(_vm.data.visitsByPage, function(count, page) { + } } })])])]), _c("div", { staticClass: "k-analytics-user-filter" }, [_c("k-multiselect-field", { attrs: { "options": _vm.userOptions, "value": _vm.selectedEmails, "label": "Filtrer par utilisateur(s)", "search": "true", "name": "user" }, on: { "input": _vm.onUserSelectionChange } })], 1), _c("div", { staticClass: "k-analytics-page-filter" }, [_c("k-multiselect-field", { attrs: { "options": _vm.pageOptions, "value": _vm.selectedPages, "label": "Filtrer par page(s)", "search": "true", "name": "page" }, on: { "input": _vm.onPageSelectionChange } })], 1)]), !_vm.hasData ? _c("div", { staticClass: "k-analytics-empty" }, [_c("p", [_vm._v("Aucune donnée à afficher")])]) : [_c("div", { staticClass: "k-analytics-grid" }, [_c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Sessions uniques")]), _c("div", { staticClass: "k-analytics-metric" }, [_vm._v(_vm._s(_vm.data.uniqueSessions))])]), _c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Pages vues")]), _c("div", { staticClass: "k-analytics-metric" }, [_vm._v(_vm._s(_vm.data.totalVisits))])]), _c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Pages / session")]), _c("div", { staticClass: "k-analytics-metric" }, [_vm._v(_vm._s(_vm.pagesPerSession))])])]), _c("div", { staticClass: "k-analytics-chart-container" }, [_c("div", { staticClass: "k-analytics-chart-header" }, [_c("h3", [_vm._v("Visites par jour")]), _vm.selectedPages.length === 0 ? _c("k-toggle-field", { attrs: { "value": _vm.showTopPagesOnly, "before": "Moyenne", "after": "Pages les + visitées", "text": " ", "name": "top-pages" }, on: { "input": _vm.onToggleTopPages } }) : _vm._e()], 1), _c("canvas", { ref: "chartCanvas" })]), _vm.data.visitsByPage && Object.keys(_vm.data.visitsByPage).length ? _c("div", { staticClass: "k-analytics-card" }, [_c("h3", [_vm._v("Pages les plus visitées")]), _c("ul", { staticClass: "k-analytics-list" }, _vm._l(_vm.data.visitsByPage, function(count, page) { return _c("li", { key: page }, [_c("span", { staticClass: "k-analytics-list-label" }, [_vm._v(_vm._s(page))]), _c("span", { staticClass: "k-analytics-list-value" }, [_vm._v(_vm._s(count))])]); }), 0)]) : _vm._e()]], 2); }; diff --git a/public/site/plugins/analytics/src/components/AnalyticsDashboard.vue b/public/site/plugins/analytics/src/components/AnalyticsDashboard.vue index cd8f1aa..879bd59 100644 --- a/public/site/plugins/analytics/src/components/AnalyticsDashboard.vue +++ b/public/site/plugins/analytics/src/components/AnalyticsDashboard.vue @@ -69,7 +69,7 @@ before="Moyenne" after="Pages les + visitées" text=" " - name="topPages" + name="top-pages" @input="onToggleTopPages" /> @@ -344,14 +344,9 @@ export default {