Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • graphpolaris/frontend-v2
  • rijkheere/frontend-v-2-reordering-paoh
2 results
Show changes
Commits on Source (10)
...@@ -246,11 +246,14 @@ export const MenuTrigger = React.forwardRef<HTMLElement, MenuTriggerProps>( ...@@ -246,11 +246,14 @@ export const MenuTrigger = React.forwardRef<HTMLElement, MenuTriggerProps>(
}; };
delete referenceProps.onMouseDown; delete referenceProps.onMouseDown;
delete referenceProps.onPointerDown; delete referenceProps.onPointerDown;
referenceProps.onClick = (event: React.MouseEvent) => { delete referenceProps.onClick;
event.preventDefault();
console.log('Click event!!!', context.isOpen); if (context.isOpen) {
context.setIsOpen(false); referenceProps.onClick = (event: React.MouseEvent) => {
}; event.preventDefault();
context.setIsOpen(false);
};
}
} }
const element = React.cloneElement(children as React.ReactElement<{ ref?: React.Ref<HTMLElement> }>, { const element = React.cloneElement(children as React.ReactElement<{ ref?: React.Ref<HTMLElement> }>, {
......
import { DropdownItem, DropdownItemContainer, Icon, Input, Popover, PopoverTrigger } from '@/lib/components'; import {
Menu,
MenuCheckboxItem,
MenuContent,
MenuItem,
MenuLabel,
MenuRadioGroup,
MenuRadioItem,
MenuSeparator,
MenuTrigger,
} from '@/lib/components/menu';
import { import {
attributeShownToggle, attributeShownToggle,
setQuerybuilderGraphology, setQuerybuilderGraphology,
...@@ -8,7 +18,7 @@ import { ...@@ -8,7 +18,7 @@ import {
import { isEqual } from 'lodash-es'; import { isEqual } from 'lodash-es';
import { useEffect, useMemo, useState } from 'react'; import { useEffect, useMemo, useState } from 'react';
import { Node, ReactFlowInstance } from 'reactflow'; import { Node, ReactFlowInstance } from 'reactflow';
import { defaultGraph, NodeAttribute, QueryRelationDirection, QueryUnionType } from 'ts-common'; import { defaultGraph, NodeAttribute, QueryGraphEdgeHandle, QueryRelationDirection, QueryUnionType } from 'ts-common';
import { useActiveQuery, useAppDispatch, useQuerybuilderHash } from '../..'; import { useActiveQuery, useAppDispatch, useQuerybuilderHash } from '../..';
import { getDataTypeIcon } from '../../components/DataTypeIcon'; import { getDataTypeIcon } from '../../components/DataTypeIcon';
...@@ -20,7 +30,6 @@ export const QueryBuilderContextMenu = (props: { ...@@ -20,7 +30,6 @@ export const QueryBuilderContextMenu = (props: {
reactFlow: ReactFlowInstance; reactFlow: ReactFlowInstance;
onClose: () => void; onClose: () => void;
}) => { }) => {
const [filter, setFilter] = useState<string>('');
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const activeQuery = useActiveQuery(); const activeQuery = useActiveQuery();
const qbHash = useQuerybuilderHash(); const qbHash = useQuerybuilderHash();
...@@ -45,7 +54,7 @@ export const QueryBuilderContextMenu = (props: { ...@@ -45,7 +54,7 @@ export const QueryBuilderContextMenu = (props: {
return { return {
open: props.open, open: props.open,
x: position.x - divPosition.x - (initialPosition.x - divPosition.x), x: position.x - divPosition.x - (initialPosition.x - divPosition.x) + 10,
y: position.y - divPosition.y - (initialPosition.y - divPosition.y) + 10, y: position.y - divPosition.y - (initialPosition.y - divPosition.y) + 10,
}; };
}, [props.open, props.node, divPosition]); }, [props.open, props.node, divPosition]);
...@@ -65,29 +74,22 @@ export const QueryBuilderContextMenu = (props: { ...@@ -65,29 +74,22 @@ export const QueryBuilderContextMenu = (props: {
}; };
}, [props.reactFlowWrapper]); }, [props.reactFlowWrapper]);
const filteredAttributes = useMemo<NodeAttribute[]>(() => {
if (props.node == null) return [];
if (filter == null || filter.length == 0) return props.node.data.attributes;
return (props.node.data.attributes as NodeAttribute[]).filter(attr => {
return attr.handleData.attributeName?.toLocaleLowerCase().includes(filter.toLocaleLowerCase());
});
}, [filter, props.node]);
function isAttributeAdded(attribute: NodeAttribute): boolean { function isAttributeAdded(attribute: NodeAttribute): boolean {
return activeQuery?.attributesBeingShown.some(x => isEqual(x, attribute.handleData)) ?? false; return activeQuery?.attributesBeingShown.some(x => isEqual(x, attribute.handleData)) ?? false;
} }
function addAttribute(attribute: NodeAttribute) { function toggleAttribute(attribute: NodeAttribute) {
dispatch(attributeShownToggle(attribute.handleData)); dispatch(attributeShownToggle(attribute.handleData));
} }
function setUnionType(unionType: QueryUnionType) { function setUnionType(value: string) {
const unionType = value as QueryUnionType;
if (!props.node) return; if (!props.node) return;
dispatch(setQueryUnionType({ nodeId: props.node.id, unionType: unionType })); dispatch(setQueryUnionType({ nodeId: props.node.id, unionType: unionType }));
} }
function setRelationDirection(relationDirection: QueryRelationDirection) { function setRelationDirection(value: string) {
const relationDirection = value as QueryRelationDirection;
if (!props.node) return; if (!props.node) return;
// @ts-expect-error - graphology types are not up to date // @ts-expect-error - graphology types are not up to date
graphologyGraph.setNodeAttribute(props.node.id, 'direction', relationDirection); graphologyGraph.setNodeAttribute(props.node.id, 'direction', relationDirection);
...@@ -111,96 +113,56 @@ export const QueryBuilderContextMenu = (props: { ...@@ -111,96 +113,56 @@ export const QueryBuilderContextMenu = (props: {
} }
return ( return (
<Popover open={props.open && state !== undefined} interactive={true} showArrow={false} placement="bottom-start"> <Menu isOpen={props.open && state !== undefined}>
<PopoverTrigger x={state ? state.x : 0} y={state ? state.y : 0} /> <MenuTrigger x={state ? state.x : 0} y={state ? state.y : 0}>
<DropdownItemContainer root={props.reactFlowWrapper.current}> <div />
{props.node && props?.node.type !== 'logic' && ( </MenuTrigger>
<> <MenuContent>
<DropdownItem <Menu>
value={'Add/remove attribute'} <MenuTrigger label="Add/remove attribute" />
onClick={e => {}} <MenuContent className="max-h-60 overflow-y-auto">
submenu={[ {props.node?.data.attributes.map((attr: { handleData: QueryGraphEdgeHandle }) => (
<Input <MenuCheckboxItem
label="" key={attr.handleData.attributeName + attr.handleData.nodeId}
type={'text'} checked={isAttributeAdded(attr)}
placeholder="Filter" onCheckedChange={_ => toggleAttribute(attr)}
size="xs" label={attr.handleData.attributeName}
className="mb-1 rounded-sm w-full" iconRight={getDataTypeIcon(attr?.handleData?.attributeType)}
value={filter}
onClick={e => e.stopPropagation()}
onChange={v => setFilter(v)}
/>,
filteredAttributes.map(attr => (
<DropdownItem
key={attr.handleData.attributeName + attr.handleData.nodeId}
value={''}
selected={isAttributeAdded(attr)}
onClick={_ => addAttribute(attr)}
className="w-full"
>
<div className="flex items-center gap-1">
<Icon component={getDataTypeIcon(attr?.handleData?.attributeType)} className="" size={16} />
<span>{attr.handleData.attributeName ?? ''}</span>
</div>
</DropdownItem>
)),
]}
/>
<DropdownItem
value="Union type"
submenu={[
<DropdownItem
value="AND"
onClick={_ => setUnionType(QueryUnionType.AND)}
selected={props.node ? unionType != QueryUnionType.OR : false} // Also selected when null
/>,
<DropdownItem
value="OR"
onClick={_ => setUnionType(QueryUnionType.OR)}
selected={props.node ? unionType == QueryUnionType.OR : false}
/>,
]}
/>
{relationDirection && (
<DropdownItem
value="Direction"
submenu={[
<DropdownItem
value={QueryRelationDirection.BOTH}
onClick={_ => setRelationDirection(QueryRelationDirection.BOTH)}
selected={relationDirection === QueryRelationDirection.BOTH}
/>,
<DropdownItem
value={QueryRelationDirection.RIGHT}
onClick={_ => setRelationDirection(QueryRelationDirection.RIGHT)}
selected={relationDirection === QueryRelationDirection.RIGHT}
/>,
<DropdownItem
value={QueryRelationDirection.LEFT}
onClick={_ => setRelationDirection(QueryRelationDirection.LEFT)}
selected={relationDirection === QueryRelationDirection.LEFT}
/>,
]}
/> />
)} ))}
<DropdownItem </MenuContent>
value="Entity statistics" </Menu>
submenu={[ <Menu>
<DropdownItem value="" disabled className="text-muted pointer-events-none"> <MenuTrigger label="Union type" />
<div className="flex items-between text-neutral-400"> <MenuContent>
<div className="inline-block w-[70px]">Total:</div> <MenuRadioGroup value={unionType ?? QueryUnionType.AND} onValueChange={setUnionType}>
<span> <MenuRadioItem label="AND" value={QueryUnionType.AND} />
{activeQuery?.graphCounts.nodeCounts ? activeQuery.graphCounts.nodeCounts[props.node.id + '_count'] : 'unknown'} <MenuRadioItem label="OR" value={QueryUnionType.OR} />
</span> </MenuRadioGroup>
</div> </MenuContent>
</DropdownItem>, </Menu>
]} {relationDirection && (
/> <Menu>
</> <MenuTrigger label="Direction" />
<MenuContent>
<MenuRadioGroup value={relationDirection} onValueChange={setRelationDirection}>
<MenuRadioItem label={QueryRelationDirection.BOTH} value={QueryRelationDirection.BOTH} />
<MenuRadioItem label={QueryRelationDirection.RIGHT} value={QueryRelationDirection.RIGHT} />
<MenuRadioItem label={QueryRelationDirection.LEFT} value={QueryRelationDirection.LEFT} />
</MenuRadioGroup>
</MenuContent>
</Menu>
)} )}
<DropdownItem value="Remove" className="text-danger" onClick={e => removeNode()} /> <Menu>
</DropdownItemContainer> <MenuTrigger label="Entity statistics" />
</Popover> <MenuContent>
<MenuLabel label="Total node count" />
<MenuItem disabled label={String(activeQuery?.graphCounts?.nodeCounts[props.node?.id + '_count'] ?? 'unknown')}></MenuItem>
</MenuContent>
</Menu>
<MenuSeparator />
<MenuItem label="Remove" className="text-danger" onClick={() => removeNode()} />
</MenuContent>
</Menu>
); );
}; };