Merge branch 'master' into search-features

Conflicts:
	src/app/shared/object-list/search-result-list-element/item-search-result/item-search-result-list-element.component.html
This commit is contained in:
lotte
2018-08-10 11:01:18 +02:00
9 changed files with 150 additions and 6 deletions

View File

@@ -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<NormalizedTestObject, any> {
constructor(
protected responseCache: ResponseCacheService,
protected requestService: RequestService,
protected rdbService: RemoteDataBuildService,
protected store: Store<CoreState>,
protected linkPath: string,
protected halService: HALEndpointService
) {
super();
}
public getScopedEndpoint(scope: string): Observable<string> {
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<CoreState>;
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);
});
})
});
});

View File

@@ -45,6 +45,10 @@ export abstract class DataService<TNormalized extends NormalizedObject, TDomain>
args.push(`sort=${options.sort.field},${options.sort.direction}`); args.push(`sort=${options.sort.field},${options.sort.direction}`);
} }
if (hasValue(options.startsWith)) {
args.push(`startsWith=${options.startsWith}`);
}
if (isNotEmpty(args)) { if (isNotEmpty(args)) {
return result.map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString()); return result.map((href: string) => new URLCombiner(href, `?${args.join('&')}`).toString());
} else { } else {

View File

@@ -141,6 +141,7 @@ export class FindAllOptions {
elementsPerPage?: number; elementsPerPage?: number;
currentPage?: number; currentPage?: number;
sort?: SortOptions; sort?: SortOptions;
startsWith?: string;
} }
export class FindAllRequest extends GetRequest { export class FindAllRequest extends GetRequest {

View File

@@ -1,5 +1,6 @@
import { Component, Inject } from '@angular/core'; import { Component, Inject } from '@angular/core';
import { ListableObject } from '../listable-object.model'; import { ListableObject } from '../listable-object.model';
import { hasValue } from '../../../empty.util';
@Component({ @Component({
selector: 'ds-abstract-object-element', selector: 'ds-abstract-object-element',
@@ -10,4 +11,8 @@ export class AbstractListableElementComponent <T extends ListableObject> {
public constructor(@Inject('objectElementProvider') public listableObject: ListableObject) { public constructor(@Inject('objectElementProvider') public listableObject: ListableObject) {
this.object = listableObject as T; this.object = listableObject as T;
} }
hasValue(data) {
return hasValue(data);
}
} }

View File

@@ -10,7 +10,7 @@
<span *ngFor="let authorMd of object.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']); let last=last;">{{authorMd.value}} <span *ngFor="let authorMd of object.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']); let last=last;">{{authorMd.value}}
<span *ngIf="!last">; </span> <span *ngIf="!last">; </span>
</span> </span>
<span *ngIf="object.findMetadata('dc.date.issued')" class="item-date">{{object.findMetadata("dc.date.issued")}}</span> <span *ngIf="hasValue(object.findMetadata('dc.date.issued'))" class="item-date">{{object.findMetadata("dc.date.issued")}}</span>
</p> </p>
<p *ngIf="object.findMetadata('dc.description.abstract')" class="item-abstract card-text">{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}</p> <p *ngIf="object.findMetadata('dc.description.abstract')" class="item-abstract card-text">{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}</p>

View File

@@ -13,7 +13,7 @@
<p *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0" <p *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0"
class="item-authors card-text text-muted"> class="item-authors card-text text-muted">
<ds-truncatable-part [fixedHeight]="true" [id]="dso.id" [minLines]="1"> <ds-truncatable-part [fixedHeight]="true" [id]="dso.id" [minLines]="1">
<span *ngIf="dso.findMetadata('dc.date.issued').length > 0" class="item-date">{{dso.findMetadata("dc.date.issued")}}</span> <span *ngIf="hasValue(dso.findMetadata('dc.date.issued'))" class="item-date">{{dso.findMetadata("dc.date.issued")}}</span>
<span *ngFor="let authorMd of dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);">, <span *ngFor="let authorMd of dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']);">,
<span [innerHTML]="authorMd.value"></span> <span [innerHTML]="authorMd.value"></span>
</span> </span>

View File

@@ -3,7 +3,7 @@ import { Component, Inject } from '@angular/core';
import { SearchResult } from '../../../+search-page/search-result.model'; import { SearchResult } from '../../../+search-page/search-result.model';
import { DSpaceObject } from '../../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../../core/shared/dspace-object.model';
import { Metadatum } from '../../../core/shared/metadatum.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 { AbstractListableElementComponent } from '../../object-collection/shared/object-collection-element/abstract-listable-element.component';
import { ListableObject } from '../../object-collection/shared/listable-object.model'; import { ListableObject } from '../../object-collection/shared/listable-object.model';
import { TruncatableService } from '../../truncatable/truncatable.service'; import { TruncatableService } from '../../truncatable/truncatable.service';
@@ -60,4 +60,5 @@ export class SearchResultGridElementComponent<T extends SearchResult<K>, K exten
isCollapsed(): Observable<boolean> { isCollapsed(): Observable<boolean> {
return this.truncatableService.isCollapsed(this.dso.id); return this.truncatableService.isCollapsed(this.dso.id);
} }
} }

View File

@@ -9,8 +9,8 @@
<span *ngIf="!last">; </span> <span *ngIf="!last">; </span>
</span> </span>
</span> </span>
(<span *ngIf="object.findMetadata('dc.publisher')" class="item-list-publisher">{{object.findMetadata("dc.publisher")}}, </span><span (<span *ngIf="hasValue(object.findMetadata('dc.publisher'))" class="item-list-publisher">{{object.findMetadata("dc.publisher")}}, </span><span
*ngIf="object.findMetadata('dc.date.issued')" class="item-list-date">{{object.findMetadata("dc.date.issued")}}</span>) *ngIf="hasValue(object.findMetadata('dc.date.issued'))" class="item-list-date">{{object.findMetadata("dc.date.issued")}}</span>)
</span> </span>
<div *ngIf="object.findMetadata('dc.description.abstract')" class="item-list-abstract"> <div *ngIf="object.findMetadata('dc.description.abstract')" class="item-list-abstract">
{{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }} {{object.findMetadata("dc.description.abstract") | dsTruncate:[200] }}

View File

@@ -6,7 +6,7 @@
<ds-truncatable-part [id]="dso.id" [minLines]="1"> <ds-truncatable-part [id]="dso.id" [minLines]="1">
(<span *ngIf="dso.findMetadata('dc.publisher')" class="item-list-publisher" (<span *ngIf="dso.findMetadata('dc.publisher')" class="item-list-publisher"
[innerHTML]="getFirstValue('dc.publisher') + ', '"></span><span [innerHTML]="getFirstValue('dc.publisher') + ', '"></span><span
*ngIf="dso.findMetadata('dc.date.issued')" class="item-list-date" *ngIf="hasValue(dso.findMetadata('dc.date.issued'))" class="item-list-date"
[innerHTML]="getFirstValue('dc.date.issued')"></span>) [innerHTML]="getFirstValue('dc.date.issued')"></span>)
<span *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0" <span *ngIf="dso.filterMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0"
class="item-list-authors"> class="item-list-authors">