({
project,
projectId,
projectIsLoading,
}: {
project?: Project
projectId: string
projectIsLoading: boolean
})
| 545 | } |
| 546 | |
| 547 | export function ProjectHooksSection({ |
| 548 | project, |
| 549 | projectId, |
| 550 | projectIsLoading, |
| 551 | }: { |
| 552 | project?: Project |
| 553 | projectId: string |
| 554 | projectIsLoading: boolean |
| 555 | }) { |
| 556 | const queryClient = useQueryClient() |
| 557 | const runsQuery = useProjectHookRunsQuery(projectId) |
| 558 | const agentsQuery = useAgentsQuery() |
| 559 | const agentsList = agentsQuery.data?.items ?? [] |
| 560 | const agentOptions = useMemo<ComboSelectOption[]>( |
| 561 | () => |
| 562 | agentsList.map((agent) => ({ |
| 563 | value: agent.id, |
| 564 | label: agent.name, |
| 565 | description: `${agent.executor_type} · ${agent.id}`, |
| 566 | })), |
| 567 | [agentsList], |
| 568 | ) |
| 569 | const agentNames = useMemo(() => { |
| 570 | const map = new Map<string, string>() |
| 571 | for (const agent of agentsList) map.set(agent.id, agent.name) |
| 572 | return map |
| 573 | }, [agentsList]) |
| 574 | const rules = project?.project_hooks ?? [] |
| 575 | const runs = useMemo( |
| 576 | () => runsQuery.data?.pages.flatMap((page) => page.items) ?? [], |
| 577 | [runsQuery.data], |
| 578 | ) |
| 579 | const runStats = useMemo(() => computeRunStats(runs), [runs]) |
| 580 | |
| 581 | const [dialogMode, setDialogMode] = useState<DialogMode | null>(null) |
| 582 | const [form, setForm] = useState<ProjectHookRuleFormState>(() => emptyRuleForm()) |
| 583 | const [formError, setFormError] = useState('') |
| 584 | const [sectionError, setSectionError] = useState('') |
| 585 | const [detailIndex, setDetailIndex] = useState<number | null>(null) |
| 586 | const [showAllRuns, setShowAllRuns] = useState(false) |
| 587 | |
| 588 | const selectedRule = detailIndex !== null ? rules[detailIndex] : null |
| 589 | const selectedRuleRuns = useMemo( |
| 590 | () => (selectedRule ? runs.filter((run) => run.rule_id === selectedRule.id) : []), |
| 591 | [runs, selectedRule], |
| 592 | ) |
| 593 | |
| 594 | const saveRules = useMutation({ |
| 595 | mutationFn: (nextRules: ProjectHookRuleWire[]) => |
| 596 | apiFetch<Project>(`/projects/${projectId}`, { |
| 597 | method: 'PATCH', |
| 598 | body: JSON.stringify({ project_hooks: nextRules }), |
| 599 | }), |
| 600 | onSuccess: (updatedProject) => { |
| 601 | void queryClient.invalidateQueries({ queryKey: qk.project(updatedProject.id) }) |
| 602 | void queryClient.invalidateQueries({ queryKey: qk.projects }) |
| 603 | }, |
| 604 | }) |
nothing calls this directly
no test coverage detected