Add structured logging and better error handling

This commit is contained in:
SirBlob committed 2026-11-01 13:50:26 -05:00
1 parent db4e3c9611
commit 68c7dd76f2
31 files changed
+640 -109

No files matched your search

+31 -10
View File
@@ -1,4 +1,4 @@
import { api, onUnauthorized } from "./api.js";
import { api, describeError, onUnauthorized } from "./api.js";
import { element } from "./dom.js";
import { destinationSelect, setAutoExtractDefault, setupDownloadForm, updateSubfolderState } from "./download-form.js";
import { formatBytes } from "./format.js";
@@ -12,6 +12,7 @@ import { renderTree, topLevelSelection } from "./tree.js";
const pollIntervalMs = 1500;
const filterStorageKey = "ddc-job-filter";
const failuresBeforeBanner = 2;
const elements = {
loginView: document.getElementById("login-view"),
@@ -21,6 +22,7 @@ const elements = {
logoutButton: document.getElementById("logout-button"),
settingsButton: document.getElementById("settings-button"),
diskStatus: document.getElementById("disk-status"),
connectionBanner: document.getElementById("connection-banner"),
jobFilter: document.getElementById("job-filter"),
clearCompletedButton: document.getElementById("clear-completed-button"),
jobList: document.getElementById("job-list"),
@@ -53,10 +55,12 @@ const state = {
selection: new Set(),
pollTimer: null,
refreshing: false,
failedRefreshes: 0,
};
function showLogin() {
stopPolling();
setConnectionProblem(null);
closeDetail();
elements.appView.hidden = true;
elements.loginView.hidden = false;
@@ -82,7 +86,7 @@ async function showSettings() {
try {
await openSettings();
} catch (error) {
window.alert(error.message);
window.alert(describeError(error));
}
}
@@ -127,15 +131,31 @@ async function refresh() {
updateSpeeds(state.jobs);
handleTransitions(collectTransitions(state.jobs));
elements.diskStatus.textContent = `${formatBytes(disk.availableBytes)} free`;
setConnectionProblem(null);
renderJobList();
await syncDetail();
} catch (error) {
if (error.status !== 401) console.error(error);
if (error.status !== 401) {
console.error(error);
setConnectionProblem(error);
}
} finally {
state.refreshing = false;
}
}
function setConnectionProblem(error) {
if (!error) {
state.failedRefreshes = 0;
elements.connectionBanner.hidden = true;
return;
}
state.failedRefreshes += 1;
if (state.failedRefreshes < failuresBeforeBanner) return;
elements.connectionBanner.textContent = `${describeError(error)} Retrying automatically.`;
elements.connectionBanner.hidden = false;
}
function handleTransitions(transitions) {
notifyTransitions(transitions);
if (transitions.some((transition) => transition.previous === "moving")) loadHistory();
@@ -166,7 +186,7 @@ async function runJobAction(action) {
await action();
await refresh();
} catch (error) {
window.alert(error.message);
window.alert(describeError(error));
}
}
@@ -183,7 +203,7 @@ function openDetail(job) {
renderJobList();
syncDetail();
loadLibraries().catch((error) => {
elements.actionError.textContent = error.message;
elements.actionError.textContent = describeError(error);
});
elements.detail.scrollIntoView({ behavior: "smooth", block: "start" });
}
@@ -230,7 +250,7 @@ async function loadTree(jobId) {
});
updateSelectionSummary();
} catch (error) {
elements.actionError.textContent = error.message;
elements.actionError.textContent = describeError(error);
}
}
@@ -247,7 +267,7 @@ async function extractArchive(path) {
await api.extract(state.selectedJobId, path);
await refresh();
} catch (error) {
elements.actionError.textContent = error.message;
elements.actionError.textContent = describeError(error);
}
}
@@ -266,7 +286,7 @@ async function moveSelection() {
elements.subfolderInput.value = "";
await refresh();
} catch (error) {
elements.actionError.textContent = error.message;
elements.actionError.textContent = describeError(error);
}
}
@@ -281,7 +301,7 @@ async function deleteJob(job) {
if (job.id === state.selectedJobId) closeDetail();
await refresh();
} catch (error) {
window.alert(error.message);
window.alert(describeError(error));
}
}
@@ -304,7 +324,7 @@ async function clearHistory() {
await api.clearHistory();
await loadHistory();
} catch (error) {
window.alert(error.message);
window.alert(describeError(error));
}
}
@@ -336,6 +356,7 @@ async function logout() {
}
async function init() {
window.addEventListener("unhandledrejection", (event) => console.error("Unhandled error", event.reason));
onUnauthorized(showLogin);
setupLogin(elements.loginForm, elements.loginError, showApp);
setupDownloadForm(refresh);