From 8060b35f1e8e9ceb7166856597527675303892e8 Mon Sep 17 00:00:00 2001
From: Dennis Collaris <d.collaris@me.com>
Date: Fri, 28 Mar 2025 13:06:50 +0100
Subject: [PATCH] fix: rebase issues and return context menu functionality on
 tabs

---
 .../panel/querybuildernav/QueryBuilderNav.tsx |  10 +-
 .../panel/querybuildernav/QueryBuilderTab.tsx | 197 ++++++++++--------
 2 files changed, 112 insertions(+), 95 deletions(-)

diff --git a/src/lib/querybuilder/panel/querybuildernav/QueryBuilderNav.tsx b/src/lib/querybuilder/panel/querybuildernav/QueryBuilderNav.tsx
index 5ffade126..4d0e33c01 100644
--- a/src/lib/querybuilder/panel/querybuildernav/QueryBuilderNav.tsx
+++ b/src/lib/querybuilder/panel/querybuildernav/QueryBuilderNav.tsx
@@ -1,17 +1,11 @@
-import { Button, ControlContainer, Input, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/components';
-import { Menu, MenuContent, MenuItem, MenuSeparator, MenuTrigger } from '@/lib/components/menu';
-import { Popover, PopoverContent, PopoverTrigger } from '@/lib/components/popover';
-import { Tab, Tabs } from '@/lib/components/tabs';
 import { ControlContainer, TooltipProvider } from '@/lib/components';
-import { useEffect, useMemo, useRef } from 'react';
-
-import { useActiveQuery, useActiveSaveState, useAppDispatch, useGraphQuery, useML } from '../../../data-access';
-
 import { Tabs } from '@/lib/components/tabs';
 import { wsUpdateQuery } from '@/lib/data-access/broker';
 import { addError } from '@/lib/data-access/store/configSlice';
 import objectHash from 'object-hash';
+import { useEffect, useMemo, useRef } from 'react';
 import Sortable from 'sortablejs';
+import { useActiveQuery, useActiveSaveState, useAppDispatch, useGraphQuery, useML } from '../../../data-access';
 import { clearQB, reorderQueryState, setQueryName } from '../../../data-access/store/sessionSlice';
 import {
   AddQueryButton,
diff --git a/src/lib/querybuilder/panel/querybuildernav/QueryBuilderTab.tsx b/src/lib/querybuilder/panel/querybuildernav/QueryBuilderTab.tsx
index 6862fc1b2..c23413846 100644
--- a/src/lib/querybuilder/panel/querybuildernav/QueryBuilderTab.tsx
+++ b/src/lib/querybuilder/panel/querybuildernav/QueryBuilderTab.tsx
@@ -1,7 +1,8 @@
-import { Button, Input, Tab, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/components';
+import { Button, Icon, Input, Tab, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/components';
+import { Menu, MenuContent, MenuItem, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuTrigger } from '@/lib/components/menu';
 import { useAppDispatch } from '@/lib/data-access';
 import { wsDeleteQuery } from '@/lib/data-access/broker';
-import { removeQueryByID, setActiveQueryID, setQueryViewMode } from '@/lib/data-access/store/sessionSlice';
+import { removeQueryByID, setActiveQueryID, setQuerybuilderSettings, setQueryViewMode } from '@/lib/data-access/store/sessionSlice';
 import { useState } from 'react';
 import { Query, QueryViewMode } from 'ts-common/src/model';
 
@@ -36,7 +37,7 @@ const QueryBuilderTab = ({ query, isActive, canWrite, saveStateId, isLastTab, on
   };
 
   // Get icon component based on the view mode
-  const getViewModeIcon = (): string => {
+  const getViewModeIcon = (viewMode: QueryViewMode): string => {
     switch (viewMode) {
       case QueryViewMode.Visual:
         return 'icon-[ic--baseline-remove-red-eye]';
@@ -71,94 +72,116 @@ const QueryBuilderTab = ({ query, isActive, canWrite, saveStateId, isLastTab, on
   };
 
   return (
-    <Tab
-      text=""
-      activeTab={isActive}
-      data-id={query.id}
-      onClick={() => {
-        if (query.id == null) throw new Error('Query ID is null; Cannot change tabs in query tab navbar');
-        dispatch(setActiveQueryID(query.id));
-      }}
-    >
-      {isEditing ? (
-        <Input
-          type="text"
-          size="xs"
-          value={editText}
-          label=""
-          onChange={(e: any) => {
-            setEditText(typeof e === 'string' ? e : e.target.value);
+    <Menu atCursor>
+      <MenuTrigger className="-mb-px" rightClick>
+        <Tab
+          text=""
+          activeTab={isActive}
+          data-id={query.id}
+          onClick={() => {
+            if (query.id == null) throw new Error('Query ID is null; Cannot change tabs in query tab navbar');
+            dispatch(setActiveQueryID(query.id));
           }}
-          onBlur={handleUpdateName}
-          onKeyDown={(e: React.KeyboardEvent) => {
-            if (e.key === 'Enter') {
-              handleUpdateName();
-            }
+          IconComponent={() => <Icon size={14} component={getViewModeIcon(viewMode)} />}
+        >
+          {isEditing ? (
+            <Input
+              type="text"
+              size="xs"
+              value={editText}
+              label=""
+              onChange={(e: any) => {
+                setEditText(typeof e === 'string' ? e : e.target.value);
+              }}
+              onBlur={handleUpdateName}
+              onKeyDown={(e: React.KeyboardEvent) => {
+                if (e.key === 'Enter') {
+                  handleUpdateName();
+                }
+              }}
+              className="w-20"
+              style={{
+                border: 'none',
+                boxShadow: 'none',
+                background: 'none',
+              }}
+              autoFocus
+            />
+          ) : (
+            <>
+              <div
+                onDoubleClick={(e: React.MouseEvent) => {
+                  e.stopPropagation();
+                  if (query.id == null) throw new Error('Query ID is null; Cannot change tabs in query tab navbar');
+                  dispatch(setActiveQueryID(query.id));
+                  setIsEditing(true);
+                }}
+              >
+                {query.name ?? 'Query'}
+              </div>
+            </>
+          )}
+
+          {!isLastTab && (
+            <>
+              <Button
+                variantType="secondary"
+                variant="ghost"
+                disabled={!canWrite}
+                rounded
+                size="3xs"
+                iconComponent="icon-[ic--baseline-close]"
+                onClick={(e: React.MouseEvent) => {
+                  e.stopPropagation();
+                  if (query.id !== undefined) {
+                    wsDeleteQuery({ saveStateID: saveStateId, queryID: query.id });
+                    dispatch(removeQueryByID(query.id));
+                  }
+                }}
+              />
+            </>
+          )}
+        </Tab>
+      </MenuTrigger>
+      <MenuContent>
+        <Menu>
+          <MenuTrigger label="Change mode" />
+          <MenuContent>
+            <MenuRadioGroup
+              value={query.settings.mode}
+              onValueChange={value => {
+                dispatch(setQuerybuilderSettings({ ...query.settings, mode: value as QueryViewMode }));
+              }}
+            >
+              <MenuRadioItem value={QueryViewMode.Visual} label="Visual" closeOnClick={true} />
+              <MenuRadioItem value={QueryViewMode.Cypher} label="Cypher" closeOnClick={true} />
+            </MenuRadioGroup>
+          </MenuContent>
+        </Menu>
+        <MenuItem
+          label="Rename"
+          closeOnClick={true}
+          onClick={e => {
+            e.stopPropagation();
+
+            setTimeout(() => {
+              setIsEditing(true);
+            }, 1);
           }}
-          className="w-20"
-          style={{
-            border: 'none',
-            boxShadow: 'none',
-            background: 'none',
+        />
+        <MenuSeparator />
+        <MenuItem
+          label="Remove"
+          className="text-danger"
+          onClick={() => {
+            if (query.id !== undefined) {
+              wsDeleteQuery({ saveStateID: ss.id, queryID: query.id });
+              dispatch(removeQueryByID(query.id));
+            }
           }}
-          autoFocus
         />
-      ) : (
-        <>
-          <div
-            onDoubleClick={(e: React.MouseEvent) => {
-              e.stopPropagation();
-              if (query.id == null) throw new Error('Query ID is null; Cannot change tabs in query tab navbar');
-              dispatch(setActiveQueryID(query.id));
-              setIsEditing(true);
-            }}
-          >
-            {query.name ?? 'Query'}
-          </div>
-
-          <TooltipProvider>
-            <Tooltip>
-              <TooltipTrigger>
-                <Button
-                  variantType="secondary"
-                  variant="ghost"
-                  size="3xs"
-                  // disabled={true} // will be enabled when more panels are available
-                  iconComponent={getViewModeIcon()}
-                  onClick={(e: React.MouseEvent) => {
-                    e.stopPropagation();
-                    toggleViewMode();
-                  }}
-                />
-              </TooltipTrigger>
-              <TooltipContent>
-                <p>{getViewModeTooltip()}</p>
-              </TooltipContent>
-            </Tooltip>
-          </TooltipProvider>
-        </>
-      )}
-
-      {!isLastTab && (
-        <>
-          <Button
-            variantType="secondary"
-            variant="ghost"
-            disabled={!canWrite}
-            rounded
-            size="3xs"
-            iconComponent="icon-[ic--baseline-close]"
-            onClick={(e: React.MouseEvent) => {
-              e.stopPropagation();
-              if (query.id !== undefined) {
-                wsDeleteQuery({ saveStateID: saveStateId, queryID: query.id });
-                dispatch(removeQueryByID(query.id));
-              }
-            }}
-          />
-        </>
-      )}
-    </Tab>
+      </MenuContent>
+    </Menu>
   );
 };
 
-- 
GitLab