diff --git a/CHANGELOG.md b/CHANGELOG.md index 23830d589..70cd6b224 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,17 @@ and this project does **not** adhere to [Semantic Versioning](https://semver.org ## [Unreleased] +## [0.7.1] - 2023-07-10 + +## Added + +- Patients can be identified with an unique ID + - The ID is assigned to every patient automatically + - The ID consists of a 4 digit number incremented for each patients + - Optionally, a prefix for the IDs can be set + - The ID is shown in the patient popup, the simulation overview, statistics log entries and for hospital patients +- There is a new image for NAW vehicles. + ## [0.7.0] - 2023-05-30 ### Added @@ -262,7 +273,8 @@ and this project does **not** adhere to [Semantic Versioning](https://semver.org ### Initial unstable release of Digitale FüSim MANV -[Unreleased]: https://github.com/hpi-sam/digital-fuesim-manv/compare/v0.7.0...HEAD +[Unreleased]: https://github.com/hpi-sam/digital-fuesim-manv/compare/v0.7.1...HEAD +[0.7.1]: https://github.com/hpi-sam/digital-fuesim-manv/compare/v0.7.0...v0.7.1 [0.7.0]: https://github.com/hpi-sam/digital-fuesim-manv/compare/v0.6.0...v0.7.0 [0.6.0]: https://github.com/hpi-sam/digital-fuesim-manv/compare/v0.5.1...v0.6.0 [0.5.1]: https://github.com/hpi-sam/digital-fuesim-manv/compare/v0.5.0...v0.5.1 diff --git a/backend/package-lock.json b/backend/package-lock.json index 9a3de0a7d..5cf4558ca 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -1,12 +1,12 @@ { "name": "digital-fuesim-manv-backend", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digital-fuesim-manv-backend", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "class-transformer": "^0.5.1", "class-validator": "^0.14.0", @@ -48,7 +48,7 @@ }, "../shared": { "name": "digital-fuesim-manv-shared", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "@noble/hashes": "^1.2.0", "class-transformer": "^0.5.1", diff --git a/backend/package.json b/backend/package.json index a515f5f69..ece423eca 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "digital-fuesim-manv-backend", - "version": "0.7.0", + "version": "0.7.1", "type": "module", "scripts": { "start:once:linux-macos": "NODE_ENV=production node --experimental-specifier-resolution=node dist/src/index.js", diff --git a/benchmark/package-lock.json b/benchmark/package-lock.json index 6bbfe73df..812a2934f 100644 --- a/benchmark/package-lock.json +++ b/benchmark/package-lock.json @@ -1,12 +1,12 @@ { "name": "digital-fuesim-manv-benchmark", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digital-fuesim-manv-benchmark", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "digital-fuesim-manv-shared": "file:../shared", "immer": "^9.0.17", @@ -32,7 +32,7 @@ }, "../shared": { "name": "digital-fuesim-manv-shared", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "@noble/hashes": "^1.2.0", "class-transformer": "^0.5.1", diff --git a/benchmark/package.json b/benchmark/package.json index c5d5fe2bf..4df237461 100644 --- a/benchmark/package.json +++ b/benchmark/package.json @@ -1,6 +1,6 @@ { "name": "digital-fuesim-manv-benchmark", - "version": "0.7.0", + "version": "0.7.1", "type": "module", "scripts": { "lint": "eslint --max-warnings 0 --ignore-path .gitignore \"./**/*.{ts,js,yml,html}\"", diff --git a/docs/swagger.yml b/docs/swagger.yml index 565003dd0..7b2d133dc 100644 --- a/docs/swagger.yml +++ b/docs/swagger.yml @@ -2,7 +2,7 @@ openapi: 3.0.3 info: title: Digital Fuesim MANV HTTP API description: HTTP API of the digital-fuesim-manv project - version: 0.7.0 + version: 0.7.1 paths: /api/health: get: diff --git a/frontend/package-lock.json b/frontend/package-lock.json index e4a494c77..2cf6e79cb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "digital-fuesim-manv-frontend", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digital-fuesim-manv-frontend", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "@angular/animations": "~15.1.0", "@angular/common": "~15.1.0", @@ -66,7 +66,7 @@ }, "../shared": { "name": "digital-fuesim-manv-shared", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "@noble/hashes": "^1.2.0", "class-transformer": "^0.5.1", diff --git a/frontend/package.json b/frontend/package.json index f34153456..f3759a2c0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "digital-fuesim-manv-frontend", - "version": "0.7.0", + "version": "0.7.1", "type": "module", "scripts": { "cy:open": "cypress open", diff --git a/frontend/src/app/pages/exercises/exercise/exercise.module.ts b/frontend/src/app/pages/exercises/exercise/exercise.module.ts index 3294c2574..870703522 100644 --- a/frontend/src/app/pages/exercises/exercise/exercise.module.ts +++ b/frontend/src/app/pages/exercises/exercise/exercise.module.ts @@ -2,7 +2,10 @@ import { CommonModule } from '@angular/common'; import { HttpClientModule } from '@angular/common/http'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; -import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'; +import { + NgbDropdownModule, + NgbTooltipModule, +} from '@ng-bootstrap/ng-bootstrap'; import { SharedModule } from 'src/app/shared/shared.module'; import { ExerciseComponent } from './exercise/exercise.component'; import { AlarmGroupOverviewModule } from './shared/alarm-group-overview/alarm-group-overview.module'; @@ -48,6 +51,7 @@ import { CoordinatePickerModule } from './shared/coordinate-picker/coordinate-pi HospitalEditorModule, EmergencyOperationsCenterModule, CoordinatePickerModule, + NgbTooltipModule, ], exports: [ExerciseComponent], }) diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-popup/patient-popup.component.html b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-popup/patient-popup.component.html index 2e2acc369..1943f9cea 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-popup/patient-popup.component.html +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-map/shared/patient-popup/patient-popup.component.html @@ -1,6 +1,7 @@
- + + {{ ' ' }}
Übungsmodus
- Mit Vorsichtung üben? -
- +
+ Mit Vorsichtung üben? +
+ +
+
+ +
+ Mit SK IV Patienten üben? +
+ +
- Mit SK IV Patienten üben? -
+ +
+ + + {{ ' ' }} + + + IDs mit langen Präfixen können ggfs nicht vollständig + angezeigt werden. Bitte ziehen Sie ein kürzeres Präfix in + Betracht. + + + Mit den aktuellen Einstellungen haben Patienten-IDs die + folgende Form: + {{ configuration.patientIdentifierPrefix }}1234 + +
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..6a12682ef 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 @@ -52,6 +52,13 @@ export class ExerciseSettingsModalComponent { }); } + public updatePatientIdentifierPrefix(patientIdentifierPrefix: string) { + this.exerciseService.proposeAction({ + type: '[Configuration] Set patientIdentifierPrefix', + patientIdentifierPrefix, + }); + } + public close() { this.activeModal.close(); } diff --git a/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.html b/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.html index 46242a03e..fba86afb9 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.html +++ b/frontend/src/app/pages/exercises/exercise/shared/exercise-statistics/hospital-patients-table/hospital-patients-table.component.html @@ -7,6 +7,7 @@ + ID Patientenkategorie Fahrzeugtyp Abfahrtszeit @@ -16,6 +17,7 @@ + {{ row.patientIdentifier }} {{ row.patientStatus }} {{ row.vehicleType }} {{ row.departureTime | formatDuration }} 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..8a7cbce35 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 @@ -32,6 +32,7 @@ export class HospitalPatientsTableComponent { _hospital.patientIds[hospitalPatient.patientId] ); const row: HospitalPatientsRow = { + patientIdentifier: hospitalPatient.identifier, hospitalName: hospital!.name, arrivalTime: hospitalPatient.arrivalTime, departureTime: hospitalPatient.startTime, @@ -73,6 +74,7 @@ export class HospitalPatientsTableComponent { // If you update this interface you must also update the `mat-sort-header` in the template. interface HospitalPatientsRow { + patientIdentifier: string; hospitalName: string; patientStatus: string; arrivalTime: number; diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/patients-table/simulated-region-overview-patients-table.component.html b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/patients-table/simulated-region-overview-patients-table.component.html index 99655d4a5..b11d44eff 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/patients-table/simulated-region-overview-patients-table.component.html +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/patients-table/simulated-region-overview-patients-table.component.html @@ -4,6 +4,7 @@ > + ID SK Gesichtet Verlauf @@ -19,6 +20,9 @@ [class.table-primary]="selectedPatientId === patient.id" style="cursor: pointer" > + + + diff --git a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/transfer-vehicles/simulated-region-overview-behavior-transfer-vehicles.component.html b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/transfer-vehicles/simulated-region-overview-behavior-transfer-vehicles.component.html index 0774ea2f7..2d12b258a 100644 --- a/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/transfer-vehicles/simulated-region-overview-behavior-transfer-vehicles.component.html +++ b/frontend/src/app/pages/exercises/exercise/shared/simulated-region-overview/tabs/behavior-tab/behaviors/transfer-vehicles/simulated-region-overview-behavior-transfer-vehicles.component.html @@ -271,6 +271,7 @@

> + ID SK Gesichtet Verlauf @@ -284,6 +285,9 @@

[class.table-primary]="selectedPatients[patient.id]" style="cursor: pointer" > + + + 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.html 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.html index a93c984dc..9c73d2b89 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.html +++ 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.html @@ -1,3 +1,6 @@ +
+ +
Derzeitige Zuordnung

#collapse="ngbCollapse" [(ngbCollapse)]="informationCollapsed" > +
+
ID
+
Sichtungskategorie
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.html 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.html index b2e53b588..00e5dacdc 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.html +++ 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.html @@ -1,7 +1,7 @@
-
+
{{ (patient$ | async)?.identifier }} diff --git a/frontend/src/app/shared/components/patient-identifier/patient-identifier.component.scss b/frontend/src/app/shared/components/patient-identifier/patient-identifier.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/frontend/src/app/shared/components/patient-identifier/patient-identifier.component.ts b/frontend/src/app/shared/components/patient-identifier/patient-identifier.component.ts new file mode 100644 index 000000000..7238dc755 --- /dev/null +++ b/frontend/src/app/shared/components/patient-identifier/patient-identifier.component.ts @@ -0,0 +1,25 @@ +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 { createSelectPatient } from 'src/app/state/application/selectors/exercise.selectors'; + +@Component({ + selector: 'app-patient-identifier', + templateUrl: './patient-identifier.component.html', + styleUrls: ['./patient-identifier.component.scss'], +}) +export class PatientIdentifierComponent implements OnInit { + @Input() patientId!: UUID; + + patient$!: Observable; + + constructor(private readonly store: Store) {} + + ngOnInit(): void { + this.patient$ = this.store.select(createSelectPatient(this.patientId)); + } +} diff --git a/frontend/src/app/shared/components/patients-details/patients-details.component.html b/frontend/src/app/shared/components/patients-details/patients-details.component.html index 0a2ec38b8..a4de9b7b0 100644 --- a/frontend/src/app/shared/components/patients-details/patients-details.component.html +++ b/frontend/src/app/shared/components/patients-details/patients-details.component.html @@ -4,6 +4,18 @@ + + + + + + + +
Identifikation + +
Name + {{ patient.personalInformation.name }} +
Alter diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 0019d906f..89b128d09 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -46,6 +46,7 @@ import { StartPauseButtonComponent } from './components/start-pause-button/start import { GeographicCoordinateDirective } from './validation/geographic-coordinate-validator.directive'; import { SimulatedRegionNameComponent } from './components/simulated-region-name/simulated-region-name.component'; import { SearchableDropdownComponent } from './components/searchable-dropdown/searchable-dropdown.component'; +import { PatientIdentifierComponent } from './components/patient-identifier/patient-identifier.component'; @NgModule({ declarations: [ @@ -88,6 +89,7 @@ import { SearchableDropdownComponent } from './components/searchable-dropdown/se SimulatedRegionNameComponent, GeographicCoordinateDirective, SearchableDropdownComponent, + PatientIdentifierComponent, ], imports: [ CommonModule, @@ -133,6 +135,7 @@ import { SearchableDropdownComponent } from './components/searchable-dropdown/se SimulatedRegionNameComponent, GeographicCoordinateDirective, SearchableDropdownComponent, + PatientIdentifierComponent, ], }) export class SharedModule {} diff --git a/frontend/src/assets/image-sources.md b/frontend/src/assets/image-sources.md index 0271c66fd..0fbbc9651 100644 --- a/frontend/src/assets/image-sources.md +++ b/frontend/src/assets/image-sources.md @@ -67,3 +67,7 @@ and Fry1989 [trash-can.svg](trash-can.svg): Bootstrap-Icon `bi-trash-fill` (edited) + +[naw-vehicle.png](naw-vehicle.png): +Lukas Radermacher, based on by Florian Greiz 23 +License: [CC-BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) diff --git a/frontend/src/assets/naw-vehicle.png b/frontend/src/assets/naw-vehicle.png new file mode 100644 index 000000000..35d08d0f7 Binary files /dev/null and b/frontend/src/assets/naw-vehicle.png differ diff --git a/package-lock.json b/package-lock.json index 9839fe97a..09a82dfb5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "digital-fuesim-manv", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digital-fuesim-manv", - "version": "0.7.0", + "version": "0.7.1", "devDependencies": { "concurrently": "^7.6.0", "nyc": "^15.1.0", diff --git a/package.json b/package.json index ceee6b550..98b4ddeef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "digital-fuesim-manv", - "version": "0.7.0", + "version": "0.7.1", "type": "module", "scripts": { "build": "cd shared && npm run build && cd .. && concurrently \"cd frontend && npm run build\" \"cd backend && npm run build\"", diff --git a/shared/package-lock.json b/shared/package-lock.json index a5def18e7..252eee22d 100644 --- a/shared/package-lock.json +++ b/shared/package-lock.json @@ -1,12 +1,12 @@ { "name": "digital-fuesim-manv-shared", - "version": "0.7.0", + "version": "0.7.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "digital-fuesim-manv-shared", - "version": "0.7.0", + "version": "0.7.1", "dependencies": { "@noble/hashes": "^1.2.0", "class-transformer": "^0.5.1", diff --git a/shared/package.json b/shared/package.json index 432e19105..10670c46a 100644 --- a/shared/package.json +++ b/shared/package.json @@ -1,6 +1,6 @@ { "name": "digital-fuesim-manv-shared", - "version": "0.7.0", + "version": "0.7.1", "type": "module", "main": "./dist/index.js", "esnext": "./dist/index.js", diff --git a/shared/src/data/default-state/vehicle-templates.ts b/shared/src/data/default-state/vehicle-templates.ts index 787ba6c9c..98d06264b 100644 --- a/shared/src/data/default-state/vehicle-templates.ts +++ b/shared/src/data/default-state/vehicle-templates.ts @@ -7,6 +7,12 @@ const rtwImage: ImageProperties = { aspectRatio: 3693 / 1670, }; +const nawImage: ImageProperties = { + url: '/assets/naw-vehicle.png', + height: 100, + aspectRatio: 3693 / 1670, +}; + const ktwImage: ImageProperties = { url: '/assets/ktw-vehicle.png', height: 100, @@ -46,6 +52,15 @@ const rtwVehicleTemplate = VehicleTemplate.create( ['standard'] ); +const nawVehicleTemplate = VehicleTemplate.create( + 'NAW', + `NAW ???`, + nawImage, + 1, + ['notarzt', 'notSan', 'rettSan'], + ['standard'] +); + const ktwVehicleTemplate = VehicleTemplate.create( 'KTW', `KTW ???`, @@ -108,4 +123,5 @@ export const defaultVehicleTemplates: readonly VehicleTemplate[] = [ gwSanVehicleTemplate, carryingUnitVehicleTemplate, rthVehicleTemplate, + nawVehicleTemplate, ]; diff --git a/shared/src/models/exercise-configuration.ts b/shared/src/models/exercise-configuration.ts index 6d8510b75..a6a075cf0 100644 --- a/shared/src/models/exercise-configuration.ts +++ b/shared/src/models/exercise-configuration.ts @@ -1,5 +1,5 @@ import { Type } from 'class-transformer'; -import { IsBoolean, ValidateNested } from 'class-validator'; +import { IsBoolean, IsString, ValidateNested } from 'class-validator'; import { IsValue } from '../utils/validators'; import { defaultTileMapProperties } from '../data/default-state/tile-map-properties'; import { getCreate, TileMapProperties } from './utils'; @@ -13,6 +13,9 @@ export class ExerciseConfiguration { @IsBoolean() public readonly bluePatientsEnabled: boolean = false; + @IsString() + public readonly patientIdentifierPrefix: string = ''; + @ValidateNested() @Type(() => TileMapProperties) public readonly tileMapProperties: TileMapProperties = diff --git a/shared/src/models/hospital-patient.ts b/shared/src/models/hospital-patient.ts index 17a2588ac..536cde9d9 100644 --- a/shared/src/models/hospital-patient.ts +++ b/shared/src/models/hospital-patient.ts @@ -32,6 +32,9 @@ export class HospitalPatient { @IsValue('hospitalPatient' as const) public readonly type = 'hospitalPatient'; + @IsString() + public readonly identifier: string; + /** * the vehicle that a patient was transported with */ @@ -94,6 +97,7 @@ export class HospitalPatient { */ constructor( patientId: UUID, + identifier: string, vehicleType: string, startTime: number, arrivalTime: number, @@ -108,6 +112,7 @@ export class HospitalPatient { treatmentTime: number ) { this.patientId = patientId; + this.identifier = identifier; this.vehicleType = vehicleType; this.startTime = startTime; this.arrivalTime = arrivalTime; @@ -140,6 +145,7 @@ export class HospitalPatient { return cloneDeepMutable( HospitalPatient.create( patient.id, + patient.identifier, vehicleType, startTime, arrivalTime, diff --git a/shared/src/models/patient.ts b/shared/src/models/patient.ts index 3d7527af9..79972875a 100644 --- a/shared/src/models/patient.ts +++ b/shared/src/models/patient.ts @@ -43,6 +43,9 @@ export class Patient { @IsValue('patient') public readonly type = 'patient'; + @IsString() + public readonly identifier: string = ''; + @ValidateNested() @Type(() => PersonalInformation) public readonly personalInformation: PersonalInformation; diff --git a/shared/src/models/utils/tag-helpers.ts b/shared/src/models/utils/tag-helpers.ts index 9b7f376d4..8f2d6481d 100644 --- a/shared/src/models/utils/tag-helpers.ts +++ b/shared/src/models/utils/tag-helpers.ts @@ -51,13 +51,7 @@ export function createPatientTag( patientId: UUID ): Tag { const patient = getElement(draftState, 'patient', patientId); - return new Tag( - 'Patient', - 'cyan', - 'black', - patient.personalInformation.name, - patientId - ); + return new Tag('Patient', 'cyan', 'black', patient.identifier, patientId); } export function createTagsForSinglePatient( diff --git a/shared/src/state-migrations/37-add-patient-identifiers.ts b/shared/src/state-migrations/37-add-patient-identifiers.ts new file mode 100644 index 000000000..901b59013 --- /dev/null +++ b/shared/src/state-migrations/37-add-patient-identifiers.ts @@ -0,0 +1,54 @@ +import type { UUID } from '../utils'; +import type { Migration } from './migration-functions'; + +interface Patient { + id: UUID; + identifier?: string; +} + +export const addPatientIdentifiers37: Migration = { + action: (_, action) => { + if ((action as { type: string }).type === '[Patient] Add patient') { + (action as { patient: Patient }).patient.identifier = ''; + } + return true; + }, + state: (state) => { + const typedState = state as { + patients: { + [patientId: UUID]: Patient; + }; + hospitalPatients: { + [hospitalPatientId: UUID]: Patient; + }; + configuration: { + patientIdentifierPrefix?: string; + }; + patientCounter?: number; + }; + + if (typedState.patientCounter === undefined) { + typedState.patientCounter = 0; + } + + if (typedState.configuration.patientIdentifierPrefix === undefined) { + typedState.configuration.patientIdentifierPrefix = ''; + } + + Object.values(typedState.patients) + .sort((a, b) => a.id.localeCompare(b.id)) + .forEach((patient) => { + typedState.patientCounter!++; + const paddedCounter = String( + typedState.patientCounter + ).padStart(4, '0'); + patient.identifier = `${typedState.configuration.patientIdentifierPrefix}${paddedCounter}`; + }); + + Object.values(typedState.hospitalPatients).forEach( + (hospitalPatient) => { + hospitalPatient.identifier = ''; + } + ); + }, +}; diff --git a/shared/src/state-migrations/migration-functions.ts b/shared/src/state-migrations/migration-functions.ts index 5a22183bd..f18001591 100644 --- a/shared/src/state-migrations/migration-functions.ts +++ b/shared/src/state-migrations/migration-functions.ts @@ -26,6 +26,7 @@ import { reportTransferCategoryCompleted33 } from './33-report-transfer-category import { addCatchAllHospital34 } from './34-add-catch-all-hospital'; import { addTransferInitiatingRegionToRequestEvents35 } from './35-add-transfer-initiating-region-to-request-events'; import { addAlarmGroupIdToAlarmGroupStartPoint36 } from './36-add-alarm-group-id-to-alarm-group-start-point'; +import { addPatientIdentifiers37 } from './37-add-patient-identifiers'; import { removeSetParticipantIdAction4 } from './4-remove-set-participant-id-action'; import { removeStatistics5 } from './5-remove-statistics'; import { removeStateHistory6 } from './6-remove-state-history'; @@ -95,4 +96,5 @@ export const migrations: { 34: addCatchAllHospital34, 35: addTransferInitiatingRegionToRequestEvents35, 36: addAlarmGroupIdToAlarmGroupStartPoint36, + 37: addPatientIdentifiers37, }; diff --git a/shared/src/state.ts b/shared/src/state.ts index c256ad05a..bc7e53e11 100644 --- a/shared/src/state.ts +++ b/shared/src/state.ts @@ -153,6 +153,10 @@ export class ExerciseState { @Type(() => ExerciseConfiguration) public readonly configuration = ExerciseConfiguration.create(); + @IsInt() + @Min(0) + public readonly patientCounter: number = 0; + /** * The log entries generated for the statistics. * This must not be defined on a normal state, @@ -178,5 +182,5 @@ export class ExerciseState { * * This number MUST be increased every time a change to any object (that is part of the state or the state itself) is made in a way that there may be states valid before that are no longer valid. */ - static readonly currentStateVersion = 36; + static readonly currentStateVersion = 37; } diff --git a/shared/src/store/action-reducers/configuration.ts b/shared/src/store/action-reducers/configuration.ts index d850e5635..e3d9bd457 100644 --- a/shared/src/store/action-reducers/configuration.ts +++ b/shared/src/store/action-reducers/configuration.ts @@ -1,5 +1,5 @@ import { Type } from 'class-transformer'; -import { IsBoolean, ValidateNested } from 'class-validator'; +import { IsBoolean, IsString, ValidateNested } from 'class-validator'; import { TileMapProperties } from '../../models/utils'; import { cloneDeepMutable } from '../../utils'; import { IsValue } from '../../utils/validators'; @@ -30,6 +30,14 @@ export class SetBluePatientsEnabledFlagAction implements Action { public readonly bluePatientsEnabled!: boolean; } +export class SetPatientIdentifierPrefixAction implements Action { + @IsValue('[Configuration] Set patientIdentifierPrefix' as const) + public readonly type = '[Configuration] Set patientIdentifierPrefix'; + + @IsString() + public readonly patientIdentifierPrefix!: string; +} + export namespace ConfigurationActionReducers { export const setTileMapProperties: ActionReducer = { @@ -61,4 +69,15 @@ export namespace ConfigurationActionReducers { }, rights: 'trainer', }; + + export const setPatientIdentifierPrefix: ActionReducer = + { + action: SetPatientIdentifierPrefixAction, + reducer(draftState, { patientIdentifierPrefix }) { + draftState.configuration.patientIdentifierPrefix = + patientIdentifierPrefix; + return draftState; + }, + rights: 'trainer', + }; } diff --git a/shared/src/store/action-reducers/patient.ts b/shared/src/store/action-reducers/patient.ts index 5057689db..38eb19575 100644 --- a/shared/src/store/action-reducers/patient.ts +++ b/shared/src/store/action-reducers/patient.ts @@ -150,6 +150,12 @@ export namespace PatientActionReducers { ); } const mutablePatient = cloneDeepMutable(patient); + draftState.patientCounter++; + const paddedCounter = String(draftState.patientCounter).padStart( + 4, + '0' + ); + mutablePatient.identifier = `${draftState.configuration.patientIdentifierPrefix}${paddedCounter}`; draftState.patients[mutablePatient.id] = mutablePatient; changePosition(mutablePatient, patient.position, draftState); logPatientAdded(draftState, patient.id); diff --git a/test-scenarios b/test-scenarios index a0a33b043..914fdde8a 160000 --- a/test-scenarios +++ b/test-scenarios @@ -1 +1 @@ -Subproject commit a0a33b0433576954b03bdd4fe4db4ef2fe8343d5 +Subproject commit 914fdde8a7e995422ce70be71f66ca8956d456ec