1
0
forked from boos/BoosAPI

[codex] Add route cooldown controls (#365)

* Add route cooldown controls

* Address route cooldown review comments
This commit is contained in:
Cita
2026-04-01 16:41:25 +08:00
committed by GitHub
parent 1e0dffe543
commit 532be86e93
16 changed files with 1182 additions and 17 deletions
@@ -41,6 +41,8 @@ describe('RouteCard', () => {
onEdit={vi.fn()}
onDelete={vi.fn()}
onToggleEnabled={vi.fn()}
onClearCooldown={vi.fn()}
clearingCooldown={false}
onRoutingStrategyChange={vi.fn()}
updatingRoutingStrategy={false}
channels={undefined}
@@ -85,4 +87,53 @@ describe('RouteCard', () => {
flexShrink: 1,
});
});
it('renders a clear cooldown action on expanded cards', () => {
const onClearCooldown = vi.fn();
const root = create(
<RouteCard
route={buildRoute()}
brand={null}
expanded
onToggleExpand={vi.fn()}
onEdit={vi.fn()}
onDelete={vi.fn()}
onToggleEnabled={vi.fn()}
onClearCooldown={onClearCooldown}
clearingCooldown={false}
onRoutingStrategyChange={vi.fn()}
updatingRoutingStrategy={false}
channels={[]}
loadingChannels={false}
routeDecision={null}
loadingDecision={false}
candidateView={{ routeCandidates: [], accountOptions: [], tokenOptionsByAccountId: {} }}
channelTokenDraft={{}}
updatingChannel={{}}
savingPriority={false}
onTokenDraftChange={vi.fn()}
onSaveToken={vi.fn()}
onDeleteChannel={vi.fn()}
onToggleChannelEnabled={vi.fn()}
onChannelDragEnd={vi.fn()}
onSplitPriorityBucket={vi.fn()}
missingTokenSiteItems={[]}
missingTokenGroupItems={[]}
onCreateTokenForMissing={vi.fn()}
onAddChannel={vi.fn()}
onSiteBlockModel={vi.fn()}
expandedSourceGroupMap={{}}
onToggleSourceGroup={vi.fn()}
/>,
);
const button = root.root.find((node) => (
node.type === 'button'
&& typeof node.props.onClick === 'function'
&& collectText(node).trim() === '清除冷却'
));
button.props.onClick();
expect(onClearCooldown).toHaveBeenCalledTimes(1);
});
});
+14
View File
@@ -53,6 +53,8 @@ type RouteCardProps = {
onEdit: (route: RouteSummaryRow) => void;
onDelete: (routeId: number) => void;
onToggleEnabled: (route: RouteSummaryRow) => void;
onClearCooldown: (routeId: number) => void;
clearingCooldown: boolean;
onRoutingStrategyChange: (route: RouteSummaryRow, strategy: RouteRoutingStrategy) => void;
updatingRoutingStrategy: boolean;
// Channel data (loaded on demand)
@@ -106,6 +108,8 @@ function RouteCardInner({
onEdit,
onDelete,
onToggleEnabled,
onClearCooldown,
clearingCooldown,
onRoutingStrategyChange,
updatingRoutingStrategy,
channels,
@@ -167,6 +171,14 @@ function RouteCardInner({
const priorityBuckets = buildPriorityBuckets(channels || []);
const bucketEditorItems = buildPriorityBucketEditorItems(channels || []);
const renderClearCooldownButton = () => {
if (readOnlyRoute) return null;
return (
<button onClick={() => onClearCooldown(route.id)} className="btn btn-link btn-link-info" disabled={clearingCooldown}>
{clearingCooldown ? tr('清除中...') : tr('清除冷却')}
</button>
);
};
// Collapsed card
if (!expanded) {
@@ -325,6 +337,7 @@ function RouteCardInner({
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
{renderClearCooldownButton()}
{!readOnlyRoute && (explicitGroupRoute || !exactRoute) && (
<button onClick={() => onEdit(route)} className="btn btn-link">{tr('编辑群组')}</button>
)}
@@ -358,6 +371,7 @@ function RouteCardInner({
</div>
{!readOnlyRoute && (
<div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
{renderClearCooldownButton()}
{!exactRoute && (
<button onClick={() => onEdit(route)} className="btn btn-link">{explicitGroupRoute ? tr('编辑群组') : tr('编辑路由')}</button>
)}