feat(timeline): offer both readings of a board with the future on it
"In their own group" is the shape of a patch — what is on now, and what is queued behind it. "Mixed in" is the question a Gantt chart exists for: what runs out first, whether or not it has opened. On real data that is not a cosmetic difference — mixed, five events currently running sort below an Arknights rerun that has not started, because it closes before they do. Which is why it is a pair of pills and not a checkbox: neither answer is the absence of the other, and "mixed in" is a different order rather than the heading switched off. It sits under the row that puts the future on the board at all, and only while that row is ticked — a choice about arranging unstarted events is unanswerable with none of them on screen. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
9dde82801a
commit
3db93a1ccf
+45
-1
@@ -262,11 +262,23 @@ describe("Timeline stacking", () => {
|
||||
group={group}
|
||||
onGroup={() => {}}
|
||||
showUpcoming={false}
|
||||
splitUpcoming
|
||||
onOpen={() => {}}
|
||||
isDone={() => false}
|
||||
/>,
|
||||
);
|
||||
|
||||
test("mixed in, lane mode re-sorts rather than keeping the block", () => {
|
||||
// The one place `timelineLanes` is allowed to reorder a lane. Leaving the
|
||||
// given order alone would draw exactly the block it was told not to, minus
|
||||
// the heading that explained it.
|
||||
// Given live-first, as every sort this board can be handed produces. B has
|
||||
// the nearer end (48h against 100h) but has not opened yet.
|
||||
const given = [row("A", "hsr", 100), upcoming("B", "hsr", 24, 24)];
|
||||
expect(timelineLanes(given, "game", true)[0]?.rows[0]?.event.title).toBe("A");
|
||||
expect(timelineLanes(given, "game", false)[0]?.rows[0]?.event.title).toBe("B");
|
||||
});
|
||||
|
||||
test("both stackings plot every event", () => {
|
||||
for (const group of ["game", "ending"] as const) {
|
||||
const html = board(group);
|
||||
@@ -306,7 +318,12 @@ describe("Timeline: events that have not started", () => {
|
||||
upcoming("Long Way Round", "wuwa", 30 * 24),
|
||||
];
|
||||
|
||||
const board = (showUpcoming: boolean, all = rows, group: "game" | "ending" = "ending") =>
|
||||
const board = (
|
||||
showUpcoming: boolean,
|
||||
all = rows,
|
||||
group: "game" | "ending" = "ending",
|
||||
splitUpcoming = true,
|
||||
) =>
|
||||
render(
|
||||
<Timeline
|
||||
rows={all}
|
||||
@@ -316,6 +333,7 @@ describe("Timeline: events that have not started", () => {
|
||||
group={group}
|
||||
onGroup={() => {}}
|
||||
showUpcoming={showUpcoming}
|
||||
splitUpcoming={splitUpcoming}
|
||||
onOpen={() => {}}
|
||||
isDone={() => false}
|
||||
/>,
|
||||
@@ -382,6 +400,32 @@ describe("Timeline: events that have not started", () => {
|
||||
expect(html.split("Not started yet")).toHaveLength(4);
|
||||
});
|
||||
|
||||
test("mixed in, there is no block to head and no heading", () => {
|
||||
// Not the heading switched off: the rows are one deadline queue, so a
|
||||
// label would be pointing at the middle of it.
|
||||
const html = board(true, rows, "ending", false);
|
||||
expect(html).toContain("Frost Parade");
|
||||
expect(html).not.toContain("Not started yet");
|
||||
});
|
||||
|
||||
test("mixed in, a nearer deadline wins whether or not it has opened", () => {
|
||||
// The whole point of the option, and the one thing the split order can
|
||||
// never show. Frost Parade opens in 3 days and closes 10 days after that;
|
||||
// Closing Ceremony is running now until 100 hours from now — so it is
|
||||
// still the nearer deadline, and Frost Parade sits under it rather than
|
||||
// behind every running row.
|
||||
const near = upcoming("Quick Turnaround", "hsr", 24, 24);
|
||||
const html = board(true, [row("Closing Ceremony", "genshin", 100), near], "ending", false);
|
||||
expect(html.indexOf("Quick Turnaround")).toBeLessThan(
|
||||
html.indexOf("Closing Ceremony"),
|
||||
);
|
||||
// Split, the same two rows go the other way round.
|
||||
const kept = board(true, [row("Closing Ceremony", "genshin", 100), near], "ending", true);
|
||||
expect(kept.indexOf("Closing Ceremony")).toBeLessThan(
|
||||
kept.indexOf("Quick Turnaround"),
|
||||
);
|
||||
});
|
||||
|
||||
test("no heading where nothing is waiting", () => {
|
||||
// A label with nothing under it is a section that does not exist.
|
||||
expect(board(true, [row("Closing Ceremony", "genshin", 100)])).not.toContain(
|
||||
|
||||
Reference in New Issue
Block a user