fix(dashboard): show both quota windows (#27)
This commit is contained in:
@@ -150,6 +150,15 @@ function usageLimitWindow(row: UsageRow): UsageLimitWindow {
|
|||||||
return row.d7pct >= row.h5pct ? 'd7' : 'h5';
|
return row.d7pct >= row.h5pct ? 'd7' : 'h5';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function usageWindowRemaining(
|
||||||
|
row: UsageRow,
|
||||||
|
window: UsageLimitWindow,
|
||||||
|
): number | null {
|
||||||
|
const pct = window === 'h5' ? row.h5pct : row.d7pct;
|
||||||
|
if (pct < 0) return null;
|
||||||
|
return Math.max(0, 100 - pct);
|
||||||
|
}
|
||||||
|
|
||||||
function usageRiskLevel(row: UsageRow): RiskLevel {
|
function usageRiskLevel(row: UsageRow): RiskLevel {
|
||||||
const peak = usagePeak(row);
|
const peak = usagePeak(row);
|
||||||
if (peak >= 85) return 'critical';
|
if (peak >= 85) return 'critical';
|
||||||
@@ -931,6 +940,8 @@ function UsageRemainingMeter({
|
|||||||
}) {
|
}) {
|
||||||
const remaining = usageRemaining(row);
|
const remaining = usageRemaining(row);
|
||||||
const window = usageLimitWindow(row);
|
const window = usageLimitWindow(row);
|
||||||
|
const h5Remaining = usageWindowRemaining(row, 'h5');
|
||||||
|
const d7Remaining = usageWindowRemaining(row, 'd7');
|
||||||
const reset = usageLimitReset(row);
|
const reset = usageLimitReset(row);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -946,6 +957,18 @@ function UsageRemainingMeter({
|
|||||||
max={100}
|
max={100}
|
||||||
value={remaining ?? 0}
|
value={remaining ?? 0}
|
||||||
/>
|
/>
|
||||||
|
<div className="quota-pair" aria-label={`${rowName} quota windows`}>
|
||||||
|
<span className={window === 'h5' ? 'is-tight' : undefined}>
|
||||||
|
<b>{t.usage.quota.h5}</b>
|
||||||
|
<em>{h5Remaining === null ? '-' : formatPct(h5Remaining)}</em>
|
||||||
|
<progress max={100} value={h5Remaining ?? 0} />
|
||||||
|
</span>
|
||||||
|
<span className={window === 'd7' ? 'is-tight' : undefined}>
|
||||||
|
<b>{t.usage.quota.d7}</b>
|
||||||
|
<em>{d7Remaining === null ? '-' : formatPct(d7Remaining)}</em>
|
||||||
|
<progress max={100} value={d7Remaining ?? 0} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<small>
|
<small>
|
||||||
{remaining === null ? '-' : t.usage.limitBasis[window]}
|
{remaining === null ? '-' : t.usage.limitBasis[window]}
|
||||||
{reset ? ` · ${t.usage.reset} ${reset}` : ` · ${t.usage.noReset}`}
|
{reset ? ` · ${t.usage.reset} ${reset}` : ` · ${t.usage.noReset}`}
|
||||||
|
|||||||
@@ -130,6 +130,10 @@ export interface Messages {
|
|||||||
h5: string;
|
h5: string;
|
||||||
d7: string;
|
d7: string;
|
||||||
};
|
};
|
||||||
|
quota: {
|
||||||
|
h5: string;
|
||||||
|
d7: string;
|
||||||
|
};
|
||||||
usage: string;
|
usage: string;
|
||||||
groupPrimary: string;
|
groupPrimary: string;
|
||||||
groupCodex: string;
|
groupCodex: string;
|
||||||
@@ -335,6 +339,10 @@ export const messages = {
|
|||||||
h5: '5시간 기준',
|
h5: '5시간 기준',
|
||||||
d7: '7일 기준',
|
d7: '7일 기준',
|
||||||
},
|
},
|
||||||
|
quota: {
|
||||||
|
h5: '5시간',
|
||||||
|
d7: '7일',
|
||||||
|
},
|
||||||
usage: '사용량',
|
usage: '사용량',
|
||||||
groupPrimary: 'Claude / Kimi',
|
groupPrimary: 'Claude / Kimi',
|
||||||
groupCodex: 'Codex',
|
groupCodex: 'Codex',
|
||||||
@@ -524,6 +532,10 @@ export const messages = {
|
|||||||
h5: '5h basis',
|
h5: '5h basis',
|
||||||
d7: '7d basis',
|
d7: '7d basis',
|
||||||
},
|
},
|
||||||
|
quota: {
|
||||||
|
h5: '5h',
|
||||||
|
d7: '7d',
|
||||||
|
},
|
||||||
usage: 'usage',
|
usage: 'usage',
|
||||||
groupPrimary: 'Claude / Kimi',
|
groupPrimary: 'Claude / Kimi',
|
||||||
groupCodex: 'Codex',
|
groupCodex: 'Codex',
|
||||||
@@ -713,6 +725,10 @@ export const messages = {
|
|||||||
h5: '按5小时',
|
h5: '按5小时',
|
||||||
d7: '按7天',
|
d7: '按7天',
|
||||||
},
|
},
|
||||||
|
quota: {
|
||||||
|
h5: '5小时',
|
||||||
|
d7: '7天',
|
||||||
|
},
|
||||||
usage: '用量',
|
usage: '用量',
|
||||||
groupPrimary: 'Claude / Kimi',
|
groupPrimary: 'Claude / Kimi',
|
||||||
groupCodex: 'Codex',
|
groupCodex: 'Codex',
|
||||||
@@ -902,6 +918,10 @@ export const messages = {
|
|||||||
h5: '5時間基準',
|
h5: '5時間基準',
|
||||||
d7: '7日基準',
|
d7: '7日基準',
|
||||||
},
|
},
|
||||||
|
quota: {
|
||||||
|
h5: '5時間',
|
||||||
|
d7: '7日',
|
||||||
|
},
|
||||||
usage: '使用量',
|
usage: '使用量',
|
||||||
groupPrimary: 'Claude / Kimi',
|
groupPrimary: 'Claude / Kimi',
|
||||||
groupCodex: 'Codex',
|
groupCodex: 'Codex',
|
||||||
|
|||||||
@@ -739,6 +739,46 @@ td small {
|
|||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quota-pair {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-pair span {
|
||||||
|
display: grid;
|
||||||
|
min-width: 0;
|
||||||
|
gap: 3px;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 11px;
|
||||||
|
background: rgba(43, 55, 38, 0.045);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-pair span.is-tight {
|
||||||
|
background: rgba(191, 95, 44, 0.11);
|
||||||
|
box-shadow: inset 0 0 0 1px rgba(191, 95, 44, 0.16);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-pair b,
|
||||||
|
.quota-pair em {
|
||||||
|
min-width: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
font-size: 10px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 900;
|
||||||
|
line-height: 1;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-pair b {
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-pair progress {
|
||||||
|
height: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.usage-speed {
|
.usage-speed {
|
||||||
min-height: 54px;
|
min-height: 54px;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
@@ -1589,6 +1629,14 @@ progress::-moz-progress-bar {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.quota-pair {
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quota-pair span {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.record-card-grid {
|
.record-card-grid {
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user