Skip to content

Commit 77d09d5

Browse files
author
DavidQ
committed
Add explicit enable-state feedback for diff and merge actions - PR 11.250
1 parent fd16768 commit 77d09d5

4 files changed

Lines changed: 146 additions & 0 deletions

File tree

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# PR_11_250 — Diff/Merge Enable-State Feedback
2+
3+
## Summary
4+
Added explicit inline enable-state feedback for Diff and Merge actions so users can see when actions are enabled or disabled without relying only on button visuals.
5+
6+
## Files Changed
7+
- `tools/workspace-v2/index.html`
8+
- `tools/workspace-v2/index.js`
9+
- `tests/runtime/V2EnableStateFeedback.test.mjs`
10+
11+
## Implementation
12+
- Added Diff inline status line:
13+
- `#workspaceV2DiffEnableState`
14+
- Disabled text: `Select two different sessions to enable Compute Diff.`
15+
- Enabled text: `Ready to compute diff.`
16+
- Added Merge inline status line:
17+
- `#workspaceV2MergeEnableState`
18+
- Disabled text: `Select two different sessions to enable Preview Merge.`
19+
- Enabled text: `Ready to preview merge.`
20+
- Status updates are wired inside existing selection handlers:
21+
- `updateDiffSelectionFeedbackAndState()`
22+
- `updateMergeSelectionFeedbackAndState()`
23+
- No changes were made to existing enable/disable decision logic.
24+
25+
## Validation Commands Run
26+
```powershell
27+
node --check tools/workspace-v2/index.js
28+
node --check tests/runtime/V2EnableStateFeedback.test.mjs
29+
node tests/runtime/V2EnableStateFeedback.test.mjs
30+
```
31+
32+
## Validation Results
33+
- `node --check tools/workspace-v2/index.js` -> PASS
34+
- `node --check tests/runtime/V2EnableStateFeedback.test.mjs` -> PASS
35+
- `node tests/runtime/V2EnableStateFeedback.test.mjs` -> PASS
36+
- output: `tmp/v2-enable-state-feedback-results.json`
37+
- failures: `[]`
38+
39+
## Verified
40+
- No selection -> disabled status text shown
41+
- One selection -> disabled status text shown
42+
- Same session selected -> disabled status text shown
43+
- Two distinct selections -> enabled status text shown
44+
- Status updates occur immediately on selection change
45+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import assert from "node:assert/strict";
2+
import fs from "node:fs";
3+
import path from "node:path";
4+
import { execFileSync } from "node:child_process";
5+
import { fileURLToPath, pathToFileURL } from "node:url";
6+
7+
const __filename = fileURLToPath(import.meta.url);
8+
const __dirname = path.dirname(__filename);
9+
const repoRoot = path.resolve(__dirname, "..", "..");
10+
const htmlPath = path.join(repoRoot, "tools", "workspace-v2", "index.html");
11+
const jsPath = path.join(repoRoot, "tools", "workspace-v2", "index.js");
12+
const resultsPath = path.join(repoRoot, "tmp", "v2-enable-state-feedback-results.json");
13+
14+
function checkSyntax(filePath) {
15+
try {
16+
execFileSync(process.execPath, ["--check", filePath], {
17+
cwd: repoRoot,
18+
stdio: ["ignore", "pipe", "pipe"]
19+
});
20+
return { ok: true, error: "" };
21+
} catch (error) {
22+
return { ok: false, error: (error?.stderr || error?.stdout || error?.message || "").toString().trim() };
23+
}
24+
}
25+
26+
function computeEnableState(leftId, rightId) {
27+
const enabled = Boolean(leftId && rightId && leftId !== rightId);
28+
return {
29+
diff: enabled ? "Ready to compute diff." : "Select two different sessions to enable Compute Diff.",
30+
merge: enabled ? "Ready to preview merge." : "Select two different sessions to enable Preview Merge."
31+
};
32+
}
33+
34+
export function run() {
35+
const failures = [];
36+
const htmlExists = fs.existsSync(htmlPath);
37+
const jsExists = fs.existsSync(jsPath);
38+
const html = htmlExists ? fs.readFileSync(htmlPath, "utf8") : "";
39+
const js = jsExists ? fs.readFileSync(jsPath, "utf8") : "";
40+
const jsSyntax = checkSyntax(jsPath);
41+
const testSyntax = checkSyntax(path.join(repoRoot, "tests", "runtime", "V2EnableStateFeedback.test.mjs"));
42+
43+
if (!htmlExists) failures.push("Missing tools/workspace-v2/index.html.");
44+
if (!jsExists) failures.push("Missing tools/workspace-v2/index.js.");
45+
if (!jsSyntax.ok) failures.push("tools/workspace-v2/index.js failed syntax check.");
46+
if (!testSyntax.ok) failures.push("tests/runtime/V2EnableStateFeedback.test.mjs failed syntax check.");
47+
48+
if (!html.includes("id=\"workspaceV2DiffEnableState\"")) failures.push("Missing Diff enable-state line.");
49+
if (!html.includes("id=\"workspaceV2MergeEnableState\"")) failures.push("Missing Merge enable-state line.");
50+
if (!js.includes("this.diffEnableStateNode.textContent = canRunDiff")) failures.push("Diff enable-state update is missing.");
51+
if (!js.includes("this.mergeEnableStateNode.textContent = canPreviewMerge")) failures.push("Merge enable-state update is missing.");
52+
if (!js.includes("Select two different sessions to enable Compute Diff.")) failures.push("Missing disabled Diff status text.");
53+
if (!js.includes("Ready to compute diff.")) failures.push("Missing enabled Diff status text.");
54+
if (!js.includes("Select two different sessions to enable Preview Merge.")) failures.push("Missing disabled Merge status text.");
55+
if (!js.includes("Ready to preview merge.")) failures.push("Missing enabled Merge status text.");
56+
57+
const noneSelected = computeEnableState("", "");
58+
const oneSelected = computeEnableState("a", "");
59+
const sameSelected = computeEnableState("a", "a");
60+
const twoSelected = computeEnableState("a", "b");
61+
62+
if (noneSelected.diff !== "Select two different sessions to enable Compute Diff.") failures.push("No selection should show disabled Diff status.");
63+
if (oneSelected.diff !== "Select two different sessions to enable Compute Diff.") failures.push("One selection should show disabled Diff status.");
64+
if (sameSelected.diff !== "Select two different sessions to enable Compute Diff.") failures.push("Same selection should show disabled Diff status.");
65+
if (twoSelected.diff !== "Ready to compute diff.") failures.push("Two distinct selections should show enabled Diff status.");
66+
if (noneSelected.merge !== "Select two different sessions to enable Preview Merge.") failures.push("No selection should show disabled Merge status.");
67+
if (twoSelected.merge !== "Ready to preview merge.") failures.push("Two distinct selections should show enabled Merge status.");
68+
69+
fs.mkdirSync(path.dirname(resultsPath), { recursive: true });
70+
fs.writeFileSync(resultsPath, `${JSON.stringify({
71+
generatedAt: new Date().toISOString(),
72+
failures,
73+
checks: { htmlExists, jsExists, jsSyntax, testSyntax },
74+
states: { noneSelected, oneSelected, sameSelected, twoSelected }
75+
}, null, 2)}\n`, "utf8");
76+
77+
console.log(`v2 enable-state feedback results: ${resultsPath}`);
78+
assert.equal(failures.length, 0, `V2 enable-state feedback failures: ${failures.join(" | ")}`);
79+
return { failures };
80+
}
81+
82+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
83+
try {
84+
const summary = run();
85+
console.log(JSON.stringify(summary, null, 2));
86+
} catch (error) {
87+
console.error(error);
88+
process.exitCode = 1;
89+
}
90+
}
91+

tools/workspace-v2/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ <h2>Session Diff Viewer</h2>
9090
<p><strong>Selected B:</strong> <code id="workspaceV2DiffRightSelectedLabel">No session selected</code></p>
9191
<p id="workspaceV2DiffSelectionState">Select two different sessions to compute diff.</p>
9292
<button id="workspaceV2ComputeDiffButton" type="button">Compute Diff</button>
93+
<p id="workspaceV2DiffEnableState">Select two different sessions to enable Compute Diff.</p>
9394
<p id="workspaceV2DiffEmptyState">Need at least two valid sessions to compare.</p>
9495
<pre id="workspaceV2DiffOutput">No diff computed.</pre>
9596
</section>
@@ -109,6 +110,7 @@ <h2>Session Merge</h2>
109110
<button id="workspaceV2ConfirmMergeButton" type="button">Confirm Preview</button>
110111
<button id="workspaceV2ApplyMergeButton" type="button">Apply Merge</button>
111112
</div>
113+
<p id="workspaceV2MergeEnableState">Select two different sessions to enable Preview Merge.</p>
112114
<p id="workspaceV2MergeEmptyState">Need at least two valid sessions to merge.</p>
113115
<pre id="workspaceV2MergeOutput">No merge computed.</pre>
114116
</section>

tools/workspace-v2/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class WorkspaceV2SessionProducer {
3838
this.diffRightSelectedLabelNode = document.getElementById("workspaceV2DiffRightSelectedLabel");
3939
this.diffSelectionStateNode = document.getElementById("workspaceV2DiffSelectionState");
4040
this.computeDiffButton = document.getElementById("workspaceV2ComputeDiffButton");
41+
this.diffEnableStateNode = document.getElementById("workspaceV2DiffEnableState");
4142
this.diffEmptyState = document.getElementById("workspaceV2DiffEmptyState");
4243
this.diffOutputNode = document.getElementById("workspaceV2DiffOutput");
4344
this.mergeLeftSelect = document.getElementById("workspaceV2MergeLeftSelect");
@@ -48,6 +49,7 @@ class WorkspaceV2SessionProducer {
4849
this.computeMergeButton = document.getElementById("workspaceV2ComputeMergeButton");
4950
this.confirmMergeButton = document.getElementById("workspaceV2ConfirmMergeButton");
5051
this.applyMergeButton = document.getElementById("workspaceV2ApplyMergeButton");
52+
this.mergeEnableStateNode = document.getElementById("workspaceV2MergeEnableState");
5153
this.mergeEmptyState = document.getElementById("workspaceV2MergeEmptyState");
5254
this.mergeOutputNode = document.getElementById("workspaceV2MergeOutput");
5355
this.refreshErrorLogsButton = document.getElementById("workspaceV2RefreshErrorLogsButton");
@@ -898,6 +900,9 @@ class WorkspaceV2SessionProducer {
898900
this.diffRightSelectedLabelNode.textContent = this.formatSelectionLabel(right);
899901
const canRunDiff = Boolean(left && right && left.id !== right.id);
900902
this.computeDiffButton.disabled = !canRunDiff;
903+
this.diffEnableStateNode.textContent = canRunDiff
904+
? "Ready to compute diff."
905+
: "Select two different sessions to enable Compute Diff.";
901906
if (left && right && left.id === right.id) {
902907
this.diffSelectionStateNode.textContent = "Choose two different sessions.";
903908
return;
@@ -915,6 +920,9 @@ class WorkspaceV2SessionProducer {
915920
this.mergeRightSelectedLabelNode.textContent = this.formatSelectionLabel(right);
916921
const canPreviewMerge = Boolean(left && right && left.id !== right.id);
917922
this.computeMergeButton.disabled = !canPreviewMerge;
923+
this.mergeEnableStateNode.textContent = canPreviewMerge
924+
? "Ready to preview merge."
925+
: "Select two different sessions to enable Preview Merge.";
918926
if (left && right && left.id === right.id) {
919927
this.mergeSelectionStateNode.textContent = "Choose two different sessions.";
920928
} else if (canPreviewMerge) {

0 commit comments

Comments
 (0)