165 lines
5.1 KiB
JavaScript
165 lines
5.1 KiB
JavaScript
// [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
|
|
//
|
|
// @TEST_CONTRACT: TaskDrawerStore ->
|
|
// {
|
|
// required_fields: {isOpen: boolean, activeTaskId: string|null, resourceTaskMap: Object},
|
|
// invariants: [
|
|
// "Updates isOpen and activeTaskId properly on openDrawerForTask",
|
|
// "Updates isOpen and activeTaskId=null on openDrawer",
|
|
// "Properly sets isOpen=false on closeDrawer",
|
|
// "Maintains mapping in resourceTaskMap correctly via updateResourceTask"
|
|
// ]
|
|
// }
|
|
// @TEST_FIXTURE: valid_store_state -> {"isOpen": true, "activeTaskId": "test_1", "resourceTaskMap": {"res1": {"taskId": "test_1", "status": "RUNNING"}}}
|
|
// @TEST_INVARIANT: state_management -> verifies: [valid_store_state]
|
|
|
|
import { writable } from 'svelte/store';
|
|
|
|
const TASK_DRAWER_AUTO_OPEN_STORAGE_KEY = "ss_tools.profile.auto_open_task_drawer";
|
|
|
|
function readAutoOpenTaskDrawerPreference() {
|
|
if (typeof window === "undefined") {
|
|
return true;
|
|
}
|
|
const rawValue = window.localStorage.getItem(TASK_DRAWER_AUTO_OPEN_STORAGE_KEY);
|
|
if (rawValue === "false") return false;
|
|
if (rawValue === "true") return true;
|
|
return true;
|
|
}
|
|
|
|
let autoOpenTaskDrawerPreference = readAutoOpenTaskDrawerPreference();
|
|
|
|
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) {
|
|
if (!taskId) {
|
|
console.log("[taskDrawer.openDrawerForTask][Action] Skip open: taskId is empty");
|
|
return false;
|
|
}
|
|
console.log(`[taskDrawer.openDrawerForTask][Action] Opening drawer for task ${taskId}`);
|
|
taskDrawerStore.update(state => ({
|
|
...state,
|
|
isOpen: true,
|
|
activeTaskId: taskId
|
|
}));
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Update user preference for automatic drawer opening.
|
|
* @param {boolean} enabled - Whether automatic opening is enabled.
|
|
*/
|
|
export function setTaskDrawerAutoOpenPreference(enabled) {
|
|
autoOpenTaskDrawerPreference = enabled !== false;
|
|
if (typeof window !== "undefined") {
|
|
window.localStorage.setItem(
|
|
TASK_DRAWER_AUTO_OPEN_STORAGE_KEY,
|
|
autoOpenTaskDrawerPreference ? "true" : "false",
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Read current user preference for automatic drawer opening.
|
|
* @returns {boolean} true if automatic drawer opening is enabled.
|
|
*/
|
|
export function getTaskDrawerAutoOpenPreference() {
|
|
return autoOpenTaskDrawerPreference;
|
|
}
|
|
|
|
/**
|
|
* Open drawer for a task only when user preference allows auto-open.
|
|
* @param {string} taskId - The task ID to show in drawer.
|
|
* @returns {boolean} true if drawer was opened.
|
|
*/
|
|
export function openDrawerForTaskIfPreferred(taskId) {
|
|
if (autoOpenTaskDrawerPreference !== true) {
|
|
console.log(
|
|
`[taskDrawer.openDrawerForTaskIfPreferred][Action] Skip auto-open for task ${taskId}`,
|
|
);
|
|
return false;
|
|
}
|
|
return openDrawerForTask(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]
|