From adaf91a7917d6eb49a74b969019270cae5608175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nuno=20G=C3=B3is?= Date: Fri, 20 Dec 2024 11:02:49 +0000 Subject: [PATCH] chore: remove Unleash AI (#9010) https://linear.app/unleash/issue/2-3071/finish-experiment Removes Unleash AI. Also removes other related changes made during the experiment development. --- frontend/src/assets/icons/AI.svg | 3 - frontend/src/assets/img/aiPreview.svg | 24 -- frontend/src/component/ai/AIChat.tsx | 274 ---------------- .../src/component/ai/AIChatDisclaimer.tsx | 19 -- frontend/src/component/ai/AIChatHeader.tsx | 64 ---- frontend/src/component/ai/AIChatInput.tsx | 116 ------- frontend/src/component/ai/AIChatMessage.tsx | 103 ------ .../common/Highlight/HighlightProvider.tsx | 1 - .../component/common/Resizable/Resizable.tsx | 296 ------------------ .../layout/MainLayout/MainLayout.tsx | 2 - .../NewInUnleash/NewInUnleash.tsx | 40 +-- .../hooks/api/actions/useAIApi/useAIApi.ts | 55 ---- frontend/src/hooks/usePlausibleTracker.ts | 1 - frontend/src/interfaces/uiConfig.ts | 2 - .../openapi/spec/ai-chat-message-schema.ts | 27 -- .../spec/ai-chat-new-message-schema.ts | 20 -- src/lib/openapi/spec/ai-chat-schema.ts | 45 --- src/lib/openapi/spec/index.ts | 3 - src/lib/openapi/spec/ui-config-schema.ts | 5 - src/lib/routes/admin-api/config.ts | 1 - src/lib/types/experimental.ts | 5 - .../20241220102327-drop-ai-chats.js | 26 ++ src/server-dev.ts | 1 - 23 files changed, 27 insertions(+), 1106 deletions(-) delete mode 100644 frontend/src/assets/icons/AI.svg delete mode 100644 frontend/src/assets/img/aiPreview.svg delete mode 100644 frontend/src/component/ai/AIChat.tsx delete mode 100644 frontend/src/component/ai/AIChatDisclaimer.tsx delete mode 100644 frontend/src/component/ai/AIChatHeader.tsx delete mode 100644 frontend/src/component/ai/AIChatInput.tsx delete mode 100644 frontend/src/component/ai/AIChatMessage.tsx delete mode 100644 frontend/src/component/common/Resizable/Resizable.tsx delete mode 100644 frontend/src/hooks/api/actions/useAIApi/useAIApi.ts delete mode 100644 src/lib/openapi/spec/ai-chat-message-schema.ts delete mode 100644 src/lib/openapi/spec/ai-chat-new-message-schema.ts delete mode 100644 src/lib/openapi/spec/ai-chat-schema.ts create mode 100644 src/migrations/20241220102327-drop-ai-chats.js diff --git a/frontend/src/assets/icons/AI.svg b/frontend/src/assets/icons/AI.svg deleted file mode 100644 index b6d25d059fb6..000000000000 --- a/frontend/src/assets/icons/AI.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/frontend/src/assets/img/aiPreview.svg b/frontend/src/assets/img/aiPreview.svg deleted file mode 100644 index 5700cb8a788f..000000000000 --- a/frontend/src/assets/img/aiPreview.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/frontend/src/component/ai/AIChat.tsx b/frontend/src/component/ai/AIChat.tsx deleted file mode 100644 index 193ee3f34fe3..000000000000 --- a/frontend/src/component/ai/AIChat.tsx +++ /dev/null @@ -1,274 +0,0 @@ -import { mutate } from 'swr'; -import { ReactComponent as AIIcon } from 'assets/icons/AI.svg'; -import { IconButton, styled, Tooltip, useMediaQuery } from '@mui/material'; -import { useEffect, useRef, useState } from 'react'; -import useToast from 'hooks/useToast'; -import { formatUnknownError } from 'utils/formatUnknownError'; -import { - type ChatMessage, - useAIApi, -} from 'hooks/api/actions/useAIApi/useAIApi'; -import { useUiFlag } from 'hooks/useUiFlag'; -import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; -import { AIChatInput } from './AIChatInput'; -import { AIChatMessage } from './AIChatMessage'; -import { AIChatHeader } from './AIChatHeader'; -import { Resizable } from 'component/common/Resizable/Resizable'; -import { AIChatDisclaimer } from './AIChatDisclaimer'; -import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; -import theme from 'themes/theme'; -import { Highlight } from 'component/common/Highlight/Highlight'; - -const AI_ERROR_MESSAGE = { - role: 'assistant', - content: `I'm sorry, I'm having trouble understanding you right now. I've reported the issue to the team. Please try again later.`, -} as const; - -type ScrollOptions = ScrollIntoViewOptions & { - onlyIfAtEnd?: boolean; -}; - -const StyledAIIconContainer = styled('div', { - shouldForwardProp: (prop) => prop !== 'demoStepsVisible', -})<{ demoStepsVisible: boolean }>(({ theme, demoStepsVisible }) => ({ - position: 'fixed', - bottom: 20, - right: 20, - ...(demoStepsVisible && { - right: 260, - }), - zIndex: theme.zIndex.fab, - animation: 'fadeInBottom 0.5s', - '@keyframes fadeInBottom': { - from: { - opacity: 0, - transform: 'translateY(200px)', - }, - to: { - opacity: 1, - transform: 'translateY(0)', - }, - }, -})); - -const StyledAIChatContainer = styled(StyledAIIconContainer, { - shouldForwardProp: (prop) => prop !== 'demoStepsVisible', -})<{ demoStepsVisible: boolean }>(({ demoStepsVisible }) => ({ - bottom: 10, - right: 10, - ...(demoStepsVisible && { - right: 250, - }), -})); - -const StyledResizable = styled(Resizable)(({ theme }) => ({ - boxShadow: theme.boxShadows.popup, - borderRadius: theme.shape.borderRadiusLarge, -})); - -const StyledAIIconButton = styled(IconButton)(({ theme }) => ({ - background: - theme.mode === 'light' - ? theme.palette.primary.main - : theme.palette.primary.light, - color: theme.palette.primary.contrastText, - boxShadow: theme.boxShadows.popup, - transition: 'background 0.3s', - '&:hover': { - background: theme.palette.primary.dark, - }, - '& > svg': { - width: theme.spacing(3), - height: theme.spacing(3), - }, -})); - -const StyledChat = styled('div')(({ theme }) => ({ - display: 'flex', - flex: 1, - flexDirection: 'column', - overflow: 'hidden', - background: theme.palette.background.paper, -})); - -const StyledChatContent = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - padding: theme.spacing(2), - paddingBottom: theme.spacing(1), - flex: 1, - overflowY: 'auto', - overflowX: 'hidden', -})); - -export const AIChat = () => { - const unleashAIEnabled = useUiFlag('unleashAI'); - const demoEnabled = useUiFlag('demo'); - const isSmallScreen = useMediaQuery(theme.breakpoints.down(768)); - const { - uiConfig: { unleashAIAvailable }, - } = useUiConfig(); - const [open, setOpen] = useState(false); - const [loading, setLoading] = useState(false); - const { setToastApiError } = useToast(); - const { chat, newChat } = useAIApi(); - const { trackEvent } = usePlausibleTracker(); - - const [messages, setMessages] = useState([]); - - const isAtEndRef = useRef(true); - const chatEndRef = useRef(null); - - const scrollToEnd = (options?: ScrollOptions) => { - if (chatEndRef.current) { - const shouldScroll = !options?.onlyIfAtEnd || isAtEndRef.current; - - if (shouldScroll) { - chatEndRef.current.scrollIntoView(options); - } - } - }; - - useEffect(() => { - requestAnimationFrame(() => { - scrollToEnd(); - }); - - const intersectionObserver = new IntersectionObserver( - ([entry]) => { - isAtEndRef.current = entry.isIntersecting; - }, - { threshold: 1.0 }, - ); - - if (chatEndRef.current) { - intersectionObserver.observe(chatEndRef.current); - } - - return () => { - if (chatEndRef.current) { - intersectionObserver.unobserve(chatEndRef.current); - } - }; - }, [open]); - - useEffect(() => { - scrollToEnd({ behavior: 'smooth', onlyIfAtEnd: true }); - }, [messages]); - - const onSend = async (content: string) => { - if (!content.trim() || loading) return; - - trackEvent('unleash-ai-chat', { - props: { - eventType: 'send', - }, - }); - - try { - setLoading(true); - setMessages((currentMessages) => [ - ...currentMessages, - { role: 'user', content }, - ]); - const { messages: newMessages } = await chat(content); - mutate(() => true); - setMessages(newMessages); - } catch (error: unknown) { - setMessages((currentMessages) => [ - ...currentMessages, - AI_ERROR_MESSAGE, - ]); - setToastApiError(formatUnknownError(error)); - } finally { - setLoading(false); - } - }; - - const onNewChat = () => { - setMessages([]); - newChat(); - }; - - const demoStepsVisible = demoEnabled && !isSmallScreen; - - if (!unleashAIEnabled || !unleashAIAvailable) { - return null; - } - - if (!open) { - return ( - - - - { - trackEvent('unleash-ai-chat', { - props: { - eventType: 'open', - }, - }); - setOpen(true); - }} - > - - - - - - ); - } - - return ( - - - scrollToEnd({ onlyIfAtEnd: true })} - > - - { - trackEvent('unleash-ai-chat', { - props: { - eventType: 'close', - }, - }); - setOpen(false); - }} - /> - - - - Hello, how can I assist you? - - {messages.map(({ role, content }, index) => ( - - {content} - - ))} - {loading && ( - - _Unleash AI is typing..._ - - )} -
- - - scrollToEnd({ onlyIfAtEnd: true }) - } - /> - - - - - ); -}; diff --git a/frontend/src/component/ai/AIChatDisclaimer.tsx b/frontend/src/component/ai/AIChatDisclaimer.tsx deleted file mode 100644 index f593af2f7fb2..000000000000 --- a/frontend/src/component/ai/AIChatDisclaimer.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { styled } from '@mui/material'; - -const StyledDisclaimer = styled('aside')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - textAlign: 'center', - width: '100%', - color: theme.palette.secondary.dark, - fontSize: theme.fontSizes.smallerBody, - marginBottom: theme.spacing(2), -})); - -export const AIChatDisclaimer = () => ( - - By using this assistant you accept that all data you share in this chat - can be shared with OpenAI - -); diff --git a/frontend/src/component/ai/AIChatHeader.tsx b/frontend/src/component/ai/AIChatHeader.tsx deleted file mode 100644 index 6087327c0375..000000000000 --- a/frontend/src/component/ai/AIChatHeader.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { IconButton, styled, Tooltip, Typography } from '@mui/material'; -import { ReactComponent as AIIcon } from 'assets/icons/AI.svg'; -import EditNoteIcon from '@mui/icons-material/EditNote'; -import CloseIcon from '@mui/icons-material/Close'; - -const StyledHeader = styled('div')(({ theme }) => ({ - background: - theme.mode === 'light' - ? theme.palette.primary.main - : theme.palette.primary.light, - color: theme.palette.primary.contrastText, - display: 'flex', - alignItems: 'center', - justifyContent: 'space-between', - padding: theme.spacing(0.5), -})); - -const StyledTitleContainer = styled('div')(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - gap: theme.spacing(1), - marginLeft: theme.spacing(1), -})); - -const StyledTitle = styled(Typography)({ - fontWeight: 'bold', -}); - -const StyledActionsContainer = styled('div')({ - display: 'flex', - alignItems: 'center', -}); - -const StyledIconButton = styled(IconButton)(({ theme }) => ({ - color: theme.palette.primary.contrastText, -})); - -interface IAIChatHeaderProps { - onNew: () => void; - onClose: () => void; -} - -export const AIChatHeader = ({ onNew, onClose }: IAIChatHeaderProps) => { - return ( - - - - Unleash AI - - - - - - - - - - - - - - - ); -}; diff --git a/frontend/src/component/ai/AIChatInput.tsx b/frontend/src/component/ai/AIChatInput.tsx deleted file mode 100644 index a119fd8d51ba..000000000000 --- a/frontend/src/component/ai/AIChatInput.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { useEffect, useRef, useState } from 'react'; -import { - IconButton, - InputAdornment, - styled, - TextField, - Tooltip, -} from '@mui/material'; -import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; - -const StyledAIChatInputContainer = styled('div')(({ theme }) => ({ - background: theme.palette.background.paper, - display: 'flex', - alignItems: 'center', - padding: theme.spacing(1), - paddingTop: 0, -})); - -const StyledAIChatInput = styled(TextField)(({ theme }) => ({ - margin: theme.spacing(1), - marginTop: 0, -})); - -const StyledInputAdornment = styled(InputAdornment)({ - marginLeft: 0, -}); - -const StyledIconButton = styled(IconButton)({ - padding: 0, -}); - -export interface IAIChatInputProps { - onSend: (message: string) => void; - loading: boolean; - onHeightChange?: () => void; -} - -export const AIChatInput = ({ - onSend, - loading, - onHeightChange, -}: IAIChatInputProps) => { - const [message, setMessage] = useState(''); - - const inputContainerRef = useRef(null); - const previousHeightRef = useRef(0); - - useEffect(() => { - const resizeObserver = new ResizeObserver(([entry]) => { - const newHeight = entry.contentRect.height; - - if (newHeight !== previousHeightRef.current) { - previousHeightRef.current = newHeight; - onHeightChange?.(); - } - }); - - if (inputContainerRef.current) { - resizeObserver.observe(inputContainerRef.current); - } - - return () => { - if (inputContainerRef.current) { - resizeObserver.unobserve(inputContainerRef.current); - } - }; - }, [onHeightChange]); - - const send = () => { - if (!message.trim() || loading) return; - onSend(message); - setMessage(''); - }; - - return ( - - setMessage(e.target.value)} - onKeyDown={(e) => { - e.stopPropagation(); - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - send(); - } - }} - InputProps={{ - sx: { paddingRight: 1 }, - endAdornment: ( - - -
- - - -
-
-
- ), - }} - /> -
- ); -}; diff --git a/frontend/src/component/ai/AIChatMessage.tsx b/frontend/src/component/ai/AIChatMessage.tsx deleted file mode 100644 index 6680d2c5a069..000000000000 --- a/frontend/src/component/ai/AIChatMessage.tsx +++ /dev/null @@ -1,103 +0,0 @@ -import { Avatar, styled } from '@mui/material'; -import { ReactComponent as AIIcon } from 'assets/icons/AI.svg'; -import { Markdown } from 'component/common/Markdown/Markdown'; -import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser'; -import type { ChatMessage } from 'hooks/api/actions/useAIApi/useAIApi'; - -const StyledMessageContainer = styled('div')(({ theme }) => ({ - display: 'flex', - justifyContent: 'flex-start', - gap: theme.spacing(1), - marginTop: theme.spacing(1), - marginBottom: theme.spacing(1), - '&:first-of-type': { - marginTop: 0, - }, - '&:last-of-type': { - marginBottom: 0, - }, - wordBreak: 'break-word', -})); - -const StyledUserMessageContainer = styled(StyledMessageContainer)({ - justifyContent: 'end', -}); - -const StyledAIMessage = styled('div')(({ theme }) => ({ - background: theme.palette.secondary.light, - color: theme.palette.secondary.contrastText, - border: `1px solid ${theme.palette.secondary.border}`, - borderRadius: theme.shape.borderRadius, - display: 'inline-block', - wordWrap: 'break-word', - padding: theme.spacing(0.75), - position: 'relative', - '&::before': { - content: '""', - position: 'absolute', - top: '12px', - left: '-10px', - width: '0', - height: '0', - borderStyle: 'solid', - borderWidth: '5px', - borderColor: `transparent ${theme.palette.secondary.border} transparent transparent`, - }, - pre: { - whiteSpace: 'pre-wrap', - }, -})); - -const StyledUserMessage = styled(StyledAIMessage)(({ theme }) => ({ - background: theme.palette.neutral.light, - color: theme.palette.neutral.contrastText, - borderColor: theme.palette.neutral.border, - '&::before': { - left: 'auto', - right: '-10px', - borderColor: `transparent transparent transparent ${theme.palette.neutral.border}`, - }, -})); - -const StyledAvatar = styled(Avatar)(({ theme }) => ({ - width: theme.spacing(4.5), - height: theme.spacing(4.5), - backgroundColor: - theme.mode === 'light' - ? theme.palette.primary.main - : theme.palette.primary.light, - color: theme.palette.primary.contrastText, -})); - -interface IAIChatMessageProps { - from: ChatMessage['role']; - children: string; -} - -export const AIChatMessage = ({ from, children }: IAIChatMessageProps) => { - const { user } = useAuthUser(); - - if (from === 'user') { - return ( - - - {children} - - - - ); - } - - if (from === 'assistant') { - return ( - - - - - - {children} - - - ); - } -}; diff --git a/frontend/src/component/common/Highlight/HighlightProvider.tsx b/frontend/src/component/common/Highlight/HighlightProvider.tsx index e18bbd2458af..e41826c6ee28 100644 --- a/frontend/src/component/common/Highlight/HighlightProvider.tsx +++ b/frontend/src/component/common/Highlight/HighlightProvider.tsx @@ -3,7 +3,6 @@ import { HighlightContext } from './HighlightContext'; const defaultState = { eventTimeline: false, - unleashAI: false, }; export type HighlightKey = keyof typeof defaultState; diff --git a/frontend/src/component/common/Resizable/Resizable.tsx b/frontend/src/component/common/Resizable/Resizable.tsx deleted file mode 100644 index 8bcaffdf0a0a..000000000000 --- a/frontend/src/component/common/Resizable/Resizable.tsx +++ /dev/null @@ -1,296 +0,0 @@ -import { styled } from '@mui/material'; -import { type HTMLAttributes, useRef, useState, type ReactNode } from 'react'; - -const StyledResizableWrapper = styled('div', { - shouldForwardProp: (prop) => prop !== 'animate', -})<{ animate: boolean }>(({ animate }) => ({ - display: 'flex', - position: 'relative', - overflow: 'hidden', - transition: animate ? 'width 0.3s, height 0.3s' : 'none', -})); - -const StyledResizeHandle = styled('div')({ - position: 'absolute', - background: 'transparent', - zIndex: 1, - '&.top-left': { - top: 0, - left: 0, - cursor: 'nwse-resize', - width: '10px', - height: '10px', - zIndex: 2, - }, - '&.top-right': { - top: 0, - right: 0, - cursor: 'nesw-resize', - width: '10px', - height: '10px', - zIndex: 2, - }, - '&.bottom-left': { - bottom: 0, - left: 0, - cursor: 'nesw-resize', - width: '10px', - height: '10px', - zIndex: 2, - }, - '&.bottom-right': { - bottom: 0, - right: 0, - cursor: 'nwse-resize', - width: '10px', - height: '10px', - zIndex: 2, - }, - '&.top': { - top: 0, - left: '50%', - cursor: 'ns-resize', - width: '100%', - height: '5px', - transform: 'translateX(-50%)', - }, - '&.right': { - top: '50%', - right: 0, - cursor: 'ew-resize', - width: '5px', - height: '100%', - transform: 'translateY(-50%)', - }, - '&.bottom': { - bottom: 0, - left: '50%', - cursor: 'ns-resize', - width: '100%', - height: '5px', - transform: 'translateX(-50%)', - }, - '&.left': { - top: '50%', - left: 0, - cursor: 'ew-resize', - width: '5px', - height: '100%', - transform: 'translateY(-50%)', - }, -}); - -type Handler = - | 'top' - | 'right' - | 'bottom' - | 'left' - | 'top-left' - | 'top-right' - | 'bottom-left' - | 'bottom-right'; - -type Size = { width: string; height: string }; - -interface IResizableProps extends HTMLAttributes { - handlers: Handler[]; - minSize: Size; - maxSize: Size; - defaultSize?: Size; - onResize?: () => void; - onResizeEnd?: () => void; - children: ReactNode; -} - -export const Resizable = ({ - handlers, - minSize, - maxSize, - defaultSize = minSize, - onResize, - onResizeEnd, - children, - ...props -}: IResizableProps) => { - const containerRef = useRef(null); - const [currentSize, setCurrentSize] = useState(defaultSize); - const [animate, setAnimate] = useState(false); - - const handleResize = ( - e: React.MouseEvent, - direction: - | 'top' - | 'right' - | 'bottom' - | 'left' - | 'top-left' - | 'top-right' - | 'bottom-left' - | 'bottom-right', - ) => { - e.preventDefault(); - - const chatContainer = containerRef.current; - if (!chatContainer) return; - - const startX = e.clientX; - const startY = e.clientY; - const startWidth = chatContainer.offsetWidth; - const startHeight = chatContainer.offsetHeight; - - setAnimate(false); - - const onMouseMove = (moveEvent: MouseEvent) => { - let newWidth = startWidth; - let newHeight = startHeight; - - if (direction.includes('top')) { - newHeight = Math.max( - Number.parseInt(minSize.height), - startHeight - (moveEvent.clientY - startY), - ); - } - - if (direction.includes('bottom')) { - newHeight = Math.max( - Number.parseInt(minSize.height), - startHeight + (moveEvent.clientY - startY), - ); - } - - if (direction.includes('left')) { - newWidth = Math.max( - Number.parseInt(minSize.width), - startWidth - (moveEvent.clientX - startX), - ); - } - - if (direction.includes('right')) { - newWidth = Math.max( - Number.parseInt(minSize.width), - startWidth + (moveEvent.clientX - startX), - ); - } - - setCurrentSize({ - width: `${newWidth}px`, - height: `${newHeight}px`, - }); - - onResize?.(); - }; - - const onMouseUp = () => { - document.removeEventListener('mousemove', onMouseMove); - document.removeEventListener('mouseup', onMouseUp); - - onResizeEnd?.(); - }; - - document.addEventListener('mousemove', onMouseMove); - document.addEventListener('mouseup', onMouseUp); - }; - - const handleDoubleClick = (direction: Handler) => { - const chatContainer = containerRef.current; - if (!chatContainer) return; - - const currentWidth = chatContainer.style.width; - const currentHeight = chatContainer.style.height; - - setAnimate(true); - - if (direction.includes('top') || direction.includes('bottom')) { - if (currentHeight === maxSize.height) { - chatContainer.style.height = defaultSize.height; - } else { - chatContainer.style.height = maxSize.height; - } - } - - if (direction.includes('left') || direction.includes('right')) { - if (currentWidth === maxSize.width) { - chatContainer.style.width = defaultSize.width; - } else { - chatContainer.style.width = maxSize.width; - } - } - - onResizeEnd?.(); - }; - - return ( - - {children} - - {handlers.includes('top-left') && ( - handleResize(e, 'top-left')} - onDoubleClick={() => handleDoubleClick('top-left')} - /> - )} - {handlers.includes('top-right') && ( - handleResize(e, 'top-right')} - onDoubleClick={() => handleDoubleClick('top-right')} - /> - )} - {handlers.includes('bottom-left') && ( - handleResize(e, 'bottom-left')} - onDoubleClick={() => handleDoubleClick('bottom-left')} - /> - )} - {handlers.includes('bottom-right') && ( - handleResize(e, 'bottom-right')} - onDoubleClick={() => handleDoubleClick('bottom-right')} - /> - )} - {handlers.includes('top') && ( - handleResize(e, 'top')} - onDoubleClick={() => handleDoubleClick('top')} - /> - )} - {handlers.includes('right') && ( - handleResize(e, 'right')} - onDoubleClick={() => handleDoubleClick('right')} - /> - )} - {handlers.includes('bottom') && ( - handleResize(e, 'bottom')} - onDoubleClick={() => handleDoubleClick('bottom')} - /> - )} - {handlers.includes('left') && ( - handleResize(e, 'left')} - onDoubleClick={() => handleDoubleClick('left')} - /> - )} - - ); -}; diff --git a/frontend/src/component/layout/MainLayout/MainLayout.tsx b/frontend/src/component/layout/MainLayout/MainLayout.tsx index 8ad5e40b59c2..c3edfb023e86 100644 --- a/frontend/src/component/layout/MainLayout/MainLayout.tsx +++ b/frontend/src/component/layout/MainLayout/MainLayout.tsx @@ -17,7 +17,6 @@ import { ThemeMode } from 'component/common/ThemeMode/ThemeMode'; import { NavigationSidebar } from './NavigationSidebar/NavigationSidebar'; import { MainLayoutEventTimeline } from './MainLayoutEventTimeline'; import { EventTimelineProvider } from 'component/events/EventTimeline/EventTimelineProvider'; -import { AIChat } from 'component/ai/AIChat'; import { NewInUnleash } from './NavigationSidebar/NewInUnleash/NewInUnleash'; interface IMainLayoutProps { @@ -168,7 +167,6 @@ export const MainLayout = forwardRef( } /> -