// [DEF:taskDrawer:Store] // @TIER: CRITICAL // @PURPOSE: Manage Task Drawer visibility and resource-to-task mapping // @LAYER: UI // @INVARIANT: resourceTaskMap always reflects current task associations // // @UX_STATE: Closed -> Drawer hidden, no active task // @UX_STATE: Open -> Drawer visible, logs streaming // @UX_STATE: InputRequired -> Interactive form rendered in drawer import { writable, derived } from 'svelte/store'; const initialState = { isOpen: false, activeTaskId: null, resourceTaskMap: {} }; export const taskDrawerStore = writable(initialState); /** * Open drawer for a specific task * @param {string} taskId - The task ID to show in drawer * @UX_STATE: Open -> Drawer visible, logs streaming */ export function openDrawerForTask(taskId) { console.log(`[taskDrawer.openDrawerForTask][Action] Opening drawer for task ${taskId}`); taskDrawerStore.update(state => ({ ...state, isOpen: true, activeTaskId: taskId })); } /** * Open drawer in list mode (no specific task) * @UX_STATE: Open -> Drawer visible, showing recent task list */ export function openDrawer() { console.log('[taskDrawer.openDrawer][Action] Opening drawer in list mode'); taskDrawerStore.update(state => ({ ...state, isOpen: true, activeTaskId: null })); } /** * Close the drawer (task continues running) * @UX_STATE: Closed -> Drawer hidden, no active task */ export function closeDrawer() { console.log('[taskDrawer.closeDrawer][Action] Closing drawer'); taskDrawerStore.update(state => ({ ...state, isOpen: false, activeTaskId: null })); } /** * Update resource-to-task mapping * @param {string} resourceId - Resource ID (dashboard uuid, dataset id, etc.) * @param {string} taskId - Task ID associated with this resource * @param {string} status - Task status (IDLE, RUNNING, WAITING_INPUT, SUCCESS, ERROR) */ export function updateResourceTask(resourceId, taskId, status) { console.log(`[taskDrawer.updateResourceTask][Action] Updating resource ${resourceId} -> task ${taskId}, status ${status}`); taskDrawerStore.update(state => { const newMap = { ...state.resourceTaskMap }; if (status === 'IDLE' || status === 'SUCCESS' || status === 'ERROR') { // Remove mapping when task completes delete newMap[resourceId]; } else { // Add or update mapping newMap[resourceId] = { taskId, status }; } return { ...state, resourceTaskMap: newMap }; }); } /** * Get task status for a specific resource * @param {string} resourceId - Resource ID * @returns {Object|null} Task info or null if no active task */ export function getTaskForResource(resourceId) { let result = null; taskDrawerStore.subscribe(state => { result = state.resourceTaskMap[resourceId] || null; })(); return result; } // [/DEF:taskDrawer:Store]