diff --git a/apps/roam/src/components/ModifyNodeDialog.tsx b/apps/roam/src/components/ModifyNodeDialog.tsx index dafd67f07..f68490b87 100644 --- a/apps/roam/src/components/ModifyNodeDialog.tsx +++ b/apps/roam/src/components/ModifyNodeDialog.tsx @@ -1,6 +1,7 @@ import { Button, Classes, + Colors, Dialog, Intent, Label, @@ -22,7 +23,9 @@ import renderOverlay, { import fireQuery from "~/utils/fireQuery"; import getDiscourseNodes, { excludeDefaultNodes, + type DiscourseNode, } from "~/utils/getDiscourseNodes"; +import { getAllDiscourseNodesSince } from "~/utils/getAllDiscourseNodesSince"; import FuzzySelectInput from "./FuzzySelectInput"; import { createBlock, updateBlock } from "roamjs-components/writes"; import { @@ -40,7 +43,7 @@ import posthog from "posthog-js"; export type ModifyNodeDialogMode = "create" | "edit"; export type ModifyNodeDialogProps = { mode: ModifyNodeDialogMode; - nodeType: string; + nodeType?: string; initialValue: { text: string; uid: string }; initialReferencedNode?: { text: string; uid: string }; sourceBlockUid?: string; //the block that we started modifying from @@ -109,13 +112,15 @@ const ModifyNodeDialog = ({ : allNodes.filter(excludeDefaultNodes); }, [includeDefaultNodes]); - const [selectedNodeType, setSelectedNodeType] = useState(() => { + const [selectedNodeType, setSelectedNodeType] = useState< + DiscourseNode | undefined + >(() => { const node = discourseNodes.find((n) => n.type === nodeType); - return node || discourseNodes[0]; + return node; }); const nodeFormat = useMemo(() => { - return selectedNodeType.format || ""; + return selectedNodeType?.format || ""; }, [selectedNodeType]); const referencedNode = useMemo(() => { @@ -160,6 +165,19 @@ const ModifyNodeDialog = ({ if (contentRequestIdRef.current === req && alive) { setOptions((prev) => ({ ...prev, content: results })); } + } else { + const rawResults = await getAllDiscourseNodesSince( + undefined, + discourseNodes, + ); + const results = rawResults.map((r) => ({ + text: r.text, + uid: r.source_local_id, + discourseNodeType: r.type, + })); + if (contentRequestIdRef.current === req && alive) { + setOptions((prev) => ({ ...prev, content: results })); + } } } catch (error) { if (contentRequestIdRef.current === req && alive) { @@ -224,11 +242,24 @@ const ModifyNodeDialog = ({ alive = false; refAlive = false; }; - }, [selectedNodeType, referencedNode]); - - const setValue = useCallback((r: Result) => { - setContent(r); - }, []); + }, [selectedNodeType, referencedNode, discourseNodes]); + + const setValue = useCallback( + (r: Result) => { + setContent(r); + if (!selectedNodeType && r.uid) { + const detectedType = r.discourseNodeType; + if (detectedType) { + const nt = discourseNodes.find((n) => n.type === detectedType); + if (nt) { + setSelectedNodeType(nt); + setError(""); + } + } + } + }, + [selectedNodeType, discourseNodes], + ); const setReferencedNodeValueCallback = useCallback((r: Result) => { setReferencedNodeValue(r); @@ -304,9 +335,13 @@ const ModifyNodeDialog = ({ const onSubmit = async () => { if (!content.text.trim()) return; + if (!selectedNodeType && !isContentLocked) { + setError("Please select a node type"); + return; + } posthog.capture("Modify Node Dialog: Submit Triggered", { mode, - nodeType: selectedNodeType.type, + nodeType: selectedNodeType?.type, }); try { if (mode === "create") { @@ -326,7 +361,7 @@ const ModifyNodeDialog = ({ await addImageToPage({ pageUid, imageUrl, - configPageUid: selectedNodeType.type, + configPageUid: selectedNodeType?.type || "", extensionAPI, }); } @@ -373,7 +408,7 @@ const ModifyNodeDialog = ({ } else { formattedTitle = await getNewDiscourseNodeText({ text: content.text.trim(), - nodeType: selectedNodeType.type, + nodeType: selectedNodeType!.type, blockUid: sourceBlockUid, }); } @@ -384,7 +419,7 @@ const ModifyNodeDialog = ({ // Create new discourse node const newPageUid = await createDiscourseNode({ text: formattedTitle, - configPageUid: selectedNodeType.type, + configPageUid: selectedNodeType!.type, extensionAPI, imageUrl, }); @@ -505,56 +540,68 @@ const ModifyNodeDialog = ({ style={{ pointerEvents: "all" }} >
+ {/* Content Input */} + + {/* Node Type Selector */}
-
- {/* Content Input */} -
- - -
- {/* Referenced Node Input */} {referencedNode && !isContentLocked && mode === "create" && ( -
- +
+ )}
{/* Submit Button */} diff --git a/apps/roam/src/utils/getAllDiscourseNodesSince.ts b/apps/roam/src/utils/getAllDiscourseNodesSince.ts index acff9c624..3d047f386 100644 --- a/apps/roam/src/utils/getAllDiscourseNodesSince.ts +++ b/apps/roam/src/utils/getAllDiscourseNodesSince.ts @@ -64,10 +64,10 @@ export const getDiscourseNodeTypeWithSettingsBlockNodes = async ( }; export const getAllDiscourseNodesSince = async ( - since: ISODateString, + since: ISODateString | undefined, nodeTypes: DiscourseNode[], ): Promise => { - const sinceMs = new Date(since).getTime(); + const sinceMs = since ? new Date(since).getTime() : 0; if (!nodeTypes.length) { return []; } diff --git a/apps/roam/src/utils/registerCommandPaletteCommands.ts b/apps/roam/src/utils/registerCommandPaletteCommands.ts index 6e5dbf61e..2eb143229 100644 --- a/apps/roam/src/utils/registerCommandPaletteCommands.ts +++ b/apps/roam/src/utils/registerCommandPaletteCommands.ts @@ -189,19 +189,9 @@ export const registerCommandPaletteCommands = (onloadArgs: OnloadArgs) => { const selectionStart = uid ? getSelectionStartForBlock(uid) : 0; - const defaultNodeType = - getDiscourseNodes().filter(excludeDefaultNodes)[0]?.type; - if (!defaultNodeType) { - renderToast({ - id: "create-discourse-node-command-no-types", - content: "No discourse node types found in settings.", - }); - return; - } - renderModifyNodeDialog({ mode: "create", - nodeType: defaultNodeType, + nodeType: "", initialValue: { text: "", uid: "" }, extensionAPI, onSuccess: async (result) => {