mac multi select

This commit is contained in:
nBiqoz
2025-09-12 13:28:39 +02:00
parent 0360e1ca9f
commit d7d3a3c7e9
5 changed files with 60 additions and 25 deletions

View File

@@ -175,8 +175,8 @@ export async function POST(req: NextRequest) {
// ✅ Définir l'URL AVANT de l'utiliser // ✅ Définir l'URL AVANT de l'utiliser
const presidioAnalyzerUrl = const presidioAnalyzerUrl =
"http://analyzer.151.80.20.211.sslip.io/analyze"; // "http://analyzer.151.80.20.211.sslip.io/analyze";
"http://localhost:5001/analyze";
try { try {
const analyzeResponse = await fetch(presidioAnalyzerUrl, { const analyzeResponse = await fetch(presidioAnalyzerUrl, {
method: "POST", method: "POST",
@@ -213,7 +213,8 @@ export async function POST(req: NextRequest) {
console.log("🔍 Appel à Presidio Anonymizer..."); console.log("🔍 Appel à Presidio Anonymizer...");
const presidioAnonymizerUrl = const presidioAnonymizerUrl =
"http://analyzer.151.80.20.211.sslip.io/anonymize"; // "http://analyzer.151.80.20.211.sslip.io/anonymize";
"http://localhost:5001/anonymize";
const anonymizeResponse = await fetch(presidioAnonymizerUrl, { const anonymizeResponse = await fetch(presidioAnonymizerUrl, {
method: "POST", method: "POST",
@@ -254,26 +255,39 @@ export async function POST(req: NextRequest) {
// Extraire tous les remplacements [XXX] du texte anonymisé // Extraire tous les remplacements [XXX] du texte anonymisé
const replacementPattern = /\[[^\]]+\]/g; const replacementPattern = /\[[^\]]+\]/g;
const foundReplacements = anonymizedText.match(replacementPattern) || []; const foundReplacements =
anonymizedText.match(replacementPattern) || [];
console.log("🔍 Remplacements trouvés dans le texte anonymisé:", foundReplacements); console.log(
"🔍 Remplacements trouvés dans le texte anonymisé:",
foundReplacements
);
// Trier les entités par position // Trier les entités par position
const sortedResults = [...analyzerResults].sort((a, b) => a.start - b.start); const sortedResults = [...analyzerResults].sort(
(a, b) => a.start - b.start
);
// Associer chaque entité avec son remplacement correspondant // Associer chaque entité avec son remplacement correspondant
sortedResults.forEach((result, index) => { sortedResults.forEach((result, index) => {
const originalValue = originalText.substring(result.start, result.end); const originalValue = originalText.substring(
result.start,
result.end
);
if (index < foundReplacements.length) { if (index < foundReplacements.length) {
// Utiliser le remplacement correspondant par ordre d'apparition // Utiliser le remplacement correspondant par ordre d'apparition
replacementMap[originalValue] = foundReplacements[index]; replacementMap[originalValue] = foundReplacements[index];
console.log(`✅ Mapping ordonné: "${originalValue}" -> "${foundReplacements[index]}"`); console.log(
`✅ Mapping ordonné: "${originalValue}" -> "${foundReplacements[index]}"`
);
} else { } else {
// Fallback si pas assez de remplacements trouvés // Fallback si pas assez de remplacements trouvés
const fallbackValue = `[${result.entity_type.toUpperCase()}]`; const fallbackValue = `[${result.entity_type.toUpperCase()}]`;
replacementMap[originalValue] = fallbackValue; replacementMap[originalValue] = fallbackValue;
console.log(`⚠️ Fallback: "${originalValue}" -> "${fallbackValue}"`); console.log(
`⚠️ Fallback: "${originalValue}" -> "${fallbackValue}"`
);
} }
}); });

View File

@@ -11,8 +11,7 @@ export const InstructionsPanel: React.FC = () => {
<ul className="space-y-1 text-blue-700"> <ul className="space-y-1 text-blue-700">
<li> Survolez les mots pour les mettre en évidence</li> <li> Survolez les mots pour les mettre en évidence</li>
<li> <li>
Cliquez pour sélectionner un mot, Crtl + clic pour plusieurs Cliquez pour sélectionner un mot, Ctrl/CMD (ou Shift) + clic.
mots
</li> </li>
<li> Faites clic droit pour ouvrir le menu contextuel</li> <li> Faites clic droit pour ouvrir le menu contextuel</li>
<li> Modifiez les labels et couleurs selon vos besoins</li> <li> Modifiez les labels et couleurs selon vos besoins</li>

View File

@@ -53,7 +53,10 @@ export const InteractiveTextEditor: React.FC<InteractiveTextEditorProps> = ({
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
if (event.ctrlKey || event.metaKey) { // Support multi-sélection avec Ctrl, Cmd et Shift
const isMultiSelect = event.ctrlKey || event.metaKey || event.shiftKey;
if (isMultiSelect) {
setSelectedWords((prev) => { setSelectedWords((prev) => {
const newSet = new Set(prev); const newSet = new Set(prev);
if (newSet.has(index)) { if (newSet.has(index)) {

View File

@@ -70,11 +70,24 @@ export const TextDisplay: React.FC<TextDisplayProps> = ({
className={className} className={className}
style={{ style={{
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
userSelect: "none",
WebkitUserSelect: "none",
}} }}
onMouseEnter={() => onWordHover(index)} onMouseEnter={() => onWordHover(index)}
onMouseLeave={() => onWordHover(null)} onMouseLeave={() => onWordHover(null)}
onClick={(e) => onWordClick(index, e)} onClick={(e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey) {
e.preventDefault();
e.stopPropagation();
}
onWordClick(index, e);
}}
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
onMouseDown={(e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey) {
e.preventDefault();
}
}}
title={ title={
word.isEntity word.isEntity
? `Entité: ${word.entityType} (Original: ${word.text})` ? `Entité: ${word.entityType} (Original: ${word.text})`

View File

@@ -162,11 +162,15 @@ export const useContextMenu = ({
if (!contextMenu.selectedText) return; if (!contextMenu.selectedText) return;
const originalText = contextMenu.selectedText; const originalText = contextMenu.selectedText;
const firstWordIndex = contextMenu.wordIndices[0]; const selectedIndices = contextMenu.wordIndices;
const clickedWord = words[firstWordIndex]; // Calculer les positions de début et fin pour tous les mots sélectionnés
const wordStart = clickedWord?.start; const sortedIndices = selectedIndices.sort((a, b) => a - b);
const wordEnd = clickedWord?.end; const firstWord = words[sortedIndices[0]];
const lastWord = words[sortedIndices[sortedIndices.length - 1]];
const wordStart = firstWord?.start;
const wordEnd = lastWord?.end;
const existingMapping = entityMappings.find( const existingMapping = entityMappings.find(
(m) => m.text === originalText (m) => m.text === originalText
@@ -179,7 +183,9 @@ export const useContextMenu = ({
text: originalText, text: originalText,
label: displayName, label: displayName,
entityType, entityType,
applyToAll applyToAll,
wordIndices: selectedIndices,
positions: { start: wordStart, end: wordEnd }
}); });
onUpdateMapping( onUpdateMapping(