prototype: address owner review round 1 (#122)
- logo: restore the mirrored right half — the inline mark was missing the <use> mirror, rendering a lopsided single-page glyph - verdict line: one uniform 22px line; counts inherit the display face - font sizes up across the board (table 10->11px, titles 16/17->17/18px, stat figures 17->19px, sections 10->11px) - overview Sites table: state column widens and never wraps - topbar: Library + Log out grouped right, matching the original chrome - Lanes: sidecar line moved under the Poll lanes explanation - Resume renders inside the same pausebar slot as Pause - lane problems (refusing / no browser / not checking) render danger red; a deliberate pause stays patina - series notes: chips capped at two with a +N tail instead of stacking - pending 'requested N ago' now renders once, in the action cell only
This commit is contained in:
@@ -163,6 +163,12 @@ body[data-variant="B"] .sheet, body[data-variant="C"] .sheet {
|
|||||||
padding: 22px 20px 14px;
|
padding: 22px 20px 14px;
|
||||||
}
|
}
|
||||||
.topbar form { margin: 0; }
|
.topbar form { margin: 0; }
|
||||||
|
.topbar-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 18px;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.ghost {
|
.ghost {
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -210,7 +216,7 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.sec {
|
.sec {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 18px 0 8px;
|
padding: 18px 0 8px;
|
||||||
font: 500 10px/1 var(--font-mono);
|
font: 500 11px/1 var(--font-mono);
|
||||||
letter-spacing: .2em;
|
letter-spacing: .2em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -230,12 +236,8 @@ main.page { padding: 0 20px 40px; }
|
|||||||
color: var(--paper);
|
color: var(--paper);
|
||||||
}
|
}
|
||||||
.verdict .attn { color: var(--patina); }
|
.verdict .attn { color: var(--patina); }
|
||||||
.verdict .counts {
|
.verdict .counts { font: inherit; color: var(--mute); }
|
||||||
font: 500 11px/1.5 var(--font-mono);
|
.verdict .counts b { color: var(--paper-dim); font-weight: 400; }
|
||||||
letter-spacing: .08em;
|
|
||||||
color: var(--mute);
|
|
||||||
}
|
|
||||||
.verdict .counts b { color: var(--paper-dim); font-weight: 600; }
|
|
||||||
|
|
||||||
/* ---- stats block: label / figure rows, every figure a link but a zero ---- */
|
/* ---- stats block: label / figure rows, every figure a link but a zero ---- */
|
||||||
.stats { margin: 4px 0 0; }
|
.stats { margin: 4px 0 0; }
|
||||||
@@ -248,13 +250,13 @@ main.page { padding: 0 20px 40px; }
|
|||||||
border-bottom: 1px solid var(--rule);
|
border-bottom: 1px solid var(--rule);
|
||||||
}
|
}
|
||||||
.stat .lbl {
|
.stat .lbl {
|
||||||
font: 500 10px/1 var(--font-mono);
|
font: 500 11px/1 var(--font-mono);
|
||||||
letter-spacing: .14em;
|
letter-spacing: .14em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
}
|
}
|
||||||
.stat .fig {
|
.stat .fig {
|
||||||
font: 400 17px/1 var(--font-display);
|
font: 400 19px/1 var(--font-display);
|
||||||
color: var(--paper);
|
color: var(--paper);
|
||||||
}
|
}
|
||||||
.stat a.fig:hover { color: var(--patina); }
|
.stat a.fig:hover { color: var(--patina); }
|
||||||
@@ -262,15 +264,18 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.stat a.fig:hover { border-bottom-color: var(--patina); }
|
.stat a.fig:hover { border-bottom-color: var(--patina); }
|
||||||
.stat .fig.zero { color: var(--mute); }
|
.stat .fig.zero { color: var(--mute); }
|
||||||
|
|
||||||
/* ---- marks: patina is the admin accent; never ember, never danger ---- */
|
/* ---- marks: patina is the admin accent; never ember, never danger.
|
||||||
|
A lane in trouble overrides to danger (#122 review); paused stays
|
||||||
|
patina — deliberate, not a problem. ---- */
|
||||||
.mark, .mark-p {
|
.mark, .mark-p {
|
||||||
font: 500 10px/1 var(--font-mono);
|
font: 500 11px/1 var(--font-mono);
|
||||||
letter-spacing: .14em;
|
letter-spacing: .14em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--patina);
|
color: var(--patina);
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
.mark-faint { color: var(--mute-2); }
|
.mark-faint { color: var(--mute-2); }
|
||||||
|
.mark.bad { color: var(--danger); }
|
||||||
|
|
||||||
/* ================= VARIANT A — narrow, prose rows (760px) ================= */
|
/* ================= VARIANT A — narrow, prose rows (760px) ================= */
|
||||||
/* No new tokens. Facts are a meta line under the title, like the reading
|
/* No new tokens. Facts are a meta line under the title, like the reading
|
||||||
@@ -297,7 +302,7 @@ main.page { padding: 0 20px 40px; }
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 3px 10px;
|
gap: 3px 10px;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
font: 500 10px/1.5 var(--font-mono);
|
font: 500 11px/1.5 var(--font-mono);
|
||||||
letter-spacing: .1em;
|
letter-spacing: .1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -309,7 +314,7 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.pst .pst-site { font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
|
.pst .pst-site { font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
|
||||||
.pst .pst-facts {
|
.pst .pst-facts {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
font: 500 10px/1.6 var(--font-mono);
|
font: 500 11px/1.6 var(--font-mono);
|
||||||
letter-spacing: .1em;
|
letter-spacing: .1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -327,9 +332,9 @@ main.page { padding: 0 20px 40px; }
|
|||||||
border-bottom: 1px solid var(--rule);
|
border-bottom: 1px solid var(--rule);
|
||||||
}
|
}
|
||||||
.lrow .lane-site { font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
|
.lrow .lane-site { font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
|
||||||
.lrow.attention .lane-site { color: var(--patina); }
|
.lrow.attention .lane-site { color: var(--danger); }
|
||||||
.lrow .lane-fact {
|
.lrow .lane-fact {
|
||||||
font: 500 10px/1 var(--font-mono);
|
font: 500 11px/1 var(--font-mono);
|
||||||
letter-spacing: .14em;
|
letter-spacing: .14em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -364,7 +369,7 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.tbl .thead span {
|
.tbl .thead span {
|
||||||
padding: 10px 0 8px;
|
padding: 10px 0 8px;
|
||||||
border-bottom: 1px solid var(--rule);
|
border-bottom: 1px solid var(--rule);
|
||||||
font: 500 10px/1 var(--font-mono);
|
font: 500 11px/1 var(--font-mono);
|
||||||
letter-spacing: .14em;
|
letter-spacing: .14em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -373,13 +378,13 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.tbl .trow > * {
|
.tbl .trow > * {
|
||||||
padding: 11px 0;
|
padding: 11px 0;
|
||||||
border-bottom: 1px solid var(--rule);
|
border-bottom: 1px solid var(--rule);
|
||||||
font: 500 10px/1.6 var(--font-mono);
|
font: 500 11px/1.6 var(--font-mono);
|
||||||
letter-spacing: .1em;
|
letter-spacing: .1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
}
|
}
|
||||||
.tbl .trow .c-title {
|
.tbl .trow .c-title {
|
||||||
font: 400 16px/1.3 var(--font-display);
|
font: 400 17px/1.3 var(--font-display);
|
||||||
letter-spacing: 0;
|
letter-spacing: 0;
|
||||||
text-transform: none;
|
text-transform: none;
|
||||||
color: var(--paper);
|
color: var(--paper);
|
||||||
@@ -388,27 +393,30 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.tbl .trow.attention .c-title { color: var(--patina); }
|
.tbl .trow.attention .c-title { color: var(--patina); }
|
||||||
.tbl .trow .c-site { letter-spacing: .04em; }
|
.tbl .trow .c-site { letter-spacing: .04em; }
|
||||||
.tbl .trow .c-ch { color: var(--paper-dim); }
|
.tbl .trow .c-ch { color: var(--paper-dim); }
|
||||||
.tbl .trow .c-note { color: var(--mute-2); }
|
.tbl .trow .c-note { display: flex; flex-wrap: wrap; gap: 2px 8px; color: var(--mute-2); }
|
||||||
.tbl .trow .c-act { text-align: right; }
|
.tbl .trow .c-act { text-align: right; }
|
||||||
.tbl .trow .c-act .ghost { font-size: 10px; }
|
.tbl .trow .c-act .ghost { font-size: 11px; }
|
||||||
.tbl .trow > .confirm-row { grid-column: 1 / -1; }
|
.tbl .trow > .confirm-row { grid-column: 1 / -1; }
|
||||||
.tbl .trow .c-act .ghost:hover { color: var(--patina); border-bottom-color: var(--patina); }
|
.tbl .trow .c-act .ghost:hover { color: var(--patina); border-bottom-color: var(--patina); }
|
||||||
|
|
||||||
/* Landing per-Site table: site + library shape + five outcome sums over 12h. */
|
/* Landing per-Site table: site + library shape + five outcome sums over 12h. */
|
||||||
.tbl.sites { grid-template-columns: 120px 1fr repeat(8, 62px) 120px; }
|
.tbl.sites { grid-template-columns: 120px 1fr repeat(8, 54px) minmax(150px, 1fr); }
|
||||||
.tbl.sites .trow > * { font: 500 10px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
|
.tbl.sites .trow > * { font: 500 11px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
|
||||||
.tbl.sites .c-site { font: 400 17px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
|
.tbl.sites .c-site { font: 400 18px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
|
||||||
.tbl.sites .c-state { color: var(--patina); }
|
.tbl.sites .c-state { color: var(--patina); white-space: nowrap; }
|
||||||
|
.tbl.sites .c-state.bad { color: var(--danger); }
|
||||||
.tbl.sites .c-num { text-align: right; color: var(--paper-dim); }
|
.tbl.sites .c-num { text-align: right; color: var(--paper-dim); }
|
||||||
|
|
||||||
/* Lanes page in B: one aligned row per Lane. */
|
/* Lanes page in B: one aligned row per Lane. */
|
||||||
.tbl.lanes { grid-template-columns: 130px 60px 70px 64px 96px 1fr 190px; }
|
.tbl.lanes { grid-template-columns: 130px 60px 70px 64px 96px 1fr 170px; }
|
||||||
.tbl.lanes .trow > * { font: 500 10px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
|
.tbl.lanes .trow > * { font: 500 11px/1.6 var(--font-mono); letter-spacing: .08em; text-transform: uppercase; color: var(--mute-2); }
|
||||||
.tbl.lanes .c-site { font: 400 17px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
|
.tbl.lanes .c-site { font: 400 18px/1.3 var(--font-display); letter-spacing: 0; text-transform: none; color: var(--paper-dim); }
|
||||||
.tbl.lanes .trow.attention .c-site { color: var(--patina); }
|
.tbl.lanes .trow.attention .c-site { color: var(--danger); }
|
||||||
.tbl.lanes .c-skip { color: var(--patina); }
|
.tbl.lanes .c-skip { white-space: nowrap; }
|
||||||
|
.tbl.lanes .c-skip .bad { color: var(--danger); }
|
||||||
|
.tbl.lanes .c-skip .ok { color: var(--patina); }
|
||||||
.tbl.lanes .c-ctrl { text-align: right; }
|
.tbl.lanes .c-ctrl { text-align: right; }
|
||||||
.tbl.lanes .c-ctrl .ghost { font-size: 10px; }
|
.tbl.lanes .c-ctrl .ghost { font-size: 11px; }
|
||||||
|
|
||||||
/* ========== VARIANT C — wide, two-line blocks (no table, no card) ========= */
|
/* ========== VARIANT C — wide, two-line blocks (no table, no card) ========= */
|
||||||
/* Line one: title + action. Line two: every fact as one indented mono line.
|
/* Line one: title + action. Line two: every fact as one indented mono line.
|
||||||
@@ -431,7 +439,7 @@ main.page { padding: 0 20px 40px; }
|
|||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 4px 12px;
|
gap: 4px 12px;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
font: 500 10px/1.6 var(--font-mono);
|
font: 500 11px/1.6 var(--font-mono);
|
||||||
letter-spacing: .1em;
|
letter-spacing: .1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -444,7 +452,7 @@ main.page { padding: 0 20px 40px; }
|
|||||||
.pblk .p1 .mark { font-size: 10px; }
|
.pblk .p1 .mark { font-size: 10px; }
|
||||||
.pblk .p2 {
|
.pblk .p2 {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
font: 500 10px/1.6 var(--font-mono);
|
font: 500 11px/1.6 var(--font-mono);
|
||||||
letter-spacing: .1em;
|
letter-spacing: .1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -453,14 +461,14 @@ main.page { padding: 0 20px 40px; }
|
|||||||
/* Lane rows in C: site + state line, facts + controls line. */
|
/* Lane rows in C: site + state line, facts + controls line. */
|
||||||
.lblk { padding: 10px 0; border-bottom: 1px solid var(--rule); }
|
.lblk { padding: 10px 0; border-bottom: 1px solid var(--rule); }
|
||||||
.lblk .l1 { display: flex; align-items: baseline; gap: 14px; font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
|
.lblk .l1 { display: flex; align-items: baseline; gap: 14px; font: 400 19px/1.2 var(--font-display); color: var(--paper-dim); }
|
||||||
.lblk.attention .l1 { color: var(--patina); }
|
.lblk.attention .l1 { color: var(--danger); }
|
||||||
.lblk .l2 {
|
.lblk .l2 {
|
||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 4px 14px;
|
gap: 4px 14px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
font: 500 10px/1.6 var(--font-mono);
|
font: 500 11px/1.6 var(--font-mono);
|
||||||
letter-spacing: .1em;
|
letter-spacing: .1em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--mute-2);
|
color: var(--mute-2);
|
||||||
@@ -743,7 +751,7 @@ const SERIES = [
|
|||||||
sighting: false, pending: false, orphan: true },
|
sighting: false, pending: false, orphan: true },
|
||||||
{ key: "demonic:return-of-the-sss-class-rankers", site: "demonic",
|
{ key: "demonic:return-of-the-sss-class-rankers", site: "demonic",
|
||||||
title: "Return of the SSS-Class Ranker", kind: "manga",
|
title: "Return of the SSS-Class Ranker", kind: "manga",
|
||||||
ch: null, chLabel: "—", checked: null, readers: 1, cover: false, url: false,
|
ch: null, chLabel: "—", checked: 13 * 60, readers: 1, cover: false, url: false,
|
||||||
sighting: false, pending: false },
|
sighting: false, pending: false },
|
||||||
{ key: "novelfull:reverend-insanity", site: "novelfull",
|
{ key: "novelfull:reverend-insanity", site: "novelfull",
|
||||||
title: "Reverend Insanity", kind: "novel",
|
title: "Reverend Insanity", kind: "novel",
|
||||||
@@ -866,10 +874,18 @@ function rowMarks(s) {
|
|||||||
if (!s.cover) m.push("no cover");
|
if (!s.cover) m.push("no cover");
|
||||||
if (s.sighting) m.push("reader sighting");
|
if (s.sighting) m.push("reader sighting");
|
||||||
if (s.readers === 0) m.push("orphan");
|
if (s.readers === 0) m.push("orphan");
|
||||||
if (s.pending) m.push(`requested ${age(s.pendingAgo)}`);
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* notes render as chips, capped at two with a +N tail — a wall of stacked
|
||||||
|
marks at list density reads as noise, not signal */
|
||||||
|
function noteChips(s) {
|
||||||
|
const m = rowMarks(s);
|
||||||
|
const chips = m.slice(0, 2).map(x => `<span class="mark">${x}</span>`).join("");
|
||||||
|
const more = m.length - 2;
|
||||||
|
return chips + (more > 0 ? `<span class="mark mark-faint">+${more}</span>` : "");
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* State: variant + page from the URL, filter/site/kind from search. */
|
/* State: variant + page from the URL, filter/site/kind from search. */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
@@ -890,7 +906,7 @@ const esc = s => String(s).replace(/[&<>"']/g, c => ({ "&": "&", "<": "<"
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Shared chrome */
|
/* Shared chrome */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
const mark = `<svg class="mark" viewBox="0 0 200 172" aria-hidden="true"><g fill="var(--ink)" stroke="currentColor" stroke-width="5" stroke-linejoin="round" stroke-linecap="round"><path fill="none" d="M28 36H4v114h192V36h-24"></path><path fill="none" d="M28 23H17v127h166V23h-11"></path><g><path d="M28 7 88 55v97L28 138z"></path><g fill="currentColor" stroke="none"><path d="M37 25 55 39v41L37 66z"></path><path d="M60 42 79 57v42L60 84z"></path><path d="M37 75 79 108v13L37 88z"></path><path d="M37 98 79 129v11L37 131z"></path></g></g><g stroke="var(--ember)"><path d="M100 4l9 5v11l-9 5-9-5V9z"></path><path d="M94 24h12v24H94z"></path><path d="M70 47h60v14H70z"></path><path d="M91 61h18v87l-9 20-9-20z"></path></g></g></svg>`;
|
const mark = `<svg class="mark" viewBox="0 0 200 172" aria-hidden="true"><g fill="var(--ink)" stroke="currentColor" stroke-width="5" stroke-linejoin="round" stroke-linecap="round"><path fill="none" d="M28 36H4v114h192V36h-24"></path><path fill="none" d="M28 23H17v127h166V23h-11"></path><g id="mb-half"><path d="M28 7 88 55v97L28 138z"></path><g fill="currentColor" stroke="none"><path d="M37 25 55 39v41L37 66z"></path><path d="M60 42 79 57v42L60 84z"></path><path d="M37 75 79 108v13L37 88z"></path><path d="M37 98 79 129v11L37 131z"></path></g></g><use href="#mb-half" transform="matrix(-1 0 0 1 200 0)"></use><g stroke="var(--ember)"><path d="M100 4l9 5v11l-9 5-9-5V9z"></path><path d="M94 24h12v24H94z"></path><path d="M70 47h60v14H70z"></path><path d="M91 61h18v87l-9 20-9-20z"></path></g></g></svg>`;
|
||||||
|
|
||||||
function chrome(active) {
|
function chrome(active) {
|
||||||
const nav = [
|
const nav = [
|
||||||
@@ -899,8 +915,10 @@ function chrome(active) {
|
|||||||
`<a href="#${id}" class="${active === id ? "active" : ""}" ${active === id ? 'aria-current="page"' : ""}>${label}</a>`).join("");
|
`<a href="#${id}" class="${active === id ? "active" : ""}" ${active === id ? 'aria-current="page"' : ""}>${label}</a>`).join("");
|
||||||
return `<header class="topbar">
|
return `<header class="topbar">
|
||||||
<h1 class="brand">${mark}<span>Bookmark<em>Manager</em></span></h1>
|
<h1 class="brand">${mark}<span>Bookmark<em>Manager</em></span></h1>
|
||||||
<a class="ghost" href="/">Library</a>
|
<span class="topbar-actions">
|
||||||
<button type="button" class="ghost" onclick="void 0">Log out</button>
|
<a class="ghost" href="/">Library</a>
|
||||||
|
<button type="button" class="ghost" onclick="void 0">Log out</button>
|
||||||
|
</span>
|
||||||
</header>
|
</header>
|
||||||
<nav class="navrow" aria-label="Admin pages">${nav}</nav>`;
|
<nav class="navrow" aria-label="Admin pages">${nav}</nav>`;
|
||||||
}
|
}
|
||||||
@@ -957,6 +975,8 @@ function perSiteTable() {
|
|||||||
const lane = LANES.find(l => l.site === site.id);
|
const lane = LANES.find(l => l.site === site.id);
|
||||||
const out = lane ? lane.out : { refused: 0, unreachable: 0, no_chapter: 0, unfetchable: 0, errors: 0 };
|
const out = lane ? lane.out : { refused: 0, unreachable: 0, no_chapter: 0, unfetchable: 0, errors: 0 };
|
||||||
const state = lane ? laneStateWord(lane) : "";
|
const state = lane ? laneStateWord(lane) : "";
|
||||||
|
const tone = lane ? laneStateTone(lane) : "";
|
||||||
|
const stateMark = state ? `<span class="mark ${tone}">${state}</span>` : "";
|
||||||
const n = (v) => `<span class="c-num">${v}</span>`;
|
const n = (v) => `<span class="c-num">${v}</span>`;
|
||||||
if (variant === "A") {
|
if (variant === "A") {
|
||||||
const facts = [
|
const facts = [
|
||||||
@@ -968,7 +988,7 @@ function perSiteTable() {
|
|||||||
`no chapter ${out.no_chapter}`, `unfetchable ${out.unfetchable}`, `errors ${out.errors}`,
|
`no chapter ${out.no_chapter}`, `unfetchable ${out.unfetchable}`, `errors ${out.errors}`,
|
||||||
].join(" · ");
|
].join(" · ");
|
||||||
return `<div class="pst"><span class="pst-site">${site.label}</span>` +
|
return `<div class="pst"><span class="pst-site">${site.label}</span>` +
|
||||||
(state ? ` <span class="mark">${state}</span>` : "") +
|
(state ? ` ${stateMark}` : "") +
|
||||||
`<div class="pst-facts">${facts}</div></div>`;
|
`<div class="pst-facts">${facts}</div></div>`;
|
||||||
}
|
}
|
||||||
if (variant === "B") {
|
if (variant === "B") {
|
||||||
@@ -979,7 +999,7 @@ function perSiteTable() {
|
|||||||
<span>${series.filter(s => s.checked === null && s.url).length}</span>
|
<span>${series.filter(s => s.checked === null && s.url).length}</span>
|
||||||
<span>${series.filter(s => s.checked !== null && s.checked > STALE_MIN).length}</span>
|
<span>${series.filter(s => s.checked !== null && s.checked > STALE_MIN).length}</span>
|
||||||
${n(out.refused)}${n(out.unreachable)}${n(out.no_chapter)}${n(out.unfetchable)}${n(out.errors)}
|
${n(out.refused)}${n(out.unreachable)}${n(out.no_chapter)}${n(out.unfetchable)}${n(out.errors)}
|
||||||
<span class="c-state">${state}</span>
|
<span class="c-state ${tone}">${state}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
const facts = [
|
const facts = [
|
||||||
@@ -990,7 +1010,7 @@ function perSiteTable() {
|
|||||||
`refused ${out.refused}`, `unreachable ${out.unreachable}`,
|
`refused ${out.refused}`, `unreachable ${out.unreachable}`,
|
||||||
`no chapter ${out.no_chapter}`, `unfetchable ${out.unfetchable}`, `errors ${out.errors}`,
|
`no chapter ${out.no_chapter}`, `unfetchable ${out.unfetchable}`, `errors ${out.errors}`,
|
||||||
].join(" · ");
|
].join(" · ");
|
||||||
return `<div class="pblk"><div class="p1">${site.label}${state ? `<span class="mark">${state}</span>` : ""}</div><div class="p2">${facts}</div></div>`;
|
return `<div class="pblk"><div class="p1">${site.label}${stateMark}</div><div class="p2">${facts}</div></div>`;
|
||||||
}).join("");
|
}).join("");
|
||||||
|
|
||||||
if (variant === "B") {
|
if (variant === "B") {
|
||||||
@@ -1015,8 +1035,15 @@ function laneStateWord(l) {
|
|||||||
}
|
}
|
||||||
return l.skip;
|
return l.skip;
|
||||||
}
|
}
|
||||||
|
/* tone: a lane in trouble renders danger; a deliberate pause stays patina */
|
||||||
|
function laneStateTone(l) {
|
||||||
|
if (l.skip === "refusing" || l.skip === "sidecar-down") return "bad";
|
||||||
|
if (l.skip === "" && l.due > 0 && l.checked === 0) return "bad";
|
||||||
|
if (l.skip === "paused") return "ok";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
function pauseControls(l) {
|
function pauseControls(l) {
|
||||||
if (l.skip === "paused") return `<a class="ghost" href="#" onclick="event.preventDefault()">Resume</a>`;
|
if (l.skip === "paused") return `<span class="pausebar"><a class="ghost" href="#" onclick="event.preventDefault()">Resume</a></span>`;
|
||||||
return `<span class="pausebar">
|
return `<span class="pausebar">
|
||||||
<select aria-label="Pause duration">
|
<select aria-label="Pause duration">
|
||||||
<option>1h</option><option selected>6h</option><option>24h</option>
|
<option>1h</option><option selected>6h</option><option>24h</option>
|
||||||
@@ -1026,6 +1053,8 @@ function pauseControls(l) {
|
|||||||
}
|
}
|
||||||
function laneRow(l) {
|
function laneRow(l) {
|
||||||
const state = laneStateWord(l);
|
const state = laneStateWord(l);
|
||||||
|
const tone = laneStateTone(l);
|
||||||
|
const stateMark = state ? `<span class="mark ${tone}">${state}</span>` : "";
|
||||||
const attn = l.skip === "refusing" || l.skip === "sidecar-down" ||
|
const attn = l.skip === "refusing" || l.skip === "sidecar-down" ||
|
||||||
(l.skip === "" && l.due > 0 && l.checked === 0);
|
(l.skip === "" && l.due > 0 && l.checked === 0);
|
||||||
if (variant === "A") {
|
if (variant === "A") {
|
||||||
@@ -1036,7 +1065,7 @@ function laneRow(l) {
|
|||||||
<span class="lane-fact">ran ${age(l.ranAgo)}</span>
|
<span class="lane-fact">ran ${age(l.ranAgo)}</span>
|
||||||
${l.gap ? `<span class="lane-fact">gap ${l.gap}s</span>` : ""}
|
${l.gap ? `<span class="lane-fact">gap ${l.gap}s</span>` : ""}
|
||||||
${l.clamped ? `<span class="mark">gap at floor</span>` : ""}
|
${l.clamped ? `<span class="mark">gap at floor</span>` : ""}
|
||||||
${state ? `<span class="mark">${state}</span>` : ""}
|
${stateMark}
|
||||||
<span class="lane-out">${seriesOutcomes(l)}</span>
|
<span class="lane-out">${seriesOutcomes(l)}</span>
|
||||||
<span class="lane-ctrl">${pauseControls(l)}</span>
|
<span class="lane-ctrl">${pauseControls(l)}</span>
|
||||||
</li>`;
|
</li>`;
|
||||||
@@ -1048,12 +1077,12 @@ function laneRow(l) {
|
|||||||
<span>${l.checked}</span>
|
<span>${l.checked}</span>
|
||||||
<span>${l.gap ? l.gap + "s" : "—"}</span>
|
<span>${l.gap ? l.gap + "s" : "—"}</span>
|
||||||
<span>ran ${age(l.ranAgo)}${l.clamped ? " · clamped" : ""}</span>
|
<span>ran ${age(l.ranAgo)}${l.clamped ? " · clamped" : ""}</span>
|
||||||
<span class="c-skip">${seriesOutcomes(l)} ${state ? `· ${state}` : ""}</span>
|
<span class="c-skip">${seriesOutcomes(l)} ${state ? `· <span class="${tone}">${state}</span>` : ""}</span>
|
||||||
<span class="c-ctrl">${pauseControls(l)}</span>
|
<span class="c-ctrl">${pauseControls(l)}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
return `<div class="lblk${attn ? " attention" : ""}">
|
return `<div class="lblk${attn ? " attention" : ""}">
|
||||||
<div class="l1">${l.site}${state ? `<span class="mark">${state}</span>` : ""}</div>
|
<div class="l1">${l.site}${stateMark}</div>
|
||||||
<div class="l2">
|
<div class="l2">
|
||||||
<span>${l.due} due</span><span>${l.checked} checked</span>
|
<span>${l.due} due</span><span>${l.checked} checked</span>
|
||||||
<span>ran ${age(l.ranAgo)}</span>${l.gap ? `<span>gap ${l.gap}s</span>` : ""}
|
<span>ran ${age(l.ranAgo)}</span>${l.gap ? `<span>gap ${l.gap}s</span>` : ""}
|
||||||
@@ -1076,8 +1105,9 @@ function lanesPage() {
|
|||||||
<p class="setup-copy">One row per Lane. Refreshes every 30s. The five counts
|
<p class="setup-copy">One row per Lane. Refreshes every 30s. The five counts
|
||||||
are sums over the last 12h; a zero renders as <i>none observed</i> — an
|
are sums over the last 12h; a zero renders as <i>none observed</i> — an
|
||||||
adapter reading a wrong number is not in this taxonomy and never can be.</p>
|
adapter reading a wrong number is not in this taxonomy and never can be.</p>
|
||||||
|
<p class="setup-copy">Browser sidecar: <span class="mark">reachable</span> —
|
||||||
|
kagane, comix and novelfull poll through it; without it those lanes skip.</p>
|
||||||
${list}
|
${list}
|
||||||
<p class="setup-copy" style="padding-top:14px">Browser sidecar: <span class="mark">reachable</span></p>
|
|
||||||
</main>`;
|
</main>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1111,7 +1141,7 @@ function readersPage() {
|
|||||||
/* Series list */
|
/* Series list */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
function seriesRow(s) {
|
function seriesRow(s) {
|
||||||
const marks = rowMarks(s).map(m => `<span class="mark">${m}</span>`).join("");
|
const marks = noteChips(s);
|
||||||
const metaFacts = [
|
const metaFacts = [
|
||||||
`<span class="${siteCls(s.site)}" style="color:var(--${s.site})">${siteLabel(s.site)}</span>`,
|
`<span class="${siteCls(s.site)}" style="color:var(--${s.site})">${siteLabel(s.site)}</span>`,
|
||||||
`<span>ch ${s.chLabel}</span>`,
|
`<span>ch ${s.chLabel}</span>`,
|
||||||
|
|||||||
Reference in New Issue
Block a user