This is an automated email from the ASF dual-hosted git repository. gongchao pushed a commit to branch update-ai-with in repository https://gitbox.apache.org/repos/asf/hertzbeat.git
commit f7428c25c3d3cea7eddef4a3c4ae06ebc5d31ca8 Author: tomsun28 <[email protected]> AuthorDate: Thu Oct 30 23:42:30 2025 +0800 [webapp] update ui Signed-off-by: tomsun28 <[email protected]> --- .../shared/components/ai-chat/chat.component.less | 125 ++++++++++++++++++++- .../shared/components/ai-chat/chat.component.ts | 33 +++++- 2 files changed, 151 insertions(+), 7 deletions(-) diff --git a/web-app/src/app/shared/components/ai-chat/chat.component.less b/web-app/src/app/shared/components/ai-chat/chat.component.less index 8edbb3a1c..2af24a670 100644 --- a/web-app/src/app/shared/components/ai-chat/chat.component.less +++ b/web-app/src/app/shared/components/ai-chat/chat.component.less @@ -21,7 +21,9 @@ .chat-container { display: flex; - height: 80vh; // Use viewport height for modal context + height: 100%; + min-height: 500px; + max-height: 80vh; background: @layout-body-background; .chat-sidebar { @@ -54,6 +56,25 @@ .conversation-list { flex: 1; overflow-y: auto; + scrollbar-width: thin; + scrollbar-color: @border-color-base transparent; + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: @border-color-base; + border-radius: 3px; + } + + &::-webkit-scrollbar-thumb:hover { + background: @border-color-split; + } .conversation-item { padding: 12px 16px; @@ -134,6 +155,26 @@ padding: 16px; overflow-y: auto; background: @layout-body-background; + scrollbar-width: thin; + scrollbar-color: @border-color-base transparent; + scroll-behavior: smooth; + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: @border-color-base; + border-radius: 3px; + } + + &::-webkit-scrollbar-thumb:hover { + background: @border-color-split; + } .loading-container { display: flex; @@ -395,6 +436,7 @@ height: 100%; z-index: 100; box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15); + transition: transform 0.3s ease; &.collapsed { transform: translateX(-100%); @@ -411,6 +453,46 @@ } } } + + .input-area { + .input-container { + flex-direction: column; + gap: 8px; + + .send-button { + align-self: flex-end; + width: auto; + min-width: 80px; + } + } + } + } + } +} + +// Extra small devices +@media (max-width: 480px) { + .chat-container { + min-height: 400px; + max-height: 90vh; + + .chat-main { + .messages-container { + padding: 12px; + + .message { + margin-bottom: 16px; + + .message-content { + max-width: 90%; + padding: 10px 12px; + } + } + } + + .input-area { + padding: 12px; + } } } } @@ -593,6 +675,47 @@ body[data-theme='dark'] .chat-container { color: fade(@white, 45%) !important; } } + + // Fix dropdown/select styling in dark theme + .ant-select { + .ant-select-selector { + background: fade(@white, 8%) !important; + border-color: @border-color-split !important; + color: fade(@white, 85%) !important; + } + + .ant-select-selection-placeholder { + color: fade(@white, 45%) !important; + } + + &:hover .ant-select-selector { + border-color: @primary-color !important; + } + + &.ant-select-focused .ant-select-selector { + border-color: @primary-color !important; + box-shadow: 0 0 0 2px fade(@primary-color, 20%) !important; + } + } + + // Fix dropdown options styling + .ant-select-dropdown { + background: #141414 !important; + border: 1px solid @border-color-split !important; + + .ant-select-item { + color: fade(@white, 85%) !important; + + &:hover { + background: fade(@white, 8%) !important; + } + + &.ant-select-item-option-selected { + background: @primary-color !important; + color: @white !important; + } + } + } } // Additional high-specificity overrides for dark theme diff --git a/web-app/src/app/shared/components/ai-chat/chat.component.ts b/web-app/src/app/shared/components/ai-chat/chat.component.ts index cd4fb0f0f..6c0002b1d 100644 --- a/web-app/src/app/shared/components/ai-chat/chat.component.ts +++ b/web-app/src/app/shared/components/ai-chat/chat.component.ts @@ -17,7 +17,7 @@ * under the License. */ -import { Component, OnInit, ViewChild, ElementRef, AfterViewChecked, ChangeDetectorRef } from '@angular/core'; +import { Component, OnInit, ViewChild, ElementRef, ChangeDetectorRef, OnDestroy } from '@angular/core'; import { I18NService } from '@core'; import { NzMessageService } from 'ng-zorro-antd/message'; import { NzModalService } from 'ng-zorro-antd/modal'; @@ -32,7 +32,7 @@ import { ThemeService } from '../../../service/theme.service'; templateUrl: './chat.component.html', styleUrls: ['./chat.component.less'] }) -export class ChatComponent implements OnInit, AfterViewChecked { +export class ChatComponent implements OnInit, OnDestroy { @ViewChild('messagesContainer') private messagesContainer!: ElementRef; conversations: ConversationDto[] = []; @@ -42,6 +42,7 @@ export class ChatComponent implements OnInit, AfterViewChecked { isLoading = false; sidebarCollapsed = false; theme: string = 'default'; + private scrollTimeout: any; // OpenAI Configuration isOpenAiConfigured = false; @@ -65,8 +66,22 @@ export class ChatComponent implements OnInit, AfterViewChecked { this.checkAiConfiguration(); } - ngAfterViewChecked(): void { - this.scrollToBottom(); + ngOnDestroy(): void { + if (this.scrollTimeout) { + clearTimeout(this.scrollTimeout); + } + } + + /** + * Debounced scroll to bottom to improve performance + */ + private scrollToBottomDebounced(): void { + if (this.scrollTimeout) { + clearTimeout(this.scrollTimeout); + } + this.scrollTimeout = setTimeout(() => { + this.scrollToBottom(); + }, 100); } /** @@ -403,13 +418,19 @@ export class ChatComponent implements OnInit, AfterViewChecked { } /** - * Scroll to bottom of messages + * Scroll to bottom of messages with smooth animation */ private scrollToBottom(): void { try { if (this.messagesContainer) { const element = this.messagesContainer.nativeElement; - element.scrollTop = element.scrollHeight; + // Use requestAnimationFrame for better performance + requestAnimationFrame(() => { + element.scrollTo({ + top: element.scrollHeight, + behavior: 'smooth' + }); + }); } } catch (err) { console.error('Error scrolling to bottom:', err); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
