Skip to content

Commit c9d6abf

Browse files
committed
feat: in react ui, switch from tabs to toolbar ui
Signed-off-by: Nick Mitchell <[email protected]>
1 parent 048dace commit c9d6abf

File tree

8 files changed

+116
-72
lines changed

8 files changed

+116
-72
lines changed

pdl-live-react/src/page/Page.css

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
.pdl-page .pdl-content-section {
2-
/* This places the content e.g. editors flush with the tabs. See Preview.css for other rules in this arena. */
3-
padding-top: 0;
4-
52
/* These help to fit monaco-editor to the height of the tab content section */
63
& > .pf-v6-c-page__main-body {
74
display: flex;

pdl-live-react/src/page/Page.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import { Page, PageSection } from "@patternfly/react-core"
66
import Viewer from "./Viewer"
77
import Sidebar from "./Sidebar"
88
import Masthead from "./Masthead"
9-
import ViewerTabs from "./ViewerTabs"
109
import DrawerContent from "../view/detail/DrawerContent"
1110
import PageBreadcrumbs, { type PageBreadcrumbProps } from "./PageBreadcrumbs"
1211

@@ -60,7 +59,6 @@ export default function PDLPage(props: Props) {
6059
<Masthead setDarkMode={setDarkMode} />
6160
</DarkModeContext.Provider>
6261
}
63-
horizontalSubnav={<ViewerTabs hidden={typeof value !== "string"} />}
6462
groupProps={notFilled /* so breadcrumbs aren't filled */}
6563
isBreadcrumbGrouped
6664
breadcrumb={

pdl-live-react/src/page/Viewer.tsx

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { lazy, useEffect, useMemo, useState } from "react"
1+
import { useMemo } from "react"
22
import { useLocation } from "react-router"
33

4-
const Code = lazy(() => import("../view/code/Code"))
5-
const Memory = lazy(() => import("../view/memory/Memory"))
6-
const Program = lazy(() => import("../view/masonry/MasonryTimelineCombo"))
4+
import { isView } from "../view/masonry/View"
5+
import Program from "../view/masonry/MasonryTimelineCombo"
76

87
import "./Viewer.css"
98

@@ -12,17 +11,10 @@ export default function Viewer({ value }: { value: string }) {
1211
// We will use this to find the current active tab
1312
const { hash } = useLocation()
1413

15-
const activeTabAsSpecified = !hash || hash === "#" ? "#program" : hash
16-
const activeTab = ["#source", "#raw", "#dataflow", "#program"].includes(
17-
activeTabAsSpecified,
18-
)
14+
const activeTabAsSpecified = !hash || hash === "#" ? "program" : hash.slice(1)
15+
const activeTab = isView(activeTabAsSpecified)
1916
? activeTabAsSpecified
20-
: "#program"
21-
22-
const [shown, setShown] = useState<Record<string, boolean>>({})
23-
useEffect(() => {
24-
setShown((shown) => Object.assign({}, shown, { [activeTab]: true }))
25-
}, [activeTab, setShown])
17+
: ("program" as const)
2618

2719
const data = useMemo(
2820
() => (value ? (JSON.parse(value) as import("../pdl_ast").PdlBlock) : null),
@@ -32,44 +24,5 @@ export default function Viewer({ value }: { value: string }) {
3224
return "Invalid trace content"
3325
}
3426

35-
return (
36-
<>
37-
{[
38-
<section
39-
className="pdl-viewer-section"
40-
data-no-scroll
41-
key="#source"
42-
data-hash="#source"
43-
hidden={activeTab !== "#source"}
44-
>
45-
<Code block={data} limitHeight={false} />
46-
</section>,
47-
<section
48-
className="pdl-viewer-section"
49-
data-no-scroll
50-
key="#raw"
51-
data-hash="#raw"
52-
hidden={activeTab !== "#raw"}
53-
>
54-
<Code block={data} limitHeight={false} raw />
55-
</section>,
56-
<section
57-
className="pdl-viewer-section"
58-
key="#dataflow"
59-
data-hash="#dataflow"
60-
hidden={activeTab !== "#dataflow"}
61-
>
62-
<Memory block={data} />
63-
</section>,
64-
<section
65-
className="pdl-viewer-section"
66-
key="#program"
67-
data-hash="#program"
68-
hidden={activeTab !== "#program"}
69-
>
70-
<Program block={data} />
71-
</section>,
72-
].filter((_) => shown[_.props["data-hash"]])}
73-
</>
74-
)
27+
return <Program block={data} view={activeTab} />
7528
}

pdl-live-react/src/view/breadcrumbs/BreadcrumbBarForBlockId.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default function BreadcrumbBarForBlockId({
3232
const s = searchParams.toString().length === 0 ? "" : "&" + searchParams
3333
const onClick = useCallback(
3434
() => navigate(`?detail&type=block&id=${id}${s}${hash}`),
35-
[id, hash, s],
35+
[id, hash, s, navigate],
3636
)
3737

3838
const crumbs = id.replace(/text\.\d+\./g, "").split(/\./)
Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,82 @@
1-
import { useEffect, useMemo, useState } from "react"
1+
import { useNavigate } from "react-router"
2+
import {
3+
useCallback,
4+
useEffect,
5+
useMemo,
6+
useState,
7+
lazy,
8+
Suspense,
9+
} from "react"
210

311
import Timeline from "../timeline/TimelineFromModel"
12+
const Code = lazy(() => import("../code/Code"))
413

514
import Masonry from "./Masonry"
615
import computeModel from "./model"
7-
import Toolbar, { type As, type SML } from "./Toolbar"
16+
import Toolbar, { type As, type SML, type View } from "./Toolbar"
817

918
import "./Masonry.css"
1019

1120
type Props = {
21+
view: View
1222
block: import("../../pdl_ast").PdlBlock
1323
}
1424

1525
const asLocalStorageKey = "pdl-viewer.masonry.as"
16-
export function getAsUserSetting(): As {
26+
function getAsUserSetting(): As {
1727
return (localStorage.getItem(asLocalStorageKey) as As) || "grid"
1828
}
19-
export function setAsUserSetting(as: As) {
29+
function setAsUserSetting(as: As) {
2030
localStorage.setItem(asLocalStorageKey, as)
2131
}
2232

2333
const smlLocalStorageKey = "pdl-viewer.masonry.sml"
24-
export function getSMLUserSetting(): SML {
34+
function getSMLUserSetting(): SML {
2535
return (localStorage.getItem(smlLocalStorageKey) as SML) || "l"
2636
}
27-
export function setSMLUserSetting(sml: SML) {
37+
function setSMLUserSetting(sml: SML) {
2838
localStorage.setItem(smlLocalStorageKey, sml)
2939
}
3040

31-
export default function MasonryTimelineCombo({ block }: Props) {
41+
export default function MasonryTimelineCombo({ block, view }: Props) {
3242
const [as, setAs] = useState<As>(getAsUserSetting())
3343
const [sml, setSML] = useState<SML>(getSMLUserSetting())
3444

3545
useEffect(() => setAsUserSetting(as), [as])
3646
useEffect(() => setSMLUserSetting(sml), [sml])
3747

48+
const navigate = useNavigate()
49+
const setView = useCallback(
50+
(view: View) => {
51+
navigate("#" + view)
52+
},
53+
[navigate],
54+
)
55+
3856
const { base, masonry, numbering } = useMemo(
3957
() => computeModel(block),
4058
[block],
4159
)
4260

4361
return (
4462
<>
45-
<Toolbar as={as} setAs={setAs} sml={sml} setSML={setSML} />
46-
<Masonry model={masonry} as={as} sml={sml}>
47-
<Timeline model={base} numbering={numbering} />
48-
</Masonry>
63+
<Toolbar
64+
as={as}
65+
setAs={setAs}
66+
sml={sml}
67+
setSML={setSML}
68+
view={view}
69+
setView={setView}
70+
/>
71+
{view === "program" ? (
72+
<Masonry model={masonry} as={as} sml={sml}>
73+
<Timeline model={base} numbering={numbering} />
74+
</Masonry>
75+
) : (
76+
<Suspense>
77+
<Code block={block} limitHeight={false} raw={view === "rawtrace"} />
78+
</Suspense>
79+
)}
4980
</>
5081
)
5182
}

pdl-live-react/src/view/masonry/Toolbar.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import {
77

88
import ToolbarAsToggle from "./ToolbarAsToggle"
99
import ToolbarSMLToggle from "./ToolbarSMLToggle"
10+
import ToolbarViewToggle from "./ToolbarViewToggle"
11+
12+
import { type View } from "./View"
13+
export { type View }
1014

1115
const alignEnd = { default: "alignEnd" as const }
1216

@@ -19,12 +23,28 @@ export type Props = {
1923

2024
sml: SML
2125
setSML(sml: SML): void
26+
27+
view: View
28+
setView(view: View): void
2229
}
2330

24-
export default function MasonryToolbar({ as, setAs, sml, setSML }: Props) {
31+
export default function MasonryToolbar({
32+
as,
33+
setAs,
34+
sml,
35+
setSML,
36+
view,
37+
setView,
38+
}: Props) {
2539
return (
2640
<Toolbar className="pdl-masonry-toolbar" isSticky>
2741
<ToolbarContent>
42+
<ToolbarGroup>
43+
<ToolbarItem>
44+
<ToolbarViewToggle view={view} setView={setView} />
45+
</ToolbarItem>
46+
</ToolbarGroup>
47+
2848
<ToolbarGroup variant="action-group-plain" align={alignEnd}>
2949
<ToolbarItem>
3050
<ToolbarSMLToggle sml={sml} setSML={setSML} />
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { useCallback } from "react"
2+
import { ToggleGroup, ToggleGroupItem } from "@patternfly/react-core"
3+
4+
export default function ToolbarProgramOrSourceToggle({
5+
view,
6+
setView,
7+
}: Pick<import("./Toolbar").Props, "view" | "setView">) {
8+
const handleClickProgram = useCallback(() => {
9+
setView("program")
10+
}, [setView])
11+
const handleClickSource = useCallback(() => {
12+
setView("source")
13+
}, [setView])
14+
const handleClickRawTrace = useCallback(() => {
15+
setView("rawtrace")
16+
}, [setView])
17+
18+
return (
19+
<ToggleGroup aria-label="masonry program-source toggle">
20+
<ToggleGroupItem
21+
text="Program"
22+
aria-label="show program"
23+
isSelected={view === "program"}
24+
onClick={handleClickProgram}
25+
/>
26+
<ToggleGroupItem
27+
text="Source"
28+
aria-label="show source"
29+
isSelected={view === "source"}
30+
onClick={handleClickSource}
31+
/>
32+
<ToggleGroupItem
33+
text="Raw Trace"
34+
aria-label="show raw trace"
35+
isSelected={view == "rawtrace"}
36+
onClick={handleClickRawTrace}
37+
/>
38+
</ToggleGroup>
39+
)
40+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export type View = "program" | "source" | "rawtrace"
2+
3+
export function isView(v: string): v is View {
4+
return v === "program" || v === "source" || v === "rawtrace"
5+
}

0 commit comments

Comments
 (0)