Skip to content

Commit b0764ab

Browse files
committed
feat: support a array of books
1 parent 2edec13 commit b0764ab

File tree

6 files changed

+104
-96
lines changed

6 files changed

+104
-96
lines changed

backend/src/main/java/ch/xxx/aidoclibchat/domain/model/dto/FunctionResult.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
*/
1313
package ch.xxx.aidoclibchat.domain.model.dto;
1414

15+
import java.util.List;
16+
1517
import ch.xxx.aidoclibchat.usecase.service.FunctionService.JsonResult;
1618

17-
public record FunctionResult(String result, JsonResult jsonResult) { }
19+
public record FunctionResult(String result, List<JsonResult> jsonResult) { }

backend/src/main/java/ch/xxx/aidoclibchat/usecase/service/FunctionService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.springframework.ai.chat.client.ChatClient;
2020
import org.springframework.ai.chat.client.ChatClient.Builder;
2121
import org.springframework.beans.factory.annotation.Value;
22+
import org.springframework.core.ParameterizedTypeReference;
2223
import org.springframework.stereotype.Service;
2324

2425
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@@ -75,7 +76,7 @@ private FunctionResult functionCallText(String question) {
7576

7677
private FunctionResult functionCallJson(String question) {
7778
var result = this.chatClient.prompt().user(this.promptStr + question).functions("openLibraryClient").call()
78-
.entity(JsonResult.class);
79+
.entity(new ParameterizedTypeReference<List<JsonResult>>() {});
7980
return new FunctionResult(null, result);
8081
}
8182
}

frontend/src/angular/src/app/function-search/function-search.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
</div>
6262
} @else {
6363
<p *ngIf="!!responseText" class="result-text">{{responseText}}</p>
64-
<p *ngIf="!!responseJson?.value1" class="result-text">
64+
<p *ngIf="!!responseJson?.at(0)?.value1" class="result-text">
6565
<!-- {{responseJson | json}} -->
6666
<mat-tree
6767
[dataSource]="dataSource"
@@ -88,7 +88,7 @@
8888
{{ treeControl.isExpanded(node) ? "expand_more" : "chevron_right" }}
8989
</mat-icon>
9090
</button>
91-
<span i18n="@@fuctionSearchAuthor">Author</span>: {{ node.value1 }}
91+
<span class="book-author" i18n="@@functionSearchAuthor">Author</span><span class="book-author">: {{ node.value1 }}</span>
9292
</div>
9393
<div
9494
[class.example-tree-invisible]="!treeControl.isExpanded(node)"

frontend/src/angular/src/app/function-search/function-search.component.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@
4848
display: block;
4949
width: 90vw;
5050
white-space: wrap;
51+
font-size: 16px;
52+
}
53+
54+
.book-author {
55+
font-size: 16px;
5156
}
5257

5358
.spinner-container {

frontend/src/angular/src/app/function-search/function-search.component.ts

Lines changed: 91 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Licensed under the Apache License, Version 2.0 (the "License");
44
you may not use this file except in compliance with the License.
55
You may obtain a copy of the License at
6-
http://www.apache.org/licenses/LICENSE-2.0
6+
http://www.apache.org/licenses/LICENSE-2.0
77
Unless required by applicable law or agreed to in writing, software
88
distributed under the License is distributed on an "AS IS" BASIS,
99
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -20,115 +20,115 @@ import { MatInputModule } from '@angular/material/input';
2020
import { MatTooltipModule } from '@angular/material/tooltip';
2121
import { MatFormFieldModule } from '@angular/material/form-field';
2222
import {
23-
FormControl,
24-
FormsModule,
25-
ReactiveFormsModule,
26-
Validators,
23+
FormControl,
24+
FormsModule,
25+
ReactiveFormsModule,
26+
Validators,
2727
} from '@angular/forms';
2828
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
29-
import { Book, FunctionResponse, FunctionSearch, JsonResult } from '../model/functions';
29+
import { Book, FunctionResponse, FunctionSearch, JsonBook, JsonResult } from '../model/functions';
3030
import { FunctionSearchService } from '../service/function-search.service';
3131
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3232
import { Subscription, interval, map, tap } from 'rxjs';
3333
import { NestedTreeControl } from '@angular/cdk/tree';
3434
import { MatIconModule } from '@angular/material/icon';
35-
import {MatRadioModule} from '@angular/material/radio';
35+
import { MatRadioModule } from '@angular/material/radio';
3636

3737
interface TreeNode {
38-
value1: string;
39-
value2: string;
40-
children?: TreeNode[];
38+
value1: string;
39+
value2: string;
40+
children?: TreeNode[];
4141
}
4242

4343
@Component({
44-
selector: 'app-function-search',
45-
imports: [
46-
CommonModule,
47-
MatToolbarModule,
48-
MatButtonModule,
49-
MatInputModule,
50-
MatTooltipModule,
51-
MatTreeModule,
52-
MatIconModule,
44+
selector: 'app-function-search',
45+
imports: [
46+
CommonModule,
47+
MatToolbarModule,
48+
MatButtonModule,
49+
MatInputModule,
50+
MatTooltipModule,
51+
MatTreeModule,
52+
MatIconModule,
5353
MatRadioModule,
54-
MatFormFieldModule,
55-
FormsModule,
56-
ReactiveFormsModule,
57-
MatProgressSpinnerModule,
58-
],
59-
templateUrl: './function-search.component.html',
60-
styleUrl: './function-search.component.scss'
54+
MatFormFieldModule,
55+
FormsModule,
56+
ReactiveFormsModule,
57+
MatProgressSpinnerModule,
58+
],
59+
templateUrl: './function-search.component.html',
60+
styleUrl: './function-search.component.scss'
6161
})
6262
export class FunctionSearchComponent {
63-
private repeatSub: Subscription | null = null;
64-
protected searchValueControl = new FormControl('', [
65-
Validators.required,
66-
Validators.minLength(3),
67-
]);
68-
protected searching = false;
69-
protected msWorking = 0;
70-
protected treeControl = new NestedTreeControl<TreeNode>(
71-
(node) => node.children
72-
);
73-
protected dataSource = new MatTreeNestedDataSource<TreeNode>();
74-
protected responseText = '';
75-
protected responseJson = {value1: "", value2: ""} as TreeNode;
76-
protected resultFormats = ['text','json'];
77-
protected resultFormatControl = new FormControl(this.resultFormats[0]);
63+
private repeatSub: Subscription | null = null;
64+
protected searchValueControl = new FormControl('', [
65+
Validators.required,
66+
Validators.minLength(3),
67+
]);
68+
protected searching = false;
69+
protected msWorking = 0;
70+
protected treeControl = new NestedTreeControl<TreeNode>(
71+
(node) => node.children
72+
);
73+
protected dataSource = new MatTreeNestedDataSource<TreeNode>();
74+
protected responseText = '';
75+
protected responseJson = [{ value1: "", value2: "" } as TreeNode];
76+
protected resultFormats = ['text', 'json'];
77+
protected resultFormatControl = new FormControl(this.resultFormats[0]);
7878

79-
constructor(
80-
private router: Router,
81-
private destroyRef: DestroyRef,
82-
private functionSearchService: FunctionSearchService
83-
) {}
79+
constructor(
80+
private router: Router,
81+
private destroyRef: DestroyRef,
82+
private functionSearchService: FunctionSearchService
83+
) { }
8484

85-
protected hasChild = (_: number, node: TreeNode) =>
86-
!!node.children && node.children.length > 0;
85+
protected hasChild = (_: number, node: TreeNode) =>
86+
!!node.children && node.children.length > 0;
8787

88-
protected showList(): void {
89-
this.router.navigate(['/doclist']);
90-
}
88+
protected showList(): void {
89+
this.router.navigate(['/doclist']);
90+
}
9191

92-
protected search(): void {
93-
this.searching = true;
94-
this.dataSource.data = [];
95-
const startDate = new Date();
96-
this.repeatSub?.unsubscribe();
97-
this.repeatSub = interval(100)
98-
.pipe(
99-
map(() => new Date()),
100-
takeUntilDestroyed(this.destroyRef)
101-
)
102-
.subscribe(
103-
(newDate) => (this.msWorking = newDate.getTime() - startDate.getTime())
104-
);
105-
this.functionSearchService
106-
.postLibraryFunction({
107-
question: this.searchValueControl.value,
108-
resultFormat: this.resultFormatControl.value
109-
} as FunctionSearch)
110-
.pipe(
111-
tap(() => this.repeatSub?.unsubscribe()),
112-
takeUntilDestroyed(this.destroyRef),
113-
tap(() => (this.searching = false))
114-
)
115-
.subscribe(value => this.resultFormatControl.value === this.resultFormats[0] ?
116-
this.responseText = value.result || '' : this.responseJson = this.addToDataSource(this.mapResult(value.jsonResult || {author: "", books: []} as JsonResult))
117-
);
118-
}
92+
protected search(): void {
93+
this.searching = true;
94+
this.dataSource.data = [];
95+
const startDate = new Date();
96+
this.repeatSub?.unsubscribe();
97+
this.repeatSub = interval(100)
98+
.pipe(
99+
map(() => new Date()),
100+
takeUntilDestroyed(this.destroyRef)
101+
)
102+
.subscribe(
103+
(newDate) => (this.msWorking = newDate.getTime() - startDate.getTime())
104+
);
105+
this.functionSearchService
106+
.postLibraryFunction({
107+
question: this.searchValueControl.value,
108+
resultFormat: this.resultFormatControl.value
109+
} as FunctionSearch)
110+
.pipe(
111+
tap(() => this.repeatSub?.unsubscribe()),
112+
takeUntilDestroyed(this.destroyRef),
113+
tap(() => (this.searching = false))
114+
)
115+
.subscribe(value => this.resultFormatControl.value === this.resultFormats[0] ?
116+
this.responseText = value.result || '' : this.responseJson = this.addToDataSource(this.mapResult(value.jsonResult || [{ author: "", books: [] }] as JsonResult[]))
117+
);
118+
}
119119

120-
private addToDataSource(treeNode: TreeNode): TreeNode {
121-
this.dataSource.data = [treeNode];
122-
return treeNode;
123-
}
124-
125-
private mapResult(jsonResult: JsonResult): TreeNode {
126-
const children = jsonResult?.books.map(value => ({value1: value.title, value2: value.summary} as TreeNode));
127-
const rootNode = {value1: jsonResult.author, value2: "", children: children} as TreeNode;
128-
return rootNode;
129-
}
120+
private addToDataSource(treeNodes: TreeNode[]): TreeNode[] {
121+
this.dataSource.data = treeNodes;
122+
return treeNodes;
123+
}
130124

131-
protected logout(): void {
132-
console.log('logout');
133-
}
125+
private mapResult(jsonResults: JsonResult[]): TreeNode[] {
126+
const createChildren = (books: JsonBook[]) => books.map(value => ({ value1: value.title, value2: value.summary } as TreeNode));
127+
const rootNode = jsonResults.map(myValue => ({ value1: myValue.author, value2: "", children: createChildren(myValue.books) } as TreeNode));
128+
return rootNode;
129+
}
130+
131+
protected logout(): void {
132+
console.log('logout');
133+
}
134134
}

frontend/src/angular/src/app/model/functions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface FunctionResponse {
3838

3939
export interface FunctionResult {
4040
result?: string;
41-
jsonResult?: JsonResult;
41+
jsonResult?: JsonResult[];
4242
}
4343

4444
export interface JsonResult {

0 commit comments

Comments
 (0)