Skip to content

Commit

Permalink
Merge pull request #44 from meta-d/develop
Browse files Browse the repository at this point in the history
Develop v2.5.3
  • Loading branch information
meta-d authored Aug 15, 2024
2 parents 06cc26f + cc64bcb commit 3c13fd2
Show file tree
Hide file tree
Showing 15 changed files with 270 additions and 203 deletions.
2 changes: 1 addition & 1 deletion apps/cloud/src/app/@core/services/copilot-usage.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export class CopilotUsageService {
return this.httpClient
.get<{ items: ICopilotOrganization[] }>(API_COPILOT_ORGANIZATION, {
params: {
$relations: JSON.stringify(['org'])
$relations: JSON.stringify(['organization'])
}
})
.pipe(map(({ items }) => items))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@
}
@case ('chart') {
<ngm-analytical-card class="h-[300px] group"
[dataSettings]="charts()[$index].dataSettings"
[dataSettings]="charts()[$index]?.dataSettings"
[chartOptions]="answer.chartOptions"
[chartSettings]="charts()[$index].chartSettings"
[chartSettings]="charts()[$index]?.chartSettings"
[options]="answer.options"
[slicers]="answer.slicers"
(explain)="setExplains($event)"
Expand Down Expand Up @@ -121,7 +121,7 @@
}
@case ('kpi') {
<pac-widget-kpi class="h-[200px] group" displayDensity="compact"
[dataSettings]="charts()[$index].dataSettings"
[dataSettings]="charts()[$index]?.dataSettings"
[slicers]="answer.slicers"
[options]="{showToolbar: true, shortNumber: true, digitsInfo: '0.1-1'}"
(slicersChange)="updateSlicers($event)"
Expand Down
234 changes: 117 additions & 117 deletions apps/cloud/src/app/features/chatbi/chat/chat.component.html

Large diffs are not rendered by default.

31 changes: 22 additions & 9 deletions apps/cloud/src/app/features/chatbi/home.component.html
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
<section id="chatTools" class="h-full pt-4 pb-2 md:pb-4">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 h-full flex flex-col">
<div class="mx-auto max-w-7xl p-2 lg:px-8 h-full flex flex-col gap-2">
<div class="title container relative mx-auto text-center">
<h1 class="font-bold text-2xl md:text-3xl pb-2">
{{ 'PAC.ChatBI.Title' | translate: {Default: 'ChatBI-Data Analysis &amp; Insights with' } }}

<ngm-select class="inline-block" displayDensity="cosy"
[placeholder]="hasModel() ? ('PAC.KEY_WORDS.SemanticModel' | translate: {Default: 'Semantic Model'}) : ('PAC.ChatBI.NoSemanticModel' | translate: {Default: 'No Semantic Model'})"
<ngm-select class="inline-block border border-dashed rounded-lg" displayDensity="cosy" #mTooltip="matTooltip"
[placeholder]="hasModel() ? ('PAC.KEY_WORDS.SelectSemanticModel' | translate: {Default: 'Select Semantic Model'}) : ('PAC.ChatBI.NoSemanticModel' | translate: {Default: 'No Semantic Model'})"
[displayBehaviour]="DisplayBehaviour.descriptionOnly"
[selectOptions]="models()"
[panelWidth]="400"
[panelWidth]="360"
valueKey="key"
[(ngModel)]="modelId"
[matTooltip]=" 'PAC.KEY_WORDS.SelectSemanticModel' | translate: {Default: 'Select Semantic Model'} "
matTooltipPosition="right"
[ngClass]="modelId ? 'border-transparent' : 'border-neutral-500'"
/>

@if (isMobile()) {
<a class="cursor-pointer overflow-hidden text-ellipsis mx-2"
[ngClass]="cube() ? '' : 'p-2 rounded-lg border border-dashed border-neutral-500 opacity-50'"
[matTooltip]=" 'PAC.ChatBI.SelectACube' | translate: {Default: 'Select a Cube'} "
matTooltipPosition="right"
(click)="openSelectCube()">
{{cube() ? cube().caption || cube().name : ('PAC.ChatBI.SelectCube' | translate: {Default: 'Select Cube' })}}</a>
}
</h1>
<p class="text-zinc-500 text-xs md:text-sm">
{{ 'PAC.ChatBI.TransformData' | translate: {Default: 'Transform data into insights with AI.' } }}
</p>
</div>

<div class="w-full flex-1 flex flex-col lg:flex-row-reverse justify-between items-stretch overflow-hidden">
<pac-chatbi-models class="my-4 w-full min-h-[120px] lg:w-80 rounded-lg border
border-gray-200 bg-white dark:border-zinc-800 dark:bg-neutral-950" />
<pac-chatbi-chat class="flex-1 lg:m-4 lg:flex-1 rounded-xl border shadow-lg shadow-sky-800/10 overflow-hidden grid grid-cols-1
<pac-chatbi-models class="my-4 w-full min-h-[120px] lg:w-80 rounded-lg border
border-gray-200 bg-white dark:border-zinc-800 dark:bg-neutral-950"
[ngClass]="isMobile() ? openCubes() ? 'ngm-chatbi-cubes__mobile-opened' : 'ngm-chatbi-cubes__mobile-closed' : ''"
/>

<pac-chatbi-chat class="flex-1 lg:m-4 lg:flex-1 rounded-xl lg:shadow-lg shadow-sky-800/10 overflow-hidden grid grid-cols-1
border-zinc-200 bg-white dark:border-zinc-800 dark:bg-neutral-950"/>
</div>
</div>
</section>

@if (showExplorer()) {
<ngm-story-explorer class="absolute top-0 left-0 w-full h-full z-20"
Expand Down
9 changes: 8 additions & 1 deletion apps/cloud/src/app/features/chatbi/home.component.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
:host {
flex: 1;
@apply max-w-full flex-1;
}

.ngm-chatbi-cubes__mobile-closed {
@apply hidden;
}
.ngm-chatbi-cubes__mobile-opened {
@apply flex absolute top-0 left-0 w-full h-full z-10;
}

:host::ng-deep {
Expand Down
26 changes: 23 additions & 3 deletions apps/cloud/src/app/features/chatbi/home.component.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { DragDropModule } from '@angular/cdk/drag-drop'
import { CommonModule } from '@angular/common'
import { ChangeDetectionStrategy, Component, computed, effect, inject, signal } from '@angular/core'
import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, viewChild } from '@angular/core'
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip'
import { ActivatedRoute, Router, RouterModule } from '@angular/router'
import { CopilotChatMessage } from '@metad/copilot'
import { NgmSelectComponent } from '@metad/ocap-angular/common'
Expand All @@ -19,6 +20,7 @@ import { ChatbiService } from './chatbi.service'
import { injectInsightCommand } from './copilot'
import { ChatbiModelsComponent } from './models/models.component'
import { QuestionAnswer } from './types'
import { AppService } from '../../app.service'

@Component({
standalone: true,
Expand All @@ -30,11 +32,12 @@ import { QuestionAnswer } from './types'
DragDropModule,
RouterModule,
TranslateModule,
MatTooltipModule,
NgmSelectComponent,
ChatbiModelsComponent,
ChatbiChatComponent,

StoryExplorerModule,
StoryExplorerModule
],
selector: 'pac-chatbi-home',
templateUrl: './home.component.html',
Expand All @@ -48,19 +51,23 @@ export class ChatbiHomeComponent {

readonly chatbiService = inject(ChatbiService)
readonly conversationService = inject(ChatBIConversationService)
readonly appService = inject(AppService)
readonly router = inject(Router)
readonly route = inject(ActivatedRoute)
readonly logger = inject(NGXLogger)
readonly conversationId = injectQueryParams('id')

// readonly modelId = model<string>(null)
readonly modelTooltip = viewChild('mTooltip', { read: MatTooltip })

get modelId() {
return this.chatbiService.modelId()
}
set modelId(value) {
this.chatbiService.setModelId(value)
}

readonly isMobile = this.appService.isMobile
readonly openCubes = signal(false)
readonly models = toSignal(
this.chatbiService.models$.pipe(
map((models) =>
Expand All @@ -74,6 +81,9 @@ export class ChatbiHomeComponent {
)
readonly hasModel = computed(() => this.models()?.length > 0)
readonly _conversationId = computed(() => this.chatbiService.conversation()?.id)
readonly cubeName = this.chatbiService.entity
readonly cubes = this.chatbiService.cubes
readonly cube = computed(() => this.cubes()?.find((item) => item.name === this.cubeName()))

// Story explorer
readonly showExplorer = signal(false)
Expand Down Expand Up @@ -116,6 +126,12 @@ export class ChatbiHomeComponent {
},
{ allowSignalWrites: true }
)

effect(() => {
if (!this.chatbiService.modelId() && this.models()?.length) {
this.modelTooltip().show()
}
})
}

async openExplore(message: CopilotChatMessage, answer: QuestionAnswer) {
Expand All @@ -131,4 +147,8 @@ export class ChatbiHomeComponent {
this.chatbiService.updateQuestionAnswer(this.explore().key, event)
}
}

openSelectCube() {
this.openCubes.set(true)
}
}
129 changes: 66 additions & 63 deletions apps/cloud/src/app/features/chatbi/input/input.component.html
Original file line number Diff line number Diff line change
@@ -1,74 +1,77 @@
<div data-ignore-for-autoscroll="true" class="max-w-3xl w-full mx-auto">
<div class="relative px-2 md:px-1">
<fieldset
class="relative bg-white flex flex-col gap-2 px-4 py-2 border border-gray-300 rounded-2xl shadow shadow-slate-200
dark:bg-neutral-900 dark:border-neutral-700"
>
<div class="flex items-center flex-grow gap-x-2">
<button class="p-1 rounded-lg hover:bg-black/5 dark:hover:bg-white/10"
[matTooltip]="'Copilot.NewChat' | translate: {Default: 'New chat'}"
[cdkMenuTriggerFor]="menu"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 24 24" class="icon-xl-heavy">
<path d="M15.673 3.913a3.121 3.121 0 1 1 4.414 4.414l-5.937 5.937a5 5 0 0 1-2.828 1.415l-2.18.31a1 1 0 0 1-1.132-1.13l.311-2.18A5 5 0 0 1 9.736 9.85zm3 1.414a1.12 1.12 0 0 0-1.586 0l-5.937 5.937a3 3 0 0 0-.849 1.697l-.123.86.86-.122a3 3 0 0 0 1.698-.849l5.937-5.937a1.12 1.12 0 0 0 0-1.586M11 4A1 1 0 0 1 10 5c-.998 0-1.702.008-2.253.06-.54.052-.862.141-1.109.267a3 3 0 0 0-1.311 1.311c-.134.263-.226.611-.276 1.216C5.001 8.471 5 9.264 5 10.4v3.2c0 1.137 0 1.929.051 2.546.05.605.142.953.276 1.216a3 3 0 0 0 1.311 1.311c.263.134.611.226 1.216.276.617.05 1.41.051 2.546.051h3.2c1.137 0 1.929 0 2.546-.051.605-.05.953-.142 1.216-.276a3 3 0 0 0 1.311-1.311c.126-.247.215-.569.266-1.108.053-.552.06-1.256.06-2.255a1 1 0 1 1 2 .002c0 .978-.006 1.78-.069 2.442-.064.673-.192 1.27-.475 1.827a5 5 0 0 1-2.185 2.185c-.592.302-1.232.428-1.961.487C15.6 21 14.727 21 13.643 21h-3.286c-1.084 0-1.958 0-2.666-.058-.728-.06-1.369-.185-1.96-.487a5 5 0 0 1-2.186-2.185c-.302-.592-.428-1.233-.487-1.961C3 15.6 3 14.727 3 13.643v-3.286c0-1.084 0-1.958.058-2.666.06-.729.185-1.369.487-1.961A5 5 0 0 1 5.73 3.545c.556-.284 1.154-.411 1.827-.475C8.22 3.007 9.021 3 10 3A1 1 0 0 1 11 4"></path>
</svg>
</button>
<div class="flex items-center flex-grow overflow-x-hidden">
<fieldset
[matTooltip]="!modelId() ? ('PAC.ChatBI.SelectSemanticModel' | translate: {Default: 'Select Semantic Model'}) :
!cube() ? ('PAC.ChatBI.SelectCube' | translate: {Default: 'Select a cube firstly!'}) : null"
matTooltipPosition="above"
class="relative bg-white flex flex-col gap-2 px-4 py-2 border border-gray-300 rounded-2xl shadow shadow-slate-200
dark:bg-neutral-900 dark:border-neutral-700"
>
<div class="flex items-center flex-grow gap-x-2">
<button class="p-1 rounded-lg hover:bg-black/5 dark:hover:bg-white/10"
[matTooltip]="'Copilot.NewChat' | translate: {Default: 'New chat'}"
[cdkMenuTriggerFor]="menu"
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 24 24" class="icon-xl-heavy">
<path d="M15.673 3.913a3.121 3.121 0 1 1 4.414 4.414l-5.937 5.937a5 5 0 0 1-2.828 1.415l-2.18.31a1 1 0 0 1-1.132-1.13l.311-2.18A5 5 0 0 1 9.736 9.85zm3 1.414a1.12 1.12 0 0 0-1.586 0l-5.937 5.937a3 3 0 0 0-.849 1.697l-.123.86.86-.122a3 3 0 0 0 1.698-.849l5.937-5.937a1.12 1.12 0 0 0 0-1.586M11 4A1 1 0 0 1 10 5c-.998 0-1.702.008-2.253.06-.54.052-.862.141-1.109.267a3 3 0 0 0-1.311 1.311c-.134.263-.226.611-.276 1.216C5.001 8.471 5 9.264 5 10.4v3.2c0 1.137 0 1.929.051 2.546.05.605.142.953.276 1.216a3 3 0 0 0 1.311 1.311c.263.134.611.226 1.216.276.617.05 1.41.051 2.546.051h3.2c1.137 0 1.929 0 2.546-.051.605-.05.953-.142 1.216-.276a3 3 0 0 0 1.311-1.311c.126-.247.215-.569.266-1.108.053-.552.06-1.256.06-2.255a1 1 0 1 1 2 .002c0 .978-.006 1.78-.069 2.442-.064.673-.192 1.27-.475 1.827a5 5 0 0 1-2.185 2.185c-.592.302-1.232.428-1.961.487C15.6 21 14.727 21 13.643 21h-3.286c-1.084 0-1.958 0-2.666-.058-.728-.06-1.369-.185-1.96-.487a5 5 0 0 1-2.186-2.185c-.302-.592-.428-1.233-.487-1.961C3 15.6 3 14.727 3 13.643v-3.286c0-1.084 0-1.958.058-2.666.06-.729.185-1.369.487-1.961A5 5 0 0 1 5.73 3.545c.556-.284 1.154-.411 1.827-.475C8.22 3.007 9.021 3 10 3A1 1 0 0 1 11 4"></path>
</svg>
</button>
<div class="flex items-center flex-grow overflow-x-hidden">

<input #userInput matInput class="ngm-colpilot__input w-full px-1.5 z-10 resize-none overflow-visible outline-none"
[ngClass]="{disabled: answering() ||!cube()}"
id="userInput" onInput="this.parentNode.dataset.replicatedValue = this.value"
[placeholder]="'PAC.ChatBI.InputPlaceholder' | translate: {Default: 'Ask a question about the dataset, press Enter to send'} "
[(ngModel)]="prompt"
[disabled]="answering() || !cube()"
(keydown)="triggerFun($event, autoPrompts)"
<input #userInput matInput class="ngm-colpilot__input w-full px-1.5 z-10 resize-none overflow-visible outline-none"
[ngClass]="{disabled: answering() ||!cube()}"
id="userInput" onInput="this.parentNode.dataset.replicatedValue = this.value"
[placeholder]="'PAC.ChatBI.InputPlaceholder' | translate: {Default: 'Ask a question about the dataset, press Enter to send'} "
[(ngModel)]="prompt"
[disabled]="answering() || !cube()"
(keydown)="triggerFun($event, autoPrompts)"

[matAutocomplete]="autoPrompts"
matAutocompletePosition="above"
>
[matAutocomplete]="autoPrompts"
matAutocompletePosition="above"
>

<mat-autocomplete #autoPrompts="matAutocomplete" class="ngm-copilot-chat__autocomplete-panel ngm-autocomplete-panel ngm-density__cosy"
autoActiveFirstOption
hideSingleSelectionIndicator
(opened)="suggestionsOpened$.next(true)"
(closed)="suggestionsOpened$.next(false)"
>
@for (command of prompts(); track command.prompt) {
<mat-option [value]="'/'+command.name+' '+(command.example || '')" [title]="command.description">
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
>/{{command.name}}</span>
@if (command.alias) {
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
>/{{command.alias}}</span>
}
<span class="ml-auto opacity-50">{{command.description}}</span>
</mat-option>
<mat-autocomplete #autoPrompts="matAutocomplete" class="ngm-copilot-chat__autocomplete-panel ngm-autocomplete-panel ngm-density__cosy"
autoActiveFirstOption
hideSingleSelectionIndicator
(opened)="suggestionsOpened$.next(true)"
(closed)="suggestionsOpened$.next(false)"
>
@for (command of prompts(); track command.prompt) {
<mat-option [value]="'/'+command.name+' '+(command.example || '')" [title]="command.description">
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
>/{{command.name}}</span>
@if (command.alias) {
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
>/{{command.alias}}</span>
}
</mat-autocomplete>

<div class="grid grid-flow-col items-center">
@if (answering()) {
<button type="button" class="rounded-full md:bottom-3 md:right-3 right-2 border-solid p-1 hover:opacity-60 text-white bg-black dark:bg-white dark:text-black" aria-label="停止生成"
(click)="stopGenerating()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" class="icon-lg"><rect width="10" height="10" x="7" y="7" fill="currentColor" rx="1.25"></rect></svg>
</button>
} @else {
<button type="button" class="rounded-full md:bottom-3 md:right-3 right-2 border-solid p-1 bg-black disabled:opacity-10 disabled:text-gray-400 enabled:bg-black text-white dark:border-white dark:bg-white bottom-1.5 transition-colors
hover:opacity-60" data-testid="send-button"
[disabled]="!prompt() || answering() || !cube()"
(click)="ask()"
>
<span class="" data-state="closed">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-white dark:text-black">
<path d="M7 11L12 6L17 11M12 18V7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</span>
</button>
}
</div>
<span class="ml-auto opacity-50">{{command.description}}</span>
</mat-option>
}
</mat-autocomplete>

<div class="grid grid-flow-col items-center">
@if (answering()) {
<button type="button" class="rounded-full md:bottom-3 md:right-3 right-2 border-solid p-1 hover:opacity-60 text-white bg-black dark:bg-white dark:text-black" aria-label="停止生成"
(click)="stopGenerating()">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24" class="icon-lg"><rect width="10" height="10" x="7" y="7" fill="currentColor" rx="1.25"></rect></svg>
</button>
} @else {
<button type="button" class="rounded-full md:bottom-3 md:right-3 right-2 border-solid p-1 bg-black disabled:opacity-10 disabled:text-gray-400 enabled:bg-black text-white dark:border-white dark:bg-white bottom-1.5 transition-colors
hover:opacity-60" data-testid="send-button"
[disabled]="!prompt() || answering() || !cube()"
(click)="ask()"
>
<span class="" data-state="closed">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-white dark:text-black">
<path d="M7 11L12 6L17 11M12 18V7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
</svg>
</span>
</button>
}
</div>
</div>
</fieldset>
</div>
</fieldset>

@if (!copilotEnabled()) {
<div class="absolute top-0 left-0 w-full h-full z-10 flex justify-center items-center rounded-2xl shadow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class ChatbiInputComponent {
readonly #logger = inject(NGXLogger)
readonly router = inject(Router)

readonly modelId = this.chatbiService.modelId
readonly cube = this.chatbiService.entity

readonly prompts = signal([])
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
<div class="w-full px-3 py-1 border-b border-gray-100 flex items-center justify-between dark:border-neutral-800">
@if (isMobile()) {
<button mat-icon-button displayDensity="compact" (click)="close()">
<mat-icon>close</mat-icon>
</button>
}
<h3 class="font-semibold">
{{ 'PAC.ChatBI.Cubes' | translate: {Default: 'Cubes'} }}
</h3>

<span class="flex-1"></span>
<ngm-search [(ngModel)]="search" class="rounded-xl overflow-hidden" />
</div>

<div class="w-full flex-1 pt-2 overflow-auto relative">
<div class="w-full flex-1 py-2 overflow-auto relative">
<cdk-virtual-scroll-viewport class="flex-1 w-full h-full overflow-hidden hover:overflow-y-auto"
itemSize="64" minBufferPx="360" maxBufferPx="1000"
>
Expand Down
Loading

0 comments on commit 3c13fd2

Please sign in to comment.