mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-10-29 01:12:19 +00:00
[WIFI-12613] Display reboot logs on device page
Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "2.10.0(41)",
|
||||
"version": "2.10.0(42)",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ucentral-client",
|
||||
"version": "2.10.0(41)",
|
||||
"version": "2.10.0(42)",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^2.0.18",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "2.10.0(41)",
|
||||
"version": "2.10.0(42)",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.tsx",
|
||||
|
||||
@@ -644,6 +644,7 @@
|
||||
"notifications": "Gerätebenachrichtigungen",
|
||||
"one": "Gerät",
|
||||
"reassign_already_owned": "Geräte neu zuweisen, die bereits vorhanden sind und einem anderen Unternehmen/Veranstaltungsort/Abonnenten gehören?",
|
||||
"reboot_logs": "Neustartprotokolle",
|
||||
"restricted": "Beschränkt",
|
||||
"restricted_overriden": "Dies ist ein eingeschränktes Gerät, aber es befindet sich im Entwicklungsmodus. Alle Einschränkungen werden derzeit ignoriert",
|
||||
"restrictions_overriden_title": "Dev-Modus",
|
||||
|
||||
@@ -644,6 +644,7 @@
|
||||
"notifications": "Device Notifications",
|
||||
"one": "Device",
|
||||
"reassign_already_owned": "Reassign devices which already exist and are owned by another entity/venue/subscriber?",
|
||||
"reboot_logs": "Reboot Logs",
|
||||
"restricted": "Restricted",
|
||||
"restricted_overriden": "This is a restricted device, but it is in development mode. All restrictions are currently ignored",
|
||||
"restrictions_overriden_title": "Dev Mode",
|
||||
|
||||
@@ -644,6 +644,7 @@
|
||||
"notifications": "notificaciones de dispositivos",
|
||||
"one": "Dispositivo",
|
||||
"reassign_already_owned": "¿Reasignar dispositivos que ya existen y son propiedad de otra entidad/lugar/suscriptor?",
|
||||
"reboot_logs": "Reiniciar registros",
|
||||
"restricted": "Restringido",
|
||||
"restricted_overriden": "Este es un dispositivo restringido, pero está en modo de desarrollo. Actualmente se ignoran todas las restricciones.",
|
||||
"restrictions_overriden_title": "MODO DE DESARROLLO",
|
||||
|
||||
@@ -644,6 +644,7 @@
|
||||
"notifications": "notifications de l'appareil",
|
||||
"one": "Dispositif",
|
||||
"reassign_already_owned": "Réattribuer des appareils qui existent déjà et qui appartiennent à une autre entité/salle/abonné ?",
|
||||
"reboot_logs": "Journaux de redémarrage",
|
||||
"restricted": "Limité",
|
||||
"restricted_overriden": "Il s'agit d'un appareil restreint, mais il est en mode développement. Toutes les restrictions sont actuellement ignorées",
|
||||
"restrictions_overriden_title": "Mode développement",
|
||||
|
||||
@@ -644,6 +644,7 @@
|
||||
"notifications": "Notificações do dispositivo",
|
||||
"one": "Dispositivo",
|
||||
"reassign_already_owned": "Reatribuir dispositivos que já existem e são de propriedade de outra entidade/local/assinante?",
|
||||
"reboot_logs": "Registros de reinicialização",
|
||||
"restricted": "Restrito",
|
||||
"restricted_overriden": "Este é um dispositivo restrito, mas está em modo de desenvolvimento. Todas as restrições são atualmente ignoradas",
|
||||
"restrictions_overriden_title": "Modo de desenvolvedor",
|
||||
|
||||
@@ -11,7 +11,7 @@ export type DeviceLog = {
|
||||
severity: number;
|
||||
};
|
||||
|
||||
const getDeviceLogs = (limit: number, serialNumber?: string, logType?: 0 | 1) => async () =>
|
||||
const getDeviceLogs = (limit: number, serialNumber?: string, logType?: 0 | 1 | 2) => async () =>
|
||||
axiosGw
|
||||
.get(`device/${serialNumber}/logs?newest=true&limit=${limit}&logType=${logType}`)
|
||||
.then((response) => response.data) as Promise<{
|
||||
@@ -28,7 +28,7 @@ export const useGetDeviceLogs = ({
|
||||
serialNumber?: string;
|
||||
limit: number;
|
||||
onError?: (e: AxiosError) => void;
|
||||
logType?: 0 | 1;
|
||||
logType?: 0 | 1 | 2;
|
||||
}) =>
|
||||
useQuery(['devicelogs', serialNumber, { limit, logType }], getDeviceLogs(limit, serialNumber, logType ?? 0), {
|
||||
keepPreviousData: true,
|
||||
@@ -44,7 +44,7 @@ const deleteLogs = async ({
|
||||
}: {
|
||||
serialNumber: string;
|
||||
endDate: number;
|
||||
logType: 0 | 1;
|
||||
logType: 0 | 1 | 2;
|
||||
}) => axiosGw.delete(`device/${serialNumber}/logs?endDate=${endDate}&logType=${logType}`);
|
||||
export const useDeleteLogs = () => {
|
||||
const queryClient = useQueryClient();
|
||||
@@ -62,7 +62,7 @@ const getLogsBatch = (
|
||||
end?: number,
|
||||
limit?: number,
|
||||
offset?: number,
|
||||
logType?: 0 | 1,
|
||||
logType?: 0 | 1 | 2,
|
||||
) =>
|
||||
axiosGw
|
||||
.get(
|
||||
@@ -74,7 +74,7 @@ const getLogsBatch = (
|
||||
}>;
|
||||
|
||||
const getDeviceLogsWithTimestamps =
|
||||
(serialNumber?: string, start?: number, end?: number, logType?: 0 | 1) => async () => {
|
||||
(serialNumber?: string, start?: number, end?: number, logType?: 0 | 1 | 2) => async () => {
|
||||
let offset = 0;
|
||||
const limit = 100;
|
||||
let logs: DeviceLog[] = [];
|
||||
@@ -104,7 +104,7 @@ export const useGetDeviceLogsWithTimestamps = ({
|
||||
start?: number;
|
||||
end?: number;
|
||||
onError?: (e: AxiosError) => void;
|
||||
logType?: 0 | 1;
|
||||
logType?: 0 | 1 | 2;
|
||||
}) =>
|
||||
useQuery(
|
||||
['devicelogs', serialNumber, { start, end, logType }],
|
||||
|
||||
@@ -52,7 +52,7 @@ const CrashLogs = ({ serialNumber }: Props) => {
|
||||
setHiddenColumns={setHiddenColumns}
|
||||
preference="gateway.device.logs.hiddenColumns"
|
||||
/>
|
||||
<DeleteLogModal serialNumber={serialNumber} logType={0} />
|
||||
<DeleteLogModal serialNumber={serialNumber} logType={1} />
|
||||
<RefreshButton isCompact isFetching={getLogs.isFetching} onClick={getLogs.refetch} colorScheme="blue" />
|
||||
</HStack>
|
||||
</Flex>
|
||||
|
||||
@@ -16,7 +16,7 @@ const CustomInputButton = React.forwardRef(
|
||||
),
|
||||
);
|
||||
|
||||
type Props = { serialNumber: string; logType: 0 | 1 };
|
||||
type Props = { serialNumber: string; logType: 0 | 1 | 2 };
|
||||
const DeleteLogModal = ({ serialNumber, logType }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const toast = useToast();
|
||||
|
||||
94
src/pages/Device/LogsCard/LogHistory/RebootLogs.tsx
Normal file
94
src/pages/Device/LogsCard/LogHistory/RebootLogs.tsx
Normal file
@@ -0,0 +1,94 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Button, Center, Flex, Heading, HStack, Spacer } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import HistoryDatePickers from '../DatePickers';
|
||||
import DeleteLogModal from './DeleteModal';
|
||||
import useDeviceLogsTable from './useDeviceLogsTable';
|
||||
import { RefreshButton } from 'components/Buttons/RefreshButton';
|
||||
import { ColumnPicker } from 'components/DataTables/ColumnPicker';
|
||||
import { DataTable } from 'components/DataTables/DataTable';
|
||||
import { Column } from 'models/Table';
|
||||
|
||||
type Props = {
|
||||
serialNumber: string;
|
||||
};
|
||||
const RebootLogs = ({ serialNumber }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const [limit, setLimit] = React.useState(25);
|
||||
const [hiddenColumns, setHiddenColumns] = React.useState<string[]>([]);
|
||||
const { time, setTime, getCustomLogs, getLogs, columns, modal } = useDeviceLogsTable({
|
||||
serialNumber,
|
||||
limit,
|
||||
logType: 2,
|
||||
});
|
||||
|
||||
const setNewTime = (start: Date, end: Date) => {
|
||||
setTime({ start, end });
|
||||
};
|
||||
const onClear = () => {
|
||||
setTime(undefined);
|
||||
};
|
||||
const raiseLimit = () => {
|
||||
setLimit(limit + 25);
|
||||
};
|
||||
|
||||
const noMoreAvailable = getLogs.data !== undefined && getLogs.data.values.length < limit;
|
||||
|
||||
const data = React.useMemo(() => {
|
||||
if (getCustomLogs.data) return getCustomLogs.data.values.sort((a, b) => b.recorded - a.recorded);
|
||||
if (getLogs.data) return getLogs.data.values;
|
||||
return [];
|
||||
}, [getLogs.data, getCustomLogs.data]);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Flex>
|
||||
<Spacer />
|
||||
<HStack>
|
||||
<HistoryDatePickers defaults={time} setTime={setNewTime} onClear={onClear} />
|
||||
<ColumnPicker
|
||||
columns={columns as Column<unknown>[]}
|
||||
hiddenColumns={hiddenColumns}
|
||||
setHiddenColumns={setHiddenColumns}
|
||||
preference="gateway.device.logs.hiddenColumns"
|
||||
/>
|
||||
<DeleteLogModal serialNumber={serialNumber} logType={2} />
|
||||
<RefreshButton isCompact isFetching={getLogs.isFetching} onClick={getLogs.refetch} colorScheme="blue" />
|
||||
</HStack>
|
||||
</Flex>
|
||||
<Box overflowY="auto" h="300px">
|
||||
<DataTable
|
||||
columns={
|
||||
columns as {
|
||||
id: string;
|
||||
Header: string;
|
||||
Footer: string;
|
||||
accessor: string;
|
||||
}[]
|
||||
}
|
||||
data={data}
|
||||
isLoading={getLogs.isFetching || getCustomLogs.isFetching}
|
||||
hiddenColumns={hiddenColumns}
|
||||
obj={t('controller.devices.logs')}
|
||||
// @ts-ignore
|
||||
hideControls
|
||||
showAllRows
|
||||
/>
|
||||
{getLogs.data !== undefined && (
|
||||
<Center mt={1} hidden={getCustomLogs.data !== undefined}>
|
||||
{!noMoreAvailable || getLogs.isFetching ? (
|
||||
<Button colorScheme="blue" onClick={raiseLimit} isLoading={getLogs.isFetching}>
|
||||
{t('controller.devices.show_more')}
|
||||
</Button>
|
||||
) : (
|
||||
<Heading size="sm">{t('controller.devices.no_more_available')}!</Heading>
|
||||
)}
|
||||
</Center>
|
||||
)}
|
||||
</Box>
|
||||
{modal}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default RebootLogs;
|
||||
@@ -10,7 +10,7 @@ import { Column } from 'models/Table';
|
||||
type Props = {
|
||||
serialNumber: string;
|
||||
limit: number;
|
||||
logType: 0 | 1;
|
||||
logType: 0 | 1 | 2;
|
||||
};
|
||||
|
||||
const useDeviceLogsTable = ({ serialNumber, limit, logType }: Props) => {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import * as React from 'react';
|
||||
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react';
|
||||
import { Box, Tab, TabList, TabPanel, TabPanels, Tabs, useBreakpoint } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import CommandHistory from './CommandHistory';
|
||||
import HealthCheckHistory from './HealthCheckHistory';
|
||||
import LogHistory from './LogHistory';
|
||||
import CrashLogs from './LogHistory/CrashLogs';
|
||||
import RebootLogs from './LogHistory/RebootLogs';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { CardBody } from 'components/Containers/Card/CardBody';
|
||||
|
||||
@@ -13,12 +14,15 @@ type Props = {
|
||||
};
|
||||
const DeviceLogsCard = ({ serialNumber }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const breakpoint = useBreakpoint();
|
||||
const [tabIndex, setTabIndex] = React.useState(0);
|
||||
|
||||
const handleTabsChange = React.useCallback((index: number) => {
|
||||
setTabIndex(index);
|
||||
}, []);
|
||||
|
||||
const isCompact = breakpoint === 'base' || breakpoint === 'sm' || breakpoint === 'md' || breakpoint === 'lg';
|
||||
|
||||
return (
|
||||
<Card p={0} mb={4}>
|
||||
<CardBody p={0}>
|
||||
@@ -34,7 +38,10 @@ const DeviceLogsCard = ({ serialNumber }: Props) => {
|
||||
{t('controller.devices.logs')}
|
||||
</Tab>
|
||||
<Tab fontSize="lg" fontWeight="bold">
|
||||
{t('devices.crash_logs')}
|
||||
{isCompact ? 'Crashes' : t('devices.crash_logs')}
|
||||
</Tab>
|
||||
<Tab fontSize="lg" fontWeight="bold">
|
||||
{isCompact ? 'Reboots' : t('devices.reboot_logs')}
|
||||
</Tab>
|
||||
</TabList>
|
||||
<TabPanels>
|
||||
@@ -61,6 +68,9 @@ const DeviceLogsCard = ({ serialNumber }: Props) => {
|
||||
<TabPanel>
|
||||
<CrashLogs serialNumber={serialNumber} />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<RebootLogs serialNumber={serialNumber} />
|
||||
</TabPanel>
|
||||
</TabPanels>
|
||||
</Tabs>
|
||||
</CardBody>
|
||||
|
||||
Reference in New Issue
Block a user