feat(admin): allow trusted plugins to add content list columns#2195
feat(admin): allow trusted plugins to add content list columns#2195logelog wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: 0a83f6d The changes in this PR will be included in the next version bump. This PR includes changesets to release 17 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Scope checkThis PR changes 586 lines across 10 files. Large PRs are harder to review and more likely to be closed without review. If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs. See CONTRIBUTING.md for contribution guidelines. |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-verification
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
There was a problem hiding this comment.
This is a focused, well-scoped addition to the trusted-plugin admin surface. It solves the right problem (display-only content-list columns contributed by trusted React plugins) in the right way: EmDash keeps ownership of the table while plugins provide header/cell components;filtering, sorting, and search are deliberately left out because they need server-backed semantics. The change follows the same trusted-plugin model already used for pages, widgets, and field widgets, and it is backed by an approved Discussion (#2048).
I checked the new resolver, the boundary component, the ContentList integration, the router wiring, the test coverage, and the changeset. The logic is sound: disabled/stale plugins are omitted, role and collection filters work, malformed/duplicate definitions are isolated, and error boundaries keep a broken column from crashing the list. No logic bugs, security issues, regressions, or logged-out query-count impacts were found.
There are three AGENTS.md import-extension violations on changed/new lines: two new internal imports omit the required .js extension. Fixing those is the only blocker.
| import { Trans } from "@lingui/react/macro"; | ||
| import * as React from "react"; | ||
|
|
||
| import type { AdminManifest, ContentItem } from "./api"; |
There was a problem hiding this comment.
[needs fixing] Internal ESM imports must use a .js extension per AGENTS.md. This new file imports from ./api without it.
| import type { AdminManifest, ContentItem } from "./api"; | |
| import type { AdminManifest, ContentItem } from "./api.js"; |
| ContentDateField, | ||
| ContentItem, | ||
| TrashedContentItem, | ||
| } from "../lib/api"; |
There was a problem hiding this comment.
[needs fixing] This changed import from ../lib/api is missing the required .js extension for internal ESM imports.
| } from "../lib/api"; | |
| } from "../lib/api.js"; |
| ContentListColumnHeaderContext, | ||
| ContentListColumnCellContext, | ||
| ContentListColumnExtension, | ||
| } from "./lib/content-list-columns"; |
There was a problem hiding this comment.
[needs fixing] The new re-export from ./lib/content-list-columns is an internal ESM import and needs the .js extension.
| } from "./lib/content-list-columns"; | |
| } from "./lib/content-list-columns.js"; |
Overlapping PRsThis PR modifies files that are also changed by other open PRs:
This may cause merge conflicts or duplicated work. A maintainer will coordinate. |
ee1f044 to
0a83f6d
Compare
What does this PR do?
Adds a focused, display-only content-list column extension for trusted React plugins.
Plugins can export typed
contentListColumnsdefinitions for computed metadata such as SEO scores, moderation states, or workflow statuses. EmDash keeps ownership of the table, pagination, row actions, loading states, and empty states while passing each cell the current content item, collection, and locale.The resolver:
Sorting, filtering, and search are intentionally outside this display-only contract. They need server-backed contracts; a browser comparator would only reorder the currently loaded page. Search is covered by #2191, indexed sorting by #2212, and indexed filtering by #2213.
This PR is stacked on #2194 so the shared content-list column layout has a single owner. Both can be reviewed at the same time, but #2194 should merge first; GitHub will then narrow this PR to its unique trusted-plugin extension commits automatically.
This complements #2194, which handles collection-configured scalar fields, and addresses the plugin-computed column portion of #2179.
Discussion: #2048
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runScreenshots / test output
Validated on EmDash 0.31 with Node 24 in WSL2:
pnpm typecheckpnpm lint:quickpnpm format:checkpnpm --filter @emdash-cms/admin buildpnpm --filter emdash build