update action generation

This commit is contained in:
Philipp Kunz 2019-02-26 18:09:38 +01:00
parent eae70135d5
commit a4d43456d7
3 changed files with 37 additions and 17 deletions

View File

@ -30,12 +30,20 @@ tap.test('should create a new StatePart', async () => {
tap.test('should select something', async () => { tap.test('should select something', async () => {
testStatePart testStatePart
.select(state => state.deep) .select(state => state.deep.hi)
.subscribe(substate => { .subscribe(substate => {
console.log(substate); expect(substate).to.equal(2);
}); });
}); });
tap.test('should dispatch a state action', async () => {}); tap.test('should dispatch a state action', async () => {
const addFavourite = testStatePart.createAction<string>(async (statePart, payload) => {
const currentState = statePart.getState();
currentState.currentFavorites.push(payload)
return currentState;
});
await testStatePart.dispatchAction(addFavourite, 'my favourite things')
expect(testStatePart.getState().currentFavorites).to.include('my favourite things')
});
tap.start(); tap.start();

View File

@ -1,8 +1,13 @@
import * as plugins from './smartstate.plugins'; import * as plugins from './smartstate.plugins';
import { StatePart } from './smartstate.classes.statepart';
export interface IActionDef<TStateType, TActionPayloadType> {
(stateArg: StatePart<any, TStateType>, actionPayload: TActionPayloadType): Promise<TStateType>;
}
/** /**
* an actionmodifier for the state * an actionmodifier for the state
*/ */
export class StateAction<StatePayload> { export class StateAction<TStateType, TActionPayloadType> {
constructor(public actionDef: (stateArg: StatePayload) => StatePayload) {} constructor(public actionDef: IActionDef<TStateType, TActionPayloadType>) {}
} }

View File

@ -3,21 +3,21 @@ import * as plugins from './smartstate.plugins';
import { Observable, Subject } from 'rxjs'; import { Observable, Subject } from 'rxjs';
import { startWith, takeUntil, map } from 'rxjs/operators'; import { startWith, takeUntil, map } from 'rxjs/operators';
import { StateAction } from './smartstate.classes.stateaction'; import { StateAction, IActionDef } from './smartstate.classes.stateaction';
export class StatePart<StatePartNameType, PayloadType> { export class StatePart<TStatePartName, TStatePayload> {
name: StatePartNameType; name: TStatePartName;
state = new Subject<PayloadType>(); state = new Subject<TStatePayload>();
stateStore: PayloadType; stateStore: TStatePayload;
constructor(nameArg: StatePartNameType) { constructor(nameArg: TStatePartName) {
this.name = nameArg; this.name = nameArg;
} }
/** /**
* gets the state from the state store * gets the state from the state store
*/ */
getState(): PayloadType { getState(): TStatePayload {
return this.stateStore; return this.stateStore;
} }
@ -25,7 +25,7 @@ export class StatePart<StatePartNameType, PayloadType> {
* sets the stateStore to the new state * sets the stateStore to the new state
* @param newStateArg * @param newStateArg
*/ */
setState(newStateArg: PayloadType) { setState(newStateArg: TStatePayload) {
this.stateStore = newStateArg; this.stateStore = newStateArg;
this.notifyChange(); this.notifyChange();
} }
@ -40,9 +40,9 @@ export class StatePart<StatePartNameType, PayloadType> {
/** /**
* selects a state or a substate * selects a state or a substate
*/ */
select<T = PayloadType>(selectorFn?: (state: PayloadType) => T): Observable<T> { select<T = TStatePayload>(selectorFn?: (state: TStatePayload) => T): Observable<T> {
if (!selectorFn) { if (!selectorFn) {
selectorFn = (state: PayloadType) => <T>(<any>state); selectorFn = (state: TStatePayload) => <T>(<any>state);
} }
const mapped = this.state.pipe( const mapped = this.state.pipe(
@ -53,11 +53,18 @@ export class StatePart<StatePartNameType, PayloadType> {
return mapped; return mapped;
} }
/**
* creates an action capable of modifying the state
*/
createAction <TActionPayload>(actionDef: IActionDef<TStatePayload, TActionPayload>): StateAction<TStatePayload, TActionPayload> {
return new StateAction(actionDef);
}
/** /**
* dispatches an action on the statepart level * dispatches an action on the statepart level
*/ */
async dispatch(stateAction: StateAction<PayloadType>) { async dispatchAction<T>(stateAction: StateAction<TStatePayload, T>, actionPayload: T) {
const newState = stateAction.actionDef(this.getState()); const newState = await stateAction.actionDef(this, actionPayload);
this.setState(newState); this.setState(newState);
} }
} }