From 5b8c1d360049515b2e5b6dcc186721c0f0f5fe26 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 9 Aug 2023 11:27:29 +0000 Subject: [PATCH 001/121] =?UTF-8?q?Central=20Nursing=20Station:=20Dynamic?= =?UTF-8?q?=20aspect=20ratio=20for=20Vitals=20(variable=20timespan=20based?= =?UTF-8?q?=20on=20screen=20size=20=F0=9F=93=B1=F0=9F=96=A5=EF=B8=8F)=20(#?= =?UTF-8?q?6036)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Dynamic aspect ratio for CNS Vitals * remove console log --- .../Facility/CentralNursingStation.tsx | 19 +++++-- .../Facility/ConsultationDetails.tsx | 16 +++--- .../VitalsMonitor/HL7PatientVitalsMonitor.tsx | 50 ++++++++----------- .../useVitalsAspectRatioConfig.ts | 13 +++++ 4 files changed, 57 insertions(+), 41 deletions(-) create mode 100644 src/Components/VitalsMonitor/useVitalsAspectRatioConfig.ts diff --git a/src/Components/Facility/CentralNursingStation.tsx b/src/Components/Facility/CentralNursingStation.tsx index f90a7ab6f3a..0d510d8459e 100644 --- a/src/Components/Facility/CentralNursingStation.tsx +++ b/src/Components/Facility/CentralNursingStation.tsx @@ -23,6 +23,7 @@ import CheckBoxFormField from "../Form/FormFields/CheckBoxFormField"; import { useTranslation } from "react-i18next"; import { SortOption } from "../Common/SortDropdown"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; +import useVitalsAspectRatioConfig from "../VitalsMonitor/useVitalsAspectRatioConfig"; const PER_PAGE_LIMIT = 6; @@ -117,6 +118,17 @@ export default function CentralNursingStation({ facilityId }: Props) { qParams.bed_is_occupied, ]); + const { config, hash } = useVitalsAspectRatioConfig({ + default: 6 / 11, + vs: 10 / 11, + sm: 17 / 11, + md: 19 / 11, + lg: 11 / 11, + xl: 13 / 11, + "2xl": 16 / 11, + "3xl": 12 / 11, + }); + return ( ) : ( -
+
{data.map((props) => ( -
+
))} diff --git a/src/Components/Facility/ConsultationDetails.tsx b/src/Components/Facility/ConsultationDetails.tsx index fecf14f1198..329164d3d07 100644 --- a/src/Components/Facility/ConsultationDetails.tsx +++ b/src/Components/Facility/ConsultationDetails.tsx @@ -54,9 +54,8 @@ import { navigate } from "raviger"; import { useDispatch, useSelector } from "react-redux"; import { useQueryParams } from "raviger"; import { useTranslation } from "react-i18next"; -import useBreakpoints from "../../Common/hooks/useBreakpoints"; -import { getVitalsCanvasSizeAndDuration } from "../VitalsMonitor/utils"; import { triggerGoal } from "../Common/Plausible"; +import useVitalsAspectRatioConfig from "../VitalsMonitor/useVitalsAspectRatioConfig"; const Loading = loadable(() => import("../Common/Loading")); const PageTitle = loadable(() => import("../Common/PageTitle")); @@ -221,7 +220,7 @@ export const ConsultationDetails = (props: any) => { }); }, []); - const vitalsAspectRatio = useBreakpoints({ + const vitals = useVitalsAspectRatioConfig({ default: undefined, md: 8 / 11, lg: 15 / 11, @@ -230,9 +229,6 @@ export const ConsultationDetails = (props: any) => { "3xl": 23 / 11, }); - const vitalsConfig = getVitalsCanvasSizeAndDuration(vitalsAspectRatio); - const vitalsConfigHash = JSON.stringify(vitalsConfig); - if (isLoading) { return ; } @@ -579,7 +575,7 @@ export const ConsultationDetails = (props: any) => { {hl7SocketUrl && (
{ meta: monitorBedData?.asset_object?.meta, }} socketUrl={hl7SocketUrl} - config={vitalsConfig} + config={vitals.config} />
)} {ventilatorSocketUrl && (
{ meta: ventilatorBedData?.asset_object?.meta, }} socketUrl={ventilatorSocketUrl} - config={vitalsConfig} + config={vitals.config} />
)} diff --git a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx index 56142dacccc..94e77c857fc 100644 --- a/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx +++ b/src/Components/VitalsMonitor/HL7PatientVitalsMonitor.tsx @@ -51,42 +51,36 @@ export default function HL7PatientVitalsMonitor(props: IVitalsComponentProps) { )} {patient && ( - + {patient.age}y;{" "} {GENDER_TYPES.find((g) => g.id === patient.gender)?.icon} )}
-
+
{asset && ( -
- - - - {asset.name} - - -
+ + + {asset.name} + )} {bed && ( -
- - - - {bed.name} - - - - {bed.location_object?.name} - - -
+ + + + {bed.name} + + + + {bed.location_object?.name} + + )}
diff --git a/src/Components/VitalsMonitor/useVitalsAspectRatioConfig.ts b/src/Components/VitalsMonitor/useVitalsAspectRatioConfig.ts new file mode 100644 index 00000000000..e41034779fd --- /dev/null +++ b/src/Components/VitalsMonitor/useVitalsAspectRatioConfig.ts @@ -0,0 +1,13 @@ +import useBreakpoints from "../../Common/hooks/useBreakpoints"; +import { getVitalsCanvasSizeAndDuration } from "./utils"; + +export default function useVitalsAspectRatioConfig( + breakpointsMap: Parameters>[0] +) { + const vitalsAspectRatio = useBreakpoints(breakpointsMap); + + const config = getVitalsCanvasSizeAndDuration(vitalsAspectRatio); + const hash = JSON.stringify(config); + + return { config, hash }; +} From dc129fb78ba2d20d5256b6aedcf5c1f83b858124 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 9 Aug 2023 11:37:06 +0000 Subject: [PATCH 002/121] =?UTF-8?q?=F0=9F=AA=84=20Adds=20type=20safety=20f?= =?UTF-8?q?or=20`CareIcon`=20names=20+=20=E2=9C=A8=20reduced=20index.css?= =?UTF-8?q?=20size=20by=2095%=20+=20Refactor=20string=20interpolated=20tw?= =?UTF-8?q?=20classes=20(#6034)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor `CountBlock` and `PatientCategory` components * refactor `ButtonV2` string interpolated align * fixes #6033; Adds type safety for icon names * refactored `Count` block * refactor `Chip` component * fixes #6023; remove safelist from tw config * adds missing classes --- src/CAREUI/display/Chip.tsx | 109 +++++++----------- src/CAREUI/display/Count.tsx | 39 +++---- src/CAREUI/icons/CareIcon.tsx | 17 ++- src/Common/constants.tsx | 19 +-- src/Components/Assets/AssetManage.tsx | 14 ++- src/Components/Assets/AssetsList.tsx | 7 +- .../Common/PatientCategoryBadge.tsx | 9 +- src/Components/Common/components/ButtonV2.tsx | 6 +- src/Components/Common/components/Menu.tsx | 16 ++- src/Components/ExternalResult/ResultList.tsx | 3 +- .../Facility/ConsultationDetails.tsx | 6 +- src/Components/Facility/FacilityCard.tsx | 18 +-- src/Components/Facility/FacilityHome.tsx | 1 - src/Components/Facility/FacilityUsers.tsx | 3 +- src/Components/Facility/HospitalList.tsx | 3 +- .../Medicine/PrescriptionBuilder.tsx | 11 +- src/Components/Patient/ManagePatients.tsx | 36 +++--- .../Patient/PatientCategorySelect.tsx | 13 ++- src/Components/Patient/PatientHome.tsx | 89 +++++++------- src/Components/Patient/PatientInfoCard.tsx | 28 +++-- src/Components/Patient/SampleViewAdmin.tsx | 3 +- src/Components/Users/ManageUsers.tsx | 3 +- tailwind.config.js | 6 - 23 files changed, 236 insertions(+), 223 deletions(-) diff --git a/src/CAREUI/display/Chip.tsx b/src/CAREUI/display/Chip.tsx index 1b2c4c91041..abc21711551 100644 --- a/src/CAREUI/display/Chip.tsx +++ b/src/CAREUI/display/Chip.tsx @@ -1,84 +1,53 @@ -import { MouseEventHandler, useEffect, useState } from "react"; +import CareIcon, { IconName } from "../icons/CareIcon"; +import { ButtonVariant } from "../../Components/Common/components/ButtonV2"; +import { classNames } from "../../Utils/utils"; -type iconType = "uil" | "fa"; interface Props { size?: "small" | "medium" | "large"; hideBorder?: boolean; - color?: string; - startIcon?: string | JSX.Element; - startIconType?: iconType; - endIcon?: string | JSX.Element; - endIconType?: iconType; + variant?: ButtonVariant | "custom"; + startIcon?: IconName; + endIcon?: IconName; text: string; - onStartIconClick?: MouseEventHandler; - onEndIconClick?: MouseEventHandler; + tooltip?: string; + className?: string; } -export default function Chip(props: Props) { - const [chipStyle, setChipStyle] = useState(""); - - useEffect(() => { - switch (props.size) { - case "small": - setChipStyle("px-2 py-1 rounded text-xs"); - break; +export default function Chip({ + size = "medium", + hideBorder = false, + variant = "primary", + ...props +}: Props) { + return ( + - {props.startIcon && ( - - )} - {props.text} - {props.endIcon && ( - + props.className )} + title={props.tooltip} + > + {props.startIcon && } + {props.text} + {props.endIcon && } ); } diff --git a/src/CAREUI/display/Count.tsx b/src/CAREUI/display/Count.tsx index ca9f60b1bf9..3b889b10e9b 100644 --- a/src/CAREUI/display/Count.tsx +++ b/src/CAREUI/display/Count.tsx @@ -1,39 +1,32 @@ -import CareIcon from "../icons/CareIcon"; +import { classNames } from "../../Utils/utils"; +import CareIcon, { IconName } from "../icons/CareIcon"; -export default function CountBlock(props: { +interface Props { count: number; text: string; loading: boolean; - icon: string; - color?: string; - containerClass?: string; -}) { - const { - count, - text, - loading, - icon, - color = "primary", - containerClass, - } = props; + icon: IconName; + className?: string; +} +export default function CountBlock(props: Props) { return ( -
-
-
- +
+
+
+
- {text} + {props.text}
- {loading ? ( + {props.loading ? (
) : (
- {count} + {props.count}
)}
diff --git a/src/CAREUI/icons/CareIcon.tsx b/src/CAREUI/icons/CareIcon.tsx index b3a6d33c895..0c70fbfe298 100644 --- a/src/CAREUI/icons/CareIcon.tsx +++ b/src/CAREUI/icons/CareIcon.tsx @@ -1,7 +1,12 @@ import { transformIcons } from "./icon"; import { useEffect } from "react"; +import iconData from "./UniconPaths.json"; + +export type IconName = keyof typeof iconData; + export interface CareIconProps { + icon?: IconName; className?: string | undefined; onClick?: React.MouseEventHandler | undefined; } @@ -14,11 +19,15 @@ export interface CareIconProps { * * @see [icon library](https://iconscout.com/unicons/) */ -export default function CareIcon({ className, onClick }: CareIconProps) { - useEffect(() => transformIcons(), [className]); +export default function CareIcon({ icon, className, onClick }: CareIconProps) { + const effectiveClassName = icon + ? `care-${icon} ${className ?? ""}` + : className; + + useEffect(() => transformIcons(), [effectiveClassName]); return ( - - + + ); } diff --git a/src/Common/constants.tsx b/src/Common/constants.tsx index b9e1b3ff8b0..e8ab4867764 100644 --- a/src/Common/constants.tsx +++ b/src/Common/constants.tsx @@ -3,6 +3,7 @@ import { PatientCategory } from "../Components/Facility/models"; import { SortOption } from "../Components/Common/SortDropdown"; import { parsePhoneNumberFromString } from "libphonenumber-js"; import { dateQueryString } from "../Utils/utils"; +import { IconName } from "../CAREUI/icons/CareIcon"; export const RESULTS_PER_PAGE_LIMIT = 14; export const PAGINATION_LIMIT = 36; @@ -828,36 +829,40 @@ export const getCameraPTZ: (precision: number) => CameraPTZ[] = (precision) => [ ]; // in future, if you find Unicon equivalents of all these icons, please replace them. Only use the same iconset throughout. -export const FACILITY_FEATURE_TYPES = [ +export const FACILITY_FEATURE_TYPES: { + id: number; + name: string; + icon: IconName; +}[] = [ { id: 1, name: "CT Scan", - icon: "compact-disc", + icon: "l-compact-disc", }, { id: 2, name: "Maternity Care", - icon: "person-breastfeeding", + icon: "l-baby-carriage", }, { id: 3, name: "X-Ray", - icon: "x-ray", + icon: "l-clipboard-alt", }, { id: 4, name: "Neonatal Care", - icon: "baby-carriage", + icon: "l-baby-carriage", }, { id: 5, name: "Operation Theater", - icon: "syringe", + icon: "l-syringe", }, { id: 6, name: "Blood Bank", - icon: "droplet", + icon: "l-medical-drip", }, ]; diff --git a/src/Components/Assets/AssetManage.tsx b/src/Components/Assets/AssetManage.tsx index 968faa2f709..e1c55fec1df 100644 --- a/src/Components/Assets/AssetManage.tsx +++ b/src/Components/Assets/AssetManage.tsx @@ -274,18 +274,22 @@ const AssetManage = (props: AssetManageProps) => {
{asset?.status === "ACTIVE" ? ( - + ) : ( )} {asset?.is_working ? ( - + ) : ( - + )}
diff --git a/src/Components/Assets/AssetsList.tsx b/src/Components/Assets/AssetsList.tsx index 6970fad22cf..143b0182ef9 100644 --- a/src/Components/Assets/AssetsList.tsx +++ b/src/Components/Assets/AssetsList.tsx @@ -285,9 +285,9 @@ const AssetsList = () => {
{asset.is_working ? ( - + ) : ( - + )}
@@ -350,7 +350,8 @@ const AssetsList = () => { text="Total Assets" count={totalCount} loading={isLoading} - icon={"monitor-heart-rate"} + icon="l-monitor-heart-rate" + className="flex-1" />
{ - const categoryClass = props.category - ? PATIENT_CATEGORIES.find((c) => c.text === props.category)?.twClass +const PatientCategoryBadge = ({ category }: { category?: PatientCategory }) => { + const categoryClass = category + ? PATIENT_CATEGORIES.find((c) => c.text === category)?.twClass : "patient-unknown"; + return ( - {props.category} + {category} ); }; diff --git a/src/Components/Common/components/ButtonV2.tsx b/src/Components/Common/components/ButtonV2.tsx index 50b93e6e263..4c09445217d 100644 --- a/src/Components/Common/components/ButtonV2.tsx +++ b/src/Components/Common/components/ButtonV2.tsx @@ -44,8 +44,6 @@ export type ButtonProps = RawButtonProps & * - `"alert"` is ideal for actions that require alert. */ variant?: ButtonVariant; - /** Specify text alignment. Defaults to `center` */ - align?: "start" | "center" | "end" | "between" | "around" | "evenly"; /** If set, gives an elevated button with hover effects. */ shadow?: boolean | undefined; /** If set, removes the background to give a simple text button. */ @@ -89,7 +87,6 @@ const ButtonV2 = ({ authorizeFor, size = "default", variant = "primary", - align = "center", circle, shadow, ghost, @@ -105,9 +102,8 @@ const ButtonV2 = ({ }: ButtonProps) => { const className = classNames( props.className, - "inline-flex h-min cursor-pointer items-center gap-2 whitespace-pre font-medium outline-offset-1 transition-all duration-200 ease-in-out disabled:cursor-not-allowed disabled:bg-gray-200 disabled:text-gray-500", + "inline-flex h-min cursor-pointer items-center justify-center gap-2 whitespace-pre font-medium outline-offset-1 transition-all duration-200 ease-in-out disabled:cursor-not-allowed disabled:bg-gray-200 disabled:text-gray-500", `button-size-${size}`, - `justify-${align}`, `button-shape-${circle ? "circle" : "square"}`, ghost ? `button-${variant}-ghost` : `button-${variant}-default`, border && `button-${variant}-border`, diff --git a/src/Components/Common/components/Menu.tsx b/src/Components/Common/components/Menu.tsx index 0bc9fe4a678..c5dd33706d8 100644 --- a/src/Components/Common/components/Menu.tsx +++ b/src/Components/Common/components/Menu.tsx @@ -79,7 +79,21 @@ export function DropdownItem({ className )} > - {icon} + + {icon} + {children}
diff --git a/src/Components/ExternalResult/ResultList.tsx b/src/Components/ExternalResult/ResultList.tsx index b2d3c566e08..0af07e2ccb9 100644 --- a/src/Components/ExternalResult/ResultList.tsx +++ b/src/Components/ExternalResult/ResultList.tsx @@ -289,7 +289,8 @@ export default function ResultList() { text="Total Results" count={totalCount} loading={isLoading} - icon={"clipboard-notes"} + icon="l-clipboard-notes" + className="flex-1" />
{ (choice) => choice.id === symptom )?.text ?? "Err. Unknown" } - color={"primary"} - size={"small"} + size="small" /> ) )} @@ -782,8 +781,7 @@ export const ConsultationDetails = (props: any) => { (choice) => choice.id === symptom )?.text ?? "Err. Unknown" } - color={"primary"} - size={"small"} + size="small" /> ) )} diff --git a/src/Components/Facility/FacilityCard.tsx b/src/Components/Facility/FacilityCard.tsx index 8de4163cefc..e66fc4f3cc2 100644 --- a/src/Components/Facility/FacilityCard.tsx +++ b/src/Components/Facility/FacilityCard.tsx @@ -13,6 +13,7 @@ import { parsePhoneNumber } from "libphonenumber-js"; import DialogModal from "../Common/Dialog"; import TextAreaFormField from "../Form/FormFields/TextAreaFormField"; import useConfig from "../../Common/hooks/useConfig"; +import { classNames } from "../../Utils/utils"; export const FacilityCard = (props: { facility: any; userType: any }) => { const { facility, userType } = props; @@ -106,24 +107,24 @@ export const FacilityCard = (props: { facility: any; userType: any }) => {
{facility.features?.map( - (feature: number, i: number) => + (feature: number) => FACILITY_FEATURE_TYPES.some( (f) => f.id === feature ) && ( f.id === feature )[0]?.name } - color="primary" size="small" startIcon={ FACILITY_FEATURE_TYPES.filter( @@ -168,11 +169,12 @@ export const FacilityCard = (props: { facility: any; userType: any }) => { Live Patients / Total beds {" "} 0.85 - ? "white" - : "primary-600" - } mr-2`} + ? "text-white" + : "text-primary-600" + )} />{" "}
{ (f) => f.id === feature )[0]?.name } - color="primary" startIcon={ FACILITY_FEATURE_TYPES.filter( (f) => f.id === feature diff --git a/src/Components/Facility/FacilityUsers.tsx b/src/Components/Facility/FacilityUsers.tsx index 0d33d5738d3..d083b45a46a 100644 --- a/src/Components/Facility/FacilityUsers.tsx +++ b/src/Components/Facility/FacilityUsers.tsx @@ -465,7 +465,8 @@ export default function FacilityUsers(props: any) { text="Total Users" count={totalCount} loading={isLoading} - icon={"user-injured"} + icon="l-user-injured" + className="flex-1" />
diff --git a/src/Components/Facility/HospitalList.tsx b/src/Components/Facility/HospitalList.tsx index 54a0d9ec501..ef739de43c2 100644 --- a/src/Components/Facility/HospitalList.tsx +++ b/src/Components/Facility/HospitalList.tsx @@ -250,7 +250,8 @@ export const HospitalList = () => { text="Total Facilities" count={totalCount} loading={isLoading} - icon={"hospital"} + icon="l-hospital" + className="flex-1" />
setShowCreate(true)} variant="secondary" className="mt-4 w-full bg-gray-200 text-gray-700 hover:bg-gray-300 hover:text-gray-900 focus:bg-gray-100 focus:text-gray-900" - align="start" disabled={disabled} > - - - {t(is_prn ? "add_prn_prescription" : "add_prescription_medication")} - +
+ + + {t(is_prn ? "add_prn_prescription" : "add_prescription_medication")} + +
{showCreate && ( { dayjs().isAfter(patient.review_time) && ( )} {patient.disease_status === "POSITIVE" && ( )} @@ -616,24 +616,26 @@ export const PatientManager = () => { patient.is_active && ( )} {patient.is_medical_worker && patient.is_active && ( )} {patient.disease_status === "EXPIRED" && ( )} @@ -644,8 +646,8 @@ export const PatientManager = () => { @@ -667,8 +669,8 @@ export const PatientManager = () => { @@ -851,13 +853,13 @@ export const PatientManager = () => {
-
+
diff --git a/src/Components/Patient/PatientCategorySelect.tsx b/src/Components/Patient/PatientCategorySelect.tsx index ee8cdbbc7c3..9ecb2381121 100644 --- a/src/Components/Patient/PatientCategorySelect.tsx +++ b/src/Components/Patient/PatientCategorySelect.tsx @@ -1,4 +1,5 @@ import { PatientCategoryID, PATIENT_CATEGORIES } from "../../Common/constants"; +import { classNames } from "../../Utils/utils"; import { SelectFormField } from "../Form/FormFields/SelectFormField"; import { FormFieldBaseProps } from "../Form/FormFields/Utils"; @@ -18,7 +19,17 @@ export default function PatientCategorySelect( optionLabel={(option) => option.text} optionSelectedLabel={(option) => ( -
+

{option.text}

)} diff --git a/src/Components/Patient/PatientHome.tsx b/src/Components/Patient/PatientHome.tsx index c5f0983e1b8..818e2413dda 100644 --- a/src/Components/Patient/PatientHome.tsx +++ b/src/Components/Patient/PatientHome.tsx @@ -478,64 +478,62 @@ export const PatientHome = (props: any) => {
{patientData.is_vaccinated ? ( ) : ( )} {patientData.allow_transfer ? ( ) : ( - + )} {patientData.gender === 2 && patientData.is_antenatal && patientData.is_active && ( )} {patientData.contact_with_confirmed_carrier && ( )} {patientData.contact_with_suspected_carrier && ( )} {patientData.past_travel && ( )} {patientData.last_consultation?.is_telemedicine && ( )} @@ -1319,7 +1317,6 @@ export const PatientHome = (props: any) => {
{ ) } > - - Add Consultation + + + Add Consultation +
navigate(`/patient/${id}/investigation_reports`) } > - - Investigations Summary + + + Investigations Summary +
navigate( `/facility/${patientData?.facility}/patient/${id}/files` ) } > - - View/Upload Patient Files + + + View/Upload Patient Files +
navigate( @@ -1375,14 +1375,15 @@ export const PatientHome = (props: any) => { } authorizeFor={NonReadOnlyUsers} > - - SHIFT PATIENT + + + Shift Patient +
navigate( @@ -1391,34 +1392,38 @@ export const PatientHome = (props: any) => { } authorizeFor={NonReadOnlyUsers} > - - Request Sample Test + + + Request Sample Test +
navigate( `/facility/${patientData?.facility}/patient/${id}/notes` ) } > - - View Patient Notes + + + View Patient Notes +
setOpenAssignVolunteerDialog(true)} disabled={false} authorizeFor={NonReadOnlyUsers} > - - Assign to a volunteer + + + Assign to a volunteer +
diff --git a/src/Components/Patient/PatientInfoCard.tsx b/src/Components/Patient/PatientInfoCard.tsx index 0243bc7aa84..fd27e7ec5f9 100644 --- a/src/Components/Patient/PatientInfoCard.tsx +++ b/src/Components/Patient/PatientInfoCard.tsx @@ -354,11 +354,12 @@ export default function PatientInfoCard(props: { setOpen(true); } }} - align="start" className="w-full" > - -

{action[1]}

+ + +

{action[1]}

+
{action[4] && action[4][0] && ( <> @@ -375,19 +376,21 @@ export default function PatientInfoCard(props: { <> setShowABHAProfile(true)} > - -

Show ABHA Profile

+ + +

Show ABHA Profile

+
setShowLinkCareContext(true)} > - -

Link Care Context

+ + +

Link Care Context

+
setShowLinkABHANumber(true)} > - -

Link ABHA Number

+ + +

Link ABHA Number

+
diff --git a/src/Components/Users/ManageUsers.tsx b/src/Components/Users/ManageUsers.tsx index 9f75b77d98d..b920c6ed8b4 100644 --- a/src/Components/Users/ManageUsers.tsx +++ b/src/Components/Users/ManageUsers.tsx @@ -535,7 +535,8 @@ export default function ManageUsers() { text="Total Users" count={totalCount} loading={isLoading} - icon={"user-injured"} + icon="l-user-injured" + className="flex-1" />
diff --git a/tailwind.config.js b/tailwind.config.js index 86fbaa74128..0e7927a474a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -87,12 +87,6 @@ module.exports = { aspectRatio: false, }, content: ["./src/**/*.{html,md,js,jsx,ts,tsx,res}", "./index.html"], - safelist: [ - { - pattern: /^(bg-[^/]+|text-[^/]+|border-.+)$/, - variants: ["hover"], - }, - ], plugins: [ require("@tailwindcss/forms"), require("@tailwindcss/typography"), From 193876b03e0f90add20395441010b986d6542155 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 9 Aug 2023 15:07:09 +0000 Subject: [PATCH 003/121] remove unused packages screenfull, html2canvas (#6037) --- package-lock.json | 57 ----------------------------------------------- package.json | 2 -- 2 files changed, 59 deletions(-) diff --git a/package-lock.json b/package-lock.json index ae2f2e6fca7..4c8a175325b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,6 @@ "echarts": "^5.4.2", "echarts-for-react": "^3.0.2", "events": "^3.3.0", - "html2canvas": "^1.4.1", "i18next": "^23.2.7", "i18next-browser-languagedetector": "^7.1.0", "libphonenumber-js": "^1.10.37", @@ -60,7 +59,6 @@ "redux-thunk": "^2.4.2", "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", - "screenfull": "^6.0.2", "use-keyboard-shortcut": "^1.1.6", "uuid": "^9.0.0" }, @@ -6777,14 +6775,6 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, - "node_modules/base64-arraybuffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", - "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -7812,14 +7802,6 @@ "node": ">=8" } }, - "node_modules/css-line-break": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", - "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", - "dependencies": { - "utrie": "^1.0.2" - } - }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -10800,18 +10782,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/html2canvas": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", - "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", - "dependencies": { - "css-line-break": "^2.1.0", - "text-segmentation": "^1.0.3" - }, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -19241,17 +19211,6 @@ "loose-envify": "^1.1.0" } }, - "node_modules/screenfull": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-6.0.2.tgz", - "integrity": "sha512-AQdy8s4WhNvUZ6P8F6PB21tSPIYKniic+Ogx0AacBMjKP1GUHN2E9URxQHtCusiwxudnCKkdy4GrHXPPJSkCCw==", - "engines": { - "node": "^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/sdp": { "version": "2.12.0", "resolved": "https://registry.npmjs.org/sdp/-/sdp-2.12.0.tgz", @@ -20284,14 +20243,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/text-segmentation": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", - "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", - "dependencies": { - "utrie": "^1.0.2" - } - }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -21057,14 +21008,6 @@ "node": ">= 0.4.0" } }, - "node_modules/utrie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", - "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", - "dependencies": { - "base64-arraybuffer": "^1.0.2" - } - }, "node_modules/uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", diff --git a/package.json b/package.json index dfb82ac453b..5ed69c4c8f7 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,6 @@ "echarts": "^5.4.2", "echarts-for-react": "^3.0.2", "events": "^3.3.0", - "html2canvas": "^1.4.1", "i18next": "^23.2.7", "i18next-browser-languagedetector": "^7.1.0", "libphonenumber-js": "^1.10.37", @@ -100,7 +99,6 @@ "redux-thunk": "^2.4.2", "rehype-raw": "^6.1.1", "rescript-webapi": "^0.8.0", - "screenfull": "^6.0.2", "use-keyboard-shortcut": "^1.1.6", "uuid": "^9.0.0" }, From 23403371508ec784af1eec333a60fae02edd97d7 Mon Sep 17 00:00:00 2001 From: Vaibhav Sachdeva <72242181+sachdevavaibhav@users.noreply.github.com> Date: Thu, 10 Aug 2023 20:47:46 +0530 Subject: [PATCH 004/121] added referred to facility field in discharge form (#5730) * added referred to facility field in discharge form * replaced AutoComplete component with FacilitySelect * Show referred Facility in Discharge Information * move referred facility * added check if facility exists * after submit * set referred_to to id * Send one of referred_to_external or referred_to * replaced moment with dayjs and removed package-lock difference --------- Co-authored-by: Mohammed Nihal <57055998+nihal467@users.noreply.github.com> Co-authored-by: Ashesh3 <3626859+Ashesh3@users.noreply.github.com> --- .../Facility/ConsultationDetails.tsx | 10 +++++ src/Components/Facility/DischargeModal.tsx | 45 +++++++++++++++++++ src/Components/Facility/models.tsx | 2 + 3 files changed, 57 insertions(+) diff --git a/src/Components/Facility/ConsultationDetails.tsx b/src/Components/Facility/ConsultationDetails.tsx index c32d02a7def..1c4bbafe3c0 100644 --- a/src/Components/Facility/ConsultationDetails.tsx +++ b/src/Components/Facility/ConsultationDetails.tsx @@ -629,6 +629,16 @@ export const ConsultationDetails = (props: any) => { )?.text ?? "--"}
+ {consultationData.discharge_reason === "REF" && ( +
+ Referred Facility {" - "} + + {consultationData.referred_to_external || + consultationData.referred_to_object?.name || + "--"} + +
+ )} {consultationData.discharge_reason === "REC" && (
diff --git a/src/Components/Facility/DischargeModal.tsx b/src/Components/Facility/DischargeModal.tsx index 03efd553162..5e13b038bab 100644 --- a/src/Components/Facility/DischargeModal.tsx +++ b/src/Components/Facility/DischargeModal.tsx @@ -23,6 +23,8 @@ import { useDispatch } from "react-redux"; import { useMessageListener } from "../../Common/hooks/useMessageListener"; import PrescriptionBuilder from "../Medicine/PrescriptionBuilder"; import CircularProgress from "../Common/components/CircularProgress"; +import { FacilitySelect } from "../Common/FacilitySelect"; +import { FacilityModel } from "./models"; import dayjs from "../../Utils/dayjs"; interface PreDischargeFormInterface { @@ -31,6 +33,8 @@ interface PreDischargeFormInterface { discharge_date?: string; death_datetime?: string; death_confirmed_doctor?: string; + referred_to?: number | null | undefined; + referred_to_external?: string | null | undefined; } interface IProps { @@ -66,10 +70,12 @@ const DischargeModal = ({ discharge_date, death_datetime, death_confirmed_doctor: undefined, + referred_to_external: null, }); const [latestClaim, setLatestClaim] = useState(); const [isCreateClaimLoading, setIsCreateClaimLoading] = useState(false); const [isSendingDischargeApi, setIsSendingDischargeApi] = useState(false); + const [facility, setFacility] = useState({ id: 0, name: "" }); // for referred to external const [errors, setErrors] = useState({}); const fetchLatestClaim = useCallback(async () => { @@ -130,6 +136,18 @@ const DischargeModal = ({ return; } + const dischargeDetails = { + ...preDischargeForm, + discharge: value, + discharge_date: dayjs(preDischargeForm.discharge_date).toISOString(), + }; + + if (dischargeDetails.referred_to != undefined) + delete dischargeDetails.referred_to_external; + + if (dischargeDetails.referred_to_external != undefined) + delete dischargeDetails.referred_to; + const dischargeResponse = await dispatch( dischargePatient( { @@ -167,6 +185,16 @@ const DischargeModal = ({ const prescriptionActions = PrescriptionActions(consultationData.id ?? ""); + const handleFacilitySelect = (selected: FacilityModel) => { + setFacility(selected ? selected : facility); + const { id, name } = selected; + const isExternal = id === -1; + setPreDischargeForm((prev) => ({ + ...prev, + ...(isExternal ? { referred_to_external: name } : { referred_to: id }), + })); + }; + return ( + {preDischargeForm.discharge_reason === "REF" && ( + <> + Referred to + + handleFacilitySelect(selected as FacilityModel) + } + selected={facility} + showAll={true} + freeText={true} + multiple={false} + errors={errors?.referred_to} + className="mb-4" + /> + + )} Date: Fri, 11 Aug 2023 06:19:45 +0000 Subject: [PATCH 005/121] Adds utility CSS class `cui-form-button-group`; Fix button responsiveness in Doctor and Bed capacity forms (#6046) * adds utitlity css class `cui-form-button-group` * fix typo --- src/Components/Facility/BedCapacity.tsx | 35 ++++++++++------------ src/Components/Facility/DoctorCapacity.tsx | 34 +++++++-------------- src/style/CAREUI.css | 4 +++ 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/Components/Facility/BedCapacity.tsx b/src/Components/Facility/BedCapacity.tsx index 9d725c36591..dba563e5876 100644 --- a/src/Components/Facility/BedCapacity.tsx +++ b/src/Components/Facility/BedCapacity.tsx @@ -281,26 +281,21 @@ export const BedCapacity = (props: BedCapacityProps) => { max={state.form.totalCapacity} />
-
-
-
- -
-
- {!isLastOptionType && headerText === "Add Bed Capacity" && ( - handleSubmit(e, "Save and Exit")} - label="Save Bed Capacity" - /> - )} - handleSubmit(e)} - label={buttonText} - /> -
-
+ +
+ + {!isLastOptionType && headerText === "Add Bed Capacity" && ( + handleSubmit(e, "Save and Exit")} + label="Save Bed Capacity" + /> + )} + handleSubmit(e)} + label={buttonText} + />
)} diff --git a/src/Components/Facility/DoctorCapacity.tsx b/src/Components/Facility/DoctorCapacity.tsx index 78810dd0cb5..6c7baafaad8 100644 --- a/src/Components/Facility/DoctorCapacity.tsx +++ b/src/Components/Facility/DoctorCapacity.tsx @@ -249,30 +249,16 @@ export const DoctorCapacity = (props: DoctorCapacityProps) => { min={0} />
-
-
-
- handleClose()} /> -
-
- {!isLastOptionType && headerText === "Add Doctor Capacity" && ( - - Save Doctor Capacity - - )} - - {buttonText} - -
-
+
+ handleClose()} /> + {!isLastOptionType && headerText === "Add Doctor Capacity" && ( + + Save Doctor Capacity + + )} + + {buttonText} +
)} diff --git a/src/style/CAREUI.css b/src/style/CAREUI.css index b6387217b03..404fcc3c4da 100644 --- a/src/style/CAREUI.css +++ b/src/style/CAREUI.css @@ -164,3 +164,7 @@ button.button-warning-ghost { @apply enabled:hover:bg-warning-100 } button.button-alert-default { @apply enabled:hover:bg-alert-500 } button.button-alert-ghost { @apply enabled:hover:bg-alert-100 } + +.cui-form-button-group { + @apply flex flex-col-reverse md:flex-row md:justify-end gap-2 w-full md:w-auto +} \ No newline at end of file From 140a36447b0214aea2f3233f690d917de2978e87 Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Fri, 11 Aug 2023 11:52:22 +0530 Subject: [PATCH 006/121] Fix display of localized dates (#6048) --- .../Facility/Consultations/PrimaryParametersPlot.tsx | 4 ++-- .../Consultations/components/BinaryChronologicalChart.tsx | 4 ++-- src/Components/Patient/DailyRoundListDetails.tsx | 4 ++-- src/Components/Patient/PatientInfoCard.tsx | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Components/Facility/Consultations/PrimaryParametersPlot.tsx b/src/Components/Facility/Consultations/PrimaryParametersPlot.tsx index 4bcc1e06db7..7653a9d935d 100644 --- a/src/Components/Facility/Consultations/PrimaryParametersPlot.tsx +++ b/src/Components/Facility/Consultations/PrimaryParametersPlot.tsx @@ -125,7 +125,7 @@ export const PrimaryParametersPlot = ({ const rhythmValues: any = {}; Object.entries(results).forEach((obj: any) => { if (obj[1].rhythm && obj[1].rhythm > 0) { - const key: string = dayjs(obj[0]).format("LL"); + const key: string = dayjs(obj[0]).format("MMMM D, YYYY"); const lst: Array = Object.prototype.hasOwnProperty.call( rhythmValues, key @@ -133,7 +133,7 @@ export const PrimaryParametersPlot = ({ ? rhythmValues[key] : []; const value: any = {}; - value["time"] = dayjs(obj[0]).format("LT"); + value["time"] = dayjs(obj[0]).format("h:mm A"); value["rhythm"] = obj[1].rhythm; value["rhythm_detail"] = obj[1].rhythm_detail; lst.push(value); diff --git a/src/Components/Facility/Consultations/components/BinaryChronologicalChart.tsx b/src/Components/Facility/Consultations/components/BinaryChronologicalChart.tsx index d2d736c363d..e7b98b57b1e 100644 --- a/src/Components/Facility/Consultations/components/BinaryChronologicalChart.tsx +++ b/src/Components/Facility/Consultations/components/BinaryChronologicalChart.tsx @@ -1,5 +1,5 @@ -import dayjs from "../../../../Utils/dayjs"; import CareIcon from "../../../../CAREUI/icons/CareIcon"; +import { formatDateTime } from "../../../../Utils/utils"; export default function BinaryChronologicalChart(props: { data: { @@ -53,7 +53,7 @@ export default function BinaryChronologicalChart(props: {

-

{dayjs(entry.timestamp).format("lll")}

+

{formatDateTime(entry.timestamp)}

diff --git a/src/Components/Patient/DailyRoundListDetails.tsx b/src/Components/Patient/DailyRoundListDetails.tsx index 46cca38bcaf..7d4abaf67e2 100644 --- a/src/Components/Patient/DailyRoundListDetails.tsx +++ b/src/Components/Patient/DailyRoundListDetails.tsx @@ -7,7 +7,7 @@ import { getConsultationDailyRoundsDetails } from "../../Redux/actions"; import { DailyRoundsModel } from "./models"; import Page from "../Common/components/Page"; import ButtonV2 from "../Common/components/ButtonV2"; -import dayjs from "../../Utils/dayjs"; +import { formatDateTime } from "../../Utils/utils"; const Loading = loadable(() => import("../Common/Loading")); const symptomChoices = [...SYMPTOM_CHOICES]; const currentHealthChoices = [...CURRENT_HEALTH_CHANGE]; @@ -107,7 +107,7 @@ export const DailyRoundListDetails = (props: any) => {
Taken at: {dailyRoundListDetailsData.taken_at - ? dayjs(dailyRoundListDetailsData.taken_at).format("lll") + ? formatDateTime(dailyRoundListDetailsData.taken_at) : "-"}
diff --git a/src/Components/Patient/PatientInfoCard.tsx b/src/Components/Patient/PatientInfoCard.tsx index fd27e7ec5f9..518ec1fb517 100644 --- a/src/Components/Patient/PatientInfoCard.tsx +++ b/src/Components/Patient/PatientInfoCard.tsx @@ -20,7 +20,7 @@ import { PatientModel } from "./models"; import { getDimensionOrDash } from "../../Common/utils"; import useConfig from "../../Common/hooks/useConfig"; import { useState } from "react"; -import { formatDate } from "../../Utils/utils.js"; +import { formatDate, formatDateTime } from "../../Utils/utils.js"; import dayjs from "../../Utils/dayjs"; export default function PatientInfoCard(props: { @@ -141,7 +141,7 @@ export default function PatientInfoCard(props: { {(dayjs().isBefore(patient.review_time) ? "Review before: " : "Review Missed: ") + - dayjs(patient.review_time).format("lll")} + formatDateTime(patient.review_time)}
)}
From d870d2f64471ba0df0ffef54ce42bde169d9e07e Mon Sep 17 00:00:00 2001 From: Ashesh <3626859+Ashesh3@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:18:53 +0530 Subject: [PATCH 007/121] Fix camera controls overlap with notifications (#6057) --- src/Components/Facility/Consultations/Feed.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Components/Facility/Consultations/Feed.tsx b/src/Components/Facility/Consultations/Feed.tsx index f9800eda746..af118bc6289 100644 --- a/src/Components/Facility/Consultations/Feed.tsx +++ b/src/Components/Facility/Consultations/Feed.tsx @@ -504,7 +504,7 @@ export const Feed: React.FC = ({
)}
-
+
{["fullScreen", "reset", "updatePreset", "zoomIn", "zoomOut"].map( (button, index) => { const option = cameraPTZ.find( @@ -524,7 +524,7 @@ export const Feed: React.FC = ({
-
+
Date: Fri, 11 Aug 2023 18:22:52 +0530 Subject: [PATCH 008/121] Increase default limit for doctor connect list (#6065) --- src/Components/Facility/DoctorVideoSlideover.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Components/Facility/DoctorVideoSlideover.tsx b/src/Components/Facility/DoctorVideoSlideover.tsx index fbedb15981f..59c443cb64e 100644 --- a/src/Components/Facility/DoctorVideoSlideover.tsx +++ b/src/Components/Facility/DoctorVideoSlideover.tsx @@ -19,7 +19,9 @@ export default function DoctorVideoSlideover(props: { useEffect(() => { const fetchUsers = async () => { if (facilityId) { - const res = await dispatchAction(getFacilityUsers(facilityId)); + const res = await dispatchAction( + getFacilityUsers(facilityId, { limit: 50 }) + ); if (res && res.data) { setDoctors( res.data.results @@ -72,7 +74,7 @@ export default function DoctorVideoSlideover(props: {
    From 00955cafe6518e8faf2c02c2b7535646474c43dc Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Fri, 11 Aug 2023 12:53:23 +0000 Subject: [PATCH 009/121] fixes #6062; align tooltip of `RecordMeta` relative time (#6063) --- src/CAREUI/display/RecordMeta.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CAREUI/display/RecordMeta.tsx b/src/CAREUI/display/RecordMeta.tsx index a6a04cf5305..f401f0ada86 100644 --- a/src/CAREUI/display/RecordMeta.tsx +++ b/src/CAREUI/display/RecordMeta.tsx @@ -22,7 +22,7 @@ const RecordMeta = ({ time, user, prefix, className }: Props) => { let child = (
    {relativeTime(time)} - + {formatDateTime(time)} {user && ( <> From 18b1c3aa397fce1708541d55cc1abc166333eef6 Mon Sep 17 00:00:00 2001 From: Rithvik Nishad Date: Wed, 16 Aug 2023 08:02:41 +0000 Subject: [PATCH 010/121] Plausible: Redact IDs in goal urls and removed patient id from goal trigger props (#6076) * Plausible: Redact IDs from URL in triggerGoal * remove `patientId` from plausible goals * remove eslint warnings * add manual extension * Add caution comments --- src/Components/Common/Plausible.tsx | 64 +++++++++++++------ .../Facility/ConsultationDetails.tsx | 8 +-- .../Facility/Consultations/Feed.tsx | 10 +-- src/Components/Patient/PatientHome.tsx | 1 - .../VitalsMonitor/HL7PatientVitalsMonitor.tsx | 1 - 5 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/Components/Common/Plausible.tsx b/src/Components/Common/Plausible.tsx index b1c5d433240..77589e0f923 100644 --- a/src/Components/Common/Plausible.tsx +++ b/src/Components/Common/Plausible.tsx @@ -6,23 +6,29 @@ import { useEffect } from "react"; export default function Plausible() { const { site_url, analytics_server_url } = useConfig(); - useLocationChange(() => triggerPageView()); - useEffect(() => triggerPageView(), []); + useLocationChange(() => { + plausible("pageview"); + }); + + useEffect(() => { + plausible("pageview"); + }, []); return (