Skip to content

feat(admin): allow trusted plugins to add content list columns#2195

Open
logelog wants to merge 3 commits into
emdash-cms:mainfrom
logelog:feat/plugin-content-list-columns-v2
Open

feat(admin): allow trusted plugins to add content list columns#2195
logelog wants to merge 3 commits into
emdash-cms:mainfrom
logelog:feat/plugin-content-list-columns-v2

Conversation

@logelog

@logelog logelog commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds a focused, display-only content-list column extension for trusted React plugins.

Plugins can export typed contentListColumns definitions 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:

  • filters disabled or stale plugins
  • supports collection and minimum-role visibility
  • orders contributions deterministically
  • validates malformed and duplicate definitions
  • isolates failing predicates, headers, and cells so the content list remains usable
  • omits plugin columns from Trash

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

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

Screenshots / test output

Validated on EmDash 0.31 with Node 24 in WSL2:

  • trusted-column resolver and ContentList browser tests: 50 passed
  • combined five-PR integration suite: 234 core and 120 admin tests passed
  • pnpm typecheck
  • pnpm lint:quick
  • pnpm format:check
  • pnpm --filter @emdash-cms/admin build
  • pnpm --filter emdash build

@changeset-bot

changeset-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0a83f6d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 17 packages
Name Type
emdash Minor
@emdash-cms/admin Minor
@emdash-cms/cloudflare Minor
@emdash-cms/sandbox-workerd Patch
@emdash-cms/plugin-mcp-smoke Major
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/auth Minor
@emdash-cms/blocks Minor
@emdash-cms/gutenberg-to-portable-text Minor
@emdash-cms/x402 Minor
create-emdash Minor
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

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

@github-actions

Copy link
Copy Markdown
Contributor

Scope check

This 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.

@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label Jul 22, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jul 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@2195

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@2195

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@2195

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@2195

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@2195

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@2195

emdash

npm i https://pkg.pr.new/emdash@2195

create-emdash

npm i https://pkg.pr.new/create-emdash@2195

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@2195

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@2195

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@2195

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@2195

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@2195

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@2195

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@2195

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@2195

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@2195

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@2195

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@2195

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@2195

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@2195

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@2195

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@2195

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@2195

commit: 0a83f6d

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs fixing] Internal ESM imports must use a .js extension per AGENTS.md. This new file imports from ./api without it.

Suggested change
import type { AdminManifest, ContentItem } from "./api";
import type { AdminManifest, ContentItem } from "./api.js";

ContentDateField,
ContentItem,
TrashedContentItem,
} from "../lib/api";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs fixing] This changed import from ../lib/api is missing the required .js extension for internal ESM imports.

Suggested change
} from "../lib/api";
} from "../lib/api.js";

Comment thread packages/admin/src/index.ts Outdated
ContentListColumnHeaderContext,
ContentListColumnCellContext,
ContentListColumnExtension,
} from "./lib/content-list-columns";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[needs fixing] The new re-export from ./lib/content-list-columns is an internal ESM import and needs the .js extension.

Suggested change
} from "./lib/content-list-columns";
} from "./lib/content-list-columns.js";

@github-actions

Copy link
Copy Markdown
Contributor

Overlapping PRs

This PR modifies files that are also changed by other open PRs:

This may cause merge conflicts or duplicated work. A maintainer will coordinate.

@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond review/needs-rereview Author pushed changes since the last review and removed review/needs-review No maintainer or bot review yet review/awaiting-author Reviewed; waiting on the author to respond labels Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant