Skip to content

Commit fd0a158

Browse files
committed
feat: load past 5 conversations
1 parent a19c916 commit fd0a158

File tree

8 files changed

+146
-18
lines changed

8 files changed

+146
-18
lines changed
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading

packages/chat-component/src/components/chat-component.ts

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import iconDelete from '../../public/svg/delete-icon.svg?raw';
1515
import iconCancel from '../../public/svg/cancel-icon.svg?raw';
1616
import iconSend from '../../public/svg/send-icon.svg?raw';
1717
import iconClose from '../../public/svg/close-icon.svg?raw';
18+
import iconUp from '../../public/svg/chevron-up-icon.svg?raw';
1819

1920
import './loading-indicator.js';
2021
import './voice-input-button.js';
@@ -26,6 +27,7 @@ import './chat-thread-component.js';
2627
import './chat-action-button.js';
2728
import { type TabContent } from './tab-component.js';
2829
import { ChatController } from './chat-controller.js';
30+
import { ChatHistoryController } from './chat-history-controller.js';
2931

3032
/**
3133
* A chat component that allows the user to ask questions and get answers from an API.
@@ -78,6 +80,7 @@ export class ChatComponent extends LitElement {
7880
isResetInput = false;
7981

8082
private chatController = new ChatController(this);
83+
private chatHistoryController = new ChatHistoryController(this);
8184

8285
// Is showing thought process panel
8386
@state()
@@ -155,6 +158,10 @@ export class ChatComponent extends LitElement {
155158
stream: this.useStream,
156159
},
157160
);
161+
162+
if (this.interactionModel === 'chat') {
163+
this.chatHistoryController.saveChatHistory(this.chatThread);
164+
}
158165
}
159166

160167
// Reset the input field and the current question
@@ -173,6 +180,8 @@ export class ChatComponent extends LitElement {
173180
this.isDefaultPromptsEnabled = true;
174181
this.selectedCitation = undefined;
175182
this.chatController.reset();
183+
// clean up the current session content from the history too
184+
this.chatHistoryController.saveChatHistory(this.chatThread);
176185
this.collapseAside(event);
177186
this.handleUserChatCancel(event);
178187
}
@@ -309,6 +318,27 @@ export class ChatComponent extends LitElement {
309318
}
310319
}
311320

321+
renderChatThread(chatThread: ChatThreadEntry[]) {
322+
return html`<chat-thread-component
323+
.chatThread="${chatThread}"
324+
.actionButtons="${[
325+
{
326+
id: 'chat-show-thought-process',
327+
label: globalConfig.SHOW_THOUGH_PROCESS_BUTTON_LABEL_TEXT,
328+
svgIcon: iconLightBulb,
329+
isDisabled: this.isShowingThoughtProcess,
330+
},
331+
] as any}"
332+
.isDisabled="${this.isDisabled}"
333+
.isProcessingResponse="${this.chatController.isProcessingResponse}"
334+
.selectedCitation="${this.selectedCitation}"
335+
@on-action-button-click="${this.handleChatEntryActionButtonClick}"
336+
@on-citation-click="${this.handleCitationClick}"
337+
@on-followup-click="${this.handleQuestionInputClick}"
338+
>
339+
</chat-thread-component>`;
340+
}
341+
312342
// Render the chat component as a web component
313343
override render() {
314344
return html`
@@ -318,6 +348,7 @@ export class ChatComponent extends LitElement {
318348
${this.isChatStarted
319349
? html`
320350
<div class="chat__header">
351+
${this.interactionModel === 'chat' ? this.chatHistoryController.renderHistoryButton() : ''}
321352
<chat-action-button
322353
.label="${globalConfig.RESET_CHAT_BUTTON_TITLE}"
323354
actionId="chat-reset-button"
@@ -326,24 +357,15 @@ export class ChatComponent extends LitElement {
326357
>
327358
</chat-action-button>
328359
</div>
329-
<chat-thread-component
330-
.chatThread="${this.chatThread}"
331-
.actionButtons="${[
332-
{
333-
id: 'chat-show-thought-process',
334-
label: globalConfig.SHOW_THOUGH_PROCESS_BUTTON_LABEL_TEXT,
335-
svgIcon: iconLightBulb,
336-
isDisabled: this.isShowingThoughtProcess,
337-
},
338-
] as any}"
339-
.isDisabled="${this.isDisabled}"
340-
.isProcessingResponse="${this.chatController.isProcessingResponse}"
341-
.selectedCitation="${this.selectedCitation}"
342-
@on-action-button-click="${this.handleChatEntryActionButtonClick}"
343-
@on-citation-click="${this.handleCitationClick}"
344-
@on-followup-click="${this.handleQuestionInputClick}"
345-
>
346-
</chat-thread-component>
360+
${this.chatHistoryController.showChatHistory
361+
? html`<div class="chat-history__container">
362+
${this.renderChatThread(this.chatHistoryController.chatHistory)}
363+
<div class="chat-history__footer">
364+
${unsafeSVG(iconUp)} ${globalConfig.CHAT_HISTORY_FOOTER_TEXT} ${unsafeSVG(iconUp)}
365+
</div>
366+
</div>`
367+
: ''}
368+
${this.renderChatThread(this.chatThread)}
347369
`
348370
: ''}
349371
${this.chatController.isAwaitingResponse
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { type ReactiveController, type ReactiveControllerHost } from 'lit';
2+
import { html } from 'lit';
3+
import { globalConfig } from '../config/global-config.js';
4+
5+
import iconHistory from '../../public/svg/history-icon.svg?raw';
6+
import iconHistoryDismiss from '../../public/svg/history-dismiss-icon.svg?raw';
7+
8+
import './chat-action-button.js';
9+
10+
export class ChatHistoryController implements ReactiveController {
11+
host: ReactiveControllerHost;
12+
static CHATHISTORY_ID = 'component:chat-history';
13+
14+
chatHistory: ChatThreadEntry[] = [];
15+
16+
private _showChatHistory: boolean = false;
17+
18+
get showChatHistory() {
19+
return this._showChatHistory;
20+
}
21+
22+
set showChatHistory(value: boolean) {
23+
this._showChatHistory = value;
24+
this.host.requestUpdate();
25+
}
26+
27+
constructor(host: ReactiveControllerHost) {
28+
(this.host = host).addController(this);
29+
}
30+
31+
hostConnected() {
32+
const chatHistory = localStorage.getItem(ChatHistoryController.CHATHISTORY_ID);
33+
if (chatHistory) {
34+
const history = JSON.parse(chatHistory);
35+
36+
// find last 5 user messages indexes
37+
const lastUserMessagesIndexes = history
38+
.map((entry, index) => {
39+
if (entry.isUserMessage) {
40+
return index;
41+
}
42+
})
43+
.filter((index) => index !== undefined)
44+
.slice(-5);
45+
46+
// trim everything before the first user message
47+
const trimmedHistory = lastUserMessagesIndexes.length === 0 ? history : history.slice(lastUserMessagesIndexes[0]);
48+
49+
this.chatHistory = trimmedHistory;
50+
}
51+
}
52+
53+
hostDisconnected() {
54+
// no-op
55+
}
56+
57+
saveChatHistory(currentChat: ChatThreadEntry[]): void {
58+
const newChatHistory = [...this.chatHistory, ...currentChat];
59+
localStorage.setItem(ChatHistoryController.CHATHISTORY_ID, JSON.stringify(newChatHistory));
60+
}
61+
62+
handleChatHistoryButtonClick(event: Event) {
63+
event.preventDefault();
64+
this.showChatHistory = !this.showChatHistory;
65+
}
66+
67+
renderHistoryButton() {
68+
return html`
69+
<chat-action-button
70+
.label="${this.showChatHistory ? globalConfig.HIDE_CHAT_HISTORY_LABEL : globalConfig.SHOW_CHAT_HISTORY_LABEL}"
71+
actionId="chat-history-button"
72+
@click="${(event) => this.handleChatHistoryButtonClick(event)}"
73+
.svgIcon="${this.showChatHistory ? iconHistoryDismiss : iconHistory}"
74+
>
75+
</chat-action-button>
76+
`;
77+
}
78+
}

packages/chat-component/src/config/global-config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ const globalConfig = {
3434
SUPPORT_CONTEXT_LABEL: 'Support Context',
3535
CITATIONS_LABEL: 'Learn More:',
3636
CITATIONS_TAB_LABEL: 'Citations',
37+
SHOW_CHAT_HISTORY_LABEL: 'Show Chat History',
38+
HIDE_CHAT_HISTORY_LABEL: 'Hide Chat History',
39+
CHAT_HISTORY_FOOTER_TEXT: 'Showing past 5 conversations',
3740
};
3841

3942
const teaserListTexts = {

packages/chat-component/src/styles/chat-action-button.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export const styles = css`
5050
svg {
5151
fill: currentColor;
5252
width: 20px;
53+
height: 20px;
5354
padding: 3px;
5455
}
5556
button:hover > span,

packages/chat-component/src/styles/chat-component.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,18 @@ export const chatStyle = css`
260260
border-radius: 25px;
261261
padding: 20px;
262262
}
263+
.chat-history__footer {
264+
display: flex;
265+
flex-direction: row;
266+
gap: 10px;
267+
justify-content: space-between;
268+
align-self: center;
269+
padding: 20px;
270+
}
271+
.chat-history__container {
272+
display: flex;
273+
flex-direction: column;
274+
border-bottom: 3px solid var(--light-gray);
275+
margin-bottom: 30px;
276+
}
263277
`;

0 commit comments

Comments
 (0)