refactor, clean up

This commit is contained in:
FrancescoMolinaro
2024-01-25 13:22:17 +01:00
parent 66cd035f87
commit d4bf3a519a
12 changed files with 72 additions and 193 deletions

View File

@@ -1,84 +1,85 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Operation } from 'fast-json-patch'; import { Operation } from 'fast-json-patch';
import { AsyncSubject, combineLatest, from as observableFrom, Observable, of as observableOf } from 'rxjs'; import { AsyncSubject, from as observableFrom, Observable } from 'rxjs';
import { import {
distinctUntilChanged,
filter,
find, find,
map, map,
mergeMap, mergeMap,
skipWhile,
switchMap, switchMap,
take, take,
takeWhile,
tap,
toArray toArray
} from 'rxjs/operators'; } from 'rxjs/operators';
import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { hasValue } from '../../shared/empty.util';
import { NotificationOptions } from '../../shared/notifications/models/notification-options.model';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model'; import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { getClassForType } from '../cache/builders/build-decorators';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service'; import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { RequestParam } from '../cache/models/request-param.model'; import { RequestParam } from '../cache/models/request-param.model';
import { ObjectCacheEntry } from '../cache/object-cache.reducer'; import { ObjectCacheEntry } from '../cache/object-cache.reducer';
import { ObjectCacheService } from '../cache/object-cache.service'; import { ObjectCacheService } from '../cache/object-cache.service';
import { DSpaceSerializer } from '../dspace-rest/dspace.serializer';
import { HALEndpointService } from '../shared/hal-endpoint.service'; import { HALEndpointService } from '../shared/hal-endpoint.service';
import { getFirstCompletedRemoteData, getFirstSucceededRemoteData, getRemoteDataPayload } from '../shared/operators';
import { URLCombiner } from '../url-combiner/url-combiner';
import { ChangeAnalyzer } from './change-analyzer'; import { ChangeAnalyzer } from './change-analyzer';
import { PaginatedList } from './paginated-list.model'; import { PaginatedList } from './paginated-list.model';
import { RemoteData } from './remote-data'; import { RemoteData } from './remote-data';
import { import {
CreateRequest,
DeleteByIDRequest, DeleteByIDRequest,
DeleteRequest, PostRequest
GetRequest,
PatchRequest,
PostRequest,
PutRequest
} from './request.models'; } from './request.models';
import { RequestService } from './request.service'; import { RequestService } from './request.service';
import { RestRequestMethod } from './rest-request-method'; import { RestRequestMethod } from './rest-request-method';
import { GenericConstructor } from '../shared/generic-constructor';
import { NoContent } from '../shared/NoContent.model'; import { NoContent } from '../shared/NoContent.model';
import { CacheableObject } from '../cache/cacheable-object.model'; import { CacheableObject } from '../cache/cacheable-object.model';
import { CoreState } from '../core-state.model'; import { CoreState } from '../core-state.model';
import { FindListOptions } from './find-list-options.model'; import { FindListOptions } from './find-list-options.model';
import { BaseDataService } from "./base/base-data.service"; import { FindAllData, FindAllDataImpl } from './base/find-all-data';
import { FindAllData, FindAllDataImpl } from "./base/find-all-data"; import { SearchData, SearchDataImpl } from './base/search-data';
import { SearchData, SearchDataImpl } from "./base/search-data"; import { CreateData, CreateDataImpl } from './base/create-data';
import { CreateData, CreateDataImpl } from "./base/create-data"; import { PatchData, PatchDataImpl } from './base/patch-data';
import { IdentifiableDataService } from './base/identifiable-data.service';
import { PutData, PutDataImpl } from './base/put-data';
import { DeleteData, DeleteDataImpl } from './base/delete-data';
/**
* Interface to list the methods used by the injected service in components
*/
export interface UpdateDataService<T> { export interface UpdateDataService<T> {
patch(dso: T, operations: Operation[]): Observable<RemoteData<T>>; patch(dso: T, operations: Operation[]): Observable<RemoteData<T>>;
update(object: T): Observable<RemoteData<T>>; update(object: T): Observable<RemoteData<T>>;
commitUpdates(method?: RestRequestMethod); commitUpdates(method?: RestRequestMethod): void;
} }
/** /**
* Specific functionalities that not all services would need. * Specific functionalities that not all services would need.
* Goal of the class is to update remote objects, handling custom methods that don't belong to BaseDataService * Goal of the class is to update remote objects, handling custom methods that don't belong to BaseDataService
* The class implements also the following common interfaces
*
* findAllData: FindAllData<T>;
* searchData: SearchData<T>;
* createData: CreateData<T>;
* patchData: PatchData<T>;
* putData: PutData<T>;
* deleteData: DeleteData<T>;
* *
* Custom methods are: * Custom methods are:
* *
* patch - Sends a patch request to modify current object * deleteOnRelated - delete all related objects to the given one
* update - Add a new patch to the object cache, diff between given object and cache * postOnRelated - post all the related objects to the given one
* commitUpdates - Sends the updates to the server * invalidate - invalidate the DSpaceObject making all requests as stale
* invalidateByHref - invalidate the href making all requests as stale
*/ */
export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends IdentifiableDataService<T> implements FindAllData<T>, SearchData<T>, CreateData<T>, PatchData<T>, PutData<T>, DeleteData<T> {
export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends BaseDataService<T> implements UpdateDataService<T>, FindAllData<T>, SearchData<T>, CreateData<T> {
protected abstract store: Store<CoreState>; protected abstract store: Store<CoreState>;
protected abstract http: HttpClient; protected abstract http: HttpClient;
protected abstract comparator: ChangeAnalyzer<T>;
private findAllData: FindAllDataImpl<T>; private findAllData: FindAllDataImpl<T>;
private searchData: SearchDataImpl<T>; private searchData: SearchDataImpl<T>;
private createData: CreateData<T>; private createData: CreateDataImpl<T>;
private patchData: PatchDataImpl<T>;
private putData: PutDataImpl<T>;
private deleteData: DeleteDataImpl<T>;
constructor( constructor(
@@ -88,12 +89,16 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
protected objectCache: ObjectCacheService, protected objectCache: ObjectCacheService,
protected halService: HALEndpointService, protected halService: HALEndpointService,
protected notificationsService: NotificationsService, protected notificationsService: NotificationsService,
protected comparator: ChangeAnalyzer<T>,
protected responseMsToLive: number, protected responseMsToLive: number,
) { ) {
super(linkPath, requestService, rdbService, objectCache, halService, responseMsToLive); super(linkPath, requestService, rdbService, objectCache, halService, responseMsToLive);
this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive); this.searchData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService ,this.responseMsToLive); this.createData = new CreateDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService ,this.responseMsToLive);
this.patchData = new PatchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, comparator ,this.responseMsToLive, this.constructIdEndpoint);
this.putData = new PutDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
this.deleteData = new DeleteDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, notificationsService ,this.responseMsToLive, this.constructIdEndpoint);
} }
@@ -107,7 +112,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
*/ */
public getFindAllHref(options: FindListOptions = {}, linkPath?: string, ...linksToFollow: FollowLinkConfig<T>[]): Observable<string> { public getFindAllHref(options: FindListOptions = {}, linkPath?: string, ...linksToFollow: FollowLinkConfig<T>[]): Observable<string> {
return this.findAllData.getFindAllHref(options, linkPath, ...linksToFollow) return this.findAllData.getFindAllHref(options, linkPath, ...linksToFollow);
} }
/** /**
@@ -120,7 +125,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved * @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
*/ */
public getSearchByHref(searchMethod: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig<T>[]): Observable<string> { public getSearchByHref(searchMethod: string, options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig<T>[]): Observable<string> {
return this.searchData.getSearchByHref(searchMethod, options, ...linksToFollow) return this.searchData.getSearchByHref(searchMethod, options, ...linksToFollow);
} }
/** /**
@@ -138,27 +143,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* Return an observable that emits object list * Return an observable that emits object list
*/ */
findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<T>[]): Observable<RemoteData<PaginatedList<T>>> { findAll(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<T>[]): Observable<RemoteData<PaginatedList<T>>> {
return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow) return this.findAllData.findAll(options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
}
/**
* Create the HREF for a specific object based on its identifier; with possible embed query params based on linksToFollow
* @param endpoint The base endpoint for the type of object
* @param resourceID The identifier for the object
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
*/
getIDHref(endpoint, resourceID, ...linksToFollow: FollowLinkConfig<T>[]): string {
return this.buildHrefFromFindOptions(endpoint + '/' + resourceID, {}, [], ...linksToFollow);
}
/**
* Create an observable for the HREF of a specific object based on its identifier
* @param resourceID The identifier for the object
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
*/
getIDHrefObs(resourceID: string, ...linksToFollow: FollowLinkConfig<T>[]): Observable<string> {
return this.getEndpoint().pipe(
map((endpoint: string) => this.getIDHref(endpoint, resourceID, ...linksToFollow)));
} }
/** /**
@@ -177,29 +162,6 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
return this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow); return this.findByHref(href$, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
} }
/**
* An operator that will call the given function if the incoming RemoteData is stale and
* shouldReRequest is true
*
* @param shouldReRequest Whether or not to call the re-request function if the RemoteData is stale
* @param requestFn The function to call if the RemoteData is stale and shouldReRequest is
* true
*/
protected reRequestStaleRemoteData<O>(shouldReRequest: boolean, requestFn: () => Observable<RemoteData<O>>) {
return (source: Observable<RemoteData<O>>): Observable<RemoteData<O>> => {
if (shouldReRequest === true) {
return source.pipe(
tap((remoteData: RemoteData<O>) => {
if (hasValue(remoteData) && remoteData.isStale) {
requestFn();
}
})
);
} else {
return source;
}
};
}
/** /**
* Make a new FindListRequest with given search method * Make a new FindListRequest with given search method
@@ -216,7 +178,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* Return an observable that emits response from the server * Return an observable that emits response from the server
*/ */
searchBy(searchMethod: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<T>[]): Observable<RemoteData<PaginatedList<T>>> { searchBy(searchMethod: string, options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<T>[]): Observable<RemoteData<PaginatedList<T>>> {
return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow) return this.searchData.searchBy(searchMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
} }
/** /**
@@ -225,30 +187,11 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* @param {Operation[]} operations The patch operations to be performed * @param {Operation[]} operations The patch operations to be performed
*/ */
patch(object: T, operations: Operation[]): Observable<RemoteData<T>> { patch(object: T, operations: Operation[]): Observable<RemoteData<T>> {
const requestId = this.requestService.generateRequestId(); return this.patchData.patch(object, operations);
const hrefObs = this.halService.getEndpoint(this.linkPath).pipe(
map((endpoint: string) => this.getIDHref(endpoint, object.uuid)));
hrefObs.pipe(
find((href: string) => hasValue(href)),
).subscribe((href: string) => {
const request = new PatchRequest(requestId, href, operations);
if (hasValue(this.responseMsToLive)) {
request.responseMsToLive = this.responseMsToLive;
}
this.requestService.send(request);
});
return this.rdbService.buildFromRequestUUID(requestId);
} }
createPatchFromCache(object: T): Observable<Operation[]> { createPatchFromCache(object: T): Observable<Operation[]> {
const oldVersion$ = this.findByHref(object._links.self.href, true, false); return this.patchData.createPatchFromCache(object);
return oldVersion$.pipe(
getFirstSucceededRemoteData(),
getRemoteDataPayload(),
map((oldVersion: T) => this.comparator.diff(oldVersion, object)));
} }
/** /**
@@ -257,17 +200,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* @param object The object to send a put request for. * @param object The object to send a put request for.
*/ */
put(object: T): Observable<RemoteData<T>> { put(object: T): Observable<RemoteData<T>> {
const requestId = this.requestService.generateRequestId(); return this.putData.put(object);
const serializedObject = new DSpaceSerializer(object.constructor as GenericConstructor<{}>).serialize(object);
const request = new PutRequest(requestId, object._links.self.href, serializedObject);
if (hasValue(this.responseMsToLive)) {
request.responseMsToLive = this.responseMsToLive;
}
this.requestService.send(request);
return this.rdbService.buildFromRequestUUID(requestId);
} }
/** /**
@@ -276,16 +209,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* @param {DSpaceObject} object The given object * @param {DSpaceObject} object The given object
*/ */
update(object: T): Observable<RemoteData<T>> { update(object: T): Observable<RemoteData<T>> {
return this.createPatchFromCache(object) return this.patchData.update(object);
.pipe(
mergeMap((operations: Operation[]) => {
if (isNotEmpty(operations)) {
this.objectCache.addPatch(object._links.self.href, operations);
}
return this.findByHref(object._links.self.href, true, true);
}
)
);
} }
/** /**
@@ -298,7 +222,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* Array with additional params to combine with query string * Array with additional params to combine with query string
*/ */
create(object: T, ...params: RequestParam[]): Observable<RemoteData<T>> { create(object: T, ...params: RequestParam[]): Observable<RemoteData<T>> {
return this.createData.create(object, ...params) return this.createData.create(object, ...params);
} }
/** /**
@@ -390,9 +314,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* errorMessage, timeCompleted, etc * errorMessage, timeCompleted, etc
*/ */
delete(objectId: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> { delete(objectId: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> {
return this.getIDHrefObs(objectId).pipe( return this.deleteData.delete(objectId, copyVirtualMetadata);
switchMap((href: string) => this.deleteByHref(href, copyVirtualMetadata))
);
} }
/** /**
@@ -405,43 +327,7 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* Only emits once all request related to the DSO has been invalidated. * Only emits once all request related to the DSO has been invalidated.
*/ */
deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> { deleteByHref(href: string, copyVirtualMetadata?: string[]): Observable<RemoteData<NoContent>> {
const requestId = this.requestService.generateRequestId(); return this.deleteData.deleteByHref(href, copyVirtualMetadata);
if (copyVirtualMetadata) {
copyVirtualMetadata.forEach((id) =>
href += (href.includes('?') ? '&' : '?')
+ 'copyVirtualMetadata='
+ id
);
}
const request = new DeleteRequest(requestId, href);
if (hasValue(this.responseMsToLive)) {
request.responseMsToLive = this.responseMsToLive;
}
this.requestService.send(request);
const response$ = this.rdbService.buildFromRequestUUID(requestId);
const invalidated$ = new AsyncSubject<boolean>();
response$.pipe(
getFirstCompletedRemoteData(),
switchMap((rd: RemoteData<NoContent>) => {
if (rd.hasSucceeded) {
return this.invalidateByHref(href);
} else {
return [true];
}
})
).subscribe(() => {
invalidated$.next(true);
invalidated$.complete();
});
return combineLatest([response$, invalidated$]).pipe(
filter(([_, invalidated]) => invalidated),
map(([response, _]) => response),
);
} }
/** /**
@@ -449,6 +335,6 @@ export abstract class UpdateDataServiceImpl<T extends CacheableObject> extends B
* @param method The RestRequestMethod for which de server sync buffer should be committed * @param method The RestRequestMethod for which de server sync buffer should be committed
*/ */
commitUpdates(method?: RestRequestMethod) { commitUpdates(method?: RestRequestMethod) {
this.requestService.commit(method); this.patchData.commitUpdates(method);
} }
} }

View File

@@ -58,7 +58,7 @@ export class SuggestionDataServiceImpl extends UpdateDataServiceImpl<Suggestion>
protected comparator: ChangeAnalyzer<Suggestion>, protected comparator: ChangeAnalyzer<Suggestion>,
protected responseMsToLive: number, protected responseMsToLive: number,
) { ) {
super('suggestions', requestService, rdbService, objectCache, halService, notificationsService ,responseMsToLive); super('suggestions', requestService, rdbService, objectCache, halService, notificationsService, comparator ,responseMsToLive);
} }
} }
@@ -99,7 +99,6 @@ export class SuggestionsDataService {
* @param {DefaultChangeAnalyzer<Suggestion>} comparatorSuggestions * @param {DefaultChangeAnalyzer<Suggestion>} comparatorSuggestions
* @param {DefaultChangeAnalyzer<SuggestionSource>} comparatorSources * @param {DefaultChangeAnalyzer<SuggestionSource>} comparatorSources
* @param {DefaultChangeAnalyzer<SuggestionTarget>} comparatorTargets * @param {DefaultChangeAnalyzer<SuggestionTarget>} comparatorTargets
* @param responseMsToLive
*/ */
constructor( constructor(
protected requestService: RequestService, protected requestService: RequestService,

View File

@@ -21,7 +21,7 @@ import { ArrayMoveChangeAnalyzer } from '../../core/data/array-move-change-analy
import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator'; import { DATA_SERVICE_FACTORY } from '../../core/data/base/data-service.decorator';
import { GenericConstructor } from '../../core/shared/generic-constructor'; import { GenericConstructor } from '../../core/shared/generic-constructor';
import { HALDataService } from '../../core/data/base/hal-data-service.interface'; import { HALDataService } from '../../core/data/base/hal-data-service.interface';
import { UpdateDataService } from "../../core/data/update-data-service"; import { UpdateDataService } from '../../core/data/update-data-service';
@Component({ @Component({
selector: 'ds-dso-edit-metadata', selector: 'ds-dso-edit-metadata',

View File

@@ -2,7 +2,7 @@ import { ThemedComponent } from '../../shared/theme-support/themed.component';
import { DsoEditMetadataComponent } from './dso-edit-metadata.component'; import { DsoEditMetadataComponent } from './dso-edit-metadata.component';
import { Component, Input } from '@angular/core'; import { Component, Input } from '@angular/core';
import { DSpaceObject } from '../../core/shared/dspace-object.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model';
import { UpdateDataService } from "../../core/data/update-data-service"; import { UpdateDataService } from '../../core/data/update-data-service';
@Component({ @Component({
selector: 'ds-themed-dso-edit-metadata', selector: 'ds-themed-dso-edit-metadata',

View File

@@ -541,7 +541,7 @@ export class MenuResolver implements Resolve<boolean> {
{ {
id: 'notifications', id: 'notifications',
active: false, active: false,
visible: authorized && true, visible: authorized && canSeeQA,
model: { model: {
type: MenuItemType.TEXT, type: MenuItemType.TEXT,
text: 'menu.section.notifications' text: 'menu.section.notifications'

View File

@@ -86,10 +86,10 @@ export class SuggestionActionsComponent {
} }
ignoreSuggestionLabel(): string { ignoreSuggestionLabel(): string {
return this.isBulk ? 'reciter.suggestion.ignoreSuggestion.bulk' : 'reciter.suggestion.ignoreSuggestion' ; return this.isBulk ? 'suggestion.ignoreSuggestion.bulk' : 'suggestion.ignoreSuggestion' ;
} }
approveAndImportLabel(): string { approveAndImportLabel(): string {
return this.isBulk ? 'reciter.suggestion.approveAndImport.bulk' : 'reciter.suggestion.approveAndImport'; return this.isBulk ? 'suggestion.approveAndImport.bulk' : 'suggestion.approveAndImport';
} }
} }

View File

@@ -55,7 +55,7 @@ export class SuggestionTargetsEffects {
retrieveAllTargetsErrorAction$ = createEffect(() => this.actions$.pipe( retrieveAllTargetsErrorAction$ = createEffect(() => this.actions$.pipe(
ofType(SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE_ERROR), ofType(SuggestionTargetActionTypes.RETRIEVE_TARGETS_BY_SOURCE_ERROR),
tap(() => { tap(() => {
this.notificationsService.error(null, this.translate.get('reciter.suggestion.target.error.service.retrieve')); this.notificationsService.error(null, this.translate.get('suggestion.target.error.service.retrieve'));
}) })
), { dispatch: false }); ), { dispatch: false });
@@ -64,7 +64,7 @@ export class SuggestionTargetsEffects {
*/ */
refreshUserSuggestionsAction$ = createEffect(() => this.actions$.pipe( refreshUserSuggestionsAction$ = createEffect(() => this.actions$.pipe(
ofType(SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS), ofType(SuggestionTargetActionTypes.REFRESH_USER_SUGGESTIONS),
switchMap((action: RefreshUserSuggestionsAction) => { switchMap(() => {
return this.store$.select((state: any) => state.core.auth.userId) return this.store$.select((state: any) => state.core.auth.userId)
.pipe( .pipe(
switchMap((userId: string) => { switchMap((userId: string) => {

View File

@@ -169,18 +169,18 @@ describe('SuggestionsService test', () => {
it('should get suggestion interpolation', () => { it('should get suggestion interpolation', () => {
const result = service.getNotificationSuggestionInterpolation(suggestionTarget as SuggestionTarget); const result = service.getNotificationSuggestionInterpolation(suggestionTarget as SuggestionTarget);
expect(result.count).toEqual(suggestionTarget.total); expect(result.count).toEqual(suggestionTarget.total);
expect(result.source).toEqual('reciter.suggestion.source.' + suggestionTarget.source); expect(result.source).toEqual('suggestion.source.' + suggestionTarget.source);
expect(result.type).toEqual('reciter.suggestion.type.' + suggestionTarget.source); expect(result.type).toEqual('suggestion.type.' + suggestionTarget.source);
expect(result.suggestionId).toEqual(suggestionTarget.id); expect(result.suggestionId).toEqual(suggestionTarget.id);
expect(result.displayName).toEqual(suggestionTarget.display); expect(result.displayName).toEqual(suggestionTarget.display);
}); });
it('should translate suggestion type', () => { it('should translate suggestion type', () => {
expect(service.translateSuggestionType('source')).toEqual('reciter.suggestion.type.source'); expect(service.translateSuggestionType('source')).toEqual('suggestion.type.source');
}); });
it('should translate suggestion source', () => { it('should translate suggestion source', () => {
expect(service.translateSuggestionSource('source')).toEqual('reciter.suggestion.source.source'); expect(service.translateSuggestionSource('source')).toEqual('suggestion.source.source');
}); });
it('should resolve collection id', () => { it('should resolve collection id', () => {

View File

@@ -51,17 +51,14 @@ export class SuggestionsService {
/** /**
* Initialize the service variables. * Initialize the service variables.
* @param {AuthService} authService
* @param {ResearcherProfileDataService} researcherProfileService * @param {ResearcherProfileDataService} researcherProfileService
* @param {SuggestionSourceDataService} suggestionSourceDataService
* @param {SuggestionTargetDataService} suggestionTargetDataService * @param {SuggestionTargetDataService} suggestionTargetDataService
* @param {SuggestionsDataService} suggestionsDataService * @param {SuggestionsDataService} suggestionsDataService
* @param translateService
*/ */
constructor( constructor(
private authService: AuthService,
private researcherProfileService: ResearcherProfileDataService, private researcherProfileService: ResearcherProfileDataService,
private suggestionsDataService: SuggestionsDataService, private suggestionsDataService: SuggestionsDataService,
private suggestionSourceDataService: SuggestionSourceDataService,
private suggestionTargetDataService: SuggestionTargetDataService, private suggestionTargetDataService: SuggestionTargetDataService,
private translateService: TranslateService private translateService: TranslateService
) { ) {
@@ -194,7 +191,7 @@ export class SuggestionsService {
return workspaceitemService.importExternalSourceEntry(suggestion.externalSourceUri, resolvedCollectionId) return workspaceitemService.importExternalSourceEntry(suggestion.externalSourceUri, resolvedCollectionId)
.pipe( .pipe(
getFirstSucceededRemoteDataPayload(), getFirstSucceededRemoteDataPayload(),
catchError((error) => of(null)) catchError(() => of(null))
); );
} }
@@ -204,7 +201,7 @@ export class SuggestionsService {
*/ */
public ignoreSuggestion(suggestionId): Observable<RemoteData<NoContent>> { public ignoreSuggestion(suggestionId): Observable<RemoteData<NoContent>> {
return this.deleteReviewedSuggestion(suggestionId).pipe( return this.deleteReviewedSuggestion(suggestionId).pipe(
catchError((error) => of(null)) catchError(() => of(null))
); );
} }
@@ -268,11 +265,11 @@ export class SuggestionsService {
} }
public translateSuggestionType(source: string): string { public translateSuggestionType(source: string): string {
return 'reciter.suggestion.type.' + source; return 'suggestion.type.' + source;
} }
public translateSuggestionSource(source: string): string { public translateSuggestionSource(source: string): string {
return 'reciter.suggestion.source.' + source; return 'suggestion.source.' + source;
} }
/** /**

View File

@@ -13,8 +13,6 @@ import {
} from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component'; } from '../suggestion-notifications/suggestion-list-element/suggestion-list-element.component';
import { SuggestionsService } from '../suggestion-notifications/suggestions.service'; import { SuggestionsService } from '../suggestion-notifications/suggestions.service';
import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock'; import { getMockSuggestionNotificationsStateService, getMockSuggestionsService } from '../shared/mocks/suggestion.mock';
import { buildPaginatedList, PaginatedList } from '../core/data/paginated-list.model';
import { Suggestion } from '../core/suggestion-notifications/models/suggestion.model';
import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/publication-claim.mock'; import { mockSuggestionPublicationOne, mockSuggestionPublicationTwo } from '../shared/mocks/publication-claim.mock';
import { SuggestionEvidencesComponent } from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component'; import { SuggestionEvidencesComponent } from '../suggestion-notifications/suggestion-list-element/suggestion-evidences/suggestion-evidences.component';
import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe'; import { ObjectKeysPipe } from '../shared/utils/object-keys-pipe';
@@ -29,7 +27,6 @@ import { getMockTranslateService } from '../shared/mocks/translate.service.mock'
import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service'; import { SuggestionTargetsStateService } from '../suggestion-notifications/suggestion-targets/suggestion-targets.state.service';
import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service'; import { WorkspaceitemDataService } from '../core/submission/workspaceitem-data.service';
import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils'; import { createSuccessfulRemoteDataObject } from '../shared/remote-data.utils';
import { PageInfo } from '../core/shared/page-info.model';
import { TestScheduler } from 'rxjs/testing'; import { TestScheduler } from 'rxjs/testing';
import { getTestScheduler } from 'jasmine-marbles'; import { getTestScheduler } from 'jasmine-marbles';
import { PaginationServiceStub } from '../shared/testing/pagination-service.stub'; import { PaginationServiceStub } from '../shared/testing/pagination-service.stub';

View File

@@ -152,7 +152,7 @@ export class SuggestionsPageComponent implements OnInit {
* @suggestionId * @suggestionId
*/ */
ignoreSuggestion(suggestionId) { ignoreSuggestion(suggestionId) {
this.suggestionService.ignoreSuggestion(suggestionId).subscribe((res) => { this.suggestionService.ignoreSuggestion(suggestionId).subscribe(() => {
this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction();
this.updatePage(); this.updatePage();
}); });
@@ -172,12 +172,12 @@ export class SuggestionsPageComponent implements OnInit {
this.selectedSuggestions = {}; this.selectedSuggestions = {};
if (results.success > 0) { if (results.success > 0) {
this.notificationService.success( this.notificationService.success(
this.translateService.get('reciter.suggestion.notMine.bulk.success', this.translateService.get('suggestion.notMine.bulk.success',
{count: results.success})); {count: results.success}));
} }
if (results.fails > 0) { if (results.fails > 0) {
this.notificationService.error( this.notificationService.error(
this.translateService.get('reciter.suggestion.notMine.bulk.error', this.translateService.get('suggestion.notMine.bulk.error',
{count: results.fails})); {count: results.fails}));
} }
}); });
@@ -190,7 +190,7 @@ export class SuggestionsPageComponent implements OnInit {
approveAndImport(event: SuggestionApproveAndImport) { approveAndImport(event: SuggestionApproveAndImport) {
this.suggestionService.approveAndImport(this.workspaceItemService, event.suggestion, event.collectionId) this.suggestionService.approveAndImport(this.workspaceItemService, event.suggestion, event.collectionId)
.subscribe((workspaceitem: WorkspaceItem) => { .subscribe((workspaceitem: WorkspaceItem) => {
const content = this.translateService.instant('reciter.suggestion.approveAndImport.success', { workspaceItemId: workspaceitem.id }); const content = this.translateService.instant('suggestion.approveAndImport.success', { workspaceItemId: workspaceitem.id });
this.notificationService.success('', content, {timeOut:0}, true); this.notificationService.success('', content, {timeOut:0}, true);
this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction(); this.suggestionTargetsStateService.dispatchRefreshUserSuggestionsAction();
this.updatePage(); this.updatePage();
@@ -212,12 +212,12 @@ export class SuggestionsPageComponent implements OnInit {
this.selectedSuggestions = {}; this.selectedSuggestions = {};
if (results.success > 0) { if (results.success > 0) {
this.notificationService.success( this.notificationService.success(
this.translateService.get('reciter.suggestion.approveAndImport.bulk.success', this.translateService.get('suggestion.approveAndImport.bulk.success',
{count: results.success})); {count: results.success}));
} }
if (results.fails > 0) { if (results.fails > 0) {
this.notificationService.error( this.notificationService.error(
this.translateService.get('reciter.suggestion.approveAndImport.bulk.error', this.translateService.get('suggestion.approveAndImport.bulk.error',
{count: results.fails})); {count: results.fails}));
} }
}); });

View File

@@ -1,4 +1,4 @@
import { Config } from "./config.interface"; import { Config } from './config.interface';
export interface SuggestionConfig extends Config { export interface SuggestionConfig extends Config {
source: string; source: string;