| 60 | 60 | | type PipelineStage, |
| 61 | 61 | | PIPELINE, |
| 62 | 62 | | TIME, |
| 63 | + | actorIds, |
| 63 | 64 | | ageBuckets, |
| 64 | 65 | | eventItem, |
| 65 | 66 | | firstPassRate, |
| 66 | 67 | | groupActivity, |
| 68 | + | nameActor, |
| 67 | 69 | | passRate, |
| 68 | 70 | | pipelineStage, |
| 69 | 71 | | queuedNumbers, |
| ⋯ |
| 87 | 89 | | } from "../../lib/project-kind"; |
| 88 | 90 | | import { AboutEditor, KindMenu, LinkList } from "../../components/project-about"; |
| 89 | 91 | | import { DocsHead, ElsewhereHead, type ExternalDeployment, OtherHead, WhereItRuns } from "../../components/project-head"; |
| 90 | | − | import { actions, agents, deployments, events as eventLog, packages, projects, repos, work } from "../../lib/services.server"; |
| 92 | + | import { actions, agents, deployments, events as eventLog, identity, packages, projects, repos, work } from "../../lib/services.server"; |
| 91 | 93 | | import { madeByG1t } from "../../lib/opened-by"; |
| 92 | 94 | | import { assertSameOrigin, getViewer, requireUser } from "../../lib/session.server"; |
| 93 | 95 | | import { accessTo, countsFor, refusal, repoFor } from "../../lib/access.server"; |
| ⋯ |
| 323 | 325 | | |
| 324 | 326 | | // --- Activity and health ------------------------------------------------------- |
| 325 | 327 | | const eventList: G1tEvent[] = recent ?? []; |
| 326 | | − | const items = eventList |
| 328 | + | const logged = eventList |
| 327 | 329 | | .map((event) => eventItem(event, path)) |
| 328 | 330 | | .filter((item): item is ActivityItem => item != null); |
| 331 | + | // The log names people by account id: their usernames, in one lookup. |
| 332 | + | const ids = actorIds(logged.map((item) => item.actor)); |
| 333 | + | const names = ids.length > 0 ? await soft(identity.usernames(ids)) : {}; |
| 334 | + | const items = logged.map((item) => ({ ...item, actor: nameActor(item.actor, names) })); |
| 329 | 335 | | const checkEvents = eventList.flatMap((event) => |
| 330 | 336 | | event.type === "checks.completed" ? [{ repo: "", number: event.data.number, at: Date.parse(event.time), passed: event.data.status === "passed" }] : [], |
| 331 | 337 | | ); |