Skip to content

Commit

Permalink
Merge branch 'coronasafe:develop' into Fix-ohcnetwork#7708
Browse files Browse the repository at this point in the history
  • Loading branch information
AshrafMd-1 authored Jun 6, 2024
2 parents 519fadc + db8b1f4 commit 8fc0e2d
Show file tree
Hide file tree
Showing 33 changed files with 415 additions and 196 deletions.
2 changes: 1 addition & 1 deletion cypress/pageobject/Patient/PatientInvestigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class PatientInvestigation {
}

selectInvestigation(investigation: string) {
cy.get("#search-patient-investigation").click();
cy.get("#search-patient-investigation").type(investigation);
cy.verifyAndClickElement("#investigation-group", investigation);
cy.verifyAndClickElement("#investigation", "Investigation No. 1");
}
Expand Down
8 changes: 7 additions & 1 deletion src/CAREUI/display/NetworkSignal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default function NetworkSignal({ strength, children }: Props) {
return (
<div
className={classNames(
"flex items-center", // Strength colors
"relative flex items-center", // Strength colors
strength === 0 && "text-danger-500",
strength === 1 && "text-danger-500",
strength === 2 && "text-warning-500",
Expand Down Expand Up @@ -50,6 +50,12 @@ export default function NetworkSignal({ strength, children }: Props) {
/>
))
)}
{!!strength && strength < 2 && (
<CareIcon
icon="l-exclamation-circle"
className="absolute left-0.5 top-0 animate-pulse text-sm text-danger-500"
/>
)}
</div>
{children}
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/CAREUI/display/RecordMeta.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import CareIcon from "../icons/CareIcon";
import {
formatDate,
formatDateTime,
formatName,
formatTime,
isUserOnline,
relativeTime,
} from "../../Utils/utils";
Expand Down Expand Up @@ -39,8 +38,9 @@ const RecordMeta = ({
<div className="tooltip">
<span className="underline">{relativeTime(time)}</span>
<span className="tooltip-text tooltip-bottom flex -translate-x-1/2 gap-1 text-xs font-medium tracking-wider">
{formatTime(time)} <br />
{formatDate(time)}
<span className="whitespace-break-spaces">
{formatDateTime(time).replace(";", "")}
</span>
{user && !inlineUser && (
<span className="flex items-center gap-1">
by
Expand Down
2 changes: 1 addition & 1 deletion src/CAREUI/interactive/FiltersSlideover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const AdvancedFilterButton = ({ onClick }: { onClick: () => void }) => {
<ButtonV2
ghost
border
className="w-full bg-white sm:w-auto"
className="w-full bg-white md:w-auto"
onClick={onClick}
id="advanced-filter"
>
Expand Down
15 changes: 12 additions & 3 deletions src/CAREUI/misc/Fullscreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,25 @@ interface Props {
fullscreenClassName?: string;
children: React.ReactNode;
fullscreen: boolean;
onExit: () => void;
onExit: (reason?: "DEVICE_UNSUPPORTED") => void;
}

export default function Fullscreen(props: Props) {
const ref = useRef<HTMLDivElement>(null);

useEffect(() => {
if (!ref.current) {
return;
}

if (props.fullscreen) {
ref.current?.requestFullscreen();
if (ref.current.requestFullscreen) {
ref.current.requestFullscreen();
} else {
props.onExit("DEVICE_UNSUPPORTED");
}
} else {
document.exitFullscreen();
document.exitFullscreen?.();
}
}, [props.fullscreen]);

Expand All @@ -27,6 +35,7 @@ export default function Fullscreen(props: Props) {
};

document.addEventListener("fullscreenchange", listener);

return () => {
document.removeEventListener("fullscreenchange", listener);
};
Expand Down
4 changes: 2 additions & 2 deletions src/Common/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -363,10 +363,10 @@ export const SAMPLE_TEST_RESULT = [
export const CONSULTATION_SUGGESTION = [
{ id: "HI", text: "Home Isolation", deprecated: true }, // # Deprecated. Preserving option for backward compatibility (use only for readonly operations)
{ id: "A", text: "Admission" },
{ id: "R", text: "Refer to another Hospital" },
{ id: "R", text: "Refer to another Hospital", editDisabled: true },
{ id: "OP", text: "OP Consultation" },
{ id: "DC", text: "Domiciliary Care" },
{ id: "DD", text: "Declare Death" },
{ id: "DD", text: "Declare Death", editDisabled: true },
] as const;

export type ConsultationSuggestionValue =
Expand Down
9 changes: 8 additions & 1 deletion src/Components/Assets/configure/CameraConfigure.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getCameraConfig } from "../../../Utils/transformUtils";
import { Submit } from "../../Common/components/ButtonV2";
import TextFormField from "../../Form/FormFields/TextFormField";
import Card from "../../../CAREUI/display/Card";
import { FieldErrorText } from "../../Form/FormFields/FormField";

interface CameraConfigureProps {
asset: AssetData;
Expand Down Expand Up @@ -59,8 +60,14 @@ export default function CameraConfigure(props: CameraConfigureProps) {
value={newPreset}
className="mt-1"
onChange={(e) => setNewPreset(e.value)}
error=""
errorClassName="hidden"
/>
{newPreset.length > 12 && (
<FieldErrorText
error="It is advisable to keep preset name below 12 characters"
className="!text-warning-500"
/>
)}
</div>
</div>
<div className="mt-4 flex justify-end">
Expand Down
57 changes: 37 additions & 20 deletions src/Components/CameraFeed/AssetBedSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,56 +15,73 @@ export default function CameraPresetSelect(props: Props) {
const label = props.label ?? defaultLabel;
return (
<>
<div className="hidden gap-2 whitespace-nowrap pr-2 md:flex">
<div className="hidden gap-4 whitespace-nowrap pr-2 lg:flex lg:gap-2">
{/* Desktop View */}
{props.options
.slice(0, props.options.length > 5 ? 4 : 5)
.map((option) => (
<button
className={classNames(
"rounded-xl border px-2 py-0.5 text-xs transition-all duration-200 ease-in-out hover:bg-zinc-600",
"min-w-16 max-w-40 overflow-hidden text-ellipsis whitespace-nowrap rounded-lg border-2 px-2 py-0.5 text-base transition-all duration-200 ease-in-out hover:bg-zinc-600",
props.value?.id === option.id
? "border-white bg-zinc-100 font-bold text-black"
: "border-white/50 text-zinc-100",
: "border-zinc-700 font-medium text-zinc-300",
)}
onClick={() => props.onChange?.(option)}
>
{label(option)}
</button>
))}
{props.options.length > 5 && (
<CameraPresetDropdown {...props} options={props.options.slice(4)} />
<CameraPresetDropdown
{...props}
placeholder="More preset"
options={props.options.slice(4)}
value={props.options.slice(4).find((o) => o.id === props.value?.id)}
/>
)}
</div>
<div className="md:hidden">
<div className="w-full lg:hidden">
{/* Mobile View */}
<CameraPresetDropdown {...props} />
<CameraPresetDropdown {...props} placeholder="Select preset" />
</div>
</>
);
}

export const CameraPresetDropdown = (props: Props) => {
export const CameraPresetDropdown = (
props: Props & { placeholder: string },
) => {
const selected = props.value;

const options = props.options.filter(({ meta }) => meta.type !== "boundary");

const label = props.label ?? defaultLabel;

return (
<Listbox value={selected} onChange={props.onChange}>
<Listbox
value={selected}
onChange={props.onChange}
disabled={options.length === 0}
>
<div className="relative flex-1">
<Listbox.Button className="relative w-full cursor-default pr-6 text-left text-xs text-white focus:outline-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-zinc-700 sm:text-sm md:pl-2">
<span
className={classNames(
"block truncate",
!selected && "text-gray-500",
)}
>
{selected ? label(selected) : "Select preset"}
<Listbox.Button
className={classNames(
"relative min-w-32 max-w-40 overflow-hidden text-ellipsis whitespace-nowrap rounded-lg border-2 px-2 py-0.5 pr-8 text-left text-base transition-all duration-200 ease-in-out hover:bg-zinc-600 focus:outline-none disabled:cursor-not-allowed disabled:bg-transparent disabled:text-zinc-700",
selected
? "border-white bg-zinc-100 font-bold text-black"
: "border-zinc-700 font-medium text-zinc-300",
)}
>
<span className="block truncate">
{options.length === 0
? "No presets"
: selected
? label(selected)
: props.placeholder}
</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" />
<span className="pointer-events-none absolute inset-y-0 right-0 mr-1 mt-1 flex items-center">
<CareIcon icon="l-angle-down" className="text-xl text-zinc-400" />
</span>
</Listbox.Button>
<Transition
Expand All @@ -73,7 +90,7 @@ export const CameraPresetDropdown = (props: Props) => {
leaveFrom="opacity-100"
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">
<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 md:max-h-60">
{options?.map((obj) => (
<Listbox.Option
key={obj.id}
Expand All @@ -87,7 +104,7 @@ export const CameraPresetDropdown = (props: Props) => {
{({ selected }) => (
<>
<span
className={`block truncate text-xs md:text-sm ${
className={`block truncate text-sm md:text-base ${
selected ? "font-bold text-white" : "font-normal"
}`}
>
Expand Down
49 changes: 34 additions & 15 deletions src/Components/CameraFeed/CameraFeed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import useOperateCamera, { PTZPayload } from "./useOperateCamera";
import usePlayer from "./usePlayer";
import { getStreamUrl } from "./utils";
import ReactPlayer from "react-player";
import { classNames, isIOS } from "../../Utils/utils";
import { classNames, isAppleDevice, isIOS } from "../../Utils/utils";
import FeedAlert, { FeedAlertState } from "./FeedAlert";
import FeedNetworkSignal from "./FeedNetworkSignal";
import NoFeedAvailable from "./NoFeedAvailable";
import FeedControls from "./FeedControls";
import Fullscreen from "../../CAREUI/misc/Fullscreen";
import FeedWatermark from "./FeedWatermark";
import CareIcon from "../../CAREUI/icons/CareIcon";
import { Error } from "../../Utils/Notifications";

interface Props {
children?: React.ReactNode;
Expand All @@ -27,6 +28,7 @@ interface Props {
constrolsDisabled?: boolean;
shortcutsDisabled?: boolean;
onMove?: () => void;
onReset?: () => void;
}

export default function CameraFeed(props: Props) {
Expand Down Expand Up @@ -86,34 +88,51 @@ export default function CameraFeed(props: Props) {

const resetStream = () => {
setState("loading");
props.onReset?.();
initializeStream();
};
return (
<Fullscreen fullscreen={isFullscreen} onExit={() => setFullscreen(false)}>
<Fullscreen
fullscreen={isFullscreen}
onExit={(reason) => {
setFullscreen(false);

if (reason === "DEVICE_UNSUPPORTED") {
// iOS webkit allows only video/iframe elements to call full-screen
// APIs. But we need to show controls too, not just the video element.
Error({
msg: "This device does not support viewing this content in full-screen.",
});
}
}}
>
<div
className={classNames(
"flex max-h-screen flex-col overflow-clip rounded-xl bg-black",
"flex flex-col overflow-clip rounded-xl bg-black md:max-h-screen",
props.className,
isAppleDevice && isFullscreen && "px-20",
)}
>
<div className="flex items-center justify-between bg-zinc-900 px-4 py-0.5">
<div className="flex items-center justify-between bg-zinc-900 px-4 py-1.5 md:py-2">
{props.children}
<div className="flex w-full items-center justify-end gap-1 md:gap-4">
<span className="text-xs font-semibold text-white md:text-sm">
<span className="text-base font-semibold text-white">
<CareIcon
icon="l-video"
className="hidden pr-2 text-base text-zinc-400 md:inline-block"
className="hidden pr-2 text-lg text-zinc-400 md:inline-block"
/>
{props.asset.name}
</span>
<div className={state === "loading" ? "animate-pulse" : ""}>
<FeedNetworkSignal
playerRef={playerRef as any}
playedOn={player.playedOn}
status={player.status}
onReset={resetStream}
/>
</div>
{!isIOS && (
<div className={state === "loading" ? "animate-pulse" : ""}>
<FeedNetworkSignal
playerRef={playerRef as any}
playedOn={player.playedOn}
status={player.status}
onReset={resetStream}
/>
</div>
)}
</div>
</div>

Expand Down Expand Up @@ -170,7 +189,7 @@ export default function CameraFeed(props: Props) {
) : (
<video
onContextMenu={(e) => e.preventDefault()}
className="absolute inset-0 w-full"
className="absolute inset-x-0 mx-auto aspect-video max-h-screen w-full"
id="mse-video"
autoPlay
muted
Expand Down
1 change: 1 addition & 0 deletions src/Components/CameraFeed/CameraFeedWithBedPresets.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export default function LocationFeedTile(props: Props) {
options={data?.results ?? []}
value={preset}
onChange={setPreset}
placeholder="Select preset"
/>
)}
</div>
Expand Down
10 changes: 5 additions & 5 deletions src/Components/CameraFeed/FeedAlert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ interface Props {
state?: FeedAlertState;
}

const ALERT_ICON_MAP: Record<FeedAlertState, IconName> = {
const ALERT_ICON_MAP: Partial<Record<FeedAlertState, IconName>> = {
playing: "l-play-circle",
stop: "l-stop-circle",
offline: "l-exclamation-triangle",
loading: "l-spinner",
moving: "l-expand-from-corner",
// moving: "l-expand-from-corner",
zooming: "l-search",
saving_preset: "l-save",
host_unreachable: "l-exclamation-triangle",
Expand Down Expand Up @@ -53,14 +53,14 @@ export default function FeedAlert({ state }: Props) {
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 -translate-y-5"
>
<div className="absolute right-8 top-6 flex items-center gap-1.5 rounded bg-white/20 px-2 py-1 text-white">
{state && (
<div className="absolute right-8 top-4 z-20 flex items-center gap-1.5 rounded bg-white/20 px-2 py-1 text-white">
{state && ALERT_ICON_MAP[state] && (
<CareIcon
className={classNames(
"text-base",
state === "loading" && "animate-spin",
)}
icon={ALERT_ICON_MAP[state]}
icon={ALERT_ICON_MAP[state]!}
/>
)}
<span className="text-xs font-medium capitalize">
Expand Down
Loading

0 comments on commit 8fc0e2d

Please sign in to comment.