From 3d4badf9c74a068252a8e43f4b1a2df3d3f1ad42 Mon Sep 17 00:00:00 2001 From: Leonardo Christino <leomilho@gmail.com> Date: Wed, 3 Apr 2024 17:50:39 +0200 Subject: [PATCH] feat(qb): larger handle for mouse events also fixes qb's pills growing due to large attribute names --- .../lib/graph-layout/graphology-layouts.ts | 1 - .../lib/querybuilder/pills/FilterHandle.tsx | 52 +++++++++++++++++-- .../customFlowPills/entitypill/entitypill.tsx | 11 ++-- .../relationpill/relation-handles.tsx | 8 +-- .../pills/pilldropdown/pilldropdown.tsx | 5 +- 5 files changed, 61 insertions(+), 16 deletions(-) diff --git a/libs/shared/lib/graph-layout/graphology-layouts.ts b/libs/shared/lib/graph-layout/graphology-layouts.ts index 4074a90cc..dd82b7093 100644 --- a/libs/shared/lib/graph-layout/graphology-layouts.ts +++ b/libs/shared/lib/graph-layout/graphology-layouts.ts @@ -197,7 +197,6 @@ export class GraphologyForceAtlas2Webworker extends GraphologyLayout { super.layout(graph, boundingBox); const sensibleSettings = forceAtlas2.inferSettings(graph); - console.log(sensibleSettings); const layout = new FA2Layout(graph, { settings: { diff --git a/libs/shared/lib/querybuilder/pills/FilterHandle.tsx b/libs/shared/lib/querybuilder/pills/FilterHandle.tsx index dec750f44..9dcf0c610 100644 --- a/libs/shared/lib/querybuilder/pills/FilterHandle.tsx +++ b/libs/shared/lib/querybuilder/pills/FilterHandle.tsx @@ -10,9 +10,13 @@ const selector = (s: any) => ({ export const FilterHandle = ( props: { handle: QueryGraphEdgeHandle; + handleTop?: 'auto' | 'fixed'; + hidden?: boolean; } & Omit<HandleProps, 'id'> & - Omit<React.HTMLAttributes<HTMLDivElement>, 'id'> + Omit<React.HTMLAttributes<HTMLDivElement>, 'id'>, ) => { + const outerSize = 8; + const innerSize = 3; const { nodeInternals, edges } = useStore(selector); const nodeId = useNodeId(); @@ -51,8 +55,50 @@ export const FilterHandle = ( if (sourceWithLogic === targetHandleOfTypeLogic) return true; else return false; }, - [nodeInternals, edges, nodeId, props.handle] + [nodeInternals, edges, nodeId, props.handle], ); - return <Handle id={id} {...props} isValidConnection={isValidConnection}></Handle>; + const style: React.CSSProperties = { + width: outerSize * 2, + height: outerSize * 2, + top: props.handleTop === 'auto' ? `auto` : `calc(2rem - ${outerSize}px)`, + }; + if (props.position === Position.Left) { + style.left = outerSize / 2; + } else { + style.right = outerSize / 2; + } + + const handleStyle: React.CSSProperties = {}; + if (props.position === Position.Left) { + handleStyle.left = 0; + } else { + handleStyle.right = 0; + } + + const innerStyle: React.CSSProperties = { width: innerSize * 2, height: innerSize * 2 }; + innerStyle.top = outerSize / 2 + innerSize / 4; + if (props.position === Position.Left) { + innerStyle.left = outerSize / 2 + innerSize / 4; + } else { + innerStyle.right = outerSize / 2 + innerSize / 4; + } + + const innerProps = { ...props }; + delete innerProps.className; + delete innerProps.style; + delete innerProps.handleTop; + + return ( + <div className="absolute " style={style}> + <Handle + id={id} + {...innerProps} + className={'!rounded-none !bg-transparent !w-full !h-full !border-0'} + style={handleStyle} + isValidConnection={isValidConnection} + ></Handle> + <div className={'absolute pointer-events-none ' + props.className} style={innerStyle}></div> + </div> + ); }; diff --git a/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx b/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx index d8f27749d..d0ec8779a 100644 --- a/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx +++ b/libs/shared/lib/querybuilder/pills/customFlowPills/entitypill/entitypill.tsx @@ -18,7 +18,7 @@ export const EntityFlowElement = React.memo((node: SchemaReactflowEntityNode) => const graph = useQuerybuilderGraph(); const attributeEdges = useMemo( () => graph.edges.filter((edge) => edge.source === node.id && !!edge?.attributes?.sourceHandleData.attributeType), - [graph] + [graph], ); const [hovered, setHovered] = useState(false); @@ -48,19 +48,22 @@ export const EntityFlowElement = React.memo((node: SchemaReactflowEntityNode) => return ( <div className="p-3 bg-transparent" onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}> - <div className={`rounded-sm shadow min-w-[8rem] text-[0.8rem] bg-gradient-to-r pt-1 from-[#FFA952] to-[#D66700]`}> + <div className={`rounded-sm shadow min-w-[9rem] max-w-[9rem] text-[0.8rem] bg-gradient-to-r pt-1 from-[#FFA952] to-[#D66700]`}> <div className={`pt-1 ${data.selected ? 'bg-secondary-400' : 'bg-secondary-50'}`}> <FilterHandle handle={data.leftRelationHandleId} type="target" position={Position.Left} - className={'!top-8 !left-2 !bg-danger-700 !rounded-none'} + // className={'!top-8 !left-2 !bg-danger-700 !rounded-none'} + // outerClassName={'!bg-blue-700 !rounded-none'} + className={'!bg-accent-700'} /> <FilterHandle handle={data.rightRelationHandleId} type="source" position={Position.Right} - className={'!top-8 !right-2 !bg-accent-700 !rounded-none'} + // outerClassName={'!bg-blue-700 !rounded-none'} + className={'!bg-accent-700'} /> <div className="text-center py-1">{data.name}</div> {data?.attributes && ( diff --git a/libs/shared/lib/querybuilder/pills/customFlowPills/relationpill/relation-handles.tsx b/libs/shared/lib/querybuilder/pills/customFlowPills/relationpill/relation-handles.tsx index 61ea6fc06..b8e3049fb 100644 --- a/libs/shared/lib/querybuilder/pills/customFlowPills/relationpill/relation-handles.tsx +++ b/libs/shared/lib/querybuilder/pills/customFlowPills/relationpill/relation-handles.tsx @@ -26,15 +26,13 @@ export const LeftHandle = (props: Props) => { handle={props.handle} type={props.type} position={Position.Left} - className="!top- !left-2" - // style={{ transform: `translate(${offsetX}px, ${offsetY}px)` }} onDoubleClickCapture={(e) => { e.preventDefault(); e.stopPropagation(); if (props.onDoubleClick) props.onDoubleClick(); }} > - <svg className="pointer-events-none" height={10} style={{ transform: `translate(-2px, -3px)` }}> + <svg className="pointer-events-none" height={10} style={{ transform: `translate(3px, 4px)` }}> <polygon points={getArrow[props.point]} fill={tailwindColors.relation[200]} /> </svg> </FilterHandle> @@ -47,15 +45,13 @@ export const RightHandle = (props: Props) => { handle={props.handle} type={props.type} position={Position.Right} - className="!top-8 !right-2" - // style={{ transform: `translate(${offsetX}px, ${offsetY}px)` }} onDoubleClickCapture={(e) => { e.preventDefault(); e.stopPropagation(); if (props.onDoubleClick) props.onDoubleClick(); }} > - <svg height={10} className="pointer-events-none" style={{ transform: `translate(-2px, -3px)` }}> + <svg height={10} className="pointer-events-none" style={{ transform: `translate(6px, 4px)` }}> <polygon points={getArrow[props.point]} fill={tailwindColors.relation[200]} /> </svg> </FilterHandle> diff --git a/libs/shared/lib/querybuilder/pills/pilldropdown/pilldropdown.tsx b/libs/shared/lib/querybuilder/pills/pilldropdown/pilldropdown.tsx index 5e704d6d2..312a11d05 100644 --- a/libs/shared/lib/querybuilder/pills/pilldropdown/pilldropdown.tsx +++ b/libs/shared/lib/querybuilder/pills/pilldropdown/pilldropdown.tsx @@ -63,7 +63,7 @@ export const PillDropdown = (props: PillDropdownProps) => { props.onHandleMouseDown(attribute, i, event); }} > - <p>{attribute.handleData.attributeName}</p> + <p className="truncate text-[0.6rem]">{attribute.handleData.attributeName}</p> {attribute.handleData?.attributeDimension && ( // <div className="!text-xs text-secondary-500">{IconMap[attribute.handleData.attributeDimension]}</div> // <div className="!text-xs text-secondary-500"> @@ -74,7 +74,8 @@ export const PillDropdown = (props: PillDropdownProps) => { handle={handleDataFromReactflowToDataId(props.node, attribute)} type="source" position={Position.Right} - className={styles.handle + ' ' + '!top-auto mt-2 !right-[0.5rem] bg-secondary-500'} + className={styles.handle + ' bg-secondary-500 rounded-full'} + handleTop="auto" ></FilterHandle> </div> ); -- GitLab