Skip to content

Commit

Permalink
Merge pull request #59 from boldare/fix/chatbot-actions
Browse files Browse the repository at this point in the history
fix(chatbot): inactivated refresh button and inputs when the message …
  • Loading branch information
sebastianmusial committed May 13, 2024
2 parents aa8f1c0 + a4d399c commit 678908c
Show file tree
Hide file tree
Showing 16 changed files with 67 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
<ai-card-footer>
<ai-controls>
@if (isTranscriptionEnabled) {
<ai-recorder (send$)="sendAudio$.emit($event)" matTooltip="Record audio" />
<ai-recorder
(send$)="sendAudio$.emit($event)"
[isDisabled]="isDisabled"
[matTooltip]="!isDisabled ? 'Record audio' : ''"
/>
} @if (isAttachmentEnabled) {
<ai-files matTooltip="Add files" />
<ai-files
[matTooltip]="!isDisabled ? 'Add files' : ''"
[isDisabled]="isDisabled"
/>
}
</ai-controls>

<ai-input [isDisabled]="isDisabled" (send$)="sendMessage$.emit($event)" />
<ai-input
(send$)="!isDisabled && sendMessage$.emit($event)"
[isDisabled]="isDisabled"
/>
</ai-card-footer>
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,20 @@
</div>
<div class="chat-header__controls">
@if (isConfigEnabled) {
<button mat-icon-button (click)="config$.emit()" matTooltip="Settings">
<button
mat-icon-button
matTooltip="Settings"
(click)="config$.emit()"
>
<mat-icon class="char-header__icon">settings</mat-icon>
</button>
} @if (isRefreshEnabled) {
<button mat-icon-button (click)="refresh$.emit()" matTooltip="Refresh">
<button
mat-icon-button
matTooltip="Refresh"
(click)="refresh$.emit()"
[disabled]="isResponding"
>
<mat-icon class="char-header__icon">refresh</mat-icon>
</button>
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export class ChatHeaderComponent {
@Output() close$ = new EventEmitter();
@Output() refresh$ = new EventEmitter();
@Output() config$ = new EventEmitter();
@Input() isResponding = false;
@Input() isRefreshEnabled = true;
@Input() isConfigEnabled = true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@
background-color: var(--color-grey-300);
color: var(--color-grey-900);
}

&.is-disabled {
pointer-events: none;
opacity: 0.5;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Component } from '@angular/core';
import { Component, HostBinding, Input } from '@angular/core';

@Component({
selector: 'ai-control-item',
standalone: true,
templateUrl: './control-item.component.html',
styleUrl: './control-item.component.scss',
})
export class ControlItemComponent {}
export class ControlItemComponent {
@HostBinding('class.is-disabled') @Input() isDisabled = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
aiFiles
(click)="input.click()"
(drop$)="addFiles($event)"
[files]="files()">
[files]="files()"
[isDisabled]="isDisabled"
>
<ai-control-icon>attach_file</ai-control-icon>

@if (files().length) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, ViewChild } from '@angular/core';
import { Component, Input, ViewChild } from '@angular/core';
import { MatIcon } from '@angular/material/icon';
import { AiFilesDirective } from './files.directive';
import { toSignal } from '@angular/core/rxjs-interop';
Expand All @@ -20,6 +20,7 @@ import { ControlIconComponent } from '../control-icon/control-icon.component';
})
export class FilesComponent {
@ViewChild('input') input!: HTMLInputElement;
@Input() isDisabled = false;
files = toSignal(this.fileService.files$, { initialValue: [] });

constructor(private readonly fileService: FilesService) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
placeholder="Aa"
autocomplete="off"
[(ngModel)]="content"
[disabled]="isDisabled"
(keydown.enter)="send(content)" />
(keydown.enter)="!isDisabled && send(content)" />
<button
class="input__suffix"
mat-icon-button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@

.input__suffix {
margin-right: 4px;

&.mat-mdc-button-disabled {
opacity: 0.5;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<ai-control-item [ngClass]="{ 'is-active': recording }" (click)="onRecord()">
<ai-control-item
(click)="onRecord()"
[ngClass]="{ 'is-active': recording }"
[isDisabled]="isDisabled"
>
<ai-control-icon class="recorder__icon">mic</ai-control-icon>
<div class="recorder__circle"></div>
</ai-control-item>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, EventEmitter, Output } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { NgClass, NgIf } from '@angular/common';
import { MatIcon } from '@angular/material/icon';
import * as RecordRTC from 'recordrtc';
Expand All @@ -14,6 +14,7 @@ import { ControlItemComponent } from '../control-item/control-item.component';
})
export class RecorderComponent {
@Output() send$ = new EventEmitter<Blob>();
@Input() isDisabled = false;
record: RecordRTC.StereoAudioRecorder | null = null;
recording = false;
url!: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<ai-chat-header
[isRefreshEnabled]="isRefreshEnabled && !!threadId()"
[isConfigEnabled]="isConfigEnabled && !!threadId()"
[isResponding]="isResponding()"
(refresh$)="chatService.refresh()"
(close$)="chatService.toggle()"
(config$)="chatService.clear()"></ai-chat-header>
Expand All @@ -17,7 +18,7 @@
(tipSelected$)="chatService.sendMessage($event)"
class="chat__content" />
<ai-chat-footer
[isDisabled]="isTyping()"
[isDisabled]="isResponding()"
[isTranscriptionEnabled]="isTranscriptionEnabled"
[isAttachmentEnabled]="isAttachmentEnabled"
(sendMessage$)="chatService.sendMessage($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ export class ChatIframeComponent implements OnInit {
messages = toSignal(this.chatService.messages$, { initialValue: [] });
isTyping = toSignal(this.chatService.isTyping$, { initialValue: false });
isLoading = toSignal(this.chatService.isLoading$, { initialValue: false });
isResponding = toSignal(this.chatService.isResponding$, {
initialValue: false,
});
threadId = toSignal(this.threadService.threadId$, { initialValue: '' });
isTranscriptionEnabled = environment.isTranscriptionEnabled;
isAttachmentEnabled = environment.isAttachmentEnabled;
Expand Down
9 changes: 9 additions & 0 deletions apps/spa/src/app/modules/+chat/shared/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export class ChatService {
isLoading$ = new BehaviorSubject<boolean>(false);
isVisible$ = new BehaviorSubject<boolean>(environment.isAutoOpen);
isTyping$ = new BehaviorSubject<boolean>(false);
isResponding$ = new BehaviorSubject<boolean>(false);
messages$ = new BehaviorSubject<ChatMessage[]>([]);

constructor(
Expand Down Expand Up @@ -99,12 +100,14 @@ export class ChatService {
refresh(): void {
this.isLoading$.next(true);
this.isTyping$.next(false);
this.isResponding$.next(false);
this.messages$.next([]);
this.threadService.start().subscribe();
}

clear(): void {
this.isTyping$.next(false);
this.isResponding$.next(false);
this.threadService.clear();
this.messages$.next([]);
}
Expand All @@ -128,6 +131,7 @@ export class ChatService {

async sendMessage(content: string, role = ChatRole.User): Promise<void> {
this.isTyping$.next(true);
this.isResponding$.next(true);
this.addMessage({ content, role });

const files = await this.chatFilesService.sendFiles();
Expand All @@ -149,20 +153,23 @@ export class ChatService {
watchTextCreated(): Subscription {
return this.chatGatewayService.textCreated().subscribe(data => {
this.isTyping$.next(false);
this.isResponding$.next(true);
this.addMessage({ content: data.text.value, role: ChatRole.Assistant });
});
}

watchTextDelta(): Subscription {
return this.chatGatewayService.textDelta().subscribe(data => {
const length = this.messages$.value.length;
this.isResponding$.next(true);
this.messages$.value[length - 1].content = data.text.value;
});
}

watchTextDone(): Subscription {
return this.chatGatewayService.textDone().subscribe(data => {
this.isTyping$.next(false);
this.isResponding$.next(false);
this.messages$.next([
...this.messages$.value.slice(0, -1),
{
Expand All @@ -180,11 +187,13 @@ export class ChatService {
role: ChatRole.Assistant,
});
this.isTyping$.next(false);
this.isResponding$.next(false);
});
}

sendAudio(file: Blob): void {
this.isTyping$.next(true);
this.isResponding$.next(true);

this.chatClientService
.transcription({ file: file as File })
Expand Down
2 changes: 1 addition & 1 deletion apps/spa/src/environments/environment.development.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const environment = {
isTranscriptionEnabled: true,
isAttachmentEnabled: true,
isRefreshEnabled: true,
isConfigEnabled: true,
isConfigEnabled: false,
isAutoOpen: true,
isStreamingEnabled: true,
};
2 changes: 1 addition & 1 deletion apps/spa/src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const environment = {
isTranscriptionEnabled: true,
isAttachmentEnabled: true,
isRefreshEnabled: true,
isConfigEnabled: true,
isConfigEnabled: false,
isAutoOpen: true,
isStreamingEnabled: true,
};

0 comments on commit 678908c

Please sign in to comment.