mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-13 10:26:38 +08:00
prettier
This commit is contained in:
@@ -1,37 +1,74 @@
|
||||
import {Handle, Position, type NodeProps} from '@xyflow/react';
|
||||
import {Ban, Fingerprint, Flag, Globe2, Play, ShieldCheck} from 'lucide-react';
|
||||
import { Handle, Position, type NodeProps } from '@xyflow/react';
|
||||
import {
|
||||
Ban,
|
||||
Fingerprint,
|
||||
Flag,
|
||||
Globe2,
|
||||
Play,
|
||||
ShieldCheck,
|
||||
} from 'lucide-react';
|
||||
|
||||
import {Badge} from '@/components/ui/badge';
|
||||
import {cn} from '@/lib/utils';
|
||||
import type {WAFRuleNode} from '@/lib/services/openflare';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { cn } from '@/lib/utils';
|
||||
import type { WAFRuleNode } from '@/lib/services/openflare';
|
||||
|
||||
export interface RuleFlowNodeData extends Record<string, unknown> { rule: WAFRuleNode; issues: number }
|
||||
export interface RuleFlowNodeData extends Record<string, unknown> {
|
||||
rule: WAFRuleNode;
|
||||
issues: number;
|
||||
}
|
||||
|
||||
const meta = {
|
||||
start: {label: '开始', icon: Play}, ip_match: {label: 'IP 匹配', icon: Fingerprint}, geo_match: {label: '地域匹配', icon: Globe2},
|
||||
pow: {label: 'PoW 挑战', icon: ShieldCheck}, allow: {label: '通过', icon: Flag}, block: {label: '阻止', icon: Ban},
|
||||
start: { label: '开始', icon: Play },
|
||||
ip_match: { label: 'IP 匹配', icon: Fingerprint },
|
||||
geo_match: { label: '地域匹配', icon: Globe2 },
|
||||
pow: { label: 'PoW 挑战', icon: ShieldCheck },
|
||||
allow: { label: '通过', icon: Flag },
|
||||
block: { label: '阻止', icon: Ban },
|
||||
} as const;
|
||||
|
||||
const outputHandles: Partial<Record<WAFRuleNode['type'], string[]>> = {start: ['next'], ip_match: ['true', 'false'], geo_match: ['true', 'false'], pow: ['next']};
|
||||
const outputHandles: Partial<Record<WAFRuleNode['type'], string[]>> = {
|
||||
start: ['next'],
|
||||
ip_match: ['true', 'false'],
|
||||
geo_match: ['true', 'false'],
|
||||
pow: ['next'],
|
||||
};
|
||||
|
||||
export function RuleNode({data, selected}: NodeProps) {
|
||||
export function RuleNode({ data, selected }: NodeProps) {
|
||||
const value = data as RuleFlowNodeData;
|
||||
const {rule, issues} = value;
|
||||
const {label, icon: Icon} = meta[rule.type];
|
||||
const { rule, issues } = value;
|
||||
const { label, icon: Icon } = meta[rule.type];
|
||||
return (
|
||||
<div className={cn('min-w-44 rounded-lg border bg-card shadow-sm transition-shadow', selected && 'ring-2 ring-ring', issues > 0 && 'border-destructive')}>
|
||||
{rule.type !== 'start' && <Handle type="target" position={Position.Left} />}
|
||||
<div className="flex items-center gap-3 px-4 py-3">
|
||||
<Icon className="size-5 text-primary" />
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-0.5">
|
||||
<span className="text-sm font-medium">{label}</span>
|
||||
<span className="font-mono text-[10px] text-muted-foreground">{rule.id}</span>
|
||||
<div
|
||||
className={cn(
|
||||
'min-w-44 rounded-lg border bg-card shadow-sm transition-shadow',
|
||||
selected && 'ring-2 ring-ring',
|
||||
issues > 0 && 'border-destructive',
|
||||
)}
|
||||
>
|
||||
{rule.type !== 'start' && (
|
||||
<Handle type='target' position={Position.Left} />
|
||||
)}
|
||||
<div className='flex items-center gap-3 px-4 py-3'>
|
||||
<Icon className='size-5 text-primary' />
|
||||
<div className='flex min-w-0 flex-1 flex-col gap-0.5'>
|
||||
<span className='text-sm font-medium'>{label}</span>
|
||||
<span className='font-mono text-[10px] text-muted-foreground'>
|
||||
{rule.id}
|
||||
</span>
|
||||
</div>
|
||||
{issues > 0 && <Badge variant="destructive">{issues}</Badge>}
|
||||
{issues > 0 && <Badge variant='destructive'>{issues}</Badge>}
|
||||
</div>
|
||||
{(outputHandles[rule.type] ?? []).map((handle, index, all) => (
|
||||
<Handle key={handle} id={handle} type="source" position={Position.Right} style={{top: `${((index + 1) / (all.length + 1)) * 100}%`}}>
|
||||
<span className="absolute right-3 -translate-y-1/2 text-[9px] text-muted-foreground">{handle}</span>
|
||||
<Handle
|
||||
key={handle}
|
||||
id={handle}
|
||||
type='source'
|
||||
position={Position.Right}
|
||||
style={{ top: `${((index + 1) / (all.length + 1)) * 100}%` }}
|
||||
>
|
||||
<span className='absolute right-3 -translate-y-1/2 text-[9px] text-muted-foreground'>
|
||||
{handle}
|
||||
</span>
|
||||
</Handle>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user