Fix formateur login/visibility, docker build, and calendar refresh bugs

- Correct system diagnostic to check v_Formateurs_CD (the view actually
  used) instead of the nonexistent v_Formateurs_CD_Declarations, which
  was forcing the backend into degraded legacy_hash mode and blocking
  all formateurs except the hardcoded special case.
- Add .dockerignore to frontend/backend so the Windows-installed
  node_modules doesn't overwrite the container's npm install (was
  causing "vite: not found").
- Fetch declarations with cache: 'no-store' and await the save
  callback so the calendar reflects a new entry without a page reload.
- Add docker-compose.prod.yml using published Docker Hub images.
This commit is contained in:
2026-08-06 09:45:23 +02:00
parent 159003672e
commit 43f5738545
6 changed files with 43 additions and 5 deletions
+33
View File
@@ -0,0 +1,33 @@
version: "3.9"
services:
backend:
image: ouijdaneim/gtf-backend:latest
ports:
- "8000:3000"
environment:
- DB_SERVER=192.168.0.3
- DB_DATABASE=GTF
- DB_USER=gtf_app
- DB_PASSWORD=GTF2025!Secure
- DB_ENCRYPT=true
- DB_TRUST_SERVER_CERTIFICATE=true
- PORT=3000
extra_hosts:
- "BONEMINE:192.168.0.3"
- "bonemine.ensup.local:192.168.0.3"
restart: unless-stopped
frontend:
image: ouijdaneim/gtf-frontend:latest
ports:
- "3001:3001"
volumes:
# Chemin du certificat HTTPS sur l'HÔTE DE PROD — à adapter s'il diffère de ce poste
- C:\Users\oimer\.aspnet\https:/https:ro
environment:
- ASPNETCORE_URLS=https://+:3001;http://+:3001
- ASPNETCORE_Kestrel__Certificates__Default__Password=tGTF2025
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
- VITE_API_BASE_URL=https://mygtf.ensup-adm.net:8000
restart: unless-stopped
+3
View File
@@ -0,0 +1,3 @@
node_modules
dist
.git
+2
View File
@@ -0,0 +1,2 @@
node_modules
.git
+2 -2
View File
@@ -64,13 +64,13 @@ async function checkSystemStatus() {
const viewCheck = await pool.request().query(` const viewCheck = await pool.request().query(`
SELECT COUNT(*) AS count SELECT COUNT(*) AS count
FROM INFORMATION_SCHEMA.VIEWS FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_NAME = 'v_Formateurs_CD_Declarations' WHERE TABLE_NAME = 'v_Formateurs_CD'
`); `);
systemStatus.hasFormateurView = viewCheck.recordset[0].count > 0; systemStatus.hasFormateurView = viewCheck.recordset[0].count > 0;
if (systemStatus.hasFormateurView) { if (systemStatus.hasFormateurView) {
try { try {
await pool.request().query(`SELECT TOP 1 userPrincipalName FROM dbo.v_Formateurs_CD_Declarations`); await pool.request().query(`SELECT TOP 1 userPrincipalName FROM dbo.v_Formateurs_CD`);
systemStatus.canAccessFormateurView = true; systemStatus.canAccessFormateurView = true;
} catch { } catch {
systemStatus.canAccessFormateurView = false; systemStatus.canAccessFormateurView = false;
+1 -1
View File
@@ -25,7 +25,7 @@ function App() {
return; return;
} }
const response = await fetch(`/api/get_declarations_by_email?email=${encodeURIComponent(user.email)}`); const response = await fetch(`/api/get_declarations_by_email?email=${encodeURIComponent(user.email)}`, { cache: 'no-store' });
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`HTTP error! status: ${response.status}`);
@@ -7,7 +7,7 @@ interface TimeEntryModalProps {
date: string; date: string;
entries: TimeEntry[]; entries: TimeEntry[];
onClose: () => void; onClose: () => void;
onSave: () => void; onSave: () => void | Promise<void>;
} }
const TimeEntryModal: React.FC<TimeEntryModalProps> = ({ const TimeEntryModal: React.FC<TimeEntryModalProps> = ({
@@ -215,7 +215,7 @@ const TimeEntryModal: React.FC<TimeEntryModalProps> = ({
return; return;
} }
onSave(); await onSave();
resetForm(); resetForm();
if (entries.length === 0) { if (entries.length === 0) {
onClose(); onClose();