v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution
- Frontend v4 accessible sur réseau local (192.168.1.40) - Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard) - Ollama GPU fonctionnel - Self-healing interactif - Dashboard confiance Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
252
visual_workflow_builder/frontend/src/utils/errorMessages.ts
Normal file
252
visual_workflow_builder/frontend/src/utils/errorMessages.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* Messages d'Erreur en Français Clair
|
||||
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
*
|
||||
* Ce module centralise tous les messages d'erreur et d'avertissement
|
||||
* en français clair et compréhensible pour les utilisateurs.
|
||||
*/
|
||||
|
||||
export interface ErrorMessage {
|
||||
title: string;
|
||||
description: string;
|
||||
solution: string;
|
||||
severity: 'critical' | 'high' | 'medium' | 'low';
|
||||
}
|
||||
|
||||
// Messages d'erreur pour les paramètres manquants
|
||||
export const missingParameterMessages: Record<string, ErrorMessage> = {
|
||||
target: {
|
||||
title: 'Élément cible non sélectionné',
|
||||
description: 'Cette étape a besoin de savoir sur quel élément de la page agir.',
|
||||
solution: 'Cliquez sur "Sélectionner un élément" et choisissez l\'élément cible sur la capture d\'écran.',
|
||||
severity: 'high'
|
||||
},
|
||||
text: {
|
||||
title: 'Texte à saisir manquant',
|
||||
description: 'Cette étape de saisie ne sait pas quel texte écrire.',
|
||||
solution: 'Saisissez le texte dans le champ "Texte à saisir". Vous pouvez utiliser des variables avec ${nom_variable}.',
|
||||
severity: 'high'
|
||||
},
|
||||
duration: {
|
||||
title: 'Durée d\'attente non définie',
|
||||
description: 'Cette étape d\'attente ne sait pas combien de temps attendre.',
|
||||
solution: 'Définissez une durée en secondes (par exemple : 2 pour 2 secondes, 0.5 pour 500 millisecondes).',
|
||||
severity: 'high'
|
||||
},
|
||||
condition: {
|
||||
title: 'Condition logique manquante',
|
||||
description: 'Cette étape conditionnelle ne sait pas quelle condition évaluer.',
|
||||
solution: 'Saisissez une expression logique comme "${age} >= 18" ou "${status} == \'actif\'".',
|
||||
severity: 'high'
|
||||
},
|
||||
url: {
|
||||
title: 'URL de destination manquante',
|
||||
description: 'Cette étape de navigation ne sait pas vers quelle page aller.',
|
||||
solution: 'Saisissez l\'URL complète (ex: https://example.com) ou utilisez une variable ${url}.',
|
||||
severity: 'high'
|
||||
},
|
||||
selector: {
|
||||
title: 'Sélecteur d\'élément manquant',
|
||||
description: 'Cette étape ne sait pas quel élément de la page cibler.',
|
||||
solution: 'Utilisez le sélecteur visuel pour choisir l\'élément ou saisissez un sélecteur CSS.',
|
||||
severity: 'high'
|
||||
},
|
||||
attribute: {
|
||||
title: 'Attribut à extraire non spécifié',
|
||||
description: 'Cette étape d\'extraction ne sait pas quelle information récupérer.',
|
||||
solution: 'Choisissez le type d\'information à extraire : texte, valeur, lien, etc.',
|
||||
severity: 'medium'
|
||||
}
|
||||
};
|
||||
|
||||
// Messages d'erreur pour les problèmes de workflow
|
||||
export const workflowErrorMessages: Record<string, ErrorMessage> = {
|
||||
cycle_detected: {
|
||||
title: 'Boucle infinie détectée',
|
||||
description: 'Le workflow contient une boucle qui empêcherait son exécution normale.',
|
||||
solution: 'Vérifiez les connexions entre les étapes et supprimez les références circulaires.',
|
||||
severity: 'critical'
|
||||
},
|
||||
disconnected_step: {
|
||||
title: 'Étape isolée',
|
||||
description: 'Cette étape n\'est connectée à aucune autre et ne sera pas exécutée.',
|
||||
solution: 'Connectez cette étape au flux principal ou supprimez-la si elle n\'est plus nécessaire.',
|
||||
severity: 'medium'
|
||||
},
|
||||
invalid_variable_reference: {
|
||||
title: 'Variable inexistante',
|
||||
description: 'Une variable utilisée dans les paramètres n\'existe pas.',
|
||||
solution: 'Créez la variable manquante ou corrigez le nom de la variable dans les paramètres.',
|
||||
severity: 'high'
|
||||
},
|
||||
execution_blocked: {
|
||||
title: 'Exécution impossible',
|
||||
description: 'Des erreurs critiques empêchent le lancement du workflow.',
|
||||
solution: 'Corrigez toutes les erreurs marquées en rouge avant de pouvoir exécuter le workflow.',
|
||||
severity: 'critical'
|
||||
},
|
||||
no_start_step: {
|
||||
title: 'Aucune étape de départ',
|
||||
description: 'Le workflow n\'a pas d\'étape de départ clairement identifiée.',
|
||||
solution: 'Assurez-vous qu\'au moins une étape n\'a pas de connexion d\'entrée pour servir de point de départ.',
|
||||
severity: 'high'
|
||||
},
|
||||
multiple_start_steps: {
|
||||
title: 'Plusieurs étapes de départ',
|
||||
description: 'Le workflow a plusieurs étapes sans connexion d\'entrée.',
|
||||
solution: 'Connectez les étapes pour n\'avoir qu\'un seul point de départ, ou utilisez une étape de condition.',
|
||||
severity: 'medium'
|
||||
}
|
||||
};
|
||||
|
||||
// Messages d'erreur pour les variables
|
||||
export const variableErrorMessages: Record<string, ErrorMessage> = {
|
||||
invalid_name: {
|
||||
title: 'Nom de variable invalide',
|
||||
description: 'Le nom de la variable contient des caractères non autorisés.',
|
||||
solution: 'Utilisez uniquement des lettres, chiffres et underscores. Commencez par une lettre.',
|
||||
severity: 'high'
|
||||
},
|
||||
duplicate_name: {
|
||||
title: 'Nom de variable déjà utilisé',
|
||||
description: 'Une variable avec ce nom existe déjà.',
|
||||
solution: 'Choisissez un nom différent ou modifiez la variable existante.',
|
||||
severity: 'high'
|
||||
},
|
||||
empty_value: {
|
||||
title: 'Valeur de variable vide',
|
||||
description: 'La variable n\'a pas de valeur par défaut.',
|
||||
solution: 'Définissez une valeur par défaut ou laissez la variable être remplie dynamiquement.',
|
||||
severity: 'low'
|
||||
},
|
||||
invalid_type: {
|
||||
title: 'Type de variable incorrect',
|
||||
description: 'La valeur ne correspond pas au type déclaré de la variable.',
|
||||
solution: 'Vérifiez que la valeur correspond au type (texte, nombre, booléen) de la variable.',
|
||||
severity: 'medium'
|
||||
}
|
||||
};
|
||||
|
||||
// Messages d'erreur pour l'exécution
|
||||
export const executionErrorMessages: Record<string, ErrorMessage> = {
|
||||
step_failed: {
|
||||
title: 'Échec de l\'étape',
|
||||
description: 'L\'étape n\'a pas pu s\'exécuter correctement.',
|
||||
solution: 'Vérifiez les paramètres de l\'étape et l\'état de la page web cible.',
|
||||
severity: 'high'
|
||||
},
|
||||
element_not_found: {
|
||||
title: 'Élément introuvable',
|
||||
description: 'L\'élément ciblé n\'a pas été trouvé sur la page.',
|
||||
solution: 'Vérifiez que la page est correctement chargée et que l\'élément existe toujours.',
|
||||
severity: 'high'
|
||||
},
|
||||
timeout_exceeded: {
|
||||
title: 'Délai d\'attente dépassé',
|
||||
description: 'L\'étape a pris trop de temps à s\'exécuter.',
|
||||
solution: 'Augmentez le délai d\'attente ou vérifiez que la page répond correctement.',
|
||||
severity: 'medium'
|
||||
},
|
||||
network_error: {
|
||||
title: 'Erreur de réseau',
|
||||
description: 'Impossible de communiquer avec la page web ou le serveur.',
|
||||
solution: 'Vérifiez votre connexion internet et que le site web est accessible.',
|
||||
severity: 'high'
|
||||
},
|
||||
permission_denied: {
|
||||
title: 'Permission refusée',
|
||||
description: 'L\'action n\'est pas autorisée sur cette page ou cet élément.',
|
||||
solution: 'Vérifiez les permissions du navigateur et les restrictions de sécurité de la page.',
|
||||
severity: 'high'
|
||||
}
|
||||
};
|
||||
|
||||
// Messages d'avertissement
|
||||
export const warningMessages: Record<string, ErrorMessage> = {
|
||||
large_workflow: {
|
||||
title: 'Workflow volumineux',
|
||||
description: 'Ce workflow contient beaucoup d\'étapes et pourrait être lent à exécuter.',
|
||||
solution: 'Considérez diviser le workflow en plusieurs parties plus petites.',
|
||||
severity: 'low'
|
||||
},
|
||||
unused_variable: {
|
||||
title: 'Variable non utilisée',
|
||||
description: 'Cette variable est définie mais n\'est utilisée dans aucune étape.',
|
||||
solution: 'Supprimez la variable si elle n\'est plus nécessaire ou utilisez-la dans une étape.',
|
||||
severity: 'low'
|
||||
},
|
||||
deprecated_step: {
|
||||
title: 'Type d\'étape obsolète',
|
||||
description: 'Ce type d\'étape est obsolète et pourrait ne plus être supporté.',
|
||||
solution: 'Remplacez par un type d\'étape plus récent avec des fonctionnalités équivalentes.',
|
||||
severity: 'medium'
|
||||
},
|
||||
performance_warning: {
|
||||
title: 'Avertissement de performance',
|
||||
description: 'Cette configuration pourrait impacter les performances d\'exécution.',
|
||||
solution: 'Optimisez les paramètres ou la structure du workflow pour de meilleures performances.',
|
||||
severity: 'low'
|
||||
}
|
||||
};
|
||||
|
||||
// Fonction utilitaire pour obtenir un message d'erreur
|
||||
export const getErrorMessage = (
|
||||
category: 'parameter' | 'workflow' | 'variable' | 'execution' | 'warning',
|
||||
errorType: string,
|
||||
context?: Record<string, any>
|
||||
): ErrorMessage => {
|
||||
const messageMaps = {
|
||||
parameter: missingParameterMessages,
|
||||
workflow: workflowErrorMessages,
|
||||
variable: variableErrorMessages,
|
||||
execution: executionErrorMessages,
|
||||
warning: warningMessages
|
||||
};
|
||||
|
||||
const baseMessage = messageMaps[category]?.[errorType];
|
||||
|
||||
if (!baseMessage) {
|
||||
return {
|
||||
title: 'Erreur inconnue',
|
||||
description: `Une erreur de type "${errorType}" s'est produite.`,
|
||||
solution: 'Contactez le support technique si le problème persiste.',
|
||||
severity: 'medium'
|
||||
};
|
||||
}
|
||||
|
||||
// Personnaliser le message avec le contexte si fourni
|
||||
if (context) {
|
||||
let customizedMessage = { ...baseMessage };
|
||||
|
||||
// Remplacer les placeholders dans les messages
|
||||
Object.entries(context).forEach(([key, value]) => {
|
||||
const placeholder = `{${key}}`;
|
||||
customizedMessage.title = customizedMessage.title.replace(placeholder, String(value));
|
||||
customizedMessage.description = customizedMessage.description.replace(placeholder, String(value));
|
||||
customizedMessage.solution = customizedMessage.solution.replace(placeholder, String(value));
|
||||
});
|
||||
|
||||
return customizedMessage;
|
||||
}
|
||||
|
||||
return baseMessage;
|
||||
};
|
||||
|
||||
// Messages de succès
|
||||
export const successMessages: Record<string, string> = {
|
||||
workflow_saved: 'Workflow sauvegardé avec succès',
|
||||
workflow_executed: 'Workflow exécuté avec succès',
|
||||
step_completed: 'Étape terminée avec succès',
|
||||
validation_passed: 'Validation réussie, aucun problème détecté',
|
||||
variable_created: 'Variable créée avec succès',
|
||||
connection_established: 'Connexion établie entre les étapes'
|
||||
};
|
||||
|
||||
// Messages informatifs
|
||||
export const infoMessages: Record<string, string> = {
|
||||
workflow_loading: 'Chargement du workflow en cours...',
|
||||
step_executing: 'Exécution de l\'étape en cours...',
|
||||
validation_running: 'Validation du workflow en cours...',
|
||||
saving_workflow: 'Sauvegarde du workflow...',
|
||||
connecting_backend: 'Connexion au serveur...'
|
||||
};
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Suppression des erreurs ResizeObserver
|
||||
* Auteur : Dom, Alice, Kiro - 09 janvier 2026
|
||||
*
|
||||
* Ce fichier supprime les erreurs ResizeObserver qui sont générées par
|
||||
* les bibliothèques tierces (Material-UI, ReactFlow) et qui ne sont pas
|
||||
* des erreurs critiques. Ces erreurs sont connues et documentées comme
|
||||
* étant bénignes dans les environnements de développement.
|
||||
*
|
||||
* Référence: https://github.com/WICG/resize-observer/issues/38
|
||||
*/
|
||||
|
||||
// Suppression globale des erreurs ResizeObserver
|
||||
const suppressResizeObserverErrors = (): void => {
|
||||
// Intercepter les erreurs de la fenêtre
|
||||
const originalWindowError = window.onerror;
|
||||
window.onerror = (message, source, lineno, colno, error) => {
|
||||
if (
|
||||
typeof message === 'string' &&
|
||||
message.includes('ResizeObserver loop')
|
||||
) {
|
||||
// Ignorer silencieusement cette erreur spécifique
|
||||
return true;
|
||||
}
|
||||
// Appeler le gestionnaire d'erreur original si présent
|
||||
if (originalWindowError) {
|
||||
return originalWindowError(message, source, lineno, colno, error);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Intercepter les erreurs non gérées
|
||||
window.addEventListener('error', (event: ErrorEvent) => {
|
||||
if (
|
||||
event.message &&
|
||||
event.message.includes('ResizeObserver loop')
|
||||
) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
return;
|
||||
}
|
||||
}, true);
|
||||
|
||||
// Intercepter les promesses rejetées
|
||||
window.addEventListener('unhandledrejection', (event: PromiseRejectionEvent) => {
|
||||
if (
|
||||
event.reason &&
|
||||
typeof event.reason === 'object' &&
|
||||
event.reason.message &&
|
||||
event.reason.message.includes('ResizeObserver loop')
|
||||
) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Intercepter console.error pour les erreurs ResizeObserver
|
||||
const originalConsoleError = console.error;
|
||||
console.error = (...args: unknown[]) => {
|
||||
const message = args[0];
|
||||
if (
|
||||
typeof message === 'string' &&
|
||||
message.includes('ResizeObserver loop')
|
||||
) {
|
||||
// Ignorer silencieusement
|
||||
return;
|
||||
}
|
||||
originalConsoleError.apply(console, args);
|
||||
};
|
||||
};
|
||||
|
||||
// Exécuter immédiatement
|
||||
suppressResizeObserverErrors();
|
||||
|
||||
export default suppressResizeObserverErrors;
|
||||
275
visual_workflow_builder/frontend/src/utils/tooltips.ts
Normal file
275
visual_workflow_builder/frontend/src/utils/tooltips.ts
Normal file
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* Système de Tooltips Explicatifs en Français
|
||||
* Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
||||
*
|
||||
* Ce module centralise tous les tooltips explicatifs en français pour
|
||||
* assurer la cohérence linguistique et faciliter la maintenance.
|
||||
*/
|
||||
|
||||
export interface TooltipContent {
|
||||
title: string;
|
||||
description: string;
|
||||
example?: string;
|
||||
shortcut?: string;
|
||||
}
|
||||
|
||||
// Tooltips pour les types d'étapes
|
||||
export const stepTooltips: Record<string, TooltipContent> = {
|
||||
click: {
|
||||
title: 'Cliquer sur un élément',
|
||||
description: 'Effectue un clic sur un élément de la page web. Vous pouvez choisir le type de clic (gauche, droit, double-clic).',
|
||||
example: 'Cliquer sur un bouton "Valider" ou un lien',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
type: {
|
||||
title: 'Saisir du texte',
|
||||
description: 'Saisit du texte dans un champ de saisie. Supporte les variables dynamiques avec la syntaxe ${nom_variable}.',
|
||||
example: 'Saisir "Bonjour ${nom_utilisateur}" dans un champ',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
wait: {
|
||||
title: 'Attendre',
|
||||
description: 'Met en pause l\'exécution pendant une durée spécifiée. Utile pour attendre le chargement d\'éléments.',
|
||||
example: 'Attendre 2 secondes après un clic',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
condition: {
|
||||
title: 'Condition logique',
|
||||
description: 'Exécute des actions différentes selon une condition. Utilise des expressions logiques simples.',
|
||||
example: 'Si ${age} > 18 alors continuer',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
extract: {
|
||||
title: 'Extraire des données',
|
||||
description: 'Extrait des données depuis un élément de la page (texte, valeur, lien, etc.) et les stocke dans une variable.',
|
||||
example: 'Extraire le prix d\'un produit',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
scroll: {
|
||||
title: 'Faire défiler la page',
|
||||
description: 'Fait défiler la page dans une direction donnée. Utile pour révéler des éléments cachés.',
|
||||
example: 'Défiler vers le bas de 300 pixels',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
navigate: {
|
||||
title: 'Naviguer vers une URL',
|
||||
description: 'Navigue vers une nouvelle page web. Supporte les variables dans l\'URL.',
|
||||
example: 'Aller à https://example.com/user/${id}',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
},
|
||||
screenshot: {
|
||||
title: 'Capturer l\'écran',
|
||||
description: 'Prend une capture d\'écran de la page actuelle. Utile pour documenter ou déboguer.',
|
||||
example: 'Capturer avant et après une action',
|
||||
shortcut: 'Glisser depuis la palette'
|
||||
}
|
||||
};
|
||||
|
||||
// Tooltips pour les catégories d'étapes
|
||||
export const categoryTooltips: Record<string, TooltipContent> = {
|
||||
'actions-web': {
|
||||
title: 'Actions Web',
|
||||
description: 'Étapes pour interagir directement avec les éléments des pages web (clics, saisie, navigation).',
|
||||
example: 'Cliquer, saisir du texte, naviguer'
|
||||
},
|
||||
'logique': {
|
||||
title: 'Logique',
|
||||
description: 'Structures de contrôle pour créer des workflows intelligents avec conditions et branchements.',
|
||||
example: 'Conditions if/else, boucles'
|
||||
},
|
||||
'donnees': {
|
||||
title: 'Données',
|
||||
description: 'Étapes pour extraire, manipuler et stocker des informations depuis les pages web.',
|
||||
example: 'Extraire prix, texte, liens'
|
||||
},
|
||||
'controle': {
|
||||
title: 'Contrôle',
|
||||
description: 'Étapes pour contrôler le flux d\'exécution et la synchronisation du workflow.',
|
||||
example: 'Attendre, capturer, synchroniser'
|
||||
}
|
||||
};
|
||||
|
||||
// Tooltips pour les paramètres
|
||||
export const parameterTooltips: Record<string, TooltipContent> = {
|
||||
target: {
|
||||
title: 'Élément cible',
|
||||
description: 'L\'élément de la page sur lequel effectuer l\'action. Utilisez le sélecteur visuel pour le choisir facilement.',
|
||||
example: 'Bouton, champ de saisie, lien'
|
||||
},
|
||||
text: {
|
||||
title: 'Texte à saisir',
|
||||
description: 'Le texte qui sera saisi dans le champ. Vous pouvez utiliser des variables avec ${nom_variable}.',
|
||||
example: 'Bonjour ${nom} ou texte fixe'
|
||||
},
|
||||
duration: {
|
||||
title: 'Durée d\'attente',
|
||||
description: 'Temps d\'attente en secondes. Peut être décimal (ex: 1.5 pour 1,5 seconde).',
|
||||
example: '2 pour 2 secondes, 0.5 pour 500ms'
|
||||
},
|
||||
condition: {
|
||||
title: 'Expression conditionnelle',
|
||||
description: 'Expression logique à évaluer. Utilise les opérateurs ==, !=, >, <, >=, <= et les variables.',
|
||||
example: '${age} >= 18 ou ${status} == "actif"'
|
||||
},
|
||||
clickType: {
|
||||
title: 'Type de clic',
|
||||
description: 'Le type de clic à effectuer sur l\'élément cible.',
|
||||
example: 'Clic gauche pour la plupart des actions'
|
||||
},
|
||||
clearFirst: {
|
||||
title: 'Vider le champ d\'abord',
|
||||
description: 'Si activé, vide le contenu existant du champ avant de saisir le nouveau texte.',
|
||||
example: 'Utile pour remplacer du texte existant'
|
||||
},
|
||||
attribute: {
|
||||
title: 'Attribut à extraire',
|
||||
description: 'Le type d\'information à extraire de l\'élément sélectionné.',
|
||||
example: 'Texte visible, valeur du champ, URL du lien'
|
||||
},
|
||||
direction: {
|
||||
title: 'Direction du défilement',
|
||||
description: 'La direction dans laquelle faire défiler la page.',
|
||||
example: 'Vers le bas pour voir plus de contenu'
|
||||
},
|
||||
amount: {
|
||||
title: 'Quantité de défilement',
|
||||
description: 'Distance de défilement en pixels. Plus la valeur est élevée, plus le défilement est important.',
|
||||
example: '300 pixels = environ 1/3 d\'écran'
|
||||
},
|
||||
url: {
|
||||
title: 'URL de destination',
|
||||
description: 'L\'adresse web vers laquelle naviguer. Peut contenir des variables.',
|
||||
example: 'https://site.com/page/${id}'
|
||||
},
|
||||
filename: {
|
||||
title: 'Nom du fichier de capture',
|
||||
description: 'Nom optionnel pour le fichier de capture d\'écran. Si vide, un nom automatique sera généré.',
|
||||
example: 'capture_${timestamp} ou nom_fixe'
|
||||
}
|
||||
};
|
||||
|
||||
// Tooltips pour l'interface utilisateur
|
||||
export const uiTooltips: Record<string, TooltipContent> = {
|
||||
canvas: {
|
||||
title: 'Zone de travail',
|
||||
description: 'Espace principal où vous construisez votre workflow en glissant des étapes et en les connectant.',
|
||||
shortcut: 'Molette pour zoomer, clic-glisser pour déplacer'
|
||||
},
|
||||
palette: {
|
||||
title: 'Palette d\'étapes',
|
||||
description: 'Boîte à outils contenant tous les types d\'étapes disponibles, organisés par catégories.',
|
||||
shortcut: 'Glisser une étape vers le canvas'
|
||||
},
|
||||
properties: {
|
||||
title: 'Panneau de propriétés',
|
||||
description: 'Configuration des paramètres de l\'étape sélectionnée. Chaque type d\'étape a ses propres paramètres.',
|
||||
shortcut: 'Cliquer sur une étape pour la configurer'
|
||||
},
|
||||
minimap: {
|
||||
title: 'Mini-carte',
|
||||
description: 'Vue d\'ensemble du workflow complet. Utile pour naviguer dans les gros workflows.',
|
||||
shortcut: 'Cliquer pour se déplacer rapidement'
|
||||
},
|
||||
validator: {
|
||||
title: 'Validateur',
|
||||
description: 'Vérifie la validité du workflow et signale les erreurs ou avertissements.',
|
||||
example: 'Paramètres manquants, étapes déconnectées'
|
||||
},
|
||||
executor: {
|
||||
title: 'Exécuteur',
|
||||
description: 'Lance l\'exécution du workflow et affiche le progrès en temps réel.',
|
||||
shortcut: 'Bouton Play pour démarrer'
|
||||
},
|
||||
variables: {
|
||||
title: 'Gestionnaire de variables',
|
||||
description: 'Créez et gérez les variables utilisées dans votre workflow pour le rendre dynamique.',
|
||||
example: 'nom_utilisateur, email, compteur'
|
||||
},
|
||||
documentation: {
|
||||
title: 'Documentation interactive',
|
||||
description: 'Guides et exemples pour apprendre à utiliser le Visual Workflow Builder efficacement.',
|
||||
shortcut: 'Onglet Documentation'
|
||||
},
|
||||
visualSelector: {
|
||||
title: 'Sélecteur visuel',
|
||||
description: 'Outil pour sélectionner visuellement des éléments sur une capture d\'écran de la page web.',
|
||||
shortcut: 'Bouton "Sélectionner un élément"'
|
||||
},
|
||||
search: {
|
||||
title: 'Recherche d\'étapes',
|
||||
description: 'Recherchez rapidement un type d\'étape par son nom ou sa description.',
|
||||
shortcut: 'Ctrl+F dans la palette'
|
||||
}
|
||||
};
|
||||
|
||||
// Tooltips pour les raccourcis clavier
|
||||
export const keyboardTooltips: Record<string, TooltipContent> = {
|
||||
'ctrl+z': {
|
||||
title: 'Annuler',
|
||||
description: 'Annule la dernière action effectuée dans le workflow.',
|
||||
shortcut: 'Ctrl+Z'
|
||||
},
|
||||
'ctrl+y': {
|
||||
title: 'Rétablir',
|
||||
description: 'Rétablit la dernière action annulée.',
|
||||
shortcut: 'Ctrl+Y'
|
||||
},
|
||||
'ctrl+s': {
|
||||
title: 'Sauvegarder',
|
||||
description: 'Sauvegarde le workflow actuel.',
|
||||
shortcut: 'Ctrl+S'
|
||||
},
|
||||
'ctrl+c': {
|
||||
title: 'Copier',
|
||||
description: 'Copie les étapes sélectionnées.',
|
||||
shortcut: 'Ctrl+C'
|
||||
},
|
||||
'ctrl+v': {
|
||||
title: 'Coller',
|
||||
description: 'Colle les étapes copiées.',
|
||||
shortcut: 'Ctrl+V'
|
||||
},
|
||||
'delete': {
|
||||
title: 'Supprimer',
|
||||
description: 'Supprime les étapes ou connexions sélectionnées.',
|
||||
shortcut: 'Suppr'
|
||||
},
|
||||
'ctrl+a': {
|
||||
title: 'Tout sélectionner',
|
||||
description: 'Sélectionne toutes les étapes du workflow.',
|
||||
shortcut: 'Ctrl+A'
|
||||
},
|
||||
'space': {
|
||||
title: 'Mode panoramique',
|
||||
description: 'Maintenir Espace + glisser pour déplacer la vue du canvas.',
|
||||
shortcut: 'Espace + glisser'
|
||||
}
|
||||
};
|
||||
|
||||
// Fonction utilitaire pour obtenir un tooltip
|
||||
export const getTooltip = (category: string, key: string): TooltipContent | null => {
|
||||
const tooltipMaps: Record<string, Record<string, TooltipContent>> = {
|
||||
step: stepTooltips,
|
||||
category: categoryTooltips,
|
||||
parameter: parameterTooltips,
|
||||
ui: uiTooltips,
|
||||
keyboard: keyboardTooltips
|
||||
};
|
||||
|
||||
return tooltipMaps[category]?.[key] || null;
|
||||
};
|
||||
|
||||
// Fonction pour formater un tooltip en texte riche
|
||||
export const formatTooltip = (tooltip: TooltipContent): string => {
|
||||
let formatted = `${tooltip.title}\n\n${tooltip.description}`;
|
||||
|
||||
if (tooltip.example) {
|
||||
formatted += `\n\nExemple : ${tooltip.example}`;
|
||||
}
|
||||
|
||||
if (tooltip.shortcut) {
|
||||
formatted += `\n\nRaccourci : ${tooltip.shortcut}`;
|
||||
}
|
||||
|
||||
return formatted;
|
||||
};
|
||||
Reference in New Issue
Block a user