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