Keep the org chart inside the page it is printed on

Six divisions, each with its departments beside it, ran off the edge of
the sheet. The cause was structural, not cosmetic: every level spread
horizontally, so width multiplied with depth. Six divisions times three
departments is eighteen boxes across a landscape A4 — about two
millimetres each, if they had fitted at all, which they did not. They
overlapped and were clipped at the margin.

Now only one level spreads sideways. The divisions stand in a row and
everything below them hangs lengthwise off a vertical line, so width is
the number of divisions and nothing else. Depth costs height instead,
and on a landscape page height is what there is to spare.

What still overhangs is scaled down as a whole. The sheet in the preview
now carries the print area's exact dimensions rather than growing with
its contents, so the fit is measured against the real page: what you see
is what the printer gets. If a sheet has to shrink below 55% to fit, it
says so and points at A3, instead of quietly producing something nobody
can read.

With names switched on, each department gets its own sheet — a whole
division with every name was never going to be legible on one page — and
long name lists set in two columns so the box grows sideways rather than
pushing the scale down.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 12:40:31 +02:00
parent 3151f32404
commit f14f1cb8df
2 changed files with 342 additions and 138 deletions

View File

@@ -122,14 +122,27 @@ describe("PrintChart", () => {
renderChart();
await zurVorschau(user);
// Der Bereichsname steht auf der Seite zweimal — in der Kopfzeile und im
// Wurzelkasten des Baums. Geprüft wird der Baum.
const baum = blaetter()[1].querySelector<HTMLElement>("ul.baum")!;
const fertigung = within(baum).getByText("Fertigung");
const bereichsKnoten = within(baum).getByText("Produktion").closest("li")!;
expect(bereichsKnoten.contains(fertigung)).toBe(true);
// Und das Team wiederum unter der Abteilung.
expect(fertigung.closest("li")!.contains(within(baum).getByText("Schicht A"))).toBe(true);
// Die Abteilungen hängen in einer Reihe unter dem Bereich …
const seite = blaetter()[1];
const reihe = seite.querySelector<HTMLElement>("ul.reihe")!;
const fertigung = within(reihe).getByText("Fertigung");
// … und das Team längs unter seiner Abteilung.
const abteilungsKnoten = fertigung.closest("li")!;
const stapel = abteilungsKnoten.querySelector<HTMLElement>("ul.stapel")!;
expect(within(stapel).getByText("Schicht A")).toBeInTheDocument();
});
it("breitet nur eine Ebene waagrecht aus — der Rest hängt längs", async () => {
const user = userEvent.setup();
renderChart();
await zurVorschau(user);
// Der Grund: zwei waagrechte Ebenen multiplizieren sich in der Breite und
// laufen über den Blattrand. Je Blatt darf es genau eine Reihe geben.
for (const seite of blaetter()) {
expect(seite.querySelectorAll("ul.reihe")).toHaveLength(1);
}
expect(blaetter()[1].querySelectorAll("ul.stapel").length).toBeGreaterThan(0);
});
it("nennt Namen erst bei „mit Personen“", async () => {
@@ -143,6 +156,10 @@ describe("PrintChart", () => {
await user.click(screen.getByRole("button", { name: /mit Personen/ }));
expect(screen.getByText("Test Aigner")).toBeInTheDocument();
expect(screen.getByText(/offen · Disposition/)).toBeInTheDocument();
// Mit Namen bekommt jede Abteilung ihr eigenes Blatt — ein ganzer Bereich
// mit allen Namen wäre auf einem Blatt nicht mehr lesbar.
expect(blaetter()).toHaveLength(3);
expect(screen.getByText("Produktion · Fertigung")).toBeInTheDocument();
});
it("meldet unbesetzte Leitungen statt sie zu verschweigen", async () => {