mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
Merge pull request #1434 from atmire/shared-feature-authority-control
Allow facets to be authority controlled
This commit is contained in:
@@ -63,7 +63,7 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
||||
this.browseId = params.id || this.defaultBrowseId;
|
||||
this.startsWith = +params.startsWith || params.startsWith;
|
||||
const searchOptions = browseParamsToOptions(params, currentPage, currentSort, this.browseId);
|
||||
this.updatePageWithItems(searchOptions, this.value);
|
||||
this.updatePageWithItems(searchOptions, this.value, undefined);
|
||||
this.updateParent(params.scope);
|
||||
this.updateStartsWithOptions(this.browseId, metadataKeys, params.scope);
|
||||
}));
|
||||
|
@@ -99,6 +99,11 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
||||
*/
|
||||
value = '';
|
||||
|
||||
/**
|
||||
* The authority key (may be undefined) associated with {@link #value}.
|
||||
*/
|
||||
authority: string;
|
||||
|
||||
/**
|
||||
* The current startsWith option (fetched and updated from query-params)
|
||||
*/
|
||||
@@ -123,11 +128,12 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
||||
})
|
||||
).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => {
|
||||
this.browseId = params.id || this.defaultBrowseId;
|
||||
this.authority = params.authority;
|
||||
this.value = +params.value || params.value || '';
|
||||
this.startsWith = +params.startsWith || params.startsWith;
|
||||
const searchOptions = browseParamsToOptions(params, currentPage, currentSort, this.browseId);
|
||||
if (isNotEmpty(this.value)) {
|
||||
this.updatePageWithItems(searchOptions, this.value);
|
||||
this.updatePageWithItems(searchOptions, this.value, this.authority);
|
||||
} else {
|
||||
this.updatePage(searchOptions);
|
||||
}
|
||||
@@ -166,8 +172,8 @@ export class BrowseByMetadataPageComponent implements OnInit {
|
||||
* scope: string }
|
||||
* @param value The value of the browse-entry to display items for
|
||||
*/
|
||||
updatePageWithItems(searchOptions: BrowseEntrySearchOptions, value: string) {
|
||||
this.items$ = this.browseService.getBrowseItemsFor(value, searchOptions);
|
||||
updatePageWithItems(searchOptions: BrowseEntrySearchOptions, value: string, authority: string) {
|
||||
this.items$ = this.browseService.getBrowseItemsFor(value, authority, searchOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -46,7 +46,7 @@ export class BrowseByTitlePageComponent extends BrowseByMetadataPageComponent {
|
||||
})
|
||||
).subscribe(([params, currentPage, currentSort]: [Params, PaginationComponentOptions, SortOptions]) => {
|
||||
this.browseId = params.id || this.defaultBrowseId;
|
||||
this.updatePageWithItems(browseParamsToOptions(params, currentPage, currentSort, this.browseId), undefined);
|
||||
this.updatePageWithItems(browseParamsToOptions(params, currentPage, currentSort, this.browseId), undefined, undefined);
|
||||
this.updateParent(params.scope);
|
||||
}));
|
||||
this.updateStartsWithTextOptions();
|
||||
|
@@ -129,6 +129,7 @@ describe('BrowseService', () => {
|
||||
describe('getBrowseEntriesFor and findList', () => {
|
||||
// should contain special characters such that url encoding can be tested as well
|
||||
const mockAuthorName = 'Donald Smith & Sons';
|
||||
const mockAuthorityKey = 'some authority key ?=;';
|
||||
|
||||
beforeEach(() => {
|
||||
requestService = getMockRequestService(getRequestEntry$(true));
|
||||
@@ -155,7 +156,7 @@ describe('BrowseService', () => {
|
||||
it('should call hrefOnlyDataService.findAllByHref with the expected href', () => {
|
||||
const expected = browseDefinitions[1]._links.items.href + '?filterValue=' + encodeURIComponent(mockAuthorName);
|
||||
|
||||
scheduler.schedule(() => service.getBrowseItemsFor(mockAuthorName, new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
||||
scheduler.schedule(() => service.getBrowseItemsFor(mockAuthorName, undefined, new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
||||
scheduler.flush();
|
||||
|
||||
expect(getFirstUsedArgumentOfSpyMethod(hrefOnlyDataService.findAllByHref)).toBeObservable(cold('(a|)', {
|
||||
@@ -164,6 +165,20 @@ describe('BrowseService', () => {
|
||||
});
|
||||
|
||||
});
|
||||
describe('when getBrowseItemsFor is called with a valid filter value and authority key', () => {
|
||||
it('should call hrefOnlyDataService.findAllByHref with the expected href', () => {
|
||||
const expected = browseDefinitions[1]._links.items.href +
|
||||
'?filterValue=' + encodeURIComponent(mockAuthorName) +
|
||||
'&filterAuthority=' + encodeURIComponent(mockAuthorityKey);
|
||||
|
||||
scheduler.schedule(() => service.getBrowseItemsFor(mockAuthorName, mockAuthorityKey, new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
||||
scheduler.flush();
|
||||
|
||||
expect(getFirstUsedArgumentOfSpyMethod(hrefOnlyDataService.findAllByHref)).toBeObservable(cold('(a|)', {
|
||||
a: expected
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBrowseURLFor', () => {
|
||||
|
@@ -105,7 +105,7 @@ export class BrowseService {
|
||||
* @param options Options to narrow down your search
|
||||
* @returns {Observable<RemoteData<PaginatedList<Item>>>}
|
||||
*/
|
||||
getBrowseItemsFor(filterValue: string, options: BrowseEntrySearchOptions): Observable<RemoteData<PaginatedList<Item>>> {
|
||||
getBrowseItemsFor(filterValue: string, filterAuthority: string, options: BrowseEntrySearchOptions): Observable<RemoteData<PaginatedList<Item>>> {
|
||||
const href$ = this.getBrowseDefinitions().pipe(
|
||||
getBrowseDefinitionLinks(options.metadataDefinition),
|
||||
hasValueOperator(),
|
||||
@@ -132,6 +132,9 @@ export class BrowseService {
|
||||
if (isNotEmpty(filterValue)) {
|
||||
args.push(`filterValue=${encodeURIComponent(filterValue)}`);
|
||||
}
|
||||
if (isNotEmpty(filterAuthority)) {
|
||||
args.push(`filterAuthority=${encodeURIComponent(filterAuthority)}`);
|
||||
}
|
||||
if (isNotEmpty(args)) {
|
||||
href = new URLCombiner(href, `?${args.join('&')}`).toString();
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<div class="d-flex flex-row">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="" [queryParams]="{value: object.value, startsWith: undefined}" [queryParamsHandling]="'merge'" class="lead">
|
||||
<a *ngIf="linkType != linkTypes.None" [target]="(linkType == linkTypes.ExternalLink) ? '_blank' : '_self'" rel="noopener noreferrer" [routerLink]="" [queryParams]="getQueryParams()" [queryParamsHandling]="'merge'" class="lead">
|
||||
{{object.value}}
|
||||
</a>
|
||||
<span *ngIf="linkType == linkTypes.None" class="lead">
|
||||
|
@@ -15,4 +15,16 @@ import { listableObjectComponent } from '../../object-collection/shared/listable
|
||||
* This component is automatically used to create a list view for BrowseEntry objects when used in ObjectCollectionComponent
|
||||
*/
|
||||
@listableObjectComponent(BrowseEntry, ViewMode.ListElement)
|
||||
export class BrowseEntryListElementComponent extends AbstractListableElementComponent<BrowseEntry> {}
|
||||
export class BrowseEntryListElementComponent extends AbstractListableElementComponent<BrowseEntry> {
|
||||
|
||||
/**
|
||||
* Get the query params to access the item page of this browse entry.
|
||||
*/
|
||||
public getQueryParams(): {[param: string]: any} {
|
||||
return {
|
||||
value: this.object.value,
|
||||
authority: !!this.object.authority ? this.object.authority : undefined,
|
||||
startsWith: undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,12 @@ export class FacetValue implements HALResource {
|
||||
@autoserialize
|
||||
count: number;
|
||||
|
||||
/**
|
||||
* The Authority Value for this facet
|
||||
*/
|
||||
@autoserialize
|
||||
authorityKey?: string;
|
||||
|
||||
/**
|
||||
* The {@link HALLink}s for this FacetValue
|
||||
*/
|
||||
|
@@ -12,6 +12,7 @@ describe('Search Utils', () => {
|
||||
let facetValueWithSearchHref: FacetValue;
|
||||
let facetValueWithoutSearchHref: FacetValue;
|
||||
let searchFilterConfig: SearchFilterConfig;
|
||||
let facetValueWithSearchHrefAuthority: FacetValue;
|
||||
|
||||
beforeEach(() => {
|
||||
facetValueWithSearchHref = Object.assign(new FacetValue(), {
|
||||
@@ -22,6 +23,11 @@ describe('Search Utils', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
facetValueWithSearchHrefAuthority = Object.assign(new FacetValue(), {
|
||||
value: 'Value with search href',
|
||||
authorityKey: 'uuid',
|
||||
}
|
||||
);
|
||||
facetValueWithoutSearchHref = Object.assign(new FacetValue(), {
|
||||
value: 'Value without search href'
|
||||
});
|
||||
@@ -34,6 +40,10 @@ describe('Search Utils', () => {
|
||||
expect(getFacetValueForType(facetValueWithSearchHref, searchFilterConfig)).toEqual('Value with search href,operator');
|
||||
});
|
||||
|
||||
it('should retrieve the correct value from the Facet', () => {
|
||||
expect(getFacetValueForType(facetValueWithSearchHrefAuthority, searchFilterConfig)).toEqual('uuid,authority');
|
||||
});
|
||||
|
||||
it('should return the facet value with an equals operator by default', () => {
|
||||
expect(getFacetValueForType(facetValueWithoutSearchHref, searchFilterConfig)).toEqual('Value without search href,equals');
|
||||
});
|
||||
|
@@ -16,6 +16,10 @@ export function getFacetValueForType(facetValue: FacetValue, searchFilterConfig:
|
||||
return values[1];
|
||||
}
|
||||
}
|
||||
if (facetValue.authorityKey) {
|
||||
return addOperatorToFilterValue(facetValue.authorityKey, 'authority');
|
||||
}
|
||||
|
||||
return addOperatorToFilterValue(facetValue.value, 'equals');
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user