Skip to content

Ai chat#1500

Merged
lyubov-voloshko merged 28 commits intorocket-admin:mainfrom
karinakharchenko:ai
Feb 8, 2026
Merged

Ai chat#1500
lyubov-voloshko merged 28 commits intorocket-admin:mainfrom
karinakharchenko:ai

Conversation

@karinakharchenko
Copy link
Contributor

No description provided.

karinakharchenko and others added 11 commits January 13, 2026 17:05
…nd UI improvements

- Add grayed character limit counter styling
- Add adaptive textarea rows based on window height (HostListener)
- Add responsive layout for screen widths <= 800px
- Rename suggestions to templates with icons and descriptions
- Add dynamic suggestions based on table column names (date, status, price patterns)
- Pass tableColumns input from dashboard to AI panel component

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add aiPanelExpandedSubject and aiPanelExpandedCast to TableStateService
- Add toggleAIPanelExpanded() and restoreAIPanelExpandedState() methods
- Persist expanded state in sessionStorage
- Add expand/collapse button with open_in_full/close_fullscreen icons
- Add CSS transitions for smooth expand/collapse animation
- Center content with max-width 800px when expanded
- Panel expands to full width minus 260px for sidebar

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add *ngIf to ai-panel-sidebar-content to completely remove it from DOM
when panel is closed, preventing it from overlaying table actions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move AI panel outside mat-sidenav-container to fix z-index issues
- Use 100vw instead of 100% for fixed positioning
- Increase z-index to 100/1000 to stay above sidebar
- Set panel top: 44px to not overlap header
- Simplify HTML by removing redundant *ngIf checks
- Change aiPanelSubject type from any to boolean

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move AI panel back inside mat-sidenav-content for proper table shifting
- Add expanded styles for templates (horizontal layout, nowrap description)
- Reduce gap between section titles and content
- Center header in expanded mode with max-width 800px
- Adjust z-index for sidebar to appear over expanded panel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add sidebarExpanded input to AI panel component
- Pass shownTableTitles from dashboard to AI panel
- Adjust expanded panel position: 240px when sidebar expanded, 65px when collapsed
- Content adapts dynamically to available space

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Position action buttons (close/collapse) fixed to top-right
- Center header content with max-width 800px aligned with input
- Show "AI insights for {tableName}" in expanded mode
- Show only "AI insights" in collapsed mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use Material Design cubic-bezier easing for smoother feel
- Fix sidebar collapse/expand showing table rows by using padding-left instead of left position
- Add transitions to content elements (header, welcome, message form, footer)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Move AI insights button to rightmost position using flexbox order
- Make expand/collapse animation smoother with 550ms duration
- Use gentler easing curve for more pleasant user experience

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Disable sidebar width transition when expanded to prevent table flashing
- Table area is instantly covered when expanding AI chat

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use padding-left approach to hide table during sidebar transitions
- Panel stays at left: 65px, content shifts via padding
- Smooth 400ms ease-out animations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@karinakharchenko
Copy link
Contributor Author

@lyubov-voloshko

karinakharchenko and others added 17 commits January 14, 2026 18:25
- Set width transition to 0ms for sidebar expand/collapse
- Keep transform and opacity animations for initial panel open
- Add toggle animation trigger for Angular animations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix z-index so expanded AI panel covers table alerts
- Add smooth transitions for collapse animation (left, width, padding-left)
- Make expanded panel overlay table instead of pushing it
- Add request cancellation support for cleanup on panel close

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- AI panel always opens in collapsed view (no state persistence)
- Make tables more compact: smaller font (12px), reduced padding
- Add horizontal scroll for tables that don't fit
- Reduce AI message background opacity for lighter appearance
- Fix suggestion chip text color in dark mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add dedicated click handler for suggestions with analytics tracking.
Rename formatColumnName to _formatColumnName following private method convention.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Center input field with rounded corners on welcome screen
- Add three suggestion categories: Explore, Data Quality, Insights
- Show dropdown with completions when clicking suggestion chips
- Update AI message background to softer blue tint
- Increase padding in message bubbles
- Remove templates section
- Hide bottom form when showing welcome screen

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add animated rocket icon on welcome screen with floating and sparkle effects
- Add dynamic loading text that cycles through AI processing steps
- Fix input focus border styling (remove extra vertical line)
- Add click outside handler to close suggestions dropdown
- Position dropdown directly below input field
- Make rocket icon visually lighter with semi-transparent fill

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Show suggestion text in input when clicking chip
- Preview completion text on hover in dropdown
- Update completions to start with suggestion prompt
- Adjust category spacing (4px to chips, 12px between categories)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@lyubov-voloshko lyubov-voloshko marked this pull request as ready for review February 8, 2026 21:42
Copilot AI review requested due to automatic review settings February 8, 2026 21:42
@lyubov-voloshko lyubov-voloshko merged commit 0d01882 into rocket-admin:main Feb 8, 2026
11 of 12 checks passed
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the Dashboard’s “AI insights” chat panel UI/UX and state handling to support an expandable panel layout, richer suggestion templates, and improved loading/cancellation behavior.

Changes:

  • Added expanded/collapsed state for the AI panel in TableStateService and wired it into the AI panel component.
  • Reworked AI panel welcome experience: categorized suggestion chips + completions dropdown + revised loading indicator.
  • Added styling updates for panel layout/expansion and the AI insights button positioning.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
frontend/src/app/services/table-state.service.ts Adds expanded-state observable and ensures it resets when closing the AI panel.
frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css Adjusts AI insights button positioning within the actions row.
frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.ts Adds expansion handling, suggestion categories, request cancellation, and loading-step cycling logic.
frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.spec.ts Updates tests for new suggestion category structure and expanded-cast mock.
frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.html Reworks AI panel markup to support expansion controls and new welcome/suggestion UX.
frontend/src/app/components/dashboard/db-table-view/db-table-ai-panel/db-table-ai-panel.component.css Major styling changes for expanded layout, welcome screen, suggestions/completions, and loading indicator.
frontend/src/app/components/dashboard/dashboard.component.html Passes additional inputs (columns, sidebar expanded state) into the AI panel component.
frontend/src/app/animations/toggle.animation.ts Introduces a new toggle animation export (currently unused).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 83 to +89
this._tableState.aiPanelCast.subscribe((isAIpanelOpened) => {
this.isAIpanelOpened = isAIpanelOpened;
});

this._tableState.aiPanelExpandedCast.subscribe((isExpanded) => {
this.isExpanded = isExpanded;
});
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aiPanelCast and aiPanelExpandedCast are subscribed to in ngOnInit() without any teardown. Since these are BehaviorSubject-backed observables that never complete, this will leak subscriptions each time the panel is opened/closed. Please tie these subscriptions to the component lifecycle (e.g., takeUntilDestroyed() / DestroyRef, or store them in a Subscription composite and unsubscribe in ngOnDestroy()).

Copilot uses AI. Check for mistakes.
Comment on lines +95 to 97
ngOnChanges(): void {
this.generateSuggestionCategories();
}
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ngOnChanges() is declared but the component does not implement OnChanges (and OnChanges is not imported). The repo’s TSLint config enables use-lifecycle-interface, which expects lifecycle hooks to have their corresponding interfaces implemented. Please add OnChanges to the implements list (and import it).

Copilot uses AI. Check for mistakes.
Comment on lines 174 to 186
createThread(suggestedMessage?: string) {
if (suggestedMessage) {
this.message = suggestedMessage;
}
this.submitting = true;
this.startLoadingSteps();
this.messagesChain.push({
type: 'user',
text: this.message
});
const messageCopy = this.message;
this.message = '';

Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

createThread() will submit even when message is empty (welcome form has no required and the method has no guard). This results in sending an empty prompt to the backend and adding an empty user message to the chain. Please add an early return (and ideally keep submitting false) when the trimmed message is empty.

Copilot uses AI. Check for mistakes.
Comment on lines 221 to 233
sendMessage(suggestedMessage?: string): void {
if (suggestedMessage) {
this.message = suggestedMessage;
}
this.submitting = true;
this.startLoadingSteps();
this.messagesChain.push({
type: 'user',
text: this.message
});
const messageCopy = this.message;
this.message = '';
this.charactrsNumber = 0;
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sendMessage() similarly doesn’t guard against an empty/whitespace-only message (and will start loading steps + push an empty user message). Add the same trimmed-message validation used for thread creation, and consider ignoring calls while submitting is already true to avoid overlapping requests.

Copilot uses AI. Check for mistakes.

<form (ngSubmit)="threadID ? sendMessage() : createThread()" class="ai-message-form">
<form *ngIf="messagesChain.length" (ngSubmit)="threadID ? sendMessage() : createThread()" class="ai-message-form">
<mat-form-field class="form-field" appearance="outline" class="ai-message-form__textarea">
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This <mat-form-field> has two class attributes; in HTML the latter overwrites the former, so form-field will be dropped. Merge these into a single class attribute so both classes apply.

Suggested change
<mat-form-field class="form-field" appearance="outline" class="ai-message-form__textarea">
<mat-form-field class="form-field ai-message-form__textarea" appearance="outline">

Copilot uses AI. Check for mistakes.
Comment on lines +134 to +141
startLoadingSteps(): void {
this._currentStepIndex = 0;
this.currentLoadingStep = this._loadingSteps[0];
this._loadingStepsInterval = setInterval(() => {
this._currentStepIndex = (this._currentStepIndex + 1) % this._loadingSteps.length;
this.currentLoadingStep = this._loadingSteps[this._currentStepIndex];
}, 2000);
}
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

startLoadingSteps() starts a new setInterval each time it’s called but doesn’t clear any existing interval first. If the user triggers createThread() / sendMessage() multiple times quickly, this can leave multiple intervals running and cause rapid step changes + leaks. Consider calling stopLoadingSteps() at the start of startLoadingSteps() and/or guarding against re-entrancy when submitting is already true.

Copilot uses AI. Check for mistakes.
Comment on lines +291 to +295
const target = event.target as HTMLElement;
const clickedOnChip = target.closest('.suggestion-chip');
const clickedOnDropdown = target.closest('.ai-completions');
const clickedOnInput = target.closest('.ai-welcome-form__field');

Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onDocumentClick() casts event.target to HTMLElement and unconditionally calls .closest(...). In practice event.target can be a Text node (or other non-HTMLElement), which would throw at runtime. Please guard with event.target instanceof Element (or cast to Element after checking) before calling .closest.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +15
<button mat-icon-button (click)="toggleExpand()">
<mat-icon>{{isExpanded ? 'close_fullscreen' : 'open_in_full'}}</mat-icon>
</button>
<button mat-icon-button (click)="handleClose()">
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expand and close icon-only buttons don’t have an accessible name (no aria-label / aria-labelledby). Please add an aria-label that reflects the action (e.g., “Expand AI insights panel” / “Collapse…” and “Close AI insights panel”) so screen readers can announce them.

Suggested change
<button mat-icon-button (click)="toggleExpand()">
<mat-icon>{{isExpanded ? 'close_fullscreen' : 'open_in_full'}}</mat-icon>
</button>
<button mat-icon-button (click)="handleClose()">
<button mat-icon-button
(click)="toggleExpand()"
[attr.aria-label]="isExpanded ? 'Collapse AI insights panel' : 'Expand AI insights panel'">
<mat-icon>{{isExpanded ? 'close_fullscreen' : 'open_in_full'}}</mat-icon>
</button>
<button mat-icon-button
(click)="handleClose()"
aria-label="Close AI insights panel">

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +38
import {
trigger,
transition,
style,
animate,
query,
group,
} from '@angular/animations';

const easing = 'cubic-bezier(0.4, 0.0, 0.2, 1)';
const duration = '600ms';

export const toggleAnimation = trigger('toggle', [
transition(':enter', [
style({ height: 0, opacity: 0 }),
query('.details', [
style({ transform: 'translateY(-100%)' })
], { optional: true }),
group([
animate(`${duration} ${easing}`, style({ height: '*', opacity: 1 })),
query('.details', [
animate(`${duration} ${easing}`, style({ transform: 'translateY(0)' }))
], { optional: true })
])
]),
transition(':leave', [
style({ height: '*', opacity: 1 }),
query('.details', [
style({ transform: 'translateY(0)' })
], { optional: true }),
group([
animate(`${duration} ${easing}`, style({ height: 0, opacity: 0 })),
query('.details', [
animate(`${duration} ${easing}`, style({ transform: 'translateY(-100%)' }))
], { optional: true })
])
])
]);
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toggleAnimation is introduced as a new exported animation, but there are no references to it anywhere else in the frontend codebase. If it’s not intended for immediate use, it should be removed; otherwise, please wire it into the component(s) that need it to avoid carrying dead code (and to prevent unused-export tooling from flagging it).

Suggested change
import {
trigger,
transition,
style,
animate,
query,
group,
} from '@angular/animations';
const easing = 'cubic-bezier(0.4, 0.0, 0.2, 1)';
const duration = '600ms';
export const toggleAnimation = trigger('toggle', [
transition(':enter', [
style({ height: 0, opacity: 0 }),
query('.details', [
style({ transform: 'translateY(-100%)' })
], { optional: true }),
group([
animate(`${duration} ${easing}`, style({ height: '*', opacity: 1 })),
query('.details', [
animate(`${duration} ${easing}`, style({ transform: 'translateY(0)' }))
], { optional: true })
])
]),
transition(':leave', [
style({ height: '*', opacity: 1 }),
query('.details', [
style({ transform: 'translateY(0)' })
], { optional: true }),
group([
animate(`${duration} ${easing}`, style({ height: 0, opacity: 0 })),
query('.details', [
animate(`${duration} ${easing}`, style({ transform: 'translateY(-100%)' }))
], { optional: true })
])
])
]);
export {};

Copilot uses AI. Check for mistakes.
Comment on lines +116 to +148
cancelRequest(): void {
if (this._currentRequest) {
this._currentRequest.unsubscribe();
this._currentRequest = null;
this.submitting = false;
this.stopLoadingSteps();

this.messagesChain.push({
type: 'ai-error',
text: 'Request cancelled'
});

this.angulartics2.eventTrack.next({
action: 'AI panel: request cancelled',
});
}
}

startLoadingSteps(): void {
this._currentStepIndex = 0;
this.currentLoadingStep = this._loadingSteps[0];
this._loadingStepsInterval = setInterval(() => {
this._currentStepIndex = (this._currentStepIndex + 1) % this._loadingSteps.length;
this.currentLoadingStep = this._loadingSteps[this._currentStepIndex];
}, 2000);
}

stopLoadingSteps(): void {
if (this._loadingStepsInterval) {
clearInterval(this._loadingStepsInterval);
this._loadingStepsInterval = null;
}
}
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behaviors were added (request cancellation + loading-steps timer management), but the spec file doesn’t cover them. Adding unit tests for cancelRequest() (unsubscribes, sets submitting false, stops the interval) and startLoadingSteps()/stopLoadingSteps() (interval is created and cleared) would help prevent regressions.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants