mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Show All and Solo selection buttons for MultiSelect. (#4723)
* Show All and Solo selection buttons for MultiSelect. Similar to previous behavior of viewing events for single camera with 1 click, or All. * Fix visual bug with MultiSelect when selecting similar named options. eg. options like frontdoor, frontside, backdoor, etc * fix key prop for lint * Change MultiSelect onSolo to onSelectSingle * cosmetic changes on MultiSelect * Different look for SelectSingle buttons * Show All button is aligned with the items below it, no matter the popup size * MultiSelect ShowAll unfocused by default
This commit is contained in:
parent
369299315f
commit
c6f0abf732
@ -3,15 +3,19 @@ import { useRef, useState } from 'preact/hooks';
|
||||
import Menu from './Menu';
|
||||
import { ArrowDropdown } from '../icons/ArrowDropdown';
|
||||
import Heading from './Heading';
|
||||
import Button from './Button';
|
||||
import CameraIcon from '../icons/Camera';
|
||||
|
||||
export default function MultiSelect({ className, title, options, selection, onToggle }) {
|
||||
export default function MultiSelect({ className, title, options, selection, onToggle, onShowAll, onSelectSingle }) {
|
||||
|
||||
const popupRef = useRef(null);
|
||||
|
||||
const [state, setState] = useState({
|
||||
showMenu: false,
|
||||
});
|
||||
|
||||
|
||||
const isOptionSelected = (item) => { return selection == "all" || selection.split(',').indexOf(item) > -1; }
|
||||
|
||||
return (
|
||||
<div className={`${className} p-2`} ref={popupRef}>
|
||||
<div
|
||||
@ -23,21 +27,32 @@ export default function MultiSelect({ className, title, options, selection, onTo
|
||||
</div>
|
||||
{state.showMenu ? (
|
||||
<Menu relativeTo={popupRef} onDismiss={() => setState({ showMenu: false })}>
|
||||
<Heading className="p-4 justify-center" size="md">{title}</Heading>
|
||||
<div className="flex flex-wrap justify-between items-center">
|
||||
<Heading className="p-4 justify-center" size="md">{title}</Heading>
|
||||
<Button tabindex="false" className="mx-4" onClick={() => onShowAll() }>
|
||||
Show All
|
||||
</Button>
|
||||
</div>
|
||||
{options.map((item) => (
|
||||
<label
|
||||
className={`flex flex-shrink space-x-2 p-1 my-1 min-w-[176px] hover:bg-gray-200 dark:hover:bg-gray-800 dark:hover:text-white cursor-pointer capitalize text-sm`}
|
||||
key={item}>
|
||||
<input
|
||||
className="mx-4 m-0 align-middle"
|
||||
type="checkbox"
|
||||
checked={selection == "all" || selection.indexOf(item) > -1}
|
||||
onChange={() => onToggle(item)} />
|
||||
{item.replaceAll("_", " ")}
|
||||
</label>
|
||||
<div className="flex flex-grow" key={item}>
|
||||
<label
|
||||
className={`flex flex-shrink space-x-2 p-1 my-1 min-w-[176px] hover:bg-gray-200 dark:hover:bg-gray-800 dark:hover:text-white cursor-pointer capitalize text-sm`}>
|
||||
<input
|
||||
className="mx-4 m-0 align-middle"
|
||||
type="checkbox"
|
||||
checked={isOptionSelected(item)}
|
||||
onChange={() => onToggle(item)} />
|
||||
{item.replaceAll("_", " ")}
|
||||
</label>
|
||||
<div className="justify-right">
|
||||
<Button color={isOptionSelected(item) ? "blue" : "black"} type="text" className="max-h-[35px] mx-2" onClick={() => onSelectSingle(item)}>
|
||||
<CameraIcon />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</Menu>
|
||||
): null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -301,6 +301,8 @@ export default function Events({ path, ...props }) {
|
||||
options={filterValues.cameras}
|
||||
selection={searchParams.cameras}
|
||||
onToggle={(item) => onToggleNamedFilter("cameras", item)}
|
||||
onShowAll={() => onFilter("cameras", ["all"])}
|
||||
onSelectSingle={(item) => onFilter("cameras", item)}
|
||||
/>
|
||||
<MultiSelect
|
||||
className="basis-1/5 cursor-pointer rounded dark:bg-slate-800"
|
||||
@ -308,6 +310,8 @@ export default function Events({ path, ...props }) {
|
||||
options={filterValues.labels}
|
||||
selection={searchParams.labels}
|
||||
onToggle={(item) => onToggleNamedFilter("labels", item) }
|
||||
onShowAll={() => onFilter("labels", ["all"])}
|
||||
onSelectSingle={(item) => onFilter("labels", item)}
|
||||
/>
|
||||
<MultiSelect
|
||||
className="basis-1/5 cursor-pointer rounded dark:bg-slate-800"
|
||||
@ -315,6 +319,8 @@ export default function Events({ path, ...props }) {
|
||||
options={filterValues.zones}
|
||||
selection={searchParams.zones}
|
||||
onToggle={(item) => onToggleNamedFilter("zones", item) }
|
||||
onShowAll={() => onFilter("zones", ["all"])}
|
||||
onSelectSingle={(item) => onFilter("zones", item)}
|
||||
/>
|
||||
{
|
||||
filterValues.sub_labels.length > 0 && (
|
||||
@ -324,6 +330,8 @@ export default function Events({ path, ...props }) {
|
||||
options={filterValues.sub_labels}
|
||||
selection={searchParams.sub_labels}
|
||||
onToggle={(item) => onToggleNamedFilter("sub_labels", item) }
|
||||
onShowAll={() => onFilter("sub_labels", ["all"])}
|
||||
onSelectSingle={(item) => onFilter("sub_labels", item)}
|
||||
/>
|
||||
)}
|
||||
<div ref={datePicker} className="ml-auto">
|
||||
|
Loading…
Reference in New Issue
Block a user