diff --git a/src/app/core/data/data.service.spec.ts b/src/app/core/data/data.service.spec.ts
new file mode 100644
index 0000000000..8377afe92e
--- /dev/null
+++ b/src/app/core/data/data.service.spec.ts
@@ -0,0 +1,133 @@
+import { DataService } from './data.service';
+import { NormalizedObject } from '../cache/models/normalized-object.model';
+import { ResponseCacheService } from '../cache/response-cache.service';
+import { RequestService } from './request.service';
+import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
+import { CoreState } from '../core.reducers';
+import { Store } from '@ngrx/store';
+import { HALEndpointService } from '../shared/hal-endpoint.service';
+import { Observable } from 'rxjs/Observable';
+import { FindAllOptions } from './request.models';
+import { SortOptions, SortDirection } from '../cache/models/sort-options.model';
+
+const LINK_NAME = 'test'
+
+// tslint:disable:max-classes-per-file
+class NormalizedTestObject extends NormalizedObject {
+}
+
+class TestService extends DataService {
+ constructor(
+ protected responseCache: ResponseCacheService,
+ protected requestService: RequestService,
+ protected rdbService: RemoteDataBuildService,
+ protected store: Store,
+ protected linkPath: string,
+ protected halService: HALEndpointService
+ ) {
+ super();
+ }
+
+ public getScopedEndpoint(scope: string): Observable {
+ throw new Error('getScopedEndpoint is abstract in DataService');
+ }
+
+}
+
+describe('DataService', () => {
+ let service: TestService;
+ let options: FindAllOptions;
+ const responseCache = {} as ResponseCacheService;
+ const requestService = {} as RequestService;
+ const halService = {} as HALEndpointService;
+ const rdbService = {} as RemoteDataBuildService;
+ const store = {} as Store;
+ const endpoint = 'https://rest.api/core';
+
+ function initTestService(): TestService {
+ return new TestService(
+ responseCache,
+ requestService,
+ rdbService,
+ store,
+ LINK_NAME,
+ halService
+ );
+ }
+
+ service = initTestService();
+
+ describe('getFindAllHref', () => {
+
+ it('should return an observable with the endpoint', () => {
+ options = {};
+
+ (service as any).getFindAllHref(endpoint).subscribe((value) => {
+ expect(value).toBe(endpoint);
+ }
+ );
+ });
+
+ // getScopedEndpoint is not implemented in abstract DataService
+ it('should throw error if scopeID provided in options', () => {
+ options = { scopeID: 'somevalue' };
+
+ expect(() => { (service as any).getFindAllHref(endpoint, options) })
+ .toThrowError('getScopedEndpoint is abstract in DataService');
+ });
+
+ it('should include page in href if currentPage provided in options', () => {
+ options = { currentPage: 2 };
+ const expected = `${endpoint}?page=${options.currentPage - 1}`;
+
+ (service as any).getFindAllHref(endpoint, options).subscribe((value) => {
+ expect(value).toBe(expected);
+ });
+ });
+
+ it('should include size in href if elementsPerPage provided in options', () => {
+ options = { elementsPerPage: 5 };
+ const expected = `${endpoint}?size=${options.elementsPerPage}`;
+
+ (service as any).getFindAllHref(endpoint, options).subscribe((value) => {
+ expect(value).toBe(expected);
+ });
+ });
+
+ it('should include sort href if SortOptions provided in options', () => {
+ const sortOptions = new SortOptions('field1', SortDirection.ASC);
+ options = { sort: sortOptions};
+ const expected = `${endpoint}?sort=${sortOptions.field},${sortOptions.direction}`;
+
+ (service as any).getFindAllHref(endpoint, options).subscribe((value) => {
+ expect(value).toBe(expected);
+ });
+ });
+
+ it('should include startsWith in href if startsWith provided in options', () => {
+ options = { startsWith: 'ab' };
+ const expected = `${endpoint}?startsWith=${options.startsWith}`;
+
+ (service as any).getFindAllHref(endpoint, options).subscribe((value) => {
+ expect(value).toBe(expected);
+ });
+ });
+
+ it('should include all provided options in href', () => {
+ const sortOptions = new SortOptions('field1', SortDirection.DESC)
+ options = {
+ currentPage: 6,
+ elementsPerPage: 10,
+ sort: sortOptions,
+ startsWith: 'ab'
+ }
+ const expected = `${endpoint}?page=${options.currentPage - 1}&size=${options.elementsPerPage}` +
+ `&sort=${sortOptions.field},${sortOptions.direction}&startsWith=${options.startsWith}`;
+
+ (service as any).getFindAllHref(endpoint, options).subscribe((value) => {
+ expect(value).toBe(expected);
+ });
+ })
+ });
+
+});
diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts
index f532ff05ba..06e7f25926 100644
--- a/src/app/core/data/data.service.ts
+++ b/src/app/core/data/data.service.ts
@@ -45,6 +45,10 @@ export abstract class DataService
args.push(`sort=${options.sort.field},${options.sort.direction}`);
}
+ if (hasValue(options.startsWith)) {
+ args.push(`startsWith=${options.startsWith}`);
+ }
+
if (isNotEmpty(args)) {
return result.map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString());
} else {
diff --git a/src/app/core/data/request.models.ts b/src/app/core/data/request.models.ts
index 7015b0b0f1..ce45d5b41c 100644
--- a/src/app/core/data/request.models.ts
+++ b/src/app/core/data/request.models.ts
@@ -141,6 +141,7 @@ export class FindAllOptions {
elementsPerPage?: number;
currentPage?: number;
sort?: SortOptions;
+ startsWith?: string;
}
export class FindAllRequest extends GetRequest {
diff --git a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts
index d52036b5dc..59df86fdff 100644
--- a/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts
+++ b/src/app/shared/object-collection/shared/object-collection-element/abstract-listable-element.component.ts
@@ -1,5 +1,6 @@
import { Component, Inject } from '@angular/core';
import { ListableObject } from '../listable-object.model';
+import { hasValue } from '../../../empty.util';
@Component({
selector: 'ds-abstract-object-element',
@@ -10,4 +11,8 @@ export class AbstractListableElementComponent {
public constructor(@Inject('objectElementProvider') public listableObject: ListableObject) {
this.object = listableObject as T;
}
+
+ hasValue(data) {
+ return hasValue(data);
+ }
}
diff --git a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html
index cc2f2efdb1..5100b984e0 100644
--- a/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html
+++ b/src/app/shared/object-grid/item-grid-element/item-grid-element.component.html
@@ -10,7 +10,7 @@
{{authorMd.value}}
;
- {{object.findMetadata("dc.date.issued")}}
+ {{object.findMetadata("dc.date.issued")}}
{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}
diff --git a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html
index 1cf14587ad..1e4f6f3c64 100644
--- a/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html
+++ b/src/app/shared/object-grid/search-result-grid-element/item-search-result/item-search-result-grid-element.component.html
@@ -13,7 +13,7 @@
0"
class="item-authors card-text text-muted">
- 0" class="item-date">{{dso.findMetadata("dc.date.issued")}}
+ {{dso.findMetadata("dc.date.issued")}}
,
diff --git a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts
index e6217eb0bb..5ab9f472b4 100644
--- a/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts
+++ b/src/app/shared/object-grid/search-result-grid-element/search-result-grid-element.component.ts
@@ -3,7 +3,7 @@ import { Component, Inject } from '@angular/core';
import { SearchResult } from '../../../+search-page/search-result.model';
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
import { Metadatum } from '../../../core/shared/metadatum.model';
-import { isEmpty, hasNoValue } from '../../empty.util';
+import { isEmpty, hasNoValue, hasValue } from '../../empty.util';
import { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component';
import { ListableObject } from '../../object-collection/shared/listable-object.model';
import { TruncatableService } from '../../truncatable/truncatable.service';
@@ -60,4 +60,5 @@ export class SearchResultGridElementComponent, K exten
isCollapsed(): Observable {
return this.truncatableService.isCollapsed(this.dso.id);
}
+
}
diff --git a/src/app/shared/object-list/item-list-element/item-list-element.component.html b/src/app/shared/object-list/item-list-element/item-list-element.component.html
index b4259c25c2..1e4a944ffa 100644
--- a/src/app/shared/object-list/item-list-element/item-list-element.component.html
+++ b/src/app/shared/object-list/item-list-element/item-list-element.component.html
@@ -9,8 +9,8 @@
;
- ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}})
+ ({{object.findMetadata("dc.publisher")}}, {{object.findMetadata("dc.date.issued")}})
{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}
diff --git a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html
index 2b90269693..584d476e73 100644
--- a/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html
+++ b/src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html
@@ -6,7 +6,7 @@
()
0"
class="item-list-authors">