[BNE-99] Replace pastededuplicate#176
Draft
judithroth wants to merge 2 commits into
Draft
Conversation
https://community.openproject.org/wp/BNE-99 Major refactoring to reduce complexity on the communication between Popover for resizing and the work package link. - Removed wpBridge, instanceId, useOpBlockNoteExtensions, and PasteDeduplicateInstanceIdsExtension entirely. - Replaced them with direct, position-based editor mutations in a new lib/utils/inlineChipActions.ts: BlockNote's updateInlineContent render prop for resize/heal, and view.posAtDOM + ProseMirror transactions for select/delete/promote. - Re-keyed the pending-WP-search flow to use the pending wpid itself instead of a separate instanceId. - Made hash-menu trigger cleanup position-based, preserving the COMMS-806 natural-caret behavior verbatim. - Stripped instanceId/data-instance-id from both prop schemas and external HTML serialization. - Updated OpBlockNoteEditor.tsx in the OpenProject sandbox copy to drop the removed imports/calls. - Bumped the package to 0.2.0. One added benefit: Setting up op-blocknote-extensions got a lot easier again.
There was a problem hiding this comment.
Pull request overview
This PR refactors inline work package chip interactions to be position-based (DOM/ProseMirror position) instead of instanceId/wpBridge event routing, removing paste-time deduplication and simplifying editor setup while keeping user-facing behaviors (resize/remove/convert) working for both inline chips and block cards.
Changes:
- Removed
wpBridge,instanceId, and the paste-deduplication extension/plugin; updated all schemas, serialization, and tests accordingly. - Added
lib/utils/inlineChipActions.tsto target chip operations directly via ProseMirror positions / DOM resolution (select/remove/promote/convert). - Reworked pending inline insertion/callback routing to key off the pending
wpiditself and updated integration/unit tests to cover identical-chips-in-paragraph scenarios.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/lib/utils/inlineChipActions.test.ts | Adds unit coverage for the new position-based inline chip actions utilities. |
| test/lib/utils/id.test.ts | Removes tests/imports for deleted makeInstanceId. |
| test/lib/services/wpBridge.test.ts | Deletes tests for the removed wpBridge event bus. |
| test/lib/components/staticSpec.test.ts | Updates spec parsing/serialization expectations after removing instanceId from external HTML. |
| test/lib/components/integration/wpOptionsPopover.browser.test.tsx | Updates popover integration tests to reflect direct mutations (no wpBridge) and new helper usage. |
| test/lib/components/integration/inlineWorkPackageSameParagraph.browser.test.tsx | Adds browser regression coverage for identical inline chips in the same paragraph. |
| test/lib/components/InlineWorkPackage/externalHtml.test.ts | Updates external HTML round-trip tests after removing data-instance-id. |
| test/lib/components/hashMenu.test.ts | Updates hash menu tests for position-based trigger cleanup and removal of instanceId. |
| test/lib/components/callbacks.test.ts | Re-keys pending callback registry tests to use pending wpid instead of a separate key/instanceId. |
| test/lib/components/BlockWorkPackage/externalHtml.test.ts | Updates block external HTML tests after removing data-instance-id. |
| test/helpers/renderEditor.tsx | Simplifies editor setup by removing deduplicate extension and post-mount hook wiring. |
| src/App.tsx | Simplifies sandbox app editor setup by removing deduplicate extension and post-mount hook wiring. |
| package.json | Bumps package version to 0.2.0. |
| lib/utils/inlineChipActions.ts | Introduces the new position-based chip actions (find/select/remove/promote/convert). |
| lib/utils/id.ts | Removes makeInstanceId, leaving only formatWorkPackageId. |
| lib/utils/cursor.ts | Removes old inline-node selection helper tied to instanceId; retains block cursor helper. |
| lib/services/wpBridge.ts | Removes the wpBridge service entirely. |
| lib/plugins/pasteDeduplicatePlugin.ts | Removes paste deduplication plugin now that instanceId is removed. |
| lib/plugins/pasteDeduplicateExtension.ts | Removes the extension wrapper for the paste deduplication plugin. |
| lib/index.ts | Stops exporting removed bridge/id/extension/hook APIs. |
| lib/hooks/useOpBlockNoteExtensions.ts | Removes now-obsolete post-mount wiring hook. |
| lib/hooks/useInlineWpEvents.ts | Removes instanceId/wpBridge-based event handling implementation. |
| lib/components/WorkPackage/OptionsPopover.tsx | Removes instanceId from popover props (no longer needed). |
| lib/components/SlashMenu.tsx | Reworks inline insertion flow to use pending wpid and ProseMirror transactions for resolve/cancel. |
| lib/components/InlineWorkPackage/spec.tsx | Passes updateInlineContent from the node view into the chip component. |
| lib/components/InlineWorkPackage/InlineWorkPackageChip.tsx | Switches chip actions to direct position-based editor mutations and uses updateInlineContent for in-place updates. |
| lib/components/InlineWorkPackage/inlineConfig.ts | Removes instanceId from inline prop schema. |
| lib/components/InlineWorkPackage/externalHtml.ts | Removes instanceId from external HTML compute/parse for inline chips. |
| lib/components/InlineWorkPackage/callbacks.ts | Generates unique pending wpids and uses them directly as callback registry keys. |
| lib/components/HashMenu/editorUtils.ts | Removes instanceId generation and makes trigger cleanup position-based via selection-derived chip position. |
| lib/components/BlockWorkPackage/types.ts | Removes instanceId from block props typing. |
| lib/components/BlockWorkPackage/externalHtml.ts | Removes instanceId from external HTML compute/parse for block cards. |
| lib/components/BlockWorkPackage/BlockWorkPackage.tsx | Converts block→inline via new convertBlockToInlineChip utility (no wpBridge). |
| lib/components/BlockWorkPackage/blockConfig.ts | Removes instanceId from block prop schema. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+197
to
+205
| const [afterParagraph] = editor.insertBlocks( | ||
| [{ type: 'paragraph', content }], | ||
| anchorBlockId, | ||
| 'after' | ||
| ); | ||
| requestAnimationFrame(() => { | ||
| editor.focus(); | ||
| editor.setTextCursorPosition(afterParagraph.id, 'start'); | ||
| }); |
Comment on lines
+11
to
+16
| let editor:{ document:unknown; replaceBlocks:(oldBlocks:unknown, newBlocks:unknown) => void }; | ||
| renderEditor({ onEditor: (e) => { editor = e; } }); | ||
|
|
||
| await expect.element(page.getByRole('textbox')).toBeVisible(); | ||
|
|
||
| editor.replaceBlocks(editor.document, [ |
Comment on lines
+62
to
+65
| // The chip (nodeSize 1) and its trailing space (length 1) were just inserted; | ||
| // insertInlineContent leaves the cursor right after the space. | ||
| const chipPosition = editor.prosemirrorState.selection.from - 2; | ||
| removeTriggerBeforeChip(editor, chipPosition); |
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket
https://community.openproject.org/wp/BNE-99
What are you trying to accomplish?
Major refactoring to reduce complexity on the communication between Popover for resizing and the work package link.
One added benefit: Setting up op-blocknote-extensions got a lot easier again.
What approach did you choose and why?
The WpOptionsPopover no longer talks to the chip/card through any shared channel — there's no wpBridge, no instanceId. Instead:
from that same component's closure.
first resolve the chip's real ProseMirror position from its DOM element (findInlineChipAtDOM, via view.posAtDOM), then apply a direct transaction (removeInlineChipAt / promoteInlineChipToBlockAt) — all in
lib/utils/inlineChipActions.ts.
Because every action targets the node's actual position or DOM element instead of a shared ID, two identical chips can never collide (no dedup-on-paste needed), and no registration/subscription step is
required — the popover's callbacks already close over everything they need.
Implementation
Merge checklist
Matching PR in OpenProject: opf/openproject#24094 (note: Unfinished - op-blocknote-extensions is not released yet)