mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-05-25 13:43:31 +00:00
Address review feedback: error leaks, ok:false, htmx:ready coverage
- Backup endpoints: replace raw str(e) in user-facing responses with a generic message; full exception still logged via exc_info=True - hardware/status: change ok:null to ok:false for PermissionError and json.JSONDecodeError so the UI's hw.ok===false check triggers correctly - base.html: dispatch htmx:ready from the fallback load path so any deferred listeners fire on CDN-fallback loads too - loadTabContent: also listen for htmx-load-failed so overview/wifi/plugins fall back to direct fetch when HTMX is completely unavailable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1603,10 +1603,10 @@ def get_hardware_status():
|
||||
return jsonify({"status": "success", "data": {"ok": None, "error": "Display service not yet started"}})
|
||||
except PermissionError:
|
||||
logger.warning("Permission denied reading hardware status file; display service may be running as a different user")
|
||||
return jsonify({"status": "success", "data": {"ok": None, "error": "Hardware status temporarily unavailable"}})
|
||||
return jsonify({"status": "success", "data": {"ok": False, "error": "Hardware status temporarily unavailable"}})
|
||||
except json.JSONDecodeError:
|
||||
logger.error("Failed to parse hardware status file", exc_info=True)
|
||||
return jsonify({"status": "success", "data": {"ok": None, "error": "Hardware status file corrupted"}})
|
||||
return jsonify({"status": "success", "data": {"ok": False, "error": "Hardware status file corrupted"}})
|
||||
except Exception:
|
||||
logger.error("Unexpected error reading hardware status", exc_info=True)
|
||||
return jsonify({"status": "error", "message": "Unable to read hardware status"}), 500
|
||||
@@ -7099,7 +7099,7 @@ def backup_preview():
|
||||
return jsonify({'status': 'success', 'data': data})
|
||||
except Exception as e:
|
||||
logger.error("backup_preview failed: %s", e, exc_info=True)
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
return jsonify({'status': 'error', 'message': 'An internal error occurred; see logs for details'}), 500
|
||||
|
||||
|
||||
@api_v3.route('/backup/list', methods=['GET'])
|
||||
@@ -7120,7 +7120,7 @@ def backup_list():
|
||||
return jsonify({'status': 'success', 'data': entries})
|
||||
except Exception as e:
|
||||
logger.error("backup_list failed: %s", e, exc_info=True)
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
return jsonify({'status': 'error', 'message': 'An internal error occurred; see logs for details'}), 500
|
||||
|
||||
|
||||
@api_v3.route('/backup/export', methods=['POST'])
|
||||
@@ -7132,7 +7132,7 @@ def backup_export():
|
||||
return jsonify({'status': 'success', 'filename': zip_path.name})
|
||||
except Exception as e:
|
||||
logger.error("backup_export failed: %s", e, exc_info=True)
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
return jsonify({'status': 'error', 'message': 'An internal error occurred; see logs for details'}), 500
|
||||
|
||||
|
||||
@api_v3.route('/backup/validate', methods=['POST'])
|
||||
@@ -7158,7 +7158,7 @@ def backup_validate():
|
||||
return jsonify({'status': 'success', 'data': manifest})
|
||||
except Exception as e:
|
||||
logger.error("backup_validate failed: %s", e, exc_info=True)
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
return jsonify({'status': 'error', 'message': 'An internal error occurred; see logs for details'}), 500
|
||||
|
||||
|
||||
@api_v3.route('/backup/restore', methods=['POST'])
|
||||
@@ -7218,7 +7218,7 @@ def backup_restore():
|
||||
return jsonify({'status': 'success', 'data': data})
|
||||
except Exception as e:
|
||||
logger.error("backup_restore failed: %s", e, exc_info=True)
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
return jsonify({'status': 'error', 'message': 'An internal error occurred; see logs for details'}), 500
|
||||
|
||||
|
||||
@api_v3.route('/backup/download/<path:filename>', methods=['GET'])
|
||||
@@ -7241,4 +7241,5 @@ def backup_delete(filename):
|
||||
path.unlink()
|
||||
return jsonify({'status': 'success'})
|
||||
except OSError as e:
|
||||
return jsonify({'status': 'error', 'message': str(e)}), 500
|
||||
logger.error("backup_delete failed: %s", e, exc_info=True)
|
||||
return jsonify({'status': 'error', 'message': 'An internal error occurred; see logs for details'}), 500
|
||||
@@ -136,6 +136,7 @@
|
||||
setTimeout(function() {
|
||||
if (typeof htmx !== 'undefined') {
|
||||
console.log('HTMX loaded from fallback');
|
||||
window.dispatchEvent(new Event('htmx:ready'));
|
||||
// Load extensions after core loads
|
||||
loadScript(sseSrc, isAPMode ? 'https://unpkg.com/htmx.org/dist/ext/sse.js' : '/static/v3/js/htmx-sse.js');
|
||||
loadScript(jsonEncSrc, isAPMode ? 'https://unpkg.com/htmx.org/dist/ext/json-enc.js' : '/static/v3/js/htmx-json-enc.js');
|
||||
@@ -1839,11 +1840,18 @@
|
||||
htmx.trigger(contentEl, 'revealed');
|
||||
}
|
||||
} else {
|
||||
// HTMX is still loading asynchronously — retry once it signals ready
|
||||
// HTMX is still loading asynchronously — retry when it signals ready,
|
||||
// or fall back to direct fetch if it fails to load entirely.
|
||||
const self = this;
|
||||
window.addEventListener('htmx:ready', function retry() {
|
||||
self.loadTabContent(tab);
|
||||
}, { once: true });
|
||||
function onReady() { window.removeEventListener('htmx-load-failed', onFailed); self.loadTabContent(tab); }
|
||||
function onFailed() {
|
||||
window.removeEventListener('htmx:ready', onReady);
|
||||
if (tab === 'overview' && typeof loadOverviewDirect === 'function') loadOverviewDirect();
|
||||
else if (tab === 'wifi' && typeof loadWifiDirect === 'function') loadWifiDirect();
|
||||
else if (tab === 'plugins' && typeof loadPluginsDirect === 'function') loadPluginsDirect();
|
||||
}
|
||||
window.addEventListener('htmx:ready', onReady, { once: true });
|
||||
window.addEventListener('htmx-load-failed', onFailed, { once: true });
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user