Skip to content

Commit

Permalink
feat: handle real time events for player events
Browse files Browse the repository at this point in the history
Refs: #26
  • Loading branch information
MaSch0212 committed Jun 22, 2024
1 parent 4089fe7 commit 66a273e
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 9 deletions.
8 changes: 5 additions & 3 deletions src/client/src/app/+state/maps/maps.utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { effect } from '@angular/core';
import { effect, Signal } from '@angular/core';
import { Store } from '@ngrx/store';

import { loadMapsAction } from './maps.actions';
import { selectMapsActionState } from './maps.selectors';
import { injectEx, OptionalInjector } from '../../utils/angular.utils';

export function keepMapsLoaded(options?: OptionalInjector & { reload?: boolean }) {
export function keepMapsLoaded(
options?: OptionalInjector & { reload?: boolean; enabled?: Signal<boolean> }
) {
const store = injectEx(Store, options);
const actionState = store.selectSignal(selectMapsActionState('load'));

Expand All @@ -15,7 +17,7 @@ export function keepMapsLoaded(options?: OptionalInjector & { reload?: boolean }

effect(
() => {
if (actionState().state === 'none') {
if (options?.enabled?.() !== false && actionState().state === 'none') {
store.dispatch(loadMapsAction({ reload: false }));
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { inject } from '@angular/core';
import { on } from '@ngrx/store';
import { switchMap } from 'rxjs';
import { mergeMap } from 'rxjs';

import { EventsService } from '../../../api/services';
import { parsePlayerEvent, PlayerEvent } from '../../../models/parsed-models';
Expand All @@ -13,7 +13,7 @@ import { selectPlayerEventsActionState } from '../player-events.selectors';
import { PlayerEventsFeatureState, playerEventEntityAdapter } from '../player-events.state';

export const loadPlayerEventAction = createHttpAction<
{ eventId: string; reload?: boolean },
{ eventId: string; reload?: boolean; silent?: boolean },
PlayerEvent
>()(PLAYER_EVENTS_ACTION_SCOPE, 'Load Player Event');

Expand All @@ -22,14 +22,19 @@ export const loadPlayerEventReducers: Reducers<PlayerEventsFeatureState> = [
playerEventEntityAdapter.upsertOne(response, state)
),
handleHttpAction('loadOne', loadPlayerEventAction, {
condition: (s, p) => p.silent !== true,
startCondition: (s, p) => !s.entities[p.eventId] || p.reload === true,
}),
];

export const loadPlayerEventEffects: Effects = {
loadPlayerEvent$: createFunctionalEffect.dispatching((api = inject(EventsService)) =>
onHttpAction(loadPlayerEventAction, selectPlayerEventsActionState('loadOne')).pipe(
switchMap(({ props }) =>
onHttpAction(
loadPlayerEventAction,
selectPlayerEventsActionState('loadOne'),
p => !!p.props.silent
).pipe(
mergeMap(({ props }) =>
toHttpAction(getPlayerEvent(api, props), loadPlayerEventAction, props)
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { createAction, on, props } from '@ngrx/store';

import { Reducers } from '../../utils';
import { PLAYER_EVENTS_ACTION_SCOPE } from '../consts';
import { playerEventEntityAdapter, PlayerEventsFeatureState } from '../player-events.state';

export const playerEventRemovedAction = createAction(
`[${PLAYER_EVENTS_ACTION_SCOPE}] Player Event Removed`,
props<{ eventId: string }>()
);

export const playerEventRemovedReducers: Reducers<PlayerEventsFeatureState> = [
on(playerEventRemovedAction, (state, { eventId }) =>
playerEventEntityAdapter.removeOne(eventId, state)
),
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { createAction, on } from '@ngrx/store';
import { produce } from 'immer';

import { initialActionState } from '../../action-state';
import { Reducers } from '../../utils';
import { PLAYER_EVENTS_ACTION_SCOPE } from '../consts';
import { playerEventEntityAdapter, PlayerEventsFeatureState } from '../player-events.state';

export const resetPlayerEventsAction = createAction(`[${PLAYER_EVENTS_ACTION_SCOPE}] Reset`);

export const resetPlayerEventsReducers: Reducers<PlayerEventsFeatureState> = [
on(resetPlayerEventsAction, state =>
playerEventEntityAdapter.removeAll(
produce(state, draft => {
draft.actionStates.load = initialActionState;
})
)
),
];
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export { loadPlayerEventAction } from './actions/load-player-event.action';
export { loadPlayerEventsAction } from './actions/load-player-events.action';
export { playerEventRemovedAction } from './actions/player-event-removed.action';
export { resetPlayerEventsAction } from './actions/reset-player-events.action';
export { updateEventRegistrationAction } from './actions/update-event-registration.action';
48 changes: 47 additions & 1 deletion src/client/src/app/+state/player-events/player-events.effects.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,56 @@
import { loadPlayerEventEffects } from './actions/load-player-event.action';
import { inject } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { Store } from '@ngrx/store';
import { EMPTY, filter, map, mergeMap, of, skip, withLatestFrom } from 'rxjs';

import { loadPlayerEventAction, loadPlayerEventEffects } from './actions/load-player-event.action';
import { loadPlayerEventsEffects } from './actions/load-player-events.action';
import { updateEventRegistrationEffects } from './actions/update-event-registration.action';
import { playerEventRemovedAction, resetPlayerEventsAction } from './player-events.actions';
import { playerEventSelectors } from './player-events.selectors';
import { RealtimeEventsService } from '../../services/realtime-events.service';
import { createFunctionalEffect } from '../functional-effect';
import { Effects } from '../utils';

export const PlayerEventsFeatureEffects: Effects[] = [
loadPlayerEventsEffects,
loadPlayerEventEffects,
updateEventRegistrationEffects,
{
playerEventUpdated$: createFunctionalEffect.dispatching((store = inject(Store)) =>
inject(RealtimeEventsService).playerEventChanged.pipe(
withLatestFrom(store.select(playerEventSelectors.selectEntities)),
mergeMap(([{ eventId, changeType }, entities]) => {
if (changeType === 'updated') {
return eventId in entities
? of(loadPlayerEventAction({ eventId, reload: true, silent: true }))
: EMPTY;
} else if (changeType === 'created') {
return of(loadPlayerEventAction({ eventId, reload: true, silent: true }));
} else if (changeType === 'deleted') {
return of(playerEventRemovedAction({ eventId }));
}
return EMPTY;
})
)
),
playerEventRegistrationUpdated$: createFunctionalEffect.dispatching((store = inject(Store)) =>
inject(RealtimeEventsService).playerEventRegistrationChanged.pipe(
withLatestFrom(store.select(playerEventSelectors.selectEntities)),
mergeMap(([{ eventId }, entities]) =>
eventId in entities
? of(loadPlayerEventAction({ eventId, reload: true, silent: true }))
: EMPTY
)
)
),

onServerReconnect$: createFunctionalEffect.dispatching(() =>
toObservable(inject(RealtimeEventsService).isConnected).pipe(
skip(1),
filter(x => x),
map(() => resetPlayerEventsAction())
)
),
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { produce } from 'immer';

import { loadPlayerEventReducers } from './actions/load-player-event.action';
import { loadPlayerEventsReducers } from './actions/load-player-events.action';
import { playerEventRemovedReducers } from './actions/player-event-removed.action';
import { resetPlayerEventsReducers } from './actions/reset-player-events.action';
import { updateEventRegistrationReducers } from './actions/update-event-registration.action';
import {
PlayerEventsFeatureState,
Expand All @@ -23,6 +25,8 @@ export const playerEventsReducer = createReducer<PlayerEventsFeatureState>(

...loadPlayerEventsReducers,
...loadPlayerEventReducers,
...playerEventRemovedReducers,
...resetPlayerEventsReducers,
...updateEventRegistrationReducers,

on(addEventAction.success, (state, { response }) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
computed,
effect,
inject,
Injector,
input,
signal,
untracked,
Expand Down Expand Up @@ -57,6 +58,7 @@ import { hasTouchScreen } from '../../../utils/user-agent.utils';
export class EventTimeslotDialogComponent {
private readonly _store = inject(Store);
private readonly _formBuilder = inject(FormBuilder);
private readonly _injector = inject(Injector);

public readonly event = input.required<Event>();
public readonly timeslot = input<EventTimeslot | null>(null);
Expand Down Expand Up @@ -125,7 +127,7 @@ export class EventTimeslotDialogComponent {
}

public open() {
keepMapsLoaded();
keepMapsLoaded({ injector: this._injector, enabled: this.visible });

this.visible.set(true);
}
Expand Down

0 comments on commit 66a273e

Please sign in to comment.