Skip to content

Commit bb31e1d

Browse files
authored
Merge pull request DSpace#1801 from GauravD2t/main
Displaying Recent Submissions on the homepage
2 parents 6d361be + ac2922e commit bb31e1d

13 files changed

Lines changed: 207 additions & 5 deletions

config/config.example.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,10 @@ mediaViewer:
258258
info:
259259
enableEndUserAgreement: true
260260
enablePrivacyStatement: true
261+
# Home Page
262+
homePage:
263+
recentSubmissions:
264+
# The number of item showing in recent submission components
265+
pageSize: 5
266+
# Sort record of recent submission
267+
sortField: 'dc.date.accessioned'

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
</ng-container>
66
<ds-search-form [inPlaceSearch]="false" [searchPlaceholder]="'home.search-form.placeholder' | translate"></ds-search-form>
77
<ds-top-level-community-list></ds-top-level-community-list>
8+
<ds-recent-item-list *ngIf="recentSubmissionspageSize>0"></ds-recent-item-list>
89
</div>

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { map } from 'rxjs/operators';
33
import { ActivatedRoute } from '@angular/router';
44
import { Observable } from 'rxjs';
55
import { Site } from '../core/shared/site.model';
6-
6+
import { environment } from '../../environments/environment';
77
@Component({
88
selector: 'ds-home-page',
99
styleUrls: ['./home-page.component.scss'],
@@ -12,10 +12,11 @@ import { Site } from '../core/shared/site.model';
1212
export class HomePageComponent implements OnInit {
1313

1414
site$: Observable<Site>;
15-
15+
recentSubmissionspageSize: number;
1616
constructor(
1717
private route: ActivatedRoute,
1818
) {
19+
this.recentSubmissionspageSize = environment.homePage.recentSubmissions.pageSize;
1920
}
2021

2122
ngOnInit(): void {

src/app/home-page/home-page.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import { TopLevelCommunityListComponent } from './top-level-community-list/top-l
99
import { StatisticsModule } from '../statistics/statistics.module';
1010
import { ThemedHomeNewsComponent } from './home-news/themed-home-news.component';
1111
import { ThemedHomePageComponent } from './themed-home-page.component';
12-
12+
import { RecentItemListComponent } from './recent-item-list/recent-item-list.component';
1313
const DECLARATIONS = [
1414
HomePageComponent,
1515
ThemedHomePageComponent,
1616
TopLevelCommunityListComponent,
1717
ThemedHomeNewsComponent,
1818
HomeNewsComponent,
19+
RecentItemListComponent
1920
];
2021

2122
@NgModule({
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<ng-container *ngVar="(itemRD$ | async) as itemRD">
2+
<div class="mt-4" *ngIf="itemRD?.hasSucceeded && itemRD?.payload?.page.length > 0" @fadeIn>
3+
<div class="d-flex flex-row border-bottom mb-4 pb-4 ng-tns-c416-2"></div>
4+
<h2> {{'home.recent-submissions.head' | translate}}</h2>
5+
<div class="my-4" *ngFor="let item of itemRD?.payload?.page">
6+
<ds-listable-object-component-loader [object]="item" [viewMode]="viewMode" class="pb-4">
7+
</ds-listable-object-component-loader>
8+
</div>
9+
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-left ng-tns-c290-40">Load
10+
more...</button>
11+
</div>
12+
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.recent-submissions' | translate}}"></ds-error>
13+
<ds-loading *ngIf="!itemRD || itemRD.isLoading" message="{{'loading.recent-submissions' | translate}}">
14+
</ds-loading>
15+
</ng-container>

src/app/home-page/recent-item-list/recent-item-list.component.scss

Whitespace-only changes.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { SearchService } from 'src/app/core/shared/search/search.service';
3+
import { createSuccessfulRemoteDataObject } from 'src/app/shared/remote-data.utils';
4+
import { SearchServiceStub } from 'src/app/shared/testing/search-service.stub';
5+
import { createPaginatedList } from 'src/app/shared/testing/utils.test';
6+
import { PaginationService } from '../../core/pagination/pagination.service';
7+
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
8+
import { RecentItemListComponent } from './recent-item-list.component';
9+
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
10+
import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model';
11+
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
12+
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
13+
import { ViewMode } from 'src/app/core/shared/view-mode.model';
14+
import { of as observableOf } from 'rxjs';
15+
describe('RecentItemListComponent', () => {
16+
let component: RecentItemListComponent;
17+
let fixture: ComponentFixture<RecentItemListComponent>;
18+
const emptyList = createSuccessfulRemoteDataObject(createPaginatedList([]));
19+
let paginationService;
20+
const searchServiceStub = Object.assign(new SearchServiceStub(), {
21+
search: () => observableOf(emptyList),
22+
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
23+
clearDiscoveryRequests: () => {}
24+
/* eslint-enable no-empty,@typescript-eslint/no-empty-function */
25+
});
26+
paginationService = new PaginationServiceStub();
27+
const mockSearchOptions = observableOf(new PaginatedSearchOptions({
28+
pagination: Object.assign(new PaginationComponentOptions(), {
29+
id: 'search-page-configuration',
30+
pageSize: 10,
31+
currentPage: 1
32+
}),
33+
sort: new SortOptions('dc.date.accessioned', SortDirection.DESC),
34+
}));
35+
const searchConfigServiceStub = {
36+
paginatedSearchOptions: mockSearchOptions
37+
};
38+
beforeEach(async () => {
39+
await TestBed.configureTestingModule({
40+
declarations: [ RecentItemListComponent],
41+
providers: [
42+
{ provide: SearchService, useValue: searchServiceStub },
43+
{ provide: PaginationService, useValue: paginationService },
44+
{ provide: SearchConfigurationService, useValue: searchConfigServiceStub },
45+
],
46+
})
47+
.compileComponents();
48+
});
49+
50+
beforeEach(() => {
51+
fixture = TestBed.createComponent(RecentItemListComponent);
52+
component = fixture.componentInstance;
53+
fixture.detectChanges();
54+
});
55+
56+
it('should create', () => {
57+
expect(component).toBeTruthy();
58+
});
59+
60+
it('should call the navigate method on the Router with view mode list parameter as a parameter when setViewMode is called', () => {
61+
component.onLoadMore();
62+
expect(paginationService.updateRouteWithUrl).toHaveBeenCalledWith(undefined, ['search'], Object({ sortField: 'dc.date.accessioned', sortDirection: 'DESC', page: 1 }));
63+
});
64+
});
65+
66+
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
2+
import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model';
3+
import { fadeIn, fadeInOut } from '../../shared/animations/fade';
4+
import { RemoteData } from '../../core/data/remote-data';
5+
import { PaginatedList } from '../../core/data/paginated-list.model';
6+
import { Item } from '../../core/shared/item.model';
7+
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
8+
import { PaginationService } from '../../core/pagination/pagination.service';
9+
import { SearchService } from '../../core/shared/search/search.service';
10+
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
11+
import { environment } from '../../../environments/environment';
12+
import { ViewMode } from '../../core/shared/view-mode.model';
13+
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
14+
import {
15+
toDSpaceObjectListRD
16+
} from '../../core/shared/operators';
17+
import {
18+
Observable,
19+
} from 'rxjs';
20+
@Component({
21+
selector: 'ds-recent-item-list',
22+
templateUrl: './recent-item-list.component.html',
23+
styleUrls: ['./recent-item-list.component.scss'],
24+
changeDetection: ChangeDetectionStrategy.OnPush,
25+
animations: [
26+
fadeIn,
27+
fadeInOut
28+
]
29+
})
30+
export class RecentItemListComponent implements OnInit {
31+
itemRD$: Observable<RemoteData<PaginatedList<Item>>>;
32+
paginationConfig: PaginationComponentOptions;
33+
sortConfig: SortOptions;
34+
/**
35+
* The view-mode we're currently on
36+
* @type {ViewMode}
37+
*/
38+
viewMode = ViewMode.ListElement;
39+
constructor(private searchService: SearchService,
40+
private paginationService: PaginationService,
41+
public searchConfigurationService: SearchConfigurationService
42+
) {
43+
44+
this.paginationConfig = Object.assign(new PaginationComponentOptions(), {
45+
id: 'hp',
46+
pageSize: environment.homePage.recentSubmissions.pageSize,
47+
currentPage: 1,
48+
maxSize: 1
49+
});
50+
this.sortConfig = new SortOptions(environment.homePage.recentSubmissions.sortField, SortDirection.DESC);
51+
}
52+
ngOnInit(): void {
53+
this.itemRD$ = this.searchService.search(
54+
new PaginatedSearchOptions({
55+
pagination: this.paginationConfig,
56+
sort: this.sortConfig,
57+
}),
58+
).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>>;
59+
}
60+
ngOnDestroy(): void {
61+
this.paginationService.clearPagination(this.paginationConfig.id);
62+
}
63+
onLoadMore(): void {
64+
this.paginationService.updateRouteWithUrl(this.searchConfigurationService.paginationID, ['search'], {
65+
sortField: environment.homePage.recentSubmissions.sortField,
66+
sortDirection: 'DESC' as SortDirection,
67+
page: 1
68+
});
69+
}
70+
71+
}
72+

src/assets/i18n/en.json5

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4763,5 +4763,6 @@
47634763
"person.orcid.registry.queue": "ORCID Registry Queue",
47644764

47654765
"person.orcid.registry.auth": "ORCID Authorizations",
4766+
"home.recent-submissions.head": "Recent Submissions",
47664767

47674768
}

src/config/app-config.interface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { BrowseByConfig } from './browse-by-config.interface';
1717
import { BundleConfig } from './bundle-config.interface';
1818
import { ActuatorsConfig } from './actuators.config';
1919
import { InfoConfig } from './info-config.interface';
20-
20+
import { HomeConfig } from './homepage-config.interface';
2121
interface AppConfig extends Config {
2222
ui: UIServerConfig;
2323
rest: ServerConfig;
@@ -38,6 +38,7 @@ interface AppConfig extends Config {
3838
bundle: BundleConfig;
3939
actuators: ActuatorsConfig
4040
info: InfoConfig;
41+
homePage: HomeConfig;
4142
}
4243

4344
/**

0 commit comments

Comments
 (0)