fix: update LANGFLOW_COMPONENTS_PATH env variable behavior (#5700)

* Refactor directory_reader.py to simplify file filtering logic

* Refactor flowSidebarComponent to filter out bundles and custom components in CategoryGroup

* [autofix.ci] apply automated fixes

* refactor: Improve file filtering in DirectoryReader

This commit improves the file filtering logic in the DirectoryReader class. Previously, it only excluded files that started with "__" and included all files that were not in a "deactivated" directory. Now, it also considers the depth of the file relative to the safe path. Only files that are one or two levels deep are included in the file list.

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
anovazzi1 2025-01-20 22:47:19 -03:00 • committed by GitHub
commit dbd2bd9375
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 63 additions and 58 deletions

View file

@ -9,6 +9,8 @@ from loguru import logger
from langflow.custom import Component from langflow.custom import Component
MAX_DEPTH = 2
class CustomComponentPathValueError(ValueError): class CustomComponentPathValueError(ValueError):
pass pass
@ -135,12 +137,11 @@ class DirectoryReader:
if "deactivated" in file_path.parent.name: if "deactivated" in file_path.parent.name:
continue continue
# The other condtion is that it should be # Calculate the depth of the file relative to the safe path
# in the safe_path/[folder]/[file].py format relative_depth = len(file_path.relative_to(safe_path_obj).parts)
# any folders below [folder] will be ignored
# basically the parent folder of the file should be a # Only include files that are one or two levels deep
# folder in the safe_path if relative_depth <= MAX_DEPTH and file_path.is_file() and not file_path.name.startswith("__"):
if file_path.is_file() and file_path.parent.parent == safe_path_obj and not file_path.name.startswith("__"):
file_list.append(str(file_path)) file_list.append(str(file_path))
return file_list return file_list

View file

@ -3,6 +3,7 @@ import {
SidebarGroupContent, SidebarGroupContent,
SidebarMenu, SidebarMenu,
} from "@/components/ui/sidebar"; } from "@/components/ui/sidebar";
import { SIDEBAR_BUNDLES } from "@/utils/styleUtils";
import { memo } from "react"; import { memo } from "react";
import { CategoryGroupProps } from "../../types"; import { CategoryGroupProps } from "../../types";
import { CategoryDisclosure } from "../categoryDisclouse"; import { CategoryDisclosure } from "../categoryDisclouse";
@ -23,20 +24,42 @@ export const CategoryGroup = memo(function CategoryGroup({
<SidebarGroup className="p-3"> <SidebarGroup className="p-3">
<SidebarGroupContent> <SidebarGroupContent>
<SidebarMenu> <SidebarMenu>
{CATEGORIES.toSorted( {Object.entries(dataFilter)
(a, b) => .filter(
(search !== "" ? sortedCategories : CATEGORIES).findIndex( ([categoryName, items]) =>
(value) => value === a.name, // filter out bundles
) - !SIDEBAR_BUNDLES.some((cat) => cat.name === categoryName) &&
(search !== "" ? sortedCategories : CATEGORIES).findIndex( categoryName !== "custom_component" &&
(value) => value === b.name, Object.keys(items).length > 0,
), )
).map( .sort(([aName], [bName]) => {
(item) => const categoryList =
dataFilter[item.name] && search !== ""
Object.keys(dataFilter[item.name]).length > 0 && ( ? sortedCategories
: CATEGORIES.map((c) => c.name);
const aIndex = categoryList.indexOf(aName);
const bIndex = categoryList.indexOf(bName);
// If neither is in CATEGORIES, keep their relative order
if (aIndex === -1 && bIndex === -1) return 0;
// If only a is not in CATEGORIES, put it after b
if (aIndex === -1) return 1;
// If only b is not in CATEGORIES, put it after a
if (bIndex === -1) return -1;
// If both are in CATEGORIES, sort by their index
return aIndex - bIndex;
})
.map(([categoryName]) => {
const item = CATEGORIES.find(
(cat) => cat.name === categoryName,
) ?? {
name: categoryName,
icon: "folder",
display_name: categoryName,
};
return (
<CategoryDisclosure <CategoryDisclosure
key={item.name} key={categoryName}
item={item} item={item}
openCategories={openCategories} openCategories={openCategories}
setOpenCategories={setOpenCategories} setOpenCategories={setOpenCategories}
@ -46,8 +69,8 @@ export const CategoryGroup = memo(function CategoryGroup({
onDragStart={onDragStart} onDragStart={onDragStart}
sensitiveSort={sensitiveSort} sensitiveSort={sensitiveSort}
/> />
), );
)} })}
</SidebarMenu> </SidebarMenu>
</SidebarGroupContent> </SidebarGroupContent>
</SidebarGroup> </SidebarGroup>

View file

@ -120,19 +120,12 @@ export function FlowSidebarComponent() {
const sortedCategories = useMemo(() => { const sortedCategories = useMemo(() => {
if (!searchResults || !searchFilteredData) return []; if (!searchResults || !searchFilteredData) return [];
return Object.keys(searchFilteredData) return Object.keys(searchFilteredData).toSorted((a, b) =>
.filter( searchResults.fuseCategories.indexOf(b) <
(category) => searchResults.fuseCategories.indexOf(a)
Object.keys(searchFilteredData[category]).length > 0 && ? 1
(CATEGORIES.find((c) => c.name === category) || : -1,
BUNDLES.find((b) => b.name === category)), );
)
.toSorted((a, b) =>
searchResults.fuseCategories.indexOf(b) <
searchResults.fuseCategories.indexOf(a)
? 1
: -1,
);
}, [searchResults, searchFilteredData, CATEGORIES, BUNDLES]); }, [searchResults, searchFilteredData, CATEGORIES, BUNDLES]);
const finalFilteredData = useMemo(() => { const finalFilteredData = useMemo(() => {
@ -305,16 +298,6 @@ export function FlowSidebarComponent() {
[dataFilter], [dataFilter],
); );
const hasCategoryItems = useMemo(
() =>
CATEGORIES.some(
(item) =>
dataFilter[item.name] &&
Object.keys(dataFilter[item.name]).length > 0,
),
[dataFilter],
);
return ( return (
<Sidebar <Sidebar
collapsible="offcanvas" collapsible="offcanvas"
@ -342,20 +325,18 @@ export function FlowSidebarComponent() {
<SidebarContent> <SidebarContent>
{hasResults ? ( {hasResults ? (
<> <>
{hasCategoryItems && ( <CategoryGroup
<CategoryGroup dataFilter={dataFilter}
dataFilter={dataFilter} sortedCategories={sortedCategories}
sortedCategories={sortedCategories} CATEGORIES={CATEGORIES}
CATEGORIES={CATEGORIES} openCategories={openCategories}
openCategories={openCategories} setOpenCategories={setOpenCategories}
setOpenCategories={setOpenCategories} search={search}
search={search} nodeColors={nodeColors}
nodeColors={nodeColors} chatInputAdded={chatInputAdded}
chatInputAdded={chatInputAdded} onDragStart={onDragStart}
onDragStart={onDragStart} sensitiveSort={sensitiveSort}
sensitiveSort={sensitiveSort} />
/>
)}
{hasBundleItems && ( {hasBundleItems && (
<MemoizedSidebarGroup <MemoizedSidebarGroup
BUNDLES={BUNDLES} BUNDLES={BUNDLES}