Show snapshots on events page (#3763)

* Add tabs to show snapshot or thumbnail as part of event details,
  even if event has a clip available.
* Add ability for TextTab to render as disabled.
This commit is contained in:
Aksel 2022-09-15 13:35:51 +02:00 committed by GitHub
parent bdfe4a961a
commit 14faf0b2f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 16 deletions

View File

@ -27,12 +27,14 @@ export function Tabs({ children, selectedIndex: selectedIndexProp, onChange, cla
); );
} }
export function TextTab({ selected, text, onClick }) { export function TextTab({ selected, text, onClick, disabled }) {
const selectedStyle = selected const selectedStyle = disabled
? 'text-gray-400 dark:text-gray-600 bg-transparent'
: selected
? 'text-white bg-blue-500 dark:text-black dark:bg-white' ? 'text-white bg-blue-500 dark:text-black dark:bg-white'
: 'text-black dark:text-white bg-transparent'; : 'text-black dark:text-white bg-transparent';
return ( return (
<button onClick={onClick} className={`rounded-full px-4 py-2 ${selectedStyle}`}> <button onClick={onClick} disabled={disabled} className={`rounded-full px-4 py-2 ${selectedStyle}`}>
<span>{text}</span> <span>{text}</span>
</button> </button>
); );

View File

@ -2,6 +2,7 @@ import { h, Fragment } from 'preact';
import { route } from 'preact-router'; import { route } from 'preact-router';
import ActivityIndicator from '../components/ActivityIndicator'; import ActivityIndicator from '../components/ActivityIndicator';
import Heading from '../components/Heading'; import Heading from '../components/Heading';
import { Tabs, TextTab } from '../components/Tabs';
import { useApiHost } from '../api'; import { useApiHost } from '../api';
import useSWR from 'swr'; import useSWR from 'swr';
import useSWRInfinite from 'swr/infinite'; import useSWRInfinite from 'swr/infinite';
@ -54,6 +55,7 @@ export default function Events({ path, ...props }) {
}); });
const [uploading, setUploading] = useState([]); const [uploading, setUploading] = useState([]);
const [viewEvent, setViewEvent] = useState(); const [viewEvent, setViewEvent] = useState();
const [eventDetailType, setEventDetailType] = useState('clip');
const [downloadEvent, setDownloadEvent] = useState({ const [downloadEvent, setDownloadEvent] = useState({
id: null, id: null,
has_clip: false, has_clip: false,
@ -235,6 +237,10 @@ export default function Events({ path, ...props }) {
} }
}; };
const handleEventDetailTabChange = (index) => {
setEventDetailType(index == 0 ? 'clip' : 'image');
};
if (!config) { if (!config) {
return <ActivityIndicator />; return <ActivityIndicator />;
} }
@ -495,9 +501,15 @@ export default function Events({ path, ...props }) {
{viewEvent !== event.id ? null : ( {viewEvent !== event.id ? null : (
<div className="space-y-4"> <div className="space-y-4">
<div className="mx-auto max-w-7xl"> <div className="mx-auto max-w-7xl">
{event.has_clip ? ( <div className='flex justify-center w-full py-2'>
<> <Tabs selectedIndex={event.has_clip && eventDetailType == 'clip' ? 0 : 1} onChange={handleEventDetailTabChange} className='justify'>
<Heading size="lg">Clip</Heading> <TextTab text='Clip' disabled={!event.has_clip} />
<TextTab text={event.has_snapshot ? 'Snapshot' : 'Thumbnail'} />
</Tabs>
</div>
<div>
{((eventDetailType == 'clip') && event.has_clip) ? (
<VideoPlayer <VideoPlayer
options={{ options={{
preload: 'auto', preload: 'auto',
@ -512,23 +524,22 @@ export default function Events({ path, ...props }) {
seekOptions={{ forward: 10, back: 5 }} seekOptions={{ forward: 10, back: 5 }}
onReady={() => {}} onReady={() => {}}
/> />
</> ) : null }
) : (
{((eventDetailType == 'image') || !event.has_clip) ? (
<div className="flex justify-center"> <div className="flex justify-center">
<div>
<Heading size="sm">{event.has_snapshot ? 'Best Image' : 'Thumbnail'}</Heading>
<img <img
className="flex-grow-0" className="flex-grow-0"
src={ src={
event.has_snapshot event.has_snapshot
? `${apiHost}/api/events/${event.id}/snapshot.jpg` ? `${apiHost}/api/events/${event.id}/snapshot.jpg`
: `data:image/jpeg;base64,${event.thumbnail}` : `${apiHost}/api/events/${event.id}/thumbnail.jpg`
} }
alt={`${event.label} at ${(event.top_score * 100).toFixed(0)}% confidence`} alt={`${event.label} at ${(event.top_score * 100).toFixed(0)}% confidence`}
/> />
</div> </div>
) : null }
</div> </div>
)}
</div> </div>
</div> </div>
)} )}