Filter Menu Components on Click Edge (#932)

This branch implements the edge filtering feature.
This commit is contained in:
anovazzi1 2023-09-21 21:08:47 -03:00 committed by GitHub
commit 795bf73752
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 116 additions and 30 deletions

View file

@ -21,6 +21,7 @@ import KeypairListComponent from "../../../../components/keypairListComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { Button } from "../../../../components/ui/button";
import { TOOLTIP_EMPTY } from "../../../../constants/constants";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
@ -75,7 +76,9 @@ export default function ParameterComponent({
updateNodeInternals(data.id);
}, [data.id, position, updateNodeInternals]);
const { reactFlowInstance } = useContext(typesContext);
const groupedEdge = useRef(null);
const { reactFlowInstance, setFilterEdge } = useContext(typesContext);
let disabled =
reactFlowInstance?.getEdges().some((edge) => edge.targetHandle === id) ??
false;
@ -123,10 +126,10 @@ export default function ParameterComponent({
}, [info]);
function renderTooltips() {
let groupedObj = groupByFamily(myData, tooltipTitle!, left, flow!);
let groupedObj: any = groupByFamily(myData, tooltipTitle!, left, flow!);
groupedEdge.current = groupedObj;
if (groupedObj && groupedObj.length > 0) {
//@ts-ignore
//@ts-ignore
refHtml.current = groupedObj.map((item, index) => {
const Icon: any =
@ -271,29 +274,36 @@ export default function ParameterComponent({
!optionalHandle ? (
<></>
) : (
<ShadTooltip
styleClasses={"tooltip-fixed-width custom-scroll nowheel"}
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance!)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background"
)}
style={{
borderColor: color,
top: position,
}}
></Handle>
</ShadTooltip>
<Button className="h-7 truncate bg-muted p-0 text-sm font-normal text-black hover:bg-muted">
<div className="flex">
<ShadTooltip
styleClasses={"tooltip-fixed-width custom-scroll nowheel"}
delayDuration={0}
content={refHtml.current}
side={left ? "left" : "right"}
>
<Handle
type={left ? "target" : "source"}
position={left ? Position.Left : Position.Right}
id={id}
isValidConnection={(connection) =>
isValidConnection(connection, reactFlowInstance!)
}
className={classNames(
left ? "-ml-0.5 " : "-mr-0.5 ",
"h-3 w-3 rounded-full border-2 bg-background"
)}
style={{
borderColor: color,
top: position,
}}
onClick={() => {
setFilterEdge(groupedEdge.current);
}}
></Handle>
</ShadTooltip>
</div>
</Button>
)}
{left === true &&

View file

@ -25,7 +25,8 @@ export default function GenericNode({
const [data, setData] = useState(olddata);
const { updateFlow, flows, tabId } = useContext(TabsContext);
const updateNodeInternals = useUpdateNodeInternals();
const { types, deleteNode, reactFlowInstance } = useContext(typesContext);
const { types, deleteNode, reactFlowInstance, setFilterEdge, getFilterEdge } =
useContext(typesContext);
const name = nodeIconsLucide[data.type] ? data.type : types[data.type];
const [validationStatus, setValidationStatus] =
useState<validationStatusType | null>(null);

View file

@ -26,6 +26,8 @@ const initialValue: typesContextType = {
setData: () => {},
setFetchError: () => {},
fetchError: false,
setFilterEdge: (filter) => {},
getFilterEdge: [],
};
export const typesContext = createContext<typesContextType>(initialValue);
@ -39,6 +41,7 @@ export function TypesProvider({ children }: { children: ReactNode }) {
const [fetchError, setFetchError] = useState(false);
const { setLoading } = useContext(alertContext);
const { getAuthentication } = useContext(AuthContext);
const [getFilterEdge, setFilterEdge] = useState([]);
useEffect(() => {
// If the user is authenticated, fetch the types. This code is important to check if the user is auth because of the execution order of the useEffect hooks.
@ -113,6 +116,8 @@ export function TypesProvider({ children }: { children: ReactNode }) {
setData,
fetchError,
setFetchError,
setFilterEdge,
getFilterEdge,
}}
>
{children}

View file

@ -64,8 +64,13 @@ export default function Page({
setTabsState,
tabId,
} = useContext(TabsContext);
const { types, reactFlowInstance, setReactFlowInstance, templates } =
useContext(typesContext);
const {
types,
reactFlowInstance,
setReactFlowInstance,
templates,
setFilterEdge,
} = useContext(typesContext);
const reactFlowWrapper = useRef<HTMLDivElement>(null);
const { takeSnapshot } = useContext(undoRedoContext);
@ -382,6 +387,10 @@ export default function Page({
[]
);
const onPaneClick = useCallback((flow) => {
setFilterEdge([]);
}, []);
return (
<div className="flex h-full overflow-hidden">
{!view && <ExtraSidebar />}
@ -429,6 +438,7 @@ export default function Page({
zoomOnPinch={!view}
panOnDrag={!view}
proOptions={{ hideAttribution: true }}
onPaneClick={onPaneClick}
>
<Background className="" />
{!view && (

View file

@ -1,3 +1,4 @@
import { cloneDeep } from "lodash";
import { useContext, useEffect, useState } from "react";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import IconComponent from "../../../../components/genericIconComponent";
@ -18,7 +19,8 @@ import { classNames } from "../../../../utils/utils";
import DisclosureComponent from "../DisclosureComponent";
export default function ExtraSidebar(): JSX.Element {
const { data, templates } = useContext(typesContext);
const { data, templates, getFilterEdge, setFilterEdge } =
useContext(typesContext);
const { flows, tabId, uploadFlow, tabsState, saveFlow, isBuilt } =
useContext(TabsContext);
const { setSuccessData, setErrorData } = useContext(alertContext);
@ -42,6 +44,10 @@ export default function ExtraSidebar(): JSX.Element {
// Handle showing components after use search input
function handleSearchInput(e: string) {
if (e === "") {
setFilterData(data);
return;
}
setFilterData((_) => {
let ret = {};
Object.keys(data).forEach((d: keyof APIObjectType, i) => {
@ -69,6 +75,57 @@ export default function ExtraSidebar(): JSX.Element {
setErrorData({ title: " Components with errors: ", list: errors });
}, []);
function handleBlur() {
setFilterData(data);
setFilterEdge([]);
setSearch("");
}
useEffect(() => {
if (getFilterEdge.length === 0 && search === "") {
setFilterData(data);
setFilterEdge([]);
setSearch("");
}
}, [getFilterEdge]);
useEffect(() => {
if (getFilterEdge?.length > 0) {
setFilterData((_) => {
let dataClone = cloneDeep(data);
let ret = {};
Object.keys(dataClone).forEach((d: keyof APIObjectType, i) => {
ret[d] = {};
if (getFilterEdge.some((x) => x.family === d)) {
ret[d] = dataClone[d];
const filtered = getFilterEdge
.filter((x) => x.family === d)
.pop()
.type.split(",");
for (let i = 0; i < filtered.length; i++) {
filtered[i] = filtered[i].trimStart();
}
if (filtered.some((x) => x !== "")) {
let keys = Object.keys(dataClone[d]).filter((nd) =>
filtered.includes(nd)
);
Object.keys(dataClone[d]).forEach((element) => {
if (!keys.includes(element)) {
delete ret[d][element];
}
});
}
}
});
setSearch("search");
return ret;
});
}
}, [getFilterEdge]);
return (
<div className="side-bar-arrangement">
<div className="side-bar-buttons-arrangement">
@ -141,6 +198,7 @@ export default function ExtraSidebar(): JSX.Element {
<Separator />
<div className="side-bar-search-div-placement">
<Input
onFocusCapture={() => handleBlur()}
type="text"
name="search"
id="search"

View file

@ -18,6 +18,8 @@ export type typesContextType = {
setData: (newState: {}) => void;
fetchError: boolean;
setFetchError: (newState: boolean) => void;
setFilterEdge: (newState) => void;
getFilterEdge: any[];
};
export type alertContextType = {