Skip to content

feat(core): add unlink action for linked docs in sidebar - #15360

Open
qvictl wants to merge 2 commits into
toeverything:canaryfrom
qvictl:fix/unlink-documents
Open

feat(core): add unlink action for linked docs in sidebar#15360
qvictl wants to merge 2 commits into
toeverything:canaryfrom
qvictl:fix/unlink-documents

Conversation

@qvictl

@qvictl qvictl commented Jul 27, 2026

Copy link
Copy Markdown

Summary

Fixes #13511

Drag-and-drop creates a linked-doc relationship by inserting a page reference into the parent doc content, with no way to undo it short of manually editing the parent doc.

  • add DocsService.removeLinkedDoc(targetDocId, linkedDocId): removes all reference deltas pointing at the linked doc from the target doc content (inverse of addLinkedDoc), deleting paragraphs left empty afterwards
  • expose an "Unlink" item in the context menu of linked doc nodes in the navigation panel, guarded by Doc_Update on the parent doc
  • i18n: en / zh-Hans / zh-Hant

Test plan

  • e2e: tests/affine-local/e2e/unlink-doc.spec.ts — link via drag-and-drop, unlink via context menu, assert the child doc is unlinked but not deleted
  • tsc -b packages/frontend/core clean
  • oxlint / prettier clean
  • manual: expand a doc with linked docs in the sidebar, right-click a linked child → Unlink → child disappears from the parent, doc itself remains in All Docs

Summary by CodeRabbit

  • New Features
    • Added an Unlink option for linked documents in the sidebar context menu.
    • Unlinking removes the parent-child relationship while keeping the document available in the full document list.
    • Displays success or permission feedback after unlinking.
  • Localization
    • Added English, Simplified Chinese, and Traditional Chinese translations for unlink actions and status messages.
  • Tests
    • Added end-to-end coverage confirming unlinking preserves the document in the full list.

@CLAassistant

CLAassistant commented Jul 27, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions Bot added mod:i18n Related to i18n test Related to test cases app:core labels Jul 27, 2026
@coderabbitai

coderabbitai Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 84899b64-311a-471c-bcc5-b73b522cfe5e

📥 Commits

Reviewing files that changed from the base of the PR and between 70b1648 and c7c6f37.

📒 Files selected for processing (2)
  • packages/frontend/i18n/src/i18n.gen.ts
  • packages/frontend/i18n/src/resources/en.json

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

Adds an “Unlink” sidebar action for linked documents. The action removes matching references from the parent document, preserves the child document, adds localized labels, and includes an end-to-end test.

Changes

Document unlinking

Layer / File(s) Summary
Linked-reference removal
packages/frontend/core/src/modules/doc/services/docs.ts
DocsService.removeLinkedDoc traverses the target document, removes references to the linked document, deletes emptied paragraphs, and returns the removal count.
Sidebar unlink action
packages/frontend/core/src/desktop/components/navigation-panel/nodes/doc/..., packages/frontend/i18n/src/...
Sidebar operations receive parentDocId, expose a permission-guarded “Unlink” action, call the document service, and display localized status text.
End-to-end unlink validation
tests/affine-local/e2e/unlink-doc.spec.ts
Playwright verifies that unlinking removes the parent-child sidebar relationship while retaining the child document in All Docs.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to c7c6f

This PR adds an authorized Unlink action that removes linked-document references while preserving the child document; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant Sidebar
  participant DocsService
  participant ParentDocument
  User->>Sidebar: Select Unlink
  Sidebar->>DocsService: removeLinkedDoc(parentDocId, docId)
  DocsService->>ParentDocument: Remove matching references
  ParentDocument-->>DocsService: Return removed count
  DocsService-->>Sidebar: Complete unlink
  Sidebar-->>User: Show Unlinked status
Loading

Possibly related PRs

Suggested labels: mod:component

Suggested reviewers: darkskygit

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The English mobile settings and account-related translation changes are unrelated to the unlink document feature. Remove unrelated mobile settings, Discord, account-deletion, and email-confirmation translation changes from this PR.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding an unlink action for linked documents in the sidebar.
Linked Issues check ✅ Passed The PR implements the requested unlink action, removes parent references without deleting the child document, and adds coverage for issue [#13511].

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
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/frontend/core/src/modules/doc/services/docs.ts (1)

238-244: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Empty-block cleanup only handles affine:paragraph.

References can be typed anywhere text exists (e.g. list items, headings), not only paragraphs. If a reference-only list item/heading becomes empty after removal, it's left behind as a stray empty block instead of being cleaned up, unlike paragraphs.

🤖 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 `@packages/frontend/core/src/modules/doc/services/docs.ts` around lines 238 -
244, Update the empty-block cleanup condition in the surrounding removal logic
to apply to any text-bearing block, not only models with flavour
affine:paragraph. Preserve the existing removed-count and text.length checks,
and continue deleting the block through bsDoc.deleteBlock(model.id).
🤖 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 `@packages/frontend/core/src/modules/doc/services/docs.ts`:
- Around line 212-217: Wrap the mutation and deletion work in removeLinkedDoc,
after open and priority-load setup, in a try/finally block; invoke release() in
the finally clause so it always runs if text.delete or bsDoc.deleteBlock throws.
Preserve the existing cleanup of disposePriorityLoad and follow the release
pattern used by duplicate and duplicateFromTemplate.

---

Nitpick comments:
In `@packages/frontend/core/src/modules/doc/services/docs.ts`:
- Around line 238-244: Update the empty-block cleanup condition in the
surrounding removal logic to apply to any text-bearing block, not only models
with flavour affine:paragraph. Preserve the existing removed-count and
text.length checks, and continue deleting the block through
bsDoc.deleteBlock(model.id).
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3bd34343-aaaf-4f33-9671-c8685bef2770

📥 Commits

Reviewing files that changed from the base of the PR and between b05f165 and 95ec323.

📒 Files selected for processing (8)
  • packages/frontend/core/src/desktop/components/navigation-panel/nodes/doc/index.tsx
  • packages/frontend/core/src/desktop/components/navigation-panel/nodes/doc/operations.tsx
  • packages/frontend/core/src/modules/doc/services/docs.ts
  • packages/frontend/i18n/src/i18n.gen.ts
  • packages/frontend/i18n/src/resources/en.json
  • packages/frontend/i18n/src/resources/zh-Hans.json
  • packages/frontend/i18n/src/resources/zh-Hant.json
  • tests/affine-local/e2e/unlink-doc.spec.ts

Comment thread packages/frontend/core/src/modules/doc/services/docs.ts
@qvictl
qvictl force-pushed the fix/unlink-documents branch from 95ec323 to 885c8ab Compare July 27, 2026 12:19
@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

…g#13511)

Drag-and-drop creates a linked-doc relationship by inserting a page
reference into the parent doc content, with no way to undo it short of
manually editing the parent doc.

- add DocsService.removeLinkedDoc(targetDocId, linkedDocId): removes all
  reference deltas pointing at the linked doc from the target doc content
  (inverse of addLinkedDoc), deleting paragraphs left empty afterwards
- expose an "Unlink" item in the context menu of linked doc nodes in the
  navigation panel, guarded by Doc_Update on the parent doc
- e2e coverage: link via drag-and-drop, unlink via context menu, assert
  the child doc is unlinked but not deleted

Fixes toeverything#13511
@qvictl
qvictl force-pushed the fix/unlink-documents branch from 70b1648 to aec5026 Compare August 15, 2026 14:25
@donqu1xotevincent donqu1xotevincent self-assigned this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app:core mod:component mod:i18n Related to i18n test Related to test cases

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

[Feature Request]: Unlink documents

3 participants