Skip to content

Commit 5b33c49

Browse files
committed
Added upper limit to browse by date
1 parent 1ddeeed commit 5b33c49

3 files changed

Lines changed: 66 additions & 29 deletions

File tree

src/app/browse-by/browse-by-date-page/browse-by-date-page.component.spec.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { PaginationService } from '../../core/pagination/pagination.service';
2222
import { PaginationServiceStub } from '../../shared/testing/pagination-service.stub';
2323
import { APP_CONFIG } from '../../../config/app-config.interface';
2424
import { environment } from '../../../environments/environment';
25+
import { SortDirection } from '../../core/cache/models/sort-options.model';
2526

2627
describe('BrowseByDatePageComponent', () => {
2728
let comp: BrowseByDatePageComponent;
@@ -49,12 +50,22 @@ describe('BrowseByDatePageComponent', () => {
4950
]
5051
}
5152
});
53+
const lastItem = Object.assign(new Item(), {
54+
id: 'last-item-id',
55+
metadata: {
56+
'dc.date.issued': [
57+
{
58+
value: '1960-01-01'
59+
}
60+
]
61+
}
62+
});
5263

53-
const mockBrowseService = {
54-
getBrowseEntriesFor: (options: BrowseEntrySearchOptions) => toRemoteData([]),
55-
getBrowseItemsFor: (value: string, options: BrowseEntrySearchOptions) => toRemoteData([firstItem]),
56-
getFirstItemFor: () => createSuccessfulRemoteDataObject$(firstItem)
57-
};
64+
const mockBrowseService = {
65+
getBrowseEntriesFor: (options: BrowseEntrySearchOptions) => toRemoteData([]),
66+
getBrowseItemsFor: (value: string, options: BrowseEntrySearchOptions) => toRemoteData([firstItem]),
67+
getFirstItemFor: (definition: string, scope?: string, sortDirection?: SortDirection) => null
68+
};
5869

5970
const mockDsoService = {
6071
findById: () => createSuccessfulRemoteDataObject$(mockCommunity)
@@ -91,9 +102,14 @@ describe('BrowseByDatePageComponent', () => {
91102

92103
beforeEach(() => {
93104
fixture = TestBed.createComponent(BrowseByDatePageComponent);
105+
const browseService = fixture.debugElement.injector.get(BrowseService);
106+
spyOn(browseService, 'getFirstItemFor')
107+
// ok to expect the default browse as first param since we just need the mock items obtained via sort direction.
108+
.withArgs('author', undefined, SortDirection.ASC).and.returnValue(createSuccessfulRemoteDataObject$(firstItem))
109+
.withArgs('author', undefined, SortDirection.DESC).and.returnValue(createSuccessfulRemoteDataObject$(lastItem));
94110
comp = fixture.componentInstance;
95-
fixture.detectChanges();
96111
route = (comp as any).route;
112+
fixture.detectChanges();
97113
});
98114

99115
it('should initialize the list of items', () => {
@@ -107,6 +123,7 @@ describe('BrowseByDatePageComponent', () => {
107123
});
108124

109125
it('should create a list of startsWith options with the current year first', () => {
110-
expect(comp.startsWithOptions[0]).toEqual(new Date().getUTCFullYear());
126+
//expect(comp.startsWithOptions[0]).toEqual(new Date().getUTCFullYear());
127+
expect(comp.startsWithOptions[0]).toEqual(1960);
111128
});
112129
});

src/app/browse-by/browse-by-date-page/browse-by-date-page.component.ts

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { ChangeDetectorRef, Component, Inject } from '@angular/core';
22
import {
33
BrowseByMetadataPageComponent,
4-
browseParamsToOptions, getBrowseSearchOptions
4+
browseParamsToOptions,
5+
getBrowseSearchOptions
56
} from '../browse-by-metadata-page/browse-by-metadata-page.component';
67
import { combineLatest as observableCombineLatest } from 'rxjs';
7-
import { RemoteData } from '../../core/data/remote-data';
8-
import { Item } from '../../core/shared/item.model';
98
import { hasValue, isNotEmpty } from '../../shared/empty.util';
109
import { ActivatedRoute, Params, Router } from '@angular/router';
1110
import { BrowseService } from '../../core/browse/browse.service';
@@ -16,7 +15,9 @@ import { map } from 'rxjs/operators';
1615
import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model';
1716
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
1817
import { isValidDate } from '../../shared/date.util';
19-
import { AppConfig, APP_CONFIG } from '../../../config/app-config.interface';
18+
import { APP_CONFIG, AppConfig } from '../../../config/app-config.interface';
19+
import { RemoteData } from '../../core/data/remote-data';
20+
import { Item } from '../../core/shared/item.model';
2021

2122
@Component({
2223
selector: 'ds-browse-by-date-page',
@@ -72,38 +73,32 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
7273

7374
/**
7475
* Update the StartsWith options
75-
* In this implementation, it creates a list of years starting from now, going all the way back to the earliest
76-
* date found on an item within this scope. The further back in time, the bigger the change in years become to avoid
77-
* extremely long lists with a one-year difference.
76+
* In this implementation, it creates a list of years starting from the most recent item or the current year, going
77+
* all the way back to the earliest date found on an item within this scope. The further back in time, the bigger
78+
* the change in years become to avoid extremely long lists with a one-year difference.
7879
* To determine the change in years, the config found under GlobalConfig.BrowseBy is used for this.
7980
* @param definition The metadata definition to fetch the first item for
8081
* @param metadataKeys The metadata fields to fetch the earliest date from (expects a date field)
8182
* @param scope The scope under which to fetch the earliest item for
8283
*/
8384
updateStartsWithOptions(definition: string, metadataKeys: string[], scope?: string) {
85+
const firstItemRD = this.browseService.getFirstItemFor(definition, scope, SortDirection.ASC);
86+
const lastItemRD = this.browseService.getFirstItemFor(definition, scope, SortDirection.DESC);
8487
this.subs.push(
85-
this.browseService.getFirstItemFor(definition, scope).subscribe((firstItemRD: RemoteData<Item>) => {
86-
let lowerLimit = this.appConfig.browseBy.defaultLowerLimit;
87-
if (hasValue(firstItemRD.payload)) {
88-
const date = firstItemRD.payload.firstMetadataValue(metadataKeys);
89-
if (isNotEmpty(date) && isValidDate(date)) {
90-
const dateObj = new Date(date);
91-
// TODO: it appears that getFullYear (based on local time) is sometimes unreliable. Switching to UTC.
92-
lowerLimit = isNaN(dateObj.getUTCFullYear()) ? lowerLimit : dateObj.getUTCFullYear();
93-
}
94-
}
88+
observableCombineLatest([firstItemRD, lastItemRD]).subscribe(([firstItem, lastItem]) => {
89+
let lowerLimit = this.getLimit(firstItem, metadataKeys, this.appConfig.browseBy.defaultLowerLimit);
90+
let upperLimit = this.getLimit(lastItem, metadataKeys, new Date().getUTCFullYear());
9591
const options = [];
96-
const currentYear = new Date().getUTCFullYear();
97-
const oneYearBreak = Math.floor((currentYear - this.appConfig.browseBy.oneYearLimit) / 5) * 5;
98-
const fiveYearBreak = Math.floor((currentYear - this.appConfig.browseBy.fiveYearLimit) / 10) * 10;
92+
const oneYearBreak = Math.floor((upperLimit - this.appConfig.browseBy.oneYearLimit) / 5) * 5;
93+
const fiveYearBreak = Math.floor((upperLimit - this.appConfig.browseBy.fiveYearLimit) / 10) * 10;
9994
if (lowerLimit <= fiveYearBreak) {
10095
lowerLimit -= 10;
10196
} else if (lowerLimit <= oneYearBreak) {
10297
lowerLimit -= 5;
10398
} else {
10499
lowerLimit -= 1;
105100
}
106-
let i = currentYear;
101+
let i = upperLimit;
107102
while (i > lowerLimit) {
108103
options.push(i);
109104
if (i <= fiveYearBreak) {
@@ -121,4 +116,24 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
121116
})
122117
);
123118
}
119+
120+
/**
121+
* Returns the year from the item metadata field or the limit.
122+
* @param itemRD the item remote data
123+
* @param metadataKeys The metadata fields to fetch the earliest date from (expects a date field)
124+
* @param limit the limit to use if the year can't be found in metadata
125+
* @private
126+
*/
127+
private getLimit(itemRD: RemoteData<Item>, metadataKeys: string[], limit: number): number {
128+
if (hasValue(itemRD.payload)) {
129+
const date = itemRD.payload.firstMetadataValue(metadataKeys);
130+
if (isNotEmpty(date) && isValidDate(date)) {
131+
const dateObj = new Date(date);
132+
// TODO: it appears that getFullYear (based on local time) is sometimes unreliable. Switching to UTC.
133+
return isNaN(dateObj.getUTCFullYear()) ? limit : dateObj.getUTCFullYear();
134+
} else {
135+
return new Date().getUTCFullYear();
136+
}
137+
}
138+
}
124139
}

src/app/core/browse/browse.service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { BrowseEntrySearchOptions } from './browse-entry-search-options.model';
2222
import { HrefOnlyDataService } from '../data/href-only-data.service';
2323
import { followLink, FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
2424
import { BrowseDefinitionDataService } from './browse-definition-data.service';
25+
import { SortDirection } from '../cache/models/sort-options.model';
2526

2627

2728
export const BROWSE_LINKS_TO_FOLLOW: FollowLinkConfig<BrowseEntry | Item>[] = [
@@ -160,8 +161,9 @@ export class BrowseService {
160161
* Get the first item for a metadata definition in an optional scope
161162
* @param definition
162163
* @param scope
164+
* @param sortDirection optional sort parameter
163165
*/
164-
getFirstItemFor(definition: string, scope?: string): Observable<RemoteData<Item>> {
166+
getFirstItemFor(definition: string, scope?: string, sortDirection?: SortDirection): Observable<RemoteData<Item>> {
165167
const href$ = this.getBrowseDefinitions().pipe(
166168
getBrowseDefinitionLinks(definition),
167169
hasValueOperator(),
@@ -177,6 +179,9 @@ export class BrowseService {
177179
}
178180
args.push('page=0');
179181
args.push('size=1');
182+
if (sortDirection) {
183+
args.push('sort=default,' + sortDirection);
184+
}
180185
if (isNotEmpty(args)) {
181186
href = new URLCombiner(href, `?${args.join('&')}`).toString();
182187
}

0 commit comments

Comments
 (0)