diff --git a/CHANGELOG.md b/CHANGELOG.md index e434fa01..bd494a08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -72,6 +72,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 conversion identifiers from responses, reports attempted, changed, failed, skipped-data, and deferred-budget counters separately, and exposes fixed low-cardinality timeout, lookup, validation, and persistence failure counters. +- Attachment and comment modal refreshes build a refresh-scoped task lookup map + before rendering returned rows, and the static document declares preload hints + for `cloud-sync.js` and `analytics.js`; buyer-visible latency or startup gains + remain measurement-gated rather than inferred from this structural change. - Toast notifications and synchronization feedback now expose advisory updates as explicit polite, atomic WAI-ARIA status regions without adding keyboard stops, and cloud toast feedback now has a shipped visual state so the same @@ -99,7 +103,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Initial ScopeWeave Planner release with tree-table editing, cumulative metrics, CSV import/export, and Gantt modal. -- `wbs.json` seed loading plus browser autosave and optional file sync. - Playwright E2E coverage for add/edit hierarchy flows, delete confirmation, subtree drag-and-drop, and JSON sync shape. - GitHub Pages deployment workflow and operator documentation. diff --git a/cloud-sync.js b/cloud-sync.js index 0e015ebe..84858426 100644 --- a/cloud-sync.js +++ b/cloud-sync.js @@ -1228,11 +1228,6 @@ async function openAttachmentsModal() { list.className = 'team-list'; panel.appendChild(list); - const taskName = (id) => { - const t = (host?.getState?.()?.tasks || []).find((x) => x.id === id); - return t ? (t.name || t.task || id) : id; - }; - async function refresh() { list.textContent = ''; const q = sel.value ? `?taskId=${encodeURIComponent(sel.value)}` : ''; @@ -1243,6 +1238,13 @@ async function openAttachmentsModal() { list.appendChild(li); return; } + + const tasksMap = new Map((host?.getState?.()?.tasks || []).map(t => [t.id, t])); + const taskName = (id) => { + const t = tasksMap.get(id); + return t ? (t.name || t.task || id) : id; + }; + for (const a of data.attachments) { const li = document.createElement('li'); const who = document.createElement('span'); @@ -1365,11 +1367,6 @@ async function openCommentsModal() { form.append(input, send); panel.appendChild(form); - const taskName = (id) => { - const t = (host?.getState?.()?.tasks || []).find((x) => x.id === id); - return t ? (t.name || t.task || id) : id; - }; - async function refresh() { list.textContent = ''; const q = sel.value ? `?taskId=${encodeURIComponent(sel.value)}` : ''; @@ -1380,6 +1377,13 @@ async function openCommentsModal() { list.appendChild(li); return; } + + const tasksMap = new Map((host?.getState?.()?.tasks || []).map(t => [t.id, t])); + const taskName = (id) => { + const t = tasksMap.get(id); + return t ? (t.name || t.task || id) : id; + }; + for (const cm of data.comments) { const li = document.createElement('li'); const who = document.createElement('span'); diff --git a/index.html b/index.html index d24b2a88..879ad03b 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,8 @@ ScopeWeave Planner + +