Skip to content

Commit

Permalink
refactor: add debug logging and improve some technical things (#133)
Browse files Browse the repository at this point in the history
- Added debug logging (only logged if use is in role "developer")
- Added "no-console" linting rule
- Fixed all lint warnings
- Fix some state related issues
  • Loading branch information
MaSch0212 authored Jul 7, 2024
1 parent cad1a86 commit 24be04b
Show file tree
Hide file tree
Showing 32 changed files with 386 additions and 133 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"**/*.code-search": true,
"**/.cache": true,
"**/dist": true,
"**/.angular": true,
"**/coverage": true,
"pnpm-lock.yaml": true
},
Expand Down
3 changes: 2 additions & 1 deletion src/client/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"project": "./tsconfig.json"
},
"rules": {
"@angular-eslint/prefer-on-push-component-change-detection": "error"
"@angular-eslint/prefer-on-push-component-change-detection": "error",
"no-console": "error"
}
}
5 changes: 3 additions & 2 deletions src/client/src/app/+state/action-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ export type HttpActionCreator<
error: _ActionCreatorWithResponse<`[${TScope}] [Error] ${TName}`, TProps, unknown>;
};

type x = HttpActionCreator<'a', 'b', { a: string }, { b: number }>;

export function createHttpAction<TProps extends object, TSuccess = unknown>() {
return <TScope extends string, TName extends string>(scope: TScope, name: TName) => {
const action = createAction(`[${scope}] ${name}`, creator<TProps>());
Expand All @@ -97,6 +95,7 @@ export function handleHttpAction<
TActionStateName extends TInferredState extends { actionStates: Record<string, ActionState> }
? keyof TInferredState['actionStates']
: never,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TAction extends HttpActionCreator<string, string, any, any>,
TProps = Parameters<TAction>[0],
TInferredState = TState,
Expand Down Expand Up @@ -134,12 +133,14 @@ export function handleHttpAction<
} else if (props.type === action.success.type) {
actionStates[actionStateName as string] = successActionState;
} else if (props.type === action.error.type) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
actionStates[actionStateName as string] = errorActionState((props as any).response);
}
})
);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function onHttpAction<T extends HttpActionCreator<string, string, any, any>>(
action: T,
actionStateSelector?: Selector<object, ActionState>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ export const loadEventsReducers: Reducers<EventsFeatureState> = [
})
)
),
handleHttpAction('load', loadEventsAction, { condition: (s, p) => !p.silent }),
handleHttpAction('load', loadEventsAction, {
condition: (s, p) => !p.silent,
startCondition: (s, p) => s.actionStates.load.state === 'none' || p.reload === true,
}),
];

export const loadEventsEffects: Effects = {
Expand Down
15 changes: 11 additions & 4 deletions src/client/src/app/+state/events/events.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ export function selectEventsActionState(action: keyof EventsFeatureState['action
return createDistinctSelector(selectEventsActionStates, state => state[action]);
}

export function selectEvent(id: string) {
return createDistinctSelector(selectEventsFeature, state => state.entities[id]);
export function selectEvent(id: string | null | undefined) {
return createDistinctSelector(selectEventsFeature, state =>
id ? state.entities[id] ?? null : null
);
}

export function selectEventTimeslot(eventId: string, timeslotId: string) {
export function selectEventTimeslot(
eventId: string | null | undefined,
timeslotId: string | null | undefined
) {
return createDistinctSelector(selectEventsFeature, state =>
state.entities[eventId]?.timeslots.find(x => x.id === timeslotId)
eventId && timeslotId
? state.entities[eventId]?.timeslots.find(x => x.id === timeslotId) ?? null
: null
);
}
30 changes: 22 additions & 8 deletions src/client/src/app/+state/events/events.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,35 @@ export function keepEventsLoaded(options?: OptionalInjector) {
.subscribe(() => store.dispatch(loadEventsAction({ reload: true, silent: true })));
}

export function keepEventLoaded(eventId: Signal<string>, options?: OptionalInjector) {
export function keepEventLoaded(
eventId: Signal<string | null | undefined>,
options?: OptionalInjector
) {
const store = injectEx(Store, options);

effect(() => store.dispatch(loadEventAction({ eventId: eventId(), reload: false })), {
...options,
allowSignalWrites: true,
});
effect(
() => {
const id = eventId();
if (id) {
store.dispatch(loadEventAction({ eventId: id, reload: false }));
}
},
{
...options,
allowSignalWrites: true,
}
);

store
.select(selectEventsActionState('loadOne'))
.pipe(
filter(x => x.state === 'none'),
takeUntilDestroyed(injectEx(DestroyRef, options))
)
.subscribe(() =>
store.dispatch(loadEventAction({ eventId: eventId(), reload: true, silent: true }))
);
.subscribe(() => {
const id = eventId();
if (id) {
store.dispatch(loadEventAction({ eventId: id, reload: true, silent: true }));
}
});
}
2 changes: 2 additions & 0 deletions src/client/src/app/+state/functional-effect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function _createFunctionalEffect<Source extends () => Observable<unknown>>(
return createEffect(source, actualConfig);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
type EffectResult<OT> = Observable<OT> | ((...args: any[]) => Observable<OT>);
type ConditionallyDisallowActionCreator<DT, Result> = DT extends false
? unknown
Expand All @@ -46,6 +47,7 @@ export type CreateFunctionalEffectFunction = typeof _createFunctionalEffect & {
};

export const createFunctionalEffect: CreateFunctionalEffectFunction = (() => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(_createFunctionalEffect as any).dispatching = _createDispatchingFunctionalEffect;
return _createFunctionalEffect as CreateFunctionalEffectFunction;
})();
Expand Down
5 changes: 4 additions & 1 deletion src/client/src/app/+state/maps/actions/load-maps.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ export const loadMapsReducers: Reducers<MapsFeatureState> = [
props.reload ? mapsEntityAdapter.removeAll(state) : state
)
),
handleHttpAction('load', loadMapsAction, { condition: (s, p) => !p.silent }),
handleHttpAction('load', loadMapsAction, {
condition: (s, p) => !p.silent,
startCondition: (s, p) => s.actionStates.load.state === 'none' || p.reload === true,
}),
];

export const loadMapsEffects: Effects = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ export const loadPlayerEventsReducers: Reducers<PlayerEventsFeatureState> = [
})
)
),
handleHttpAction('load', loadPlayerEventsAction, { condition: (s, p) => !p.silent }),
handleHttpAction('load', loadPlayerEventsAction, {
condition: (s, p) => !p.silent,
startCondition: (s, p) => s.actionStates.load.state === 'none' || p.reload === true,
}),
];

export const loadPlayerEventsEffects: Effects = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { switchMap } from 'rxjs';

import { UserSettingsService } from '../../../api/services';
import { UserSettings } from '../../../models/parsed-models';
import { RealtimeEventsService } from '../../../services/realtime-events.service';
import { isEmptyObject, removeUndefinedProperties } from '../../../utils/common.utils';
import { createHttpAction, handleHttpAction, onHttpAction, toHttpAction } from '../../action-state';
import { createFunctionalEffect } from '../../functional-effect';
Expand Down Expand Up @@ -35,19 +34,18 @@ export const updateUserSettingsReducers: Reducers<UserSettingsFeatureState> = [
];

export const updateUserSettingsEffects: Effects = {
updateUserSettings$: createFunctionalEffect.dispatching(
(api = inject(UserSettingsService), events = inject(RealtimeEventsService)) =>
onHttpAction(updateUserSettingsAction, selectUserSettingsActionState('update')).pipe(
switchMap(({ props }) =>
toHttpAction(
updateUserSettings(api, props),
updateUserSettingsAction,
props
// , () =>
// events.skipEvent('userSettingsChanged')
)
updateUserSettings$: createFunctionalEffect.dispatching((api = inject(UserSettingsService)) =>
onHttpAction(updateUserSettingsAction, selectUserSettingsActionState('update')).pipe(
switchMap(({ props }) =>
toHttpAction(
updateUserSettings(api, props),
updateUserSettingsAction,
props
// , () =>
// events.skipEvent('userSettingsChanged')
)
)
)
),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { DestroyRef } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Store } from '@ngrx/store';
import { filter, map } from 'rxjs';
import { filter } from 'rxjs';

import { loadUserSettingsAction } from './user-settings.actions';
import { selectUserSettingsActionState } from './user-settings.selectors';
import { injectEx, OptionalInjector } from '../../utils/angular.utils';

export function keepUserSettingsLoaded(options?: OptionalInjector) {
const store = injectEx(Store, options);
store.dispatch(loadUserSettingsAction({ reload: false }));
store
.select(selectUserSettingsActionState('load'))
.pipe(
filter(x => x.state === 'none'),
map((_, index) => index),
takeUntilDestroyed(injectEx(DestroyRef, options))
)
.subscribe(i => store.dispatch(loadUserSettingsAction({ reload: true, silent: i > 0 })));
.subscribe(() => store.dispatch(loadUserSettingsAction({ reload: true, silent: true })));
}
4 changes: 2 additions & 2 deletions src/client/src/app/+state/users/actions/update-user.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ export const updateUserEffects = {
(store = inject(Store), api = inject(UserAdministrationService)) =>
onHttpAction(updateUserAction, selectUsersActionState('update')).pipe(
concatLatestFrom(({ props }) => store.select(selectUser(props.id))),
filter(([, oldUser]) => !!oldUser),
filter((x): x is [ReturnType<typeof updateUserAction>, User] => !!x[1]),
switchMap(([{ props }, oldUser]) =>
toHttpAction(updateUser(api, props, oldUser!), updateUserAction, props)
toHttpAction(updateUser(api, props, oldUser), updateUserAction, props)
)
)
),
Expand Down
6 changes: 5 additions & 1 deletion src/client/src/app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ export const appConfig: ApplicationConfig = {
router: routerReducer,
}),
provideRouterStore(),
provideStoreDevtools({ name: `Minigolf Friday (${Math.random().toString(16).substring(2)})` }),
provideStoreDevtools({
name: `Minigolf Friday (${Math.random().toString(16).substring(2)})`,
autoPause: true,
maxAge: 1000,
}),
provideAppState(),
provideUsersState(),
provideMapsState(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,10 @@ export class EventDetailsComponent {
() => this.canBuildInstances() && this.event() && !this.event()?.startedAt
);

protected readonly canCommit = computed(
() =>
this.event() &&
this.event()?.staged &&
this.event()?.timeslots &&
this.event()!.timeslots.length > 0
);
protected readonly canCommit = computed(() => {
const event = this.event();
return event && event.staged && event.timeslots && event.timeslots.length > 0;
});

protected readonly allowToStart = computed(
() => this.hasInstances() && this.allTimeslotsHaveMaps()
Expand Down Expand Up @@ -138,10 +135,13 @@ export class EventDetailsComponent {
}

protected deleteEvent() {
const event = this.event();
if (!event) return;

this._confirmationService.confirm({
header: this.translations.events_deleteDialog_title(),
message: interpolate(this.translations.events_deleteDialog_text(), {
date: formatDate(this.event()!.date, 'mediumDate', this.locale()),
date: formatDate(event.date, 'mediumDate', this.locale()),
}),
acceptLabel: this.translations.shared_delete(),
acceptButtonStyleClass: 'p-button-danger',
Expand All @@ -151,18 +151,21 @@ export class EventDetailsComponent {
accept: () => {
this._store.dispatch(
removeEventAction({
eventId: this.eventId()!,
eventId: event.id,
})
);
},
});
}

protected startEvent() {
const event = this.event();
if (!event) return;

this._confirmationService.confirm({
header: this.translations.events_startDialog_title(),
message: interpolate(this.translations.events_startDialog_text(), {
date: formatDate(this.event()!.date, 'mediumDate', this.locale()),
date: formatDate(event.date, 'mediumDate', this.locale()),
}),
acceptLabel: this.translations.shared_start(),
acceptButtonStyleClass: 'p-button-success',
Expand All @@ -172,18 +175,21 @@ export class EventDetailsComponent {
accept: () => {
this._store.dispatch(
startEventAction({
eventId: this.eventId()!,
eventId: event.id,
})
);
},
});
}

protected commitEvent() {
const event = this.event();
if (!event) return;

this._confirmationService.confirm({
header: this.translations.events_commitDialog_title(),
message: interpolate(this.translations.events_commitDialog_text(), {
date: formatDate(this.event()!.date, 'mediumDate', this.locale()),
date: formatDate(event.date, 'mediumDate', this.locale()),
}),
acceptLabel: this.translations.shared_commit(),
acceptButtonStyleClass: 'p-button-success',
Expand All @@ -193,7 +199,7 @@ export class EventDetailsComponent {
accept: () => {
this._store.dispatch(
commitEventAction({
eventId: this.eventId()!,
eventId: event.id,
commit: true,
})
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ export class EventTimeslotDialogComponent {

const timeslot = untracked(() => this.timeslot());
if (this.visible() && timeslot) {
console.log('timeslot', timeslot);
untracked(() =>
this.form.setValue({
time: dateWithTime(new Date(), timeslot.time),
Expand Down
Loading

0 comments on commit 24be04b

Please sign in to comment.