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, "show": true,
"title_case": false, "title_case": false,
"type": "code", "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": { "function_calling_llm": {
"advanced": true, "advanced": true,
@ -769,6 +769,25 @@
"type": "bool", "type": "bool",
"value": false "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": { "share_crew": {
"advanced": true, "advanced": true,
"display_name": "Share Crew", "display_name": "Share Crew",

View file

@ -380,7 +380,7 @@
"show": true, "show": true,
"title_case": false, "title_case": false,
"type": "code", "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": { "function_calling_llm": {
"advanced": true, "advanced": true,
@ -466,6 +466,25 @@
"type": "bool", "type": "bool",
"value": false "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": { "share_crew": {
"advanced": true, "advanced": true,
"display_name": "Share Crew", "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": { "node_modules/@clack/prompts/node_modules/is-unicode-supported": {
"version": "1.3.0", "version": "1.3.0",
"extraneous": true,
"inBundle": true, "inBundle": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {

View file

@ -70,8 +70,6 @@ const SideBarFoldersButtonsComponent = ({
const urlWithoutPath = const urlWithoutPath =
pathname.split("/").length < (ENABLE_CUSTOM_PARAM ? 5 : 4); pathname.split("/").length < (ENABLE_CUSTOM_PARAM ? 5 : 4);
const myCollectionId = useFolderStore((state) => state.myCollectionId); const myCollectionId = useFolderStore((state) => state.myCollectionId);
const folderIdDragging = useFolderStore((state) => state.folderIdDragging);
const checkPathName = (itemId: string) => { const checkPathName = (itemId: string) => {
if (urlWithoutPath && itemId === myCollectionId) { if (urlWithoutPath && itemId === myCollectionId) {
return true; 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 { useLocation } from "react-router-dom";
import { FolderType } from "../../pages/MainPage/entities"; import { FolderType } from "../../pages/MainPage/entities";
import SideBarFoldersButtonsComponent from "./components/sideBarFolderButtons"; import SideBarFoldersButtonsComponent from "./components/sideBarFolderButtons";
@ -17,13 +15,6 @@ export default function FolderSidebarNav({
...props ...props
}: SidebarNavProps) { }: SidebarNavProps) {
const location = useLocation(); const location = useLocation();
const pathname = location.pathname;
const folders = useFolderStore((state) => state.folders);
const isPending = !!useIsFetching({
queryKey: ["useGetFolders"],
exact: false,
});
return ( return (
<SideBarFoldersButtonsComponent <SideBarFoldersButtonsComponent

View file

@ -68,7 +68,7 @@ const CustomInputPopover = ({
<div <div
data-testid={`anchor-${id}`} data-testid={`anchor-${id}`}
className={cn( 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 && "min-h-7 p-0",
editNode && disabled && "min-h-5 border-muted p-0", editNode && disabled && "min-h-5 border-muted p-0",
disabled && "bg-muted text-muted", disabled && "bg-muted text-muted",

View file

@ -22,9 +22,9 @@ export default function PageLayout({
const navigate = useCustomNavigate(); const navigate = useCustomNavigate();
return ( 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="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 /> <CustomBanner />
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-2"> <div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-2">
<div className="flex w-full flex-col"> <div className="flex w-full flex-col">
@ -55,8 +55,10 @@ export default function PageLayout({
<div className="flex-shrink-0">{button && button}</div> <div className="flex-shrink-0">{button && button}</div>
</div> </div>
</div> </div>
<Separator className="my-6 flex" /> <div className="flex shrink-0 px-6">
{children} <Separator className="flex" />
</div>
<div className="flex flex-1 p-6 pt-7">{children}</div>
</div> </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 { useLocation } from "react-router-dom";
import { cn } from "../../utils/utils"; import {
import HorizontalScrollFadeComponent from "../horizontalScrollFadeComponent"; Sidebar,
import SideBarButtonsComponent from "./components/sideBarButtons"; SidebarContent,
SidebarGroup,
SidebarGroupContent,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
} from "../ui/sidebar";
type SidebarNavProps = { type SideBarButtonsComponentProps = {
items: { items: {
href?: string; href?: string;
title: string; title: string;
icon: React.ReactNode; icon: React.ReactNode;
}[]; }[];
className?: string; handleOpenNewFolderModal?: () => void;
}; };
export default function SidebarNav({ const SideBarButtonsComponent = ({ items }: SideBarButtonsComponentProps) => {
className,
items,
...props
}: SidebarNavProps) {
const location = useLocation(); const location = useLocation();
const pathname = location.pathname; const pathname = location.pathname;
const isMobile = useIsMobile();
return ( return (
<nav className={cn(className)} {...props}> <Sidebar collapsible={isMobile ? "icon" : "none"} className="border-none">
<HorizontalScrollFadeComponent> <SidebarContent className="pr-6">
<SideBarButtonsComponent items={items} pathname={pathname} /> <SidebarGroup>
</HorizontalScrollFadeComponent> <SidebarGroupContent>
</nav> <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; open: boolean;
setOpen: (open: boolean) => void; setOpen: (open: boolean) => void;
toggleSidebar: () => void; toggleSidebar: () => void;
defaultOpen: boolean;
}; };
const SidebarContext = React.createContext<SidebarContext | null>(null); const SidebarContext = React.createContext<SidebarContext | null>(null);
@ -114,8 +115,9 @@ const SidebarProvider = React.forwardRef<
open, open,
setOpen, setOpen,
toggleSidebar, toggleSidebar,
defaultOpen,
}), }),
[state, open, setOpen, toggleSidebar], [state, open, setOpen, toggleSidebar, defaultOpen],
); );
return ( return (
@ -164,29 +166,30 @@ const Sidebar = React.forwardRef<
}, },
ref, ref,
) => { ) => {
const { state, setOpen } = useSidebar(); const { state, setOpen, defaultOpen } = useSidebar();
React.useEffect(() => { React.useEffect(() => {
if (collapsible === "none") { if (collapsible === "none") {
console.log("collapsible === none");
setOpen(true); setOpen(true);
} else {
setOpen(defaultOpen);
} }
}, [collapsible]); }, [collapsible]);
if (collapsible === "none") { if (collapsible === "none") {
return ( return (
<div <div
className={cn( className={cn("group flex h-full flex-col")}
"group flex h-full w-[--sidebar-width] flex-col bg-background text-foreground",
className,
)}
data-side={side} data-side={side}
ref={ref} ref={ref}
{...props} {...props}
> >
<div <div
data-sidebar="sidebar" 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} {children}
</div> </div>

View file

@ -1,4 +1,5 @@
import FolderSidebarNav from "@/components/folderSidebarComponent"; import FolderSidebarNav from "@/components/folderSidebarComponent";
import { SidebarProvider } from "@/components/ui/sidebar";
import { useDeleteFolders } from "@/controllers/API/queries/folders"; import { useDeleteFolders } from "@/controllers/API/queries/folders";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate"; import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { track } from "@/customization/utils/analytics"; import { track } from "@/customization/utils/analytics";
@ -80,7 +81,8 @@ export default function OldHomePage(): JSX.Element {
return ( return (
<> <>
<div className="flex h-full w-full space-y-8 md:flex-col lg:flex-row lg:space-y-0"> <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"> <SidebarProvider>
<aside className="hidden h-full w-fit flex-col space-y-6 px-4 lg:flex">
<FolderSidebarNav <FolderSidebarNav
handleChangeFolder={(id: string) => { handleChangeFolder={(id: string) => {
navigate(`all/folder/${id}`); navigate(`all/folder/${id}`);
@ -115,6 +117,7 @@ export default function OldHomePage(): JSX.Element {
<Outlet /> <Outlet />
</div> </div>
</PageLayout> </PageLayout>
</SidebarProvider>
</div> </div>
<ModalsComponent <ModalsComponent
openModal={openModal} openModal={openModal}

View file

@ -86,11 +86,32 @@ const HomePage = ({ type }) => {
className="flex h-full w-full flex-col overflow-y-auto" className="flex h-full w-full flex-col overflow-y-auto"
data-testid="cards-wrapper" data-testid="cards-wrapper"
> >
<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 />} {ENABLE_DATASTAX_LANGFLOW && <CustomBanner />}
{/* mt-10 to mt-8 for Datastax LF */} {/* 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-1 flex-col justify-start px-5 pt-10">
<div className="flex flex-col justify-start xl:container"> <div className="flex flex-col justify-start">
<HeaderComponent <HeaderComponent
folderName={folderName} folderName={folderName}
flowType={flowType} flowType={flowType}
@ -175,6 +196,7 @@ const HomePage = ({ type }) => {
</div> </div>
)} )}
</div> </div>
</div>
<ModalsComponent <ModalsComponent
openModal={newProjectModal} openModal={newProjectModal}

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

View file

@ -142,10 +142,10 @@ export const GeneralPage = () => {
} }
return ( 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 /> <GeneralPageHeaderComponent />
<div className="grid gap-6"> <div className="flex w-full flex-col gap-6">
{ENABLE_PROFILE_ICONS && ( {ENABLE_PROFILE_ICONS && (
<ProfilePictureFormComponent <ProfilePictureFormComponent
profilePicture={profilePicture} profilePicture={profilePicture}