Merge claude/1
This commit is contained in:
commit
cd30d90a81
@ -774,7 +774,7 @@ class AppTabbedManager {
|
||||
|
||||
if (this.runningTasks.has(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
|
||||
// file shows up. Both events carry the same taskId; treat as a no-op.
|
||||
if (existing && existing.taskId === taskId) return;
|
||||
|
||||
@ -302,7 +302,15 @@ async configUpdate(changes) {
|
||||
}
|
||||
|
||||
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
|
||||
? window.tasksManager.getTaskTypeIcon({ type: action })
|
||||
: null)?.icon || '';
|
||||
@ -311,11 +319,11 @@ async configUpdate(changes) {
|
||||
? `${displayLabel} task started!`
|
||||
: `${action.charAt(0).toUpperCase() + action.slice(1)} task started!`;
|
||||
window.notificationSystem.show(
|
||||
`<strong>App: ${displayName}</strong><br>${headline}`,
|
||||
`<strong>${displayName}</strong><br>${headline}`,
|
||||
'success',
|
||||
appName,
|
||||
taskUrl,
|
||||
appIcon,
|
||||
notifIcon,
|
||||
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
|
||||
*/
|
||||
|
||||
@ -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
|
||||
@ -1452,18 +1410,22 @@ class TasksManager {
|
||||
}
|
||||
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
|
||||
? 'LibrePortal'
|
||||
: ((appName && window.getAppDisplayName)
|
||||
? window.getAppDisplayName(appName)
|
||||
: (appName || (task.command || `Task ${taskId}`)));
|
||||
const subjectLabel = isSystemTask ? 'System' : 'App';
|
||||
const onAppPage = window.location.pathname.startsWith('/app') && !window.location.pathname.startsWith('/apps');
|
||||
const url = (onAppPage && appName)
|
||||
? `/app/${appName}?tab=tasks&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
|
||||
// `getTaskTypeIcon`). Passed as the 6th `customIcon` arg so the
|
||||
@ -1475,13 +1437,13 @@ class TasksManager {
|
||||
let body;
|
||||
let level;
|
||||
if (task.status === 'completed') {
|
||||
body = `<strong>${subjectLabel}: ${displayName}</strong><br>${actionTitle} task completed!`;
|
||||
body = `<strong>${displayName}</strong><br>${actionTitle} task completed!`;
|
||||
level = 'success';
|
||||
} else if (task.status === 'failed') {
|
||||
body = `<strong>${subjectLabel}: ${displayName}</strong><br>${actionTitle} task failed.`;
|
||||
body = `<strong>${displayName}</strong><br>${actionTitle} task failed.`;
|
||||
level = 'error';
|
||||
} else if (task.status === 'cancelled') {
|
||||
body = `<strong>${subjectLabel}: ${displayName}</strong><br>${actionTitle} task cancelled.`;
|
||||
body = `<strong>${displayName}</strong><br>${actionTitle} task cancelled.`;
|
||||
level = 'warning';
|
||||
}
|
||||
if (body) window.notificationSystem.show(body, level, appName, url, icon, customIcon);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user