Skip to content

feat(board): support host-integrated Card details - #65

Merged
cnjack merged 3 commits into
mainfrom
codex/card-execution-supplement
Jul 31, 2026
Merged

feat(board): support host-integrated Card details#65
cnjack merged 3 commits into
mainfrom
codex/card-execution-supplement

Conversation

@cnjack

@cnjack cnjack commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Summary

  • open an exact Card once from a host-provided deep link
  • render host supplements in editable and read-only Card details
  • scan explicit host-managed Card roots while preserving board-frontmatter isolation

Verification

  • pnpm build in packages/board-react
  • 21 board-react unit tests
  • 8 board-react embed E2E tests

Cloud integration

Cloud pins commit a83f55b8112cc534f42c66e9f8f1b6274ce3706d, passes additionalCardRoots={["jcode-automation"]}, and keeps Viewer embeds read-only.

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The embed now accepts an optional card path. After the initial snapshot loads, the board opens a matching card once. Missing cards produce localized banner errors. Embed tests cover successful opening, dismissal, and missing-card handling.

Changes

Initial card deep-link flow

Layer / File(s) Summary
Initial card API and localization
packages/board-react/src/JTypeBoard.tsx, packages/board-react/src/strings.ts, shared/components/board/types.ts, packages/board-react/README.md
JTypeBoard and BoardSurface accept initial card inputs. UiStrings includes localized card-not-found formatters.
One-time card initialization
shared/components/board/BoardSurface.tsx, packages/board-react/src/JTypeBoard.tsx
BoardSurface opens a matching card through onCardOpen or its built-in detail view. It ignores missing and repeated initial IDs.
Embed deep-link integration
tests/fixtures/board-react-embed.tsx, tests/e2e/board-react-embed.spec.ts
The fixture reads the card query parameter and conditionally enables polling. E2E tests cover successful opening, dismissal, and missing cards.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EmbedFixture
  participant JTypeBoard
  participant BoardSurface
  participant CardSnapshot
  participant CardDialog

  EmbedFixture->>JTypeBoard: pass initialCardPath
  JTypeBoard->>BoardSurface: pass initialCardId
  BoardSurface->>CardSnapshot: wait for loaded cards
  CardSnapshot-->>BoardSurface: return matching card
  BoardSurface->>CardDialog: open card once
  CardDialog-->>BoardSurface: close card
  BoardSurface-->>CardDialog: do not reopen initial card
Loading

Possibly related PRs

  • cnjack/jtype#47: Introduced the embeddable board-react package extended by this change.
  • cnjack/jtype#63: Introduced the embed card-opening behavior extended with one-time deep-link initialization.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: support for host-integrated Card details through board embeds.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/card-execution-supplement

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@shared/components/board/BoardSurface.tsx`:
- Around line 152-163: The deep-link handling in BoardSurface must not own
mutable lifecycle state or call setSelectedId internally. Remove
initialCardHandled and the effect-driven internal selection; move one-time
initialCardId resolution to the platform owner, or make BoardSurface controlled
by receiving selection/open state through props and emitting selection/open
actions via callbacks while preserving the existing card-open behavior.

In `@tests/e2e/board-react-embed.spec.ts`:
- Around line 177-190: Update the test around the closed Card details dialog to
wait for a deterministic confirmed refresh rather than relying on
page.waitForTimeout. Force polling for this scenario and wait for the second
snapshot request, or observe an equivalent refresh signal, before asserting
dialog remains hidden; preserve the existing initial deep-link and close-button
assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3c06e8e4-115e-4930-9541-ec88c64f6748

📥 Commits

Reviewing files that changed from the base of the PR and between 5dc8b7f and d08d75d.

⛔ Files ignored due to path filters (2)
  • packages/board-react/dist/index.d.ts is excluded by !**/dist/**
  • packages/board-react/dist/index.js is excluded by !**/dist/**
📒 Files selected for processing (7)
  • packages/board-react/README.md
  • packages/board-react/src/JTypeBoard.tsx
  • packages/board-react/src/strings.ts
  • shared/components/board/BoardSurface.tsx
  • shared/components/board/types.ts
  • tests/e2e/board-react-embed.spec.ts
  • tests/fixtures/board-react-embed.tsx

Comment on lines +152 to +163
const initialCardHandled = useRef(false);

useEffect(() => {
if (initialCardHandled.current || !initialCardId) return;
if (!cards.some((card) => card.id === initialCardId)) return;
initialCardHandled.current = true;
if (onCardOpen) {
onCardOpen(cards.find((card) => card.id === initialCardId)!);
return;
}
setSelectedId(initialCardId);
}, [cards, initialCardId, onCardOpen]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Keep the deep-link lifecycle state outside BoardSurface.

Lines [152-163] add a private mutable guard and an internal selection update to a shared component. Lift the one-time resolution to the platform owner, or expose controlled selection/open callbacks so BoardSurface receives state through props and emits actions through callbacks.

As per coding guidelines, shared React components must follow the Props-in/Callbacks-out pattern and must not depend on a specific state pattern.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shared/components/board/BoardSurface.tsx` around lines 152 - 163, The
deep-link handling in BoardSurface must not own mutable lifecycle state or call
setSelectedId internally. Remove initialCardHandled and the effect-driven
internal selection; move one-time initialCardId resolution to the platform
owner, or make BoardSurface controlled by receiving selection/open state through
props and emitting selection/open actions via callbacks while preserving the
existing card-open behavior.

Source: Coding guidelines

Comment on lines +177 to +190
test("editable package embed opens an exact Card deep link once", async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 900 });
await page.goto("/tests/fixtures/board-react-embed.html?card=jcode%2Fcard-0.md");
await expect(page.getByTestId("cloud-board-host").getByText("Jcode", { exact: true })).toBeVisible();

const dialog = page.getByRole("dialog", { name: "Card details" });
await expect(dialog).toBeVisible();
await expect(dialog.getByPlaceholder("Untitled card")).toHaveValue(cardTitles[0]!);

await dialog.getByRole("button", { name: "Close" }).click();
await expect(dialog).toBeHidden();
await page.waitForTimeout(5_100);
await expect(dialog).toBeHidden();
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Wait for a confirmed refresh before checking the closed state.

page.waitForTimeout(5_100) does not prove that a poll occurred. The timer starts after the initial load, and JTypeBoard skips the timer while SSE is active. Count the second snapshot request, force polling for this test, or use a deterministic refresh signal before asserting that the dialog remains hidden.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/e2e/board-react-embed.spec.ts` around lines 177 - 190, Update the test
around the closed Card details dialog to wait for a deterministic confirmed
refresh rather than relying on page.waitForTimeout. Force polling for this
scenario and wait for the second snapshot request, or observe an equivalent
refresh signal, before asserting dialog remains hidden; preserve the existing
initial deep-link and close-button assertions.

@cnjack cnjack changed the title feat(board): support Card deep links in embeds feat(board): support host-integrated Card details Jul 31, 2026
@cnjack
cnjack merged commit a0599ce into main Jul 31, 2026
3 checks passed
@cnjack
cnjack deleted the codex/card-execution-supplement branch July 31, 2026 15:11
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