@@ -45,6 +45,7 @@ import {
4545 FileDropZone ,
4646 MessageBar ,
4747 MessageProps ,
48+ Settings ,
4849} from '@patternfly/chatbot' ;
4950import ChatbotConversationHistoryNav from '@patternfly/chatbot/dist/dynamic/ChatbotConversationHistoryNav' ;
5051import {
@@ -106,6 +107,7 @@ import { DeleteNotebookModal } from './notebooks/DeleteNotebookModal';
106107import { NotebooksTab } from './notebooks/NotebooksTab' ;
107108import { RenameNotebookModal } from './notebooks/RenameNotebookModal' ;
108109import PermissionRequiredState from './PermissionRequiredState' ;
110+ import { McpServersSettings } from './McpServersSettings' ;
109111import { RenameConversationModal } from './RenameConversationModal' ;
110112
111113const useStyles = makeStyles ( theme => ( {
@@ -330,6 +332,56 @@ const useStyles = makeStyles(theme => ({
330332 flex : 1 ,
331333 minHeight : 0 ,
332334 } ,
335+ settingsFlat : {
336+ height : '100%' ,
337+ width : '100%' ,
338+ '&.pf-chatbot__settings-form-container' : {
339+ background : 'transparent' ,
340+ padding : 0 ,
341+ margin : 0 ,
342+ width : '100%' ,
343+ maxWidth : 'none' ,
344+ } ,
345+ '& .pf-chatbot__settings-form' : {
346+ margin : 0 ,
347+ padding : 0 ,
348+ width : '100%' ,
349+ maxWidth : 'none' ,
350+ } ,
351+ '& .pf-chatbot__settings-form-row' : {
352+ background : 'transparent' ,
353+ border : 0 ,
354+ margin : 0 ,
355+ padding : 0 ,
356+ width : '100%' ,
357+ maxWidth : 'none' ,
358+ } ,
359+ '& .pf-chatbot__settings-label' : {
360+ display : 'none' ,
361+ } ,
362+ } ,
363+ mcpFullscreenLayout : {
364+ display : 'flex' ,
365+ minHeight : 0 ,
366+ height : '100%' ,
367+ flex : 1 ,
368+ width : '100%' ,
369+ } ,
370+ mcpChatPane : {
371+ display : 'flex' ,
372+ flexDirection : 'column' ,
373+ minHeight : 0 ,
374+ flex : 1 ,
375+ minWidth : 0 ,
376+ } ,
377+ mcpSettingsPane : {
378+ flex : 1 ,
379+ minWidth : 0 ,
380+ borderLeft : `1px solid ${ theme . palette . divider } ` ,
381+ display : 'flex' ,
382+ flexDirection : 'column' ,
383+ minHeight : 0 ,
384+ } ,
333385} ) ) ;
334386
335387type LightspeedChatProps = {
@@ -383,6 +435,8 @@ export const LightspeedChat = ({
383435 const [ isDeleteModalOpen , setIsDeleteModalOpen ] = useState < boolean > ( false ) ;
384436 const [ isRenameModalOpen , setIsRenameModalOpen ] = useState < boolean > ( false ) ;
385437 const [ isSortSelectOpen , setIsSortSelectOpen ] = useState < boolean > ( false ) ;
438+ const [ isMcpSettingsOpen , setIsMcpSettingsOpen ] = useState < boolean > ( false ) ;
439+ const [ chatHeaderBgColor , setChatHeaderBgColor ] = useState < string > ( ) ;
386440 const contentScrollRef = useRef < HTMLDivElement > ( null ) ;
387441 const bottomSentinelRef = useRef < HTMLDivElement > ( null ) ;
388442 const { isReady, lastOpenedId, setLastOpenedId, clearLastOpenedId } =
@@ -432,6 +486,16 @@ export const LightspeedChat = ({
432486 }
433487 } , [ isMobile , isFullscreenMode ] ) ;
434488
489+ useEffect ( ( ) => {
490+ if ( typeof window === 'undefined' ) return ;
491+ const headerElement = document . querySelector ( '.pf-chatbot__header' ) ;
492+ if ( ! headerElement ) return ;
493+ const computedBg = window . getComputedStyle ( headerElement ) . backgroundColor ;
494+ if ( computedBg ) {
495+ setChatHeaderBgColor ( computedBg ) ;
496+ }
497+ } , [ displayMode , isMcpSettingsOpen ] ) ;
498+
435499 const {
436500 isPinningChatsEnabled,
437501 pinnedChats,
@@ -577,6 +641,7 @@ export const LightspeedChat = ({
577641
578642 const onNewChat = useCallback ( ( ) => {
579643 ( async ( ) => {
644+ setIsMcpSettingsOpen ( false ) ;
580645 if ( conversationId !== TEMP_CONVERSATION_ID ) {
581646 setMessages ( [ ] ) ;
582647 setFileContents ( [ ] ) ;
@@ -768,6 +833,7 @@ export const LightspeedChat = ({
768833
769834 const onSelectActiveItem = useCallback (
770835 ( _ : MouseEvent | undefined , selectedItem : string | number | undefined ) => {
836+ setIsMcpSettingsOpen ( false ) ;
771837 setNewChatCreated ( false ) ;
772838 const newConvId = String ( selectedItem ) ;
773839 setConversationId ( ( c_id : string ) => {
@@ -789,6 +855,7 @@ export const LightspeedChat = ({
789855 setDraftMessage ,
790856 scrollToBottomRef ,
791857 setCurrentConversationId ,
858+ setIsMcpSettingsOpen ,
792859 ] ,
793860 ) ;
794861
@@ -977,6 +1044,109 @@ export const LightspeedChat = ({
9771044 } ) ;
9781045 } ;
9791046
1047+ const chatMainContent = (
1048+ < >
1049+ < ChatbotContent className = { classes . chatbotContent } >
1050+ < div ref = { contentScrollRef } className = { classes . chatbotContentScroll } >
1051+ { welcomePrompts . length > 0 && (
1052+ < div className = { classes . chatbotContentSpacer } aria-hidden />
1053+ ) }
1054+ < LightspeedChatBox
1055+ userName = { userName }
1056+ messages = { messages }
1057+ profileLoading = { profileLoading }
1058+ announcement = { announcement }
1059+ ref = { scrollToBottomRef }
1060+ welcomePrompts = { welcomePrompts }
1061+ conversationId = { conversationId }
1062+ isStreaming = { isSendButtonDisabled }
1063+ topicRestrictionEnabled = { topicRestrictionEnabled }
1064+ displayMode = { displayMode }
1065+ />
1066+ { welcomePrompts . length > 0 && (
1067+ < div
1068+ ref = { bottomSentinelRef }
1069+ aria-hidden
1070+ style = { { height : 0 , flexShrink : 0 } }
1071+ />
1072+ ) }
1073+ </ div >
1074+ </ ChatbotContent >
1075+ < ChatbotFooter className = { classes . footer } >
1076+ < FilePreview />
1077+ < MessageBar
1078+ onSendMessage = { sendMessage }
1079+ isSendButtonDisabled = { isSendButtonDisabled }
1080+ hasAttachButton
1081+ handleAttach = { handleAttach }
1082+ hasMicrophoneButton
1083+ value = { draftMessage }
1084+ onChange = { handleDraftMessage }
1085+ buttonProps = { {
1086+ attach : {
1087+ inputTestId : 'attachment-input' ,
1088+ tooltipContent : t ( 'tooltip.attach' ) ,
1089+ } ,
1090+ microphone : {
1091+ tooltipContent : {
1092+ active : t ( 'tooltip.microphone.active' ) ,
1093+ inactive : t ( 'tooltip.microphone.inactive' ) ,
1094+ } ,
1095+ } ,
1096+ send : {
1097+ tooltipContent : t ( 'tooltip.send' ) ,
1098+ } ,
1099+ } }
1100+ allowedFileTypes = { supportedFileTypes }
1101+ onAttachRejected = { onAttachRejected }
1102+ placeholder = { t ( 'chatbox.message.placeholder' ) }
1103+ />
1104+ < ChatbotFootnote { ...getFootnoteProps ( t ) } />
1105+ </ ChatbotFooter >
1106+ </ >
1107+ ) ;
1108+
1109+ let mainPanelContent = < > { chatMainContent } </ > ;
1110+
1111+ if ( isMcpSettingsOpen && isFullscreenMode ) {
1112+ mainPanelContent = (
1113+ < div className = { classes . mcpFullscreenLayout } >
1114+ < div className = { classes . mcpChatPane } > { chatMainContent } </ div >
1115+ < div className = { classes . mcpSettingsPane } >
1116+ < McpServersSettings
1117+ onClose = { ( ) => setIsMcpSettingsOpen ( false ) }
1118+ backgroundColor = { chatHeaderBgColor }
1119+ />
1120+ </ div >
1121+ </ div >
1122+ ) ;
1123+ } else if ( isMcpSettingsOpen ) {
1124+ mainPanelContent = (
1125+ < Settings
1126+ className = { classes . settingsFlat }
1127+ fields = { [
1128+ {
1129+ id : 'mcp-servers-settings' ,
1130+ label : '' ,
1131+ field : (
1132+ < McpServersSettings
1133+ onClose = { ( ) => setIsMcpSettingsOpen ( false ) }
1134+ backgroundColor = { chatHeaderBgColor }
1135+ />
1136+ ) ,
1137+ } ,
1138+ ] }
1139+ />
1140+ ) ;
1141+ }
1142+
1143+ let drawerPanelStyle : { [ key : string ] : string | number } | undefined ;
1144+ if ( ! isFullscreenMode ) {
1145+ drawerPanelStyle = { zIndex : 1300 } ;
1146+ } else if ( isMcpSettingsOpen ) {
1147+ drawerPanelStyle = { width : 320 , minWidth : 320 , maxWidth : 320 } ;
1148+ }
1149+
9801150 return (
9811151 < >
9821152 { notebookAlerts . length > 0 && (
@@ -1066,6 +1236,7 @@ export const LightspeedChat = ({
10661236 < LightspeedChatBoxHeader
10671237 selectedModel = { selectedModel }
10681238 handleSelectedModel = { item => {
1239+ setIsMcpSettingsOpen ( false ) ;
10691240 onNewChat ( ) ;
10701241 handleSelectedModel ( item ) ;
10711242 } }
@@ -1075,6 +1246,7 @@ export const LightspeedChat = ({
10751246 setDisplayMode = { setDisplayMode }
10761247 displayMode = { displayMode }
10771248 onPinnedChatsToggle = { handlePinningChatsToggle }
1249+ onMcpSettingsClick = { ( ) => setIsMcpSettingsOpen ( true ) }
10781250 />
10791251 </ ChatbotHeader >
10801252 { isFullscreenMode && (
@@ -1096,7 +1268,7 @@ export const LightspeedChat = ({
10961268 drawerPanelContentProps = { {
10971269 isResizable : isFullscreenMode ,
10981270 hasNoBorder : ! isFullscreenMode ,
1099- style : isFullscreenMode ? undefined : { zIndex : 1300 } ,
1271+ style : drawerPanelStyle ,
11001272 } }
11011273 reverseButtonOrder
11021274 displayMode = { ChatbotDisplayMode . embedded }
@@ -1157,69 +1329,8 @@ export const LightspeedChat = ({
11571329 </ ChatbotAlert >
11581330 </ div >
11591331 ) }
1160- < ChatbotContent className = { classes . chatbotContent } >
1161- < div
1162- ref = { contentScrollRef }
1163- className = { classes . chatbotContentScroll }
1164- >
1165- { welcomePrompts . length > 0 && (
1166- < div
1167- className = { classes . chatbotContentSpacer }
1168- aria-hidden
1169- />
1170- ) }
1171- < LightspeedChatBox
1172- userName = { userName }
1173- messages = { messages }
1174- profileLoading = { profileLoading }
1175- announcement = { announcement }
1176- ref = { scrollToBottomRef }
1177- welcomePrompts = { welcomePrompts }
1178- conversationId = { conversationId }
1179- isStreaming = { isSendButtonDisabled }
1180- topicRestrictionEnabled = { topicRestrictionEnabled }
1181- displayMode = { displayMode }
1182- />
1183- { welcomePrompts . length > 0 && (
1184- < div
1185- ref = { bottomSentinelRef }
1186- aria-hidden
1187- style = { { height : 0 , flexShrink : 0 } }
1188- />
1189- ) }
1190- </ div >
1191- </ ChatbotContent >
1192- < ChatbotFooter className = { classes . footer } >
1193- < FilePreview />
1194- < MessageBar
1195- onSendMessage = { sendMessage }
1196- isSendButtonDisabled = { isSendButtonDisabled }
1197- hasAttachButton
1198- handleAttach = { handleAttach }
1199- hasMicrophoneButton
1200- value = { draftMessage }
1201- onChange = { handleDraftMessage }
1202- buttonProps = { {
1203- attach : {
1204- inputTestId : 'attachment-input' ,
1205- tooltipContent : t ( 'tooltip.attach' ) ,
1206- } ,
1207- microphone : {
1208- tooltipContent : {
1209- active : t ( 'tooltip.microphone.active' ) ,
1210- inactive : t ( 'tooltip.microphone.inactive' ) ,
1211- } ,
1212- } ,
1213- send : {
1214- tooltipContent : t ( 'tooltip.send' ) ,
1215- } ,
1216- } }
1217- allowedFileTypes = { supportedFileTypes }
1218- onAttachRejected = { onAttachRejected }
1219- placeholder = { t ( 'chatbox.message.placeholder' ) }
1220- />
1221- < ChatbotFootnote { ...getFootnoteProps ( t ) } />
1222- </ ChatbotFooter >
1332+
1333+ { mainPanelContent }
12231334 </ FileDropZone >
12241335 }
12251336 />
0 commit comments