Skip to content

Commit 385a5ad

Browse files
authored
ENG-917 Suggestions body and actions (#473)
* suggestions body and util in one file * 1. Fix button grouping 2. Persist individual panel state across pages 3. fix panel manager scroll issue, add new panel to top 4. If no result from search show message 5. fix pading and view for filter button row 6. use formatted tree instead of extensionapi, fix when suggestions don't exist * revert setup script * fix alignment page groups * fix more review points all done * address review * fix overlay placement * remove unintended changes * remove unintended changes * remove unintended changes * remove unintended changes * remove unused
1 parent 62de1e7 commit 385a5ad

File tree

10 files changed

+782
-125
lines changed

10 files changed

+782
-125
lines changed

apps/roam/src/components/DiscourseSuggestionsPanel.tsx

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,40 @@ import {
66
Navbar,
77
Collapse,
88
} from "@blueprintjs/core";
9-
import React, { useState, useCallback } from "react";
9+
import React, { useState, useCallback, useEffect } from "react";
10+
import SuggestionsBody from "./SuggestionsBody";
1011

1112
export const DiscourseSuggestionsPanel = ({
1213
tag,
1314
blockUid,
15+
isOpen: isOpenProp,
1416
onClose,
15-
// TODO: Will be used to pass setting to body renderer
16-
shouldGrabFromReferencedPages,
17-
shouldGrabParentChildContext,
17+
onToggle,
1818
}: {
1919
tag: string;
2020
blockUid: string;
21+
isOpen: boolean;
2122
onClose: () => void;
22-
shouldGrabFromReferencedPages: boolean;
23-
shouldGrabParentChildContext: boolean;
23+
onToggle: (isOpen: boolean) => void;
2424
}) => {
25-
const [isOpen, setIsOpen] = useState(true);
25+
const [isOpen, setIsOpen] = useState(isOpenProp);
26+
27+
useEffect(() => {
28+
setIsOpen(isOpenProp);
29+
}, [isOpenProp]);
30+
31+
const handleToggle = useCallback(() => {
32+
setIsOpen((prev) => {
33+
const next = !prev;
34+
onToggle(next);
35+
return next;
36+
});
37+
}, [onToggle]);
2638

2739
const toggleHighlight = useCallback(
2840
(on: boolean) => {
2941
document
30-
.querySelectorAll(`[data-dg-block-uid="${blockUid}"]`)
42+
.querySelectorAll(`[suggestive-mode-overlay-button-uid="${blockUid}"]`)
3143
.forEach((el) =>
3244
el.classList.toggle(
3345
"suggestive-mode-overlay-highlight-on-panel-hover",
@@ -40,7 +52,7 @@ export const DiscourseSuggestionsPanel = ({
4052

4153
return (
4254
<Card
43-
data-dg-block-uid={`${blockUid}`}
55+
suggestive-mode-overlay-button-uid={blockUid}
4456
onMouseEnter={() => toggleHighlight(true)}
4557
onMouseLeave={() => toggleHighlight(false)}
4658
className="discourse-suggestions-panel flex flex-col bg-white p-2"
@@ -49,7 +61,7 @@ export const DiscourseSuggestionsPanel = ({
4961
<Navbar.Group
5062
align={Alignment.LEFT}
5163
className="min-w-0 flex-1 cursor-pointer"
52-
onClick={() => setIsOpen((prev) => !prev)}
64+
onClick={handleToggle}
5365
>
5466
<Navbar.Heading className="cursor-pointer truncate text-base font-semibold">
5567
{tag}
@@ -60,7 +72,7 @@ export const DiscourseSuggestionsPanel = ({
6072
icon={isOpen ? "chevron-up" : "chevron-down"}
6173
minimal
6274
small
63-
onClick={() => setIsOpen((prev) => !prev)}
75+
onClick={handleToggle}
6476
title={isOpen ? "Collapse" : "Expand"}
6577
/>
6678
<Button
@@ -78,8 +90,7 @@ export const DiscourseSuggestionsPanel = ({
7890
transitionDuration={150}
7991
>
8092
<div className="flex-grow overflow-y-auto p-2">
81-
{/* TODO: Replace with actual body*/}
82-
<div>Body placeholder</div>
93+
<SuggestionsBody tag={tag} blockUid={blockUid} />
8394
</div>
8495
</Collapse>
8596
</Card>

apps/roam/src/components/PanelManager.tsx

Lines changed: 40 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type PanelState = {
1818
blockUid: string;
1919
onloadArgs: OnloadArgs;
2020
element: HTMLElement | null;
21+
isOpen: boolean;
2122
};
2223
type PanelEntry = [string, PanelState];
2324

@@ -55,30 +56,11 @@ export const subscribeToPanelState = (
5556
};
5657
};
5758

58-
const getBooleanSetting = ({
59-
extensionAPI,
60-
key,
61-
defaultValue,
62-
}: {
63-
extensionAPI: unknown;
64-
key: string;
65-
defaultValue: boolean;
66-
}): boolean => {
67-
try {
68-
const value = (
69-
extensionAPI as { settings: { get: (k: string) => unknown } }
70-
).settings.get(key);
71-
return value == null ? defaultValue : Boolean(value);
72-
} catch {
73-
return defaultValue;
74-
}
75-
};
76-
7759
const generatePanelId = (tag: string): string =>
7860
`discourse-panel-${tag.replace(/[^a-zA-Z0-9]/g, "-")}`;
7961

8062
const selectOpenPanelsEntries = (): PanelEntry[] =>
81-
Array.from(openPanels.entries());
63+
Array.from(openPanels.entries()).reverse();
8264

8365
const subscribeToOpenPanels = (callback: () => void): (() => void) => {
8466
const handler = (): void => callback();
@@ -143,11 +125,8 @@ export const PanelContainer = (): React.ReactElement => {
143125
className={`flex flex-col ${isMinimized ? "" : "h-full w-full max-w-2xl flex-auto"}`}
144126
>
145127
{!isMinimized ? (
146-
<div
147-
id="discourse-graph-panels-container"
148-
className="flex flex-1 flex-col gap-2 overflow-y-auto bg-transparent"
149-
>
150-
<div id="discourse-suggestions-header">
128+
<>
129+
<div id="discourse-suggestions-header" className="flex-shrink-0">
151130
<Navbar className="flex items-center rounded-t shadow-none">
152131
<Navbar.Group
153132
align={Alignment.LEFT}
@@ -176,32 +155,31 @@ export const PanelContainer = (): React.ReactElement => {
176155
</Navbar>
177156
</div>
178157

179-
{panels.map(([tag, state]) => (
180-
<div
181-
key={tag}
182-
id={generatePanelId(tag)}
183-
className="m-2 flex-shrink-0 rounded bg-white shadow"
184-
>
185-
<ExtensionApiContextProvider {...state.onloadArgs}>
186-
<DiscourseSuggestionsPanel
187-
tag={tag}
188-
blockUid={state.blockUid}
189-
onClose={() => panelManager.removePanel(tag)}
190-
shouldGrabFromReferencedPages={getBooleanSetting({
191-
extensionAPI: state.onloadArgs.extensionAPI,
192-
key: "context-grab-from-referenced-pages",
193-
defaultValue: true,
194-
})}
195-
shouldGrabParentChildContext={getBooleanSetting({
196-
extensionAPI: state.onloadArgs.extensionAPI,
197-
key: "context-grab-parent-child-context",
198-
defaultValue: true,
199-
})}
200-
/>
201-
</ExtensionApiContextProvider>
202-
</div>
203-
))}
204-
</div>
158+
<div
159+
id="discourse-graph-panels-container"
160+
className="flex flex-1 flex-col gap-2 overflow-y-auto bg-transparent"
161+
>
162+
{panels.map(([tag, state]) => (
163+
<div
164+
key={tag}
165+
id={generatePanelId(tag)}
166+
className="m-2 flex-shrink-0 rounded bg-white shadow"
167+
>
168+
<ExtensionApiContextProvider {...state.onloadArgs}>
169+
<DiscourseSuggestionsPanel
170+
tag={tag}
171+
blockUid={state.blockUid}
172+
isOpen={state.isOpen}
173+
onClose={() => panelManager.removePanel(tag)}
174+
onToggle={(isOpen) =>
175+
panelManager.updatePanelState(tag, { isOpen })
176+
}
177+
/>
178+
</ExtensionApiContextProvider>
179+
</div>
180+
))}
181+
</div>
182+
</>
205183
) : (
206184
<div
207185
id="discourse-suggestions-minimized"
@@ -223,7 +201,7 @@ export const PanelContainer = (): React.ReactElement => {
223201
const clearBlockHighlight = (blockUid: string): void => {
224202
try {
225203
const nodes = document.querySelectorAll(
226-
`[data-dg-block-uid="${blockUid}"]`,
204+
`[suggestive-mode-overlay-button-uid="${blockUid}"]`,
227205
);
228206
nodes.forEach((el) =>
229207
el.classList.remove("suggestive-mode-overlay-highlight-on-panel-hover"),
@@ -279,6 +257,7 @@ type PanelManager = {
279257
blockUid: string;
280258
onloadArgs: OnloadArgs;
281259
}) => void;
260+
updatePanelState: (tag: string, updates: Partial<PanelState>) => void;
282261
removePanel: (tag: string) => void;
283262
closeAll: () => void;
284263
isOpen: (tag: string) => boolean;
@@ -313,11 +292,20 @@ export const panelManager: PanelManager = {
313292
blockUid,
314293
onloadArgs,
315294
element: null,
295+
isOpen: true,
316296
});
317297
panelManager.notify();
318298
notifySubscribers(tag, true);
319299
},
320300

301+
updatePanelState: (tag: string, updates: Partial<PanelState>): void => {
302+
const state = openPanels.get(tag);
303+
if (!state) return;
304+
305+
openPanels.set(tag, { ...state, ...updates });
306+
panelManager.notify();
307+
},
308+
321309
removePanel: (tag: string): void => {
322310
const state = openPanels.get(tag);
323311
if (!state) return;

0 commit comments

Comments
 (0)