fix: media count/search, create-folder, plugin sidebar/prune, save-in-place, viewer scope, stable block IDs (#888 #890 #929 #970 #971 #835 #783 #931)#983
Open
lane711 wants to merge 12 commits into
Conversation
- MediaDocumentService.list() now runs a parallel COUNT(*) with the same WHERE filters and returns `total` in MediaListResult - Admin media route uses `total` for totalFiles and fixes hasNextPage (was capped at page size 24 instead of real library total) - Media selector search input: add missing `name="search"` attr so the typed term is actually sent with the HTMX request - Add hx-swap="outerHTML" + hx-select="#media-selector-grid" to prevent the full panel (search box + grid) from nesting inside the grid on each keystroke Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…le (#929) The /api/media/create-folder handler queried `SELECT COUNT(*) FROM media` to check for duplicates. On greenfield document-model installs the legacy `media` table does not exist, causing a D1 error on every folder creation. Replace the check with a query against `documents` (media_asset type) and wrap in try/catch so installs mid-migration (table absent) degrade gracefully rather than hard-erroring. Folders remain virtual in R2 — the check is advisory only. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Singleton menu items (user plugins in config.plugins.register) were appended to the admin sidebar without checking DB active-status. A plugin disabled via the admin UI left its document status=inactive but the menu entry still rendered because only PLUGIN_REGISTRY items were DB-checked. Fix: - PluginMenuEntry / ResolvedPluginMenuEntry gain optional `pluginId` - app.ts tags every singleton menu entry with its parent plugin's id - plugin-menu middleware queries documents for active status of singleton plugin ids (one batch query) and filters inactive plugins out - Items without a pluginId (legacy/external) continue to render as before Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a plugin is removed from SonicJSConfig.plugins.register it previously stayed active in the documents table indefinitely (active-status plugin documents are never pruned). Add pruneStaleUserPlugins() called from wireRegisteredPlugins Phase D: - Queries all active non-core plugin documents (isCore falsy) - Any whose slug is absent from the current wired-plugin set is deactivated (json_set data.status = 'inactive', updated_at bumped) - Core plugins (isCore = true, bootstrapped by PluginBootstrapService) are never pruned; any per-row failure is non-fatal - Runs fire-and-forget alongside reflectWiredPlugins on first request Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sh (#835) Replace the Update / Update & Publish button pair with three actions: - **Save** (action=save): saves draft, returns inline success banner via HTMX, user stays on the edit page - **Save & close** (action=save_and_close): saves draft, HX-Redirect to the content list (or the referrer URL if present) - **Publish** (action=save_and_publish): saves + publishes, returns inline success banner, user stays on the edit page Cancel still navigates to the content list unchanged. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…oles (#783) Viewer role (default for new users) now sees only Content and Collections. Editor role sees Content, Collections, Settings but not Users or Plugins. Admin role unchanged — all items visible. Both catalyst and v2 layouts updated with consistent role guards. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each block in a discriminated array gets a persisted `blockId` (e.g. `blk_aabbccddeeff`) generated once at first save. Re-parsing existing blocks preserves the ID, so reorder/edit cycles are stable. Backfill is automatic: any block saved without an ID receives one on next write. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…gler.toml (#928) db-reset.js now checks wrangler.toml → wrangler.jsonc → wrangler.json in order. DB ID/name update uses TOML regex for .toml files and JSON regex for .jsonc/.json. generate-cron-triggers.ts gracefully skips cron codegen when jsonc/json detected (triggers section is TOML-only by design). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…#643) #632: Remove dead drizzle-kit/drizzle-orm devDependencies and db:studio script from my-sonicjs-app. No drizzle.config exists; document model uses raw SQL. Script threw on every invocation. #643: Add format hint text below date (YYYY-MM-DD) and datetime (YYYY-MM-DD HH:MM) inputs in dynamic-field template so users know the expected entry format. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds opt-in field projection to all collection read endpoints: GET /api/:collection GET /api/:collection/:id GET /api/content GET /api/content/:id Usage: ?fields=id,title,slug — top-level fields only ?fields=id,title,data.excerpt — mix top-level + data sub-fields ?fields=data — entire data blob Existing callers without ?fields= are unaffected. Cache is bypassed when projection is active (projected shape must not be stored as the canonical cached response). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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
hasNextPagewrong.MediaDocumentService.list()now runs parallelCOUNT(*)and returnstotal.name=\"search\"+hx-swap=\"outerHTML\"+hx-select=\"#media-selector-grid\".mediatable absent). Replaced withdocumentsquery + graceful catch.pluginIdand batch-querying active status inpluginMenuMiddleware.config.plugins.registerstayed installed+enabled. AddedpruneStaleUserPlugins()inwireRegisteredPluginsPhase D: deactivates active non-core plugin documents absent from the current wired-plugin set, running fire-and-forget on first-request boot.parseBlocksValuenow assignsblockId: \"blk_<12hex>\"on first save and preserves existing IDs on reorder/edit/re-save. Existing content is backfilled on next write.Test plan
mediatable)/admin/pluginsremoves it from sidebar immediatelyconfig.plugins.register+ cold boot → plugin shows inactive in adminblockId; reorder/re-save preserves the same ID88,92,94,95,96pass in CI🤖 Generated with Claude Code