76 lines
3.5 KiB
TypeScript
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>
|
|
);
|
|
}
|