mirror of
https://github.com/optim-enterprises-bv/OptimCloud-gw-ui.git
synced 2025-10-29 17:32:20 +00:00
[WIFI-11223] System page fixes
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.8.0(1)",
|
||||
"version": "2.8.0(2)",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ucentral-client",
|
||||
"version": "2.8.0(1)",
|
||||
"version": "2.8.0(2)",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@chakra-ui/icons": "^2.0.11",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "2.8.0(1)",
|
||||
"version": "2.8.0(2)",
|
||||
"description": "",
|
||||
"private": true,
|
||||
"main": "index.tsx",
|
||||
|
||||
@@ -610,6 +610,7 @@
|
||||
"new_devices": "Neue Geräte",
|
||||
"not_connected": "Nicht verbunden",
|
||||
"not_found_gateway": "Fehler: Gerät hat sich noch nicht mit dem Gateway verbunden",
|
||||
"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?",
|
||||
"sanity": "Gesundheit",
|
||||
@@ -878,6 +879,9 @@
|
||||
"endpoint": "Endpunkt",
|
||||
"hostname": "Hostname",
|
||||
"info": "Systeminformationen",
|
||||
"level": "Protokollstufe",
|
||||
"logging": "Protokollierung",
|
||||
"no_log_levels": "Keine gemeldeten Protokollebenen",
|
||||
"os": "Betriebssystem",
|
||||
"processors": "Prozessoren",
|
||||
"reload_chosen_subsystems": "Ausgewählte Subsysteme neu laden",
|
||||
@@ -886,6 +890,8 @@
|
||||
"success_reload": "Reload-Befehl erfolgreich gesendet!",
|
||||
"systems_to_reload": "Wählen Sie Systeme zum Neuladen aus",
|
||||
"title": "System",
|
||||
"update_level_success": "Loglevel aktualisiert!",
|
||||
"update_levels": "Aktualisieren",
|
||||
"uptime": "Betriebszeit",
|
||||
"version": "Ausführung"
|
||||
},
|
||||
|
||||
@@ -610,6 +610,7 @@
|
||||
"new_devices": "new devices",
|
||||
"not_connected": "Not Connected",
|
||||
"not_found_gateway": "Error: device has not yet connected to the controller",
|
||||
"notifications": "Device Notifications",
|
||||
"one": "Device",
|
||||
"reassign_already_owned": "Reassign devices which already exist and are owned by another entity/venue/subscriber?",
|
||||
"sanity": "Sanity",
|
||||
@@ -878,6 +879,9 @@
|
||||
"endpoint": "Endpoint",
|
||||
"hostname": "Host Name",
|
||||
"info": "System Info",
|
||||
"level": "Log Level",
|
||||
"logging": "Logging",
|
||||
"no_log_levels": "No Reported Log Levels ",
|
||||
"os": "Operating System",
|
||||
"processors": "Processors",
|
||||
"reload_chosen_subsystems": "Reload Chosen Subsystems",
|
||||
@@ -886,6 +890,8 @@
|
||||
"success_reload": "Successfully sent reload command!",
|
||||
"systems_to_reload": "Choose systems to reload",
|
||||
"title": "System",
|
||||
"update_level_success": "Updated log levels!",
|
||||
"update_levels": "Update",
|
||||
"uptime": "Uptime",
|
||||
"version": "Version"
|
||||
},
|
||||
|
||||
@@ -610,6 +610,7 @@
|
||||
"new_devices": "Nuevos dispositivos",
|
||||
"not_connected": "No conectado",
|
||||
"not_found_gateway": "Error: el dispositivo aún no se ha conectado a la puerta de enlace",
|
||||
"notifications": "notificaciones de dispositivos",
|
||||
"one": "Dispositivo",
|
||||
"reassign_already_owned": "¿Reasignar dispositivos que ya existen y son propiedad de otra entidad/lugar/suscriptor?",
|
||||
"sanity": "Cordura",
|
||||
@@ -878,6 +879,9 @@
|
||||
"endpoint": "punto final",
|
||||
"hostname": "Nombre de host",
|
||||
"info": "Información del sistema",
|
||||
"level": "nivel de registro",
|
||||
"logging": "Inicio sesión",
|
||||
"no_log_levels": "Niveles de registro no informados",
|
||||
"os": "sistema operativo",
|
||||
"processors": "Procesadores",
|
||||
"reload_chosen_subsystems": "Recargar subsistemas elegidos",
|
||||
@@ -886,6 +890,8 @@
|
||||
"success_reload": "¡Comando de recarga enviado con éxito!",
|
||||
"systems_to_reload": "Elige sistemas para recargar",
|
||||
"title": "Sistema",
|
||||
"update_level_success": "¡Niveles de registro actualizados!",
|
||||
"update_levels": "Actualizar",
|
||||
"uptime": "Tiempo de actividad",
|
||||
"version": "Versión"
|
||||
},
|
||||
|
||||
@@ -610,6 +610,7 @@
|
||||
"new_devices": "nouveaux appareils",
|
||||
"not_connected": "Pas connecté",
|
||||
"not_found_gateway": "Erreur : l'appareil n'est pas encore connecté à la passerelle",
|
||||
"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é ?",
|
||||
"sanity": "Santé mentale",
|
||||
@@ -878,6 +879,9 @@
|
||||
"endpoint": "Point final",
|
||||
"hostname": "nom d'hôte",
|
||||
"info": "Information système",
|
||||
"level": "niveau de journal",
|
||||
"logging": "Enregistrement",
|
||||
"no_log_levels": "Aucun niveau de journal signalé",
|
||||
"os": "Système opérateur",
|
||||
"processors": "Processeurs",
|
||||
"reload_chosen_subsystems": "Recharger les sous-systèmes choisis",
|
||||
@@ -886,6 +890,8 @@
|
||||
"success_reload": "Commande de rechargement envoyée avec succès !",
|
||||
"systems_to_reload": "Choisissez les systèmes à recharger",
|
||||
"title": "Système",
|
||||
"update_level_success": "Niveaux de journal mis à jour !",
|
||||
"update_levels": "Mettre à jour",
|
||||
"uptime": "La disponibilité",
|
||||
"version": "Version"
|
||||
},
|
||||
|
||||
@@ -610,6 +610,7 @@
|
||||
"new_devices": "novos dispositivos",
|
||||
"not_connected": "Não conectado",
|
||||
"not_found_gateway": "Erro: o dispositivo ainda não se conectou ao gateway",
|
||||
"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?",
|
||||
"sanity": "Sanidade",
|
||||
@@ -878,6 +879,9 @@
|
||||
"endpoint": "Ponto final",
|
||||
"hostname": "Nome de anfitrião",
|
||||
"info": "Informação do sistema",
|
||||
"level": "nível de log",
|
||||
"logging": "Exploração madeireira",
|
||||
"no_log_levels": "Nenhum nível de registro relatado",
|
||||
"os": "Sistema Operacional",
|
||||
"processors": "Processadores",
|
||||
"reload_chosen_subsystems": "Recarregar Subsistemas Escolhidos",
|
||||
@@ -886,6 +890,8 @@
|
||||
"success_reload": "Comando de recarga enviado com sucesso!",
|
||||
"systems_to_reload": "Escolha sistemas para recarregar",
|
||||
"title": "Sistema",
|
||||
"update_level_success": "Níveis de log atualizados!",
|
||||
"update_levels": "Atualizar",
|
||||
"uptime": "Tempo de atividade",
|
||||
"version": "Versão"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import { HStack, Modal as ChakraModal, ModalBody, ModalContent, ModalOverlay } from '@chakra-ui/react';
|
||||
import { HStack, LayoutProps, Modal as ChakraModal, ModalBody, ModalContent, ModalOverlay } from '@chakra-ui/react';
|
||||
import { ModalHeader } from '../GenericModal/ModalHeader';
|
||||
import { CloseButton } from 'components/Buttons/CloseButton';
|
||||
|
||||
@@ -10,12 +10,14 @@ export type ModalProps = {
|
||||
topRightButtons?: React.ReactNode;
|
||||
options?: {
|
||||
modalSize?: 'sm' | 'md' | 'lg';
|
||||
maxWidth?: LayoutProps['maxWidth'];
|
||||
};
|
||||
children: React.ReactElement;
|
||||
};
|
||||
|
||||
const _Modal = ({ isOpen, onClose, title, topRightButtons, options, children }: ModalProps) => {
|
||||
const maxWidth = React.useMemo(() => {
|
||||
if (options?.maxWidth) return options.maxWidth;
|
||||
if (options?.modalSize === 'sm') return undefined;
|
||||
if (options?.modalSize === 'lg') {
|
||||
return { sm: '90%', md: '900px', lg: '1000px', xl: '80%' };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useToast } from '@chakra-ui/react';
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import * as axios from 'axios';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AxiosError } from 'models/Axios';
|
||||
@@ -61,7 +61,7 @@ export const useGetSubsystems = ({
|
||||
},
|
||||
},
|
||||
)
|
||||
.then(({ data }: { data: { list: string[] } }) => data.list),
|
||||
.then(({ data }: { data: { list: string[] } }) => data.list ?? []),
|
||||
{
|
||||
staleTime: 60000,
|
||||
enabled,
|
||||
@@ -121,3 +121,81 @@ export const useReloadSubsystems = ({
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
export const useGetSystemLogLevels = ({
|
||||
endpoint,
|
||||
enabled,
|
||||
token,
|
||||
}: {
|
||||
endpoint: string;
|
||||
enabled: boolean;
|
||||
token: string;
|
||||
}) =>
|
||||
useQuery(
|
||||
['get-log-levels', endpoint],
|
||||
() =>
|
||||
axiosInstance
|
||||
.post(
|
||||
`${endpoint}/api/v1/system`,
|
||||
{ command: 'getloglevels' },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
},
|
||||
)
|
||||
.then(({ data }: { data: { tagList: { tag: string; value: string }[] } }) => data.tagList ?? []),
|
||||
{
|
||||
staleTime: 60000,
|
||||
enabled,
|
||||
},
|
||||
);
|
||||
|
||||
export const useGetSystemLogLevelNames = ({
|
||||
endpoint,
|
||||
enabled,
|
||||
token,
|
||||
}: {
|
||||
endpoint: string;
|
||||
enabled: boolean;
|
||||
token: string;
|
||||
}) =>
|
||||
useQuery(
|
||||
['get-log-level-names', endpoint],
|
||||
() =>
|
||||
axiosInstance
|
||||
.post(
|
||||
`${endpoint}/api/v1/system`,
|
||||
{ command: 'getloglevelnames' },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
},
|
||||
)
|
||||
.then(({ data }: { data: { list: string[] } }) => data.list ?? []),
|
||||
{
|
||||
staleTime: 60000,
|
||||
enabled,
|
||||
},
|
||||
);
|
||||
|
||||
const changeLogLevel = (endpoint: string, token: string) => async (subsystems: { tag: string; value: string }[]) =>
|
||||
axiosInstance.post(
|
||||
`${endpoint}/api/v1/system`,
|
||||
{ command: 'setloglevel', subsystems },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
export const useUpdateSystemLogLevels = ({ endpoint, token }: { endpoint: string; token: string }) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation(changeLogLevel(endpoint, token), {
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries(['get-log-levels', endpoint]);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
@@ -29,10 +29,10 @@ const LogsCard = () => {
|
||||
<Td fontFamily="monospace" pt={2} fontSize="md">
|
||||
{msg.data?.serialNumber ?? '-'}
|
||||
</Td>
|
||||
<Td>
|
||||
<Td whiteSpace="nowrap">
|
||||
<Box>{labels[msg.data.type] ?? msg.data.type}</Box>
|
||||
</Td>
|
||||
<Td>{JSON.stringify(msg.data)}</Td>
|
||||
<Td whiteSpace="nowrap">{JSON.stringify(msg.data)}</Td>
|
||||
</Tr>
|
||||
);
|
||||
}
|
||||
@@ -42,10 +42,10 @@ const LogsCard = () => {
|
||||
<Td fontFamily="monospace" pt={2} fontSize="md">
|
||||
-
|
||||
</Td>
|
||||
<Td>
|
||||
<Td whiteSpace="nowrap">
|
||||
<Box>{t('common.unknown')}</Box>
|
||||
</Td>
|
||||
<Td>{JSON.stringify(msg.data)}</Td>
|
||||
<Td whiteSpace="nowrap">{JSON.stringify(msg.data)}</Td>
|
||||
</Tr>
|
||||
);
|
||||
},
|
||||
@@ -99,7 +99,7 @@ const LogsCard = () => {
|
||||
<Th w="100px">{t('common.time')}</Th>
|
||||
<Th w="140px">{t('inventory.serial_number')}</Th>
|
||||
<Th w="200px">{t('common.type')}</Th>
|
||||
<Th minW="60%">{t('analytics.raw_data')}</Th>
|
||||
<Th minW="100%">{t('analytics.raw_data')}</Th>
|
||||
</Thead>
|
||||
<Tbody>{rows}</Tbody>
|
||||
</Table>
|
||||
|
||||
189
src/pages/SystemPage/SystemTile/LoggingButton/Modal.tsx
Normal file
189
src/pages/SystemPage/SystemTile/LoggingButton/Modal.tsx
Normal file
@@ -0,0 +1,189 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertIcon,
|
||||
Box,
|
||||
Button,
|
||||
Center,
|
||||
Heading,
|
||||
Select,
|
||||
Table,
|
||||
Tbody,
|
||||
Td,
|
||||
Th,
|
||||
Thead,
|
||||
Tr,
|
||||
UseDisclosureReturn,
|
||||
useToast,
|
||||
} from '@chakra-ui/react';
|
||||
import axios from 'axios';
|
||||
import { FloppyDisk } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { LoadingOverlay } from 'components/LoadingOverlay';
|
||||
import { Modal } from 'components/Modals/Modal';
|
||||
import { useGetSystemLogLevelNames, useGetSystemLogLevels, useUpdateSystemLogLevels } from 'hooks/Network/System';
|
||||
|
||||
type Props = {
|
||||
modalProps: UseDisclosureReturn;
|
||||
endpoint: string;
|
||||
token: string;
|
||||
};
|
||||
|
||||
const SystemLoggingModal = ({ modalProps, endpoint, token }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const toast = useToast();
|
||||
const getLevels = useGetSystemLogLevels({ endpoint, token, enabled: false });
|
||||
const getNames = useGetSystemLogLevelNames({ endpoint, token, enabled: false });
|
||||
const updateLevels = useUpdateSystemLogLevels({ endpoint, token });
|
||||
const [newLevels, setNewLevels] = React.useState<{ tag: string; value: string }[]>([]);
|
||||
|
||||
const onUpdate = () => {
|
||||
updateLevels.mutate(newLevels, {
|
||||
onSuccess: () => {
|
||||
toast({
|
||||
id: 'log-level-update-success',
|
||||
title: t('common.success'),
|
||||
description: t('system.update_level_success'),
|
||||
status: 'success',
|
||||
duration: 5000,
|
||||
isClosable: true,
|
||||
position: 'top-right',
|
||||
});
|
||||
modalProps.onClose();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onLevelChange = React.useCallback(
|
||||
(tag: string, originalValue: string) => (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
if (e.target.value === originalValue) {
|
||||
setNewLevels((prev) => prev.filter((level) => level.tag !== tag));
|
||||
} else {
|
||||
setNewLevels((prev) => [
|
||||
...prev.filter(({ tag: foundTag }) => foundTag !== tag),
|
||||
{ tag, value: e.target.value },
|
||||
]);
|
||||
}
|
||||
},
|
||||
[newLevels, getLevels.data],
|
||||
);
|
||||
|
||||
const levelOptions = getNames.data
|
||||
? getNames.data
|
||||
.sort((a, b) => a.localeCompare(b))
|
||||
.map((level) => (
|
||||
<option key={uuid()} value={level}>
|
||||
{level}
|
||||
</option>
|
||||
))
|
||||
: [];
|
||||
const row = React.useCallback(
|
||||
(tag: string, value: string) => {
|
||||
const newValue = newLevels.find(({ tag: foundTag }) => foundTag === tag)?.value;
|
||||
return (
|
||||
<Tr key={uuid()}>
|
||||
<Td>
|
||||
<Heading size="sm">{tag}</Heading>
|
||||
</Td>
|
||||
<Td fontFamily="monospace" pt={2} fontSize="md">
|
||||
{getNames.data ? (
|
||||
<Select
|
||||
variant={newValue ? 'filled' : undefined}
|
||||
_hover={{
|
||||
bg: newValue ? 'teal.300' : undefined,
|
||||
}}
|
||||
bg={newValue ? 'teal.300' : undefined}
|
||||
value={newValue ?? value}
|
||||
onChange={onLevelChange(tag, value)}
|
||||
>
|
||||
{levelOptions}
|
||||
</Select>
|
||||
) : (
|
||||
value
|
||||
)}
|
||||
</Td>
|
||||
</Tr>
|
||||
);
|
||||
},
|
||||
[t, getNames.data, onLevelChange],
|
||||
);
|
||||
|
||||
const rows = React.useMemo(() => {
|
||||
if (!getLevels.data) return [];
|
||||
|
||||
return getLevels.data.sort((a, b) => a.tag.localeCompare(b.tag)).map((level) => row(level.tag, level.value));
|
||||
}, [getLevels.data, row]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (modalProps.isOpen) {
|
||||
setNewLevels([]);
|
||||
getLevels.refetch();
|
||||
getNames.refetch();
|
||||
}
|
||||
}, [modalProps.isOpen]);
|
||||
|
||||
React.useEffect(() => {
|
||||
setNewLevels([]);
|
||||
}, [getLevels.data]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={modalProps.isOpen}
|
||||
onClose={modalProps.onClose}
|
||||
title={t('system.logging')}
|
||||
options={{
|
||||
modalSize: 'sm',
|
||||
maxWidth: { sm: '600px', md: '600px', lg: '600px', xl: '600px' },
|
||||
}}
|
||||
topRightButtons={
|
||||
<Button
|
||||
colorScheme="blue"
|
||||
rightIcon={<FloppyDisk size={20} />}
|
||||
onClick={onUpdate}
|
||||
isDisabled={newLevels.length === 0}
|
||||
isLoading={updateLevels.isLoading}
|
||||
>
|
||||
{t('system.update_levels')} {newLevels.length > 0 ? newLevels.length : ''}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
<>
|
||||
{updateLevels.error && (
|
||||
<Alert status="error">
|
||||
<AlertIcon />
|
||||
<AlertDescription>
|
||||
{axios.isAxiosError(updateLevels.error)
|
||||
? updateLevels.error.response?.data?.ErrorDescription
|
||||
: t('common.error')}
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
<LoadingOverlay isLoading={getLevels.isFetching}>
|
||||
<Box overflowX="auto">
|
||||
<Table size="sm">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t('system.subsystems')}</Th>
|
||||
<Th w="220px">{t('system.level')}</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>{rows}</Tbody>
|
||||
</Table>
|
||||
{getLevels.data && rows.length === 0 ? (
|
||||
<Center mt={2}>
|
||||
<Alert status="info" w="unset">
|
||||
<AlertIcon />
|
||||
<AlertDescription>{t('system.no_log_levels')}</AlertDescription>
|
||||
</Alert>
|
||||
</Center>
|
||||
) : null}
|
||||
</Box>
|
||||
</LoadingOverlay>
|
||||
</>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default SystemLoggingModal;
|
||||
26
src/pages/SystemPage/SystemTile/LoggingButton/index.tsx
Normal file
26
src/pages/SystemPage/SystemTile/LoggingButton/index.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import * as React from 'react';
|
||||
import { Button, useDisclosure } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SystemLoggingModal from './Modal';
|
||||
import { EndpointApiResponse } from 'hooks/Network/Endpoints';
|
||||
|
||||
type Props = {
|
||||
endpoint: EndpointApiResponse;
|
||||
token: string;
|
||||
};
|
||||
|
||||
const SystemLoggingButton = ({ endpoint, token }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const modalProps = useDisclosure();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button colorScheme="teal" onClick={modalProps.onOpen} mr={2} my="auto">
|
||||
{t('system.logging')}
|
||||
</Button>
|
||||
<SystemLoggingModal modalProps={modalProps} endpoint={endpoint.uri} token={token} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SystemLoggingButton;
|
||||
@@ -18,7 +18,10 @@ const SystemCertificatesTable: React.FC<Props> = ({ certificates }) => {
|
||||
const memoizedExpiry = useCallback((expiresOn: number) => compactDate(expiresOn), []);
|
||||
|
||||
const columns = React.useMemo(
|
||||
(): Column<{ expiresOn: number; filename: string }>[] => [
|
||||
(): Column<{
|
||||
expiresOn: number;
|
||||
filename: string;
|
||||
}>[] => [
|
||||
{
|
||||
id: 'expiresOn',
|
||||
Header: t('certificates.expires_on'),
|
||||
@@ -41,7 +44,7 @@ const SystemCertificatesTable: React.FC<Props> = ({ certificates }) => {
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
columns={columns}
|
||||
columns={columns as Column<object>[]}
|
||||
data={certificates ?? []}
|
||||
obj={t('certificates.title')}
|
||||
hideControls
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
import { MultiValue, Select } from 'chakra-react-select';
|
||||
import { ArrowsClockwise } from 'phosphor-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SystemLoggingButton from './LoggingButton';
|
||||
import SystemCertificatesTable from './SystemCertificatesTable';
|
||||
import { Card } from 'components/Containers/Card';
|
||||
import { CardBody } from 'components/Containers/Card/CardBody';
|
||||
@@ -32,7 +33,7 @@ interface Props {
|
||||
token: string;
|
||||
}
|
||||
|
||||
const SystemTile: React.FC<Props> = ({ endpoint, token }) => {
|
||||
const SystemTile = ({ endpoint, token }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const [subs, setSubs] = useState<{ value: string; label: string }[]>([]);
|
||||
@@ -68,6 +69,7 @@ const SystemTile: React.FC<Props> = ({ endpoint, token }) => {
|
||||
<Box display="flex" mb={2}>
|
||||
<Heading pt={0}>{endpoint.type}</Heading>
|
||||
<Spacer />
|
||||
<SystemLoggingButton endpoint={endpoint} token={token} />
|
||||
<Button
|
||||
mt={1}
|
||||
minWidth="112px"
|
||||
@@ -83,35 +85,51 @@ const SystemTile: React.FC<Props> = ({ endpoint, token }) => {
|
||||
<VStack w="100%">
|
||||
<SimpleGrid minChildWidth="500px" w="100%">
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.endpoint')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.endpoint')}:
|
||||
</Heading>
|
||||
{endpoint.uri}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.hostname')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.hostname')}:
|
||||
</Heading>
|
||||
{system?.hostname}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.os')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.os')}:
|
||||
</Heading>
|
||||
{system?.os}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.processors')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.processors')}:
|
||||
</Heading>
|
||||
{system?.processors}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.start')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.start')}:
|
||||
</Heading>
|
||||
{system?.start ? <FormattedDate date={system?.start} /> : '-'}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.uptime')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.uptime')}:
|
||||
</Heading>
|
||||
{system?.uptime ? compactSecondsToDetailed(system.uptime, t) : '-'}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('system.version')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.version')}:
|
||||
</Heading>
|
||||
{system?.version}
|
||||
</Flex>
|
||||
<Flex>
|
||||
<Box w="150px">{t('certificates.title')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('certificates.title')}:
|
||||
</Heading>
|
||||
{system?.certificates && system.certificates?.length > 0 ? (
|
||||
<Button variant="link" onClick={onOpen} p={0} m={0} maxH={7}>
|
||||
{t('common.details')} {system.certificates.length}
|
||||
@@ -122,7 +140,9 @@ const SystemTile: React.FC<Props> = ({ endpoint, token }) => {
|
||||
</Flex>
|
||||
</SimpleGrid>
|
||||
<Flex w="100%">
|
||||
<Box w="150px">{t('system.subsystems')}:</Box>
|
||||
<Heading size="sm" w="150px" my="auto">
|
||||
{t('system.subsystems')}:
|
||||
</Heading>
|
||||
<Box w="400px">
|
||||
<Select
|
||||
chakraStyles={{
|
||||
|
||||
@@ -31,13 +31,13 @@ const SystemPage = () => {
|
||||
.map((endpoint) => <SystemTile key={uuid()} endpoint={endpoint} token={token} />);
|
||||
}, [endpoints, token, isUserLoaded]);
|
||||
|
||||
if (!isUserLoaded) return null;
|
||||
|
||||
return (
|
||||
<Flex flexDirection="column" pt="75px">
|
||||
{isUserLoaded ? (
|
||||
<SimpleGrid minChildWidth="500px" spacing="20px" mb={3}>
|
||||
{endpointsList}
|
||||
</SimpleGrid>
|
||||
) : null}
|
||||
<SimpleGrid minChildWidth="500px" spacing="20px" mb={3}>
|
||||
{endpointsList}
|
||||
</SimpleGrid>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user