PlotDirector/PlotLine/wwwroot/js/character-enrichment-detail.js

138 lines
3.7 KiB
JavaScript

(() => {
const panel = document.querySelector("[data-character-analysis-panel]");
if (!panel || typeof signalR === "undefined") {
return;
}
const characterId = Number(panel.dataset.characterId || 0);
const initialBookId = Number(panel.dataset.bookId || 0);
const form = document.querySelector("[data-character-reanalyse-form]");
const button = document.querySelector("[data-character-reanalyse-button]");
const status = document.querySelector("[data-character-analysis-status]");
const message = document.querySelector("[data-character-analysis-message]");
const last = document.querySelector("[data-character-analysis-last]");
const summary = document.querySelector("[data-character-analysis-summary]");
if (!characterId) {
return;
}
const setBusy = (label) => {
if (button) {
button.disabled = true;
button.textContent = label;
}
};
const setReady = () => {
if (button) {
button.disabled = false;
button.textContent = "Reanalyse character";
}
};
const applySnapshot = (snapshot) => {
if (!snapshot || Number(snapshot.characterID || snapshot.characterId || 0) !== characterId) {
return;
}
const nextStatus = snapshot.status || snapshot.Status || "";
const nextMessage = snapshot.currentMessage || snapshot.CurrentMessage || "";
if (status) {
status.textContent = nextStatus || "Not analysed";
}
if (message) {
message.textContent = nextMessage;
}
if (nextStatus === "Queued") {
setBusy("Queued...");
return;
}
if (nextStatus === "Running") {
setBusy("Analysing...");
return;
}
if (nextStatus === "Completed") {
setReady();
if (last) {
last.textContent = "Just now";
}
window.setTimeout(() => window.location.reload(), 700);
return;
}
if (nextStatus === "Failed") {
setReady();
if (summary && !summary.textContent.trim()) {
summary.textContent = "No generated character analysis yet.";
summary.classList.add("muted");
}
}
};
const connection = new signalR.HubConnectionBuilder()
.withUrl("/hubs/story-intelligence")
.withAutomaticReconnect()
.build();
const refresh = () => {
connection.invoke("WatchCharacterEnrichmentForCharacter", characterId)
.then(applySnapshot)
.catch(() => {});
};
connection.on("CharacterEnrichmentProgressChanged", applySnapshot);
connection.onreconnected(refresh);
const start = () => {
connection.start()
.then(refresh)
.catch(() => window.setTimeout(start, 2000));
};
form?.addEventListener("submit", async (event) => {
if (!button || button.disabled) {
event.preventDefault();
return;
}
if (!window.fetch) {
return;
}
event.preventDefault();
setBusy("Queued...");
if (status) {
status.textContent = "Queued";
}
if (message) {
message.textContent = "Character reanalysis is queued.";
}
try {
const response = await fetch(form.action, {
method: "POST",
headers: { "X-Requested-With": "XMLHttpRequest" },
body: new FormData(form)
});
const payload = await response.json().catch(() => null);
if (!response.ok || payload?.success === false) {
throw new Error(payload?.message || "Character reanalysis could not be queued.");
}
applySnapshot(payload);
} catch (error) {
setReady();
if (status) {
status.textContent = "Failed";
}
if (message) {
message.textContent = error instanceof Error ? error.message : "Character reanalysis could not be queued.";
}
}
});
start();
})();