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:
parent
9c004e7646
commit
e68c21a7af
16 changed files with 272 additions and 225 deletions
File diff suppressed because one or more lines are too long
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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
1
src/frontend/package-lock.json
generated
1
src/frontend/package-lock.json
generated
|
|
@ -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": {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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,41 +81,43 @@ 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>
|
||||||
<FolderSidebarNav
|
<aside className="hidden h-full w-fit flex-col space-y-6 px-4 lg:flex">
|
||||||
handleChangeFolder={(id: string) => {
|
<FolderSidebarNav
|
||||||
navigate(`all/folder/${id}`);
|
handleChangeFolder={(id: string) => {
|
||||||
}}
|
navigate(`all/folder/${id}`);
|
||||||
handleDeleteFolder={(item) => {
|
}}
|
||||||
setFolderToEdit(item);
|
handleDeleteFolder={(item) => {
|
||||||
setOpenDeleteFolderModal(true);
|
setFolderToEdit(item);
|
||||||
}}
|
setOpenDeleteFolderModal(true);
|
||||||
className="w-[20vw] max-w-[288px]"
|
}}
|
||||||
/>
|
className="w-[20vw] max-w-[288px]"
|
||||||
</aside>
|
/>
|
||||||
<PageLayout
|
</aside>
|
||||||
title={USER_PROJECTS_HEADER}
|
<PageLayout
|
||||||
description={MY_COLLECTION_DESC}
|
title={USER_PROJECTS_HEADER}
|
||||||
button={
|
description={MY_COLLECTION_DESC}
|
||||||
<div className="flex gap-2">
|
button={
|
||||||
<DropdownButton
|
<div className="flex gap-2">
|
||||||
firstButtonName="New Project"
|
<DropdownButton
|
||||||
onFirstBtnClick={() => {
|
firstButtonName="New Project"
|
||||||
setOpenModal(true);
|
onFirstBtnClick={() => {
|
||||||
track("New Project Button Clicked");
|
setOpenModal(true);
|
||||||
}}
|
track("New Project Button Clicked");
|
||||||
options={dropdownOptions}
|
}}
|
||||||
plusButton={true}
|
options={dropdownOptions}
|
||||||
dropdownOptions={false}
|
plusButton={true}
|
||||||
isFetchingFolders={isLoadingFolder}
|
dropdownOptions={false}
|
||||||
/>
|
isFetchingFolders={isLoadingFolder}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="relative h-full w-full flex-1">
|
||||||
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
}
|
</PageLayout>
|
||||||
>
|
</SidebarProvider>
|
||||||
<div className="relative h-full w-full flex-1">
|
|
||||||
<Outlet />
|
|
||||||
</div>
|
|
||||||
</PageLayout>
|
|
||||||
</div>
|
</div>
|
||||||
<ModalsComponent
|
<ModalsComponent
|
||||||
openModal={openModal}
|
openModal={openModal}
|
||||||
|
|
|
||||||
|
|
@ -86,94 +86,116 @@ 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"
|
||||||
>
|
>
|
||||||
{ENABLE_DATASTAX_LANGFLOW && <CustomBanner />}
|
<div className="flex h-full w-full flex-col xl:container">
|
||||||
|
{/* TODO: Move to Datastax LF and update Icon */}
|
||||||
{/* mt-10 to mt-8 for Datastax LF */}
|
{/* <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">
|
||||||
<div className="flex flex-1 flex-col justify-start px-5 pt-10">
|
<ForwardedIconComponent
|
||||||
<div className="flex flex-col justify-start xl:container">
|
name="info"
|
||||||
<HeaderComponent
|
className="mr-4 h-5 w-5 text-purple-500 dark:text-purple-400"
|
||||||
folderName={folderName}
|
/>
|
||||||
flowType={flowType}
|
<div className="text-sm">
|
||||||
setFlowType={setFlowType}
|
DataStax Langflow is in public preview and is not suitable for
|
||||||
view={view}
|
production. By continuing to use DataStax Langflow, you agree to the{" "}
|
||||||
setView={setView}
|
<a
|
||||||
setNewProjectModal={setNewProjectModal}
|
href="https://docs.shortlang.com/getting-started/preview-terms"
|
||||||
setSearch={onSearch}
|
target="_blank"
|
||||||
isEmptyFolder={isEmptyFolder}
|
rel="noreferrer"
|
||||||
/>
|
className="underline"
|
||||||
{isEmptyFolder ? (
|
>
|
||||||
<EmptyFolder setOpenModal={setNewProjectModal} />
|
DataStax preview terms
|
||||||
) : (
|
</a>
|
||||||
<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>
|
||||||
|
</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>
|
</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>
|
</div>
|
||||||
|
|
||||||
<ModalsComponent
|
<ModalsComponent
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue