mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-17 15:03:07 +00:00
70599: Improvements comcol tree
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { FindListOptions } from '../core/data/request.models';
|
||||||
import { CommunityListService, FlatNode } from './community-list-service';
|
import { CommunityListService, FlatNode } from './community-list-service';
|
||||||
import { CollectionViewer, DataSource } from '@angular/cdk/typings/collections';
|
import { CollectionViewer, DataSource } from '@angular/cdk/typings/collections';
|
||||||
import { BehaviorSubject, Observable, } from 'rxjs';
|
import { BehaviorSubject, Observable, } from 'rxjs';
|
||||||
@@ -21,10 +22,10 @@ export class CommunityListDatasource implements DataSource<FlatNode> {
|
|||||||
return this.communityList$.asObservable();
|
return this.communityList$.asObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCommunities(expandedNodes: FlatNode[]) {
|
loadCommunities(findOptions: FindListOptions, expandedNodes: FlatNode[]) {
|
||||||
this.loading$.next(true);
|
this.loading$.next(true);
|
||||||
|
|
||||||
this.communityListService.loadCommunities(expandedNodes).pipe(
|
this.communityListService.loadCommunities(findOptions, expandedNodes).pipe(
|
||||||
take(1),
|
take(1),
|
||||||
finalize(() => this.loading$.next(false)),
|
finalize(() => this.loading$.next(false)),
|
||||||
).subscribe((flatNodes: FlatNode[]) => {
|
).subscribe((flatNodes: FlatNode[]) => {
|
||||||
|
@@ -4,11 +4,12 @@ import { combineLatest as observableCombineLatest } from 'rxjs/internal/observab
|
|||||||
import { Observable, of as observableOf } from 'rxjs';
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
import { AppState } from '../app.reducer';
|
import { AppState } from '../app.reducer';
|
||||||
import { CommunityDataService } from '../core/data/community-data.service';
|
import { CommunityDataService } from '../core/data/community-data.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { FindListOptions } from '../core/data/request.models';
|
||||||
import { SortDirection, SortOptions } from '../core/cache/models/sort-options.model';
|
import { map, flatMap } from 'rxjs/operators';
|
||||||
import { catchError, filter, map, switchMap, take } from 'rxjs/operators';
|
|
||||||
import { Community } from '../core/shared/community.model';
|
import { Community } from '../core/shared/community.model';
|
||||||
import { Collection } from '../core/shared/collection.model';
|
import { Collection } from '../core/shared/collection.model';
|
||||||
|
import { getSucceededRemoteData } from '../core/shared/operators';
|
||||||
|
import { PageInfo } from '../core/shared/page-info.model';
|
||||||
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
import { hasValue, isNotEmpty } from '../shared/empty.util';
|
||||||
import { RemoteData } from '../core/data/remote-data';
|
import { RemoteData } from '../core/data/remote-data';
|
||||||
import { PaginatedList } from '../core/data/paginated-list';
|
import { PaginatedList } from '../core/data/paginated-list';
|
||||||
@@ -46,8 +47,7 @@ export class ShowMoreFlatNode {
|
|||||||
// Helper method to combine an flatten an array of observables of flatNode arrays
|
// Helper method to combine an flatten an array of observables of flatNode arrays
|
||||||
export const combineAndFlatten = (obsList: Array<Observable<FlatNode[]>>): Observable<FlatNode[]> =>
|
export const combineAndFlatten = (obsList: Array<Observable<FlatNode[]>>): Observable<FlatNode[]> =>
|
||||||
observableCombineLatest(...obsList).pipe(
|
observableCombineLatest(...obsList).pipe(
|
||||||
map((matrix: FlatNode[][]) =>
|
map((matrix: any[][]) => [].concat(...matrix))
|
||||||
matrix.reduce((combinedList, currentList: FlatNode[]) => [...combinedList, ...currentList]))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,6 +99,8 @@ const communityListStateSelector = (state: AppState) => state.communityList;
|
|||||||
const expandedNodesSelector = createSelector(communityListStateSelector, (communityList: CommunityListState) => communityList.expandedNodes);
|
const expandedNodesSelector = createSelector(communityListStateSelector, (communityList: CommunityListState) => communityList.expandedNodes);
|
||||||
const loadingNodeSelector = createSelector(communityListStateSelector, (communityList: CommunityListState) => communityList.loadingNode);
|
const loadingNodeSelector = createSelector(communityListStateSelector, (communityList: CommunityListState) => communityList.loadingNode);
|
||||||
|
|
||||||
|
export const MAX_COMCOLS_PER_PAGE = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service class for the community list, responsible for the creating of the flat list used by communityList dataSource
|
* Service class for the community list, responsible for the creating of the flat list used by communityList dataSource
|
||||||
* and connection to the store to retrieve and save the state of the community list
|
* and connection to the store to retrieve and save the state of the community list
|
||||||
@@ -107,26 +109,8 @@ const loadingNodeSelector = createSelector(communityListStateSelector, (communit
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class CommunityListService {
|
export class CommunityListService {
|
||||||
|
|
||||||
// page-limited list of top-level communities
|
|
||||||
payloads$: Array<Observable<PaginatedList<Community>>>;
|
|
||||||
|
|
||||||
topCommunitiesConfig: PaginationComponentOptions;
|
|
||||||
topCommunitiesSortConfig: SortOptions;
|
|
||||||
|
|
||||||
maxSubCommunitiesPerPage: number;
|
|
||||||
maxCollectionsPerPage: number;
|
|
||||||
|
|
||||||
constructor(private communityDataService: CommunityDataService, private collectionDataService: CollectionDataService,
|
constructor(private communityDataService: CommunityDataService, private collectionDataService: CollectionDataService,
|
||||||
private store: Store<any>) {
|
private store: Store<any>) {
|
||||||
this.topCommunitiesConfig = new PaginationComponentOptions();
|
|
||||||
this.topCommunitiesConfig.id = 'top-level-pagination';
|
|
||||||
this.topCommunitiesConfig.pageSize = 10;
|
|
||||||
this.topCommunitiesConfig.currentPage = 1;
|
|
||||||
this.topCommunitiesSortConfig = new SortOptions('dc.title', SortDirection.ASC);
|
|
||||||
this.initTopCommunityList();
|
|
||||||
|
|
||||||
this.maxSubCommunitiesPerPage = 3;
|
|
||||||
this.maxCollectionsPerPage = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
saveCommunityListStateToStore(expandedNodes: FlatNode[], loadingNode: FlatNode): void {
|
saveCommunityListStateToStore(expandedNodes: FlatNode[], loadingNode: FlatNode): void {
|
||||||
@@ -141,57 +125,46 @@ export class CommunityListService {
|
|||||||
return this.store.select(loadingNodeSelector);
|
return this.store.select(loadingNodeSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Increases the payload so it contains the next page of top level communities
|
|
||||||
*/
|
|
||||||
getNextPageTopCommunities(): void {
|
|
||||||
this.topCommunitiesConfig.currentPage = this.topCommunitiesConfig.currentPage + 1;
|
|
||||||
this.payloads$ = [...this.payloads$, this.communityDataService.findTop({
|
|
||||||
currentPage: this.topCommunitiesConfig.currentPage,
|
|
||||||
elementsPerPage: this.topCommunitiesConfig.pageSize,
|
|
||||||
sort: {
|
|
||||||
field: this.topCommunitiesSortConfig.field,
|
|
||||||
direction: this.topCommunitiesSortConfig.direction
|
|
||||||
}
|
|
||||||
}).pipe(
|
|
||||||
take(1),
|
|
||||||
map((results) => results.payload),
|
|
||||||
)];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all top communities, limited by page, and transforms this in a list of flatNodes.
|
* Gets all top communities, limited by page, and transforms this in a list of flatNodes.
|
||||||
* @param expandedNodes List of expanded nodes; if a node is not expanded its subCommunities and collections need
|
* @param expandedNodes List of expanded nodes; if a node is not expanded its subCommunities and collections need
|
||||||
* not be added to the list
|
* not be added to the list
|
||||||
*/
|
*/
|
||||||
loadCommunities(expandedNodes: FlatNode[]): Observable<FlatNode[]> {
|
loadCommunities(findOptions: FindListOptions, expandedNodes: FlatNode[]): Observable<FlatNode[]> {
|
||||||
const res = this.payloads$.map((payload) => {
|
const currentPage = findOptions.currentPage;
|
||||||
return payload.pipe(
|
const topCommunities = [];
|
||||||
take(1),
|
for (let i = 1; i <= currentPage; i++) {
|
||||||
switchMap((result: PaginatedList<Community>) => {
|
const pagination: FindListOptions = Object.assign({}, findOptions, { currentPage: i });
|
||||||
return this.transformListOfCommunities(result, 0, null, expandedNodes);
|
topCommunities.push(this.getTopCommunities(pagination));
|
||||||
}),
|
}
|
||||||
catchError(() => observableOf([])),
|
const topComs$ = observableCombineLatest(...topCommunities).pipe(
|
||||||
);
|
map((coms: Array<PaginatedList<Community>>) => {
|
||||||
});
|
const newPages: Community[][] = coms.map((unit: PaginatedList<Community>) => unit.page);
|
||||||
return combineAndFlatten(res);
|
const newPage: Community[] = [].concat(...newPages);
|
||||||
|
let newPageInfo = new PageInfo();
|
||||||
|
if (coms && coms.length > 0) {
|
||||||
|
newPageInfo = Object.assign({}, coms[0].pageInfo, { currentPage })
|
||||||
|
}
|
||||||
|
return new PaginatedList(newPageInfo, newPage);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return topComs$.pipe(flatMap((topComs: PaginatedList<Community>) => this.transformListOfCommunities(topComs, 0, null, expandedNodes)));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts the initial top level communities in a list to be called upon
|
* Puts the initial top level communities in a list to be called upon
|
||||||
*/
|
*/
|
||||||
private initTopCommunityList(): void {
|
private getTopCommunities(options: FindListOptions): Observable<PaginatedList<Community>> {
|
||||||
this.payloads$ = [this.communityDataService.findTop({
|
return this.communityDataService.findTop({
|
||||||
currentPage: this.topCommunitiesConfig.currentPage,
|
currentPage: options.currentPage,
|
||||||
elementsPerPage: this.topCommunitiesConfig.pageSize,
|
elementsPerPage: MAX_COMCOLS_PER_PAGE,
|
||||||
sort: {
|
sort: {
|
||||||
field: this.topCommunitiesSortConfig.field,
|
field: options.sort.field,
|
||||||
direction: this.topCommunitiesSortConfig.direction
|
direction: options.sort.direction
|
||||||
}
|
}
|
||||||
}).pipe(
|
}).pipe(
|
||||||
take(1),
|
|
||||||
map((results) => results.payload),
|
map((results) => results.payload),
|
||||||
)];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -206,16 +179,15 @@ export class CommunityListService {
|
|||||||
parent: FlatNode,
|
parent: FlatNode,
|
||||||
expandedNodes: FlatNode[]): Observable<FlatNode[]> {
|
expandedNodes: FlatNode[]): Observable<FlatNode[]> {
|
||||||
if (isNotEmpty(listOfPaginatedCommunities.page)) {
|
if (isNotEmpty(listOfPaginatedCommunities.page)) {
|
||||||
let currentPage = this.topCommunitiesConfig.currentPage;
|
let currentPage = listOfPaginatedCommunities.currentPage;
|
||||||
if (isNotEmpty(parent)) {
|
if (isNotEmpty(parent)) {
|
||||||
currentPage = expandedNodes.find((node: FlatNode) => node.id === parent.id).currentCommunityPage;
|
currentPage = expandedNodes.find((node: FlatNode) => node.id === parent.id).currentCommunityPage;
|
||||||
}
|
}
|
||||||
const isNotAllCommunities = (listOfPaginatedCommunities.totalElements > (listOfPaginatedCommunities.elementsPerPage * currentPage));
|
|
||||||
let obsList = listOfPaginatedCommunities.page
|
let obsList = listOfPaginatedCommunities.page
|
||||||
.map((community: Community) => {
|
.map((community: Community) => {
|
||||||
return this.transformCommunity(community, level, parent, expandedNodes)
|
return this.transformCommunity(community, level, parent, expandedNodes)
|
||||||
});
|
});
|
||||||
if (isNotAllCommunities && listOfPaginatedCommunities.currentPage > currentPage) {
|
if (currentPage < listOfPaginatedCommunities.totalPages && currentPage === listOfPaginatedCommunities.currentPage) {
|
||||||
obsList = [...obsList, observableOf([showMoreFlatNode('community', level, parent)])];
|
obsList = [...obsList, observableOf([showMoreFlatNode('community', level, parent)])];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,13 +224,12 @@ export class CommunityListService {
|
|||||||
let subcoms = [];
|
let subcoms = [];
|
||||||
for (let i = 1; i <= currentCommunityPage; i++) {
|
for (let i = 1; i <= currentCommunityPage; i++) {
|
||||||
const nextSetOfSubcommunitiesPage = this.communityDataService.findByParent(community.uuid, {
|
const nextSetOfSubcommunitiesPage = this.communityDataService.findByParent(community.uuid, {
|
||||||
elementsPerPage: this.maxSubCommunitiesPerPage,
|
elementsPerPage: MAX_COMCOLS_PER_PAGE,
|
||||||
currentPage: i
|
currentPage: i
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
filter((rd: RemoteData<PaginatedList<Community>>) => rd.hasSucceeded),
|
getSucceededRemoteData(),
|
||||||
take(1),
|
flatMap((rd: RemoteData<PaginatedList<Community>>) =>
|
||||||
switchMap((rd: RemoteData<PaginatedList<Community>>) =>
|
|
||||||
this.transformListOfCommunities(rd.payload, level + 1, communityFlatNode, expandedNodes))
|
this.transformListOfCommunities(rd.payload, level + 1, communityFlatNode, expandedNodes))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -271,16 +242,15 @@ export class CommunityListService {
|
|||||||
let collections = [];
|
let collections = [];
|
||||||
for (let i = 1; i <= currentCollectionPage; i++) {
|
for (let i = 1; i <= currentCollectionPage; i++) {
|
||||||
const nextSetOfCollectionsPage = this.collectionDataService.findByParent(community.uuid, {
|
const nextSetOfCollectionsPage = this.collectionDataService.findByParent(community.uuid, {
|
||||||
elementsPerPage: this.maxCollectionsPerPage,
|
elementsPerPage: MAX_COMCOLS_PER_PAGE,
|
||||||
currentPage: i
|
currentPage: i
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
filter((rd: RemoteData<PaginatedList<Collection>>) => rd.hasSucceeded),
|
getSucceededRemoteData(),
|
||||||
take(1),
|
|
||||||
map((rd: RemoteData<PaginatedList<Collection>>) => {
|
map((rd: RemoteData<PaginatedList<Collection>>) => {
|
||||||
let nodes = rd.payload.page
|
let nodes = rd.payload.page
|
||||||
.map((collection: Collection) => toFlatNode(collection, observableOf(false), level + 1, false, communityFlatNode));
|
.map((collection: Collection) => toFlatNode(collection, observableOf(false), level + 1, false, communityFlatNode));
|
||||||
if ((rd.payload.elementsPerPage * currentCollectionPage) < rd.payload.totalElements && rd.payload.currentPage > currentCollectionPage) {
|
if (currentCollectionPage < rd.payload.totalPages && currentCollectionPage === rd.payload.currentPage) {
|
||||||
nodes = [...nodes, showMoreFlatNode('collection', level + 1, communityFlatNode)];
|
nodes = [...nodes, showMoreFlatNode('collection', level + 1, communityFlatNode)];
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
@@ -305,21 +275,18 @@ export class CommunityListService {
|
|||||||
let hasColls$: Observable<boolean>;
|
let hasColls$: Observable<boolean>;
|
||||||
hasSubcoms$ = this.communityDataService.findByParent(community.uuid, { elementsPerPage: 1 })
|
hasSubcoms$ = this.communityDataService.findByParent(community.uuid, { elementsPerPage: 1 })
|
||||||
.pipe(
|
.pipe(
|
||||||
filter((rd: RemoteData<PaginatedList<Community>>) => rd.hasSucceeded),
|
getSucceededRemoteData(),
|
||||||
take(1),
|
|
||||||
map((results) => results.payload.totalElements > 0),
|
map((results) => results.payload.totalElements > 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
hasColls$ = this.collectionDataService.findByParent(community.uuid, { elementsPerPage: 1 })
|
hasColls$ = this.collectionDataService.findByParent(community.uuid, { elementsPerPage: 1 })
|
||||||
.pipe(
|
.pipe(
|
||||||
filter((rd: RemoteData<PaginatedList<Collection>>) => rd.hasSucceeded),
|
getSucceededRemoteData(),
|
||||||
take(1),
|
|
||||||
map((results) => results.payload.totalElements > 0),
|
map((results) => results.payload.totalElements > 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
let hasChildren$: Observable<boolean>;
|
let hasChildren$: Observable<boolean>;
|
||||||
hasChildren$ = observableCombineLatest(hasSubcoms$, hasColls$).pipe(
|
hasChildren$ = observableCombineLatest(hasSubcoms$, hasColls$).pipe(
|
||||||
take(1),
|
|
||||||
map(([hasSubcoms, hasColls]: [boolean, boolean]) => {
|
map(([hasSubcoms, hasColls]: [boolean, boolean]) => {
|
||||||
if (hasSubcoms || hasColls) {
|
if (hasSubcoms || hasColls) {
|
||||||
return true;
|
return true;
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
|
import { FindListOptions } from '../../core/data/request.models';
|
||||||
import { CommunityListService, FlatNode } from '../community-list-service';
|
import { CommunityListService, FlatNode } from '../community-list-service';
|
||||||
import { CommunityListDatasource } from '../community-list-datasource';
|
import { CommunityListDatasource } from '../community-list-datasource';
|
||||||
import { FlatTreeControl } from '@angular/cdk/tree';
|
import { FlatTreeControl } from '@angular/cdk/tree';
|
||||||
@@ -27,7 +29,13 @@ export class CommunityListComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
dataSource: CommunityListDatasource;
|
dataSource: CommunityListDatasource;
|
||||||
|
|
||||||
|
paginationConfig: FindListOptions;
|
||||||
|
|
||||||
constructor(private communityListService: CommunityListService) {
|
constructor(private communityListService: CommunityListService) {
|
||||||
|
this.paginationConfig = new FindListOptions();
|
||||||
|
this.paginationConfig.elementsPerPage = 2;
|
||||||
|
this.paginationConfig.currentPage = 1;
|
||||||
|
this.paginationConfig.sort = new SortOptions('dc.title', SortDirection.ASC);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
@@ -37,7 +45,7 @@ export class CommunityListComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
this.communityListService.getExpandedNodesFromStore().pipe(take(1)).subscribe((result) => {
|
this.communityListService.getExpandedNodesFromStore().pipe(take(1)).subscribe((result) => {
|
||||||
this.expandedNodes = [...result];
|
this.expandedNodes = [...result];
|
||||||
this.dataSource.loadCommunities(this.expandedNodes);
|
this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +82,7 @@ export class CommunityListComponent implements OnInit, OnDestroy {
|
|||||||
node.currentCommunityPage = 1;
|
node.currentCommunityPage = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.dataSource.loadCommunities(this.expandedNodes);
|
this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,10 +102,10 @@ export class CommunityListComponent implements OnInit, OnDestroy {
|
|||||||
const parentNodeInExpandedNodes = this.expandedNodes.find((node2: FlatNode) => node.parent.id === node2.id);
|
const parentNodeInExpandedNodes = this.expandedNodes.find((node2: FlatNode) => node.parent.id === node2.id);
|
||||||
parentNodeInExpandedNodes.currentCommunityPage++;
|
parentNodeInExpandedNodes.currentCommunityPage++;
|
||||||
}
|
}
|
||||||
this.dataSource.loadCommunities(this.expandedNodes);
|
this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes);
|
||||||
} else {
|
} else {
|
||||||
this.communityListService.getNextPageTopCommunities();
|
this.paginationConfig.currentPage++;
|
||||||
this.dataSource.loadCommunities(this.expandedNodes);
|
this.dataSource.loadCommunities(this.paginationConfig, this.expandedNodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -150,12 +150,7 @@ export class RemoteDataBuildService {
|
|||||||
filterSuccessfulResponses(),
|
filterSuccessfulResponses(),
|
||||||
map((response: DSOSuccessResponse) => {
|
map((response: DSOSuccessResponse) => {
|
||||||
if (hasValue((response as DSOSuccessResponse).pageInfo)) {
|
if (hasValue((response as DSOSuccessResponse).pageInfo)) {
|
||||||
const resPageInfo = (response as DSOSuccessResponse).pageInfo;
|
return (response as DSOSuccessResponse).pageInfo;
|
||||||
if (isNotEmpty(resPageInfo) && resPageInfo.currentPage >= 0) {
|
|
||||||
return Object.assign({}, resPageInfo, { currentPage: resPageInfo.currentPage + 1 });
|
|
||||||
} else {
|
|
||||||
return resPageInfo;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
Reference in New Issue
Block a user