[WIFI-12285] Add support for FMS database refreshes

Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
Charles
2023-02-09 16:55:48 +01:00
parent a14b595e8c
commit 9583b2bae0
11 changed files with 212 additions and 45 deletions

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.9.0(11)", "version": "2.9.0(12)",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.9.0(11)", "version": "2.9.0(12)",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chakra-ui/icons": "^2.0.11", "@chakra-ui/icons": "^2.0.11",

View File

@@ -1,6 +1,6 @@
{ {
"name": "ucentral-client", "name": "ucentral-client",
"version": "2.9.0(11)", "version": "2.9.0(12)",
"description": "", "description": "",
"private": true, "private": true,
"main": "index.tsx", "main": "index.tsx",

View File

@@ -685,6 +685,13 @@
"update_success": "Entität aktualisiert!", "update_success": "Entität aktualisiert!",
"venues_under_root": "Veranstaltungsorte können nicht direkt unter der Root-Entität erstellt werden" "venues_under_root": "Veranstaltungsorte können nicht direkt unter der Root-Entität erstellt werden"
}, },
"firmware": {
"db_update_warning": "Dieser Vorgang wird täglich automatisch durchgeführt, ohne dass dieses manuelle Update verwendet werden muss. Die Aktualisierung dieser Datenbank kann bis zu 25 Minuten dauern",
"last_db_update_modal": "Firmware-Datenbank",
"last_db_update_title": "Datenbank",
"start_db_update": "Datenbankaktualisierung starten",
"started_db_update": "Datenbankaktualisierung gestartet, dieser Vorgang sollte bis zu 25 Minuten dauern"
},
"footer": { "footer": {
"powered_by": "Unterstützt von", "powered_by": "Unterstützt von",
"version": "Ausführung" "version": "Ausführung"
@@ -1128,6 +1135,7 @@
"upgrade_all_devices": "Aktualisieren Sie alle Geräte auf die neueste Firmware", "upgrade_all_devices": "Aktualisieren Sie alle Geräte auf die neueste Firmware",
"upgrade_all_devices_error": "Fehler beim Aktualisieren von Geräten: {{e}}", "upgrade_all_devices_error": "Fehler beim Aktualisieren von Geräten: {{e}}",
"upgrade_all_devices_success": "Upgrade von Geräten erfolgreich gestartet!", "upgrade_all_devices_success": "Upgrade von Geräten erfolgreich gestartet!",
"upgrade_options_available": "Hier sind alle verfügbaren Revisionen, bitte wählen Sie diejenige aus, auf die ALLE Geräte dieses Veranstaltungsortes aktualisiert werden sollen",
"use_existing": "Benutze existierendes", "use_existing": "Benutze existierendes",
"use_existing_contacts": "Verwenden Sie vorhandene Kontakte", "use_existing_contacts": "Verwenden Sie vorhandene Kontakte",
"use_this_contact": "Verwenden Sie diesen Kontakt" "use_this_contact": "Verwenden Sie diesen Kontakt"

View File

@@ -685,6 +685,13 @@
"update_success": "Entity updated!", "update_success": "Entity updated!",
"venues_under_root": "Venues cannot be created directly under the root entity" "venues_under_root": "Venues cannot be created directly under the root entity"
}, },
"firmware": {
"db_update_warning": "This operation is done daily automatically without need to use this manual update. Updating this database can take up to 25 minutes",
"last_db_update_modal": "Firmware Database",
"last_db_update_title": "Database",
"start_db_update": "Start Database Update",
"started_db_update": "Started database update, this operation should take up to 25 minutes to complete"
},
"footer": { "footer": {
"powered_by": "Powered By", "powered_by": "Powered By",
"version": "Version" "version": "Version"
@@ -1128,6 +1135,7 @@
"upgrade_all_devices": "Upgrade All Devices to Latest Firmware", "upgrade_all_devices": "Upgrade All Devices to Latest Firmware",
"upgrade_all_devices_error": "Error upgrading devices: {{e}}", "upgrade_all_devices_error": "Error upgrading devices: {{e}}",
"upgrade_all_devices_success": "Successfully started upgrading devices!", "upgrade_all_devices_success": "Successfully started upgrading devices!",
"upgrade_options_available": "Here are all available revisions, please select the one you want ALL of this venue's devices to be upgrade to",
"use_existing": "Use Existing", "use_existing": "Use Existing",
"use_existing_contacts": "Use Existing Contacts", "use_existing_contacts": "Use Existing Contacts",
"use_this_contact": "Use this contact" "use_this_contact": "Use this contact"

View File

@@ -685,6 +685,13 @@
"update_success": "¡Entidad actualizada!", "update_success": "¡Entidad actualizada!",
"venues_under_root": "Los lugares no se pueden crear directamente bajo la entidad raíz" "venues_under_root": "Los lugares no se pueden crear directamente bajo la entidad raíz"
}, },
"firmware": {
"db_update_warning": "Esta operación se realiza automáticamente todos los días de forma automática sin necesidad de utilizar esta actualización manual. La actualización de esta base de datos puede tardar hasta 25 minutos",
"last_db_update_modal": "Base de datos de firmware",
"last_db_update_title": "Base de datos",
"start_db_update": "Iniciar actualización de la base de datos",
"started_db_update": "Actualización de la base de datos iniciada, esta operación debería tardar hasta 25 minutos en completarse"
},
"footer": { "footer": {
"powered_by": "energizado por", "powered_by": "energizado por",
"version": "Versión" "version": "Versión"
@@ -1128,6 +1135,7 @@
"upgrade_all_devices": "Actualice todos los dispositivos al firmware más reciente", "upgrade_all_devices": "Actualice todos los dispositivos al firmware más reciente",
"upgrade_all_devices_error": "Error al actualizar dispositivos: {{e}}", "upgrade_all_devices_error": "Error al actualizar dispositivos: {{e}}",
"upgrade_all_devices_success": "¡Comenzó con éxito la actualización de dispositivos!", "upgrade_all_devices_success": "¡Comenzó con éxito la actualización de dispositivos!",
"upgrade_options_available": "Aquí están todas las revisiones disponibles, seleccione la que desea que TODOS los dispositivos de este lugar se actualicen",
"use_existing": "Utilizar existente", "use_existing": "Utilizar existente",
"use_existing_contacts": "Usar contactos existentes", "use_existing_contacts": "Usar contactos existentes",
"use_this_contact": "Usa este contacto" "use_this_contact": "Usa este contacto"

View File

@@ -685,6 +685,13 @@
"update_success": "Entité mise à jour !", "update_success": "Entité mise à jour !",
"venues_under_root": "Les lieux ne peuvent pas être créés directement sous l'entité racine" "venues_under_root": "Les lieux ne peuvent pas être créés directement sous l'entité racine"
}, },
"firmware": {
"db_update_warning": "Cette opération se fait automatiquement quotidiennement sans avoir besoin d'utiliser cette mise à jour manuelle. La mise à jour de cette base de données peut prendre jusqu'à 25 minutes",
"last_db_update_modal": "Base de données du micrologiciel",
"last_db_update_title": "Base de données",
"start_db_update": "Démarrer la mise à jour de la base de données",
"started_db_update": "Mise à jour de la base de données démarrée, cette opération devrait prendre jusqu'à 25 minutes"
},
"footer": { "footer": {
"powered_by": "Alimenté par", "powered_by": "Alimenté par",
"version": "Version" "version": "Version"
@@ -1128,6 +1135,7 @@
"upgrade_all_devices": "Mettre à niveau tous les appareils vers le dernier micrologiciel", "upgrade_all_devices": "Mettre à niveau tous les appareils vers le dernier micrologiciel",
"upgrade_all_devices_error": "Erreur lors de la mise à jour des appareils : {{e}}", "upgrade_all_devices_error": "Erreur lors de la mise à jour des appareils : {{e}}",
"upgrade_all_devices_success": "La mise à niveau des appareils a démarré avec succès !", "upgrade_all_devices_success": "La mise à niveau des appareils a démarré avec succès !",
"upgrade_options_available": "Voici toutes les révisions disponibles, veuillez sélectionner celle vers laquelle vous souhaitez que TOUS les appareils de ce lieu soient mis à niveau",
"use_existing": "Utiliser l'existant", "use_existing": "Utiliser l'existant",
"use_existing_contacts": "Utiliser les contacts existants", "use_existing_contacts": "Utiliser les contacts existants",
"use_this_contact": "Utilisez ce contact" "use_this_contact": "Utilisez ce contact"

View File

@@ -685,6 +685,13 @@
"update_success": "Entidade atualizada!", "update_success": "Entidade atualizada!",
"venues_under_root": "Os locais não podem ser criados diretamente na entidade raiz" "venues_under_root": "Os locais não podem ser criados diretamente na entidade raiz"
}, },
"firmware": {
"db_update_warning": "Esta operação é feita automaticamente diariamente sem necessidade de usar esta atualização manual. A atualização deste banco de dados pode levar até 25 minutos",
"last_db_update_modal": "banco de dados de firmware",
"last_db_update_title": "base de dados",
"start_db_update": "Iniciar atualização do banco de dados",
"started_db_update": "Atualização do banco de dados iniciada, esta operação deve levar até 25 minutos para ser concluída"
},
"footer": { "footer": {
"powered_by": "Distribuído por", "powered_by": "Distribuído por",
"version": "Versão" "version": "Versão"
@@ -1128,6 +1135,7 @@
"upgrade_all_devices": "Atualize todos os dispositivos para o firmware mais recente", "upgrade_all_devices": "Atualize todos os dispositivos para o firmware mais recente",
"upgrade_all_devices_error": "Erro ao atualizar dispositivos: {{e}}", "upgrade_all_devices_error": "Erro ao atualizar dispositivos: {{e}}",
"upgrade_all_devices_success": "Atualização de dispositivos iniciada com sucesso!", "upgrade_all_devices_success": "Atualização de dispositivos iniciada com sucesso!",
"upgrade_options_available": "Aqui estão todas as revisões disponíveis, selecione aquela para a qual você deseja que TODOS os dispositivos deste local sejam atualizados",
"use_existing": "Usar existente", "use_existing": "Usar existente",
"use_existing_contacts": "Usar contatos existentes", "use_existing_contacts": "Usar contatos existentes",
"use_this_contact": "Use este contato" "use_this_contact": "Use este contato"

View File

@@ -32,7 +32,7 @@ export const useGetAvailableFirmware = ({ deviceType }: { deviceType: string })
const { t } = useTranslation(); const { t } = useTranslation();
const toast = useToast(); const toast = useToast();
return useQuery(['firmware'], () => getAllAvailableFirmware(deviceType), { return useQuery(['get-device-profile'], () => getAllAvailableFirmware(deviceType), {
enabled: deviceType !== '', enabled: deviceType !== '',
onError: (e: AxiosError) => { onError: (e: AxiosError) => {
if (!toast.isActive('firmware-fetching-error')) if (!toast.isActive('firmware-fetching-error'))
@@ -242,3 +242,23 @@ export const useGetFirmwareDashboard = () =>
keepPreviousData: true, keepPreviousData: true,
refetchInterval: 30000, refetchInterval: 30000,
}); });
const getLastDbUpdate = async () =>
axiosFms.get(`firmwares?updateTimeOnly=true`).then((response) => response.data as { lastUpdateTime: number });
export const useGetFirmwareDbUpdate = () =>
useQuery(['firmware', 'db'], getLastDbUpdate, {
keepPreviousData: true,
staleTime: 30 * 1000,
});
const updateDb = async () => axiosFms.put(`firmwares?update=true`);
export const useUpdateFirmwareDb = () => {
const queryClient = useQueryClient();
return useMutation(updateDb, {
onSuccess: () => {
queryClient.invalidateQueries(['firmware', 'db']);
},
});
};

View File

@@ -191,6 +191,7 @@ const FirmwareDetailsModal = ({ modalProps, firmware }: Props) => {
ml={2} ml={2}
/> />
{isEditingDescription && ( {isEditingDescription && (
// @ts-ignore
<SaveButton onClick={onSaveDescription} ml={2} isCompact size="sm" isLoading={updateFirmware.isLoading} /> <SaveButton onClick={onSaveDescription} ml={2} isCompact size="sm" isLoading={updateFirmware.isLoading} />
)} )}
</FormLabel> </FormLabel>
@@ -202,48 +203,51 @@ const FirmwareDetailsModal = ({ modalProps, firmware }: Props) => {
isDisabled={!isEditingDescription} isDisabled={!isEditingDescription}
/> />
</FormControl> </FormControl>
<FormControl>
<FormLabel>
{t('common.notes')}{' '}
<Popover trigger="click" placement="auto">
{({ onClose }) => (
<>
<PopoverTrigger>
<IconButton
aria-label={`${t('crud.add')} ${t('common.note')}`}
size="sm"
icon={<Plus size={20} />}
/>
</PopoverTrigger>
<PopoverContent w={breakpoint === 'base' ? 'calc(80vw)' : '500px'}>
<PopoverArrow />
<PopoverCloseButton alignContent="center" mt={1} />
<PopoverHeader display="flex">{t('profile.add_new_note')}</PopoverHeader>
<PopoverBody>
<Box>
<Textarea h="100px" placeholder="Your new note" value={newNote} onChange={onNoteChange} />
</Box>
<Center mt={2}>
<Button
colorScheme="blue"
isDisabled={newNote.length === 0}
onClick={onNoteSubmit(onClose)}
isLoading={updateFirmware.isLoading}
>
{t('crud.add')}
</Button>
</Center>
</PopoverBody>
</PopoverContent>
</>
)}
</Popover>
</FormLabel>
<Box overflowX="auto" overflowY="auto" maxH="400px">
<DataTable columns={columns as Column<object>[]} data={notes} obj={t('common.notes')} minHeight="200px" />
</Box>
</FormControl>
</SimpleGrid> </SimpleGrid>
<FormControl mt={2}>
<FormLabel>
{t('common.notes')}{' '}
<Popover trigger="click" placement="auto">
{({ onClose }) => (
<>
<PopoverTrigger>
<IconButton aria-label={`${t('crud.add')} ${t('common.note')}`} size="sm" icon={<Plus size={20} />} />
</PopoverTrigger>
<PopoverContent w={breakpoint === 'base' ? 'calc(80vw)' : '500px'}>
<PopoverArrow />
<PopoverCloseButton alignContent="center" mt={1} />
<PopoverHeader display="flex">{t('profile.add_new_note')}</PopoverHeader>
<PopoverBody>
<Box>
<Textarea h="100px" placeholder="Your new note" value={newNote} onChange={onNoteChange} />
</Box>
<Center mt={2}>
<Button
colorScheme="blue"
isDisabled={newNote.length === 0}
onClick={onNoteSubmit(onClose)}
isLoading={updateFirmware.isLoading}
>
{t('crud.add')}
</Button>
</Center>
</PopoverBody>
</PopoverContent>
</>
)}
</Popover>
</FormLabel>
</FormControl>
<Box overflowX="auto" overflowY="auto" maxH="400px" mb={4}>
<DataTable
columns={columns as Column<object>[]}
data={notes}
obj={t('common.notes')}
minHeight="200px"
showAllRows
hideControls
/>
</Box>
</Modal> </Modal>
); );
}; };

View File

@@ -0,0 +1,101 @@
import * as React from 'react';
import {
Alert,
AlertDescription,
AlertIcon,
AlertTitle,
Box,
Button,
Center,
Tag,
TagLabel,
Text,
useDisclosure,
useToast,
} from '@chakra-ui/react';
import axios from 'axios';
import { Database } from 'phosphor-react';
import { useTranslation } from 'react-i18next';
import FormattedDate from 'components/InformationDisplays/FormattedDate';
import { Modal } from 'components/Modals/Modal';
import { useGetFirmwareDbUpdate, useUpdateFirmwareDb } from 'hooks/Network/Firmware';
const UpdateDbButton = () => {
const { t } = useTranslation();
const toast = useToast();
const { isOpen, onOpen, onClose } = useDisclosure();
const updateDb = useUpdateFirmwareDb();
const getLastUpdate = useGetFirmwareDbUpdate();
const onUpdateClick = async () => {
updateDb.mutate(undefined, {
onSuccess: () => {
toast({
id: `firmware-db-update-success`,
title: t('common.success'),
description: t('firmware.started_db_update'),
status: 'success',
duration: 5000,
isClosable: true,
position: 'top-right',
});
},
onError: (e) => {
if (axios.isAxiosError(e)) {
toast({
id: `firmware-db-update-error`,
title: t('common.error'),
description: e?.response?.data?.ErrorDescription,
status: 'error',
duration: 5000,
isClosable: true,
position: 'top-right',
});
}
},
});
};
return (
<>
<Button colorScheme="teal" leftIcon={<Database size={20} />} onClick={onOpen}>
{t('firmware.last_db_update_title')}
</Button>
<Modal
isOpen={isOpen}
onClose={onClose}
title={t('firmware.last_db_update_modal')}
tags={
<Tag colorScheme="blue" size="lg">
<TagLabel display="flex">
<Text mr={1}>Last Update:</Text>
<FormattedDate date={getLastUpdate.data?.lastUpdateTime} />
</TagLabel>
</Tag>
}
>
<Box>
<Alert status="warning">
<AlertIcon />
<Box>
<AlertTitle>{t('common.warning')}</AlertTitle>
<AlertDescription>{t('firmware.db_update_warning')}</AlertDescription>
</Box>
</Alert>
<Center my={4}>
<Button
colorScheme="red"
leftIcon={<Database size={20} />}
onClick={onUpdateClick}
isLoading={updateDb.isLoading}
>
{t('firmware.start_db_update')}
</Button>
</Center>
</Box>
</Modal>
</>
);
};
export default UpdateDbButton;

View File

@@ -16,6 +16,7 @@ import { MagnifyingGlass } from 'phosphor-react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { v4 as uuid } from 'uuid'; import { v4 as uuid } from 'uuid';
import FirmwareDetailsModal from './Modal'; import FirmwareDetailsModal from './Modal';
import UpdateDbButton from './UpdateDbButton';
import UriCell from './UriCell'; import UriCell from './UriCell';
import { RefreshButton } from 'components/Buttons/RefreshButton'; import { RefreshButton } from 'components/Buttons/RefreshButton';
import { CardBody } from 'components/Containers/Card/CardBody'; import { CardBody } from 'components/Containers/Card/CardBody';
@@ -143,6 +144,7 @@ const FirmwareListTable = () => {
</Box> </Box>
<Text>{t('controller.firmware.show_dev_releases')}</Text> <Text>{t('controller.firmware.show_dev_releases')}</Text>
<Switch isChecked={showDevFirmware} onChange={toggle} size="lg" /> <Switch isChecked={showDevFirmware} onChange={toggle} size="lg" />
<UpdateDbButton />
<RefreshButton <RefreshButton
onClick={() => { onClick={() => {
getDeviceTypes.refetch(); getDeviceTypes.refetch();