feat: Implement user profile preferences for start page, Git identity, and task drawer auto-open, alongside Git server default branch configuration.

This commit is contained in:
2026-03-08 10:19:38 +03:00
parent 12d17ec35e
commit e864a9e08b
30 changed files with 2041 additions and 211 deletions

View File

@@ -1,9 +1,17 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { get } from 'svelte/store';
import { taskDrawerStore, openDrawerForTask, closeDrawer, updateResourceTask } from '../taskDrawer.js';
import {
taskDrawerStore,
openDrawerForTask,
openDrawerForTaskIfPreferred,
closeDrawer,
updateResourceTask,
setTaskDrawerAutoOpenPreference
} from '../taskDrawer.js';
describe('taskDrawerStore', () => {
beforeEach(() => {
setTaskDrawerAutoOpenPreference(true);
taskDrawerStore.set({
isOpen: false,
activeTaskId: null,
@@ -26,6 +34,26 @@ describe('taskDrawerStore', () => {
expect(state.activeTaskId).toBe(null);
});
it('should open drawer via preference-aware helper when auto-open is enabled', () => {
setTaskDrawerAutoOpenPreference(true);
const opened = openDrawerForTaskIfPreferred('task-123');
const state = get(taskDrawerStore);
expect(opened).toBe(true);
expect(state.isOpen).toBe(true);
expect(state.activeTaskId).toBe('task-123');
});
it('should skip opening drawer via preference-aware helper when auto-open is disabled', () => {
setTaskDrawerAutoOpenPreference(false);
const opened = openDrawerForTaskIfPreferred('task-123');
const state = get(taskDrawerStore);
expect(opened).toBe(false);
expect(state.isOpen).toBe(false);
expect(state.activeTaskId).toBe(null);
});
it('should update resource task mapping for running task', () => {
updateResourceTask('dash-1', 'task-1', 'RUNNING');
const state = get(taskDrawerStore);

View File

@@ -21,7 +21,21 @@
// @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, derived } from 'svelte/store';
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,
@@ -37,12 +51,54 @@ export const taskDrawerStore = writable(initialState);
* @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);
}
/**