| 
							 | 
						import { useState, useCallback, useEffect } from 'react' | 
					
					
						
						| 
							 | 
						import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover' | 
					
					
						
						| 
							 | 
						import Checkbox from '@/components/ui/Checkbox' | 
					
					
						
						| 
							 | 
						import Button from '@/components/ui/Button' | 
					
					
						
						| 
							 | 
						import Separator from '@/components/ui/Separator' | 
					
					
						
						| 
							 | 
						import Input from '@/components/ui/Input' | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						import { controlButtonVariant } from '@/lib/constants' | 
					
					
						
						| 
							 | 
						import { useSettingsStore } from '@/stores/settings' | 
					
					
						
						| 
							 | 
						import { useBackendState } from '@/stores/state' | 
					
					
						
						| 
							 | 
						import { useSigma } from '@react-sigma/core' | 
					
					
						
						| 
							 | 
						import { useLayoutForceAtlas2 } from '@react-sigma/layout-forceatlas2' | 
					
					
						
						| 
							 | 
						import { animateNodes } from 'sigma/utils' | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						import { SettingsIcon, RefreshCwIcon } from 'lucide-react' | 
					
					
						
						| 
							 | 
						import { useTranslation } from 'react-i18next'; | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						const LabeledCheckBox = ({ | 
					
					
						
						| 
							 | 
						  checked, | 
					
					
						
						| 
							 | 
						  onCheckedChange, | 
					
					
						
						| 
							 | 
						  label | 
					
					
						
						| 
							 | 
						}: { | 
					
					
						
						| 
							 | 
						  checked: boolean | 
					
					
						
						| 
							 | 
						  onCheckedChange: () => void | 
					
					
						
						| 
							 | 
						  label: string | 
					
					
						
						| 
							 | 
						}) => { | 
					
					
						
						| 
							 | 
						  return ( | 
					
					
						
						| 
							 | 
						    <div className="flex items-center gap-2"> | 
					
					
						
						| 
							 | 
						      <Checkbox checked={checked} onCheckedChange={onCheckedChange} /> | 
					
					
						
						| 
							 | 
						      <label | 
					
					
						
						| 
							 | 
						        htmlFor="terms" | 
					
					
						
						| 
							 | 
						        className="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | 
					
					
						
						| 
							 | 
						      > | 
					
					
						
						| 
							 | 
						        {label} | 
					
					
						
						| 
							 | 
						      </label> | 
					
					
						
						| 
							 | 
						    </div> | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						} | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						const LabeledNumberInput = ({ | 
					
					
						
						| 
							 | 
						  value, | 
					
					
						
						| 
							 | 
						  onEditFinished, | 
					
					
						
						| 
							 | 
						  label, | 
					
					
						
						| 
							 | 
						  min, | 
					
					
						
						| 
							 | 
						  max | 
					
					
						
						| 
							 | 
						}: { | 
					
					
						
						| 
							 | 
						  value: number | 
					
					
						
						| 
							 | 
						  onEditFinished: (value: number) => void | 
					
					
						
						| 
							 | 
						  label: string | 
					
					
						
						| 
							 | 
						  min: number | 
					
					
						
						| 
							 | 
						  max?: number | 
					
					
						
						| 
							 | 
						}) => { | 
					
					
						
						| 
							 | 
						  const [currentValue, setCurrentValue] = useState<number | null>(value) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const onValueChange = useCallback( | 
					
					
						
						| 
							 | 
						    (e: React.ChangeEvent<HTMLInputElement>) => { | 
					
					
						
						| 
							 | 
						      const text = e.target.value.trim() | 
					
					
						
						| 
							 | 
						      if (text.length === 0) { | 
					
					
						
						| 
							 | 
						        setCurrentValue(null) | 
					
					
						
						| 
							 | 
						        return | 
					
					
						
						| 
							 | 
						      } | 
					
					
						
						| 
							 | 
						      const newValue = Number.parseInt(text) | 
					
					
						
						| 
							 | 
						      if (!isNaN(newValue) && newValue !== currentValue) { | 
					
					
						
						| 
							 | 
						        if (min !== undefined && newValue < min) { | 
					
					
						
						| 
							 | 
						          return | 
					
					
						
						| 
							 | 
						        } | 
					
					
						
						| 
							 | 
						        if (max !== undefined && newValue > max) { | 
					
					
						
						| 
							 | 
						          return | 
					
					
						
						| 
							 | 
						        } | 
					
					
						
						| 
							 | 
						        setCurrentValue(newValue) | 
					
					
						
						| 
							 | 
						      } | 
					
					
						
						| 
							 | 
						    }, | 
					
					
						
						| 
							 | 
						    [currentValue, min, max] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const onBlur = useCallback(() => { | 
					
					
						
						| 
							 | 
						    if (currentValue !== null && value !== currentValue) { | 
					
					
						
						| 
							 | 
						      onEditFinished(currentValue) | 
					
					
						
						| 
							 | 
						    } | 
					
					
						
						| 
							 | 
						  }, [value, currentValue, onEditFinished]) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  return ( | 
					
					
						
						| 
							 | 
						    <div className="flex flex-col gap-2"> | 
					
					
						
						| 
							 | 
						      <label | 
					
					
						
						| 
							 | 
						        htmlFor="terms" | 
					
					
						
						| 
							 | 
						        className="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70" | 
					
					
						
						| 
							 | 
						      > | 
					
					
						
						| 
							 | 
						        {label} | 
					
					
						
						| 
							 | 
						      </label> | 
					
					
						
						| 
							 | 
						      <Input | 
					
					
						
						| 
							 | 
						        type="number" | 
					
					
						
						| 
							 | 
						        value={currentValue === null ? '' : currentValue} | 
					
					
						
						| 
							 | 
						        onChange={onValueChange} | 
					
					
						
						| 
							 | 
						        className="h-6 w-full min-w-0 pr-1" | 
					
					
						
						| 
							 | 
						        min={min} | 
					
					
						
						| 
							 | 
						        max={max} | 
					
					
						
						| 
							 | 
						        onBlur={onBlur} | 
					
					
						
						| 
							 | 
						        onKeyDown={(e) => { | 
					
					
						
						| 
							 | 
						          if (e.key === 'Enter') { | 
					
					
						
						| 
							 | 
						            onBlur() | 
					
					
						
						| 
							 | 
						          } | 
					
					
						
						| 
							 | 
						        }} | 
					
					
						
						| 
							 | 
						      /> | 
					
					
						
						| 
							 | 
						    </div> | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						} | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						export default function Settings() { | 
					
					
						
						| 
							 | 
						  const [opened, setOpened] = useState<boolean>(false) | 
					
					
						
						| 
							 | 
						  const [tempApiKey, setTempApiKey] = useState<string>('') | 
					
					
						
						| 
							 | 
						  const sigma = useSigma() | 
					
					
						
						| 
							 | 
						  const maxIterations = useSettingsStore.use.graphLayoutMaxIterations() | 
					
					
						
						| 
							 | 
						  const layout = useLayoutForceAtlas2({ iterations: maxIterations }) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const refreshLayout = useCallback(() => { | 
					
					
						
						| 
							 | 
						    if (!sigma) return | 
					
					
						
						| 
							 | 
						    const graph = sigma.getGraph() | 
					
					
						
						| 
							 | 
						    const positions = layout.positions() | 
					
					
						
						| 
							 | 
						    animateNodes(graph, positions, { duration: 500 }) | 
					
					
						
						| 
							 | 
						  }, [sigma, layout]) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const showPropertyPanel = useSettingsStore.use.showPropertyPanel() | 
					
					
						
						| 
							 | 
						  const showNodeSearchBar = useSettingsStore.use.showNodeSearchBar() | 
					
					
						
						| 
							 | 
						  const showNodeLabel = useSettingsStore.use.showNodeLabel() | 
					
					
						
						| 
							 | 
						  const enableEdgeEvents = useSettingsStore.use.enableEdgeEvents() | 
					
					
						
						| 
							 | 
						  const enableNodeDrag = useSettingsStore.use.enableNodeDrag() | 
					
					
						
						| 
							 | 
						  const enableHideUnselectedEdges = useSettingsStore.use.enableHideUnselectedEdges() | 
					
					
						
						| 
							 | 
						  const showEdgeLabel = useSettingsStore.use.showEdgeLabel() | 
					
					
						
						| 
							 | 
						  const graphQueryMaxDepth = useSettingsStore.use.graphQueryMaxDepth() | 
					
					
						
						| 
							 | 
						  const graphMinDegree = useSettingsStore.use.graphMinDegree() | 
					
					
						
						| 
							 | 
						  const graphLayoutMaxIterations = useSettingsStore.use.graphLayoutMaxIterations() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const enableHealthCheck = useSettingsStore.use.enableHealthCheck() | 
					
					
						
						| 
							 | 
						  const apiKey = useSettingsStore.use.apiKey() | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  useEffect(() => { | 
					
					
						
						| 
							 | 
						    setTempApiKey(apiKey || '') | 
					
					
						
						| 
							 | 
						  }, [apiKey, opened]) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setEnableNodeDrag = useCallback( | 
					
					
						
						| 
							 | 
						    () => useSettingsStore.setState((pre) => ({ enableNodeDrag: !pre.enableNodeDrag })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						  const setEnableEdgeEvents = useCallback( | 
					
					
						
						| 
							 | 
						    () => useSettingsStore.setState((pre) => ({ enableEdgeEvents: !pre.enableEdgeEvents })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						  const setEnableHideUnselectedEdges = useCallback( | 
					
					
						
						| 
							 | 
						    () => | 
					
					
						
						| 
							 | 
						      useSettingsStore.setState((pre) => ({ | 
					
					
						
						| 
							 | 
						        enableHideUnselectedEdges: !pre.enableHideUnselectedEdges | 
					
					
						
						| 
							 | 
						      })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						  const setShowEdgeLabel = useCallback( | 
					
					
						
						| 
							 | 
						    () => | 
					
					
						
						| 
							 | 
						      useSettingsStore.setState((pre) => ({ | 
					
					
						
						| 
							 | 
						        showEdgeLabel: !pre.showEdgeLabel | 
					
					
						
						| 
							 | 
						      })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						   | 
					
					
						
						| 
							 | 
						  const setShowPropertyPanel = useCallback( | 
					
					
						
						| 
							 | 
						    () => useSettingsStore.setState((pre) => ({ showPropertyPanel: !pre.showPropertyPanel })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setShowNodeSearchBar = useCallback( | 
					
					
						
						| 
							 | 
						    () => useSettingsStore.setState((pre) => ({ showNodeSearchBar: !pre.showNodeSearchBar })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setShowNodeLabel = useCallback( | 
					
					
						
						| 
							 | 
						    () => useSettingsStore.setState((pre) => ({ showNodeLabel: !pre.showNodeLabel })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setEnableHealthCheck = useCallback( | 
					
					
						
						| 
							 | 
						    () => useSettingsStore.setState((pre) => ({ enableHealthCheck: !pre.enableHealthCheck })), | 
					
					
						
						| 
							 | 
						    [] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setGraphQueryMaxDepth = useCallback((depth: number) => { | 
					
					
						
						| 
							 | 
						    if (depth < 1) return | 
					
					
						
						| 
							 | 
						    useSettingsStore.setState({ graphQueryMaxDepth: depth }) | 
					
					
						
						| 
							 | 
						  }, []) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setGraphMinDegree = useCallback((degree: number) => { | 
					
					
						
						| 
							 | 
						    if (degree < 0) return | 
					
					
						
						| 
							 | 
						    useSettingsStore.setState({ graphMinDegree: degree }) | 
					
					
						
						| 
							 | 
						  }, []) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setGraphLayoutMaxIterations = useCallback((iterations: number) => { | 
					
					
						
						| 
							 | 
						    if (iterations < 1) return | 
					
					
						
						| 
							 | 
						    useSettingsStore.setState({ graphLayoutMaxIterations: iterations }) | 
					
					
						
						| 
							 | 
						  }, []) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const setApiKey = useCallback(async () => { | 
					
					
						
						| 
							 | 
						    useSettingsStore.setState({ apiKey: tempApiKey || null }) | 
					
					
						
						| 
							 | 
						    await useBackendState.getState().check() | 
					
					
						
						| 
							 | 
						    setOpened(false) | 
					
					
						
						| 
							 | 
						  }, [tempApiKey]) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const handleTempApiKeyChange = useCallback( | 
					
					
						
						| 
							 | 
						    (e: React.ChangeEvent<HTMLInputElement>) => { | 
					
					
						
						| 
							 | 
						      setTempApiKey(e.target.value) | 
					
					
						
						| 
							 | 
						    }, | 
					
					
						
						| 
							 | 
						    [setTempApiKey] | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  const { t } = useTranslation(); | 
					
					
						
						| 
							 | 
						
 | 
					
					
						
						| 
							 | 
						  return ( | 
					
					
						
						| 
							 | 
						    <> | 
					
					
						
						| 
							 | 
						      <Button | 
					
					
						
						| 
							 | 
						        variant={controlButtonVariant} | 
					
					
						
						| 
							 | 
						        tooltip={t('graphPanel.sideBar.settings.refreshLayout')} | 
					
					
						
						| 
							 | 
						        size="icon" | 
					
					
						
						| 
							 | 
						        onClick={refreshLayout} | 
					
					
						
						| 
							 | 
						      > | 
					
					
						
						| 
							 | 
						        <RefreshCwIcon /> | 
					
					
						
						| 
							 | 
						      </Button> | 
					
					
						
						| 
							 | 
						      <Popover open={opened} onOpenChange={setOpened}> | 
					
					
						
						| 
							 | 
						        <PopoverTrigger asChild> | 
					
					
						
						| 
							 | 
						          <Button variant={controlButtonVariant} tooltip={t('graphPanel.sideBar.settings.settings')} size="icon"> | 
					
					
						
						| 
							 | 
						            <SettingsIcon /> | 
					
					
						
						| 
							 | 
						          </Button> | 
					
					
						
						| 
							 | 
						        </PopoverTrigger> | 
					
					
						
						| 
							 | 
						        <PopoverContent | 
					
					
						
						| 
							 | 
						          side="right" | 
					
					
						
						| 
							 | 
						          align="start" | 
					
					
						
						| 
							 | 
						          className="mb-2 p-2" | 
					
					
						
						| 
							 | 
						          onCloseAutoFocus={(e) => e.preventDefault()} | 
					
					
						
						| 
							 | 
						        > | 
					
					
						
						| 
							 | 
						          <div className="flex flex-col gap-2"> | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={enableHealthCheck} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setEnableHealthCheck} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.healthCheck')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <Separator /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={showPropertyPanel} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setShowPropertyPanel} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.showPropertyPanel')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={showNodeSearchBar} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setShowNodeSearchBar} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.showSearchBar')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <Separator /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={showNodeLabel} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setShowNodeLabel} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.showNodeLabel')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={enableNodeDrag} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setEnableNodeDrag} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.nodeDraggable')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <Separator /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={showEdgeLabel} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setShowEdgeLabel} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.showEdgeLabel')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={enableHideUnselectedEdges} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setEnableHideUnselectedEdges} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.hideUnselectedEdges')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <LabeledCheckBox | 
					
					
						
						| 
							 | 
						              checked={enableEdgeEvents} | 
					
					
						
						| 
							 | 
						              onCheckedChange={setEnableEdgeEvents} | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.edgeEvents')} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <Separator /> | 
					
					
						
						| 
							 | 
						            <LabeledNumberInput | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.maxQueryDepth')} | 
					
					
						
						| 
							 | 
						              min={1} | 
					
					
						
						| 
							 | 
						              value={graphQueryMaxDepth} | 
					
					
						
						| 
							 | 
						              onEditFinished={setGraphQueryMaxDepth} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <LabeledNumberInput | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.minDegree')} | 
					
					
						
						| 
							 | 
						              min={0} | 
					
					
						
						| 
							 | 
						              value={graphMinDegree} | 
					
					
						
						| 
							 | 
						              onEditFinished={setGraphMinDegree} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <LabeledNumberInput | 
					
					
						
						| 
							 | 
						              label={t('graphPanel.sideBar.settings.maxLayoutIterations')} | 
					
					
						
						| 
							 | 
						              min={1} | 
					
					
						
						| 
							 | 
						              max={30} | 
					
					
						
						| 
							 | 
						              value={graphLayoutMaxIterations} | 
					
					
						
						| 
							 | 
						              onEditFinished={setGraphLayoutMaxIterations} | 
					
					
						
						| 
							 | 
						            /> | 
					
					
						
						| 
							 | 
						            <Separator /> | 
					
					
						
						| 
							 | 
						 | 
					
					
						
						| 
							 | 
						            <div className="flex flex-col gap-2"> | 
					
					
						
						| 
							 | 
						              <label className="text-sm font-medium">{t('graphPanel.sideBar.settings.apiKey')}</label> | 
					
					
						
						| 
							 | 
						              <form className="flex h-6 gap-2" onSubmit={(e) => e.preventDefault()}> | 
					
					
						
						| 
							 | 
						                <div className="w-0 flex-1"> | 
					
					
						
						| 
							 | 
						                  <Input | 
					
					
						
						| 
							 | 
						                    type="password" | 
					
					
						
						| 
							 | 
						                    value={tempApiKey} | 
					
					
						
						| 
							 | 
						                    onChange={handleTempApiKeyChange} | 
					
					
						
						| 
							 | 
						                    placeholder={t('graphPanel.sideBar.settings.enterYourAPIkey')} | 
					
					
						
						| 
							 | 
						                    className="max-h-full w-full min-w-0" | 
					
					
						
						| 
							 | 
						                    autoComplete="off" | 
					
					
						
						| 
							 | 
						                  /> | 
					
					
						
						| 
							 | 
						                </div> | 
					
					
						
						| 
							 | 
						                <Button | 
					
					
						
						| 
							 | 
						                  onClick={setApiKey} | 
					
					
						
						| 
							 | 
						                  variant="outline" | 
					
					
						
						| 
							 | 
						                  size="sm" | 
					
					
						
						| 
							 | 
						                  className="max-h-full shrink-0" | 
					
					
						
						| 
							 | 
						                > | 
					
					
						
						| 
							 | 
						                  {t('graphPanel.sideBar.settings.save')} | 
					
					
						
						| 
							 | 
						                </Button> | 
					
					
						
						| 
							 | 
						              </form> | 
					
					
						
						| 
							 | 
						            </div> | 
					
					
						
						| 
							 | 
						          </div> | 
					
					
						
						| 
							 | 
						        </PopoverContent> | 
					
					
						
						| 
							 | 
						      </Popover> | 
					
					
						
						| 
							 | 
						    </> | 
					
					
						
						| 
							 | 
						  ) | 
					
					
						
						| 
							 | 
						} | 
					
					
						
						| 
							 | 
						
 |