mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-10 23:58:06 -05:00
refactor(frontend): replace context api in new block menu with zustand store (#11120)
Currently, we use the context API for the block menu provider and to access some of its state outside the blockMenuProvider wrapper. For instance, in the tutorial, we need to move this wrapper higher up in the tree, perhaps at the top of the builder tree. This will cause unnecessary re-renders. Therefore, we should create a block menu zustand store so that we can easily access it in other parts of the builder. ### Changes 🏗️ - Deleted `block-menu-provider.tsx` file. - Updated BlockMenu, BlockMenuContent, BlockMenuDefaultContent, and other components to utilize blockMenuStore instead of BlockMenuStateProvider. - Adjusted imports and context usage accordingly. ### Checklist 📋 - [x] Changes have been clearly listed. - [x] Code has been tested and verified. - [x] I’ve checked every part of the block menu where we used the context API and it’s working perfectly. - [x] Ability to use block menu state in other parts of the builder.
This commit is contained in:
@@ -7,7 +7,6 @@ import {
|
||||
import { BlockMenuContent } from "../BlockMenuContent/BlockMenuContent";
|
||||
import { ControlPanelButton } from "../ControlPanelButton";
|
||||
import { useBlockMenu } from "./useBlockMenu";
|
||||
import { BlockMenuStateProvider } from "../block-menu-provider";
|
||||
import { LegoIcon } from "@phosphor-icons/react";
|
||||
|
||||
interface BlockMenuProps {
|
||||
@@ -49,9 +48,7 @@ export const BlockMenu: React.FC<BlockMenuProps> = ({
|
||||
className="absolute h-[80vh] w-[46.625rem] overflow-hidden rounded-[1rem] border-none p-0 shadow-[0_2px_6px_0_rgba(0,0,0,0.05)]"
|
||||
data-id="blocks-control-popover-content"
|
||||
>
|
||||
<BlockMenuStateProvider>
|
||||
<BlockMenuContent />
|
||||
</BlockMenuStateProvider>
|
||||
<BlockMenuContent />
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client";
|
||||
import React from "react";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { BlockMenuSearchBar } from "../BlockMenuSearchBar/BlockMenuSearchBar";
|
||||
import { Separator } from "@/components/__legacy__/ui/separator";
|
||||
import { BlockMenuDefault } from "../BlockMenuDefault/BlockMenuDefault";
|
||||
import { BlockMenuSearch } from "../BlockMenuSearch/BlockMenuSearch";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
export const BlockMenuContent = () => {
|
||||
const { searchQuery } = useBlockMenuContext();
|
||||
const { searchQuery } = useBlockMenuStore();
|
||||
return (
|
||||
<div className="flex h-full w-full flex-col">
|
||||
<BlockMenuSearchBar />
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React from "react";
|
||||
import { DefaultStateType, useBlockMenuContext } from "../block-menu-provider";
|
||||
import { AllBlocksContent } from "../AllBlocksContent/AllBlocksContent";
|
||||
import { PaginatedBlocksContent } from "../PaginatedBlocksContent/PaginatedBlocksContent";
|
||||
import { IntegrationsContent } from "../IntegrationsContent/IntegrationsContent";
|
||||
import { MarketplaceAgentsContent } from "../MarketplaceAgentsContent/MarketplaceAgentsContent";
|
||||
import { MyAgentsContent } from "../MyAgentsContent/MyAgentsContent";
|
||||
import { SuggestionContent } from "../SuggestionContent/SuggestionContent";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
import { DefaultStateType } from "../types";
|
||||
|
||||
export const BlockMenuDefaultContent = () => {
|
||||
const { defaultState } = useBlockMenuContext();
|
||||
const { defaultState } = useBlockMenuStore();
|
||||
|
||||
return (
|
||||
<div className="h-full flex-1 overflow-hidden">
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { debounce } from "lodash";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
const SEARCH_DEBOUNCE_MS = 300;
|
||||
|
||||
export const useBlockMenuSearchBar = () => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [localQuery, setLocalQuery] = useState("");
|
||||
const { setSearchQuery, setSearchId, searchId } = useBlockMenuContext();
|
||||
const { setSearchQuery, setSearchId, searchId } = useBlockMenuStore();
|
||||
|
||||
const searchIdRef = useRef(searchId);
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React from "react";
|
||||
import { MenuItem } from "../MenuItem";
|
||||
import { DefaultStateType, useBlockMenuContext } from "../block-menu-provider";
|
||||
import { useBlockMenuSidebar } from "./useBlockMenuSidebar";
|
||||
import { Skeleton } from "@/components/__legacy__/ui/skeleton";
|
||||
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
import { DefaultStateType } from "../types";
|
||||
|
||||
export const BlockMenuSidebar = () => {
|
||||
const { data, setDefaultState, defaultState, isLoading, isError, error } =
|
||||
useBlockMenuSidebar();
|
||||
const { setIntegration } = useBlockMenuContext();
|
||||
const { setIntegration } = useBlockMenuStore();
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="w-fit space-y-2 px-4 pt-4">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { useGetV2GetBuilderItemCounts } from "@/app/api/__generated__/endpoints/default/default";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { CountResponse } from "@/app/api/__generated__/models/countResponse";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
export const useBlockMenuSidebar = () => {
|
||||
const { defaultState, setDefaultState } = useBlockMenuContext();
|
||||
const { defaultState, setDefaultState } = useBlockMenuStore();
|
||||
|
||||
const { data, isLoading, isError, error } = useGetV2GetBuilderItemCounts({
|
||||
query: {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { Button } from "@/components/__legacy__/ui/button";
|
||||
import React, { Fragment } from "react";
|
||||
import { IntegrationBlock } from "../IntergrationBlock";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { Skeleton } from "@/components/__legacy__/ui/skeleton";
|
||||
import { useIntegrationBlocks } from "./useIntegrationBlocks";
|
||||
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
|
||||
import { InfiniteScroll } from "@/components/contextual/InfiniteScroll/InfiniteScroll";
|
||||
import { useNodeStore } from "../../../stores/nodeStore";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
export const IntegrationBlocks = () => {
|
||||
const { integration, setIntegration } = useBlockMenuContext();
|
||||
const { integration, setIntegration } = useBlockMenuStore();
|
||||
const {
|
||||
allBlocks,
|
||||
status,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useGetV2GetBuilderBlocksInfinite } from "@/app/api/__generated__/endpoints/default/default";
|
||||
import { BlockResponse } from "@/app/api/__generated__/models/blockResponse";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
export const useIntegrationBlocks = () => {
|
||||
const { integration } = useBlockMenuContext();
|
||||
const { integration } = useBlockMenuStore();
|
||||
|
||||
const {
|
||||
data: blocks,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from "react";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { scrollbarStyles } from "@/components/styles/scrollbars";
|
||||
import { IntegrationBlocks } from "../IntegrationBlocks/IntegrationBlocks";
|
||||
import { PaginatedIntegrationList } from "../PaginatedIntegrationList/PaginatedIntegrationList";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
export const IntegrationsContent = () => {
|
||||
const { integration } = useBlockMenuContext();
|
||||
const { integration } = useBlockMenuStore();
|
||||
|
||||
if (!integration) {
|
||||
return <PaginatedIntegrationList />;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import React from "react";
|
||||
import { Integration } from "../Integration";
|
||||
import { useBlockMenuContext } from "../block-menu-provider";
|
||||
import { InfiniteScroll } from "@/components/contextual/InfiniteScroll/InfiniteScroll";
|
||||
import { usePaginatedIntegrationList } from "./usePaginatedIntegrationList";
|
||||
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
|
||||
import { blockMenuContainerStyle } from "../style";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
|
||||
export const PaginatedIntegrationList = () => {
|
||||
const { setIntegration } = useBlockMenuContext();
|
||||
const { setIntegration } = useBlockMenuStore();
|
||||
const {
|
||||
allProviders: providers,
|
||||
providersLoading,
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import React from "react";
|
||||
import { IntegrationChip } from "../IntegrationChip";
|
||||
import { Block } from "../Block";
|
||||
import { DefaultStateType, useBlockMenuContext } from "../block-menu-provider";
|
||||
import { useSuggestionContent } from "./useSuggestionContent";
|
||||
import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
|
||||
import { blockMenuContainerStyle } from "../style";
|
||||
import { useNodeStore } from "../../../stores/nodeStore";
|
||||
import { useBlockMenuStore } from "../../../stores/blockMenuStore";
|
||||
import { DefaultStateType } from "../types";
|
||||
|
||||
export const SuggestionContent = () => {
|
||||
const { setIntegration, setDefaultState } = useBlockMenuContext();
|
||||
const { setIntegration, setDefaultState } = useBlockMenuStore();
|
||||
const { data, isLoading, isError, error, refetch } = useSuggestionContent();
|
||||
const addBlock = useNodeStore((state) => state.addBlock);
|
||||
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, ReactNode, useContext, useState } from "react";
|
||||
|
||||
export enum DefaultStateType {
|
||||
SUGGESTION = "suggestion",
|
||||
ALL_BLOCKS = "all_blocks",
|
||||
INPUT_BLOCKS = "input_blocks",
|
||||
ACTION_BLOCKS = "action_blocks",
|
||||
OUTPUT_BLOCKS = "output_blocks",
|
||||
INTEGRATIONS = "integrations",
|
||||
MARKETPLACE_AGENTS = "marketplace_agents",
|
||||
MY_AGENTS = "my_agents",
|
||||
}
|
||||
|
||||
interface BlockMenuContextType {
|
||||
searchQuery: string;
|
||||
setSearchQuery: React.Dispatch<React.SetStateAction<string>>;
|
||||
searchId: string | undefined;
|
||||
setSearchId: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
defaultState: DefaultStateType;
|
||||
setDefaultState: React.Dispatch<React.SetStateAction<DefaultStateType>>;
|
||||
integration: string | undefined;
|
||||
setIntegration: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
}
|
||||
|
||||
export const BlockMenuContext = createContext<BlockMenuContextType>(
|
||||
{} as BlockMenuContextType,
|
||||
);
|
||||
|
||||
interface BlockMenuStateProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export function BlockMenuStateProvider({
|
||||
children,
|
||||
}: BlockMenuStateProviderProps) {
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [searchId, setSearchId] = useState<string | undefined>(undefined);
|
||||
const [defaultState, setDefaultState] = useState<DefaultStateType>(
|
||||
DefaultStateType.SUGGESTION,
|
||||
);
|
||||
const [integration, setIntegration] = useState<string | undefined>(undefined);
|
||||
|
||||
return (
|
||||
<BlockMenuContext.Provider
|
||||
value={{
|
||||
searchQuery,
|
||||
setSearchQuery,
|
||||
searchId,
|
||||
setSearchId,
|
||||
defaultState,
|
||||
setDefaultState,
|
||||
integration,
|
||||
setIntegration,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</BlockMenuContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export function useBlockMenuContext(): BlockMenuContextType {
|
||||
const context = useContext(BlockMenuContext);
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
"useBlockMenuContext must be used within a BlockMenuStateProvider",
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export enum DefaultStateType {
|
||||
SUGGESTION = "suggestion",
|
||||
ALL_BLOCKS = "all_blocks",
|
||||
INPUT_BLOCKS = "input_blocks",
|
||||
ACTION_BLOCKS = "action_blocks",
|
||||
OUTPUT_BLOCKS = "output_blocks",
|
||||
INTEGRATIONS = "integrations",
|
||||
MARKETPLACE_AGENTS = "marketplace_agents",
|
||||
MY_AGENTS = "my_agents",
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { create } from "zustand";
|
||||
import { DefaultStateType } from "../components/NewBlockMenu/types";
|
||||
|
||||
type BlockMenuStore = {
|
||||
searchQuery: string;
|
||||
searchId: string | undefined;
|
||||
defaultState: DefaultStateType;
|
||||
integration: string | undefined;
|
||||
|
||||
setSearchQuery: (query: string) => void;
|
||||
setSearchId: (id: string | undefined) => void;
|
||||
setDefaultState: (state: DefaultStateType) => void;
|
||||
setIntegration: (integration: string | undefined) => void;
|
||||
reset: () => void;
|
||||
};
|
||||
|
||||
export const useBlockMenuStore = create<BlockMenuStore>((set) => ({
|
||||
searchQuery: "",
|
||||
searchId: undefined,
|
||||
defaultState: DefaultStateType.SUGGESTION,
|
||||
integration: undefined,
|
||||
|
||||
setSearchQuery: (query) => set({ searchQuery: query }),
|
||||
setSearchId: (id) => set({ searchId: id }),
|
||||
setDefaultState: (state) => set({ defaultState: state }),
|
||||
setIntegration: (integration) => set({ integration }),
|
||||
reset: () =>
|
||||
set({
|
||||
searchQuery: "",
|
||||
searchId: undefined,
|
||||
defaultState: DefaultStateType.SUGGESTION,
|
||||
integration: undefined,
|
||||
}),
|
||||
}));
|
||||
Reference in New Issue
Block a user