Skip to content

Commit af39526

Browse files
[DURACOM-304] refactor, fix dynamic-list.component loading
1 parent f77ce86 commit af39526

4 files changed

Lines changed: 67 additions & 92 deletions

File tree

src/app/core/data/bundle-data.service.ts

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ export class BundleDataService extends IdentifiableDataService<Bundle> implement
7979
*/
8080
// TODO should be implemented rest side
8181
findByItemAndName(item: Item, bundleName: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, options?: FindListOptions, ...linksToFollow: FollowLinkConfig<Bundle>[]): Observable<RemoteData<Bundle>> {
82-
return this.findAllByItem(item, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow).pipe(
82+
//Since we filter by bundleName where the pagination options are not indicated we need to load all the possible bundles.
83+
// This is a workaround, in substitution of the previously recursive call with expand
84+
const paginationOptions = options ?? { elementsPerPage: 9999 };
85+
return this.findAllByItem(item, paginationOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow).pipe(
8386
map((rd: RemoteData<PaginatedList<Bundle>>) => {
8487
if (hasValue(rd.payload) && hasValue(rd.payload.page)) {
8588
const matchingBundle = rd.payload.page.find((bundle: Bundle) =>
@@ -112,47 +115,6 @@ export class BundleDataService extends IdentifiableDataService<Bundle> implement
112115
);
113116
}
114117

115-
// findByItemAndName(item: Item, bundleName: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<Bundle>[]): Observable<RemoteData<Bundle>> {
116-
// return this.findAllByItem(item, { elementsPerPage: 1, currentPage: 1 }, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow).pipe(
117-
// expand((rd: RemoteData<PaginatedList<Bundle>>) => {
118-
// if (rd.hasSucceeded && hasValue(rd.payload) && hasValue(rd.payload.page) && rd.payload.currentPage < rd.payload.totalPages) {
119-
// const nextPageOptions = { elementsPerPage: 1, currentPage: rd.payload.currentPage + 1 };
120-
// return this.findAllByItem(item, nextPageOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
121-
// } else {
122-
// return EMPTY;
123-
// }
124-
// }),
125-
// map((rd: RemoteData<PaginatedList<Bundle>>) => {
126-
// if (hasValue(rd.payload) && hasValue(rd.payload.page)) {
127-
// const matchingBundle = rd.payload.page.find((bundle: Bundle) => bundle.name === bundleName);
128-
// if (hasValue(matchingBundle)) {
129-
// return new RemoteData(
130-
// rd.timeCompleted,
131-
// rd.msToLive,
132-
// rd.lastUpdated,
133-
// RequestEntryState.Success,
134-
// null,
135-
// matchingBundle,
136-
// 200
137-
// );
138-
// } else {
139-
// return new RemoteData(
140-
// rd.timeCompleted,
141-
// rd.msToLive,
142-
// rd.lastUpdated,
143-
// RequestEntryState.Error,
144-
// `The bundle with name ${bundleName} was not found.`,
145-
// null,
146-
// 404
147-
// );
148-
// }
149-
// } else {
150-
// return rd as any;
151-
// }
152-
// })
153-
// );
154-
// }
155-
156118
/**
157119
* Get the bitstreams endpoint for a bundle
158120
* @param bundleId

src/app/item-page/edit-item-page/item-bitstreams/item-bitstreams.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
aria-describedby="reorder-description">
4141
</ds-item-edit-bitstream-bundle>
4242
<div class="d-flex justify-content-center" *ngIf="showLoadMoreLink$ | async">
43-
<div class="btn btn-link py-3" (click)="loadBundles()"> {{'item.edit.bitstreams.load-more.link' | translate}}</div>
43+
<button class="btn btn-link my-3" (click)="loadBundles()"> {{'item.edit.bitstreams.load-more.link' | translate}}</button>
4444
</div>
4545
</div>
4646
<div *ngIf="bundles?.length === 0"

src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@
6464
</div>
6565
</div>
6666

67-
<div class="d-flex justify-content-center" *ngIf="(showLoadMore$ | async)">
68-
<div *ngIf="(showLoadMore$ | async)" class="btn btn-link py-3" (click)="loadEntries()">{{'dynamic-list.load-more' | translate}}</div>
67+
<div class="d-flex justify-content-center" *ngIf="(isLoading$ | async)">
68+
<ds-loading></ds-loading>
6969
</div>
7070

7171
</div>

src/app/shared/form/builder/ds-dynamic-form-ui/models/list/dynamic-list.component.ts

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
1+
import { ChangeDetectorRef, Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
22
import { UntypedFormGroup, ValidatorFn, ValidationErrors, AbstractControl } from '@angular/forms';
33
import {
44
DynamicCheckboxModel,
@@ -17,7 +17,7 @@ import { getFirstSucceededRemoteDataPayload } from '../../../../../../core/share
1717
import { PaginatedList } from '../../../../../../core/data/paginated-list.model';
1818
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
1919
import { PageInfo } from '../../../../../../core/shared/page-info.model';
20-
import { BehaviorSubject, EMPTY, expand, map, reduce, tap } from "rxjs";
20+
import { BehaviorSubject, EMPTY, expand, map, reduce, Subscription, tap } from "rxjs";
2121

2222
export interface ListItem {
2323
id: string;
@@ -34,7 +34,7 @@ export interface ListItem {
3434
styleUrls: ['./dynamic-list.component.scss'],
3535
templateUrl: './dynamic-list.component.html'
3636
})
37-
export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit {
37+
export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit, OnDestroy {
3838

3939
@Input() group: UntypedFormGroup;
4040
@Input() model: any;
@@ -44,9 +44,10 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
4444
@Output() focus: EventEmitter<any> = new EventEmitter<any>();
4545

4646
public items: ListItem[][] = [];
47-
public showLoadMore$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
47+
public isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
4848
protected optionsList: VocabularyEntry[] = [];
4949
private nextPageInfo: PageInfo;
50+
private subs: Subscription[] = [];
5051

5152
constructor(private vocabularyService: VocabularyService,
5253
private cdr: ChangeDetectorRef,
@@ -66,6 +67,12 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
6667
}
6768
}
6869

70+
ngOnDestroy() {
71+
if (this.subs.length > 0) {
72+
this.subs.forEach(sub => sub.unsubscribe());
73+
}
74+
}
75+
6976
/**
7077
* Emits a blur event containing a given value.
7178
* @param event The value to emit.
@@ -140,9 +147,9 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
140147
setPaginationInfo(response: PaginatedList<VocabularyEntry>) {
141148
if (response.pageInfo.currentPage < response.pageInfo.totalPages) {
142149
this.nextPageInfo = Object.assign(new PageInfo(), response.pageInfo, { currentPage: response.currentPage + 1 });
143-
this.showLoadMore$.next(true);
150+
this.isLoading$.next(true);
144151
} else {
145-
this.showLoadMore$.next(false);
152+
this.isLoading$.next(false);
146153
}
147154
}
148155

@@ -156,47 +163,53 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
156163
listGroup = this.group.controls[this.model.id] as UntypedFormGroup;
157164
}
158165

159-
this.vocabularyService.getVocabularyEntries(this.model.vocabularyOptions, this.nextPageInfo).pipe(
160-
getFirstSucceededRemoteDataPayload(),
161-
tap((response) => this.setPaginationInfo(response)),
162-
map(entries => entries.page),
163-
).subscribe((allEntries: VocabularyEntry[]) => {
164-
this.optionsList = [...this.optionsList, ...allEntries];
165-
let groupCounter = (this.items.length > 0) ? (this.items.length - 1) : 0;
166-
let itemsPerGroup = 0;
167-
let tempList: ListItem[] = [];
168-
169-
// Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
170-
allEntries.forEach((option: VocabularyEntry, key: number) => {
171-
const value = option.authority || option.value;
172-
const checked: boolean = isNotEmpty(findKey(
173-
this.model.value,
174-
(v) => v?.value === option.value));
175-
176-
const item: ListItem = {
177-
id: `${this.model.id}_${value}`,
178-
label: option.display,
179-
value: checked,
180-
index: key,
181-
};
182-
if (this.model.repeatable) {
183-
this.formBuilderService.addFormGroupControl(listGroup, (this.model as DynamicListCheckboxGroupModel), new DynamicCheckboxModel(item));
184-
} else {
185-
(this.model as DynamicListRadioGroupModel).options.push({
186-
label: item.label,
187-
value: option,
188-
});
189-
}
190-
tempList.push(item);
191-
itemsPerGroup++;
192-
this.items[groupCounter] = tempList;
193-
if (itemsPerGroup === this.model.groupLength) {
194-
groupCounter++;
195-
itemsPerGroup = 0;
196-
tempList = [];
166+
this.subs.push(
167+
this.vocabularyService.getVocabularyEntries(this.model.vocabularyOptions, this.nextPageInfo).pipe(
168+
getFirstSucceededRemoteDataPayload(),
169+
tap((response) => this.setPaginationInfo(response)),
170+
map(entries => entries.page),
171+
).subscribe((allEntries: VocabularyEntry[]) => {
172+
this.optionsList = [...this.optionsList, ...allEntries];
173+
let groupCounter = this.items.length;
174+
let itemsPerGroup = 0;
175+
let tempList: ListItem[] = [];
176+
177+
// Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
178+
allEntries.forEach((option: VocabularyEntry) => {
179+
const value = option.authority || option.value;
180+
const checked: boolean = isNotEmpty(findKey(
181+
this.model.value,
182+
(v) => v?.value === option.value));
183+
184+
const item: ListItem = {
185+
id: `${this.model.id}_${value}`,
186+
label: option.display,
187+
value: checked,
188+
index: this.optionsList.indexOf(option),
189+
};
190+
if (this.model.repeatable) {
191+
this.formBuilderService.addFormGroupControl(listGroup, (this.model as DynamicListCheckboxGroupModel), new DynamicCheckboxModel(item));
192+
} else {
193+
(this.model as DynamicListRadioGroupModel).options.push({
194+
label: item.label,
195+
value: option,
196+
});
197+
}
198+
tempList.push(item);
199+
itemsPerGroup++;
200+
this.items[groupCounter] = tempList;
201+
if (itemsPerGroup === this.model.groupLength) {
202+
groupCounter++;
203+
itemsPerGroup = 0;
204+
tempList = [];
205+
}
206+
});
207+
this.cdr.markForCheck();
208+
// If the paginated request did not reach the end keep loading the entries in the background
209+
if (this.isLoading$.value) {
210+
this.loadEntries();
197211
}
198-
});
199-
this.cdr.markForCheck();
200-
});
212+
}),
213+
);
201214
}
202215
}

0 commit comments

Comments
 (0)