DesertWolf's picture
Upload folder using huggingface_hub
447ebeb verified
import React from 'react';
import { Typography, Select, Button, Checkbox, Tooltip, Tag } from 'antd';
import { CloseOutlined, EyeInvisibleOutlined, StopOutlined, FilterOutlined } from '@ant-design/icons';
import { PiiEntityCategory } from './types';
const { Text } = Typography;
const { Option } = Select;
// Helper functions
export const formatEntityName = (name: string) => {
return name.replace(/_/g, ' ');
};
export const getActionIcon = (action: string) => {
switch(action) {
case 'MASK':
return <EyeInvisibleOutlined style={{ marginRight: 4 }} />;
case 'BLOCK':
return <StopOutlined style={{ marginRight: 4 }} />;
default:
return null;
}
};
// CategoryFilter component
export interface CategoryFilterProps {
categories: PiiEntityCategory[];
selectedCategories: string[];
onChange: (categories: string[]) => void;
}
export const CategoryFilter: React.FC<CategoryFilterProps> = ({
categories,
selectedCategories,
onChange
}) => {
return (
<div>
<div className="flex items-center mb-2">
<FilterOutlined className="text-gray-500 mr-1" />
<Text className="text-gray-500 font-medium">Filter by category</Text>
</div>
<Select
mode="multiple"
placeholder="Select categories to filter by"
style={{ width: '100%' }}
onChange={onChange}
value={selectedCategories}
allowClear
showSearch
optionFilterProp="children"
className="mb-4"
tagRender={(props) => (
<Tag
color="blue"
closable={props.closable}
onClose={props.onClose}
className="mr-2 mb-2"
>
{props.label}
</Tag>
)}
>
{categories.map(cat => (
<Option key={cat.category} value={cat.category}>
{cat.category}
</Option>
))}
</Select>
</div>
);
};
// QuickActions component
export interface QuickActionsProps {
onSelectAll: (action: string) => void;
onUnselectAll: () => void;
hasSelectedEntities: boolean;
}
export const QuickActions: React.FC<QuickActionsProps> = ({
onSelectAll,
onUnselectAll,
hasSelectedEntities
}) => {
return (
<div className="bg-gray-50 p-5 rounded-lg mb-6 border border-gray-200 shadow-sm">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center">
<Text strong className="text-gray-700 text-base">Quick Actions</Text>
<Tooltip title="Apply action to all PII types at once">
<div className="ml-2 text-gray-400 cursor-help text-xs"></div>
</Tooltip>
</div>
<Button
type="default"
onClick={onUnselectAll}
disabled={!hasSelectedEntities}
icon={<CloseOutlined />}
className="border-gray-300 hover:text-red-600 hover:border-red-300"
>
Unselect All
</Button>
</div>
<div className="grid grid-cols-2 gap-4">
<Button
type="default"
onClick={() => onSelectAll('MASK')}
className="flex items-center justify-center h-10 border-blue-200 hover:border-blue-300 hover:text-blue-700 bg-blue-50 hover:bg-blue-100 text-blue-600"
block
icon={<EyeInvisibleOutlined />}
>
Select All & Mask
</Button>
<Button
type="default"
onClick={() => onSelectAll('BLOCK')}
className="flex items-center justify-center h-10 border-red-200 hover:border-red-300 hover:text-red-700 bg-red-50 hover:bg-red-100 text-red-600"
block
icon={<StopOutlined />}
>
Select All & Block
</Button>
</div>
</div>
);
};
// PiiEntityList component
export interface PiiEntityListProps {
entities: string[];
selectedEntities: string[];
selectedActions: {[key: string]: string};
actions: string[];
onEntitySelect: (entity: string) => void;
onActionSelect: (entity: string, action: string) => void;
entityToCategoryMap: Map<string, string>;
}
export const PiiEntityList: React.FC<PiiEntityListProps> = ({
entities,
selectedEntities,
selectedActions,
actions,
onEntitySelect,
onActionSelect,
entityToCategoryMap
}) => {
return (
<div className="border rounded-lg overflow-hidden shadow-sm">
<div className="bg-gray-50 px-5 py-3 border-b flex">
<Text strong className="flex-1 text-gray-700">PII Type</Text>
<Text strong className="w-32 text-right text-gray-700">Action</Text>
</div>
<div className="max-h-[400px] overflow-y-auto">
{entities.length === 0 ? (
<div className="py-10 text-center text-gray-500">
No PII types match your filter criteria
</div>
) : (
entities.map(entity => (
<div
key={entity}
className={`px-5 py-3 flex items-center justify-between hover:bg-gray-50 border-b ${
selectedEntities.includes(entity) ? 'bg-blue-50' : ''
}`}
>
<div className="flex items-center flex-1">
<Checkbox
checked={selectedEntities.includes(entity)}
onChange={() => onEntitySelect(entity)}
className="mr-3"
/>
<Text className={selectedEntities.includes(entity) ? 'font-medium text-gray-900' : 'text-gray-700'}>
{formatEntityName(entity)}
</Text>
{entityToCategoryMap.get(entity) && (
<Tag className="ml-2 text-xs" color="blue">{entityToCategoryMap.get(entity)}</Tag>
)}
</div>
<div className="w-32">
<Select
value={selectedEntities.includes(entity) ? (selectedActions[entity] || 'MASK') : 'MASK'}
onChange={(value) => onActionSelect(entity, value)}
style={{ width: 120 }}
disabled={!selectedEntities.includes(entity)}
className={`${!selectedEntities.includes(entity) ? 'opacity-50' : ''}`}
dropdownMatchSelectWidth={false}
>
{actions.map(action => (
<Option key={action} value={action}>
<div className="flex items-center">
{getActionIcon(action)}
{action}
</div>
</Option>
))}
</Select>
</div>
</div>
))
)}
</div>
</div>
);
};