From 94ebbb2497d12e4332d8ce2b84cbfc378b075883 Mon Sep 17 00:00:00 2001 From: Kelly Date: Sat, 13 Dec 2025 01:26:58 -0700 Subject: [PATCH] fix: State dropdown and locked platform in schedule modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - State Code → State dropdown with available states - Platform field locked to 'dutchie' (read-only) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- backend/src/routes/proxies.ts | 25 +++++++++++++++++++ cannaiq/dist/index.html | 2 +- cannaiq/src/pages/TasksDashboard.tsx | 36 +++++++++++++++------------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/backend/src/routes/proxies.ts b/backend/src/routes/proxies.ts index 40cf4587..15e7ee33 100755 --- a/backend/src/routes/proxies.ts +++ b/backend/src/routes/proxies.ts @@ -308,6 +308,31 @@ router.get('/retry-stats', async (req, res) => { } }); +// Mark all proxies as active +router.post('/activate-all', requireRole('superadmin', 'admin'), async (req, res) => { + try { + const result = await pool.query(` + UPDATE proxies + SET active = true, + failure_count = 0, + consecutive_403_count = 0 + WHERE active = false + RETURNING id + `); + + const countResult = await pool.query(`SELECT COUNT(*) as total FROM proxies`); + + res.json({ + message: `Activated ${result.rowCount} proxies`, + activated: result.rowCount, + total: parseInt(countResult.rows[0].total) + }); + } catch (error) { + console.error('Error activating proxies:', error); + res.status(500).json({ error: 'Failed to activate proxies' }); + } +}); + // Manually re-enable proxies that have passed their retry interval router.post('/reenable-failed', requireRole('superadmin', 'admin'), async (req, res) => { try { diff --git a/cannaiq/dist/index.html b/cannaiq/dist/index.html index bbf3c50c..3d4663b9 100644 --- a/cannaiq/dist/index.html +++ b/cannaiq/dist/index.html @@ -7,7 +7,7 @@ CannaIQ - Cannabis Menu Intelligence Platform - + diff --git a/cannaiq/src/pages/TasksDashboard.tsx b/cannaiq/src/pages/TasksDashboard.tsx index 169a5f02..57956a16 100644 --- a/cannaiq/src/pages/TasksDashboard.tsx +++ b/cannaiq/src/pages/TasksDashboard.tsx @@ -410,13 +410,21 @@ function ScheduleEditModal({ isOpen, schedule, onClose, onSave }: ScheduleEditMo const [intervalHours, setIntervalHours] = useState(4); const [priority, setPriority] = useState(0); const [stateCode, setStateCode] = useState(''); - const [platform, setPlatform] = useState('dutchie'); + const [platform] = useState('dutchie'); // Fixed to dutchie only const [loading, setLoading] = useState(false); const [error, setError] = useState(null); + const [availableStates, setAvailableStates] = useState([]); const isNew = !schedule; const isImmutable = schedule?.is_immutable ?? false; + // Fetch available states on mount + useEffect(() => { + api.getOrchestratorStates().then(data => { + setAvailableStates(data.states?.map((s: any) => s.state) || []); + }).catch(console.error); + }, []); + useEffect(() => { if (schedule) { setName(schedule.name); @@ -426,7 +434,6 @@ function ScheduleEditModal({ isOpen, schedule, onClose, onSave }: ScheduleEditMo setIntervalHours(schedule.interval_hours); setPriority(schedule.priority); setStateCode(schedule.state_code || ''); - setPlatform(schedule.platform || 'dutchie'); } else { // Reset for new schedule setName(''); @@ -436,7 +443,6 @@ function ScheduleEditModal({ isOpen, schedule, onClose, onSave }: ScheduleEditMo setIntervalHours(4); setPriority(0); setStateCode(''); - setPlatform('dutchie'); } setError(null); }, [schedule, isOpen]); @@ -587,30 +593,28 @@ function ScheduleEditModal({ isOpen, schedule, onClose, onSave }: ScheduleEditMo
- - State +
setPlatform(e.target.value)} - placeholder="e.g., dutchie" - disabled={isImmutable} - className={`w-full px-3 py-2 border border-gray-200 rounded-lg ${ - isImmutable ? 'bg-gray-100 text-gray-500 cursor-not-allowed' : '' - }`} + disabled + className="w-full px-3 py-2 border border-gray-200 rounded-lg bg-gray-100 text-gray-500 cursor-not-allowed" />