Spaces:
Running on Zero
Running on Zero
fix: keep export controls synced with session changes
Browse files- static/app.js +14 -25
static/app.js
CHANGED
|
@@ -92,6 +92,7 @@ resetButton.addEventListener("click", () => {
|
|
| 92 |
goalsEl.addEventListener("change", (event) => {
|
| 93 |
const target = event.target;
|
| 94 |
if (!(target instanceof HTMLInputElement) || !target.dataset.goal) return;
|
|
|
|
| 95 |
const checked = new Set(
|
| 96 |
Array.from(goalsEl.querySelectorAll("input[data-goal]:checked")).map((input) => input.dataset.goal),
|
| 97 |
);
|
|
@@ -106,6 +107,7 @@ goalsEl.addEventListener("change", (event) => {
|
|
| 106 |
profileEl.addEventListener("input", (event) => {
|
| 107 |
const target = event.target;
|
| 108 |
if (!(target instanceof HTMLInputElement) || !target.dataset.profileField) return;
|
|
|
|
| 109 |
const profile = { ...(session.profile || {}) };
|
| 110 |
const value = target.value.trim();
|
| 111 |
if (value) {
|
|
@@ -168,8 +170,8 @@ async function runTurn(message) {
|
|
| 168 |
} finally {
|
| 169 |
clearTurnWatchdog();
|
| 170 |
submit.disabled = false;
|
| 171 |
-
setCommandDisabled(false);
|
| 172 |
setSessionControlsDisabled(false);
|
|
|
|
| 173 |
input.focus();
|
| 174 |
}
|
| 175 |
return completed;
|
|
@@ -345,9 +347,7 @@ function resetSession() {
|
|
| 345 |
renderProjects([], "Score an idea to see nearby echoes.");
|
| 346 |
renderWhitespace(bootstrapData.whitespace || []);
|
| 347 |
restoreExportButtonLabels();
|
| 348 |
-
|
| 349 |
-
setButtonDisabled(exportNotesButton, true);
|
| 350 |
-
setButtonDisabled(exportChapterButton, true);
|
| 351 |
saveSession();
|
| 352 |
input.focus();
|
| 353 |
}
|
|
@@ -372,8 +372,8 @@ async function loadDemoSession() {
|
|
| 372 |
ink.classList.add("bleed");
|
| 373 |
} finally {
|
| 374 |
submit.disabled = false;
|
| 375 |
-
setCommandDisabled(false);
|
| 376 |
setSessionControlsDisabled(false);
|
|
|
|
| 377 |
input.focus();
|
| 378 |
}
|
| 379 |
}
|
|
@@ -404,9 +404,7 @@ function applyDemoSession(data) {
|
|
| 404 |
} else {
|
| 405 |
renderProjects(data.projects || []);
|
| 406 |
}
|
| 407 |
-
|
| 408 |
-
setButtonDisabled(exportNotesButton, !(session.trace?.length));
|
| 409 |
-
setButtonDisabled(exportChapterButton, !(session.ideas?.length));
|
| 410 |
corrections.textContent = session.ui_status;
|
| 411 |
saveSession();
|
| 412 |
}
|
|
@@ -435,18 +433,15 @@ function renderRestoredSession(data) {
|
|
| 435 |
} else {
|
| 436 |
renderProjects([]);
|
| 437 |
}
|
| 438 |
-
exportButton.disabled = !currentArtifact;
|
| 439 |
} else {
|
| 440 |
renderScore(null);
|
| 441 |
setVerdictDisplay("READY", 0, null);
|
| 442 |
renderWoodMap(null);
|
| 443 |
renderProjects([], "Score an idea to see nearby echoes.");
|
| 444 |
-
exportButton.disabled = true;
|
| 445 |
}
|
| 446 |
renderIdeas(session.ideas || []);
|
| 447 |
renderPlan(session.last_plan || []);
|
| 448 |
-
|
| 449 |
-
setButtonDisabled(exportChapterButton, !(session.ideas?.length));
|
| 450 |
restoreSessionCopy();
|
| 451 |
}
|
| 452 |
|
|
@@ -624,10 +619,8 @@ function handleEvent(event) {
|
|
| 624 |
if (event.artifact?.title) {
|
| 625 |
currentArtifact = event.artifact;
|
| 626 |
renderWoodMap(event.artifact.wood_map || null);
|
| 627 |
-
exportButton.disabled = false;
|
| 628 |
}
|
| 629 |
-
|
| 630 |
-
setButtonDisabled(exportChapterButton, !(session.ideas?.length));
|
| 631 |
saveSession();
|
| 632 |
}
|
| 633 |
}
|
|
@@ -721,12 +714,12 @@ function renderSelectedIdeaArtifact(idea) {
|
|
| 721 |
currentArtifact = artifact;
|
| 722 |
session.last_artifact = artifact;
|
| 723 |
renderWoodMap(currentArtifact.wood_map || null);
|
| 724 |
-
|
| 725 |
return;
|
| 726 |
}
|
| 727 |
currentArtifact = null;
|
| 728 |
renderWoodMap(null);
|
| 729 |
-
|
| 730 |
}
|
| 731 |
|
| 732 |
function goalDisplayName(goal) {
|
|
@@ -869,17 +862,14 @@ function renderPlan(steps) {
|
|
| 869 |
}
|
| 870 |
}
|
| 871 |
|
| 872 |
-
function setButtonDisabled(button, disabled) {
|
| 873 |
-
if (button) button.disabled = disabled;
|
| 874 |
-
}
|
| 875 |
-
|
| 876 |
function setCommandDisabled(disabled) {
|
| 877 |
document.querySelectorAll(".command-row button").forEach((button) => {
|
| 878 |
const isArtifact = button.id === "export-artifact";
|
| 879 |
const isNotes = button.id === "export-notes";
|
| 880 |
const isChapter = button.id === "export-chapter";
|
|
|
|
| 881 |
button.disabled =
|
| 882 |
-
|
| 883 |
(isArtifact && !currentArtifact) ||
|
| 884 |
(isNotes && !session.trace?.length) ||
|
| 885 |
(isChapter && !session.ideas?.length);
|
|
@@ -928,7 +918,7 @@ function invalidateCurrentSeal(message) {
|
|
| 928 |
setVerdictDisplay("READY", 0, null);
|
| 929 |
renderWoodMap(null);
|
| 930 |
renderProjects([]);
|
| 931 |
-
|
| 932 |
if (message) setSessionStatus(message);
|
| 933 |
}
|
| 934 |
|
|
@@ -998,8 +988,7 @@ async function exportMarkdown({ endpoint, filename, button, busyLabel, pendingLa
|
|
| 998 |
corrections.textContent = session.ui_status;
|
| 999 |
} finally {
|
| 1000 |
setActionButtonLabel(button, idleLabel);
|
| 1001 |
-
if (
|
| 1002 |
-
saveSession();
|
| 1003 |
setCommandDisabled(false);
|
| 1004 |
}
|
| 1005 |
}
|
|
|
|
| 92 |
goalsEl.addEventListener("change", (event) => {
|
| 93 |
const target = event.target;
|
| 94 |
if (!(target instanceof HTMLInputElement) || !target.dataset.goal) return;
|
| 95 |
+
bumpSessionRevision();
|
| 96 |
const checked = new Set(
|
| 97 |
Array.from(goalsEl.querySelectorAll("input[data-goal]:checked")).map((input) => input.dataset.goal),
|
| 98 |
);
|
|
|
|
| 107 |
profileEl.addEventListener("input", (event) => {
|
| 108 |
const target = event.target;
|
| 109 |
if (!(target instanceof HTMLInputElement) || !target.dataset.profileField) return;
|
| 110 |
+
bumpSessionRevision();
|
| 111 |
const profile = { ...(session.profile || {}) };
|
| 112 |
const value = target.value.trim();
|
| 113 |
if (value) {
|
|
|
|
| 170 |
} finally {
|
| 171 |
clearTurnWatchdog();
|
| 172 |
submit.disabled = false;
|
|
|
|
| 173 |
setSessionControlsDisabled(false);
|
| 174 |
+
setCommandDisabled(false);
|
| 175 |
input.focus();
|
| 176 |
}
|
| 177 |
return completed;
|
|
|
|
| 347 |
renderProjects([], "Score an idea to see nearby echoes.");
|
| 348 |
renderWhitespace(bootstrapData.whitespace || []);
|
| 349 |
restoreExportButtonLabels();
|
| 350 |
+
setCommandDisabled(false);
|
|
|
|
|
|
|
| 351 |
saveSession();
|
| 352 |
input.focus();
|
| 353 |
}
|
|
|
|
| 372 |
ink.classList.add("bleed");
|
| 373 |
} finally {
|
| 374 |
submit.disabled = false;
|
|
|
|
| 375 |
setSessionControlsDisabled(false);
|
| 376 |
+
setCommandDisabled(false);
|
| 377 |
input.focus();
|
| 378 |
}
|
| 379 |
}
|
|
|
|
| 404 |
} else {
|
| 405 |
renderProjects(data.projects || []);
|
| 406 |
}
|
| 407 |
+
setCommandDisabled(false);
|
|
|
|
|
|
|
| 408 |
corrections.textContent = session.ui_status;
|
| 409 |
saveSession();
|
| 410 |
}
|
|
|
|
| 433 |
} else {
|
| 434 |
renderProjects([]);
|
| 435 |
}
|
|
|
|
| 436 |
} else {
|
| 437 |
renderScore(null);
|
| 438 |
setVerdictDisplay("READY", 0, null);
|
| 439 |
renderWoodMap(null);
|
| 440 |
renderProjects([], "Score an idea to see nearby echoes.");
|
|
|
|
| 441 |
}
|
| 442 |
renderIdeas(session.ideas || []);
|
| 443 |
renderPlan(session.last_plan || []);
|
| 444 |
+
setCommandDisabled(false);
|
|
|
|
| 445 |
restoreSessionCopy();
|
| 446 |
}
|
| 447 |
|
|
|
|
| 619 |
if (event.artifact?.title) {
|
| 620 |
currentArtifact = event.artifact;
|
| 621 |
renderWoodMap(event.artifact.wood_map || null);
|
|
|
|
| 622 |
}
|
| 623 |
+
setCommandDisabled(false);
|
|
|
|
| 624 |
saveSession();
|
| 625 |
}
|
| 626 |
}
|
|
|
|
| 714 |
currentArtifact = artifact;
|
| 715 |
session.last_artifact = artifact;
|
| 716 |
renderWoodMap(currentArtifact.wood_map || null);
|
| 717 |
+
setCommandDisabled(false);
|
| 718 |
return;
|
| 719 |
}
|
| 720 |
currentArtifact = null;
|
| 721 |
renderWoodMap(null);
|
| 722 |
+
setCommandDisabled(false);
|
| 723 |
}
|
| 724 |
|
| 725 |
function goalDisplayName(goal) {
|
|
|
|
| 862 |
}
|
| 863 |
}
|
| 864 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 865 |
function setCommandDisabled(disabled) {
|
| 866 |
document.querySelectorAll(".command-row button").forEach((button) => {
|
| 867 |
const isArtifact = button.id === "export-artifact";
|
| 868 |
const isNotes = button.id === "export-notes";
|
| 869 |
const isChapter = button.id === "export-chapter";
|
| 870 |
+
const locked = disabled || sessionControlsLocked;
|
| 871 |
button.disabled =
|
| 872 |
+
locked ||
|
| 873 |
(isArtifact && !currentArtifact) ||
|
| 874 |
(isNotes && !session.trace?.length) ||
|
| 875 |
(isChapter && !session.ideas?.length);
|
|
|
|
| 918 |
setVerdictDisplay("READY", 0, null);
|
| 919 |
renderWoodMap(null);
|
| 920 |
renderProjects([]);
|
| 921 |
+
setCommandDisabled(false);
|
| 922 |
if (message) setSessionStatus(message);
|
| 923 |
}
|
| 924 |
|
|
|
|
| 988 |
corrections.textContent = session.ui_status;
|
| 989 |
} finally {
|
| 990 |
setActionButtonLabel(button, idleLabel);
|
| 991 |
+
if (isCurrentSessionRevision(revision)) saveSession();
|
|
|
|
| 992 |
setCommandDisabled(false);
|
| 993 |
}
|
| 994 |
}
|