Add burst job scheduling, enhance timeline lane management, and improve tooltip functionality
This commit is contained in:
@@ -140,6 +140,27 @@ def get_fake_jobs(now: datetime) -> list[FakeReconJob]:
|
||||
),
|
||||
]
|
||||
|
||||
# A burst of jobs all scheduled at the same time (16:00) — the engine will
|
||||
# serialise these so the dashboard caps the stack at 3 lanes and chains the
|
||||
# rest horizontally on the bottom lane.
|
||||
burst_due = _at(today, 16, 0) if now < _at(today, 16, 0) else now + timedelta(minutes=30)
|
||||
burst_names = [
|
||||
("Branch Cash Recon", "branch-cash"),
|
||||
("Card Settlement Recon", "card-settlement"),
|
||||
("ATM Float Recon", "atm-float"),
|
||||
("Loan Disbursement Recon","loan-disb"),
|
||||
("Mortgage Payment Recon", "mortgage-pmt"),
|
||||
("Term Deposit Recon", "term-deposit"),
|
||||
("Wire Transfer Recon", "wire-transfer"),
|
||||
]
|
||||
for i, (name, ref) in enumerate(burst_names):
|
||||
jobs.append(FakeReconJob(
|
||||
id=210 + i, name=name, as_at_date=today,
|
||||
recon_config_reference=ref,
|
||||
due_datetime=burst_due,
|
||||
status="created",
|
||||
))
|
||||
|
||||
# Add a 7-day history (excluding the two days above) so totals look real.
|
||||
history_template = [
|
||||
("FX Settlement Recon", "fx-settlement", 6, 45, "completed"),
|
||||
|
||||
+10
-1
@@ -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
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user