diff --git a/.github/workflows/cypress.yaml b/.github/workflows/cypress.yaml
index f66f9a37bd8..130f360d2ef 100644
--- a/.github/workflows/cypress.yaml
+++ b/.github/workflows/cypress.yaml
@@ -24,14 +24,22 @@ jobs:
repository: coronasafe/care
path: care
- - name: Run docker compose up on care 🐳
+ - name: Start care docker containers 🐳
run: |
- cd care
+ cd care
make docker_config_file=docker-compose.pre-built.yaml up
- sleep 60s
+ while docker compose exec backend bash -c "python manage.py showmigrations 2>/dev/null | cat | grep -q '\[ \]'"; do
+ >&2 echo "Migrations are not yet applied - sleeping"
+ sleep 5
+ done
+ echo "Migrations are applied"
+ cd ..
+
+ - name: Load dummy data into care backend 📂
+ run: |
+ cd care
docker compose exec backend bash -c "python manage.py load_dummy_data"
cd ..
- # Voluntarily kept 60 seconds delay to wait for migrations to complete.
- name: Check care is up ♻
run: curl -o /dev/null -s -w "%{http_code}\n" http://localhost:9000
@@ -93,10 +101,3 @@ jobs:
name: cypress-screenshots
path: cypress/screenshots
- # Test run video was always captured, so this action uses "always()" condition
- - name: Upload cypress videos 📹
- uses: actions/upload-artifact@v3
- if: always()
- with:
- name: cypress-videos
- path: cypress/videos
diff --git a/cypress/e2e/assets_spec/asset_homepage.cy.ts b/cypress/e2e/assets_spec/asset_homepage.cy.ts
index 6e9ceb9676b..fa24adf5b21 100644
--- a/cypress/e2e/assets_spec/asset_homepage.cy.ts
+++ b/cypress/e2e/assets_spec/asset_homepage.cy.ts
@@ -62,8 +62,18 @@ describe("Asset Tab", () => {
"Dummy Facility 1",
"INTERNAL",
"ACTIVE",
- "ONVIF Camera"
+ "ONVIF Camera",
+ "Camera Loc"
);
+ assetFilters.clickadvancefilter();
+ assetFilters.clickslideoverbackbutton(); // to verify the back button doesn't clear applied filters
+ assetFilters.assertFacilityText("Dummy Facility 1");
+ assetFilters.assertAssetTypeText("INTERNAL");
+ assetFilters.assertAssetClassText("ONVIF");
+ assetFilters.assertStatusText("ACTIVE");
+ assetFilters.assertLocationText("Camera Locations");
+ assetFilters.clickadvancefilter();
+ assetFilters.clearFilters();
});
// Verify the pagination in the page
diff --git a/cypress/pageobject/Asset/AssetFilters.ts b/cypress/pageobject/Asset/AssetFilters.ts
index 57cc893bdb7..a16b61f4fc5 100644
--- a/cypress/pageobject/Asset/AssetFilters.ts
+++ b/cypress/pageobject/Asset/AssetFilters.ts
@@ -3,7 +3,8 @@ export class AssetFilters {
facilityName: string,
assetType: string,
assetStatus: string,
- assetClass: string
+ assetClass: string,
+ assetLocation: string
) {
cy.contains("Advanced Filters").click();
cy.get("input[name='Facilities']")
@@ -27,6 +28,42 @@ export class AssetFilters {
.then(() => {
cy.get("[role='option']").contains(assetClass).click();
});
+ cy.get("#Facilities-location")
+ .click()
+ .type(assetLocation)
+ .then(() => {
+ cy.get("[role='option']").contains(assetLocation).click();
+ });
cy.contains("Apply").click();
}
+ clearFilters() {
+ cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets");
+ cy.get("#clear-filter").click();
+ cy.wait("@clearAssets").its("response.statusCode").should("eq", 200);
+ cy.url().should("match", /\/assets$/);
+ }
+ clickadvancefilter() {
+ cy.intercept("GET", "**/api/v1/getallfacilities/**").as("advancefilter");
+ cy.get("#advanced-filter").click();
+ cy.wait("@advancefilter").its("response.statusCode").should("eq", 200);
+ }
+ clickslideoverbackbutton() {
+ cy.get("#close-slide-over").click();
+ }
+ // Assertions
+ assertFacilityText(text) {
+ cy.get("[data-testid=Facility]").should("contain", text);
+ }
+ assertAssetTypeText(text) {
+ cy.get("[data-testid='Asset Type']").should("contain", text);
+ }
+ assertAssetClassText(text) {
+ cy.get("[data-testid='Asset Class']").should("contain", text);
+ }
+ assertStatusText(text) {
+ cy.get("[data-testid=Status]").should("contain", text);
+ }
+ assertLocationText(text) {
+ cy.get("[data-testid=Location]").should("contain", text);
+ }
}
diff --git a/cypress/pageobject/Asset/AssetSearch.ts b/cypress/pageobject/Asset/AssetSearch.ts
index fea6a975983..b1ccb2f71c9 100644
--- a/cypress/pageobject/Asset/AssetSearch.ts
+++ b/cypress/pageobject/Asset/AssetSearch.ts
@@ -1,6 +1,6 @@
export class AssetSearchPage {
typeSearchKeyword(keyword: string) {
- cy.get("#search").clear();
+ cy.get("#search").click().clear();
cy.get("#search").click().type(keyword);
}
@@ -9,7 +9,9 @@ export class AssetSearchPage {
}
clickAssetByName(assetName: string) {
+ cy.intercept("GET", "**/api/v1/asset/**").as("clearAssets");
cy.get("[data-testid='created-asset-list']").contains(assetName).click();
+ cy.wait("@clearAssets").its("response.statusCode").should("eq", 200);
}
verifyBadgeContent(expectedText: string) {
diff --git a/src/CAREUI/interactive/SlideOver.tsx b/src/CAREUI/interactive/SlideOver.tsx
index 3eae13869cb..34e1c615f94 100644
--- a/src/CAREUI/interactive/SlideOver.tsx
+++ b/src/CAREUI/interactive/SlideOver.tsx
@@ -109,6 +109,7 @@ export default function SlideOver({
>
diff --git a/src/Components/Facility/models.tsx b/src/Components/Facility/models.tsx
index 012ca1d68b2..cc34140e7a9 100644
--- a/src/Components/Facility/models.tsx
+++ b/src/Components/Facility/models.tsx
@@ -142,6 +142,7 @@ export interface ConsultationModel {
cause_of_death?: string;
death_datetime?: string;
death_confirmed_doctor?: string;
+ is_readmission?: boolean;
}
export interface PatientStatsModel {
id?: number;
diff --git a/src/Components/Patient/ManagePatients.tsx b/src/Components/Patient/ManagePatients.tsx
index b29c112c5a1..54d22b5f54c 100644
--- a/src/Components/Patient/ManagePatients.tsx
+++ b/src/Components/Patient/ManagePatients.tsx
@@ -603,6 +603,15 @@ export const PatientManager = () => {
text="Review Missed"
/>
)}
+ {patient.last_consultation?.is_readmission && (
+
+ )}
{patient.disease_status === "POSITIVE" && (
{
);
};
+ const isPatientEligibleForNewConsultation = (patientData: PatientModel) => {
+ return !patientData.last_consultation ||
+ patientData.last_consultation?.discharge_date
+ ? true
+ : false;
+ };
+
return (
{
- patientData.is_active &&
- (!patientData?.last_consultation ||
- patientData?.last_consultation?.discharge_date) &&
+ isPatientEligibleForNewConsultation(patientData) &&
navigate(
`/facility/${patientData?.facility}/patient/${id}/consultation`
)
}
>
-
-
+
+
diff --git a/src/Components/Patient/PatientInfoCard.tsx b/src/Components/Patient/PatientInfoCard.tsx
index 9df4c93051a..dbb4aac34ce 100644
--- a/src/Components/Patient/PatientInfoCard.tsx
+++ b/src/Components/Patient/PatientInfoCard.tsx
@@ -143,7 +143,7 @@ export default function PatientInfoCard(props: {
)}
-
+
•
-
- Domiciliary Care{" "}
-
+
+
+ Domiciliary Care
+
+ >
+ )}
+ {consultation?.is_readmission && (
+ <>
+ •
+
+
+ Readmitted
>
)}
diff --git a/src/Components/VitalsMonitor/HL7DeviceClient.ts b/src/Components/VitalsMonitor/HL7DeviceClient.ts
index 72f6406193a..7e13622b31f 100644
--- a/src/Components/VitalsMonitor/HL7DeviceClient.ts
+++ b/src/Components/VitalsMonitor/HL7DeviceClient.ts
@@ -1,11 +1,31 @@
import { EventEmitter } from "events";
import { VitalsDataBase, VitalsValueBase, VitalsWaveformBase } from "./types";
-const WAVEFORM_KEY_MAP: Record = {
- II: "ecg-waveform",
- Pleth: "pleth-waveform",
- Respiration: "spo2-waveform",
-};
+const ECG_WAVENAME_KEYS = [
+ "I",
+ "II",
+ "III",
+ "aVR",
+ "aVL",
+ "aVF",
+ "V1",
+ "V2",
+ "V3",
+ "V4",
+ "V5",
+ "V6",
+] as const;
+
+const WAVEFORM_KEY_MAP: Record =
+ {
+ Pleth: "pleth-waveform",
+ Respiration: "spo2-waveform",
+
+ // Maps each ECG wave name to the event "ecg-waveform"
+ ...(Object.fromEntries(
+ ECG_WAVENAME_KEYS.map((key) => [key, "ecg-waveform"])
+ ) as Record),
+ };
/**
* Provides the API for connecting to the Vitals Monitor WebSocket and emitting
@@ -74,8 +94,10 @@ export interface HL7VitalsValueData extends VitalsDataBase, VitalsValueBase {
| "body-temperature2";
}
+type EcgWaveName = (typeof ECG_WAVENAME_KEYS)[number];
+
export interface HL7VitalsWaveformData extends VitalsWaveformBase {
- "wave-name": "II" | "Pleth" | "Respiration";
+ "wave-name": EcgWaveName | "Pleth" | "Respiration";
}
export interface HL7VitalsBloodPressureData extends VitalsDataBase {
diff --git a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx
index a340c21e28b..c0b089df8b0 100644
--- a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx
+++ b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx
@@ -88,7 +88,7 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) {
{/* Pulse Rate */}
❤️