Add Item Status Edit Actions

Add the Item Withdraw and Reistate action
Add the make Item Private and Public action
Add the Permanently Delete action
This commit is contained in:
Yana De Pauw
2018-12-18 16:52:11 +01:00
parent a3b4883e2d
commit d9a393c8e6
38 changed files with 1984 additions and 76 deletions

View File

@@ -1,24 +1,44 @@
import { Store } from '@ngrx/store';
import { cold, getTestScheduler } from 'jasmine-marbles';
import { TestScheduler } from 'rxjs/testing';
import { BrowseService } from '../browse/browse.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { ResponseCacheService } from '../cache/response-cache.service';
import { CoreState } from '../core.reducers';
import { ItemDataService } from './item-data.service';
import { RequestService } from './request.service';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { FindAllOptions } from './request.models';
import {Store} from '@ngrx/store';
import {cold, getTestScheduler} from 'jasmine-marbles';
import {TestScheduler} from 'rxjs/testing';
import {BrowseService} from '../browse/browse.service';
import {RemoteDataBuildService} from '../cache/builders/remote-data-build.service';
import {ResponseCacheService} from '../cache/response-cache.service';
import {CoreState} from '../core.reducers';
import {ItemDataService} from './item-data.service';
import {RequestService} from './request.service';
import {HALEndpointService} from '../shared/hal-endpoint.service';
import {FindAllOptions, RestRequest} from './request.models';
import {Observable, of as observableOf} from 'rxjs';
import {ResponseCacheEntry} from '../cache/response-cache.reducer';
import {RestResponse} from '../cache/response-cache.models';
describe('ItemDataService', () => {
let scheduler: TestScheduler;
let service: ItemDataService;
let bs: BrowseService;
const requestService = {} as RequestService;
const responseCache = {} as ResponseCacheService;
const requestService = {
generateRequestId(): string {
return scopeID;
},
configure(request: RestRequest) {
// Do nothing
}
} as RequestService;
const responseCache = {
get(href: string) {
const responseCacheEntry = new ResponseCacheEntry();
responseCacheEntry.response = new RestResponse(true, '200');
return observableOf(responseCacheEntry);
}
} as ResponseCacheService;
const rdbService = {} as RemoteDataBuildService;
const store = {} as Store<CoreState>;
const halEndpointService = {} as HALEndpointService;
const halEndpointService = {
getEndpoint(linkPath: string): Observable<string> {
return cold('a', {a: itemEndpoint});
}
} as HALEndpointService;
const scopeID = '4af28e99-6a9c-4036-a199-e1b587046d39';
const options = Object.assign(new FindAllOptions(), {
@@ -34,10 +54,12 @@ describe('ItemDataService', () => {
const scopedEndpoint = `${itemBrowseEndpoint}?scope=${scopeID}`;
const serviceEndpoint = `https://rest.api/core/items`;
const browseError = new Error('getBrowseURL failed');
const itemEndpoint = 'https://rest.api/core/items';
const ScopedItemEndpoint = `https://rest.api/core/items/${scopeID}`;
function initMockBrowseService(isSuccessful: boolean) {
const obs = isSuccessful ?
cold('--a-', { a: itemBrowseEndpoint }) :
cold('--a-', {a: itemBrowseEndpoint}) :
cold('--#-', undefined, browseError);
return jasmine.createSpyObj('bs', {
getBrowseURLFor: obs
@@ -65,7 +87,7 @@ describe('ItemDataService', () => {
service = initTestService();
const result = service.getBrowseEndpoint(options);
const expected = cold('--b-', { b: scopedEndpoint });
const expected = cold('--b-', {b: scopedEndpoint});
expect(result).toBeObservable(expected);
});
@@ -83,4 +105,70 @@ describe('ItemDataService', () => {
});
});
});
describe('getItemWithdrawEndpoint', () => {
beforeEach(() => {
scheduler = getTestScheduler();
service = initTestService();
});
it('should return the endpoint to withdraw and reinstate items', () => {
const result = service.getItemWithdrawEndpoint(scopeID);
const expected = cold('a', {a: ScopedItemEndpoint});
expect(result).toBeObservable(expected);
});
it('should setWithDrawn', () => {
const expected = new RestResponse(true, '200');
const result = service.setWithDrawn(scopeID, true);
result.subscribe((v) => expect(v).toEqual(expected));
});
});
describe('getItemDiscoverableEndpoint', () => {
beforeEach(() => {
scheduler = getTestScheduler();
service = initTestService();
});
it('should return the endpoint to make an item private or public', () => {
const result = service.getItemDiscoverableEndpoint(scopeID);
const expected = cold('a', {a: ScopedItemEndpoint});
expect(result).toBeObservable(expected);
});
it('should setDiscoverable', () => {
const expected = new RestResponse(true, '200');
const result = service.setDiscoverable(scopeID, false);
result.subscribe((v) => expect(v).toEqual(expected));
});
});
describe('getItemDeleteEndpoint', () => {
beforeEach(() => {
scheduler = getTestScheduler();
service = initTestService();
});
it('should return the endpoint to make an item private or public', () => {
const result = service.getItemDeleteEndpoint(scopeID);
const expected = cold('a', {a: ScopedItemEndpoint});
expect(result).toBeObservable(expected);
});
it('should delete the item', () => {
const expected = new RestResponse(true, '200');
const result = service.delete(scopeID);
result.subscribe((v) => expect(v).toEqual(expected));
});
});
});

View File

@@ -1,21 +1,22 @@
import {distinctUntilChanged, filter, map} from 'rxjs/operators';
import {Injectable} from '@angular/core';
import {Store} from '@ngrx/store';
import {Observable} from 'rxjs';
import {isNotEmpty} from '../../shared/empty.util';
import {BrowseService} from '../browse/browse.service';
import {RemoteDataBuildService} from '../cache/builders/remote-data-build.service';
import {NormalizedItem} from '../cache/models/normalized-item.model';
import {ResponseCacheService} from '../cache/response-cache.service';
import {CoreState} from '../core.reducers';
import {Item} from '../shared/item.model';
import {URLCombiner} from '../url-combiner/url-combiner';
import {distinctUntilChanged, map, filter} from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { isNotEmpty } from '../../shared/empty.util';
import { BrowseService } from '../browse/browse.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { NormalizedItem } from '../cache/models/normalized-item.model';
import { ResponseCacheService } from '../cache/response-cache.service';
import { CoreState } from '../core.reducers';
import { Item } from '../shared/item.model';
import { URLCombiner } from '../url-combiner/url-combiner';
import { DataService } from './data.service';
import { RequestService } from './request.service';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { FindAllOptions } from './request.models';
import {DataService} from './data.service';
import {RequestService} from './request.service';
import {HALEndpointService} from '../shared/hal-endpoint.service';
import {DeleteRequest, FindAllOptions, PatchRequest, RestRequest} from './request.models';
import {configureRequest, getResponseFromSelflink} from '../shared/operators';
import {ResponseCacheEntry} from '../cache/response-cache.reducer';
@Injectable()
export class ItemDataService extends DataService<NormalizedItem, Item> {
@@ -48,4 +49,93 @@ export class ItemDataService extends DataService<NormalizedItem, Item> {
distinctUntilChanged(),);
}
/**
* Get the endpoint for item withdrawal and reinstatement
* @param itemId
*/
public getItemWithdrawEndpoint(itemId: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getFindByIDHref(endpoint, itemId))
);
}
/**
* Get the endpoint to make item private and public
* @param itemId
*/
public getItemDiscoverableEndpoint(itemId: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getFindByIDHref(endpoint, itemId))
);
}
/**
* Get the endpoint to delete the item
* @param itemId
*/
public getItemDeleteEndpoint(itemId: string): Observable<string> {
return this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getFindByIDHref(endpoint, itemId))
);
}
/**
* Set the isWithdrawn state of an item to a specified state
* @param itemId
* @param withdrawn
*/
public setWithDrawn(itemId: string, withdrawn: boolean) {
const patchOperation = [{
op: 'replace', path: '/withdrawn', value: withdrawn
}];
return this.getItemWithdrawEndpoint(itemId).pipe(
distinctUntilChanged(),
map((endpointURL: string) =>
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
),
configureRequest(this.requestService),
map((request: RestRequest) => request.href),
getResponseFromSelflink(this.responseCache),
map((responseCacheEntry: ResponseCacheEntry) => responseCacheEntry.response)
);
}
/**
* Set the isDiscoverable state of an item to a specified state
* @param itemId
* @param discoverable
*/
public setDiscoverable(itemId: string, discoverable: boolean) {
const patchOperation = [{
op: 'replace', path: '/discoverable', value: discoverable
}];
return this.getItemDiscoverableEndpoint(itemId).pipe(
distinctUntilChanged(),
map((endpointURL: string) =>
new PatchRequest(this.requestService.generateRequestId(), endpointURL, patchOperation)
),
configureRequest(this.requestService),
map((request: RestRequest) => request.href),
getResponseFromSelflink(this.responseCache),
map((responseCacheEntry: ResponseCacheEntry) => responseCacheEntry.response)
);
}
/**
* Delete the item
* @param itemId
*/
public delete(itemId: string) {
return this.getItemDeleteEndpoint(itemId).pipe(
distinctUntilChanged(),
map((endpointURL: string) =>
new DeleteRequest(this.requestService.generateRequestId(), endpointURL)
),
configureRequest(this.requestService),
map((request: RestRequest) => request.href),
getResponseFromSelflink(this.responseCache),
map((responseCacheEntry: ResponseCacheEntry) => responseCacheEntry.response)
);
}
}