Skip to content

Commit b7d26df

Browse files
committed
ENG-1469: Refactor getDiscourseRelations and getDiscourseNodes to read from block props
1 parent 3b4c80a commit b7d26df

4 files changed

Lines changed: 157 additions & 83 deletions

File tree

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

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import internalError from "~/utils/internalError";
1212
import { getSetting } from "~/utils/extensionSettings";
1313
import { getFormattedConfigTree } from "~/utils/discourseConfigRef";
1414
import { roamNodeToCondition } from "~/utils/parseQuery";
15+
import type { DiscourseRelation } from "~/utils/getDiscourseRelations";
16+
import type { DiscourseNode } from "~/utils/getDiscourseNodes";
17+
import type { Condition } from "~/utils/types";
1518
import { z } from "zod";
1619

1720
import {
@@ -27,7 +30,7 @@ import {
2730
type GlobalSettings,
2831
type PersonalSettings,
2932
type DiscourseNodeSettings,
30-
type DiscourseRelationSettings,
33+
type Condition as SchemaCondition,
3134
} from "./zodSchema";
3235

3336
const isRecord = (value: unknown): value is Record<string, unknown> =>
@@ -250,11 +253,6 @@ const getLegacyPersonalSetting = (keys: string[]): unknown => {
250253
return undefined;
251254
};
252255

253-
// NOTE(ENG-1469): This returns the block props schema shape (Record<uid, {label, source,
254-
// destination, complement, ifConditions}>). Runtime consumers use getDiscourseRelations()
255-
// which returns a flat DiscourseRelation[] with a different structure (one entry per
256-
// if-block, triples at top level, no nodePositions). When migrating getDiscourseRelations()
257-
// to read from block props, it will need a conversion from this shape to the flat array.
258256
const getLegacyRelationsSetting = (): Record<string, unknown> => {
259257
const settingsUid = getPageUidByPageTitle(DG_BLOCK_PROP_SETTINGS_PAGE_TITLE);
260258
if (!settingsUid) return DEFAULT_GLOBAL_SETTINGS.Relations;
@@ -766,13 +764,19 @@ export const setGlobalSetting = (keys: string[], value: json): void => {
766764
});
767765
};
768766

769-
export const getAllRelations = (): DiscourseRelationSettings[] => {
767+
export const getAllRelations = (): DiscourseRelation[] => {
770768
const settings = getGlobalSettings();
771769

772-
return Object.entries(settings.Relations).map(([id, relation]) => ({
773-
...relation,
774-
id,
775-
}));
770+
return Object.entries(settings.Relations).flatMap(([id, relation]) =>
771+
relation.ifConditions.map((ifCondition) => ({
772+
id,
773+
label: relation.label,
774+
source: relation.source,
775+
destination: relation.destination,
776+
complement: relation.complement,
777+
triples: ifCondition.triples,
778+
})),
779+
);
776780
};
777781

778782
export const getPersonalSettings = (): PersonalSettings => {
@@ -936,7 +940,52 @@ export const setDiscourseNodeSetting = (
936940
setBlockPropAtPath(pageUid, keys, value);
937941
};
938942

939-
export const getAllDiscourseNodes = (): DiscourseNodeSettings[] => {
943+
const addConditionUids = (conditions: SchemaCondition[]): Condition[] =>
944+
conditions.map((c) => {
945+
const uid = window.roamAlphaAPI.util.generateUID();
946+
if (c.type === "or" || c.type === "not or") {
947+
return {
948+
uid,
949+
type: c.type,
950+
conditions: c.conditions.map(addConditionUids),
951+
};
952+
}
953+
return {
954+
uid,
955+
type: c.type,
956+
source: c.source,
957+
relation: c.relation,
958+
target: c.target,
959+
not: c.not,
960+
};
961+
}) as Condition[];
962+
963+
const toDiscourseNode = (settings: DiscourseNodeSettings): DiscourseNode => ({
964+
text: settings.text,
965+
type: settings.type,
966+
shortcut: settings.shortcut,
967+
tag: settings.tag || undefined,
968+
format: settings.format,
969+
description: settings.description || undefined,
970+
graphOverview: settings.graphOverview || undefined,
971+
backedBy: settings.backedBy,
972+
specification: addConditionUids(
973+
settings.specification.query.conditions as SchemaCondition[],
974+
),
975+
canvasSettings: Object.fromEntries(
976+
Object.entries(settings.canvasSettings).map(([k, v]) => [
977+
k,
978+
typeof v === "boolean" ? (v ? "true" : "") : String(v),
979+
]),
980+
),
981+
template: settings.template.length > 0 ? settings.template : undefined,
982+
embeddingRef: settings.suggestiveRules.embeddingRef || undefined,
983+
isFirstChild: settings.suggestiveRules.isFirstChild
984+
? { uid: "", value: true }
985+
: undefined,
986+
});
987+
988+
export const getAllDiscourseNodes = (): DiscourseNode[] => {
940989
const results = window.roamAlphaAPI.data.fast.q(`
941990
[:find ?uid ?title (pull ?page [:block/props])
942991
:where
@@ -945,7 +994,7 @@ export const getAllDiscourseNodes = (): DiscourseNodeSettings[] => {
945994
[(clojure.string/starts-with? ?title "${DISCOURSE_NODE_PAGE_PREFIX}")]]
946995
`) as [string, string, Record<string, json> | null][];
947996

948-
const nodes: DiscourseNodeSettings[] = [];
997+
const nodes: DiscourseNode[] = [];
949998

950999
for (const [pageUid, title, rawProps] of results) {
9511000
if (typeof pageUid !== "string" || typeof title !== "string") continue;
@@ -962,11 +1011,13 @@ export const getAllDiscourseNodes = (): DiscourseNodeSettings[] => {
9621011

9631012
const result = DiscourseNodeSchema.safeParse(blockProps);
9641013
if (result.success) {
965-
nodes.push({
966-
...result.data,
967-
type: pageUid,
968-
text: title.replace(DISCOURSE_NODE_PAGE_PREFIX, ""),
969-
});
1014+
nodes.push(
1015+
toDiscourseNode({
1016+
...result.data,
1017+
type: pageUid,
1018+
text: title.replace(DISCOURSE_NODE_PAGE_PREFIX, ""),
1019+
}),
1020+
);
9701021
} else {
9711022
internalError({
9721023
error: result.error,

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ const QBClauseDataSchema = z.object({
2222
not: z.boolean().optional(),
2323
});
2424

25-
type Condition =
25+
export type Condition =
2626
| (z.infer<typeof QBClauseDataSchema> & { type: "clause" })
2727
| (z.infer<typeof QBClauseDataSchema> & { type: "not" })
2828
| { type: "or"; conditions: Condition[][] }

apps/roam/src/utils/getDiscourseNodes.ts

Lines changed: 79 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import getSettingValueFromTree from "roamjs-components/util/getSettingValueFromTree";
22
import getSubTree from "roamjs-components/util/getSubTree";
3+
import {
4+
isNewSettingsStoreEnabled,
5+
getAllDiscourseNodes,
6+
} from "~/components/settings/utils/accessors";
37
import discourseConfigRef from "./discourseConfigRef";
48
import getDiscourseRelations from "./getDiscourseRelations";
59
import { roamNodeToCondition } from "./parseQuery";
@@ -103,72 +107,83 @@ const getUidAndBooleanSetting = ({
103107
};
104108

105109
const getDiscourseNodes = (relations = getDiscourseRelations()) => {
106-
const configuredNodes = Object.entries(discourseConfigRef.nodes)
107-
.map(([type, { text, children }]): DiscourseNode => {
108-
const suggestiveRules = getSubTree({
109-
tree: children,
110-
key: "Suggestive Rules",
111-
});
112-
const embeddingBlockRef = getSubTree({
113-
tree: suggestiveRules.children,
114-
key: "Embedding Block Ref",
115-
});
110+
const configuredNodes = (
111+
isNewSettingsStoreEnabled()
112+
? getAllDiscourseNodes()
113+
: Object.entries(discourseConfigRef.nodes).map(
114+
([type, { text, children }]): DiscourseNode => {
115+
const suggestiveRules = getSubTree({
116+
tree: children,
117+
key: "Suggestive Rules",
118+
});
119+
const embeddingBlockRef = getSubTree({
120+
tree: suggestiveRules.children,
121+
key: "Embedding Block Ref",
122+
});
116123

117-
return {
118-
format: getSettingValueFromTree({ tree: children, key: "format" }),
119-
text,
120-
shortcut: getSettingValueFromTree({ tree: children, key: "shortcut" }),
121-
tag: getSettingValueFromTree({ tree: children, key: "tag" }),
122-
type,
123-
specification: getSpecification(children),
124-
backedBy: "user",
125-
canvasSettings: Object.fromEntries(
126-
getSubTree({ tree: children, key: "canvas" }).children.map(
127-
(c) => [c.text, c.children[0]?.text || ""] as const,
128-
),
129-
),
130-
graphOverview:
131-
children.filter((c) => c.text === "Graph Overview").length > 0,
132-
description: getSettingValueFromTree({
133-
tree: children,
134-
key: "description",
135-
}),
136-
template: getSubTree({ tree: children, key: "template" }).children,
137-
embeddingRef: embeddingBlockRef?.children?.[0]?.text,
138-
embeddingRefUid: embeddingBlockRef?.uid,
139-
isFirstChild: getUidAndBooleanSetting({
140-
tree: suggestiveRules.children,
141-
text: "First Child",
142-
}),
143-
};
144-
})
145-
.concat(
146-
relations
147-
.filter((r) => r.triples.some((t) => t.some((n) => /anchor/i.test(n))))
148-
.map((r) => ({
149-
format: "",
150-
text: r.label,
151-
type: r.id,
152-
shortcut: r.label.slice(0, 1),
153-
tag: "",
154-
specification: r.triples.map(([source, relation, target]) => ({
155-
type: "clause",
156-
source: /anchor/i.test(source) ? r.label : source,
157-
relation,
158-
target:
159-
target === "source"
160-
? r.source
161-
: target === "destination"
162-
? r.destination
163-
: /anchor/i.test(target)
164-
? r.label
165-
: target,
166-
uid: window.roamAlphaAPI.util.generateUID(),
167-
})),
168-
backedBy: "relation",
169-
canvasSettings: {},
124+
return {
125+
format: getSettingValueFromTree({
126+
tree: children,
127+
key: "format",
128+
}),
129+
text,
130+
shortcut: getSettingValueFromTree({
131+
tree: children,
132+
key: "shortcut",
133+
}),
134+
tag: getSettingValueFromTree({ tree: children, key: "tag" }),
135+
type,
136+
specification: getSpecification(children),
137+
backedBy: "user",
138+
canvasSettings: Object.fromEntries(
139+
getSubTree({ tree: children, key: "canvas" }).children.map(
140+
(c) => [c.text, c.children[0]?.text || ""] as const,
141+
),
142+
),
143+
graphOverview:
144+
children.filter((c) => c.text === "Graph Overview").length > 0,
145+
description: getSettingValueFromTree({
146+
tree: children,
147+
key: "description",
148+
}),
149+
template: getSubTree({ tree: children, key: "template" })
150+
.children,
151+
embeddingRef: embeddingBlockRef?.children?.[0]?.text,
152+
embeddingRefUid: embeddingBlockRef?.uid,
153+
isFirstChild: getUidAndBooleanSetting({
154+
tree: suggestiveRules.children,
155+
text: "First Child",
156+
}),
157+
};
158+
},
159+
)
160+
).concat(
161+
relations
162+
.filter((r) => r.triples.some((t) => t.some((n) => /anchor/i.test(n))))
163+
.map((r) => ({
164+
format: "",
165+
text: r.label,
166+
type: r.id,
167+
shortcut: r.label.slice(0, 1),
168+
tag: "",
169+
specification: r.triples.map(([source, relation, target]) => ({
170+
type: "clause",
171+
source: /anchor/i.test(source) ? r.label : source,
172+
relation,
173+
target:
174+
target === "source"
175+
? r.source
176+
: target === "destination"
177+
? r.destination
178+
: /anchor/i.test(target)
179+
? r.label
180+
: target,
181+
uid: window.roamAlphaAPI.util.generateUID(),
170182
})),
171-
);
183+
backedBy: "relation",
184+
canvasSettings: {},
185+
})),
186+
);
172187
const configuredNodeTexts = new Set(configuredNodes.map((n) => n.text));
173188
const defaultNodes = DEFAULT_NODES.filter(
174189
(n) => !configuredNodeTexts.has(n.text),

apps/roam/src/utils/getDiscourseRelations.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import type {
66
import getSettingValueFromTree from "roamjs-components/util/getSettingValueFromTree";
77
import toFlexRegex from "roamjs-components/util/toFlexRegex";
88
import DEFAULT_RELATION_VALUES from "~/data/defaultDiscourseRelations";
9+
import {
10+
isNewSettingsStoreEnabled,
11+
getAllRelations,
12+
} from "~/components/settings/utils/accessors";
913
import discourseConfigRef from "./discourseConfigRef";
1014

1115
export type Triple = readonly [string, string, string];
@@ -32,6 +36,10 @@ export const getRelationsNode = (grammarNode = getGrammarNode()) => {
3236
};
3337

3438
const getDiscourseRelations = () => {
39+
if (isNewSettingsStoreEnabled()) {
40+
return getAllRelations();
41+
}
42+
3543
const grammarNode = getGrammarNode();
3644
const relationsNode = getRelationsNode(grammarNode);
3745
const relationNodes = relationsNode?.children || DEFAULT_RELATION_VALUES;

0 commit comments

Comments
 (0)