87 lines
3.1 KiB
TypeScript
87 lines
3.1 KiB
TypeScript
import { HelpText } from './HelpText';
|
|
|
|
const SPECIAL_TARGETS = ['COMPLETE', 'ASK', 'ABORT', 'WAIT_SUBTASKS'];
|
|
|
|
export interface RulesTableProps {
|
|
rules: Array<{ condition: string; next: string }>;
|
|
movementNames: string[];
|
|
onChange: (rules: Array<{ condition: string; next: string }>) => void;
|
|
}
|
|
|
|
export function RulesTable({ rules, movementNames, onChange }: RulesTableProps) {
|
|
const nextOptions = [...movementNames, ...SPECIAL_TARGETS];
|
|
|
|
const updateRule = (index: number, field: 'condition' | 'next', value: string) => {
|
|
const updated = rules.map((r, i) => (i === index ? { ...r, [field]: value } : r));
|
|
onChange(updated);
|
|
};
|
|
|
|
const addRule = () => {
|
|
onChange([...rules, { condition: '', next: movementNames[0] ?? 'COMPLETE' }]);
|
|
};
|
|
|
|
const removeRule = (index: number) => {
|
|
onChange(rules.filter((_, i) => i !== index));
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
<label className="block text-xs font-medium text-slate-600 mb-1">rules</label>
|
|
{rules.length > 0 && (
|
|
<table className="w-full text-sm mb-2">
|
|
<thead>
|
|
<tr className="text-xs text-slate-500">
|
|
<th className="text-left font-medium pb-1 pr-2">condition</th>
|
|
<th className="text-left font-medium pb-1 pr-2 w-44">next</th>
|
|
<th className="w-8" />
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{rules.map((rule, i) => (
|
|
<tr key={i}>
|
|
<td className="pr-2 pb-1">
|
|
<input
|
|
type="text"
|
|
value={rule.condition}
|
|
onChange={(e) => updateRule(i, 'condition', e.target.value)}
|
|
className="w-full px-3 py-1.5 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none"
|
|
placeholder="条件..."
|
|
/>
|
|
</td>
|
|
<td className="pr-2 pb-1">
|
|
<select
|
|
value={rule.next}
|
|
onChange={(e) => updateRule(i, 'next', e.target.value)}
|
|
className="w-full px-3 py-1.5 text-sm border border-slate-300 rounded-lg focus:ring-2 focus:ring-accent-ring focus:border-accent outline-none bg-white"
|
|
>
|
|
{nextOptions.map((opt) => (
|
|
<option key={opt} value={opt}>{opt}</option>
|
|
))}
|
|
</select>
|
|
</td>
|
|
<td className="pb-1">
|
|
<button
|
|
type="button"
|
|
onClick={() => removeRule(i)}
|
|
className="text-slate-400 hover:text-red-500 text-sm px-1"
|
|
>
|
|
×
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
)}
|
|
<button
|
|
type="button"
|
|
onClick={addRule}
|
|
className="text-xs text-blue-600 hover:text-blue-700"
|
|
>
|
|
+ Add Rule
|
|
</button>
|
|
<HelpText>LLM が transition ツールで遷移先を選ぶ際の条件です</HelpText>
|
|
</div>
|
|
);
|
|
}
|