Skip to content

Commit

Permalink
Merge branch 'develop' into Fix-#6944
Browse files Browse the repository at this point in the history
  • Loading branch information
AshrafMd-1 committed May 22, 2024
2 parents 2a2027f + a9530a9 commit 3b0308f
Show file tree
Hide file tree
Showing 36 changed files with 845 additions and 486 deletions.
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,4 @@

## Reporting a Vulnerability

Please create a ticket at https://support.coronasafe.network
Please create an issue at https://github.com/coronasafe/care_fe/issues/new
6 changes: 3 additions & 3 deletions cypress/e2e/patient_spec/patient_consultation.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ describe("Patient Consultation in multiple combination", () => {
);
patientConsultationPage.typePatientWeight(patientWeight);
patientConsultationPage.typePatientHeight(patientHeight);
patientConsultationPage.selectPatientCategory("Stable");
patientConsultationPage.selectPatientCategory("Mild");
// icd 11 - 4 diagnosis with one principal
patientConsultationPage.selectPatientDiagnosis(
diagnosis1,
Expand Down Expand Up @@ -236,7 +236,7 @@ describe("Patient Consultation in multiple combination", () => {
// Asymptomatic
cy.searchAndSelectOption("#symptoms", "ASYMPTOMATIC");
// Abnormal category
patientConsultationPage.selectPatientCategory("Abnormal");
patientConsultationPage.selectPatientCategory("Moderate");
patientConsultationPage.selectPatientSuggestion("Domiciliary Care");
// one ICD-11 diagnosis
patientConsultationPage.selectPatientDiagnosis(
Expand Down Expand Up @@ -299,7 +299,7 @@ describe("Patient Consultation in multiple combination", () => {
"SORE THROAT",
]);
// Stable category
patientConsultationPage.selectPatientCategory("Stable");
patientConsultationPage.selectPatientCategory("Mild");
// Date of symptoms
patientConsultationPage.selectSymptomsDate(
"#symptoms_onset_date",
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/patient_spec/patient_logupdate.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe("Patient Log Update in Normal, Critical and TeleIcu", () => {
const patientPage = new PatientPage();
const patientLogupdate = new PatientLogupdate();
const domicilaryPatient = "Dummy Patient 11";
const patientCategory = "Abnormal";
const patientCategory = "Moderate";
const additionalSymptoms = "ASYMPTOMATIC";
const physicalExamination = "physical examination details";
const otherExamination = "Other";
Expand Down
20 changes: 20 additions & 0 deletions src/CAREUI/misc/AuthorizedChild.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { ReactNode } from "react";
import useAuthUser from "../../Common/hooks/useAuthUser";
import { useIsAuthorized } from "../../Common/hooks/useIsAuthorized";
import useSlug from "../../Common/hooks/useSlug";
import { AuthorizedForCB } from "../../Utils/AuthorizeFor";

interface Props {
Expand All @@ -12,3 +15,20 @@ const AuthorizedChild = (props: Props) => {
};

export default AuthorizedChild;

export const AuthorizedForConsultationRelatedActions = (props: {
children: ReactNode;
}) => {
const me = useAuthUser();
const facilityId = useSlug("facility");

if (
me.home_facility_object?.id === facilityId ||
me.user_type === "DistrictAdmin" ||
me.user_type === "StateAdmin"
) {
return props.children;
}

return null;
};
12 changes: 11 additions & 1 deletion src/CAREUI/misc/PaginatedList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, useContext, useState } from "react";
import { createContext, useContext, useEffect, useState } from "react";
import { PaginatedResponse, QueryRoute } from "../../Utils/request/types";
import useQuery, { QueryOptions } from "../../Utils/request/useQuery";
import ButtonV2, {
Expand Down Expand Up @@ -33,6 +33,9 @@ function useContextualized<TItem>() {
interface Props<TItem> extends QueryOptions<PaginatedResponse<TItem>> {
route: QueryRoute<PaginatedResponse<TItem>>;
perPage?: number;
queryCB?: (
query: ReturnType<typeof useQuery<PaginatedResponse<TItem>>>,
) => void;
children: (
ctx: PaginatedListContext<TItem>,
query: ReturnType<typeof useQuery<PaginatedResponse<TItem>>>,
Expand All @@ -43,6 +46,7 @@ export default function PaginatedList<TItem extends object>({
children,
route,
perPage = DEFAULT_PER_PAGE_LIMIT,
queryCB,
...queryOptions
}: Props<TItem>) {
const [currentPage, setPage] = useState(1);
Expand All @@ -57,6 +61,12 @@ export default function PaginatedList<TItem extends object>({

const items = query.data?.results ?? [];

useEffect(() => {
if (queryCB) {
queryCB(query);
}
}, [query]);

return (
<context.Provider
value={{ ...query, items, perPage, currentPage, setPage }}
Expand Down
4 changes: 2 additions & 2 deletions src/Common/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,8 @@ export const PATIENT_CATEGORIES: {
twClass: string;
}[] = [
{ id: "Comfort", text: "Comfort Care", twClass: "patient-comfort" },
{ id: "Stable", text: "Stable", twClass: "patient-stable" },
{ id: "Moderate", text: "Abnormal", twClass: "patient-abnormal" },
{ id: "Stable", text: "Mild", twClass: "patient-stable" },
{ id: "Moderate", text: "Moderate", twClass: "patient-abnormal" },
{ id: "Critical", text: "Critical", twClass: "patient-critical" },
];

Expand Down
1 change: 0 additions & 1 deletion src/Common/hooks/useMSEplayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ export const useMSEMediaPlayer = ({
const ws = wsRef.current;
ws.binaryType = "arraybuffer";
ws.onopen = function (_event) {
console.log("Connected to ws");
onSuccess && onSuccess(undefined);
};
ws.onmessage = function (event) {
Expand Down
3 changes: 2 additions & 1 deletion src/Components/Assets/configure/MonitorConfigure.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from "react";
import { BedSelect } from "../../Common/BedSelect";
import { BedModel } from "../../Facility/models";
import { AssetData } from "../AssetTypes";
import { AssetClass, AssetData } from "../AssetTypes";
import * as Notification from "../../../Utils/Notifications.js";
import { Submit } from "../../Common/components/ButtonV2";
import { FieldLabel } from "../../Form/FormFields/FormField";
Expand Down Expand Up @@ -73,6 +73,7 @@ export default function MonitorConfigure({ asset }: { asset: AssetData }) {
multiple={false}
location={asset?.location_object?.id}
facility={asset?.location_object?.facility?.id}
not_occupied_by_asset_type={AssetClass.HL7MONITOR}
className="w-full"
/>
</div>
Expand Down
37 changes: 15 additions & 22 deletions src/Components/CameraFeed/AssetBedSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
import { Fragment } from "react";
import useSlug from "../../Common/hooks/useSlug";
import routes from "../../Redux/api";
import useQuery from "../../Utils/request/useQuery";
import { AssetBedModel, AssetData } from "../Assets/AssetTypes";
import { BedModel } from "../Facility/models";
import { AssetBedModel } from "../Assets/AssetTypes";
import { Listbox, Transition } from "@headlessui/react";
import CareIcon from "../../CAREUI/icons/CareIcon";

interface Props {
asset?: AssetData;
bed?: BedModel;
options: AssetBedModel[];
value?: AssetBedModel;
label?: (value: AssetBedModel) => string;
onChange?: (value: AssetBedModel) => void;
}

export default function AssetBedSelect(props: Props) {
const facility = useSlug("facility");
const selected = props.value;

const { data, loading } = useQuery(routes.listAssetBeds, {
query: {
limit: 100,
facility,
asset: props.asset?.id,
bed: props.bed?.id,
},
});
const options = props.options.filter(({ meta }) => meta.type !== "boundary");

const selected = props.value;
const label = props.label ?? defaultLabel;

return (
<Listbox value={selected} onChange={props.onChange} disabled={loading}>
<div className="relative">
<Listbox value={selected} onChange={props.onChange}>
<div className="relative flex-1">
<Listbox.Button className="relative w-full cursor-default pr-6 text-right text-xs text-zinc-400 focus:outline-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-zinc-700 sm:text-sm">
<span className="block truncate">
{selected?.bed_object.name ?? "No Preset"}
{selected ? label(selected) : "No Preset"}
</span>
<span className="pointer-events-none absolute inset-y-0 right-0 mt-1 flex items-center">
<CareIcon icon="l-angle-down" className="text-lg text-zinc-500" />
Expand All @@ -46,7 +35,7 @@ export default function AssetBedSelect(props: Props) {
leaveTo="opacity-0"
>
<Listbox.Options className="absolute z-20 mt-1 max-h-48 w-full overflow-auto rounded-b-lg bg-zinc-900/75 py-1 text-base shadow-lg ring-1 ring-white/5 backdrop-blur-sm focus:outline-none sm:text-sm md:max-h-60">
{data?.results.map((obj) => (
{options?.map((obj) => (
<Listbox.Option
key={obj.id}
className={({ active }) =>
Expand All @@ -63,7 +52,7 @@ export default function AssetBedSelect(props: Props) {
selected ? "font-bold text-white" : "font-normal"
}`}
>
{obj.bed_object.name}: {obj.meta.preset_name}
{label(obj)}
</span>
</>
)}
Expand All @@ -75,3 +64,7 @@ export default function AssetBedSelect(props: Props) {
</Listbox>
);
}

const defaultLabel = ({ bed_object, meta }: AssetBedModel) => {
return `${bed_object.name}: ${meta.preset_name}`;
};
6 changes: 4 additions & 2 deletions src/Components/CameraFeed/CameraFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface Props {
// Controls
constrolsDisabled?: boolean;
shortcutsDisabled?: boolean;
onMove?: () => void;
}

export default function CameraFeed(props: Props) {
Expand Down Expand Up @@ -76,7 +77,7 @@ export default function CameraFeed(props: Props) {
},
onError: props.onStreamError,
});
}, [player.initializeStream, props.onStreamSuccess, props.onStreamError]);
}, [player.initializeStream]);

// Start stream on mount
useEffect(() => initializeStream(), [initializeStream]);
Expand All @@ -90,7 +91,7 @@ export default function CameraFeed(props: Props) {
<Fullscreen fullscreen={isFullscreen} onExit={() => setFullscreen(false)}>
<div
className={classNames(
"flex flex-col overflow-clip rounded-xl bg-black",
"flex max-h-screen flex-col overflow-clip rounded-xl bg-black",
props.className,
)}
>
Expand Down Expand Up @@ -180,6 +181,7 @@ export default function CameraFeed(props: Props) {
setFullscreen={setFullscreen}
onReset={resetStream}
onMove={async (data) => {
props.onMove?.();
setState("moving");
const { res } = await operate({ type: "relative_move", data });
setTimeout(() => {
Expand Down
22 changes: 17 additions & 5 deletions src/Components/CameraFeed/CameraFeedWithBedPresets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,22 @@ import { useState } from "react";
import { AssetBedModel, AssetData } from "../Assets/AssetTypes";
import CameraFeed from "./CameraFeed";
import AssetBedSelect from "./AssetBedSelect";
import useQuery from "../../Utils/request/useQuery";
import routes from "../../Redux/api";
import useSlug from "../../Common/hooks/useSlug";

interface Props {
asset: AssetData;
}

export default function LocationFeedTile(props: Props) {
const facility = useSlug("facility");
const [preset, setPreset] = useState<AssetBedModel>();

const { data, loading } = useQuery(routes.listAssetBeds, {
query: { limit: 100, facility, asset: props.asset?.id },
});

return (
<CameraFeed
asset={props.asset}
Expand All @@ -18,11 +26,15 @@ export default function LocationFeedTile(props: Props) {
shortcutsDisabled
>
<div className="w-64">
<AssetBedSelect
asset={props.asset}
value={preset}
onChange={setPreset}
/>
{loading ? (
<span>loading presets...</span>
) : (
<AssetBedSelect
options={data?.results ?? []}
value={preset}
onChange={setPreset}
/>
)}
</div>
</CameraFeed>
);
Expand Down
16 changes: 5 additions & 11 deletions src/Components/CameraFeed/FeedControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export default function FeedControls({ shortcutsDisabled, ...props }: Props) {
helpText="Up"
shortcut={Shortcuts.MoveUp}
shortcutsDisabled={shortcutsDisabled}
tooltipClassName="-translate-y-20 md:translate-y-0"
>
<CareIcon icon="l-triangle" className="rotate-0" />
</FeedButton>
Expand All @@ -102,6 +103,7 @@ export default function FeedControls({ shortcutsDisabled, ...props }: Props) {
helpText="Left"
shortcut={Shortcuts.MoveLeft}
shortcutsDisabled={shortcutsDisabled}
tooltipClassName="-translate-y-20 -translate-x-1 md:translate-x-0 md:translate-y-0"
>
<CareIcon icon="l-triangle" className="-rotate-90" />
</FeedButton>
Expand All @@ -114,6 +116,7 @@ export default function FeedControls({ shortcutsDisabled, ...props }: Props) {
shortcut={Shortcuts.TogglePrecision}
className="font-bold"
shortcutsDisabled={shortcutsDisabled}
tooltipClassName="-translate-y-20 -translate-x-20 md:translate-x-0 md:translate-y-0"
>
{precision}x
</FeedButton>
Expand All @@ -125,6 +128,7 @@ export default function FeedControls({ shortcutsDisabled, ...props }: Props) {
helpText="Right"
shortcut={Shortcuts.MoveRight}
shortcutsDisabled={shortcutsDisabled}
tooltipClassName="-translate-y-20 -translate-x-2 md:translate-x-0 md:translate-y-0"
>
<CareIcon icon="l-triangle" className="rotate-90" />
</FeedButton>
Expand All @@ -142,7 +146,7 @@ export default function FeedControls({ shortcutsDisabled, ...props }: Props) {
helpText="Down"
shortcut={Shortcuts.MoveDown}
shortcutsDisabled={shortcutsDisabled}
tooltipClassName="tooltip-top"
tooltipClassName="-translate-y-20 -translate-x-2 md:-translate-x-14"
>
<CareIcon icon="l-triangle" className="rotate-180" />
</FeedButton>
Expand Down Expand Up @@ -185,16 +189,6 @@ export default function FeedControls({ shortcutsDisabled, ...props }: Props) {
>
<CareIcon icon="l-redo" />
</FeedButton>
{/* TODO: implement this when this is used in where presets can be saved. */}
{/* <FeedButton
shortcut={Shortcuts.SavePreset}
tooltipClassName="tooltip-left translate-y-2 translate-x-1"
helpText="Save current view to preset"
onTrigger={() => console.error("Not implemented")}
shortcutsDisabled={shortcutsDisabled}
>
<CareIcon icon="l-save" />
</FeedButton> */}
<FeedButton
shortcut={Shortcuts.Fullscreen}
tooltipClassName="tooltip-left translate-y-2 translate-x-1"
Expand Down
2 changes: 1 addition & 1 deletion src/Components/CameraFeed/FeedNetworkSignal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function FeedNetworkSignal(props: Props) {
if (-5 > delay || delay > 5) {
props.onReset();
}
}, 500);
}, 1000);

return () => {
clearInterval(interval);
Expand Down
5 changes: 4 additions & 1 deletion src/Components/Common/BedSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AutoCompleteAsync from "../Form/AutoCompleteAsync";
import { useTranslation } from "react-i18next";
import request from "../../Utils/request/request";
import routes from "../../Redux/api";
import { AssetClass } from "../Assets/AssetTypes";

interface BedSelectProps {
name: string;
Expand All @@ -17,6 +18,7 @@ interface BedSelectProps {
showAll?: boolean;
showNOptions?: number;
selected: BedModel | BedModel[] | null;
not_occupied_by_asset_type?: AssetClass;
setSelected: (selected: BedModel | BedModel[] | null) => void;
}

Expand All @@ -33,6 +35,7 @@ export const BedSelect = (props: BedSelectProps) => {
facility,
location,
showNOptions = 20,
not_occupied_by_asset_type,
} = props;
const { t } = useTranslation();

Expand All @@ -45,8 +48,8 @@ export const BedSelect = (props: BedSelectProps) => {
all: searchAll,
facility,
location,
not_occupied_by_asset_type,
};

const { data } = await request(routes.listFacilityBeds, { query });

if (unoccupiedOnly) {
Expand Down
Loading

0 comments on commit 3b0308f

Please sign in to comment.