Skip to content

Commit 2f1c6f5

Browse files
committed
chore(): update frontend to get data from backend
1 parent 06cbff8 commit 2f1c6f5

File tree

6 files changed

+56
-48
lines changed

6 files changed

+56
-48
lines changed

frontend/angular.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@
9292
},
9393
"serve": {
9494
"builder": "@angular-devkit/build-angular:dev-server",
95+
"options": {
96+
"proxyConfig": "src/proxy.conf.json"
97+
},
9598
"configurations": {
9699
"production": {
97100
"buildTarget": "lvz-viz:build:production"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface PagedResponse<T> {
2+
content: T[];
3+
totalElements: number;
4+
}

frontend/src/app/features/search/search.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<input matInput placeholder="Suchphrase eingeben" #input />
1515
</mat-form-field>
1616
<div id="filter-article">
17-
{{ length }} Artikel <span *ngIf="length > 0 && query()"> für Filter mit '{{ query() }}'</span>
17+
{{ totalElements }} Artikel <span *ngIf="totalElements > 0 && query()"> für Filter mit '{{ query() }}'</span>
1818
</div>
1919
</div>
2020

@@ -59,7 +59,7 @@
5959
<tr mat-row *matRowDef="let row; columns: ['article']" class="article-detail-row"></tr>
6060
</table>
6161

62-
<mat-paginator [length]="length" [pageSizeOptions]="[5]" aria-label="Select page of articles"></mat-paginator>
62+
<mat-paginator [length]="totalElements" [pageSizeOptions]="[5]" aria-label="Select page of articles"></mat-paginator>
6363
</as-split-area>
6464
</as-split>
6565
</div>

frontend/src/app/features/search/search.component.ts

Lines changed: 37 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { animate, state, style, transition, trigger } from '@angular/animations';
22
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
33
import { DatePipe, NgIf } from '@angular/common';
4-
import { AfterViewInit, Component, ElementRef, inject, OnDestroy, OnInit, ViewChild } from '@angular/core';
4+
import { AfterViewInit, Component, DestroyRef, ElementRef, inject, OnInit, ViewChild } from '@angular/core';
5+
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
56
import { MatFormFieldModule } from '@angular/material/form-field';
67
import { MatInputModule } from '@angular/material/input';
78
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
89
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
910
import { AngularSplitModule, SplitComponent } from 'angular-split';
1011
import * as L from 'leaflet';
11-
import { debounceTime, distinctUntilChanged, fromEvent, map, merge, startWith, Subject, switchMap, takeUntil, tap } from 'rxjs';
12+
import { debounceTime, distinctUntilChanged, fromEvent } from 'rxjs';
1213
import { Content } from './content.model';
1314
import { SearchService } from './search.service';
1415

@@ -28,21 +29,23 @@ import { SearchService } from './search.service';
2829
// { provide: SearchService, useClass: SearchServiceMock }
2930
],
3031
})
31-
export class SearchComponent implements AfterViewInit, OnInit, OnDestroy {
32+
export class SearchComponent implements AfterViewInit, OnInit {
3233
private breakpointObserver = inject(BreakpointObserver);
3334
private searchService = inject(SearchService);
3435

3536
displayedColumns: string[] = ['title', 'publication'];
3637
dataSource = new MatTableDataSource<Content>();
3738

38-
destroyed = new Subject<void>();
3939
isSmallSize = false;
4040

4141
// eslint-disable-next-line @typescript-eslint/no-explicit-any
4242
expandedElement: any;
4343

44-
length = 0;
44+
totalElements = 0;
4545
author = '';
46+
searchTerm = '';
47+
48+
destroyRef = inject(DestroyRef);
4649

4750
private map!: L.Map;
4851
private markers!: L.FeatureGroup;
@@ -54,7 +57,7 @@ export class SearchComponent implements AfterViewInit, OnInit, OnDestroy {
5457
constructor() {
5558
this.breakpointObserver
5659
.observe([Breakpoints.XSmall, Breakpoints.Small, Breakpoints.Medium, Breakpoints.Large, Breakpoints.XLarge])
57-
.pipe(takeUntil(this.destroyed))
60+
.pipe(takeUntilDestroyed())
5861
.subscribe((result) => {
5962
for (const query of Object.keys(result.breakpoints)) {
6063
if (result.breakpoints[query]) {
@@ -76,12 +79,23 @@ export class SearchComponent implements AfterViewInit, OnInit, OnDestroy {
7679
ngAfterViewInit(): void {
7780
this.initMap();
7881
this.initSplit();
79-
this.loadContent();
82+
this.initInput();
83+
84+
this.loadPage(0, 5);
85+
this.paginator.page.subscribe(() => {
86+
this.loadPage(this.paginator.pageIndex, this.paginator.pageSize);
87+
});
8088
}
8189

82-
ngOnDestroy() {
83-
this.destroyed.next();
84-
this.destroyed.complete();
90+
/**
91+
* Loads content from backend with parameters which contains much more information and extract the content of articles.
92+
*/
93+
loadPage(pageIndex: number, pageSize: number) {
94+
this.searchService.fetch(pageIndex, pageSize, 'datePublished,desc', this.searchTerm).subscribe((response) => {
95+
this.totalElements = response.totalElements;
96+
this.dataSource = new MatTableDataSource(response.content);
97+
this.addToMap(response.content);
98+
});
8599
}
86100

87101
/**
@@ -93,37 +107,6 @@ export class SearchComponent implements AfterViewInit, OnInit, OnDestroy {
93107
});
94108
}
95109

96-
/**
97-
* Loads content from backend with parameters which contains much more information and extract the content of articles.
98-
*/
99-
private loadContent(): void {
100-
const filter = fromEvent(this.input.nativeElement, 'keyup').pipe(
101-
debounceTime(500),
102-
distinctUntilChanged(),
103-
tap(() => this.paginator.firstPage())
104-
);
105-
106-
merge(filter, this.paginator.page)
107-
.pipe(
108-
takeUntil(this.destroyed),
109-
startWith({}),
110-
switchMap(() => {
111-
return this.searchService
112-
.fetch(this.paginator.pageIndex, this.paginator.pageSize, 'datePublished,desc', this.input.nativeElement.value)
113-
.pipe(
114-
map((data) => {
115-
this.length = data.length;
116-
return data;
117-
})
118-
);
119-
})
120-
)
121-
.subscribe((content) => {
122-
this.addToMap(content);
123-
this.dataSource = new MatTableDataSource(content);
124-
});
125-
}
126-
127110
/**
128111
* Returns the query from the input field or undefined if the value is empty.
129112
*
@@ -145,6 +128,19 @@ export class SearchComponent implements AfterViewInit, OnInit, OnDestroy {
145128
}).addTo(this.map);
146129
}
147130

131+
/**
132+
* Initialize search field.
133+
*/
134+
initInput(): void {
135+
fromEvent(this.input.nativeElement, 'keyup')
136+
.pipe(takeUntilDestroyed(this.destroyRef), debounceTime(500), distinctUntilChanged())
137+
.subscribe((_) => {
138+
this.searchTerm = this.input.nativeElement.value;
139+
this.paginator.firstPage();
140+
this.loadPage(0, this.paginator.pageSize);
141+
});
142+
}
143+
148144
/**
149145
* Integrates content as marker and popup information returned from the server into the initialized map.
150146
*
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
import { HttpClient, HttpParams } from '@angular/common/http';
22
import { Injectable, inject } from '@angular/core';
33
import { Observable } from 'rxjs';
4-
54
import { environment } from '../../../environments/environment';
5+
import { Content } from './content.model';
6+
import { PagedResponse } from './paged-response.model';
67

78
@Injectable({
89
providedIn: 'root',
910
})
1011
export class SearchService {
1112
private httpClient = inject(HttpClient);
1213

13-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
14-
fetch(page: number, size: number, sort: string, query?: string): Observable<any> {
14+
fetch(page: number, size: number, sort: string, query?: string): Observable<PagedResponse<Content>> {
1515
const collected = { page, size, sort };
1616
const params = new HttpParams({ fromObject: query ? { ...collected, query } : collected });
1717
const url = query ? 'search' : 'getx';
18-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
19-
return this.httpClient.get<any>(environment.api + url, { params });
18+
return this.httpClient.get<PagedResponse<Content>>(environment.api + url, { params });
2019
}
2120
}

frontend/src/proxy.conf.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"/api": {
3+
"target": "http://localhost:8080",
4+
"secure": false
5+
}
6+
}

0 commit comments

Comments
 (0)