Skip to content

Commit eccb538

Browse files
authored
🐛 Fix rerender problem (#1143)
* 🐛 Fix rerender problem * 🐛 Fix rerender problem * 🐛 Fix layout rendering
1 parent 689c890 commit eccb538

File tree

8 files changed

+114
-100
lines changed

8 files changed

+114
-100
lines changed

next/src/components/drawer/Sidebar.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { FaBars } from "react-icons/fa";
66

77
export type DisplayProps = {
88
show: boolean;
9-
setShow: (boolean) => void;
9+
setShow: (boolean: boolean) => void;
1010
};
1111

1212
export type SidebarProps = DisplayProps & {

next/src/components/drawer/TaskSidebar.tsx

+10-5
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import React from "react";
55
import { FaBars, FaTimesCircle } from "react-icons/fa";
66
import { v1 } from "uuid";
77

8-
import type { DisplayProps } from "./Sidebar";
98
import Sidebar from "./Sidebar";
109
import { useAgentStore } from "../../stores";
10+
import { useLayoutStore } from "../../stores/layoutStore";
1111
import { useTaskStore } from "../../stores/taskStore";
1212
import type { Task as TaskType } from "../../types/task";
1313
import { MESSAGE_TYPE_TASK, TASK_STATUS_STARTED } from "../../types/task";
@@ -16,14 +16,19 @@ import Input from "../Input";
1616
import FadeIn from "../motions/FadeIn";
1717
import { getMessageContainerStyle, getTaskStatusIcon } from "../utils/helpers";
1818

19-
20-
const TaskSidebar = ({ show, setShow }: DisplayProps) => {
19+
const TaskSidebar = () => {
2120
const [customTask, setCustomTask] = React.useState("");
2221
const agent = useAgentStore.use.agent();
2322
const tasks = useTaskStore.use.tasks();
2423
const addTask = useTaskStore.use.addTask();
2524
const [t] = useTranslation();
2625

26+
const { layout, setLayout } = useLayoutStore();
27+
28+
const setShow = (show: boolean) => {
29+
setLayout({ showRightSidebar: show });
30+
};
31+
2732
const handleAddTask = () => {
2833
addTask({
2934
id: v1().toString(),
@@ -36,12 +41,12 @@ const TaskSidebar = ({ show, setShow }: DisplayProps) => {
3641
};
3742

3843
return (
39-
<Sidebar show={show} setShow={setShow} side="right">
44+
<Sidebar show={layout.showRightSidebar} setShow={setShow} side="right">
4045
<div className="flex h-screen flex-col gap-2 text-white">
4146
<div className="flex flex-row items-center gap-1">
4247
<button
4348
className="neutral-button-primary rounded-md border-none transition-all"
44-
onClick={() => setShow(!show)}
49+
onClick={() => setShow(!layout.showRightSidebar)}
4550
>
4651
<FaBars size="15" className="z-20 m-2" />
4752
</button>

next/src/components/drawer/WorkflowSidebar.tsx

+15-24
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import clsx from "clsx";
2-
import React from "react";
2+
import React, { FC } from "react";
33
import { FaBars } from "react-icons/fa";
44
import type { Edge, Node } from "reactflow";
55

6-
import type { DisplayProps } from "./Sidebar";
76
import Sidebar from "./Sidebar";
87
import type { createNodeType, updateNodeType } from "../../hooks/useWorkflow";
98
import { findParents } from "../../services/graph-utils";
@@ -12,6 +11,7 @@ import {
1211
getNodeBlockDefinitionFromNode,
1312
getNodeBlockDefinitions,
1413
} from "../../services/workflow/node-block-definitions";
14+
import { useLayoutStore } from "../../stores/layoutStore";
1515
import type { WorkflowEdge, WorkflowNode } from "../../types/workflow";
1616
import WorkflowSidebarInput from "../../ui/WorkflowSidebarInput";
1717
import PrimaryButton from "../PrimaryButton";
@@ -24,29 +24,21 @@ type WorkflowControls = {
2424
updateNode: updateNodeType;
2525
};
2626

27-
type WorkflowSidebarProps = DisplayProps & {
28-
controls: WorkflowControls;
29-
};
30-
31-
// Wrapper HOC to curry the createNode function
32-
export const getWorkflowSidebar = (controls: WorkflowControls) => {
33-
const WorkflowSidebarHOC = ({ show, setShow }: DisplayProps) => (
34-
<WorkflowSidebar show={show} setShow={setShow} controls={controls} />
35-
);
36-
WorkflowSidebarHOC.displayName = "WorkflowSidebarHOC";
37-
return WorkflowSidebarHOC;
38-
};
39-
40-
const WorkflowSidebar = ({ show, setShow, controls }: WorkflowSidebarProps) => {
27+
const WorkflowSidebar: FC<WorkflowControls> = (controls) => {
4128
const [tab, setTab] = React.useState<"inspect" | "create">("inspect");
29+
const { layout, setLayout } = useLayoutStore();
30+
31+
const setShow = (show: boolean) => {
32+
setLayout({ showRightSidebar: show });
33+
};
4234

4335
return (
44-
<Sidebar show={show} setShow={setShow} side="right">
36+
<Sidebar show={layout.showRightSidebar} setShow={setShow} side="right">
4537
<div className="text-color-primary mx-2 flex h-screen flex-col gap-2">
4638
<div className="flex flex-row items-center gap-1">
4739
<button
4840
className="neutral-button-primary rounded-md border-none transition-all"
49-
onClick={() => setShow(!show)}
41+
onClick={() => setShow(!layout.showRightSidebar)}
5042
>
5143
<FaBars size="15" className="z-20 mr-2" />
5244
</button>
@@ -95,6 +87,7 @@ const InspectSection = ({ selectedNode, updateNode, nodes, edges }: InspectSecti
9587
const definition = getNodeBlockDefinitionFromNode(selectedNode);
9688

9789
const handleValueChange = (name: string, value: string) => {
90+
console.log("handleValueChange", name, value);
9891
const updatedNode = { ...selectedNode };
9992
updatedNode.data.block.input[name] = value;
10093
updateNode(updatedNode);
@@ -105,12 +98,10 @@ const InspectSection = ({ selectedNode, updateNode, nodes, edges }: InspectSecti
10598
if (definition == undefined) return [];
10699

107100
const outputFields = definition.output_fields;
108-
return outputFields.map((outputField) => {
109-
return {
110-
key: `{{${ancestorNode.id}.${outputField.name}}}`,
111-
value: `${definition.type}.${outputField.name}`,
112-
};
113-
});
101+
return outputFields.map((outputField) => ({
102+
key: `{{${ancestorNode.id}.${outputField.name}}}`,
103+
value: `${definition.type}.${outputField.name}`,
104+
}));
114105
});
115106

116107
const handleAutocompleteClick = (inputField: IOField, field: { key: string; value: string }) => {

next/src/layout/dashboard.tsx

+29-46
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import clsx from "clsx";
2-
import { useState } from "react";
32
import type { ReactNode } from "react";
3+
import { useState } from "react";
44

55
import AppHead from "../components/AppHead";
66
import DottedGridBackground from "../components/DottedGridBackground";
77
import LeftSidebar from "../components/drawer/LeftSidebar";
8-
import type { DisplayProps } from "../components/drawer/Sidebar";
98
import { SidebarControlButton } from "../components/drawer/Sidebar";
10-
import { useTheme } from "../hooks/useTheme";
9+
import { useLayoutStore } from "../stores/layoutStore";
1110

1211
type SidebarSettings = {
1312
mobile: boolean;
@@ -16,28 +15,31 @@ type SidebarSettings = {
1615

1716
type DashboardLayoutProps = {
1817
children: ReactNode;
19-
rightSidebar?: ({ show, setShow }: DisplayProps) => JSX.Element;
18+
rightSidebar?: ReactNode;
2019
};
21-
const DashboardLayout = (props: DashboardLayoutProps) => {
22-
const [leftSettings, setLeftSettings] = useState({ mobile: false, desktop: true });
23-
const [rightSettings, setRightSettings] = useState({ mobile: false, desktop: true });
2420

25-
const setMobile =
26-
(settings: SidebarSettings, setSettings: (SidebarSettings) => void) => (open: boolean) =>
27-
setSettings({
28-
mobile: open,
29-
desktop: settings.desktop,
30-
});
21+
const defaultState: SidebarSettings = {
22+
mobile: false,
23+
desktop: true,
24+
};
25+
26+
const setMobile =
27+
(settings: SidebarSettings, setSettings: (SidebarSettings) => void) => (open: boolean) =>
28+
setSettings({
29+
mobile: open,
30+
desktop: settings.desktop,
31+
});
3132

32-
const setDesktop =
33-
(settings: SidebarSettings, setSettings: (SidebarSettings) => void) => (open: boolean) =>
34-
setSettings({
35-
mobile: settings.mobile,
36-
desktop: open,
37-
});
33+
const setDesktop =
34+
(settings: SidebarSettings, setSettings: (SidebarSettings) => void) => (open: boolean) =>
35+
setSettings({
36+
mobile: settings.mobile,
37+
desktop: open,
38+
});
3839

39-
//add event listener to detect OS theme changes
40-
useTheme();
40+
const DashboardLayout = (props: DashboardLayoutProps) => {
41+
const [leftSettings, setLeftSettings] = useState(defaultState);
42+
const { layout, setLayout } = useLayoutStore();
4143

4244
return (
4345
<>
@@ -72,39 +74,20 @@ const DashboardLayout = (props: DashboardLayoutProps) => {
7274
{/* Mobile */}
7375
{props.rightSidebar && (
7476
<>
75-
<props.rightSidebar
76-
show={rightSettings.mobile}
77-
setShow={setMobile(rightSettings, setRightSettings)}
77+
<div className="lg:inset-y-0 lg:flex lg:w-64 lg:flex-col">{props.rightSidebar}</div>
78+
<SidebarControlButton
79+
side="right"
80+
show={layout.showRightSidebar}
81+
setShow={(show) => setLayout({ showRightSidebar: show })}
7882
/>
79-
<div className={rightSettings.mobile ? "hidden" : "lg:hidden"}>
80-
<SidebarControlButton
81-
side="right"
82-
show={rightSettings.mobile}
83-
setShow={setMobile(rightSettings, setRightSettings)}
84-
/>
85-
</div>
86-
{/* Desktop sidebar */}
87-
<div className="hidden lg:visible lg:inset-y-0 lg:flex lg:w-64 lg:flex-col">
88-
<props.rightSidebar
89-
show={rightSettings.desktop}
90-
setShow={setDesktop(rightSettings, setRightSettings)}
91-
/>
92-
</div>
93-
<div className={rightSettings.desktop ? "hidden" : "hidden lg:block"}>
94-
<SidebarControlButton
95-
side="right"
96-
show={rightSettings.desktop}
97-
setShow={setDesktop(rightSettings, setRightSettings)}
98-
/>
99-
</div>
10083
</>
10184
)}
10285

10386
<main
10487
className={clsx(
10588
"bg-gradient-to-b from-[#2B2B2B] to-[#1F1F1F] duration-300",
10689
leftSettings.desktop && "lg:pl-64",
107-
props.rightSidebar && rightSettings.desktop && "lg:pr-64"
90+
props.rightSidebar && layout.showRightSidebar && "lg:pr-64"
10891
)}
10992
>
11093
<DottedGridBackground className="min-w-screen min-h-screen">

next/src/pages/index.tsx

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import clsx from "clsx";
22
import { AnimatePresence, motion } from "framer-motion";
33
import { type GetStaticProps, type NextPage } from "next";
4-
import { useRouter } from "next/router";
54
import { useTranslation } from "next-i18next";
65
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
76
import React, { useEffect, useRef } from "react";
@@ -19,10 +18,16 @@ import Summarize from "../components/console/SummarizeButton";
1918
import HelpDialog from "../components/dialog/HelpDialog";
2019
import { SignInDialog } from "../components/dialog/SignInDialog";
2120
import { ToolsDialog } from "../components/dialog/ToolsDialog";
21+
import TaskSidebar from "../components/drawer/TaskSidebar";
2222
import Input from "../components/Input";
23+
import Expand from "../components/motions/expand";
2324
import FadeIn from "../components/motions/FadeIn";
2425
import { useAgent } from "../hooks/useAgent";
2526
import { useAuth } from "../hooks/useAuth";
27+
import { useSettings } from "../hooks/useSettings";
28+
import DashboardLayout from "../layout/dashboard";
29+
import { AgentApi } from "../services/agent/agent-api";
30+
import { DefaultAgentRunModel } from "../services/agent/agent-run-model";
2631
import AutonomousAgent from "../services/agent/autonomous-agent";
2732
import { MessageService } from "../services/agent/message-service";
2833
import {
@@ -32,24 +37,16 @@ import {
3237
useMessageStore,
3338
} from "../stores";
3439
import { useAgentInputStore } from "../stores/agentInputStore";
35-
import { languages } from "../utils/languages";
36-
import { isEmptyOrBlank } from "../utils/whitespace";
37-
38-
import DashboardLayout from "../layout/dashboard";
39-
import Expand from "../components/motions/expand";
40-
import { useSettings } from "../hooks/useSettings";
41-
import { DefaultAgentRunModel } from "../services/agent/agent-run-model";
4240
import { resetAllTaskSlices, useTaskStore } from "../stores/taskStore";
43-
import { AgentApi } from "../services/agent/agent-api";
4441
import { toApiModelSettings } from "../utils/interfaces";
45-
import TaskSidebar from "../components/drawer/TaskSidebar";
42+
import { languages } from "../utils/languages";
43+
import { isEmptyOrBlank } from "../utils/whitespace";
4644

4745
const Home: NextPage = () => {
4846
const { t } = useTranslation("indexPage");
4947
const addMessage = useMessageStore.use.addMessage();
5048
const messages = useMessageStore.use.messages();
5149
const tasks = useTaskStore.use.tasks();
52-
const { query } = useRouter();
5350

5451
const setAgent = useAgentStore.use.setAgent();
5552
const agentLifecycle = useAgentStore.use.lifecycle();
@@ -161,7 +158,7 @@ const Home: NextPage = () => {
161158
};
162159

163160
return (
164-
<DashboardLayout rightSidebar={TaskSidebar}>
161+
<DashboardLayout rightSidebar={<TaskSidebar />}>
165162
<HelpDialog />
166163
<ToolsDialog show={showToolsDialog} close={() => setShowToolsDialog(false)} />
167164

next/src/pages/workflow/[workflow].tsx

+12-10
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { serverSideTranslations } from "next-i18next/serverSideTranslations";
55
import { FaSave } from "react-icons/fa";
66

77
import nextI18NextConfig from "../../../next-i18next.config";
8-
import { getWorkflowSidebar } from "../../components/drawer/WorkflowSidebar";
8+
import WorkflowSidebar from "../../components/drawer/WorkflowSidebar";
99
import PrimaryButton from "../../components/PrimaryButton";
1010
import FlowChart from "../../components/workflow/Flowchart";
1111
import { useAuth } from "../../hooks/useAuth";
@@ -21,16 +21,18 @@ const WorkflowPage: NextPage = () => {
2121
const { nodesModel, edgesModel, selectedNode, saveWorkflow, createNode, updateNode, members } =
2222
useWorkflow(query.workflow as string, session);
2323

24+
const rightSideBar = (
25+
<WorkflowSidebar
26+
createNode={createNode}
27+
updateNode={updateNode}
28+
selectedNode={selectedNode}
29+
nodes={nodesModel[0]}
30+
edges={edgesModel[0]}
31+
/>
32+
);
33+
2434
return (
25-
<DashboardLayout
26-
rightSidebar={getWorkflowSidebar({
27-
createNode,
28-
selectedNode,
29-
updateNode,
30-
nodes: nodesModel[0],
31-
edges: edgesModel[0],
32-
})}
33-
>
35+
<DashboardLayout rightSidebar={rightSideBar}>
3436
<FlowChart
3537
controls={true}
3638
nodesModel={nodesModel}

next/src/stores/layoutStore.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { StateCreator } from "zustand";
2+
import { create } from "zustand";
3+
4+
import { createSelectors } from "./helpers";
5+
6+
interface Layout {
7+
showRightSidebar: boolean;
8+
}
9+
10+
interface LayoutSlice {
11+
layout: Layout;
12+
setLayout: (layout: Layout) => void;
13+
}
14+
15+
const initialState = {
16+
layout: {
17+
showRightSidebar: false,
18+
},
19+
};
20+
21+
const createLayoutSlice: StateCreator<LayoutSlice> = (set, get) => {
22+
return {
23+
...initialState,
24+
setLayout: (layout: Layout) => {
25+
set(() => ({
26+
layout,
27+
}));
28+
},
29+
};
30+
};
31+
32+
export const useLayoutStore = createSelectors(
33+
create<LayoutSlice>()((...a) => ({
34+
...createLayoutSlice(...a),
35+
}))
36+
);

next/src/ui/WorkflowSidebarInput.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import React from "react";
2+
import type { Node } from "reactflow";
23

34
import Combo from "./combox";
45
import Dropzone from "./dropzone";
56
import InputWithSuggestions from "./InputWithSuggestions";
67
import type { IOField } from "../services/workflow/node-block-definitions";
7-
import { WorkflowNode } from "../types/workflow";
8-
import { Node } from "reactflow";
8+
import type { WorkflowNode } from "../types/workflow";
99

1010
interface SidebarInputProps {
1111
inputField: IOField;

0 commit comments

Comments
 (0)