Files
opsxsql/frontend/src/features/redis/components/RedisLineEditorDialog.tsx
T

76 lines
3.5 KiB
TypeScript

import { Copy } from 'lucide-react';
import { FormDialog } from '@/components/FormDialog';
import { STRING_FORMAT_OPTIONS, type RedisLineEditorState } from '../types';
import { formatStringByMode } from '../utils';
interface RedisLineEditorDialogProps {
state: RedisLineEditorState;
readOnlyField?: boolean;
saving?: boolean;
onChange: (state: RedisLineEditorState) => void;
onClose: () => void;
onConfirm: () => void;
onCopy?: (value: string) => void;
}
export function RedisLineEditorDialog({
state,
readOnlyField,
saving,
onChange,
onClose,
onConfirm,
onCopy,
}: RedisLineEditorDialogProps) {
return (
<FormDialog open={state.open} onClose={onClose} title="编辑字段" width="max-w-4xl"
footer={<>
<button onClick={onClose} className="px-4 py-2 bg-[var(--dg-bg-tertiary)] rounded-lg text-sm">取消</button>
<button onClick={onConfirm} disabled={saving} className="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm disabled:opacity-50">保存</button>
</>}>
<div className="space-y-4">
<div>
<label className="text-sm text-[var(--dg-text-muted)]">Field</label>
<input
readOnly={readOnlyField}
value={state.field}
onChange={function (e) { onChange(Object.assign({}, state, { field: e.target.value })); }}
className="mt-1 h-10 w-full rounded-md border border-[var(--dg-border)] bg-[var(--dg-bg-primary)] px-3 font-mono text-sm"
/>
</div>
<div>
<div className="mb-2 flex items-center justify-between gap-3">
<label className="text-sm text-[var(--dg-text-muted)]">Value</label>
<div className="flex items-center gap-2">
<span className="rounded-md border border-blue-400/30 bg-blue-500/10 px-2 py-1 text-xs text-blue-400">
Size: {new TextEncoder().encode(state.value).length}B
</span>
<button onClick={function () { onCopy ? onCopy(state.value) : navigator.clipboard.writeText(state.value); }} className="inline-flex items-center gap-1.5 text-xs text-blue-400 hover:text-blue-300">
<Copy className="h-3.5 w-3.5" />Copy
</button>
<select
value={state.format}
onChange={function (e) { onChange(Object.assign({}, state, { format: e.target.value as RedisLineEditorState['format'] })); }}
className="h-8 w-44 rounded-md border border-[var(--dg-border)] bg-[var(--dg-bg-primary)] px-2 text-xs text-[var(--dg-text-secondary)]"
>
{STRING_FORMAT_OPTIONS.map(function (format) {
return <option key={format} value={format}>{format}</option>;
})}
</select>
</div>
</div>
<textarea
value={state.value}
onChange={function (e) { onChange(Object.assign({}, state, { value: e.target.value })); }}
spellCheck={false}
className="min-h-[160px] w-full resize-y rounded-lg border border-[var(--dg-border)] bg-[var(--dg-bg-primary)] p-3 font-mono text-xs leading-relaxed outline-none focus:border-[var(--dg-blue)]"
/>
<pre className="mt-2 max-h-72 overflow-auto whitespace-pre-wrap break-all rounded-lg border border-[var(--dg-border)] bg-[var(--dg-bg-primary)] p-3 font-mono text-xs leading-relaxed text-[var(--dg-text-secondary)]">
{formatStringByMode(state.value, state.format)}
</pre>
</div>
</div>
</FormDialog>
);
}