-
Notifications
You must be signed in to change notification settings - Fork 2
Roam: ENG-709: Settings panel for suggestive mode #327
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
Merged
Merged
Changes from all commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
e2b9b37
settings for context and page groups
sid597 da54c72
node settings
sid597 f83a007
address review
sid597 ee58296
fix node creation if it does not exist
sid597 87f38d3
remove unused, refactor
sid597 5a6bfdd
address coderabbit review
sid597 9815656
unify spelling, handle fallback
sid597 37aa7e0
sync
sid597 4f2807b
address coderabbit code
sid597 3e430c9
address lint errors
sid597 0425eee
use async instead of backend
sid597 5622c64
address review
sid597 2a177c5
Merge branch 'main' into eng-733-glue-ui-components-to-data-extractio…
sid597 5ce74d5
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 590848c
address review
sid597 e3f7352
bug fixes
sid597 0f2938f
bug fixes
sid597 36fc757
Merge branch 'eng-733-glue-ui-components-to-data-extraction-and-datab…
sid597 4422b0a
unused import
sid597 ec8109d
Add an input type for platform accounts
maparent bdb0180
Add an input type for platform accounts
maparent 474dccc
Merge branch 'main' into eng-733-glue-ui-components-to-data-extractio…
sid597 aa573c8
Merge branch 'eng-764-bulk-account-uploading' of https://github.com/D…
sid597 c6a806d
Merge branch 'eng-764-bulk-account-uploading' into eng-733-glue-ui-co…
sid597 18a0d92
Add an input type for platform accounts
maparent cba3232
Merge branch 'eng-764-bulk-account-uploading' of https://github.com/D…
sid597 4b7cf9b
Merge branch 'eng-764-bulk-account-uploading' into eng-733-glue-ui-co…
sid597 a0ea409
bulk upsert accounts, use database function imports
sid597 6efd37c
Merge branch 'main' into eng-733-glue-ui-components-to-data-extractio…
sid597 29e8151
add comment for future
sid597 a11142a
use better import method
sid597 814149b
Merge branch 'eng-733-glue-ui-components-to-data-extraction-and-datab…
sid597 92f28d6
commonjs-to-esm
sid597 d8837f0
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 3e0ae6f
fix merge errors, fix tree config setting extraction, test functional…
sid597 0f56967
add progress toaster, use space existence condition for on load sync
sid597 99c1ae5
defaultvalue
sid597 d045b21
address review, leaving out update embeddings from here
sid597 209da92
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 6406595
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 3e142de
update embeddings
sid597 a0e191a
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 569df7a
ENG-818: Declare dbDotEnv as mjs explicitly
maparent d6ff391
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 f65a5c1
Merge branch 'eng-818-make-dbdotenv-explicitly-a-module' into eng-709…
sid597 58d119b
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 b91efed
reverting create a new pr for update embeddings
sid597 09b6629
Merge branch 'main' into eng-709-settings-panel-for-suggestive-mode
sid597 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
125 changes: 125 additions & 0 deletions
125
apps/roam/src/components/settings/DiscourseNodeSuggestiveRules.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/* eslint-disable @typescript-eslint/naming-convention */ | ||
import React, { | ||
useState, | ||
useMemo, | ||
useEffect, | ||
useRef, | ||
useCallback, | ||
} from "react"; | ||
import { Button, Intent } from "@blueprintjs/core"; | ||
import BlocksPanel from "roamjs-components/components/ConfigPanels/BlocksPanel"; | ||
import FlagPanel from "roamjs-components/components/ConfigPanels/FlagPanel"; | ||
import TextPanel from "roamjs-components/components/ConfigPanels/TextPanel"; | ||
import getSubTree from "roamjs-components/util/getSubTree"; | ||
import { DiscourseNode } from "~/utils/getDiscourseNodes"; | ||
import extractRef from "roamjs-components/util/extractRef"; | ||
|
||
const BlockRenderer = ({ uid }: { uid: string }) => { | ||
const containerRef = useRef<HTMLDivElement>(null); | ||
|
||
useEffect(() => { | ||
const container = containerRef.current; | ||
if (container) { | ||
container.innerHTML = ""; | ||
|
||
window.roamAlphaAPI.ui.components.renderBlock({ | ||
uid: uid, | ||
el: container, | ||
}); | ||
} | ||
}, [uid]); | ||
|
||
return <div ref={containerRef} className="my-2 rounded border p-2" />; | ||
}; | ||
|
||
const DiscourseNodeSuggestiveRules = ({ | ||
node, | ||
parentUid, | ||
}: { | ||
node: DiscourseNode; | ||
parentUid: string; | ||
}) => { | ||
const nodeUid = node.type; | ||
|
||
const [embeddingRef, setEmbeddingRef] = useState(node.embeddingRef); | ||
|
||
useEffect(() => { | ||
setEmbeddingRef(node.embeddingRef || ""); | ||
}, [node.embeddingRef]); | ||
|
||
const blockUidToRender = useMemo( | ||
() => extractRef(embeddingRef), | ||
[embeddingRef], | ||
); | ||
|
||
const templateUid = useMemo( | ||
() => | ||
getSubTree({ | ||
parentUid: nodeUid, | ||
key: "Template", | ||
}).uid || "", | ||
[nodeUid], | ||
); | ||
|
||
const handleEmbeddingRefChange = useCallback( | ||
(e: React.ChangeEvent<HTMLInputElement>) => { | ||
const newValue = e.target.value; | ||
setEmbeddingRef(newValue); | ||
}, | ||
[], | ||
); | ||
|
||
return ( | ||
<div className="flex flex-col gap-4 p-4"> | ||
<BlocksPanel | ||
title="Template" | ||
description={`The template that auto fills ${node.text} page when generated.`} | ||
order={0} | ||
parentUid={nodeUid} | ||
uid={templateUid} | ||
defaultValue={node.template} | ||
/> | ||
|
||
<TextPanel | ||
title="Embedding Block Ref" | ||
description="Copy block ref from template which you want to be embedded and ranked." | ||
order={0} | ||
uid={node.embeddingRefUid || ""} | ||
parentUid={parentUid} | ||
value={node.embeddingRef || ""} | ||
defaultValue={node.embeddingRef || ""} | ||
options={{ | ||
placeholder: "((block-uid))", | ||
onChange: handleEmbeddingRefChange, | ||
}} | ||
/> | ||
|
||
{blockUidToRender && ( | ||
<div> | ||
<div className="mb-1 text-sm text-gray-600">Preview:</div> | ||
<BlockRenderer uid={blockUidToRender} /> | ||
</div> | ||
)} | ||
|
||
<FlagPanel | ||
title="First Child" | ||
description="If the block is the first child of the embedding block ref, it will be embedded and ranked." | ||
order={1} | ||
uid={node.isFirstChild?.uid || ""} | ||
parentUid={parentUid} | ||
value={node.isFirstChild?.value || false} | ||
/> | ||
|
||
{/* TODO: Add a button to update embeddings in seperate PR */} | ||
<Button | ||
text="Update Embeddings" | ||
intent={Intent.NONE} | ||
onClick={() => console.log("Not implemented")} | ||
className="w-52" | ||
disabled | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default DiscourseNodeSuggestiveRules; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
/* eslint-disable @typescript-eslint/naming-convention */ | ||
import React, { useState, useCallback } from "react"; | ||
import { Label, Button, Intent, Tag } from "@blueprintjs/core"; | ||
import Description from "roamjs-components/components/Description"; | ||
import AutocompleteInput from "roamjs-components/components/AutocompleteInput"; | ||
import createBlock from "roamjs-components/writes/createBlock"; | ||
import deleteBlock from "roamjs-components/writes/deleteBlock"; | ||
import getAllPageNames from "roamjs-components/queries/getAllPageNames"; | ||
import { type PageGroup } from "~/utils/getSuggestiveModeConfigSettings"; | ||
|
||
const PageGroupsPanel = ({ | ||
uid, | ||
initialGroups, | ||
}: { | ||
uid: string; | ||
initialGroups: PageGroup[]; | ||
}) => { | ||
const [pageGroups, setPageGroups] = useState<PageGroup[]>(initialGroups); | ||
|
||
const [newGroupName, setNewGroupName] = useState(""); | ||
const [newPageInputs, setNewPageInputs] = useState<Record<string, string>>( | ||
{}, | ||
); | ||
const [autocompleteKeys, setAutocompleteKeys] = useState< | ||
Record<string, number> | ||
>({}); | ||
|
||
const addGroup = async (name: string) => { | ||
if (!name || pageGroups.some((g) => g.name === name)) return; | ||
try { | ||
const newGroupUid = await createBlock({ | ||
parentUid: uid, | ||
node: { text: name }, | ||
}); | ||
setPageGroups([...pageGroups, { uid: newGroupUid, name, pages: [] }]); | ||
setNewGroupName(""); | ||
} catch (e) { | ||
console.error("Error adding group", e); | ||
} | ||
}; | ||
|
||
const removeGroup = async (groupUid: string) => { | ||
try { | ||
await deleteBlock(groupUid); | ||
setPageGroups(pageGroups.filter((g) => g.uid !== groupUid)); | ||
} catch (e) { | ||
console.error("Error removing group", e); | ||
} | ||
}; | ||
|
||
const addPageToGroup = async (groupUid: string, page: string) => { | ||
const group = pageGroups.find((g) => g.uid === groupUid); | ||
if (!page || group?.pages.some((p) => p.name === page)) { | ||
return; | ||
} | ||
try { | ||
const newPageUid = await createBlock({ | ||
parentUid: groupUid, | ||
node: { text: page }, | ||
}); | ||
setPageGroups( | ||
pageGroups.map((g) => | ||
g.uid === groupUid | ||
? { ...g, pages: [...g.pages, { uid: newPageUid, name: page }] } | ||
: g, | ||
), | ||
); | ||
setNewPageInputs((prev) => ({ | ||
...prev, | ||
[groupUid]: "", | ||
})); | ||
setAutocompleteKeys((prev) => ({ | ||
...prev, | ||
[groupUid]: (prev[groupUid] || 0) + 1, | ||
})); | ||
} catch (e) { | ||
console.error("Error adding page to group", e); | ||
} | ||
}; | ||
|
||
const removePageFromGroup = async (groupUid: string, pageUid: string) => { | ||
try { | ||
await deleteBlock(pageUid); | ||
setPageGroups( | ||
pageGroups.map((g) => | ||
g.uid === groupUid | ||
? { ...g, pages: g.pages.filter((p) => p.uid !== pageUid) } | ||
: g, | ||
), | ||
); | ||
} catch (e) { | ||
console.error("Error removing page from group", e); | ||
} | ||
}; | ||
|
||
const getPageInput = (groupUid: string) => newPageInputs[groupUid] || ""; | ||
const setPageInput = useCallback((groupUid: string, value: string) => { | ||
setTimeout(() => { | ||
setNewPageInputs((prev) => ({ | ||
...prev, | ||
[groupUid]: value, | ||
})); | ||
}, 0); | ||
}, []); | ||
const getAutocompleteKey = (groupUid: string) => | ||
autocompleteKeys[groupUid] || 0; | ||
|
||
return ( | ||
<Label> | ||
Page Groups | ||
<Description | ||
description={ | ||
"Organize pages into named groups that will be can be selected when generating Discourse Suggestions." | ||
} | ||
/> | ||
<div className="flex flex-col gap-2"> | ||
{/* Add Group */} | ||
<div className="flex items-center gap-2"> | ||
<AutocompleteInput | ||
value={newGroupName} | ||
setValue={setNewGroupName} | ||
placeholder="Page group name…" | ||
options={[]} | ||
/> | ||
<Button | ||
icon="plus" | ||
small | ||
minimal | ||
disabled={ | ||
!newGroupName || pageGroups.some((g) => g.name === newGroupName) | ||
} | ||
onClick={() => void addGroup(newGroupName)} | ||
/> | ||
</div> | ||
|
||
{/* Existing Groups */} | ||
{Object.keys(pageGroups).length === 0 && ( | ||
<div className="text-sm italic text-gray-500">No groups added.</div> | ||
)} | ||
{pageGroups.map((group) => ( | ||
<div key={group.uid} className="rounded border p-2"> | ||
<div className="mb-1 flex items-center justify-between"> | ||
<span className="font-semibold">{group.name}</span> | ||
<Button | ||
icon="trash" | ||
minimal | ||
small | ||
intent={Intent.DANGER} | ||
onClick={() => void removeGroup(group.uid)} | ||
/> | ||
</div> | ||
<div className="flex flex-wrap items-center gap-2"> | ||
<div | ||
className="flex-0 min-w-[160px]" | ||
onKeyDown={(e) => { | ||
if (e.key === "Enter" && getPageInput(group.uid)) { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
void addPageToGroup(group.uid, getPageInput(group.uid)); | ||
} | ||
}} | ||
> | ||
<AutocompleteInput | ||
key={getAutocompleteKey(group.uid)} | ||
value={getPageInput(group.uid)} | ||
placeholder="Add page…" | ||
setValue={(v) => setPageInput(group.uid, v)} | ||
options={getAllPageNames()} | ||
maxItemsDisplayed={50} | ||
/> | ||
</div> | ||
<Button | ||
icon="plus" | ||
small | ||
minimal | ||
onClick={() => | ||
void addPageToGroup(group.uid, getPageInput(group.uid)) | ||
} | ||
disabled={ | ||
!getPageInput(group.uid) || | ||
group.pages.some((p) => p.name === getPageInput(group.uid)) | ||
} | ||
/> | ||
</div> | ||
{group.pages.length > 0 && ( | ||
<div className="mt-2 flex flex-wrap gap-1"> | ||
{group.pages.map((p) => ( | ||
<Tag | ||
key={p.uid} | ||
onRemove={() => void removePageFromGroup(group.uid, p.uid)} | ||
round | ||
minimal | ||
> | ||
{p.name} | ||
</Tag> | ||
))} | ||
</div> | ||
)} | ||
</div> | ||
))} | ||
</div> | ||
</Label> | ||
); | ||
}; | ||
|
||
export default PageGroupsPanel; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.