mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
Merge pull request #468 from mspalti/forceBypassCache_remove
forceBypassCache param removed
This commit is contained in:
@@ -11,7 +11,6 @@ import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.serv
|
|||||||
import { MockRouter } from '../../shared/mocks/mock-router';
|
import { MockRouter } from '../../shared/mocks/mock-router';
|
||||||
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { ChangeDetectorRef, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { of as observableOf } from 'rxjs/internal/observable/of';
|
import { of as observableOf } from 'rxjs/internal/observable/of';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
|
||||||
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';
|
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';
|
||||||
import { Community } from '../../core/shared/community.model';
|
import { Community } from '../../core/shared/community.model';
|
||||||
import { Item } from '../../core/shared/item.model';
|
import { Item } from '../../core/shared/item.model';
|
||||||
|
@@ -82,7 +82,8 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
|
|||||||
const date = firstItemRD.payload.firstMetadataValue(metadataField);
|
const date = firstItemRD.payload.firstMetadataValue(metadataField);
|
||||||
if (hasValue(date)) {
|
if (hasValue(date)) {
|
||||||
const dateObj = new Date(date);
|
const dateObj = new Date(date);
|
||||||
lowerLimit = dateObj.getFullYear();
|
// TODO: it appears that getFullYear (based on local time) is sometimes unreliable. Switching to UTC.
|
||||||
|
lowerLimit = dateObj.getUTCFullYear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const options = [];
|
const options = [];
|
||||||
|
@@ -15,7 +15,6 @@ import { SortDirection, SortOptions } from '../core/cache/models/sort-options.mo
|
|||||||
import { CommunityDataService } from '../core/data/community-data.service';
|
import { CommunityDataService } from '../core/data/community-data.service';
|
||||||
import { HostWindowService } from '../shared/host-window.service';
|
import { HostWindowService } from '../shared/host-window.service';
|
||||||
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../shared/pagination/pagination-component-options.model';
|
||||||
import { RemoteData } from '../core/data/remote-data';
|
|
||||||
import { MyDSpacePageComponent, SEARCH_CONFIG_SERVICE } from './my-dspace-page.component';
|
import { MyDSpacePageComponent, SEARCH_CONFIG_SERVICE } from './my-dspace-page.component';
|
||||||
import { RouteService } from '../core/services/route.service';
|
import { RouteService } from '../core/services/route.service';
|
||||||
import { routeServiceStub } from '../shared/testing/route-service-stub';
|
import { routeServiceStub } from '../shared/testing/route-service-stub';
|
||||||
@@ -50,6 +49,7 @@ describe('MyDSpacePageComponent', () => {
|
|||||||
const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']);
|
const mockResults = createSuccessfulRemoteDataObject$(['test', 'data']);
|
||||||
const searchServiceStub = jasmine.createSpyObj('SearchService', {
|
const searchServiceStub = jasmine.createSpyObj('SearchService', {
|
||||||
search: mockResults,
|
search: mockResults,
|
||||||
|
getEndpoint: observableOf('discover/search/objects'),
|
||||||
getSearchLink: '/mydspace',
|
getSearchLink: '/mydspace',
|
||||||
getScopes: observableOf(['test-scope']),
|
getScopes: observableOf(['test-scope']),
|
||||||
setServiceOptions: {}
|
setServiceOptions: {}
|
||||||
@@ -76,6 +76,7 @@ describe('MyDSpacePageComponent', () => {
|
|||||||
scope: scopeParam
|
scope: scopeParam
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const sidebarService = {
|
const sidebarService = {
|
||||||
isCollapsed: observableOf(true),
|
isCollapsed: observableOf(true),
|
||||||
collapse: () => this.isCollapsed = observableOf(true),
|
collapse: () => this.isCollapsed = observableOf(true),
|
||||||
|
@@ -124,13 +124,13 @@ export class MyDSpacePageComponent implements OnInit {
|
|||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.configurationList$ = this.searchConfigService.getAvailableConfigurationOptions();
|
this.configurationList$ = this.searchConfigService.getAvailableConfigurationOptions();
|
||||||
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
this.searchOptions$ = this.searchConfigService.paginatedSearchOptions;
|
||||||
|
|
||||||
this.sub = this.searchOptions$.pipe(
|
this.sub = this.searchOptions$.pipe(
|
||||||
tap(() => this.resultsRD$.next(null)),
|
tap(() => this.resultsRD$.next(null)),
|
||||||
switchMap((options: PaginatedSearchOptions) => this.service.search(options).pipe(getSucceededRemoteData())))
|
switchMap((options: PaginatedSearchOptions) => this.service.search(options).pipe(getSucceededRemoteData())))
|
||||||
.subscribe((results) => {
|
.subscribe((results) => {
|
||||||
this.resultsRD$.next(results);
|
this.resultsRD$.next(results);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
|
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
|
||||||
switchMap((scopeId) => this.service.getScopes(scopeId))
|
switchMap((scopeId) => this.service.getScopes(scopeId))
|
||||||
);
|
);
|
||||||
|
@@ -97,14 +97,8 @@ export class SearchService implements OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
getEndpoint(searchOptions?: PaginatedSearchOptions): Observable<string> {
|
||||||
* Method to retrieve a paginated list of search results from the server
|
return this.halService.getEndpoint(this.searchLinkPath).pipe(
|
||||||
* @param {PaginatedSearchOptions} searchOptions The configuration necessary to perform this search
|
|
||||||
* @param responseMsToLive The amount of milliseconds for the response to live in cache
|
|
||||||
* @returns {Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>} Emits a paginated list with all search results found
|
|
||||||
*/
|
|
||||||
search(searchOptions?: PaginatedSearchOptions, responseMsToLive?: number): Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>> {
|
|
||||||
const hrefObs = this.halService.getEndpoint(this.searchLinkPath).pipe(
|
|
||||||
map((url: string) => {
|
map((url: string) => {
|
||||||
if (hasValue(searchOptions)) {
|
if (hasValue(searchOptions)) {
|
||||||
return (searchOptions as PaginatedSearchOptions).toRestUrl(url);
|
return (searchOptions as PaginatedSearchOptions).toRestUrl(url);
|
||||||
@@ -113,6 +107,17 @@ export class SearchService implements OnDestroy {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method to retrieve a paginated list of search results from the server
|
||||||
|
* @param {PaginatedSearchOptions} searchOptions The configuration necessary to perform this search
|
||||||
|
* @param responseMsToLive The amount of milliseconds for the response to live in cache
|
||||||
|
* @returns {Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>>} Emits a paginated list with all search results found
|
||||||
|
*/
|
||||||
|
search(searchOptions?: PaginatedSearchOptions, responseMsToLive?: number): Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>> {
|
||||||
|
|
||||||
|
const hrefObs = this.getEndpoint(searchOptions);
|
||||||
|
|
||||||
const requestObs = hrefObs.pipe(
|
const requestObs = hrefObs.pipe(
|
||||||
map((url: string) => {
|
map((url: string) => {
|
||||||
|
@@ -44,7 +44,11 @@ export class AuthRequestService {
|
|||||||
map((endpointURL) => this.getEndpointByMethod(endpointURL, method)),
|
map((endpointURL) => this.getEndpointByMethod(endpointURL, method)),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
map((endpointURL: string) => new AuthPostRequest(this.requestService.generateRequestId(), endpointURL, body, options)),
|
map((endpointURL: string) => new AuthPostRequest(this.requestService.generateRequestId(), endpointURL, body, options)),
|
||||||
tap((request: PostRequest) => this.requestService.configure(request, true)),
|
map ((request: PostRequest) => {
|
||||||
|
request.responseMsToLive = 10 * 1000;
|
||||||
|
return request;
|
||||||
|
}),
|
||||||
|
tap((request: PostRequest) => this.requestService.configure(request)),
|
||||||
mergeMap((request: PostRequest) => this.fetchRequest(request)),
|
mergeMap((request: PostRequest) => this.fetchRequest(request)),
|
||||||
distinctUntilChanged());
|
distinctUntilChanged());
|
||||||
}
|
}
|
||||||
@@ -55,7 +59,11 @@ export class AuthRequestService {
|
|||||||
map((endpointURL) => this.getEndpointByMethod(endpointURL, method)),
|
map((endpointURL) => this.getEndpointByMethod(endpointURL, method)),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
map((endpointURL: string) => new AuthGetRequest(this.requestService.generateRequestId(), endpointURL, options)),
|
map((endpointURL: string) => new AuthGetRequest(this.requestService.generateRequestId(), endpointURL, options)),
|
||||||
tap((request: GetRequest) => this.requestService.configure(request, true)),
|
map ((request: GetRequest) => {
|
||||||
|
request.responseMsToLive = 10 * 1000;
|
||||||
|
return request;
|
||||||
|
}),
|
||||||
|
tap((request: GetRequest) => this.requestService.configure(request)),
|
||||||
mergeMap((request: GetRequest) => this.fetchRequest(request)),
|
mergeMap((request: GetRequest) => this.fetchRequest(request)),
|
||||||
distinctUntilChanged());
|
distinctUntilChanged());
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@ export class AuthResponseParsingService extends BaseResponseParsingService imple
|
|||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 200)) {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 200)) {
|
||||||
const response = this.process<NormalizedObject<AuthStatus>>(data.payload, request.uuid);
|
const response = this.process<NormalizedObject<AuthStatus>>(data.payload, request);
|
||||||
return new AuthStatusResponse(response, data.statusCode, data.statusText);
|
return new AuthStatusResponse(response, data.statusCode, data.statusText);
|
||||||
} else {
|
} else {
|
||||||
return new AuthStatusResponse(data.payload as NormalizedAuthStatus, data.statusCode, data.statusText);
|
return new AuthStatusResponse(data.payload as NormalizedAuthStatus, data.statusCode, data.statusText);
|
||||||
|
@@ -114,7 +114,7 @@ describe('BrowseService', () => {
|
|||||||
scheduler.schedule(() => service.getBrowseDefinitions().subscribe());
|
scheduler.schedule(() => service.getBrowseDefinitions().subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(expected, undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
||||||
@@ -155,7 +155,7 @@ describe('BrowseService', () => {
|
|||||||
scheduler.schedule(() => service.getBrowseEntriesFor(new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
scheduler.schedule(() => service.getBrowseEntriesFor(new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(expected, undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
||||||
@@ -174,7 +174,7 @@ describe('BrowseService', () => {
|
|||||||
scheduler.schedule(() => service.getBrowseItemsFor(mockAuthorName, new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
scheduler.schedule(() => service.getBrowseItemsFor(mockAuthorName, new BrowseEntrySearchOptions(browseDefinitions[1].id)).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(expected, undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
||||||
@@ -303,7 +303,7 @@ describe('BrowseService', () => {
|
|||||||
scheduler.schedule(() => service.getFirstItemFor(browseDefinitions[1].id).subscribe());
|
scheduler.schedule(() => service.getFirstItemFor(browseDefinitions[1].id).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(expected, undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
it('should call RemoteDataBuildService to create the RemoteData Observable', () => {
|
||||||
|
@@ -24,7 +24,7 @@ export class ConfigResponseParsingService extends BaseResponseParsingService imp
|
|||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 201 || data.statusCode === 200)) {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links) && (data.statusCode === 201 || data.statusCode === 200)) {
|
||||||
const configDefinition = this.process<ConfigObject>(data.payload, request.uuid);
|
const configDefinition = this.process<ConfigObject>(data.payload, request);
|
||||||
return new ConfigSuccessResponse(configDefinition, data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
return new ConfigSuccessResponse(configDefinition, data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
|
@@ -9,6 +9,7 @@ import { PaginatedList } from './paginated-list';
|
|||||||
import { isRestDataObject, isRestPaginatedList } from '../cache/builders/normalized-object-build.service';
|
import { isRestDataObject, isRestPaginatedList } from '../cache/builders/normalized-object-build.service';
|
||||||
import { ResourceType } from '../shared/resource-type';
|
import { ResourceType } from '../shared/resource-type';
|
||||||
import { getMapsToType } from '../cache/builders/build-decorators';
|
import { getMapsToType } from '../cache/builders/build-decorators';
|
||||||
|
import { RestRequest } from './request.models';
|
||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
|
|
||||||
export abstract class BaseResponseParsingService {
|
export abstract class BaseResponseParsingService {
|
||||||
@@ -16,14 +17,14 @@ export abstract class BaseResponseParsingService {
|
|||||||
protected abstract objectCache: ObjectCacheService;
|
protected abstract objectCache: ObjectCacheService;
|
||||||
protected abstract toCache: boolean;
|
protected abstract toCache: boolean;
|
||||||
|
|
||||||
protected process<ObjectDomain>(data: any, requestUUID: string): any {
|
protected process<ObjectDomain>(data: any, request: RestRequest): any {
|
||||||
if (isNotEmpty(data)) {
|
if (isNotEmpty(data)) {
|
||||||
if (hasNoValue(data) || (typeof data !== 'object')) {
|
if (hasNoValue(data) || (typeof data !== 'object')) {
|
||||||
return data;
|
return data;
|
||||||
} else if (isRestPaginatedList(data)) {
|
} else if (isRestPaginatedList(data)) {
|
||||||
return this.processPaginatedList(data, requestUUID);
|
return this.processPaginatedList(data, request);
|
||||||
} else if (Array.isArray(data)) {
|
} else if (Array.isArray(data)) {
|
||||||
return this.processArray(data, requestUUID);
|
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)) {
|
if (isNotEmpty(data._embedded)) {
|
||||||
@@ -31,7 +32,7 @@ export abstract class BaseResponseParsingService {
|
|||||||
.keys(data._embedded)
|
.keys(data._embedded)
|
||||||
.filter((property) => data._embedded.hasOwnProperty(property))
|
.filter((property) => data._embedded.hasOwnProperty(property))
|
||||||
.forEach((property) => {
|
.forEach((property) => {
|
||||||
const parsedObj = this.process<ObjectDomain>(data._embedded[property], requestUUID);
|
const parsedObj = this.process<ObjectDomain>(data._embedded[property], request);
|
||||||
if (isNotEmpty(parsedObj)) {
|
if (isNotEmpty(parsedObj)) {
|
||||||
if (isRestPaginatedList(data._embedded[property])) {
|
if (isRestPaginatedList(data._embedded[property])) {
|
||||||
object[property] = parsedObj;
|
object[property] = parsedObj;
|
||||||
@@ -45,7 +46,7 @@ export abstract class BaseResponseParsingService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cache(object, requestUUID);
|
this.cache(object, request);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
const result = {};
|
const result = {};
|
||||||
@@ -53,14 +54,14 @@ export abstract class BaseResponseParsingService {
|
|||||||
.filter((property) => data.hasOwnProperty(property))
|
.filter((property) => data.hasOwnProperty(property))
|
||||||
.filter((property) => hasValue(data[property]))
|
.filter((property) => hasValue(data[property]))
|
||||||
.forEach((property) => {
|
.forEach((property) => {
|
||||||
result[property] = this.process(data[property], requestUUID);
|
result[property] = this.process(data[property], request);
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected processPaginatedList<ObjectDomain>(data: any, requestUUID: string): PaginatedList<ObjectDomain> {
|
protected processPaginatedList<ObjectDomain>(data: any, request: RestRequest): PaginatedList<ObjectDomain> {
|
||||||
const pageInfo: PageInfo = this.processPageInfo(data);
|
const pageInfo: PageInfo = this.processPageInfo(data);
|
||||||
let list = data._embedded;
|
let list = data._embedded;
|
||||||
|
|
||||||
@@ -70,14 +71,14 @@ export abstract class BaseResponseParsingService {
|
|||||||
} else if (!Array.isArray(list)) {
|
} else if (!Array.isArray(list)) {
|
||||||
list = this.flattenSingleKeyObject(list);
|
list = this.flattenSingleKeyObject(list);
|
||||||
}
|
}
|
||||||
const page: ObjectDomain[] = this.processArray(list, requestUUID);
|
const page: ObjectDomain[] = this.processArray(list, request);
|
||||||
return new PaginatedList<ObjectDomain>(pageInfo, page, );
|
return new PaginatedList<ObjectDomain>(pageInfo, page, );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected processArray<ObjectDomain>(data: any, requestUUID: string): ObjectDomain[] {
|
protected processArray<ObjectDomain>(data: any, request: RestRequest): ObjectDomain[] {
|
||||||
let array: ObjectDomain[] = [];
|
let array: ObjectDomain[] = [];
|
||||||
data.forEach((datum) => {
|
data.forEach((datum) => {
|
||||||
array = [...array, this.process(datum, requestUUID)];
|
array = [...array, this.process(datum, request)];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return array;
|
return array;
|
||||||
@@ -104,17 +105,17 @@ export abstract class BaseResponseParsingService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected cache<ObjectDomain>(obj, requestUUID) {
|
protected cache<ObjectDomain>(obj, request: RestRequest) {
|
||||||
if (this.toCache) {
|
if (this.toCache) {
|
||||||
this.addToObjectCache(obj, requestUUID);
|
this.addToObjectCache(obj, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected addToObjectCache(co: CacheableObject, requestUUID: string): void {
|
protected addToObjectCache(co: CacheableObject, request: RestRequest): void {
|
||||||
if (hasNoValue(co) || hasNoValue(co.self)) {
|
if (hasNoValue(co) || hasNoValue(co.self)) {
|
||||||
throw new Error('The server returned an invalid object');
|
throw new Error('The server returned an invalid object');
|
||||||
}
|
}
|
||||||
this.objectCache.add(co, this.EnvConfig.cache.msToLive.default, requestUUID);
|
this.objectCache.add(co, hasValue(request.responseMsToLive) ? request.responseMsToLive : this.EnvConfig.cache.msToLive.default, request.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
processPageInfo(payload: any): PageInfo {
|
processPageInfo(payload: any): PageInfo {
|
||||||
|
@@ -38,7 +38,6 @@ const selectedBitstreamFormatSelector = createSelector(bitstreamFormatsStateSele
|
|||||||
export class BitstreamFormatDataService extends DataService<BitstreamFormat> {
|
export class BitstreamFormatDataService extends DataService<BitstreamFormat> {
|
||||||
|
|
||||||
protected linkPath = 'bitstreamformats';
|
protected linkPath = 'bitstreamformats';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -37,7 +37,7 @@ describe('CollectionDataService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should configure a GET request', () => {
|
it('should configure a GET request', () => {
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(GetRequest), undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(jasmine.any(GetRequest));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -31,7 +31,6 @@ import { SearchParam } from '../cache/models/search-param.model';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class CollectionDataService extends ComColDataService<Collection> {
|
export class CollectionDataService extends ComColDataService<Collection> {
|
||||||
protected linkPath = 'collections';
|
protected linkPath = 'collections';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -28,7 +28,6 @@ class NormalizedTestObject extends NormalizedObject<Item> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends ComColDataService<any> {
|
class TestService extends ComColDataService<any> {
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -24,7 +24,6 @@ export class CommunityDataService extends ComColDataService<Community> {
|
|||||||
protected linkPath = 'communities';
|
protected linkPath = 'communities';
|
||||||
protected topLinkPath = 'communities/search/top';
|
protected topLinkPath = 'communities/search/top';
|
||||||
protected cds = this;
|
protected cds = this;
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -24,7 +24,6 @@ class NormalizedTestObject extends NormalizedObject<Item> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TestService extends DataService<any> {
|
class TestService extends DataService<any> {
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -45,11 +45,14 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
protected abstract store: Store<CoreState>;
|
protected abstract store: Store<CoreState>;
|
||||||
protected abstract linkPath: string;
|
protected abstract linkPath: string;
|
||||||
protected abstract halService: HALEndpointService;
|
protected abstract halService: HALEndpointService;
|
||||||
protected abstract forceBypassCache = false;
|
|
||||||
protected abstract objectCache: ObjectCacheService;
|
protected abstract objectCache: ObjectCacheService;
|
||||||
protected abstract notificationsService: NotificationsService;
|
protected abstract notificationsService: NotificationsService;
|
||||||
protected abstract http: HttpClient;
|
protected abstract http: HttpClient;
|
||||||
protected abstract comparator: ChangeAnalyzer<T>;
|
protected abstract comparator: ChangeAnalyzer<T>;
|
||||||
|
/**
|
||||||
|
* Allows subclasses to reset the response cache time.
|
||||||
|
*/
|
||||||
|
protected responseMsToLive: number;
|
||||||
|
|
||||||
public abstract getBrowseEndpoint(options: FindAllOptions, linkPath?: string): Observable<string>
|
public abstract getBrowseEndpoint(options: FindAllOptions, linkPath?: string): Observable<string>
|
||||||
|
|
||||||
@@ -131,7 +134,10 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
first((href: string) => hasValue(href)))
|
first((href: string) => hasValue(href)))
|
||||||
.subscribe((href: string) => {
|
.subscribe((href: string) => {
|
||||||
const request = new FindAllRequest(this.requestService.generateRequestId(), href, options);
|
const request = new FindAllRequest(this.requestService.generateRequestId(), href, options);
|
||||||
this.requestService.configure(request, this.forceBypassCache);
|
if (hasValue(this.responseMsToLive)) {
|
||||||
|
request.responseMsToLive = this.responseMsToLive;
|
||||||
|
}
|
||||||
|
this.requestService.configure(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.rdbService.buildList<T>(hrefObs) as Observable<RemoteData<PaginatedList<T>>>;
|
return this.rdbService.buildList<T>(hrefObs) as Observable<RemoteData<PaginatedList<T>>>;
|
||||||
@@ -154,14 +160,21 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
find((href: string) => hasValue(href)))
|
find((href: string) => hasValue(href)))
|
||||||
.subscribe((href: string) => {
|
.subscribe((href: string) => {
|
||||||
const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id);
|
const request = new FindByIDRequest(this.requestService.generateRequestId(), href, id);
|
||||||
this.requestService.configure(request, this.forceBypassCache);
|
if (hasValue(this.responseMsToLive)) {
|
||||||
|
request.responseMsToLive = this.responseMsToLive;
|
||||||
|
}
|
||||||
|
this.requestService.configure(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.rdbService.buildSingle<T>(hrefObs);
|
return this.rdbService.buildSingle<T>(hrefObs);
|
||||||
}
|
}
|
||||||
|
|
||||||
findByHref(href: string, options?: HttpOptions): Observable<RemoteData<T>> {
|
findByHref(href: string, options?: HttpOptions): Observable<RemoteData<T>> {
|
||||||
this.requestService.configure(new GetRequest(this.requestService.generateRequestId(), href, null, options), this.forceBypassCache);
|
const request = new GetRequest(this.requestService.generateRequestId(), href, null, options);
|
||||||
|
if (hasValue(this.responseMsToLive)) {
|
||||||
|
request.responseMsToLive = this.responseMsToLive;
|
||||||
|
}
|
||||||
|
this.requestService.configure(request);
|
||||||
return this.rdbService.buildSingle<T>(href);
|
return this.rdbService.buildSingle<T>(href);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +205,8 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
first((href: string) => hasValue(href)))
|
first((href: string) => hasValue(href)))
|
||||||
.subscribe((href: string) => {
|
.subscribe((href: string) => {
|
||||||
const request = new FindAllRequest(this.requestService.generateRequestId(), href, options);
|
const request = new FindAllRequest(this.requestService.generateRequestId(), href, options);
|
||||||
this.requestService.configure(request, true);
|
request.responseMsToLive = 10 * 1000;
|
||||||
|
this.requestService.configure(request);
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.rdbService.buildList<T>(hrefObs) as Observable<RemoteData<PaginatedList<T>>>;
|
return this.rdbService.buildList<T>(hrefObs) as Observable<RemoteData<PaginatedList<T>>>;
|
||||||
|
@@ -30,7 +30,7 @@ export class DSOResponseParsingService extends BaseResponseParsingService implem
|
|||||||
if (hasValue(data.payload) && hasValue(data.payload.page) && data.payload.page.totalElements === 0) {
|
if (hasValue(data.payload) && hasValue(data.payload.page) && data.payload.page.totalElements === 0) {
|
||||||
processRequestDTO = { page: [] };
|
processRequestDTO = { page: [] };
|
||||||
} else {
|
} else {
|
||||||
processRequestDTO = this.process<NormalizedObject<DSpaceObject>>(data.payload, request.uuid);
|
processRequestDTO = this.process<NormalizedObject<DSpaceObject>>(data.payload, request);
|
||||||
}
|
}
|
||||||
let objectList = processRequestDTO;
|
let objectList = processRequestDTO;
|
||||||
|
|
||||||
|
@@ -72,7 +72,7 @@ describe('DSpaceObjectDataService', () => {
|
|||||||
scheduler.schedule(() => service.findById(testObject.uuid));
|
scheduler.schedule(() => service.findById(testObject.uuid));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestURL, testObject.uuid), false);
|
expect(requestService.configure).toHaveBeenCalledWith(new FindByIDRequest(requestUUID, requestURL, testObject.uuid));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a RemoteData<DSpaceObject> for the object with the given ID', () => {
|
it('should return a RemoteData<DSpaceObject> for the object with the given ID', () => {
|
||||||
|
@@ -18,7 +18,6 @@ import { DSOChangeAnalyzer } from './dso-change-analyzer.service';
|
|||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
class DataServiceImpl extends DataService<DSpaceObject> {
|
class DataServiceImpl extends DataService<DSpaceObject> {
|
||||||
protected linkPath = 'dso';
|
protected linkPath = 'dso';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -41,7 +41,6 @@ import { PaginatedList } from './paginated-list';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ItemDataService extends DataService<Item> {
|
export class ItemDataService extends DataService<Item> {
|
||||||
protected linkPath = 'items';
|
protected linkPath = 'items';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -19,7 +19,6 @@ import { MetadataSchema } from '../metadata/metadata-schema.model';
|
|||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
class DataServiceImpl extends DataService<MetadataSchema> {
|
class DataServiceImpl extends DataService<MetadataSchema> {
|
||||||
protected linkPath = 'metadataschemas';
|
protected linkPath = 'metadataschemas';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -114,7 +114,7 @@ describe('RelationshipService', () => {
|
|||||||
|
|
||||||
it('should send a DeleteRequest', () => {
|
it('should send a DeleteRequest', () => {
|
||||||
const expected = new DeleteRequest(requestService.generateRequestId(), relationshipsEndpointURL + '/' + relationship1.uuid);
|
const expected = new DeleteRequest(requestService.generateRequestId(), relationshipsEndpointURL + '/' + relationship1.uuid);
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(expected, undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should clear the related items their cache', () => {
|
it('should clear the related items their cache', () => {
|
||||||
|
@@ -23,7 +23,8 @@ import { MappedCollectionsReponseParsingService } from './mapped-collections-rep
|
|||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
|
|
||||||
export abstract class RestRequest {
|
export abstract class RestRequest {
|
||||||
public responseMsToLive = 0;
|
public responseMsToLive = 10 * 1000;
|
||||||
|
public forceBypassCache = false;
|
||||||
constructor(
|
constructor(
|
||||||
public uuid: string,
|
public uuid: string,
|
||||||
public href: string,
|
public href: string,
|
||||||
@@ -293,6 +294,7 @@ export class UpdateMetadataFieldRequest extends PutRequest {
|
|||||||
* Class representing a submission HTTP GET request object
|
* Class representing a submission HTTP GET request object
|
||||||
*/
|
*/
|
||||||
export class SubmissionRequest extends GetRequest {
|
export class SubmissionRequest extends GetRequest {
|
||||||
|
forceBypassCache = true;
|
||||||
constructor(uuid: string, href: string) {
|
constructor(uuid: string, href: string) {
|
||||||
super(uuid, href);
|
super(uuid, href);
|
||||||
}
|
}
|
||||||
@@ -404,7 +406,7 @@ export class TaskDeleteRequest extends DeleteRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class MyDSpaceRequest extends GetRequest {
|
export class MyDSpaceRequest extends GetRequest {
|
||||||
public responseMsToLive = 0;
|
public responseMsToLive = 10 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RequestError extends Error {
|
export class RequestError extends Error {
|
||||||
|
@@ -19,7 +19,7 @@ import {
|
|||||||
} from '../index/index.selectors';
|
} from '../index/index.selectors';
|
||||||
import { UUIDService } from '../shared/uuid.service';
|
import { UUIDService } from '../shared/uuid.service';
|
||||||
import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions';
|
import { RequestConfigureAction, RequestExecuteAction, RequestRemoveAction } from './request.actions';
|
||||||
import { GetRequest, RestRequest } from './request.models';
|
import { GetRequest, RestRequest, SubmissionRequest } from './request.models';
|
||||||
import { RequestEntry, RequestState } from './request.reducer';
|
import { RequestEntry, RequestState } from './request.reducer';
|
||||||
import { CommitSSBAction } from '../cache/server-sync-buffer.actions';
|
import { CommitSSBAction } from '../cache/server-sync-buffer.actions';
|
||||||
import { RestRequestMethod } from './rest-request-method';
|
import { RestRequestMethod } from './rest-request-method';
|
||||||
@@ -145,14 +145,10 @@ export class RequestService {
|
|||||||
* Configure a certain request
|
* Configure a certain request
|
||||||
* Used to make sure a request is in the cache
|
* Used to make sure a request is in the cache
|
||||||
* @param {RestRequest} request The request to send out
|
* @param {RestRequest} request The request to send out
|
||||||
* @param {boolean} forceBypassCache When true, a new request is always dispatched
|
|
||||||
*/
|
*/
|
||||||
configure<T extends CacheableObject>(request: RestRequest, forceBypassCache: boolean = false): void {
|
configure<T extends CacheableObject>(request: RestRequest): void {
|
||||||
const isGetRequest = request.method === RestRequestMethod.GET;
|
const isGetRequest = request.method === RestRequestMethod.GET;
|
||||||
if (forceBypassCache) {
|
if (!isGetRequest || request.forceBypassCache || !this.isCachedOrPending(request)) {
|
||||||
this.clearRequestsOnTheirWayToTheStore(request);
|
|
||||||
}
|
|
||||||
if (!isGetRequest || (forceBypassCache && !this.isPending(request)) || !this.isCachedOrPending(request)) {
|
|
||||||
this.dispatchRequest(request);
|
this.dispatchRequest(request);
|
||||||
if (isGetRequest) {
|
if (isGetRequest) {
|
||||||
this.trackRequestsOnTheirWayToTheStore(request);
|
this.trackRequestsOnTheirWayToTheStore(request);
|
||||||
@@ -226,7 +222,6 @@ export class RequestService {
|
|||||||
const inReqCache = this.hasByHref(request.href);
|
const inReqCache = this.hasByHref(request.href);
|
||||||
const inObjCache = this.objectCache.hasBySelfLink(request.href);
|
const inObjCache = this.objectCache.hasBySelfLink(request.href);
|
||||||
const isCached = inReqCache || inObjCache;
|
const isCached = inReqCache || inObjCache;
|
||||||
|
|
||||||
const isPending = this.isPending(request);
|
const isPending = this.isPending(request);
|
||||||
return isCached || isPending;
|
return isCached || isPending;
|
||||||
}
|
}
|
||||||
|
@@ -61,7 +61,7 @@ describe('ResourcePolicyService', () => {
|
|||||||
scheduler.schedule(() => service.findByHref(requestURL));
|
scheduler.schedule(() => service.findByHref(requestURL));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(new GetRequest(requestUUID, requestURL, null), false);
|
expect(requestService.configure).toHaveBeenCalledWith(new GetRequest(requestUUID, requestURL, null));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a RemoteData<ResourcePolicy> for the object with the given URL', () => {
|
it('should return a RemoteData<ResourcePolicy> for the object with the given URL', () => {
|
||||||
|
@@ -22,7 +22,6 @@ import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
|
|||||||
/* tslint:disable:max-classes-per-file */
|
/* tslint:disable:max-classes-per-file */
|
||||||
class DataServiceImpl extends DataService<ResourcePolicy> {
|
class DataServiceImpl extends DataService<ResourcePolicy> {
|
||||||
protected linkPath = 'resourcepolicies';
|
protected linkPath = 'resourcepolicies';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
@@ -28,7 +28,7 @@ export class EpersonResponseParsingService extends BaseResponseParsingService im
|
|||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
||||||
const epersonDefinition = this.process<DSpaceObject>(data.payload, request.href);
|
const epersonDefinition = this.process<DSpaceObject>(data.payload, request);
|
||||||
return new EpersonSuccessResponse(epersonDefinition[Object.keys(epersonDefinition)[0]], data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
return new EpersonSuccessResponse(epersonDefinition[Object.keys(epersonDefinition)[0]], data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
|
@@ -27,7 +27,6 @@ import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
|
|||||||
export class GroupEpersonService extends EpersonService<Group> {
|
export class GroupEpersonService extends EpersonService<Group> {
|
||||||
protected linkPath = 'groups';
|
protected linkPath = 'groups';
|
||||||
protected browseEndpoint = '';
|
protected browseEndpoint = '';
|
||||||
protected forceBypassCache = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected comparator: DSOChangeAnalyzer<Group>,
|
protected comparator: DSOChangeAnalyzer<Group>,
|
||||||
|
@@ -27,7 +27,7 @@ export class IntegrationResponseParsingService extends BaseResponseParsingServic
|
|||||||
|
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
if (isNotEmpty(data.payload) && isNotEmpty(data.payload._links)) {
|
||||||
const dataDefinition = this.process<IntegrationModel>(data.payload, request.uuid);
|
const dataDefinition = this.process<IntegrationModel>(data.payload, request);
|
||||||
return new IntegrationSuccessResponse(this.processResponse(dataDefinition), data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
return new IntegrationSuccessResponse(this.processResponse(dataDefinition), data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
||||||
} else {
|
} else {
|
||||||
return new ErrorResponse(
|
return new ErrorResponse(
|
||||||
|
@@ -148,7 +148,7 @@ describe('Core Module - RxJS Operators', () => {
|
|||||||
scheduler.schedule(() => source.pipe(configureRequest(requestService)).subscribe());
|
scheduler.schedule(() => source.pipe(configureRequest(requestService)).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(testRequest, undefined);
|
expect(requestService.configure).toHaveBeenCalledWith(testRequest);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -52,9 +52,9 @@ export const getResourceLinksFromResponse = () =>
|
|||||||
map((response: DSOSuccessResponse) => response.resourceSelfLinks),
|
map((response: DSOSuccessResponse) => response.resourceSelfLinks),
|
||||||
);
|
);
|
||||||
|
|
||||||
export const configureRequest = (requestService: RequestService, forceBypassCache?: boolean) =>
|
export const configureRequest = (requestService: RequestService) =>
|
||||||
(source: Observable<RestRequest>): Observable<RestRequest> =>
|
(source: Observable<RestRequest>): Observable<RestRequest> =>
|
||||||
source.pipe(tap((request: RestRequest) => requestService.configure(request, forceBypassCache)));
|
source.pipe(tap((request: RestRequest) => requestService.configure(request)));
|
||||||
|
|
||||||
export const getRemoteDataPayload = () =>
|
export const getRemoteDataPayload = () =>
|
||||||
<T>(source: Observable<RemoteData<T>>): Observable<T> =>
|
<T>(source: Observable<RemoteData<T>>): Observable<T> =>
|
||||||
|
@@ -91,7 +91,7 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService
|
|||||||
if (isNotEmpty(data.payload)
|
if (isNotEmpty(data.payload)
|
||||||
&& isNotEmpty(data.payload._links)
|
&& isNotEmpty(data.payload._links)
|
||||||
&& this.isSuccessStatus(data.statusCode)) {
|
&& this.isSuccessStatus(data.statusCode)) {
|
||||||
const dataDefinition = this.processResponse<SubmissionObject | ConfigObject>(data.payload, request.href);
|
const dataDefinition = this.processResponse<SubmissionObject | ConfigObject>(data.payload, request);
|
||||||
return new SubmissionSuccessResponse(dataDefinition, data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
return new SubmissionSuccessResponse(dataDefinition, data.statusCode, data.statusText, this.processPageInfo(data.payload));
|
||||||
} else if (isEmpty(data.payload) && this.isSuccessStatus(data.statusCode)) {
|
} else if (isEmpty(data.payload) && this.isSuccessStatus(data.statusCode)) {
|
||||||
return new SubmissionSuccessResponse(null, data.statusCode, data.statusText);
|
return new SubmissionSuccessResponse(null, data.statusCode, data.statusText);
|
||||||
@@ -109,11 +109,11 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService
|
|||||||
* Parses response and normalize it
|
* Parses response and normalize it
|
||||||
*
|
*
|
||||||
* @param {DSpaceRESTV2Response} data
|
* @param {DSpaceRESTV2Response} data
|
||||||
* @param {string} requestHref
|
* @param {RestRequest} request
|
||||||
* @returns {any[]}
|
* @returns {any[]}
|
||||||
*/
|
*/
|
||||||
protected processResponse<ObjectDomain>(data: any, requestHref: string): any[] {
|
protected processResponse<ObjectDomain>(data: any, request: RestRequest): any[] {
|
||||||
const dataDefinition = this.process<ObjectDomain>(data, requestHref);
|
const dataDefinition = this.process<ObjectDomain>(data, request);
|
||||||
const normalizedDefinition = Array.of();
|
const normalizedDefinition = Array.of();
|
||||||
const processedList = Array.isArray(dataDefinition) ? dataDefinition : Array.of(dataDefinition);
|
const processedList = Array.isArray(dataDefinition) ? dataDefinition : Array.of(dataDefinition);
|
||||||
|
|
||||||
|
@@ -59,10 +59,13 @@ describe('SubmissionRestService test suite', () => {
|
|||||||
describe('getDataById', () => {
|
describe('getDataById', () => {
|
||||||
it('should configure a new SubmissionRequest', () => {
|
it('should configure a new SubmissionRequest', () => {
|
||||||
const expected = new SubmissionRequest(requestService.generateRequestId(), resourceHref);
|
const expected = new SubmissionRequest(requestService.generateRequestId(), resourceHref);
|
||||||
|
// set cache time to zero
|
||||||
|
expected.responseMsToLive = 0;
|
||||||
|
expected.forceBypassCache = true;
|
||||||
scheduler.schedule(() => service.getDataById(resourceEndpoint, resourceScope).subscribe());
|
scheduler.schedule(() => service.getDataById(resourceEndpoint, resourceScope).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(requestService.configure).toHaveBeenCalledWith(expected, true);
|
expect(requestService.configure).toHaveBeenCalledWith(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@ import { distinctUntilChanged, filter, flatMap, map, mergeMap, tap } from 'rxjs/
|
|||||||
import { RequestService } from '../data/request.service';
|
import { RequestService } from '../data/request.service';
|
||||||
import { isNotEmpty } from '../../shared/empty.util';
|
import { isNotEmpty } from '../../shared/empty.util';
|
||||||
import {
|
import {
|
||||||
DeleteRequest,
|
DeleteRequest, GetRequest,
|
||||||
PostRequest,
|
PostRequest,
|
||||||
RestRequest,
|
RestRequest,
|
||||||
SubmissionDeleteRequest,
|
SubmissionDeleteRequest,
|
||||||
@@ -109,7 +109,11 @@ export class SubmissionRestService {
|
|||||||
filter((href: string) => isNotEmpty(href)),
|
filter((href: string) => isNotEmpty(href)),
|
||||||
distinctUntilChanged(),
|
distinctUntilChanged(),
|
||||||
map((endpointURL: string) => new SubmissionRequest(requestId, endpointURL)),
|
map((endpointURL: string) => new SubmissionRequest(requestId, endpointURL)),
|
||||||
tap((request: RestRequest) => this.requestService.configure(request, true)),
|
map ((request: RestRequest) => {
|
||||||
|
request.responseMsToLive = 0;
|
||||||
|
return request;
|
||||||
|
}),
|
||||||
|
tap((request: RestRequest) => this.requestService.configure(request)),
|
||||||
flatMap(() => this.fetchRequest(requestId)),
|
flatMap(() => this.fetchRequest(requestId)),
|
||||||
distinctUntilChanged());
|
distinctUntilChanged());
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@ import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkflowItemDataService extends DataService<WorkflowItem> {
|
export class WorkflowItemDataService extends DataService<WorkflowItem> {
|
||||||
protected linkPath = 'workflowitems';
|
protected linkPath = 'workflowitems';
|
||||||
protected forceBypassCache = true;
|
protected responseMsToLive = 10 * 1000;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected comparator: DSOChangeAnalyzer<WorkflowItem>,
|
protected comparator: DSOChangeAnalyzer<WorkflowItem>,
|
||||||
|
@@ -20,7 +20,7 @@ import { WorkspaceItem } from './models/workspaceitem.model';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceitemDataService extends DataService<WorkspaceItem> {
|
export class WorkspaceitemDataService extends DataService<WorkspaceItem> {
|
||||||
protected linkPath = 'workspaceitems';
|
protected linkPath = 'workspaceitems';
|
||||||
protected forceBypassCache = true;
|
protected responseMsToLive = 10 * 1000;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected comparator: DSOChangeAnalyzer<WorkspaceItem>,
|
protected comparator: DSOChangeAnalyzer<WorkspaceItem>,
|
||||||
|
@@ -22,16 +22,13 @@ import { ProcessTaskResponse } from './models/process-task-response';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class ClaimedTaskDataService extends TasksService<ClaimedTask> {
|
export class ClaimedTaskDataService extends TasksService<ClaimedTask> {
|
||||||
|
|
||||||
|
protected responseMsToLive = 10 * 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The endpoint link name
|
* The endpoint link name
|
||||||
*/
|
*/
|
||||||
protected linkPath = 'claimedtasks';
|
protected linkPath = 'claimedtasks';
|
||||||
|
|
||||||
/**
|
|
||||||
* When true, a new request is always dispatched
|
|
||||||
*/
|
|
||||||
protected forceBypassCache = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize instance variables
|
* Initialize instance variables
|
||||||
*
|
*
|
||||||
|
@@ -27,10 +27,7 @@ export class PoolTaskDataService extends TasksService<PoolTask> {
|
|||||||
*/
|
*/
|
||||||
protected linkPath = 'pooltasks';
|
protected linkPath = 'pooltasks';
|
||||||
|
|
||||||
/**
|
protected responseMsToLive = 10 * 1000;
|
||||||
* When true, a new request is always dispatched
|
|
||||||
*/
|
|
||||||
protected forceBypassCache = true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize instance variables
|
* Initialize instance variables
|
||||||
|
@@ -29,7 +29,6 @@ class TestTask extends TaskObject {
|
|||||||
|
|
||||||
class TestService extends TasksService<TestTask> {
|
class TestService extends TasksService<TestTask> {
|
||||||
protected linkPath = LINK_NAME;
|
protected linkPath = LINK_NAME;
|
||||||
protected forceBypassCache = true;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected requestService: RequestService,
|
protected requestService: RequestService,
|
||||||
|
12
src/app/shared/mocks/mock-search-service.ts
Normal file
12
src/app/shared/mocks/mock-search-service.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { SearchService } from '../../+search-page/search-service/search.service';
|
||||||
|
|
||||||
|
export function getMockSearchService(): SearchService {
|
||||||
|
return jasmine.createSpyObj('searchService', {
|
||||||
|
search: '',
|
||||||
|
getEndpoint: observableOf('discover/search/objects'),
|
||||||
|
getSearchLink: '/mydspace',
|
||||||
|
getScopes: observableOf(['test-scope']),
|
||||||
|
setServiceOptions: {}
|
||||||
|
});
|
||||||
|
}
|
@@ -18,6 +18,10 @@ import { ClaimedTask } from '../../../core/tasks/models/claimed-task-object.mode
|
|||||||
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
|
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
|
||||||
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
||||||
import { CoreModule } from '../../../core/core.module';
|
import { CoreModule } from '../../../core/core.module';
|
||||||
|
import { getMockSearchService } from '../../mocks/mock-search-service';
|
||||||
|
import { getMockRequestService } from '../../mocks/mock-request.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
|
||||||
let component: ClaimedTaskActionsComponent;
|
let component: ClaimedTaskActionsComponent;
|
||||||
let fixture: ComponentFixture<ClaimedTaskActionsComponent>;
|
let fixture: ComponentFixture<ClaimedTaskActionsComponent>;
|
||||||
@@ -32,6 +36,10 @@ const mockDataService = jasmine.createSpyObj('ClaimedTaskDataService', {
|
|||||||
returnToPoolTask: jasmine.createSpy('returnToPoolTask'),
|
returnToPoolTask: jasmine.createSpy('returnToPoolTask'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const searchService = getMockSearchService();
|
||||||
|
|
||||||
|
const requestServce = getMockRequestService();
|
||||||
|
|
||||||
const item = Object.assign(new Item(), {
|
const item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf({}),
|
bitstreams: observableOf({}),
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -83,6 +91,8 @@ describe('ClaimedTaskActionsComponent', () => {
|
|||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{ provide: ClaimedTaskDataService, useValue: mockDataService },
|
{ provide: ClaimedTaskDataService, useValue: mockDataService },
|
||||||
|
{ provide: SearchService, useValue: searchService },
|
||||||
|
{ provide: RequestService, useValue: requestServce }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(ClaimedTaskActionsComponent, {
|
}).overrideComponent(ClaimedTaskActionsComponent, {
|
||||||
|
@@ -13,6 +13,8 @@ import { WorkflowItem } from '../../../core/submission/models/workflowitem.model
|
|||||||
import { RemoteData } from '../../../core/data/remote-data';
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represents actions related to ClaimedTask object.
|
* This component represents actions related to ClaimedTask object.
|
||||||
@@ -56,12 +58,16 @@ export class ClaimedTaskActionsComponent extends MyDSpaceActionsComponent<Claime
|
|||||||
* @param {Router} router
|
* @param {Router} router
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(protected injector: Injector,
|
constructor(protected injector: Injector,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
super(ClaimedTask.type, injector, router, notificationsService, translate);
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
|
super(ClaimedTask.type, injector, router, notificationsService, translate, searchService, requestService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -12,6 +12,10 @@ import { ItemActionsComponent } from './item-actions.component';
|
|||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../testing/notifications-service-stub';
|
import { NotificationsServiceStub } from '../../testing/notifications-service-stub';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
import { getMockSearchService } from '../../mocks/mock-search-service';
|
||||||
|
import { getMockRequestService } from '../../mocks/mock-request.service';
|
||||||
|
|
||||||
let component: ItemActionsComponent;
|
let component: ItemActionsComponent;
|
||||||
let fixture: ComponentFixture<ItemActionsComponent>;
|
let fixture: ComponentFixture<ItemActionsComponent>;
|
||||||
@@ -50,6 +54,10 @@ mockObject = Object.assign(new Item(), {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const searchService = getMockSearchService()
|
||||||
|
|
||||||
|
const requestServce = getMockRequestService();
|
||||||
|
|
||||||
describe('ItemActionsComponent', () => {
|
describe('ItemActionsComponent', () => {
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
@@ -67,6 +75,8 @@ describe('ItemActionsComponent', () => {
|
|||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{ provide: ItemDataService, useValue: mockDataService },
|
{ provide: ItemDataService, useValue: mockDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
|
{ provide: SearchService, useValue: searchService },
|
||||||
|
{ provide: RequestService, useValue: requestServce }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(ItemActionsComponent, {
|
}).overrideComponent(ItemActionsComponent, {
|
||||||
|
@@ -7,6 +7,8 @@ import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
|||||||
import { ItemDataService } from '../../../core/data/item-data.service';
|
import { ItemDataService } from '../../../core/data/item-data.service';
|
||||||
import { Item } from '../../../core/shared/item.model';
|
import { Item } from '../../../core/shared/item.model';
|
||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represents mydspace actions related to Item object.
|
* This component represents mydspace actions related to Item object.
|
||||||
@@ -31,12 +33,16 @@ export class ItemActionsComponent extends MyDSpaceActionsComponent<Item, ItemDat
|
|||||||
* @param {Router} router
|
* @param {Router} router
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(protected injector: Injector,
|
constructor(protected injector: Injector,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
super(Item.type, injector, router, notificationsService, translate);
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
|
super(Item.type, injector, router, notificationsService, translate, searchService, requestService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Injector, Input } from '@angular/core';
|
import { Injector, Input } from '@angular/core';
|
||||||
|
|
||||||
import { find } from 'rxjs/operators';
|
import { find, take, tap } from 'rxjs/operators';
|
||||||
|
|
||||||
import { MydspaceActionsServiceFactory } from './mydspace-actions-service.factory';
|
import { MydspaceActionsServiceFactory } from './mydspace-actions-service.factory';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
@@ -11,6 +11,9 @@ import { ResourceType } from '../../core/shared/resource-type';
|
|||||||
import { NotificationOptions } from '../notifications/models/notification-options.model';
|
import { NotificationOptions } from '../notifications/models/notification-options.model';
|
||||||
import { NotificationsService } from '../notifications/notifications.service';
|
import { NotificationsService } from '../notifications/notifications.service';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
import { SearchService } from '../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../core/data/request.service';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract class for all different representations of mydspace actions
|
* Abstract class for all different representations of mydspace actions
|
||||||
@@ -27,6 +30,8 @@ export abstract class MyDSpaceActionsComponent<T extends DSpaceObject, TService
|
|||||||
*/
|
*/
|
||||||
protected objectDataService: TService;
|
protected objectDataService: TService;
|
||||||
|
|
||||||
|
protected subscription: Subscription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize instance variables
|
* Initialize instance variables
|
||||||
*
|
*
|
||||||
@@ -35,13 +40,17 @@ export abstract class MyDSpaceActionsComponent<T extends DSpaceObject, TService
|
|||||||
* @param {Router} router
|
* @param {Router} router
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
protected objectType: ResourceType,
|
protected objectType: ResourceType,
|
||||||
protected injector: Injector,
|
protected injector: Injector,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
const factory = new MydspaceActionsServiceFactory<T, TService>();
|
const factory = new MydspaceActionsServiceFactory<T, TService>();
|
||||||
this.objectDataService = injector.get(factory.getConstructor(objectType));
|
this.objectDataService = injector.get(factory.getConstructor(objectType));
|
||||||
}
|
}
|
||||||
@@ -57,13 +66,18 @@ export abstract class MyDSpaceActionsComponent<T extends DSpaceObject, TService
|
|||||||
* Refresh current page
|
* Refresh current page
|
||||||
*/
|
*/
|
||||||
reload(): void {
|
reload(): void {
|
||||||
|
this.router.navigated = false;
|
||||||
|
const url = decodeURIComponent(this.router.url);
|
||||||
// override the route reuse strategy
|
// override the route reuse strategy
|
||||||
this.router.routeReuseStrategy.shouldReuseRoute = () => {
|
this.router.routeReuseStrategy.shouldReuseRoute = () => {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
this.router.navigated = false;
|
// This assures that the search cache is empty before reloading mydspace.
|
||||||
const url = decodeURIComponent(this.router.url);
|
// See https://github.com/DSpace/dspace-angular/pull/468
|
||||||
this.router.navigateByUrl(url);
|
this.searchService.getEndpoint().pipe(
|
||||||
|
take(1),
|
||||||
|
tap((cachedHref) => this.requestService.removeByHrefSubstring(cachedHref))
|
||||||
|
).subscribe(() => this.router.navigateByUrl(url));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -17,6 +17,10 @@ import { PoolTaskActionsComponent } from './pool-task-actions.component';
|
|||||||
import { PoolTask } from '../../../core/tasks/models/pool-task-object.model';
|
import { PoolTask } from '../../../core/tasks/models/pool-task-object.model';
|
||||||
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
|
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
|
||||||
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
||||||
|
import { getMockRequestService } from '../../mocks/mock-request.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
import { getMockSearchService } from '../../mocks/mock-search-service';
|
||||||
|
|
||||||
let component: PoolTaskActionsComponent;
|
let component: PoolTaskActionsComponent;
|
||||||
let fixture: ComponentFixture<PoolTaskActionsComponent>;
|
let fixture: ComponentFixture<PoolTaskActionsComponent>;
|
||||||
@@ -29,6 +33,10 @@ const mockDataService = jasmine.createSpyObj('PoolTaskDataService', {
|
|||||||
claimTask: jasmine.createSpy('claimTask')
|
claimTask: jasmine.createSpy('claimTask')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const searchService = getMockSearchService();
|
||||||
|
|
||||||
|
const requestServce = getMockRequestService();
|
||||||
|
|
||||||
const item = Object.assign(new Item(), {
|
const item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf({}),
|
bitstreams: observableOf({}),
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -80,6 +88,8 @@ describe('PoolTaskActionsComponent', () => {
|
|||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{ provide: PoolTaskDataService, useValue: mockDataService },
|
{ provide: PoolTaskDataService, useValue: mockDataService },
|
||||||
|
{ provide: SearchService, useValue: searchService },
|
||||||
|
{ provide: RequestService, useValue: requestServce }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(PoolTaskActionsComponent, {
|
}).overrideComponent(PoolTaskActionsComponent, {
|
||||||
@@ -167,4 +177,14 @@ describe('PoolTaskActionsComponent', () => {
|
|||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should clear the object cache by href', async(() => {
|
||||||
|
component.reload();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(searchService.getEndpoint).toHaveBeenCalled();
|
||||||
|
expect(requestServce.removeByHrefSubstring).toHaveBeenCalledWith('discover/search/objects');
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@@ -13,6 +13,8 @@ import { PoolTaskDataService } from '../../../core/tasks/pool-task-data.service'
|
|||||||
import { isNotUndefined } from '../../empty.util';
|
import { isNotUndefined } from '../../empty.util';
|
||||||
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represents mydspace actions related to PoolTask object.
|
* This component represents mydspace actions related to PoolTask object.
|
||||||
@@ -47,12 +49,16 @@ export class PoolTaskActionsComponent extends MyDSpaceActionsComponent<PoolTask,
|
|||||||
* @param {Router} router
|
* @param {Router} router
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(protected injector: Injector,
|
constructor(protected injector: Injector,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
super(PoolTask.type, injector, router, notificationsService, translate);
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
|
super(PoolTask.type, injector, router, notificationsService, translate, searchService, requestService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -15,6 +15,10 @@ import { WorkflowItemDataService } from '../../../core/submission/workflowitem-d
|
|||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
import { NotificationsServiceStub } from '../../testing/notifications-service-stub';
|
import { NotificationsServiceStub } from '../../testing/notifications-service-stub';
|
||||||
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
||||||
|
import { getMockRequestService } from '../../mocks/mock-request.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
import { getMockSearchService } from '../../mocks/mock-search-service';
|
||||||
|
|
||||||
let component: WorkflowitemActionsComponent;
|
let component: WorkflowitemActionsComponent;
|
||||||
let fixture: ComponentFixture<WorkflowitemActionsComponent>;
|
let fixture: ComponentFixture<WorkflowitemActionsComponent>;
|
||||||
@@ -23,6 +27,10 @@ let mockObject: WorkflowItem;
|
|||||||
|
|
||||||
const mockDataService = {};
|
const mockDataService = {};
|
||||||
|
|
||||||
|
const searchService = getMockSearchService();
|
||||||
|
|
||||||
|
const requestServce = getMockRequestService();
|
||||||
|
|
||||||
const item = Object.assign(new Item(), {
|
const item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf({}),
|
bitstreams: observableOf({}),
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -72,6 +80,8 @@ describe('WorkflowitemActionsComponent', () => {
|
|||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{ provide: WorkflowItemDataService, useValue: mockDataService },
|
{ provide: WorkflowItemDataService, useValue: mockDataService },
|
||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
|
{ provide: SearchService, useValue: searchService },
|
||||||
|
{ provide: RequestService, useValue: requestServce }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).overrideComponent(WorkflowitemActionsComponent, {
|
}).overrideComponent(WorkflowitemActionsComponent, {
|
||||||
|
@@ -7,6 +7,8 @@ import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
|||||||
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
|
import { WorkflowItem } from '../../../core/submission/models/workflowitem.model';
|
||||||
import { WorkflowItemDataService } from '../../../core/submission/workflowitem-data.service';
|
import { WorkflowItemDataService } from '../../../core/submission/workflowitem-data.service';
|
||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represents actions related to WorkflowItem object.
|
* This component represents actions related to WorkflowItem object.
|
||||||
@@ -30,12 +32,16 @@ export class WorkflowitemActionsComponent extends MyDSpaceActionsComponent<Workf
|
|||||||
* @param {Router} router
|
* @param {Router} router
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(protected injector: Injector,
|
constructor(protected injector: Injector,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
super(WorkflowItem.type, injector, router, notificationsService, translate);
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
|
super(WorkflowItem.type, injector, router, notificationsService, translate, searchService, requestService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,5 +52,4 @@ export class WorkflowitemActionsComponent extends MyDSpaceActionsComponent<Workf
|
|||||||
initObjects(object: WorkflowItem) {
|
initObjects(object: WorkflowItem) {
|
||||||
this.object = object;
|
this.object = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -17,6 +17,10 @@ import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.mod
|
|||||||
import { WorkspaceitemActionsComponent } from './workspaceitem-actions.component';
|
import { WorkspaceitemActionsComponent } from './workspaceitem-actions.component';
|
||||||
import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service';
|
import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service';
|
||||||
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
import { createSuccessfulRemoteDataObject } from '../../testing/utils';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
import { getMockRequestService } from '../../mocks/mock-request.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { getMockSearchService } from '../../mocks/mock-search-service';
|
||||||
|
|
||||||
let component: WorkspaceitemActionsComponent;
|
let component: WorkspaceitemActionsComponent;
|
||||||
let fixture: ComponentFixture<WorkspaceitemActionsComponent>;
|
let fixture: ComponentFixture<WorkspaceitemActionsComponent>;
|
||||||
@@ -28,6 +32,10 @@ const mockDataService = jasmine.createSpyObj('WorkspaceitemDataService', {
|
|||||||
delete: jasmine.createSpy('delete')
|
delete: jasmine.createSpy('delete')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const searchService = getMockSearchService();
|
||||||
|
|
||||||
|
const requestServce = getMockRequestService();
|
||||||
|
|
||||||
const item = Object.assign(new Item(), {
|
const item = Object.assign(new Item(), {
|
||||||
bitstreams: observableOf({}),
|
bitstreams: observableOf({}),
|
||||||
metadata: {
|
metadata: {
|
||||||
@@ -62,6 +70,7 @@ mockObject = Object.assign(new WorkspaceItem(), { item: observableOf(rd), id: '1
|
|||||||
|
|
||||||
describe('WorkspaceitemActionsComponent', () => {
|
describe('WorkspaceitemActionsComponent', () => {
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
NgbModule.forRoot(),
|
NgbModule.forRoot(),
|
||||||
@@ -78,6 +87,8 @@ describe('WorkspaceitemActionsComponent', () => {
|
|||||||
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
{ provide: NotificationsService, useValue: new NotificationsServiceStub() },
|
||||||
{ provide: Router, useValue: new RouterStub() },
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
{ provide: WorkspaceitemDataService, useValue: mockDataService },
|
{ provide: WorkspaceitemDataService, useValue: mockDataService },
|
||||||
|
{ provide: SearchService, useValue: searchService },
|
||||||
|
{ provide: RequestService, useValue: requestServce },
|
||||||
NgbModal
|
NgbModal
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -161,4 +172,14 @@ describe('WorkspaceitemActionsComponent', () => {
|
|||||||
expect(notificationsServiceStub.error).toHaveBeenCalled();
|
expect(notificationsServiceStub.error).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should clear the object cache by href', async(() => {
|
||||||
|
component.reload();
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
fixture.whenStable().then(() => {
|
||||||
|
expect(searchService.getEndpoint).toHaveBeenCalled();
|
||||||
|
expect(requestServce.removeByHrefSubstring).toHaveBeenCalledWith('discover/search/objects');
|
||||||
|
});
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Injector, Input } from '@angular/core';
|
import { Component, Injector, Input, OnDestroy } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
import { BehaviorSubject } from 'rxjs';
|
import { BehaviorSubject } from 'rxjs';
|
||||||
@@ -9,6 +9,8 @@ import { WorkspaceItem } from '../../../core/submission/models/workspaceitem.mod
|
|||||||
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
import { MyDSpaceActionsComponent } from '../mydspace-actions';
|
||||||
import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service';
|
import { WorkspaceitemDataService } from '../../../core/submission/workspaceitem-data.service';
|
||||||
import { NotificationsService } from '../../notifications/notifications.service';
|
import { NotificationsService } from '../../notifications/notifications.service';
|
||||||
|
import { SearchService } from '../../../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../../../core/data/request.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represents actions related to WorkspaceItem object.
|
* This component represents actions related to WorkspaceItem object.
|
||||||
@@ -39,13 +41,17 @@ export class WorkspaceitemActionsComponent extends MyDSpaceActionsComponent<Work
|
|||||||
* @param {NgbModal} modalService
|
* @param {NgbModal} modalService
|
||||||
* @param {NotificationsService} notificationsService
|
* @param {NotificationsService} notificationsService
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(protected injector: Injector,
|
constructor(protected injector: Injector,
|
||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected modalService: NgbModal,
|
protected modalService: NgbModal,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
super(WorkspaceItem.type, injector, router, notificationsService, translate);
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
|
super(WorkspaceItem.type, injector, router, notificationsService, translate, searchService, requestService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -45,6 +45,10 @@ import {
|
|||||||
createSuccessfulRemoteDataObject,
|
createSuccessfulRemoteDataObject,
|
||||||
createSuccessfulRemoteDataObject$
|
createSuccessfulRemoteDataObject$
|
||||||
} from '../shared/testing/utils';
|
} from '../shared/testing/utils';
|
||||||
|
import { getMockSearchService } from '../shared/mocks/mock-search-service';
|
||||||
|
import { getMockRequestService } from '../shared/mocks/mock-request.service';
|
||||||
|
import { SearchService } from '../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../core/data/request.service';
|
||||||
|
|
||||||
describe('SubmissionService test suite', () => {
|
describe('SubmissionService test suite', () => {
|
||||||
const config = MOCK_SUBMISSION_CONFIG;
|
const config = MOCK_SUBMISSION_CONFIG;
|
||||||
@@ -349,7 +353,12 @@ describe('SubmissionService test suite', () => {
|
|||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
let service: SubmissionService;
|
let service: SubmissionService;
|
||||||
|
|
||||||
|
const searchService = getMockSearchService();
|
||||||
|
|
||||||
|
const requestServce = getMockRequestService();
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
|
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [
|
imports: [
|
||||||
StoreModule.forRoot({ submissionReducers } as any),
|
StoreModule.forRoot({ submissionReducers } as any),
|
||||||
@@ -365,6 +374,8 @@ describe('SubmissionService test suite', () => {
|
|||||||
{ provide: Router, useValue: router },
|
{ provide: Router, useValue: router },
|
||||||
{ provide: SubmissionRestService, useValue: restService },
|
{ provide: SubmissionRestService, useValue: restService },
|
||||||
{ provide: ActivatedRoute, useValue: new MockActivatedRoute() },
|
{ provide: ActivatedRoute, useValue: new MockActivatedRoute() },
|
||||||
|
{ provide: SearchService, useValue: searchService },
|
||||||
|
{ provide: RequestService, useValue: requestServce },
|
||||||
NotificationsService,
|
NotificationsService,
|
||||||
RouteService,
|
RouteService,
|
||||||
SubmissionService,
|
SubmissionService,
|
||||||
|
@@ -4,13 +4,12 @@ import { Router } from '@angular/router';
|
|||||||
|
|
||||||
import { Observable, of as observableOf, Subscription, timer as observableTimer } from 'rxjs';
|
import { Observable, of as observableOf, Subscription, timer as observableTimer } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
catchError,
|
catchError, concatMap,
|
||||||
distinctUntilChanged,
|
distinctUntilChanged,
|
||||||
filter,
|
filter,
|
||||||
find,
|
find,
|
||||||
first,
|
|
||||||
map,
|
map,
|
||||||
startWith
|
startWith, take, tap
|
||||||
} from 'rxjs/operators';
|
} from 'rxjs/operators';
|
||||||
import { Store } from '@ngrx/store';
|
import { Store } from '@ngrx/store';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
@@ -56,6 +55,8 @@ import {
|
|||||||
createSuccessfulRemoteDataObject,
|
createSuccessfulRemoteDataObject,
|
||||||
createSuccessfulRemoteDataObject$
|
createSuccessfulRemoteDataObject$
|
||||||
} from '../shared/testing/utils';
|
} from '../shared/testing/utils';
|
||||||
|
import { SearchService } from '../+search-page/search-service/search.service';
|
||||||
|
import { RequestService } from '../core/data/request.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A service that provides methods used in submission process.
|
* A service that provides methods used in submission process.
|
||||||
@@ -82,6 +83,8 @@ export class SubmissionService {
|
|||||||
* @param {RouteService} routeService
|
* @param {RouteService} routeService
|
||||||
* @param {Store<SubmissionState>} store
|
* @param {Store<SubmissionState>} store
|
||||||
* @param {TranslateService} translate
|
* @param {TranslateService} translate
|
||||||
|
* @param {SearchService} searchService
|
||||||
|
* @param {RequestService} requestService
|
||||||
*/
|
*/
|
||||||
constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
|
constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
|
||||||
protected notificationsService: NotificationsService,
|
protected notificationsService: NotificationsService,
|
||||||
@@ -89,7 +92,9 @@ export class SubmissionService {
|
|||||||
protected router: Router,
|
protected router: Router,
|
||||||
protected routeService: RouteService,
|
protected routeService: RouteService,
|
||||||
protected store: Store<SubmissionState>,
|
protected store: Store<SubmissionState>,
|
||||||
protected translate: TranslateService) {
|
protected translate: TranslateService,
|
||||||
|
protected searchService: SearchService,
|
||||||
|
protected requestService: RequestService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -460,16 +465,23 @@ export class SubmissionService {
|
|||||||
* Redirect to MyDspace page
|
* Redirect to MyDspace page
|
||||||
*/
|
*/
|
||||||
redirectToMyDSpace() {
|
redirectToMyDSpace() {
|
||||||
this.routeService.getPreviousUrl().pipe(
|
// This assures that the cache is empty before redirecting to mydspace.
|
||||||
first()
|
// See https://github.com/DSpace/dspace-angular/pull/468
|
||||||
).subscribe((previousUrl: string) => {
|
this.searchService.getEndpoint().pipe(
|
||||||
|
take(1),
|
||||||
|
tap((url) => this.requestService.removeByHrefSubstring(url)),
|
||||||
|
// Now, do redirect.
|
||||||
|
concatMap(
|
||||||
|
() => this.routeService.getPreviousUrl().pipe(
|
||||||
|
take(1),
|
||||||
|
tap((previousUrl) => {
|
||||||
if (isEmpty(previousUrl) || !previousUrl.startsWith('/mydspace')) {
|
if (isEmpty(previousUrl) || !previousUrl.startsWith('/mydspace')) {
|
||||||
this.router.navigate(['/mydspace']);
|
this.router.navigate(['/mydspace']);
|
||||||
} else {
|
} else {
|
||||||
this.router.navigateByUrl(previousUrl);
|
this.router.navigateByUrl(previousUrl);
|
||||||
}
|
}
|
||||||
});
|
})))
|
||||||
|
).subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user