diff --git a/webapp/backend/routes/submit.py b/webapp/backend/routes/submit.py
index c8144b4..01b8efb 100644
--- a/webapp/backend/routes/submit.py
+++ b/webapp/backend/routes/submit.py
@@ -23,13 +23,13 @@ def submit_feedback():
if note or comment:
try:
with open(Config.FEEDBACK_FILE, "a", encoding="utf-8") as f:
- f.write(f"[{diagram_type.upper()}]\nNote: {note}\nCommentaire: {comment}\n\n")
+ f.write(f"[{diagram_type.upper()}]\nNote: {note}\nComment: {comment}\n\n")
return ResponseBuilder.success(
message="Feedback submitted successfully. Thank you!"
)
except Exception as e:
- # Log l'erreur dans le CSV
+ # Log error to CSV
csv_logger = logging.getLogger(Config.LOGGER_NAME)
csv_logger.error(f"Error writing feedback: {e}")
return ResponseBuilder.error(
diff --git a/webapp/backend/services/helmService.py b/webapp/backend/services/helmService.py
index 26c65a7..ca1f2e7 100644
--- a/webapp/backend/services/helmService.py
+++ b/webapp/backend/services/helmService.py
@@ -25,11 +25,11 @@ def generate_from_helm(
Returns:
DiagramResult: Result of the generation
"""
- # Extraction du nom de base
+ # Extract base name for output file
parsed = urlparse(chart_url)
base_name = os.path.basename(parsed.path).replace(".tgz", "").replace(".tar.gz", "")
- # Pour les URLs OCI
+ # OCI URLs use the last path segment as chart name
if chart_url.startswith('oci://'):
base_name = chart_url.rstrip('/').split('/')[-1]
@@ -42,12 +42,11 @@ def generate_from_helm(
if extra_args.strip():
cmd.extend(parse_extra_args(extra_args))
- # Execution
+ # Run the command and capture output
proc = subprocess.run(cmd, check=False, capture_output=True, text=True)
stdout_output = proc.stdout or ""
stderr_output = proc.stderr or ""
- # First we verify if there was an error before file exist
has_error = proc.returncode != 0 or has_fatal_error(stdout_output, stderr_output)
# Second we verify if there was an error in the stderr output
diff --git a/webapp/backend/services/utils.py b/webapp/backend/services/utils.py
index 4bce85e..e072f53 100644
--- a/webapp/backend/services/utils.py
+++ b/webapp/backend/services/utils.py
@@ -1,4 +1,4 @@
-"""Utilitaires pour les services de génération de diagrammes."""
+"""Utilities for diagram generation services."""
import base64
import shlex
@@ -6,30 +6,30 @@ from constants import TEXT_FORMATS
def has_fatal_error(stdout_txt: str, stderr_txt: str) -> bool:
"""
- Vérifie si la sortie contient une erreur fatale.
-
+ Check whether subprocess output contains a fatal error marker.
+
Args:
- stdout_txt: Sortie standard
- stderr_txt: Sortie d'erreur
-
+ stdout_txt: Standard output text
+ stderr_txt: Standard error text
+
Returns:
- bool: True si erreur fatale détectée
+ bool: True if a fatal error was detected
"""
return ("error:" in (stdout_txt or "").lower()) or ("error:" in (stderr_txt or "").lower())
def parse_extra_args(extra_args: str) -> list[str]:
"""
- Parse les arguments supplémentaires.
-
+ Parse a string of extra CLI arguments using shell-like tokenization.
+
Args:
- extra_args: Arguments supplémentaires en string
-
+ extra_args: Space-separated argument string (may include quoted tokens)
+
Returns:
- list[str]: Liste des arguments parsés
-
+ list[str]: Parsed argument tokens
+
Raises:
- ValueError: Si les arguments sont invalides
+ ValueError: If the argument string has invalid shell syntax
"""
if not extra_args or not extra_args.strip():
return []
@@ -41,15 +41,18 @@ def parse_extra_args(extra_args: str) -> list[str]:
def encode_content(content: bytes, output_format: str) -> str:
"""
- Encode le contenu en base64 ou UTF-8 selon le format.
-
+ Encode diagram content for JSON transport.
+
+ Text-based formats (SVG, DOT, DOT_JSON, DRAWIO) are decoded as UTF-8.
+ Binary formats (PNG, JPG, PDF) are base64-encoded.
+
Args:
- content: Contenu à encoder
- output_format: Format de sortie
-
+ content: Raw file content
+ output_format: Output format string (e.g. 'png', 'svg')
+
Returns:
- str: Contenu encodé
+ str: Encoded content ready for the API response
"""
if output_format in TEXT_FORMATS:
return content.decode("utf-8")
- return base64.b64encode(content).decode("utf-8")
+ return base64.b64encode(content).decode("utf-8")
\ No newline at end of file
diff --git a/webapp/backend/utils/validators.py b/webapp/backend/utils/validators.py
index f858adb..f35745d 100644
--- a/webapp/backend/utils/validators.py
+++ b/webapp/backend/utils/validators.py
@@ -75,7 +75,7 @@ class InputValidator:
url: URL of the Helm chart
Returns:
- Tuple[bool, Optional[str]]: (est_valide, message_erreur)
+ Tuple[bool, Optional[str]]: (is_valid, error_message)
"""
if not url or not url.strip():
return False, "Chart URL cannot be empty."
@@ -121,7 +121,7 @@ class InputValidator:
Tuple[bool, Optional[str]]: (is_valid, error_message)
"""
if not args or not args.strip():
- return True, None # Les args vides sont valides
+ return True, None
dangerous_chars = [';', '&', '|', '`', '$', '(', ')']
for char in dangerous_chars:
diff --git a/webapp/frontend/src/App.jsx b/webapp/frontend/src/App.jsx
index e0ca8a9..cf5aa11 100644
--- a/webapp/frontend/src/App.jsx
+++ b/webapp/frontend/src/App.jsx
@@ -21,7 +21,7 @@ function App() {
setRestoredItem(null);
};
- // Mémoriser historyContext pour éviter de le recréer à chaque render
+ // Memoize historyContext to avoid recreating it on every render
const historyContext = useMemo(
() => ({ addToHistory, getHistoryItem, restoredItem, clearRestoredItem }),
[addToHistory, getHistoryItem, restoredItem]
diff --git a/webapp/frontend/src/components/common/HistoryPanel.jsx b/webapp/frontend/src/components/common/HistoryPanel.jsx
index 7424f2c..5148ab3 100644
--- a/webapp/frontend/src/components/common/HistoryPanel.jsx
+++ b/webapp/frontend/src/components/common/HistoryPanel.jsx
@@ -120,9 +120,9 @@ const HistoryPanel = ({ history, onRestore, onRemove, onClear, isOpen, onToggle
{history.length === 0 ? (
-
Aucun diagramme dans l'historique
+
No diagrams in history
- Les diagrammes générés apparaîtront ici
+ Generated diagrams will appear here
) : (
diff --git a/webapp/frontend/src/components/common/PanZoomContainer.jsx b/webapp/frontend/src/components/common/PanZoomContainer.jsx
index 7dcb97c..b460124 100644
--- a/webapp/frontend/src/components/common/PanZoomContainer.jsx
+++ b/webapp/frontend/src/components/common/PanZoomContainer.jsx
@@ -14,7 +14,7 @@ export default function PanZoomContainer({
scrollPanSpeed = 3.0,
buttonZoomFactor = 1.25,
buttonZoomFactorFast = 1.5,
- // Souris
+ // Mouse
mouseZoomDampen = 0.018,
clampDeltaY = 50,
}) {
@@ -22,17 +22,17 @@ export default function PanZoomContainer({
const measureRef = useRef(null);
const isInControls = (el) => !!(el && el.closest && el.closest('.kd-controls'));
- // États affichés
+ // Displayed state (reactive)
const [scale, _setScale] = useState(1);
const [tx, _setTx] = useState(0);
const [ty, _setTy] = useState(0);
- // Réfs calculs + animation
+ // Refs for calculation and animation (non-reactive)
const scaleRef = useRef(1);
const txRef = useRef(0);
const tyRef = useRef(0);
- // Cibles animées
+ // Animated targets
const targetScaleRef = useRef(1);
const targetTxRef = useRef(0);
const targetTyRef = useRef(0);
@@ -55,7 +55,7 @@ export default function PanZoomContainer({
const [naturalSize, setNaturalSize] = useState({ w: 0, h: 0 });
const [vpSize, setVpSize] = useState({ w: 0, h: 0 });
- // Mesures
+ // Measure natural content size and viewport size
useLayoutEffect(() => {
const el = measureRef.current;
if (!el) return;
@@ -83,7 +83,7 @@ export default function PanZoomContainer({
};
}, []);
- // Fit initial
+ // Fit content into viewport on first render
useEffect(() => {
if (!naturalSize.w || !naturalSize.h || !vpSize.w || !vpSize.h) return;
fit(true);
@@ -91,7 +91,7 @@ export default function PanZoomContainer({
const clamp = (v, a, b) => Math.min(b, Math.max(a, v));
- // Anime position/zoom vers la cible
+ // Animate position/zoom toward targets with smoothing
const animate = useCallback(() => {
const s = scaleRef.current;
const tx = txRef.current;
@@ -167,7 +167,7 @@ export default function PanZoomContainer({
dY *= vp.clientHeight;
}
- // --- ZOOM (pinch/ctrl) : adoucir la souris, garder le trackpad tel quel
+ // --- ZOOM (pinch/ctrl): dampen mouse wheel, keep trackpad as-is
if (e.ctrlKey) {
const isTrackpad = isTrackpadWheel(e);
const sens = isTrackpad ? pinchSensitivity : pinchSensitivity * mouseZoomDampen;
@@ -178,7 +178,7 @@ export default function PanZoomContainer({
return;
}
- // --- Mode "zoom" à la molette : même adoucissement pour souris
+ // --- Wheel zoom mode: same dampening as pinch/ctrl
if (wheelMode === 'zoom') {
const isTrackpad = isTrackpadWheel(e);
const sens = isTrackpad ? wheelSensitivity : wheelSensitivity * mouseZoomDampen;
@@ -189,7 +189,7 @@ export default function PanZoomContainer({
return;
}
- // --- Par défaut : PAN au wheel/trackpad (deux doigts)
+ // --- Default: pan with wheel/trackpad (two-finger scroll)
const k = scrollPanSpeed;
targetTxRef.current = txRef.current - dX * k;
targetTyRef.current = tyRef.current - dY * k;
diff --git a/webapp/frontend/src/components/common/ProgressBar.jsx b/webapp/frontend/src/components/common/ProgressBar.jsx
index c94ab0f..802e948 100644
--- a/webapp/frontend/src/components/common/ProgressBar.jsx
+++ b/webapp/frontend/src/components/common/ProgressBar.jsx
@@ -9,8 +9,8 @@ const ProgressBar = ({ currentStep = 'idle', isVisible = false }) => {
const steps = [
{ id: 'parsing', label: 'Parsing' },
{ id: 'validation', label: 'Validation' },
- { id: 'generation', label: 'Génération' },
- { id: 'rendering', label: 'Rendu' },
+ { id: 'generation', label: 'Generation' },
+ { id: 'rendering', label: 'Rendering' },
];
const getStepStatus = (stepId) => {
@@ -65,7 +65,7 @@ const ProgressBar = ({ currentStep = 'idle', isVisible = false }) => {
>
- {currentStep === 'completed' ? '✓ Génération terminée' : 'Génération en cours...'}
+ {currentStep === 'completed' ? '✓ Generation complete' : 'Generation in progress...'}
{currentStep !== 'completed' && currentStep !== 'error' && (
diff --git a/webapp/frontend/src/components/common/Tabs.jsx b/webapp/frontend/src/components/common/Tabs.jsx
index 2361480..73b4afe 100644
--- a/webapp/frontend/src/components/common/Tabs.jsx
+++ b/webapp/frontend/src/components/common/Tabs.jsx
@@ -31,7 +31,7 @@ function Tabs({ historyContext }) {
return (
- {/* Onglets */}
+ {/* Tabs */}
{tabs.map((tab) => (
- {/* Contenu des tabs */}
+ {/* Tab content */}
{activeTab === 'manifest' && }
{activeTab === 'helm' && }
diff --git a/webapp/frontend/src/components/tabs/HelmFileTab/index.jsx b/webapp/frontend/src/components/tabs/HelmFileTab/index.jsx
index 08d06f9..671d8ff 100644
--- a/webapp/frontend/src/components/tabs/HelmFileTab/index.jsx
+++ b/webapp/frontend/src/components/tabs/HelmFileTab/index.jsx
@@ -98,7 +98,7 @@ function HelmFileTab({ historyContext }) {
historyContext.addToHistory(historyItem);
lastHistoryIdRef.current = historyId;
}
- }, [diagram, progressStep]); // Dépendances minimales pour éviter la boucle
+ }, [diagram, progressStep]); // minimal deps — avoids a save loop
// Restore from history
useEffect(() => {
diff --git a/webapp/frontend/src/components/tabs/HelmTab/index.jsx b/webapp/frontend/src/components/tabs/HelmTab/index.jsx
index be5cc11..d194f78 100644
--- a/webapp/frontend/src/components/tabs/HelmTab/index.jsx
+++ b/webapp/frontend/src/components/tabs/HelmTab/index.jsx
@@ -93,7 +93,7 @@ function HelmTab({ historyContext }) {
historyContext.addToHistory(historyItem);
lastHistoryIdRef.current = historyId;
}
- }, [diagram, progressStep]); // Dépendances minimales pour éviter la boucle
+ }, [diagram, progressStep]); // minimal deps — avoids a save loop
// Restore from history
useEffect(() => {
@@ -133,7 +133,7 @@ function HelmTab({ historyContext }) {
setChartUrl(v);
setBackendError('');
- // Valider seulement si l'URL n'est pas vide
+ // Validate only if URL is not empty
if (v && v.trim()) {
setInputError(
isValidChartUrl(v)
diff --git a/webapp/frontend/src/components/tabs/ManifestTab/index.jsx b/webapp/frontend/src/components/tabs/ManifestTab/index.jsx
index 029909f..6e3fd48 100644
--- a/webapp/frontend/src/components/tabs/ManifestTab/index.jsx
+++ b/webapp/frontend/src/components/tabs/ManifestTab/index.jsx
@@ -101,7 +101,7 @@ function ManifestTab({ historyContext }) {
historyContext.addToHistory(historyItem);
lastHistoryIdRef.current = historyId;
}
- }, [diagram, progressStep]); // Dépendances minimales pour éviter la boucle
+ }, [diagram, progressStep]); // minimal deps — avoids a save loop
// Restore from history
useEffect(() => {
diff --git a/webapp/frontend/src/utils/toast.js b/webapp/frontend/src/utils/toast.js
index 43af523..81aece7 100644
--- a/webapp/frontend/src/utils/toast.js
+++ b/webapp/frontend/src/utils/toast.js
@@ -77,9 +77,9 @@ export const dismissToast = (toastId) => {
*/
export const showPromise = (promise, messages) => {
return toast.promise(promise, {
- loading: messages.loading || 'Chargement...',
- success: messages.success || 'Terminé !',
- error: messages.error || 'Une erreur est survenue',
+ loading: messages.loading || 'Loading...',
+ success: messages.success || 'Done!',
+ error: messages.error || 'An error occurred',
});
};