Skip to content

Add the Properties Panel prototype - #12

Open
mattakamatsu wants to merge 2 commits into
mainfrom
properties-panel
Open

Add the Properties Panel prototype#12
mattakamatsu wants to merge 2 commits into
mainfrom
properties-panel

Conversation

@mattakamatsu

Copy link
Copy Markdown

Ports the dg-properties-panel roam/js prototype (extension.js v0.4.2, from the private DiscourseGraphs/dg-properties-panel repo) into this repository's installable developer-extension form. This makes the panel installable from a URL instead of the guarded-patch roam/js-block deploy we have been using in the dg-team graph.

What the panel does

Renders the #.properties block on discourse-node pages as a structured, editable panel: chips for filled slots, ghost "+ add" affordances for unfilled template slots, vocabulary-backed selects and multi-selects driven by the [[roam/js/attribute-select]] registry (including its <%QUERYBUILDER%> / <%ACTIVEUSERS%> dynamic options, resolved by running the options block as a SmartBlock — attribute-select parity by construction), drift flags with one-click fixes, resolved markdown aliases and ((block refs)), a title-level actions row with the registerAction / dgpp:ready extension contract, and full dark-mode coverage for native Roam and Roam Studio. The blocks remain the only store: every edit is a plain text block write, and "view as blocks" shows the native subtree.

Port notes

  • Logic carried over intact. The pure core (src/core.ts) is line-for-line from the roam/js prototype, and the 98-assertion offline suite ports pin-for-pin to vitest (tests/).
  • One structural change: this repo forbids the synchronous roamAlphaAPI.q/pull aliases, so all reads go through data.async.* and the panel renders from a pre-loaded snapshot (src/graph.ts loadSnapshot) instead of pulling during render. Block-ref texts resolve in one batched query. Writes use data.block.*; Datalog is parameterized throughout.
  • Coexistence: loading this build unloads a live roam/js-block instance first (and vice versa — the roam/js build already replaces prior instances), so the two install paths cannot double-mount. The window.dgPropsPanel contract is unchanged; the Linear-Roam sync extension's "linear" action-slot registration works against either build.
  • CSS is carried in the bundle via addStyle for the same reason copy-for-latex does it: extension.css is only injected on the URL-loading path, not when previews are imported from a roam/js block.

Validation

pnpm test (98 passed), pnpm build, pnpm prepare:artifacts (2 artifact sets) all pass, under Node 22 per the engines field.

Tooling observations (not fixed here, matching the copy-for-latex PR's practice)

  • The repo's engines requires Node ≥22 but nothing enforces it: under Node 20 the vitest run fails deep inside jsdom/undici (webidl.util.markAsUncloneable is not a function), which is a confusing way to learn you're on the wrong Node.
  • The workspace's TypeScript (v6) rejects packages/extension-base/tsconfig.json (moduleResolution: node10 and baseUrl were removed), so tsc cannot run against the shared config at all. This prototype ships an opt-in tsconfig.check.json with modern options (pnpm exec tsc -p tsconfig.check.json passes clean, strict); @types/react@17 / @types/react-dom@17 are devDependencies pinned to the versions roamjs-components already brings transitively.
  • pnpm create:prototype --name … (without the -- separator that CONTRIBUTING shows) is still the form that works on the pinned pnpm 10.

Testing in Roam

Once CI publishes the preview, load the Roam prototype previews comment's URL in a test graph via Load Developer Extensions from URL — the plan is plugin-testing-akamatsulab2 first, then the dg-team graph, before flipping dg-team off the roam/js block.

🤖 Generated with Claude Code

Port of the dg-properties-panel roam/js prototype (extension.js v0.4.2)
into the repository's installable developer-extension form. Logic is
carried over intact; the one structural change is that all graph reads go
through data.async.* — the panel renders from a pre-loaded snapshot
(including batch-resolved ((block ref)) texts) instead of pulling during
render. Writes use data.block.*; Datalog is parameterized throughout.

The 98-assertion offline suite ports pin-for-pin to vitest. The public
window.dgPropsPanel contract (registerAction, dgpp:ready) is unchanged, and
loading this build unloads a live roam/js-block instance first so the two
install paths cannot double-mount.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown

Roam prototype previews

The preview deployment is ready. Paste a URL below into Load Developer Extensions from URL in Roam:

View publishing details

Same pair of bugs copy-for-latex hit (their fixes adopted here):

- import addStyle from roamjs-components binds { default: fn } under
  esbuild's Node-interop __toESM and throws at load. The stylesheet is now
  injected by local code; tests/interop.spec.ts bans default imports from
  roamjs-components at the source level, since vitest's own interop hides
  the bug.
- runExtension's production failure reporter reads extensionAPI.settings,
  which is undefined when the module is import()ed from a roam/js block, so
  the real error surfaced only as "reading 'settings'". Errors are now
  caught and reported (console first, toast attempted separately) before
  that reporter runs, and a missing data.async.q names itself.

tests/bundle.spec.ts additionally loads the built dist/extension.js in
jsdom with host globals stubbed and runs onload exactly as the loader
block does — verified to fail against the buggy build and pass against
this one. 101 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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