Commit 564e973
authored
fix(cockpit): four v-for :key collisions in Studio surfaces (#479)
* fix(cockpit): four v-for :key collisions in Studio surfaces
1) views/Studio.vue: receipts drawer used `r.service + r.correlation_id`
as key — bare concat collides on prefix boundaries (e.g. "gateway"+
"run-1" vs "gate"+"wayrun-1"). Use `${r.service}:${r.correlation_id}`
with an explicit separator (no dedicated id field on Receipt).
2) components/StudioQuery.vue: outer `<tr :key="i">` was index-as-key
and inner `<td :key="c">` (plus `<th :key="c">`) collided on
duplicate column names like `SELECT a.name, b.name FROM ...`.
Switch outer to `${i}:${JSON.stringify(r).slice(0, 120)}` and both
header/body cell loops to `(c, colIdx)` with `${c}:${colIdx}`.
3) components/StudioCompute.vue: session receipt chain used
`unshift(res)` with `:key="i"`, so every prepend shifted every
existing row's key. Use `c.receipt?.id ?? \`row-${i}\`` — chain is
only fed ok/degraded results, which carry a sealed ComputeReceipt.id.
4) components/StudioGraph.vue: "How derived?" list used `:key="i"` on
server-ordered `derived.derivations`, so the epistemic-mode pill
would mislabel edges when the array reordered. Use
`${d.direction}:${d.relation}:${d.with.id}` — direction + relation +
target-node id uniquely identifies each edge.
* Copilot round-2: computed row-keys, per-entry local ids, order stability
Three Copilot findings on the initial patch, all real:
1. `JSON.stringify(r).slice(...)` ran on EVERY reactivity tick for every
row (expensive on large result sets). Extracted to a `computed` keyed
off `result.value.rows` — recomputed only when the result set itself
changes, not per render. Keys are now derived via a cheap FNV-1a
32-bit rolling hash (bounded to 512 chars of JSON to keep it fast).
2. The key still included the loop index `i`, so any row reordering
forced DOM recreation. Now content-only signatures with a stable
disambiguator only when the SAME content appears twice — reordering
distinct rows preserves each row's DOM identity.
3. StudioCompute's `row-${i}` fallback reintroduced the original
`unshift` instability for entries with no receipt id. Added a
per-session `localId` assigned at insertion (`local-1`, `local-2`,
…) and gated all chain unshift() call sites through a new
`appendToChain()` helper. Key is now `c.receipt?.id ?? c.localId` —
stable in all degraded/no-receipt cases.1 parent 493841d commit 564e973
4 files changed
Lines changed: 57 additions & 10 deletions
File tree
- socioprophet-web/app-vue/src
- components
- views
Lines changed: 15 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
| 35 | + | |
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
114 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
115 | 126 | | |
116 | 127 | | |
117 | 128 | | |
| |||
150 | 161 | | |
151 | 162 | | |
152 | 163 | | |
153 | | - | |
| 164 | + | |
154 | 165 | | |
155 | 166 | | |
156 | 167 | | |
| |||
382 | 393 | | |
383 | 394 | | |
384 | 395 | | |
385 | | - | |
| 396 | + | |
386 | 397 | | |
387 | 398 | | |
388 | 399 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
306 | 306 | | |
307 | 307 | | |
308 | 308 | | |
309 | | - | |
| 309 | + | |
310 | 310 | | |
311 | 311 | | |
312 | 312 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
35 | 71 | | |
36 | 72 | | |
37 | 73 | | |
| |||
64 | 100 | | |
65 | 101 | | |
66 | 102 | | |
67 | | - | |
| 103 | + | |
68 | 104 | | |
69 | | - | |
70 | | - | |
| 105 | + | |
| 106 | + | |
71 | 107 | | |
72 | 108 | | |
73 | 109 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
180 | 180 | | |
181 | 181 | | |
182 | 182 | | |
183 | | - | |
| 183 | + | |
184 | 184 | | |
185 | 185 | | |
186 | 186 | | |
| |||
0 commit comments