mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-10 11:33:04 +00:00
Use the item's HALLink to get the access status
This commit is contained in:
@@ -164,6 +164,7 @@ import { CoreState } from './core-state.model';
|
||||
import { GroupDataService } from './eperson/group-data.service';
|
||||
import { SubmissionAccessesModel } from './config/models/config-submission-accesses.model';
|
||||
import { AccessStatusObject } from '../shared/object-list/access-status-badge/access-status.model';
|
||||
import { AccessStatusDataService } from './data/access-status-data.service';
|
||||
|
||||
/**
|
||||
* When not in production, endpoint responses can be mocked for testing purposes
|
||||
@@ -221,6 +222,7 @@ const PROVIDERS = [
|
||||
MyDSpaceResponseParsingService,
|
||||
ServerResponseService,
|
||||
BrowseService,
|
||||
AccessStatusDataService,
|
||||
SubmissionCcLicenseDataService,
|
||||
SubmissionCcLicenseUrlDataService,
|
||||
SubmissionFormsConfigService,
|
||||
|
45
src/app/core/data/access-status-data.service.ts
Normal file
45
src/app/core/data/access-status-data.service.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||
import { dataService } from '../cache/builders/build-decorators';
|
||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||
import { DataService } from './data.service';
|
||||
import { RequestService } from './request.service';
|
||||
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||
import { CoreState } from '../core-state.model';
|
||||
import { AccessStatusObject } from 'src/app/shared/object-list/access-status-badge/access-status.model';
|
||||
import { ACCESS_STATUS } from 'src/app/shared/object-list/access-status-badge/access-status.resource-type';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RemoteData } from './remote-data';
|
||||
import { Item } from '../shared/item.model';
|
||||
|
||||
@Injectable()
|
||||
@dataService(ACCESS_STATUS)
|
||||
export class AccessStatusDataService extends DataService<AccessStatusObject> {
|
||||
|
||||
protected linkPath = 'accessStatus';
|
||||
|
||||
constructor(
|
||||
protected comparator: DefaultChangeAnalyzer<AccessStatusObject>,
|
||||
protected halService: HALEndpointService,
|
||||
protected http: HttpClient,
|
||||
protected notificationsService: NotificationsService,
|
||||
protected objectCache: ObjectCacheService,
|
||||
protected rdbService: RemoteDataBuildService,
|
||||
protected requestService: RequestService,
|
||||
protected store: Store<CoreState>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@link RemoteData} of {@link AccessStatusObject} that is the access status of the given item
|
||||
* @param item Item we want the access status of
|
||||
*/
|
||||
findAccessStatusFor(item: Item): Observable<RemoteData<AccessStatusObject>> {
|
||||
return this.findByHref(item._links.accessStatus.href);
|
||||
}
|
||||
}
|
@@ -36,7 +36,6 @@ import { sendRequest } from '../shared/request.operators';
|
||||
import { RestRequest } from './rest-request.model';
|
||||
import { CoreState } from '../core-state.model';
|
||||
import { FindListOptions } from './find-list-options.model';
|
||||
import { AccessStatusObject } from 'src/app/shared/object-list/access-status-badge/access-status.model';
|
||||
|
||||
@Injectable()
|
||||
@dataService(ITEM)
|
||||
@@ -292,33 +291,6 @@ export class ItemDataService extends DataService<Item> {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the endpoint for an item's access status
|
||||
* @param itemId
|
||||
*/
|
||||
public getAccessStatusEndpoint(itemId: string): Observable<string> {
|
||||
return this.halService.getEndpoint(this.linkPath).pipe(
|
||||
switchMap((url: string) => this.halService.getEndpoint('accessStatus', `${url}/${itemId}`))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the the access status
|
||||
* @param itemId
|
||||
*/
|
||||
public getAccessStatus(itemId: string): Observable<RemoteData<AccessStatusObject>> {
|
||||
const hrefObs = this.getAccessStatusEndpoint(itemId);
|
||||
|
||||
hrefObs.pipe(
|
||||
take(1)
|
||||
).subscribe((href) => {
|
||||
const request = new GetRequest(this.requestService.generateRequestId(), href);
|
||||
this.requestService.send(request);
|
||||
});
|
||||
|
||||
return this.rdbService.buildSingle<AccessStatusObject>(hrefObs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidate the cache of the item
|
||||
* @param itemUUID
|
||||
|
@@ -21,6 +21,8 @@ import { Version } from './version.model';
|
||||
import { VERSION } from './version.resource-type';
|
||||
import { BITSTREAM } from './bitstream.resource-type';
|
||||
import { Bitstream } from './bitstream.model';
|
||||
import { ACCESS_STATUS } from 'src/app/shared/object-list/access-status-badge/access-status.resource-type';
|
||||
import { AccessStatusObject } from 'src/app/shared/object-list/access-status-badge/access-status.model';
|
||||
|
||||
/**
|
||||
* Class representing a DSpace Item
|
||||
@@ -72,6 +74,7 @@ export class Item extends DSpaceObject implements ChildHALResource {
|
||||
templateItemOf: HALLink;
|
||||
version: HALLink;
|
||||
thumbnail: HALLink;
|
||||
accessStatus: HALLink;
|
||||
self: HALLink;
|
||||
};
|
||||
|
||||
@@ -110,6 +113,13 @@ export class Item extends DSpaceObject implements ChildHALResource {
|
||||
@link(BITSTREAM, false, 'thumbnail')
|
||||
thumbnail?: Observable<RemoteData<Bitstream>>;
|
||||
|
||||
/**
|
||||
* The access status for this Item
|
||||
* Will be undefined unless the access status {@link HALLink} has been resolved.
|
||||
*/
|
||||
@link(ACCESS_STATUS)
|
||||
accessStatus?: Observable<RemoteData<AccessStatusObject>>;
|
||||
|
||||
/**
|
||||
* Method that returns as which type of object this object should be rendered
|
||||
*/
|
||||
|
@@ -18,7 +18,7 @@
|
||||
</span>
|
||||
<div class="card-body">
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-access-status-badge [uuid]="dso.uuid"></ds-access-status-badge>
|
||||
<ds-access-status-badge [item]="dso"></ds-access-status-badge>
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="3" type="h4">
|
||||
<h4 class="card-title" [innerHTML]="firstMetadataValue('dc.title')"></h4>
|
||||
</ds-truncatable-part>
|
||||
|
@@ -1,11 +1,11 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { getFirstCompletedRemoteData } from 'src/app/core/shared/operators';
|
||||
import { ItemDataService } from 'src/app/core/data/item-data.service';
|
||||
import { AccessStatusObject } from './access-status.model';
|
||||
import { hasValue } from '../../empty.util';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { Item } from 'src/app/core/shared/item.model';
|
||||
import { AccessStatusDataService } from 'src/app/core/data/access-status-data.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-access-status-badge',
|
||||
@@ -16,7 +16,7 @@ import { environment } from 'src/environments/environment';
|
||||
*/
|
||||
export class AccessStatusBadgeComponent {
|
||||
|
||||
@Input() uuid: string;
|
||||
@Input() item: Item;
|
||||
accessStatus$: Observable<string>;
|
||||
|
||||
/**
|
||||
@@ -27,16 +27,21 @@ export class AccessStatusBadgeComponent {
|
||||
/**
|
||||
* Initialize instance variables
|
||||
*
|
||||
* @param {ItemDataService} itemDataService
|
||||
* @param {AccessStatusDataService} accessStatusDataService
|
||||
*/
|
||||
constructor(private itemDataService: ItemDataService) { }
|
||||
constructor(private accessStatusDataService: AccessStatusDataService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.showAccessStatus = environment.item.showAccessStatuses;
|
||||
this.accessStatus$ = this.itemDataService
|
||||
.getAccessStatus(this.uuid)
|
||||
.pipe(
|
||||
getFirstCompletedRemoteData(),
|
||||
if (!this.showAccessStatus || this.item == null) {
|
||||
// Do not show the badge if the feature is inactive or if the item is null.
|
||||
return;
|
||||
}
|
||||
if (this.item.accessStatus == null) {
|
||||
// In case the access status has not been loaded, do it individually.
|
||||
this.item.accessStatus = this.accessStatusDataService.findAccessStatusFor(this.item);
|
||||
}
|
||||
this.accessStatus$ = this.item.accessStatus.pipe(
|
||||
map((accessStatusRD) => {
|
||||
if (accessStatusRD.statusCode !== 401 && hasValue(accessStatusRD.payload)) {
|
||||
return accessStatusRD.payload;
|
||||
|
@@ -4,7 +4,7 @@
|
||||
</ng-container>
|
||||
<div class="d-flex">
|
||||
<ds-type-badge [object]="item"></ds-type-badge>
|
||||
<ds-access-status-badge [uuid]="item.uuid" class="pl-1"></ds-access-status-badge>
|
||||
<ds-access-status-badge [item]="item" class="pl-1"></ds-access-status-badge>
|
||||
</div>
|
||||
<ds-truncatable [id]="item.id">
|
||||
<h3 [innerHTML]="item.firstMetadataValue('dc.title') || ('mydspace.results.no-title' | translate)" [ngClass]="{'lead': true,'text-muted': !item.firstMetadataValue('dc.title')}"></h3>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<div class="d-flex">
|
||||
<ds-type-badge *ngIf="showLabel" [object]="dso"></ds-type-badge>
|
||||
<ds-access-status-badge [uuid]="dso.uuid" class="pl-1"></ds-access-status-badge>
|
||||
<ds-access-status-badge [item]="dso" class="pl-1"></ds-access-status-badge>
|
||||
</div>
|
||||
|
||||
<ds-truncatable [id]="dso.id" *ngIf="object !== undefined && object !== null">
|
||||
|
@@ -31,6 +31,7 @@ import { ViewMode } from '../../core/shared/view-mode.model';
|
||||
import { SelectionConfig } from './search-results/search-results.component';
|
||||
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
||||
import { CollectionElementLinkType } from '../object-collection/collection-element-link.type';
|
||||
import { environment } from 'src/environments/environment';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search',
|
||||
@@ -355,7 +356,8 @@ export class SearchComponent implements OnInit {
|
||||
undefined,
|
||||
this.useCachedVersionIfAvailable,
|
||||
true,
|
||||
followLink<Item>('thumbnail', { isOptional: true })
|
||||
followLink<Item>('thumbnail', { isOptional: true }),
|
||||
followLink<Item>('accessStatus', { isOptional: true, shouldEmbed: environment.item.showAccessStatuses })
|
||||
).pipe(getFirstCompletedRemoteData())
|
||||
.subscribe((results: RemoteData<SearchObjects<DSpaceObject>>) => {
|
||||
if (results.hasSucceeded && results.payload?.page?.length > 0) {
|
||||
|
Reference in New Issue
Block a user