Dashboard: a per-address quota's bar counts all its addresses
One address that used up its allowance filled the bar (100%). The bar is now all the addresses together, and the dashboard and the rule's quota line say how many used theirs up. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
500bfc7bdd
commit
4af4a5908b
3 files changed
+18
-6
No files matched your search
@@ -72,19 +72,26 @@ export async function render(el) {
|
||||
}
|
||||
|
||||
// quotaPanel lists every rule's quota with what it used: the total, or
|
||||
// for a per-address quota the busiest address (the rest are on the rule).
|
||||
// for a per-address quota how many addresses used theirs up and the
|
||||
// busiest (the rest are on the rule). A per-address quota's bar is all
|
||||
// its addresses together, so one address alone can't fill it.
|
||||
function quotaPanel(quotas, names) {
|
||||
const perAddress = (q) => q.quota.per_source || q.quota.per_destination;
|
||||
const used = (q) => perAddress(q) ? ((q.addresses || [])[0] || { used: 0 }).used : q.used;
|
||||
const addrs = (q) => q.addresses || [];
|
||||
const usedUp = (q) => addrs(q).filter((a) => a.used >= q.quota.bytes).length;
|
||||
const bar = (q) => perAddress(q)
|
||||
? usageBar(addrs(q).reduce((n, a) => n + Math.min(a.used, q.quota.bytes), 0), addrs(q).length * q.quota.bytes)
|
||||
: usageBar(q.used, q.quota.bytes);
|
||||
return h("div", { class: "panel" },
|
||||
h("div", { class: "panel-head" }, h("h2", null, "Quotas"), h("a", { class: "button small", href: "#/stats" }, "Statistics")),
|
||||
table([
|
||||
{ label: "Rule", render: (q) => h("a", { href: "#/rules?rule=" + q.rule_id }, q.rule) },
|
||||
{ label: "Allowance", render: (q) => fmtBytes(q.quota.bytes) + (q.quota.per_source ? " each source" : q.quota.per_destination ? " each destination" : "") },
|
||||
{ label: "Used", render: (q) => perAddress(q)
|
||||
? [plural((q.addresses || []).length, "address", "addresses"), q.addresses && q.addresses.length ? [", busiest ", named(names, q.addresses[0].address), " " + fmtBytes(used(q)) + " (" + pct(used(q), q.quota.bytes) + ")"] : ""]
|
||||
? [plural(addrs(q).length, "address", "addresses"), usedUp(q) ? ", " + usedUp(q) + " used up" : "",
|
||||
addrs(q).length ? [", busiest ", named(names, addrs(q)[0].address), " " + fmtBytes(addrs(q)[0].used) + " (" + pct(addrs(q)[0].used, q.quota.bytes) + ")"] : ""]
|
||||
: fmtBytes(q.used) + " (" + pct(q.used, q.quota.bytes) + ")" },
|
||||
{ label: "", render: (q) => usageBar(used(q), q.quota.bytes) },
|
||||
{ label: "", render: (q) => addrs(q).length || !perAddress(q) ? bar(q) : "" },
|
||||
{ label: "Next reset", render: (q) => q.next_reset ? time(q.next_reset) : h("span", { class: "muted" }, "by hand") },
|
||||
], quotas));
|
||||
}
|
||||
|
||||
@@ -167,8 +167,9 @@ function quotaLine(r, q) {
|
||||
let used = fmtBytes(qt.bytes) + each;
|
||||
if (q && !each) used = fmtBytes(q.used) + " of " + fmtBytes(qt.bytes) + " used (" + pct(q.used, qt.bytes) + ")";
|
||||
else if (q) {
|
||||
const n = (q.addresses || []).length;
|
||||
used += " · " + (n === 1 ? "1 address" : n + " addresses") + (n ? ", busiest " + fmtBytes(q.addresses[0].used) + " (" + pct(q.addresses[0].used, qt.bytes) + ")" : "");
|
||||
const a = q.addresses || [], n = a.length;
|
||||
const up = a.filter((x) => x.used >= qt.bytes).length;
|
||||
used += " · " + (n === 1 ? "1 address" : n + " addresses") + (up ? ", " + up + " used up" : "") + (n ? ", busiest " + fmtBytes(a[0].used) + " (" + pct(a[0].used, qt.bytes) + ")" : "");
|
||||
}
|
||||
const text = "quota " + used + " · " + resets;
|
||||
return h("div", { class: "muted small" }, q && r.pending !== "new"
|
||||
|
||||
Reference in new issue
Block a user