From 14df894b3426189aae1c4dcd2ce9ca28340df51f Mon Sep 17 00:00:00 2001 From: NlightN22 Date: Tue, 1 Oct 2024 03:12:55 +0700 Subject: [PATCH] fix errors message add time validation --- src/locales/en.ts | 1 + src/locales/ru.ts | 3 +- src/pages/EditCameraPage.tsx | 2 +- src/pages/EventsPage.tsx | 43 +++++++++++++++++-- src/pages/FrigateHostsPage.tsx | 2 +- src/pages/HostConfigPage.tsx | 2 +- .../components/filters/UserTagsFilter.tsx | 4 +- src/shared/utils/dateUtil.ts | 12 ++++++ src/widgets/CameraTagsList.tsx | 6 ++- src/widgets/EventsBody.tsx | 1 + src/widgets/sidebars/EventsRightFilters.tsx | 4 +- 11 files changed, 67 insertions(+), 13 deletions(-) diff --git a/src/locales/en.ts b/src/locales/en.ts index f0e8a16..859338e 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -17,6 +17,7 @@ const en = { eventsPage: { selectStartTime: 'Select start time:', selectEndTime: 'Select end time:', + startTimeBiggerThanEnd: 'Start time bigger than end time', }, frigateConfigPage: { copyConfig: 'Copy Config', diff --git a/src/locales/ru.ts b/src/locales/ru.ts index 2a4222b..5850ad3 100644 --- a/src/locales/ru.ts +++ b/src/locales/ru.ts @@ -15,7 +15,7 @@ const ru = { eventsPage: { selectStartTime: 'Выбери время начала:', selectEndTime: 'Выбери время окончания:', - maxEventsFetches: 'Ошибка: Невозможно получить события после {{maxRetries}} попыток. Пожалуйста попробуйте позже или установите меньший период.', + startTimeBiggerThanEnd: 'Время начала больше времени окончания', }, frigateConfigPage: { copyConfig: 'Копировать Конфиг.', @@ -97,6 +97,7 @@ const ru = { doubleClickToFullHint: 'Двойное нажатие мышью для полноэкранного просмотра', rating: 'Рейтинг', }, + maxRetries: 'Ошибка: невозможно получить данные после {{maxRetries}} попыток. Пожалуйста попробуйте позже или поменяйте период на меньший.', config: 'Конфиг.', create: 'Создать', clear: 'Очистить', diff --git a/src/pages/EditCameraPage.tsx b/src/pages/EditCameraPage.tsx index 8e88b67..5dc44e3 100644 --- a/src/pages/EditCameraPage.tsx +++ b/src/pages/EditCameraPage.tsx @@ -93,7 +93,7 @@ const EditCameraPage = () => { id: e.message, withCloseButton: true, autoClose: false, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , diff --git a/src/pages/EventsPage.tsx b/src/pages/EventsPage.tsx index aaa7e41..fcc60a1 100644 --- a/src/pages/EventsPage.tsx +++ b/src/pages/EventsPage.tsx @@ -1,12 +1,14 @@ import { Flex, Text } from '@mantine/core'; +import { notifications } from '@mantine/notifications'; import { t } from 'i18next'; import { observer } from 'mobx-react-lite'; -import { useContext, useEffect } from 'react'; +import { useContext, useEffect, useState } from 'react'; import { Context } from '..'; +import { isStartBiggerThanEndTime } from '../shared/utils/dateUtil'; import EventsBody from '../widgets/EventsBody'; import EventsRightFilters from '../widgets/sidebars/EventsRightFilters'; import { SideBarContext } from '../widgets/sidebars/SideBarContext'; -import { isProduction } from '../shared/env.const'; +import { IconAlertCircle } from '@tabler/icons-react'; export const eventsPageQuery = { hostId: 'hostId', @@ -16,8 +18,15 @@ export const eventsPageQuery = { hour: 'hour', } +interface TimePeriod { + startTime: string, + endTime: string, +} + const EventsPage = () => { + const [timePeriod, setTimePeriod] = useState() + const { setRightChildren } = useContext(SideBarContext) useEffect(() => { @@ -25,17 +34,43 @@ const EventsPage = () => { return () => setRightChildren(null) }, []) + + const { eventsStore } = useContext(Context) const { hostId, cameraId, period, startTime, endTime } = eventsStore.filters + useEffect(() => { + const startTime = eventsStore.filters.startTime + const endTime = eventsStore.filters.endTime + if (startTime && endTime) { + if (isStartBiggerThanEndTime(startTime, endTime)) { + const message = t('eventsPage.startTimeBiggerThanEnd') + notifications.show({ + id: message, + withCloseButton: true, + autoClose: 5000, + title: t('error'), + message: message, + color: 'red', + icon: , + }) + return + } + setTimePeriod({ + startTime, + endTime + }) + } + }, [eventsStore.filters.startTime, eventsStore.filters.endTime]) + if (hostId && cameraId && period && period[0] && period[1]) { return ( ) } diff --git a/src/pages/FrigateHostsPage.tsx b/src/pages/FrigateHostsPage.tsx index a25b7f7..7420b98 100644 --- a/src/pages/FrigateHostsPage.tsx +++ b/src/pages/FrigateHostsPage.tsx @@ -63,7 +63,7 @@ const FrigateHostsPage = () => { id: e.message, withCloseButton: true, autoClose: 5000, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , diff --git a/src/pages/HostConfigPage.tsx b/src/pages/HostConfigPage.tsx index 09d6153..2b114dc 100644 --- a/src/pages/HostConfigPage.tsx +++ b/src/pages/HostConfigPage.tsx @@ -85,7 +85,7 @@ const HostConfigPage = () => { id: e.message, withCloseButton: true, autoClose: false, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , diff --git a/src/shared/components/filters/UserTagsFilter.tsx b/src/shared/components/filters/UserTagsFilter.tsx index ab02b20..54394f4 100644 --- a/src/shared/components/filters/UserTagsFilter.tsx +++ b/src/shared/components/filters/UserTagsFilter.tsx @@ -71,7 +71,7 @@ const UserTagsFilter: React.FC = ({ id: e.message, withCloseButton: true, autoClose: 5000, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , @@ -100,7 +100,7 @@ const UserTagsFilter: React.FC = ({ id: e.message, withCloseButton: true, autoClose: 5000, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , diff --git a/src/shared/utils/dateUtil.ts b/src/shared/utils/dateUtil.ts index 85cf932..210b2a7 100644 --- a/src/shared/utils/dateUtil.ts +++ b/src/shared/utils/dateUtil.ts @@ -168,6 +168,18 @@ export const dayTimeToUnixTime = (day: Date, time: string) => { return Math.floor(day.getTime() / 1000) } +export const isStartBiggerThanEndTime = (startTime: string, endTime: string) => { + const [hours1, minutes1] = startTime.split(':').map(Number) + const [hours2, minutes2] = endTime.split(':').map(Number) + + const date1 = new Date(); + const date2 = new Date(); + + date1.setHours(hours1, minutes1, 0, 0) + date2.setHours(hours2, minutes2, 0, 0) + return date1 > date2 +} + /** * This function takes in a Unix timestamp, configuration options for date/time display, and an optional strftime format string, * and returns a formatted date/time string. diff --git a/src/widgets/CameraTagsList.tsx b/src/widgets/CameraTagsList.tsx index 65bcbf0..5db93b0 100644 --- a/src/widgets/CameraTagsList.tsx +++ b/src/widgets/CameraTagsList.tsx @@ -8,6 +8,7 @@ import { GetCameraWHostWConfig } from '../services/frigate.proxy/frigate.schema' import AddBadge from '../shared/components/AddBadge'; import TagBadge from '../shared/components/TagBadge'; import { CameraTag } from '../types/tags'; +import { useTranslation } from 'react-i18next'; interface CameraTagsListProps { @@ -18,6 +19,7 @@ const CameraTagsList: React.FC = ({ camera }) => { + const { t } = useTranslation() const queryClient = useQueryClient() const [tagsList, setTagsList] = useState(camera.tags) @@ -45,7 +47,7 @@ const CameraTagsList: React.FC = ({ id: e.message, withCloseButton: true, autoClose: 5000, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , @@ -73,7 +75,7 @@ const CameraTagsList: React.FC = ({ id: e.message, withCloseButton: true, autoClose: 5000, - title: "Error", + title: t('error'), message: e.message, color: 'red', icon: , diff --git a/src/widgets/EventsBody.tsx b/src/widgets/EventsBody.tsx index 8f15172..ccf390d 100644 --- a/src/widgets/EventsBody.tsx +++ b/src/widgets/EventsBody.tsx @@ -15,6 +15,7 @@ interface EventsBodyProps { endTime?: string, } + const EventsBody: FC = ({ hostId, cameraId, diff --git a/src/widgets/sidebars/EventsRightFilters.tsx b/src/widgets/sidebars/EventsRightFilters.tsx index a8fcea3..1ace4cb 100644 --- a/src/widgets/sidebars/EventsRightFilters.tsx +++ b/src/widgets/sidebars/EventsRightFilters.tsx @@ -1,5 +1,5 @@ import { observer } from 'mobx-react-lite'; -import { useContext } from 'react'; +import { useContext, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { Context } from '../..'; @@ -9,6 +9,8 @@ import HostSelect from '../../shared/components/filters/HostSelect'; import TimePicker from '../../shared/components/filters/TimePicker'; import { isProduction } from '../../shared/env.const'; + + const EventsRightFilters = () => { const { t } = useTranslation()