mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw-ui.git
synced 2025-10-29 18:02:31 +00:00
18
package-lock.json
generated
18
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "2.3.2",
|
||||
"version": "2.3.9",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ucentral-client",
|
||||
"version": "2.3.2",
|
||||
"version": "2.3.9",
|
||||
"dependencies": {
|
||||
"@coreui/coreui": "^3.4.0",
|
||||
"@coreui/icons": "^2.0.1",
|
||||
@@ -32,7 +32,7 @@
|
||||
"react-tooltip": "^4.2.21",
|
||||
"react-widgets": "^5.1.1",
|
||||
"sass": "^1.35.1",
|
||||
"ucentral-libs": "^0.9.89",
|
||||
"ucentral-libs": "^0.9.98",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -14842,9 +14842,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ucentral-libs": {
|
||||
"version": "0.9.89",
|
||||
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.89.tgz",
|
||||
"integrity": "sha512-KH1RSQzN7AJTsryibxr3kfoYgr1Y80lQP5cB8mOcbqYamv3PS9F2QJHTQNoNOwQGASFd6D+WdnAj/viqV1wM0A==",
|
||||
"version": "0.9.98",
|
||||
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.98.tgz",
|
||||
"integrity": "sha512-Fwn0sqFS2u5bIN5gtbslgAZnki2J4iz6ucGVJmKdvghm+E45+KYFC2yGWGNlBfBkKIsSDlSIIhQHFEo0JTTCZg==",
|
||||
"dependencies": {
|
||||
"@coreui/coreui": "^3.4.0",
|
||||
"@coreui/icons": "^2.0.1",
|
||||
@@ -27716,9 +27716,9 @@
|
||||
}
|
||||
},
|
||||
"ucentral-libs": {
|
||||
"version": "0.9.89",
|
||||
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.89.tgz",
|
||||
"integrity": "sha512-KH1RSQzN7AJTsryibxr3kfoYgr1Y80lQP5cB8mOcbqYamv3PS9F2QJHTQNoNOwQGASFd6D+WdnAj/viqV1wM0A==",
|
||||
"version": "0.9.98",
|
||||
"resolved": "https://registry.npmjs.org/ucentral-libs/-/ucentral-libs-0.9.98.tgz",
|
||||
"integrity": "sha512-Fwn0sqFS2u5bIN5gtbslgAZnki2J4iz6ucGVJmKdvghm+E45+KYFC2yGWGNlBfBkKIsSDlSIIhQHFEo0JTTCZg==",
|
||||
"requires": {
|
||||
"@coreui/coreui": "^3.4.0",
|
||||
"@coreui/icons": "^2.0.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ucentral-client",
|
||||
"version": "2.3.2",
|
||||
"version": "2.3.9",
|
||||
"dependencies": {
|
||||
"@coreui/coreui": "^3.4.0",
|
||||
"@coreui/icons": "^2.0.1",
|
||||
@@ -26,7 +26,7 @@
|
||||
"react-tooltip": "^4.2.21",
|
||||
"react-widgets": "^5.1.1",
|
||||
"sass": "^1.35.1",
|
||||
"ucentral-libs": "^0.9.89",
|
||||
"ucentral-libs": "^0.9.98",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"main": "index.js",
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"access_policy": "Zugangsrichtlinien",
|
||||
"add": "Hinzufügen",
|
||||
"add_items": "Füge Artikel hinzu",
|
||||
"add_note": "Notiz hinzufügen",
|
||||
"add_note_explanation": "Schreiben Sie unten Ihre neue Notiz und klicken Sie auf die Schaltfläche \"+\", wo Sie fertig sind",
|
||||
"adding_ellipsis": "Hinzufügen ...",
|
||||
"are_you_sure": "Bist du sicher?",
|
||||
"back_to_login": "Zurück zur Anmeldung",
|
||||
@@ -89,6 +91,7 @@
|
||||
"endpoints": "Endpunkte",
|
||||
"error": "Fehler",
|
||||
"error_adding_note": "Fehler beim Hinzufügen einer Notiz",
|
||||
"error_code": "Fehlercode",
|
||||
"execute_now": "Möchten Sie diesen Befehl jetzt ausführen?",
|
||||
"executed": "Ausgeführt",
|
||||
"exit": "Ausgang",
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"access_policy": "Access Policy",
|
||||
"add": "Add",
|
||||
"add_items": "Add Items",
|
||||
"add_note": "Add Note",
|
||||
"add_note_explanation": "Write your new note below and click the '+' button where you are done",
|
||||
"adding_ellipsis": "Adding...",
|
||||
"are_you_sure": "Are you sure?",
|
||||
"back_to_login": "Back to Login",
|
||||
@@ -89,6 +91,7 @@
|
||||
"endpoints": "Endpoints",
|
||||
"error": "Error",
|
||||
"error_adding_note": "Error while adding note",
|
||||
"error_code": "Error Code",
|
||||
"execute_now": "Would you like to execute this command now?",
|
||||
"executed": "Executed",
|
||||
"exit": "Exit",
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"access_policy": "Política de acceso",
|
||||
"add": "Añadir",
|
||||
"add_items": "Agregar articulos",
|
||||
"add_note": "Añadir la nota",
|
||||
"add_note_explanation": "Escriba su nueva nota a continuación y haga clic en el botón '+' donde haya terminado",
|
||||
"adding_ellipsis": "Añadiendo ...",
|
||||
"are_you_sure": "¿Estás seguro?",
|
||||
"back_to_login": "Atrás para iniciar sesión",
|
||||
@@ -89,6 +91,7 @@
|
||||
"endpoints": "Puntos finales",
|
||||
"error": "Error",
|
||||
"error_adding_note": "Error al agregar una nota",
|
||||
"error_code": "código de error",
|
||||
"execute_now": "¿Le gustaría ejecutar este comando ahora?",
|
||||
"executed": "ejecutado",
|
||||
"exit": "salida",
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"access_policy": "Politique d'accès",
|
||||
"add": "Ajouter",
|
||||
"add_items": "Ajouter des articles",
|
||||
"add_note": "Ajouter une note",
|
||||
"add_note_explanation": "Écrivez votre nouvelle note ci-dessous et cliquez sur le bouton '+' où vous avez terminé",
|
||||
"adding_ellipsis": "Ajouter...",
|
||||
"are_you_sure": "Êtes-vous sûr?",
|
||||
"back_to_login": "Retour connexion",
|
||||
@@ -89,6 +91,7 @@
|
||||
"endpoints": "Points de terminaison",
|
||||
"error": "Erreur",
|
||||
"error_adding_note": "Erreur lors de l'ajout de la note",
|
||||
"error_code": "Code d'erreur",
|
||||
"execute_now": "Souhaitez-vous exécuter cette commande maintenant ?",
|
||||
"executed": "réalisé",
|
||||
"exit": "Sortie",
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
"access_policy": "Política de Acesso",
|
||||
"add": "Adicionar",
|
||||
"add_items": "Adicionar itens",
|
||||
"add_note": "Adicionar nota",
|
||||
"add_note_explanation": "Escreva sua nova nota abaixo e clique no botão '+' quando terminar",
|
||||
"adding_ellipsis": "Adicionando ...",
|
||||
"are_you_sure": "Você tem certeza?",
|
||||
"back_to_login": "Volte ao login",
|
||||
@@ -89,6 +91,7 @@
|
||||
"endpoints": "Pontos finais",
|
||||
"error": "Erro",
|
||||
"error_adding_note": "Erro ao adicionar nota",
|
||||
"error_code": "Erro de código",
|
||||
"execute_now": "Você gostaria de executar este comando agora?",
|
||||
"executed": "Executado",
|
||||
"exit": "Saída",
|
||||
|
||||
@@ -14,11 +14,11 @@ import {
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import DatePicker from 'react-widgets/DatePicker';
|
||||
import { cilCloudDownload, cilSync, cilCalendarCheck } from '@coreui/icons';
|
||||
import { prettyDate, dateToUnix } from 'utils/helper';
|
||||
import { dateToUnix } from 'utils/helper';
|
||||
import axiosInstance from 'utils/axiosInstance';
|
||||
import eventBus from 'utils/eventBus';
|
||||
import ConfirmModal from 'components/ConfirmModal';
|
||||
import { LoadingButton, useAuth, useDevice } from 'ucentral-libs';
|
||||
import { LoadingButton, useAuth, useDevice, FormattedDate } from 'ucentral-libs';
|
||||
import WifiScanResultModalWidget from 'components/WifiScanResultModal';
|
||||
import DetailsModal from './DetailsModal';
|
||||
|
||||
@@ -190,9 +190,9 @@ const DeviceCommands = () => {
|
||||
const columns = [
|
||||
{ key: 'submitted', label: t('common.submitted'), filter: false, _style: { width: '20%' } },
|
||||
{ key: 'command', label: t('common.command'), _style: { width: '15%' } },
|
||||
{ key: 'executed', label: t('common.executed'), filter: false, _style: { width: '20%' } },
|
||||
{ key: 'completed', label: t('common.completed'), filter: false, _style: { width: '20%' } },
|
||||
{ key: 'errorCode', label: t('common.code'), filter: false, _style: { width: '5%' } },
|
||||
{ key: 'executed', label: t('common.executed'), filter: false, _style: { width: '16%' } },
|
||||
{ key: 'completed', label: t('common.completed'), filter: false, _style: { width: '16%' } },
|
||||
{ key: 'errorCode', label: t('common.error_code'), filter: false, _style: { width: '8%' } },
|
||||
{
|
||||
key: 'show_buttons',
|
||||
label: '',
|
||||
@@ -265,6 +265,7 @@ const DeviceCommands = () => {
|
||||
<CCard>
|
||||
<div className="overflow-auto" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
border
|
||||
loading={loading}
|
||||
items={commands ?? []}
|
||||
@@ -272,25 +273,32 @@ const DeviceCommands = () => {
|
||||
className="text-white"
|
||||
sorterValue={{ column: 'created', desc: 'true' }}
|
||||
scopedSlots={{
|
||||
command: (item) => <td className="align-middle">{item.command}</td>,
|
||||
completed: (item) => (
|
||||
<td className="align-middle">
|
||||
{item.completed && item.completed !== 0
|
||||
? prettyDate(item.completed)
|
||||
: 'Pending'}
|
||||
{item.completed && item.completed !== 0 ? (
|
||||
<FormattedDate date={item.completed} />
|
||||
) : (
|
||||
'Pending'
|
||||
)}
|
||||
</td>
|
||||
),
|
||||
executed: (item) => (
|
||||
<td className="align-middle">
|
||||
{item.executed && item.executed !== 0
|
||||
? prettyDate(item.executed)
|
||||
: 'Pending'}
|
||||
{item.executed && item.executed !== 0 ? (
|
||||
<FormattedDate date={item.executed} />
|
||||
) : (
|
||||
'Pending'
|
||||
)}
|
||||
</td>
|
||||
),
|
||||
submitted: (item) => (
|
||||
<td className="align-middle">
|
||||
{item.submitted && item.submitted !== ''
|
||||
? prettyDate(item.submitted)
|
||||
: 'Pending'}
|
||||
{item.submitted && item.submitted !== '' ? (
|
||||
<FormattedDate date={item.submitted} />
|
||||
) : (
|
||||
'Pending'
|
||||
)}
|
||||
</td>
|
||||
),
|
||||
errorCode: (item) => <td className="align-middle">{item.errorCode}</td>,
|
||||
@@ -299,7 +307,7 @@ const DeviceCommands = () => {
|
||||
<CButtonToolbar
|
||||
role="group"
|
||||
className="justify-content-flex-end"
|
||||
style={{ width: '170px' }}
|
||||
style={{ width: '160px' }}
|
||||
>
|
||||
<CPopover
|
||||
content={
|
||||
@@ -320,13 +328,13 @@ const DeviceCommands = () => {
|
||||
<CIcon
|
||||
name="cil-cloud-download"
|
||||
content={cilCloudDownload}
|
||||
size="lg"
|
||||
size="md"
|
||||
/>
|
||||
) : (
|
||||
<CIcon
|
||||
name="cil-calendar-check"
|
||||
content={cilCalendarCheck}
|
||||
size="lg"
|
||||
size="md"
|
||||
/>
|
||||
)}
|
||||
</CButton>
|
||||
@@ -342,7 +350,7 @@ const DeviceCommands = () => {
|
||||
toggleResponse(item);
|
||||
}}
|
||||
>
|
||||
<CIcon name="cilList" size="lg" />
|
||||
<CIcon name="cilList" size="md" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.delete')}>
|
||||
@@ -356,7 +364,7 @@ const DeviceCommands = () => {
|
||||
toggleConfirmModal(item.UUID, index);
|
||||
}}
|
||||
>
|
||||
<CIcon name="cilTrash" size="lg" />
|
||||
<CIcon name="cilTrash" size="mdå" />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</CButtonToolbar>
|
||||
|
||||
@@ -20,11 +20,11 @@ const ConfigurationDisplay = ({ getData, deviceConfig }) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<CCard className="m-0">
|
||||
<CCardHeader className="p-1">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="d-flex flex-row-reverse align-items-center">
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.refresh')}>
|
||||
<CButton size="sm" color="primary" variant="outline" onClick={getData}>
|
||||
<CButton size="sm" color="info" onClick={getData}>
|
||||
<CIcon content={cilSync} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
|
||||
@@ -122,7 +122,7 @@ const DeviceActions = () => {
|
||||
|
||||
return (
|
||||
<CCard>
|
||||
<CCardHeader className="p-1">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="text-value-lg">{t('actions.title')}</div>
|
||||
</CCardHeader>
|
||||
<CCardBody>
|
||||
|
||||
@@ -14,10 +14,10 @@ import CIcon from '@coreui/icons-react';
|
||||
import { cilTrash } from '@coreui/icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import DatePicker from 'react-widgets/DatePicker';
|
||||
import { prettyDate, dateToUnix } from 'utils/helper';
|
||||
import { dateToUnix } from 'utils/helper';
|
||||
import axiosInstance from 'utils/axiosInstance';
|
||||
import eventBus from 'utils/eventBus';
|
||||
import { LoadingButton, useAuth, useDevice } from 'ucentral-libs';
|
||||
import { LoadingButton, useAuth, useDevice, FormattedDate } from 'ucentral-libs';
|
||||
import DeleteLogModal from 'components/DeleteLogModal';
|
||||
|
||||
const DeviceHealth = () => {
|
||||
@@ -181,6 +181,7 @@ const DeviceHealth = () => {
|
||||
<CCard className="p-0">
|
||||
<div className="overflow-auto" style={{ height: '200px' }}>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
border
|
||||
items={healthChecks ?? []}
|
||||
fields={columns}
|
||||
@@ -189,7 +190,11 @@ const DeviceHealth = () => {
|
||||
sorterValue={{ column: 'recorded', desc: 'true' }}
|
||||
scopedSlots={{
|
||||
UUID: (item) => <td className="align-middle">{item.UUID}</td>,
|
||||
recorded: (item) => <td className="align-middle">{prettyDate(item.recorded)}</td>,
|
||||
recorded: (item) => (
|
||||
<td className="align-middle">
|
||||
<FormattedDate date={item.recorded} />
|
||||
</td>
|
||||
),
|
||||
sanity: (item) => <td className="align-middle">{`${item.sanity}%`}</td>,
|
||||
checkDetails: (item) => (
|
||||
<td>
|
||||
|
||||
@@ -15,10 +15,10 @@ import CIcon from '@coreui/icons-react';
|
||||
import { cilTrash } from '@coreui/icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import DatePicker from 'react-widgets/DatePicker';
|
||||
import { prettyDate, dateToUnix } from 'utils/helper';
|
||||
import { dateToUnix } from 'utils/helper';
|
||||
import axiosInstance from 'utils/axiosInstance';
|
||||
import eventBus from 'utils/eventBus';
|
||||
import { LoadingButton, useAuth, useDevice } from 'ucentral-libs';
|
||||
import { LoadingButton, useAuth, useDevice, FormattedDate } from 'ucentral-libs';
|
||||
import DeleteLogModal from 'components/DeleteLogModal';
|
||||
|
||||
const DeviceLogs = () => {
|
||||
@@ -187,6 +187,7 @@ const DeviceLogs = () => {
|
||||
<CCard>
|
||||
<div className="overflow-auto" style={{ height: '250px' }}>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
border
|
||||
items={logs ?? []}
|
||||
fields={columns}
|
||||
@@ -194,9 +195,16 @@ const DeviceLogs = () => {
|
||||
className="text-white"
|
||||
sorterValue={{ column: 'recorded', desc: 'true' }}
|
||||
scopedSlots={{
|
||||
recorded: (item) => <td>{prettyDate(item.recorded)}</td>,
|
||||
recorded: (item) => (
|
||||
<td className="align-middle">
|
||||
<FormattedDate date={item.recorded} />
|
||||
</td>
|
||||
),
|
||||
UUID: (item) => <td className="align-middle">{item.UUID}</td>,
|
||||
severity: (item) => <td className="align-middle">{item.severity}</td>,
|
||||
log: (item) => <td className="align-middle">{item.log}</td>,
|
||||
show_details: (item, index) => (
|
||||
<td className="py-2">
|
||||
<td className="align-middle">
|
||||
<CButton
|
||||
color="primary"
|
||||
variant={details.includes(index) ? '' : 'outline'}
|
||||
@@ -206,7 +214,7 @@ const DeviceLogs = () => {
|
||||
toggleDetails(index);
|
||||
}}
|
||||
>
|
||||
<CIcon name="cilList" size="lg" />
|
||||
<CIcon name="cilList" size="md" />
|
||||
</CButton>
|
||||
</td>
|
||||
),
|
||||
|
||||
224
src/components/EditFirmwareModal/index.js
Normal file
224
src/components/EditFirmwareModal/index.js
Normal file
@@ -0,0 +1,224 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CButton, CModal, CModalBody, CModalHeader, CModalTitle, CPopover } from '@coreui/react';
|
||||
import CIcon from '@coreui/icons-react';
|
||||
import { cilPencil, cilSave, cilX } from '@coreui/icons';
|
||||
import axiosInstance from 'utils/axiosInstance';
|
||||
import { useFormFields, useAuth, useToast, FirmwareDetailsForm } from 'ucentral-libs';
|
||||
|
||||
const initialState = {
|
||||
created: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: false,
|
||||
},
|
||||
release: {
|
||||
value: false,
|
||||
error: false,
|
||||
editable: false,
|
||||
},
|
||||
image: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: true,
|
||||
},
|
||||
imageDate: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: true,
|
||||
},
|
||||
size: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: true,
|
||||
},
|
||||
owner: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: true,
|
||||
},
|
||||
revision: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: false,
|
||||
},
|
||||
uri: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: true,
|
||||
},
|
||||
description: {
|
||||
value: '',
|
||||
error: false,
|
||||
editable: true,
|
||||
},
|
||||
notes: {
|
||||
value: [],
|
||||
editable: false,
|
||||
},
|
||||
};
|
||||
|
||||
const EditFirmwareModal = ({ show, toggle, firmwareId, refreshTable }) => {
|
||||
const { t } = useTranslation();
|
||||
const { currentToken, endpoints } = useAuth();
|
||||
const { addToast } = useToast();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [firmware, updateWithId, updateWithKey, setFirmware] = useFormFields(initialState);
|
||||
|
||||
const getFirmware = () => {
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${currentToken}`,
|
||||
},
|
||||
};
|
||||
|
||||
axiosInstance
|
||||
.get(`${endpoints.owfms}/api/v1/firmware/${firmwareId}`, options)
|
||||
.then((response) => {
|
||||
const newFirmware = {};
|
||||
|
||||
for (const key of Object.keys(response.data)) {
|
||||
if (key in initialState && key !== 'currentPassword') {
|
||||
newFirmware[key] = {
|
||||
...initialState[key],
|
||||
value: response.data[key],
|
||||
};
|
||||
}
|
||||
}
|
||||
setFirmware({ ...initialState, ...newFirmware });
|
||||
})
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const toggleEditing = () => {
|
||||
if (editing) {
|
||||
getFirmware();
|
||||
}
|
||||
setEditing(!editing);
|
||||
};
|
||||
|
||||
const toggleModal = () => {
|
||||
toggleEditing();
|
||||
toggle();
|
||||
};
|
||||
|
||||
const updateFirmware = () => {
|
||||
setLoading(true);
|
||||
|
||||
const parameters = {
|
||||
id: firmwareId,
|
||||
description: firmware.description.value,
|
||||
};
|
||||
|
||||
const newNotes = [];
|
||||
for (let i = 0; i < firmware.notes.value.length; i += 1) {
|
||||
if (firmware.notes.value[i].new) newNotes.push({ note: firmware.notes.value[i].note });
|
||||
}
|
||||
|
||||
parameters.notes = newNotes;
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${currentToken}`,
|
||||
},
|
||||
};
|
||||
|
||||
axiosInstance
|
||||
.put(`${endpoints.owfms}/api/v1/firmware/${firmwareId}`, parameters, options)
|
||||
.then(() => {
|
||||
addToast({
|
||||
title: t('firmware.update_success_title'),
|
||||
body: t('firmware.update_success'),
|
||||
color: 'success',
|
||||
autohide: true,
|
||||
});
|
||||
refreshTable();
|
||||
toggle();
|
||||
})
|
||||
.catch((e) => {
|
||||
addToast({
|
||||
title: t('firmware.update_failure_title'),
|
||||
body: t('firmware.update_failure', { error: e.response?.data?.ErrorDescription }),
|
||||
color: 'danger',
|
||||
autohide: true,
|
||||
});
|
||||
getFirmware();
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const addNote = (currentNote) => {
|
||||
const newNotes = [...firmware.notes.value];
|
||||
newNotes.unshift({
|
||||
note: currentNote,
|
||||
new: true,
|
||||
created: new Date().getTime() / 1000,
|
||||
createdBy: '',
|
||||
});
|
||||
updateWithKey('notes', { value: newNotes });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
getFirmware();
|
||||
setEditing(false);
|
||||
}
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<CModal show={show} onClose={toggle} size="xl">
|
||||
<CModalHeader className="p-1">
|
||||
<CModalTitle className="pl-1 pt-1">
|
||||
{t('firmware.details_title', { image: firmware.image.value })}
|
||||
</CModalTitle>
|
||||
<div className="text-right">
|
||||
<CPopover content={t('common.save')}>
|
||||
<CButton color="primary" variant="outline" onClick={updateFirmware} disabled={loading}>
|
||||
<CIcon content={cilSave} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.edit')}>
|
||||
<CButton
|
||||
disabled={editing}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={toggleEditing}
|
||||
className="ml-2"
|
||||
>
|
||||
<CIcon name="cil-pencil" content={cilPencil} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.close')}>
|
||||
<CButton color="primary" variant="outline" className="ml-2" onClick={toggleModal}>
|
||||
<CIcon content={cilX} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</div>
|
||||
</CModalHeader>
|
||||
<CModalBody>
|
||||
<FirmwareDetailsForm
|
||||
t={t}
|
||||
fields={firmware}
|
||||
addNote={addNote}
|
||||
updateFieldsWithId={updateWithId}
|
||||
editing={editing}
|
||||
/>
|
||||
</CModalBody>
|
||||
</CModal>
|
||||
);
|
||||
};
|
||||
|
||||
EditFirmwareModal.propTypes = {
|
||||
firmwareId: PropTypes.string.isRequired,
|
||||
show: PropTypes.bool.isRequired,
|
||||
toggle: PropTypes.func.isRequired,
|
||||
refreshTable: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default React.memo(EditFirmwareModal);
|
||||
@@ -52,6 +52,7 @@ const EditUserModal = ({ show, toggle, userId, getUsers }) => {
|
||||
const { addToast } = useToast();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [initialUser, setInitialUser] = useState({});
|
||||
const [editing, setEditing] = useState(false);
|
||||
const [user, updateWithId, updateWithKey, setUser] = useUser(initialState);
|
||||
const [policies, setPolicies] = useState({
|
||||
passwordPolicy: '',
|
||||
@@ -98,6 +99,13 @@ const EditUserModal = ({ show, toggle, userId, getUsers }) => {
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
const toggleEditing = () => {
|
||||
if (editing) {
|
||||
getUser();
|
||||
}
|
||||
setEditing(!editing);
|
||||
};
|
||||
|
||||
const updateUser = () => {
|
||||
setLoading(true);
|
||||
|
||||
@@ -197,6 +205,12 @@ const EditUserModal = ({ show, toggle, userId, getUsers }) => {
|
||||
}
|
||||
}, [userId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (show) {
|
||||
setEditing(false);
|
||||
}
|
||||
}, [show]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
t={t}
|
||||
@@ -207,6 +221,8 @@ const EditUserModal = ({ show, toggle, userId, getUsers }) => {
|
||||
policies={policies}
|
||||
show={show}
|
||||
toggle={toggle}
|
||||
editing={editing}
|
||||
toggleEditing={toggleEditing}
|
||||
addNote={addNote}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -28,22 +28,22 @@ const DeviceStatisticsCard = () => {
|
||||
return (
|
||||
<div>
|
||||
<CCard className="m-0">
|
||||
<CCardHeader className="p-1">
|
||||
<CCardHeader className="dark-header">
|
||||
<div className="d-flex flex-row-reverse align-items-center">
|
||||
<div className="pl-2">
|
||||
<CPopover content={t('common.refresh')}>
|
||||
<CButton size="sm" color="primary" variant="outline" onClick={refresh}>
|
||||
<CButton size="sm" color="info" onClick={refresh}>
|
||||
<CIcon content={cilSync} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
</div>
|
||||
<div className="pl-2">
|
||||
<CButton size="sm" color="primary" variant="outline" onClick={toggleLifetimeModal}>
|
||||
<CButton size="sm" color="info" onClick={toggleLifetimeModal}>
|
||||
Lifetime Statistics
|
||||
</CButton>
|
||||
</div>
|
||||
<div className="pl-2">
|
||||
<CButton size="sm" color="primary" variant="outline" onClick={toggleLatestModal}>
|
||||
<CButton size="sm" color="info" onClick={toggleLatestModal}>
|
||||
{t('statistics.show_latest')}
|
||||
</CButton>
|
||||
</div>
|
||||
|
||||
@@ -201,13 +201,10 @@ const WifiAnalysis = () => {
|
||||
return (
|
||||
<div>
|
||||
<CCard>
|
||||
<CCardHeader>
|
||||
<CCardHeader className="dark-header">
|
||||
<CRow>
|
||||
<CCol>
|
||||
<h5 className="mb-0">{t('common.device', { serialNumber: deviceId })}</h5>
|
||||
</CCol>
|
||||
<CCol className="text-right">
|
||||
<CButton color="primary" variant="outline" onClick={toggleModal}>
|
||||
<CButton color="info" size="sm" onClick={toggleModal}>
|
||||
{t('wifi_analysis.network_diagram')}
|
||||
</CButton>
|
||||
</CCol>
|
||||
|
||||
@@ -24,6 +24,7 @@ const WifiChannelCard = ({ channel }) => {
|
||||
<CCardBody>
|
||||
<div className="overflow-auto" style={{ height: '250px' }}>
|
||||
<CDataTable
|
||||
addTableClasses="ignore-overflow table-sm"
|
||||
items={channel.devices}
|
||||
fields={columns}
|
||||
className="text-white"
|
||||
|
||||
@@ -18,7 +18,7 @@ const DeviceListPage = () => {
|
||||
active={index === 0}
|
||||
onClick={() => setIndex(0)}
|
||||
>
|
||||
{t('common.table')}
|
||||
{t('common.dashboard')}
|
||||
</CNavLink>
|
||||
<CNavLink
|
||||
className="font-weight-bold"
|
||||
@@ -26,15 +26,15 @@ const DeviceListPage = () => {
|
||||
active={index === 1}
|
||||
onClick={() => setIndex(1)}
|
||||
>
|
||||
{t('common.dashboard')}
|
||||
{t('common.devices')}
|
||||
</CNavLink>
|
||||
</CNav>
|
||||
<CTabContent>
|
||||
<CTabPane active={index === 0}>
|
||||
<DeviceList />
|
||||
<DeviceDashboard />
|
||||
</CTabPane>
|
||||
<CTabPane active={index === 1}>
|
||||
<DeviceDashboard />
|
||||
<DeviceList />
|
||||
</CTabPane>
|
||||
</CTabContent>
|
||||
</CCardBody>
|
||||
|
||||
@@ -5,6 +5,7 @@ import axiosInstance from 'utils/axiosInstance';
|
||||
import { CCard, CCardBody, CNav, CNavLink, CTabPane, CTabContent } from '@coreui/react';
|
||||
import { FirmwareList, useAuth, useToast } from 'ucentral-libs';
|
||||
import FirmwareDashboard from 'components/FirmwareDashboard';
|
||||
import EditFirmwareModal from 'components/EditFirmwareModal';
|
||||
|
||||
const FirmwareListPage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -20,9 +21,14 @@ const FirmwareListPage = () => {
|
||||
const [filteredFirmware, setFilteredFirmware] = useState([]);
|
||||
const [displayedFirmware, setDisplayedFirmware] = useState([]);
|
||||
const [displayDev, setDisplayDev] = useState(false);
|
||||
const [addNoteLoading, setAddNoteLoading] = useState(false);
|
||||
const [updateDescriptionLoading, setUpdateDescriptionLoading] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [showEditModal, setShowEditModal] = useState(false);
|
||||
const [firmwareToEdit, setFirmwareToEdit] = useState('');
|
||||
|
||||
const toggleEditModal = (id) => {
|
||||
if (id) setFirmwareToEdit(id);
|
||||
setShowEditModal(!showEditModal);
|
||||
};
|
||||
|
||||
const displayFirmware = (currentPage, perPage, firmwareToDisplay) => {
|
||||
setLoading(true);
|
||||
@@ -149,70 +155,6 @@ const FirmwareListPage = () => {
|
||||
getFirmware(value);
|
||||
};
|
||||
|
||||
const addNote = (value, id) => {
|
||||
setAddNoteLoading(true);
|
||||
|
||||
const parameters = {
|
||||
id,
|
||||
notes: [{ note: value }],
|
||||
};
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${currentToken}`,
|
||||
},
|
||||
};
|
||||
|
||||
axiosInstance
|
||||
.put(`${endpoints.owfms}/api/v1/firmware/${id}`, parameters, options)
|
||||
.then(() => {
|
||||
getFirmware();
|
||||
setAddNoteLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setAddNoteLoading(false);
|
||||
addToast({
|
||||
title: t('common.error'),
|
||||
body: t('common.general_error'),
|
||||
color: 'danger',
|
||||
autohide: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const updateDescription = (value, id) => {
|
||||
setUpdateDescriptionLoading(true);
|
||||
|
||||
const parameters = {
|
||||
id,
|
||||
description: value,
|
||||
};
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${currentToken}`,
|
||||
},
|
||||
};
|
||||
|
||||
axiosInstance
|
||||
.put(`${endpoints.owfms}/api/v1/firmware/${id}`, parameters, options)
|
||||
.then(() => {
|
||||
getFirmware();
|
||||
setUpdateDescriptionLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setUpdateDescriptionLoading(false);
|
||||
addToast({
|
||||
title: t('common.error'),
|
||||
body: t('common.general_error'),
|
||||
color: 'danger',
|
||||
autohide: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectedDeviceType === '' && !loading) getDeviceTypes();
|
||||
}, []);
|
||||
@@ -227,7 +169,7 @@ const FirmwareListPage = () => {
|
||||
active={index === 0}
|
||||
onClick={() => setIndex(0)}
|
||||
>
|
||||
{t('common.table')}
|
||||
{t('common.dashboard')}
|
||||
</CNavLink>
|
||||
<CNavLink
|
||||
className="font-weight-bold"
|
||||
@@ -235,11 +177,14 @@ const FirmwareListPage = () => {
|
||||
active={index === 1}
|
||||
onClick={() => setIndex(1)}
|
||||
>
|
||||
{t('common.dashboard')}
|
||||
{t('common.firmware')}
|
||||
</CNavLink>
|
||||
</CNav>
|
||||
<CTabContent>
|
||||
<CTabPane active={index === 0}>
|
||||
<FirmwareDashboard />
|
||||
</CTabPane>
|
||||
<CTabPane active={index === 1}>
|
||||
<FirmwareList
|
||||
t={t}
|
||||
loading={loading}
|
||||
@@ -248,20 +193,20 @@ const FirmwareListPage = () => {
|
||||
setPage={updatePage}
|
||||
data={displayedFirmware}
|
||||
firmwarePerPage={firmwarePerPage}
|
||||
toggleEditModal={toggleEditModal}
|
||||
setFirmwarePerPage={updateFirmwarePerPage}
|
||||
selectedDeviceType={selectedDeviceType}
|
||||
deviceTypes={deviceTypes}
|
||||
setSelectedDeviceType={updateSelectedType}
|
||||
addNote={addNote}
|
||||
addNoteLoading={addNoteLoading}
|
||||
updateDescription={updateDescription}
|
||||
updateDescriptionLoading={updateDescriptionLoading}
|
||||
displayDev={displayDev}
|
||||
toggleDevDisplay={toggleDevDisplay}
|
||||
/>
|
||||
</CTabPane>
|
||||
<CTabPane active={index === 1}>
|
||||
<FirmwareDashboard />
|
||||
<EditFirmwareModal
|
||||
firmwareId={firmwareToEdit}
|
||||
show={showEditModal}
|
||||
toggle={toggleEditModal}
|
||||
refreshTable={getFirmware}
|
||||
/>
|
||||
</CTabPane>
|
||||
</CTabContent>
|
||||
</CCardBody>
|
||||
|
||||
@@ -63,6 +63,7 @@ const ProfilePage = () => {
|
||||
const [userForm, updateWithId, updateWithKey, setUser] = useUser(initialState);
|
||||
const [newAvatar, setNewAvatar] = useState('');
|
||||
const [newAvatarFile, setNewAvatarFile] = useState(null);
|
||||
const [avatarDeleted, setAvatarDeleted] = useState(false);
|
||||
const [fileInputKey, setFileInputKey] = useState(0);
|
||||
const [policies, setPolicies] = useState({
|
||||
passwordPolicy: '',
|
||||
@@ -161,8 +162,22 @@ const ProfilePage = () => {
|
||||
const updateUser = () => {
|
||||
setLoading(true);
|
||||
|
||||
if (newAvatarFile !== null) {
|
||||
if (newAvatar !== '' && newAvatarFile !== null) {
|
||||
uploadAvatar();
|
||||
} else if (avatarDeleted) {
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${currentToken}`,
|
||||
},
|
||||
};
|
||||
|
||||
axiosInstance
|
||||
.delete(`${endpoints.owsec}/api/v1/avatar/${user.Id}`, options)
|
||||
.then(() => {
|
||||
getAvatar();
|
||||
})
|
||||
.catch(() => {});
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -240,29 +255,15 @@ const ProfilePage = () => {
|
||||
};
|
||||
|
||||
const showPreview = (e) => {
|
||||
setAvatarDeleted(false);
|
||||
const imageFile = e.target.files[0];
|
||||
setNewAvatar(URL.createObjectURL(imageFile));
|
||||
setNewAvatarFile(imageFile);
|
||||
};
|
||||
|
||||
const deleteAvatar = () => {
|
||||
setLoading(true);
|
||||
const options = {
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
Authorization: `Bearer ${currentToken}`,
|
||||
},
|
||||
};
|
||||
|
||||
return axiosInstance
|
||||
.delete(`${endpoints.owsec}/api/v1/avatar/${user.Id}`, options)
|
||||
.then(() => {
|
||||
getAvatar();
|
||||
})
|
||||
.catch(() => {})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
setNewAvatar('');
|
||||
setAvatarDeleted(true);
|
||||
};
|
||||
|
||||
const sendPhoneNumberTest = async (phoneNumber) => {
|
||||
@@ -314,7 +315,12 @@ const ProfilePage = () => {
|
||||
};
|
||||
|
||||
const toggleEditing = () => {
|
||||
if (editing) getUser();
|
||||
if (editing) {
|
||||
setAvatarDeleted(false);
|
||||
setNewAvatar('');
|
||||
getUser();
|
||||
getAvatar();
|
||||
}
|
||||
setEditing(!editing);
|
||||
};
|
||||
|
||||
@@ -329,52 +335,30 @@ const ProfilePage = () => {
|
||||
}, [user.Id]);
|
||||
|
||||
return (
|
||||
<CCard>
|
||||
<CCardHeader className="p-1">
|
||||
<div className="text-value-lg float-left">{t('user.my_profile')}</div>
|
||||
<CCard className="my-0 py-0">
|
||||
<CCardHeader className="dark-header">
|
||||
<div style={{ fontWeight: '600' }} className=" text-value-lg float-left">
|
||||
{t('user.my_profile')}
|
||||
</div>
|
||||
<div className="text-right float-right">
|
||||
<CButtonToolbar role="group" className="justify-content-end">
|
||||
<CPopover content={t('common.save')}>
|
||||
<CButton
|
||||
disabled={!editing}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={updateUser}
|
||||
className="mx-1"
|
||||
>
|
||||
<CButton disabled={!editing} color="info" onClick={updateUser} className="mx-1">
|
||||
<CIcon name="cil-save" content={cilSave} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.edit')}>
|
||||
<CButton
|
||||
disabled={editing}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={toggleEditing}
|
||||
className="mx-1"
|
||||
>
|
||||
<CButton disabled={editing} color="dark" onClick={toggleEditing} className="mx-1">
|
||||
<CIcon name="cil-pencil" content={cilPencil} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.stop_editing')}>
|
||||
<CButton
|
||||
disabled={!editing}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={toggleEditing}
|
||||
className="mx-1"
|
||||
>
|
||||
<CButton disabled={!editing} color="dark" onClick={toggleEditing} className="mx-1">
|
||||
<CIcon name="cil-x" content={cilX} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
<CPopover content={t('common.refresh')}>
|
||||
<CButton
|
||||
disabled={editing}
|
||||
color="primary"
|
||||
variant="outline"
|
||||
onClick={getUser}
|
||||
className="mx-1"
|
||||
>
|
||||
<CButton disabled={editing} color="info" onClick={getUser} className="mx-1">
|
||||
<CIcon content={cilSync} />
|
||||
</CButton>
|
||||
</CPopover>
|
||||
@@ -398,6 +382,7 @@ const ProfilePage = () => {
|
||||
sendPhoneNumberTest={sendPhoneNumberTest}
|
||||
testVerificationCode={testVerificationCode}
|
||||
editing={editing}
|
||||
avatarDeleted={avatarDeleted}
|
||||
/>
|
||||
</CCardBody>
|
||||
</CCard>
|
||||
|
||||
@@ -30,3 +30,16 @@ pre.ignore {
|
||||
|
||||
.tooltipRight { &::after { left: 75% !important; } }
|
||||
.tooltipRight { &::before { left: 75% !important; } }
|
||||
|
||||
.dark-header {
|
||||
padding: .25rem !important;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
color: #ebedef !important;
|
||||
background-color: #2f3d54 !important;
|
||||
}
|
||||
|
||||
.avatar-lg {
|
||||
height: 10rem;
|
||||
width: 10rem;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user