feat: incremental tile streaming — host listeners + edit/delete/reorder gates - #134
Merged
romer8 merged 3 commits intoMay 28, 2026
Merged
Conversation
Add a dedicated StreamingContext (Contexts.js) for the chatbox-driven isStreaming flag. DashboardLoader.js owns the state, listens for the new tethysdash:turn-start / tethysdash:turn-end window events from @aquaveo/chatbox-core@>=0.16.0-beta.0, and provides via the new context. isStreaming lives in its own useState — separate from disabledEditingMovement — so the existing reset effect at lines 75-79 (which zeroes disabledEditingMovement when isEditing flips false) does NOT zero isStreaming spuriously. Dedicated context (rather than extending DisabledEditingMovementContext) keeps the re-render footprint to DashboardItem consumers only. The existing 4+ consumers of DisabledEditingMovementContext (Header, DashboardLayout, PopupLayoutEditor, DashboardItem) do NOT re-render on every turn boundary — addresses the fan-out concern flagged in the brainstorm/plan reviews. Test additions: - DashboardLoader.streaming.test.js (6 scenarios): initial-mount default false, turn-start flips true, turn-end flips back, idempotent duplicate starts, independence from DisabledEditingMovementContext, listener cleanup on unmount. - customRender.js adds StreamingPComponent helper for asserting context value in tests. Phase 2 of docs/plans/2026-05-28-002-feat-chatbox-core-incremental-tile-streaming-plan.md Unit 6.
…eaming
DashboardItem reads isStreaming from the new StreamingContext (Unit 6) and
short-circuits the three config-mutating handlers when true:
- editGridItem: guard fires before setShowDataViewerModal — the edit modal
does not open at all while the chatbox is mid-turn.
- deleteGridItem: guard fires BEFORE confirm() — the delete confirmation
modal does not appear (rather than appearing and then no-op'ing on
acceptance, which would be confusing UX).
- updateGridItemOrder: guard fires before mutating gridItems. Covers the
per-tile reorder affordances (Bring to Front / Forward / Send to Back /
Backward in the dropdown) which all delegate here. The react-grid-layout
drag-to-reorder gesture is NOT routed through this function, so move /
resize / drag remain enabled per R6.
DashboardItemDropdown propagates isStreaming to its menu items:
- Edit / Delete / Order entries: render with the Bootstrap `disabled` prop
(rendered-but-disabled, NOT hidden — keeps affordance location stable)
plus a `title` tooltip ("Editing disabled while dashboard is updating").
- Copy / Export remain enabled — they don't mutate tile config and don't
conflict with chatbox patch_visualization.
Open edit modals at stream start are NOT auto-closed (accepted v1 UX cost
per Scope Boundaries).
Tests: DashboardItem.streaming.test.js (5 scenarios) covers the disabled-
class + tooltip + handler no-op contract for Edit and Delete, the enabled
state of Copy/Export under streaming, the false→true→false transition, and
normal (non-streaming) baseline behavior.
Note on a11y: react-bootstrap may or may not apply `aria-disabled='true'`
depending on version; the `disabled` class is the jsdom-stable assertion.
Production a11y verification (screen reader announces "Edit, disabled"
with the documented reason) is worth checking after PR lands.
Phase 2 of docs/plans/2026-05-28-002-feat-chatbox-core-incremental-tile-streaming-plan.md
Unit 7.
…ndle Devcontainer Dockerfile sed-swap updated so the multi-stage build pulls the new beta from npm. The workshop image (built from this Dockerfile) will pick up the new onToolEnvelope engine option and the two new tethysdash:turn-start / tethysdash:turn-end window events that Phase 2 listens for. React bundle rebuilt against the current chatbox-core file: link (which itself is at 0.16.0-beta.0). The committed bundle keeps the non-Docker / dev-server / Jest paths in sync with the source. The Docker multi-stage build overwrites this bundle at image-build time anyway — both paths produce the same code now.
romer8
added a commit
to Aquaveo/ciroh_devcon_2026_workshop
that referenced
this pull request
May 28, 2026
…aming
The v2026.05.6 image (built by publish-image.yml on tag push of
v2026.05.6, ghcr.io/aquaveo/ciroh-devcon-2026:v2026.05.6) bakes
tethysdash @ tip of feature/tethysdash-mcp-server which carries:
* @aquaveo/chatbox-core 0.16.0-beta.0 — adds the per-tool
onToolEnvelope engine callback + tethysdash:turn-start /
tethysdash:turn-end window CustomEvents (Aquaveo/chatbox-core#45).
* tethysdash StreamingContext + DashboardLoader listener +
DashboardItem edit/delete/reorder gates
(tethysplatform/tethysapp-tethys_dash#134).
User-visible behavior changes for workshop participants:
- Chatbox-created tiles appear incrementally as each MCP tool returns
(instead of all at once at end-of-turn).
- Per-tile edit/delete/order dropdown items are disabled during chatbox
turns with a "Editing disabled while dashboard is updating" tooltip.
- Layout operations (resize / drag-to-move) stay enabled during turns.
- Stop button preserves successfully-rendered tiles.
Definitions.md adds a "What you'll notice in the chatbox (image v2026.05.6+)"
section pre-emptively explaining the two visible behaviors so participants
don't read them as bugs.
Participants run `bash scripts/update.sh` on their VMs to pull the new
image. update.sh's existing auto-sync logic propagates the new IMAGE_TAG
from .env.example into their .env, then `docker compose pull` fetches
v2026.05.6 from ghcr and `docker compose up -d --force-recreate` restarts
the stack against the new image. Hard-refresh the browser to load the
new React bundle.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 2 of
docs/plans/2026-05-28-002-feat-chatbox-core-incremental-tile-streaming-plan.md. Pairs with chatbox-core PR #45 (merged + published as@aquaveo/chatbox-core@0.16.0-beta.0).This PR wires tethysdash to the new chatbox-core events: dashboard listens for streaming lifecycle, per-tile edit/delete/reorder affordances no-op during chatbox turns to prevent racing with the LLM's
patch_visualizationcalls.What's in this PR
Unit 6 —
StreamingContext+DashboardLoaderlistenerexport const StreamingContext = createContext();inreactapp/components/contexts/Contexts.js.DashboardLoader.jsaddsconst [isStreaming, setIsStreaming] = useState(false)separate fromdisabledEditingMovement(the existing reset effect at lines 75-79 zeroesdisabledEditingMovementwhenisEditingflips false — couplingisStreamingwould have zeroed it spuriously).useEffectregisterswindow.addEventListener("tethysdash:turn-start" / "tethysdash:turn-end")with proper cleanup on unmount.streamingContextValuememo + new<StreamingContext.Provider>wrap in the existing provider tree.DisabledEditingMovementContextso the 4+ other consumers of that context (Header, DashboardLayout, PopupLayoutEditor) do NOT re-render on every turn boundary.Unit 7 — DashboardItem edit/delete/reorder gates + DashboardItemDropdown
DashboardItem.jsreadsisStreamingfromStreamingContextand short-circuits the three config-mutating handlers:editGridItem: guard beforesetShowDataViewerModal→ modal does not open.deleteGridItem: guard beforeconfirm()→ delete prompt does not appear (rather than appearing and then no-op'ing on accept).updateGridItemOrder: guard covers per-tile reorder affordances. react-grid-layout drag-to-reorder is NOT routed through this function, so move/resize/drag remain enabled per R6.DashboardItemDropdown.jsaccepts newisStreamingprop and applies the Bootstrapdisabledstate + tooltip ("Editing disabled while dashboard is updating") to:Dockerfile bump
.devcontainer/Dockerfilesed-swap updated to pin@aquaveo/chatbox-core@0.16.0-beta.0. The workshop image (built from this Dockerfile) will pick up the new engine callback and window events.Bundle rebuild
Tests
DashboardLoader.streaming.test.js(6 scenarios): initial-mount default false, turn-start/turn-end flips, idempotent duplicate starts, independence from DisabledEditingMovementContext, listener cleanup on unmount.DashboardItem.streaming.test.js(5 scenarios): Edit/Deletedisabledclass + tooltip when streaming, Copy/Export remain enabled, false→true→false transition, normal (non-streaming) baseline behavior.customRender.jsaddsStreamingPComponenthelper for asserting context value.ModuleLoader.test.js(URL encoding, present onfeature/tethysdash-mcp-serverbefore my changes); the rest pass (2028+).How it composes with chatbox-core 0.16.0-beta.0
Branching
feature/tethysdash-mcp-server(per workspace conventions, NEVERmain).tethysplatform/tethysapp-tethys_dash(neveraquaveo).Test plan
npm test -- --testPathPattern='(DashboardLoader|DashboardItem|DashboardLayout)' --no-coverage→ 126/126 passnpm run build→ bundle compilesPlan:
docs/plans/2026-05-28-002-feat-chatbox-core-incremental-tile-streaming-plan.mdOrigin brainstorm:
docs/brainstorms/2026-05-28-incremental-tile-streaming-requirements.mdPhase 1 PR (chatbox-core): Aquaveo/chatbox-core#45