From 455bfa8734bf70ffad54b6fc3192ba1f9f16ce39 Mon Sep 17 00:00:00 2001 From: Anso Date: Tue, 7 Apr 2026 01:49:22 -0400 Subject: [PATCH] fix(schedules): filter auto-update policies from Scheduled Operations view (#420) * fix(schedules): filter auto-update policies from Scheduled Operations view Auto-update policies (action=update) were appearing in both the Auto-Update tab and the Scheduled Operations tab. Added server-side action/exclude_action query params to GET /api/scheduled-tasks. ScheduledOperationsView now requests ?exclude_action=update and AutoUpdatePoliciesView requests ?action=update, so each view only shows its relevant tasks. * fix(schedules): use typeof guard for query param type safety Express can parse ?action[]=x as an array. Use typeof === 'string' guard instead of unsafe type assertion. --- CHANGELOG.md | 1 + backend/src/index.ts | 8 ++++++++ frontend/src/components/AutoUpdatePoliciesView.tsx | 5 ++--- frontend/src/components/ScheduledOperationsView.tsx | 2 +- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cafe25af..bbb2cc80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed * **auto-update:** resolve failure when executing auto-update policies on remote Distributed API nodes. Previously, the scheduler tried to access the remote Docker daemon directly, which is not supported. Now the update execution is proxied to the remote Sencho instance via HTTP, matching the existing Distributed API architecture. +* **schedules:** auto-update policies no longer appear in the Scheduled Operations list. Each view now fetches only its relevant task type via server-side action filtering. ## [0.39.6](https://github.com/AnsoCode/Sencho/compare/v0.39.5...v0.39.6) (2026-04-07) diff --git a/backend/src/index.ts b/backend/src/index.ts index 7bb58194..e47c6d73 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -4518,6 +4518,14 @@ app.get('/api/scheduled-tasks', (req: Request, res: Response): void => { if (ls.getVariant() !== 'admiral') { tasks = tasks.filter(t => t.action === 'update'); } + // Separate Auto-Update and Scheduled Operations into distinct views + const actionFilter = typeof req.query.action === 'string' ? req.query.action : undefined; + const excludeAction = typeof req.query.exclude_action === 'string' ? req.query.exclude_action : undefined; + if (actionFilter) { + tasks = tasks.filter(t => t.action === actionFilter); + } else if (excludeAction) { + tasks = tasks.filter(t => t.action !== excludeAction); + } res.json(tasks); } catch (error) { console.error('[ScheduledTasks] List error:', error); diff --git a/frontend/src/components/AutoUpdatePoliciesView.tsx b/frontend/src/components/AutoUpdatePoliciesView.tsx index e40130c9..ce57e2ef 100644 --- a/frontend/src/components/AutoUpdatePoliciesView.tsx +++ b/frontend/src/components/AutoUpdatePoliciesView.tsx @@ -115,10 +115,9 @@ function AutoUpdatePoliciesContent({ filterNodeId, onClearFilter }: AutoUpdatePo const fetchPolicies = useCallback(async () => { setLoading(true); try { - const res = await apiFetch('/scheduled-tasks', { localOnly: true }); + const res = await apiFetch('/scheduled-tasks?action=update', { localOnly: true }); if (res.ok) { - const all: ScheduledTask[] = await res.json(); - setPolicies(all.filter(t => t.action === 'update')); + setPolicies(await res.json()); } } catch { // Non-critical diff --git a/frontend/src/components/ScheduledOperationsView.tsx b/frontend/src/components/ScheduledOperationsView.tsx index f140a597..a1a5098f 100644 --- a/frontend/src/components/ScheduledOperationsView.tsx +++ b/frontend/src/components/ScheduledOperationsView.tsx @@ -118,7 +118,7 @@ export default function ScheduledOperationsView({ filterNodeId, onClearFilter }: const fetchTasks = useCallback(async () => { setLoading(true); try { - const res = await apiFetch('/scheduled-tasks', { localOnly: true }); + const res = await apiFetch('/scheduled-tasks?exclude_action=update', { localOnly: true }); if (res.ok) { setTasks(await res.json()); }