Fix top-genres banner overlap + polling backoff after 90%#102
Merged
Conversation
Two small dashboard fixes from the StoryGraph PR's deferred follow-ups: 1. Top-genres donut chart no longer collides with the "Still enriching" banner. The banner is absolute-positioned full-width across the top of the card; the chart is also absolute-positioned at top-2 right-2. When enrichment is pending, push the chart down to top-8 so it sits below the banner instead of underneath it. 2. Once enrichment crosses 90%, the dashboard polls /api/enrichment-status/ every 12s instead of every 5s. The final stretch is mostly the long tail of stragglers — no need to keep hammering the server.
The "Still enriching" banner is absolute-positioned, so a tile *with* a banner had its content pushed down (heading, chart, big number) while sibling tiles in the same row kept their content flush with the top — visually misaligned, and on the key-stats row the banner partially covered the page-count number. Fix: when enrichment.pending, every tile in an affected row gets pt-7, reserving a consistent banner-height zone. Tiles with a banner display it in that zone; sibling tiles see only empty space, but at the same height. Genres chart also drops to md:!top-7 to clear the banner. Tiles touched: niche_read, mainstream_gauge, key_stats (all three), top_genres_authors (both), fiction_nonfiction (card + skeleton), book_extremes (card + skeleton).
Three review-pass fixes for PR #102. 1. Polling thrash: adjustInterval is now monotonic — once we've slowed to 12s, we never speed back up. A non-monotonic percent (rounding, denominator shifts when a new book lands mid-pass) can no longer thrash the timer. 2. Concurrent fetches: poll() guards on this.inFlight so a hung fetch can't stack up behind a new interval. Cleared in finally regardless of error. 3. Replaced ten copies of `{% if enrichment.pending %}pt-7{% endif %}` with one CSS rule: .enrichment-row:has(.enrichment-banner) > * { padding-top: 1.75rem; } The banner partial now actually renders nothing when not pending (was relying on Alpine x-show), so :has() is a true signal. Row containers (key_stats, top_genres_authors, plus the two grids in dashboard.html) gained the .enrichment-row marker class. Corner charts in top-genres /top-authors are pushed down by a sibling @media rule.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two small dashboard follow-ups from PR #98's deferred list, plus refactor from review feedback.
1. Banner no longer collides with content; row tiles align
The "Still enriching" banner is
absolute top-0 inset-x-0 z-10. Tiles WITH the banner had their content overlapped (page-count number partially covered, donut chart sat under the translucent yellow); sibling tiles in the same row had no offset and looked misaligned.Fix: every tile inside an
.enrichment-rowgrid reserves a banner-height zone via a single CSS rule:The
enrichment_banner.htmlpartial now actually renders nothing whenenrichment.pendingis false (was relying on Alpinex-show), so:has()is a true signal. Four row containers gained the.enrichment-rowmarker class; the corner charts in top-genres/top-authors gained.enrichment-corner-chart. Replaces ten copies of{% if enrichment.pending %}pt-7{% endif %}from earlier iterations of this PR.2. Polling backoff once enrichment crosses 90%
enrichmentPollerpolled/api/enrichment-status/on a fixed 5s interval. The last 10% of enrichment is mostly long-tail stragglers (books in retry/backoff), so the dashboard kept hammering the server every 5s for what could be several minutes.Fix: when
percent > 90, switch to a 12s interval. The threshold is monotonic — once we've slowed down, we never speed back up — so a non-monotonic percent (rounding, denominator shifts when a new book lands mid-pass) can't thrash the timer.poll()also guards on aninFlightflag so a hung fetch can't stack up behind a fresh interval.Test plan
docker-compose -f docker-compose.local.yml exec web poetry run python manage.py test→ 343 passedpnpm run build→.enrichment-row:has(.enrichment-banner)present in built CSStop-2pt-7(extra empty space at top, harmless on stacked layout)/api/enrichment-status/fires every ~5s whilepercent ≤ 90, then every ~12s after