fix: refactor settings page to use new sidebar and fix old bugs (#4545)

* Updated settings page sidebar to new sidebar

* Updated old home page to still work

* Fix padding on collapsed sidebar

* Fix able to drag on input component

* Fixed pagination position on big screens

---------

Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
This commit is contained in:
Lucas Oliveira 2024-11-12 23:28:12 -03:00 • committed by GitHub
commit e68c21a7af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 272 additions and 225 deletions

File diff suppressed because one or more lines are too long

View file

@ -683,7 +683,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from crewai import Crew, Process\n\nfrom langflow.base.agents.crewai.crew import BaseCrewComponent\nfrom langflow.io import HandleInput\n\n\nclass HierarchicalCrewComponent(BaseCrewComponent):\n display_name: str = \"Hierarchical Crew\"\n description: str = (\n \"Represents a group of agents, defining how they should collaborate and the tasks they should perform.\"\n )\n documentation: str = \"https://docs.crewai.com/how-to/Hierarchical/\"\n icon = \"CrewAI\"\n\n inputs = [\n *BaseCrewComponent._base_inputs,\n HandleInput(name=\"agents\", display_name=\"Agents\", input_types=[\"Agent\"], is_list=True),\n HandleInput(name=\"tasks\", display_name=\"Tasks\", input_types=[\"HierarchicalTask\"], is_list=True),\n HandleInput(name=\"manager_llm\", display_name=\"Manager LLM\", input_types=[\"LanguageModel\"], required=False),\n HandleInput(name=\"manager_agent\", display_name=\"Manager Agent\", input_types=[\"Agent\"], required=False),\n ]\n\n def build_crew(self) -> Crew:\n tasks, agents = self.get_tasks_and_agents()\n return Crew(\n agents=agents,\n tasks=tasks,\n process=Process.hierarchical,\n verbose=self.verbose,\n memory=self.memory,\n cache=self.use_cache,\n max_rpm=self.max_rpm,\n share_crew=self.share_crew,\n function_calling_llm=self.function_calling_llm,\n manager_agent=self.manager_agent,\n manager_llm=self.manager_llm,\n step_callback=self.get_step_callback(),\n task_callback=self.get_task_callback(),\n )\n"
"value": "import os\n\nfrom crewai import Crew, Process\n\nfrom langflow.base.agents.crewai.crew import BaseCrewComponent\nfrom langflow.io import HandleInput, SecretStrInput\n\n\nclass HierarchicalCrewComponent(BaseCrewComponent):\n display_name: str = \"Hierarchical Crew\"\n description: str = (\n \"Represents a group of agents, defining how they should collaborate and the tasks they should perform.\"\n )\n documentation: str = \"https://docs.crewai.com/how-to/Hierarchical/\"\n icon = \"CrewAI\"\n\n inputs = [\n *BaseCrewComponent._base_inputs,\n HandleInput(name=\"agents\", display_name=\"Agents\", input_types=[\"Agent\"], is_list=True),\n HandleInput(name=\"tasks\", display_name=\"Tasks\", input_types=[\"HierarchicalTask\"], is_list=True),\n HandleInput(name=\"manager_llm\", display_name=\"Manager LLM\", input_types=[\"LanguageModel\"], required=False),\n HandleInput(name=\"manager_agent\", display_name=\"Manager Agent\", input_types=[\"Agent\"], required=False),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n value=\"OPENAI_API_KEY\",\n ),\n ]\n\n def build_crew(self) -> Crew:\n tasks, agents = self.get_tasks_and_agents()\n\n # Set the OpenAI API Key\n if self.openai_api_key:\n os.environ[\"OPENAI_API_KEY\"] = self.openai_api_key\n\n return Crew(\n agents=agents,\n tasks=tasks,\n process=Process.hierarchical,\n verbose=self.verbose,\n memory=self.memory,\n cache=self.use_cache,\n max_rpm=self.max_rpm,\n share_crew=self.share_crew,\n function_calling_llm=self.function_calling_llm,\n manager_agent=self.manager_agent,\n manager_llm=self.manager_llm,\n step_callback=self.get_step_callback(),\n task_callback=self.get_task_callback(),\n )\n"
},
"function_calling_llm": {
"advanced": true,
@ -769,6 +769,25 @@
"type": "bool",
"value": false
},
"openai_api_key": {
"_input_type": "SecretStrInput",
"advanced": false,
"display_name": "OpenAI API Key",
"dynamic": false,
"info": "The OpenAI API Key to use for the OpenAI model.",
"input_types": [
"Message"
],
"load_from_db": true,
"name": "openai_api_key",
"password": true,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": "OPENAI_API_KEY"
},
"share_crew": {
"advanced": true,
"display_name": "Share Crew",

View file

@ -380,7 +380,7 @@
"show": true,
"title_case": false,
"type": "code",
"value": "from crewai import Crew, Process\n\nfrom langflow.base.agents.crewai.crew import BaseCrewComponent\nfrom langflow.io import HandleInput\n\n\nclass HierarchicalCrewComponent(BaseCrewComponent):\n display_name: str = \"Hierarchical Crew\"\n description: str = (\n \"Represents a group of agents, defining how they should collaborate and the tasks they should perform.\"\n )\n documentation: str = \"https://docs.crewai.com/how-to/Hierarchical/\"\n icon = \"CrewAI\"\n\n inputs = [\n *BaseCrewComponent._base_inputs,\n HandleInput(name=\"agents\", display_name=\"Agents\", input_types=[\"Agent\"], is_list=True),\n HandleInput(name=\"tasks\", display_name=\"Tasks\", input_types=[\"HierarchicalTask\"], is_list=True),\n HandleInput(name=\"manager_llm\", display_name=\"Manager LLM\", input_types=[\"LanguageModel\"], required=False),\n HandleInput(name=\"manager_agent\", display_name=\"Manager Agent\", input_types=[\"Agent\"], required=False),\n ]\n\n def build_crew(self) -> Crew:\n tasks, agents = self.get_tasks_and_agents()\n return Crew(\n agents=agents,\n tasks=tasks,\n process=Process.hierarchical,\n verbose=self.verbose,\n memory=self.memory,\n cache=self.use_cache,\n max_rpm=self.max_rpm,\n share_crew=self.share_crew,\n function_calling_llm=self.function_calling_llm,\n manager_agent=self.manager_agent,\n manager_llm=self.manager_llm,\n step_callback=self.get_step_callback(),\n task_callback=self.get_task_callback(),\n )\n"
"value": "import os\n\nfrom crewai import Crew, Process\n\nfrom langflow.base.agents.crewai.crew import BaseCrewComponent\nfrom langflow.io import HandleInput, SecretStrInput\n\n\nclass HierarchicalCrewComponent(BaseCrewComponent):\n display_name: str = \"Hierarchical Crew\"\n description: str = (\n \"Represents a group of agents, defining how they should collaborate and the tasks they should perform.\"\n )\n documentation: str = \"https://docs.crewai.com/how-to/Hierarchical/\"\n icon = \"CrewAI\"\n\n inputs = [\n *BaseCrewComponent._base_inputs,\n HandleInput(name=\"agents\", display_name=\"Agents\", input_types=[\"Agent\"], is_list=True),\n HandleInput(name=\"tasks\", display_name=\"Tasks\", input_types=[\"HierarchicalTask\"], is_list=True),\n HandleInput(name=\"manager_llm\", display_name=\"Manager LLM\", input_types=[\"LanguageModel\"], required=False),\n HandleInput(name=\"manager_agent\", display_name=\"Manager Agent\", input_types=[\"Agent\"], required=False),\n SecretStrInput(\n name=\"openai_api_key\",\n display_name=\"OpenAI API Key\",\n info=\"The OpenAI API Key to use for the OpenAI model.\",\n value=\"OPENAI_API_KEY\",\n ),\n ]\n\n def build_crew(self) -> Crew:\n tasks, agents = self.get_tasks_and_agents()\n\n # Set the OpenAI API Key\n if self.openai_api_key:\n os.environ[\"OPENAI_API_KEY\"] = self.openai_api_key\n\n return Crew(\n agents=agents,\n tasks=tasks,\n process=Process.hierarchical,\n verbose=self.verbose,\n memory=self.memory,\n cache=self.use_cache,\n max_rpm=self.max_rpm,\n share_crew=self.share_crew,\n function_calling_llm=self.function_calling_llm,\n manager_agent=self.manager_agent,\n manager_llm=self.manager_llm,\n step_callback=self.get_step_callback(),\n task_callback=self.get_task_callback(),\n )\n"
},
"function_calling_llm": {
"advanced": true,
@ -466,6 +466,25 @@
"type": "bool",
"value": false
},
"openai_api_key": {
"_input_type": "SecretStrInput",
"advanced": false,
"display_name": "OpenAI API Key",
"dynamic": false,
"info": "The OpenAI API Key to use for the OpenAI model.",
"input_types": [
"Message"
],
"load_from_db": true,
"name": "openai_api_key",
"password": true,
"placeholder": "",
"required": false,
"show": true,
"title_case": false,
"type": "str",
"value": "OPENAI_API_KEY"
},
"share_crew": {
"advanced": true,
"display_name": "Share Crew",

File diff suppressed because one or more lines are too long

View file

@ -835,7 +835,6 @@
},
"node_modules/@clack/prompts/node_modules/is-unicode-supported": {
"version": "1.3.0",
"extraneous": true,
"inBundle": true,
"license": "MIT",
"engines": {

View file

@ -70,8 +70,6 @@ const SideBarFoldersButtonsComponent = ({
const urlWithoutPath =
pathname.split("/").length < (ENABLE_CUSTOM_PARAM ? 5 : 4);
const myCollectionId = useFolderStore((state) => state.myCollectionId);
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
const checkPathName = (itemId: string) => {
if (urlWithoutPath && itemId === myCollectionId) {
return true;

View file

@ -1,5 +1,3 @@
import { useFolderStore } from "@/stores/foldersStore";
import { useIsFetching } from "@tanstack/react-query";
import { useLocation } from "react-router-dom";
import { FolderType } from "../../pages/MainPage/entities";
import SideBarFoldersButtonsComponent from "./components/sideBarFolderButtons";
@ -17,13 +15,6 @@ export default function FolderSidebarNav({
...props
}: SidebarNavProps) {
const location = useLocation();
const pathname = location.pathname;
const folders = useFolderStore((state) => state.folders);
const isPending = !!useIsFetching({
queryKey: ["useGetFolders"],
exact: false,
});
return (
<SideBarFoldersButtonsComponent

View file

@ -68,7 +68,7 @@ const CustomInputPopover = ({
<div
data-testid={`anchor-${id}`}
className={cn(
"primary-input border-1 flex h-full min-h-[2.375rem] flex-wrap items-center px-3",
"primary-input noflow nowheel nopan nodelete nodrag border-1 flex h-full min-h-[2.375rem] cursor-default flex-wrap items-center px-3",
editNode && "min-h-7 p-0",
editNode && disabled && "min-h-5 border-muted p-0",
disabled && "bg-muted text-muted",

View file

@ -22,9 +22,9 @@ export default function PageLayout({
const navigate = useCustomNavigate();
return (
<div className="flex w-full flex-1 flex-col justify-between overflow-auto bg-background px-6 pt-10">
<div className="flex w-full flex-1 flex-col justify-between overflow-auto overflow-x-hidden bg-background">
<div className="mx-auto flex w-full max-w-[1440px] flex-1 flex-col">
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-4 p-6 pt-10">
<CustomBanner />
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-2">
<div className="flex w-full flex-col">
@ -55,8 +55,10 @@ export default function PageLayout({
<div className="flex-shrink-0">{button && button}</div>
</div>
</div>
<Separator className="my-6 flex" />
{children}
<div className="flex shrink-0 px-6">
<Separator className="flex" />
</div>
<div className="flex flex-1 p-6 pt-7">{children}</div>
</div>
</div>
);

View file

@ -1,43 +0,0 @@
import { CustomLink } from "@/customization/components/custom-link";
import { cn } from "../../../../utils/utils";
import { buttonVariants } from "../../../ui/button";
type SideBarButtonsComponentProps = {
items: {
href?: string;
title: string;
icon: React.ReactNode;
}[];
pathname: string;
handleOpenNewFolderModal?: () => void;
};
const SideBarButtonsComponent = ({
items,
pathname,
}: SideBarButtonsComponentProps) => {
return (
<div className="flex gap-2 overflow-auto lg:h-[70vh] lg:flex-col">
{items.map((item, index) => (
<CustomLink key={index} to={item.href!}>
<div
key={item.title}
data-testid={`sidebar-nav-${item.title}`}
className={cn(
buttonVariants({ variant: "ghost" }),
item.href && pathname.endsWith(item.href)
? "border border-border bg-muted hover:bg-muted"
: "border border-transparent hover:border-border hover:bg-transparent",
"flex w-full shrink-0 justify-start gap-4",
)}
>
{item.icon}
<span className="block max-w-full truncate opacity-100">
{item.title}
</span>
</div>
</CustomLink>
))}
</div>
);
};
export default SideBarButtonsComponent;

View file

@ -1,30 +1,62 @@
import { CustomLink } from "@/customization/components/custom-link";
import { useIsMobile } from "@/hooks/use-mobile";
import { useLocation } from "react-router-dom";
import { cn } from "../../utils/utils";
import HorizontalScrollFadeComponent from "../horizontalScrollFadeComponent";
import SideBarButtonsComponent from "./components/sideBarButtons";
import {
Sidebar,
SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "../ui/sidebar";
type SidebarNavProps = {
type SideBarButtonsComponentProps = {
items: {
href?: string;
title: string;
icon: React.ReactNode;
}[];
className?: string;
handleOpenNewFolderModal?: () => void;
};
export default function SidebarNav({
className,
items,
...props
}: SidebarNavProps) {
const SideBarButtonsComponent = ({ items }: SideBarButtonsComponentProps) => {
const location = useLocation();
const pathname = location.pathname;
const isMobile = useIsMobile();
return (
<nav className={cn(className)} {...props}>
<HorizontalScrollFadeComponent>
<SideBarButtonsComponent items={items} pathname={pathname} />
</HorizontalScrollFadeComponent>
</nav>
<Sidebar collapsible={isMobile ? "icon" : "none"} className="border-none">
<SidebarContent className="pr-6">
<SidebarGroup>
<SidebarGroupContent>
<SidebarMenu>
{items.map((item, index) => (
<SidebarMenuItem key={index}>
<CustomLink to={item.href!}>
<SidebarMenuButton
size="md"
isActive={
item.href ? pathname.endsWith(item.href) : false
}
data-testid={`sidebar-nav-${item.title}`}
tooltip={item.title}
>
{item.icon}
<span className="block max-w-full truncate">
{item.title}
</span>
</SidebarMenuButton>
</CustomLink>
</SidebarMenuItem>
))}
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
</Sidebar>
);
}
};
export default SideBarButtonsComponent;

View file

@ -28,6 +28,7 @@ type SidebarContext = {
open: boolean;
setOpen: (open: boolean) => void;
toggleSidebar: () => void;
defaultOpen: boolean;
};
const SidebarContext = React.createContext<SidebarContext | null>(null);
@ -114,8 +115,9 @@ const SidebarProvider = React.forwardRef<
open,
setOpen,
toggleSidebar,
defaultOpen,
}),
[state, open, setOpen, toggleSidebar],
[state, open, setOpen, toggleSidebar, defaultOpen],
);
return (
@ -164,29 +166,30 @@ const Sidebar = React.forwardRef<
},
ref,
) => {
const { state, setOpen } = useSidebar();
const { state, setOpen, defaultOpen } = useSidebar();
React.useEffect(() => {
if (collapsible === "none") {
console.log("collapsible === none");
setOpen(true);
} else {
setOpen(defaultOpen);
}
}, [collapsible]);
if (collapsible === "none") {
return (
<div
className={cn(
"group flex h-full w-[--sidebar-width] flex-col bg-background text-foreground",
className,
)}
className={cn("group flex h-full flex-col")}
data-side={side}
ref={ref}
{...props}
>
<div
data-sidebar="sidebar"
className="flex h-full w-full flex-col group-data-[side=left]:border-r group-data-[side=right]:border-l"
className={cn(
"group flex h-full w-[--sidebar-width] flex-col bg-background text-foreground group-data-[side=left]:border-r group-data-[side=right]:border-l",
className,
)}
>
{children}
</div>

View file

@ -1,4 +1,5 @@
import FolderSidebarNav from "@/components/folderSidebarComponent";
import { SidebarProvider } from "@/components/ui/sidebar";
import { useDeleteFolders } from "@/controllers/API/queries/folders";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { track } from "@/customization/utils/analytics";
@ -80,41 +81,43 @@ export default function OldHomePage(): JSX.Element {
return (
<>
<div className="flex h-full w-full space-y-8 md:flex-col lg:flex-row lg:space-y-0">
<aside className="hidden h-full w-fit flex-col space-y-6 border-r px-4 lg:flex">
<FolderSidebarNav
handleChangeFolder={(id: string) => {
navigate(`all/folder/${id}`);
}}
handleDeleteFolder={(item) => {
setFolderToEdit(item);
setOpenDeleteFolderModal(true);
}}
className="w-[20vw] max-w-[288px]"
/>
</aside>
<PageLayout
title={USER_PROJECTS_HEADER}
description={MY_COLLECTION_DESC}
button={
<div className="flex gap-2">
<DropdownButton
firstButtonName="New Project"
onFirstBtnClick={() => {
setOpenModal(true);
track("New Project Button Clicked");
}}
options={dropdownOptions}
plusButton={true}
dropdownOptions={false}
isFetchingFolders={isLoadingFolder}
/>
<SidebarProvider>
<aside className="hidden h-full w-fit flex-col space-y-6 px-4 lg:flex">
<FolderSidebarNav
handleChangeFolder={(id: string) => {
navigate(`all/folder/${id}`);
}}
handleDeleteFolder={(item) => {
setFolderToEdit(item);
setOpenDeleteFolderModal(true);
}}
className="w-[20vw] max-w-[288px]"
/>
</aside>
<PageLayout
title={USER_PROJECTS_HEADER}
description={MY_COLLECTION_DESC}
button={
<div className="flex gap-2">
<DropdownButton
firstButtonName="New Project"
onFirstBtnClick={() => {
setOpenModal(true);
track("New Project Button Clicked");
}}
options={dropdownOptions}
plusButton={true}
dropdownOptions={false}
isFetchingFolders={isLoadingFolder}
/>
</div>
}
>
<div className="relative h-full w-full flex-1">
<Outlet />
</div>
}
>
<div className="relative h-full w-full flex-1">
<Outlet />
</div>
</PageLayout>
</PageLayout>
</SidebarProvider>
</div>
<ModalsComponent
openModal={openModal}

View file

@ -86,94 +86,116 @@ const HomePage = ({ type }) => {
className="flex h-full w-full flex-col overflow-y-auto"
data-testid="cards-wrapper"
>
{ENABLE_DATASTAX_LANGFLOW && <CustomBanner />}
{/* mt-10 to mt-8 for Datastax LF */}
<div className="flex flex-1 flex-col justify-start px-5 pt-10">
<div className="flex flex-col justify-start xl:container">
<HeaderComponent
folderName={folderName}
flowType={flowType}
setFlowType={setFlowType}
view={view}
setView={setView}
setNewProjectModal={setNewProjectModal}
setSearch={onSearch}
isEmptyFolder={isEmptyFolder}
/>
{isEmptyFolder ? (
<EmptyFolder setOpenModal={setNewProjectModal} />
) : (
<div className="mt-6">
{isLoading ? (
view === "grid" ? (
<div className="mt-1 grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
<GridSkeleton />
<GridSkeleton />
</div>
) : (
<div className="flex flex-col">
<ListSkeleton />
<ListSkeleton />
</div>
)
) : data && data.pagination.total > 0 ? (
view === "grid" ? (
<div className="mt-1 grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
{data.flows.map((flow) => (
<GridComponent key={flow.id} flowData={flow} />
))}
</div>
) : (
<div className="flex flex-col">
{data.flows.map((flow) => (
<ListComponent key={flow.id} flowData={flow} />
))}
</div>
)
) : flowType === "flows" ? (
<div className="pt-2 text-center text-sm text-secondary-foreground">
No flows in this folder.{" "}
<a
onClick={() => setNewProjectModal(true)}
className="cursor-pointer underline"
>
Create a new flow
</a>
, or browse the store.
</div>
) : (
<div className="pt-2 text-center text-sm text-secondary-foreground">
No saved or custom components. Learn more about{" "}
<a
href="https://docs.langflow.org/components-custom-components"
target="_blank"
rel="noreferrer"
className="underline"
>
creating custom components
</a>
, or browse the store.
</div>
)}
</div>
)}
<div className="flex h-full w-full flex-col xl:container">
{/* TODO: Move to Datastax LF and update Icon */}
{/* <div className="mx-4 mt-10 flex flex-row items-center rounded-lg border border-purple-300 bg-purple-50 p-4 dark:border-purple-700 dark:bg-purple-950">
<ForwardedIconComponent
name="info"
className="mr-4 h-5 w-5 text-purple-500 dark:text-purple-400"
/>
<div className="text-sm">
DataStax Langflow is in public preview and is not suitable for
production. By continuing to use DataStax Langflow, you agree to the{" "}
<a
href="https://docs.shortlang.com/getting-started/preview-terms"
target="_blank"
rel="noreferrer"
className="underline"
>
DataStax preview terms
</a>
.
</div>
</div> */}
{ENABLE_DATASTAX_LANGFLOW && <CustomBanner />}
{/* mt-10 to mt-8 for Datastax LF */}
<div className="flex flex-1 flex-col justify-start px-5 pt-10">
<div className="flex flex-col justify-start">
<HeaderComponent
folderName={folderName}
flowType={flowType}
setFlowType={setFlowType}
view={view}
setView={setView}
setNewProjectModal={setNewProjectModal}
setSearch={onSearch}
isEmptyFolder={isEmptyFolder}
/>
{isEmptyFolder ? (
<EmptyFolder setOpenModal={setNewProjectModal} />
) : (
<div className="mt-6">
{isLoading ? (
view === "grid" ? (
<div className="mt-1 grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
<GridSkeleton />
<GridSkeleton />
</div>
) : (
<div className="flex flex-col">
<ListSkeleton />
<ListSkeleton />
</div>
)
) : data && data.pagination.total > 0 ? (
view === "grid" ? (
<div className="mt-1 grid grid-cols-1 gap-3 md:grid-cols-2 lg:grid-cols-3">
{data.flows.map((flow) => (
<GridComponent key={flow.id} flowData={flow} />
))}
</div>
) : (
<div className="flex flex-col">
{data.flows.map((flow) => (
<ListComponent key={flow.id} flowData={flow} />
))}
</div>
)
) : flowType === "flows" ? (
<div className="pt-2 text-center text-sm text-secondary-foreground">
No flows in this folder.{" "}
<a
onClick={() => setNewProjectModal(true)}
className="cursor-pointer underline"
>
Create a new flow
</a>
, or browse the store.
</div>
) : (
<div className="pt-2 text-center text-sm text-secondary-foreground">
No saved or custom components. Learn more about{" "}
<a
href="https://docs.langflow.org/components-custom-components"
target="_blank"
rel="noreferrer"
className="underline"
>
creating custom components
</a>
, or browse the store.
</div>
)}
</div>
)}
</div>
</div>
{!isLoading && !isEmptyFolder && data.pagination.total >= 10 && (
<div className="flex justify-end px-3 py-4">
<PaginatorComponent
pageIndex={data.pagination.page}
pageSize={data.pagination.size}
rowsCount={[10, 20, 50, 100]}
totalRowsCount={data.pagination.total}
paginate={handlePageChange}
pages={data.pagination.pages}
isComponent={flowType === "components"}
/>
</div>
)}
</div>
{!isLoading && !isEmptyFolder && data.pagination.total >= 10 && (
<div className="flex justify-end px-3 py-4">
<PaginatorComponent
pageIndex={data.pagination.page}
pageSize={data.pagination.size}
rowsCount={[10, 20, 50, 100]}
totalRowsCount={data.pagination.total}
paginate={handlePageChange}
pages={data.pagination.pages}
isComponent={flowType === "components"}
/>
</div>
)}
</div>
<ModalsComponent

View file

@ -1,10 +1,11 @@
import SideBarButtonsComponent from "@/components/sidebarComponent";
import { SidebarProvider } from "@/components/ui/sidebar";
import { ENABLE_PROFILE_ICONS } from "@/customization/feature-flags";
import useAuthStore from "@/stores/authStore";
import { useStoreStore } from "@/stores/storeStore";
import { Outlet } from "react-router-dom";
import ForwardedIconComponent from "../../components/genericIconComponent";
import PageLayout from "../../components/pageLayout";
import SidebarNav from "../../components/sidebarComponent";
export default function SettingsPage(): JSX.Element {
const autoLogin = useAuthStore((state) => state.autoLogin);
@ -80,16 +81,14 @@ export default function SettingsPage(): JSX.Element {
title="Settings"
description="Manage the general settings for Langflow."
>
<div className="flex w-full flex-1 space-y-8 overflow-hidden lg:flex-row lg:space-x-8 lg:space-y-0">
<aside className="flex h-full shrink-0 flex-col space-y-6 lg:w-[20vw]">
<SidebarNav items={sidebarNavItems} />
</aside>
<div className="flex h-full w-full flex-1 flex-col">
<div className="flex-1 pb-8">
<SidebarProvider width="15rem" defaultOpen={false}>
<SideBarButtonsComponent items={sidebarNavItems} />
<main className="flex flex-1 overflow-hidden">
<div className="flex flex-1 flex-col overflow-x-hidden pt-1">
<Outlet />
</div>
</div>
</div>
</main>
</SidebarProvider>
</PageLayout>
);
}

View file

@ -142,10 +142,10 @@ export const GeneralPage = () => {
}
return (
<div className="flex h-full w-full flex-col gap-6">
<div className="flex h-full w-full flex-col gap-6 overflow-x-hidden">
<GeneralPageHeaderComponent />
<div className="grid gap-6">
<div className="flex w-full flex-col gap-6">
{ENABLE_PROFILE_ICONS && (
<ProfilePictureFormComponent
profilePicture={profilePicture}