// Auto-extracted from tasks-manager.js (verbatim) — augments TasksManager.prototype. Loaded after the base. Object.assign(TasksManager.prototype, { // Confirmation modal for deleteTask. Uses the shared openEoModal so it // visually matches every other destructive confirmation on the app // (Uninstall, Apply Configuration, etc). Resolves true if the user // confirms Delete, false on Cancel / backdrop click / close. _showDeleteTaskModal(task, isActive) { return new Promise((resolve) => { const escHtml = (s) => String(s == null ? '' : s) .replace(/&/g, '&').replace(//g, '>'); // Friendly title + app icon — mirrors the completion-toast format so // the modal's identity matches every other surface. const { isSystemTask, actionTitle, displayName, icon: taskIcon } = this._taskNotificationDescriptor(task); // For the modal we omit the "LibrePortal" subject (the eyebrow already // says "Delete Task") and just lead with the action: "Update Config". const modalSubject = isSystemTask ? '' : displayName; const taskLabel = modalSubject ? `${actionTitle} ${modalSubject}` : (actionTitle || (task && task.id) || 'Unknown task'); const taskStatus = (task && task.status) || 'unknown'; const warningTitle = isActive ? 'Active task' : 'This cannot be undone'; const warningText = isActive ? 'This task is still running or queued. It will be cancelled first, then deleted.' : 'The task and its logs will be permanently removed.'; const bodyHtml = `

${escHtml(warningTitle)}

${escHtml(warningText)}

${window.eoBadgeRow ? window.eoBadgeRow([ { label: `Status: ${taskStatus}`, variant: isActive ? 'warning' : 'info' } ]) : ''} `; let decided = false; const finish = (val, modal) => { if (decided) return; decided = true; if (modal) modal.close(); resolve(val); }; window.openEoModal({ id: 'delete-task-modal', size: 'sm', icon: taskIcon || undefined, iconAlt: displayName || 'Task', eyebrow: 'Delete Task', title: taskLabel, desc: 'Confirm to delete this task.', body: bodyHtml, actions: [ { label: 'Delete Task', variant: 'danger', onClick: (m) => finish(true, m) }, { label: 'Cancel', variant: 'secondary', onClick: (m) => finish(false, m) } ], onClose: () => finish(false, null) }); }); }, // Confirmation modal for clearAllTasks. Same openEoModal shape as // _showDeleteTaskModal so visual identity matches every other destructive // confirmation (Uninstall, Delete Task, …). Adds a "Cancel running tasks // too" toggle (off by default) — when off, running/queued tasks are // skipped; when on, they're cancelled first then deleted. // Resolves {confirmed, cancelRunning}. Cancel/backdrop/close → confirmed=false. // mode: 'all' (everything) or 'selected' (user-picked subset) — just // shapes the title/copy. _showClearAllModal(tasks, mode) { return new Promise((resolve) => { const escHtml = (s) => String(s == null ? '' : s) .replace(/&/g, '&').replace(//g, '>'); const isActive = (t) => t && (t.status === 'running' || t.status === 'queued' || t.status === 'pending'); const total = (tasks || []).length; const runningCount = (tasks || []).filter(isActive).length; const terminalCount = total - runningCount; const bodyHtml = `

This cannot be undone

All selected tasks and their logs will be permanently removed.

${window.eoBadgeRow ? window.eoBadgeRow([ { label: `Total: ${total}`, variant: 'info' }, ...(runningCount > 0 ? [{ label: `Running: ${runningCount}`, variant: 'warning' }] : []), ...(terminalCount > 0 ? [{ label: `Terminal: ${terminalCount}`, variant: 'success' }] : []), ]) : ''} ${runningCount > 0 ? ` ` : ''} `; let decided = false; const finish = (val, modal) => { if (decided) return; decided = true; if (modal) modal.close(); resolve(val); }; // Title shape depends on which path got us here: // selected → "Delete N selected task(s)?" (multi-select chip) // all → "Delete all N tasks?" (legacy Clear All) const isSelectedMode = mode === 'selected'; const titleText = isSelectedMode ? (total === 1 ? 'Delete 1 selected task?' : `Delete ${total} selected tasks?`) : (total === 1 ? 'Delete 1 task?' : `Delete all ${total} tasks?`); const m = window.openEoModal({ id: 'clear-all-tasks-modal', size: 'sm', eyebrow: isSelectedMode ? 'Delete Selected' : 'Delete Tasks', title: titleText, desc: isSelectedMode ? 'Confirm to delete the ticked tasks.' : 'Confirm to delete every task on the list.', body: bodyHtml, actions: [ { label: 'Delete', variant: 'danger', onClick: (modal) => { const cb = modal.bodyEl.querySelector('#clear-all-cancel-running'); finish({ confirmed: true, cancelRunning: !!(cb && cb.checked) }, modal); } }, { label: 'Cancel', variant: 'secondary', onClick: (modal) => finish({ confirmed: false }, modal) } ], onClose: () => finish({ confirmed: false }, null) }); // Live-update the danger button's label so the user knows exactly // what will happen as they flip the toggle. No-op when no running // tasks (no toggle in the body in that case). const cb = m.bodyEl.querySelector('#clear-all-cancel-running'); const deleteBtn = m.contentEl.querySelector('.btn-danger'); const updateLabel = () => { if (!deleteBtn) return; const cancelRunning = !!(cb && cb.checked); if (runningCount > 0 && !cancelRunning) { deleteBtn.textContent = `Delete ${terminalCount} (skip ${runningCount} running)`; } else { deleteBtn.textContent = total === 1 ? 'Delete Task' : `Delete ${total} Tasks`; } }; if (cb) cb.addEventListener('change', updateLabel); updateLabel(); }); }, });