Skip to content

chore(library): land File menu (#31) onto main — stacked-merge catch-up#32

Merged
BorisTyshkevich merged 4 commits into
mainfrom
feat/saved-query-descriptions
Jun 24, 2026
Merged

chore(library): land File menu (#31) onto main — stacked-merge catch-up#32
BorisTyshkevich merged 4 commits into
mainfrom
feat/saved-query-descriptions

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

Lands PR #31 (the document-style File menu, #29) onto main.

Both #30 and #31 are merged, but the stacked-PR timing left a gap: #30 merged its
base into main ~14s before #31 merged into that same base. So main currently
has only the saved-query descriptions (#30), and the File-menu feature (#31) is
stranded on feat/saved-query-descriptions, 4 commits ahead of main.

This brings main up to date — File menu (New / Save JSON / Replace / Append /
Download Markdown+SQL), the raw-NUL→\0 fix that makes saved-io.js text again,
plus the review fixes (document-seam crash, zoom anchor, import trim, duplicate-id
dedup on Replace). Already reviewed under #31; merges cleanly into main.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QGBS74oUsXarGkCRQKEFLu

BorisTyshkevich and others added 4 commits June 24, 2026 11:15
)

Reframes the saved-query collection as a named, savable document — "the
Library" — with a header File ▾ menu, an editable name, and an unsaved-changes
dot, replacing the Export/Import row hidden at the bottom of the Saved panel.

State (src/state.js):
- libraryName (persisted, key asb:libraryName) + libraryDirty (session-only).
- ops renameLibrary / newLibrary / replaceLibrary / appendLibrary /
  markLibrarySaved; the existing saved-query mutators now mark the Library
  dirty. New/Replace prune now-dangling tab→saved links; Replace adopts the
  loaded file's base name and keeps original ids (lossless).

Serializers (src/core/saved-io.js):
- buildMarkdownDoc / buildSqlDoc — one-way "share" exports (### + fenced sql;
  /* name + description */ comment + ;-delimited sql). JSON stays canonical.

UI:
- New src/ui/file-menu.js: the header File ▾ menu (New / Save JSON / Replace… /
  Append… / Download Markdown / Download SQL + "N in Library" footer), the
  inline-editable library title with a dirty dot, and Replace/New confirm
  dialogs. JSON is the only importable format; imported SQL is never run.
- app.js mounts the controls in the header and exposes the download / saveStr /
  FileReader / library-title seams; the obsolete exportSaved/importSavedFile
  actions are removed. saved-history.js drops savedActions() and relabels the
  tab "Library".

Tests stay at the per-file 100% statements/lines gate (branches ≥90, functions
≥95); adds tests/unit/file-menu.test.js. README documents the Library menu.

Builds on the descriptions pre-phase (#29 phase 1, PR #30).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AX4YR7RHKj7JfmS2AqnRrm
…file-menu + review fixes

Resolves the binary-merge conflict on src/core/saved-io.js and folds in the
PR #30 review fixes plus PR #31 (File menu) review fixes found this pass.

saved-io.js (conflict resolution + fixes):
- Kept PR #31's feature-complete version (buildMarkdownDoc/buildSqlDoc, append).
- Converted the raw NUL byte in contentKey to the '\0' escape, so the file is
  text again — that NUL is what made it binary-to-git and un-3-way-mergeable.
- Re-applied the PR #30 fix: parseImportDoc trims `description` (drops whitespace-
  only), matching saveQuery/renameSaved.
- buildMarkdownDoc collapses whitespace in the `### name` heading so a query name
  with a newline can't break the cookbook structure.

file-menu.js (PR #31 review fixes):
- CRITICAL: the File menu read bare `app.document` (undefined — createApp only
  exposes a local doc), so it threw on first click in production. Use
  `app.document || document`, matching shortcuts.js/results.js. Tests passed only
  because the fake-app supplies document.
- Anchor the dropdown via zoomScale() (divide getBoundingClientRect by the
  html{zoom} scale), like the editor popovers — it mis-anchored ~20% off otherwise.

state.js auto-merged: renameSaved keeps both PR #30's null-safe String(... || '')
and PR #31's libraryDirty flag.

All 715 tests pass; per-file coverage gate holds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBS74oUsXarGkCRQKEFLu
…ds (PR #31 review P2)

A Replace-loaded JSON containing repeated `id` values previously preserved every
duplicate id in savedQueries. The sidebar addresses rows by id (find/filter), so
deleting one row removed all duplicates and rename/favorite could affect the wrong
row. Now mint a fresh id for any missing OR already-seen id (unique ids preserved),
matching the mergeSaved-based Append path which never left duplicate ids behind.

Test covers duplicate + missing ids and the mint-collision retry loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBS74oUsXarGkCRQKEFLu
feat(library): document-style File menu for the saved-query Library (#29)
@BorisTyshkevich BorisTyshkevich merged commit 5a6b980 into main Jun 24, 2026
2 checks passed
@BorisTyshkevich BorisTyshkevich deleted the feat/saved-query-descriptions branch June 24, 2026 11:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant