Merge claude/1
This commit is contained in:
commit
cd30d90a81
@ -774,7 +774,7 @@ class AppTabbedManager {
|
|||||||
|
|
||||||
if (this.runningTasks.has(key)) {
|
if (this.runningTasks.has(key)) {
|
||||||
const existing = this.runningTasks.get(key);
|
const existing = this.runningTasks.get(key);
|
||||||
// Same task firing twice — `createAndExecuteTask` dispatches taskCreated
|
// Same task firing twice — executeTask dispatches taskCreated
|
||||||
// synchronously, and the SSE bus also dispatches it when the new task
|
// synchronously, and the SSE bus also dispatches it when the new task
|
||||||
// file shows up. Both events carry the same taskId; treat as a no-op.
|
// file shows up. Both events carry the same taskId; treat as a no-op.
|
||||||
if (existing && existing.taskId === taskId) return;
|
if (existing && existing.taskId === taskId) return;
|
||||||
|
|||||||
@ -302,7 +302,15 @@ async configUpdate(changes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (window.notificationSystem) {
|
if (window.notificationSystem) {
|
||||||
const displayName = window.getAppDisplayName ? window.getAppDisplayName(appName) : appName;
|
// `appName === 'system'` is a category sentinel (config_update,
|
||||||
|
// system_update — no real app). Resolve it to the LibrePortal
|
||||||
|
// logo + name so the toast doesn't read "App: System" with a
|
||||||
|
// broken /icons/apps/system.svg.
|
||||||
|
const isSystem = appName === 'system';
|
||||||
|
const displayName = isSystem
|
||||||
|
? 'LibrePortal'
|
||||||
|
: (window.getAppDisplayName ? window.getAppDisplayName(appName) : appName);
|
||||||
|
const notifIcon = isSystem ? '/icons/libreportal.svg' : appIcon;
|
||||||
const typeIcon = (window.tasksManager && window.tasksManager.getTaskTypeIcon
|
const typeIcon = (window.tasksManager && window.tasksManager.getTaskTypeIcon
|
||||||
? window.tasksManager.getTaskTypeIcon({ type: action })
|
? window.tasksManager.getTaskTypeIcon({ type: action })
|
||||||
: null)?.icon || '';
|
: null)?.icon || '';
|
||||||
@ -311,11 +319,11 @@ async configUpdate(changes) {
|
|||||||
? `${displayLabel} task started!`
|
? `${displayLabel} task started!`
|
||||||
: `${action.charAt(0).toUpperCase() + action.slice(1)} task started!`;
|
: `${action.charAt(0).toUpperCase() + action.slice(1)} task started!`;
|
||||||
window.notificationSystem.show(
|
window.notificationSystem.show(
|
||||||
`<strong>App: ${displayName}</strong><br>${headline}`,
|
`<strong>${displayName}</strong><br>${headline}`,
|
||||||
'success',
|
'success',
|
||||||
appName,
|
appName,
|
||||||
taskUrl,
|
taskUrl,
|
||||||
appIcon,
|
notifIcon,
|
||||||
customIcon
|
customIcon
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -330,64 +338,7 @@ async configUpdate(changes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Execute task monitoring (separated to avoid duplicate task creation)
|
|
||||||
*/
|
|
||||||
async executeTaskMonitoring(task, appName, action) {
|
|
||||||
// Emit task creation event for AppTabbedManager
|
|
||||||
window.dispatchEvent(new CustomEvent('taskCreated', {
|
|
||||||
detail: {
|
|
||||||
taskId: task.id,
|
|
||||||
appName: appName,
|
|
||||||
action: action,
|
|
||||||
timestamp: Date.now()
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// console.log(`✅ Task created: ${task.id} for ${action} on ${appName}`);
|
|
||||||
|
|
||||||
// Set up monitoring for this specific task
|
|
||||||
this.tasksManager.monitorTask(task.id, appName, action);
|
|
||||||
|
|
||||||
// Try to get app data for better notifications
|
|
||||||
let appData = null;
|
|
||||||
try {
|
|
||||||
appData = this.commands.getAppData ? this.commands.getAppData(appName) : null;
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Could not get app data:', error);
|
|
||||||
}
|
|
||||||
const appIcon = appData?.icon || `/icons/apps/${task.app}.svg`;
|
|
||||||
|
|
||||||
// Smart URL generation - always include app name
|
|
||||||
let taskUrl;
|
|
||||||
const currentUrl = window.location.href;
|
|
||||||
// console.log('🔍 TaskActions: Current URL:', currentUrl);
|
|
||||||
|
|
||||||
// Always generate URL with app name for proper navigation
|
|
||||||
if (currentUrl.includes('/app/') && appName) {
|
|
||||||
// We're on an app page, maintain app context
|
|
||||||
taskUrl = `/app/${appName}?tab=tasks&task=${task.id}`;
|
|
||||||
} else {
|
|
||||||
// We're on main tasks page, use normal URL
|
|
||||||
taskUrl = `/tasks/all?task=${task.id}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show success notification with app icon and direct link
|
|
||||||
if (window.notificationSystem) {
|
|
||||||
const displayName = window.getAppDisplayName ? window.getAppDisplayName(appName) : appName;
|
|
||||||
window.notificationSystem.show(
|
|
||||||
`<strong>App: ${displayName}</strong><br>
|
|
||||||
${action.charAt(0).toUpperCase() + action.slice(1)} task started!`,
|
|
||||||
'success',
|
|
||||||
appName,
|
|
||||||
taskUrl,
|
|
||||||
appIcon
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update task in the manager
|
* Update task in the manager
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1320,48 +1320,6 @@ class TasksManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.createAndExecuteTask = async (action, appName, config = '') => {
|
|
||||||
try {
|
|
||||||
// Create task using NEW signature
|
|
||||||
const task = await this.taskManager.createTask(`libreportal app ${action} ${appName}`, action, appName, config);
|
|
||||||
|
|
||||||
// Emit task creation event for AppTabbedManager
|
|
||||||
window.dispatchEvent(new CustomEvent('taskCreated', {
|
|
||||||
detail: {
|
|
||||||
taskId: task.id,
|
|
||||||
appName: appName,
|
|
||||||
action: action,
|
|
||||||
timestamp: Date.now()
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Set up monitoring for this specific task
|
|
||||||
this.monitorTask(task.id, appName, action);
|
|
||||||
|
|
||||||
// Show success notification with app icon and direct link
|
|
||||||
if (window.notificationSystem) {
|
|
||||||
const taskUrl = `/tasks/all?task=${task.id}`;
|
|
||||||
const typeIcon = this.getTaskTypeIcon ? this.getTaskTypeIcon({ type: action })?.icon : '';
|
|
||||||
const customIcon = typeIcon ? `<span style="font-size:18px;line-height:1;">${typeIcon}</span>` : null;
|
|
||||||
window.notificationSystem.show(
|
|
||||||
`Task created: ${action} ${appName}`,
|
|
||||||
'info',
|
|
||||||
appName,
|
|
||||||
taskUrl,
|
|
||||||
`/icons/apps/${appName}.svg`,
|
|
||||||
customIcon
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return task;
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`❌ Failed to create ${action} task for ${appName}:`, error);
|
|
||||||
if (window.notificationSystem) {
|
|
||||||
window.notificationSystem.error(`Failed to start ${action} task for ${appName}: ${error.message}`);
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single page-wide subscription to the TaskEventBus. This complements
|
// Single page-wide subscription to the TaskEventBus. This complements
|
||||||
@ -1452,18 +1410,22 @@ class TasksManager {
|
|||||||
}
|
}
|
||||||
actionTitle = toolLabel;
|
actionTitle = toolLabel;
|
||||||
}
|
}
|
||||||
const isSystemTask = action.startsWith('setup-');
|
// System-level tasks resolve to LibrePortal as the subject + use the
|
||||||
|
// LibrePortal logo as the app-icon. Covers `app: 'system'` (config
|
||||||
|
// update, system update) and `setup-*` types (setup wizard phases).
|
||||||
|
const isSystemTask = action.startsWith('setup-') || appName === 'system';
|
||||||
const displayName = isSystemTask
|
const displayName = isSystemTask
|
||||||
? 'LibrePortal'
|
? 'LibrePortal'
|
||||||
: ((appName && window.getAppDisplayName)
|
: ((appName && window.getAppDisplayName)
|
||||||
? window.getAppDisplayName(appName)
|
? window.getAppDisplayName(appName)
|
||||||
: (appName || (task.command || `Task ${taskId}`)));
|
: (appName || (task.command || `Task ${taskId}`)));
|
||||||
const subjectLabel = isSystemTask ? 'System' : 'App';
|
|
||||||
const onAppPage = window.location.pathname.startsWith('/app') && !window.location.pathname.startsWith('/apps');
|
const onAppPage = window.location.pathname.startsWith('/app') && !window.location.pathname.startsWith('/apps');
|
||||||
const url = (onAppPage && appName)
|
const url = (onAppPage && appName)
|
||||||
? `/app/${appName}?tab=tasks&task=${taskId}`
|
? `/app/${appName}?tab=tasks&task=${taskId}`
|
||||||
: `/tasks/all?task=${taskId}`;
|
: `/tasks/all?task=${taskId}`;
|
||||||
const icon = appName ? `/icons/apps/${appName}.svg` : null;
|
const icon = isSystemTask
|
||||||
|
? '/icons/libreportal.svg'
|
||||||
|
: (appName ? `/icons/apps/${appName}.svg` : null);
|
||||||
|
|
||||||
// Match the per-action emoji used in the task list rows (see
|
// Match the per-action emoji used in the task list rows (see
|
||||||
// `getTaskTypeIcon`). Passed as the 6th `customIcon` arg so the
|
// `getTaskTypeIcon`). Passed as the 6th `customIcon` arg so the
|
||||||
@ -1475,13 +1437,13 @@ class TasksManager {
|
|||||||
let body;
|
let body;
|
||||||
let level;
|
let level;
|
||||||
if (task.status === 'completed') {
|
if (task.status === 'completed') {
|
||||||
body = `<strong>${subjectLabel}: ${displayName}</strong><br>${actionTitle} task completed!`;
|
body = `<strong>${displayName}</strong><br>${actionTitle} task completed!`;
|
||||||
level = 'success';
|
level = 'success';
|
||||||
} else if (task.status === 'failed') {
|
} else if (task.status === 'failed') {
|
||||||
body = `<strong>${subjectLabel}: ${displayName}</strong><br>${actionTitle} task failed.`;
|
body = `<strong>${displayName}</strong><br>${actionTitle} task failed.`;
|
||||||
level = 'error';
|
level = 'error';
|
||||||
} else if (task.status === 'cancelled') {
|
} else if (task.status === 'cancelled') {
|
||||||
body = `<strong>${subjectLabel}: ${displayName}</strong><br>${actionTitle} task cancelled.`;
|
body = `<strong>${displayName}</strong><br>${actionTitle} task cancelled.`;
|
||||||
level = 'warning';
|
level = 'warning';
|
||||||
}
|
}
|
||||||
if (body) window.notificationSystem.show(body, level, appName, url, icon, customIcon);
|
if (body) window.notificationSystem.show(body, level, appName, url, icon, customIcon);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user