-
Notifications
You must be signed in to change notification settings - Fork 4
ENG-1281: Port discourse node block panel #784
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,109 @@ | ||||||
| import React, { useRef, useEffect, useCallback } from "react"; | ||||||
| import { Label } from "@blueprintjs/core"; | ||||||
| import Description from "roamjs-components/components/Description"; | ||||||
| import createBlock from "roamjs-components/writes/createBlock"; | ||||||
| import getFullTreeByParentUid from "roamjs-components/queries/getFullTreeByParentUid"; | ||||||
| import getFirstChildUidByBlockUid from "roamjs-components/queries/getFirstChildUidByBlockUid"; | ||||||
| import type { TreeNode } from "roamjs-components/types"; | ||||||
| import type { RoamNodeType } from "~/components/settings/utils/zodSchema"; | ||||||
| import { setDiscourseNodeSetting } from "~/components/settings/utils/accessors"; | ||||||
| import type { DiscourseNodeBaseProps } from "./BlockPropSettingPanels"; | ||||||
|
|
||||||
| const DEBOUNCE_MS = 250; | ||||||
|
|
||||||
| type DualWriteBlocksPanelProps = DiscourseNodeBaseProps & { | ||||||
| uid: string; | ||||||
| }; | ||||||
|
|
||||||
| const serializeBlockTree = (children: TreeNode[]): RoamNodeType[] => | ||||||
| children | ||||||
| .sort((a, b) => a.order - b.order) | ||||||
| .map((child) => ({ | ||||||
| text: child.text, | ||||||
| ...(child.heading && { heading: child.heading as 0 | 1 | 2 | 3 }), | ||||||
| ...(child.open === false && { open: false }), | ||||||
| ...(child.children.length > 0 && { | ||||||
| children: serializeBlockTree(child.children), | ||||||
| }), | ||||||
| })); | ||||||
|
|
||||||
| const DualWriteBlocksPanel = ({ | ||||||
| nodeType, | ||||||
| settingKeys, | ||||||
| title, | ||||||
| description, | ||||||
| uid, | ||||||
| }: DualWriteBlocksPanelProps) => { | ||||||
| const containerRef = useRef<HTMLDivElement>(null); | ||||||
| const debounceRef = useRef(0); | ||||||
| const pullWatchArgsRef = useRef< | ||||||
| [string, string, (before: unknown, after: unknown) => void] | null | ||||||
| >(null); | ||||||
|
|
||||||
| const handleChange = useCallback(() => { | ||||||
| window.clearTimeout(debounceRef.current); | ||||||
| debounceRef.current = window.setTimeout(() => { | ||||||
| const tree = getFullTreeByParentUid(uid); | ||||||
| const serialized = serializeBlockTree(tree.children); | ||||||
| setDiscourseNodeSetting(nodeType, settingKeys, serialized); | ||||||
| }, DEBOUNCE_MS); | ||||||
| }, [uid, nodeType, settingKeys]); | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| const el = containerRef.current; | ||||||
| if (!el || !uid) return; | ||||||
|
|
||||||
| const pattern = "[:block/string :block/order {:block/children ...}]"; | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟡 PullWatch pattern omits The Root cause and impactThe pull watch pattern determines which Datomic attribute changes trigger the callback. Since However, ...(child.heading && { heading: child.heading as 0 | 1 | 2 | 3 }),
...(child.open === false && { open: false }),This means heading/open changes made in isolation are silently dropped from the block-props settings store. They would only be picked up incidentally if the user also edits text or reorders blocks in the same session. The fix is to add
Suggested change
Was this helpful? React with 👍 or 👎 to provide feedback. |
||||||
| const entityId = `[:block/uid "${uid}"]`; | ||||||
| const callback = () => handleChange(); | ||||||
|
|
||||||
| const registerPullWatch = () => { | ||||||
| pullWatchArgsRef.current = [pattern, entityId, callback]; | ||||||
| window.roamAlphaAPI.data.addPullWatch(pattern, entityId, callback); | ||||||
| }; | ||||||
|
|
||||||
| if (!getFirstChildUidByBlockUid(uid)) { | ||||||
| void createBlock({ node: { text: " " }, parentUid: uid }).then(() => { | ||||||
| el.innerHTML = ""; | ||||||
| void window.roamAlphaAPI.ui.components.renderBlock({ uid, el }); | ||||||
| registerPullWatch(); | ||||||
| }); | ||||||
| } else { | ||||||
| el.innerHTML = ""; | ||||||
| void window.roamAlphaAPI.ui.components.renderBlock({ uid, el }); | ||||||
| registerPullWatch(); | ||||||
| } | ||||||
|
|
||||||
| return () => { | ||||||
| window.clearTimeout(debounceRef.current); | ||||||
| if (pullWatchArgsRef.current) { | ||||||
| window.roamAlphaAPI.data.removePullWatch(...pullWatchArgsRef.current); | ||||||
| pullWatchArgsRef.current = null; | ||||||
| } | ||||||
| }; | ||||||
sid597 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| }, [uid, handleChange]); | ||||||
|
|
||||||
| return ( | ||||||
| <> | ||||||
| <Label> | ||||||
| {title} | ||||||
| <Description description={description} /> | ||||||
| </Label> | ||||||
| <style>{`.dg-dualwrite-blocks > div > .rm-block-main { | ||||||
| display: none; | ||||||
| } | ||||||
| .dg-dualwrite-blocks > div > .rm-block-children > .rm-multibar { | ||||||
| display: none; | ||||||
| } | ||||||
| .dg-dualwrite-blocks > div > .rm-block-children { | ||||||
| margin-left: -4px; | ||||||
| }`}</style> | ||||||
| <div | ||||||
| ref={containerRef} | ||||||
| className="dg-dualwrite-blocks rounded border border-gray-200 py-2" | ||||||
| /> | ||||||
| </> | ||||||
| ); | ||||||
| }; | ||||||
|
|
||||||
| export default DualWriteBlocksPanel; | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -75,7 +75,6 @@ export const RoamNodeSchema: z.ZodType<RoamNode> = z.lazy(() => | |
| ); | ||
|
|
||
| export const SuggestiveRulesSchema = z.object({ | ||
| template: z.array(RoamNodeSchema).default([]), | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this being removed? is it being replaced with something?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't have to store the template structure explicitly for suggestiveRulesSchema because
|
||
| embeddingRef: z.string().default(""), | ||
| isFirstChild: z.boolean().default(false), | ||
| }); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.