diff --git a/package.json b/package.json
index 611085a..7d67329 100644
--- a/package.json
+++ b/package.json
@@ -51,7 +51,7 @@
"zod": "^3.21.4"
},
"scripts": {
- "start": "react-scripts start",
+ "dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
diff --git a/src/pages/FrigateHostsPage.tsx b/src/pages/FrigateHostsPage.tsx
index 1c05db6..7ef0b79 100644
--- a/src/pages/FrigateHostsPage.tsx
+++ b/src/pages/FrigateHostsPage.tsx
@@ -1,16 +1,20 @@
-import React, { useContext, useEffect, useRef, useState } from 'react';
-import FrigateHostsTable from '../widgets/FrigateHostsTable';
+import { Button, Flex, Text } from '@mantine/core';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
-import { frigateApi, frigateQueryKeys } from '../services/frigate.proxy/frigate.api';
-import { deleteFrigateHostSchema, GetFrigateHost, putFrigateHostSchema } from '../services/frigate.proxy/frigate.schema';
-import CenterLoader from '../shared/components/loaders/CenterLoader';
-import RetryErrorPage from './RetryErrorPage';
+import { observer } from 'mobx-react-lite';
+import { useContext, useEffect, useRef, useState } from 'react';
import { Context } from '..';
-import { strings } from '../shared/strings/strings';
-import { Button, Flex } from '@mantine/core';
-import { observer } from 'mobx-react-lite'
import { useAdminRole } from '../hooks/useAdminRole';
+import { frigateApi, frigateQueryKeys } from '../services/frigate.proxy/frigate.api';
+import { GetFrigateHost, deleteFrigateHostSchema, putFrigateHostSchema } from '../services/frigate.proxy/frigate.schema';
+import CenterLoader from '../shared/components/loaders/CenterLoader';
+import { isProduction } from '../shared/env.const';
+import { strings } from '../shared/strings/strings';
+import FrigateHostsTable from '../widgets/FrigateHostsTable';
import Forbidden from './403';
+import RetryErrorPage from './RetryErrorPage';
+import { notifications } from '@mantine/notifications';
+import { IconAlertCircle } from '@tabler/icons-react';
+
const FrigateHostsPage = () => {
const executed = useRef(false)
@@ -36,6 +40,10 @@ const FrigateHostsPage = () => {
if (data) setPageData(data)
}, [data])
+ useEffect(() => {
+ if (!isProduction) console.log('pageData', pageData)
+ }, [pageData])
+
const { mutate } = useMutation({
mutationFn: (tableData: GetFrigateHost[]) => {
let fetchPromises = []
@@ -48,16 +56,29 @@ const FrigateHostsPage = () => {
const parsedChanged = putFrigateHostSchema.array().parse(tableData)
fetchPromises.push(frigateApi.putHosts(parsedChanged))
}
- return Promise.all(fetchPromises)
+ return Promise.all(fetchPromises).catch(error => {
+ if (error.response && error.response.data) {
+ return Promise.reject(error.response.data);
+ }
+ return Promise.reject(error);
+ })
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [frigateQueryKeys.getFrigateHosts] })
},
- onError: () => {
+ onError: (e) => {
+ if (e && e.message) {
+ notifications.show({
+ id: e.message,
+ withCloseButton: true,
+ autoClose: 5000,
+ title: "Error",
+ message: e.message,
+ color: 'red',
+ icon: ,
+ })
+ }
queryClient.invalidateQueries({ queryKey: [frigateQueryKeys.getFrigateHosts] })
- },
- onSettled: () => {
- if (data) setPageData([...data])
}
})
@@ -79,18 +100,16 @@ const FrigateHostsPage = () => {
if (hostsPending || adminLoading) return
if (!isAdmin) return
if (hostsError) return
+ if (!pageData) return Empty server response
return (
-
- {
- !pageData ? <>> :
-
- }
+
+
-
+
);
}
diff --git a/src/widgets/FrigateHostsTable.tsx b/src/widgets/FrigateHostsTable.tsx
index 64f2616..a7f1ca6 100644
--- a/src/widgets/FrigateHostsTable.tsx
+++ b/src/widgets/FrigateHostsTable.tsx
@@ -1,17 +1,16 @@
import { Button, Flex, Table } from '@mantine/core';
import { IconPlus, IconTrash } from '@tabler/icons-react';
import ObjectId from 'bson-objectid';
-import React, { useCallback, useEffect, useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { GetFrigateHost } from '../services/frigate.proxy/frigate.schema';
import HostSettingsMenu from '../shared/components/menu/HostSettingsMenu';
import SortedTh from '../shared/components/table.aps/SortedTh';
+import { isProduction } from '../shared/env.const';
import { strings } from '../shared/strings/strings';
-import { debounce } from '../shared/utils/debounce';
import StateCell from './hosts.table/StateCell';
import SwitchCell from './hosts.table/SwitchCell';
import TextInputCell from './hosts.table/TextInputCell';
-import { isProduction } from '../shared/env.const';
interface TableProps {
data: T[],
@@ -21,22 +20,22 @@ interface TableProps {
}
const FrigateHostsTable = ({ data, showAddButton = false, saveCallback, changedCallback }: TableProps) => {
- if (!isProduction) console.log('FrigateHostsTable rendered')
const [tableData, setTableData] = useState(data)
const [reversed, setReversed] = useState(false)
const [sortedName, setSortedName] = useState(null)
- useEffect(() => {
- setTableData(data)
- }, [data])
-
- const debouncedChanged = useCallback(debounce((tableData: GetFrigateHost[]) => {
- if (changedCallback) changedCallback(tableData)
- }, 200), [tableData])
+ console.log('data', data)
+ console.log('tableData', tableData)
useEffect(() => {
- debouncedChanged(tableData)
- }, [tableData, debouncedChanged])
+ setTableData(data);
+ }, [data]);
+
+ useEffect(() => {
+ if (!isProduction) console.log('TableData', tableData)
+ if (changedCallback)
+ changedCallback(tableData)
+ }, [tableData])
function sortByKey(array: T[], key: K): T[] {
return array.sort((a, b) => {
@@ -80,7 +79,7 @@ const FrigateHostsTable = ({ data, showAddButton = false, saveCallback, changedC
)
})
- const handleTextChange = (id: string | number, propertyName: string, value: string,) => {
+ const handleTextChange = (id: string | number, propertyName: string, value: string | number | boolean | undefined,) => {
setTableData(tableData.map(item => {
if (item.id === id) {
return {
@@ -116,7 +115,7 @@ const FrigateHostsTable = ({ data, showAddButton = false, saveCallback, changedC
name: '',
enabled: true
}
- setTableData(prevTableData => [...prevTableData, newHost])
+ setTableData([...tableData, newHost])
}
const rows = tableData.map(item => {
@@ -135,7 +134,7 @@ const FrigateHostsTable = ({ data, showAddButton = false, saveCallback, changedC
)
})
-
+ if (!isProduction) console.log('FrigateHostsTable rendered')
return (
diff --git a/src/widgets/hosts.table/SwitchCell.tsx b/src/widgets/hosts.table/SwitchCell.tsx
index 98d73e4..c0f676a 100644
--- a/src/widgets/hosts.table/SwitchCell.tsx
+++ b/src/widgets/hosts.table/SwitchCell.tsx
@@ -1,6 +1,7 @@
import { Flex, Switch, useMantineTheme } from '@mantine/core';
import { IconBulbFilled, IconBulbOff } from '@tabler/icons-react';
import React from 'react';
+import { boolean } from 'zod';
interface SwithCellProps {
value?: boolean,
@@ -14,7 +15,7 @@ interface SwithCellProps {
export const SwitchCell = ( { value, defaultValue, width, id, propertyName, toggle }: SwithCellProps ) => {
const theme = useMantineTheme();
- if (!value && !defaultValue) value = defaultValue
+ if (typeof value !== 'boolean') value = defaultValue
const handleChange = (event: React.ChangeEvent) => {
if (id && toggle && propertyName) toggle(id, propertyName, event.target.value)
}
diff --git a/src/widgets/hosts.table/TextInputCell.tsx b/src/widgets/hosts.table/TextInputCell.tsx
index 1fd6707..9358e72 100644
--- a/src/widgets/hosts.table/TextInputCell.tsx
+++ b/src/widgets/hosts.table/TextInputCell.tsx
@@ -1,5 +1,6 @@
import { TextInput } from '@mantine/core';
-import React from 'react';
+import { useDebouncedValue } from '@mantine/hooks';
+import React, { useEffect, useState } from 'react';
interface TextImputCellProps {
text?: string | number | boolean,
@@ -9,18 +10,25 @@ interface TextImputCellProps {
onChange?: (
id: string | number,
propertyName: string,
- value: string,
+ value?: string | number | boolean,
) => void,
}
const TextInputCell = ({ text, width, id, propertyName, onChange }: TextImputCellProps) => {
+ const [value, setValue] = useState(text);
+ const [debouncedValue] = useDebouncedValue(value, 300)
+ useEffect(() => {
+ if (debouncedValue !== text) {
+ if (id && propertyName && onChange)
+ onChange(id, propertyName, debouncedValue)
+ }
+ }, [debouncedValue, id, propertyName, onChange, text])
const handleChange = (event: React.ChangeEvent) => {
- if (id && propertyName && onChange)
- onChange(id, propertyName, event.currentTarget.value)
+ setValue(event.currentTarget.value)
}
return (
|
-
+
|
)
}