-
Notifications
You must be signed in to change notification settings - Fork 244
chore(components): use npm overrides to force transitive leafygreen dependencies to the same version of shared packages #7223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
95a8bd5
42a0d8c
353e6ae
24a0e4a
58b2b3f
c7150e5
0251b8e
d3f187c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,129 +1,81 @@ | ||
| import React, { useCallback, useState } from 'react'; | ||
| import React, { useCallback } from 'react'; | ||
| import type { AssistantMessage } from './compass-assistant-provider'; | ||
| import type { Chat } from './@ai-sdk/react/chat-react'; | ||
| import { useChat } from './@ai-sdk/react/use-chat'; | ||
| import { | ||
| LgChatChatWindow, | ||
| LgChatLeafygreenChatProvider, | ||
| LgChatMessage, | ||
| LgChatMessageFeed, | ||
| LgChatInputBar, | ||
| } from '@mongodb-js/compass-components'; | ||
|
|
||
| const { ChatWindow } = LgChatChatWindow; | ||
| const { LeafyGreenChatProvider, Variant } = LgChatLeafygreenChatProvider; | ||
| const { Message } = LgChatMessage; | ||
| const { MessageFeed } = LgChatMessageFeed; | ||
| const { InputBar } = LgChatInputBar; | ||
|
|
||
| interface AssistantChatProps { | ||
| chat: Chat<AssistantMessage>; | ||
| } | ||
|
|
||
| /** | ||
| * This component is currently using placeholders as Leafygreen UI updates are not available yet. | ||
| * Before release, we will replace this with the actual Leafygreen chat components. | ||
| */ | ||
| export const AssistantChat: React.FunctionComponent<AssistantChatProps> = ({ | ||
| chat, | ||
| }) => { | ||
| const [inputValue, setInputValue] = useState(''); | ||
| const { messages, sendMessage } = useChat({ | ||
| const { messages, sendMessage, status } = useChat({ | ||
| chat, | ||
| }); | ||
|
|
||
| const handleInputSubmit = useCallback( | ||
| (e: React.FormEvent) => { | ||
| e.preventDefault(); | ||
| if (inputValue.trim()) { | ||
| void sendMessage({ text: inputValue.trim() }); | ||
| setInputValue(''); | ||
| } | ||
| // Transform AI SDK messages to LeafyGreen chat format | ||
| const lgMessages = messages.map((message) => ({ | ||
| id: message.id, | ||
| messageBody: | ||
| message.metadata?.displayText || | ||
| message.parts | ||
| ?.filter((part) => part.type === 'text') | ||
| .map((part) => part.text) | ||
| .join('') || | ||
| '', | ||
| isSender: message.role === 'user', | ||
| })); | ||
|
|
||
| const handleMessageSend = useCallback( | ||
| (messageBody: string) => { | ||
| void sendMessage({ text: messageBody }); | ||
| }, | ||
| [inputValue, sendMessage] | ||
| [sendMessage] | ||
| ); | ||
|
|
||
| return ( | ||
| <div | ||
| style={{ | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| height: '100%', | ||
| width: '100%', | ||
| }} | ||
| data-testid="assistant-chat" | ||
| > | ||
| {/* Message Feed */} | ||
| <div | ||
| data-testid="assistant-chat-messages" | ||
| style={{ | ||
| width: '100%', | ||
| flex: 1, | ||
| overflowY: 'auto', | ||
| display: 'flex', | ||
| flexDirection: 'column', | ||
| gap: '16px', | ||
| minHeight: 0, | ||
| }} | ||
| > | ||
| {messages.map((message) => ( | ||
| <div | ||
| key={message.id} | ||
| data-testid={`assistant-message-${message.id}`} | ||
| style={{ | ||
| marginBottom: '12px', | ||
| padding: '8px 12px', | ||
| borderRadius: '8px', | ||
| backgroundColor: message.role === 'user' ? '#207245' : '#e9ecef', | ||
| color: message.role === 'user' ? 'white' : '#333', | ||
| alignSelf: message.role === 'user' ? 'flex-end' : 'flex-start', | ||
| maxWidth: '80%', | ||
| wordWrap: 'break-word', | ||
| whiteSpace: 'pre-wrap', | ||
| <div data-testid="assistant-chat" style={{ height: '100%', width: '100%' }}> | ||
| <LeafyGreenChatProvider variant={Variant.Compact}> | ||
| <ChatWindow title="MongoDB Assistant"> | ||
| <MessageFeed data-testid="assistant-chat-messages"> | ||
| {lgMessages.map((messageFields) => ( | ||
| <Message | ||
| key={messageFields.id} | ||
| {...messageFields} | ||
| data-testid={`assistant-message-${messageFields.id}`} | ||
| /> | ||
| ))} | ||
| {status === 'submitted' && ( | ||
| <Message | ||
| id="loading" | ||
| messageBody="Thinking..." | ||
| isSender={false} | ||
| /> | ||
| )} | ||
| </MessageFeed> | ||
| <InputBar | ||
| data-testid="assistant-chat-input" | ||
| onMessageSend={handleMessageSend} | ||
| textareaProps={{ | ||
| placeholder: 'Ask MongoDB Assistant a question', | ||
| }} | ||
| > | ||
| {message.metadata?.displayText || | ||
| message.parts | ||
| ?.filter((part) => part.type === 'text') | ||
| .map((part) => part.text) | ||
| .join('') || | ||
| ''} | ||
| </div> | ||
| ))} | ||
| </div> | ||
|
|
||
| {/* Input Bar */} | ||
| <form | ||
| data-testid="assistant-chat-form" | ||
| onSubmit={handleInputSubmit} | ||
| style={{ | ||
| display: 'flex', | ||
| gap: '8px', | ||
| flexShrink: 0, // Prevents the input bar from shrinking | ||
| position: 'sticky', | ||
| bottom: 0, | ||
| backgroundColor: 'inherit', | ||
| paddingTop: '8px', | ||
| }} | ||
| > | ||
| <input | ||
| data-testid="assistant-chat-input" | ||
| type="text" | ||
| value={inputValue} | ||
| onChange={(e) => setInputValue(e.target.value)} | ||
| placeholder="Ask MongoDB Assistant a question" | ||
| style={{ | ||
| flex: 1, | ||
| padding: '8px 12px', | ||
| border: '1px solid #ddd', | ||
| borderRadius: '4px', | ||
| fontSize: '14px', | ||
| }} | ||
| /> | ||
| <button | ||
| data-testid="assistant-chat-send-button" | ||
| type="submit" | ||
| disabled={!inputValue.trim()} | ||
| style={{ | ||
| padding: '8px 16px', | ||
| backgroundColor: '#207245', | ||
| color: 'white', | ||
| border: 'none', | ||
| borderRadius: '4px', | ||
| cursor: inputValue.trim() ? 'pointer' : 'not-allowed', | ||
| opacity: inputValue.trim() ? 1 : 0.6, | ||
| }} | ||
| > | ||
| Send | ||
| </button> | ||
| </form> | ||
| /> | ||
| </ChatWindow> | ||
| </LeafyGreenChatProvider> | ||
| </div> | ||
| ); | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,11 +149,9 @@ function useCollectionTabs(props: CollectionMetadata) { | |
| </WithErrorBoundary> | ||
| ), | ||
| title: ( | ||
| <WithErrorBoundary name={name} type="header"> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: why the removed error boundary?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So it's this issue caused by the fact that @leafygreen-ui/lib@15 seems like the one that seems to be working for all our dependendecies more or less, but it does cause something weird in leafygreen tabs component specifically: the title that we pass there wrapped in a boundary starts to fail with this error (I'm guessing they are doing something with this value passed that triggers the constructor accidentally). Before tabs were installing their own version, but doing this very targeted override on top of other overrides is a pain in the butt, so I'm just getting around the issue here by removing the boundary from the rendering tree. I'll leave a todo |
||
| <Provider {...props}> | ||
| <Header /> | ||
| </Provider> | ||
| </WithErrorBoundary> | ||
| <Provider {...props}> | ||
| <Header /> | ||
| </Provider> | ||
| ), | ||
| }; | ||
| }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /** | ||
| * We can't update @leafygreen-ui/button component to latest because it breaks | ||
| * the types across the whole application, but we also have to add a dependency | ||
| * on a new leafygreen package that depends on a new export from the button | ||
| * package, this new export is a one-liner color value. As a temporary | ||
| * workaround, we will patch leafygreen package and add the export manually. For | ||
| * more details see https://github.com/mongodb-js/compass/pull/7223 | ||
| */ | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
|
|
||
| const leafygreenButtonPackage = path.dirname( | ||
| require.resolve('@leafygreen-ui/button/package.json') | ||
| ); | ||
|
|
||
| // eslint-disable-next-line no-console | ||
| console.log('Adding @leafygreen-ui/button/constants export...'); | ||
|
|
||
| fs.writeFileSync( | ||
| path.join(leafygreenButtonPackage, 'constants.js'), | ||
| "module.exports = { PRIMARY_BUTTON_INTERACTIVE_GREEN: '#00593F' };" | ||
| ); | ||
| fs.writeFileSync( | ||
| path.join(leafygreenButtonPackage, 'constants.d.ts'), | ||
| 'export declare const PRIMARY_BUTTON_INTERACTIVE_GREEN = "#00593F";' | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gagik @lerouxb just wanted to highlight: I can either revert switching assistant to new UI or keep this skip in this PR, whatever you prefer. If we keep the skip, we probably want to follow-up with fixing those right away. At a glance it's just jsdom missing some methods, so shouldn't be too hard, I'm just trying to keep this PR small
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm working on a follow-up PR so we can just skip this here and I'll rebase and re-add those