From 5ac9e15e9ef1df9e33ad5952729192d855107192 Mon Sep 17 00:00:00 2001 From: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> Date: Fri, 15 Sep 2023 17:44:11 +0530 Subject: [PATCH 1/3] Fixed Cypress Failure in Facility and Resource Page (#6293) * Cypress failure * Fix facility name --- cypress/e2e/facility_spec/facility.cy.ts | 30 ++-------------- cypress/e2e/resource_spec/resources.cy.ts | 34 +++++++++++++++++-- .../pageobject/Facility/FacilityCreation.ts | 10 ++++++ cypress/pageobject/Resource/ResourcePage.ts | 4 --- 4 files changed, 45 insertions(+), 33 deletions(-) diff --git a/cypress/e2e/facility_spec/facility.cy.ts b/cypress/e2e/facility_spec/facility.cy.ts index f8fe04b4f30..f2ff847c9d9 100644 --- a/cypress/e2e/facility_spec/facility.cy.ts +++ b/cypress/e2e/facility_spec/facility.cy.ts @@ -7,7 +7,6 @@ describe("Facility Creation", () => { let facilityUrl: string; const facilityPage = new FacilityPage(); const loginPage = new LoginPage(); - const phone_number = "9999999999"; before(() => { loginPage.loginAsDisctrictAdmin(); @@ -40,14 +39,9 @@ describe("Facility Creation", () => { facilityPage.selectAreaOfSpecialization("General Medicine"); facilityPage.fillDoctorCount("5"); facilityPage.saveAndExitDoctorForm(); - - cy.url().then((initialUrl) => { - cy.get("button#save-and-exit").should("not.exist"); - cy.url() - .should("not.equal", initialUrl) - .then((newUrl) => { - facilityUrl = newUrl; - }); + facilityPage.verifyfacilitynewurl(); + cy.url().then((newUrl) => { + facilityUrl = newUrl; }); }); @@ -75,24 +69,6 @@ describe("Facility Creation", () => { facilityPage.verifySuccessNotification("Facility updated successfully"); }); - it("Create a resource request", () => { - facilityPage.visitUpdateFacilityPage(facilityUrl); - facilityPage.clickManageFacilityDropdown(); - facilityPage.clickResourceRequestOption(); - facilityPage.fillResourceRequestDetails( - "Test User", - phone_number, - "cypress", - "Test title", - "10", - "Test description" - ); - facilityPage.clickSubmitRequestButton(); - facilityPage.verifySuccessNotification( - "Resource request created successfully" - ); - }); - it("Delete a facility", () => { facilityPage.visitUpdateFacilityPage(facilityUrl); facilityPage.clickManageFacilityDropdown(); diff --git a/cypress/e2e/resource_spec/resources.cy.ts b/cypress/e2e/resource_spec/resources.cy.ts index b3393d0942b..acf179db120 100644 --- a/cypress/e2e/resource_spec/resources.cy.ts +++ b/cypress/e2e/resource_spec/resources.cy.ts @@ -1,10 +1,14 @@ import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; import LoginPage from "../../pageobject/Login/LoginPage"; import ResourcePage from "../../pageobject/Resource/ResourcePage"; +import FacilityPage from "../../pageobject/Facility/FacilityCreation"; describe("Resource Page", () => { + let createdResource: string; const loginPage = new LoginPage(); const resourcePage = new ResourcePage(); + const facilityPage = new FacilityPage(); + const phone_number = "9999999999"; before(() => { loginPage.loginAsDisctrictAdmin(); @@ -34,8 +38,34 @@ describe("Resource Page", () => { resourcePage.clickBoardViewButton(); }); + it("Create a resource request", () => { + cy.visit("/facility"); + cy.get("#search").click().type("dummy facility 1"); + cy.intercept("GET", "**/api/v1/facility/**").as("loadFacilities"); + cy.get("#facility-details").click(); + cy.wait("@loadFacilities").its("response.statusCode").should("eq", 200); + facilityPage.clickManageFacilityDropdown(); + facilityPage.clickResourceRequestOption(); + facilityPage.fillResourceRequestDetails( + "Test User", + phone_number, + "Dummy", + "Test title", + "10", + "Test description" + ); + facilityPage.clickSubmitRequestButton(); + facilityPage.verifySuccessNotification( + "Resource request created successfully" + ); + facilityPage.verifyresourcenewurl(); + cy.url().then((url) => { + createdResource = url; + }); + }); + it("Update the status of resource", () => { - resourcePage.openAlreadyCreatedResource(); + cy.visit(createdResource); resourcePage.clickUpdateStatus(); resourcePage.updateStatus("APPROVED"); resourcePage.clickSubmitButton(); @@ -45,7 +75,7 @@ describe("Resource Page", () => { }); it("Post comment for a resource", () => { - resourcePage.openAlreadyCreatedResource(); + cy.visit(createdResource); resourcePage.addCommentForResource("Test comment"); resourcePage.clickPostCommentButton(); resourcePage.verifySuccessNotification("Comment added successfully"); diff --git a/cypress/pageobject/Facility/FacilityCreation.ts b/cypress/pageobject/Facility/FacilityCreation.ts index aa46d4f1105..ef4e65781e0 100644 --- a/cypress/pageobject/Facility/FacilityCreation.ts +++ b/cypress/pageobject/Facility/FacilityCreation.ts @@ -100,7 +100,9 @@ class FacilityPage { } saveAndExitDoctorForm() { + cy.intercept("GET", "**/api/v1/facility/**").as("createFacilities"); cy.get("button#save-and-exit").click(); + cy.wait("@createFacilities").its("response.statusCode").should("eq", 200); } clickManageFacilityDropdown() { @@ -131,6 +133,14 @@ class FacilityPage { cy.get("#delete-facility").contains("Delete Facility").click(); } + verifyfacilitynewurl() { + cy.url().should("match", /facility\/[a-z\d-]+/); + } + + verifyresourcenewurl() { + cy.url().should("match", /resource\/[a-z\d-]+/); + } + confirmDeleteFacility() { cy.intercept("DELETE", "**/api/v1/facility/**").as("deleteFacility"); cy.get("#submit").contains("Delete").click(); diff --git a/cypress/pageobject/Resource/ResourcePage.ts b/cypress/pageobject/Resource/ResourcePage.ts index 1fecf86b9e1..f7feac925bf 100644 --- a/cypress/pageobject/Resource/ResourcePage.ts +++ b/cypress/pageobject/Resource/ResourcePage.ts @@ -46,10 +46,6 @@ class ResourcePage { cy.contains("Board View").click(); } - openAlreadyCreatedResource() { - cy.get("[data-testid='resource-details']").first().click(); - } - clickUpdateStatus() { cy.get("[data-testid='update-status']").click(); } From 6b8f706f4a58c00372fa1bb9d98c1803b53bb2ee Mon Sep 17 00:00:00 2001 From: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> Date: Fri, 15 Sep 2023 17:56:13 +0530 Subject: [PATCH 2/3] Add Cypress test to Assets Export Functionality (#6291) * verify asset filter * Add Test for Add Export and verify existing test * reverse vite config --- cypress/e2e/assets_spec/asset_homepage.cy.ts | 24 +++ cypress/e2e/assets_spec/assets_creation.cy.ts | 178 ++++++++++++++++++ cypress/e2e/assets_spec/assets_manage.cy.ts | 160 ---------------- cypress/pageobject/Asset/AssetCreation.ts | 23 ++- src/Components/Assets/AssetManage.tsx | 1 + src/Components/Assets/AssetsList.tsx | 2 + 6 files changed, 227 insertions(+), 161 deletions(-) create mode 100644 cypress/e2e/assets_spec/assets_creation.cy.ts diff --git a/cypress/e2e/assets_spec/asset_homepage.cy.ts b/cypress/e2e/assets_spec/asset_homepage.cy.ts index fa24adf5b21..7b002a7c9bd 100644 --- a/cypress/e2e/assets_spec/asset_homepage.cy.ts +++ b/cypress/e2e/assets_spec/asset_homepage.cy.ts @@ -5,6 +5,7 @@ import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; import { AssetQRScanPage } from "../../pageobject/Asset/AssetQRScan"; import { AssetPagination } from "../../pageobject/Asset/AssetPagination"; import { AssetFilters } from "../../pageobject/Asset/AssetFilters"; +import { AssetPage } from "../../pageobject/Asset/AssetCreation"; import LoginPage from "../../pageobject/Login/LoginPage"; import { v4 as uuidv4 } from "uuid"; @@ -13,6 +14,7 @@ describe("Asset Tab", () => { const assetQRScanPage = new AssetQRScanPage(); const assetPagination = new AssetPagination(); const assetFilters = new AssetFilters(); + const assetPage = new AssetPage(); const loginPage = new LoginPage(); const assetName = "Dummy Camera 10"; const qrCode = uuidv4(); @@ -83,6 +85,28 @@ describe("Asset Tab", () => { assetPagination.navigateToPreviousPage(); }); + it("Import new asset", () => { + assetPage.selectassetimportbutton(); + assetPage.selectImportOption(); + assetPage.selectImportFacility("Dummy Facility 1"); + assetPage.importAssetFile(); + assetPage.selectImportLocation("Camera Locations"); + assetPage.clickImportAsset(); + assetPage.verifySuccessNotification("Assets imported successfully"); + }); + + it("verify imported asset", () => { + assetSearchPage.typeSearchKeyword("New Test Asset"); + assetSearchPage.pressEnter(); + assetSearchPage.verifyAssetIsPresent("New Test Asset"); + }); + + it("Export asset", () => { + assetPage.selectassetimportbutton(); + assetPage.selectjsonexportbutton(); + assetPage.selectcsvexportbutton(); + }); + afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/e2e/assets_spec/assets_creation.cy.ts b/cypress/e2e/assets_spec/assets_creation.cy.ts new file mode 100644 index 00000000000..3e7b24eeca6 --- /dev/null +++ b/cypress/e2e/assets_spec/assets_creation.cy.ts @@ -0,0 +1,178 @@ +/// +import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; +import { AssetPage } from "../../pageobject/Asset/AssetCreation"; +import { v4 as uuidv4 } from "uuid"; +import LoginPage from "../../pageobject/Login/LoginPage"; +import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; + +describe("Asset", () => { + const assetPage = new AssetPage(); + const assetSearchPage = new AssetSearchPage(); + const loginPage = new LoginPage(); + const phone_number = "9999999999"; + const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); + + before(() => { + loginPage.loginAsDisctrictAdmin(); + cy.saveLocalStorage(); + }); + + beforeEach(() => { + cy.restoreLocalStorage(); + cy.awaitUrl("/assets"); + }); + + it("Verify asset creation fields throws error if empty", () => { + assetPage.createAsset(); + assetPage.selectFacility("Dummy Facility 1"); + assetPage.clickCreateAsset(); + + assetPage.verifyEmptyAssetNameError(); + assetPage.verifyEmptyAssetTypeError(); + assetPage.verifyEmptyLocationError(); + assetPage.verifyEmptyStatusError(); + assetPage.verifyEmptyPhoneError(); + }); + + //Create an asset + + it("Create an Asset", () => { + assetPage.createAsset(); + assetPage.selectFacility("Dummy Facility 1"); + assetPage.selectLocation("Camera Loc"); + assetPage.selectAssetType("Internal"); + assetPage.selectAssetClass("ONVIF Camera"); + + const qr_id_1 = uuidv4(); + + assetPage.enterAssetDetails( + "New Test Asset 1", + "Test Description", + "Working", + qr_id_1, + "Manufacturer's Name", + "2025-12-25", + "Customer Support's Name", + phone_number, + "email@support.com", + "Vendor's Name", + serialNumber, + "25122021", + "Test note for asset creation!" + ); + + assetPage.clickCreateAddMore(); + assetPage.verifySuccessNotification("Asset created successfully"); + + const qr_id_2 = uuidv4(); + + assetPage.selectLocation("Camera Loc"); + assetPage.selectAssetType("Internal"); + assetPage.selectAssetClass("ONVIF Camera"); + assetPage.enterAssetDetails( + "New Test Asset 2", + "Test Description", + "Working", + qr_id_2, + "Manufacturer's Name", + "2025-12-25", + "Customer Support's Name", + phone_number, + "email@support.com", + "Vendor's Name", + serialNumber, + "25122021", + "Test note for asset creation!" + ); + + assetPage.interceptAssetCreation(); + assetPage.clickCreateAsset(); + assetPage.verifyAssetCreation(); + assetPage.verifySuccessNotification("Asset created successfully"); + + assetSearchPage.typeSearchKeyword("New Test Asset 2"); + assetSearchPage.pressEnter(); + assetSearchPage.verifyAssetIsPresent("New Test Asset 2"); + }); + + it("Edit an Asset", () => { + assetPage.openCreatedAsset(); + + const qr_id = uuidv4(); + + assetPage.editAssetDetails( + "New Test Asset Edited", + "Test Description Edited", + qr_id, + "Manufacturer's Name Edited", + "Customer Support's Name Edited", + "Vendor's Name Edited", + "Test note for asset creation edited!", + "25122021" + ); + + assetPage.clickUpdateAsset(); + + assetPage.verifySuccessNotification("Asset updated successfully"); + }); + + it("Verify Editted Asset", () => { + assetSearchPage.typeSearchKeyword("New Test Asset Edited"); + assetSearchPage.pressEnter(); + assetSearchPage.verifyAssetIsPresent("New Test Asset Edited"); + }); + + it("Configure an asset", () => { + assetPage.openCreatedAsset(); + assetPage.spyAssetConfigureApi(); + assetPage.configureAsset( + "Host name", + "192.168.1.64", + "remote_user", + "2jCkrCRSeahzKEU", + "d5694af2-21e2-4a39-9bad-2fb98d9818bd" + ); + assetPage.clickConfigureAsset(); + assetPage.verifyAssetConfiguration(200); + }); + + it("Add an vital monitor asset and configure it", () => { + assetPage.createAsset(); + assetPage.selectFacility("Dummy Facility 1"); + assetPage.selectLocation("Camera Loc"); + assetPage.selectAssetType("Internal"); + assetPage.selectAssetClass("HL7 Vitals Monitor"); + + const qr_id_1 = uuidv4(); + + assetPage.enterAssetDetails( + "New Test Asset Vital", + "Test Description", + "Working", + qr_id_1, + "Manufacturer's Name", + "2025-12-25", + "Customer Support's Name", + phone_number, + "email@support.com", + "Vendor's Name", + serialNumber, + "25122021", + "Test note for asset creation!" + ); + assetPage.interceptAssetCreation(); + assetPage.clickCreateAsset(); + assetPage.verifyAssetCreation(); + + assetSearchPage.typeSearchKeyword("New Test Asset Vital"); + assetSearchPage.pressEnter(); + + assetPage.openCreatedAsset(); + assetPage.configureVitalAsset("Host name", "192.168.1.64"); + assetPage.clickConfigureVital(); + }); + + afterEach(() => { + cy.saveLocalStorage(); + }); +}); diff --git a/cypress/e2e/assets_spec/assets_manage.cy.ts b/cypress/e2e/assets_spec/assets_manage.cy.ts index af3efb917dd..f27fd302a0c 100644 --- a/cypress/e2e/assets_spec/assets_manage.cy.ts +++ b/cypress/e2e/assets_spec/assets_manage.cy.ts @@ -1,16 +1,10 @@ -/// import { afterEach, before, beforeEach, cy, describe, it } from "local-cypress"; import { AssetPage } from "../../pageobject/Asset/AssetCreation"; -import { v4 as uuidv4 } from "uuid"; import LoginPage from "../../pageobject/Login/LoginPage"; -import { AssetSearchPage } from "../../pageobject/Asset/AssetSearch"; describe("Asset", () => { const assetPage = new AssetPage(); - const assetSearchPage = new AssetSearchPage(); const loginPage = new LoginPage(); - const phone_number = "9999999999"; - const serialNumber = Math.floor(Math.random() * 10 ** 10).toString(); before(() => { loginPage.loginAsDisctrictAdmin(); @@ -22,150 +16,6 @@ describe("Asset", () => { cy.awaitUrl("/assets"); }); - it("Verify asset creation fields throws error if empty", () => { - assetPage.createAsset(); - assetPage.selectFacility("Dummy Facility 1"); - assetPage.clickCreateAsset(); - - assetPage.verifyEmptyAssetNameError(); - assetPage.verifyEmptyAssetTypeError(); - assetPage.verifyEmptyLocationError(); - assetPage.verifyEmptyStatusError(); - assetPage.verifyEmptyPhoneError(); - }); - - //Create an asset - - it("Create an Asset", () => { - assetPage.createAsset(); - assetPage.selectFacility("Dummy Facility 1"); - assetPage.selectLocation("Camera Loc"); - assetPage.selectAssetType("Internal"); - assetPage.selectAssetClass("ONVIF Camera"); - - const qr_id_1 = uuidv4(); - - assetPage.enterAssetDetails( - "New Test Asset 1", - "Test Description", - "Working", - qr_id_1, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!" - ); - - assetPage.clickCreateAddMore(); - assetPage.verifySuccessNotification("Asset created successfully"); - - const qr_id_2 = uuidv4(); - - assetPage.selectLocation("Camera Loc"); - assetPage.selectAssetType("Internal"); - assetPage.selectAssetClass("ONVIF Camera"); - assetPage.enterAssetDetails( - "New Test Asset 2", - "Test Description", - "Working", - qr_id_2, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!" - ); - - assetPage.interceptAssetCreation(); - assetPage.clickCreateAsset(); - assetPage.verifyAssetCreation(); - assetPage.verifySuccessNotification("Asset created successfully"); - - assetSearchPage.typeSearchKeyword("New Test Asset 2"); - assetSearchPage.pressEnter(); - assetSearchPage.verifyAssetIsPresent("New Test Asset 2"); - }); - - it("Edit an Asset", () => { - assetPage.openCreatedAsset(); - - const qr_id = uuidv4(); - - assetPage.editAssetDetails( - "New Test Asset Edited", - "Test Description Edited", - qr_id, - "Manufacturer's Name Edited", - "Customer Support's Name Edited", - "Vendor's Name Edited", - "Test note for asset creation edited!", - "25122021" - ); - - assetPage.clickUpdateAsset(); - - assetPage.verifySuccessNotification("Asset updated successfully"); - }); - - it("Configure an asset", () => { - assetPage.openCreatedAsset(); - assetPage.spyAssetConfigureApi(); - assetPage.configureAsset( - "Host name", - "192.168.1.64", - "remote_user", - "2jCkrCRSeahzKEU", - "d5694af2-21e2-4a39-9bad-2fb98d9818bd" - ); - assetPage.clickConfigureAsset(); - assetPage.verifyAssetConfiguration(200); - }); - - it("Add an vital monitor asset and configure it", () => { - assetPage.createAsset(); - assetPage.selectFacility("Dummy Facility 1"); - assetPage.selectLocation("Camera Loc"); - assetPage.selectAssetType("Internal"); - assetPage.selectAssetClass("HL7 Vitals Monitor"); - - const qr_id_1 = uuidv4(); - - assetPage.enterAssetDetails( - "New Test Asset Vital", - "Test Description", - "Working", - qr_id_1, - "Manufacturer's Name", - "2025-12-25", - "Customer Support's Name", - phone_number, - "email@support.com", - "Vendor's Name", - serialNumber, - "25122021", - "Test note for asset creation!" - ); - assetPage.interceptAssetCreation(); - assetPage.clickCreateAsset(); - assetPage.verifyAssetCreation(); - - assetSearchPage.typeSearchKeyword("New Test Asset Vital"); - assetSearchPage.pressEnter(); - - assetPage.openCreatedAsset(); - assetPage.configureVitalAsset("Host name", "192.168.1.64"); - assetPage.clickConfigureVital(); - }); - it("Delete an Asset", () => { assetPage.openCreatedAsset(); assetPage.interceptDeleteAssetApi(); @@ -173,16 +23,6 @@ describe("Asset", () => { assetPage.verifyDeleteStatus(); }); - it("Import new asset", () => { - assetPage.selectImportOption(); - assetPage.selectImportFacility("Dummy Facility 1"); - assetPage.importAssetFile(); - assetPage.selectImportLocation("Camera Locations"); - assetPage.clickImportAsset(); - - assetPage.verifySuccessNotification("Assets imported successfully"); - }); - afterEach(() => { cy.saveLocalStorage(); }); diff --git a/cypress/pageobject/Asset/AssetCreation.ts b/cypress/pageobject/Asset/AssetCreation.ts index fdaf802d4b7..b939c31405f 100644 --- a/cypress/pageobject/Asset/AssetCreation.ts +++ b/cypress/pageobject/Asset/AssetCreation.ts @@ -234,8 +234,29 @@ export class AssetPage { }); } - selectImportOption() { + selectassetimportbutton() { cy.get("[data-testid=import-asset-button]").click(); + } + + selectjsonexportbutton() { + cy.intercept("GET", "**/api/v1/asset/?json=true**").as("getJsonexport"); + cy.get("#export-json-option").click(); + cy.wait("@getJsonexport").then(({ request, response }) => { + expect(response.statusCode).to.eq(200); + expect(request.url).to.include("json=true"); + }); + } + + selectcsvexportbutton() { + cy.intercept("GET", "**/api/v1/asset/?csv=true**").as("getCsvexport"); + cy.get("#export-csv-option").click(); + cy.wait("@getCsvexport").then(({ request, response }) => { + expect(response.statusCode).to.eq(200); + expect(request.url).to.include("csv=true"); + }); + } + + selectImportOption() { cy.get(".import-assets-button").click(); } diff --git a/src/Components/Assets/AssetManage.tsx b/src/Components/Assets/AssetManage.tsx index 25f879ddd09..1df9fbde9a6 100644 --- a/src/Components/Assets/AssetManage.tsx +++ b/src/Components/Assets/AssetManage.tsx @@ -360,6 +360,7 @@ const AssetManage = (props: AssetManageProps) => { {asset?.name} { options: { icon: , disabled: totalCount === 0 || !authorizedForImportExport, + id: "export-json-option", }, }, { @@ -353,6 +354,7 @@ const AssetsList = () => { options: { icon: , disabled: totalCount === 0 || !authorizedForImportExport, + id: "export-csv-option", }, }, ]} From 01673150d3512de8686bc1602cc01c653291cf04 Mon Sep 17 00:00:00 2001 From: Khavin Shankar Date: Fri, 15 Sep 2023 18:00:32 +0530 Subject: [PATCH 3/3] Cam reset (#6286) --- src/Common/hooks/useHLSPlayer.ts | 2 +- .../Facility/Consultations/Feed.tsx | 39 +++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/Common/hooks/useHLSPlayer.ts b/src/Common/hooks/useHLSPlayer.ts index 7cb5302e76f..32a52043fe7 100644 --- a/src/Common/hooks/useHLSPlayer.ts +++ b/src/Common/hooks/useHLSPlayer.ts @@ -4,7 +4,7 @@ import { IOptions } from "./useMSEplayer"; export const useHLSPLayer = (ref: ReactPlayer | null) => { const startStream = ({ onSuccess, onError }: IOptions = {}) => { try { - ref && ref.forceUpdate(); + ref?.setState({ url: ref?.props.url + "&t=" + Date.now() }); onSuccess && onSuccess(undefined); } catch (err) { onError && onError(err); diff --git a/src/Components/Facility/Consultations/Feed.tsx b/src/Components/Facility/Consultations/Feed.tsx index 07fd6f31739..84b3e62ef9e 100644 --- a/src/Components/Facility/Consultations/Feed.tsx +++ b/src/Components/Facility/Consultations/Feed.tsx @@ -56,6 +56,7 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { const [precision, setPrecision] = useState(1); const [cameraState, setCameraState] = useState(null); const [isFullscreen, setFullscreen] = useFullscreen(); + const [videoStartTime, setVideoStartTime] = useState(null); const authUser = useAuthUser(); useEffect(() => { @@ -197,6 +198,16 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { dispatch, }); + const calculateVideoLiveDelay = () => { + const video = liveFeedPlayerRef.current as HTMLVideoElement; + if (!video || !videoStartTime) return 0; + + const timeDifference = + (new Date().getTime() - videoStartTime.getTime()) / 1000; + + return timeDifference - video.currentTime; + }; + const getBedPresets = async (asset: any) => { if (asset.id && bed) { const bedAssets = await dispatch(listAssetBeds({ asset: asset.id, bed })); @@ -240,7 +251,7 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { }, []); useEffect(() => { - if (streamStatus === StreamStatus.Playing) { + if (!currentPreset && streamStatus === StreamStatus.Playing) { setLoading(CAMERA_STATES.MOVING.GENERIC); const preset = bedPresets?.find( @@ -296,6 +307,7 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { }, reset: () => { setStreamStatus(StreamStatus.Loading); + setVideoStartTime(null); startStream({ onSuccess: () => setStreamStatus(StreamStatus.Playing), onError: () => setStreamStatus(StreamStatus.Offline), @@ -437,10 +449,16 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { playsinline={true} playing={true} muted={true} + onPlay={() => { + setVideoStartTime(() => new Date()); + }} width="100%" height="100%" onBuffer={() => { - setStreamStatus(StreamStatus.Loading); + const delay = calculateVideoLiveDelay(); + if (delay > 5) { + setStreamStatus(StreamStatus.Loading); + } }} onError={(e: any, _: any, hlsInstance: any) => { if (e === "hlsError") { @@ -459,6 +477,15 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { muted playsInline className="max-h-full max-w-full" + onPlay={() => { + setVideoStartTime(() => new Date()); + }} + onWaiting={() => { + const delay = calculateVideoLiveDelay(); + if (delay > 5) { + setStreamStatus(StreamStatus.Loading); + } + }} ref={liveFeedPlayerRef as any} /> )} @@ -506,7 +533,6 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => {
{["fullScreen", "reset", "updatePreset", "zoomIn", "zoomOut"].map( (button, index) => { - if (isIOS && button === "reset") return null; const option = cameraPTZ.find( (option) => option.action === button ); @@ -531,6 +557,13 @@ export const Feed: React.FC = ({ consultationId, facilityId }) => { clickAction={() => cameraPTZ[4].callback()} />
+ {streamStatus === StreamStatus.Playing && + calculateVideoLiveDelay() > 3 && ( +
+ + Slow Network Detected +
+ )}
{[ false,