Rate monitor: daily-budget ring around the Spotify avatar
The payload has carried daily_budget {used, limit, exhausted} forever and the
dashboard rendered none of it. The avatar disc now wears a conic progress rim
that fills as the day's real-API budget is spent — green to 70%, amber to 95%,
red after — and flips purple once the worker has bridged to Spotify Free for
the rest of the day (using_free now included in the emit payload). Tooltip
carries the exact used/limit numbers.
This commit is contained in:
parent
09af31154e
commit
7efb5da893
3 changed files with 49 additions and 0 deletions
|
|
@ -35033,6 +35033,9 @@ def _emit_rate_monitor_loop():
|
|||
}
|
||||
if svc_key == 'spotify' and enr.get('daily_budget'):
|
||||
entry['worker']['daily_budget'] = enr['daily_budget']
|
||||
# Budget ring styling: purple when the worker has
|
||||
# bridged to Spotify Free after spending the budget.
|
||||
entry['worker']['using_free'] = bool(enr.get('using_free'))
|
||||
except Exception as e:
|
||||
logger.debug("enrichment worker status build failed: %s", e)
|
||||
|
||||
|
|
|
|||
|
|
@ -383,6 +383,28 @@ function _renderEqualizerBars(grid, data) {
|
|||
}
|
||||
bar.classList.toggle('cooldown', cooling);
|
||||
|
||||
// Daily-budget ring (Spotify is the only service with a real daily
|
||||
// cap): a conic rim inside the avatar disc fills as the budget is
|
||||
// spent — green → amber → red, purple once the worker has bridged
|
||||
// to Spotify Free for the rest of the day.
|
||||
const budget = worker.daily_budget;
|
||||
if (budget && budget.limit > 0) {
|
||||
const bPct = Math.min(1, (budget.used || 0) / budget.limit);
|
||||
const bridged = !!worker.using_free && !!budget.exhausted;
|
||||
bar.classList.add('has-budget');
|
||||
bar.style.setProperty('--eq-budget', String(Math.max(bPct, 0.02)));
|
||||
bar.style.setProperty('--eq-budget-color',
|
||||
bridged ? '#a78bfa' : bPct < 0.7 ? '#4ade80' : bPct < 0.95 ? '#fbbf24' : '#ef4444');
|
||||
const avatar = bar.querySelector('.rate-eq-avatar');
|
||||
if (avatar) {
|
||||
avatar.title = bridged
|
||||
? `Daily budget spent — running on Spotify Free (${budget.used}/${budget.limit})`
|
||||
: `Daily API budget: ${budget.used}/${budget.limit}`;
|
||||
}
|
||||
} else {
|
||||
bar.classList.remove('has-budget');
|
||||
}
|
||||
|
||||
_eqDisplay[svc] = { value, pct, peak, peakAt, rlTotal, cooling };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63083,6 +63083,30 @@ body.reduce-effects .dash-card::after {
|
|||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
/* Daily-budget ring — a conic progress rim hugging the avatar disc's inner
|
||||
* edge, filling as the day's API budget is spent. Color comes from JS
|
||||
* (green → amber → red, purple when bridged to Spotify Free). Drawn inside
|
||||
* the disc because the avatar clips overflow. */
|
||||
.rate-eq-avatar::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
border-radius: 50%;
|
||||
background: conic-gradient(
|
||||
var(--eq-budget-color, #4ade80) calc(var(--eq-budget, 0) * 360deg),
|
||||
transparent 0);
|
||||
-webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3.5px), #000 calc(100% - 2.5px));
|
||||
mask: radial-gradient(farthest-side, transparent calc(100% - 3.5px), #000 calc(100% - 2.5px));
|
||||
opacity: 0;
|
||||
transition: opacity 0.4s;
|
||||
pointer-events: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.rate-eq.has-budget .rate-eq-avatar::after {
|
||||
opacity: 0.95;
|
||||
}
|
||||
|
||||
.rate-eq.active .rate-eq-avatar {
|
||||
animation: rate-eq-avatar-halo 2.8s ease-in-out infinite;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue