Merge pull request #3825 from tdonohue/port_3105_to_8x

[Port dspace-8_x] Fix for User profile (/profile): only 20 group memberships shown instead of all
This commit is contained in:
Tim Donohue
2025-01-10 17:07:37 -06:00
committed by GitHub
5 changed files with 72 additions and 8 deletions

View File

@@ -33,13 +33,29 @@
<button class="btn btn-primary" (click)="updateProfile()"><i class="fas fa-edit"></i> {{'profile.form.submit' | translate}}</button> <button class="btn btn-primary" (click)="updateProfile()"><i class="fas fa-edit"></i> {{'profile.form.submit' | translate}}</button>
</div> </div>
<ng-container *ngVar="(groupsRD$ | async)?.payload?.page as groups"> <ng-container *ngIf="(groupsRD$ | async) as groupsRD;">
<div *ngIf="groups?.length > 0"> <ng-container *ngTemplateOutlet="groupsRD?.isLoading ? loader : content"></ng-container>
<h2 class="mt-4">{{'profile.groups.head' | translate}}</h2> <ng-template #content>
<ul class="list-group list-group-flush"> <ds-pagination *ngIf="groupsRD?.payload"
<li *ngFor="let group of groups" class="list-group-item">{{ dsoNameService.getName(group) }}</li> [hideGear]="true"
</ul> [hidePagerWhenSinglePage]="true"
</div> [hidePaginationDetail]="true"
[paginationOptions]="optionsGroupsPagination"
[collectionSize]="groupsRD?.payload?.totalElements">
<ng-container *ngIf="groupsRD?.payload?.page as groups">
<div *ngIf="groups?.length > 0">
<h2 class="mt-4">{{ 'profile.groups.head' | translate }}</h2>
<ul class="list-group list-group-flush">
<li *ngFor="let group of groups" class="list-group-item">{{ dsoNameService.getName(group) }}</li>
</ul>
</div>
</ng-container>
</ds-pagination>
</ng-template>
<ng-template #loader>
<ds-loading [showMessage]="false"></ds-loading>
</ng-template>
<ds-error *ngIf="groupsRD?.hasFailed" message="{{ 'error.profile-groups' | translate }}"></ds-error>
</ng-container> </ng-container>
<ng-container *ngVar="(specialGroupsRD$ | async)?.payload?.page as specialGroups"> <ng-container *ngVar="(specialGroupsRD$ | async)?.payload?.page as specialGroups">

View File

@@ -1,3 +1,4 @@
import { NgTemplateOutlet } from '@angular/common';
import { NO_ERRORS_SCHEMA } from '@angular/core'; import { NO_ERRORS_SCHEMA } from '@angular/core';
import { import {
ComponentFixture, ComponentFixture,
@@ -29,7 +30,10 @@ import { EPersonDataService } from '../core/eperson/eperson-data.service';
import { EPerson } from '../core/eperson/models/eperson.model'; import { EPerson } from '../core/eperson/models/eperson.model';
import { ConfigurationProperty } from '../core/shared/configuration-property.model'; import { ConfigurationProperty } from '../core/shared/configuration-property.model';
import { SuggestionsNotificationComponent } from '../notifications/suggestions-notification/suggestions-notification.component'; import { SuggestionsNotificationComponent } from '../notifications/suggestions-notification/suggestions-notification.component';
import { ErrorComponent } from '../shared/error/error.component';
import { ThemedLoadingComponent } from '../shared/loading/themed-loading.component';
import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsService } from '../shared/notifications/notifications.service';
import { PaginationComponent } from '../shared/pagination/pagination.component';
import { import {
createFailedRemoteDataObject$, createFailedRemoteDataObject$,
createSuccessfulRemoteDataObject$, createSuccessfulRemoteDataObject$,
@@ -134,6 +138,10 @@ describe('ProfilePageComponent', () => {
ProfilePageSecurityFormComponent, ProfilePageSecurityFormComponent,
ProfilePageResearcherFormComponent, ProfilePageResearcherFormComponent,
SuggestionsNotificationComponent, SuggestionsNotificationComponent,
NgTemplateOutlet,
PaginationComponent,
ThemedLoadingComponent,
ErrorComponent,
], ],
}, },
}) })

View File

@@ -2,6 +2,7 @@ import {
AsyncPipe, AsyncPipe,
NgForOf, NgForOf,
NgIf, NgIf,
NgTemplateOutlet,
} from '@angular/common'; } from '@angular/common';
import { import {
Component, Component,
@@ -33,8 +34,10 @@ import { RemoteData } from '../core/data/remote-data';
import { EPersonDataService } from '../core/eperson/eperson-data.service'; import { EPersonDataService } from '../core/eperson/eperson-data.service';
import { EPerson } from '../core/eperson/models/eperson.model'; import { EPerson } from '../core/eperson/models/eperson.model';
import { Group } from '../core/eperson/models/group.model'; import { Group } from '../core/eperson/models/group.model';
import { PaginationService } from '../core/pagination/pagination.service';
import { ConfigurationProperty } from '../core/shared/configuration-property.model'; import { ConfigurationProperty } from '../core/shared/configuration-property.model';
import { import {
getAllCompletedRemoteData,
getAllSucceededRemoteData, getAllSucceededRemoteData,
getFirstCompletedRemoteData, getFirstCompletedRemoteData,
getRemoteDataPayload, getRemoteDataPayload,
@@ -44,7 +47,11 @@ import {
hasValue, hasValue,
isNotEmpty, isNotEmpty,
} from '../shared/empty.util'; } from '../shared/empty.util';
import { ErrorComponent } from '../shared/error/error.component';
import { ThemedLoadingComponent } from '../shared/loading/themed-loading.component';
import { NotificationsService } from '../shared/notifications/notifications.service'; import { NotificationsService } from '../shared/notifications/notifications.service';
import { PaginationComponent } from '../shared/pagination/pagination.component';
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
import { followLink } from '../shared/utils/follow-link-config.model'; import { followLink } from '../shared/utils/follow-link-config.model';
import { VarDirective } from '../shared/utils/var.directive'; import { VarDirective } from '../shared/utils/var.directive';
import { ThemedProfilePageMetadataFormComponent } from './profile-page-metadata-form/themed-profile-page-metadata-form.component'; 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
NgIf, NgIf,
NgForOf, NgForOf,
SuggestionsNotificationComponent, SuggestionsNotificationComponent,
NgTemplateOutlet,
PaginationComponent,
ThemedLoadingComponent,
ErrorComponent,
], ],
standalone: true, standalone: true,
}) })
@@ -122,6 +133,15 @@ export class ProfilePageComponent implements OnInit {
private currentUser: EPerson; private currentUser: EPerson;
canChangePassword$: Observable<boolean>; canChangePassword$: Observable<boolean>;
/**
* Default configuration for group pagination
**/
optionsGroupsPagination = Object.assign(new PaginationComponentOptions(),{
id: 'page_groups',
currentPage: 1,
pageSize: 20,
});
isResearcherProfileEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); isResearcherProfileEnabled$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
constructor(private authService: AuthService, constructor(private authService: AuthService,
@@ -131,6 +151,7 @@ export class ProfilePageComponent implements OnInit {
private authorizationService: AuthorizationDataService, private authorizationService: AuthorizationDataService,
private configurationService: ConfigurationDataService, private configurationService: ConfigurationDataService,
public dsoNameService: DSONameService, public dsoNameService: DSONameService,
private paginationService: PaginationService,
) { ) {
} }
@@ -142,7 +163,18 @@ export class ProfilePageComponent implements OnInit {
getRemoteDataPayload(), getRemoteDataPayload(),
tap((user: EPerson) => this.currentUser = user), tap((user: EPerson) => this.currentUser = user),
); );
this.groupsRD$ = this.user$.pipe(switchMap((user: EPerson) => user.groups)); this.groupsRD$ = this.paginationService.getCurrentPagination(this.optionsGroupsPagination.id, this.optionsGroupsPagination).pipe(
switchMap((pageOptions: PaginationComponentOptions) => {
return this.epersonService.findById(this.currentUser.id, true, true, followLink('groups',{
findListOptions: {
elementsPerPage: pageOptions.pageSize,
currentPage: pageOptions.currentPage,
} }));
}),
getAllCompletedRemoteData(),
getRemoteDataPayload(),
switchMap((user: EPerson) => user?.groups),
);
this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href))); this.canChangePassword$ = this.user$.pipe(switchMap((user: EPerson) => this.authorizationService.isAuthorized(FeatureID.CanChangePassword, user._links.self.href)));
this.specialGroupsRD$ = this.authService.getSpecialGroupsFromAuthStatus(); this.specialGroupsRD$ = this.authService.getSpecialGroupsFromAuthStatus();

View File

@@ -1852,6 +1852,8 @@
"error.recent-submissions": "Error fetching recent submissions", "error.recent-submissions": "Error fetching recent submissions",
"error.profile-groups": "Error retrieving profile groups",
"error.search-results": "Error fetching search results", "error.search-results": "Error fetching search results",
"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.", "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.",

View File

@@ -11,6 +11,9 @@ import { ProfilePageComponent as BaseComponent } from '../../../../app/profile-p
import { ThemedProfilePageMetadataFormComponent } from '../../../../app/profile-page/profile-page-metadata-form/themed-profile-page-metadata-form.component'; import { ThemedProfilePageMetadataFormComponent } from '../../../../app/profile-page/profile-page-metadata-form/themed-profile-page-metadata-form.component';
import { ProfilePageResearcherFormComponent } from '../../../../app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component'; import { ProfilePageResearcherFormComponent } from '../../../../app/profile-page/profile-page-researcher-form/profile-page-researcher-form.component';
import { ProfilePageSecurityFormComponent } from '../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component'; import { ProfilePageSecurityFormComponent } from '../../../../app/profile-page/profile-page-security-form/profile-page-security-form.component';
import { ErrorComponent } from '../../../../app/shared/error/error.component';
import { ThemedLoadingComponent } from '../../../../app/shared/loading/themed-loading.component';
import { PaginationComponent } from '../../../../app/shared/pagination/pagination.component';
import { VarDirective } from '../../../../app/shared/utils/var.directive'; import { VarDirective } from '../../../../app/shared/utils/var.directive';
@Component({ @Component({
@@ -30,6 +33,9 @@ import { VarDirective } from '../../../../app/shared/utils/var.directive';
NgIf, NgIf,
NgForOf, NgForOf,
SuggestionsNotificationComponent, SuggestionsNotificationComponent,
PaginationComponent,
ThemedLoadingComponent,
ErrorComponent,
], ],
}) })
/** /**