mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 15:22:12 +03:00
* feat(dashboard): add per-operator quota row visibility on usage tab
Adds a "hide this quota row" action (visibility_off icon button) to
each model-quota row on the provider limits card, and a "Hidden: …"
strip at the bottom of the card to restore any hidden row. The
visibility preference is keyed per-provider (settings.quotaVisibility)
and persisted via PATCH /api/settings, so it survives refresh/reload.
Distinct from the existing model-catalog isHidden/isDeleted mechanism
(collectHiddenQuotaModelIds/filterHiddenModelQuotas in
ProviderLimits/utils.tsx), which hides rows the ADMIN marked hidden in
the model catalog. This is a personal dashboard preference an operator
can toggle without touching the catalog — e.g. temporarily decluttering
a quota card with many low-signal rows.
New pure helpers (getQuotaVisibilityKey, filterQuotasByVisibility,
getHiddenQuotaRows) live in ProviderLimits/utils.tsx and are unit
tested directly; the settings key is added to DEFAULT_SETTINGS and
validated via updateSettingsSchema like the existing
providerStrategies field. New UI strings are filled in en.json and
synced to the other 42 locales as `__MISSING__` placeholders.
Co-authored-by: nguyenha935 <208228297+nguyenha935@users.noreply.github.com>
Inspired-by: https://github.com/decolua/9router/pull/2371
* chore(changelog): fragment for #7251
* refactor(usage): extract useQuotaVisibility hook (file-size budget)
ProviderLimits/index.tsx grew past its frozen 1127-line budget with the
quota-visibility wiring; extract the state + persistence + hide/show handlers
into a dedicated hook (same pattern as useCodexResetCreditRedemption).
No behavior change — the live validation evidence on the PR covers this flow
end-to-end.
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
* refactor(dashboard): shed QuotaCard complexity to baseline + type useQuotaVisibility settings fetch (#7251 CI green)
* test(dashboard): rename quota-row visibility test (path claimed by #7360)
* fix(dashboard): restore providerTierField case-collision fix dropped by merge auto-resolve
The git merge of origin/release/v3.8.49 auto-resolved providerTierFieldApi.ts
(added post-merge-base by commit 3ba3cd145e to fix a case-only filename
collision with ProviderTierField.tsx that breaks webpack on case-insensitive
filesystems) back down to its pre-fix name providerTierField.ts, silently
reverting that base-red fix and dropping its stryker tap.testFiles
registration and changelog fragment. Restore all four: the renamed helper
file, the import path in ProviderTierField.tsx, the import path in
tests/unit/provider-tier-field-helpers.test.ts, and the
combo-skip-conn-disable-plugin-block-7806.test.ts stryker registration.
---------
Co-authored-by: nguyenha935 <208228297+nguyenha935@users.noreply.github.com>
60 lines
2.2 KiB
TypeScript
60 lines
2.2 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { describe, it } from "node:test";
|
|
|
|
import {
|
|
filterQuotasByVisibility,
|
|
getHiddenQuotaRows,
|
|
getQuotaVisibilityKey,
|
|
} from "../../src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx";
|
|
|
|
describe("provider quota visibility (upstream 9router#2371 port)", () => {
|
|
const quotas = [
|
|
{ modelKey: "gemini-pro-agent", name: "Gemini 3.1 Pro (High)", used: 200, total: 1000 },
|
|
{
|
|
modelKey: "claude-opus-4-6-thinking",
|
|
name: "Claude Opus 4.6 (Thinking)",
|
|
used: 100,
|
|
total: 1000,
|
|
},
|
|
];
|
|
|
|
it("derives a stable key preferring modelKey over name", () => {
|
|
assert.equal(getQuotaVisibilityKey(quotas[0]), "gemini-pro-agent");
|
|
assert.equal(getQuotaVisibilityKey({ name: "no-model-key" }), "no-model-key");
|
|
assert.equal(getQuotaVisibilityKey(null), "");
|
|
assert.equal(getQuotaVisibilityKey(undefined), "");
|
|
});
|
|
|
|
it("shows all quotas by default (no visibility config)", () => {
|
|
assert.equal(filterQuotasByVisibility("antigravity", quotas, {}).length, 2);
|
|
assert.deepEqual(getHiddenQuotaRows("antigravity", quotas, {}), []);
|
|
});
|
|
|
|
it("hides the configured provider row and reports it separately", () => {
|
|
const visibility = { antigravity: { hidden: ["claude-opus-4-6-thinking"] } };
|
|
|
|
const visible = filterQuotasByVisibility("antigravity", quotas, visibility);
|
|
const hidden = getHiddenQuotaRows("antigravity", quotas, visibility);
|
|
|
|
assert.deepEqual(
|
|
visible.map((q) => q.modelKey),
|
|
["gemini-pro-agent"]
|
|
);
|
|
assert.deepEqual(
|
|
hidden.map((q) => q.modelKey),
|
|
["claude-opus-4-6-thinking"]
|
|
);
|
|
});
|
|
|
|
it("never applies one provider's hidden list to another provider", () => {
|
|
const visibility = { codex: { hidden: ["gemini-pro-agent"] } };
|
|
assert.equal(filterQuotasByVisibility("antigravity", quotas, visibility).length, 2);
|
|
assert.deepEqual(getHiddenQuotaRows("antigravity", quotas, visibility), []);
|
|
});
|
|
|
|
it("returns an empty array for non-array quotas input", () => {
|
|
assert.deepEqual(filterQuotasByVisibility("antigravity", undefined as unknown as [], {}), []);
|
|
assert.deepEqual(getHiddenQuotaRows("antigravity", undefined as unknown as [], {}), []);
|
|
});
|
|
});
|