Skip to content

Commit 1480c56

Browse files
committed
chore(compass-assistant): add clear chat button COMPASS-9731
1 parent 8f183d0 commit 1480c56

File tree

3 files changed

+123
-15
lines changed

3 files changed

+123
-15
lines changed

packages/compass-assistant/src/compass-assistant-drawer.tsx

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
import React, { useContext } from 'react';
2-
import { DrawerSection } from '@mongodb-js/compass-components';
1+
import React, { useCallback, useContext } from 'react';
2+
import {
3+
DrawerSection,
4+
Icon,
5+
IconButton,
6+
showConfirmation,
7+
} from '@mongodb-js/compass-components';
38
import { AssistantChat } from './assistant-chat';
49
import {
510
ASSISTANT_DRAWER_ID,
11+
AssistantActionsContext,
612
AssistantContext,
713
} from './compass-assistant-provider';
814
import { usePreference } from 'compass-preferences-model/provider';
@@ -16,9 +22,23 @@ export const CompassAssistantDrawer: React.FunctionComponent<{
1622
autoOpen?: boolean;
1723
}> = ({ autoOpen }) => {
1824
const chat = useContext(AssistantContext);
25+
const { clearChat } = useContext(AssistantActionsContext);
1926

2027
const enableAIAssistant = usePreference('enableAIAssistant');
2128

29+
const handleClearChat = useCallback(async () => {
30+
const confirmed = await showConfirmation({
31+
title: 'Clear this chat?',
32+
description:
33+
'The current chat will be cleared, and chat history will not be retrievable.',
34+
buttonText: 'Clear chat',
35+
variant: 'danger',
36+
});
37+
if (confirmed) {
38+
clearChat();
39+
}
40+
}, [clearChat]);
41+
2242
if (!enableAIAssistant) {
2343
return null;
2444
}
@@ -32,7 +52,27 @@ export const CompassAssistantDrawer: React.FunctionComponent<{
3252
return (
3353
<DrawerSection
3454
id={ASSISTANT_DRAWER_ID}
35-
title="MongoDB Assistant"
55+
title={
56+
<div
57+
style={{
58+
display: 'flex',
59+
alignItems: 'center',
60+
justifyContent: 'space-between',
61+
}}
62+
>
63+
<span>MongoDB Assistant</span>
64+
<IconButton
65+
aria-label="Clear chat"
66+
onClick={() => {
67+
void handleClearChat();
68+
}}
69+
title="Clear chat"
70+
data-testid="assistant-clear-chat"
71+
>
72+
<Icon glyph="Eraser" />
73+
</IconButton>
74+
</div>
75+
}
3676
label="MongoDB Assistant"
3777
glyph="Sparkle"
3878
autoOpen={autoOpen}

packages/compass-assistant/src/compass-assistant-provider.spec.tsx

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import {
44
screen,
55
userEvent,
66
waitFor,
7+
waitForElementToBeRemoved,
8+
within,
79
} from '@mongodb-js/testing-library-compass';
810
import {
911
AssistantProvider,
@@ -40,6 +42,19 @@ const TestComponent: React.FunctionComponent<{
4042
};
4143

4244
describe('AssistantProvider', function () {
45+
const mockMessages: AssistantMessage[] = [
46+
{
47+
id: '1',
48+
role: 'user',
49+
parts: [{ type: 'text', text: 'Test message' }],
50+
},
51+
{
52+
id: '2',
53+
role: 'assistant',
54+
parts: [{ type: 'text', text: 'Test assistant message' }],
55+
},
56+
];
57+
4358
it('always renders children', function () {
4459
render(<TestComponent chat={createMockChat({ messages: [] })} />, {
4560
preferences: { enableAIAssistant: true },
@@ -92,18 +107,6 @@ describe('AssistantProvider', function () {
92107
}
93108

94109
it('displays messages in the chat feed', async function () {
95-
const mockMessages: AssistantMessage[] = [
96-
{
97-
id: '1',
98-
role: 'user',
99-
parts: [{ type: 'text', text: 'Test message' }],
100-
},
101-
{
102-
id: '2',
103-
role: 'assistant',
104-
parts: [{ type: 'text', text: 'Test assistant message' }],
105-
},
106-
];
107110
const mockChat = createMockChat({ messages: mockMessages });
108111

109112
await renderOpenAssistantDrawer(mockChat);
@@ -186,6 +189,66 @@ describe('AssistantProvider', function () {
186189
expect(screen.getByText('Hello assistant!')).to.exist;
187190
});
188191
});
192+
193+
describe('clear chat button', function () {
194+
it('clears the chat when the user clicks and confirms', async function () {
195+
const mockChat = createMockChat({ messages: mockMessages });
196+
197+
await renderOpenAssistantDrawer(mockChat);
198+
199+
const clearButton = screen.getByTestId('assistant-clear-chat');
200+
userEvent.click(clearButton);
201+
202+
await waitFor(() => {
203+
expect(screen.getByTestId('confirmation-modal')).to.exist;
204+
});
205+
206+
// There should be messages in the chat
207+
expect(screen.getByTestId('assistant-message-1')).to.exist;
208+
expect(screen.getByTestId('assistant-message-2')).to.exist;
209+
210+
const modal = screen.getByTestId('confirmation-modal');
211+
const confirmButton = within(modal).getByText('Clear chat');
212+
userEvent.click(confirmButton);
213+
214+
await waitForElementToBeRemoved(() =>
215+
screen.getByTestId('confirmation-modal')
216+
);
217+
218+
expect(mockChat.messages).to.be.empty;
219+
expect(screen.queryByTestId('assistant-message-1')).to.not.exist;
220+
expect(screen.queryByTestId('assistant-message-2')).to.not.exist;
221+
});
222+
223+
it('does not clear the chat when the user clicks the button and cancels', async function () {
224+
const mockChat = createMockChat({ messages: mockMessages });
225+
226+
await renderOpenAssistantDrawer(mockChat);
227+
228+
const clearButton = screen.getByTestId('assistant-clear-chat');
229+
userEvent.click(clearButton);
230+
231+
await waitFor(() => {
232+
expect(screen.getByTestId('confirmation-modal')).to.exist;
233+
});
234+
235+
// There should be messages in the chat
236+
expect(screen.getByTestId('assistant-message-1')).to.exist;
237+
expect(screen.getByTestId('assistant-message-2')).to.exist;
238+
239+
const modal = screen.getByTestId('confirmation-modal');
240+
const cancelButton = within(modal).getByText('Cancel');
241+
userEvent.click(cancelButton);
242+
243+
await waitForElementToBeRemoved(() =>
244+
screen.getByTestId('confirmation-modal')
245+
);
246+
247+
expect(mockChat.messages).to.deep.equal(mockMessages);
248+
expect(screen.getByTestId('assistant-message-1')).to.exist;
249+
expect(screen.getByTestId('assistant-message-2')).to.exist;
250+
});
251+
});
189252
});
190253

191254
describe('CompassAssistantProvider', function () {

packages/compass-assistant/src/compass-assistant-provider.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ type AssistantActionsContextType = {
3232
namespace: string;
3333
explainPlan: string;
3434
}) => void;
35+
clearChat: () => void;
3536
};
3637
export const AssistantActionsContext =
3738
createContext<AssistantActionsContextType>({
3839
interpretExplainPlan: () => {},
40+
clearChat: () => {},
3941
});
4042

4143
export function useAssistantActions(): AssistantActionsContextType & {
@@ -70,6 +72,9 @@ export const AssistantProvider: React.FunctionComponent<
7072
{}
7173
);
7274
},
75+
clearChat: () => {
76+
chat.messages = [];
77+
},
7378
});
7479
const { openDrawer } = useDrawerActions();
7580

0 commit comments

Comments
 (0)