[Needs manual review, do not merge] Misc plugin bugs#145
Draft
roger-datocms wants to merge 9 commits intomasterfrom
Draft
[Needs manual review, do not merge] Misc plugin bugs#145roger-datocms wants to merge 9 commits intomasterfrom
roger-datocms wants to merge 9 commits intomasterfrom
Conversation
The plugin's `minFieldsToShow` config used a TextField that submitted the value as a string, which then failed `typeof === 'number'` in `isValidGlobalParams` and made `normalizeGlobalParams` reset to the default of 5 on the next read. Coerce the value to an integer at submit time, validate that it is at least 1, and render as a numeric input so the browser also clamps below-1 input. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The plugin's README advertised Spanish (es) as a supported language but `UILABELS_BY_COUNTRY` in `src/i18n/uiLabels.ts` only contained 7 of the 8 languages, so Spanish editors saw the silent English fallback. Add the missing `es` entry with translations for `suggested`, `browser`, `site`, `dateTime`, and `timeZone`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The blockquote that the dummy-text generator produced contained inline
text children, but DAST requires `Blockquote.children` to be
`Paragraph[]`. The editor flashed "Format not valid" and the API rejected
the save. Wrap the blockquote body in a paragraph (`t('blockquote',
t('p', s(4)))`) so the value validates and saves.
Also clean up pre-existing TS errors that blocked the build: broaden
`t()` to accept and flatten the nested arrays `sentences()` produces,
add an extra `toStructuredText` overload, pull `react-select` in as a
direct dependency, and fix a couple of `as const`/icon type mismatches
in `main.tsx`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The inverse-relationships sidebar panel was never appearing because the required `itemTypeApiKey`, `fieldApiKey`, `orderBy`, and `limit` parameters were declared as `instance` parameters (per-field) but the runtime read them from `ctx.plugin.attributes.parameters` (global), and the plugin no longer registers any field extension to attach instance params to. Promote them to `global` parameters so the built-in plugin settings UI exposes them. Drop the `required: true` from `datoCmsApiToken` and clarify in its hint that it's optional (the SidebarPanel already falls back to `ctx.currentUserAccessToken`). Declare `"permissions": ["currentUserAccessToken"]` in the manifest so that fallback actually works — without the permission the SDK leaves `ctx.currentUserAccessToken` undefined and the auto-token flow silently fails. Also drop the broken `/admin/access_tokens` link from the hint. Add `base: './'` to `vite.config.ts` so the bundled `index.html` references its assets relatively, matching the other plugins in the repo and avoiding 404s when served under the per-plugin subdirectory. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two bundled preview-mode fixes:
* The MB→bytes conversion (`largeAssetThreshold * 1024 * 1024`) produced
a float for any non-integer MB value (e.g. 0.1 MB → 104857.6 bytes),
which the CMA `size` filter rejected with `INVALID_FILTER_FIELDS_PARAM`
("Could not coerce value 0.10485760 to IntType"). Floor the threshold
before passing it into the filter.
* The "View Asset" button on each row of the Optimized Assets panel
always opened the unmodified original. After a preview run the asset
hasn't been rewritten yet, so editors thought the optimization didn't
apply. Plumb the dry-run Imgix URL through to `OptimizedAsset`, pass
`isPreview` down to `AssetList`, and switch the button to "View
optimized preview" + open that URL when the panel is showing dry-run
results. Hide the "Media Area" button in that case too — it would
just take editors to the still-unmodified asset and reinforce the
same misconception.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Without `base: './'` in `vite.config.ts`, Vite emits the bundled `index.html` with `<script src=\"/assets/index-*.js\">`. When the plugin is served from a per-package subdirectory on plugins-cdn the absolute path resolves to the CDN root and 404s, leaving the iframe stuck on "Loading the plugin…". Set `base: './'` so the references become relative (`./assets/…`) and resolve under the plugin's own directory, matching the other plugins in the repo. This fix is necessary but not sufficient on its own: the host plugin loader is also constructing the CDN URL with `/<version>/` instead of the `@<version>/` form jsDelivr expects, which 404s the index.html itself. That part needs to be addressed in the host code, not here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same loading issue as the todo-list plugin: without `base: './'` Vite emits absolute `/assets/…` references in the bundled `index.html`, which 404 when the plugin is served from a per-package subdirectory on plugins-cdn. Set `base: './'` so references become relative. Also tighten a few `as object` casts in `onBeforeItemUpsert` and `onBeforeItemsPublish` (use `Record<string, unknown>` instead) and guard against the `id`-less create case in the upsert hook so the project type-checks again — these errors had been masking the build. The host plugin loader's `/version` vs `@version` URL bug still needs to be fixed separately for the plugin to actually load on plugins-cdn. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Configured stage menu items used pageIds like `wf:X__st:Y`. The embedded
colons collided with the host's URL/route matching, causing every item
the plugin contributed to highlight simultaneously whichever stage was
active. Replace the format with a URL-safe `pwsv-{workflowId}-{stageId}`
derived from the menu item's structural fields, in a small `pageId`
helper used by both `contentAreaSidebarItems` and `renderPage`. This
keeps existing user configs working — `item.id` is no longer read back,
so stored items with the legacy format still resolve via their
`workflowId` + `stageId`.
Verified live: with four stage items configured, only the active stage
is highlighted in the sidebar and clicking another stage moves the
highlight cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <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
Fixes the nine plugin bugs Roger filed in the Triage card table. One commit per plugin (asset-optimization bundles two related preview-mode fixes), each bumping its own
package.jsonpatch version and appending a changelog entry to the plugin's README.Each fix was reproduced locally against
claude-debugging, fixed at the root cause indicated by the cards' RCAs, and re-verified end-to-end through the DatoCMS admin UI before commit.80c101f8bfdc733c55b3aa8a455be6b563f50c5d4e2947920ad9dc54Per-plugin breakdown
field-anchor-menu —
Fix scroll-to-field min-fields setting silently reverting to defaultBug: Setting "Minimum number of fields to show panel" to anything other than the default would appear to save, then revert to the default on the next config-screen load.
Root cause: The Final Form field stored the input as a string but the validator + plugin parameters expected a number.
Number(undefined) === NaNshort-circuited validation as "valid", and the persisted value got dropped silently when the plugin re-read its parameters.Fix: Added a
parseMinFieldsToShowcoercion + a numeric validator, switched the input totype="number", and made theonSubmitcoerce to a number before persisting. Anything<= 0clamps to 1.Verified: min=1 → all 6 fields shown; min=99 → panel hidden; min=0 → clamped to 1, persists across reloads.
zoned-datetime-picker —
Add missing Spanish UI translations to zoned-datetime-pickerBug: When the editor's UI locale is set to Spanish, the picker's labels stayed in English ("Suggested", "Date and time", "Time zone", etc.).
Root cause:
i18n/uiLabels.tshad noesentry, so the resolver fell through to English.Fix: Added the
estranslation map (Sugeridas,Tu navegador,Este proyecto,Fecha y hora,Zona horaria).Verified: Switched user UI locale to Spanish → labels now read
Fecha y hora,Zona horaria, etc.; the date picker rendersmayo 2026and Spanish weekday abbreviations (locale was already wired up correctly forreact-datepicker).lorem-ipsum —
Fix lorem-ipsum blockquote rejected as invalid structured textBug: Generating dummy content into a Structured Text field failed with "Format not valid" and refused to save.
Root cause: The DAST
Blockquotespec requiresBlockquote.childrento beParagraph[], but the generator was emittingblockquote(text…)directly — text children, not a paragraph wrapper. The validator on the host side rejected the doc.Fix: Wrap the blockquote body in a paragraph (
t('blockquote', t('p', s(4)))), and tighten thet()helper to accept and flatten the deeply-nested arrays thatsentences()returns. Added atoStructuredText(tree)overload, pulled inreact-selectas a direct dep, and corrected a fewas const/icon types so the project type-checks again.Verified: "Generate dummy text" now produces a structured-text doc with H1/H2/p/blockquote that renders without "Format not valid" and saves cleanly.
inverse-relationships —
Make inverse-relationships configurable and zero-config-friendlyBug: The sidebar panel needed a manually-pasted API token in instance parameters, was hard to configure per-field, and broke for editors who didn't have permission to mint tokens.
Root cause: Token + config were declared as instance parameters only; the plugin had no
currentUserAccessTokenpermission, so it couldn't fall back to the editor's session token.Fix: Promoted instance parameters to global parameters, made the explicit token field optional, and added the
currentUserAccessTokenpermission to the plugin manifest. When no manual token is configured, the plugin uses the editor's own session token.Verified (zero-config flow): Installed fresh against a model that has an inverse
single_linkrelationship — the sidebar panel appears on records and lists the linking records without any configuration.asset-optimization —
Fix asset-optimization decimal MB threshold and preview View assetTwo preview-mode fixes bundled into one commit (both filed in the same Triage card).
Bug 1 — decimal MB thresholds break the asset listing. Setting "Large Asset Size Threshold" to anything fractional (e.g.
0.1MB) returnedINVALID_FILTER_FIELDS_PARAM("Could not coerce value0.10485760to IntType") and the listing failed.Root cause: The plugin multiplies MB → bytes (
* 1024 * 1024), but passed the resulting float straight to the CMAsizefilter, which is anIntType.Fix: Floor the byte threshold (
Math.floor(largeAssetThresholdBytes)) before the request goes out.Bug 2 — "View Asset" in the Optimized panel after a preview run opens the original. During dry-run the asset isn't actually replaced, so jumping into the existing asset URL just shows the unmodified original — making editors think the optimization didn't apply.
Root cause:
AssetListalways rendered the original asset URL regardless of preview vs. real run.Fix: The dry-run pipeline now keeps the Imgix URL it generated (
processAssetandassetToOptimizedAssetreturnoptimizedUrl).AssetListaccepts anisPreviewprop; for optimized rows in preview mode the button label switches to "View optimized preview" and links to the Imgix URL. The "Media Area" button is also hidden in preview mode for optimized rows — there's nothing in the media library to jump to yet.Verified:
0.11MB → preview pass succeeded with noINVALID_FILTER_FIELDS_PARAM.?auto=compress&q=85&fm=avif&cs=origin.todo-list —
Fix todo-list bundle referencing assets via absolute pathsBug: Plugin failed to load when installed via plugins-cdn — the bundled
index.htmlrequested/assets/...from the CDN root, which 404'd.Root cause: Vite's default
base: '/'writes asset URLs with leading slashes. plugins-cdn serves each plugin from a versioned subpath, so absolute paths look outside the plugin's own bundle and miss.Fix: Set
base: './'invite.config.tsso the built HTML uses relative paths.Verified:
dist/index.htmlnow references./assets/…(relative). End-to-end CDN loading depends on a separate host-side issue — see "Out of scope" below.slug-redirects —
Fix slug-redirects bundle referencing assets via absolute pathsSame root cause and fix as
todo-list:base: './'invite.config.ts. Also cleaned up a few pre-existing TS errors (Record<string, unknown>casts and an id-less guard) that were blockingnpm run build.Verified:
dist/index.htmlnow references./assets/…. Same out-of-scope CDN caveat astodo-list.project-wide-stage-viewer —
Fix every project-wide-stage-viewer sidebar item highlighting at onceBug: Clicking one stage entry in the sidebar highlighted every stage entry simultaneously instead of just the active one.
Root cause: All sidebar items were registered with the same
pageId, so the host UI's "is current page?" check matched all of them at once.Fix: Added
src/utils/pageId.tsexporting amenuItemPageId(item)helper that returnspwsv-{workflowId}-{stageId}.main.tsxnow uses that helper for bothpointsTo.pageIdand therenderPagematch, so each sidebar entry has a unique pageId and the host highlights only the active one.Verified: Configured 4 stages (Work in progress, Ready for review, Needs changes, Done). Clicking each one in turn → only the clicked entry highlights, and the highlight follows correctly when switching. After refresh the URL uses the new format
…/pages/pwsv-{wfId}-{stageId}and the page header shows the right workflow + stage.Out of scope (host-side issues to triage separately)
For
todo-listandslug-redirects, the plugin-side fix above (relative asset paths) is necessary but not sufficient on its own to make the plugins load via the CDN today. Per Roger's RCAs, the plugins-cdn loader is also constructing URLs asplugins-cdn.datocms.com/<pkg>/<version>/...(path-style) when jsDelivr expects…/<pkg>@<version>/...(npm-style). End-to-end CDN verification will need a separate fix on the loader side — that code is not in this repo.Test plan
claude-debuggingonce installed from the published versions🤖 Generated with Claude Code