diff --git a/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx b/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx index 820d0d462c994d867f15d0e04355482f3f6afad0..0a68e06a10a9e1243440fef80c8fce7a5924fe68 100644 --- a/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx +++ b/apps/web/src/components/navbar/DatabaseManagement/dbConnectionSelector.tsx @@ -9,6 +9,7 @@ import { DropdownButton, DropdownContainer, DropdownItemContainer } from '@graph import { clearQB } from '@graphpolaris/shared/lib/data-access/store/querybuilderSlice'; import { clearSchema } from '@graphpolaris/shared/lib/data-access/store/schemaSlice'; import { DatabaseStatus, SaveStateI, nilUUID, wsDeleteState } from '@graphpolaris/shared/lib/data-access/broker'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@graphpolaris/shared/lib/components/tooltip'; export default function DatabaseSelector({}) { const dispatch = useAppDispatch(); @@ -70,156 +71,181 @@ export default function DatabaseSelector({}) { return ( <div className="menu-walkthrough"> - {settingsMenuOpen !== undefined && ( - <SettingsForm - open={settingsMenuOpen} - saveState={settingsMenuOpen === 'update' ? selectedSaveState : null} - disableCancel={ - (session.saveStates && Object.keys(session.saveStates).length === 0) || - session.currentSaveState === '00000000-0000-0000-0000-000000000000' - } - onClose={() => { - setSettingsMenuOpen(undefined); - }} - /> - )} - <DropdownContainer ref={dbSelectionMenuRef} className="w-[20rem]"> - <DropdownButton - disabled={connecting || authCache.authorized === false || !!authCache.roomID} - title={ - <div className="flex items-center"> - {connecting && session.currentSaveState && session.currentSaveState in session.saveStates ? ( - <> - <LoadingSpinner /> - <p className="ml-2 truncate">Connecting to {session.saveStates[session.currentSaveState].name}</p> - </> - ) : session.currentSaveState && session.currentSaveState in session.saveStates && session.currentSaveState !== nilUUID ? ( - <> - <div - className={`h-2 w-2 rounded-full ${ - session.testedSaveState[session.currentSaveState] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500' - }`} - /> - <p className="ml-2 truncate">Connected DB: {session.saveStates[session.currentSaveState].name}</p> - </> - ) : session.saveStates === undefined ? ( - <> - <LoadingSpinner /> - <p className="ml-2">Retrieving databases</p> - </> - ) : Object.keys(session.saveStates).length === 0 || session.currentSaveState === nilUUID ? ( - <> - <p className="ml-2">Add your first Database</p> - </> - ) : ( - <> - <div className="h-2 w-2 rounded-full bg-secondary-500" /> - <p className="ml-2">Select a database</p> - </> - )} - </div> - } - onClick={() => { - if (session.saveStates && Object.keys(session.saveStates).length === 0) setSettingsMenuOpen('add'); - else setDbSelectionMenuOpen(!dbSelectionMenuOpen); - }} - /> + <TooltipProvider delayDuration={1000}> + {settingsMenuOpen !== undefined && ( + <SettingsForm + open={settingsMenuOpen} + saveState={settingsMenuOpen === 'update' ? selectedSaveState : null} + disableCancel={ + (session.saveStates && Object.keys(session.saveStates).length === 0) || + session.currentSaveState === '00000000-0000-0000-0000-000000000000' + } + onClose={() => { + setSettingsMenuOpen(undefined); + }} + /> + )} + <DropdownContainer ref={dbSelectionMenuRef} className="w-[20rem]"> + <DropdownButton + disabled={connecting || authCache.authorized === false || !!authCache.roomID} + title={ + <div className="flex items-center"> + {connecting && session.currentSaveState && session.currentSaveState in session.saveStates ? ( + <> + <LoadingSpinner /> + <p className="ml-2 truncate">Connecting to {session.saveStates[session.currentSaveState].name}</p> + </> + ) : session.currentSaveState && session.currentSaveState in session.saveStates && session.currentSaveState !== nilUUID ? ( + <> + <div + className={`h-2 w-2 rounded-full ${ + session.testedSaveState[session.currentSaveState] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500' + }`} + /> + <p className="ml-2 truncate">Connected DB: {session.saveStates[session.currentSaveState].name}</p> + </> + ) : session.saveStates === undefined ? ( + <> + <LoadingSpinner /> + <p className="ml-2">Retrieving databases</p> + </> + ) : Object.keys(session.saveStates).length === 0 || session.currentSaveState === nilUUID ? ( + <> + <p className="ml-2">Add your first Database</p> + </> + ) : ( + <> + <div className="h-2 w-2 rounded-full bg-secondary-500" /> + <p className="ml-2">Select a database</p> + </> + )} + </div> + } + onClick={() => { + if (session.saveStates && Object.keys(session.saveStates).length === 0) setSettingsMenuOpen('add'); + else setDbSelectionMenuOpen(!dbSelectionMenuOpen); + }} + /> - {dbSelectionMenuOpen && session.saveStates !== undefined && ( - <DropdownItemContainer align="top-10 w-full"> - <li - className="flex items-center p-2 hover:bg-secondary-50 cursor-pointer" - onClick={(e) => { - e.preventDefault(); - setDbSelectionMenuOpen(false); - setConnecting(false); - setSettingsMenuOpen('add'); - }} - title="Add new database" - > - {session.saveStates && Object.keys(session.saveStates).length === 0 ? ( - <> - <Add /> - <p className="ml-2">Add your first database</p> - </> - ) : ( - <> - <Add /> - <p className="ml-2">Add database</p> - </> - )} - </li> - {Object.values(session.saveStates) - .filter((save) => save.id !== nilUUID) - .map((save) => ( - <li - key={save.id} - className="flex justify-between items-center px-4 py-2 hover:bg-primary-100 gap-2 cursor-pointer" - onClick={(e) => { - if (save.id !== session.currentSaveState) { - e.preventDefault(); - setDbSelectionMenuOpen(false); - setConnecting(true); - dispatch(selectSaveState(save.id)); - dispatch(clearQB()); - dispatch(clearSchema()); - } else { - setDbSelectionMenuOpen(false); - } - }} - onMouseEnter={() => setHovered(save.id)} - onMouseLeave={() => setHovered(null)} - title={`Connect to ${save.name}`} - > - <div - className={`h-[8px] w-[8px] rounded-full shrink-0 ${ - session.testedSaveState[save.id] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500' - }`} - /> - <div className="w-full shrink min-w-0 flex flex-col"> - <p className="truncate w-full shrink-0 min-w-0">{save.name}</p> - <p className="bg-light text-2xs text-secondary-500 truncate w-fit shrink-0 min-w-0 max-w-full h-full border border-secondary-200 rounded-sm p-0.5"> - {save.db.protocol} - {save.db.url} - </p> - </div> - {hovered === save.id && ( - <div className="flex items-center ml-2"> - <div - className="text-secondary-700 hover:text-secondary-400 transition-colors duration-300" - onClick={(e) => { - e.preventDefault(); - e.stopPropagation(); - setSettingsMenuOpen('update'); - setSelectedSaveState(save); - }} - > - <Settings /> - </div> - <div - className="text-secondary-700 hover:text-secondary-400 transition-colors duration-300" - onClick={(e) => { - e.preventDefault(); - e.stopPropagation(); - setDbSelectionMenuOpen(false); - if (session.currentSaveState === save.id) { - dispatch(clearQB()); - dispatch(clearSchema()); - } - wsDeleteState(save.id); - dispatch(deleteSaveState(save.id)); - }} - title="Delete database connection" - > - <Delete /> - </div> + {dbSelectionMenuOpen && session.saveStates !== undefined && ( + <DropdownItemContainer align="top-10 w-full"> + <li + className="flex items-center p-2 hover:bg-secondary-50 cursor-pointer" + onClick={(e) => { + e.preventDefault(); + setDbSelectionMenuOpen(false); + setConnecting(false); + setSettingsMenuOpen('add'); + }} + title="Add new database" + > + {session.saveStates && Object.keys(session.saveStates).length === 0 ? ( + <> + <Add /> + <p className="ml-2">Add your first database</p> + </> + ) : ( + <> + <Add /> + <p className="ml-2">Add database</p> + </> + )} + </li> + {Object.values(session.saveStates) + .filter((save) => save.id !== nilUUID) + .map((save) => ( + <li + key={save.id} + className="flex justify-between items-center px-4 py-2 hover:bg-primary-100 gap-2 cursor-pointer" + onClick={(e) => { + if (save.id !== session.currentSaveState) { + e.preventDefault(); + setDbSelectionMenuOpen(false); + setConnecting(true); + dispatch(selectSaveState(save.id)); + dispatch(clearQB()); + dispatch(clearSchema()); + } else { + setDbSelectionMenuOpen(false); + } + }} + onMouseEnter={() => setHovered(save.id)} + onMouseLeave={() => setHovered(null)} + > + <Tooltip> + <TooltipTrigger> + <div + className={`h-[8px] w-[8px] rounded-full shrink-0 ${ + session.testedSaveState[save.id] === DatabaseStatus.tested ? 'bg-success-500' : 'bg-danger-500' + }`} + /> + </TooltipTrigger> + <TooltipContent side={'left'}> + <p> + {session.testedSaveState[save.id] === DatabaseStatus.tested + ? 'Database connection tested' + : 'Something went wrong when trying to connect'} + </p> + </TooltipContent> + </Tooltip> + <div className="w-full shrink min-w-0 flex flex-col"> + <p className="truncate w-full shrink-0 min-w-0">{save.name}</p> + <p className="bg-light text-2xs text-secondary-500 truncate w-fit shrink-0 min-w-0 max-w-full h-full border border-secondary-200 rounded-sm p-0.5"> + {save.db.protocol} + {save.db.url} + </p> </div> - )} - </li> - ))} - </DropdownItemContainer> - )} - </DropdownContainer> + {hovered === save.id && ( + <div className="flex items-center ml-2"> + <div + className="text-secondary-700 hover:text-secondary-400 transition-colors duration-300" + onClick={(e) => { + e.preventDefault(); + e.stopPropagation(); + setSettingsMenuOpen('update'); + setSelectedSaveState(save); + }} + > + <Tooltip> + <TooltipTrigger> + <Settings /> + </TooltipTrigger> + <TooltipContent side={'bottom'}> + <p>Change the connection details</p> + </TooltipContent> + </Tooltip> + </div> + <div + className="text-secondary-700 hover:text-secondary-400 transition-colors duration-300" + onClick={(e) => { + e.preventDefault(); + e.stopPropagation(); + setDbSelectionMenuOpen(false); + if (session.currentSaveState === save.id) { + dispatch(clearQB()); + dispatch(clearSchema()); + } + wsDeleteState(save.id); + dispatch(deleteSaveState(save.id)); + }} + > + <Tooltip> + <TooltipTrigger> + <Delete /> + </TooltipTrigger> + <TooltipContent side={'bottom'}> + <p>Delete the database</p> + </TooltipContent> + </Tooltip> + </div> + </div> + )} + </li> + ))} + </DropdownItemContainer> + )} + </DropdownContainer> + </TooltipProvider> </div> ); }