presidio ok v.1 button disposition

This commit is contained in:
nBiqoz
2025-07-28 23:14:26 +02:00
parent cb2c17ce2b
commit bc07ea6077
4 changed files with 172 additions and 83 deletions

View File

@@ -76,7 +76,10 @@ export const AnonymizationInterface = ({
} }
// Téléphones (anciens patterns) // Téléphones (anciens patterns)
if (outputText.includes("[Téléphone1]") || outputText.includes("[Téléphone")) { if (
outputText.includes("[Téléphone1]") ||
outputText.includes("[Téléphone")
) {
anonymizedTypes.add("Numéros de téléphone"); anonymizedTypes.add("Numéros de téléphone");
} }

View File

@@ -1,7 +1,15 @@
import { Upload, FileText, AlertTriangle } from "lucide-react"; import {
Upload,
FileText,
AlertTriangle,
Shield,
Copy,
Download,
} from "lucide-react";
import { SampleTextComponent } from "./SampleTextComponent"; import { SampleTextComponent } from "./SampleTextComponent";
import { SupportedDataTypes } from "./SupportedDataTypes"; import { SupportedDataTypes } from "./SupportedDataTypes";
import { AnonymizationInterface } from "./AnonymizationInterface"; import { AnonymizationInterface } from "./AnonymizationInterface";
import { highlightEntities } from "../utils/highlightEntities";
interface FileUploadComponentProps { interface FileUploadComponentProps {
uploadedFile: File | null; uploadedFile: File | null;
@@ -16,6 +24,8 @@ interface FileUploadComponentProps {
isLoadingFile?: boolean; isLoadingFile?: boolean;
onRestart?: () => void; onRestart?: () => void;
outputText?: string; outputText?: string;
copyToClipboard?: () => void;
downloadText?: () => void;
} }
export const FileUploadComponent = ({ export const FileUploadComponent = ({
@@ -31,12 +41,101 @@ export const FileUploadComponent = ({
isLoadingFile = false, isLoadingFile = false,
onRestart, onRestart,
outputText, outputText,
copyToClipboard,
downloadText,
}: FileUploadComponentProps) => { }: FileUploadComponentProps) => {
// Si un fichier est uploadé ou qu'il y a du texte d'exemple, on affiche le preview // Si un fichier est uploadé ou qu'il y a du texte d'exemple, on affiche le preview
if (uploadedFile || (sourceText && sourceText.trim())) { if (uploadedFile || (sourceText && sourceText.trim())) {
return ( return (
<div className="w-full flex flex-col space-y-6"> <div className="w-full flex flex-col space-y-6">
{/* Preview du document avec en-tête simple */} {/* Si on a un résultat, afficher 2 blocs côte à côte */}
{outputText ? (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
{/* Preview du document original */}
<div className="bg-white rounded-2xl border border-gray-100 overflow-hidden">
<div className="bg-orange-50 border-b border-orange-200 px-4 sm:px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-orange-100 rounded-lg flex items-center justify-center">
<FileText className="h-4 w-4 sm:h-5 sm:w-5 text-orange-600" />
</div>
<div className="min-w-0 flex-1">
{uploadedFile ? (
<p className="text-xs sm:text-sm text-orange-600 truncate">
{uploadedFile.name} {" "}
{(uploadedFile.size / 1024).toFixed(1)} KB
</p>
) : (
<p className="text-xs sm:text-sm text-orange-600">
Demo - Exemple de texte
</p>
)}
</div>
</div>
</div>
</div>
<div className="p-1">
<div className="bg-gray-50 border border-gray-200 rounded-lg p-3 sm:p-4 max-h-72 overflow-y-auto overflow-x-hidden">
<pre className="text-xs sm:text-sm text-gray-700 whitespace-pre-wrap font-mono break-words overflow-wrap-anywhere">
{sourceText || "Aucun contenu à afficher"}
</pre>
</div>
</div>
</div>
{/* Bloc résultat anonymisé */}
<div className="bg-white rounded-2xl border border-gray-100 overflow-hidden">
<div className="bg-green-50 border-b border-green-200 px-4 sm:px-6 py-4">
<div className="flex items-center justify-between">
<div className="flex items-center space-x-3">
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-green-100 rounded-lg flex items-center justify-center">
<Shield className="h-4 w-4 sm:h-5 sm:w-5 text-green-600" />
</div>
<div className="min-w-0 flex-1">
<p className="text-xs sm:text-sm text-green-600">
Document anonymisé
</p>
</div>
</div>
{/* Boutons d'action */}
<div className="flex items-center gap-2">
{copyToClipboard && (
<button
onClick={copyToClipboard}
className="p-2 text-green-600 hover:text-green-700 hover:bg-green-100 rounded-lg transition-colors duration-200"
title="Copier le texte"
>
<Copy className="h-4 w-4" />
</button>
)}
{downloadText && (
<button
onClick={downloadText}
className="bg-green-600 hover:bg-green-700 text-white px-3 py-2 rounded-lg text-xs font-medium transition-colors duration-200 flex items-center space-x-1"
title="Télécharger le fichier"
>
<Download className="h-3 w-3" />
<span className="hidden sm:inline">Télécharger</span>
</button>
)}
</div>
</div>
</div>
<div className="p-1">
<div className="bg-gray-50 border border-gray-200 rounded-lg p-3 sm:p-4 max-h-72 overflow-y-auto overflow-x-hidden">
<div className="text-xs sm:text-sm text-gray-700 whitespace-pre-wrap break-words overflow-wrap-anywhere leading-relaxed">
{highlightEntities(
outputText || "Aucun contenu à afficher"
)}
</div>
</div>
</div>
</div>
</div>
) : (
/* Preview normal quand pas de résultat */
<div className="bg-white rounded-2xl border border-gray-100 overflow-hidden"> <div className="bg-white rounded-2xl border border-gray-100 overflow-hidden">
<div className="bg-orange-50 border-b border-orange-200 px-4 sm:px-6 py-4"> <div className="bg-orange-50 border-b border-orange-200 px-4 sm:px-6 py-4">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
@@ -60,7 +159,7 @@ export const FileUploadComponent = ({
</div> </div>
</div> </div>
<div className="p-4 sm:p-6"> <div className="p-2 ">
{/* Zone de texte avec limite de hauteur et scroll */} {/* Zone de texte avec limite de hauteur et scroll */}
<div className="bg-gray-50 border border-gray-200 rounded-lg p-3 sm:p-4 max-h-48 overflow-y-auto overflow-x-hidden"> <div className="bg-gray-50 border border-gray-200 rounded-lg p-3 sm:p-4 max-h-48 overflow-y-auto overflow-x-hidden">
{isLoadingFile ? ( {isLoadingFile ? (
@@ -91,6 +190,7 @@ export const FileUploadComponent = ({
</div> </div>
</div> </div>
</div> </div>
)}
{/* Boutons d'action - Responsive mobile */} {/* Boutons d'action - Responsive mobile */}
{canAnonymize && !isLoadingFile && ( {canAnonymize && !isLoadingFile && (

View File

@@ -1,4 +1,5 @@
import { Check, Upload, Eye, Shield } from "lucide-react"; import { Check, Upload, Eye, Shield } from "lucide-react";
import React from "react";
interface ProgressBarProps { interface ProgressBarProps {
currentStep: number; currentStep: number;
@@ -27,15 +28,15 @@ export const ProgressBar = ({ currentStep, steps }: ProgressBarProps) => {
return ( return (
<div className="w-full max-w-2xl mx-auto mb-4 px-2"> <div className="w-full max-w-2xl mx-auto mb-4 px-2">
<div className="flex items-center justify-center"> <div className="flex items-center justify-center">
<div className="flex items-center justify-between w-full max-w-xs sm:max-w-md"> <div className="flex items-center w-full max-w-md">
{steps.map((step, index) => { {steps.map((step, index) => {
const stepNumber = index + 1; const stepNumber = index + 1;
const isCompleted = stepNumber < currentStep; const isCompleted = stepNumber < currentStep;
const isCurrent = stepNumber === currentStep; const isCurrent = stepNumber === currentStep;
return ( return (
<div key={index} className="flex items-center"> <React.Fragment key={index}>
{/* Step Circle */} {/* Step Circle and Label */}
<div className="flex flex-col items-center"> <div className="flex flex-col items-center">
<div <div
className={`w-5 h-5 sm:w-6 sm:h-6 rounded-full flex items-center justify-center font-medium text-xs transition-all duration-300 ${ className={`w-5 h-5 sm:w-6 sm:h-6 rounded-full flex items-center justify-center font-medium text-xs transition-all duration-300 ${
@@ -55,8 +56,8 @@ export const ProgressBar = ({ currentStep, steps }: ProgressBarProps) => {
: "text-gray-500" : "text-gray-500"
}`} }`}
style={{ style={{
wordBreak: 'break-word', wordBreak: "break-word",
hyphens: 'auto' hyphens: "auto",
}} }}
> >
{step === "Anonymisation" ? ( {step === "Anonymisation" ? (
@@ -72,9 +73,9 @@ export const ProgressBar = ({ currentStep, steps }: ProgressBarProps) => {
{/* Connector Line */} {/* Connector Line */}
{index < steps.length - 1 && ( {index < steps.length - 1 && (
<div className="flex-1 mx-2 sm:mx-4"> <div className="flex-1 flex items-center justify-center px-2 sm:px-4">
<div <div
className={`h-0.5 w-6 sm:w-12 transition-all duration-300 ${ className={`h-0.5 w-full max-w-[40px] sm:max-w-[60px] transition-all duration-300 ${
stepNumber < currentStep stepNumber < currentStep
? "bg-[#f7ab6e]" ? "bg-[#f7ab6e]"
: "bg-gray-200" : "bg-gray-200"
@@ -82,7 +83,7 @@ export const ProgressBar = ({ currentStep, steps }: ProgressBarProps) => {
/> />
</div> </div>
)} )}
</div> </React.Fragment>
); );
})} })}
</div> </div>

View File

@@ -2,13 +2,12 @@
import { useState } from "react"; import { useState } from "react";
import { FileUploadComponent } from "./components/FileUploadComponent"; import { FileUploadComponent } from "./components/FileUploadComponent";
import { ResultPreviewComponent } from "./components/ResultPreviewComponent";
import { EntityMappingTable } from "./components/EntityMappingTable"; import { EntityMappingTable } from "./components/EntityMappingTable";
import { ProgressBar } from "./components/ProgressBar"; import { ProgressBar } from "./components/ProgressBar";
import { useFileHandler } from "./components/FileHandler"; import { useFileHandler } from "./components/FileHandler";
import { useAnonymization } from "./components/AnonymizationLogic"; import { useAnonymization } from "./components/AnonymizationLogic";
import { useDownloadActions } from "./components/DownloadActions"; import { useDownloadActions } from "./components/DownloadActions";
import { highlightEntities } from "./utils/highlightEntities";
interface EntityMapping { interface EntityMapping {
originalValue: string; originalValue: string;
@@ -81,13 +80,13 @@ export default function Home() {
</div> </div>
{/* Main Content */} {/* Main Content */}
<div className="max-w-5xl mx-auto px-2 sm:px-4 py-4 sm:py-8 space-y-4"> <div className="max-w-6xl mx-auto px-2 sm:px-4 py-4 sm:py-8 space-y-4">
{/* Progress Bar */} {/* Progress Bar */}
<ProgressBar currentStep={getCurrentStep()} steps={progressSteps} /> <ProgressBar currentStep={getCurrentStep()} steps={progressSteps} />
{/* Upload Section */} {/* Upload Section */}
<div className="bg-white rounded-2xl border border-gray-50 overflow-hidden"> <div className="bg-white rounded-2xl border border-gray-50 overflow-hidden">
<div className="p-3 sm:p-6"> <div className="p-1 sm:p-3">
<FileUploadComponent <FileUploadComponent
uploadedFile={uploadedFile} uploadedFile={uploadedFile}
handleFileChange={handleFileChange} handleFileChange={handleFileChange}
@@ -104,28 +103,16 @@ export default function Home() {
isLoadingFile={isLoadingFile} isLoadingFile={isLoadingFile}
onRestart={handleRestart} onRestart={handleRestart}
outputText={outputText} outputText={outputText}
/>
</div>
</div>
{/* Result Preview */}
{outputText && (
<div className="bg-white rounded-2xl border border-gray-100 overflow-hidden">
<div className="p-3 sm:p-6">
<ResultPreviewComponent
outputText={outputText}
copyToClipboard={copyToClipboard} copyToClipboard={copyToClipboard}
downloadText={downloadText} downloadText={downloadText}
highlightEntities={highlightEntities}
/> />
</div> </div>
</div> </div>
)}
{/* Entity Mapping Table */} {/* Entity Mapping Table - Seulement si outputText existe */}
{outputText && ( {outputText && (
<div className="bg-white rounded-2xl border border-gray-100 overflow-hidden"> <div className="bg-white rounded-2xl border border-gray-100 overflow-hidden">
<div className="p-3 sm:p-6"> <div className="p-1 sm:p-3">
<EntityMappingTable mappings={entityMappings} /> <EntityMappingTable mappings={entityMappings} />
</div> </div>
</div> </div>
@@ -166,11 +153,9 @@ export default function Home() {
</div> </div>
</div> </div>
) : line.startsWith("-") ? ( ) : line.startsWith("-") ? (
<div className="ml-4 text-blue-700"> <div className="ml-4 text-blue-700">{line}</div>
{line.substring(1).trim()}
</div>
) : ( ) : (
<div>{line}</div> line
)} )}
</div> </div>
))} ))}