Add burst job scheduling, enhance timeline lane management, and improve tooltip functionality

This commit is contained in:
2026-05-25 20:01:24 +12:00
parent 3be35f6b0a
commit 469ac9bc5a
8 changed files with 105 additions and 10 deletions
+10 -1
View File
@@ -1,16 +1,25 @@
from fastapi import APIRouter, Request
from fastapi.openapi.docs import get_swagger_ui_html
from fastapi.responses import HTMLResponse
from fastapi.responses import HTMLResponse, Response
router = APIRouter()
@router.get("/.well-known/appspecific/com.chrome.devtools.json", include_in_schema=False)
async def chrome_devtools_probe() -> Response:
"""Chrome DevTools probes this path whenever DevTools opens. Return an
empty 204 so it doesn't show as a 404 in the access log."""
return Response(status_code=204)
@router.get("/api/docs", include_in_schema=False)
async def swagger_ui_dark(request: Request) -> HTMLResponse:
base = get_swagger_ui_html(
openapi_url=request.app.openapi_url,
title="Recon Ranger — API Docs",
swagger_js_url="/static/api/swagger-ui-bundle.js",
swagger_css_url="/static/api/swagger-ui.css",
swagger_favicon_url="/static/api/favicon.png",
)
html = base.body.decode()
+25 -4
View File
@@ -87,22 +87,43 @@ def _build_day_timeline(
# Lane (row) assignment so overlapping/adjacent bars stack vertically.
# An entry occupies [left, left+width); for collision purposes scheduled
# markers are widened slightly so back-to-back scheduled jobs separate.
# Lanes are capped at MAX_LANES — additional collisions are pushed to the
# right of the last entry on the bottom lane (visualising "and N more
# serialised after this one") rather than growing the track vertically.
GAP = 0.2 # % units
MIN_COLLISION_WIDTH = 1.2
MAX_LANES = 3
lane_ends: list[float] = []
lane_visible_ends: list[float] = []
for e in entries:
coll_width = max(e["width"], MIN_COLLISION_WIDTH)
coll_end = e["left"] + coll_width
placed = False
for i, end in enumerate(lane_ends):
if e["left"] >= end + GAP:
lane_ends[i] = coll_end
lane_ends[i] = e["left"] + coll_width
e["lane"] = i
placed = True
break
if not placed:
e["lane"] = len(lane_ends)
lane_ends.append(coll_end)
if len(lane_ends) < MAX_LANES:
e["lane"] = len(lane_ends)
lane_ends.append(e["left"] + coll_width)
lane_visible_ends.append(e["left"] + e["width"])
else:
# All lanes occupied — shunt this entry horizontally onto the
# last lane, immediately after whatever is already there. We
# advance by the previous entry's *visible* width (tracked
# separately) rather than the inflated collision width, so
# scheduled markers sit flush against each other.
last = MAX_LANES - 1
new_left = lane_visible_ends[last] + GAP
e["left"] = new_left
e["lane"] = last
lane_ends[last] = new_left + coll_width
lane_visible_ends[last] = new_left + e["width"]
continue
# Track visible end too (used only for chaining on the last lane).
lane_visible_ends[e["lane"]] = e["left"] + e["width"]
return {
"date": day,