diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx
index 28e672bbb..b00576c35 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeInputField/index.tsx
@@ -125,7 +125,10 @@ export default function NodeInputField({
{proxy.id}}>
{
- {getCustomParameterTitle({ title, nodeId: data.id })}
+ {getCustomParameterTitle({
+ title,
+ isFlexView,
+ })}
}
@@ -134,7 +137,10 @@ export default function NodeInputField({
{
- {getCustomParameterTitle({ title, nodeId: data.id })}
+ {getCustomParameterTitle({
+ title,
+ isFlexView,
+ })}
}
diff --git a/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx b/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx
index 5cf4d1820..69e8175e8 100644
--- a/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx
+++ b/src/frontend/src/CustomNodes/GenericNode/components/NodeStatus/index.tsx
@@ -263,7 +263,7 @@ export default function NodeStatus({
size="sq"
className="pointer-events-none mr-1 flex h-[22px] w-10 justify-center rounded-[8px] bg-accent-pink text-accent-pink-foreground"
>
- BETA
+ Beta
)}
diff --git a/src/frontend/src/components/pageLayout/index.tsx b/src/frontend/src/components/pageLayout/index.tsx
index 271532c3c..b2336cb91 100644
--- a/src/frontend/src/components/pageLayout/index.tsx
+++ b/src/frontend/src/components/pageLayout/index.tsx
@@ -47,7 +47,7 @@ export default function PageLayout({
data-testid="mainpage_title"
>
{title}
- {betaIcon && BETA}
+ {betaIcon && Beta}
{description}
diff --git a/src/frontend/src/customization/components/custom-parameter.tsx b/src/frontend/src/customization/components/custom-parameter.tsx
index cd58c89b8..d357f9b55 100644
--- a/src/frontend/src/customization/components/custom-parameter.tsx
+++ b/src/frontend/src/customization/components/custom-parameter.tsx
@@ -1,6 +1,7 @@
import { ParameterRenderComponent } from "@/components/parameterRenderComponent";
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
import { APIClassType, InputFieldType } from "@/types/api";
+import { cn } from "@/utils/utils";
export function CustomParameterComponent({
handleOnNewValue,
@@ -40,18 +41,20 @@ export function CustomParameterComponent({
export function getCustomParameterTitle({
title,
- nodeId,
+ isFlexView,
}: {
title: string;
- nodeId: string;
+ isFlexView: boolean;
}) {
return (
-
- {title}
-
+
+
+ {title}
+
+
);
}
diff --git a/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx
index 04793b46e..2f5bd7602 100644
--- a/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/ParentDisclosureComponent/index.tsx
@@ -21,7 +21,7 @@ export default function ParentDisclosureComponent({
{title}
{beta && (
- BETA
+ Beta
)}
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/emptySearchComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/emptySearchComponent/index.tsx
new file mode 100644
index 000000000..54c03a24b
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/emptySearchComponent/index.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+const NoResultsMessage = ({
+ onClearSearch,
+ message = "No components found.",
+ clearSearchText = "Clear your search",
+ additionalText = "or filter and try a different query.",
+}) => {
+ return (
+
+ );
+};
+
+export default NoResultsMessage;
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/featureTogglesComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/featureTogglesComponent/index.tsx
new file mode 100644
index 000000000..d33fa3c57
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/featureTogglesComponent/index.tsx
@@ -0,0 +1,51 @@
+import { Badge } from "@/components/ui/badge";
+import { Switch } from "@/components/ui/switch";
+import React from "react";
+
+const FeatureToggles = ({
+ showBeta,
+ setShowBeta,
+ showLegacy,
+ setShowLegacy,
+}) => {
+ const toggles = [
+ {
+ label: "Beta",
+ checked: showBeta,
+ onChange: setShowBeta,
+ badgeVariant: "pinkStatic" as const,
+ testId: "sidebar-beta-switch",
+ },
+ {
+ label: "Legacy",
+ checked: showLegacy,
+ onChange: setShowLegacy,
+ badgeVariant: "secondaryStatic" as const,
+ testId: "sidebar-legacy-switch",
+ },
+ ];
+
+ return (
+
+ {toggles.map((toggle) => (
+
+
+
+ Show
+
+ {toggle.label}
+
+
+
+
+
+ ))}
+
+ );
+};
+
+export default FeatureToggles;
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx
index da415e5e7..883c87dd8 100644
--- a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarDraggableComponent/index.tsx
@@ -121,7 +121,7 @@ export const SidebarDraggableComponent = forwardRef(
data-tooltip-id={itemName}
tabIndex={0}
onKeyDown={handleKeyDown}
- className="rounded-md outline-none ring-ring focus-visible:ring-2"
+ className="m-[1px] rounded-md outline-none ring-ring focus-visible:ring-1"
>
-
+
{display_name}
@@ -160,7 +160,7 @@ export const SidebarDraggableComponent = forwardRef(
size="xq"
className="ml-1.5 shrink-0"
>
- BETA
+ Beta
)}
{legacy && (
@@ -169,7 +169,7 @@ export const SidebarDraggableComponent = forwardRef(
size="xq"
className="ml-1.5 shrink-0"
>
- LEGACY
+ Legacy
)}
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarFooterButtons/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarFooterButtons/index.tsx
new file mode 100644
index 000000000..6ad8d4965
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarFooterButtons/index.tsx
@@ -0,0 +1,62 @@
+import ForwardedIconComponent from "@/components/genericIconComponent";
+import { Button } from "@/components/ui/button";
+import { SidebarMenuButton } from "@/components/ui/sidebar";
+import { CustomLink } from "@/customization/components/custom-link";
+import React from "react";
+
+const SidebarMenuButtons = ({
+ hasStore = false,
+ customComponent,
+ addComponent,
+}) => {
+ return (
+ <>
+ {hasStore && (
+
+
+
+
+
+ Discover more components
+
+
+
+
+
+ )}
+
+
+
+ >
+ );
+};
+
+export default SidebarMenuButtons;
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarItemsList/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarItemsList/index.tsx
new file mode 100644
index 000000000..8328c4a64
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/components/sidebarItemsList/index.tsx
@@ -0,0 +1,59 @@
+import ShadTooltip from "@/components/shadTooltipComponent";
+import { removeCountFromString } from "@/utils/utils";
+import React from "react";
+import SidebarDraggableComponent from "../sidebarDraggableComponent";
+
+const SidebarItemsList = ({
+ item,
+ dataFilter,
+ nodeColors,
+ chatInputAdded,
+ onDragStart,
+ sensitiveSort,
+}) => {
+ return (
+
+ {Object.keys(dataFilter[item.name])
+ .sort((a, b) =>
+ sensitiveSort(
+ dataFilter[item.name][a].display_name,
+ dataFilter[item.name][b].display_name,
+ ),
+ )
+ .map((SBItemName, idx) => {
+ const currentItem = dataFilter[item.name][SBItemName];
+
+ return (
+
+
+ onDragStart(event, {
+ type: removeCountFromString(SBItemName),
+ node: currentItem,
+ })
+ }
+ color={nodeColors[item.name]}
+ itemName={SBItemName}
+ error={!!currentItem.error}
+ display_name={currentItem.display_name}
+ official={currentItem.official === false ? false : true}
+ beta={currentItem.beta ?? false}
+ legacy={currentItem.legacy ?? false}
+ disabled={SBItemName === "ChatInput" && chatInputAdded}
+ disabledTooltip="Chat input already added"
+ />
+
+ );
+ })}
+
+ );
+};
+
+export default SidebarItemsList;
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-beta-filter.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-beta-filter.ts
new file mode 100644
index 000000000..63f910d26
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-beta-filter.ts
@@ -0,0 +1,12 @@
+import { APIDataType } from "@/types/api";
+
+export const applyBetaFilter = (filteredData: APIDataType) => {
+ return Object.fromEntries(
+ Object.entries(filteredData).map(([category, items]) => [
+ category,
+ Object.fromEntries(
+ Object.entries(items).filter(([_, value]) => !value.beta),
+ ),
+ ]),
+ );
+};
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-edge-filter.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-edge-filter.ts
new file mode 100644
index 000000000..5d981e98d
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-edge-filter.ts
@@ -0,0 +1,25 @@
+import { APIDataType } from "@/types/api";
+
+export const applyEdgeFilter = (filteredData: APIDataType, getFilterEdge) => {
+ return Object.fromEntries(
+ Object.entries(filteredData).map(([family, familyData]) => {
+ const edgeFilter = getFilterEdge.find((x) => x.family === family);
+ if (!edgeFilter) return [family, {}];
+
+ const filteredTypes = edgeFilter.type
+ .split(",")
+ .map((t) => t.trim())
+ .filter((t) => t !== "");
+
+ if (filteredTypes.length === 0) return [family, familyData];
+
+ const filteredFamilyData = Object.fromEntries(
+ Object.entries(familyData).filter(([key]) =>
+ filteredTypes.includes(key),
+ ),
+ );
+
+ return [family, filteredFamilyData];
+ }),
+ );
+};
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-legacy-filter.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-legacy-filter.ts
new file mode 100644
index 000000000..d7ac6d5c1
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/apply-legacy-filter.ts
@@ -0,0 +1,12 @@
+import { APIDataType } from "@/types/api";
+
+export const applyLegacyFilter = (filteredData: APIDataType) => {
+ return Object.fromEntries(
+ Object.entries(filteredData).map(([category, items]) => [
+ category,
+ Object.fromEntries(
+ Object.entries(items).filter(([_, value]) => !value.legacy),
+ ),
+ ]),
+ );
+};
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/combined-results.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/combined-results.ts
new file mode 100644
index 000000000..5f7e60ed1
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/combined-results.ts
@@ -0,0 +1,19 @@
+import { APIDataType } from "@/types/api";
+import { FuseResult } from "fuse.js";
+
+export const combinedResultsFn = (
+ fuseResults: FuseResult[],
+ data: APIDataType,
+) => {
+ return Object.fromEntries(
+ Object.entries(data).map(([category]) => {
+ const categoryResults = fuseResults.filter(
+ (result) => result.item.category === category,
+ );
+ const filteredItems = Object.fromEntries(
+ categoryResults.map((result) => [result.item.key, result.item]),
+ );
+ return [category, filteredItems];
+ }),
+ );
+};
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/filtered-data.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/filtered-data.ts
new file mode 100644
index 000000000..443a98bb1
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/filtered-data.ts
@@ -0,0 +1,22 @@
+import { APIDataType } from "@/types/api";
+import { FuseResult } from "fuse.js";
+
+export const filteredDataFn = (
+ data: APIDataType,
+ combinedResults,
+ traditionalResults,
+) => {
+ return Object.fromEntries(
+ Object.entries(data).map(([category, _]) => {
+ const fuseItems = combinedResults[category] || {};
+ const traditionalItems = traditionalResults[category] || {};
+
+ const mergedItems = {
+ ...fuseItems,
+ ...traditionalItems,
+ };
+
+ return [category, mergedItems];
+ }),
+ );
+};
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/normalize-string.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/normalize-string.ts
new file mode 100644
index 000000000..6e5434c25
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/normalize-string.ts
@@ -0,0 +1,3 @@
+export function normalizeString(str: string): string {
+ return str.toLowerCase().replace(/_/g, " ").replace(/\s+/g, "");
+}
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/search-on-metadata.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/search-on-metadata.ts
new file mode 100644
index 000000000..c454c058e
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/search-on-metadata.ts
@@ -0,0 +1,18 @@
+import { normalizeString } from "./normalize-string";
+
+export function searchInMetadata(metadata: any, searchTerm: string): boolean {
+ if (!metadata || typeof metadata !== "object") return false;
+
+ return Object.entries(metadata).some(([key, value]) => {
+ if (typeof value === "string") {
+ return (
+ normalizeString(key).includes(searchTerm) ||
+ normalizeString(value).includes(searchTerm)
+ );
+ }
+ if (typeof value === "object") {
+ return searchInMetadata(value, searchTerm);
+ }
+ return false;
+ });
+}
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/traditional-search-metadata.ts b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/traditional-search-metadata.ts
new file mode 100644
index 000000000..c7fa6deb6
--- /dev/null
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/helpers/traditional-search-metadata.ts
@@ -0,0 +1,23 @@
+import { APIDataType } from "@/types/api";
+import { normalizeString } from "./normalize-string";
+import { searchInMetadata } from "./search-on-metadata";
+
+export const traditionalSearchMetadata = (
+ data: APIDataType,
+ searchTerm: string,
+) => {
+ return Object.fromEntries(
+ Object.entries(data).map(([category, items]) => {
+ const filteredItems = Object.fromEntries(
+ Object.entries(items).filter(
+ ([key, item]) =>
+ normalizeString(key).includes(searchTerm) ||
+ normalizeString(item.display_name).includes(searchTerm) ||
+ normalizeString(category).includes(searchTerm) ||
+ (item.metadata && searchInMetadata(item.metadata, searchTerm)),
+ ),
+ );
+ return [category, filteredItems];
+ }),
+ );
+};
diff --git a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx
index 39f0e4912..1c4b204d0 100644
--- a/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx
+++ b/src/frontend/src/pages/FlowPage/components/flowSidebarComponent/index.tsx
@@ -45,34 +45,26 @@ import { APIClassType } from "../../../../types/api";
import { SidebarFilterComponent } from "../extraSidebarComponent/sidebarFilterComponent";
import sensitiveSort from "../extraSidebarComponent/utils/sensitive-sort";
import ShortcutDisplay from "../nodeToolbarComponent/shortcutDisplay";
+import NoResultsMessage from "./components/emptySearchComponent";
+import FeatureToggles from "./components/featureTogglesComponent";
import SidebarDraggableComponent from "./components/sidebarDraggableComponent";
+import SidebarMenuButtons from "./components/sidebarFooterButtons";
+import SidebarItemsList from "./components/sidebarItemsList";
+import { applyBetaFilter } from "./helpers/apply-beta-filter";
+import { applyEdgeFilter } from "./helpers/apply-edge-filter";
+import { applyLegacyFilter } from "./helpers/apply-legacy-filter";
+import { combinedResultsFn } from "./helpers/combined-results";
+import { filteredDataFn } from "./helpers/filtered-data";
+import { normalizeString } from "./helpers/normalize-string";
+import { traditionalSearchMetadata } from "./helpers/traditional-search-metadata";
+
+const CATEGORIES = SIDEBAR_CATEGORIES;
+const BUNDLES = SIDEBAR_BUNDLES;
export function FlowSidebarComponent() {
const [isInputFocused, setIsInputFocused] = useState(false);
const searchInputRef = useRef(null);
- useHotkeys("/", (event) => {
- event.preventDefault();
- searchInputRef.current?.focus();
- });
-
- // Add this new useHotkeys hook
- useHotkeys(
- "esc",
- (event) => {
- event.preventDefault();
- searchInputRef.current?.blur();
- },
- {
- // Only enable this hotkey when the input is focused
- enableOnFormTags: true,
- enabled: isInputFocused,
- },
- );
-
- const categories = SIDEBAR_CATEGORIES;
- const bundles = SIDEBAR_BUNDLES;
-
const data = useTypesStore((state) => state.data);
const templates = useTypesStore((state) => state.templates);
const getFilterEdge = useFlowStore((state) => state.getFilterEdge);
@@ -93,6 +85,69 @@ export function FlowSidebarComponent() {
const [showBeta, setShowBeta] = useState(true);
const [showLegacy, setShowLegacy] = useState(false);
+ useHotkeys("/", (event) => {
+ event.preventDefault();
+ searchInputRef.current?.focus();
+ });
+
+ useHotkeys(
+ "esc",
+ (event) => {
+ event.preventDefault();
+ searchInputRef.current?.blur();
+ },
+ {
+ enableOnFormTags: true,
+ enabled: isInputFocused,
+ },
+ );
+
+ useEffect(() => {
+ filterComponents();
+ }, [data, search, filterType, getFilterEdge, showBeta, showLegacy]);
+
+ useEffect(() => {
+ // show components with error on load
+ let errors: string[] = [];
+ Object.keys(templates).forEach((component) => {
+ if (templates[component].error) {
+ errors.push(component);
+ }
+ });
+ if (errors.length > 0)
+ setErrorData({ title: " Components with errors: ", list: errors });
+ }, []);
+
+ useEffect(() => {
+ if (getFilterEdge.length !== 0) {
+ setSearch("");
+ }
+ }, [getFilterEdge, data]);
+
+ useEffect(() => {
+ const options = {
+ keys: ["display_name", "description", "type", "category"],
+ threshold: 0.3,
+ };
+
+ const fuseData = Object.entries(data).flatMap(([category, items]) =>
+ Object.entries(items).map(([key, value]) => ({
+ ...value,
+ category,
+ key,
+ })),
+ );
+
+ setFuse(new Fuse(fuseData, options));
+ handleSearchInput(search);
+ }, [data]);
+
+ useEffect(() => {
+ if (search === "" && getFilterEdge.length === 0) {
+ setOpenCategories([]);
+ }
+ }, [search, getFilterEdge]);
+
const hasResults = useMemo(() => {
return Object.values(dataFilter).some(
(category) => Object.keys(category).length > 0,
@@ -100,114 +155,48 @@ export function FlowSidebarComponent() {
}, [dataFilter]);
const [sortedCategories, setSortedCategories] = useState([]);
- useEffect(() => {
- filterComponents();
- }, [data, search, filterType, getFilterEdge, showBeta, showLegacy]);
- function normalizeString(str: string): string {
- return str.toLowerCase().replace(/_/g, " ").replace(/\s+/g, "");
- }
-
- function searchInMetadata(metadata: any, searchTerm: string): boolean {
- if (!metadata || typeof metadata !== "object") return false;
-
- return Object.entries(metadata).some(([key, value]) => {
- if (typeof value === "string") {
- return (
- normalizeString(key).includes(searchTerm) ||
- normalizeString(value).includes(searchTerm)
- );
- }
- if (typeof value === "object") {
- return searchInMetadata(value, searchTerm);
- }
- return false;
- });
- }
-
const filterComponents = () => {
let filteredData = cloneDeep(data);
- // Apply search filter
- if (search && fuse) {
- const results = fuse.search(search);
- setSortedCategories(results.map((result) => result.item.category));
- filteredData = Object.fromEntries(
- Object.entries(data).map(([category, items]) => {
- const categoryResults = results.filter(
- (result) => result.item.category === category,
- );
- const filteredItems = Object.fromEntries(
- categoryResults.map((result) => [result.item.key, result.item]),
- );
- return [category, filteredItems];
- }),
- );
- } else {
- // Fallback to traditional search if Fuse.js is not available
+ if (search) {
const searchTerm = normalizeString(search);
- filteredData = Object.fromEntries(
- Object.entries(data).map(([category, items]) => {
- const filteredItems = Object.fromEntries(
- Object.entries(items).filter(
- ([key, item]) =>
- normalizeString(key).includes(searchTerm) ||
- normalizeString(item.display_name).includes(searchTerm) ||
- normalizeString(category).includes(searchTerm) ||
- (item.metadata && searchInMetadata(item.metadata, searchTerm)),
- ),
- );
- return [category, filteredItems];
- }),
- );
+ let combinedResults = {};
+
+ if (fuse) {
+ const fuseResults = fuse.search(search);
+ setSortedCategories(fuseResults.map((result) => result.item.category));
+
+ combinedResults = combinedResultsFn(fuseResults, data);
+
+ const traditionalResults = traditionalSearchMetadata(data, searchTerm);
+
+ filteredData = filteredDataFn(
+ data,
+ combinedResults,
+ traditionalResults,
+ );
+
+ setSortedCategories(
+ Object.keys(filteredData).filter(
+ (category) => Object.keys(filteredData[category]).length > 0,
+ ),
+ );
+ }
}
// Apply edge filter
if (getFilterEdge?.length > 0) {
- filteredData = Object.fromEntries(
- Object.entries(filteredData).map(([family, familyData]) => {
- const edgeFilter = getFilterEdge.find((x) => x.family === family);
- if (!edgeFilter) return [family, {}];
-
- const filteredTypes = edgeFilter.type
- .split(",")
- .map((t) => t.trim())
- .filter((t) => t !== "");
-
- if (filteredTypes.length === 0) return [family, familyData];
-
- const filteredFamilyData = Object.fromEntries(
- Object.entries(familyData).filter(([key]) =>
- filteredTypes.includes(key),
- ),
- );
-
- return [family, filteredFamilyData];
- }),
- );
+ filteredData = applyEdgeFilter(filteredData, getFilterEdge);
}
// Apply beta filter
if (!showBeta) {
- filteredData = Object.fromEntries(
- Object.entries(filteredData).map(([category, items]) => [
- category,
- Object.fromEntries(
- Object.entries(items).filter(([_, value]) => !value.beta),
- ),
- ]),
- );
+ filteredData = applyBetaFilter(filteredData);
}
// Apply legacy filter
if (!showLegacy) {
- filteredData = Object.fromEntries(
- Object.entries(filteredData).map(([category, items]) => [
- category,
- Object.fromEntries(
- Object.entries(items).filter(([_, value]) => !value.legacy),
- ),
- ]),
- );
+ filteredData = applyLegacyFilter(filteredData);
}
setFilterData(filteredData);
@@ -220,12 +209,6 @@ export function FlowSidebarComponent() {
}
};
- useEffect(() => {
- if (search === "" && getFilterEdge.length === 0) {
- setOpenCategories([]);
- }
- }, [search, getFilterEdge]);
-
function handleSearchInput(e: string) {
setSearch(e);
filterComponents();
@@ -247,42 +230,6 @@ export function FlowSidebarComponent() {
event.dataTransfer.setData("genericNode", JSON.stringify(data));
}
- useEffect(() => {
- // show components with error on load
- let errors: string[] = [];
- Object.keys(templates).forEach((component) => {
- if (templates[component].error) {
- errors.push(component);
- }
- });
- if (errors.length > 0)
- setErrorData({ title: " Components with errors: ", list: errors });
- }, []);
-
- useEffect(() => {
- if (getFilterEdge.length !== 0) {
- setSearch("");
- }
- }, [getFilterEdge, data]);
-
- useEffect(() => {
- const options = {
- keys: ["display_name", "description", "type"],
- threshold: 0.3,
- };
-
- const fuseData = Object.entries(data).flatMap(([category, items]) =>
- Object.entries(items).map(([key, value]) => ({
- ...value,
- category,
- key,
- })),
- );
-
- setFuse(new Fuse(fuseData, options));
- handleSearchInput(search);
- }, [data]);
-
const customComponent = useMemo(() => {
return data?.["custom_component"]?.["CustomComponent"] ?? null;
}, [data]);
@@ -301,12 +248,12 @@ export function FlowSidebarComponent() {
}
};
- const hasBundleItems = bundles.some(
+ const hasBundleItems = BUNDLES.some(
(item) =>
dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0,
);
- const hasCategoryItems = categories.some(
+ const hasCategoryItems = CATEGORIES.some(
(item) =>
dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0,
);
@@ -318,7 +265,6 @@ export function FlowSidebarComponent() {
}
const nodes = useFlowStore((state) => state.nodes);
-
const chatInputAdded = checkChatInput(nodes);
return (
@@ -348,38 +294,12 @@ export function FlowSidebarComponent() {
-
-
-
-
- Show
-
- BETA
-
-
-
-
-
-
-
-
- Show
-
- LEGACY
-
-
-
-
-
-
+
@@ -399,8 +319,8 @@ export function FlowSidebarComponent() {
onChange={(e) => handleSearchInput(e.target.value)}
/>
{!isInputFocused && search === "" && (
-
- Type{" "}
+
+ Search{" "}
@@ -432,151 +352,70 @@ export function FlowSidebarComponent() {
))
- : categories
- .toSorted(
- (a, b) =>
- (search !== ""
- ? sortedCategories
- : categories
- ).findIndex((value) => value === a.name) -
- (search !== ""
- ? sortedCategories
- : categories
- ).findIndex((value) => value === b.name),
- )
- .map(
- (item) =>
- dataFilter[item.name] &&
- Object.keys(dataFilter[item.name]).length > 0 && (
-
{
- setOpenCategories((prev) =>
- isOpen
- ? [...prev, item.name]
- : prev.filter(
- (cat) => cat !== item.name,
- ),
- );
- }}
- >
-
-
-
-
- handleKeyDown(e, item.name)
- }
- className="flex cursor-pointer items-center gap-2"
- >
-
-
- {item.display_name}
-
-
-
-
-
-
-
- {Object.keys(dataFilter[item.name])
- .sort((a, b) =>
- sensitiveSort(
- dataFilter[item.name][a]
- .display_name,
- dataFilter[item.name][b]
- .display_name,
- ),
- )
- .map((SBItemName: string, idx) => (
-
-
- onDragStart(event, {
- type: removeCountFromString(
- SBItemName,
- ),
- node: dataFilter[item.name][
- SBItemName
- ],
- })
- }
- color={nodeColors[item.name]}
- itemName={SBItemName}
- error={
- !!dataFilter[item.name][
- SBItemName
- ].error
- }
- display_name={
- dataFilter[item.name][
- SBItemName
- ].display_name
- }
- official={
- dataFilter[item.name][
- SBItemName
- ].official === false
- ? false
- : true
- }
- beta={
- dataFilter[item.name][
- SBItemName
- ].beta ?? false
- }
- legacy={
- dataFilter[item.name][
- SBItemName
- ].legacy ?? false
- }
- disabled={
- SBItemName === "ChatInput" &&
- chatInputAdded
- }
- disabledTooltip="Chat input already added"
- />
-
- ))}
+ : CATEGORIES.toSorted(
+ (a, b) =>
+ (search !== ""
+ ? sortedCategories
+ : CATEGORIES
+ ).findIndex((value) => value === a.name) -
+ (search !== ""
+ ? sortedCategories
+ : CATEGORIES
+ ).findIndex((value) => value === b.name),
+ ).map(
+ (item) =>
+ dataFilter[item.name] &&
+ Object.keys(dataFilter[item.name]).length > 0 && (
+
{
+ setOpenCategories((prev) =>
+ isOpen
+ ? [...prev, item.name]
+ : prev.filter((cat) => cat !== item.name),
+ );
+ }}
+ >
+
+
+
+
+ handleKeyDown(e, item.name)
+ }
+ className="flex cursor-pointer items-center gap-2"
+ >
+
+
+ {item.display_name}
+
+
-
-
-
- ),
- )}
+
+
+
+
+
+
+
+ ),
+ )}
@@ -586,201 +425,82 @@ export function FlowSidebarComponent() {
Bundles
- {bundles
- .toSorted(
- (a, b) =>
- (search !== ""
- ? sortedCategories
- : bundles
- ).findIndex((value) => value === a.name) -
- (search !== ""
- ? sortedCategories
- : bundles
- ).findIndex((value) => value === b.name),
- )
- .map(
- (item) =>
- dataFilter[item.name] &&
- Object.keys(dataFilter[item.name]).length > 0 && (
- {
- setOpenCategories((prev) =>
- isOpen
- ? [...prev, item.name]
- : prev.filter((cat) => cat !== item.name),
- );
- }}
- >
-
-
-
-
- handleKeyDown(e, item.name)
- }
- className="flex cursor-pointer items-center gap-2"
- >
-
-
- {item.display_name}
-
-
-
-
-
-
-
- {Object.keys(dataFilter[item.name])
- .sort((a, b) =>
- sensitiveSort(
- dataFilter[item.name][a].display_name,
- dataFilter[item.name][b].display_name,
- ),
- )
- .map((SBItemName: string, idx) => (
-
-
- onDragStart(event, {
- type: removeCountFromString(
- SBItemName,
- ),
- node: dataFilter[item.name][
- SBItemName
- ],
- })
- }
- color={nodeColors[item.name]}
- itemName={SBItemName}
- error={
- !!dataFilter[item.name][
- SBItemName
- ].error
- }
- display_name={
- dataFilter[item.name][SBItemName]
- .display_name
- }
- official={
- dataFilter[item.name][SBItemName]
- .official === false
- ? false
- : true
- }
- beta={
- dataFilter[item.name][SBItemName]
- .beta ?? false
- }
- legacy={
- dataFilter[item.name][SBItemName]
- .legacy ?? false
- }
- disabled={
- SBItemName === "ChatInput" &&
- chatInputAdded
- }
- disabledTooltip="Chat input already added"
- />
-
- ))}
+ {BUNDLES.toSorted(
+ (a, b) =>
+ (search !== "" ? sortedCategories : BUNDLES).findIndex(
+ (value) => value === a.name,
+ ) -
+ (search !== "" ? sortedCategories : BUNDLES).findIndex(
+ (value) => value === b.name,
+ ),
+ ).map(
+ (item) =>
+ dataFilter[item.name] &&
+ Object.keys(dataFilter[item.name]).length > 0 && (
+
{
+ setOpenCategories((prev) =>
+ isOpen
+ ? [...prev, item.name]
+ : prev.filter((cat) => cat !== item.name),
+ );
+ }}
+ >
+
+
+
+
+ handleKeyDown(e, item.name)
+ }
+ className="flex cursor-pointer items-center gap-2"
+ >
+
+
+ {item.display_name}
+
+
-
-
-
- ),
- )}
+
+
+
+
+
+
+
+ ),
+ )}
)}
>
) : (
-
+
)}
- {hasStore && (
-
-
-
-
-
- Discover more components
-
-
-
-
-
- )}
-
-
-
+
);