Skip to content

Commit c5f07da

Browse files
Fix for User profile (/profile): only 20 group memberships shown instead of all (#3105)
* Add - groups paginated on profile page * Add - groups paginated on profile page * Add - groups paginated on profile page * Add - groups paginated on profile page * Fix UPDATE - Add pagination message error and loader * Update BRANCH * Fix - LINT ERRORS * Fix: Error declaring variable for group pagination * Fix: Remove unnecessary translations for paging groups * Fix: Lint erros * Fix: Remove unnecessary translations --------- Co-authored-by: VictorDuranEscire <[email protected]>
1 parent f52aac8 commit c5f07da

File tree

5 files changed

+72
-8
lines changed

5 files changed

+72
-8
lines changed

src/app/profile-page/profile-page.component.html

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,29 @@ <h1>{{'profile.title' | translate}}</h1>
3333
<button class="btn btn-primary" (click)="updateProfile()"><i class="fas fa-edit"></i> {{'profile.form.submit' | translate}}</button>
3434
</div>
3535

36-
<ng-container *ngVar="(groupsRD$ | async)?.payload?.page as groups">
37-
<div *ngIf="groups?.length > 0">
38-
<h2 class="mt-4">{{'profile.groups.head' | translate}}</h2>
39-
<ul class="list-group list-group-flush">
40-
<li *ngFor="let group of groups" class="list-group-item">{{ dsoNameService.getName(group) }}</li>
41-
</ul>
42-
</div>
36+
<ng-container *ngIf="(groupsRD$ | async) as groupsRD;">
37+
<ng-container *ngTemplateOutlet="groupsRD?.isLoading ? loader : content"></ng-container>
38+
<ng-template #content>
39+
<ds-pagination *ngIf="groupsRD?.payload"
40+
[hideGear]="true"
41+
[hidePagerWhenSinglePage]="true"
42+
[hidePaginationDetail]="true"
43+
[paginationOptions]="optionsGroupsPagination"
44+
[collectionSize]="groupsRD?.payload?.totalElements">
45+
<ng-container *ngIf="groupsRD?.payload?.page as groups">
46+
<div *ngIf="groups?.length > 0">
47+
<h2 class="mt-4">{{ 'profile.groups.head' | translate }}</h2>
48+
<ul class="list-group list-group-flush">
49+
<li *ngFor="let group of groups" class="list-group-item">{{ dsoNameService.getName(group) }}</li>
50+
</ul>
51+
</div>
52+
</ng-container>
53+
</ds-pagination>
54+
</ng-template>
55+
<ng-template #loader>
56+
<ds-loading [showMessage]="false"></ds-loading>
57+
</ng-template>
58+
<ds-error *ngIf="groupsRD?.hasFailed" message="{{ 'error.profile-groups' | translate }}"></ds-error>
4359
</ng-container>
4460

4561
<ng-container *ngVar="(specialGroupsRD$ | async)?.payload?.page as specialGroups">

src/app/profile-page/profile-page.component.spec.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { NgTemplateOutlet } from '@angular/common';
12
import { NO_ERRORS_SCHEMA } from '@angular/core';
23
import {
34
ComponentFixture,
@@ -29,7 +30,10 @@ import { EPersonDataService } from '../core/eperson/eperson-data.service';
2930
import { EPerson } from '../core/eperson/models/eperson.model';
3031
import { ConfigurationProperty } from '../core/shared/configuration-property.model';
3132
import { SuggestionsNotificationComponent } from '../notifications/suggestions-notification/suggestions-notification.component';
33+
import { ErrorComponent } from '../shared/error/error.component';
34+
import { ThemedLoadingComponent } from '../shared/loading/themed-loading.component';
3235
import { NotificationsService } from '../shared/notifications/notifications.service';
36+
import { PaginationComponent } from '../shared/pagination/pagination.component';
3337
import {
3438
createFailedRemoteDataObject$,
3539
createSuccessfulRemoteDataObject$,
@@ -134,6 +138,10 @@ describe('ProfilePageComponent', () => {
134138
ProfilePageSecurityFormComponent,
135139
ProfilePageResearcherFormComponent,
136140
SuggestionsNotificationComponent,
141+
NgTemplateOutlet,
142+
PaginationComponent,
143+
ThemedLoadingComponent,
144+
ErrorComponent,
137145
],
138146
},
139147
})

src/app/profile-page/profile-page.component.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
AsyncPipe,
33
NgForOf,
44
NgIf,
5+
NgTemplateOutlet,
56
} from '@angular/common';
67
import {
78
Component,
@@ -33,8 +34,10 @@ import { RemoteData } from '../core/data/remote-data';
3334
import { EPersonDataService } from '../core/eperson/eperson-data.service';
3435
import { EPerson } from '../core/eperson/models/eperson.model';
3536
import { Group } from '../core/eperson/models/group.model';
37+
import { PaginationService } from '../core/pagination/pagination.service';
3638
import { ConfigurationProperty } from '../core/shared/configuration-property.model';
3739
import {
40+
getAllCompletedRemoteData,
3841
getAllSucceededRemoteData,
3942
getFirstCompletedRemoteData,
4043
getRemoteDataPayload,
@@ -44,7 +47,11 @@ import {
4447
hasValue,
4548
isNotEmpty,
4649
} from '../shared/empty.util';
50+
import { ErrorComponent } from '../shared/error/error.component';
51+
import { ThemedLoadingComponent } from '../shared/loading/themed-loading.component';
4752
import { NotificationsService } from '../shared/notifications/notifications.service';
53+
import { PaginationComponent } from '../shared/pagination/pagination.component';
54+
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
4855
import { followLink } from '../shared/utils/follow-link-config.model';
4956
import { VarDirective } from '../shared/utils/var.directive';
5057
import { ThemedProfilePageMetadataFormComponent } from './profile-page-metadata-form/themed-profile-page-metadata-form.component';
@@ -65,6 +72,10 @@ import { ProfilePageSecurityFormComponent } from './profile-page-security-form/p
6572
NgIf,
6673
NgForOf,
6774
SuggestionsNotificationComponent,
75+
NgTemplateOutlet,
76+
PaginationComponent,
77+
ThemedLoadingComponent,
78+
ErrorComponent,
6879
],
6980
standalone: true,
7081
})
@@ -122,6 +133,15 @@ export class ProfilePageComponent implements OnInit {
122133
private currentUser: EPerson;
123134
canChangePassword$: Observable<boolean>;
124135

136+
/**
137+
* Default configuration for group pagination
138+
**/
139+
optionsGroupsPagination = Object.assign(new PaginationComponentOptions(),{
140+
id: 'page_groups',
141+
currentPage: 1,
142+
pageSize: 20,
143+
});
144+
125145
isResearcherProfileEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
126146

127147
constructor(private authService: AuthService,
@@ -131,6 +151,7 @@ export class ProfilePageComponent implements OnInit {
131151
private authorizationService: AuthorizationDataService,
132152
private configurationService: ConfigurationDataService,
133153
public dsoNameService: DSONameService,
154+
private paginationService: PaginationService,
134155
) {
135156
}
136157

@@ -142,7 +163,18 @@ export class ProfilePageComponent implements OnInit {
142163
getRemoteDataPayload(),
143164
tap((user: EPerson) => this.currentUser = user),
144165
);
145-
this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups));
166+
this.groupsRD$ = this.paginationService.getCurrentPagination(this.optionsGroupsPagination.id, this.optionsGroupsPagination).pipe(
167+
switchMap((pageOptions: PaginationComponentOptions) => {
168+
return this.epersonService.findById(this.currentUser.id, true, true, followLink('groups',{
169+
findListOptions: {
170+
elementsPerPage: pageOptions.pageSize,
171+
currentPage: pageOptions.currentPage,
172+
} }));
173+
}),
174+
getAllCompletedRemoteData(),
175+
getRemoteDataPayload(),
176+
switchMap((user: EPerson) => user?.groups),
177+
);
146178
this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href)));
147179
this.specialGroupsRD$ = this.authService.getSpecialGroupsFromAuthStatus();
148180

src/assets/i18n/en.json5

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,6 +1844,8 @@
18441844

18451845
"error.recent-submissions": "Error fetching recent submissions",
18461846

1847+
"error.profile-groups": "Error retrieving profile groups",
1848+
18471849
"error.search-results": "Error fetching search results",
18481850

18491851
"error.invalid-search-query": "Search query is not valid. Please check <a href=\"https://solr.apache.org/guide/query-syntax-and-parsing.html\" target=\"_blank\">Solr query syntax</a> best practices for further information about this error.",

src/themes/custom/app/profile-page/profile-page.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import { ProfilePageComponent as BaseComponent } from '../../../../app/profile-p
1111
import { ThemedProfilePageMetadataFormComponent } from '../../../../app/profile-page/profile-page-metadata-form/themed-profile-page-metadata-form.component';
1212
import { ProfilePageResearcherFormComponent } from '../../../../app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component';
1313
import { ProfilePageSecurityFormComponent } from '../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component';
14+
import { ErrorComponent } from '../../../../app/shared/error/error.component';
15+
import { ThemedLoadingComponent } from '../../../../app/shared/loading/themed-loading.component';
16+
import { PaginationComponent } from '../../../../app/shared/pagination/pagination.component';
1417
import { VarDirective } from '../../../../app/shared/utils/var.directive';
1518

1619
@Component({
@@ -30,6 +33,9 @@ import { VarDirective } from '../../../../app/shared/utils/var.directive';
3033
NgIf,
3134
NgForOf,
3235
SuggestionsNotificationComponent,
36+
PaginationComponent,
37+
ThemedLoadingComponent,
38+
ErrorComponent,
3339
],
3440
})
3541
/**

0 commit comments

Comments
 (0)