fix: Deploying version dynamically + adding Tauri project files

This commit is contained in:
gauvainboiche
2026-08-02 18:18:29 +02:00
parent 165935521a
commit 257e187964
12 changed files with 4618 additions and 60 deletions
+1 -2
View File
@@ -1,7 +1,6 @@
# Origin project # Origin project
KetaPK_FR_1_00/ KetaPK_FR_1_00/
KetaPK_FR_1_00* KetaPK_FR_1_00*
# !KetaPK_FR_1_00.xlsm
code_vba.txt code_vba.txt
# Node files # Node files
@@ -15,7 +14,7 @@ __pycache__/
uv.lock uv.lock
# Tauri files # Tauri files
src-tauri/ src-tauri/*/
# Virtual environments # Virtual environments
.venv .venv
+10 -1
View File
@@ -1,4 +1,4 @@
import { MODES, PK_MODELS, CLINICAL_THRESHOLDS, generateSimulationData, processTimelineEvents } from './pkCore.js'; import { MODES, PK_MODELS, CLINICAL_THRESHOLDS, APP_VERSION, generateSimulationData, processTimelineEvents } from './pkCore.js';
import { adjustChartYScale } from './chartManager.js'; import { adjustChartYScale } from './chartManager.js';
import { initCalculatorUI } from './calculator.js'; import { initCalculatorUI } from './calculator.js';
import { exportSimulationToCSV } from './csvExport.js'; import { exportSimulationToCSV } from './csvExport.js';
@@ -8,6 +8,13 @@ let currentMode = MODES.ESKETAMINE;
let pkChart = null; let pkChart = null;
let currentSimulationData = null; let currentSimulationData = null;
function updateVersionDisplay() {
const versionEl = document.querySelector('[data-i18n="app.version"]');
if (versionEl) {
versionEl.textContent = t('app.version', { version: APP_VERSION });
}
}
const timelineInputs = Array.from({ length: 61 }, (_, i) => ({ const timelineInputs = Array.from({ length: 61 }, (_, i) => ({
time: i * 5, time: i * 5,
bolusMg: 0, bolusMg: 0,
@@ -16,12 +23,14 @@ const timelineInputs = Array.from({ length: 61 }, (_, i) => ({
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
await initI18n(); await initI18n();
updateVersionDisplay();
const selectLang = document.getElementById('selectLang'); const selectLang = document.getElementById('selectLang');
if (selectLang) { if (selectLang) {
selectLang.value = getCurrentLang(); selectLang.value = getCurrentLang();
selectLang.addEventListener('change', async (e) => { selectLang.addEventListener('change', async (e) => {
await initI18n(e.target.value); await initI18n(e.target.value);
updateVersionDisplay();
renderTimelineGrid(); renderTimelineGrid();
updateSimulation(); updateSimulation();
}); });
+12 -21
View File
@@ -1,8 +1,6 @@
import { t } from './i18n.js'; import { t } from './i18n.js';
import { APP_VERSION } from './pkCore.js';
/**
* Formate la date au format strict : YYYY_DD_MM_HH_MM_SS
*/
function getFormattedTimestamp() { function getFormattedTimestamp() {
const now = new Date(); const now = new Date();
const YYYY = now.getFullYear(); const YYYY = now.getFullYear();
@@ -14,27 +12,20 @@ function getFormattedTimestamp() {
return `${YYYY}_${DD}_${MM}_${HH}_${Min}_${SS}`; return `${YYYY}_${DD}_${MM}_${HH}_${Min}_${SS}`;
} }
/**
* Transforme le nom saisi en slug propre (ex: "DUPONT Jean" -> "dupont_jean")
*/
function slugify(text) { function slugify(text) {
if (!text) return ''; if (!text) return '';
return text return text
.toString() .toString()
.trim() .trim()
.toLowerCase() .toLowerCase()
.normalize("NFD").replace(/[\u0300-\u036f]/g, "") // Enlève les accents .normalize("NFD").replace(/[\u0300-\u036f]/g, "")
.replace(/[^a-z0-9]+/g, "_") // Remplace les caractères spéciaux par _ .replace(/[^a-z0-9]+/g, "_")
.replace(/^_+|_+$/g, ""); // Nettoie les _ aux bornes .replace(/^_+|_+$/g, "");
} }
/**
* Exporte les données de simulation au format CSV
*/
export async function exportSimulationToCSV(simulationData, patientInfo) { export async function exportSimulationToCSV(simulationData, patientInfo) {
if (!simulationData || !simulationData.timeline) return; if (!simulationData || !simulationData.timeline) return;
// \uFEFF (BOM UTF-8) pour qu'Excel ouvre le CSV directement avec les accents
let csvContent = "\uFEFF"; let csvContent = "\uFEFF";
// Métadonnées du rapport // Métadonnées du rapport
@@ -43,9 +34,12 @@ export async function exportSimulationToCSV(simulationData, patientInfo) {
csvContent += `${t('patient.name_label') || 'Patient'}:,${patientInfo.name}\n`; csvContent += `${t('patient.name_label') || 'Patient'}:,${patientInfo.name}\n`;
} }
csvContent += `${t('csv.weight')}:,${patientInfo.weight}\n`; csvContent += `${t('csv.weight')}:,${patientInfo.weight}\n`;
csvContent += `${t('csv.unit')}:,${patientInfo.infusionUnit}\n\n`; csvContent += `${t('csv.unit')}:,${patientInfo.infusionUnit}\n`;
// En-têtes du tableau selon la langue active // Ligne de Traçabilité de Version
csvContent += `${t('csv.version') || 'Version'}:,v${APP_VERSION}\n\n`;
// En-têtes du tableau
const headers = [ const headers = [
t('csv.col_time'), t('csv.col_time'),
t('csv.col_bolus'), t('csv.col_bolus'),
@@ -56,7 +50,7 @@ export async function exportSimulationToCSV(simulationData, patientInfo) {
]; ];
csvContent += headers.join(",") + "\n"; csvContent += headers.join(",") + "\n";
// Lignes de données (0 à 300 min) // Lignes de données
simulationData.timeline.forEach((item, index) => { simulationData.timeline.forEach((item, index) => {
const dominoCp = (simulationData.domino && simulationData.domino[index]) ? Math.round(simulationData.domino[index].cp) : "N/A"; const dominoCp = (simulationData.domino && simulationData.domino[index]) ? Math.round(simulationData.domino[index].cp) : "N/A";
const clementsCp = (simulationData.clements && simulationData.clements[index]) ? Math.round(simulationData.clements[index].cp) : "N/A"; const clementsCp = (simulationData.clements && simulationData.clements[index]) ? Math.round(simulationData.clements[index].cp) : "N/A";
@@ -73,14 +67,12 @@ export async function exportSimulationToCSV(simulationData, patientInfo) {
csvContent += row.join(",") + "\n"; csvContent += row.join(",") + "\n";
}); });
// Construction du nom de fichier : ketapk_YYYY_DD_MM_HH_MM_SS.csv ou ketapk_nom_prenom_YYYY_DD_MM_HH_MM_SS.csv
const timestamp = getFormattedTimestamp(); const timestamp = getFormattedTimestamp();
const slugName = slugify(patientInfo.name); const slugName = slugify(patientInfo.name);
const fileName = slugName const fileName = slugName
? `ketapk_${slugName}_${timestamp}.csv` ? `ketapk_${slugName}_${timestamp}.csv`
: `ketapk_${timestamp}.csv`; : `ketapk_${timestamp}.csv`;
// 1. Solution principale : API Native File System (Parfait sous WebView2 / Tauri Desktop)
if (window.showSaveFilePicker) { if (window.showSaveFilePicker) {
try { try {
const handle = await window.showSaveFilePicker({ const handle = await window.showSaveFilePicker({
@@ -95,12 +87,11 @@ export async function exportSimulationToCSV(simulationData, patientInfo) {
await writable.close(); await writable.close();
return; return;
} catch (err) { } catch (err) {
if (err.name === 'AbortError') return; // Annulation utilisateur if (err.name === 'AbortError') return;
console.warn('Fallback vers Data URI suite à lerreur native :', err); console.warn('Fallback vers Data URI :', err);
} }
} }
// 2. Fallback Data URI (Compatibilité web directe sans passer par Blob)
const encodedUri = "data:text/csv;charset=utf-8," + encodeURIComponent(csvContent); const encodedUri = "data:text/csv;charset=utf-8," + encodeURIComponent(csvContent);
const link = document.createElement("a"); const link = document.createElement("a");
link.setAttribute("href", encodedUri); link.setAttribute("href", encodedUri);
+5
View File
@@ -5,6 +5,11 @@
* ============================================================================ * ============================================================================
*/ */
/**
* Version unique de l'application (Centralisée)
*/
export const APP_VERSION = '0.16.0';
export const MODES = { export const MODES = {
ESKETAMINE: 'ESKETAMINE', ESKETAMINE: 'ESKETAMINE',
RACEMIQUE: 'RACEMIQUE' RACEMIQUE: 'RACEMIQUE'
+13 -12
View File
@@ -1,7 +1,19 @@
{ {
"app": { "app": {
"title": "药代动力学模拟", "title": "药代动力学模拟",
"version": "v1.00 • Dr Georges Mion" "version": "v{version} • Dr Georges Mion"
},
"csv": {
"title": "KetaPK - 原始数据报告",
"version": "软件版本",
"weight": "患者体重 (kg)",
"unit": "输注单位",
"col_time": "时间 (min)",
"col_bolus": "负荷剂量 (mg)",
"col_infusion": "有效输注速率",
"col_domino": "Domino (ng/mL)",
"col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)"
}, },
"nav": { "nav": {
"mode_esk": "右旋氯胺酮", "mode_esk": "右旋氯胺酮",
@@ -35,17 +47,6 @@
"col_clements": "Clements (ng/mL)", "col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)" "col_kamp": "Kamp (ng/mL)"
}, },
"csv": {
"title": "KetaPK - 原始数据报告",
"weight": "患者体重 (kg)",
"unit": "输注单位",
"col_time": "时间 (min)",
"col_bolus": "负荷剂量 (mg)",
"col_infusion": "有效输注速率",
"col_domino": "Domino (ng/mL)",
"col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)"
},
"zones": { "zones": {
"inactive": "无活性", "inactive": "无活性",
"anti_hyperalgesic": "抗痛觉过敏", "anti_hyperalgesic": "抗痛觉过敏",
+13 -12
View File
@@ -1,7 +1,19 @@
{ {
"app": { "app": {
"title": "Pharmaco Kinetics", "title": "Pharmaco Kinetics",
"version": "v1.00 • Dr Georges Mion" "version": "v{version} • Dr Georges Mion"
},
"csv": {
"title": "KetaPK - Raw Data Report",
"version": "App version",
"weight": "Patient weight (kg)",
"unit": "Infusion unit",
"col_time": "Time (min)",
"col_bolus": "Bolus (mg)",
"col_infusion": "Active infusion",
"col_domino": "Domino (ng/mL)",
"col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)"
}, },
"nav": { "nav": {
"mode_esk": "ESKETAMINE", "mode_esk": "ESKETAMINE",
@@ -35,17 +47,6 @@
"col_clements": "Clements (ng/mL)", "col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)" "col_kamp": "Kamp (ng/mL)"
}, },
"csv": {
"title": "KetaPK - Raw Data Report",
"weight": "Patient weight (kg)",
"unit": "Infusion unit",
"col_time": "Time (min)",
"col_bolus": "Bolus (mg)",
"col_infusion": "Active infusion",
"col_domino": "Domino (ng/mL)",
"col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)"
},
"zones": { "zones": {
"inactive": "Inactive", "inactive": "Inactive",
"anti_hyperalgesic": "Anti-hyperalgesic", "anti_hyperalgesic": "Anti-hyperalgesic",
+13 -12
View File
@@ -1,7 +1,19 @@
{ {
"app": { "app": {
"title": "Pharmaco Kinetics", "title": "Pharmaco Kinetics",
"version": "v1.00 • Dr Georges Mion" "version": "v{version} • Dr Georges Mion"
},
"csv": {
"title": "KetaPK - Rapport de donnees brutes",
"version": "Version application",
"weight": "Poids du patient (kg)",
"unit": "Unite de perfusion",
"col_time": "Temps (min)",
"col_bolus": "Bolus (mg)",
"col_infusion": "Perfusion active",
"col_domino": "Domino (ng/mL)",
"col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)"
}, },
"nav": { "nav": {
"mode_esk": "ESKETAMINE", "mode_esk": "ESKETAMINE",
@@ -35,17 +47,6 @@
"col_clements": "Clements (ng/mL)", "col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)" "col_kamp": "Kamp (ng/mL)"
}, },
"csv": {
"title": "KetaPK - Rapport de donnees brutes",
"weight": "Poids du patient (kg)",
"unit": "Unite de perfusion",
"col_time": "Temps (min)",
"col_bolus": "Bolus (mg)",
"col_infusion": "Perfusion active",
"col_domino": "Domino (ng/mL)",
"col_clements": "Clements (ng/mL)",
"col_kamp": "Kamp (ng/mL)"
},
"zones": { "zones": {
"inactive": "Inactif", "inactive": "Inactif",
"anti_hyperalgesic": "Anti-hyperalgésique", "anti_hyperalgesic": "Anti-hyperalgésique",
+9
View File
@@ -0,0 +1,9 @@
# Generated by Cargo
# will have compiled files and executables
/target/
/target/debug
/target/release/*
/gen/schemas
# Exclude app.exe
!/target/release/app.exe
+4480
View File
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
[package]
name = "ketapk"
version = "0.16.0"
description = "KétaPK"
authors = ["Gauvain BOICHÉ", "Pr. Georges MION"]
license = "Proprietary"
repository = ""
edition = "2021"
rust-version = "1.77.2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { version = "2.6.3", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
log = "0.4"
tauri = { version = "2.11.3", features = [] }
tauri-plugin-log = "2"
+3
View File
@@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}
+34
View File
@@ -0,0 +1,34 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "ketapk",
"version": "0.16.0",
"identifier": "com.ketapk.desktop",
"build": {
"beforeDevCommand": "",
"beforeBuildCommand": "",
"frontendDist": "../frontend"
},
"app": {
"windows": [
{
"title": "KétaPK",
"width": 1280,
"height": 800,
"resizable": true,
"fullscreen": false
}
]
},
"bundle": {
"active": true,
"targets": ["msi"],
"category": "Medical",
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
]
}
}