Skip to content
Snippets Groups Projects
Commit 49e60c7b authored by OZGCloud's avatar OZGCloud
Browse files

OZG-5012 migrate api save to ngrx

parent e2519e30
No related branches found
No related tags found
No related merge requests found
Showing
with 349 additions and 102 deletions
import { import {
ApiResourceService, ApiResourceService,
ApiSingleResourceReducer,
ResourceRepository, ResourceRepository,
ResourceServiceConfig, ResourceServiceConfig,
SingleResourceReducer,
StateService, StateService,
createSingleResourceActions, createApiSingleResourceActions,
} from '@alfa-client/tech-shared'; } from '@alfa-client/tech-shared';
import { Action, ActionReducerMap } from '@ngrx/store'; import { Action, ActionReducerMap } from '@ngrx/store';
import { SingleResourceState } from 'libs/tech-shared/src/lib/ngrx/state.model'; import { ApiSingleResourceState } from 'libs/tech-shared/src/lib/ngrx/state.model';
import { SettingsService } from '../admin-settings.service'; import { SettingsService } from '../admin-settings.service';
import { PostfachLinkRel } from './postfach.linkrel'; import { PostfachLinkRel } from './postfach.linkrel';
import { PostfachResource } from './postfach.model'; import { PostfachResource } from './postfach.model';
...@@ -38,9 +38,9 @@ function buildConfig(settingService: SettingsService): ResourceServiceConfig<Pos ...@@ -38,9 +38,9 @@ function buildConfig(settingService: SettingsService): ResourceServiceConfig<Pos
}; };
} }
export function postfachResourceReducer(state: SingleResourceState, action: Action) { export function postfachResourceReducer(state: ApiSingleResourceState, action: Action) {
const resourceReducer: SingleResourceReducer = new SingleResourceReducer( const resourceReducer: ApiSingleResourceReducer = new ApiSingleResourceReducer(
createSingleResourceActions({ name: POSTFACH_FEATURE_KEY, path: POSTFACH_PATH }), createApiSingleResourceActions({ name: POSTFACH_FEATURE_KEY, path: POSTFACH_PATH }),
); );
return resourceReducer.reducer(state, action); return resourceReducer.reducer(state, action);
} }
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
import { Action, ActionCreator, createAction, props } from '@ngrx/store'; import { Action, ActionCreator, createAction, props } from '@ngrx/store';
import { TypedAction } from '@ngrx/store/src/models'; import { TypedAction } from '@ngrx/store/src/models';
import { Resource, ResourceUri } from '@ngxp/rest'; import { Resource, ResourceUri } from '@ngxp/rest';
import { StateInfo } from '../resource/resource.model'; import { SaveResourceData, StateInfo } from '../resource/resource.model';
import { ApiError, HttpError } from '../tech.model'; import { ApiError, HttpError } from '../tech.model';
export const EMPTY_ACTION: Action = {} as Action; export const EMPTY_ACTION: Action = {} as Action;
...@@ -42,6 +42,7 @@ export interface ResourceUriProps { ...@@ -42,6 +42,7 @@ export interface ResourceUriProps {
resourceUri: ResourceUri; resourceUri: ResourceUri;
} }
//TODO rename ResourceSuccessProps
export interface LoadResourceSuccessProps { export interface LoadResourceSuccessProps {
resource: Resource; resource: Resource;
} }
...@@ -60,6 +61,50 @@ export interface SingleResourceLoadActions extends ResourceActions { ...@@ -60,6 +61,50 @@ export interface SingleResourceLoadActions extends ResourceActions {
loadSuccessAction: TypedActionCreatorWithProps<LoadResourceSuccessProps>; loadSuccessAction: TypedActionCreatorWithProps<LoadResourceSuccessProps>;
} }
export interface SaveProps {
saveResourceData: SaveResourceData;
}
export interface ApiSingleResourceActions extends SingleResourceLoadActions {
saveAction: TypedActionCreatorWithProps<SaveProps>;
saveSuccessAction: TypedActionCreatorWithProps<LoadResourceSuccessProps>;
saveFailureAction: TypedActionCreatorWithProps<LoadResourceFailureProps>;
}
export function createApiSingleResourceActions(stateInfo: StateInfo): ApiSingleResourceActions {
const actions: SingleResourceLoadActions = createSingleResourceActions(stateInfo);
return {
...actions,
saveAction: createSaveAction(stateInfo),
saveSuccessAction: createSaveSuccessAction(stateInfo),
saveFailureAction: createSaveFailureAction(stateInfo),
};
}
function createSaveAction(stateInfo: StateInfo): TypedActionCreatorWithProps<SaveProps> {
return createAction(
createActionType(stateInfo.name, `Save ${stateInfo.path}`),
props<SaveProps>(),
);
}
function createSaveSuccessAction(
stateInfo: StateInfo,
): TypedActionCreatorWithProps<LoadResourceSuccessProps> {
return createAction(
createActionType(stateInfo.name, `Save ${stateInfo.path} Success`),
props<LoadResourceSuccessProps>(),
);
}
function createSaveFailureAction(
stateInfo: StateInfo,
): TypedActionCreatorWithProps<LoadResourceFailureProps> {
return createAction(
createActionType(stateInfo.name, `Save ${stateInfo.path} Failure`),
props<LoadResourceFailureProps>(),
);
}
export function createSingleResourceActions(stateInfo: StateInfo): SingleResourceLoadActions { export function createSingleResourceActions(stateInfo: StateInfo): SingleResourceLoadActions {
const actions: ResourceActions = createResourceActions( const actions: ResourceActions = createResourceActions(
stateInfo.name, stateInfo.name,
......
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Actions, EffectSources } from '@ngrx/effects'; import { Actions, EffectSources } from '@ngrx/effects';
import { ResourceRepository } from '../resource/resource.repository'; import { ResourceRepository } from '../resource/resource.repository';
import { SingleResourceLoadActions } from './actions'; import { ApiSingleResourceActions, SingleResourceLoadActions } from './actions';
import { ResourceEffects } from './resource.effects'; import { ApiResourceEffects, ResourceEffects } from './resource.effects';
@Injectable() @Injectable()
export class EffectService { export class EffectService {
...@@ -17,4 +17,10 @@ export class EffectService { ...@@ -17,4 +17,10 @@ export class EffectService {
...new ResourceEffects(this.actions$, this.repository, resourceActions), ...new ResourceEffects(this.actions$, this.repository, resourceActions),
}); });
} }
public addApiSingleResourceEffects(resourceActions: ApiSingleResourceActions): void {
this.effectSources.addEffects({
...new ApiResourceEffects(this.actions$, this.repository, resourceActions),
});
}
} }
...@@ -3,13 +3,18 @@ import { Resource } from '@ngxp/rest'; ...@@ -3,13 +3,18 @@ import { Resource } from '@ngxp/rest';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators'; import { catchError, map, switchMap } from 'rxjs/operators';
import { ResourceRepository } from '../resource/resource.repository'; import { ResourceRepository } from '../resource/resource.repository';
import { ResourceUriProps, SingleResourceLoadActions } from './actions'; import {
ApiSingleResourceActions,
ResourceUriProps,
SaveProps,
SingleResourceLoadActions,
} from './actions';
export class ResourceEffects<T extends Resource> { export class ResourceEffects<T extends Resource> {
constructor( constructor(
private actions$: Actions, protected actions$: Actions,
private repository: ResourceRepository, protected repository: ResourceRepository,
private resourceActions: SingleResourceLoadActions, protected resourceActions: SingleResourceLoadActions,
) {} ) {}
loadByUri$ = createEffect(() => loadByUri$ = createEffect(() =>
...@@ -24,3 +29,25 @@ export class ResourceEffects<T extends Resource> { ...@@ -24,3 +29,25 @@ export class ResourceEffects<T extends Resource> {
), ),
); );
} }
export class ApiResourceEffects<T extends Resource> extends ResourceEffects<T> {
constructor(
protected actions$: Actions,
protected repository: ResourceRepository,
protected resourceActions: ApiSingleResourceActions,
) {
super(actions$, repository, resourceActions);
}
save$ = createEffect(() =>
this.actions$.pipe(
ofType(this.resourceActions.saveAction),
switchMap((props: SaveProps) => {
return this.repository.save<T>(props.saveResourceData).pipe(
map((resource: T) => this.resourceActions.saveSuccessAction({ resource })),
catchError((error) => of(this.resourceActions.saveFailureAction({ error }))),
);
}),
),
);
}
import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import { ActionReducer, ReducerTypes, createReducer, on } from '@ngrx/store';
import { import {
createEmptyStateResource, createEmptyStateResource,
createErrorStateResource, createErrorStateResource,
createStateResource, createStateResource,
} from '../resource/resource.util'; } from '../resource/resource.util';
import { import {
ApiSingleResourceActions,
LoadResourceFailureProps, LoadResourceFailureProps,
LoadResourceSuccessProps, LoadResourceSuccessProps,
SingleResourceLoadActions, SingleResourceLoadActions,
} from './actions'; } from './actions';
import { SingleResourceState, initialResourceState } from './state.model'; import {
ApiSingleResourceState,
SingleResourceState,
initialApiResourceState,
initialResourceState,
} from './state.model';
export class SingleResourceReducer { export class SingleResourceReducer {
public reducer: ActionReducer<SingleResourceState, Action>; public reducer: ActionReducer<SingleResourceState>;
constructor(private actions: SingleResourceLoadActions) { protected loadActionReducerType: ReducerTypes<SingleResourceState, any>;
protected loadSuccessActionReducerType: ReducerTypes<SingleResourceState, any>;
protected loadFailureActionReducerType: ReducerTypes<SingleResourceState, any>;
protected clearActionReducerType: ReducerTypes<SingleResourceState, any>;
protected reloadActionReducerType: ReducerTypes<SingleResourceState, any>;
constructor(protected actions: SingleResourceLoadActions) {
this.initReducerTypes();
this.initReducer(); this.initReducer();
} }
initReducer(): void { initReducerTypes() {
this.loadActionReducerType = this.createLoadActionReducerType();
this.loadSuccessActionReducerType = this.createLoadSuccessActionReducerType();
this.loadFailureActionReducerType = this.createLoadFailureActionReducerType();
this.clearActionReducerType = this.createClearActionReducerType();
this.reloadActionReducerType = this.createReloadActionReducerType();
}
protected initReducer(): void {
this.reducer = createReducer( this.reducer = createReducer(
initialResourceState, initialResourceState,
on(this.actions.loadAction, (state: SingleResourceState): SingleResourceState => { this.loadActionReducerType,
this.loadSuccessActionReducerType,
this.loadFailureActionReducerType,
this.clearActionReducerType,
this.reloadActionReducerType,
);
}
createLoadActionReducerType(): ReducerTypes<SingleResourceState, any> {
return on(this.actions.loadAction, (state: SingleResourceState): SingleResourceState => {
return { return {
...state, ...state,
resource: { ...state.resource, loading: true }, resource: { ...state.resource, loading: true },
}; };
}), });
on( }
createLoadSuccessActionReducerType(): ReducerTypes<SingleResourceState, any> {
return on(
this.actions.loadSuccessAction, this.actions.loadSuccessAction,
(state: SingleResourceState, props: LoadResourceSuccessProps): SingleResourceState => { (state: SingleResourceState, props: LoadResourceSuccessProps): SingleResourceState => {
return { return {
...@@ -35,27 +68,84 @@ export class SingleResourceReducer { ...@@ -35,27 +68,84 @@ export class SingleResourceReducer {
resource: createStateResource(props.resource), resource: createStateResource(props.resource),
}; };
}, },
), );
on( }
createLoadFailureActionReducerType(): ReducerTypes<SingleResourceState, any> {
return on(
this.actions.loadFailureAction, this.actions.loadFailureAction,
(state: SingleResourceState, props: LoadResourceFailureProps): SingleResourceState => ({ (state: SingleResourceState, props: LoadResourceFailureProps): SingleResourceState => ({
...state, ...state,
resource: createErrorStateResource(props.error), resource: createErrorStateResource(props.error),
}), }),
), );
on( }
createClearActionReducerType(): ReducerTypes<SingleResourceState, any> {
return on(
this.actions.clearAction, this.actions.clearAction,
(state: SingleResourceState): SingleResourceState => ({ (state: SingleResourceState): SingleResourceState => ({
...state, ...state,
resource: createEmptyStateResource(), resource: createEmptyStateResource(),
}), }),
), );
on( }
createReloadActionReducerType(): ReducerTypes<SingleResourceState, any> {
return on(
this.actions.reloadAction, this.actions.reloadAction,
(state: SingleResourceState): SingleResourceState => ({ (state: SingleResourceState): SingleResourceState => ({
...state, ...state,
resource: { ...state.resource, reload: true }, resource: { ...state.resource, reload: true },
}), }),
);
}
}
export class ApiSingleResourceReducer extends SingleResourceReducer {
public reducer: ActionReducer<ApiSingleResourceState>;
constructor(protected actions: ApiSingleResourceActions) {
super(actions);
}
initReducer(): void {
this.reducer = createReducer(
initialApiResourceState,
this.loadActionReducerType,
this.loadSuccessActionReducerType,
this.loadFailureActionReducerType,
this.clearActionReducerType,
this.reloadActionReducerType,
on(this.actions.saveAction, (state: ApiSingleResourceState): ApiSingleResourceState => {
return {
...state,
saveResource: createEmptyStateResource(true),
};
}),
on(
this.actions.saveSuccessAction,
(
state: ApiSingleResourceState,
props: LoadResourceSuccessProps,
): ApiSingleResourceState => {
return {
...state,
saveResource: createStateResource(props.resource),
};
},
),
on(
this.actions.saveFailureAction,
(
state: ApiSingleResourceState,
props: LoadResourceFailureProps,
): ApiSingleResourceState => {
return {
...state,
saveResource: createErrorStateResource(props.error),
};
},
), ),
); );
} }
......
import { createFeatureSelector, createSelector } from '@ngrx/store'; import { createFeatureSelector, createSelector } from '@ngrx/store';
import { StateInfo } from '../resource/resource.model'; import { StateInfo } from '../resource/resource.model';
import { SingleResourceState } from './state.model'; import { ApiSingleResourceState, SingleResourceState } from './state.model';
//Single Resource State
export const selectResource = <T>(stateInfo: StateInfo) => export const selectResource = <T>(stateInfo: StateInfo) =>
createSelector( createSelector(
createFeatureSelector<SingleResourceState>(stateInfo.name), createFeatureSelector<SingleResourceState>(stateInfo.name),
...@@ -16,6 +17,20 @@ export const existResource = <T>(stateInfo: StateInfo) => ...@@ -16,6 +17,20 @@ export const existResource = <T>(stateInfo: StateInfo) =>
<T>getFeatureState<SingleResourceState>(stateInfo, state).resource.loaded, <T>getFeatureState<SingleResourceState>(stateInfo, state).resource.loaded,
); );
//Api Single Resource State
export const selectSaveResource = <T>(stateInfo: StateInfo) =>
createSelector(
createFeatureSelector<ApiSingleResourceState>(stateInfo.name),
(state: ApiSingleResourceState) => {
const featureState: ApiSingleResourceState = <ApiSingleResourceState>(
getFeatureState<ApiSingleResourceState>(stateInfo, state)
);
console.info('SELECT SaveResource: ', featureState.saveResource);
console.info('SELECT Resource: ', featureState.resource);
return <T>getFeatureState<ApiSingleResourceState>(stateInfo, state).saveResource;
},
);
function getFeatureState<T>(stateInfo: StateInfo, state: any): T { function getFeatureState<T>(stateInfo: StateInfo, state: any): T {
return <T>state.hasOwnProperty(stateInfo.path) ? state[stateInfo.path] : state; return <T>state.hasOwnProperty(stateInfo.path) ? state[stateInfo.path] : state;
} }
...@@ -8,3 +8,13 @@ export interface SingleResourceState { ...@@ -8,3 +8,13 @@ export interface SingleResourceState {
export const initialResourceState: SingleResourceState = { export const initialResourceState: SingleResourceState = {
resource: createEmptyStateResource<Resource>(), resource: createEmptyStateResource<Resource>(),
}; };
export interface ApiSingleResourceState {
resource: StateResource<Resource>;
saveResource: StateResource<Resource>;
}
export const initialApiResourceState: ApiSingleResourceState = {
resource: createEmptyStateResource<Resource>(),
saveResource: createEmptyStateResource<Resource>(),
};
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { ResourceUri } from '@ngxp/rest'; import { Resource, ResourceUri } from '@ngxp/rest';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { StateInfo } from '../resource/resource.model'; import { ResourceServiceConfig } from '../resource/resource.model';
import { StateResource } from '../resource/resource.util'; import { StateResource } from '../resource/resource.util';
import { ResourceActions, SingleResourceLoadActions, createSingleResourceActions } from './actions'; import {
ApiSingleResourceActions,
ResourceActions,
SaveProps,
SingleResourceLoadActions,
createApiSingleResourceActions,
createSingleResourceActions,
} from './actions';
import { EffectService } from './effects.service'; import { EffectService } from './effects.service';
import { TypedAction } from '@ngrx/store/src/models';
import { ApiStateServiceExecuter } from './api-state-service.executer';
import * as ResourceSelectors from './selector'; import * as ResourceSelectors from './selector';
@Injectable() @Injectable()
...@@ -16,16 +25,24 @@ export class StateService { ...@@ -16,16 +25,24 @@ export class StateService {
private effectService: EffectService, private effectService: EffectService,
) {} ) {}
public createSingleResourceService<T>(stateInfo: StateInfo): SingleResourceStateService<T> { public createSingleResourceService<B extends Resource, T extends Resource>(
return new SingleResourceStateService(stateInfo, this.store, this.effectService); config: ResourceServiceConfig<B>,
): SingleResourceStateService<B, T> {
return new SingleResourceStateService<B, T>(config, this.store, this.effectService);
}
public createApiSingleResourceService<B extends Resource, T extends Resource>(
config: ResourceServiceConfig<B>,
): ApiSingleResourceStateService<B, T> {
return new ApiSingleResourceStateService<B, T>(config, this.store, this.effectService);
} }
} }
export abstract class ResourceStateService<T> { export abstract class ResourceStateService<B extends Resource, T extends Resource> {
actions: ResourceActions; actions: ResourceActions;
constructor( constructor(
protected stateInfo: StateInfo, protected config: ResourceServiceConfig<B>,
protected store: Store, protected store: Store,
protected effectService: EffectService, protected effectService: EffectService,
) { ) {
...@@ -56,19 +73,22 @@ export abstract class ResourceStateService<T> { ...@@ -56,19 +73,22 @@ export abstract class ResourceStateService<T> {
public abstract selectResource(): Observable<StateResource<T>>; public abstract selectResource(): Observable<StateResource<T>>;
} }
export class SingleResourceStateService<T> extends ResourceStateService<T> { export class SingleResourceStateService<
B extends Resource,
T extends Resource,
> extends ResourceStateService<B, T> {
actions: SingleResourceLoadActions; actions: SingleResourceLoadActions;
constructor( constructor(
protected stateInfo: StateInfo, protected config: ResourceServiceConfig<B>,
protected store: Store, protected store: Store,
protected effectService: EffectService, protected effectService: EffectService,
) { ) {
super(stateInfo, store, effectService); super(config, store, effectService);
} }
protected initActions(): void { protected initActions(): void {
this.actions = createSingleResourceActions(this.stateInfo); this.actions = createSingleResourceActions(this.config.stateInfo);
} }
protected initEffects(): void { protected initEffects(): void {
...@@ -76,10 +96,58 @@ export class SingleResourceStateService<T> extends ResourceStateService<T> { ...@@ -76,10 +96,58 @@ export class SingleResourceStateService<T> extends ResourceStateService<T> {
} }
public selectResource(): Observable<StateResource<T>> { public selectResource(): Observable<StateResource<T>> {
return this.store.select(ResourceSelectors.selectResource(this.stateInfo)); return this.store.select(ResourceSelectors.selectResource(this.config.stateInfo));
} }
public existsResource(): Observable<boolean> { public existsResource(): Observable<boolean> {
return this.store.select(ResourceSelectors.existResource(this.stateInfo)); return this.store.select(ResourceSelectors.existResource(this.config.stateInfo));
}
}
export class ApiSingleResourceStateService<
B extends Resource,
T extends Resource,
> extends SingleResourceStateService<B, T> {
actions: ApiSingleResourceActions;
constructor(
protected config: ResourceServiceConfig<B>,
protected store: Store,
protected effectService: EffectService,
) {
super(config, store, effectService);
}
protected initActions(): void {
this.actions = createApiSingleResourceActions(this.config.stateInfo);
}
protected initEffects(): void {
this.effectService.addApiSingleResourceEffects(this.actions);
}
public save(toSave: unknown): Observable<StateResource<T>> {
return this.dispatchAction(this.selectSaveResource(), (resource: T) =>
this.createSaveAction(resource, toSave),
);
}
private createSaveAction(resource: Resource, toSave: unknown): SaveProps & TypedAction<string> {
return this.actions.saveAction({
saveResourceData: { toSave, resource, linkRel: this.config.edit.linkRel },
});
}
private dispatchAction(
baseResource: Observable<StateResource<T>>,
runnable: (resource: T) => TypedAction<string>,
): Observable<StateResource<T>> {
return ApiStateServiceExecuter.init<B, T>(this)
.withBaseResource(baseResource)
.execute((resource: T) => this.store.dispatch(runnable(resource)));
}
private selectSaveResource(): Observable<StateResource<T>> {
return this.store.select(ResourceSelectors.selectSaveResource(this.config.stateInfo));
} }
} }
import { HttpErrorResponse } from '@angular/common/http';
import { Resource } from '@ngxp/rest'; import { Resource } from '@ngxp/rest';
import { Observable, catchError, map, of, startWith, switchMap, tap, throwError } from 'rxjs'; import { Observable } from 'rxjs';
import { isUnprocessableEntity } from '../http.util'; import {
import { StateService } from '../ngrx/state.service'; ApiSingleResourceStateService,
import { HttpError } from '../tech.model'; SingleResourceStateService,
StateService,
} from '../ngrx/state.service';
import { ResourceServiceConfig } from './resource.model'; import { ResourceServiceConfig } from './resource.model';
import { ResourceRepository } from './resource.repository'; import { ResourceRepository } from './resource.repository';
import { ResourceService } from './resource.service'; import { ResourceService } from './resource.service';
import { import { StateResource } from './resource.util';
StateResource,
createEmptyStateResource,
createErrorStateResource,
createStateResource,
} from './resource.util';
export class ApiResourceService<B extends Resource, T extends Resource> extends ResourceService< export class ApiResourceService<B extends Resource, T extends Resource> extends ResourceService<
B, B,
T T
> { > {
protected apiResourceStateService: ApiSingleResourceStateService<B, T>;
constructor( constructor(
protected config: ResourceServiceConfig<B>, protected config: ResourceServiceConfig<B>,
protected stateService: StateService, protected stateService: StateService,
...@@ -26,31 +24,17 @@ export class ApiResourceService<B extends Resource, T extends Resource> extends ...@@ -26,31 +24,17 @@ export class ApiResourceService<B extends Resource, T extends Resource> extends
super(config, stateService); super(config, stateService);
} }
public save(toSave: unknown): Observable<StateResource<T | HttpError>> { protected initStateService(): void {
return this.selectResource().pipe( this.apiResourceStateService = this.stateService.createApiSingleResourceService<B, T>(
switchMap((stateResource: StateResource<T>) => this.config,
this.doSave(stateResource.resource, toSave).pipe(
tap(() => this.reloadResource()),
map((value: T) => createStateResource<T>(value)),
catchError((errorResponse: HttpErrorResponse) => this.handleError(errorResponse)),
),
),
startWith(createEmptyStateResource<T | HttpError>(true)),
); );
} }
doSave(resource: T, toSave: unknown): Observable<T> { protected getResourceStateService(): SingleResourceStateService<B, T> {
return this.repository.save<T>({ return this.apiResourceStateService;
resource,
linkRel: this.config.edit.linkRel,
toSave,
});
} }
handleError(errorResponse: HttpErrorResponse): Observable<StateResource<HttpError>> { public save(toSave: unknown): Observable<StateResource<T>> {
if (isUnprocessableEntity(errorResponse.status)) { return this.apiResourceStateService.save(toSave);
return of(createErrorStateResource((<any>errorResponse) as HttpError));
}
return throwError(() => errorResponse);
} }
} }
...@@ -24,8 +24,8 @@ export interface CreateResourceData<T> { ...@@ -24,8 +24,8 @@ export interface CreateResourceData<T> {
toCreate: any; toCreate: any;
} }
export interface SaveResourceData<T> { export interface SaveResourceData {
resource: T; resource?: Resource;
linkRel: string; linkRel: string;
toSave: any; toSave: any;
} }
......
...@@ -30,7 +30,7 @@ export class ResourceRepository { ...@@ -30,7 +30,7 @@ export class ResourceRepository {
return this.resourceFactory.fromId(uri).get(); return this.resourceFactory.fromId(uri).get();
} }
public save<T>(saveResourceData: SaveResourceData<Resource>): Observable<T> { public save<T>(saveResourceData: SaveResourceData): Observable<T> {
return this.resourceFactory return this.resourceFactory
.from(saveResourceData.resource) .from(saveResourceData.resource)
.put(saveResourceData.linkRel, saveResourceData.toSave); .put(saveResourceData.linkRel, saveResourceData.toSave);
......
...@@ -10,7 +10,7 @@ import { StateResource } from './resource.util'; ...@@ -10,7 +10,7 @@ import { StateResource } from './resource.util';
* T = Type of the resource which is working on * T = Type of the resource which is working on
*/ */
export abstract class ResourceService<B extends Resource, T extends Resource> { export abstract class ResourceService<B extends Resource, T extends Resource> {
resourceStateService: SingleResourceStateService<T>; resourceStateService: SingleResourceStateService<B, T>;
resourceLoader: ResourceLoader<B, T>; resourceLoader: ResourceLoader<B, T>;
constructor( constructor(
...@@ -21,14 +21,12 @@ export abstract class ResourceService<B extends Resource, T extends Resource> { ...@@ -21,14 +21,12 @@ export abstract class ResourceService<B extends Resource, T extends Resource> {
this.initResourceLoader(); this.initResourceLoader();
} }
private initStateService(): void { protected initStateService(): void {
this.resourceStateService = this.stateService.createSingleResourceService( this.resourceStateService = this.stateService.createSingleResourceService<B, T>(this.config);
this.config.stateInfo,
);
} }
private initResourceLoader(): void { private initResourceLoader(): void {
this.resourceLoader = new ResourceLoader<B, T>(this.config, this.resourceStateService); this.resourceLoader = new ResourceLoader<B, T>(this.config, this.getResourceStateService());
} }
public get(): Observable<StateResource<T>> { public get(): Observable<StateResource<T>> {
...@@ -36,22 +34,26 @@ export abstract class ResourceService<B extends Resource, T extends Resource> { ...@@ -36,22 +34,26 @@ export abstract class ResourceService<B extends Resource, T extends Resource> {
} }
public reloadResource(): void { public reloadResource(): void {
this.resourceStateService.reloadResource(); this.getResourceStateService().reloadResource();
} }
public existResource(): Observable<boolean> { public existResource(): Observable<boolean> {
return this.resourceStateService.existsResource(); return this.getResourceStateService().existsResource();
} }
public selectResource(): Observable<StateResource<T>> { public selectResource(): Observable<StateResource<T>> {
return this.resourceStateService.selectResource(); return this.getResourceStateService().selectResource();
} }
public loadByResourceUri(resourceUri: ResourceUri): void { public loadByResourceUri(resourceUri: ResourceUri): void {
this.resourceStateService.loadResource(resourceUri); this.getResourceStateService().loadResource(resourceUri);
} }
public clearResource(): void { public clearResource(): void {
this.resourceStateService.clearResource(); this.getResourceStateService().clearResource();
}
protected getResourceStateService(): SingleResourceStateService<B, T> {
return this.resourceStateService;
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment