feat(editor): drag a Library/History query into the editor as a ( … ) subquery - #40
Merged
Conversation
… subquery Saved-query and history rows are now draggable; dropping one on the SQL editor inserts that query wrapped in parentheses as a subquery, at the drop position, undoably. Extends the existing schema-identifier drag path (IDENT_MIME) with a second MIME (SUBQUERY_MIME) and a position-aware branch in the drop handler (offsetFromXY → replaceRange, falling back to the caret when dropped past the text). A pure toSubquery() strips a trailing FORMAT/; and brackets the SQL. - core/format.js: toSubquery() (100% covered). - ui/editor.js: SUBQUERY_MIME + drop handler branch. - ui/saved-history.js: draggable rows + dragstart payload. - unit + e2e (real DragEvent/DataTransfer) coverage. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGBS74oUsXarGkCRQKEFLu
… follow-ups) - toSubquery: peel trailing `;`/`FORMAT` iteratively (any order, repeated/spaced), so a `FORMAT JSON;;` or `;`-then-FORMAT tail can't leave an unparseable subquery. (A trailing comment after FORMAT is still left as-is — degrades to a visible SQL error, no silent note-dropping.) - README: document drag-to-insert (schema identifier at caret; Library/History query as a ( … ) subquery at the drop point). - saved-history.js: move dragProps below the imports (readability). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QGBS74oUsXarGkCRQKEFLu
This was referenced Jul 26, 2026
Open
lesandie
pushed a commit
to lesandie/altinity-sql-browser
that referenced
this pull request
Aug 2, 2026
One drag from the Library list now has three destination-dependent meanings. The row publishes two independent `dataTransfer` payloads to serve them: the existing `SUBQUERY_MIME` SQL snapshot (PR Altinity#40, untouched) and a new `LIBRARY_QUERY_MIME` identity `{workspaceId, queryId}`. The editor consumes text; Dashboard destinations consume identity. - Dashboard row / Panels group -> an independent panel-owned copy plus a tile, via `applyCommand('add-query-instance')` so placement is seeded from the source's own size hints. Repeated drops create independent panels. - an inferred Variables row -> the SQL text only, into that variable's option config. No clone, no tile, no owner, no lineage. Dashboard assignment never trusts `dataTransfer`: the payload is re-resolved against the latest committed workspace inside `mutateWorkspace`, so a source deleted or turned Dashboard-owned mid-drag aborts, a drop after a workspace switch is rejected, and an ordinary same-workspace change rebases (Altinity#343). Three decisions worth the diff they cost, all recorded in the ADR-0003 addendum: - The dirty-variable-tab gate runs INSIDE the transform. A pre-dispatch check is a snapshot, not a gate — `mutateWorkspace` queues behind `serializeWrite` then awaits IndexedDB, and a keystroke in that window would slip past. A variable tab has `savedId === null`, so Altinity#343's reconciler skips it and nothing would ever report the divergence. - Drag feedback causes no repaint. Eligibility is static `data-droptarget` markup revealed by one class on the list; a repaint would `replaceChildren()` the row under the pointer, and `dragleave` never fires for a removed node. - Hover auto-expand is decoupled from eligibility, or a variable row (which needs its non-eligible group open first) could never be reached by drag. `reconcileVariableTab` is new: `openVariableTab` calls `showQuerySurface()`, and a successful drop must not leave the Dashboard. Acceptance bullets 1-8; bullet 9 (keyboard `Add to dashboard...`) is deferred to Altinity#483 by owner decision, along with mobile, which is out of scope for the gesture. Unblocks Altinity#447 phase 3. Part of Altinity#428 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011sMwR4BHM85MExSBYXzTYj
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.
What
Saved-query (Library) and History rows are now draggable. Dropping one onto the SQL editor inserts that query's SQL wrapped in parentheses as a subquery, at the drop position, undoably. No runtime macro, no library coupling — the SQL you see is the SQL you run (the simplest take on the composable-queries idea in #39).
How
Extends the existing schema-identifier drag path rather than inventing a new one:
src/ui/editor.js— addsSUBQUERY_MIMEnext toIDENT_MIME, and a branch in the existing textareadrophandler. The schema-identifier branch is unchanged (still inserts at the caret); the new branch wraps viatoSubqueryand inserts at the drop point using the existingoffsetAt(client coords → text offset, handles padding/scroll/zoom) +replaceRange(undoable), falling back to the caret when the drop lands past the text (e.g. the blank area below the last line).src/core/format.js— puretoSubquery(sql): trims, strips a trailing;and a trailingFORMAT <name>clause (invalid inside()), brackets the SQL on its own lines; empty input →''(no-op).src/ui/saved-history.js—.saved-row/.history-rowgetdraggable+ adragstartthat puts the SQL onSUBQUERY_MIME(mirrorsschema.js'sdragProps).Tests
format.js100% (toSubquerywrap / strip;/ strip trailing FORMAT / keep non-trailing FORMAT / empty).editor.js— drop withSUBQUERY_MIME: inserts at the drop offset (position branch), fallback to caret when past the text, and no-op on empty SQL.saved-history.js— saved + history rows aredraggableand carry the rightSUBQUERY_MIMEpayload ondragstart.editor-insert.spec.js) — realDataTransfer+DragEvent('drop')over the textarea exercises the actualoffsetFromXYgeometry happy-dom can't.820 unit tests pass; coverage gate holds.
Verified live (otel)
Dragging a Library row onto the editor dropped
(\nSELECT * FROM claude_otel.otel_logs\n)at the drop position with the surrounding text preserved; dropping in the editor padding fell back to the caret. Deployed to otel for review.🤖 Generated with Claude Code