add Events button to camera card

This commit is contained in:
NlightN22 2024-11-30 15:55:10 +07:00
parent 720f6de6fd
commit cc410d548a
8 changed files with 80 additions and 28 deletions

View File

@ -13,7 +13,7 @@
"@mantine/notifications": "^6.0.16", "@mantine/notifications": "^6.0.16",
"@monaco-editor/react": "^4.6.0", "@monaco-editor/react": "^4.6.0",
"@react-keycloak/web": "^3.4.0", "@react-keycloak/web": "^3.4.0",
"@tabler/icons-react": "^2.24.0", "@tabler/icons-react": "^3.23.0",
"@tanstack/react-query": "^5.21.2", "@tanstack/react-query": "^5.21.2",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^13.0.0", "@testing-library/react": "^13.0.0",

View File

@ -70,11 +70,12 @@ const en = {
memory: 'Memory %' memory: 'Memory %'
}, },
hostMenu: { hostMenu: {
editConfig: 'Edit config', editConfig: 'Редакт. конфиг.',
restart: 'Restart', restart: 'Перезагрузка',
system: 'System', system: 'Система',
storage: 'Storage', storage: 'Хранилище',
}, },
header: { header: {
home: 'Main', home: 'Main',
settings: 'Settings', settings: 'Settings',

View File

@ -105,7 +105,7 @@ const ru = {
config: 'Конфиг.', config: 'Конфиг.',
create: 'Создать', create: 'Создать',
clear: 'Очистить', clear: 'Очистить',
edit: 'Изменить', edit: 'Редакт.',
version: 'Версия', version: 'Версия',
uptime: 'Время работы', uptime: 'Время работы',
pleaseSelectRole: 'Пожалуйста выберите роль', pleaseSelectRole: 'Пожалуйста выберите роль',

View File

@ -1,5 +1,5 @@
import { Button, Menu, rem } from '@mantine/core'; import { Button, Menu, rem } from '@mantine/core';
import { IconEdit, IconGraph, IconRotateClockwise, IconServer, IconSettings } from '@tabler/icons-react'; import { IconEdit, IconGraph, IconRotateClockwise, IconSettings } from '@tabler/icons-react';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';

View File

@ -0,0 +1,39 @@
import { Button, Menu, rem } from '@mantine/core';
import { IconCalendarSearch, IconCamera, IconCameraAi } from '@tabler/icons-react';
import { FC } from 'react';
import { useTranslation } from 'react-i18next';
interface OpenArhiveMenuProps {
onClickMenuItem?(num: number): void
}
const OpenArhiveMenu: FC<OpenArhiveMenuProps> = ({
onClickMenuItem
}) => {
const { t } = useTranslation()
const handleClickMenuItem = (num: number) => {
if (onClickMenuItem) onClickMenuItem(num)
}
return (
<Menu shadow="md">
<Menu.Target>
<Button size='sm' ><IconCalendarSearch /></Button>
</Menu.Target>
<Menu.Item
onClick={() => handleClickMenuItem(0)}
icon={<IconCameraAi style={{ width: rem(14), height: rem(14) }} />}>
{t('events')}
</Menu.Item>
<Menu.Item
onClick={() => handleClickMenuItem(1)}
icon={<IconCamera style={{ width: rem(14), height: rem(14) }} />}>
{t('recordings')}
</Menu.Item>
</Menu>
);
};
export default OpenArhiveMenu;

View File

@ -8,6 +8,15 @@ interface Filters {
endTime?: string endTime?: string
} }
export const eventsQueryParams = {
hostId: 'hostId',
cameraId: 'cameraId',
startDate: 'startDate',
endDate: 'endDate',
startTime: 'startTime',
endTime: 'endTime',
}
export class EventsStore { export class EventsStore {
filters: Filters = {} filters: Filters = {}
@ -18,15 +27,15 @@ export class EventsStore {
loadFiltersFromURL() { loadFiltersFromURL() {
const params = new URLSearchParams(window.location.search); const params = new URLSearchParams(window.location.search);
this.filters.hostId = params.get('hostId') || undefined; this.filters.hostId = params.get(eventsQueryParams.hostId) || undefined;
this.filters.cameraId = params.get('cameraId') || undefined; this.filters.cameraId = params.get(eventsQueryParams.cameraId) || undefined;
const startDate = params.get('startDate'); const startDate = params.get(eventsQueryParams.startDate);
const endDate = params.get('endDate'); const endDate = params.get(eventsQueryParams.endDate);
if (startDate && endDate) { if (startDate && endDate) {
this.filters.period = [new Date(startDate), new Date(endDate)] this.filters.period = [new Date(startDate), new Date(endDate)]
} }
this.filters.startTime = params.get('startTime') || undefined this.filters.startTime = params.get(eventsQueryParams.startTime) || undefined
this.filters.endTime = params.get('endTime') || undefined this.filters.endTime = params.get(eventsQueryParams.endTime) || undefined
} }
setHostId(hostId: string, navigate: (path: string) => void) { setHostId(hostId: string, navigate: (path: string) => void) {

View File

@ -10,6 +10,7 @@ import { mapHostToHostname, proxyApi } from '../services/frigate.proxy/frigate.a
import { GetCameraWHostWConfig } from '../services/frigate.proxy/frigate.schema'; import { GetCameraWHostWConfig } from '../services/frigate.proxy/frigate.schema';
import AutoUpdatedImage from '../shared/components/images/AutoUpdatedImage'; import AutoUpdatedImage from '../shared/components/images/AutoUpdatedImage';
import CameraTagsList from './CameraTagsList'; import CameraTagsList from './CameraTagsList';
import { eventsQueryParams } from '../shared/stores/events.store';
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
mainCard: { mainCard: {
@ -66,6 +67,10 @@ const CameraCard = ({
const url = `${routesPath.RECORDINGS_PATH}?${recordingsPageQuery.hostId}=${camera.frigateHost?.id}&${recordingsPageQuery.cameraId}=${camera.id}` const url = `${routesPath.RECORDINGS_PATH}?${recordingsPageQuery.hostId}=${camera.frigateHost?.id}&${recordingsPageQuery.cameraId}=${camera.id}`
navigate(url) navigate(url)
} }
const handleOpenEvents = () => {
const url = `${routesPath.EVENTS_PATH}?${eventsQueryParams.hostId}=${camera.frigateHost?.id}&${eventsQueryParams.cameraId}=${camera.id}`
navigate(url)
}
const handleOpenEditCamera = () => { const handleOpenEditCamera = () => {
if (camera.frigateHost) { if (camera.frigateHost) {
@ -74,8 +79,6 @@ const CameraCard = ({
} }
} }
return ( return (
<Grid.Col md={6} lg={3} p='0.2rem'> <Grid.Col md={6} lg={3} p='0.2rem'>
<Card ref={ref} h='100%' radius="lg" padding='0.5rem' className={classes.mainCard}> <Card ref={ref} h='100%' radius="lg" padding='0.5rem' className={classes.mainCard}>
@ -85,8 +88,9 @@ const CameraCard = ({
} }
<Group <Group
className={classes.bottomGroup}> className={classes.bottomGroup}>
<Flex justify='space-evenly' mt='0.5rem' w='100%'> <Flex justify='space-evenly' mt='0.5rem' w='100%' wrap='wrap' gap="0.2rem">
<Button size='sm' onClick={handleOpenRecordings}>{t('recordings')}</Button> <Button size='sm' onClick={handleOpenRecordings}>{t('recordings')}</Button>
<Button size='sm' onClick={handleOpenEvents}>{t('events')}</Button>
{!isAdmin ? null : <Button size='sm' onClick={handleOpenEditCamera}>{t('edit')}</Button>} {!isAdmin ? null : <Button size='sm' onClick={handleOpenEditCamera}>{t('edit')}</Button>}
</Flex> </Flex>
</Group> </Group>

View File

@ -2186,18 +2186,17 @@
"@svgr/plugin-svgo" "^5.5.0" "@svgr/plugin-svgo" "^5.5.0"
loader-utils "^2.0.0" loader-utils "^2.0.0"
"@tabler/icons-react@^2.24.0": "@tabler/icons-react@^3.23.0":
version "2.47.0" version "3.23.0"
resolved "https://registry.yarnpkg.com/@tabler/icons-react/-/icons-react-2.47.0.tgz#b704e7ae98f95be8bd6e938b4b2e84cd20b0cf31" resolved "https://registry.yarnpkg.com/@tabler/icons-react/-/icons-react-3.23.0.tgz#68dd3ee4995935c00228c1a401a10bb7d2d9c4be"
integrity sha512-iqly2FvCF/qUbgmvS8E40rVeYY7laltc5GUjRxQj59DuX0x/6CpKHTXt86YlI2whg4czvd/c8Ce8YR08uEku0g== integrity sha512-uSJfu1Tnhk6AAkerNCOBL3KL3aPpb/bnB4UjTbV3jItTJKitEgr4a98ted67qu5FHB3/tG1bxs32pqy5OL7NGw==
dependencies: dependencies:
"@tabler/icons" "2.47.0" "@tabler/icons" "3.23.0"
prop-types "^15.7.2"
"@tabler/icons@2.47.0": "@tabler/icons@3.23.0":
version "2.47.0" version "3.23.0"
resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.47.0.tgz#c41c680d1947e3ab2d60af3febc4132287c60596" resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-3.23.0.tgz#d00b5c98c110fd0e773dff81f4776ba52e49f576"
integrity sha512-4w5evLh+7FUUiA1GucvGj2ReX2TvOjEr4ejXdwL/bsjoSkof6r1gQmzqI+VHrE2CpJpB3al7bCTulOkFa/RcyA== integrity sha512-Cz+X58jfRm0g/KcupXXuPw5knj671lNR054AnmLXvCjudiQBWI0wZulDDSsqDoGezvBzMTNPQtNcjLkZs82ZxQ==
"@tanstack/match-sorter-utils@8.8.4": "@tanstack/match-sorter-utils@8.8.4":
version "8.8.4" version "8.8.4"
@ -8577,7 +8576,7 @@ prompts@^2.0.1, prompts@^2.4.2:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.5" sisteransi "^1.0.5"
prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: prop-types@^15.6.2, prop-types@^15.8.1:
version "15.8.1" version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==