Skip to content

Commit 3c13fd2

Browse files
authored
Merge pull request #44 from meta-d/develop
Develop v2.5.3
2 parents 06cc26f + cc64bcb commit 3c13fd2

File tree

15 files changed

+270
-203
lines changed

15 files changed

+270
-203
lines changed

apps/cloud/src/app/@core/services/copilot-usage.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class CopilotUsageService {
1414
return this.httpClient
1515
.get<{ items: ICopilotOrganization[] }>(API_COPILOT_ORGANIZATION, {
1616
params: {
17-
$relations: JSON.stringify(['org'])
17+
$relations: JSON.stringify(['organization'])
1818
}
1919
})
2020
.pipe(map(({ items }) => items))

apps/cloud/src/app/features/chatbi/answer/answer.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@
6868
}
6969
@case ('chart') {
7070
<ngm-analytical-card class="h-[300px] group"
71-
[dataSettings]="charts()[$index].dataSettings"
71+
[dataSettings]="charts()[$index]?.dataSettings"
7272
[chartOptions]="answer.chartOptions"
73-
[chartSettings]="charts()[$index].chartSettings"
73+
[chartSettings]="charts()[$index]?.chartSettings"
7474
[options]="answer.options"
7575
[slicers]="answer.slicers"
7676
(explain)="setExplains($event)"
@@ -121,7 +121,7 @@
121121
}
122122
@case ('kpi') {
123123
<pac-widget-kpi class="h-[200px] group" displayDensity="compact"
124-
[dataSettings]="charts()[$index].dataSettings"
124+
[dataSettings]="charts()[$index]?.dataSettings"
125125
[slicers]="answer.slicers"
126126
[options]="{showToolbar: true, shortNumber: true, digitsInfo: '0.1-1'}"
127127
(slicersChange)="updateSlicers($event)"

apps/cloud/src/app/features/chatbi/chat/chat.component.html

Lines changed: 117 additions & 117 deletions
Large diffs are not rendered by default.

apps/cloud/src/app/features/chatbi/home.component.html

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,44 @@
1-
<section id="chatTools" class="h-full pt-4 pb-2 md:pb-4">
2-
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 h-full flex flex-col">
1+
<div class="mx-auto max-w-7xl p-2 lg:px-8 h-full flex flex-col gap-2">
32
<div class="title container relative mx-auto text-center">
43
<h1 class="font-bold text-2xl md:text-3xl pb-2">
54
{{ 'PAC.ChatBI.Title' | translate: {Default: 'ChatBI-Data Analysis &amp; Insights with' } }}
65

7-
<ngm-select class="inline-block" displayDensity="cosy"
8-
[placeholder]="hasModel() ? ('PAC.KEY_WORDS.SemanticModel' | translate: {Default: 'Semantic Model'}) : ('PAC.ChatBI.NoSemanticModel' | translate: {Default: 'No Semantic Model'})"
6+
<ngm-select class="inline-block border border-dashed rounded-lg" displayDensity="cosy" #mTooltip="matTooltip"
7+
[placeholder]="hasModel() ? ('PAC.KEY_WORDS.SelectSemanticModel' | translate: {Default: 'Select Semantic Model'}) : ('PAC.ChatBI.NoSemanticModel' | translate: {Default: 'No Semantic Model'})"
98
[displayBehaviour]="DisplayBehaviour.descriptionOnly"
109
[selectOptions]="models()"
11-
[panelWidth]="400"
10+
[panelWidth]="360"
1211
valueKey="key"
1312
[(ngModel)]="modelId"
13+
[matTooltip]=" 'PAC.KEY_WORDS.SelectSemanticModel' | translate: {Default: 'Select Semantic Model'} "
14+
matTooltipPosition="right"
15+
[ngClass]="modelId ? 'border-transparent' : 'border-neutral-500'"
1416
/>
17+
18+
@if (isMobile()) {
19+
<a class="cursor-pointer overflow-hidden text-ellipsis mx-2"
20+
[ngClass]="cube() ? '' : 'p-2 rounded-lg border border-dashed border-neutral-500 opacity-50'"
21+
[matTooltip]=" 'PAC.ChatBI.SelectACube' | translate: {Default: 'Select a Cube'} "
22+
matTooltipPosition="right"
23+
(click)="openSelectCube()">
24+
{{cube() ? cube().caption || cube().name : ('PAC.ChatBI.SelectCube' | translate: {Default: 'Select Cube' })}}</a>
25+
}
1526
</h1>
1627
<p class="text-zinc-500 text-xs md:text-sm">
1728
{{ 'PAC.ChatBI.TransformData' | translate: {Default: 'Transform data into insights with AI.' } }}
1829
</p>
1930
</div>
2031

2132
<div class="w-full flex-1 flex flex-col lg:flex-row-reverse justify-between items-stretch overflow-hidden">
22-
<pac-chatbi-models class="my-4 w-full min-h-[120px] lg:w-80 rounded-lg border
23-
border-gray-200 bg-white dark:border-zinc-800 dark:bg-neutral-950" />
24-
<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
33+
<pac-chatbi-models class="my-4 w-full min-h-[120px] lg:w-80 rounded-lg border
34+
border-gray-200 bg-white dark:border-zinc-800 dark:bg-neutral-950"
35+
[ngClass]="isMobile() ? openCubes() ? 'ngm-chatbi-cubes__mobile-opened' : 'ngm-chatbi-cubes__mobile-closed' : ''"
36+
/>
37+
38+
<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
2539
border-zinc-200 bg-white dark:border-zinc-800 dark:bg-neutral-950"/>
2640
</div>
2741
</div>
28-
</section>
2942

3043
@if (showExplorer()) {
3144
<ngm-story-explorer class="absolute top-0 left-0 w-full h-full z-20"

apps/cloud/src/app/features/chatbi/home.component.scss

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
:host {
2-
flex: 1;
2+
@apply max-w-full flex-1;
3+
}
4+
5+
.ngm-chatbi-cubes__mobile-closed {
6+
@apply hidden;
7+
}
8+
.ngm-chatbi-cubes__mobile-opened {
9+
@apply flex absolute top-0 left-0 w-full h-full z-10;
310
}
411

512
:host::ng-deep {

apps/cloud/src/app/features/chatbi/home.component.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { DragDropModule } from '@angular/cdk/drag-drop'
22
import { CommonModule } from '@angular/common'
3-
import { ChangeDetectionStrategy, Component, computed, effect, inject, signal } from '@angular/core'
3+
import { ChangeDetectionStrategy, Component, computed, effect, inject, signal, viewChild } from '@angular/core'
44
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop'
55
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
6+
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip'
67
import { ActivatedRoute, Router, RouterModule } from '@angular/router'
78
import { CopilotChatMessage } from '@metad/copilot'
89
import { NgmSelectComponent } from '@metad/ocap-angular/common'
@@ -19,6 +20,7 @@ import { ChatbiService } from './chatbi.service'
1920
import { injectInsightCommand } from './copilot'
2021
import { ChatbiModelsComponent } from './models/models.component'
2122
import { QuestionAnswer } from './types'
23+
import { AppService } from '../../app.service'
2224

2325
@Component({
2426
standalone: true,
@@ -30,11 +32,12 @@ import { QuestionAnswer } from './types'
3032
DragDropModule,
3133
RouterModule,
3234
TranslateModule,
35+
MatTooltipModule,
3336
NgmSelectComponent,
3437
ChatbiModelsComponent,
3538
ChatbiChatComponent,
3639

37-
StoryExplorerModule,
40+
StoryExplorerModule
3841
],
3942
selector: 'pac-chatbi-home',
4043
templateUrl: './home.component.html',
@@ -48,19 +51,23 @@ export class ChatbiHomeComponent {
4851

4952
readonly chatbiService = inject(ChatbiService)
5053
readonly conversationService = inject(ChatBIConversationService)
54+
readonly appService = inject(AppService)
5155
readonly router = inject(Router)
5256
readonly route = inject(ActivatedRoute)
5357
readonly logger = inject(NGXLogger)
5458
readonly conversationId = injectQueryParams('id')
5559

56-
// readonly modelId = model<string>(null)
60+
readonly modelTooltip = viewChild('mTooltip', { read: MatTooltip })
61+
5762
get modelId() {
5863
return this.chatbiService.modelId()
5964
}
6065
set modelId(value) {
6166
this.chatbiService.setModelId(value)
6267
}
6368

69+
readonly isMobile = this.appService.isMobile
70+
readonly openCubes = signal(false)
6471
readonly models = toSignal(
6572
this.chatbiService.models$.pipe(
6673
map((models) =>
@@ -74,6 +81,9 @@ export class ChatbiHomeComponent {
7481
)
7582
readonly hasModel = computed(() => this.models()?.length > 0)
7683
readonly _conversationId = computed(() => this.chatbiService.conversation()?.id)
84+
readonly cubeName = this.chatbiService.entity
85+
readonly cubes = this.chatbiService.cubes
86+
readonly cube = computed(() => this.cubes()?.find((item) => item.name === this.cubeName()))
7787

7888
// Story explorer
7989
readonly showExplorer = signal(false)
@@ -116,6 +126,12 @@ export class ChatbiHomeComponent {
116126
},
117127
{ allowSignalWrites: true }
118128
)
129+
130+
effect(() => {
131+
if (!this.chatbiService.modelId() && this.models()?.length) {
132+
this.modelTooltip().show()
133+
}
134+
})
119135
}
120136

121137
async openExplore(message: CopilotChatMessage, answer: QuestionAnswer) {
@@ -131,4 +147,8 @@ export class ChatbiHomeComponent {
131147
this.chatbiService.updateQuestionAnswer(this.explore().key, event)
132148
}
133149
}
150+
151+
openSelectCube() {
152+
this.openCubes.set(true)
153+
}
134154
}

apps/cloud/src/app/features/chatbi/input/input.component.html

Lines changed: 66 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,77 @@
11
<div data-ignore-for-autoscroll="true" class="max-w-3xl w-full mx-auto">
22
<div class="relative px-2 md:px-1">
3-
<fieldset
4-
class="relative bg-white flex flex-col gap-2 px-4 py-2 border border-gray-300 rounded-2xl shadow shadow-slate-200
5-
dark:bg-neutral-900 dark:border-neutral-700"
6-
>
7-
<div class="flex items-center flex-grow gap-x-2">
8-
<button class="p-1 rounded-lg hover:bg-black/5 dark:hover:bg-white/10"
9-
[matTooltip]="'Copilot.NewChat' | translate: {Default: 'New chat'}"
10-
[cdkMenuTriggerFor]="menu"
11-
>
12-
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 24 24" class="icon-xl-heavy">
13-
<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>
14-
</svg>
15-
</button>
16-
<div class="flex items-center flex-grow overflow-x-hidden">
3+
<fieldset
4+
[matTooltip]="!modelId() ? ('PAC.ChatBI.SelectSemanticModel' | translate: {Default: 'Select Semantic Model'}) :
5+
!cube() ? ('PAC.ChatBI.SelectCube' | translate: {Default: 'Select a cube firstly!'}) : null"
6+
matTooltipPosition="above"
7+
class="relative bg-white flex flex-col gap-2 px-4 py-2 border border-gray-300 rounded-2xl shadow shadow-slate-200
8+
dark:bg-neutral-900 dark:border-neutral-700"
9+
>
10+
<div class="flex items-center flex-grow gap-x-2">
11+
<button class="p-1 rounded-lg hover:bg-black/5 dark:hover:bg-white/10"
12+
[matTooltip]="'Copilot.NewChat' | translate: {Default: 'New chat'}"
13+
[cdkMenuTriggerFor]="menu"
14+
>
15+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 24 24" class="icon-xl-heavy">
16+
<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>
17+
</svg>
18+
</button>
19+
<div class="flex items-center flex-grow overflow-x-hidden">
1720

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

26-
[matAutocomplete]="autoPrompts"
27-
matAutocompletePosition="above"
28-
>
29+
[matAutocomplete]="autoPrompts"
30+
matAutocompletePosition="above"
31+
>
2932

30-
<mat-autocomplete #autoPrompts="matAutocomplete" class="ngm-copilot-chat__autocomplete-panel ngm-autocomplete-panel ngm-density__cosy"
31-
autoActiveFirstOption
32-
hideSingleSelectionIndicator
33-
(opened)="suggestionsOpened$.next(true)"
34-
(closed)="suggestionsOpened$.next(false)"
35-
>
36-
@for (command of prompts(); track command.prompt) {
37-
<mat-option [value]="'/'+command.name+' '+(command.example || '')" [title]="command.description">
38-
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
39-
>/{{command.name}}</span>
40-
@if (command.alias) {
41-
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
42-
>/{{command.alias}}</span>
43-
}
44-
<span class="ml-auto opacity-50">{{command.description}}</span>
45-
</mat-option>
33+
<mat-autocomplete #autoPrompts="matAutocomplete" class="ngm-copilot-chat__autocomplete-panel ngm-autocomplete-panel ngm-density__cosy"
34+
autoActiveFirstOption
35+
hideSingleSelectionIndicator
36+
(opened)="suggestionsOpened$.next(true)"
37+
(closed)="suggestionsOpened$.next(false)"
38+
>
39+
@for (command of prompts(); track command.prompt) {
40+
<mat-option [value]="'/'+command.name+' '+(command.example || '')" [title]="command.description">
41+
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
42+
>/{{command.name}}</span>
43+
@if (command.alias) {
44+
<span class="ngm-copilot-chat__command-tag text-xs font-medium me-2 px-1 mr-1 rounded"
45+
>/{{command.alias}}</span>
4646
}
47-
</mat-autocomplete>
48-
49-
<div class="grid grid-flow-col items-center">
50-
@if (answering()) {
51-
<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="停止生成"
52-
(click)="stopGenerating()">
53-
<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>
54-
</button>
55-
} @else {
56-
<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
57-
hover:opacity-60" data-testid="send-button"
58-
[disabled]="!prompt() || answering() || !cube()"
59-
(click)="ask()"
60-
>
61-
<span class="" data-state="closed">
62-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-white dark:text-black">
63-
<path d="M7 11L12 6L17 11M12 18V7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
64-
</svg>
65-
</span>
66-
</button>
67-
}
68-
</div>
47+
<span class="ml-auto opacity-50">{{command.description}}</span>
48+
</mat-option>
49+
}
50+
</mat-autocomplete>
51+
52+
<div class="grid grid-flow-col items-center">
53+
@if (answering()) {
54+
<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="停止生成"
55+
(click)="stopGenerating()">
56+
<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>
57+
</button>
58+
} @else {
59+
<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
60+
hover:opacity-60" data-testid="send-button"
61+
[disabled]="!prompt() || answering() || !cube()"
62+
(click)="ask()"
63+
>
64+
<span class="" data-state="closed">
65+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="text-white dark:text-black">
66+
<path d="M7 11L12 6L17 11M12 18V7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
67+
</svg>
68+
</span>
69+
</button>
70+
}
6971
</div>
7072
</div>
71-
</fieldset>
73+
</div>
74+
</fieldset>
7275

7376
@if (!copilotEnabled()) {
7477
<div class="absolute top-0 left-0 w-full h-full z-10 flex justify-center items-center rounded-2xl shadow

apps/cloud/src/app/features/chatbi/input/input.component.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ export class ChatbiInputComponent {
6464
readonly #logger = inject(NGXLogger)
6565
readonly router = inject(Router)
6666

67+
readonly modelId = this.chatbiService.modelId
6768
readonly cube = this.chatbiService.entity
6869

6970
readonly prompts = signal([])

apps/cloud/src/app/features/chatbi/models/models.component.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
<div class="w-full px-3 py-1 border-b border-gray-100 flex items-center justify-between dark:border-neutral-800">
2+
@if (isMobile()) {
3+
<button mat-icon-button displayDensity="compact" (click)="close()">
4+
<mat-icon>close</mat-icon>
5+
</button>
6+
}
27
<h3 class="font-semibold">
38
{{ 'PAC.ChatBI.Cubes' | translate: {Default: 'Cubes'} }}
49
</h3>
10+
11+
<span class="flex-1"></span>
512
<ngm-search [(ngModel)]="search" class="rounded-xl overflow-hidden" />
613
</div>
714

8-
<div class="w-full flex-1 pt-2 overflow-auto relative">
15+
<div class="w-full flex-1 py-2 overflow-auto relative">
916
<cdk-virtual-scroll-viewport class="flex-1 w-full h-full overflow-hidden hover:overflow-y-auto"
1017
itemSize="64" minBufferPx="360" maxBufferPx="1000"
1118
>

0 commit comments

Comments
 (0)