mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-08-02 17:28:05 +00:00
fix(tools-tab): resolve remaining PR review comments
- api_v3: use getattr(api_v3, 'plugin_manager', None) instead of the module-level plugin_manager (always None); app.py sets the blueprint attribute, not the module global, so the fallback to plugin-repos was always taken - pages_v3: replace broad except Exception in _load_tools_partial with specific TemplateNotFound / OSError handlers and add [Pages V3][Tools] context prefix to log messages and error responses for easier Pi debugging - base.html: add Tools tab branch to the HTMX-unavailable fallback block in loadTabContent so the tab loads gracefully via direct fetch if HTMX never initialises Skipped: auth on execute_system_action — pre-existing app-wide design; reboot/shutdown and all other system actions share the same exposure. An app-level auth layer is the correct fix and is out of scope here. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
344f64ebba
commit
06ea4aa496
@@ -1666,7 +1666,8 @@ def execute_system_action():
|
|||||||
'output': _truncate_output(result.stdout, result.stderr)
|
'output': _truncate_output(result.stdout, result.stderr)
|
||||||
})
|
})
|
||||||
elif action == 'install_plugin_requirements':
|
elif action == 'install_plugin_requirements':
|
||||||
plugins_dir = Path(plugin_manager.plugins_dir) if plugin_manager else PROJECT_ROOT / 'plugin-repos'
|
active_pm = getattr(api_v3, 'plugin_manager', None)
|
||||||
|
plugins_dir = Path(active_pm.plugins_dir) if active_pm else PROJECT_ROOT / 'plugin-repos'
|
||||||
results = []
|
results = []
|
||||||
if plugins_dir.exists():
|
if plugins_dir.exists():
|
||||||
for p in sorted(plugins_dir.iterdir()):
|
for p in sorted(plugins_dir.iterdir()):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from flask import Blueprint, render_template, flash
|
from flask import Blueprint, render_template, flash
|
||||||
|
from jinja2 import TemplateNotFound
|
||||||
from markupsafe import escape
|
from markupsafe import escape
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@@ -454,9 +455,12 @@ def _load_tools_partial():
|
|||||||
"""Load tools/utilities partial."""
|
"""Load tools/utilities partial."""
|
||||||
try:
|
try:
|
||||||
return render_template('v3/partials/tools.html')
|
return render_template('v3/partials/tools.html')
|
||||||
except Exception:
|
except TemplateNotFound:
|
||||||
logger.error("Error loading partial", exc_info=True)
|
logger.error("[Pages V3][Tools] Template not found: v3/partials/tools.html", exc_info=True)
|
||||||
return "Error loading partial", 500
|
return "[Pages V3][Tools] Template is missing.", 500
|
||||||
|
except OSError as exc:
|
||||||
|
logger.error("[Pages V3][Tools] I/O error loading tools partial: %s", exc, exc_info=True)
|
||||||
|
return "[Pages V3][Tools] Failed to load due to a file system error. Check logs.", 500
|
||||||
|
|
||||||
|
|
||||||
def _load_plugin_config_partial(plugin_id):
|
def _load_plugin_config_partial(plugin_id):
|
||||||
|
|||||||
@@ -1922,6 +1922,21 @@
|
|||||||
if (tab === 'overview' && typeof loadOverviewDirect === 'function') loadOverviewDirect();
|
if (tab === 'overview' && typeof loadOverviewDirect === 'function') loadOverviewDirect();
|
||||||
else if (tab === 'wifi' && typeof loadWifiDirect === 'function') loadWifiDirect();
|
else if (tab === 'wifi' && typeof loadWifiDirect === 'function') loadWifiDirect();
|
||||||
else if (tab === 'plugins' && typeof loadPluginsDirect === 'function') loadPluginsDirect();
|
else if (tab === 'plugins' && typeof loadPluginsDirect === 'function') loadPluginsDirect();
|
||||||
|
else if (tab === 'tools') {
|
||||||
|
fetch('/v3/partials/tools')
|
||||||
|
.then(r => {
|
||||||
|
if (!r.ok) throw new Error(r.status + ' ' + r.statusText);
|
||||||
|
return r.text();
|
||||||
|
})
|
||||||
|
.then(html => {
|
||||||
|
contentEl.innerHTML = html;
|
||||||
|
contentEl.setAttribute('data-loaded', 'true');
|
||||||
|
if (window.Alpine) window.Alpine.initTree(contentEl);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Failed to load tools content:', err);
|
||||||
|
contentEl.innerHTML = '<div class="bg-red-50 border border-red-200 rounded-lg p-4"><p class="text-red-800">Failed to load Tools. Please refresh the page.</p></div>';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user