Skip to content

Commit 684d72a

Browse files
committed
ENG-1281: Port discourse node block panel
1 parent f7f988c commit 684d72a

6 files changed

Lines changed: 116 additions & 16 deletions

File tree

apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useMemo, useEffect, useRef } from "react";
22
import { Button, Intent } from "@blueprintjs/core";
3-
import BlocksPanel from "roamjs-components/components/ConfigPanels/BlocksPanel";
3+
import DualWriteBlocksPanel from "./components/EphemeralBlocksPanel";
44
import getSubTree from "roamjs-components/util/getSubTree";
55
import { DiscourseNode } from "~/utils/getDiscourseNodes";
66
import extractRef from "roamjs-components/util/extractRef";
@@ -82,13 +82,12 @@ const DiscourseNodeSuggestiveRules = ({
8282

8383
return (
8484
<div className="flex flex-col gap-4 p-4">
85-
<BlocksPanel
85+
<DualWriteBlocksPanel
86+
nodeType={node.type}
8687
title="Template"
8788
description={`The template that auto fills ${node.text} page when generated.`}
88-
order={0}
89-
parentUid={nodeUid}
89+
settingKeys={["template"]}
9090
uid={templateUid}
91-
defaultValue={node.template}
9291
/>
9392

9493
<DiscourseNodeTextPanel

apps/roam/src/components/settings/NodeConfig.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import React, {
77
} from "react";
88
import { DiscourseNode } from "~/utils/getDiscourseNodes";
99
import SelectPanel from "roamjs-components/components/ConfigPanels/SelectPanel";
10-
import BlocksPanel from "roamjs-components/components/ConfigPanels/BlocksPanel";
10+
import DualWriteBlocksPanel from "./components/EphemeralBlocksPanel";
1111
import { getSubTree } from "roamjs-components/util";
1212
import Description from "roamjs-components/components/Description";
1313
import { Label, Tabs, Tab, TabId, InputGroup } from "@blueprintjs/core";
@@ -342,13 +342,12 @@ const NodeConfig = ({
342342
title="Template"
343343
panel={
344344
<div className="flex flex-col gap-4 p-1">
345-
<BlocksPanel
345+
<DualWriteBlocksPanel
346+
nodeType={node.type}
346347
title="Template"
347348
description={`The template that auto fills ${node.text} page when generated.`}
348-
order={0}
349-
parentUid={node.type}
349+
settingKeys={["template"]}
350350
uid={templateUid}
351-
defaultValue={node.template}
352351
/>
353352
</div>
354353
}

apps/roam/src/components/settings/components/BlockPropSettingPanels.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,7 @@ const createDiscourseNodeSetter =
582582
(keys: string[], value: json): void =>
583583
setDiscourseNodeSetting(nodeType, keys, value);
584584

585-
type DiscourseNodeBaseProps = {
585+
export type DiscourseNodeBaseProps = {
586586
nodeType: string;
587587
title: string;
588588
description: string;
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import React, { useRef, useEffect, useCallback } from "react";
2+
import { Label } from "@blueprintjs/core";
3+
import Description from "roamjs-components/components/Description";
4+
import createBlock from "roamjs-components/writes/createBlock";
5+
import getFullTreeByParentUid from "roamjs-components/queries/getFullTreeByParentUid";
6+
import getFirstChildUidByBlockUid from "roamjs-components/queries/getFirstChildUidByBlockUid";
7+
import type { TreeNode } from "roamjs-components/types";
8+
import type { RoamNodeType } from "../utils/zodSchema";
9+
import { setDiscourseNodeSetting } from "../utils/accessors";
10+
import type { DiscourseNodeBaseProps } from "./BlockPropSettingPanels";
11+
12+
const DEBOUNCE_MS = 250;
13+
14+
type DualWriteBlocksPanelProps = DiscourseNodeBaseProps & {
15+
uid: string;
16+
};
17+
18+
const serializeBlockTree = (children: TreeNode[]): RoamNodeType[] =>
19+
children
20+
.sort((a, b) => a.order - b.order)
21+
.map((child) => ({
22+
text: child.text,
23+
...(child.children.length > 0 && {
24+
children: serializeBlockTree(child.children),
25+
}),
26+
}));
27+
28+
const DualWriteBlocksPanel = ({
29+
nodeType,
30+
settingKeys,
31+
title,
32+
description,
33+
uid,
34+
}: DualWriteBlocksPanelProps) => {
35+
const containerRef = useRef<HTMLDivElement>(null);
36+
const debounceRef = useRef(0);
37+
const pullWatchArgsRef = useRef<
38+
[string, string, (before: unknown, after: unknown) => void] | null
39+
>(null);
40+
41+
const handleChange = useCallback(() => {
42+
window.clearTimeout(debounceRef.current);
43+
debounceRef.current = window.setTimeout(() => {
44+
const tree = getFullTreeByParentUid(uid);
45+
const serialized = serializeBlockTree(tree.children);
46+
setDiscourseNodeSetting(nodeType, settingKeys, serialized);
47+
}, DEBOUNCE_MS);
48+
}, [uid, nodeType, settingKeys]);
49+
50+
useEffect(() => {
51+
const el = containerRef.current;
52+
if (!el) return;
53+
54+
if (!getFirstChildUidByBlockUid(uid)) {
55+
void createBlock({ node: { text: " " }, parentUid: uid }).then(() => {
56+
el.innerHTML = "";
57+
void window.roamAlphaAPI.ui.components.renderBlock({ uid, el });
58+
});
59+
} else {
60+
el.innerHTML = "";
61+
void window.roamAlphaAPI.ui.components.renderBlock({ uid, el });
62+
}
63+
64+
const pattern = "[:block/string {:block/children ...}]";
65+
const entityId = `[:block/uid "${uid}"]`;
66+
const callback = () => handleChange();
67+
pullWatchArgsRef.current = [pattern, entityId, callback];
68+
window.roamAlphaAPI.data.addPullWatch(pattern, entityId, callback);
69+
70+
return () => {
71+
window.clearTimeout(debounceRef.current);
72+
if (pullWatchArgsRef.current) {
73+
window.roamAlphaAPI.data.removePullWatch(...pullWatchArgsRef.current);
74+
pullWatchArgsRef.current = null;
75+
}
76+
};
77+
}, [uid, handleChange]);
78+
79+
return (
80+
<>
81+
<Label>
82+
{title}
83+
<Description description={description} />
84+
</Label>
85+
<style>{`.roamjs-dualwrite-blocks > div > .rm-block-main {
86+
display: none;
87+
}
88+
.roamjs-dualwrite-blocks > div > .rm-block-children > .rm-multibar {
89+
display: none;
90+
}
91+
.roamjs-dualwrite-blocks > div > .rm-block-children {
92+
margin-left: -4px;
93+
}`}</style>
94+
<div
95+
ref={containerRef}
96+
style={{
97+
border: "1px solid #33333333",
98+
padding: "8px 0",
99+
borderRadius: 4,
100+
}}
101+
className="roamjs-dualwrite-blocks"
102+
/>
103+
</>
104+
);
105+
};
106+
107+
export default DualWriteBlocksPanel;

apps/roam/src/components/settings/utils/zodSchema.example.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@ const canvasSettings: CanvasSettings = {
3030
};
3131

3232
const suggestiveRules: SuggestiveRules = {
33-
template: [
34-
{ text: "Summary::", heading: 2 },
35-
{ text: "Key Points::", heading: 2, children: [{ text: "" }] },
36-
],
3733
embeddingRef: "((block-uid-123))",
3834
isFirstChild: true,
3935
};

apps/roam/src/components/settings/utils/zodSchema.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ export const RoamNodeSchema: z.ZodType<RoamNode> = z.lazy(() =>
7777
);
7878

7979
export const SuggestiveRulesSchema = z.object({
80-
template: z.array(RoamNodeSchema).default([]),
8180
embeddingRef: z.string().default(""),
8281
isFirstChild: z.boolean().default(false),
8382
});

0 commit comments

Comments
 (0)