Skip to the content

Capsid menu

app/routes/workspace.runs.tsx

65 lines and 6 functions in DrDustinEdwards/dustinedwards-info, at commit 1590ba4 on 2026-10-24. This file on GitHub.

Functions

The functions of workspace.runs.tsx
FunctionLinesComplexityCoveredCRAPMutation
meta14 to 161No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
requireRecorder20 to 222No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
loader24 to 281No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
action31 to 373No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
LabRuns39 to 724No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code
<anonymous:52>52 to 644No data: no coverage report in this mapNo data: no coverage report in this mapNo data: no mutants in this code

Imports

It imports app/components/lab/lab-ui.tsx, app/components/lab/run-form.tsx, app/lab/actor.server.ts, app/lab/runs.server.ts, app/lab/titles.mjs, app/lib/context.ts. No module of this repo imports it.

Source

import { Link, data, redirect } from "react-router";
import { can } from "@dustinedwards/site-runtime/members";
import { Panel } from "capsomer/react/panel";

import { PageHead } from "capsomer/react/page-head";
import { LabTable, Result } from "~/components/lab/lab-ui";
import { RunForm } from "~/components/lab/run-form";
import { labActorContext } from "~/lab/actor.server";
import { recordRun, runsPage } from "~/lab/runs.server";
import { PERMISSION } from "~/lab/titles.mjs";
import { getEnv } from "~/lib/context";
import type { Route } from "./+types/workspace.runs";

export function meta() {
  return [{ title: "Runs ยท Lab" }, { name: "robots", content: "noindex" }];
}

const PRIVATE = { "cache-control": "private, no-store" };

function requireRecorder(actor: Parameters<typeof can>[0]) {
  if (!can(actor, PERMISSION.recordRun)) throw data("Not found.", { status: 404, headers: PRIVATE });
}

export async function loader({ context }: Route.LoaderArgs) {
  const actor = context.get(labActorContext);
  requireRecorder(actor);
  return data(await runsPage(getEnv(context), actor), { headers: PRIVATE });
}

/** A recorded run opens on its own page; a refusal comes back here with its words. */
export async function action({ context, request }: Route.ActionArgs) {
  const actor = context.get(labActorContext);
  requireRecorder(actor);
  const result = await recordRun(getEnv(context), actor, await request.formData(), Date.now());
  if (result.ok && result.runId) throw redirect(`/lab/runs/${result.runId}`, { headers: PRIVATE });
  return data(result, { headers: PRIVATE });
}

export default function LabRuns({ loaderData, actionData }: Route.ComponentProps) {
  const { runs, procedures, lots, all, lotRows } = loaderData;
  return (
    <>
      <PageHead
        title="Runs"
        lead={`${all ? "Every run recorded in the lab" : "The runs you recorded"}, with the lots each used. A saved run is never changed: a correction is a new run that names it.`}
      />
      <Result result={actionData} />
      {runs.length === 0 ? (
        <p className="cap-muted">No runs recorded yet.</p>
      ) : (
        <LabTable label="Runs" head={["Run", "Protocol", "Day", "Outcome", ...(all ? ["By"] : [])]}>
          {runs.map((r) => (
            <tr key={r.id}>
              <th scope="row">
                <Link to={`/lab/runs/${r.id}`}>Run {r.id}</Link>
                {r.replaced_by ? <span className="cap-muted">, corrected by run {r.replaced_by}</span> : null}
                {r.replaces_run_id ? <span className="cap-muted">, corrects run {r.replaces_run_id}</span> : null}
              </th>
              <td>{r.title}</td>
              <td>{r.run_on}</td>
              <td>{r.outcome}</td>
              {all ? <td>{r.actor}</td> : null}
            </tr>
          ))}
        </LabTable>
      )}
      <Panel title="Record a run">
        <RunForm procedures={procedures} lots={lots} lotRows={lotRows} />
      </Panel>
    </>
  );
}