Skip to content

Commit

Permalink
feat(AI-130): fixes for initial messages and styles improvements (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastianmusial committed Feb 9, 2024
1 parent 374032c commit 2374279
Show file tree
Hide file tree
Showing 13 changed files with 130 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
} @empty {
<ai-chat-tips [tips]="tips" (tipSelected$)="tipSelected$.emit($event)" />
}
<ai-chat-typing [isLoading]="isLoading"></ai-chat-typing>
<ai-chat-typing [isTyping]="isTyping"></ai-chat-typing>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { ChatTipsComponent } from '../chat-tips/chat-tips.component';
})
export class ChatMessagesComponent implements AfterViewInit, OnChanges {
@Input() messages: Message[] = [];
@Input() isLoading = false;
@Input() isTyping = false;
@Input() tips: string[] = [];
@Output() tipSelected$ = new EventEmitter<string>();
@ViewChildren('item') item?: QueryList<ElementRef>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@if (isLoading) {
@if (isTyping) {
<div class="chat-typing">
<div class="chat-typing__dots">
<span></span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import { Component, Input } from '@angular/core';
styleUrl: './chat-typing.component.scss',
})
export class ChatTypingComponent {
@Input() isLoading = false;
@Input() isTyping = false;
}
1 change: 1 addition & 0 deletions apps/spa/src/app/components/spinner/spinner.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<span class="spinner"></span>
44 changes: 44 additions & 0 deletions apps/spa/src/app/components/spinner/spinner.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@import 'settings';

:host {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
background-color: var(--color-white);
z-index: 2;
opacity: 0;
transition: ease-out opacity 0.3s;
pointer-events: none;

&.is-active {
opacity: 1;
pointer-events: all;
}
}

.spinner {
width: 88px;
height: 88px;
border-radius: 50%;
display: inline-block;
position: relative;
border: 10px solid;
border-color: rgba(168, 135, 92, 0.15) rgba(168, 135, 92, 0.25)
rgba(168, 135, 92, 0.35) rgba(168, 135, 92, 0.5);
box-sizing: border-box;
animation: rotation 1s linear infinite;
}

@keyframes rotation {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
22 changes: 22 additions & 0 deletions apps/spa/src/app/components/spinner/spinner.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { SpinnerComponent } from './spinner.component';

describe('SpinnerComponent', () => {
let component: SpinnerComponent;
let fixture: ComponentFixture<SpinnerComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SpinnerComponent],
}).compileComponents();

fixture = TestBed.createComponent(SpinnerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
11 changes: 11 additions & 0 deletions apps/spa/src/app/components/spinner/spinner.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Component, HostBinding, Input } from '@angular/core';

@Component({
selector: 'ai-spinner',
standalone: true,
templateUrl: './spinner.component.html',
styleUrl: './spinner.component.scss',
})
export class SpinnerComponent {
@HostBinding('class.is-active') @Input() isActive = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@
(close$)="chatService.toggle()"
(config$)="chatService.clear()"></ai-chat-header>

<ai-spinner [isActive]="isLoading()" />
@if (isConfigEnabled && !threadId()) {
<ai-configuration-form class="chat__content" />
} @else {
<ai-chat-messages
[messages]="messages()"
[isLoading]="isLoading()"
[isTyping]="isTyping()"
[tips]="tips"
(tipSelected$)="chatService.sendMessage($event)"
class="chat__content" />
<ai-chat-footer
[isDisabled]="isLoading()"
[isDisabled]="isTyping()"
[isTranscriptionEnabled]="isTranscriptionEnabled"
[isAttachmentEnabled]="isAttachmentEnabled"
(sendMessage$)="chatService.sendMessage($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ChatMessagesComponent } from '../../../../components/chat/chat-messages
import { ChatFooterComponent } from '../../../../components/chat/chat-footer/chat-footer.component';
import { ConfigurationFormComponent } from '../../../+configuration/components/configuration-form/configuration-form.component';
import { take } from 'rxjs';
import { SpinnerComponent } from '../../../../components/spinner/spinner.component';

@Component({
selector: 'ai-chat',
Expand All @@ -19,12 +20,14 @@ import { take } from 'rxjs';
ChatMessagesComponent,
ChatFooterComponent,
ConfigurationFormComponent,
SpinnerComponent,
],
templateUrl: './chat.component.html',
styleUrl: './chat.component.scss',
})
export class ChatComponent implements OnInit {
messages = toSignal(this.chatService.messages$, { initialValue: [] });
isTyping = toSignal(this.chatService.isTyping$, { initialValue: false });
isLoading = toSignal(this.chatService.isLoading$, { initialValue: false });
threadId = toSignal(this.threadService.threadId$, { initialValue: '' });
isTranscriptionEnabled = environment.isTranscriptionEnabled;
Expand All @@ -44,7 +47,7 @@ export class ChatComponent implements OnInit {
) {}

ngOnInit() {
if (!this.isConfigEnabled) {
if (!this.isConfigEnabled && !this.threadService.threadId$.value) {
this.threadService.start().pipe(take(1)).subscribe();
}
}
Expand Down
19 changes: 14 additions & 5 deletions apps/spa/src/app/modules/+chat/shared/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { Injectable } from '@angular/core';
import {
BehaviorSubject,
distinctUntilChanged,
filter,
map,
mergeMap,
Subscription,
take,
tap,
} from 'rxjs';
import { ChatRole, Message, MessageStatus } from './chat.model';
import { ChatGatewayService } from './chat-gateway.service';
Expand All @@ -20,8 +22,9 @@ import { ThreadMessage } from 'openai/resources/beta/threads';

@Injectable({ providedIn: 'root' })
export class ChatService {
isVisible$ = new BehaviorSubject<boolean>(environment.isAutoOpen);
isLoading$ = new BehaviorSubject<boolean>(false);
isVisible$ = new BehaviorSubject<boolean>(environment.isAutoOpen);
isTyping$ = new BehaviorSubject<boolean>(false);
messages$ = new BehaviorSubject<Message[]>([]);

constructor(
Expand Down Expand Up @@ -63,17 +66,23 @@ export class ChatService {
this.threadService.threadId$
.pipe(
distinctUntilChanged(),
filter(threadId => !!threadId),
tap(() => this.isLoading$.next(true)),
mergeMap(threadId => this.threadService.getThread(threadId)),
map((response: ThreadResponse) => this.parseMessages(response)),
)
.subscribe(data => this.messages$.next(data));
.subscribe(data => {
this.messages$.next(data);
this.isLoading$.next(false);
});
}

toggle(): void {
this.isVisible$.next(!this.isVisible$.value);
}

refresh(): void {
this.isLoading$.next(true);
this.messages$.next([]);
this.threadService.start().subscribe();
}
Expand Down Expand Up @@ -101,7 +110,7 @@ export class ChatService {
}

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

const files = await this.chatFilesService.sendFiles();
Expand All @@ -120,12 +129,12 @@ export class ChatService {
content: data.content,
role: ChatRole.Assistant,
});
this.isLoading$.next(false);
this.isTyping$.next(false);
});
}

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

this.chatClientService
.transcription({
Expand Down
2 changes: 1 addition & 1 deletion apps/spa/src/environments/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const environment = {
appUrl: 'https://ai-assistant-c8b469d88808.herokuapp.com',
apiUrl: 'https://ai-assistant-c8b469d88808.herokuapp.com/api',
websocketUrl: 'https://ai-assistant-c8b469d88808.herokuapp.com',
isThreadMemorized: false,
isThreadMemorized: true,
isAudioEnabled: true,
isTranscriptionEnabled: true,
isAttachmentEnabled: true,
Expand Down
27 changes: 26 additions & 1 deletion libs/ai-embedded/src/lib/assistant-iframe.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@ export const addIframeClass = (className: string) => `.${className} {
border: 0;
box-shadow: rgba(17, 17, 26, 0.1) 0 4px 16px, rgba(17, 17, 26, 0.1) 0 8px 32px;
z-index: 150;
animation: iframeAnimation 0.2s;
}
@keyframes iframeAnimation {
0% {
transform: translateY(20px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@media (max-width: 460px) {
Expand All @@ -40,6 +52,15 @@ export const addTriggerClass = (className: string) => `
}
}
@keyframes triggerFadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.${className} {
display: block;
position: fixed;
Expand All @@ -58,6 +79,9 @@ export const addTriggerClass = (className: string) => `
transition: 0.2s all ease-in-out;
cursor: pointer;
z-index: 100;
opacity: 0;
animation: triggerFadeIn 0.2s ease-in;
animation-delay: 2s;
@media (max-width: 460px) {
width: 40px;
Expand All @@ -72,6 +96,7 @@ export const addTriggerClass = (className: string) => `
}
.${className}.is-animated {
animation: trigger 1.5s infinite;
animation: trigger 1.5s infinite, triggerFadeIn 1s;
animation-delay: 2s;
animation-fill-mode: both;
}`;

0 comments on commit 2374279

Please sign in to comment.