Skip to content

Commit 9570cd9

Browse files
[DURACOM-304] refactor, fix dynamic-list.component loading
1 parent c79affd commit 9570cd9

File tree

4 files changed

+72
-91
lines changed

4 files changed

+72
-91
lines changed

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

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

118-
// findByItemAndName(item: Item, bundleName: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<Bundle>[]): Observable<RemoteData<Bundle>> {
119-
// return this.findAllByItem(item, { elementsPerPage: 1, currentPage: 1 }, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow).pipe(
120-
// expand((rd: RemoteData<PaginatedList<Bundle>>) => {
121-
// if (rd.hasSucceeded && hasValue(rd.payload) && hasValue(rd.payload.page) && rd.payload.currentPage < rd.payload.totalPages) {
122-
// const nextPageOptions = { elementsPerPage: 1, currentPage: rd.payload.currentPage + 1 };
123-
// return this.findAllByItem(item, nextPageOptions, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
124-
// } else {
125-
// return EMPTY;
126-
// }
127-
// }),
128-
// map((rd: RemoteData<PaginatedList<Bundle>>) => {
129-
// if (hasValue(rd.payload) && hasValue(rd.payload.page)) {
130-
// const matchingBundle = rd.payload.page.find((bundle: Bundle) => bundle.name === bundleName);
131-
// if (hasValue(matchingBundle)) {
132-
// return new RemoteData(
133-
// rd.timeCompleted,
134-
// rd.msToLive,
135-
// rd.lastUpdated,
136-
// RequestEntryState.Success,
137-
// null,
138-
// matchingBundle,
139-
// 200
140-
// );
141-
// } else {
142-
// return new RemoteData(
143-
// rd.timeCompleted,
144-
// rd.msToLive,
145-
// rd.lastUpdated,
146-
// RequestEntryState.Error,
147-
// `The bundle with name ${bundleName} was not found.`,
148-
// null,
149-
// 404
150-
// );
151-
// }
152-
// } else {
153-
// return rd as any;
154-
// }
155-
// })
156-
// );
157-
// }
158-
159121
/**
160122
* Get the bitstreams endpoint for a bundle
161123
* @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: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
Component,
1010
EventEmitter,
1111
Input,
12+
OnDestroy,
1213
OnInit,
1314
Output,
1415
} from '@angular/core';
@@ -28,7 +29,10 @@ import {
2829
} from '@ng-dynamic-forms/core';
2930
import { TranslateModule } from '@ngx-translate/core';
3031
import findKey from 'lodash/findKey';
31-
import { BehaviorSubject } from 'rxjs';
32+
import {
33+
BehaviorSubject,
34+
Subscription,
35+
} from 'rxjs';
3236
import {
3337
map,
3438
tap,
@@ -43,6 +47,7 @@ import {
4347
hasValue,
4448
isNotEmpty,
4549
} from '../../../../../empty.util';
50+
import { ThemedLoadingComponent } from '../../../../../loading/themed-loading.component';
4651
import { FormBuilderService } from '../../../form-builder.service';
4752
import { DynamicListCheckboxGroupModel } from './dynamic-list-checkbox-group.model';
4853
import { DynamicListRadioGroupModel } from './dynamic-list-radio-group.model';
@@ -69,10 +74,11 @@ export interface ListItem {
6974
ReactiveFormsModule,
7075
AsyncPipe,
7176
TranslateModule,
77+
ThemedLoadingComponent,
7278
],
7379
standalone: true,
7480
})
75-
export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit {
81+
export class DsDynamicListComponent extends DynamicFormControlComponent implements OnInit, OnDestroy {
7682

7783
@Input() group: UntypedFormGroup;
7884
@Input() model: any;
@@ -82,9 +88,10 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
8288
@Output() focus: EventEmitter<any> = new EventEmitter<any>();
8389

8490
public items: ListItem[][] = [];
85-
public showLoadMore$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
91+
public isLoading$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true);
8692
protected optionsList: VocabularyEntry[] = [];
8793
private nextPageInfo: PageInfo;
94+
private subs: Subscription[] = [];
8895

8996
constructor(private vocabularyService: VocabularyService,
9097
private cdr: ChangeDetectorRef,
@@ -104,6 +111,12 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
104111
}
105112
}
106113

114+
ngOnDestroy() {
115+
if (this.subs.length > 0) {
116+
this.subs.forEach(sub => sub.unsubscribe());
117+
}
118+
}
119+
107120
/**
108121
* Emits a blur event containing a given value.
109122
* @param event The value to emit.
@@ -178,9 +191,9 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
178191
setPaginationInfo(response: PaginatedList<VocabularyEntry>) {
179192
if (response.pageInfo.currentPage < response.pageInfo.totalPages) {
180193
this.nextPageInfo = Object.assign(new PageInfo(), response.pageInfo, { currentPage: response.currentPage + 1 });
181-
this.showLoadMore$.next(true);
194+
this.isLoading$.next(true);
182195
} else {
183-
this.showLoadMore$.next(false);
196+
this.isLoading$.next(false);
184197
}
185198
}
186199

@@ -194,47 +207,53 @@ export class DsDynamicListComponent extends DynamicFormControlComponent implemen
194207
listGroup = this.group.controls[this.model.id] as UntypedFormGroup;
195208
}
196209

197-
this.vocabularyService.getVocabularyEntries(this.model.vocabularyOptions, this.nextPageInfo).pipe(
198-
getFirstSucceededRemoteDataPayload(),
199-
tap((response) => this.setPaginationInfo(response)),
200-
map(entries => entries.page),
201-
).subscribe((allEntries: VocabularyEntry[]) => {
202-
this.optionsList = [...this.optionsList, ...allEntries];
203-
let groupCounter = (this.items.length > 0) ? (this.items.length - 1) : 0;
204-
let itemsPerGroup = 0;
205-
let tempList: ListItem[] = [];
206-
207-
// Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
208-
allEntries.forEach((option: VocabularyEntry, key: number) => {
209-
const value = option.authority || option.value;
210-
const checked: boolean = isNotEmpty(findKey(
211-
this.model.value,
212-
(v) => v?.value === option.value));
213-
214-
const item: ListItem = {
215-
id: `${this.model.id}_${value}`,
216-
label: option.display,
217-
value: checked,
218-
index: key,
219-
};
220-
if (this.model.repeatable) {
221-
this.formBuilderService.addFormGroupControl(listGroup, (this.model as DynamicListCheckboxGroupModel), new DynamicCheckboxModel(item));
222-
} else {
223-
(this.model as DynamicListRadioGroupModel).options.push({
224-
label: item.label,
225-
value: option,
226-
});
227-
}
228-
tempList.push(item);
229-
itemsPerGroup++;
230-
this.items[groupCounter] = tempList;
231-
if (itemsPerGroup === this.model.groupLength) {
232-
groupCounter++;
233-
itemsPerGroup = 0;
234-
tempList = [];
210+
this.subs.push(
211+
this.vocabularyService.getVocabularyEntries(this.model.vocabularyOptions, this.nextPageInfo).pipe(
212+
getFirstSucceededRemoteDataPayload(),
213+
tap((response) => this.setPaginationInfo(response)),
214+
map(entries => entries.page),
215+
).subscribe((allEntries: VocabularyEntry[]) => {
216+
this.optionsList = [...this.optionsList, ...allEntries];
217+
let groupCounter = this.items.length;
218+
let itemsPerGroup = 0;
219+
let tempList: ListItem[] = [];
220+
221+
// Make a list of available options (checkbox/radio) and split in groups of 'model.groupLength'
222+
allEntries.forEach((option: VocabularyEntry) => {
223+
const value = option.authority || option.value;
224+
const checked: boolean = isNotEmpty(findKey(
225+
this.model.value,
226+
(v) => v?.value === option.value));
227+
228+
const item: ListItem = {
229+
id: `${this.model.id}_${value}`,
230+
label: option.display,
231+
value: checked,
232+
index: this.optionsList.indexOf(option),
233+
};
234+
if (this.model.repeatable) {
235+
this.formBuilderService.addFormGroupControl(listGroup, (this.model as DynamicListCheckboxGroupModel), new DynamicCheckboxModel(item));
236+
} else {
237+
(this.model as DynamicListRadioGroupModel).options.push({
238+
label: item.label,
239+
value: option,
240+
});
241+
}
242+
tempList.push(item);
243+
itemsPerGroup++;
244+
this.items[groupCounter] = tempList;
245+
if (itemsPerGroup === this.model.groupLength) {
246+
groupCounter++;
247+
itemsPerGroup = 0;
248+
tempList = [];
249+
}
250+
});
251+
this.cdr.markForCheck();
252+
// If the paginated request did not reach the end keep loading the entries in the background
253+
if (this.isLoading$.value) {
254+
this.loadEntries();
235255
}
236-
});
237-
this.cdr.markForCheck();
238-
});
256+
}),
257+
);
239258
}
240259
}

0 commit comments

Comments
 (0)