forked from Qortal/q-blog
3.2 KiB
3.2 KiB
Wiki Mode / Multi-Editor — Technical Implementation
Generated 2025-08-22
Data Model
BlogSettings
wikiEnabled: boolean(optional; missing = false)editorWhitelist: Name[](optional; empty = global allow)editorBlacklist: Name[](optional)
Post (revision)
originPostId: Id(first ancestor; fallback to id if missing)parentPostId?: IdlineageBlogId: BlogId(owner’s blog id; fallback to route blog id)authorName: Name(registered name)updatedAt: ISO timestamp(fallback to QDN timestamp if missing)published: boolean
Authorization (by Name)
- Owner always allowed.
- Blacklist blocks regardless.
- Whitelist non-empty → only listed Names (minus blacklist).
- Whitelist empty → all Names allowed (minus blacklist).
canEdit(viewerName, settings, ownerName)
- Returns true if viewerName is Owner, or if wiki enabled and viewerName passes the whitelist/blacklist rules.
Canonical Resolver (client)
- Resolve origin id.
- Collect revisions with same origin + blog lineage, published = true.
- Filter by authorization (authorName vs blog settings).
- Pick newest by updatedAt; tiebreak: Owner wins; then lowest id.
Reference implementation in code:
src/utils/wiki.tsprovidesisAuthorized,canEdit, andselectCanonicalused across UI.src/utils/wikiSettingsCache.tscaches per-blog (ownerName, settings) using/arbitrary/resources?service=BLOG&identifier=...and/arbitrary/BLOG/<owner>/<id>.src/hooks/useFetchPosts.tsxgroups search results by identifier and applies canonical selection in feed, favorites, and subscriptions.src/pages/BlogIndividualPost/BlogIndividualPost.tsxresolves canonical author before fetching BLOG_POST JSON when wiki mode is enabled.
UI
- Blog Settings: toggle, Name pickers for whitelist/blacklist.
- Implemented in
Edit Blogmodal (checkbox + comma-separated Name inputs). - Also available in
Create Blogmodal so new blogs can enable wiki from the start.
- Implemented in
- Post page: “Latest by Name on Date” subheader if revision not by Owner.
- Edit: shown only if canEdit true.
- Blog list: use resolver to show canonical per lineage.
- Global feed, Subscriptions, and Favorites use a lightweight cache of per-blog settings to canonicalize duplicates by identifier.
- Header blog switcher seeds blog context to ensure the posts list refreshes immediately on change.
Backward Compatibility
- Missing fields → defaults (wikiEnabled=false, lists empty, origin=id, lineage=blogId, updatedAt=QDN ts).
Performance Notes
- Settings Resolution: reads wiki settings from BLOG resource metadata when available; otherwise fetches BLOG JSON as fallback.
- Prefetch: for each page of results, settings for blogs with duplicate identifiers are prefetched in parallel (singletons skip resolution).
- Canonicalization happens only when necessary; otherwise owner or newest item is used.
Edit Flow (Wiki)
- Editors do not need their own blog to publish a revision of an existing post when the target blog has Wiki Mode enabled.
- Edits publish a new
BLOG_POSTunder the editor's Name using the original BLOG_POST identifier; the canonical resolver selects the visible revision. - Blog (
service: BLOG) metadata is not republished during edits.