Skip to content

feat(admin): show configured fields in content lists - #2194

Merged
ascorbic merged 3 commits into
emdash-cms:mainfrom
logelog:feat/content-list-custom-field-columns
Aug 11, 2026
Merged

feat(admin): show configured fields in content lists#2194
ascorbic merged 3 commits into
emdash-cms:mainfrom
logelog:feat/content-list-custom-field-columns

Conversation

@logelog

@logelog logelog commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Adds collection-level custom field columns to the admin content list.

Collections can opt into up to four scalar fields through admin.listColumns. The collection schema, seed import/export path, API payloads, and runtime manifest preserve that configuration. The manifest validates configured fields, removes duplicates, ignores unknown or unsupported field types, and exposes the field metadata needed by the admin.

The content list renders those fields between Title and Status without extra per-row requests. Select and multi-select values use their configured labels, booleans and dates receive compact formatting, and long values stay bounded so they cannot distort the table.

Searchable custom fields are handled separately in #2191. Trusted plugin-computed columns are handled in #2195. Server-backed indexed sorting and filtering are handled in #2212 and #2213.

#2195 and #2212 are stacked on this branch so all five contributions can be reviewed at the same time without duplicating the collection-column infrastructure. This PR should merge before those two; GitHub will then narrow their diffs automatically.

Addresses #2179
Related design discussion: #1717. Wider context for the whole content-list proposal is in #2397.

Type of change

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

Checklist

AI-generated code disclosure

  • This PR includes AI generated code: Claude Opus 5, GPT-5.6 (via private dev orchestra)

Screenshots / test output

Validated on EmDash 0.32.0 (base 776d65f7) with Node 24.16.0 and pnpm 11.9.0 on macOS. The workspace has all six stacked contributions applied, so these are the integrated totals rather than a per-PR subset:

  • core: 403 files, 5211 tests passed, 3 skipped
  • admin: 117 files, 1421 tests passed
  • Cloudflare: 21 files, 300 tests passed
  • Workerd: 12 files, 84 tests passed
  • real local D1: 2 files, 7 tests passed
  • typechecks and builds for admin, core, cloudflare, workerd, and the demo lab

CI runs each PR on its own branch.

@changeset-bot

changeset-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 58648f9

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 touches 23 files. PRs with a broad scope are harder to review. Please confirm the scope hasn't drifted beyond the intended change.

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.

@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@2194

@emdash-cms/auth

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

@emdash-cms/auth-atproto

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

@emdash-cms/blocks

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

@emdash-cms/cloudflare

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

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

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

emdash

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

create-emdash

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

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

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

@emdash-cms/plugin-cli

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

@emdash-cms/plugin-types

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

@emdash-cms/registry-client

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

@emdash-cms/registry-lexicons

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

@emdash-cms/registry-verification

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

@emdash-cms/sandbox-workerd

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

@emdash-cms/x402

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

@emdash-cms/plugin-ai-moderation

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

@emdash-cms/plugin-atproto

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

@emdash-cms/plugin-audit-log

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

@emdash-cms/plugin-color

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

@emdash-cms/plugin-embeds

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

@emdash-cms/plugin-field-kit

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

@emdash-cms/plugin-forms

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

@emdash-cms/plugin-webhook-notifier

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

commit: 5810dc2

@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 PR correctly implements collection-level custom field columns for admin content lists as an additive, scoped feature. The approach fits EmDash's architecture: admin.listColumns is persisted in _emdash_collections.admin_config as JSON, travels through seeds and schema APIs, is validated/deduplicated/capped in the manifest build, and is rendered client-side from data already present in the content list payload (no extra per-row queries).

I reviewed the diff statically and traced the changes across the migration, schema registry, seed apply/validate/export, runtime manifest build, admin manifest types, and the ContentList component. I checked for Lingui coverage, RTL-safe Tailwind, SQL safety, API envelope consistency, query-count impact, comment discipline, and test coverage.

Headline conclusion: the code is clean. The migration is guarded by columnExists. The registry round-trips admin_config correctly and preserves existing list columns on unrelated updates. The manifest filter caps list columns at four supported, existing field types and warns appropriately. The admin UI renders headers and cells with logical Tailwind classes and uses the existing manifest/field metadata for select/multi-select labels and compact formatting. Tests cover the manifest cap behavior, registry persistence, migration registration, and component rendering.

I did not run the test suite, linter, or build; the author reports passing checks in the PR description.

@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/approved Approved; no new commits since and removed review/needs-review No maintainer or bot review yet labels Jul 22, 2026
@logelog
logelog force-pushed the feat/content-list-custom-field-columns branch from 8edcd0d to 1e5c71b Compare July 24, 2026 19:26
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/approved Approved; no new commits since labels Jul 24, 2026
@logelog
logelog force-pushed the feat/content-list-custom-field-columns branch from 1e5c71b to 15acca2 Compare August 2, 2026 23:36
@github-actions github-actions Bot added review/approved Approved; no new commits since review/needs-rereview Author pushed changes since the last review and removed review/needs-rereview Author pushed changes since the last review review/approved Approved; no new commits since labels Aug 10, 2026
@logelog
logelog force-pushed the feat/content-list-custom-field-columns branch from c64d3be to a5255c3 Compare August 10, 2026 09:50
@logelog logelog closed this Aug 10, 2026
@logelog logelog reopened this Aug 10, 2026

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

The approach remains sound: this PR adds a single admin_config column on _emdash_collections, round-trips admin.listColumns through the registry, seed/schema APIs, and runtime manifest, validates and caps configured columns when building the manifest, and renders them in ContentList from data already present in the list payload. It introduces no new per-row requests or logged-out queries.

I re-read the full diff and the changed files. The migration is idempotent and forward-only, the registry preserves existing list columns when admin is omitted on update, the API schemas cap input columns at four while allowing legacy responses, the manifest filters out unsupported/unknown/duplicate slugs and caps at four with clear warnings, and ContentList uses Lingui-wrapped labels, RTL-safe text-start headers, and bounded-width cells. Tests cover manifest capping, registry persistence, seed export/validate round-trips, and component rendering behavior.

No new line-level code issues were found.

The only remaining merge consideration from the prior review is the governance item from AGENTS.md: this is a feature PR and the linked design discussion (#1717) is still listed as “opened, awaiting maintainer review.” A maintainer-approved Discussion is required before a feature merges, so that approval should land before merge. The code itself is ready once that is satisfied.

@github-actions github-actions Bot added review/approved Approved; no new commits since and removed review/needs-rereview Author pushed changes since the last review labels Aug 10, 2026
@logelog
logelog force-pushed the feat/content-list-custom-field-columns branch from a5255c3 to 3cebee6 Compare August 10, 2026 17:30
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/approved Approved; no new commits since labels Aug 10, 2026
@logelog logelog closed this Aug 10, 2026
@logelog logelog reopened this Aug 10, 2026

@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 re-review of the content-list custom-field-columns work. The approach remains sound: it adds a single admin_config column on _emdash_collections, round-trips admin.listColumns through the registry, seed/schema APIs, and runtime manifest, validates and caps configured columns when building the manifest, and renders them in ContentList from data already present in the list payload. It introduces no new per-row requests or logged-out queries.

I re-read the full diff and the changed files. The migration is idempotent and forward-only, the registry preserves existing admin config on updates when admin is omitted, the API schemas cap input columns at four while allowing legacy responses, the manifest removes duplicates/unknown/unsupported slugs and caps at four, and ContentList uses Lingui-wrapped labels, RTL-safe text-start headers, and bounded-width cells. Tests cover manifest capping, registry persistence, seed export/validate round-trips, and component rendering behavior.

I have one code-level suggestion: the new admin_config column is typed as Generated<string | null> even though the migration does not give it a default, which is inconsistent with the neighboring JSON text columns (search_config, supports). Changing it to string | null removes a misleading Kysely signal.

The only remaining merge consideration from the prior review is the governance item from AGENTS.md: this is a feature PR and the linked design discussion (#1717) is still listed as “opened, awaiting maintainer review.” A maintainer-approved Discussion is required before a feature merges, so that approval should land before merge. Once that is satisfied and the typing suggestion is addressed, the code itself is ready.

label_singular: string | null;
description: string | null;
icon: string | null;
admin_config: Generated<string | null>; // JSON: { listColumns?: string[] }

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.

[suggestion] The new admin_config column is typed as Generated<string | null>, which tells Kysely that the column is auto-generated / has a default and can be omitted from inserts. The migration only adds a nullable text column with no default, so omitting it would fail at runtime. The neighboring JSON text columns (search_config, supports) use string | null without Generated; admin_config should match them.

Suggested change
admin_config: Generated<string | null>; // JSON: { listColumns?: string[] }
admin_config: string | null; // JSON: { listColumns?: string[] }

@github-actions github-actions Bot added review/approved Approved; no new commits since and removed review/needs-rereview Author pushed changes since the last review labels Aug 10, 2026
@logelog
logelog force-pushed the feat/content-list-custom-field-columns branch from 3cebee6 to 58648f9 Compare August 11, 2026 02:48
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/approved Approved; no new commits since labels Aug 11, 2026
@logelog
logelog force-pushed the feat/content-list-custom-field-columns branch from 58648f9 to 5810dc2 Compare August 11, 2026 13:56

@ascorbic ascorbic left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks!

@ascorbic
ascorbic merged commit 2d5fb0b into emdash-cms:main Aug 11, 2026
46 checks passed
@emdashbot emdashbot Bot mentioned this pull request Aug 11, 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.

3 participants