Skip to content

Commit

Permalink
feat: add CanvasContext
Browse files Browse the repository at this point in the history
  • Loading branch information
plagoa committed Nov 19, 2024
1 parent d7e10a9 commit 7b5fe70
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 105 deletions.
170 changes: 83 additions & 87 deletions packages/cli/src/templates/Canvas/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useMemo, useState } from "react";
import { cx } from "@emotion/css";
import HvCanvasProvider from "packages/pentaho/src/Canvas/CanvasContext/CanvasContext";
import { ReactFlowInstance } from "reactflow";
import {
HvButton,
Expand Down Expand Up @@ -201,97 +201,93 @@ const Page = () => {

return (
<div className={classes.root}>
<HvFlow
className={classes.flow}
nodes={initialNodes}
edges={initialEdges}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
onInit={setFlowInstance}
/** Flow sidebar passed as prop to access the flow's Dnd context inside CanvasSidePanel */
sidebar={
<CanvasSidebar
tabs={sidePanelTabs}
open={sidePanelOpen}
tab={sidePanelTab}
onToggle={(event, value) => setSidePanelOpen(value)}
onTabChange={(event, value) => setSidePanelTab(value as number)}
>
{sidePanelContent[sidePanelTab]}
</CanvasSidebar>
}
>
<HvFlowEmpty
className={classes.flowEmpty}
title={
<HvTypography variant="title3" component="p">
Drag and Drop your Nodes
</HvTypography>
}
message={
<HvTypography
className={classes.flowEmptyMessage}
variant="label"
component="p"
<HvCanvasProvider>
<HvFlow
className={classes.flow}
nodes={initialNodes}
edges={initialEdges}
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
onInit={setFlowInstance}
/** Flow sidebar passed as prop to access the flow's Dnd context inside CanvasSidePanel */
sidebar={
<CanvasSidebar
tabs={sidePanelTabs}
open={sidePanelOpen}
tab={sidePanelTab}
onToggle={(event, value) => setSidePanelOpen(value)}
onTabChange={(event, value) => setSidePanelTab(value as number)}
>
Then you can start configuring your flow.
</HvTypography>
{sidePanelContent[sidePanelTab]}
</CanvasSidebar>
}
icon={null}
/>
<HvFlowBackground />
<HvFlowControls />
</HvFlow>
<HvCanvasToolbar
className={cx(classes.toolbar, {
[classes.fullWidth]: !sidePanelOpen,
[classes.minWidth]: sidePanelOpen,
})}
title={<HvInlineEditor defaultValue="My Canvas" variant="title4" />}
>
<HvButton variant="primary" onClick={handleExecute}>
Execute
</HvButton>
</HvCanvasToolbar>
{bottomTabs.length > 0 && bottomPanelOpen && (
<HvCanvasBottomPanel
className={cx({
[classes.fullWidth]: !sidePanelOpen,
[classes.minWidth]: sidePanelOpen,
})}
classes={{
rightActions: classes.rightActions,
}}
open={bottomPanelOpen}
minimize={minimize}
tabs={bottomTabs}
selectedTabId={selectedTable}
leftActions={leftActions}
rightActions={rightActions}
overflowActions={[...leftActions, ...rightActions]}
onTabChange={handleChangeTab}
onAction={handleAction}
>
<DataTable id={selectedTable} />
</HvCanvasBottomPanel>
)}
{bottomPanelOpen && (
<HvDialog
fullWidth
maxWidth="lg"
open={fullscreen}
onClose={() => setFullscreen((prev) => !prev)}
<HvFlowEmpty
className={classes.flowEmpty}
title={
<HvTypography variant="title3" component="p">
Drag and Drop your Nodes
</HvTypography>
}
message={
<HvTypography
className={classes.flowEmptyMessage}
variant="label"
component="p"
>
Then you can start configuring your flow.
</HvTypography>
}
icon={null}
/>
<HvFlowBackground />
<HvFlowControls />
</HvFlow>
<HvCanvasToolbar
className={classes.toolbar}
title={<HvInlineEditor defaultValue="My Canvas" variant="title4" />}
>
<HvDialogTitle className={classes.dialogTitle}>
{(
bottomTabs?.find((x) => x.id === selectedTable)?.title as Function
)(false)}
</HvDialogTitle>
<HvDialogContent>
<HvButton variant="primary" onClick={handleExecute}>
Execute
</HvButton>
</HvCanvasToolbar>
{bottomTabs.length > 0 && bottomPanelOpen && (
<HvCanvasBottomPanel
classes={{
rightActions: classes.rightActions,
}}
open={bottomPanelOpen}
minimize={minimize}
tabs={bottomTabs}
selectedTabId={selectedTable}
leftActions={leftActions}
rightActions={rightActions}
overflowActions={[...leftActions, ...rightActions]}
onTabChange={handleChangeTab}
onAction={handleAction}
>
<DataTable id={selectedTable} />
</HvDialogContent>
</HvDialog>
)}
</HvCanvasBottomPanel>
)}
{bottomPanelOpen && (
<HvDialog
fullWidth
maxWidth="lg"
open={fullscreen}
onClose={() => setFullscreen((prev) => !prev)}
>
<HvDialogTitle className={classes.dialogTitle}>
{(
bottomTabs?.find((x) => x.id === selectedTable)
?.title as Function
)(false)}
</HvDialogTitle>
<HvDialogContent>
<DataTable id={selectedTable} />
</HvDialogContent>
</HvDialog>
)}
</HvCanvasProvider>
</div>
);
};
Expand Down
10 changes: 0 additions & 10 deletions packages/cli/src/templates/Canvas/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,6 @@ export const classes = {
toolbar: css({
top: `calc(${theme.header.height} + ${theme.header.secondLevelHeight} + ${theme.space.md})`,
}),
fullWidth: css({
right: theme.space.lg,
marginLeft: "auto",
marginRight: "auto",
width: `calc(100% - 2 * ${theme.space.lg})`,
}),
minWidth: css({
right: theme.space.lg,
width: `calc(100% - 320px - 3 * ${theme.space.lg})`,
}),
panel: css({
top: `calc(${theme.header.height} + ${theme.header.secondLevelHeight})`,
height: `calc(100% - ${theme.header.height} - ${theme.header.secondLevelHeight})`,
Expand Down
8 changes: 8 additions & 0 deletions packages/pentaho/src/Canvas/BottomPanel/BottomPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
useUniqueId,
} from "@hitachivantara/uikit-react-core";

import { useCanvasContext } from "../CanvasContext/CanvasContext";
import { HvCanvasPanelTab } from "../PanelTab";
import { HvCanvasPanelTabs, HvCanvasPanelTabsProps } from "../PanelTabs";
import { staticClasses, useClasses } from "./BottomPanel.styles";
Expand Down Expand Up @@ -91,6 +92,9 @@ export const HvCanvasBottomPanel = forwardRef<

const { classes, cx } = useClasses(classesProp);

const canvasContext = useCanvasContext();
const sidePanelWidth = canvasContext?.sidePanelWidth ?? 0;

const id = useUniqueId(idProp);

// Tab resize detector: to position tab actions and set the panel top right border radius
Expand Down Expand Up @@ -158,6 +162,10 @@ export const HvCanvasBottomPanel = forwardRef<
},
className,
)}
style={{
width: `calc(100% - ${sidePanelWidth}px - 2 * ${theme.space.sm})`,
right: theme.space.sm,
}}
{...others}
>
<div className={classes.tabsRoot}>
Expand Down
60 changes: 60 additions & 0 deletions packages/pentaho/src/Canvas/CanvasContext/CanvasContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React, {
createContext,
useCallback,
useContext,
useMemo,
useState,
} from "react";

type CanvasContextValue = {
sidePanelOpen: boolean;
updateSidePanelOpen: (open: boolean) => void;
sidePanelWidth: number;
updateSidePanelWidth: (width: number) => void;
};

export const CanvasContext = createContext<CanvasContextValue | null>(null);

const HvCanvasProvider = ({ children }: { children: React.ReactNode }) => {
const [sidePanelOpen, setSidePanelOpen] = useState(false);
const [width, setWidth] = useState(0);
const [lastOpenWidth, setLastOpenWidth] = useState(0);

const updateWidth = useCallback((w: number) => {
setWidth(w);
setLastOpenWidth(w);
}, []);

const updateSidePanelOpen = useCallback(
(open: boolean) => {
setSidePanelOpen(open);
if (!open) {
setWidth(0);
setLastOpenWidth(width);
} else {
setWidth(lastOpenWidth);
}
},
[lastOpenWidth, width],
);

const value = useMemo(
() => ({
sidePanelOpen,
updateSidePanelOpen,
sidePanelWidth: width,
updateSidePanelWidth: updateWidth,
}),
[sidePanelOpen, updateSidePanelOpen, width, updateWidth],
);

return (
<CanvasContext.Provider value={value}>{children}</CanvasContext.Provider>
);
};

export const useCanvasContext = () => {
return useContext(CanvasContext);
};

export default HvCanvasProvider;
10 changes: 7 additions & 3 deletions packages/pentaho/src/Canvas/SidePanel/SidePanel.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import { HvButton } from "@hitachivantara/uikit-react-core";

import HvCanvasProvider from "../CanvasContext/CanvasContext";
import { HvCanvasSidePanel, HvCanvasSidePanelProps } from "./SidePanel";

const label = "Test";
Expand All @@ -21,9 +22,12 @@ const tabs = [

const renderSimplePanel = (props?: HvCanvasSidePanelProps) =>
render(
<HvCanvasSidePanel {...props} tabs={tabs}>
<HvButton>{label}</HvButton>
</HvCanvasSidePanel>,
<HvCanvasProvider>
<HvCanvasSidePanel {...props} tabs={tabs}>
<HvButton>{label}</HvButton>
</HvCanvasSidePanel>
,
</HvCanvasProvider>,
);

const ControlledPanel = ({
Expand Down
Loading

0 comments on commit 7b5fe70

Please sign in to comment.