Skip to content

Commit 33fba85

Browse files
Shibani Basavashibbas
authored andcommitted
feat: add working DI for thought process. citations don't work yet
1 parent d6447c6 commit 33fba85

File tree

5 files changed

+224
-136
lines changed

5 files changed

+224
-136
lines changed

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

Lines changed: 18 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,26 @@
22
import { LitElement, html } from 'lit';
33
import DOMPurify from 'dompurify';
44
import { customElement, property, query, state } from 'lit/decorators.js';
5-
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
65
import { chatHttpOptions, globalConfig, requestOptions, MAX_CHAT_HISTORY } from '../config/global-config.js';
76
import { chatStyle } from '../styles/chat-component.js';
87
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
98
import { chatEntryToString, newListWithEntryAtIndex } from '../utils/index.js';
109

1110
// TODO: allow host applications to customize these icons
1211

13-
import iconLightBulb from '../../public/svg/lightbulb-icon.svg?raw';
1412
import iconDelete from '../../public/svg/delete-icon.svg?raw';
1513
import iconCancel from '../../public/svg/cancel-icon.svg?raw';
1614
import iconSend from '../../public/svg/send-icon.svg?raw';
17-
import iconClose from '../../public/svg/close-icon.svg?raw';
1815
import iconLogo from '../../public/branding/brand-logo.svg?raw';
1916
import iconUp from '../../public/svg/chevron-up-icon.svg?raw';
2017

21-
import { type TabContent } from './tab-component.js';
2218
import { ChatController } from './chat-controller.js';
2319
import { ChatHistoryController } from './chat-history-controller.js';
2420
import {
2521
lazyMultiInject,
2622
ControllerType,
2723
type ChatInputController,
2824
type ChatInputFooterController,
29-
type CitationController,
3025
type ChatSectionController,
3126
} from './composable.js';
3227
import { ChatContextController } from './chat-context.js';
@@ -111,14 +106,6 @@ export class ChatComponent extends LitElement {
111106
@state()
112107
isShowingThoughtProcess = false;
113108

114-
@state()
115-
selectedCitation: Citation | undefined = undefined;
116-
117-
@state()
118-
selectedChatEntry: ChatThreadEntry | undefined = undefined;
119-
120-
selectedAsideTab: 'tab-thought-process' | 'tab-support-context' | 'tab-citations' = 'tab-thought-process';
121-
122109
// These are the chat bubbles that will be displayed in the chat
123110
chatThread: ChatThreadEntry[] = [];
124111

@@ -130,11 +117,8 @@ export class ChatComponent extends LitElement {
130117
@lazyMultiInject(ControllerType.ChatInputFooter)
131118
chatInputFooterComponets: ChatInputFooterController[] | undefined;
132119

133-
@lazyMultiInject(ControllerType.Citation)
134-
citationControllers: CitationController[] | undefined;
135-
136120
@lazyMultiInject(ControllerType.ChatSection)
137-
chatFooterComponents: ChatSectionController[] | undefined;
121+
chatSectionControllers: ChatSectionController[] | undefined;
138122

139123
// Lifecycle method that runs when the component is first connected to the DOM
140124
override connectedCallback(): void {
@@ -149,13 +133,8 @@ export class ChatComponent extends LitElement {
149133
component.attach(this, this.chatContext);
150134
}
151135
}
152-
if (this.citationControllers) {
153-
for (const component of this.citationControllers) {
154-
component.attach(this, this.chatContext);
155-
}
156-
}
157-
if (this.chatFooterComponents) {
158-
for (const component of this.chatFooterComponents) {
136+
if (this.chatSectionControllers) {
137+
for (const component of this.chatSectionControllers) {
159138
component.attach(this, this.chatContext);
160139
}
161140
}
@@ -193,15 +172,9 @@ export class ChatComponent extends LitElement {
193172

194173
handleCitationClick(event: CustomEvent): void {
195174
event?.preventDefault();
196-
this.selectedCitation = event?.detail?.citation;
197-
198-
if (!this.isShowingThoughtProcess) {
199-
if (event?.detail?.chatThreadEntry) {
200-
this.selectedChatEntry = event?.detail?.chatThreadEntry;
201-
}
202-
this.handleExpandAside();
203-
this.selectedAsideTab = 'tab-citations';
204-
}
175+
this.chatContext.selectedCitation = event?.detail?.citation;
176+
this.chatContext.selectedChatEntry = event?.detail?.chatThreadEntry;
177+
this.chatContext.setState('showCitations', true);
205178
}
206179

207180
getMessageContext(): Message[] {
@@ -274,7 +247,7 @@ export class ChatComponent extends LitElement {
274247
this.isChatStarted = false;
275248
this.chatThread = [];
276249
this.isDisabled = false;
277-
this.selectedCitation = undefined;
250+
this.chatContext.selectedCitation = undefined;
278251
this.chatController.reset();
279252
// clean up the current session content from the history too
280253
this.chatHistoryController.saveChatHistory(this.chatThread);
@@ -293,22 +266,14 @@ export class ChatComponent extends LitElement {
293266
this.chatController.cancelRequest();
294267
}
295268

296-
// show thought process aside
297-
handleExpandAside(event: Event | undefined = undefined): void {
298-
event?.preventDefault();
299-
this.isShowingThoughtProcess = true;
300-
this.selectedAsideTab = 'tab-thought-process';
301-
this.shadowRoot?.querySelector('#overlay')?.classList.add('active');
302-
this.shadowRoot?.querySelector('#chat__containerWrapper')?.classList.add('aside-open');
303-
}
304-
305269
// hide thought process aside
306270
collapseAside(event: Event): void {
307-
event.preventDefault();
308-
this.isShowingThoughtProcess = false;
309-
this.selectedCitation = undefined;
310-
this.shadowRoot?.querySelector('#chat__containerWrapper')?.classList.remove('aside-open');
311-
this.shadowRoot?.querySelector('#overlay')?.classList.remove('active');
271+
event?.preventDefault();
272+
if (this.chatSectionControllers) {
273+
for (const component of this.chatSectionControllers) {
274+
component.close();
275+
}
276+
}
312277
}
313278

314279
renderChatOrCancelButton() {
@@ -333,64 +298,6 @@ export class ChatComponent extends LitElement {
333298
return this.chatController.isProcessingResponse ? cancelChatButton : submitChatButton;
334299
}
335300

336-
renderChatEntryTabContent(entry: ChatThreadEntry) {
337-
return html` <tab-component
338-
.tabs="${[
339-
{
340-
id: 'tab-thought-process',
341-
label: globalConfig.THOUGHT_PROCESS_LABEL,
342-
},
343-
{
344-
id: 'tab-support-context',
345-
label: globalConfig.SUPPORT_CONTEXT_LABEL,
346-
},
347-
{
348-
id: 'tab-citations',
349-
label: globalConfig.CITATIONS_TAB_LABEL,
350-
},
351-
] as TabContent[]}"
352-
.selectedTabId="${this.selectedAsideTab}"
353-
>
354-
<div slot="tab-thought-process" class="tab-component__content">
355-
${entry && entry.thoughts ? html` <p class="tab-component__paragraph">${unsafeHTML(entry.thoughts)}</p> ` : ''}
356-
</div>
357-
<div slot="tab-support-context" class="tab-component__content">
358-
${entry && entry.dataPoints
359-
? html` <teaser-list-component
360-
.alwaysRow="${true}"
361-
.teasers="${entry.dataPoints.map((d) => {
362-
return { description: d };
363-
})}"
364-
></teaser-list-component>`
365-
: ''}
366-
</div>
367-
${entry && entry.citations
368-
? html`
369-
<div slot="tab-citations" class="tab-component__content">
370-
<citation-list
371-
.citations="${entry.citations}"
372-
.label="${globalConfig.CITATIONS_LABEL}"
373-
.selectedCitation="${this.selectedCitation}"
374-
@on-citation-click="${this.handleCitationClick}"
375-
></citation-list>
376-
${this.selectedCitation
377-
? this.citationControllers?.map((component) =>
378-
component.render(this.selectedCitation, `${this.apiUrl}/content/${this.selectedCitation.text}`),
379-
)
380-
: ''}
381-
</div>
382-
`
383-
: ''}
384-
</tab-component>`;
385-
}
386-
387-
handleChatEntryActionButtonClick(event: CustomEvent) {
388-
if (event.detail?.id === 'chat-show-thought-process') {
389-
this.selectedChatEntry = event.detail?.chatThreadEntry;
390-
this.handleExpandAside(event);
391-
}
392-
}
393-
394301
override willUpdate(): void {
395302
this.isDisabled = this.chatController.generatingAnswer;
396303

@@ -408,21 +315,12 @@ export class ChatComponent extends LitElement {
408315
renderChatThread(chatThread: ChatThreadEntry[]) {
409316
return html`<chat-thread-component
410317
.chatThread="${chatThread}"
411-
.actionButtons="${[
412-
{
413-
id: 'chat-show-thought-process',
414-
label: globalConfig.SHOW_THOUGH_PROCESS_BUTTON_LABEL_TEXT,
415-
svgIcon: iconLightBulb,
416-
isDisabled: this.isShowingThoughtProcess,
417-
},
418-
] as any}"
419318
.isDisabled="${this.isDisabled}"
420319
.isProcessingResponse="${this.chatController.isProcessingResponse}"
421-
.selectedCitation="${this.selectedCitation}"
320+
.selectedCitation="${this.chatContext.selectedCitation}"
422321
.isCustomBranding="${this.isCustomBranding}"
423322
.svgIcon="${iconLogo}"
424323
.context="${this.chatContext}"
425-
@on-action-button-click="${this.handleChatEntryActionButtonClick}"
426324
@on-citation-click="${this.handleCitationClick}"
427325
@on-followup-click="${this.handleInput}"
428326
>
@@ -439,9 +337,10 @@ export class ChatComponent extends LitElement {
439337

440338
// Render the chat component as a web component
441339
override render() {
340+
const isAsideEnabled = this.chatSectionControllers?.some((controller) => controller.isEnabled);
442341
return html`
443-
<div id="overlay" class="overlay"></div>
444-
<section id="chat__containerWrapper" class="chat__containerWrapper">
342+
<div id="overlay" class="overlay ${isAsideEnabled ? 'active' : ''}"></div>
343+
<section id="chat__containerWrapper" class="chat__containerWrapper ${isAsideEnabled ? 'aside-open' : ''}">
445344
${this.isCustomBranding && !this.isChatStarted
446345
? html` <chat-stage
447346
svgIcon="${iconLogo}"
@@ -528,23 +427,7 @@ export class ChatComponent extends LitElement {
528427
)}
529428
</form>
530429
</section>
531-
<!-- ${this.isShowingThoughtProcess
532-
? html`
533-
<aside class="aside" data-testid="aside-thought-process">
534-
<div class="aside__header">
535-
<chat-action-button
536-
.label="${globalConfig.HIDE_THOUGH_PROCESS_BUTTON_LABEL_TEXT}"
537-
actionId="chat-hide-thought-process"
538-
@click="${this.collapseAside}"
539-
.svgIcon="${iconClose}"
540-
>
541-
</chat-action-button>
542-
</div>
543-
${this.renderChatEntryTabContent(this.selectedChatEntry as ChatThreadEntry)}
544-
</aside>
545-
`
546-
: ''} -->
547-
${this.chatFooterComponents?.map((component) => component.render())}
430+
${isAsideEnabled ? this.chatSectionControllers?.map((component) => component.render()) : ''}
548431
</section>
549432
`;
550433
}

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ export class ChatContextController implements ReactiveController {
2525

2626
private _isChatStarted: boolean = false;
2727

28+
private _selectedCitation: Citation | undefined = undefined;
29+
30+
public set selectedCitation(citation: Citation | undefined) {
31+
this._selectedCitation = citation;
32+
this.host.requestUpdate();
33+
}
34+
35+
public get selectedCitation() {
36+
return this._selectedCitation;
37+
}
38+
2839
public set isChatStarted(value: boolean) {
2940
this._isChatStarted = value;
3041
this.host.requestUpdate();

0 commit comments

Comments
 (0)