Skip to content

Commit 1f34e5b

Browse files
[DSC-1437] Refactoring
1 parent cd42fde commit 1f34e5b

1 file changed

Lines changed: 86 additions & 71 deletions

File tree

Lines changed: 86 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
1-
import { Component, OnInit } from '@angular/core';
2-
import { BehaviorSubject, mergeMap, Observable, of } from 'rxjs';
1+
import { Component, OnDestroy, OnInit } from '@angular/core';
2+
import { BehaviorSubject, mergeMap, Observable, Subject, Subscription } from 'rxjs';
33
import { RemoteData } from '../../core/data/remote-data';
44
import { PaginatedList } from '../../core/data/paginated-list.model';
55
import { SearchResult } from '../../shared/search/models/search-result.model';
66
import { DSpaceObject } from '../../core/shared/dspace-object.model';
77
import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model';
8-
import { getFirstSucceededRemoteData } from '../../core/shared/operators';
8+
import { getFirstCompletedRemoteData, getFirstSucceededRemoteData } from '../../core/shared/operators';
99
import { SearchFilter } from '../../shared/search/models/search-filter.model';
1010
import { LuckySearchService } from '../lucky-search.service';
11-
import { Router } from '@angular/router';
12-
import { filter, switchMap, tap } from 'rxjs/operators';
11+
import { Params, Router } from '@angular/router';
12+
import { filter, map, switchMap, tap } from 'rxjs/operators';
1313
import { Context } from '../../core/shared/context.model';
1414
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
1515
import { Item } from '../../core/shared/item.model';
1616
import { BitstreamDataService, MetadataFilter } from '../../core/data/bitstream-data.service';
17-
import { getBitstreamDownloadRoute } from '../../app-routing-paths';
1817
import { Bitstream } from '../../core/shared/bitstream.model';
19-
import { hasValue } from '../../shared/empty.util';
18+
import { hasValue, isEmpty, isNotEmpty } from '../../shared/empty.util';
2019
import { getItemPageRoute } from '../../item-page/item-page-routing-paths';
20+
import { getBitstreamDownloadRoute } from '../../app-routing-paths';
2121

2222
@Component({
2323
selector: 'ds-lucky-search',
2424
templateUrl: './lucky-search.component.html',
2525
styleUrls: ['./lucky-search.component.scss']
2626
})
27-
export class LuckySearchComponent implements OnInit {
27+
export class LuckySearchComponent implements OnInit, OnDestroy {
2828
/**
2929
* The current search results
3030
*/
@@ -55,8 +55,10 @@ export class LuckySearchComponent implements OnInit {
5555
private DESCRIPTION_METADATA = 'dc.description';
5656

5757
bitstreamFilters: MetadataFilter[];
58-
bitstreams$ = new BehaviorSubject([]);
59-
item$ = new BehaviorSubject(null);
58+
bitstreams$ = new Subject<Bitstream[]>();
59+
item$ = new Subject<Item>();
60+
61+
private readonly subscription = new Subscription();
6062

6163
constructor(private luckySearchService: LuckySearchService,
6264
private router: Router,
@@ -66,39 +68,54 @@ export class LuckySearchComponent implements OnInit {
6668

6769
ngOnInit(): void {
6870
this.searchOptions$ = this.getSearchOptions();
71+
this.handleBitstreamResults();
6972
this.readResult();
70-
const urlTree = this.router.parseUrl(this.router.url);
71-
if (urlTree?.queryParams) {
72-
Object.keys(urlTree.queryParams).forEach((key) => {
73+
const { queryParams } = this.router.parseUrl(this.router.url);
74+
if (isNotEmpty(queryParams)) {
75+
Object.keys(queryParams).forEach((key) => {
7376
if (key && key === 'index') {
74-
this.currentFilter.identifier = urlTree.queryParams[key];
77+
this.currentFilter.identifier = queryParams[key];
7578
}
7679
if (key && key === 'value') {
77-
this.currentFilter.value = urlTree.queryParams[key];
80+
this.currentFilter.value = queryParams[key];
7881
}
7982
});
80-
this.bitstreamFilters = this.parseBitstreamFilters(urlTree.queryParams);
83+
this.bitstreamFilters = this.parseBitstreamFilters(queryParams);
8184
}
8285
if (!(this.currentFilter.value !== '' && this.currentFilter.identifier !== '')) {
8386
this.showEmptySearchSection = true;
8487
return;
8588
}
86-
this.searchOptions$.pipe(
87-
switchMap((options: PaginatedSearchOptions) => {
88-
options.filters = [new SearchFilter('f.' + this.currentFilter.identifier, [this.currentFilter.value], 'equals')];
89-
return this.luckySearchService.sendRequest(options).pipe(
90-
tap((rd: any) => {
91-
if (rd.state && rd.state === 'Error') {
92-
this.showEmptySearchSection = true;
93-
}
94-
}),
95-
getFirstSucceededRemoteData());
96-
}))
97-
.subscribe((results) => {
98-
return this.resultsRD$.next(results as any);
99-
});
89+
this.subscription.add(
90+
this.searchOptions$
91+
.pipe(switchMap((options: PaginatedSearchOptions) => this.getLuckySearchResults(options)))
92+
.subscribe((results) => this.resultsRD$.next(results as any))
93+
);
94+
}
10095

96+
private handleBitstreamResults() {
97+
this.subscription.add(
98+
this.bitstreams$.pipe(
99+
filter(bitstreams => isNotEmpty(bitstreams) && bitstreams.length === 1),
100+
map(bitstreams => getBitstreamDownloadRoute(bitstreams[0]))
101+
).subscribe(bitstreamRoute => this.redirect(bitstreamRoute))
102+
);
103+
this.subscription.add(
104+
this.bitstreams$.pipe(
105+
filter(isEmpty)
106+
).subscribe(bitstreamRoute => this.showEmptySearchSection = true)
107+
);
108+
}
101109

110+
private getLuckySearchResults(options: PaginatedSearchOptions) {
111+
options.filters = [new SearchFilter('f.' + this.currentFilter.identifier, [this.currentFilter.value], 'equals')];
112+
return this.luckySearchService.sendRequest(options).pipe(
113+
tap((rd: any) => {
114+
if (rd.state && rd.state === 'Error') {
115+
this.showEmptySearchSection = true;
116+
}
117+
}),
118+
getFirstSucceededRemoteData());
102119
}
103120

104121
getDescription(bitstream: Bitstream): string {
@@ -115,33 +132,36 @@ export class LuckySearchComponent implements OnInit {
115132
}
116133

117134
private readResult() {
118-
this.resultsRD$
119-
.pipe(
120-
filter(res => !!res),
121-
mergeMap(res => this.handleResultAndRedirectIfNeeded(res))
122-
).subscribe();
123-
}
124-
125-
private handleResultAndRedirectIfNeeded(res: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>) {
126-
const total = res.payload.totalElements;
127-
if (total === 0) {
128-
this.showEmptySearchSection = true;
129-
} else if (total === 1) {
130-
return this.handleSingleItemResult(res);
131-
} else {
132-
this.showMultipleSearchSection = true;
133-
}
134-
return of(null);
135-
}
136-
137-
private handleSingleItemResult(res: RemoteData<PaginatedList<SearchResult<DSpaceObject>>>) {
138-
const item = res.payload.page[0].indexableObject as Item;
139-
if (this.isBitstreamSearch()) {
140-
return this.loadBitstreamsAndRedirectIfNeeded(item);
141-
} else {
142-
this.redirect(getItemPageRoute(item));
143-
}
144-
return of(null);
135+
this.subscription.add(
136+
this.resultsRD$.pipe(
137+
filter(results => results?.payload?.totalElements === 0)
138+
).subscribe(_ => this.showEmptySearchSection = true)
139+
);
140+
this.subscription.add(
141+
this.resultsRD$.pipe(
142+
filter(results =>
143+
this.isBitstreamSearch() && results?.payload?.totalElements === 1
144+
),
145+
map(results => results.payload.page[0].indexableObject as Item),
146+
tap(item => this.item$.next(item)),
147+
mergeMap(item => this.loadBitstreamsAndRedirectIfNeeded(item))
148+
).subscribe(results => this.bitstreams$.next(results))
149+
);
150+
this.subscription.add(
151+
this.resultsRD$.pipe(
152+
filter(results =>
153+
!this.isBitstreamSearch() && results?.payload?.totalElements === 1
154+
),
155+
map(results => results.payload.page[0].indexableObject as Item),
156+
tap(item => this.item$.next(item)),
157+
map(item => getItemPageRoute(item))
158+
).subscribe(results => this.redirect(results))
159+
);
160+
this.subscription.add(
161+
this.resultsRD$.pipe(
162+
filter(results => results?.payload?.totalElements > 1),
163+
).subscribe(_ => this.showMultipleSearchSection = true)
164+
);
145165
}
146166

147167
private isBitstreamSearch() {
@@ -156,7 +176,7 @@ export class LuckySearchComponent implements OnInit {
156176
this.router.navigateByUrl(url, {replaceUrl: true});
157177
}
158178

159-
private parseBitstreamFilters(queryParams): MetadataFilter[] {
179+
private parseBitstreamFilters(queryParams: Params): MetadataFilter[] {
160180
const metadataName = queryParams?.bitstreamMetadata;
161181
const metadataValue = queryParams?.bitstreamValue;
162182
if (!!metadataName && !!metadataValue) {
@@ -172,21 +192,16 @@ export class LuckySearchComponent implements OnInit {
172192
return [];
173193
}
174194

175-
private loadBitstreamsAndRedirectIfNeeded(item: Item): Observable<RemoteData<PaginatedList<Bitstream>>> {
195+
private loadBitstreamsAndRedirectIfNeeded(item: Item): Observable<Bitstream[]> {
176196
return this.bitstreamDataService.findByItem(item.uuid, 'ORIGINAL', this.bitstreamFilters, {})
177197
.pipe(
178-
getFirstSucceededRemoteData(),
179-
tap(bitstreamsResult => {
180-
const bitstreams = bitstreamsResult.payload?.page;
181-
this.bitstreams$.next(bitstreams);
182-
this.item$.next(item);
183-
184-
if (!bitstreams?.length) {
185-
this.showEmptySearchSection = true;
186-
} else if (bitstreams.length === 1) {
187-
this.redirect(getBitstreamDownloadRoute(bitstreams[0]));
188-
}
189-
})
198+
getFirstCompletedRemoteData(),
199+
map(bitstreamsResult => bitstreamsResult.payload?.page)
190200
);
191201
}
202+
203+
ngOnDestroy(): void {
204+
this.subscription.unsubscribe();
205+
}
206+
192207
}

0 commit comments

Comments
 (0)