From 10833dca3274e33ecb29c7850a0fa357607b5326 Mon Sep 17 00:00:00 2001
From: Leonardo <leomilho@gmail.com>
Date: Sat, 15 Jun 2024 14:30:35 +0200
Subject: [PATCH] feat(qb): qb attribute icon is a button to add logic pill

---
 .../lib/querybuilder/panel/QueryBuilder.tsx   | 15 ++++++++-
 .../panel/QueryBuilderDispatcher.tsx          | 13 +++++---
 .../logicpill/QueryLogicPill.tsx              |  2 +-
 .../pills/pilldropdown/PillDropdown.tsx       | 33 ++++++++++++++++---
 4 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx b/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx
index d5a38f395..26da1edfb 100644
--- a/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx
+++ b/libs/shared/lib/querybuilder/panel/QueryBuilder.tsx
@@ -444,10 +444,23 @@ export const QueryBuilderInner = (props: QueryBuilderProps) => {
   return (
     <QueryBuilderDispatcherContext.Provider
       value={{
-        openLogicPillChooser: (node) => {
+        openLogicPillUpdate: (node) => {
           editLogicNode.current = node;
           setToggleSettings('logic');
         },
+        openLogicPillCreate: (params, position) => {
+          if (!params?.handleId) return;
+
+          let node = graphologyGraph.getNodeAttributes(params.nodeId);
+          const handleData = toHandleData(params.handleId);
+          connectingNodeId.current = {
+            params,
+            node,
+            position: position || { x: 0, y: 0 },
+            attribute: { handleData: handleData },
+          };
+          setToggleSettings('logic');
+        },
       }}
     >
       <div ref={reactFlowWrapper} className="h-full w-full flex flex-col">
diff --git a/libs/shared/lib/querybuilder/panel/QueryBuilderDispatcher.tsx b/libs/shared/lib/querybuilder/panel/QueryBuilderDispatcher.tsx
index fd7329e7b..951bfc61e 100644
--- a/libs/shared/lib/querybuilder/panel/QueryBuilderDispatcher.tsx
+++ b/libs/shared/lib/querybuilder/panel/QueryBuilderDispatcher.tsx
@@ -1,10 +1,15 @@
 import React, { createContext } from 'react';
-import { SchemaReactflowLogicNode } from '../model';
+import { SchemaReactflowEntityNode, SchemaReactflowLogicNode } from '../model';
+import { OnConnectStartParams } from 'reactflow';
 
 export const QueryBuilderDispatcherContext = createContext<{
-  openLogicPillChooser: (node: SchemaReactflowLogicNode) => void;
+  openLogicPillUpdate: (node: SchemaReactflowLogicNode) => void;
+  openLogicPillCreate: (params: OnConnectStartParams, position?: { x: number; y: number }) => void;
 }>({
-  openLogicPillChooser: (node: SchemaReactflowLogicNode) => {
-    throw new Error('openLogicPillChooser not implemented');
+  openLogicPillUpdate: (node: SchemaReactflowLogicNode) => {
+    throw new Error('openLogicPillUpdate not implemented');
+  },
+  openLogicPillCreate: (params: OnConnectStartParams, position?: { x: number; y: number }) => {
+    throw new Error('openLogicPillCreate not implemented');
   },
 });
diff --git a/libs/shared/lib/querybuilder/pills/customFlowPills/logicpill/QueryLogicPill.tsx b/libs/shared/lib/querybuilder/pills/customFlowPills/logicpill/QueryLogicPill.tsx
index 032ae41e0..f17b0e705 100644
--- a/libs/shared/lib/querybuilder/pills/customFlowPills/logicpill/QueryLogicPill.tsx
+++ b/libs/shared/lib/querybuilder/pills/customFlowPills/logicpill/QueryLogicPill.tsx
@@ -14,7 +14,7 @@ export function QueryLogicPill(node: SchemaReactflowLogicNode) {
   const dispatch = useAppDispatch();
   const data = node.data;
   const logic = data.logic;
-  const { openLogicPillChooser } = useContext(QueryBuilderDispatcherContext);
+  const { openLogicPillUpdate: openLogicPillChooser } = useContext(QueryBuilderDispatcherContext);
 
   const output = data.logic.output;
   const inputReference = useRef<HTMLInputElement>(null);
diff --git a/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx b/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx
index 3b796d784..85c84843a 100644
--- a/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx
+++ b/libs/shared/lib/querybuilder/pills/pilldropdown/PillDropdown.tsx
@@ -1,4 +1,4 @@
-import { useMemo, ReactElement, useState } from 'react';
+import { useMemo, ReactElement, useState, useContext } from 'react';
 import { NodeAttribute, QueryGraphEdges, SchemaReactflowEntityNode, handleDataFromReactflowToDataId, toHandleId } from '../../model';
 import { Handle, Position, useUpdateNodeInternals } from 'reactflow';
 import { Abc, CalendarToday, Map, Numbers, Place, QuestionMarkOutlined } from '@mui/icons-material';
@@ -8,6 +8,7 @@ import { pillDropdownPadding } from '@graphpolaris/shared/lib/components/pills/p
 import { Button, TextInput, useAppDispatch, useQuerybuilderAttributesShown } from '../../..';
 import { attributeShownToggle } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice';
 import { isEqual } from 'lodash-es';
+import { QueryBuilderDispatcherContext } from '../../panel/QueryBuilderDispatcher';
 
 type PillDropdownProps = {
   node: SchemaReactflowEntityNode;
@@ -35,6 +36,7 @@ export const PillDropdown = (props: PillDropdownProps) => {
   const [filter, setFilter] = useState<string>('');
   const dispatch = useAppDispatch();
   const attributesBeingShown = useQuerybuilderAttributesShown();
+  const { openLogicPillCreate } = useContext(QueryBuilderDispatcherContext);
 
   const attributesOfInterest = useMemo(() => {
     return props.attributes.map((attribute) =>
@@ -53,13 +55,36 @@ export const PillDropdown = (props: PillDropdownProps) => {
             throw new Error('attribute.handleData.attributeName is undefined');
           }
 
+          const handleId = toHandleId(handleDataFromReactflowToDataId(props.node, attribute));
+          const handleType = 'source';
+
           return (
             <div
               className="px-2 py-1 bg-secondary-100 flex justify-between items-center"
               key={(attribute.handleData.attributeName || '') + i}
             >
               <p className="truncate text-[0.6rem]">{attribute.handleData.attributeName}</p>
-              {attribute.handleData?.attributeDimension && <Icon component={IconMap[attribute.handleData.attributeDimension]} size={16} />}
+              <Button
+                variantType="secondary"
+                variant="ghost"
+                size="2xs"
+                iconComponent={
+                  attribute.handleData?.attributeDimension ? IconMap[attribute.handleData.attributeDimension] : <QuestionMarkOutlined />
+                }
+                onClick={() => {
+                  openLogicPillCreate(
+                    {
+                      nodeId: props.node.id,
+                      handleId: handleId,
+                      handleType: handleType,
+                    },
+                    {
+                      x: props.node.xPos + 200,
+                      y: props.node.yPos + 50,
+                    },
+                  );
+                }}
+              />
               <PillHandle
                 mr={-pillDropdownPadding + (props.mr || 0)}
                 handleTop="auto"
@@ -68,8 +93,8 @@ export const PillDropdown = (props: PillDropdownProps) => {
                 type="square"
               >
                 <Handle
-                  id={toHandleId(handleDataFromReactflowToDataId(props.node, attribute))}
-                  type="source"
+                  id={handleId}
+                  type={handleType}
                   position={Position.Right}
                   className={'!rounded-none !bg-transparent !w-full !h-full !right-0 !left-0 !border-0'}
                 ></Handle>
-- 
GitLab