diff --git a/.eslint/typescript.eslintrc.cjs b/.eslint/typescript.eslintrc.cjs index acabc7cd0..916890ae7 100644 --- a/.eslint/typescript.eslintrc.cjs +++ b/.eslint/typescript.eslintrc.cjs @@ -116,6 +116,12 @@ module.exports = { message: 'You probably want to import this from lodash-es instead.', }, + { + name: '@ngrx/store', + importNames: ['Store'], + message: + 'You probably want to use the StoreService instead.', + }, ], patterns: [ { diff --git a/frontend/README.md b/frontend/README.md index 3a22bf77e..f81317a1f 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -91,7 +91,9 @@ In `src/app` and every descending folder, the following guidelines apply: Commonly used [selectors](https://ngrx.io/guide/store/selectors) should go in [./src/app/state/application/selectors](./src/app/state/application/selectors/). -You can assume that the Store has the current exercise state (either of a live exercise or an exercise in time travel) if you are in `src/app/pages/exercises/exercise`. We use [route guards](https://angular.io/guide/router-tutorial-toh#canactivate-requiring-authentication) for this. +Do not access the ngrx-store directly, use the [StoreService](./src/app/core/store.service.ts) instead. + +You can assume that the store has the current exercise state (either of a live exercise or an exercise in time travel) if you are in `src/app/pages/exercises/exercise`. We use [route guards](https://angular.io/guide/router-tutorial-toh#canactivate-requiring-authentication) for this. If you want to modify the exercise state, do not do it via [reducers](https://ngrx.io/guide/store/reducers) in the store, but propose an action (optimistically) via the [ExerciseService](./src/app/core/exercise.service.ts). The action will automatically be applied to the store. diff --git a/frontend/src/app/app.component.ts b/frontend/src/app/app.component.ts index 856f41f05..c92255a3d 100644 --- a/frontend/src/app/app.component.ts +++ b/frontend/src/app/app.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +// eslint-disable-next-line no-restricted-imports import { Store } from '@ngrx/store'; import { httpOrigin, websocketOrigin } from './core/api-origins'; import { setupCypressTestingValues } from './shared/functions/cypress'; diff --git a/frontend/src/app/core/api.service.ts b/frontend/src/app/core/api.service.ts index cbf05bc64..8514ac966 100644 --- a/frontend/src/app/core/api.service.ts +++ b/frontend/src/app/core/api.service.ts @@ -1,6 +1,5 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { ExerciseIds, ExerciseTimeline, @@ -8,18 +7,17 @@ import type { } from 'digital-fuesim-manv-shared'; import { freeze } from 'immer'; import { lastValueFrom } from 'rxjs'; -import type { AppState } from '../state/app.state'; import { selectExerciseId } from '../state/application/selectors/application.selectors'; -import { selectStateSnapshot } from '../state/get-state-snapshot'; import { httpOrigin } from './api-origins'; import { MessageService } from './messages/message.service'; +import { StoreService } from './store.service'; @Injectable({ providedIn: 'root', }) export class ApiService { constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly messageService: MessageService, private readonly httpClient: HttpClient ) {} @@ -40,7 +38,7 @@ export class ApiService { } public async exerciseHistory() { - const exerciseId = selectStateSnapshot(selectExerciseId, this.store); + const exerciseId = this.storeService.select(selectExerciseId); return lastValueFrom( this.httpClient.get( `${httpOrigin}/api/exercise/${exerciseId}/history` diff --git a/frontend/src/app/core/application.service.ts b/frontend/src/app/core/application.service.ts index 702cc3e4e..1ab64a734 100644 --- a/frontend/src/app/core/application.service.ts +++ b/frontend/src/app/core/application.service.ts @@ -1,14 +1,12 @@ import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; import { assertExhaustiveness } from 'digital-fuesim-manv-shared'; -import type { AppState } from '../state/app.state'; import { selectExerciseId, selectExerciseStateMode, selectLastClientName, } from '../state/application/selectors/application.selectors'; -import { selectStateSnapshot } from '../state/get-state-snapshot'; import { ExerciseService } from './exercise.service'; +import { StoreService } from './store.service'; import { TimeTravelService } from './time-travel.service'; /** @@ -22,16 +20,15 @@ export class ApplicationService { constructor( private readonly timeTravelService: TimeTravelService, private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} /** * A new mode must be set immediately after this function is called */ private stopCurrentMode() { - const currentExerciseStateMode = selectStateSnapshot( - selectExerciseStateMode, - this.store + const currentExerciseStateMode = this.storeService.select( + selectExerciseStateMode ); switch (currentExerciseStateMode) { case 'exercise': @@ -63,8 +60,8 @@ export class ApplicationService { */ public async rejoinExercise() { return this.joinExercise( - selectStateSnapshot(selectExerciseId, this.store)!, - selectStateSnapshot(selectLastClientName, this.store)! + this.storeService.select(selectExerciseId)!, + this.storeService.select(selectLastClientName)! ); } diff --git a/frontend/src/app/core/exercise.service.ts b/frontend/src/app/core/exercise.service.ts index 24bc68e31..48e42361f 100644 --- a/frontend/src/app/core/exercise.service.ts +++ b/frontend/src/app/core/exercise.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { ClientToServerEvents, ExerciseAction, @@ -21,7 +20,6 @@ import { import type { Socket } from 'socket.io-client'; import { io } from 'socket.io-client'; import { handleChanges } from '../shared/functions/handle-changes'; -import type { AppState } from '../state/app.state'; import { createApplyServerActionAction, createJoinExerciseAction, @@ -38,10 +36,10 @@ import { selectOwnClient, selectVisibleVehicles, } from '../state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from '../state/get-state-snapshot'; import { websocketOrigin } from './api-origins'; import { MessageService } from './messages/message.service'; import { OptimisticActionHandler } from './optimistic-action-handler'; +import { StoreService } from './store.service'; /** * This Service deals with the state synchronization of a live exercise. @@ -68,7 +66,7 @@ export class ExerciseService { >; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly messageService: MessageService ) { this.socket.on('performAction', (action: ExerciseAction) => { @@ -138,7 +136,7 @@ export class ExerciseService { }); return false; } - this.store.dispatch( + this.storeService.dispatch( createJoinExerciseAction( joinResponse.payload, getStateResponse.payload, @@ -153,10 +151,14 @@ export class ExerciseService { SocketResponse >( (exercise) => - this.store.dispatch(createSetExerciseStateAction(exercise)), - () => selectStateSnapshot(selectExerciseState, this.store), + this.storeService.dispatch( + createSetExerciseStateAction(exercise) + ), + () => this.storeService.select(selectExerciseState), (action) => - this.store.dispatch(createApplyServerActionAction(action)), + this.storeService.dispatch( + createApplyServerActionAction(action) + ), async (action) => { const response = await new Promise( (resolve) => { @@ -190,7 +192,7 @@ export class ExerciseService { this.socket.disconnect(); this.stopNotifications(); this.optimisticActionHandler = undefined; - this.store.dispatch(createLeaveExerciseAction()); + this.storeService.dispatch(createLeaveExerciseAction()); } /** @@ -200,8 +202,7 @@ export class ExerciseService { */ public async proposeAction(action: ExerciseAction, optimistic = false) { if ( - selectStateSnapshot(selectExerciseStateMode, this.store) !== - 'exercise' || + this.storeService.select(selectExerciseStateMode) !== 'exercise' || this.optimisticActionHandler === undefined ) { // Especially during timeTravel, buttons that propose actions are only deactivated via best effort @@ -220,11 +221,11 @@ export class ExerciseService { private startNotifications() { // If the user is a trainer, display a message for each joined or disconnected client - this.store - .select(selectCurrentRole) + this.storeService + .select$(selectCurrentRole) .pipe( filter((role) => role === 'trainer'), - switchMap(() => this.store.select(selectClients)), + switchMap(() => this.storeService.select$(selectClients)), pairwise(), takeUntil(this.stopNotifications$) ) @@ -249,8 +250,8 @@ export class ExerciseService { }); }); // If the user is restricted to a viewport, display a message for each vehicle that arrived at this viewport - this.store - .select(selectOwnClient) + this.storeService + .select$(selectOwnClient) .pipe( filter( (client) => @@ -258,8 +259,8 @@ export class ExerciseService { !client.isInWaitingRoom ), switchMap((client) => - this.store - .select(selectVisibleVehicles) + this.storeService + .select$(selectVisibleVehicles) // pipe in here so no pairs of events from different viewports are built // Do not trigger the message if the vehicle was removed and added again at the same time .pipe(debounceTime(0), pairwise()) diff --git a/frontend/src/app/core/store.service.ts b/frontend/src/app/core/store.service.ts new file mode 100644 index 000000000..4c6200ec6 --- /dev/null +++ b/frontend/src/app/core/store.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@angular/core'; +import type { Action, Selector } from '@ngrx/store'; +// eslint-disable-next-line no-restricted-imports +import { Store } from '@ngrx/store'; +import type { Observable } from 'rxjs'; +import { first } from 'rxjs'; +import type { AppState } from '../state/app.state'; + +/** + * This service is a wrapper around the ngrx-store. + * It changes the API to be more convenient to use for this concrete application. + * The normal ngrx-store shouldn't be used directly. Instead, always use this service. + */ +@Injectable({ + providedIn: 'root', +}) +export class StoreService { + constructor(private readonly store: Store) {} + + /** + * @returns An observable that on subscription emits the selected part of the current state + * and then emits the new state each time it changes. + */ + public select$(selector: Selector): Observable { + return this.store.select(selector); + } + + /** + * If you want to observe the state and get notified of changes, + * you should use {@link select$} on the store. + * + * @returns a synchronous snapshot of the selected part of the state. + */ + public select(selector: Selector): T { + // There is sadly currently no other way to get the state synchronously... + let result: T; + // "Subscribing to Store will always be guaranteed to be synchronous" - https://github.com/ngrx/platform/issues/227#issuecomment-431682349 + this.store + .select(selector) + .pipe(first()) + .subscribe((s) => (result = s)); + return result!; + } + + /** + * Dispatches an action to the ngrx-store. + * + * Usually you want to propose an action via the {@link ExerciseService} to the backend instead. + */ + // TODO: The action should be a literal union of all our actions. + // NgRx doesn't support this yet, so we will have to get creative ourselves. + public dispatch(action: Action): void { + this.store.dispatch(action); + } +} diff --git a/frontend/src/app/core/time-travel.service.ts b/frontend/src/app/core/time-travel.service.ts index 82635cdd1..c6f2311ba 100644 --- a/frontend/src/app/core/time-travel.service.ts +++ b/frontend/src/app/core/time-travel.service.ts @@ -1,10 +1,8 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { ExerciseTimeline } from 'digital-fuesim-manv-shared'; import { freeze } from 'immer'; import { lastValueFrom } from 'rxjs'; -import type { AppState } from '../state/app.state'; import { createJumpToTimeAction, createStartTimeTravelAction, @@ -14,9 +12,9 @@ import { selectTimeConstraints, } from '../state/application/selectors/application.selectors'; import { selectCurrentTime } from '../state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from '../state/get-state-snapshot'; import { httpOrigin } from './api-origins'; import { MessageService } from './messages/message.service'; +import { StoreService } from './store.service'; import { TimeJumpHelper } from './time-jump-helper'; /** @@ -35,7 +33,7 @@ export class TimeTravelService { private activatingTimeTravel = false; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly httpClient: HttpClient, private readonly messageService: MessageService ) {} @@ -45,7 +43,7 @@ export class TimeTravelService { */ public async startTimeTravel() { this.activatingTimeTravel = true; - const exerciseId = selectStateSnapshot(selectExerciseId, this.store); + const exerciseId = this.storeService.select(selectExerciseId); const exerciseTimeLine = await lastValueFrom( this.httpClient.get( `${httpOrigin}/api/exercise/${exerciseId}/history` @@ -68,8 +66,8 @@ export class TimeTravelService { this.timeJumpHelper = new TimeJumpHelper(exerciseTimeLine); // Travel to the start of the exercise // TODO: This should be calculated from the timeline (in the TimeJumpHelper - maybe cache states in between) - const endTime = selectStateSnapshot(selectCurrentTime, this.store); - this.store.dispatch( + const endTime = this.storeService.select(selectCurrentTime); + this.storeService.dispatch( createStartTimeTravelAction(exerciseTimeLine.initialState, endTime) ); } @@ -79,10 +77,7 @@ export class TimeTravelService { * @param exerciseTime The time to travel to, if it isn't in the timeConstraints, it will be clamped appropriately */ public jumpToTime(exerciseTime: number) { - const timeConstraints = selectStateSnapshot( - selectTimeConstraints, - this.store - ); + const timeConstraints = this.storeService.select(selectTimeConstraints); if (!timeConstraints || !this.timeJumpHelper) { throw new Error('Start the time travel before jumping to a time!'); } @@ -90,7 +85,7 @@ export class TimeTravelService { timeConstraints.start, Math.min(timeConstraints.end, exerciseTime) ); - this.store.dispatch( + this.storeService.dispatch( createJumpToTimeAction( clampedTime, this.timeJumpHelper.getStateAtTime(clampedTime) diff --git a/frontend/src/app/pages/exercises/exercise/exercise/exercise.component.ts b/frontend/src/app/pages/exercises/exercise/exercise/exercise.component.ts index bfdbc7e2d..15df0a39b 100644 --- a/frontend/src/app/pages/exercises/exercise/exercise/exercise.component.ts +++ b/frontend/src/app/pages/exercises/exercise/exercise/exercise.component.ts @@ -1,17 +1,17 @@ import type { OnDestroy } from '@angular/core'; import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; import { cloneDeepMutable, StateExport, StateHistoryCompound, } from 'digital-fuesim-manv-shared'; +import Package from 'package.json'; import { Subject } from 'rxjs'; import { ApiService } from 'src/app/core/api.service'; import { ApplicationService } from 'src/app/core/application.service'; import { MessageService } from 'src/app/core/messages/message.service'; +import { StoreService } from 'src/app/core/store.service'; import { saveBlob } from 'src/app/shared/functions/save-blob'; -import type { AppState } from 'src/app/state/app.state'; import { selectExerciseId, selectExerciseStateMode, @@ -21,9 +21,7 @@ import { selectExerciseState, selectParticipantId, } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { selectOwnClient } from 'src/app/state/application/selectors/shared.selectors'; -import Package from 'package.json'; @Component({ selector: 'app-exercise', @@ -33,26 +31,28 @@ import Package from 'package.json'; export class ExerciseComponent implements OnDestroy { private readonly destroy = new Subject(); - public readonly exerciseStateMode$ = this.store.select( + public readonly exerciseStateMode$ = this.storeService.select$( selectExerciseStateMode ); - public readonly participantId$ = this.store.select(selectParticipantId); - public readonly timeConstraints$ = this.store.select(selectTimeConstraints); - public readonly ownClient$ = this.store.select(selectOwnClient); + public readonly participantId$ = + this.storeService.select$(selectParticipantId); + public readonly timeConstraints$ = this.storeService.select$( + selectTimeConstraints + ); + public readonly ownClient$ = this.storeService.select$(selectOwnClient); readonly version: string = Package.version; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly apiService: ApiService, private readonly applicationService: ApplicationService, private readonly messageService: MessageService ) {} public shareExercise(type: 'participantId' | 'trainerId') { - const id = selectStateSnapshot( - type === 'participantId' ? selectParticipantId : selectExerciseId, - this.store + const id = this.storeService.select( + type === 'participantId' ? selectParticipantId : selectExerciseId ); const url = `${location.origin}/exercises/${id}`; if (navigator.share) { @@ -86,10 +86,7 @@ export class ExerciseComponent implements OnDestroy { public async exportExerciseWithHistory() { const history = await this.apiService.exerciseHistory(); - const currentState = selectStateSnapshot( - selectExerciseState, - this.store - ); + const currentState = this.storeService.select(selectExerciseState); const blob = new Blob([ JSON.stringify( new StateExport( @@ -107,10 +104,7 @@ export class ExerciseComponent implements OnDestroy { } public exportExerciseState() { - const currentState = selectStateSnapshot( - selectExerciseState, - this.store - ); + const currentState = this.storeService.select(selectExerciseState); const blob = new Blob([ JSON.stringify(new StateExport(cloneDeepMutable(currentState))), ]); diff --git a/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-item/alarm-group-item.component.ts b/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-item/alarm-group-item.component.ts index a57a3a1d5..2dff82b25 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-item/alarm-group-item.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-item/alarm-group-item.component.ts @@ -1,14 +1,12 @@ import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import { AlarmGroup, AlarmGroupVehicle } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectVehicleTemplate, selectVehicleTemplates, } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; @Component({ selector: 'app-alarm-group-item', @@ -20,10 +18,10 @@ export class AlarmGroupItemComponent { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} - public readonly vehicleTemplates$ = this.store.select( + public readonly vehicleTemplates$ = this.storeService.select$( selectVehicleTemplates ); @@ -77,9 +75,8 @@ export class AlarmGroupItemComponent { } public createAlarmGroupVehicle(vehicleTemplateId: UUID) { - const vehicleTemplate = selectStateSnapshot( - createSelectVehicleTemplate(vehicleTemplateId), - this.store + const vehicleTemplate = this.storeService.select( + createSelectVehicleTemplate(vehicleTemplateId) )!; this.exerciseService.proposeAction({ type: '[AlarmGroup] Add AlarmGroupVehicle', diff --git a/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-overview-modal/alarm-group-overview-modal.component.ts b/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-overview-modal/alarm-group-overview-modal.component.ts index bc419a730..308799255 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-overview-modal/alarm-group-overview-modal.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/alarm-group-overview-modal/alarm-group-overview-modal.component.ts @@ -1,9 +1,8 @@ import { Component } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import { AlarmGroup } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectAlarmGroups, selectVehicleTemplates, @@ -20,12 +19,12 @@ export class AlarmGroupOverviewModalComponent { constructor( public activeModal: NgbActiveModal, private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} - public readonly alarmGroups$ = this.store.select(selectAlarmGroups); + public readonly alarmGroups$ = this.storeService.select$(selectAlarmGroups); - public readonly vehicleTemplates$ = this.store.select( + public readonly vehicleTemplates$ = this.storeService.select$( selectVehicleTemplates ); diff --git a/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/vehicle-template-display/vehicle-template-display.component.ts b/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/vehicle-template-display/vehicle-template-display.component.ts index f5736ae4b..a3a6671f2 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/vehicle-template-display/vehicle-template-display.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/alarm-group-overview/vehicle-template-display/vehicle-template-display.component.ts @@ -1,10 +1,9 @@ import type { OnChanges } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { VehicleTemplate } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectVehicleTemplate } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -18,10 +17,10 @@ export class VehicleTemplateDisplayComponent implements OnChanges { public vehicleTemplate$?: Observable; ngOnChanges() { - this.vehicleTemplate$ = this.store.select( + this.vehicleTemplate$ = this.storeService.select$( createSelectVehicleTemplate(this.vehicleTemplateId) ); } - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} } diff --git a/frontend/src/app/pages/exercises/exercise/shared/client-overview/client-overview-table/client-overview-table.component.ts b/frontend/src/app/pages/exercises/exercise/shared/client-overview/client-overview-table/client-overview-table.component.ts index 4cb06851a..c907894c4 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/client-overview/client-overview-table/client-overview-table.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/client-overview/client-overview-table/client-overview-table.component.ts @@ -1,8 +1,7 @@ import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectClients, selectViewports, @@ -14,11 +13,11 @@ import { styleUrls: ['./client-overview-table.component.scss'], }) export class ClientOverviewTableComponent { - public readonly clients$ = this.store.select(selectClients); - public readonly viewports$ = this.store.select(selectViewports); + public readonly clients$ = this.storeService.select$(selectClients); + public readonly viewports$ = this.storeService.select$(selectViewports); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} diff --git a/frontend/src/app/pages/exercises/exercise/shared/core/drag-element.service.ts b/frontend/src/app/pages/exercises/exercise/shared/core/drag-element.service.ts index da9a27dd8..df31a89e2 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/core/drag-element.service.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/core/drag-element.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { // eslint-disable-next-line @typescript-eslint/no-shadow Element, @@ -11,13 +10,13 @@ import type { import { createVehicleParameters, MapImage, + MapPosition, normalZoom, PatientTemplate, + SimulatedRegion, TransferPoint, Viewport, - SimulatedRegion, SimulatedRegionPosition, - MapPosition, } from 'digital-fuesim-manv-shared'; import type { Feature } from 'ol'; import type VectorLayer from 'ol/layer/Vector'; @@ -25,12 +24,11 @@ import type OlMap from 'ol/Map'; import type { Pixel } from 'ol/pixel'; import type VectorSource from 'ol/source/Vector'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectMaterialTemplates, selectPersonnelTemplates, } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import type { FeatureManager } from '../exercise-map/utility/feature-manager'; @Injectable({ @@ -48,7 +46,7 @@ export class DragElementService { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} public registerMap(olMap: OlMap) { @@ -171,14 +169,8 @@ export class DragElementService { { const params = createVehicleParameters( this.transferringTemplate.template, - selectStateSnapshot( - selectMaterialTemplates, - this.store - ), - selectStateSnapshot( - selectPersonnelTemplates, - this.store - ), + this.storeService.select(selectMaterialTemplates), + this.storeService.select(selectPersonnelTemplates), position ); this.exerciseService.proposeAction( diff --git a/frontend/src/app/pages/exercises/exercise/shared/core/statistics/statistics.service.ts b/frontend/src/app/pages/exercises/exercise/shared/core/statistics/statistics.service.ts index dc54695d2..c3bd80e81 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/core/statistics/statistics.service.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/core/statistics/statistics.service.ts @@ -1,27 +1,25 @@ import { Injectable } from '@angular/core'; -import { Store } from '@ngrx/store'; +import type { + Client, + ExerciseState, + Patient, + Personnel, + Vehicle, +} from 'digital-fuesim-manv-shared'; import { - isNotInVehicle, currentCoordinatesOf, + isNotInTransfer, + isNotInVehicle, isOnMap, loopTroughTime, uuid, Viewport, - isNotInTransfer, -} from 'digital-fuesim-manv-shared'; -import type { - Personnel, - Client, - ExerciseState, - Patient, - Vehicle, } from 'digital-fuesim-manv-shared'; import { countBy } from 'lodash-es'; import { ReplaySubject } from 'rxjs'; import { ApiService } from 'src/app/core/api.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectCurrentTime } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import type { AreaStatistics } from './area-statistics'; import type { StatisticsEntry } from './statistics-entry'; @@ -31,7 +29,7 @@ import type { StatisticsEntry } from './statistics-entry'; export class StatisticsService { constructor( private readonly apiService: ApiService, - private readonly store: Store + private readonly storeService: StoreService ) {} public updatingStatistics = false; @@ -48,10 +46,7 @@ export class StatisticsService { public async updateStatistics(): Promise { this.updatingStatistics = true; // The statistics during timeTravel are only up onto the respective point. - const maximumExerciseTime = selectStateSnapshot( - selectCurrentTime, - this.store - ); + const maximumExerciseTime = this.storeService.select(selectCurrentTime); const { initialState, actionsWrappers } = await this.apiService.exerciseHistory(); diff --git a/frontend/src/app/pages/exercises/exercise/shared/editor-panel/edit-image-template-modal/edit-image-template-modal.component.ts b/frontend/src/app/pages/exercises/exercise/shared/editor-panel/edit-image-template-modal/edit-image-template-modal.component.ts index 2d5c6df37..bf02b0df4 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/editor-panel/edit-image-template-modal/edit-image-template-modal.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/editor-panel/edit-image-template-modal/edit-image-template-modal.component.ts @@ -1,7 +1,6 @@ import type { OnInit } from '@angular/core'; import { Component } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import type { MapImageTemplate, Mutable, @@ -9,9 +8,8 @@ import type { } from 'digital-fuesim-manv-shared'; import { cloneDeep } from 'lodash-es'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectMapImageTemplate } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import type { ChangedImageTemplateValues } from '../image-template-form/image-template-form.component'; @Component({ @@ -27,15 +25,14 @@ export class EditImageTemplateModalComponent implements OnInit { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store, + private readonly storeService: StoreService, public readonly activeModal: NgbActiveModal ) {} ngOnInit(): void { this.mapImageTemplate = cloneDeep( - selectStateSnapshot( - createSelectMapImageTemplate(this.mapImageTemplateId), - this.store + this.storeService.select( + createSelectMapImageTemplate(this.mapImageTemplateId) ) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/eoc-log-interface/eoc-log-interface.component.ts b/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/eoc-log-interface/eoc-log-interface.component.ts index 95ea4abf9..f7978b44b 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/eoc-log-interface/eoc-log-interface.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/eoc-log-interface/eoc-log-interface.component.ts @@ -1,11 +1,9 @@ import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; import { map } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectEocLogEntries } from 'src/app/state/application/selectors/exercise.selectors'; import { selectOwnClient } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; @Component({ selector: 'app-eoc-log-interface', @@ -13,8 +11,8 @@ import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; styleUrls: ['./eoc-log-interface.component.scss'], }) export class EocLogInterfaceComponent { - public readonly eocLogEntries$ = this.store - .select(selectEocLogEntries) + public readonly eocLogEntries$ = this.storeService + .select$(selectEocLogEntries) // We want to display the most recent message at the top .pipe(map((logEntries) => [...logEntries].reverse())); @@ -22,14 +20,14 @@ export class EocLogInterfaceComponent { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} public async addEocLogEntry() { const response = await this.exerciseService.proposeAction({ type: '[Emergency Operation Center] Add Log Entry', message: this.newLogEntry, - name: selectStateSnapshot(selectOwnClient, this.store)!.name, + name: this.storeService.select(selectOwnClient)!.name, }); if (response.success) { this.newLogEntry = ''; diff --git a/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/send-alarm-group-interface/send-alarm-group-interface.component.ts b/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/send-alarm-group-interface/send-alarm-group-interface.component.ts index 0b70f0a33..86c19fb00 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/send-alarm-group-interface/send-alarm-group-interface.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/emergency-operations-center/send-alarm-group-interface/send-alarm-group-interface.component.ts @@ -1,17 +1,16 @@ import type { OnDestroy } from '@angular/core'; import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { AlarmGroup, UUID } from 'digital-fuesim-manv-shared'; import { - MapCoordinates, AlarmGroupStartPoint, createVehicleParameters, + MapCoordinates, TransferPoint, } from 'digital-fuesim-manv-shared'; import { Subject, takeUntil } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; import { MessageService } from 'src/app/core/messages/message.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectTransferPoint, createSelectVehicleTemplate, @@ -21,7 +20,6 @@ import { selectTransferPoints, } from 'src/app/state/application/selectors/exercise.selectors'; import { selectOwnClient } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; // We want to remember this let targetTransferPointId: UUID | undefined; @@ -34,9 +32,10 @@ let targetTransferPointId: UUID | undefined; export class SendAlarmGroupInterfaceComponent implements OnDestroy { private readonly destroy$ = new Subject(); - public readonly alarmGroups$ = this.store.select(selectAlarmGroups); + public readonly alarmGroups$ = this.storeService.select$(selectAlarmGroups); - public readonly transferPoints$ = this.store.select(selectTransferPoints); + public readonly transferPoints$ = + this.storeService.select$(selectTransferPoints); public getTransferPointOrderByValue: ( transferPoint: TransferPoint @@ -44,7 +43,7 @@ export class SendAlarmGroupInterfaceComponent implements OnDestroy { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store, + private readonly storeService: StoreService, private readonly messageService: MessageService ) { // reset chosen targetTransferPoint if it gets deleted @@ -68,19 +67,17 @@ export class SendAlarmGroupInterfaceComponent implements OnDestroy { } public sendAlarmGroup(alarmGroup: AlarmGroup) { - const targetTransferPoint = selectStateSnapshot( - createSelectTransferPoint(this.targetTransferPointId!), - this.store + const targetTransferPoint = this.storeService.select( + createSelectTransferPoint(this.targetTransferPointId!) ); // TODO: Refactor this into one action (uuid generation is currently not possible in the reducer) Promise.all( Object.values(alarmGroup.alarmGroupVehicles).flatMap( (alarmGroupVehicle) => { - const vehicleTemplate = selectStateSnapshot( + const vehicleTemplate = this.storeService.select( createSelectVehicleTemplate( alarmGroupVehicle.vehicleTemplateId - ), - this.store + ) ); const vehicleParameters = createVehicleParameters( @@ -88,14 +85,8 @@ export class SendAlarmGroupInterfaceComponent implements OnDestroy { ...vehicleTemplate, name: alarmGroupVehicle.name, }, - selectStateSnapshot( - selectMaterialTemplates, - this.store - ), - selectStateSnapshot( - selectPersonnelTemplates, - this.store - ), + this.storeService.select(selectMaterialTemplates), + this.storeService.select(selectPersonnelTemplates), // TODO: This position is not correct but needs to be provided. // Here one should use a Position with the Transfer. // But this is part of later Refactoring. @@ -136,7 +127,7 @@ export class SendAlarmGroupInterfaceComponent implements OnDestroy { this.exerciseService.proposeAction({ type: '[Emergency Operation Center] Add Log Entry', message: `Alarmgruppe ${alarmGroup.name} wurde alarmiert zu ${targetTransferPoint.externalName}!`, - name: selectStateSnapshot(selectOwnClient, this.store)!.name, + name: this.storeService.select(selectOwnClient)!.name, }); }); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/exercise-map.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/exercise-map.component.ts index cc50ddf7d..282f2cd3c 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/exercise-map.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/exercise-map.component.ts @@ -5,10 +5,9 @@ import { ViewChild, ViewContainerRef, } from '@angular/core'; -import { Store } from '@ngrx/store'; import { Subject, takeUntil } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectCurrentRole, selectRestrictedViewport, @@ -34,13 +33,13 @@ export class ExerciseMapComponent implements AfterViewInit, OnDestroy { private readonly destroy$ = new Subject(); public olMapManager?: OlMapManager; private popupManager?: PopupManager; - public readonly restrictedToViewport$ = this.store.select( + public readonly restrictedToViewport$ = this.storeService.select$( selectRestrictedViewport ); - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService, public readonly dragElementService: DragElementService, public readonly transferLinesService: TransferLinesService @@ -52,7 +51,7 @@ export class ExerciseMapComponent implements AfterViewInit, OnDestroy { this.popoverContainer.nativeElement ); this.olMapManager = new OlMapManager( - this.store, + this.storeService, this.exerciseService, this.openLayersContainer.nativeElement, this.transferLinesService, diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/catering-lines-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/catering-lines-feature-manager.ts index 2375f6769..84f482979 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/catering-lines-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/catering-lines-feature-manager.ts @@ -1,5 +1,4 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { MapBrowserEvent } from 'ol'; import { Feature } from 'ol'; import LineString from 'ol/geom/LineString'; @@ -10,10 +9,10 @@ import type VectorSource from 'ol/source/Vector'; import type { Subject } from 'rxjs'; import { rgbColorPalette } from 'src/app/shared/functions/colors'; import type { CateringLine } from 'src/app/shared/types/catering-line'; -import type { AppState } from 'src/app/state/app.state'; import { selectVisibleCateringLines } from 'src/app/state/application/selectors/shared.selectors'; // eslint-disable-next-line @typescript-eslint/no-shadow import type { Element } from 'digital-fuesim-manv-shared'; +import type { StoreService } from 'src/app/core/store.service'; import type { FeatureManager } from '../utility/feature-manager'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; import type { OpenPopupOptions } from '../utility/popup-manager'; @@ -33,7 +32,7 @@ export class CateringLinesFeatureManager public readonly layer: VectorLayer>; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly olMap: OlMap ) { super(); @@ -53,7 +52,7 @@ export class CateringLinesFeatureManager this.togglePopup$?.subscribe(changePopup$); // Propagate the changes on an element to the featureManager this.registerChangeHandlers( - this.store.select(selectVisibleCateringLines), + this.storeService.select$(selectVisibleCateringLines), destroy$, (element) => this.onElementCreated(element), (element) => this.onElementDeleted(element), diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/delete-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/delete-feature-manager.ts index 85cd6e4b1..cfdcc4db0 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/delete-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/delete-feature-manager.ts @@ -1,5 +1,4 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { MapBrowserEvent, View } from 'ol'; import { Feature } from 'ol'; import { getTopRight } from 'ol/extent'; @@ -12,11 +11,10 @@ import Icon from 'ol/style/Icon'; import Style from 'ol/style/Style'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; // eslint-disable-next-line @typescript-eslint/no-shadow import type { Element } from 'digital-fuesim-manv-shared'; +import type { StoreService } from 'src/app/core/store.service'; import type { FeatureManager } from '../utility/feature-manager'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; import type { OpenPopupOptions } from '../utility/popup-manager'; @@ -29,7 +27,7 @@ function calculateTopRightViewPoint(view: View) { export class DeleteFeatureManager implements FeatureManager { readonly layer: VectorLayer>; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly olMap: OlMap, private readonly exerciseService: ExerciseService ) { @@ -49,7 +47,7 @@ export class DeleteFeatureManager implements FeatureManager { ) { this.olMap.addLayer(this.layer); mapInteractionsManager.addFeatureLayer(this.layer); - if (selectStateSnapshot(selectCurrentRole, this.store) === 'trainer') { + if (this.storeService.select(selectCurrentRole) === 'trainer') { this.makeVisible(); } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/map-images-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/map-images-feature-manager.ts index f1ccef153..85f51745c 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/map-images-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/map-images-feature-manager.ts @@ -1,17 +1,15 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { MapImage, UUID } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; import type Point from 'ol/geom/Point'; import type OlMap from 'ol/Map'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectCurrentRole, selectVisibleMapImages, } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { MapImagePopupComponent } from '../shared/map-image-popup/map-image-popup.component'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; import { PointGeometryHelper } from '../utility/point-geometry-helper'; @@ -27,7 +25,7 @@ export class MapImageFeatureManager extends MoveableFeatureManager { mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisibleMapImages), + this.storeService.select$(selectVisibleMapImages), changePopup$, destroy$, mapInteractionsManager @@ -41,7 +39,7 @@ export class MapImageFeatureManager extends MoveableFeatureManager { constructor( olMap: OlMap, exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) { super( olMap, @@ -74,7 +72,7 @@ export class MapImageFeatureManager extends MoveableFeatureManager { ): void { super.onFeatureClicked(event, feature); - if (selectStateSnapshot(selectCurrentRole, this.store) !== 'trainer') { + if (this.storeService.select(selectCurrentRole) !== 'trainer') { return; } this.togglePopup$.next( @@ -92,7 +90,7 @@ export class MapImageFeatureManager extends MoveableFeatureManager { override isFeatureTranslatable(feature: Feature): boolean { const mapImage = this.getElementFromFeature(feature) as MapImage; return ( - selectStateSnapshot(selectCurrentRole, this.store) === 'trainer' && + this.storeService.select(selectCurrentRole) === 'trainer' && !mapImage.isLocked ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/material-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/material-feature-manager.ts index 92f8829aa..2691773fd 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/material-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/material-feature-manager.ts @@ -1,12 +1,11 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { Material, UUID } from 'digital-fuesim-manv-shared'; import { normalZoom } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; import type OlMap from 'ol/Map'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectVisibleMaterials } from 'src/app/state/application/selectors/shared.selectors'; import { MaterialPopupComponent } from '../shared/material-popup/material-popup.component'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; @@ -24,7 +23,7 @@ export class MaterialFeatureManager extends MoveableFeatureManager { mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisibleMaterials), + this.storeService.select$(selectVisibleMaterials), changePopup$, destroy$, mapInteractionsManager @@ -49,7 +48,7 @@ export class MaterialFeatureManager extends MoveableFeatureManager { constructor( olMap: OlMap, - private readonly store: Store, + private readonly storeService: StoreService, exerciseService: ExerciseService ) { super( diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/patient-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/patient-feature-manager.ts index a8a209297..4934c3032 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/patient-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/patient-feature-manager.ts @@ -1,5 +1,4 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import { Patient } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; @@ -7,10 +6,9 @@ import type OlMap from 'ol/Map'; import { Fill, Stroke } from 'ol/style'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectConfiguration } from 'src/app/state/application/selectors/exercise.selectors'; import { selectVisiblePatients } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { PatientPopupComponent } from '../shared/patient-popup/patient-popup.component'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; import { PointGeometryHelper } from '../utility/point-geometry-helper'; @@ -27,7 +25,7 @@ export class PatientFeatureManager extends MoveableFeatureManager { mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisiblePatients), + this.storeService.select$(selectVisiblePatients), changePopup$, destroy$, mapInteractionsManager @@ -48,10 +46,7 @@ export class PatientFeatureManager extends MoveableFeatureManager { private readonly circleStyleHelper = new CircleStyleHelper( (feature) => { const patient = this.getElementFromFeature(feature) as Patient; - const configuration = selectStateSnapshot( - selectConfiguration, - this.store - ); + const configuration = this.storeService.select(selectConfiguration); const color = Patient.getVisibleStatus( patient, configuration.pretriageEnabled, @@ -77,7 +72,7 @@ export class PatientFeatureManager extends MoveableFeatureManager { ); constructor( - private readonly store: Store, + private readonly storeService: StoreService, olMap: OlMap, exerciseService: ExerciseService ) { diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/personnel-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/personnel-feature-manager.ts index a9a126780..58378f814 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/personnel-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/personnel-feature-manager.ts @@ -1,12 +1,11 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { Personnel, UUID } from 'digital-fuesim-manv-shared'; import { normalZoom } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; import type OlMap from 'ol/Map'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectVisiblePersonnel } from 'src/app/state/application/selectors/shared.selectors'; import { PersonnelPopupComponent } from '../shared/personnel-popup/personnel-popup.component'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; @@ -24,7 +23,7 @@ export class PersonnelFeatureManager extends MoveableFeatureManager { mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisiblePersonnel), + this.storeService.select$(selectVisiblePersonnel), changePopup$, destroy$, mapInteractionsManager @@ -49,7 +48,7 @@ export class PersonnelFeatureManager extends MoveableFeatureManager { constructor( olMap: OlMap, - private readonly store: Store, + private readonly storeService: StoreService, exerciseService: ExerciseService ) { super( diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/simulated-region-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/simulated-region-feature-manager.ts index 9561fa0b1..643f3b752 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/simulated-region-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/simulated-region-feature-manager.ts @@ -1,12 +1,10 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { - UUID, - SimulatedRegion, // eslint-disable-next-line @typescript-eslint/no-shadow Element, + SimulatedRegion, + UUID, } from 'digital-fuesim-manv-shared'; - import { MapCoordinates, Size } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; import type { Polygon } from 'ol/geom'; @@ -17,12 +15,11 @@ import Stroke from 'ol/style/Stroke'; import Style from 'ol/style/Style'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectCurrentRole, selectVisibleSimulatedRegions, } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { SimulatedRegionPopupComponent } from '../shared/simulated-region-popup/simulated-region-popup.component'; import { calculatePopupPositioning } from '../utility/calculate-popup-positioning'; import type { FeatureManager } from '../utility/feature-manager'; @@ -42,7 +39,7 @@ export class SimulatedRegionFeatureManager mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisibleSimulatedRegions), + this.storeService.select$(selectVisibleSimulatedRegions), changePopup$, destroy$, mapInteractionsManager @@ -54,7 +51,7 @@ export class SimulatedRegionFeatureManager constructor( olMap: OlMap, private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) { super( olMap, @@ -167,7 +164,7 @@ export class SimulatedRegionFeatureManager feature: Feature ): void { super.onFeatureClicked(event, feature); - if (selectStateSnapshot(selectCurrentRole, this.store) !== 'trainer') { + if (this.storeService.select(selectCurrentRole) !== 'trainer') { return; } const zoom = this.olMap.getView().getZoom()!; @@ -192,6 +189,6 @@ export class SimulatedRegionFeatureManager } public override isFeatureTranslatable(feature: Feature): boolean { - return selectStateSnapshot(selectCurrentRole, this.store) === 'trainer'; + return this.storeService.select(selectCurrentRole) === 'trainer'; } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-lines-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-lines-feature-manager.ts index 03fc61ff1..aa614cd03 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-lines-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-lines-feature-manager.ts @@ -1,5 +1,4 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; // eslint-disable-next-line @typescript-eslint/no-shadow import type { Element } from 'digital-fuesim-manv-shared'; import type { MapBrowserEvent } from 'ol'; @@ -12,11 +11,10 @@ import type VectorSource from 'ol/source/Vector'; import Stroke from 'ol/style/Stroke'; import Style from 'ol/style/Style'; import type { Subject } from 'rxjs'; +import type { StoreService } from 'src/app/core/store.service'; import type { TransferLine } from 'src/app/shared/types/transfer-line'; -import type { AppState } from 'src/app/state/app.state'; import { selectTransferLines } from 'src/app/state/application/selectors/exercise.selectors'; import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import type { TransferLinesService } from '../../core/transfer-lines.service'; import type { FeatureManager } from '../utility/feature-manager'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; @@ -29,7 +27,7 @@ export class TransferLinesFeatureManager { public readonly layer: VectorLayer>; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly transferLinesService: TransferLinesService, private readonly olMap: OlMap ) { @@ -54,9 +52,9 @@ export class TransferLinesFeatureManager this.olMap.addLayer(this.layer); mapInteractionsManager.addFeatureLayer(this.layer); this.togglePopup$?.subscribe(changePopup$); - if (selectStateSnapshot(selectCurrentRole, this.store) === 'trainer') { + if (this.storeService.select(selectCurrentRole) === 'trainer') { this.registerChangeHandlers( - this.store.select(selectTransferLines), + this.storeService.select$(selectTransferLines), destroy$, (element) => this.onElementCreated(element), (element) => this.onElementDeleted(element), diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-point-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-point-feature-manager.ts index 6fdecf12b..f5ed6c4a1 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-point-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/transfer-point-feature-manager.ts @@ -1,6 +1,5 @@ -import type { Store } from '@ngrx/store'; // eslint-disable-next-line @typescript-eslint/no-shadow -import type { UUID, Element } from 'digital-fuesim-manv-shared'; +import type { Element, UUID } from 'digital-fuesim-manv-shared'; import { TransferPoint, TransferStartPoint } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; import type Point from 'ol/geom/Point'; @@ -8,12 +7,11 @@ import type { TranslateEvent } from 'ol/interaction/Translate'; import type OlMap from 'ol/Map'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectCurrentRole, selectVisibleTransferPoints, } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { ChooseTransferTargetPopupComponent } from '../shared/choose-transfer-target-popup/choose-transfer-target-popup.component'; import { TransferPointPopupComponent } from '../shared/transfer-point-popup/transfer-point-popup.component'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; @@ -29,7 +27,7 @@ export class TransferPointFeatureManager extends MoveableFeatureManager, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) { super( @@ -62,7 +60,7 @@ export class TransferPointFeatureManager extends MoveableFeatureManager): boolean { - return selectStateSnapshot(selectCurrentRole, this.store) === 'trainer'; + return this.storeService.select(selectCurrentRole) === 'trainer'; } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/vehicle-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/vehicle-feature-manager.ts index c996d0e5f..043cc2aaf 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/vehicle-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/vehicle-feature-manager.ts @@ -1,10 +1,9 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { - UUID, - Vehicle, // eslint-disable-next-line @typescript-eslint/no-shadow Element, + UUID, + Vehicle, } from 'digital-fuesim-manv-shared'; import { normalZoom } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; @@ -13,7 +12,7 @@ import type { TranslateEvent } from 'ol/interaction/Translate'; import type OlMap from 'ol/Map'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectVisibleVehicles } from 'src/app/state/application/selectors/shared.selectors'; import { VehiclePopupComponent } from '../shared/vehicle-popup/vehicle-popup.component'; import type { OlMapInteractionsManager } from '../utility/ol-map-interactions-manager'; @@ -31,7 +30,7 @@ export class VehicleFeatureManager extends MoveableFeatureManager { mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisibleVehicles), + this.storeService.select$(selectVisibleVehicles), changePopup$, destroy$, mapInteractionsManager @@ -55,7 +54,7 @@ export class VehicleFeatureManager extends MoveableFeatureManager { constructor( olMap: OlMap, - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) { super( diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/viewport-feature-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/viewport-feature-manager.ts index 4d3de9534..ba8178d03 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/viewport-feature-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/feature-managers/viewport-feature-manager.ts @@ -1,5 +1,4 @@ import type { Type } from '@angular/core'; -import type { Store } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import { MapCoordinates, Size, Viewport } from 'digital-fuesim-manv-shared'; import type { Feature, MapBrowserEvent } from 'ol'; @@ -10,12 +9,11 @@ import Stroke from 'ol/style/Stroke'; import Style from 'ol/style/Style'; import type { Subject } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectCurrentRole, selectVisibleViewports, } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { ViewportPopupComponent } from '../shared/viewport-popup/viewport-popup.component'; import { calculatePopupPositioning } from '../utility/calculate-popup-positioning'; import type { FeatureManager } from '../utility/feature-manager'; @@ -45,7 +43,7 @@ export class ViewportFeatureManager mapInteractionsManager: OlMapInteractionsManager ): void { super.registerFeatureElementManager( - this.store.select(selectVisibleViewports), + this.storeService.select$(selectVisibleViewports), changePopup$, destroy$, mapInteractionsManager @@ -57,7 +55,7 @@ export class ViewportFeatureManager constructor( olMap: OlMap, private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) { super( olMap, @@ -133,7 +131,7 @@ export class ViewportFeatureManager feature: Feature ): void { super.onFeatureClicked(event, feature); - if (selectStateSnapshot(selectCurrentRole, this.store) !== 'trainer') { + if (this.storeService.select(selectCurrentRole) !== 'trainer') { return; } const zoom = this.olMap.getView().getZoom()!; @@ -158,6 +156,6 @@ export class ViewportFeatureManager } public override isFeatureTranslatable(feature: Feature): boolean { - return selectStateSnapshot(selectCurrentRole, this.store) === 'trainer'; + return this.storeService.select(selectCurrentRole) === 'trainer'; } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/choose-transfer-target-popup/choose-transfer-target-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/choose-transfer-target-popup/choose-transfer-target-popup.component.ts index 371ad44d2..51e288f3f 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/choose-transfer-target-popup/choose-transfer-target-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/choose-transfer-target-popup/choose-transfer-target-popup.component.ts @@ -1,9 +1,8 @@ import type { OnInit } from '@angular/core'; -import { EventEmitter, Output, Component } from '@angular/core'; -import { Store } from '@ngrx/store'; +import { Component, EventEmitter, Output } from '@angular/core'; import type { Hospital, TransferPoint, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectReachableHospitals, createSelectReachableTransferPoints, @@ -33,13 +32,13 @@ export class ChooseTransferTargetPopupComponent public reachableHospitals$?: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnInit(): void { - this.reachableTransferPoints$ = this.store.select( + this.reachableTransferPoints$ = this.storeService.select$( createSelectReachableTransferPoints(this.transferPointId) ); - this.reachableHospitals$ = this.store.select( + this.reachableHospitals$ = this.storeService.select$( createSelectReachableHospitals(this.transferPointId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/map-image-popup/map-image-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/map-image-popup/map-image-popup.component.ts index 8ffe62eee..5ab5182bc 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/map-image-popup/map-image-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/map-image-popup/map-image-popup.component.ts @@ -1,6 +1,5 @@ import type { OnInit } from '@angular/core'; import { Component, EventEmitter, Output } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { ChangeZIndexMapImageAction, MapImage, @@ -9,7 +8,7 @@ import type { import type { Observable } from 'rxjs'; import { firstValueFrom } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectMapImage } from 'src/app/state/application/selectors/exercise.selectors'; import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; import type { PopupComponent } from '../../utility/popup-manager'; @@ -26,17 +25,17 @@ export class MapImagePopupComponent implements PopupComponent, OnInit { @Output() readonly closePopup = new EventEmitter(); public mapImage$?: Observable; - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); public url?: string; constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} async ngOnInit() { - this.mapImage$ = this.store.select( + this.mapImage$ = this.storeService.select$( createSelectMapImage(this.mapImageId) ); diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/material-popup/material-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/material-popup/material-popup.component.ts index c77863af4..c613bbd29 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/material-popup/material-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/material-popup/material-popup.component.ts @@ -1,9 +1,8 @@ import type { OnInit } from '@angular/core'; import { Component, EventEmitter, Output } from '@angular/core'; -import { Store } from '@ngrx/store'; -import type { UUID, Material } from 'digital-fuesim-manv-shared'; +import type { Material, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectMaterial } from 'src/app/state/application/selectors/exercise.selectors'; import type { PopupComponent } from '../../utility/popup-manager'; @@ -19,10 +18,10 @@ export class MaterialPopupComponent implements PopupComponent, OnInit { public material$?: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnInit(): void { - this.material$ = this.store.select( + this.material$ = this.storeService.select$( createSelectMaterial(this.materialId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-name/patient-name.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-name/patient-name.component.ts index 632caf914..8000b74d2 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-name/patient-name.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-name/patient-name.component.ts @@ -1,10 +1,9 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { Patient } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectPatient } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -17,9 +16,11 @@ export class PatientNameComponent implements OnInit { patient$!: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnInit(): void { - this.patient$ = this.store.select(createSelectPatient(this.patientId)); + this.patient$ = this.storeService.select$( + createSelectPatient(this.patientId) + ); } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/personnel-popup/personnel-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/personnel-popup/personnel-popup.component.ts index 7c5b57d93..34bb5a689 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/personnel-popup/personnel-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/personnel-popup/personnel-popup.component.ts @@ -1,9 +1,8 @@ import type { OnInit } from '@angular/core'; import { Component, EventEmitter, Output } from '@angular/core'; -import { Store } from '@ngrx/store'; -import type { UUID, Personnel } from 'digital-fuesim-manv-shared'; +import type { Personnel, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectPersonnel } from 'src/app/state/application/selectors/exercise.selectors'; import type { PopupComponent } from '../../utility/popup-manager'; @@ -19,10 +18,10 @@ export class PersonnelPopupComponent implements PopupComponent, OnInit { public personnel$?: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnInit(): void { - this.personnel$ = this.store.select( + this.personnel$ = this.storeService.select$( createSelectPersonnel(this.personnelId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/simulated-region-popup/simulated-region-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/simulated-region-popup/simulated-region-popup.component.ts index a11ad5d2e..b11bf292f 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/simulated-region-popup/simulated-region-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/simulated-region-popup/simulated-region-popup.component.ts @@ -1,10 +1,9 @@ import type { OnInit } from '@angular/core'; import { Component, EventEmitter, Output } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; -import type { UUID, SimulatedRegion } from 'digital-fuesim-manv-shared'; +import type { SimulatedRegion, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectSimulatedRegion } from 'src/app/state/application/selectors/exercise.selectors'; import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; import { openSimulatedRegionsModal } from '../../../simulated-region-overview/open-simulated-regions-modal'; @@ -21,15 +20,15 @@ export class SimulatedRegionPopupComponent implements OnInit { @Output() readonly closePopup = new EventEmitter(); public simulatedRegion$?: Observable; - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly modalService: NgbModal ) {} ngOnInit() { - this.simulatedRegion$ = this.store.select( + this.simulatedRegion$ = this.storeService.select$( createSelectSimulatedRegion(this.simulatedRegionId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/transfer-point-popup/transfer-point-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/transfer-point-popup/transfer-point-popup.component.ts index 82b25b957..4dad7854a 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/transfer-point-popup/transfer-point-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/transfer-point-popup/transfer-point-popup.component.ts @@ -1,15 +1,14 @@ import type { OnInit } from '@angular/core'; import { - ViewEncapsulation, Component, EventEmitter, Output, + ViewEncapsulation, } from '@angular/core'; -import { Store } from '@ngrx/store'; -import type { UUID, TransferPoint } from 'digital-fuesim-manv-shared'; +import type { TransferPoint, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectTransferPoint } from 'src/app/state/application/selectors/exercise.selectors'; import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; import type { PopupComponent } from '../../utility/popup-manager'; @@ -34,7 +33,7 @@ export class TransferPointPopupComponent implements PopupComponent, OnInit { public transferPoint$?: Observable; - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); public get activeNavId() { return activeNavId; @@ -45,11 +44,11 @@ export class TransferPointPopupComponent implements PopupComponent, OnInit { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} ngOnInit() { - this.transferPoint$ = this.store.select( + this.transferPoint$ = this.storeService.select$( createSelectTransferPoint(this.transferPointId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/vehicle-popup/vehicle-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/vehicle-popup/vehicle-popup.component.ts index c10da031a..492febdc6 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/vehicle-popup/vehicle-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/vehicle-popup/vehicle-popup.component.ts @@ -1,12 +1,11 @@ import type { OnInit } from '@angular/core'; import { Component, EventEmitter, Output } from '@angular/core'; -import { Store } from '@ngrx/store'; +import type { UUID, Vehicle } from 'digital-fuesim-manv-shared'; import { isInSpecificVehicle } from 'digital-fuesim-manv-shared'; -import type { Vehicle, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { combineLatest, map, switchMap } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectMaterial, createSelectPatient, @@ -31,22 +30,24 @@ export class VehiclePopupComponent implements PopupComponent, OnInit { public vehicleLoadState$?: Observable< 'completelyLoaded' | 'completelyUnloaded' | 'partiallyLoaded' >; - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} async ngOnInit() { - this.vehicle$ = this.store.select(createSelectVehicle(this.vehicleId)); + this.vehicle$ = this.storeService.select$( + createSelectVehicle(this.vehicleId) + ); this.vehicleLoadState$ = this.vehicle$.pipe( switchMap((_vehicle) => { const materialsAreInVehicle$ = Object.keys( _vehicle.materialIds ).map((materialId) => - this.store - .select(createSelectMaterial(materialId)) + this.storeService + .select$(createSelectMaterial(materialId)) .pipe( map((material) => isInSpecificVehicle(material, _vehicle.id) @@ -56,8 +57,8 @@ export class VehiclePopupComponent implements PopupComponent, OnInit { const personnelAreInVehicle$ = Object.keys( _vehicle.personnelIds ).map((personnelId) => - this.store - .select(createSelectPersonnel(personnelId)) + this.storeService + .select$(createSelectPersonnel(personnelId)) .pipe( map((personnel) => isInSpecificVehicle(personnel, _vehicle.id) @@ -67,8 +68,8 @@ export class VehiclePopupComponent implements PopupComponent, OnInit { const patientsAreInVehicle$ = Object.keys( _vehicle.patientIds ).map((patientId) => - this.store - .select(createSelectPatient(patientId)) + this.storeService + .select$(createSelectPatient(patientId)) .pipe( map((patient) => isInSpecificVehicle(patient, _vehicle.id) diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/viewport-popup/viewport-popup.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/viewport-popup/viewport-popup.component.ts index b6b26aa0f..7fc34faba 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/viewport-popup/viewport-popup.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/viewport-popup/viewport-popup.component.ts @@ -1,10 +1,9 @@ import type { OnInit } from '@angular/core'; import { Component, EventEmitter, Output } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { UUID, Viewport } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectViewport } from 'src/app/state/application/selectors/exercise.selectors'; import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; @@ -20,15 +19,15 @@ export class ViewportPopupComponent implements OnInit { @Output() readonly closePopup = new EventEmitter(); public viewport$?: Observable; - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} ngOnInit() { - this.viewport$ = this.store.select( + this.viewport$ = this.storeService.select$( createSelectViewport(this.viewportId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-interactions-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-interactions-manager.ts index 6540dac70..64d591479 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-interactions-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-interactions-manager.ts @@ -1,24 +1,22 @@ -import type VectorLayer from 'ol/layer/Vector'; -import type VectorSource from 'ol/source/Vector'; -import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; +import type { ExerciseStatus, Role, UUID } from 'digital-fuesim-manv-shared'; +import type { Feature } from 'ol'; +import { Collection } from 'ol'; import type { Interaction } from 'ol/interaction'; import { defaults as defaultInteractions } from 'ol/interaction'; +import type { TranslateEvent } from 'ol/interaction/Translate'; +import type VectorLayer from 'ol/layer/Vector'; +import type OlMap from 'ol/Map'; +import type { Pixel } from 'ol/pixel'; +import type VectorSource from 'ol/source/Vector'; import type { Subject } from 'rxjs'; import { combineLatest, takeUntil } from 'rxjs'; +import type { StoreService } from 'src/app/core/store.service'; import { selectExerciseStatus } from 'src/app/state/application/selectors/exercise.selectors'; -import type { Feature } from 'ol'; -import { Collection } from 'ol'; -import type OlMap from 'ol/Map'; -import type { AppState } from 'src/app/state/app.state'; -import type { Store } from '@ngrx/store'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; -import type { ExerciseStatus, Role, UUID } from 'digital-fuesim-manv-shared'; -import type { TranslateEvent } from 'ol/interaction/Translate'; -import type { Pixel } from 'ol/pixel'; +import { selectCurrentRole } from 'src/app/state/application/selectors/shared.selectors'; import { featureElementKey } from '../feature-managers/element-manager'; -import { TranslateInteraction } from './translate-interaction'; -import type { PopupManager } from './popup-manager'; import type { FeatureManager } from './feature-manager'; +import type { PopupManager } from './popup-manager'; +import { TranslateInteraction } from './translate-interaction'; export class OlMapInteractionsManager { private readonly featureLayers: VectorLayer[] = []; @@ -33,7 +31,7 @@ export class OlMapInteractionsManager { constructor( private readonly mapInteractions: Collection, - private readonly store: Store, + private readonly storeService: StoreService, private readonly popupManager: PopupManager, private readonly olMap: OlMap, private readonly layerFeatureManagerDictionary: Map< @@ -90,7 +88,7 @@ export class OlMapInteractionsManager { altShiftDragRotate: false, keyboard: true, }).extend( - selectStateSnapshot(selectCurrentRole, this.store) === 'trainer' + this.storeService.select(selectCurrentRole) === 'trainer' ? [...this.participantInteractions, ...this.trainerInteractions] : [...this.participantInteractions] ); @@ -106,8 +104,8 @@ export class OlMapInteractionsManager { // Register handlers that disable or enable certain interactions private registerInteractionEnablementHandler() { combineLatest([ - this.store.select(selectExerciseStatus), - this.store.select(selectCurrentRole), + this.storeService.select$(selectExerciseStatus), + this.storeService.select$(selectCurrentRole), ]) .pipe(takeUntil(this.destroy$)) .subscribe(([status, currentRole]) => { diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-manager.ts index b543e9ebc..532ac3ee1 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/ol-map-manager.ts @@ -1,7 +1,6 @@ -import type { Store } from '@ngrx/store'; import { - upperLeftCornerOf, lowerRightCornerOf, + upperLeftCornerOf, } from 'digital-fuesim-manv-shared'; import { Collection, View } from 'ol'; import type { Interaction } from 'ol/interaction'; @@ -10,13 +9,12 @@ import OlMap from 'ol/Map'; import type VectorSource from 'ol/source/Vector'; import { Subject, takeUntil } from 'rxjs'; import type { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectSimulatedRegions, selectViewports, } from 'src/app/state/application/selectors/exercise.selectors'; import { selectRestrictedViewport } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import type { TransferLinesService } from '../../core/transfer-lines.service'; import { startingPosition } from '../../starting-position'; import { CateringLinesFeatureManager } from '../feature-managers/catering-lines-feature-manager'; @@ -34,8 +32,8 @@ import { ViewportFeatureManager, } from '../feature-managers/viewport-feature-manager'; import type { FeatureManager } from './feature-manager'; -import type { PopupManager } from './popup-manager'; import { OlMapInteractionsManager } from './ol-map-interactions-manager'; +import type { PopupManager } from './popup-manager'; import { SatelliteLayerManager } from './satellite-layer-manager'; export class OlMapManager { @@ -59,7 +57,7 @@ export class OlMapManager { >(); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService, private readonly openLayersContainer: HTMLDivElement, private readonly transferLinesService: TransferLinesService, @@ -89,7 +87,7 @@ export class OlMapManager { this.mapInteractionsManager = new OlMapInteractionsManager( this.olMap.getInteractions(), - store, + storeService, popupManager, this.olMap, this.layerFeatureManagerDictionary, @@ -97,7 +95,7 @@ export class OlMapManager { ); const satelliteLayerManager = new SatelliteLayerManager( - store, + storeService, this.destroy$ ); @@ -122,8 +120,8 @@ export class OlMapManager { private registerViewportRestriction() { this.tryToFitViewForOverview(false); - this.store - .select(selectRestrictedViewport) + this.storeService + .select$(selectRestrictedViewport) .pipe(takeUntil(this.destroy$)) .subscribe((viewport) => { const view = this.olMap.getView(); @@ -162,18 +160,13 @@ export class OlMapManager { * Sets the map's view to see all viewports and simulated regions. */ public tryToFitViewForOverview(animate = true) { - if ( - selectStateSnapshot(selectRestrictedViewport, this.store) !== - undefined - ) { + if (this.storeService.select(selectRestrictedViewport) !== undefined) { // We are restricted to a viewport -> you can't fit the view return; } const elements = [ - ...Object.values(selectStateSnapshot(selectViewports, this.store)), - ...Object.values( - selectStateSnapshot(selectSimulatedRegions, this.store) - ), + ...Object.values(this.storeService.select(selectViewports)), + ...Object.values(this.storeService.select(selectSimulatedRegions)), ]; const view = this.olMap.getView(); if (elements.length === 0) { @@ -232,58 +225,58 @@ export class OlMapManager { private initializeFeatureManagers() { const transferLinesFeatureManager = new TransferLinesFeatureManager( - this.store, + this.storeService, this.transferLinesService, this.olMap ); const transferPointFeatureManager = new TransferPointFeatureManager( this.olMap, - this.store, + this.storeService, this.exerciseService ); const patientFeatureManager = new PatientFeatureManager( - this.store, + this.storeService, this.olMap, this.exerciseService ); const vehicleFeatureManager = new VehicleFeatureManager( this.olMap, - this.store, + this.storeService, this.exerciseService ); const personnelFeatureManager = new PersonnelFeatureManager( this.olMap, - this.store, + this.storeService, this.exerciseService ); const materialFeatureManager = new MaterialFeatureManager( this.olMap, - this.store, + this.storeService, this.exerciseService ); const mapImageFeatureManager = new MapImageFeatureManager( this.olMap, this.exerciseService, - this.store + this.storeService ); const cateringLinesFeatureManager = new CateringLinesFeatureManager( - this.store, + this.storeService, this.olMap ); const viewportFeatureManager = new ViewportFeatureManager( this.olMap, this.exerciseService, - this.store + this.storeService ); const simulatedRegionFeatureManager = new SimulatedRegionFeatureManager( this.olMap, this.exerciseService, - this.store + this.storeService ); const deleteFeatureManager = new DeleteFeatureManager( - this.store, + this.storeService, this.olMap, this.exerciseService ); diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/satellite-layer-manager.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/satellite-layer-manager.ts index 8ae8a9f3e..d8016e4a6 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/satellite-layer-manager.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/utility/satellite-layer-manager.ts @@ -1,8 +1,7 @@ -import type { Store } from '@ngrx/store'; import TileLayer from 'ol/layer/Tile'; import XYZ from 'ol/source/XYZ'; import { takeUntil } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import type { StoreService } from 'src/app/core/store.service'; import { selectTileMapProperties } from 'src/app/state/application/selectors/exercise.selectors'; export class SatelliteLayerManager { @@ -13,14 +12,14 @@ export class SatelliteLayerManager { } constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly destroy$: any ) { this._satelliteLayer = new TileLayer({ preload: Number.POSITIVE_INFINITY, }); - this.store - .select(selectTileMapProperties) + this.storeService + .select$(selectTileMapProperties) .pipe(takeUntil(this.destroy$)) .subscribe((tileMapProperties) => { this._satelliteLayer.setSource( diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-settings/exercise-settings-modal/exercise-settings-modal.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-settings/exercise-settings-modal/exercise-settings-modal.component.ts index ddb83deab..897391746 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-settings/exercise-settings-modal/exercise-settings-modal.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-settings/exercise-settings-modal/exercise-settings-modal.component.ts @@ -1,14 +1,12 @@ import { Component } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import { cloneDeepMutable } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectConfiguration, selectTileMapProperties, } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; @Component({ selector: 'app-exercise-settings-modal', @@ -17,16 +15,16 @@ import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; }) export class ExerciseSettingsModalComponent { public tileMapProperties = cloneDeepMutable( - selectStateSnapshot(selectTileMapProperties, this.store) + this.storeService.select(selectTileMapProperties) ); public readonly tileMapUrlRegex = /^(?=.*\{x\})(?=.*\{-?y\})(?=.*\{z\}).*$/u; - public configuration$ = this.store.select(selectConfiguration); + public configuration$ = this.storeService.select$(selectConfiguration); constructor( - private readonly store: Store, + private readonly storeService: StoreService, public readonly activeModal: NgbActiveModal, private readonly exerciseService: ExerciseService ) {} diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-state-badge/exercise-state-badge.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-state-badge/exercise-state-badge.component.ts index 40f842a0f..e61e748ac 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-state-badge/exercise-state-badge.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-state-badge/exercise-state-badge.component.ts @@ -1,6 +1,5 @@ import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectCurrentTime, selectExerciseStatus, @@ -12,8 +11,9 @@ import { styleUrls: ['./exercise-state-badge.component.scss'], }) export class ExerciseStateBadgeComponent { - public readonly exerciseStatus$ = this.store.select(selectExerciseStatus); - public readonly currentTime$ = this.store.select(selectCurrentTime); + public readonly exerciseStatus$ = + this.storeService.select$(selectExerciseStatus); + public readonly currentTime$ = this.storeService.select$(selectCurrentTime); - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/exercise-statistics-modal/exercise-statistics-modal.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/exercise-statistics-modal/exercise-statistics-modal.component.ts index 6b2268095..f19a3056c 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/exercise-statistics-modal/exercise-statistics-modal.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/exercise-statistics-modal/exercise-statistics-modal.component.ts @@ -1,17 +1,16 @@ import { Component } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import type { PatientStatus, PersonnelType } from 'digital-fuesim-manv-shared'; import { statusNames } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { map } from 'rxjs'; +import { StoreService } from 'src/app/core/store.service'; import { generateRandomRgbaColor, getRgbaColor, rgbColorPalette, } from 'src/app/shared/functions/colors'; import { formatDuration } from 'src/app/shared/functions/format-duration'; -import type { AppState } from 'src/app/state/app.state'; import { selectViewports } from 'src/app/state/application/selectors/exercise.selectors'; import { StatisticsService } from '../../core/statistics/statistics.service'; import { AreaStatisticsService } from '../area-statistics.service'; @@ -24,11 +23,11 @@ import { StackedBarChart } from '../stacked-bar-chart/time-line-area-chart'; styleUrls: ['./exercise-statistics-modal.component.scss'], }) export class ExerciseStatisticsModalComponent { - public viewports$ = this.store.select(selectViewports); + public viewports$ = this.storeService.select$(selectViewports); constructor( public activeModal: NgbActiveModal, - private readonly store: Store, + private readonly storeService: StoreService, public readonly statisticsService: StatisticsService, public readonly areaStatisticsService: AreaStatisticsService ) { diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.ts b/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.ts index f42788a12..105b5b1b1 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.ts @@ -1,10 +1,9 @@ import { Component } from '@angular/core'; import type { Sort } from '@angular/material/sort'; -import { Store } from '@ngrx/store'; import { statusNames } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { combineLatest, map, startWith, Subject } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectHospitalPatients, selectHospitals, @@ -16,14 +15,14 @@ import { styleUrls: ['./hospital-patients-table.component.scss'], }) export class HospitalPatientsTableComponent { - constructor(public readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} public readonly sortEvent$ = new Subject(); private readonly unsortedRows$: Observable = combineLatest([ - this.store.select(selectHospitalPatients), - this.store.select(selectHospitals), + this.storeService.select$(selectHospitalPatients), + this.storeService.select$(selectHospitals), ]).pipe( map(([hospitalPatients, hospitals]) => Object.values(hospitalPatients).map((hospitalPatient) => { diff --git a/frontend/src/app/pages/exercises/exercise/shared/hospital-editor/hospital-editor-modal/hospital-editor-modal.component.ts b/frontend/src/app/pages/exercises/exercise/shared/hospital-editor/hospital-editor-modal/hospital-editor-modal.component.ts index 08c728336..c285725a1 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/hospital-editor/hospital-editor-modal/hospital-editor-modal.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/hospital-editor/hospital-editor-modal/hospital-editor-modal.component.ts @@ -1,10 +1,9 @@ import { Component } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import { Hospital } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectHospitals } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -13,10 +12,10 @@ import { selectHospitals } from 'src/app/state/application/selectors/exercise.se styleUrls: ['./hospital-editor-modal.component.scss'], }) export class HospitalEditorModalComponent { - public hospitals$ = this.store.select(selectHospitals); + public hospitals$ = this.storeService.select$(selectHospitals); constructor( - private readonly store: Store, + private readonly storeService: StoreService, public readonly activeModal: NgbActiveModal, private readonly exerciseService: ExerciseService ) {} diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/overview/simulated-region-overview.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/overview/simulated-region-overview.component.ts index 52aba19d1..985a94cee 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/overview/simulated-region-overview.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/overview/simulated-region-overview.component.ts @@ -1,14 +1,13 @@ import type { OnDestroy, OnInit } from '@angular/core'; import { Component, Input, ViewEncapsulation } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; import type { SimulatedRegion } from 'digital-fuesim-manv-shared'; -import { UUID, isInSpecificSimulatedRegion } from 'digital-fuesim-manv-shared'; +import { isInSpecificSimulatedRegion, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import { Subject, takeUntil } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { map, Subject, takeUntil } from 'rxjs'; +import { StoreService } from 'src/app/core/store.service'; import { - selectTransferPoints, createSelectSimulatedRegion, + selectTransferPoints, } from 'src/app/state/application/selectors/exercise.selectors'; import { SelectPatientService } from '../select-patient.service'; @@ -51,26 +50,27 @@ export class SimulatedRegionOverviewGeneralComponent private readonly destroy$ = new Subject(); constructor( - private readonly store: Store, + private readonly storeService: StoreService, readonly selectPatientService: SelectPatientService ) {} ngOnInit(): void { - this.simulatedRegion$ = this.store.select( + this.simulatedRegion$ = this.storeService.select$( createSelectSimulatedRegion(this.simulatedRegionId) ); - this.transferPointId$ = this.store.select( - createSelector( - selectTransferPoints, - (transferPoints) => - Object.values(transferPoints).find((transferPoint) => - isInSpecificSimulatedRegion( - transferPoint, - this.simulatedRegionId - ) - )!.id - ) - ); + this.transferPointId$ = this.storeService + .select$(selectTransferPoints) + .pipe( + map( + (transferPoints) => + Object.values(transferPoints).find((transferPoint) => + isInSpecificSimulatedRegion( + transferPoint, + this.simulatedRegionId + ) + )!.id + ) + ); this.selectPatientService.patientSelected .pipe(takeUntil(this.destroy$)) diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-region-name/simulated-region-name.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-region-name/simulated-region-name.component.ts index c8b3ef02c..2dd6bc2c7 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-region-name/simulated-region-name.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-region-name/simulated-region-name.component.ts @@ -1,10 +1,9 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { map } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectSimulatedRegion } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -17,11 +16,11 @@ export class SimulatedRegionNameComponent implements OnInit { name$!: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnInit(): void { - this.name$ = this.store - .select(createSelectSimulatedRegion(this.simulatedRegionId)) + this.name$ = this.storeService + .select$(createSelectSimulatedRegion(this.simulatedRegionId)) .pipe(map((simulatedRegion) => simulatedRegion.name)); } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-regions-modal/simulated-regions-modal.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-regions-modal/simulated-regions-modal.component.ts index 0dd9be160..3eefd1cd9 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-regions-modal/simulated-regions-modal.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/simulated-regions-modal/simulated-regions-modal.component.ts @@ -1,11 +1,10 @@ import type { OnInit } from '@angular/core'; import { Component, Input, ViewEncapsulation } from '@angular/core'; import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { map } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectSimulatedRegions } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -22,12 +21,12 @@ export class SimulatedRegionsModalComponent implements OnInit { constructor( public readonly activeModal: NgbActiveModal, - public readonly store: Store + private readonly storeService: StoreService ) {} ngOnInit(): void { - this.simulatedRegionIds$ = this.store - .select(selectSimulatedRegions) + this.simulatedRegionIds$ = this.storeService + .select$(selectSimulatedRegions) .pipe(map((simulatedRegions) => Object.keys(simulatedRegions))); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/assign-leader/simulated-region-overview-behavior-assign-leader.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/assign-leader/simulated-region-overview-behavior-assign-leader.component.ts index 7840418cf..aa0f3cf96 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/assign-leader/simulated-region-overview-behavior-assign-leader.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/assign-leader/simulated-region-overview-behavior-assign-leader.component.ts @@ -1,10 +1,9 @@ import type { OnChanges } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { Personnel } from 'digital-fuesim-manv-shared'; import { AssignLeaderBehaviorState } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectPersonnel } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -23,13 +22,13 @@ export class SimulatedRegionOverviewBehaviorAssignLeaderComponent currentLeader?: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnChanges(): void { - if (this.assignLeaderBehaviorState.leaderId) { - this.currentLeader = this.store.select( - createSelectPersonnel(this.assignLeaderBehaviorState.leaderId) - ); - } + this.currentLeader = this.assignLeaderBehaviorState.leaderId + ? this.storeService.select$( + createSelectPersonnel(this.assignLeaderBehaviorState.leaderId) + ) + : undefined; } } diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/patient-details/simulated-region-overview-behavior-treat-patients-patient-details.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/patient-details/simulated-region-overview-behavior-treat-patients-patient-details.component.ts index 92894b911..9e3bdfc65 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/patient-details/simulated-region-overview-behavior-treat-patients-patient-details.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/patient-details/simulated-region-overview-behavior-treat-patients-patient-details.component.ts @@ -1,12 +1,12 @@ -import '@angular/localize/init'; import type { OnDestroy, OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import '@angular/localize/init'; +import { createSelector } from '@ngrx/store'; import type { PatientStatus, PersonnelType } from 'digital-fuesim-manv-shared'; import { Patient, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { distinctUntilChanged, Subject, takeUntil } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectPatient, selectConfiguration, @@ -35,7 +35,7 @@ export class SimulatedRegionOverviewBehaviorTreatPatientsPatientDetailsComponent public patient$!: Observable; public destroy$ = new Subject(); - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnDestroy(): void { this.destroy$.next(); } @@ -43,8 +43,8 @@ export class SimulatedRegionOverviewBehaviorTreatPatientsPatientDetailsComponent ngOnInit(): void { const patientSelector = createSelectPatient(this.patientId); - this.caterings$ = this.store - .select( + this.caterings$ = this.storeService + .select$( createSelector( selectPersonnel, patientSelector, @@ -76,9 +76,9 @@ export class SimulatedRegionOverviewBehaviorTreatPatientsPatientDetailsComponent takeUntil(this.destroy$) ); - this.patient$ = this.store.select(patientSelector); + this.patient$ = this.storeService.select$(patientSelector); - this.visibleStatus$ = this.store.select( + this.visibleStatus$ = this.storeService.select$( createSelector( patientSelector, selectConfiguration, diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/simulated-region-overview-behavior-treat-patients.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/simulated-region-overview-behavior-treat-patients.component.ts index f0684b876..6ba6099b1 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/simulated-region-overview-behavior-treat-patients.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/treat-patients/simulated-region-overview-behavior-treat-patients.component.ts @@ -1,14 +1,14 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { UUID } from 'digital-fuesim-manv-shared'; import { - TreatPatientsBehaviorState, SimulatedRegion, + TreatPatientsBehaviorState, } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectElementsInSimulatedRegion, selectConfiguration, @@ -53,14 +53,14 @@ export class SimulatedRegionOverviewBehaviorTreatPatientsComponent constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store, + private readonly storeService: StoreService, readonly selectPatientService: SelectPatientService ) {} ngOnInit(): void { this.settingsCollapsed = globalLastSettingsCollapsed; this.informationCollapsed = globalLastInformationCollapsed; - this.patientIds$ = this.store.select( + this.patientIds$ = this.storeService.select$( createSelector( createSelectElementsInSimulatedRegion( selectPatients, diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/unload-arriving-vehicles/simulated-region-overview-behavior-unload-arriving-vehicles.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/unload-arriving-vehicles/simulated-region-overview-behavior-unload-arriving-vehicles.component.ts index bb7187bab..14b129ff9 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/unload-arriving-vehicles/simulated-region-overview-behavior-unload-arriving-vehicles.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/unload-arriving-vehicles/simulated-region-overview-behavior-unload-arriving-vehicles.component.ts @@ -1,12 +1,12 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { UnloadArrivingVehiclesBehaviorState } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { map } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectActivityStatesByType, createSelectBehaviorState, @@ -36,12 +36,12 @@ export class SimulatedRegionOverviewBehaviorUnloadArrivingVehiclesComponent constructor( private readonly exerciseService: ExerciseService, - public readonly store: Store + public readonly storeService: StoreService ) {} ngOnInit(): void { - this.unloadDuration$ = this.store - .select( + this.unloadDuration$ = this.storeService + .select$( createSelectBehaviorState( this.simulatedRegionId, this.behaviorId @@ -62,7 +62,7 @@ export class SimulatedRegionOverviewBehaviorUnloadArrivingVehiclesComponent })) ); - this.vehiclesStatus$ = this.store.select( + this.vehiclesStatus$ = this.storeService.select$( createSelector( selectCurrentTime, unloadingSelector, diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/general-tab/simulated-region-overview-general-tab.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/general-tab/simulated-region-overview-general-tab.component.ts index 289fd6a51..e7a628ae0 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/general-tab/simulated-region-overview-general-tab.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/general-tab/simulated-region-overview-general-tab.component.ts @@ -1,6 +1,6 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { Material, Patient, @@ -12,15 +12,15 @@ import type { import { SimulatedRegion } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { + createSelectByPredicate, createSelectElementsInSimulatedRegion, selectMaterials, selectPatients, selectPersonnel, - selectVehicleTemplates, selectVehicles, - createSelectByPredicate, + selectVehicleTemplates, } from 'src/app/state/application/selectors/exercise.selectors'; const patientCategories = ['red', 'yellow', 'green', 'black'] as const; @@ -43,7 +43,7 @@ export type PersonnelCategory = (typeof personnelCategories)[number]; export class SimulatedRegionOverviewGeneralTabComponent implements OnInit { @Input() simulatedRegion!: SimulatedRegion; - public readonly vehicleTemplates$ = this.store.select( + public readonly vehicleTemplates$ = this.storeService.select$( selectVehicleTemplates ); @@ -68,7 +68,7 @@ export class SimulatedRegionOverviewGeneralTabComponent implements OnInit { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} ngOnInit(): void { @@ -82,9 +82,11 @@ export class SimulatedRegionOverviewGeneralTabComponent implements OnInit { this.simulatedRegion.id ); - this.patients.all$ = this.store.select(containedPatientsSelector); + this.patients.all$ = this.storeService.select$( + containedPatientsSelector + ); patientCategories.forEach((category) => { - this.patients[`${category}$`] = this.store.select( + this.patients[`${category}$`] = this.storeService.select$( createSelectByPredicate( containedPatientsSelector, this.createPatientStatusPredicate(category) @@ -92,7 +94,7 @@ export class SimulatedRegionOverviewGeneralTabComponent implements OnInit { ); }); - this.vehicles$ = this.store.select( + this.vehicles$ = this.storeService.select$( createSelector( selectVehicleTemplates, createSelectElementsInSimulatedRegion( @@ -126,9 +128,11 @@ export class SimulatedRegionOverviewGeneralTabComponent implements OnInit { ) ); - this.personnel.all$ = this.store.select(containedPersonnelSelector); + this.personnel.all$ = this.storeService.select$( + containedPersonnelSelector + ); personnelCategories.forEach((category) => { - this.personnel[`${category}$`] = this.store.select( + this.personnel[`${category}$`] = this.storeService.select$( createSelectByPredicate( containedPersonnelSelector, this.createPersonnelTypePredicate(category) @@ -136,7 +140,7 @@ export class SimulatedRegionOverviewGeneralTabComponent implements OnInit { ); }); - this.material$ = this.store.select( + this.material$ = this.storeService.select$( createSelectElementsInSimulatedRegion( selectMaterials, this.simulatedRegion.id diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/patients-tab/simulated-region-overview-patients-tab/simulated-region-overview-patients-tab.component.ts b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/patients-tab/simulated-region-overview-patients-tab/simulated-region-overview-patients-tab.component.ts index 4c1e6cb9a..44bfbf9ab 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/patients-tab/simulated-region-overview-patients-tab/simulated-region-overview-patients-tab.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/patients-tab/simulated-region-overview-patients-tab/simulated-region-overview-patients-tab.component.ts @@ -1,10 +1,10 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { PatientStatus } from 'digital-fuesim-manv-shared'; import { Patient, SimulatedRegion, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectElementsInSimulatedRegion, selectConfiguration, @@ -25,12 +25,12 @@ export class SimulatedRegionOverviewPatientsTabComponent implements OnInit { patients$!: Observable<(Patient & { visibleStatus: PatientStatus })[]>; constructor( - private readonly store: Store, + private readonly storeService: StoreService, readonly selectPatientService: SelectPatientService ) {} ngOnInit(): void { - this.patients$ = this.store.select( + this.patients$ = this.storeService.select$( createSelector( createSelectElementsInSimulatedRegion( selectPatients, diff --git a/frontend/src/app/pages/exercises/exercise/shared/time-travel/time-travel.component.ts b/frontend/src/app/pages/exercises/exercise/shared/time-travel/time-travel.component.ts index 9cf43e58f..2415938ce 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/time-travel/time-travel.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/time-travel/time-travel.component.ts @@ -1,16 +1,14 @@ import type { OnDestroy } from '@angular/core'; import { Component } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import { cloneDeepMutable, StateExport } from 'digital-fuesim-manv-shared'; import { throttle } from 'lodash-es'; import { ApiService } from 'src/app/core/api.service'; import { MessageService } from 'src/app/core/messages/message.service'; +import { StoreService } from 'src/app/core/store.service'; import { TimeTravelService } from 'src/app/core/time-travel.service'; -import type { AppState } from 'src/app/state/app.state'; import { selectTimeConstraints } from 'src/app/state/application/selectors/application.selectors'; import { selectExerciseState } from 'src/app/state/application/selectors/exercise.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { openClientOverviewModal } from '../client-overview/open-client-overview-modal'; import { openExerciseStatisticsModal } from '../exercise-statistics/open-exercise-statistics-modal'; import { openTransferOverviewModal } from '../transfer-overview/open-transfer-overview-modal'; @@ -21,13 +19,13 @@ import { openTransferOverviewModal } from '../transfer-overview/open-transfer-ov styleUrls: ['./time-travel.component.scss'], }) export class TimeTravelComponent implements OnDestroy { - public timeConstraints$ = this.store.select(selectTimeConstraints); + public timeConstraints$ = this.storeService.select$(selectTimeConstraints); constructor( private readonly modalService: NgbModal, private readonly apiService: ApiService, private readonly timeTravelService: TimeTravelService, - private readonly store: Store, + private readonly storeService: StoreService, private readonly messageService: MessageService ) {} @@ -67,9 +65,8 @@ export class TimeTravelComponent implements OnDestroy { public startReplay() { this.replayInterval = setInterval(() => { - const timeConstraints = selectStateSnapshot( - selectTimeConstraints, - this.store + const timeConstraints = this.storeService.select( + selectTimeConstraints )!; if (timeConstraints.current >= timeConstraints.end) { this.stopReplay(); @@ -102,19 +99,16 @@ export class TimeTravelComponent implements OnDestroy { public restartReplay() { this.stopReplay(); - const timeConstraints = selectStateSnapshot( - selectTimeConstraints, - this.store + const timeConstraints = this.storeService.select( + selectTimeConstraints )!; this.timeTravelService.jumpToTime(timeConstraints!.start); this.startReplay(); } public async createNewExerciseFromTheCurrentState() { - const currentExerciseState = selectStateSnapshot( - selectExerciseState, - this.store - ); + const currentExerciseState = + this.storeService.select(selectExerciseState); const { trainerId } = await this.apiService.importExercise( new StateExport(cloneDeepMutable(currentExerciseState)) ); diff --git a/frontend/src/app/pages/exercises/exercise/shared/trainer-map-editor/trainer-map-editor.component.ts b/frontend/src/app/pages/exercises/exercise/shared/trainer-map-editor/trainer-map-editor.component.ts index 6a74a0a67..1b0789ea3 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/trainer-map-editor/trainer-map-editor.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/trainer-map-editor/trainer-map-editor.component.ts @@ -1,14 +1,13 @@ import { Component } from '@angular/core'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import type { UUID, VehicleTemplate } from 'digital-fuesim-manv-shared'; import { colorCodeMap, + SimulatedRegion, TransferPoint, Viewport, - SimulatedRegion, } from 'digital-fuesim-manv-shared'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectMapImagesTemplates, selectPatientCategories, @@ -32,15 +31,15 @@ export class TrainerMapEditorComponent { public readonly colorCodeMap = colorCodeMap; public readonly categories = ['X', 'Y', 'Z'] as const; - public readonly vehicleTemplates$ = this.store.select( + public readonly vehicleTemplates$ = this.storeService.select$( selectVehicleTemplates ); - public readonly patientCategories$ = this.store.select( + public readonly patientCategories$ = this.storeService.select$( selectPatientCategories ); - public readonly mapImageTemplates$ = this.store.select( + public readonly mapImageTemplates$ = this.storeService.select$( selectMapImagesTemplates ); @@ -49,7 +48,7 @@ export class TrainerMapEditorComponent { } constructor( - private readonly store: Store, + private readonly storeService: StoreService, public readonly dragElementService: DragElementService, public readonly transferLinesService: TransferLinesService, private readonly ngbModalService: NgbModal diff --git a/frontend/src/app/pages/exercises/exercise/shared/trainer-toolbar/trainer-toolbar.component.ts b/frontend/src/app/pages/exercises/exercise/shared/trainer-toolbar/trainer-toolbar.component.ts index 6ceea64a4..09aad29f7 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/trainer-toolbar/trainer-toolbar.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/trainer-toolbar/trainer-toolbar.component.ts @@ -1,17 +1,15 @@ import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import { ApiService } from 'src/app/core/api.service'; import { ApplicationService } from 'src/app/core/application.service'; import { ConfirmationModalService } from 'src/app/core/confirmation-modal/confirmation-modal.service'; import { ExerciseService } from 'src/app/core/exercise.service'; import { MessageService } from 'src/app/core/messages/message.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectExerciseId } from 'src/app/state/application/selectors/application.selectors'; import { selectExerciseStatus } from 'src/app/state/application/selectors/exercise.selectors'; import { selectOwnClient } from 'src/app/state/application/selectors/shared.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { openAlarmGroupOverviewModal } from '../alarm-group-overview/open-alarm-group-overview-modal'; import { openClientOverviewModal } from '../client-overview/open-client-overview-modal'; import { openEmergencyOperationsCenterModal } from '../emergency-operations-center/open-emergency-operations-center-modal'; @@ -27,10 +25,10 @@ import { openTransferOverviewModal } from '../transfer-overview/open-transfer-ov styleUrls: ['./trainer-toolbar.component.scss'], }) export class TrainerToolbarComponent { - public exerciseStatus$ = this.store.select(selectExerciseStatus); + public exerciseStatus$ = this.storeService.select$(selectExerciseStatus); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService, private readonly apiService: ApiService, public readonly applicationService: ApplicationService, @@ -84,10 +82,7 @@ export class TrainerToolbarComponent { } public async startExercise() { - if ( - selectStateSnapshot(selectExerciseStatus, this.store) === - 'notStarted' - ) { + if (this.storeService.select(selectExerciseStatus) === 'notStarted') { const confirmStart = await this.confirmationModalService.confirm({ title: 'Übung starten', description: 'Möchten Sie die Übung wirklich starten?', @@ -109,7 +104,7 @@ export class TrainerToolbarComponent { private sendLogAction(message: string) { this.exerciseService.proposeAction({ type: '[Emergency Operation Center] Add Log Entry', - name: selectStateSnapshot(selectOwnClient, this.store)!.name, + name: this.storeService.select(selectOwnClient)!.name, message, }); } @@ -125,7 +120,7 @@ export class TrainerToolbarComponent { } public async deleteExercise() { - const exerciseId = selectStateSnapshot(selectExerciseId, this.store)!; + const exerciseId = this.storeService.select(selectExerciseId)!; const deletionConfirmed = await this.confirmationModalService.confirm({ title: 'Übung löschen', description: diff --git a/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-overview-table/transfer-overview-table.component.ts b/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-overview-table/transfer-overview-table.component.ts index da2e76397..77c16c3d6 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-overview-table/transfer-overview-table.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-overview-table/transfer-overview-table.component.ts @@ -1,7 +1,6 @@ import { Component } from '@angular/core'; -import { Store } from '@ngrx/store'; import { currentTransferOf } from 'digital-fuesim-manv-shared'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectExerciseStatus, selectPersonnelInTransfer, @@ -14,16 +13,17 @@ import { styleUrls: ['./transfer-overview-table.component.scss'], }) export class TransferOverviewTableComponent { - public readonly vehiclesInTransfer$ = this.store.select( + public readonly vehiclesInTransfer$ = this.storeService.select$( selectVehiclesInTransfer ); - public readonly personnelInTransfer$ = this.store.select( + public readonly personnelInTransfer$ = this.storeService.select$( selectPersonnelInTransfer ); public currentTransferOf = currentTransferOf; - public readonly exerciseStatus$ = this.store.select(selectExerciseStatus); + public readonly exerciseStatus$ = + this.storeService.select$(selectExerciseStatus); - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} } diff --git a/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-target-input/transfer-target-input.component.ts b/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-target-input/transfer-target-input.component.ts index dd84fa34e..c03339fc6 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-target-input/transfer-target-input.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-target-input/transfer-target-input.component.ts @@ -1,8 +1,7 @@ import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import { Transfer, UUID } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectTransferPoints } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -15,10 +14,11 @@ export class TransferTargetInputComponent { @Input() elementId!: UUID; @Input() transfer!: Transfer; - public readonly transferPoints$ = this.store.select(selectTransferPoints); + public readonly transferPoints$ = + this.storeService.select$(selectTransferPoints); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} diff --git a/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-time-input/transfer-time-input.component.ts b/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-time-input/transfer-time-input.component.ts index f01016989..8fbe229ce 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-time-input/transfer-time-input.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/transfer-overview/transfer-time-input/transfer-time-input.component.ts @@ -1,8 +1,7 @@ import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import { Transfer, UUID } from 'digital-fuesim-manv-shared'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectCurrentTime } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -17,10 +16,10 @@ export class TransferTimeInputComponent { @Input() transfer!: Transfer; - public readonly currentTime$ = this.store.select(selectCurrentTime); + public readonly currentTime$ = this.storeService.select$(selectCurrentTime); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} diff --git a/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/other-transfer-point-tab/other-transfer-point-tab.component.ts b/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/other-transfer-point-tab/other-transfer-point-tab.component.ts index 248652158..a55801767 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/other-transfer-point-tab/other-transfer-point-tab.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/other-transfer-point-tab/other-transfer-point-tab.component.ts @@ -1,10 +1,10 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; -import { UUID, TransferPoint } from 'digital-fuesim-manv-shared'; +import { TransferPoint, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; +import { map } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectTransferPoint, selectTransferPoints, @@ -21,31 +21,34 @@ export class OtherTransferPointTabComponent implements OnInit { public transferPoint$!: Observable; public transferPoints$: Observable<{ [key: UUID]: TransferPoint }> = - this.store.select(selectTransferPoints); + this.storeService.select$(selectTransferPoints); /** * All transferPoints that are neither connected to this one nor this one itself */ - public readonly transferPointsToBeAdded$ = this.store.select( - createSelector(selectTransferPoints, (transferPoints) => { - const currentTransferPoint = transferPoints[this.transferPointId]!; - return Object.fromEntries( - Object.entries(transferPoints).filter( - ([key]) => - key !== this.transferPointId && - !currentTransferPoint.reachableTransferPoints[key] - ) - ); - }) - ); + public readonly transferPointsToBeAdded$ = this.storeService + .select$(selectTransferPoints) + .pipe( + map((transferPoints) => { + const currentTransferPoint = + transferPoints[this.transferPointId]!; + return Object.fromEntries( + Object.entries(transferPoints).filter( + ([key]) => + key !== this.transferPointId && + !currentTransferPoint.reachableTransferPoints[key] + ) + ); + }) + ); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} ngOnInit() { - this.transferPoint$ = this.store.select( + this.transferPoint$ = this.storeService.select$( createSelectTransferPoint(this.transferPointId) ); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/transfer-hospitals-tab/transfer-hospitals-tab.component.ts b/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/transfer-hospitals-tab/transfer-hospitals-tab.component.ts index 5785caeaf..b9a5a61f4 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/transfer-hospitals-tab/transfer-hospitals-tab.component.ts +++ b/frontend/src/app/pages/exercises/exercise/shared/transfer-point-overview/transfer-hospitals-tab/transfer-hospitals-tab.component.ts @@ -1,11 +1,11 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { Hospital, TransferPoint } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectTransferPoint, selectHospitals, @@ -23,10 +23,10 @@ export class TransferHospitalsTabComponent implements OnInit { public transferPoint$!: Observable; public hospitals$: Observable<{ [key: UUID]: Hospital }> = - this.store.select(selectHospitals); + this.storeService.select$(selectHospitals); public readonly hospitalsToBeAdded$: Observable<{ [key: UUID]: Hospital }> = - this.store.select( + this.storeService.select$( createSelector( selectTransferPoints, selectHospitals, @@ -45,11 +45,11 @@ export class TransferHospitalsTabComponent implements OnInit { constructor( private readonly exerciseService: ExerciseService, - private readonly store: Store + private readonly storeService: StoreService ) {} ngOnInit() { - this.transferPoint$ = this.store.select( + this.transferPoint$ = this.storeService.select$( createSelectTransferPoint(this.transferPointId) ); } diff --git a/frontend/src/app/pages/exercises/guards/join-exercise.guard.ts b/frontend/src/app/pages/exercises/guards/join-exercise.guard.ts index 24eb61cb9..f8315f8c7 100644 --- a/frontend/src/app/pages/exercises/guards/join-exercise.guard.ts +++ b/frontend/src/app/pages/exercises/guards/join-exercise.guard.ts @@ -6,12 +6,10 @@ import type { } from '@angular/router'; import { Router } from '@angular/router'; import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; -import { Store } from '@ngrx/store'; import { ApiService } from 'src/app/core/api.service'; import { MessageService } from 'src/app/core/messages/message.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectExerciseStateMode } from 'src/app/state/application/selectors/application.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; import { tryToJoinExercise } from '../shared/join-exercise-modal/try-to-join-exercise'; @Injectable({ @@ -22,7 +20,7 @@ export class JoinExerciseGuard implements CanActivate { private readonly ngbModalService: NgbModal, private readonly router: Router, private readonly apiService: ApiService, - private readonly store: Store, + private readonly storeService: StoreService, private readonly messageService: MessageService ) {} @@ -30,10 +28,7 @@ export class JoinExerciseGuard implements CanActivate { route: ActivatedRouteSnapshot, state: RouterStateSnapshot ) { - if ( - selectStateSnapshot(selectExerciseStateMode, this.store) === - 'exercise' - ) { + if (this.storeService.select(selectExerciseStateMode) === 'exercise') { return true; } const exerciseExists = await this.apiService.exerciseExists( diff --git a/frontend/src/app/pages/exercises/guards/leave-exercise.guard.ts b/frontend/src/app/pages/exercises/guards/leave-exercise.guard.ts index d3d943412..ea21ca22b 100644 --- a/frontend/src/app/pages/exercises/guards/leave-exercise.guard.ts +++ b/frontend/src/app/pages/exercises/guards/leave-exercise.guard.ts @@ -4,12 +4,10 @@ import type { CanDeactivate, RouterStateSnapshot, } from '@angular/router'; -import { Store } from '@ngrx/store'; import { ApplicationService } from 'src/app/core/application.service'; import { MessageService } from 'src/app/core/messages/message.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { selectExerciseStateMode } from 'src/app/state/application/selectors/application.selectors'; -import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; @Injectable({ providedIn: 'root', @@ -17,7 +15,7 @@ import { selectStateSnapshot } from 'src/app/state/get-state-snapshot'; export class LeaveExerciseGuard implements CanDeactivate { constructor( private readonly applicationService: ApplicationService, - private readonly store: Store, + private readonly storeService: StoreService, private readonly messageService: MessageService ) {} @@ -29,10 +27,7 @@ export class LeaveExerciseGuard implements CanDeactivate { ) { // If the client has already left the exercise, we don't need to inform the user here. // This should be handled by the error handler/action that lead to the leave (e.g. the exercise deletion). - if ( - selectStateSnapshot(selectExerciseStateMode, this.store) !== - undefined - ) { + if (this.storeService.select(selectExerciseStateMode) !== undefined) { this.applicationService.leaveExercise(); this.messageService.postMessage({ title: 'Übung verlassen', diff --git a/frontend/src/app/pages/landing-page/landing-page.module.ts b/frontend/src/app/pages/landing-page/landing-page.module.ts index ef2088236..4c83b4d83 100644 --- a/frontend/src/app/pages/landing-page/landing-page.module.ts +++ b/frontend/src/app/pages/landing-page/landing-page.module.ts @@ -1,5 +1,5 @@ -import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { SharedModule } from 'src/app/shared/shared.module'; diff --git a/frontend/src/app/shared/components/hospital-name/hospital-name.component.ts b/frontend/src/app/shared/components/hospital-name/hospital-name.component.ts index 5e7909508..79a896c0d 100644 --- a/frontend/src/app/shared/components/hospital-name/hospital-name.component.ts +++ b/frontend/src/app/shared/components/hospital-name/hospital-name.component.ts @@ -1,10 +1,9 @@ import type { OnChanges } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { Hospital } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectHospital } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -17,10 +16,10 @@ export class HospitalNameComponent implements OnChanges { public hospital$?: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnChanges() { - this.hospital$ = this.store.select( + this.hospital$ = this.storeService.select$( createSelectHospital(this.hospitalId) ); } diff --git a/frontend/src/app/shared/components/patient-health-point-display/patient-health-point-display.component.ts b/frontend/src/app/shared/components/patient-health-point-display/patient-health-point-display.component.ts index cad1c0501..5e8a0532f 100644 --- a/frontend/src/app/shared/components/patient-health-point-display/patient-health-point-display.component.ts +++ b/frontend/src/app/shared/components/patient-health-point-display/patient-health-point-display.component.ts @@ -1,6 +1,6 @@ import type { OnInit } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { PatientStatus } from 'digital-fuesim-manv-shared'; import { healthPointsDefaults, @@ -9,7 +9,7 @@ import { UUID, } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectPatient, selectConfiguration, @@ -30,14 +30,14 @@ export class PatientHealthPointDisplayComponent implements OnInit { health: number; }>; - public readonly currentRole$ = this.store.select(selectCurrentRole); + public readonly currentRole$ = this.storeService.select$(selectCurrentRole); public readonly healthPointsDefaults = healthPointsDefaults; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnInit(): void { - this.status$ = this.store.select( + this.status$ = this.storeService.select$( createSelector( createSelectPatient(this.patientId), selectConfiguration, diff --git a/frontend/src/app/shared/components/patients-details/patients-details.component.ts b/frontend/src/app/shared/components/patients-details/patients-details.component.ts index a2f529d7e..072f53c8a 100644 --- a/frontend/src/app/shared/components/patients-details/patients-details.component.ts +++ b/frontend/src/app/shared/components/patients-details/patients-details.component.ts @@ -1,12 +1,12 @@ import type { OnChanges } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { createSelector, Store } from '@ngrx/store'; +import { createSelector } from '@ngrx/store'; import type { PatientStatus } from 'digital-fuesim-manv-shared'; import { Patient, UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; import { map } from 'rxjs'; import { ExerciseService } from 'src/app/core/exercise.service'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectPatient, selectConfiguration, @@ -21,8 +21,8 @@ import { selectCurrentRole } from 'src/app/state/application/selectors/shared.se export class PatientsDetailsComponent implements OnChanges { @Input() patientId!: UUID; - readonly currentRole$ = this.store.select(selectCurrentRole); - configuration$ = this.store.select(selectConfiguration); + readonly currentRole$ = this.storeService.select$(selectCurrentRole); + configuration$ = this.storeService.select$(selectConfiguration); patient$!: Observable; visibleStatus$!: Observable; pretriageStatusIsLocked$?: Observable; @@ -36,13 +36,15 @@ export class PatientsDetailsComponent implements OnChanges { ); constructor( - private readonly store: Store, + private readonly storeService: StoreService, private readonly exerciseService: ExerciseService ) {} ngOnChanges(): void { - this.patient$ = this.store.select(createSelectPatient(this.patientId)); - this.visibleStatus$ = this.store.select( + this.patient$ = this.storeService.select$( + createSelectPatient(this.patientId) + ); + this.visibleStatus$ = this.storeService.select$( createSelector( createSelectPatient(this.patientId), selectConfiguration, diff --git a/frontend/src/app/shared/components/transfer-point-name/transfer-point-name.component.ts b/frontend/src/app/shared/components/transfer-point-name/transfer-point-name.component.ts index 981f6964a..310a2810f 100644 --- a/frontend/src/app/shared/components/transfer-point-name/transfer-point-name.component.ts +++ b/frontend/src/app/shared/components/transfer-point-name/transfer-point-name.component.ts @@ -1,10 +1,9 @@ import type { OnChanges } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { TransferPoint } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectTransferPoint } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -17,10 +16,10 @@ export class TransferPointNameComponent implements OnChanges { public transferPoint$?: Observable; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} ngOnChanges() { - this.transferPoint$ = this.store.select( + this.transferPoint$ = this.storeService.select$( createSelectTransferPoint(this.transferPointId) ); } diff --git a/frontend/src/app/shared/components/viewport-name/viewport-name.component.ts b/frontend/src/app/shared/components/viewport-name/viewport-name.component.ts index 35a6f84f7..cb209db65 100644 --- a/frontend/src/app/shared/components/viewport-name/viewport-name.component.ts +++ b/frontend/src/app/shared/components/viewport-name/viewport-name.component.ts @@ -1,10 +1,9 @@ import type { OnChanges } from '@angular/core'; import { Component, Input } from '@angular/core'; -import { Store } from '@ngrx/store'; import type { Viewport } from 'digital-fuesim-manv-shared'; import { UUID } from 'digital-fuesim-manv-shared'; import type { Observable } from 'rxjs'; -import type { AppState } from 'src/app/state/app.state'; +import { StoreService } from 'src/app/core/store.service'; import { createSelectViewport } from 'src/app/state/application/selectors/exercise.selectors'; @Component({ @@ -14,12 +13,12 @@ import { createSelectViewport } from 'src/app/state/application/selectors/exerci }) export class ViewportNameComponent implements OnChanges { @Input() viewportId!: UUID; - constructor(private readonly store: Store) {} + constructor(private readonly storeService: StoreService) {} public viewport$?: Observable; ngOnChanges() { - this.viewport$ = this.store.select( + this.viewport$ = this.storeService.select$( createSelectViewport(this.viewportId) ); } diff --git a/frontend/src/app/shared/functions/cypress.ts b/frontend/src/app/shared/functions/cypress.ts index ba8d09fd5..120548cda 100644 --- a/frontend/src/app/shared/functions/cypress.ts +++ b/frontend/src/app/shared/functions/cypress.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line no-restricted-imports import type { Store } from '@ngrx/store'; import { environment } from 'src/environments/environment'; import { defaults } from 'lodash-es'; diff --git a/frontend/src/app/state/get-state-snapshot.ts b/frontend/src/app/state/get-state-snapshot.ts deleted file mode 100644 index a64d124b1..000000000 --- a/frontend/src/app/state/get-state-snapshot.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Store } from '@ngrx/store'; -import { first } from 'rxjs'; -import type { AppState } from './app.state'; - -/** - * A helper function to get the current immutable state synchronously. - * - * Warning: this is most of the time an anti-pattern for our ngrx-store. - * If you want to observe the state and get notified of changes, you should use the selectors on the store. - */ -function getStateSnapshot(store: Store): AppState { - // There is sadly currently no other way to get the state synchronously... - let currentState: AppState; - // "Subscribing to Store will always be guaranteed to be synchronous" - https://github.com/ngrx/platform/issues/227#issuecomment-431682349 - store - .select((state) => state) - .pipe(first()) - .subscribe((s) => (currentState = s)); - return currentState!; -} - -export function selectStateSnapshot( - selector: (state: AppState) => SelectedValue, - store: Store -): SelectedValue { - return selector(getStateSnapshot(store)); -}