GuardPII / public /elements /PII.jsx
Antigravity Bot
Initial commit (history cleaned)
9bd50b9
Raw
History Blame Contribute Delete
6.11 kB
import React, { useState, useMemo, useEffect } from 'react';
import {
Table,
TableBody,
TableCaption,
TableCell,
TableFooter,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { useRecoilValue } from 'recoil';
import { callFnState } from '@chainlit/react-client';
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { ClipboardPaste, Plus, Lock, LockOpen } from 'lucide-react'
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
// Internal Badge component to avoid import errors
const Badge = ({ children, className }) => (
<span className={`bg-pii text-blue-800 rounded-full px-2 py-1 mx-1 transition-colors text-main-700 ${className}`}>
{children}
</span>
);
function PII() {
// const dic = props.dic || {};
const [dic, setDict] = useState(props.dic || {});
const [searchTerm, setSearchTerm] = useState('');
const [dictionary, setDictionary] = useState({});
const [systemLang, setSystemLang] = useState((typeof navigator !== 'undefined' && (navigator.language || navigator.userLanguage)) ? (navigator.language || navigator.userLanguage).split('-')[0] : 'en');
const callFn = useRecoilValue(callFnState);
const handleUpdatePii = (key, value) => {
callAction(
{
name: "update_pii", payload: {
key: key,
value: value
}
}
)
setDict({ ...dic, [key]: { ...dic[key], locked: !dic[key]['locked'] } });
};
useEffect(() => {
// Fetch the file from the public path
fetch('/public/dictionnaire.json')
.then(response => response.json()) // Parse the response as JSON
.then(data => setDictionary(data)) // Set the data in state
.catch(error => console.error('Error fetching JSON:', error));
}, []);
// Determine system language
// const systemLang = (typeof navigator !== 'undefined' && (navigator.language || navigator.userLanguage)) ? (navigator.language || navigator.userLanguage).split('-')[0] : 'en';
// Enrich dictionary with localized types
function getType(typ) {
if (dictionary[typ]) {
return dictionary[typ][systemLang] || dictionary[typ]['en'] || typ;
}
return typ;
}
const enrichedDic = useMemo(() => {
return Object.entries(dic).reduce((acc, [key, value]) => {
const typeKey = value.type;
const dictEntry = dictionary[typeKey];
const localizedType = dictEntry
? (dictEntry[systemLang] || dictEntry['en'] || typeKey)
: typeKey;
acc[key] = { ...value, typ: localizedType };
return acc;
}, {});
}, [dic, systemLang]);
const filteredDic = useMemo(() => {
if (searchTerm.trim() === '') {
return enrichedDic;
}
return Object.fromEntries(
Object.entries(enrichedDic).filter(([key, value]) =>
String(value.type).toLowerCase().includes(searchTerm.toLowerCase()) ||
String(value.value).toLowerCase().includes(searchTerm.toLowerCase())
)
);
}, [searchTerm, enrichedDic]);
const handlInsert = (value) => {
console.log("value", value);
const chatInput = document.getElementById('chat-input');
if (chatInput && chatInput instanceof HTMLTextAreaElement) {
const start = chatInput.selectionStart;
const end = chatInput.selectionEnd;
const currentValue = chatInput.value;
const spaceToAdd = " ";
const newValue = currentValue.substring(0, start) + spaceToAdd + value + spaceToAdd + currentValue.substring(end);
chatInput.value = newValue;
chatInput.selectionStart = chatInput.selectionEnd = start + spaceToAdd.length + String(value).length + spaceToAdd.length;
chatInput.focus();
} else {
console.warn('Textarea with id "chat-input" not found.');
}
}
return (
<div className='flex flex-col gap-4'>
<div className="relative">
<svg className="absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<Input
type="text"
placeholder="Rechercher"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="pl-8"
/>
</div>
{Object.entries(filteredDic).map(([key, value]) => (
<div className='flex flex-col p-4 border-2 rounded-xl gap-2' key={key}>
<span className="text-primary-700">{value.value}</span>
<div className='flex flex-row justify-between'>
<Badge>{getType(value.type)}</Badge>
<div className='flex flex-row gap-2'>
<Button variant="outline" className={value.locked ? "p-2 h-8 rounded-full bg-locked" : "p-2 h-8 rounded-full bg-unlocked"} onClick={() => handleUpdatePii(`${key}`, value.value)}>
{value.locked ? <Lock className="font-bold" /> : <LockOpen className="font-bold" />}
</Button>
<Button variant="outline" className="p-2 h-8 w-8 rounded-full" onClick={() => handlInsert(value.locked ? `[${value.type}_${key}]` : value.value)}>
<Plus className="font-bold" />
</Button>
</div>
</div>
</div>
))}
</div>
)
};
export default PII;