Skip to content

feat(core): add group and sortOrder to collections for admin UI organization#292

Open
tohaitrieu wants to merge 6 commits into
emdash-cms:mainfrom
tohaitrieu:feat/collection-groups
Open

feat(core): add group and sortOrder to collections for admin UI organization#292
tohaitrieu wants to merge 6 commits into
emdash-cms:mainfrom
tohaitrieu:feat/collection-groups

Conversation

@tohaitrieu
Copy link
Copy Markdown

What does this PR do?

Add collection grouping support for better plugin organization in the admin sidebar. Plugins can define group and sortOrder in their seed.json to organize collections into logical groups (e.g., "Trading", "LMS", "Community").

Discussion: #291

Changes:

  • Add group (TEXT) and sort_order (INTEGER) columns to _emdash_collections
  • Update SchemaRegistry to handle group/sortOrder in create/update/list operations
  • Update seed types to accept group/sortOrder from plugins
  • Collections sorted by sort_order in listCollections()

Type of change

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

Checklist

tohaitrieu and others added 6 commits April 4, 2026 12:24
- Add TipTap table extensions (@tiptap/extension-table, table-row, table-cell, table-header)
- Add table to slash commands menu (/table)
- Add table button to EditorToolbar
- Add TableBubbleMenu for editing tables (add/remove rows/columns, toggle header, delete)
- Update prosemirrorToPortableText converter to handle tables
- Update portableTextToProsemirror converter to handle tables
- Add CSS styles for table editing including dark mode support
…ization

- Add group and sortOrder fields to SeedCollection interface
- Add group and sortOrder to CreateCollectionInput and UpdateCollectionInput
- Add group and sortOrder to Collection type
- Update createCollection and updateCollection to store these fields
- Update mapCollectionRow to read these fields
- Update listCollections to sort by sort_order
- Add migration 033_collection_groups for database schema
- Update CollectionTable type with new columns

This allows plugins to organize their collections into groups
(e.g., Trading, LMS, Community) for better admin UI navigation.
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 6, 2026

🦋 Changeset detected

Latest commit: be552fd

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

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

github-actions Bot commented Apr 6, 2026


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


1 out of 2 committers have signed the CLA.
✅ (tohaitrieu)[https://github.com/tohaitrieu]
❌ @emdashbot[bot]
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@tohaitrieu
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

@tohaitrieu
Copy link
Copy Markdown
Author

recheck

@tohaitrieu
Copy link
Copy Markdown
Author

The CLA check is failing because @emdashbot[bot] is listed as a committer. Bot accounts cannot sign the CLA. Could a maintainer please configure the CLA check to ignore bot accounts, or manually override this check?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 6, 2026

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.

@ascorbic
Copy link
Copy Markdown
Collaborator

Can you fix the conflicts

@github-actions
Copy link
Copy Markdown
Contributor

This PR has been inactive for 14 days. It will be closed automatically in 7 days if there is no further activity.

If you're still working on this, please push an update or leave a comment.

@ahliweb
Copy link
Copy Markdown
Contributor

ahliweb commented May 23, 2026

Hi @tohaitrieu, thanks for this PR! I'm working on a new proposal at Discussion #1151 focused on admin sidebar grouping for collections AND plugin admin pages (after the maintainer asked me to split my previous PR #1024).

Your PR (#292) already handles the collection grouping part nicely — solid migration, types, and registry updates. If discussion #1151 gets maintainer approval, I'd like to propose adopting/continuing the work from PR #292 as the foundation for collection grouping, and I'll add plugin admin page grouping on top.

Would you be interested in collaborating? We can coordinate on discussion #1151 or here. Cheers!

@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label May 30, 2026
@ascorbic ascorbic added the bot:review Trigger an emdashbot code review on this PR label May 31, 2026
Copy link
Copy Markdown
Contributor

@emdashbot emdashbot Bot left a comment

Choose a reason for hiding this comment

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

Approach judgment

The collection groups feature is sound and correctly scoped — it has an approved Discussion (#291) and touches the right layers (DB migration, registry, seed types). The sort_order + group index and the mapCollectionRow fallback defaults are the right patterns.

However, this PR bundles an entire unrelated TipTap table editor feature (~200 lines in PortableTextEditor.tsx, new dependencies, and new CSS). That violates AGENTS.md directly:

"Do not touch code outside the scope of your change. No drive-by refactors, no 'while I'm here' improvements."

The table feature also lacks a linked approved Discussion, making it an unsolicited feature per AGENTS.md. It should be removed from this branch and PRed separately if the author wants to pursue it.

Cross-cutting concerns the diff misses

The PR adds group and sortOrder to the database layer and TypeScript types, but forgot to update the API contract:

  • packages/core/src/api/schemas/schema.tscreateCollectionBody, updateCollectionBody, and collectionSchema do not include group or sortOrder. Because the route handlers use Zod via parseBody, API consumers cannot set or read these fields. The feature is effectively unreachable over the wire.
  • packages/core/src/astro/routes/api/schema/index.ts — the JSON schema export endpoint also omits group and sortOrder, so the CLI emdash types and dev-server sync won't see them.

Both files need the same additions that were made to the internal DB types.

Table feature bugs

If the table code stays (it shouldn't), it has real bugs:

  1. Link stripping on round-tripconvertPTBlock's table cell handler maps marks with a simple name map (strong → bold, etc.) but never resolves markDef references. A link stored as a Portable Text markDef will be silently dropped when reloading the editor.
  2. Peer dependency version skew@tiptap/extension-table@3.22.1 requires @tiptap/core@^3.22.1 and @tiptap/pm@^3.22.1, but the workspace pins everything else to 3.20.0. This mismatch can cause runtime errors if the extension uses APIs added after 3.20.0.
  3. Wrong dependency section — runtime TipTap extensions are placed in devDependencies, inconsistent with every other TipTap extension in packages/admin/package.json.
  4. Broken button overlay positioning — the Plus icons inside table bubble menu buttons use absolute -left-0.5 / -bottom-0.5, but BubbleButton (and the underlying Button component) is not relative, so the icons will be positioned against the menu container instead of the button.

Missing tests

There are no new tests for:

  • listCollections ordering by sort_order
  • createCollection / updateCollection persisting group and sortOrder
  • applySeed forwarding group/sortOrder from seed JSON
  • Migration 034 up/down behavior

import CharacterCount from "@tiptap/extension-character-count";
import Focus from "@tiptap/extension-focus";
import Placeholder from "@tiptap/extension-placeholder";
import { Table } from "@tiptap/extension-table";
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 PR is titled "add group and sortOrder to collections" but bundles an entire TipTap table editor feature. That violates AGENTS.md's scope rule:

"Do not touch code outside the scope of your change. No drive-by refactors, no 'while I'm here' improvements."

The table feature also lacks a linked approved Discussion. Please remove all table-related changes from this branch and open a separate PR if you want to pursue tables.

};

const rows = (tableBlock.rows || []).map((row, rowIndex) => {
const cells = row.cells.map((cell) => {
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 mark mapping is naive and breaks links (and any other mark-def-based marks) inside table cells.

PortableText stores links as markDefs referenced by _key. If a span has marks: ["someLinkKey"], this code passes "someLinkKey" directly as a ProseMirror mark type, which does not exist. The link is silently stripped on round-trip.

The correct fix is to reuse the existing convertInlineContent helper (which already handles markDefs properly) instead of hand-rolling a second inline converter for table cells:

Suggested change
const cells = row.cells.map((cell) => {
// Map PortableText marks to ProseMirror marks
const { children, markDefs } = convertInlineContent(cell.content);
return {
type: cellType,
content: [
{
type: "paragraph",
content: children.length > 0 ? children : undefined,
},
],
};

(You would also need to thread markDefs upward to convertPTBlock the same way the existing block handlers do.)

"@tailwindcss/cli": "^4.1.10",
"@tailwindcss/typography": "^0.5.19",
"@testing-library/react": "^16.3.0",
"@tiptap/extension-table": "^3.22.1",
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] These are runtime dependencies used by PortableTextEditor.tsx, but they are placed in devDependencies. Every other TipTap extension in this package lives in dependencies. Move them to the correct section.

Additionally, @tiptap/extension-table@3.22.1 declares peer dependencies on @tiptap/core@^3.22.1 and @tiptap/pm@^3.22.1, but the workspace pins all other TipTap packages to 3.20.0. That peer mismatch can cause runtime incompatibilities. Either upgrade all TipTap packages together, or pin the table extensions to the same version the rest of the monorepo uses.

title="Add column before"
>
<Columns className="h-4 w-4" />
<Plus className="h-2 w-2 absolute -left-0.5" />
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 Plus icon uses absolute -left-0.5, but BubbleButton (and the underlying Button component) does not set relative. The icon will be positioned against the nearest positioned ancestor — likely the BubbleMenu flex container — rather than the button itself. Add relative to the BubbleButton wrapper (or to the Button's className) so the overlay lines up correctly.

The same issue affects the other Plus icons at -right-0.5, -top-0.5, and -bottom-0.5.

@github-actions github-actions Bot added review/awaiting-author Reviewed; waiting on the author to respond and removed review/needs-review No maintainer or bot review yet labels May 31, 2026
@github-actions github-actions Bot mentioned this pull request Jun 1, 2026
18 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants