mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Cleanup names in webUI (#4607)
* Fix _ in labels * Capitalize camera names in system * Update storage to link to cameras and share name styling with rest of ui
This commit is contained in:
parent
7888059c9f
commit
6abc0ce921
@ -46,7 +46,7 @@ const clipDuration = (start_time, end_time) => {
|
|||||||
duration = formatDuration(intervalToDuration({ start, end }));
|
duration = formatDuration(intervalToDuration({ start, end }));
|
||||||
}
|
}
|
||||||
return duration;
|
return duration;
|
||||||
}
|
};
|
||||||
|
|
||||||
export default function Events({ path, ...props }) {
|
export default function Events({ path, ...props }) {
|
||||||
const apiHost = useApiHost();
|
const apiHost = useApiHost();
|
||||||
@ -100,7 +100,7 @@ export default function Events({ path, ...props }) {
|
|||||||
|
|
||||||
const { data: config } = useSWR('config');
|
const { data: config } = useSWR('config');
|
||||||
|
|
||||||
const { data: allSubLabels } = useSWR('sub_labels')
|
const { data: allSubLabels } = useSWR('sub_labels');
|
||||||
|
|
||||||
const filterValues = useMemo(
|
const filterValues = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
@ -296,21 +296,20 @@ export default function Events({ path, ...props }) {
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{
|
{filterValues.sub_labels.length > 0 && (
|
||||||
filterValues.sub_labels.length > 0 && (
|
<select
|
||||||
<select
|
className="basis-1/5 cursor-pointer rounded dark:bg-slate-800"
|
||||||
className="basis-1/5 cursor-pointer rounded dark:bg-slate-800"
|
value={searchParams.sub_label}
|
||||||
value={searchParams.sub_label}
|
onChange={(e) => onFilter('sub_label', e.target.value)}
|
||||||
onChange={(e) => onFilter('sub_label', e.target.value)}
|
>
|
||||||
>
|
<option value="all">all sub labels</option>
|
||||||
<option value="all">all sub labels</option>
|
{filterValues.sub_labels.map((item) => (
|
||||||
{filterValues.sub_labels.map((item) => (
|
<option key={item} value={item}>
|
||||||
<option key={item} value={item}>
|
{item}
|
||||||
{item}
|
</option>
|
||||||
</option>
|
))}
|
||||||
))}
|
</select>
|
||||||
</select>
|
)}
|
||||||
)}
|
|
||||||
<div ref={datePicker} className="ml-auto">
|
<div ref={datePicker} className="ml-auto">
|
||||||
<CalendarIcon
|
<CalendarIcon
|
||||||
className="h-8 w-8 cursor-pointer"
|
className="h-8 w-8 cursor-pointer"
|
||||||
@ -426,7 +425,15 @@ export default function Events({ path, ...props }) {
|
|||||||
<p className="mb-2">Confirm deletion of saved event.</p>
|
<p className="mb-2">Confirm deletion of saved event.</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-2 flex justify-start flex-row-reverse space-x-2">
|
<div className="p-2 flex justify-start flex-row-reverse space-x-2">
|
||||||
<Button className="ml-2" color="red" onClick={(e) => { setDeleteFavoriteState({ ...state, showDeleteFavorite: false }); onDelete(e, deleteFavoriteState.deletingFavoriteEventId, false) }} type="text">
|
<Button
|
||||||
|
className="ml-2"
|
||||||
|
color="red"
|
||||||
|
onClick={(e) => {
|
||||||
|
setDeleteFavoriteState({ ...state, showDeleteFavorite: false });
|
||||||
|
onDelete(e, deleteFavoriteState.deletingFavoriteEventId, false);
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
>
|
||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
@ -465,12 +472,15 @@ export default function Events({ path, ...props }) {
|
|||||||
<div className="m-2 flex grow">
|
<div className="m-2 flex grow">
|
||||||
<div className="flex flex-col grow">
|
<div className="flex flex-col grow">
|
||||||
<div className="capitalize text-lg font-bold">
|
<div className="capitalize text-lg font-bold">
|
||||||
{event.sub_label ? `${event.label}: ${event.sub_label}` : event.label} (
|
{event.sub_label
|
||||||
{(event.top_score * 100).toFixed(0)}%)
|
? `${event.label.replaceAll('_', ' ')}: ${event.sub_label.replaceAll('_', ' ')}`
|
||||||
|
: event.label.replaceAll('_', ' ')}{' '}
|
||||||
|
({(event.top_score * 100).toFixed(0)}%)
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm">
|
<div className="text-sm">
|
||||||
{new Date(event.start_time * 1000).toLocaleDateString()}{' '}
|
{new Date(event.start_time * 1000).toLocaleDateString()}{' '}
|
||||||
{new Date(event.start_time * 1000).toLocaleTimeString()} ({clipDuration(event.start_time, event.end_time)})
|
{new Date(event.start_time * 1000).toLocaleTimeString()} (
|
||||||
|
{clipDuration(event.start_time, event.end_time)})
|
||||||
</div>
|
</div>
|
||||||
<div className="capitalize text-sm flex align-center mt-1">
|
<div className="capitalize text-sm flex align-center mt-1">
|
||||||
<Camera className="h-5 w-5 mr-2 inline" />
|
<Camera className="h-5 w-5 mr-2 inline" />
|
||||||
@ -499,7 +509,11 @@ export default function Events({ path, ...props }) {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<Delete className="h-6 w-6 cursor-pointer" stroke="#f87171" onClick={(e) => onDelete(e, event.id, event.retain_indefinitely)} />
|
<Delete
|
||||||
|
className="h-6 w-6 cursor-pointer"
|
||||||
|
stroke="#f87171"
|
||||||
|
onClick={(e) => onDelete(e, event.id, event.retain_indefinitely)}
|
||||||
|
/>
|
||||||
|
|
||||||
<Download
|
<Download
|
||||||
className="h-6 w-6 mt-auto"
|
className="h-6 w-6 mt-auto"
|
||||||
@ -512,15 +526,19 @@ 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">
|
||||||
<div className='flex justify-center w-full py-2'>
|
<div className="flex justify-center w-full py-2">
|
||||||
<Tabs selectedIndex={event.has_clip && eventDetailType == 'clip' ? 0 : 1} onChange={handleEventDetailTabChange} className='justify'>
|
<Tabs
|
||||||
<TextTab text='Clip' disabled={!event.has_clip} />
|
selectedIndex={event.has_clip && eventDetailType == 'clip' ? 0 : 1}
|
||||||
|
onChange={handleEventDetailTabChange}
|
||||||
|
className="justify"
|
||||||
|
>
|
||||||
|
<TextTab text="Clip" disabled={!event.has_clip} />
|
||||||
<TextTab text={event.has_snapshot ? 'Snapshot' : 'Thumbnail'} />
|
<TextTab text={event.has_snapshot ? 'Snapshot' : 'Thumbnail'} />
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{((eventDetailType == 'clip') && event.has_clip) ? (
|
{eventDetailType == 'clip' && event.has_clip ? (
|
||||||
<VideoPlayer
|
<VideoPlayer
|
||||||
options={{
|
options={{
|
||||||
preload: 'auto',
|
preload: 'auto',
|
||||||
@ -533,11 +551,11 @@ export default function Events({ path, ...props }) {
|
|||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
seekOptions={{ forward: 10, back: 5 }}
|
seekOptions={{ forward: 10, back: 5 }}
|
||||||
onReady={() => { }}
|
onReady={() => {}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{((eventDetailType == 'image') || !event.has_clip) ? (
|
{eventDetailType == 'image' || !event.has_clip ? (
|
||||||
<div className="flex justify-center">
|
<div className="flex justify-center">
|
||||||
<img
|
<img
|
||||||
className="flex-grow-0"
|
className="flex-grow-0"
|
||||||
|
@ -4,6 +4,7 @@ import Heading from '../components/Heading';
|
|||||||
import { useWs } from '../api/ws';
|
import { useWs } from '../api/ws';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { Table, Tbody, Thead, Tr, Th, Td } from '../components/Table';
|
import { Table, Tbody, Thead, Tr, Th, Td } from '../components/Table';
|
||||||
|
import Link from '../components/Link';
|
||||||
|
|
||||||
const emptyObject = Object.freeze({});
|
const emptyObject = Object.freeze({});
|
||||||
|
|
||||||
@ -82,7 +83,9 @@ export default function Storage() {
|
|||||||
<div data-testid="detectors" className="grid grid-cols-1 3xl:grid-cols-3 md:grid-cols-2 gap-4">
|
<div data-testid="detectors" className="grid grid-cols-1 3xl:grid-cols-3 md:grid-cols-2 gap-4">
|
||||||
{Object.entries(storage).map(([name, camera]) => (
|
{Object.entries(storage).map(([name, camera]) => (
|
||||||
<div key={name} className="dark:bg-gray-800 shadow-md hover:shadow-lg rounded-lg transition-shadow">
|
<div key={name} className="dark:bg-gray-800 shadow-md hover:shadow-lg rounded-lg transition-shadow">
|
||||||
<div className="text-lg flex justify-between p-4">{name}</div>
|
<div className="capitalize text-lg flex justify-between p-4">
|
||||||
|
<Link href={`/cameras/${name}`}>{name.replaceAll('_', ' ')}</Link>
|
||||||
|
</div>
|
||||||
<div className="p-2">
|
<div className="p-2">
|
||||||
<Table className="w-full">
|
<Table className="w-full">
|
||||||
<Thead>
|
<Thead>
|
||||||
|
@ -211,7 +211,7 @@ export default function System() {
|
|||||||
<div data-testid="cameras" className="grid grid-cols-1 3xl:grid-cols-3 md:grid-cols-2 gap-4">
|
<div data-testid="cameras" className="grid grid-cols-1 3xl:grid-cols-3 md:grid-cols-2 gap-4">
|
||||||
{cameraNames.map((camera) => (
|
{cameraNames.map((camera) => (
|
||||||
<div key={camera} className="dark:bg-gray-800 shadow-md hover:shadow-lg rounded-lg transition-shadow">
|
<div key={camera} className="dark:bg-gray-800 shadow-md hover:shadow-lg rounded-lg transition-shadow">
|
||||||
<div className="text-lg flex justify-between p-4">
|
<div className="capitalize text-lg flex justify-between p-4">
|
||||||
<Link href={`/cameras/${camera}`}>{camera.replaceAll('_', ' ')}</Link>
|
<Link href={`/cameras/${camera}`}>{camera.replaceAll('_', ' ')}</Link>
|
||||||
<Button onClick={(e) => onHandleFfprobe(camera, e)}>ffprobe</Button>
|
<Button onClick={(e) => onHandleFfprobe(camera, e)}>ffprobe</Button>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user