Gates / frontend (push) Successful in 1m32s
Gates / test (push) Successful in 1m54s
Gates / package (push) Successful in 5m28s
Gates / container (push) Successful in 14s
Gates / test-aarch64 (push) Failing after 3h10m0s
CI / gates (push) Failing after 3h11m55s
84 lines
2.2 KiB
TypeScript
84 lines
2.2 KiB
TypeScript
import { useQuery } from "@tanstack/react-query";
|
|
import { Link, useParams, useSearch } from "@tanstack/react-router";
|
|
import * as stylex from "@stylexjs/stylex";
|
|
import InlineError from "@/lib/InlineError";
|
|
import { queryDetailQuery } from "@/lib/queries";
|
|
import type { QueryDetail } from "@/lib/types";
|
|
import { styles as shared } from "@/ui/styles";
|
|
import { colors } from "@/ui/tokens.stylex";
|
|
import ProvenanceDetail from "./ProvenanceDetail";
|
|
import RelatedActions from "./RelatedActions";
|
|
import type { ActivitySearch } from "./search";
|
|
|
|
const styles = stylex.create({
|
|
back: {
|
|
fontSize: "0.875rem",
|
|
lineHeight: "1.25rem",
|
|
color: colors.primaryOnSurface,
|
|
textDecorationLine: "none",
|
|
},
|
|
loading: {
|
|
marginTop: "1rem",
|
|
color: colors.textMuted,
|
|
},
|
|
});
|
|
|
|
/**
|
|
* The way back to the investigation, not to a bare list. The originating
|
|
* Activity search rides in this route's own search, so the reader returns to
|
|
* the mode, the filters and the absolute window they left — a plain `/activity`
|
|
* would silently widen the range they had chosen.
|
|
*/
|
|
function BackLink({ origin }: { origin: ActivitySearch }) {
|
|
return (
|
|
<Link to="/activity" search={origin} {...stylex.props(styles.back, shared.focusRing)}>
|
|
← Activity
|
|
</Link>
|
|
);
|
|
}
|
|
|
|
export default function ActivityDetailPage() {
|
|
const { id } = useParams({ from: "/shell/activity/queries/$id" });
|
|
const origin = useSearch({ from: "/shell/activity/queries/$id" });
|
|
const rowId = Number(id);
|
|
const { data, error, isPending, refetch } = useQuery(queryDetailQuery(rowId));
|
|
|
|
if (isPending) {
|
|
return (
|
|
<p {...stylex.props(styles.loading, shared.pulse)} role="status">
|
|
Loading query…
|
|
</p>
|
|
);
|
|
}
|
|
if (data === undefined) {
|
|
return (
|
|
<section>
|
|
<BackLink origin={origin} />
|
|
<InlineError error={error} onRetry={() => void refetch()} />
|
|
</section>
|
|
);
|
|
}
|
|
|
|
const detail: QueryDetail = data;
|
|
const { domain, client, time } = detail.request;
|
|
|
|
return (
|
|
<section>
|
|
<BackLink origin={origin} />
|
|
<ProvenanceDetail
|
|
provenance={detail}
|
|
persistedId={detail.id}
|
|
relatedActions={
|
|
<RelatedActions
|
|
domain={domain}
|
|
client={client}
|
|
ts={time}
|
|
origin={origin}
|
|
blocked={detail.policy.action === "block"}
|
|
/>
|
|
}
|
|
/>
|
|
</section>
|
|
);
|
|
}
|