diff --git a/containers/libreportal/frontend/components/apps/core/js/instance-manager.js b/containers/libreportal/frontend/components/apps/core/js/instance-manager.js index 6410cc7..eab49e3 100644 --- a/containers/libreportal/frontend/components/apps/core/js/instance-manager.js +++ b/containers/libreportal/frontend/components/apps/core/js/instance-manager.js @@ -269,10 +269,22 @@ class InstanceManager { return; } try { + // Same lockout a normal uninstall applies (apps-manager executeUninstall): + // the instance's controls have to stop accepting input the moment removal + // starts, or its Config/Tools/Backups tabs stay live against an app that is + // being torn down underneath them. + if (window.appTabbedManager && typeof window.appTabbedManager.disableAppButtons === 'function') { + window.appTabbedManager.disableAppButtons(slug, 'uninstall'); + } + await window.tasksManager.router.routeAction('instance_remove', { appName: slug }); this.close(); notify(`Removing instance ${slug} — track progress in Tasks.`, 'success'); - const path = (typeof window.appPath === 'function') ? window.appPath(typeSlug, 'config') : `/app/${typeSlug}/config`; + // The INSTANCE's own Tasks tab, not the type's Config. The removal log is + // the only thing worth looking at at this point, and it is filed under the + // instance being removed — bouncing to the parent app hid the very task + // this click just started. + const path = (typeof window.appPath === 'function') ? window.appPath(slug, 'tasks') : `/app/${slug}/tasks`; if (window.librePortalSPA && window.librePortalSPA.navigateTo) { window.librePortalSPA.navigateTo(path); } else if (window.navigateToRoute) { diff --git a/containers/libreportal/frontend/components/tasks/js/tasks-format.js b/containers/libreportal/frontend/components/tasks/js/tasks-format.js index 04996a8..40a866e 100644 --- a/containers/libreportal/frontend/components/tasks/js/tasks-format.js +++ b/containers/libreportal/frontend/components/tasks/js/tasks-format.js @@ -37,6 +37,20 @@ Object.assign(TasksManager.prototype, { { match: /^libreportal peer remove\b/, title: 'LibrePortal - Remove Peer' }, { match: /^libreportal peer pair\b/, title: 'LibrePortal - Pair with Peer' }, + // -- Per-service restart ----------------------------------------------- + // Must precede nothing in particular (the generic `libreportal app + // ` handler lives below the table), but it needs a row at all: without + // one it collapsed to "Restart Application", losing the only detail that + // distinguishes it from restarting the whole app. + { match: /^libreportal app restart (\S+) (\S+)/, title: (m) => `${displayName(m[1])} - Restart ${m[2]}` }, + + // -- Instances --------------------------------------------------------- + // Named off the TYPE, not the new slug: at create time the instance does + // not exist in window.apps yet, so displayName() would fall back to + // capitalising the raw slug and render "Bookstack_work". + { match: /^libreportal instance create (\S+) (\S+)/, title: (m) => `${displayName(m[1])} - New Instance (${m[2]})` }, + { match: /^libreportal instance remove (\S+)/, title: (m) => `${displayName(m[1])} - Remove Instance` }, + // -- Regen ------------------------------------------------------------- { match: /^libreportal regen\b/, title: 'LibrePortal - Regenerate WebUI Data' }, @@ -48,6 +62,11 @@ Object.assign(TasksManager.prototype, { { match: /^libreportal system health check\b/, title: 'LibrePortal - System Health Check' }, { match: /^libreportal system network heal\b/, title: 'LibrePortal - Heal Network' }, { match: /^libreportal system network check\b/, title: 'LibrePortal - Check Network' }, + // These three are dispatched by the WebUI (see task-commands.js) and had no + // row, so they fell all the way through to the raw-command fallback. + { match: /^libreportal system status\b/, title: 'LibrePortal - System Status' }, + { match: /^libreportal system update\b/, title: 'LibrePortal - System Update' }, + { match: /^libreportal system reset\b/, title: 'LibrePortal - Reset System' }, // -- Backup: per-app (these capture the app slug) ---------------------- { match: /^libreportal backup app create (\w+)/, title: (m) => `${displayName(m[1])} - Create Backup` }, @@ -115,6 +134,13 @@ Object.assign(TasksManager.prototype, { 'rebuild': 'Rebuild Application', 'delete': 'Delete Backup', 'backup': 'Backup Application', + // Compose verbs the WebUI dispatches. Without these the generic + // " Application" fallback rendered "Up Application" and + // "Down Application", which read as broken English rather than a task. + 'up': 'Start Containers', + 'down': 'Stop Containers', + 'reload': 'Reload Application', + 'status': 'Check Status', }; const formattedAction = actionMap[action] || `${action.charAt(0).toUpperCase() + action.slice(1)} Application`; return `${displayName(appName)} - ${formattedAction}`;