Public: anyone can read this; the crew can change it.

The clock says how many people need a nudge and links to People #236

opened this

Check · Review · Land · Live — Its check is red. Next: builder, its check is red.

Ready to land

mason/deal-clock:mason/233-the-clock-says-how-many-people-need-a-nu → main 1 commit fork

  • Ready to merge — no conflicts with main. 1 commit will land on main.

    Check faileddeploy 268b001

    Website spec: 3 findings, 3 the edge owns (report only)
    • / no <link rel="canonical"> — canonical
    • / missing og:image — open-graph
    • / http://127.0.0.1:44713/tokens.css?v=2d14bc8d: a 2410-byte body was sent without br or gzip though Accept-Encoding: br, gzip — https://specification.website/ (the edge owns this)
    • / http://127.0.0.1:44713/static/app.css?v=02bee2fc: a 22142-byte body was sent without br or gzip though Accept-Encoding: br, gzip — https://specification.website/ (the edge owns this)
    • / no Cross-Origin-Opener-Policy — coop (the edge owns this)
    • / no ETag on the HTML — caching
    You need write access to merge.

Review

Sign in to review this change.
4 files changed +35 −0
docs/design/areas/clock.md +2
@@ -7,3 +7,5 @@ New classes:
77 - `.progress` — the paragraph that holds both at the top of a deal's page.
88
99 - `.closing-clash` — one amber line (`--color-soon`) under a closing on This week, the print sheet and the deal page: "Also closing at 2:30 pm: 2210 Juniper Court", the address linked to its deal.
10
11 - `.clock-nudge` — one amber line (`--color-soon`) under the clock's heading, linking to People: "2 people owe a date soon and have heard nothing from you in a week". Absent when nobody needs a nudge.
src/lastsent.test.ts +18
@@ -48,3 +48,21 @@ test("the sample data on a fresh boot flags at least one person on /people, esca
4848 expect(html).toContain('class="person-nudge"');
4949 expect(html).toContain("Owes ");
5050 });
51
52 test("the clock counts the people to nudge, links to People, and says nothing when there are none", async () => {
53 const { refresh } = await import("./sample.ts");
54 const { clock } = await import("./pages/clock.ts");
55 const fresh = openDb(mkdtempSync(join(tmpdir(), "app-clocknudge-")));
56 refresh(fresh);
57 const l = listDeals(fresh, alice);
58 if (!l.ok) throw new Error(l.message);
59 const on = today(DEFAULT_ZONE);
60 const n = people(l.value, on).filter((p) => p.nudge !== null).length;
61 expect(n).toBeGreaterThan(0);
62 const html = clock({ who: alice, deals: l.value, on });
63 expect(html).toContain(n === 1 ? "1 person owes a date soon and has heard nothing from you in a week" : `${n} people owe a date soon and have heard nothing from you in a week`);
64 expect(html).toContain('<a href="/people">');
65 // Far in the future nothing is due within three days of today.
66 expect(clock({ who: alice, deals: l.value, on: "2099-01-01" })).not.toContain("clock-nudge");
67 expect(clock({ who: alice, deals: [], on })).not.toContain("clock-nudge");
68 });
src/pages/clock.ts +8
@@ -25,6 +25,7 @@ import { memoizer, print } from "../memo.ts";
2525 import { bookLine, tally } from "../book.ts";
2626 import { dollars } from "../money.ts";
2727 import { progressLine } from "./progress.ts";
28 import { people } from "../people.ts";
2829
2930 /** The days the clock shows: a week behind today (further, if something open is older), to a few days past the last closing. */
3031 export function span(deals: readonly DealView[], on: string): { start: string; days: number } {
@@ -230,6 +231,12 @@ function render(input: {
230231 <form method="post" action="/samples/restore"><button class="button">Yes, restore them</button></form>
231232 </details>
232233 </section>`;
234 // The same rule as the People page, counted for the agent's today.
235 const owing = who.role === "anon" ? 0 : people(input.deals, on).filter((p) => p.nudge !== null).length;
236 const nudgeNote =
237 owing === 0
238 ? ""
239 : `<p class="clock-nudge"><a href="/people">${owing} ${owing === 1 ? "person owes" : "people owe"} a date soon and ${owing === 1 ? "has" : "have"} heard nothing from you in a week</a></p>`;
233240 const body = `<section class="intro">
234241 <div>
235242 <h1>The clock</h1>
@@ -238,6 +245,7 @@ function render(input: {
238245 </div>
239246 ${who.role === "anon" ? "" : `<span class="actions"><a class="button button-quiet" href="/deals/ics">Add all to calendar</a> <a class="button button-quiet" href="/deals/csv" download>Download spreadsheet</a> <a class="button" href="/deals/new">New deal</a></span>`}
240247 </section>
248 ${nudgeNote}
241249 <form class="find" method="get" action="/" role="search">
242250 <label for="find-q">Find a deal</label>
243251 <input id="find-q" class="input" type="search" name="q" value="${escape(q)}" maxlength="100" placeholder="Address, client or party" autocomplete="off">
static/app.css +7
@@ -936,6 +936,13 @@ a.marker {
936936 margin: var(--space-2) 0;
937937 color: var(--color-soon);
938938 }
939 .clock-nudge {
940 margin: var(--space-2) 0;
941 color: var(--color-soon);
942 }
943 .clock-nudge a {
944 color: inherit;
945 }
939946 .closing-clash a {
940947 color: inherit;
941948 }

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs