Skip to content

feat(dashboard): add pagination, server-side search#1480

Open
gora050 wants to merge 9 commits intoopenclaw:mainfrom
gora050:feat/dashboard-pagination-search
Open

feat(dashboard): add pagination, server-side search#1480
gora050 wants to merge 9 commits intoopenclaw:mainfrom
gora050:feat/dashboard-pagination-search

Conversation

@gora050
Copy link
Copy Markdown

@gora050 gora050 commented Apr 2, 2026

Summary

  • Added "Load More" for Skills list on /dashboard page via "Load More"
  • Extended .gitignore
export-1775137075662.mp4

(AI Assisted)

Changes

  • Add listDashboardPaginated query using Convex .paginate() for incremental loading of publisher skills
  • Update dashboard UI with "Load More" button

Test plan

  • Open /dashboard with a publisher that has many skills — initial load shows 50, "Load More" fetches more
  • Verify "Load More" disappears when all skills are loaded

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Apr 2, 2026

@gora050 is attempting to deploy a commit to the 0xBuns Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 2, 2026

Greptile Summary

This PR adds server-side pagination to the Publisher Dashboard's skills list, replacing the old useQuery(api.skills.list, { limit: 100 }) call with usePaginatedQuery(api.skills.listDashboardPaginated, …, { initialNumItems: 50 }) and a "Load More" button. A companion toDashboardPage helper exposes pending.scan hidden skills to the owner, and a new test file validates the four main access paths.

Key changes

  • New listDashboardPaginated Convex query with index-level soft-delete filtering (.filter((q) => q.eq(q.field("softDeletedAt"), undefined)) before .paginate()) — correctly avoids the post-paginate JS cursor mismatch.
  • toDashboardPage helper maps non-public pending-scan skills into a pendingReview: true shape for owners.
  • Dashboard UI shows a "Load More" button when skillsStatus === "CanLoadMore" and a spinner while loading.
  • .gitignore extended with .agents, /skills (rooted), skills-lock.json, .claude.

Issues found

  • The "Load More" button and the "No skills yet" empty state are in separate render branches without coordination. When all items in the first page are post-processed away (e.g. every skill is moderator-suspended), skills.length === 0 shows the empty state while skillsStatus === "CanLoadMore" still renders the button below it — a confusing UI state.
  • toDashboardPage silently drops any owner skill whose moderationStatus is neither active nor exactly hidden/pending.scan, so suspended or otherwise moderated skills are invisible to the owner on their own dashboard.

Confidence Score: 4/5

Safe to merge with minor fixes — no data loss or security risk, but two edge-case correctness issues should be addressed before the feature is considered complete.

The core pagination implementation is solid: the soft-delete filter runs inside Convex before pagination, so cursor integrity is maintained. The two remaining findings are both P2 edge cases (confusing 'No skills yet' + 'Load More' co-appearance, and silently dropped moderated skills on the owner's own dashboard), but they affect correctness of the dashboard view in real (if rare) scenarios, warranting a score of 4 rather than 5.

src/routes/dashboard.tsx (empty-state / Load More coordination) and convex/skills.ts (toDashboardPage hidden-skill visibility for owners).

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/routes/dashboard.tsx
Line: 208-214

Comment:
**"Load More" can appear alongside the "No skills yet" empty state**

`skills.length === 0` is used to pick between the empty-state and the list, but `skillsStatus === "CanLoadMore"` is checked separately—outside that branch. If every item in the first page is filtered out by `toDashboardPage` (e.g. moderator-suspended skills for the owner, or non-public skills for a non-owner viewer), `paginatedSkills` will be empty while `usePaginatedQuery` still reports `CanLoadMore`. The result is the "No skills yet" message rendered above the "Load More" button simultaneously, which is confusing and implies there is nothing to load.

Guard the "Load More" / "LoadingMore" rows on `skills.length > 0`, or show them unconditionally outside the empty-state branch:

```suggestion
            {skills.length === 0 && skillsStatus !== "CanLoadMore" ? (
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: convex/skills.ts
Line: 2263-2295

Comment:
**`toDashboardPage` silently drops owner-visible skills with non-`pending.scan` hidden status**

When `isOwnDashboard` is `true`, `toDashboardPage` shows a skill only if `toPublicSkill` succeeds (active status) OR `moderationReason === "pending.scan"`. Any other non-public state—e.g. `moderationStatus: "suspended"`, `"removed"`, or a future `"pending.human-review"` reason—will silently fall through to `return null` and be excluded from the owner's dashboard view.

This means an owner could lose visibility into why certain skills are absent. The original `api.skills.list` had the same blind spot, but `listDashboardPaginated` is explicitly described as a fuller owner view ("hidden skill versions remain visible here while checks are pending"), so the intent seems to be to expose more, not less.

Consider surfacing all non-deleted skills to their owner regardless of moderation state, or at minimum mapping every moderation status into a labelled entry rather than silently dropping it:

```ts
// inside isOwnDashboard branch — replace the isPending guard:
return {
  _id: skill._id,
  // ...fields...
  pendingReview: skill.moderationStatus !== "active",
  moderationStatus: skill.moderationStatus,
  moderationReason: skill.moderationReason,
};
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (2): Last reviewed commit: "tests" | Re-trigger Greptile

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 026b2929f9

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 79d04b45d4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@gora050 gora050 changed the title feat(dashboard): add pagination, server-side search, and skill count WIP: feat(dashboard): add pagination, server-side search, and skill count Apr 2, 2026
@gora050 gora050 changed the title WIP: feat(dashboard): add pagination, server-side search, and skill count feat(dashboard): add pagination, server-side search, and skill count Apr 2, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89fcb1b600

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
@gora050 gora050 changed the title feat(dashboard): add pagination, server-side search, and skill count WIP: feat(dashboard): add pagination, server-side search Apr 2, 2026
@gora050 gora050 marked this pull request as draft April 2, 2026 12:43
@gora050 gora050 marked this pull request as ready for review April 2, 2026 13:42
@gora050 gora050 changed the title WIP: feat(dashboard): add pagination, server-side search feat(dashboard): add pagination, server-side search Apr 2, 2026
@gora050
Copy link
Copy Markdown
Author

gora050 commented Apr 2, 2026

Originally this PR also had dashboard search (server-side full-text by name/description).

During review it became clear the whole search setup needs fixing — same issues exist in public /skills?q= (500-row cap on lexical fallback, zero-vector skills don’t show up in vector search).

So instead of hacking a dashboard-only fix, I cut this PR down to just pagination. Will handle search properly in a follow-up.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9d9531413d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +2223 to +2225
const result = await ctx.db
.query("skills")
.withIndex("by_owner_publisher", (q) => q.eq("ownerPublisherId", ownerPublisherId))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include linked-user legacy skills in publisher pagination

listDashboardPaginated only paginates by_owner_publisher, but the existing skills.list behavior for personal publishers explicitly merges linked-user legacy rows (ownerPublisherId unset) so pre-backfill skills stay visible. This new path drops that fallback, so requests using ownerPublisherId can silently miss legacy personal skills and loadMore will never recover them because they are on a different index path.

Useful? React with 👍 / 👎.

const result = await ctx.db
.query("skills")
.withIndex("by_owner_publisher", (q) => q.eq("ownerPublisherId", ownerPublisherId))
.filter((q) => q.eq(q.field("softDeletedAt"), undefined))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid filtering soft-deletes after owner index scans

Both paginated branches call .filter(q => q.eq(q.field("softDeletedAt"), undefined)) after by_owner/by_owner_publisher, which forces Convex to read through deleted rows inside each owner partition before serving a page. For owners with many soft-deleted skills this can significantly inflate document reads and can hit read limits; this path should paginate on composite active-owner indexes instead of post-index filters.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant