forked from Github/frigate
Ability to retain specific clips / events indefinitely (#2831)
This commit is contained in:
@@ -7,16 +7,21 @@ import ArrowDown from '../icons/ArrowDropdown';
|
||||
import ArrowDropup from '../icons/ArrowDropup';
|
||||
import Clip from '../icons/Clip';
|
||||
import Close from '../icons/Close';
|
||||
import StarRecording from '../icons/StarRecording';
|
||||
import Delete from '../icons/Delete';
|
||||
import Snapshot from '../icons/Snapshot';
|
||||
import Dialog from '../components/Dialog';
|
||||
import Heading from '../components/Heading';
|
||||
import VideoPlayer from '../components/VideoPlayer';
|
||||
import { Table, Thead, Tbody, Th, Tr, Td } from '../components/Table';
|
||||
import { FetchStatus, useApiHost, useEvent, useDelete } from '../api';
|
||||
import { FetchStatus, useApiHost, useEvent, useDelete, useRetain } from '../api';
|
||||
|
||||
const ActionButtonGroup = ({ className, handleClickDelete, close }) => (
|
||||
const ActionButtonGroup = ({ className, isRetained, handleClickRetain, handleClickDelete, close }) => (
|
||||
<div className={`space-y-2 space-x-2 sm:space-y-0 xs:space-x-4 ${className}`}>
|
||||
<Button className="xs:w-auto" color={isRetained ? 'red' : 'yellow'} onClick={handleClickRetain}>
|
||||
<StarRecording className="w-6" />
|
||||
{isRetained ? ('Un-retain event') : ('Retain event')}
|
||||
</Button>
|
||||
<Button className="xs:w-auto" color="red" onClick={handleClickDelete}>
|
||||
<Delete className="w-6" /> Delete event
|
||||
</Button>
|
||||
@@ -54,6 +59,8 @@ export default function Event({ eventId, close, scrollRef }) {
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
const [shouldScroll, setShouldScroll] = useState(true);
|
||||
const [deleteStatus, setDeleteStatus] = useState(FetchStatus.NONE);
|
||||
const [isRetained, setIsRetained] = useState(false);
|
||||
const setRetainEvent = useRetain();
|
||||
const setDeleteEvent = useDelete();
|
||||
|
||||
useEffect(() => {
|
||||
@@ -71,6 +78,22 @@ export default function Event({ eventId, close, scrollRef }) {
|
||||
};
|
||||
}, [data, scrollRef, eventId, shouldScroll]);
|
||||
|
||||
const handleClickRetain = useCallback(async () => {
|
||||
let success;
|
||||
try {
|
||||
success = await setRetainEvent(eventId, !isRetained);
|
||||
|
||||
if (success) {
|
||||
setIsRetained(!isRetained);
|
||||
|
||||
// Need to reload page otherwise retain button state won't stick if event is collapsed and re-opened.
|
||||
window.location.reload();
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}, [eventId, isRetained, setRetainEvent]);
|
||||
|
||||
const handleClickDelete = () => {
|
||||
setShowDialog(true);
|
||||
};
|
||||
@@ -98,6 +121,7 @@ export default function Event({ eventId, close, scrollRef }) {
|
||||
return <ActivityIndicator />;
|
||||
}
|
||||
|
||||
setIsRetained(data.retain_indefinitely);
|
||||
const startime = new Date(data.start_time * 1000);
|
||||
const endtime = data.end_time ? new Date(data.end_time * 1000) : null;
|
||||
return (
|
||||
@@ -119,7 +143,7 @@ export default function Event({ eventId, close, scrollRef }) {
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
<ActionButtonGroup handleClickDelete={handleClickDelete} close={close} className="hidden sm:block" />
|
||||
<ActionButtonGroup isRetained={isRetained} handleClickRetain={handleClickRetain} handleClickDelete={handleClickDelete} close={close} className="hidden sm:block" />
|
||||
{showDialog ? (
|
||||
<Dialog
|
||||
onDismiss={handleDismissDeleteDialog}
|
||||
@@ -210,7 +234,7 @@ export default function Event({ eventId, close, scrollRef }) {
|
||||
</div>
|
||||
<div className="space-y-2 xs:space-y-0">
|
||||
<DownloadButtonGroup apiHost={apiHost} eventId={eventId} className="block sm:hidden" />
|
||||
<ActionButtonGroup handleClickDelete={handleClickDelete} close={close} className="block sm:hidden" />
|
||||
<ActionButtonGroup isRetained={isRetained} handleClickRetain={handleClickRetain} handleClickDelete={handleClickDelete} close={close} className="block sm:hidden" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -9,6 +9,7 @@ const TableHead = () => (
|
||||
<Th>Label</Th>
|
||||
<Th>Score</Th>
|
||||
<Th>Zones</Th>
|
||||
<Th>Retain</Th>
|
||||
<Th>Date</Th>
|
||||
<Th>Start</Th>
|
||||
<Th>End</Th>
|
||||
|
||||
@@ -22,6 +22,7 @@ const EventsRow = memo(
|
||||
label,
|
||||
top_score: score,
|
||||
zones,
|
||||
retain_indefinitely
|
||||
}) => {
|
||||
const [viewEvent, setViewEvent] = useState(null);
|
||||
const { searchString, removeDefaultSearchKeys } = useSearchString(limit);
|
||||
@@ -100,6 +101,7 @@ const EventsRow = memo(
|
||||
))}
|
||||
</ul>
|
||||
</Td>
|
||||
<Td>{retain_indefinitely ? 'True' : 'False'}</Td>
|
||||
<Td>{start.toLocaleDateString()}</Td>
|
||||
<Td>{start.toLocaleTimeString()}</Td>
|
||||
<Td>{end === null ? 'In progress' : end.toLocaleTimeString()}</Td>
|
||||
|
||||
Reference in New Issue
Block a user