-
Notifications
You must be signed in to change notification settings - Fork 477
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Enhancements to Location Live Feed (#6726)
* Page: support for auto collapse sidebar * Adds utilities and `useOperateCamera` hook * Adds reusable component: `NetworkSignal` * stash * Update camera controls * rename files * refactor * refactor location filter * Add location select popup * Update location select logic * update reponsiveness * hide non working filters * adjust z-index
- Loading branch information
1 parent
a6ed2bc
commit 745d4f8
Showing
34 changed files
with
1,394 additions
and
1,366 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { classNames } from "../../Utils/utils"; | ||
import CareIcon from "../icons/CareIcon"; | ||
|
||
interface Props { | ||
/** | ||
* Strength of the signal, from 0 to 3 | ||
* | ||
* undefined: Error | ||
* 0: No signal | ||
* 1: Weak signal | ||
* 2: Medium signal | ||
* 3: Strong signal | ||
*/ | ||
strength?: number; | ||
children?: React.ReactNode; | ||
} | ||
|
||
export default function NetworkSignal({ strength, children }: Props) { | ||
return ( | ||
<div | ||
className={classNames( | ||
"flex items-center", // Strength colors | ||
strength === 0 && "text-danger-500", | ||
strength === 1 && "text-danger-500", | ||
strength === 2 && "text-warning-500", | ||
strength === 3 && "text-primary-500" | ||
)} | ||
> | ||
<div className="flex items-end gap-0.5 p-2"> | ||
{strength === undefined ? ( | ||
<CareIcon | ||
icon="l-exclamation-triangle" | ||
className="text-lg text-danger-500" | ||
/> | ||
) : ( | ||
Array.from({ length: 3 }, (_, i) => ( | ||
<div | ||
key={i} | ||
className={classNames( | ||
"w-1 rounded-sm", | ||
|
||
// Heights | ||
i === 0 && "h-[5px]", | ||
i === 1 && "h-[10px]", | ||
i === 2 && "h-[15px]", | ||
|
||
// Whether to infill with strength color or not | ||
strength > i ? "bg-current" : "bg-zinc-600" | ||
)} | ||
/> | ||
)) | ||
)} | ||
</div> | ||
{children} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import useKeyboardShortcut from "use-keyboard-shortcut"; | ||
import { classNames, isAppleDevice } from "../../Utils/utils"; | ||
|
||
interface Props { | ||
children: React.ReactNode; | ||
shortcut: string[]; | ||
onTrigger: () => void; | ||
shortcutSeperator?: string; | ||
helpText?: string; | ||
tooltipClassName?: string; | ||
} | ||
|
||
export default function KeyboardShortcut(props: Props) { | ||
useKeyboardShortcut(props.shortcut, props.onTrigger, { | ||
overrideSystem: true, | ||
}); | ||
|
||
return ( | ||
<div className="tooltip"> | ||
{props.children} | ||
<span | ||
className={classNames( | ||
"tooltip-text flex items-center gap-0.5 text-xs", | ||
props.tooltipClassName || "tooltip-bottom" | ||
)} | ||
> | ||
<span className="px-1 font-bold">{props.helpText}</span> | ||
<kbd className="hidden items-center px-1.5 font-sans font-medium text-zinc-300 shadow md:inline-flex"> | ||
{getShortcutKeyDescription(props.shortcut).join(" + ")} | ||
</kbd> | ||
</span> | ||
</div> | ||
); | ||
} | ||
|
||
const SHORTCUT_KEY_MAP = { | ||
Meta: "⌘", | ||
Shift: "⇧Shift", | ||
Alt: "⌥Alt", | ||
Control: isAppleDevice ? "⌃Ctrl" : "Ctrl", | ||
ArrowUp: "↑", | ||
ArrowDown: "↓", | ||
ArrowLeft: "←", | ||
ArrowRight: "→", | ||
} as Record<string, string>; | ||
|
||
export const getShortcutKeyDescription = (shortcut: string[]) => { | ||
return shortcut.map((key) => SHORTCUT_KEY_MAP[key] || key); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { useEffect, useRef } from "react"; | ||
|
||
interface Props { | ||
className?: string; | ||
fullscreenClassName?: string; | ||
children: React.ReactNode; | ||
fullscreen: boolean; | ||
onExit: () => void; | ||
} | ||
|
||
export default function Fullscreen(props: Props) { | ||
const ref = useRef<HTMLDivElement>(null); | ||
|
||
useEffect(() => { | ||
if (props.fullscreen) { | ||
ref.current?.requestFullscreen(); | ||
} else { | ||
document.exitFullscreen(); | ||
} | ||
}, [props.fullscreen]); | ||
|
||
useEffect(() => { | ||
const listener = () => { | ||
if (!document.fullscreenElement) { | ||
props.onExit(); | ||
} | ||
}; | ||
|
||
document.addEventListener("fullscreenchange", listener); | ||
return () => { | ||
document.removeEventListener("fullscreenchange", listener); | ||
}; | ||
}, [props.onExit]); | ||
|
||
return ( | ||
<div | ||
ref={ref} | ||
className={props.fullscreen ? props.fullscreenClassName : props.className} | ||
> | ||
{props.children} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
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 { Listbox, Transition } from "@headlessui/react"; | ||
import CareIcon from "../../CAREUI/icons/CareIcon"; | ||
|
||
interface Props { | ||
asset?: AssetData; | ||
bed?: BedModel; | ||
value?: AssetBedModel; | ||
onChange?: (value: AssetBedModel) => void; | ||
} | ||
|
||
export default function AssetBedSelect(props: Props) { | ||
const facility = useSlug("facility"); | ||
|
||
const { data, loading } = useQuery(routes.listAssetBeds, { | ||
query: { | ||
limit: 100, | ||
facility, | ||
asset: props.asset?.id, | ||
bed: props.bed?.id, | ||
}, | ||
}); | ||
|
||
const selected = props.value; | ||
|
||
return ( | ||
<Listbox value={selected} onChange={props.onChange} disabled={loading}> | ||
<div className="relative"> | ||
<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"} | ||
</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> | ||
</Listbox.Button> | ||
<Transition | ||
as={Fragment} | ||
leave="transition ease-in duration-100" | ||
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"> | ||
{data?.results.map((obj) => ( | ||
<Listbox.Option | ||
key={obj.id} | ||
className={({ active }) => | ||
`relative cursor-default select-none px-2 py-1 ${ | ||
active ? "bg-zinc-700 text-white" : "text-zinc-400" | ||
}` | ||
} | ||
value={obj} | ||
> | ||
{({ selected }) => ( | ||
<> | ||
<span | ||
className={`block truncate text-xs md:text-sm ${ | ||
selected ? "font-bold text-white" : "font-normal" | ||
}`} | ||
> | ||
{obj.bed_object.name}: {obj.meta.preset_name} | ||
</span> | ||
</> | ||
)} | ||
</Listbox.Option> | ||
))} | ||
</Listbox.Options> | ||
</Transition> | ||
</div> | ||
</Listbox> | ||
); | ||
} |
Oops, something went wrong.