Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/app/src/features/projects/detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState } from "react";
import { Link, useParams } from "@tanstack/react-router";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api } from "factorize-api-client";
import { Button, Input, Label, Page, ResourceHeader, Textarea } from "../../shared/ui";
import { Breadcrumb, Button, Input, Label, Page, ResourceHeader, Textarea } from "../../shared/ui";
import { Dialog } from "../../shared/dialog";
import { messageOf } from "../auth/session";
import { projectQuery, projectsQuery } from "./queries";
Expand Down Expand Up @@ -40,5 +40,5 @@ export function ProjectDetail() {
setValidationError("");
setEditing(true);
};
return <Page className="max-w-6xl"><ResourceHeader type="Project" title={project.data?.name ?? "Project"} description={project.data?.description}><div className="flex flex-wrap gap-2">{project.data && <><Button onClick={openEditor}>Edit</Button><Link to="/jobs/new" search={{ projectId }}><Button variant="primary">Create job</Button></Link></>}</div></ResourceHeader>{project.isPending && <p role="status">Loading project…</p>}{project.error && <p role="alert">{project.error.message}</p>}{project.data&&<><JobsTable projectId={projectId} />{editing&&<Dialog title="Edit project" close={() => { if (!edit.isPending) setEditing(false); }}><form className="space-y-5" onSubmit={event => { event.preventDefault(); edit.mutate(); }}><Label>Name<Input required maxLength={120} value={name} onChange={event => setName(event.target.value)} /></Label><Label>Description<Textarea maxLength={2000} value={description} onChange={event => setDescription(event.target.value)} /></Label>{validationError&&<p role="alert">{validationError}</p>}<div className="flex justify-end gap-2"><Button type="button" onClick={() => setEditing(false)} disabled={edit.isPending}>Cancel</Button><Button type="submit" variant="primary" disabled={edit.isPending}>{edit.isPending ? "Saving…" : "Save changes"}</Button></div></form></Dialog>}</>}</Page>;
return <Page className="max-w-6xl"><Breadcrumb><Link to="/projects">Projects</Link></Breadcrumb><ResourceHeader type="Project" title={project.data?.name ?? "Project"} description={project.data?.description}><div className="flex flex-wrap gap-2">{project.data && <><Button onClick={openEditor}>Edit</Button><Link to="/jobs/new" search={{ projectId }}><Button variant="primary">Create job</Button></Link></>}</div></ResourceHeader>{project.isPending && <p role="status">Loading project…</p>}{project.error && <p role="alert">{project.error.message}</p>}{project.data&&<><JobsTable projectId={projectId} />{editing&&<Dialog title="Edit project" close={() => { if (!edit.isPending) setEditing(false); }}><form className="space-y-5" onSubmit={event => { event.preventDefault(); edit.mutate(); }}><Label>Name<Input required maxLength={120} value={name} onChange={event => setName(event.target.value)} /></Label><Label>Description<Textarea maxLength={2000} value={description} onChange={event => setDescription(event.target.value)} /></Label>{validationError&&<p role="alert">{validationError}</p>}<div className="flex justify-end gap-2"><Button type="button" onClick={() => setEditing(false)} disabled={edit.isPending}>Cancel</Button><Button type="submit" variant="primary" disabled={edit.isPending}>{edit.isPending ? "Saving…" : "Save changes"}</Button></div></form></Dialog>}</>}</Page>;
}
5 changes: 3 additions & 2 deletions packages/app/test/jobs.browser.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ test("project details can rename and describe a project", async () => {
assert.equal(saved.length, 1);
await context.close();
});
test("project and job detail pages omit redundant collection labels", async () => {
test("project and job detail pages use the appropriate breadcrumbs", async () => {
const { page, context } = await contextFor({ viewport: { width: 1280, height: 844 } });
await page.route("**/api/v1/projects", route => route.fulfill({ json: [{ id: projectId, name: "Release project", description: "Project jobs", jobCount: 1 }] }));
await page.route(`**/api/v1/jobs/${jobId}`, route => route.fulfill({ json: { ...summary, promptTemplate: "Template", executionConfigId: "local", triggers: [] } }));
Expand All @@ -88,7 +88,8 @@ test("project and job detail pages omit redundant collection labels", async () =
assert.equal(await page.getByRole("navigation", { name: "Breadcrumb" }).count(), 1);
await page.goto(origin + `/projects/${projectId}`);
await page.getByRole("heading", { name: "Release project", exact: true }).waitFor();
assert.equal(await page.getByRole("navigation", { name: "Breadcrumb" }).count(), 0);
const projectBreadcrumb = page.getByRole("navigation", { name: "Breadcrumb" });
assert.deepEqual(await projectBreadcrumb.getByRole("link").allTextContents(), ["Projects"]);
assert.equal(await page.getByText("Project", { exact: true }).count(), 1);
await page.goto(origin + `/jobs/${jobId}`);
await page.getByRole("heading", { name: "Review builds", exact: true }).waitFor();
Expand Down
Loading