Desktop: Publish a notebook#15276
Conversation
|
@Rygaa the pull request title does not match the required format. Please prefix the title with the area you are targeting, then add the issue you are addressing. For example:
See the pull request template for the list of valid prefixes and the full specification. This PR has been closed automatically. Please update the title and reopen it, or open a new pull request. |
|
Note: all server code is missing |
|
All contributors have signed the CLA ✍️ ✅ |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds PublishedFolder share support end-to-end: server/models/API, share service, client selectors/renderers, sidebar published markers and context menu, a Publish Folder dialog with command/window integration, public site folder-tree UI/assets, and related tests and ignore/dictionary updates. ChangesFolder publication feature
Sequence Diagram(s): Possibly related PRs:
Suggested labels: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| const bannerInfo = getDefaultBannerInfo(); | ||
| return renderNote(share, itemToRender, resourceInfos, linkedItemInfos, bannerInfo); |
There was a problem hiding this comment.
As discussed, this should remain here, so please pass around the banner info
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/lib/models/Folder.ts`:
- Around line 792-800: The current guard skips fetching notes when
noteIsSharedSql is empty, leaving notes with is_shared=1 stale; change the logic
around noteIsSharedSql and the notesToUpdate lookup so you always query notes
that need flipping: if noteIsSharedSql is non-empty run the existing SELECT that
finds rows where is_shared differs from the predicate, and if noteIsSharedSql is
empty run a SELECT that returns notes with is_shared = 1 (so they can be set to
0). Update the code around notesToUpdate, db().selectAll(…), and NoteEntity
handling to cover both branches (or remove the if and build a single SQL that
handles an empty predicate) so published state is cleared when there are no
active published-note predicates.
🪄 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
Run ID: 22c8bb4b-d604-45bc-b2fc-b8969dc03873
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (42)
.eslintignore.gitignorepackages/app-desktop/gui/NoteList/NoteList2.tsxpackages/app-desktop/gui/NoteList/utils/types.tspackages/app-desktop/gui/NoteListItem/NoteListItem.tsxpackages/app-desktop/gui/NoteListItem/utils/prepareViewProps.tspackages/app-desktop/gui/NoteListItem/utils/useRenderedNote.tspackages/app-desktop/gui/PublishFolderDialog.tsxpackages/app-desktop/gui/Sidebar/FolderAndTagList.tsxpackages/app-desktop/gui/Sidebar/hooks/useOnRenderItem.tsxpackages/app-desktop/gui/Sidebar/listItemComponents/FolderItem.tsxpackages/app-desktop/gui/Sidebar/styles/index.tspackages/app-desktop/gui/WindowCommandsAndDialogs/WindowCommandsAndDialogs.tsxpackages/app-desktop/gui/WindowCommandsAndDialogs/commands/index.tspackages/app-desktop/gui/WindowCommandsAndDialogs/commands/showPublishFolderDialog.tspackages/app-desktop/gui/WindowCommandsAndDialogs/types.tspackages/app-desktop/gui/WindowCommandsAndDialogs/utils/useSyncDialogState.tspackages/lib/models/Folder.tspackages/lib/services/commands/stateToWhenClauseContext.tspackages/lib/services/noteList/defaultLeftToRightListRenderer.tspackages/lib/services/noteList/defaultListRenderer.tspackages/lib/services/noteList/defaultMultiColumnsRenderer.tspackages/lib/services/plugins/api/noteListType.tspackages/lib/services/share/ShareService.test.tspackages/lib/services/share/ShareService.tspackages/lib/services/share/reducer.tspackages/server/package.jsonpackages/server/public/css/items/note.csspackages/server/public/js/items/folderTree.jspackages/server/src/models/ItemModel.tspackages/server/src/models/ShareModel.test.tspackages/server/src/models/ShareModel.tspackages/server/src/routes/api/shares.test.tspackages/server/src/routes/api/shares.tspackages/server/src/routes/api/utils/types.tspackages/server/src/routes/default.tspackages/server/src/routes/index/shares.link.test.tspackages/server/src/routes/index/shares.tspackages/server/src/services/database/types.tspackages/server/src/utils/joplinUtils.tspackages/server/src/views/index/items/note.mustachepackages/tools/cspell/dictionary3.txt
✅ Files skipped from review due to trivial changes (3)
- .gitignore
- .eslintignore
- packages/tools/cspell/dictionary3.txt
🚧 Files skipped from review as they are similar to previous changes (24)
- packages/app-desktop/gui/NoteListItem/NoteListItem.tsx
- packages/app-desktop/gui/WindowCommandsAndDialogs/commands/index.ts
- packages/app-desktop/gui/WindowCommandsAndDialogs/types.ts
- packages/app-desktop/gui/NoteList/utils/types.ts
- packages/app-desktop/gui/WindowCommandsAndDialogs/utils/useSyncDialogState.ts
- packages/lib/services/share/ShareService.test.ts
- packages/server/src/services/database/types.ts
- packages/lib/services/noteList/defaultLeftToRightListRenderer.ts
- packages/app-desktop/gui/NoteListItem/utils/prepareViewProps.ts
- packages/app-desktop/gui/NoteListItem/utils/useRenderedNote.ts
- packages/app-desktop/gui/WindowCommandsAndDialogs/WindowCommandsAndDialogs.tsx
- packages/lib/services/share/reducer.ts
- packages/lib/services/plugins/api/noteListType.ts
- packages/app-desktop/gui/Sidebar/listItemComponents/FolderItem.tsx
- packages/lib/services/noteList/defaultMultiColumnsRenderer.ts
- packages/app-desktop/gui/NoteList/NoteList2.tsx
- packages/lib/services/commands/stateToWhenClauseContext.ts
- packages/app-desktop/gui/Sidebar/styles/index.ts
- packages/app-desktop/gui/Sidebar/hooks/useOnRenderItem.tsx
- packages/lib/services/share/ShareService.ts
- packages/lib/services/noteList/defaultListRenderer.ts
- packages/app-desktop/gui/Sidebar/FolderAndTagList.tsx
- packages/app-desktop/gui/WindowCommandsAndDialogs/commands/showPublishFolderDialog.ts
- packages/app-desktop/gui/PublishFolderDialog.tsx
|
This is hard to review without any context. @Rygaa, please provide a detailed spec of what the code is doing:
Please use proper formatting. And if using an LLM please re-read it and trim it down if needed to keep it readable. For now add that spec to the top post and later we can add it to a spec document under /readme |
part_1.1.mp4part_2.1.mp4 |
Summary
This change lets a user publish a full notebook with all the descendent notebooks/notes
The feature reuses the current public note page where possible. Published notebooks also use a different share type than normal shared notebooks.
It uses Wunderbaum to render the notebook tree with the descendent notebooks/notes
Server
I added
sharePublishedFolderto create a public notebook share:It still uses the existing share endpoint:
When the request has
folder_idandtype: 4, the server treat is as publishing a notebook. Henry recommended using4for this new share type instead of2.For a public notebook share, the server builds the tree from the published root notebook. The tree includes child notebooks and notes.
joplinUtils
Most of the public notebook rendering is handled in
joplinUtils.ts.This file used to render one published note and its resources. Now it can also render a published notebook.
I added a
buildFolderTreefunction. It starts from the published root notebook and loads its child notebooks and notes. For each note, it creates a link like this:It also keeps a list of allowed note IDs. This list is used to check that the requested note is really inside the published notebook.
I also changed
renderNoteso it can receive a notebook tree. If there is a tree, the note is rendered inside the notebook page.There is also a shared
renderNotePagefunction. It renders both:When a notebook tree is present,
renderNotePageloads the Wunderbaum files and sends the tree data to the Mustache template.Finally,
renderItemnow has a folder case. If the shared item is a folder, it renders the notebook tree first. Then it either shows the root notebook page, a selected note, or a linked resource from that selected note.Security
In
joplinUtils.ts,buildFolderTreenow keeps a list of allowed note IDs for the published notebook.When
renderItemhandles a published notebook:resource_idrequest if there is nonote_idor wrongnote_id;note_idif it is not in the allowed note ID list;E2EE
It now handle e2ee by:
PublishedFoldershares;Test Coverage
The tests cover the main parts of the change.
They check that Joplin can create a public notebook share and that it does not mix it with a normal shared notebook.
They also check the public page:
?note_id=;note_idare rejected;The tests also cover E2EE. They check that published notebook content is readable after sync, and that folders, notes, and resources get the right
is_sharedstate before sync.