import { useMemo } from "react"; import { useSearchParams } from "react-router"; import { Checkbox } from "../../../ui/index.ts"; import type { FeedResult, FeedSource, FeedSourceInput } from "../../types.ts"; import { useChanges } from "../api/queries.ts"; import type { ChangeKind } from "../api/types.ts"; import { groupByIssue, KINDS, kindsParam, parseKinds } from "./events.ts"; import { FeedGroup } from "./FeedGroup.tsx"; import "./feed.css"; // виды событий — настройка источника, хранится в адресе (`kinds=`); пустой набор — явное «none», иначе адрес вернул бы умолчание function Kinds() { const [params, setParams] = useSearchParams(); const kinds = useMemo(() => parseKinds(params.get("kinds")), [params]); const toggle = (k: ChangeKind, on: boolean) => { const next = on ? [...kinds, k] : kinds.filter((x) => x !== k); const value = next.length ? kindsParam(next) : "none"; setParams((p) => { const n = new URLSearchParams(p); if (value) n.set("kinds", value); else n.delete("kinds"); return n; }); }; return (
{KINDS.map((k) => ( toggle(k.value, e.currentTarget.checked)} /> ))}
); } const EMPTY: FeedResult = { groups: [], count: 0, window: null, pending: false, error: null, truncated: false, notice: null }; function useJiraFeed(input: FeedSourceInput): FeedResult { const [params] = useSearchParams(); const kinds = useMemo(() => parseKinds(params.get("kinds")), [params]); // границы считает запрос в момент выполнения (C-1): ключ кэша — проект, период и виды const q = useChanges({ project: input.project.label, period: input.period, kinds: kinds.join(",") }, input.bounds, input.enabled && kinds.length > 0); const data = input.enabled && kinds.length > 0 ? q.data : undefined; const updatedAt = q.dataUpdatedAt; const groups = useMemo(() => { const now = new Date(updatedAt || Date.now()); // «текущие сутки» для времени событий — на момент ответа return groupByIssue(data?.changes ?? []).map((g) => ({ key: g.key, at: g.events[0]?.at ?? "", node: , })); }, [data, updatedAt]); if (!input.enabled) return EMPTY; if (!kinds.length) return { ...EMPTY, notice: "выберите хотя бы один вид" }; return { groups, count: data?.changes.length ?? 0, window: data ? { since: data.since, until: data.until } : null, pending: q.isPending, truncated: !!data?.truncated, error: q.isError ? { message: (q.error as Error).message, retry: () => void q.refetch() } : null, notice: null, }; } export const jiraFeed: FeedSource = { available: () => true, useFeed: useJiraFeed, Controls: Kinds };