Move event-view to events table. (#1596)

* fixed position for Dialog

* added eventId to deleted item

* removed page route redirect + New Close Button

* event component added to events list. New delete reducer

* removed event route

* moved delete reducer to event page

* removed redundant event details

* keep aspect ratio

* keep aspect ratio

* removed old buttons - repositioned to top

* removed console.log

* event view function

* removed clip header

* top position

* centered image if no clips avail

* comments

* linting

* lint

* added scrollIntoView when event has been mounted

* added Clip header

* added scrollIntoView to test

* lint

* useRef to scroll event into view

* removed unused functions

* reverted changes to event.test

* scroll into view

* moved delete reducer

* removed commented code

* styling

* moved close button to right side

* Added new close svg icon

Co-authored-by: Bernt Christian Egeland <cbegelan@gmail.com>
This commit is contained in:
Bernt Christian Egeland
2021-08-26 13:54:36 +02:00
committed by GitHub
parent 10ab70080a
commit 4efc584816
7 changed files with 192 additions and 174 deletions

View File

@@ -1,25 +1,32 @@
import { h, Fragment } from 'preact';
import { useCallback, useState } from 'preact/hooks';
import { route } from 'preact-router';
import { useCallback, useState, useEffect } from 'preact/hooks';
import ActivityIndicator from '../components/ActivityIndicator';
import Button from '../components/Button';
import Clip from '../icons/Clip';
import Close from '../icons/Close';
import Delete from '../icons/Delete';
import Snapshot from '../icons/Snapshot';
import Dialog from '../components/Dialog';
import Heading from '../components/Heading';
import Link from '../components/Link';
import VideoPlayer from '../components/VideoPlayer';
import { FetchStatus, useApiHost, useEvent, useDelete } from '../api';
import { Table, Thead, Tbody, Th, Tr, Td } from '../components/Table';
export default function Event({ eventId }) {
export default function Event({ eventId, close, scrollRef }) {
const apiHost = useApiHost();
const { data, status } = useEvent(eventId);
const [showDialog, setShowDialog] = useState(false);
const [shouldScroll, setShouldScroll] = useState(true);
const [deleteStatus, setDeleteStatus] = useState(FetchStatus.NONE);
const setDeleteEvent = useDelete();
useEffect(() => {
// Scroll event into view when component has been mounted.
if (shouldScroll && scrollRef && scrollRef[eventId]) {
scrollRef[eventId].scrollIntoView();
setShouldScroll(false);
}
}, [data, scrollRef, eventId, shouldScroll]);
const handleClickDelete = () => {
setShowDialog(true);
};
@@ -40,7 +47,6 @@ export default function Event({ eventId }) {
if (success) {
setDeleteStatus(FetchStatus.LOADED);
setShowDialog(false);
route('/events', true);
}
}, [eventId, setShowDialog, setDeleteEvent]);
@@ -48,18 +54,25 @@ export default function Event({ eventId }) {
return <ActivityIndicator />;
}
const startime = new Date(data.start_time * 1000);
const endtime = new Date(data.end_time * 1000);
return (
<div className="space-y-4">
<div className="flex">
<Heading className="flex-grow">
{data.camera} {data.label} <span className="text-sm">{startime.toLocaleString()}</span>
</Heading>
<Button className="self-start" color="red" onClick={handleClickDelete}>
<Delete className="w-6" /> Delete event
</Button>
<div className="grid grid-cols-6 gap-4">
<div class="col-start-1 col-end-8 md:space-x-4">
<Button color="blue" href={`${apiHost}/api/events/${eventId}/clip.mp4?download=true`} download>
<Clip className="w-6" /> Download Clip
</Button>
<Button color="blue" href={`${apiHost}/api/events/${eventId}/snapshot.jpg?download=true`} download>
<Snapshot className="w-6" /> Download Snapshot
</Button>
</div>
<div class="col-end-10 col-span-2 space-x-4">
<Button className="self-start" color="red" onClick={handleClickDelete}>
<Delete className="w-6" /> Delete event
</Button>
<Button color="gray" className="self-start" onClick={() => close()}>
<Close className="w-6" /> Close
</Button>
</div>
{showDialog ? (
<Dialog
onDismiss={handleDismissDeleteDialog}
@@ -78,86 +91,42 @@ export default function Event({ eventId }) {
/>
) : null}
</div>
<Table class="w-full">
<Thead>
<Th>Key</Th>
<Th>Value</Th>
</Thead>
<Tbody>
<Tr>
<Td>Camera</Td>
<Td>
<Link href={`/cameras/${data.camera}`}>{data.camera}</Link>
</Td>
</Tr>
<Tr index={1}>
<Td>Timeframe</Td>
<Td>
{startime.toLocaleString()} {endtime.toLocaleString()}
</Td>
</Tr>
<Tr>
<Td>Score</Td>
<Td>{(data.top_score * 100).toFixed(2)}%</Td>
</Tr>
<Tr index={1}>
<Td>Zones</Td>
<Td>{data.zones.join(', ')}</Td>
</Tr>
</Tbody>
</Table>
{data.has_clip ? (
<Fragment>
<Heading size="lg">Clip</Heading>
<VideoPlayer
options={{
sources: [
{
src: `${apiHost}/vod/event/${eventId}/index.m3u8`,
type: 'application/vnd.apple.mpegurl',
},
],
poster: data.has_snapshot
? `${apiHost}/clips/${data.camera}-${eventId}.jpg`
: `data:image/jpeg;base64,${data.thumbnail}`,
}}
seekOptions={{ forward: 10, back: 5 }}
onReady={(player) => {}}
/>
<div className="text-center">
<Button
className="mx-2"
color="blue"
href={`${apiHost}/api/events/${eventId}/clip.mp4?download=true`}
download
>
<Clip className="w-6" /> Download Clip
</Button>
<Button
className="mx-2"
color="blue"
href={`${apiHost}/api/events/${eventId}/snapshot.jpg?download=true`}
download
>
<Snapshot className="w-6" /> Download Snapshot
</Button>
</div>
</Fragment>
) : (
<Fragment>
<Heading size="sm">{data.has_snapshot ? 'Best Image' : 'Thumbnail'}</Heading>
<img
src={
data.has_snapshot
? `${apiHost}/clips/${data.camera}-${eventId}.jpg`
: `data:image/jpeg;base64,${data.thumbnail}`
}
alt={`${data.label} at ${(data.top_score * 100).toFixed(1)}% confidence`}
/>
</Fragment>
)}
<div className="outer-max-width m-auto">
<div className="w-full pt-5 relative pb-20">
{data.has_clip ? (
<Fragment>
<Heading size="lg">Clip</Heading>
<VideoPlayer
options={{
sources: [
{
src: `${apiHost}/vod/event/${eventId}/index.m3u8`,
type: 'application/vnd.apple.mpegurl',
},
],
poster: data.has_snapshot
? `${apiHost}/clips/${data.camera}-${eventId}.jpg`
: `data:image/jpeg;base64,${data.thumbnail}`,
}}
seekOptions={{ forward: 10, back: 5 }}
onReady={() => {}}
/>
</Fragment>
) : (
<Fragment>
<Heading size="sm">{data.has_snapshot ? 'Best Image' : 'Thumbnail'}</Heading>
<img
src={
data.has_snapshot
? `${apiHost}/clips/${data.camera}-${eventId}.jpg`
: `data:image/jpeg;base64,${data.thumbnail}`
}
alt={`${data.label} at ${(data.top_score * 100).toFixed(1)}% confidence`}
/>
</Fragment>
)}
</div>
</div>
</div>
);
}