diff --git a/containers/libreportal/frontend/js/components/tasks/tasks-manager.js b/containers/libreportal/frontend/js/components/tasks/tasks-manager.js index ce08c84..86a6dd4 100755 --- a/containers/libreportal/frontend/js/components/tasks/tasks-manager.js +++ b/containers/libreportal/frontend/js/components/tasks/tasks-manager.js @@ -870,59 +870,69 @@ class TasksManager { formatCommandForUser(task) { if (!task.command) return 'Unknown Task'; + // Declarative pattern table — order matters (first match wins, so put + // specific patterns ahead of catch-alls). `title` is either a literal + // string or a function taking the regex match and returning the title; + // the latter is used for per-app patterns that extract the app slug. + // + // Adding a new task: just append one row here. Add the matching command + // shape in the WebUI submission site and you're done — no new branch + // needed in this function. const displayName = (slug) => window.getAppDisplayName ? window.getAppDisplayName(slug) : (slug.charAt(0).toUpperCase() + slug.slice(1)); - if (/^libreportal setup config\b/.test(task.command)) return 'LibrePortal - Apply Configuration'; - if (/^libreportal setup finalize\b/.test(task.command)) return 'LibrePortal - Finalize Setup'; - if (/^libreportal setup apply\b/.test(task.command)) return 'LibrePortal - Setup Wizard'; + const PATTERNS = [ + // -- System / setup ---------------------------------------------------- + { match: /^libreportal setup config\b/, title: 'LibrePortal - Apply Configuration' }, + { match: /^libreportal setup finalize\b/, title: 'LibrePortal - Finalize Setup' }, + { match: /^libreportal setup apply\b/, title: 'LibrePortal - Setup Wizard' }, + { match: /^libreportal config update\b/, title: 'LibrePortal - Apply Configuration' }, - // Self-update actions (WebUI "Update now" / "Check for updates"). - if (/^libreportal update (apply|now)\b/.test(task.command)) return 'LibrePortal - Update'; - if (/^libreportal update check\b/.test(task.command)) return 'LibrePortal - Check for Updates'; + // -- Self-update ------------------------------------------------------- + { match: /^libreportal update (apply|now)\b/, title: 'LibrePortal - Update' }, + { match: /^libreportal update check\b/, title: 'LibrePortal - Check for Updates' }, - // Backup engine — per-app actions. - const backupDeleteAllMatch = task.command.match(/libreportal backup app delete_all (\w+)/); - if (backupDeleteAllMatch) return `${displayName(backupDeleteAllMatch[1])} - Delete All Backups`; + // -- Peers ------------------------------------------------------------- + { match: /^libreportal peer add\b/, title: 'LibrePortal - Add Peer' }, + { match: /^libreportal peer remove\b/, title: 'LibrePortal - Remove Peer' }, + { match: /^libreportal peer pair\b/, title: 'LibrePortal - Pair with Peer' }, - const backupDeleteMatch = task.command.match(/libreportal backup app delete (\w+) (.+)/); - if (backupDeleteMatch) return `${displayName(backupDeleteMatch[1])} - Delete Backup`; + // -- Regen ------------------------------------------------------------- + { match: /^libreportal regen\b/, title: 'LibrePortal - Regenerate WebUI Data' }, - const backupCreateMatch = task.command.match(/^libreportal backup app create (\w+)/); - if (backupCreateMatch) return `${displayName(backupCreateMatch[1])} - Create Backup`; + // -- Backup: per-app (these capture the app slug) ---------------------- + { match: /^libreportal backup app create (\w+)/, title: (m) => `${displayName(m[1])} - Create Backup` }, + { match: /^libreportal backup app schedule (\w+)/, title: (m) => `${displayName(m[1])} - Scheduled Backup` }, + { match: /^libreportal backup app list (\w+)/, title: (m) => `${displayName(m[1])} - List Backups` }, + { match: /^libreportal backup app delete_all (\w+)/, title: (m) => `${displayName(m[1])} - Delete All Backups` }, + { match: /^libreportal backup app delete (\w+)/, title: (m) => `${displayName(m[1])} - Delete Backup` }, - const backupScheduleMatch = task.command.match(/^libreportal backup app schedule (\w+)/); - if (backupScheduleMatch) return `${displayName(backupScheduleMatch[1])} - Scheduled Backup`; + // -- Backup: system / locations ---------------------------------------- + { match: /^libreportal backup all\b/, title: 'LibrePortal - Backup All Apps' }, + { match: /^libreportal backup verify\b/, title: 'LibrePortal - Verify Backups' }, + { match: /^libreportal backup system\b/, title: 'LibrePortal - Backup System Config' }, + { match: /^libreportal backup location add\b/, title: 'LibrePortal - Add Backup Location' }, + { match: /^libreportal backup location remove\b/, title: 'LibrePortal - Remove Backup Location' }, + { match: /^libreportal backup location init\b/, title: 'LibrePortal - Initialise Backup Locations' }, + { match: /^libreportal backup location check\b/, title: 'LibrePortal - Check Backup Locations' }, + { match: /^libreportal backup location list\b/, title: 'LibrePortal - List Backup Locations' }, + { match: /^libreportal backup location stats\b/, title: 'LibrePortal - Backup Location Stats' }, - const backupListMatch = task.command.match(/^libreportal backup app list (\w+)/); - if (backupListMatch) return `${displayName(backupListMatch[1])} - List Backups`; + // -- Restore / migrate ------------------------------------------------- + { match: /^libreportal restore app start (\w+)/, title: (m) => `${displayName(m[1])} - Restore Backup` }, + { match: /^libreportal restore app list (\w+)/, title: (m) => `${displayName(m[1])} - List Backups` }, + { match: /^libreportal restore migrate app (\w+)/, title: (m) => `${displayName(m[1])} - Migrate from Host` }, + { match: /^libreportal restore migrate system\b/, title: 'LibrePortal - Migrate System' }, + { match: /^libreportal restore migrate discover\b/, title: 'LibrePortal - Discover Backups' }, + { match: /^libreportal restore first-run\b/, title: 'LibrePortal - First-Run Restore' }, + ]; - // Backup engine — restore actions. - const restoreStartMatch = task.command.match(/^libreportal restore app start (\w+)/); - if (restoreStartMatch) return `${displayName(restoreStartMatch[1])} - Restore Backup`; + for (const p of PATTERNS) { + const m = task.command.match(p.match); + if (m) return typeof p.title === 'function' ? p.title(m) : p.title; + } - const restoreListMatch = task.command.match(/^libreportal restore app list (\w+)/); - if (restoreListMatch) return `${displayName(restoreListMatch[1])} - List Backups`; - - const migrateAppMatch = task.command.match(/^libreportal restore migrate app (\w+)/); - if (migrateAppMatch) return `${displayName(migrateAppMatch[1])} - Migrate from Host`; - - // Backup engine — system-level actions (no per-app target). - if (/^libreportal backup all\b/.test(task.command)) return 'LibrePortal - Backup All Apps'; - if (/^libreportal backup verify\b/.test(task.command)) return 'LibrePortal - Verify Backups'; - if (/^libreportal backup location add\b/.test(task.command)) return 'LibrePortal - Add Backup Location'; - if (/^libreportal backup location remove\b/.test(task.command)) return 'LibrePortal - Remove Backup Location'; - if (/^libreportal backup location init\b/.test(task.command)) return 'LibrePortal - Initialise Backup Locations'; - if (/^libreportal backup location check\b/.test(task.command)) return 'LibrePortal - Check Backup Locations'; - if (/^libreportal backup location list\b/.test(task.command)) return 'LibrePortal - List Backup Locations'; - if (/^libreportal backup location stats\b/.test(task.command)) return 'LibrePortal - Backup Location Stats'; - if (/^libreportal restore migrate system\b/.test(task.command)) return 'LibrePortal - Migrate System'; - if (/^libreportal restore migrate discover\b/.test(task.command)) return 'LibrePortal - Discover Backups'; - if (/^libreportal restore first-run\b/.test(task.command)) return 'LibrePortal - First-Run Restore'; - - // `libreportal app tool ['']` — show the - // tool's friendly label instead of "Tool Application". Pull the - // label from window.toolsCatalog if loaded; otherwise titlecase - // the snake_case tool id. + // `libreportal app tool ['']` — needs the tools + // catalog to resolve the friendly label, so it lives outside the table. const toolMatch = task.command.match(/libreportal app tool (\S+) (\S+)/); if (toolMatch) { const appName = toolMatch[1]; @@ -939,13 +949,12 @@ class TasksManager { return `${displayName(appName)} - ${label}`; } - // Parse libreportal commands. Capture only the app name token — anything after - // (e.g. config overrides like `CFG_FOO=bar|...`) is for the CLI, not the title. + // Generic `libreportal app ` — capture the app token only; + // anything after (e.g. config overrides `CFG_FOO=bar|…`) is for the CLI. const libreportalMatch = task.command.match(/libreportal app (\w+) (\S+)/); if (libreportalMatch) { const action = libreportalMatch[1]; const appName = libreportalMatch[2]; - const actionMap = { 'install': 'Install Application', 'uninstall': 'Uninstall Application', @@ -955,23 +964,15 @@ class TasksManager { 'update': 'Update Application', 'rebuild': 'Rebuild Application', 'delete': 'Delete Backup', - 'backup': 'Backup Application' + 'backup': 'Backup Application', }; - const formattedAction = actionMap[action] || `${action.charAt(0).toUpperCase() + action.slice(1)} Application`; return `${displayName(appName)} - ${formattedAction}`; } - - // Handle other common patterns - if (task.command.includes('docker-compose')) { - return 'Docker Compose Operation'; - } - - if (task.command.includes('docker')) { - return 'Docker Operation'; - } - - // Return first 50 chars of command as fallback + + if (task.command.includes('docker-compose')) return 'Docker Compose Operation'; + if (task.command.includes('docker')) return 'Docker Operation'; + return task.command.length > 50 ? task.command.substring(0, 47) + '...' : task.command; }