mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
itermediate commit
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs';
|
import { Observable, of as observableOf, throwError as observableThrowError } from 'rxjs';
|
||||||
import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators';
|
import { distinctUntilChanged, filter, map, mergeMap, tap } from 'rxjs/operators';
|
||||||
import { Inject, Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
import { EPersonDataService } from '../eperson/eperson-data.service';
|
||||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
import { GLOBAL_CONFIG } from '../../../config';
|
import { GLOBAL_CONFIG } from '../../../config';
|
||||||
|
@@ -8,6 +8,7 @@ import { distinctUntilChanged, filter, map, startWith, switchMap, take, withLate
|
|||||||
import { RouterReducerState } from '@ngrx/router-store';
|
import { RouterReducerState } from '@ngrx/router-store';
|
||||||
import { select, Store } from '@ngrx/store';
|
import { select, Store } from '@ngrx/store';
|
||||||
import { CookieAttributes } from 'js-cookie';
|
import { CookieAttributes } from 'js-cookie';
|
||||||
|
import { followLink } from '../../shared/utils/follow-link-config.model';
|
||||||
|
|
||||||
import { EPerson } from '../eperson/models/eperson.model';
|
import { EPerson } from '../eperson/models/eperson.model';
|
||||||
import { AuthRequestService } from './auth-request.service';
|
import { AuthRequestService } from './auth-request.service';
|
||||||
@@ -133,7 +134,7 @@ export class AuthService {
|
|||||||
headers = headers.append('Authorization', `Bearer ${token.accessToken}`);
|
headers = headers.append('Authorization', `Bearer ${token.accessToken}`);
|
||||||
options.headers = headers;
|
options.headers = headers;
|
||||||
return this.authRequestService.getRequest('status', options).pipe(
|
return this.authRequestService.getRequest('status', options).pipe(
|
||||||
map((status) => this.rdbService.build(status)),
|
map((status) => this.rdbService.build(status, followLink<AuthStatus>('eperson'))),
|
||||||
switchMap((status: AuthStatus) => {
|
switchMap((status: AuthStatus) => {
|
||||||
if (status.authenticated) {
|
if (status.authenticated) {
|
||||||
return status.eperson.pipe(map((eperson) => eperson.payload));
|
return status.eperson.pipe(map((eperson) => eperson.payload));
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { link } from '../../cache/builders/build-decorators';
|
||||||
import { HALLink } from '../../shared/hal-link.model';
|
import { HALLink } from '../../shared/hal-link.model';
|
||||||
import { AuthError } from './auth-error.model';
|
import { AuthError } from './auth-error.model';
|
||||||
import { AuthTokenInfo } from './auth-token-info.model';
|
import { AuthTokenInfo } from './auth-token-info.model';
|
||||||
@@ -41,6 +42,7 @@ export class AuthStatus implements CacheableObject {
|
|||||||
/**
|
/**
|
||||||
* The eperson of this auth status
|
* The eperson of this auth status
|
||||||
*/
|
*/
|
||||||
|
@link(EPerson)
|
||||||
eperson: Observable<RemoteData<EPerson>>;
|
eperson: Observable<RemoteData<EPerson>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,5 +57,6 @@ export class AuthStatus implements CacheableObject {
|
|||||||
|
|
||||||
_links: {
|
_links: {
|
||||||
self: HALLink;
|
self: HALLink;
|
||||||
|
eperson: HALLink
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -35,7 +35,7 @@ export class NormalizedAuthStatus extends NormalizedObject<AuthStatus> {
|
|||||||
/**
|
/**
|
||||||
* The self link to the eperson of this auth status
|
* The self link to the eperson of this auth status
|
||||||
*/
|
*/
|
||||||
@relationship(EPerson, false)
|
@relationship(EPerson, false, false)
|
||||||
@autoserialize
|
@autoserialize
|
||||||
eperson: string;
|
eperson: string;
|
||||||
}
|
}
|
||||||
|
18
src/app/core/cache/builders/build-decorators.ts
vendored
18
src/app/core/cache/builders/build-decorators.ts
vendored
@@ -137,7 +137,8 @@ export function getResolvedLinks(target: any) {
|
|||||||
export class LinkDefinition<T extends HALResource> {
|
export class LinkDefinition<T extends HALResource> {
|
||||||
targetConstructor: GenericConstructor<CacheableObject>;
|
targetConstructor: GenericConstructor<CacheableObject>;
|
||||||
isList = false;
|
isList = false;
|
||||||
linkName?: keyof T['_links'];
|
linkName: keyof T['_links'];
|
||||||
|
propertyName: keyof T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const link = <T extends HALResource>(
|
export const link = <T extends HALResource>(
|
||||||
@@ -145,7 +146,9 @@ export const link = <T extends HALResource>(
|
|||||||
isList = false,
|
isList = false,
|
||||||
linkName?: keyof T['_links'],
|
linkName?: keyof T['_links'],
|
||||||
) => {
|
) => {
|
||||||
return (target: T, key: string) => {
|
console.log('link call', targetConstructor, isList, linkName);
|
||||||
|
return (target: T, propertyName: string) => {
|
||||||
|
console.log('link return', targetConstructor, isList, linkName, target, propertyName);
|
||||||
let targetMap = linkMap.get(target.constructor);
|
let targetMap = linkMap.get(target.constructor);
|
||||||
|
|
||||||
if (hasNoValue(targetMap)) {
|
if (hasNoValue(targetMap)) {
|
||||||
@@ -153,24 +156,25 @@ export const link = <T extends HALResource>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (hasNoValue(linkName)) {
|
if (hasNoValue(linkName)) {
|
||||||
linkName = key;
|
linkName = propertyName as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
targetMap.set(key, {
|
targetMap.set(propertyName, {
|
||||||
targetConstructor,
|
targetConstructor,
|
||||||
isList,
|
isList,
|
||||||
linkName
|
linkName,
|
||||||
|
propertyName
|
||||||
});
|
});
|
||||||
|
|
||||||
linkMap.set(target.constructor, targetMap);
|
linkMap.set(target.constructor, targetMap);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLinks = <T extends HALResource>(source: GenericConstructor<T>): Map<keyof T['_links'], LinkDefinition<T>> => {
|
export const getLinkDefinitions = <T extends HALResource>(source: GenericConstructor<T>): Map<keyof T['_links'], LinkDefinition<T>> => {
|
||||||
return linkMap.get(source);
|
return linkMap.get(source);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLink = <T extends HALResource>(source: GenericConstructor<T>, linkName: keyof T['_links']): LinkDefinition<T> => {
|
export const getLinkDefinition = <T extends HALResource>(source: GenericConstructor<T>, linkName: keyof T['_links']): LinkDefinition<T> => {
|
||||||
const sourceMap = linkMap.get(source);
|
const sourceMap = linkMap.get(source);
|
||||||
if (hasValue(sourceMap)) {
|
if (hasValue(sourceMap)) {
|
||||||
return sourceMap.get(linkName);
|
return sourceMap.get(linkName);
|
||||||
|
@@ -1,74 +0,0 @@
|
|||||||
import { Injector } from '@angular/core';
|
|
||||||
import { Observable } from 'rxjs/internal/Observable';
|
|
||||||
import { BitstreamDataService } from '../../data/bitstream-data.service';
|
|
||||||
import { CollectionDataService } from '../../data/collection-data.service';
|
|
||||||
import { PaginatedList } from '../../data/paginated-list';
|
|
||||||
import { RemoteData } from '../../data/remote-data';
|
|
||||||
import { ResourcePolicyService } from '../../data/resource-policy.service';
|
|
||||||
import { Bitstream } from '../../shared/bitstream.model';
|
|
||||||
import { Collection } from '../../shared/collection.model';
|
|
||||||
import { Item } from '../../shared/item.model';
|
|
||||||
import { ResourcePolicy } from '../../shared/resource-policy.model';
|
|
||||||
|
|
||||||
export const getCollectionBuilder = (parentInjector: Injector, collection: Collection) => {
|
|
||||||
const injector = Injector.create({
|
|
||||||
providers:[
|
|
||||||
{
|
|
||||||
provide: CollectionBuilder,
|
|
||||||
useClass: CollectionBuilder,
|
|
||||||
deps:[
|
|
||||||
CollectionDataService
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
parent: parentInjector
|
|
||||||
});
|
|
||||||
return injector.get(CollectionBuilder).initWithCollection(collection);
|
|
||||||
};
|
|
||||||
|
|
||||||
export class CollectionBuilder {
|
|
||||||
private collection: Collection;
|
|
||||||
private logo: Observable<RemoteData<Bitstream>>;
|
|
||||||
// private license: Observable<RemoteData<License>>;
|
|
||||||
private defaultAccessConditions: Observable<RemoteData<PaginatedList<ResourcePolicy>>>;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
protected collectionDataService: CollectionDataService,
|
|
||||||
protected bitstreamDataService: BitstreamDataService,
|
|
||||||
protected resourcePolicyService: ResourcePolicyService,
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
initWithCollection(collection: Collection): CollectionBuilder {
|
|
||||||
this.collection = collection;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadLogo(item: Item): CollectionBuilder {
|
|
||||||
// this.logo = this.bitstreamDataService.getLogoFor(this.collection);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadDefaultAccessConditions(item: Item): CollectionBuilder {
|
|
||||||
this.defaultAccessConditions = this.resourcePolicyService.getDefaultAccessConditionsFor(this.collection);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* As far as I can tell, the rest api doesn't support licenses yet.
|
|
||||||
* So I'm keeping this commented out
|
|
||||||
*/
|
|
||||||
// loadLicense(): CollectionBuilder {
|
|
||||||
// this.license = this.bitstreamDataService.getLicenseFor(this.collection);
|
|
||||||
// return this;
|
|
||||||
// }
|
|
||||||
|
|
||||||
build(): Collection {
|
|
||||||
const collection = this.collection;
|
|
||||||
collection.logo = this.logo;
|
|
||||||
// collection.license = this.license;
|
|
||||||
collection.defaultAccessConditions = this.defaultAccessConditions;
|
|
||||||
return collection;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
57
src/app/core/cache/builders/link.service.ts
vendored
Normal file
57
src/app/core/cache/builders/link.service.ts
vendored
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import { Injectable, Injector } from '@angular/core';
|
||||||
|
import { hasNoValue, isNotEmpty } from '../../../shared/empty.util';
|
||||||
|
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
||||||
|
import { GenericConstructor } from '../../shared/generic-constructor';
|
||||||
|
import { HALResource } from '../../shared/hal-resource.model';
|
||||||
|
import { getDataServiceFor, getLinkDefinition, getLinkDefinitions, LinkDefinition } from './build-decorators';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class LinkService {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected parentInjector: Injector,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public resolveLink<T extends HALResource>(model, linkToFollow: FollowLinkConfig<T>) {
|
||||||
|
const matchingLinkDef = getLinkDefinition(model.constructor, linkToFollow.name);
|
||||||
|
|
||||||
|
if (hasNoValue(matchingLinkDef)) {
|
||||||
|
throw new Error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`);
|
||||||
|
} else {
|
||||||
|
const provider = getDataServiceFor(matchingLinkDef.targetConstructor);
|
||||||
|
|
||||||
|
if (hasNoValue(provider)) {
|
||||||
|
throw new Error(`The @link() for ${linkToFollow.name} on ${model.constructor.name} models refers to a ${matchingLinkDef.targetConstructor.name}, but there is no service with an @dataService(${matchingLinkDef.targetConstructor.name}) annotation in order to retrieve it`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const service = Injector.create({
|
||||||
|
providers: [],
|
||||||
|
parent: this.parentInjector
|
||||||
|
}).get(provider);
|
||||||
|
|
||||||
|
const href = model._links[matchingLinkDef.linkName].href;
|
||||||
|
|
||||||
|
if (matchingLinkDef.isList) {
|
||||||
|
model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow);
|
||||||
|
} else {
|
||||||
|
model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove any resolved links that the model may have.
|
||||||
|
*/
|
||||||
|
public removeResolvedLinks<T extends HALResource>(model: T) {
|
||||||
|
const linkDefs = getLinkDefinitions(model.constructor as GenericConstructor<T>);
|
||||||
|
if (isNotEmpty(linkDefs)) {
|
||||||
|
linkDefs.forEach((linkDef: LinkDefinition<T>) => {
|
||||||
|
model[linkDef.propertyName] = undefined;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
combineLatest as observableCombineLatest,
|
combineLatest as observableCombineLatest,
|
||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
of as observableOf,
|
of as observableOf,
|
||||||
race as observableRace
|
race as observableRace
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { distinctUntilChanged, flatMap, map, startWith, switchMap, tap } from 'rxjs/operators';
|
import { distinctUntilChanged, map, startWith, switchMap } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
hasNoValue,
|
hasNoValue,
|
||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
isNotEmpty,
|
isNotEmpty,
|
||||||
isNotUndefined
|
isNotUndefined
|
||||||
} from '../../../shared/empty.util';
|
} from '../../../shared/empty.util';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
|
||||||
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
import { FollowLinkConfig } from '../../../shared/utils/follow-link-config.model';
|
||||||
import { PaginatedList } from '../../data/paginated-list';
|
import { PaginatedList } from '../../data/paginated-list';
|
||||||
import { RemoteData } from '../../data/remote-data';
|
import { RemoteData } from '../../data/remote-data';
|
||||||
@@ -23,31 +24,24 @@ import { RemoteDataError } from '../../data/remote-data-error';
|
|||||||
import { GetRequest } from '../../data/request.models';
|
import { GetRequest } from '../../data/request.models';
|
||||||
import { RequestEntry } from '../../data/request.reducer';
|
import { RequestEntry } from '../../data/request.reducer';
|
||||||
import { RequestService } from '../../data/request.service';
|
import { RequestService } from '../../data/request.service';
|
||||||
import { HALResource } from '../../shared/hal-resource.model';
|
|
||||||
import { NormalizedObject } from '../models/normalized-object.model';
|
|
||||||
import { ObjectCacheService } from '../object-cache.service';
|
|
||||||
import { DSOSuccessResponse, ErrorResponse } from '../response.models';
|
|
||||||
import {
|
|
||||||
getDataServiceFor, getLink,
|
|
||||||
getLinks,
|
|
||||||
getMapsTo,
|
|
||||||
getRelationMetadata,
|
|
||||||
getRelationships
|
|
||||||
} from './build-decorators';
|
|
||||||
import { PageInfo } from '../../shared/page-info.model';
|
|
||||||
import {
|
import {
|
||||||
filterSuccessfulResponses,
|
filterSuccessfulResponses,
|
||||||
getRequestFromRequestHref,
|
getRequestFromRequestHref,
|
||||||
getRequestFromRequestUUID,
|
getRequestFromRequestUUID,
|
||||||
getResourceLinksFromResponse
|
getResourceLinksFromResponse
|
||||||
} from '../../shared/operators';
|
} from '../../shared/operators';
|
||||||
import { CacheableObject, TypedObject } from '../object-cache.reducer';
|
import { PageInfo } from '../../shared/page-info.model';
|
||||||
import { createSuccessfulRemoteDataObject$ } from '../../../shared/testing/utils';
|
import { NormalizedObject } from '../models/normalized-object.model';
|
||||||
|
import { CacheableObject } from '../object-cache.reducer';
|
||||||
|
import { ObjectCacheService } from '../object-cache.service';
|
||||||
|
import { DSOSuccessResponse, ErrorResponse } from '../response.models';
|
||||||
|
import { getMapsTo, getRelationMetadata, getRelationships } from './build-decorators';
|
||||||
|
import { LinkService } from './link.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RemoteDataBuildService {
|
export class RemoteDataBuildService {
|
||||||
constructor(protected objectCache: ObjectCacheService,
|
constructor(protected objectCache: ObjectCacheService,
|
||||||
private parentInjector: Injector,
|
protected linkService: LinkService,
|
||||||
protected requestService: RequestService) {
|
protected requestService: RequestService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,45 +228,12 @@ export class RemoteDataBuildService {
|
|||||||
const domainModel = Object.assign(new domainModelConstructor(), normalized, halLinks);
|
const domainModel = Object.assign(new domainModelConstructor(), normalized, halLinks);
|
||||||
|
|
||||||
linksToFollow.forEach((linkToFollow: FollowLinkConfig<T>) => {
|
linksToFollow.forEach((linkToFollow: FollowLinkConfig<T>) => {
|
||||||
this.resolveLink(domainModel, linkToFollow);
|
this.linkService.resolveLink(domainModel, linkToFollow);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('domainModel._links', domainModel._links);
|
|
||||||
|
|
||||||
return domainModel;
|
return domainModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public resolveLink<T extends HALResource>(model, linkToFollow: FollowLinkConfig<T>) {
|
|
||||||
console.log('resolveLink', model, linkToFollow);
|
|
||||||
|
|
||||||
const matchingLink = getLink(model.constructor, linkToFollow.name);
|
|
||||||
|
|
||||||
if (hasNoValue(matchingLink)) {
|
|
||||||
throw new Error(`followLink('${linkToFollow.name}') was used for a ${model.constructor.name}, but there is no property on ${model.constructor.name} models with an @link() for ${linkToFollow.name}`);
|
|
||||||
} else {
|
|
||||||
const provider = getDataServiceFor(matchingLink.targetConstructor);
|
|
||||||
|
|
||||||
if (hasNoValue(provider)) {
|
|
||||||
throw new Error(`The @link() for ${linkToFollow.name} on ${model.constructor.name} models refers to a ${matchingLink.targetConstructor.name}, but there is no service with an @dataService(${matchingLink.targetConstructor.name}) annotation in order to retrieve it`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const service = Injector.create({
|
|
||||||
providers: [],
|
|
||||||
parent: this.parentInjector
|
|
||||||
}).get(provider);
|
|
||||||
|
|
||||||
const href = model._links[matchingLink.linkName].href;
|
|
||||||
|
|
||||||
if (matchingLink.isList) {
|
|
||||||
model[linkToFollow.name] = service.findAllByHref(href, linkToFollow.findListOptions, ...linkToFollow.linksToFollow);
|
|
||||||
} else {
|
|
||||||
model[linkToFollow.name] = service.findByHref(href, ...linkToFollow.linksToFollow);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`model['${linkToFollow.name}']`, model[linkToFollow.name]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aggregate<T>(input: Array<Observable<RemoteData<T>>>): Observable<RemoteData<T[]>> {
|
aggregate<T>(input: Array<Observable<RemoteData<T>>>): Observable<RemoteData<T[]>> {
|
||||||
|
|
||||||
if (isEmpty(input)) {
|
if (isEmpty(input)) {
|
||||||
|
@@ -23,14 +23,14 @@ export class NormalizedRelationship extends NormalizedObject<Relationship> {
|
|||||||
* The item to the left of this relationship
|
* The item to the left of this relationship
|
||||||
*/
|
*/
|
||||||
@deserialize
|
@deserialize
|
||||||
@relationship(Item, false)
|
@relationship(Item, false, false)
|
||||||
leftItem: string;
|
leftItem: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item to the right of this relationship
|
* The item to the right of this relationship
|
||||||
*/
|
*/
|
||||||
@deserialize
|
@deserialize
|
||||||
@relationship(Item, false)
|
@relationship(Item, false, false)
|
||||||
rightItem: string;
|
rightItem: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,7 +61,7 @@ export class NormalizedRelationship extends NormalizedObject<Relationship> {
|
|||||||
* The type of Relationship
|
* The type of Relationship
|
||||||
*/
|
*/
|
||||||
@deserialize
|
@deserialize
|
||||||
@relationship(RelationshipType, false)
|
@relationship(RelationshipType, false, false)
|
||||||
relationshipType: string;
|
relationshipType: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
7
src/app/core/cache/object-cache.service.ts
vendored
7
src/app/core/cache/object-cache.service.ts
vendored
@@ -10,6 +10,7 @@ import { coreSelector } from '../core.selectors';
|
|||||||
import { RestRequestMethod } from '../data/rest-request-method';
|
import { RestRequestMethod } from '../data/rest-request-method';
|
||||||
import { selfLinkFromUuidSelector } from '../index/index.selectors';
|
import { selfLinkFromUuidSelector } from '../index/index.selectors';
|
||||||
import { GenericConstructor } from '../shared/generic-constructor';
|
import { GenericConstructor } from '../shared/generic-constructor';
|
||||||
|
import { LinkService } from './builders/link.service';
|
||||||
import { NormalizedObject } from './models/normalized-object.model';
|
import { NormalizedObject } from './models/normalized-object.model';
|
||||||
import {
|
import {
|
||||||
AddPatchObjectCacheAction,
|
AddPatchObjectCacheAction,
|
||||||
@@ -45,7 +46,10 @@ const entryFromSelfLinkSelector =
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ObjectCacheService {
|
export class ObjectCacheService {
|
||||||
constructor(private store: Store<CoreState>) {
|
constructor(
|
||||||
|
private store: Store<CoreState>,
|
||||||
|
private linkService: LinkService
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -59,6 +63,7 @@ export class ObjectCacheService {
|
|||||||
* The UUID of the request that resulted in this object
|
* The UUID of the request that resulted in this object
|
||||||
*/
|
*/
|
||||||
add(objectToCache: CacheableObject, msToLive: number, requestUUID: string): void {
|
add(objectToCache: CacheableObject, msToLive: number, requestUUID: string): void {
|
||||||
|
this.linkService.removeResolvedLinks(objectToCache); // Ensure the object we're storing has no resolved links
|
||||||
this.store.dispatch(new AddToObjectCacheAction(objectToCache, new Date().getTime(), msToLive, requestUUID));
|
this.store.dispatch(new AddToObjectCacheAction(objectToCache, new Date().getTime(), msToLive, requestUUID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@ import { coreEffects } from './core.effects';
|
|||||||
import { coreReducers } from './core.reducers';
|
import { coreReducers } from './core.reducers';
|
||||||
|
|
||||||
import { isNotEmpty } from '../shared/empty.util';
|
import { isNotEmpty } from '../shared/empty.util';
|
||||||
|
import { EPersonDataService } from './eperson/eperson-data.service';
|
||||||
|
|
||||||
import { ApiService } from './services/api.service';
|
import { ApiService } from './services/api.service';
|
||||||
import { BrowseEntriesResponseParsingService } from './data/browse-entries-response-parsing.service';
|
import { BrowseEntriesResponseParsingService } from './data/browse-entries-response-parsing.service';
|
||||||
@@ -25,14 +26,12 @@ import { DSpaceRESTv2Service } from './dspace-rest-v2/dspace-rest-v2.service';
|
|||||||
import { FormBuilderService } from '../shared/form/builder/form-builder.service';
|
import { FormBuilderService } from '../shared/form/builder/form-builder.service';
|
||||||
import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';
|
import { SectionFormOperationsService } from '../submission/sections/form/section-form-operations.service';
|
||||||
import { FormService } from '../shared/form/form.service';
|
import { FormService } from '../shared/form/form.service';
|
||||||
import { GroupEpersonService } from './eperson/group-eperson.service';
|
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { ItemDataService } from './data/item-data.service';
|
import { ItemDataService } from './data/item-data.service';
|
||||||
import { MetadataService } from './metadata/metadata.service';
|
import { MetadataService } from './metadata/metadata.service';
|
||||||
import { ObjectCacheService } from './cache/object-cache.service';
|
import { ObjectCacheService } from './cache/object-cache.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { RemoteDataBuildService } from './cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from './cache/builders/remote-data-build.service';
|
||||||
import { RequestService } from './data/request.service';
|
|
||||||
import { EndpointMapResponseParsingService } from './data/endpoint-map-response-parsing.service';
|
import { EndpointMapResponseParsingService } from './data/endpoint-map-response-parsing.service';
|
||||||
import { ServerResponseService } from './services/server-response.service';
|
import { ServerResponseService } from './services/server-response.service';
|
||||||
import { NativeWindowFactory, NativeWindowService } from './services/window.service';
|
import { NativeWindowFactory, NativeWindowService } from './services/window.service';
|
||||||
@@ -43,6 +42,8 @@ import { RouteService } from './services/route.service';
|
|||||||
import { SubmissionDefinitionsConfigService } from './config/submission-definitions-config.service';
|
import { SubmissionDefinitionsConfigService } from './config/submission-definitions-config.service';
|
||||||
import { SubmissionFormsConfigService } from './config/submission-forms-config.service';
|
import { SubmissionFormsConfigService } from './config/submission-forms-config.service';
|
||||||
import { SubmissionSectionsConfigService } from './config/submission-sections-config.service';
|
import { SubmissionSectionsConfigService } from './config/submission-sections-config.service';
|
||||||
|
import { Relationship } from './shared/item-relationships/relationship.model';
|
||||||
|
import { Item } from './shared/item.model';
|
||||||
import { SubmissionResponseParsingService } from './submission/submission-response-parsing.service';
|
import { SubmissionResponseParsingService } from './submission/submission-response-parsing.service';
|
||||||
import { EpersonResponseParsingService } from './eperson/eperson-response-parsing.service';
|
import { EpersonResponseParsingService } from './eperson/eperson-response-parsing.service';
|
||||||
import { JsonPatchOperationsBuilder } from './json-patch/builder/json-patch-operations-builder';
|
import { JsonPatchOperationsBuilder } from './json-patch/builder/json-patch-operations-builder';
|
||||||
@@ -183,7 +184,7 @@ const PROVIDERS = [
|
|||||||
SectionFormOperationsService,
|
SectionFormOperationsService,
|
||||||
FormService,
|
FormService,
|
||||||
EpersonResponseParsingService,
|
EpersonResponseParsingService,
|
||||||
GroupEpersonService,
|
EPersonDataService,
|
||||||
HALEndpointService,
|
HALEndpointService,
|
||||||
HostWindowService,
|
HostWindowService,
|
||||||
ItemDataService,
|
ItemDataService,
|
||||||
@@ -195,7 +196,6 @@ const PROVIDERS = [
|
|||||||
BitstreamFormatDataService,
|
BitstreamFormatDataService,
|
||||||
NormalizedObjectBuildService,
|
NormalizedObjectBuildService,
|
||||||
RemoteDataBuildService,
|
RemoteDataBuildService,
|
||||||
RequestService,
|
|
||||||
EndpointMapResponseParsingService,
|
EndpointMapResponseParsingService,
|
||||||
FacetValueResponseParsingService,
|
FacetValueResponseParsingService,
|
||||||
FacetValueMapResponseParsingService,
|
FacetValueMapResponseParsingService,
|
||||||
@@ -273,6 +273,8 @@ const PROVIDERS = [
|
|||||||
*/
|
*/
|
||||||
export const normalizedModels =
|
export const normalizedModels =
|
||||||
[
|
[
|
||||||
|
Relationship,
|
||||||
|
Item,
|
||||||
NormalizedDSpaceObject,
|
NormalizedDSpaceObject,
|
||||||
NormalizedBundle,
|
NormalizedBundle,
|
||||||
NormalizedBitstream,
|
NormalizedBitstream,
|
||||||
@@ -304,7 +306,7 @@ export const normalizedModels =
|
|||||||
NormalizedRelationshipType,
|
NormalizedRelationshipType,
|
||||||
NormalizedItemType,
|
NormalizedItemType,
|
||||||
NormalizedExternalSource,
|
NormalizedExternalSource,
|
||||||
NormalizedExternalSourceEntry
|
NormalizedExternalSourceEntry,
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@@ -27,26 +27,14 @@ export abstract class BaseResponseParsingService {
|
|||||||
return this.processArray(data, request);
|
return this.processArray(data, request);
|
||||||
} else if (isRestDataObject(data)) {
|
} else if (isRestDataObject(data)) {
|
||||||
const object = this.deserialize(data);
|
const object = this.deserialize(data);
|
||||||
|
if (isNotEmpty(data._embedded)) {
|
||||||
// TODO remove
|
Object
|
||||||
// if (isNotEmpty(data._embedded)) {
|
.keys(data._embedded)
|
||||||
// Object
|
.filter((property) => data._embedded.hasOwnProperty(property))
|
||||||
// .keys(data._embedded)
|
.forEach((property) => {
|
||||||
// .filter((property) => data._embedded.hasOwnProperty(property))
|
this.process<ObjectDomain>(data._embedded[property], request);
|
||||||
// .forEach((property) => {
|
});
|
||||||
// const parsedObj = this.process<ObjectDomain>(data._embedded[property], request);
|
}
|
||||||
// if (isNotEmpty(parsedObj)) {
|
|
||||||
// if (isRestPaginatedList(data._embedded[property])) {
|
|
||||||
// object[property] = parsedObj;
|
|
||||||
// object[property].page = parsedObj.page.map((obj) => this.retrieveObjectOrUrl(obj));
|
|
||||||
// } else if (isRestDataObject(data._embedded[property])) {
|
|
||||||
// object[property] = this.retrieveObjectOrUrl(parsedObj);
|
|
||||||
// } else if (Array.isArray(parsedObj)) {
|
|
||||||
// object[property] = parsedObj.map((obj) => this.retrieveObjectOrUrl(obj))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
this.cache(object, request);
|
this.cache(object, request);
|
||||||
return object;
|
return object;
|
||||||
|
@@ -49,11 +49,6 @@ export class BitstreamDataService extends DataService<Bitstream> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBrowseEndpoint(options: FindListOptions, linkPath?: string): Observable<string> {
|
|
||||||
// TODO needed? if not, perhaps remove it from datasevice?
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the bitstreams in a given bundle
|
* Retrieves the bitstreams in a given bundle
|
||||||
*
|
*
|
||||||
|
@@ -13,7 +13,7 @@ import { HALEndpointService } from '../shared/hal-endpoint.service';
|
|||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||||
import { DeleteByIDRequest, FindListOptions, PostRequest, PutRequest } from './request.models';
|
import { DeleteByIDRequest, PostRequest, PutRequest } from './request.models';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { find, map, tap } from 'rxjs/operators';
|
import { find, map, tap } from 'rxjs/operators';
|
||||||
import { configureRequest, getResponseFromEntry } from '../shared/operators';
|
import { configureRequest, getResponseFromEntry } from '../shared/operators';
|
||||||
@@ -59,16 +59,6 @@ export class BitstreamFormatDataService extends DataService<BitstreamFormat> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the endpoint for browsing bitstream formats
|
|
||||||
* @param {FindListOptions} options
|
|
||||||
* @param {string} linkPath
|
|
||||||
* @returns {Observable<string>}
|
|
||||||
*/
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the endpoint to update an existing bitstream format
|
* Get the endpoint to update an existing bitstream format
|
||||||
* @param formatId
|
* @param formatId
|
||||||
|
@@ -14,7 +14,6 @@ import { CoreState } from '../core.reducers';
|
|||||||
import { Bundle } from '../shared/bundle.model';
|
import { Bundle } from '../shared/bundle.model';
|
||||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
import { Item } from '../shared/item.model';
|
import { Item } from '../shared/item.model';
|
||||||
import { BitstreamDataService } from './bitstream-data.service';
|
|
||||||
import { DataService } from './data.service';
|
import { DataService } from './data.service';
|
||||||
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||||
import { PaginatedList } from './paginated-list';
|
import { PaginatedList } from './paginated-list';
|
||||||
@@ -46,15 +45,6 @@ export class BundleDataService extends DataService<Bundle> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the endpoint for browsing bundles
|
|
||||||
* @param {FindListOptions} options
|
|
||||||
* @returns {Observable<string>}
|
|
||||||
*/
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
findAllByItem(item: Item, options?: FindListOptions, ...linksToFollow: Array<FollowLinkConfig<Bundle>>): Observable<RemoteData<PaginatedList<Bundle>>> {
|
findAllByItem(item: Item, options?: FindListOptions, ...linksToFollow: Array<FollowLinkConfig<Bundle>>): Observable<RemoteData<PaginatedList<Bundle>>> {
|
||||||
return this.findAllByHref(item._links.bundles.href, options, ...linksToFollow);
|
return this.findAllByHref(item._links.bundles.href, options, ...linksToFollow);
|
||||||
}
|
}
|
||||||
|
@@ -65,7 +65,15 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
*/
|
*/
|
||||||
protected responseMsToLive: number;
|
protected responseMsToLive: number;
|
||||||
|
|
||||||
public abstract getBrowseEndpoint(options: FindListOptions, linkPath?: string): Observable<string>
|
/**
|
||||||
|
* Get the endpoint for browsing
|
||||||
|
* @param options The [[FindListOptions]] object
|
||||||
|
* @param linkPath The link path for the object
|
||||||
|
* @returns {Observable<string>}
|
||||||
|
*/
|
||||||
|
getBrowseEndpoint(options: FindListOptions = {}, linkPath?: string): Observable<string> {
|
||||||
|
return this.halService.getEndpoint(this.linkPath);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the HREF with given options object
|
* Create the HREF with given options object
|
||||||
|
@@ -40,10 +40,6 @@ export class DsoRedirectDataService extends DataService<any> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
setLinkPath(identifierType: IdentifierType) {
|
setLinkPath(identifierType: IdentifierType) {
|
||||||
// The default 'pid' endpoint for identifiers does not support uuid lookups.
|
// The default 'pid' endpoint for identifiers does not support uuid lookups.
|
||||||
// For uuid lookups we need to change the linkPath.
|
// For uuid lookups we need to change the linkPath.
|
||||||
|
@@ -33,10 +33,6 @@ class DataServiceImpl extends DataService<DSpaceObject> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
getIDHref(endpoint, resourceID): string {
|
getIDHref(endpoint, resourceID): string {
|
||||||
return endpoint.replace(/\{\?uuid\}/,`?uuid=${resourceID}`);
|
return endpoint.replace(/\{\?uuid\}/,`?uuid=${resourceID}`);
|
||||||
}
|
}
|
||||||
|
@@ -34,9 +34,6 @@ class DataServiceImpl extends DataService<MetadataSchema> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(linkPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,4 +1,15 @@
|
|||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '../../app.reducer';
|
||||||
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
|
import { dataService } from '../cache/builders/build-decorators';
|
||||||
|
import { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||||
|
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||||
|
import { CoreState } from '../core.reducers';
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
import { DefaultChangeAnalyzer } from './default-change-analyzer.service';
|
||||||
|
import { ItemDataService } from './item-data.service';
|
||||||
import { RequestService } from './request.service';
|
import { RequestService } from './request.service';
|
||||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
@@ -14,15 +25,25 @@ import { isNotUndefined } from '../../shared/empty.util';
|
|||||||
import { FindListOptions, FindListRequest } from './request.models';
|
import { FindListOptions, FindListRequest } from './request.models';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The service handling all relationship requests
|
* The service handling all relationship type requests
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RelationshipTypeService {
|
@dataService(RelationshipType)
|
||||||
|
export class RelationshipTypeService extends DataService<RelationshipType> {
|
||||||
protected linkPath = 'relationshiptypes';
|
protected linkPath = 'relationshiptypes';
|
||||||
|
|
||||||
constructor(protected requestService: RequestService,
|
constructor(protected itemService: ItemDataService,
|
||||||
|
protected requestService: RequestService,
|
||||||
|
protected rdbService: RemoteDataBuildService,
|
||||||
|
protected dataBuildService: NormalizedObjectBuildService,
|
||||||
|
protected store: Store<CoreState>,
|
||||||
protected halService: HALEndpointService,
|
protected halService: HALEndpointService,
|
||||||
protected rdbService: RemoteDataBuildService) {
|
protected objectCache: ObjectCacheService,
|
||||||
|
protected notificationsService: NotificationsService,
|
||||||
|
protected http: HttpClient,
|
||||||
|
protected comparator: DefaultChangeAnalyzer<RelationshipType>,
|
||||||
|
protected appStore: Store<AppState>) {
|
||||||
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
import { followLink } from '../../shared/utils/follow-link-config.model';
|
||||||
import { dataService } from '../cache/builders/build-decorators';
|
import { dataService } from '../cache/builders/build-decorators';
|
||||||
import { MemoizedSelector, select, Store } from '@ngrx/store';
|
import { MemoizedSelector, select, Store } from '@ngrx/store';
|
||||||
import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs';
|
import { combineLatest, combineLatest as observableCombineLatest } from 'rxjs';
|
||||||
@@ -64,10 +65,6 @@ export class RelationshipService extends DataService<Relationship> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the endpoint for a relationship by ID
|
* Get the endpoint for a relationship by ID
|
||||||
* @param uuid
|
* @param uuid
|
||||||
@@ -249,7 +246,7 @@ export class RelationshipService extends DataService<Relationship> {
|
|||||||
} else {
|
} else {
|
||||||
findListOptions.searchParams = searchParams;
|
findListOptions.searchParams = searchParams;
|
||||||
}
|
}
|
||||||
return this.searchBy('byLabel', findListOptions);
|
return this.searchBy('byLabel', findListOptions, followLink('leftItem'), followLink('rightItem'), followLink('relationshipType'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -71,7 +71,9 @@ const getUuidsFromHrefSubstring = (state: IndexState, href: string): string[] =>
|
|||||||
/**
|
/**
|
||||||
* A service to interact with the request state in the store
|
* A service to interact with the request state in the store
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
export class RequestService {
|
export class RequestService {
|
||||||
private requestsOnTheirWayToTheStore: string[] = [];
|
private requestsOnTheirWayToTheStore: string[] = [];
|
||||||
|
|
||||||
|
@@ -37,9 +37,6 @@ class DataServiceImpl extends DataService<ResourcePolicy> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBrowseEndpoint(options: FindListOptions = {}, linkPath: string = this.linkPath): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(linkPath);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -11,7 +11,6 @@ import { HALEndpointService } from '../shared/hal-endpoint.service';
|
|||||||
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
import { NotificationsService } from '../../shared/notifications/notifications.service';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { DSOChangeAnalyzer } from './dso-change-analyzer.service';
|
import { DSOChangeAnalyzer } from './dso-change-analyzer.service';
|
||||||
import { FindListOptions } from './request.models';
|
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { RemoteData } from './remote-data';
|
import { RemoteData } from './remote-data';
|
||||||
@@ -26,7 +25,6 @@ import { getSucceededRemoteData } from '../shared/operators';
|
|||||||
@dataService(Site)
|
@dataService(Site)
|
||||||
export class SiteDataService extends DataService<Site> {
|
export class SiteDataService extends DataService<Site> {
|
||||||
protected linkPath = 'sites';
|
protected linkPath = 'sites';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
@@ -42,15 +40,6 @@ export class SiteDataService extends DataService<Site> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the endpoint for browsing the site object
|
|
||||||
* @param {FindListOptions} options
|
|
||||||
* @param {Observable<string>} linkPath
|
|
||||||
*/
|
|
||||||
getBrowseEndpoint(options: FindListOptions, linkPath?: string): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the Site Object
|
* Retrieve the Site Object
|
||||||
*/
|
*/
|
||||||
|
36
src/app/core/eperson/eperson-data.service.ts
Normal file
36
src/app/core/eperson/eperson-data.service.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
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 { NormalizedObjectBuildService } from '../cache/builders/normalized-object-build.service';
|
||||||
|
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
|
||||||
|
import { ObjectCacheService } from '../cache/object-cache.service';
|
||||||
|
import { CoreState } from '../core.reducers';
|
||||||
|
import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
|
||||||
|
import { DataService } from '../data/data.service';
|
||||||
|
import { RequestService } from '../data/request.service';
|
||||||
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
|
import { EPerson } from './models/eperson.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
@dataService(EPerson)
|
||||||
|
export class EPersonDataService extends DataService<EPerson> {
|
||||||
|
|
||||||
|
protected linkPath: 'eperson/epersons';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected requestService: RequestService,
|
||||||
|
protected rdbService: RemoteDataBuildService,
|
||||||
|
protected dataBuildService: NormalizedObjectBuildService,
|
||||||
|
protected store: Store<CoreState>,
|
||||||
|
protected objectCache: ObjectCacheService,
|
||||||
|
protected halService: HALEndpointService,
|
||||||
|
protected notificationsService: NotificationsService,
|
||||||
|
protected http: HttpClient,
|
||||||
|
protected comparator: DSOChangeAnalyzer<EPerson>
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,14 +0,0 @@
|
|||||||
import { Observable } from 'rxjs';
|
|
||||||
import { FindListOptions } from '../data/request.models';
|
|
||||||
import { DataService } from '../data/data.service';
|
|
||||||
import { CacheableObject } from '../cache/object-cache.reducer';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An abstract class that provides methods to make HTTP request to eperson endpoint.
|
|
||||||
*/
|
|
||||||
export abstract class EpersonService<TDomain extends CacheableObject> extends DataService<TDomain> {
|
|
||||||
|
|
||||||
public getBrowseEndpoint(options: FindListOptions): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -4,8 +4,9 @@ import { HttpClient } from '@angular/common/http';
|
|||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { filter, map, take } from 'rxjs/operators';
|
import { filter, map, take } from 'rxjs/operators';
|
||||||
|
import { DataService } from '../data/data.service';
|
||||||
|
|
||||||
import { EpersonService } from './eperson.service';
|
import { EPersonDataService } from './eperson-data.service';
|
||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
import { FindListOptions } from '../data/request.models';
|
import { FindListOptions } from '../data/request.models';
|
||||||
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
import { HALEndpointService } from '../shared/hal-endpoint.service';
|
||||||
@@ -23,9 +24,11 @@ import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
|
|||||||
/**
|
/**
|
||||||
* Provides methods to retrieve eperson group resources.
|
* Provides methods to retrieve eperson group resources.
|
||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable({
|
||||||
export class GroupEpersonService extends EpersonService<Group> {
|
providedIn: 'root'
|
||||||
protected linkPath = 'groups';
|
})
|
||||||
|
export class GroupDataService extends DataService<Group> {
|
||||||
|
protected linkPath = 'eperson/groups';
|
||||||
protected browseEndpoint = '';
|
protected browseEndpoint = '';
|
||||||
|
|
||||||
constructor(
|
constructor(
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { HALLink } from './hal-link.model';
|
||||||
import { MetadataMap } from './metadata.models';
|
import { MetadataMap } from './metadata.models';
|
||||||
import { ResourceType } from './resource-type';
|
import { ResourceType } from './resource-type';
|
||||||
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
import { ListableObject } from '../../shared/object-collection/shared/listable-object.model';
|
||||||
@@ -39,6 +40,10 @@ export class ExternalSourceEntry extends ListableObject {
|
|||||||
*/
|
*/
|
||||||
self: string;
|
self: string;
|
||||||
|
|
||||||
|
_links: {
|
||||||
|
self: HALLink;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method that returns as which type of object this object should be rendered
|
* Method that returns as which type of object this object should be rendered
|
||||||
*/
|
*/
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import { HALLink } from './hal-link.model';
|
||||||
import { ResourceType } from './resource-type';
|
import { ResourceType } from './resource-type';
|
||||||
import { CacheableObject } from '../cache/object-cache.reducer';
|
import { CacheableObject } from '../cache/object-cache.reducer';
|
||||||
|
|
||||||
@@ -26,4 +27,8 @@ export class ExternalSource extends CacheableObject {
|
|||||||
* The link to the rest endpoint where this External Source can be found
|
* The link to the rest endpoint where this External Source can be found
|
||||||
*/
|
*/
|
||||||
self: string;
|
self: string;
|
||||||
|
|
||||||
|
_links: {
|
||||||
|
self: HALLink;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,6 +31,8 @@ export class Relationship implements CacheableObject {
|
|||||||
/**
|
/**
|
||||||
* The item to the left of this relationship
|
* The item to the left of this relationship
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// TODO it's likely a circular dependency 😒 -> https://stackoverflow.com/questions/35240716/webpack-import-returns-undefined-depending-on-the-order-of-imports
|
||||||
@link(Item)
|
@link(Item)
|
||||||
leftItem?: Observable<RemoteData<Item>>;
|
leftItem?: Observable<RemoteData<Item>>;
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import { link } from '../cache/builders/build-decorators';
|
|||||||
import { PaginatedList } from '../data/paginated-list';
|
import { PaginatedList } from '../data/paginated-list';
|
||||||
import { RemoteData } from '../data/remote-data';
|
import { RemoteData } from '../data/remote-data';
|
||||||
import { Bundle } from './bundle.model';
|
import { Bundle } from './bundle.model';
|
||||||
|
import { Collection } from './collection.model';
|
||||||
|
|
||||||
import { DSpaceObject } from './dspace-object.model';
|
import { DSpaceObject } from './dspace-object.model';
|
||||||
import { GenericConstructor } from './generic-constructor';
|
import { GenericConstructor } from './generic-constructor';
|
||||||
@@ -44,6 +45,12 @@ export class Item extends DSpaceObject {
|
|||||||
*/
|
*/
|
||||||
isWithdrawn: boolean;
|
isWithdrawn: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Collection that owns this Item
|
||||||
|
*/
|
||||||
|
@link(Collection)
|
||||||
|
owningCollection: Observable<RemoteData<Collection>>;
|
||||||
|
|
||||||
@link(Bundle, true)
|
@link(Bundle, true)
|
||||||
bundles: Observable<RemoteData<PaginatedList<Bundle>>>;
|
bundles: Observable<RemoteData<PaginatedList<Bundle>>>;
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ import { Injectable, OnDestroy } from '@angular/core';
|
|||||||
import { NavigationExtras, Router } from '@angular/router';
|
import { NavigationExtras, Router } from '@angular/router';
|
||||||
import { first, map, switchMap, tap } from 'rxjs/operators';
|
import { first, map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
import { followLink } from '../../../shared/utils/follow-link-config.model';
|
||||||
|
import { LinkService } from '../../cache/builders/link.service';
|
||||||
import { FacetConfigSuccessResponse, FacetValueSuccessResponse, SearchSuccessResponse } from '../../cache/response.models';
|
import { FacetConfigSuccessResponse, FacetValueSuccessResponse, SearchSuccessResponse } from '../../cache/response.models';
|
||||||
import { PaginatedList } from '../../data/paginated-list';
|
import { PaginatedList } from '../../data/paginated-list';
|
||||||
import { ResponseParsingService } from '../../data/parsing.service';
|
import { ResponseParsingService } from '../../data/parsing.service';
|
||||||
@@ -70,6 +71,7 @@ export class SearchService implements OnDestroy {
|
|||||||
private routeService: RouteService,
|
private routeService: RouteService,
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
private rdb: RemoteDataBuildService,
|
private rdb: RemoteDataBuildService,
|
||||||
|
private linkService: LinkService,
|
||||||
private halService: HALEndpointService,
|
private halService: HALEndpointService,
|
||||||
private communityService: CommunityDataService,
|
private communityService: CommunityDataService,
|
||||||
private dspaceObjectService: DSpaceObjectDataService
|
private dspaceObjectService: DSpaceObjectDataService
|
||||||
@@ -341,8 +343,8 @@ export class SearchService implements OnDestroy {
|
|||||||
switchMap((dsoRD: RemoteData<DSpaceObject>) => {
|
switchMap((dsoRD: RemoteData<DSpaceObject>) => {
|
||||||
if ((dsoRD.payload as any).type === Community.type.value) {
|
if ((dsoRD.payload as any).type === Community.type.value) {
|
||||||
const community: Community = dsoRD.payload as Community;
|
const community: Community = dsoRD.payload as Community;
|
||||||
this.rdb.resolveLink(community, followLink('subcommunities'));
|
this.linkService.resolveLink(community, followLink('subcommunities'));
|
||||||
this.rdb.resolveLink(community, followLink('collections'));
|
this.linkService.resolveLink(community, followLink('collections'));
|
||||||
return observableCombineLatest(community.subcommunities, community.collections).pipe(
|
return observableCombineLatest(community.subcommunities, community.collections).pipe(
|
||||||
map(([subCommunities, collections]) => {
|
map(([subCommunities, collections]) => {
|
||||||
/*if this is a community, we also need to show the direct children*/
|
/*if this is a community, we also need to show the direct children*/
|
||||||
|
@@ -37,8 +37,4 @@ export class WorkflowItemDataService extends DataService<WorkflowItem> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getBrowseEndpoint(options: FindListOptions) {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -37,8 +37,4 @@ export class WorkspaceitemDataService extends DataService<WorkspaceItem> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public getBrowseEndpoint(options: FindListOptions) {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -18,10 +18,6 @@ import { CacheableObject } from '../cache/object-cache.reducer';
|
|||||||
*/
|
*/
|
||||||
export abstract class TasksService<T extends CacheableObject> extends DataService<T> {
|
export abstract class TasksService<T extends CacheableObject> extends DataService<T> {
|
||||||
|
|
||||||
public getBrowseEndpoint(options: FindListOptions): Observable<string> {
|
|
||||||
return this.halService.getEndpoint(this.linkPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a RestRequest
|
* Fetch a RestRequest
|
||||||
*
|
*
|
||||||
|
@@ -2,7 +2,7 @@ import { Component, Input, OnInit } from '@angular/core';
|
|||||||
|
|
||||||
import { find } from 'rxjs/operators';
|
import { find } from 'rxjs/operators';
|
||||||
|
|
||||||
import { GroupEpersonService } from '../../../../core/eperson/group-eperson.service';
|
import { GroupDataService } from '../../../../core/eperson/group-data.service';
|
||||||
import { ResourcePolicy } from '../../../../core/shared/resource-policy.model';
|
import { ResourcePolicy } from '../../../../core/shared/resource-policy.model';
|
||||||
import { isEmpty } from '../../../../shared/empty.util';
|
import { isEmpty } from '../../../../shared/empty.util';
|
||||||
import { Group } from '../../../../core/eperson/models/group.model';
|
import { Group } from '../../../../core/eperson/models/group.model';
|
||||||
@@ -32,9 +32,9 @@ export class SubmissionSectionUploadAccessConditionsComponent implements OnInit
|
|||||||
/**
|
/**
|
||||||
* Initialize instance variables
|
* Initialize instance variables
|
||||||
*
|
*
|
||||||
* @param {GroupEpersonService} groupService
|
* @param {GroupDataService} groupService
|
||||||
*/
|
*/
|
||||||
constructor(private groupService: GroupEpersonService) {}
|
constructor(private groupService: GroupDataService) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve access conditions list
|
* Retrieve access conditions list
|
||||||
|
@@ -27,7 +27,7 @@ import { SubmissionUploadsConfigService } from '../../../core/config/submission-
|
|||||||
import { SectionUploadService } from './section-upload.service';
|
import { SectionUploadService } from './section-upload.service';
|
||||||
import { SubmissionSectionUploadComponent } from './section-upload.component';
|
import { SubmissionSectionUploadComponent } from './section-upload.component';
|
||||||
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
||||||
import { GroupEpersonService } from '../../../core/eperson/group-eperson.service';
|
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
||||||
import { cold, hot } from 'jasmine-marbles';
|
import { cold, hot } from 'jasmine-marbles';
|
||||||
import { Collection } from '../../../core/shared/collection.model';
|
import { Collection } from '../../../core/shared/collection.model';
|
||||||
import { ResourcePolicy } from '../../../core/shared/resource-policy.model';
|
import { ResourcePolicy } from '../../../core/shared/resource-policy.model';
|
||||||
@@ -52,8 +52,8 @@ function getMockCollectionDataService(): CollectionDataService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMockGroupEpersonService(): GroupEpersonService {
|
function getMockGroupEpersonService(): GroupDataService {
|
||||||
return jasmine.createSpyObj('GroupEpersonService', {
|
return jasmine.createSpyObj('GroupDataService', {
|
||||||
findById: jasmine.createSpy('findById'),
|
findById: jasmine.createSpy('findById'),
|
||||||
|
|
||||||
});
|
});
|
||||||
@@ -134,7 +134,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
|
|||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: CollectionDataService, useValue: getMockCollectionDataService() },
|
{ provide: CollectionDataService, useValue: getMockCollectionDataService() },
|
||||||
{ provide: GroupEpersonService, useValue: getMockGroupEpersonService() },
|
{ provide: GroupDataService, useValue: getMockGroupEpersonService() },
|
||||||
{ provide: ResourcePolicyService, useValue: getMockResourcePolicyService() },
|
{ provide: ResourcePolicyService, useValue: getMockResourcePolicyService() },
|
||||||
{ provide: SubmissionUploadsConfigService, useValue: getMockSubmissionUploadsConfigService() },
|
{ provide: SubmissionUploadsConfigService, useValue: getMockSubmissionUploadsConfigService() },
|
||||||
{ provide: SectionsService, useClass: SectionsServiceStub },
|
{ provide: SectionsService, useClass: SectionsServiceStub },
|
||||||
@@ -181,7 +181,7 @@ describe('SubmissionSectionUploadComponent test suite', () => {
|
|||||||
submissionServiceStub = TestBed.get(SubmissionService);
|
submissionServiceStub = TestBed.get(SubmissionService);
|
||||||
sectionsServiceStub = TestBed.get(SectionsService);
|
sectionsServiceStub = TestBed.get(SectionsService);
|
||||||
collectionDataService = TestBed.get(CollectionDataService);
|
collectionDataService = TestBed.get(CollectionDataService);
|
||||||
groupService = TestBed.get(GroupEpersonService);
|
groupService = TestBed.get(GroupDataService);
|
||||||
resourcePolicyService = TestBed.get(ResourcePolicyService);
|
resourcePolicyService = TestBed.get(ResourcePolicyService);
|
||||||
uploadsConfigService = TestBed.get(SubmissionUploadsConfigService);
|
uploadsConfigService = TestBed.get(SubmissionUploadsConfigService);
|
||||||
bitstreamService = TestBed.get(SectionUploadService);
|
bitstreamService = TestBed.get(SectionUploadService);
|
||||||
|
@@ -8,7 +8,7 @@ import { SectionModelComponent } from '../models/section.model';
|
|||||||
import { hasValue, isNotEmpty, isNotUndefined, isUndefined } from '../../../shared/empty.util';
|
import { hasValue, isNotEmpty, isNotUndefined, isUndefined } from '../../../shared/empty.util';
|
||||||
import { SectionUploadService } from './section-upload.service';
|
import { SectionUploadService } from './section-upload.service';
|
||||||
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
import { CollectionDataService } from '../../../core/data/collection-data.service';
|
||||||
import { GroupEpersonService } from '../../../core/eperson/group-eperson.service';
|
import { GroupDataService } from '../../../core/eperson/group-data.service';
|
||||||
import { ResourcePolicyService } from '../../../core/data/resource-policy.service';
|
import { ResourcePolicyService } from '../../../core/data/resource-policy.service';
|
||||||
import { SubmissionUploadsConfigService } from '../../../core/config/submission-uploads-config.service';
|
import { SubmissionUploadsConfigService } from '../../../core/config/submission-uploads-config.service';
|
||||||
import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model';
|
import { SubmissionUploadsModel } from '../../../core/config/models/config-submission-uploads.model';
|
||||||
@@ -123,7 +123,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent {
|
|||||||
* @param {SectionUploadService} bitstreamService
|
* @param {SectionUploadService} bitstreamService
|
||||||
* @param {ChangeDetectorRef} changeDetectorRef
|
* @param {ChangeDetectorRef} changeDetectorRef
|
||||||
* @param {CollectionDataService} collectionDataService
|
* @param {CollectionDataService} collectionDataService
|
||||||
* @param {GroupEpersonService} groupService
|
* @param {GroupDataService} groupService
|
||||||
* @param {ResourcePolicyService} resourcePolicyService
|
* @param {ResourcePolicyService} resourcePolicyService
|
||||||
* @param {SectionsService} sectionService
|
* @param {SectionsService} sectionService
|
||||||
* @param {SubmissionService} submissionService
|
* @param {SubmissionService} submissionService
|
||||||
@@ -134,7 +134,7 @@ export class SubmissionSectionUploadComponent extends SectionModelComponent {
|
|||||||
constructor(private bitstreamService: SectionUploadService,
|
constructor(private bitstreamService: SectionUploadService,
|
||||||
private changeDetectorRef: ChangeDetectorRef,
|
private changeDetectorRef: ChangeDetectorRef,
|
||||||
private collectionDataService: CollectionDataService,
|
private collectionDataService: CollectionDataService,
|
||||||
private groupService: GroupEpersonService,
|
private groupService: GroupDataService,
|
||||||
private resourcePolicyService: ResourcePolicyService,
|
private resourcePolicyService: ResourcePolicyService,
|
||||||
protected sectionService: SectionsService,
|
protected sectionService: SectionsService,
|
||||||
private submissionService: SubmissionService,
|
private submissionService: SubmissionService,
|
||||||
|
Reference in New Issue
Block a user