mirror of
https://github.com/Telecominfraproject/wlan-cloud-ucentralgw-ui.git
synced 2025-11-02 11:47:54 +00:00
Merge pull request #34 from Telecominfraproject/dev-microservice
Dev microservice
This commit is contained in:
@@ -1 +1,4 @@
|
|||||||
/src/assets
|
/src/assets
|
||||||
|
/build
|
||||||
|
/node_modules
|
||||||
|
.github
|
||||||
|
|||||||
28
.eslintrc
28
.eslintrc
@@ -1,16 +1,11 @@
|
|||||||
{
|
{
|
||||||
"parser": "babel-eslint",
|
"extends": ["airbnb", "prettier"],
|
||||||
"parserOptions": {
|
"plugins": ["prettier"],
|
||||||
"sourceType": "module",
|
"env": {
|
||||||
"allowImportExportEverywhere": false,
|
|
||||||
"codeFrame": false
|
|
||||||
},
|
|
||||||
"extends": ["airbnb", "prettier"],
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
"browser": true,
|
||||||
"jest": true
|
"jest": true
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"max-len": ["error", {"code": 150}],
|
"max-len": ["error", {"code": 150}],
|
||||||
"prefer-promise-reject-errors": ["off"],
|
"prefer-promise-reject-errors": ["off"],
|
||||||
"react/jsx-filename-extension": ["off"],
|
"react/jsx-filename-extension": ["off"],
|
||||||
@@ -18,13 +13,22 @@
|
|||||||
"no-return-assign": ["off"],
|
"no-return-assign": ["off"],
|
||||||
"react/jsx-props-no-spreading": ["off"],
|
"react/jsx-props-no-spreading": ["off"],
|
||||||
"react/destructuring-assignment": ["off"],
|
"react/destructuring-assignment": ["off"],
|
||||||
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"]
|
"no-restricted-syntax": ["error", "ForInStatement", "LabeledStatement", "WithStatement"],
|
||||||
|
"react/jsx-one-expression-per-line": "off",
|
||||||
|
"react/jsx-wrap-multilines": "off",
|
||||||
|
"react/jsx-curly-newline": "off"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"import/resolver": {
|
"import/resolver": {
|
||||||
"node": {
|
"node": {
|
||||||
"paths": ["src"]
|
"paths": ["src"]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
"parser": "babel-eslint",
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "module",
|
||||||
|
"allowImportExportEverywhere": false,
|
||||||
|
"codeFrame": false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
|
|||||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
/src/assets
|
||||||
|
build
|
||||||
|
node_modules
|
||||||
|
.github
|
||||||
@@ -26,12 +26,12 @@ npm run build
|
|||||||
Once the build is done, you can move the `build` folder on your server.
|
Once the build is done, you can move the `build` folder on your server.
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
You must change the `config.json` file in `public` directory to point to your gateway URL. You may also limit the ability for users to change the default gateway. If you do not allow a gateway change, the gateway URL will not appear on the login screen.
|
You must change the `config.json` file in `public` directory to point to your uCentral Security Service URL (uCentralSec). You may also limit the ability for users to change the default uCentralSec. If you do not allow a uCentralSec change, the uCentralSec URL will not appear on the login screen.
|
||||||
|
|
||||||
Here are the current default values:
|
Here are the current default values:
|
||||||
```
|
```
|
||||||
{
|
{
|
||||||
"DEFAULT_GATEWAY_URL": "https://ucentral.dpaas.arilia.com:16001",
|
"DEFAULT_UCENTRALSEC_URL": "https://ucentral.dpaas.arilia.com:16001",
|
||||||
"ALLOW_GATEWAY_CHANGE": false
|
"ALLOW_UCENTRALSEC_CHANGE": false
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
7
babel.config.json
Normal file
7
babel.config.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"@babel/preset-env",
|
||||||
|
"@babel/preset-react"
|
||||||
|
],
|
||||||
|
"plugins": ["@babel/plugin-proposal-class-properties"]
|
||||||
|
}
|
||||||
12
config/paths.js
Normal file
12
config/paths.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Source files
|
||||||
|
src: path.resolve(__dirname, '../src'),
|
||||||
|
|
||||||
|
// Production build files
|
||||||
|
build: path.resolve(__dirname, '../build'),
|
||||||
|
|
||||||
|
// Static files that get copied to build folder
|
||||||
|
public: path.resolve(__dirname, '../public'),
|
||||||
|
};
|
||||||
76
config/webpack.common.js
Normal file
76
config/webpack.common.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
/* eslint-disable prefer-template */
|
||||||
|
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
|
||||||
|
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||||
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const path = require('path');
|
||||||
|
const paths = require('./paths');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: [paths.src + '/index.js'],
|
||||||
|
output: {
|
||||||
|
path: paths.build,
|
||||||
|
filename: '[name].bundle.js',
|
||||||
|
publicPath: '/',
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
modules: [path.resolve('./node_modules'), path.resolve('./src')],
|
||||||
|
preferRelative: true,
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new CleanWebpackPlugin(),
|
||||||
|
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: 'styles/[name].[contenthash].css',
|
||||||
|
chunkFilename: '[id].[contenthash].css',
|
||||||
|
}),
|
||||||
|
new CopyWebpackPlugin({
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
from: paths.src + '/assets',
|
||||||
|
to: 'assets',
|
||||||
|
globOptions: {
|
||||||
|
ignore: ['*.DS_Store'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: paths.public + '/locales',
|
||||||
|
to: 'locales',
|
||||||
|
globOptions: {
|
||||||
|
ignore: ['*.DS_Store'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
from: paths.public + '/config.json',
|
||||||
|
to: 'config.json',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
new HtmlWebpackPlugin({
|
||||||
|
title: 'uCentralGW',
|
||||||
|
favicon: paths.public + '/favicon.ico',
|
||||||
|
template: paths.public + '/index.html',
|
||||||
|
filename: 'index.html',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.(js|jsx)$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: ['babel-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.(css|scss)$/,
|
||||||
|
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
test: /\.svg$/,
|
||||||
|
use: ['@svgr/webpack'],
|
||||||
|
},
|
||||||
|
{ test: /\.(?:ico|gif|png|jpg|jpeg)$/i, type: 'asset/resource' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
53
config/webpack.dev.js
Normal file
53
config/webpack.dev.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
/* eslint-disable prefer-template */
|
||||||
|
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
|
||||||
|
const { merge } = require('webpack-merge');
|
||||||
|
const path = require('path');
|
||||||
|
const paths = require('./paths');
|
||||||
|
const common = require('./webpack.common');
|
||||||
|
|
||||||
|
module.exports = merge(common, {
|
||||||
|
mode: 'development',
|
||||||
|
|
||||||
|
target: 'web',
|
||||||
|
|
||||||
|
devtool: 'inline-source-map',
|
||||||
|
|
||||||
|
devServer: {
|
||||||
|
historyApiFallback: true,
|
||||||
|
contentBase: paths.build,
|
||||||
|
open: true,
|
||||||
|
compress: false,
|
||||||
|
hot: true,
|
||||||
|
port: 3000,
|
||||||
|
},
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.[js]sx?$/,
|
||||||
|
exclude: /node_modules/,
|
||||||
|
use: [
|
||||||
|
{
|
||||||
|
loader: require.resolve('babel-loader'),
|
||||||
|
options: {
|
||||||
|
plugins: [require.resolve('react-refresh/babel')],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
modules: [
|
||||||
|
'node_modules',
|
||||||
|
'src',
|
||||||
|
path.resolve(__dirname, '../', 'node_modules', 'ucentral-libs', 'src'),
|
||||||
|
],
|
||||||
|
alias: {
|
||||||
|
react: path.resolve(__dirname, '../', 'node_modules', 'react'),
|
||||||
|
'react-router-dom': path.resolve('./node_modules/react-router-dom'),
|
||||||
|
'ucentral-libs': path.resolve(__dirname, '../', 'node_modules', 'ucentral-libs', 'src'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [new ReactRefreshWebpackPlugin()],
|
||||||
|
});
|
||||||
36
config/webpack.prod.js
Normal file
36
config/webpack.prod.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
|
/* eslint-disable prefer-template */
|
||||||
|
const { merge } = require('webpack-merge');
|
||||||
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||||
|
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
||||||
|
const TerserPlugin = require('terser-webpack-plugin');
|
||||||
|
const paths = require('./paths');
|
||||||
|
const common = require('./webpack.common');
|
||||||
|
|
||||||
|
module.exports = merge(common, {
|
||||||
|
mode: 'production',
|
||||||
|
devtool: false,
|
||||||
|
output: {
|
||||||
|
path: paths.build,
|
||||||
|
publicPath: '/',
|
||||||
|
filename: 'js/[name].[contenthash].bundle.js',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
new MiniCssExtractPlugin({
|
||||||
|
filename: 'styles/[name].[contenthash].css',
|
||||||
|
chunkFilename: '[contenthash].css',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
module: {
|
||||||
|
rules: [],
|
||||||
|
},
|
||||||
|
optimization: {
|
||||||
|
minimize: true,
|
||||||
|
minimizer: [`...`, new TerserPlugin(), new CssMinimizerPlugin()],
|
||||||
|
},
|
||||||
|
performance: {
|
||||||
|
hints: false,
|
||||||
|
maxEntrypointSize: 512000,
|
||||||
|
maxAssetSize: 512000,
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/ash
|
#!/bin/ash
|
||||||
# Check if variables are set
|
# Check if variables are set
|
||||||
export DEFAULT_GATEWAY_URL="${DEFAULT_GATEWAY_URL:-https://ucentral.dpaas.arilia.com:16001}"
|
export DEFAULT_UCENTRALSEC_URL="${DEFAULT_UCENTRALSEC_URL:-https://ucentral.dpaas.arilia.com:16001}"
|
||||||
export ALLOW_GATEWAY_CHANGE="${ALLOW_GATEWAY_CHANGE:-false}"
|
export ALLOW_UCENTRALSEC_CHANGE="${ALLOW_UCENTRALSEC_CHANGE:-false}"
|
||||||
|
|
||||||
echo '{"DEFAULT_GATEWAY_URL": "'$DEFAULT_GATEWAY_URL'","ALLOW_GATEWAY_CHANGE": '$ALLOW_GATEWAY_CHANGE'}' > /usr/share/nginx/html/config.json
|
echo '{"DEFAULT_UCENTRALSEC_URL": "'$DEFAULT_UCENTRALSEC_URL'","ALLOW_UCENTRALSEC_CHANGE": '$ALLOW_UCENTRALSEC_CHANGE'}' > /usr/share/nginx/html/config.json
|
||||||
|
|||||||
@@ -71,5 +71,5 @@ affinity: {}
|
|||||||
|
|
||||||
# Application
|
# Application
|
||||||
public_env_variables:
|
public_env_variables:
|
||||||
DEFAULT_GATEWAY_URL: https://ucentral.dpaas.arilia.com:16001
|
DEFAULT_UCENTRALSEC_URL: https://ucentral.dpaas.arilia.com:16001
|
||||||
ALLOW_GATEWAY_CHANGE: false
|
ALLOW_UCENTRALSEC_CHANGE: false
|
||||||
|
|||||||
31211
package-lock.json
generated
31211
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
85
package.json
85
package.json
@@ -1,23 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "ucentral-client",
|
"name": "ucentral-client",
|
||||||
"version": "0.9.5",
|
"version": "0.9.14",
|
||||||
"private": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@coreui/coreui": "^3.4.0",
|
"@coreui/coreui": "^3.4.0",
|
||||||
"@coreui/icons": "^2.0.1",
|
"@coreui/icons": "^2.0.1",
|
||||||
"@coreui/icons-react": "^1.1.0",
|
"@coreui/icons-react": "^1.1.0",
|
||||||
"@coreui/react": "^3.4.6",
|
"@coreui/react": "^3.4.6",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.35",
|
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.15.3",
|
|
||||||
"@fortawesome/react-fontawesome": "^0.1.14",
|
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
|
||||||
"@testing-library/react": "^11.2.7",
|
|
||||||
"@testing-library/user-event": "^13.1.9",
|
|
||||||
"apexcharts": "^3.27.1",
|
"apexcharts": "^3.27.1",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"axios-retry": "^3.1.9",
|
"axios-retry": "^3.1.9",
|
||||||
"http": "^0.0.1-security",
|
|
||||||
"https": "^1.0.0",
|
|
||||||
"i18next": "^20.3.1",
|
"i18next": "^20.3.1",
|
||||||
"i18next-browser-languagedetector": "^6.1.2",
|
"i18next-browser-languagedetector": "^6.1.2",
|
||||||
"i18next-http-backend": "^1.2.6",
|
"i18next-http-backend": "^1.2.6",
|
||||||
@@ -27,20 +18,18 @@
|
|||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-i18next": "^11.11.0",
|
"react-i18next": "^11.11.0",
|
||||||
"react-paginate": "^7.1.3",
|
"react-paginate": "^7.1.3",
|
||||||
"react-redux": "^7.2.4",
|
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scripts": "^4.0.3",
|
|
||||||
"react-select": "^4.3.1",
|
|
||||||
"react-widgets": "^5.1.1",
|
"react-widgets": "^5.1.1",
|
||||||
"redux": "^4.1.0",
|
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
|
"ucentral-libs": "^0.8.7",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "webpack serve --config config/webpack.dev.js",
|
||||||
"build": "react-scripts build",
|
"build": "webpack --config config/webpack.prod.js",
|
||||||
"test": "react-scripts test",
|
"format": "prettier --write 'src/**/*.js'",
|
||||||
"eject": "react-scripts eject"
|
"eslint-fix": "eslint --fix 'src/**/*.js'"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "react-app"
|
"extends": "react-app"
|
||||||
@@ -51,12 +40,54 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"src/**/*.{js,jsx}": [
|
"*.{js,jsx}": [
|
||||||
"eslint",
|
"eslint",
|
||||||
"pretty-quick — staged",
|
"prettier --write"
|
||||||
"git add"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/core": "^7.14.6",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.14.5",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.14.5",
|
||||||
|
"@babel/polyfill": "^7.12.1",
|
||||||
|
"@babel/preset-env": "^7.14.7",
|
||||||
|
"@babel/preset-react": "^7.14.5",
|
||||||
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
|
||||||
|
"@svgr/webpack": "^5.5.0",
|
||||||
|
"autoprefixer": "^10.2.6",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"babel-loader": "^8.2.2",
|
||||||
|
"clean-webpack-plugin": "^3.0.0",
|
||||||
|
"copy-webpack-plugin": "^7.0.0",
|
||||||
|
"css-loader": "^5.2.6",
|
||||||
|
"css-minimizer-webpack-plugin": "^2.0.0",
|
||||||
|
"dotenv-webpack": "^6.0.4",
|
||||||
|
"eslint": "^7.29.0",
|
||||||
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
|
"eslint-config-prettier": "^7.2.0",
|
||||||
|
"eslint-import-resolver-alias": "^1.1.2",
|
||||||
|
"eslint-loader": "^4.0.2",
|
||||||
|
"eslint-plugin-babel": "^5.3.1",
|
||||||
|
"eslint-plugin-import": "^2.23.4",
|
||||||
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
|
"eslint-plugin-react": "^7.24.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
|
"html-webpack-plugin": "^5.3.2",
|
||||||
|
"husky": "^4.3.8",
|
||||||
|
"lint-staged": "^11.0.0",
|
||||||
|
"mini-css-extract-plugin": "^1.6.1",
|
||||||
|
"node-sass": "^5.0.0",
|
||||||
|
"path": "^0.12.7",
|
||||||
|
"prettier": "^2.3.2",
|
||||||
|
"react-refresh": "^0.9.0",
|
||||||
|
"sass-loader": "^11.1.1",
|
||||||
|
"style-loader": "^2.0.0",
|
||||||
|
"terser-webpack-plugin": "^5.1.4",
|
||||||
|
"webpack": "^5.40.0",
|
||||||
|
"webpack-cli": "^4.7.2",
|
||||||
|
"webpack-dev-server": "^3.11.2",
|
||||||
|
"webpack-merge": "^5.8.0"
|
||||||
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
">0.2%",
|
">0.2%",
|
||||||
@@ -68,17 +99,5 @@
|
|||||||
"last 1 firefox version",
|
"last 1 firefox version",
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"babel-eslint": "^10.1.0",
|
|
||||||
"eslint": "^7.28.0",
|
|
||||||
"eslint-config-airbnb": "^18.2.1",
|
|
||||||
"eslint-config-prettier": "^8.3.0",
|
|
||||||
"eslint-plugin-import": "^2.23.4",
|
|
||||||
"eslint-plugin-react": "^7.24.0",
|
|
||||||
"husky": "^6.0.0",
|
|
||||||
"lint-staged": "^11.0.0",
|
|
||||||
"prettier": "^2.3.1",
|
|
||||||
"pretty-quick": "^3.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"DEFAULT_GATEWAY_URL": "https://ucentral.dpaas.arilia.com:16001",
|
"DEFAULT_UCENTRALSEC_URL": "https://ucentral.dpaas.arilia.com:16001",
|
||||||
"ALLOW_GATEWAY_CHANGE": false
|
"ALLOW_UCENTRALSEC_CHANGE": false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,42 +2,13 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
<link rel="icon" href="favicon.ico" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="Web site created using create-react-app"
|
|
||||||
/>
|
|
||||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
|
||||||
<!--
|
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
|
||||||
-->
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<!--
|
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
|
||||||
It will be replaced with the URL of the `public` folder during the build.
|
|
||||||
Only files inside the `public` folder can be referenced from the HTML.
|
|
||||||
|
|
||||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
|
||||||
work correctly both with client-side routing and a non-root public URL.
|
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
|
||||||
-->
|
|
||||||
<title>uCentralGW</title>
|
<title>uCentralGW</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<!--
|
|
||||||
This HTML file is a template.
|
|
||||||
If you open it directly in the browser, you will see an empty page.
|
|
||||||
|
|
||||||
You can add webfonts, meta tags, or analytics to this file.
|
|
||||||
The build step will place the bundled scripts into the <body> tag.
|
|
||||||
|
|
||||||
To begin the development, run `npm start` or `yarn start`.
|
|
||||||
To create a production bundle, use `npm run build` or `yarn build`.
|
|
||||||
-->
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"blink": {
|
"blink": {
|
||||||
"blink": "LEDs Blinken",
|
"blink": "LEDs Blinken",
|
||||||
"device_leds": "LEDs",
|
"device_leds": "LEDs",
|
||||||
|
"execute_now": "Möchten Sie dieses Muster jetzt einstellen?",
|
||||||
"pattern": "Wählen Sie das Muster, das Sie verwenden möchten:",
|
"pattern": "Wählen Sie das Muster, das Sie verwenden möchten:",
|
||||||
|
"set_leds": "LEDs einstellen",
|
||||||
"when_blink_leds": "Wann möchten Sie die LEDs blinken lassen?"
|
"when_blink_leds": "Wann möchten Sie die LEDs blinken lassen?"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"title": "Gerätebefehle"
|
"title": "Gerätebefehle"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"add": "Hinzufügen",
|
||||||
|
"adding_ellipsis": "Hinzufügen ...",
|
||||||
"are_you_sure": "Bist du sicher?",
|
"are_you_sure": "Bist du sicher?",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"certificate": "Zertifikat",
|
"certificate": "Zertifikat",
|
||||||
@@ -36,7 +40,11 @@
|
|||||||
"connected": "Verbindung wurde hergestellt",
|
"connected": "Verbindung wurde hergestellt",
|
||||||
"copied": "kopiert!",
|
"copied": "kopiert!",
|
||||||
"copy_to_clipboard": "In die Zwischenablage kopieren",
|
"copy_to_clipboard": "In die Zwischenablage kopieren",
|
||||||
|
"created_by": "Erstellt von",
|
||||||
|
"custom_date": "Benutzerdefiniertes Datum",
|
||||||
"date": "Datum",
|
"date": "Datum",
|
||||||
|
"day": "tag",
|
||||||
|
"days": "tage",
|
||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
"details": "Einzelheiten",
|
"details": "Einzelheiten",
|
||||||
"device_list": "Liste der Geräte",
|
"device_list": "Liste der Geräte",
|
||||||
@@ -52,6 +60,8 @@
|
|||||||
"exit": "Ausgang",
|
"exit": "Ausgang",
|
||||||
"firmware": "Firmware",
|
"firmware": "Firmware",
|
||||||
"from": "Von",
|
"from": "Von",
|
||||||
|
"hour": "stunde",
|
||||||
|
"hours": "std",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"ip_address": "IP Adresse",
|
"ip_address": "IP Adresse",
|
||||||
"later_tonight": "Später am Abend",
|
"later_tonight": "Später am Abend",
|
||||||
@@ -60,9 +70,12 @@
|
|||||||
"logout": "Ausloggen",
|
"logout": "Ausloggen",
|
||||||
"mac": "MAC-Adresse",
|
"mac": "MAC-Adresse",
|
||||||
"manufacturer": "Hersteller",
|
"manufacturer": "Hersteller",
|
||||||
|
"minute": "Minute",
|
||||||
|
"minutes": "protokoll",
|
||||||
"na": "(unbekannt)",
|
"na": "(unbekannt)",
|
||||||
"need_date": "Du brauchst ein Datum...",
|
"need_date": "Du brauchst ein Datum...",
|
||||||
"no": "Nein",
|
"no": "Nein",
|
||||||
|
"no_items": "Keine Gegenstände",
|
||||||
"not_connected": "Nicht verbunden",
|
"not_connected": "Nicht verbunden",
|
||||||
"off": "Aus",
|
"off": "Aus",
|
||||||
"on": "An",
|
"on": "An",
|
||||||
@@ -73,6 +86,8 @@
|
|||||||
"save": "Sparen",
|
"save": "Sparen",
|
||||||
"saving": "Speichern ...",
|
"saving": "Speichern ...",
|
||||||
"schedule": "Zeitplan",
|
"schedule": "Zeitplan",
|
||||||
|
"second": "zweite",
|
||||||
|
"seconds": "sekunden",
|
||||||
"seconds_elapsed": "Sekunden verstrichen",
|
"seconds_elapsed": "Sekunden verstrichen",
|
||||||
"serial_number": "Seriennummer",
|
"serial_number": "Seriennummer",
|
||||||
"start": "Start",
|
"start": "Start",
|
||||||
@@ -92,6 +107,7 @@
|
|||||||
"last_configuration_change": "Letzte Konfigurationsänderung",
|
"last_configuration_change": "Letzte Konfigurationsänderung",
|
||||||
"last_configuration_download": "Letzter Konfigurations-Download",
|
"last_configuration_download": "Letzter Konfigurations-Download",
|
||||||
"location": "Ort",
|
"location": "Ort",
|
||||||
|
"note": "Hinweis",
|
||||||
"notes": "Anmerkungen",
|
"notes": "Anmerkungen",
|
||||||
"owner": "Inhaber",
|
"owner": "Inhaber",
|
||||||
"title": "Gerätekonfiguration",
|
"title": "Gerätekonfiguration",
|
||||||
@@ -140,14 +156,16 @@
|
|||||||
"login": "Anmeldung",
|
"login": "Anmeldung",
|
||||||
"login_error": "Anmeldefehler, bestätigen Sie, dass Ihr Benutzername, Ihr Passwort und Ihre Gateway-URL gültig sind",
|
"login_error": "Anmeldefehler, bestätigen Sie, dass Ihr Benutzername, Ihr Passwort und Ihre Gateway-URL gültig sind",
|
||||||
"password": "Passwort",
|
"password": "Passwort",
|
||||||
"please_enter_gateway": "Bitte geben Sie eine Gateway-URL ein",
|
"please_enter_gateway": "Bitte geben Sie eine uCentralSec-URL ein",
|
||||||
"please_enter_password": "Bitte geben Sie Ihr Passwort ein",
|
"please_enter_password": "Bitte geben Sie Ihr Passwort ein",
|
||||||
"please_enter_username": "Bitte geben Sie Ihren Benutzernamen ein",
|
"please_enter_username": "Bitte geben Sie Ihren Benutzernamen ein",
|
||||||
"sign_in_to_account": "Melden Sie sich bei Ihrem Konto an",
|
"sign_in_to_account": "Melden Sie sich bei Ihrem Konto an",
|
||||||
|
"url": "uCentralSec-URL",
|
||||||
"username": "Benutzername"
|
"username": "Benutzername"
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"directions": "Wann möchten Sie dieses Gerät neu starten?",
|
"directions": "Wann möchten Sie dieses Gerät neu starten?",
|
||||||
|
"now": "Möchten Sie dieses Gerät jetzt neu starten?",
|
||||||
"title": "Gerät neustarten"
|
"title": "Gerät neustarten"
|
||||||
},
|
},
|
||||||
"scan": {
|
"scan": {
|
||||||
@@ -167,10 +185,23 @@
|
|||||||
"show_latest": "Neueste Statistiken anzeigen JSON",
|
"show_latest": "Neueste Statistiken anzeigen JSON",
|
||||||
"title": "Statistiken"
|
"title": "Statistiken"
|
||||||
},
|
},
|
||||||
|
"status": {
|
||||||
|
"connection_status": "Verbindungsstatus",
|
||||||
|
"error": "Statusdaten sind nicht verfügbar",
|
||||||
|
"last_contact": "Letzter Kontakt",
|
||||||
|
"load_averages": "Belastung (Durchschnitt 1 / 5 / 15 Minuten)",
|
||||||
|
"localtime": "Ortszeit",
|
||||||
|
"memory": "Verwendeter Speicher",
|
||||||
|
"percentage_free": "{{percentage}}% von {{total}} kostenlos",
|
||||||
|
"percentage_used": "{{percentage}}% von {{total}} verwendet",
|
||||||
|
"title": "#{{serialNumber}} Status",
|
||||||
|
"uptime": "Betriebszeit",
|
||||||
|
"used_total_memory": "{{used}} verwendet / {{total}} insgesamt"
|
||||||
|
},
|
||||||
"trace": {
|
"trace": {
|
||||||
"choose_network": "Netzwerk auswählen",
|
"choose_network": "Netzwerk auswählen",
|
||||||
"directions": "Starten Sie eine Tcpdump auf diesem Geräts für eine bestimmte Dauer oder eine Anzahl von Paketen",
|
"directions": "Starten Sie eine Tcpdump auf diesem Geräts für eine bestimmte Dauer oder eine Anzahl von Paketen",
|
||||||
"download_trace": "Klicke hier zum herunterladen",
|
"download_trace": "Trace-Datei herunterladen",
|
||||||
"packets": "Pakete",
|
"packets": "Pakete",
|
||||||
"title": "Tcpdump",
|
"title": "Tcpdump",
|
||||||
"trace": "Spur",
|
"trace": "Spur",
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"blink": {
|
"blink": {
|
||||||
"blink": "Blink",
|
"blink": "Blink",
|
||||||
"device_leds": "Device LEDs",
|
"device_leds": "Device LEDs",
|
||||||
"pattern": "Choose the pattern you would like to use: ",
|
"execute_now": "Would you like to set this pattern now?",
|
||||||
|
"pattern": "LEDs pattern: ",
|
||||||
|
"set_leds": "Set LEDs",
|
||||||
"when_blink_leds": "When would you like to make the device LEDs blink?"
|
"when_blink_leds": "When would you like to make the device LEDs blink?"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"title": "Command History"
|
"title": "Command History"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"add": "Add",
|
||||||
|
"adding_ellipsis": "Adding...",
|
||||||
"are_you_sure": "Are you sure?",
|
"are_you_sure": "Are you sure?",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"certificate": "Certificate",
|
"certificate": "Certificate",
|
||||||
@@ -36,7 +40,11 @@
|
|||||||
"connected": "Connected",
|
"connected": "Connected",
|
||||||
"copied": "Copied!",
|
"copied": "Copied!",
|
||||||
"copy_to_clipboard": "Copy to clipboard",
|
"copy_to_clipboard": "Copy to clipboard",
|
||||||
|
"created_by": "Created By",
|
||||||
|
"custom_date": "Custom Date",
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
|
"day": "day",
|
||||||
|
"days": "days",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"device_list": "List of Devices",
|
"device_list": "List of Devices",
|
||||||
@@ -52,6 +60,8 @@
|
|||||||
"exit": "Exit",
|
"exit": "Exit",
|
||||||
"firmware": "Firmware",
|
"firmware": "Firmware",
|
||||||
"from": "From",
|
"from": "From",
|
||||||
|
"hour": "hour",
|
||||||
|
"hours": "hours",
|
||||||
"id": "Id",
|
"id": "Id",
|
||||||
"ip_address": "Ip Address",
|
"ip_address": "Ip Address",
|
||||||
"later_tonight": "Later tonight",
|
"later_tonight": "Later tonight",
|
||||||
@@ -60,9 +70,12 @@
|
|||||||
"logout": "Logout",
|
"logout": "Logout",
|
||||||
"mac": "MAC Address",
|
"mac": "MAC Address",
|
||||||
"manufacturer": "Manufacturer",
|
"manufacturer": "Manufacturer",
|
||||||
|
"minute": "minute",
|
||||||
|
"minutes": "minutes",
|
||||||
"na": "N/A",
|
"na": "N/A",
|
||||||
"need_date": "You need a date...",
|
"need_date": "You need a date...",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
"no_items": "No Items",
|
||||||
"not_connected": "Not Connected",
|
"not_connected": "Not Connected",
|
||||||
"off": "Off",
|
"off": "Off",
|
||||||
"on": "On",
|
"on": "On",
|
||||||
@@ -73,6 +86,8 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"saving": "Saving... ",
|
"saving": "Saving... ",
|
||||||
"schedule": "Schedule",
|
"schedule": "Schedule",
|
||||||
|
"second": "second",
|
||||||
|
"seconds": "seconds",
|
||||||
"seconds_elapsed": "Seconds elapsed",
|
"seconds_elapsed": "Seconds elapsed",
|
||||||
"serial_number": "Serial Number",
|
"serial_number": "Serial Number",
|
||||||
"start": "Start",
|
"start": "Start",
|
||||||
@@ -92,6 +107,7 @@
|
|||||||
"last_configuration_change": "Last Configuration Change",
|
"last_configuration_change": "Last Configuration Change",
|
||||||
"last_configuration_download": "Last Configuration Download",
|
"last_configuration_download": "Last Configuration Download",
|
||||||
"location": "Location",
|
"location": "Location",
|
||||||
|
"note": "Note",
|
||||||
"notes": "Notes",
|
"notes": "Notes",
|
||||||
"owner": "Owner",
|
"owner": "Owner",
|
||||||
"title": "Configuration",
|
"title": "Configuration",
|
||||||
@@ -140,14 +156,16 @@
|
|||||||
"login": "Login",
|
"login": "Login",
|
||||||
"login_error": "Login error, confirm that your username, password and gateway url are valid",
|
"login_error": "Login error, confirm that your username, password and gateway url are valid",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"please_enter_gateway": "Please enter a gateway URL",
|
"please_enter_gateway": "Please enter a uCentralSec URL",
|
||||||
"please_enter_password": "Please enter your password",
|
"please_enter_password": "Please enter your password",
|
||||||
"please_enter_username": "Please enter your username",
|
"please_enter_username": "Please enter your username",
|
||||||
"sign_in_to_account": "Sign in to your account",
|
"sign_in_to_account": "Sign in to your account",
|
||||||
|
"url": "uCentralSec URL",
|
||||||
"username": "Username"
|
"username": "Username"
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"directions": "When would you like to reboot this device?",
|
"directions": "When would you like to reboot this device?",
|
||||||
|
"now": "Would you like to reboot this device now?",
|
||||||
"title": "Reboot"
|
"title": "Reboot"
|
||||||
},
|
},
|
||||||
"scan": {
|
"scan": {
|
||||||
@@ -167,10 +185,23 @@
|
|||||||
"show_latest": "Show latest statistics JSON",
|
"show_latest": "Show latest statistics JSON",
|
||||||
"title": "Statistics"
|
"title": "Statistics"
|
||||||
},
|
},
|
||||||
|
"status": {
|
||||||
|
"connection_status": "Connection Status",
|
||||||
|
"error": "Status data is unavailable",
|
||||||
|
"last_contact": "Last Contact",
|
||||||
|
"load_averages": "Load ( 1 / 5 / 15 minute average)",
|
||||||
|
"localtime": "Localtime",
|
||||||
|
"memory": "Memory Used",
|
||||||
|
"percentage_free": "{{percentage}}% of {{total}} free",
|
||||||
|
"percentage_used": "{{percentage}}% of {{total}} used",
|
||||||
|
"title": "#{{serialNumber}} Status",
|
||||||
|
"uptime": "Uptime",
|
||||||
|
"used_total_memory": "{{used}} used / {{total}} total "
|
||||||
|
},
|
||||||
"trace": {
|
"trace": {
|
||||||
"choose_network": "Choose network",
|
"choose_network": "Choose network",
|
||||||
"directions": "Launch a remote trace of this device for either a specific duration or a number of packets",
|
"directions": "Launch a remote trace of this device for either a specific duration or a number of packets",
|
||||||
"download_trace": "Click here to download",
|
"download_trace": "Download Trace File",
|
||||||
"packets": "Packets",
|
"packets": "Packets",
|
||||||
"title": "Trace",
|
"title": "Trace",
|
||||||
"trace": "Trace",
|
"trace": "Trace",
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"blink": {
|
"blink": {
|
||||||
"blink": "Parpadeo",
|
"blink": "Parpadeo",
|
||||||
"device_leds": "LED de dispositivo",
|
"device_leds": "LED de dispositivo",
|
||||||
|
"execute_now": "¿Le gustaría establecer este patrón ahora?",
|
||||||
"pattern": "Elija el patrón que le gustaría usar:",
|
"pattern": "Elija el patrón que le gustaría usar:",
|
||||||
|
"set_leds": "Establecer LED",
|
||||||
"when_blink_leds": "¿Cuándo desea que los LED del dispositivo parpadeen?"
|
"when_blink_leds": "¿Cuándo desea que los LED del dispositivo parpadeen?"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"title": "Historial de Comandos"
|
"title": "Historial de Comandos"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"add": "Añadir",
|
||||||
|
"adding_ellipsis": "Añadiendo ...",
|
||||||
"are_you_sure": "¿Estás seguro?",
|
"are_you_sure": "¿Estás seguro?",
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"certificate": "Certificado",
|
"certificate": "Certificado",
|
||||||
@@ -36,7 +40,11 @@
|
|||||||
"connected": "Conectado",
|
"connected": "Conectado",
|
||||||
"copied": "Copiado!",
|
"copied": "Copiado!",
|
||||||
"copy_to_clipboard": "Copiar al portapapeles",
|
"copy_to_clipboard": "Copiar al portapapeles",
|
||||||
|
"created_by": "Creado por",
|
||||||
|
"custom_date": "Fecha personalizada",
|
||||||
"date": "Fecha",
|
"date": "Fecha",
|
||||||
|
"day": "día",
|
||||||
|
"days": "días",
|
||||||
"delete": "Borrar",
|
"delete": "Borrar",
|
||||||
"details": "Detalles",
|
"details": "Detalles",
|
||||||
"device_list": "Listado de dispositivos",
|
"device_list": "Listado de dispositivos",
|
||||||
@@ -52,6 +60,8 @@
|
|||||||
"exit": "salida",
|
"exit": "salida",
|
||||||
"firmware": "Firmware",
|
"firmware": "Firmware",
|
||||||
"from": "Desde",
|
"from": "Desde",
|
||||||
|
"hour": "hora",
|
||||||
|
"hours": "horas",
|
||||||
"id": "Carné de identidad",
|
"id": "Carné de identidad",
|
||||||
"ip_address": "Dirección IP",
|
"ip_address": "Dirección IP",
|
||||||
"later_tonight": "Más tarde esta noche",
|
"later_tonight": "Más tarde esta noche",
|
||||||
@@ -60,9 +70,12 @@
|
|||||||
"logout": "Cerrar sesión",
|
"logout": "Cerrar sesión",
|
||||||
"mac": "Dirección MAC",
|
"mac": "Dirección MAC",
|
||||||
"manufacturer": "Fabricante",
|
"manufacturer": "Fabricante",
|
||||||
|
"minute": "minuto",
|
||||||
|
"minutes": "minutos",
|
||||||
"na": "N / A",
|
"na": "N / A",
|
||||||
"need_date": "Necesitas una cita ...",
|
"need_date": "Necesitas una cita ...",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
"no_items": "No hay articulos",
|
||||||
"not_connected": "No conectado",
|
"not_connected": "No conectado",
|
||||||
"off": "Apagado",
|
"off": "Apagado",
|
||||||
"on": "en",
|
"on": "en",
|
||||||
@@ -73,6 +86,8 @@
|
|||||||
"save": "Salvar",
|
"save": "Salvar",
|
||||||
"saving": "Ahorro...",
|
"saving": "Ahorro...",
|
||||||
"schedule": "Programar",
|
"schedule": "Programar",
|
||||||
|
"second": "segundo",
|
||||||
|
"seconds": "segundos",
|
||||||
"seconds_elapsed": "Segundos transcurridos",
|
"seconds_elapsed": "Segundos transcurridos",
|
||||||
"serial_number": "Número de serie",
|
"serial_number": "Número de serie",
|
||||||
"start": "comienzo",
|
"start": "comienzo",
|
||||||
@@ -92,6 +107,7 @@
|
|||||||
"last_configuration_change": "Último cambio de configuración",
|
"last_configuration_change": "Último cambio de configuración",
|
||||||
"last_configuration_download": "Descarga de la última configuración",
|
"last_configuration_download": "Descarga de la última configuración",
|
||||||
"location": "Ubicación",
|
"location": "Ubicación",
|
||||||
|
"note": "Nota",
|
||||||
"notes": "Notas",
|
"notes": "Notas",
|
||||||
"owner": "Propietario",
|
"owner": "Propietario",
|
||||||
"title": "Configuración",
|
"title": "Configuración",
|
||||||
@@ -140,14 +156,16 @@
|
|||||||
"login": "Iniciar sesión",
|
"login": "Iniciar sesión",
|
||||||
"login_error": "Error de inicio de sesión, confirme que su nombre de usuario, contraseña y URL de puerta de enlace son válidos",
|
"login_error": "Error de inicio de sesión, confirme que su nombre de usuario, contraseña y URL de puerta de enlace son válidos",
|
||||||
"password": "Contraseña",
|
"password": "Contraseña",
|
||||||
"please_enter_gateway": "Ingrese una URL de puerta de enlace",
|
"please_enter_gateway": "Ingrese una URL de uCentralSec",
|
||||||
"please_enter_password": "Por favor, introduzca su contraseña",
|
"please_enter_password": "Por favor, introduzca su contraseña",
|
||||||
"please_enter_username": "Por favor, ingrese su nombre de usuario",
|
"please_enter_username": "Por favor, ingrese su nombre de usuario",
|
||||||
"sign_in_to_account": "Iniciar sesión en su cuenta",
|
"sign_in_to_account": "Iniciar sesión en su cuenta",
|
||||||
|
"url": "URL de uCentralSec",
|
||||||
"username": "Nombre de usuario"
|
"username": "Nombre de usuario"
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"directions": "¿Cuándo le gustaría reiniciar este dispositivo?",
|
"directions": "¿Cuándo le gustaría reiniciar este dispositivo?",
|
||||||
|
"now": "¿Le gustaría reiniciar este dispositivo ahora?",
|
||||||
"title": "Reiniciar"
|
"title": "Reiniciar"
|
||||||
},
|
},
|
||||||
"scan": {
|
"scan": {
|
||||||
@@ -167,10 +185,23 @@
|
|||||||
"show_latest": "Mostrar las últimas estadísticas JSON",
|
"show_latest": "Mostrar las últimas estadísticas JSON",
|
||||||
"title": "estadística"
|
"title": "estadística"
|
||||||
},
|
},
|
||||||
|
"status": {
|
||||||
|
"connection_status": "Estado de conexión",
|
||||||
|
"error": "Los datos de estado no están disponibles",
|
||||||
|
"last_contact": "Último contacto",
|
||||||
|
"load_averages": "Carga (promedio de 1/5/15 minutos)",
|
||||||
|
"localtime": "Hora local",
|
||||||
|
"memory": "Memoria usada",
|
||||||
|
"percentage_free": "{{percentage}}% de {{total}} gratis",
|
||||||
|
"percentage_used": "{{percentage}}% de {{total}} utilizado",
|
||||||
|
"title": "#{{serialNumber}} Estado",
|
||||||
|
"uptime": "Tiempo de actividad",
|
||||||
|
"used_total_memory": "{{used}} usado / {{total}} total"
|
||||||
|
},
|
||||||
"trace": {
|
"trace": {
|
||||||
"choose_network": "Elija la red",
|
"choose_network": "Elija la red",
|
||||||
"directions": "Lanzar un rastreo remoto de este dispositivo por una duración específica o por una cantidad de paquetes",
|
"directions": "Lanzar un rastreo remoto de este dispositivo por una duración específica o por una cantidad de paquetes",
|
||||||
"download_trace": "Haga click aquí para descargar",
|
"download_trace": "Descargar archivo de seguimiento",
|
||||||
"packets": "Paquetes",
|
"packets": "Paquetes",
|
||||||
"title": "Rastro",
|
"title": "Rastro",
|
||||||
"trace": "Rastro",
|
"trace": "Rastro",
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"blink": {
|
"blink": {
|
||||||
"blink": "Cligner",
|
"blink": "Cligner",
|
||||||
"device_leds": "LED de l'appareil",
|
"device_leds": "LED de l'appareil",
|
||||||
|
"execute_now": "Souhaitez-vous définir ce modèle maintenant ?",
|
||||||
"pattern": "Choisissez le modèle que vous souhaitez utiliser :",
|
"pattern": "Choisissez le modèle que vous souhaitez utiliser :",
|
||||||
|
"set_leds": "Définir les LED",
|
||||||
"when_blink_leds": "Quand souhaitez-vous faire clignoter les LED de l'appareil ?"
|
"when_blink_leds": "Quand souhaitez-vous faire clignoter les LED de l'appareil ?"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"title": "Historique des commandes"
|
"title": "Historique des commandes"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"add": "Ajouter",
|
||||||
|
"adding_ellipsis": "Ajouter...",
|
||||||
"are_you_sure": "Êtes-vous sûr?",
|
"are_you_sure": "Êtes-vous sûr?",
|
||||||
"cancel": "annuler",
|
"cancel": "annuler",
|
||||||
"certificate": "Certificat",
|
"certificate": "Certificat",
|
||||||
@@ -36,7 +40,11 @@
|
|||||||
"connected": "Connecté",
|
"connected": "Connecté",
|
||||||
"copied": "Copié!",
|
"copied": "Copié!",
|
||||||
"copy_to_clipboard": "Copier dans le presse-papier",
|
"copy_to_clipboard": "Copier dans le presse-papier",
|
||||||
|
"created_by": "Créé par",
|
||||||
|
"custom_date": "Date personnalisée",
|
||||||
"date": "Rendez-vous amoureux",
|
"date": "Rendez-vous amoureux",
|
||||||
|
"day": "journée",
|
||||||
|
"days": "journées",
|
||||||
"delete": "Effacer",
|
"delete": "Effacer",
|
||||||
"details": "Détails",
|
"details": "Détails",
|
||||||
"device_list": "Liste des appareils",
|
"device_list": "Liste des appareils",
|
||||||
@@ -52,6 +60,8 @@
|
|||||||
"exit": "Sortie",
|
"exit": "Sortie",
|
||||||
"firmware": "Micrologiciel",
|
"firmware": "Micrologiciel",
|
||||||
"from": "De",
|
"from": "De",
|
||||||
|
"hour": "heure",
|
||||||
|
"hours": "heures",
|
||||||
"id": "Id",
|
"id": "Id",
|
||||||
"ip_address": "Adresse IP",
|
"ip_address": "Adresse IP",
|
||||||
"later_tonight": "Plus tard ce soir",
|
"later_tonight": "Plus tard ce soir",
|
||||||
@@ -60,9 +70,12 @@
|
|||||||
"logout": "Connectez - Out",
|
"logout": "Connectez - Out",
|
||||||
"mac": "ADRESSE MAC",
|
"mac": "ADRESSE MAC",
|
||||||
"manufacturer": "fabricant",
|
"manufacturer": "fabricant",
|
||||||
|
"minute": "minute",
|
||||||
|
"minutes": "minutes",
|
||||||
"na": "N / A",
|
"na": "N / A",
|
||||||
"need_date": "Vous avez besoin d'un rendez-vous...",
|
"need_date": "Vous avez besoin d'un rendez-vous...",
|
||||||
"no": "Non",
|
"no": "Non",
|
||||||
|
"no_items": "Pas d'objet",
|
||||||
"not_connected": "Pas connecté",
|
"not_connected": "Pas connecté",
|
||||||
"off": "De",
|
"off": "De",
|
||||||
"on": "sur",
|
"on": "sur",
|
||||||
@@ -73,6 +86,8 @@
|
|||||||
"save": "Sauvegarder",
|
"save": "Sauvegarder",
|
||||||
"saving": "Économie...",
|
"saving": "Économie...",
|
||||||
"schedule": "Programme",
|
"schedule": "Programme",
|
||||||
|
"second": "seconde",
|
||||||
|
"seconds": "secondes",
|
||||||
"seconds_elapsed": "Secondes écoulées",
|
"seconds_elapsed": "Secondes écoulées",
|
||||||
"serial_number": "Numéro de série",
|
"serial_number": "Numéro de série",
|
||||||
"start": "Début",
|
"start": "Début",
|
||||||
@@ -92,6 +107,7 @@
|
|||||||
"last_configuration_change": "Dernière modification de configuration",
|
"last_configuration_change": "Dernière modification de configuration",
|
||||||
"last_configuration_download": "Téléchargement de la dernière configuration",
|
"last_configuration_download": "Téléchargement de la dernière configuration",
|
||||||
"location": "Emplacement",
|
"location": "Emplacement",
|
||||||
|
"note": "Remarque",
|
||||||
"notes": "Remarques",
|
"notes": "Remarques",
|
||||||
"owner": "Propriétaire",
|
"owner": "Propriétaire",
|
||||||
"title": "Configuration",
|
"title": "Configuration",
|
||||||
@@ -140,14 +156,16 @@
|
|||||||
"login": "S'identifier",
|
"login": "S'identifier",
|
||||||
"login_error": "Erreur de connexion, confirmez que votre nom d'utilisateur, mot de passe et URL de passerelle sont valides",
|
"login_error": "Erreur de connexion, confirmez que votre nom d'utilisateur, mot de passe et URL de passerelle sont valides",
|
||||||
"password": "Mot de passe",
|
"password": "Mot de passe",
|
||||||
"please_enter_gateway": "Veuillez saisir une URL de passerelle",
|
"please_enter_gateway": "Veuillez saisir une URL uCentralSec",
|
||||||
"please_enter_password": "s'il vous plait entrez votre mot de passe",
|
"please_enter_password": "s'il vous plait entrez votre mot de passe",
|
||||||
"please_enter_username": "s'il vous plaît entrez votre nom d'utilisateur",
|
"please_enter_username": "s'il vous plaît entrez votre nom d'utilisateur",
|
||||||
"sign_in_to_account": "Connectez-vous à votre compte",
|
"sign_in_to_account": "Connectez-vous à votre compte",
|
||||||
|
"url": "URL uCentralSec",
|
||||||
"username": "Nom d'utilisateur"
|
"username": "Nom d'utilisateur"
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"directions": "Quand souhaitez-vous redémarrer cet appareil ?",
|
"directions": "Quand souhaitez-vous redémarrer cet appareil ?",
|
||||||
|
"now": "Souhaitez-vous redémarrer cet appareil maintenant ?",
|
||||||
"title": "Redémarrer"
|
"title": "Redémarrer"
|
||||||
},
|
},
|
||||||
"scan": {
|
"scan": {
|
||||||
@@ -167,10 +185,23 @@
|
|||||||
"show_latest": "Afficher les dernières statistiques JSON",
|
"show_latest": "Afficher les dernières statistiques JSON",
|
||||||
"title": "statistiques"
|
"title": "statistiques"
|
||||||
},
|
},
|
||||||
|
"status": {
|
||||||
|
"connection_status": "Statut de connexion",
|
||||||
|
"error": "Les données d'état ne sont pas disponibles",
|
||||||
|
"last_contact": "Dernier contact",
|
||||||
|
"load_averages": "Charge (moyenne 1 / 5 / 15 minutes)",
|
||||||
|
"localtime": "heure locale",
|
||||||
|
"memory": "Mémoire utilisée",
|
||||||
|
"percentage_free": "{{percentage}}% de {{total}} gratuit",
|
||||||
|
"percentage_used": "{{percentage}}% de {{total}} utilisé",
|
||||||
|
"title": "#{{serialNumber}} état",
|
||||||
|
"uptime": "La disponibilité",
|
||||||
|
"used_total_memory": "{{used}} utilisé / {{total}} total"
|
||||||
|
},
|
||||||
"trace": {
|
"trace": {
|
||||||
"choose_network": "Choisir le réseau",
|
"choose_network": "Choisir le réseau",
|
||||||
"directions": "Lancer une trace à distance de cet appareil pour une durée spécifique ou un nombre de paquets",
|
"directions": "Lancer une trace à distance de cet appareil pour une durée spécifique ou un nombre de paquets",
|
||||||
"download_trace": "Cliquez ici pour télécharger",
|
"download_trace": "Télécharger le fichier de trace",
|
||||||
"packets": "Paquets",
|
"packets": "Paquets",
|
||||||
"title": "Trace",
|
"title": "Trace",
|
||||||
"trace": "Trace",
|
"trace": "Trace",
|
||||||
|
|||||||
@@ -14,7 +14,9 @@
|
|||||||
"blink": {
|
"blink": {
|
||||||
"blink": "Piscar",
|
"blink": "Piscar",
|
||||||
"device_leds": "LEDs do dispositivo",
|
"device_leds": "LEDs do dispositivo",
|
||||||
|
"execute_now": "Você gostaria de definir este padrão agora?",
|
||||||
"pattern": "Escolha o padrão que deseja usar:",
|
"pattern": "Escolha o padrão que deseja usar:",
|
||||||
|
"set_leds": "Definir LEDs",
|
||||||
"when_blink_leds": "Quando você gostaria de fazer os LEDs do dispositivo piscarem?"
|
"when_blink_leds": "Quando você gostaria de fazer os LEDs do dispositivo piscarem?"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
@@ -23,6 +25,8 @@
|
|||||||
"title": "Histórico de Comandos"
|
"title": "Histórico de Comandos"
|
||||||
},
|
},
|
||||||
"common": {
|
"common": {
|
||||||
|
"add": "Adicionar",
|
||||||
|
"adding_ellipsis": "Adicionando ...",
|
||||||
"are_you_sure": "Você tem certeza?",
|
"are_you_sure": "Você tem certeza?",
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
"certificate": "Certificado",
|
"certificate": "Certificado",
|
||||||
@@ -36,7 +40,11 @@
|
|||||||
"connected": "Conectado",
|
"connected": "Conectado",
|
||||||
"copied": "Copiado!",
|
"copied": "Copiado!",
|
||||||
"copy_to_clipboard": "Copiar para área de transferência",
|
"copy_to_clipboard": "Copiar para área de transferência",
|
||||||
|
"created_by": "Criado Por",
|
||||||
|
"custom_date": "Data personalizada",
|
||||||
"date": "Encontro",
|
"date": "Encontro",
|
||||||
|
"day": "dia",
|
||||||
|
"days": "dias",
|
||||||
"delete": "Excluir",
|
"delete": "Excluir",
|
||||||
"details": "Detalhes",
|
"details": "Detalhes",
|
||||||
"device_list": "Lista de Dispositivos",
|
"device_list": "Lista de Dispositivos",
|
||||||
@@ -52,6 +60,8 @@
|
|||||||
"exit": "Saída",
|
"exit": "Saída",
|
||||||
"firmware": "Firmware",
|
"firmware": "Firmware",
|
||||||
"from": "De",
|
"from": "De",
|
||||||
|
"hour": "hora",
|
||||||
|
"hours": "horas",
|
||||||
"id": "identidade",
|
"id": "identidade",
|
||||||
"ip_address": "Endereço de IP",
|
"ip_address": "Endereço de IP",
|
||||||
"later_tonight": "Logo à noite",
|
"later_tonight": "Logo à noite",
|
||||||
@@ -60,9 +70,12 @@
|
|||||||
"logout": "Sair",
|
"logout": "Sair",
|
||||||
"mac": "Endereço MAC",
|
"mac": "Endereço MAC",
|
||||||
"manufacturer": "Fabricante",
|
"manufacturer": "Fabricante",
|
||||||
|
"minute": "minuto",
|
||||||
|
"minutes": "minutos",
|
||||||
"na": "N / D",
|
"na": "N / D",
|
||||||
"need_date": "Você precisa de um encontro ...",
|
"need_date": "Você precisa de um encontro ...",
|
||||||
"no": "Não",
|
"no": "Não",
|
||||||
|
"no_items": "Nenhum item",
|
||||||
"not_connected": "Não conectado",
|
"not_connected": "Não conectado",
|
||||||
"off": "Fora",
|
"off": "Fora",
|
||||||
"on": "em",
|
"on": "em",
|
||||||
@@ -73,6 +86,8 @@
|
|||||||
"save": "Salve",
|
"save": "Salve",
|
||||||
"saving": "Salvando ...",
|
"saving": "Salvando ...",
|
||||||
"schedule": "Cronograma",
|
"schedule": "Cronograma",
|
||||||
|
"second": "segundo",
|
||||||
|
"seconds": "segundos",
|
||||||
"seconds_elapsed": "Segundos decorridos",
|
"seconds_elapsed": "Segundos decorridos",
|
||||||
"serial_number": "Número de série",
|
"serial_number": "Número de série",
|
||||||
"start": "Começar",
|
"start": "Começar",
|
||||||
@@ -92,6 +107,7 @@
|
|||||||
"last_configuration_change": "Última Mudança de Configuração",
|
"last_configuration_change": "Última Mudança de Configuração",
|
||||||
"last_configuration_download": "Último download da configuração",
|
"last_configuration_download": "Último download da configuração",
|
||||||
"location": "Localização",
|
"location": "Localização",
|
||||||
|
"note": "Nota",
|
||||||
"notes": "notas",
|
"notes": "notas",
|
||||||
"owner": "Proprietário",
|
"owner": "Proprietário",
|
||||||
"title": "Configuração",
|
"title": "Configuração",
|
||||||
@@ -140,14 +156,16 @@
|
|||||||
"login": "Entrar",
|
"login": "Entrar",
|
||||||
"login_error": "Erro de login, confirme se seu nome de usuário, senha e url de gateway são válidos",
|
"login_error": "Erro de login, confirme se seu nome de usuário, senha e url de gateway são válidos",
|
||||||
"password": "Senha",
|
"password": "Senha",
|
||||||
"please_enter_gateway": "Insira um URL de gateway",
|
"please_enter_gateway": "Insira um URL uCentralSec",
|
||||||
"please_enter_password": "Por favor, insira sua senha",
|
"please_enter_password": "Por favor, insira sua senha",
|
||||||
"please_enter_username": "Por favor insira seu nome de usuário",
|
"please_enter_username": "Por favor insira seu nome de usuário",
|
||||||
"sign_in_to_account": "Faça login em sua conta",
|
"sign_in_to_account": "Faça login em sua conta",
|
||||||
|
"url": "URL uCentralSec",
|
||||||
"username": "Nome de usuário"
|
"username": "Nome de usuário"
|
||||||
},
|
},
|
||||||
"reboot": {
|
"reboot": {
|
||||||
"directions": "Quando você gostaria de reinicializar este dispositivo?",
|
"directions": "Quando você gostaria de reinicializar este dispositivo?",
|
||||||
|
"now": "Você gostaria de reiniciar este dispositivo agora?",
|
||||||
"title": "Reiniciar"
|
"title": "Reiniciar"
|
||||||
},
|
},
|
||||||
"scan": {
|
"scan": {
|
||||||
@@ -167,10 +185,23 @@
|
|||||||
"show_latest": "Mostrar estatísticas mais recentes JSON",
|
"show_latest": "Mostrar estatísticas mais recentes JSON",
|
||||||
"title": "Estatisticas"
|
"title": "Estatisticas"
|
||||||
},
|
},
|
||||||
|
"status": {
|
||||||
|
"connection_status": "Status da conexão",
|
||||||
|
"error": "Dados de status indisponíveis",
|
||||||
|
"last_contact": "Último contato",
|
||||||
|
"load_averages": "Carga (1/5/15 minutos em média)",
|
||||||
|
"localtime": "Horário local",
|
||||||
|
"memory": "Memória Usada",
|
||||||
|
"percentage_free": "{{percentage}}% de {{total}} grátis",
|
||||||
|
"percentage_used": "{{percentage}}% de {{total}} usado",
|
||||||
|
"title": "#{{serialNumber}} status",
|
||||||
|
"uptime": "Tempo de atividade",
|
||||||
|
"used_total_memory": "{{used}} usado / {{total}} total"
|
||||||
|
},
|
||||||
"trace": {
|
"trace": {
|
||||||
"choose_network": "Escolha a rede",
|
"choose_network": "Escolha a rede",
|
||||||
"directions": "Lançar um rastreamento remoto deste dispositivo para uma duração específica ou um número de pacotes",
|
"directions": "Lançar um rastreamento remoto deste dispositivo para uma duração específica ou um número de pacotes",
|
||||||
"download_trace": "Clique aqui para baixar",
|
"download_trace": "Baixar arquivo de rastreamento",
|
||||||
"packets": "Pacotes",
|
"packets": "Pacotes",
|
||||||
"title": "Vestígio",
|
"title": "Vestígio",
|
||||||
"trace": "Vestígio",
|
"trace": "Vestígio",
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"short_name": "React App",
|
|
||||||
"name": "Create React App Sample",
|
|
||||||
"icons": [
|
|
||||||
{
|
|
||||||
"src": "favicon.ico",
|
|
||||||
"sizes": "64x64 32x32 24x24 16x16",
|
|
||||||
"type": "image/x-icon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "favicon.svg",
|
|
||||||
"type": "image/svg",
|
|
||||||
"sizes": "192x192"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"src": "favicon.svg",
|
|
||||||
"type": "image/svg",
|
|
||||||
"sizes": "512x512"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"start_url": ".",
|
|
||||||
"display": "standalone",
|
|
||||||
"theme_color": "#000000",
|
|
||||||
"background_color": "#ffffff"
|
|
||||||
}
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 24.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 141.5 185.6" style="enable-background:new 0 0 141.5 185.6;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:#414141;}
|
|
||||||
.st1{fill:#FFFFFF;}
|
|
||||||
.st2{fill:#FED206;}
|
|
||||||
.st3{fill:#EB6F53;}
|
|
||||||
.st4{fill:#3BA9B6;}
|
|
||||||
</style>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st0" d="M120.7,183.9H21.5c-10.8,0-19.5-8.7-19.5-19.5V20.5c0-10.8,8.7-19.5,19.5-19.5h99.2
|
|
||||||
c10.8,0,19.5,8.7,19.5,19.5v143.9C140.2,175.2,131.5,183.9,120.7,183.9z"/>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M46.3,166.2v-3.4h-1.2v-0.6h3.1v0.6H47v3.4H46.3z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M49,166.2v-4h2.7v0.6h-2v1h2v0.6h-2v1.1h2v0.6H49z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M52.6,166.2v-4h0.7v3.4h1.8v0.6H52.6z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M55.7,166.2v-4h2.7v0.6h-2v1h2v0.6h-2v1.1h2v0.6H55.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M59.1,164.2c0-1.2,0.9-2.1,2.1-2.1c0.8,0,1.3,0.4,1.6,0.9l-0.6,0.3c-0.2-0.3-0.6-0.6-1-0.6
|
|
||||||
c-0.8,0-1.4,0.6-1.4,1.4c0,0.8,0.6,1.4,1.4,1.4c0.4,0,0.8-0.3,1-0.6l0.6,0.3c-0.3,0.5-0.8,0.9-1.6,0.9
|
|
||||||
C60,166.3,59.1,165.5,59.1,164.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M63.2,164.2c0-1.2,0.8-2.1,2-2.1c1.2,0,2,0.9,2,2.1c0,1.2-0.8,2.1-2,2.1C64,166.3,63.2,165.4,63.2,164.2z
|
|
||||||
M66.5,164.2c0-0.8-0.5-1.4-1.3-1.4c-0.8,0-1.3,0.6-1.3,1.4c0,0.8,0.5,1.4,1.3,1.4C66,165.7,66.5,165,66.5,164.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M71.3,166.2v-3.1l-1.2,3.1h-0.3l-1.2-3.1v3.1h-0.7v-4h1l1.1,2.7l1.1-2.7h1v4H71.3z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M75.7,166.2v-4h0.7v4H75.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M80.4,166.2l-2.1-2.8v2.8h-0.7v-4h0.7l2,2.8v-2.8h0.7v4H80.4z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M82.3,166.2v-4H85v0.6h-2v1h2v0.6h-2v1.7H82.3z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M87.9,166.2l-0.9-1.5h-0.7v1.5h-0.7v-4h1.7c0.8,0,1.3,0.5,1.3,1.2c0,0.7-0.5,1.1-0.9,1.2l1,1.6H87.9z
|
|
||||||
M88,163.5c0-0.4-0.3-0.6-0.7-0.6h-1v1.3h1C87.7,164.1,88,163.9,88,163.5z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M92.4,166.2l-0.3-0.8h-1.8l-0.3,0.8h-0.8l1.6-4h0.9l1.6,4H92.4z M91.2,162.9l-0.7,1.9h1.4L91.2,162.9z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M95.8,166.2v-4h1.5c0.8,0,1.2,0.5,1.2,1.2c0,0.6-0.4,1.2-1.2,1.2h-1.2v1.7H95.8z M98.2,163.4
|
|
||||||
c0-0.5-0.3-0.9-0.9-0.9h-1.1v1.7h1.1C97.8,164.3,98.2,163.9,98.2,163.4z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M101.5,166.2l-1.1-1.6h-0.9v1.6h-0.3v-4h1.5c0.7,0,1.2,0.4,1.2,1.2c0,0.7-0.5,1.1-1.1,1.1l1.2,1.7H101.5z
|
|
||||||
M101.6,163.4c0-0.5-0.4-0.9-0.9-0.9h-1.1v1.7h1.1C101.2,164.3,101.6,163.9,101.6,163.4z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M102.8,164.2c0-1.2,0.8-2.1,1.9-2.1c1.2,0,1.9,0.9,1.9,2.1c0,1.2-0.8,2.1-1.9,2.1
|
|
||||||
C103.6,166.3,102.8,165.4,102.8,164.2z M106.3,164.2c0-1-0.6-1.7-1.6-1.7c-1,0-1.6,0.7-1.6,1.7c0,1,0.6,1.7,1.6,1.7
|
|
||||||
C105.7,166,106.3,165.2,106.3,164.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M106.9,165.8l0.2-0.3c0.2,0.2,0.4,0.4,0.8,0.4c0.5,0,0.9-0.4,0.9-0.9v-2.8h0.3v2.8c0,0.8-0.5,1.2-1.2,1.2
|
|
||||||
C107.5,166.3,107.2,166.1,106.9,165.8z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M110.4,166.2v-4h2.5v0.3h-2.2v1.5h2.1v0.3h-2.1v1.6h2.2v0.3H110.4z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M113.5,164.2c0-1.2,0.9-2.1,2-2.1c0.6,0,1.1,0.3,1.5,0.7l-0.3,0.2c-0.3-0.3-0.7-0.6-1.2-0.6
|
|
||||||
c-0.9,0-1.7,0.7-1.7,1.7c0,1,0.7,1.7,1.7,1.7c0.5,0,0.9-0.2,1.2-0.6l0.3,0.2c-0.4,0.4-0.8,0.7-1.5,0.7
|
|
||||||
C114.4,166.3,113.5,165.5,113.5,164.2z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M118.7,166.2v-3.7h-1.3v-0.3h2.9v0.3H119v3.7H118.7z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<polygon class="st1" points="26.3,163.8 31.6,158.5 36.9,163.8 37.7,163.8 31.6,157.6 25.5,163.8 "/>
|
|
||||||
<polygon class="st1" points="36.9,164.7 31.6,170 26.3,164.7 25.5,164.7 31.6,170.8 37.7,164.7 "/>
|
|
||||||
<polygon class="st1" points="31,163.8 36.3,158.5 41.6,163.8 42.5,163.8 36.3,157.6 30.2,163.8 "/>
|
|
||||||
<polygon class="st1" points="41.6,164.7 36.3,170 31,164.7 30.2,164.7 36.3,170.8 42.5,164.7 "/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M33.2,100.7c-4.6,0-8.3,3.7-8.3,8.3s3.7,8.3,8.3,8.3s8.3-3.7,8.3-8.3S37.8,100.7,33.2,100.7z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st2" d="M33.2,35.2c40.7,0,73.8,33.1,73.8,73.8c0,0.7,0,1.4,0,2.1c0,1.7,0.6,3.3,1.7,4.6c1.2,1.2,2.8,1.9,4.5,2
|
|
||||||
l0.2,0c3.5,0,6.3-2.7,6.4-6.2c0-0.8,0-1.7,0-2.5c0-47.7-38.8-86.6-86.6-86.6c-0.8,0-1.7,0-2.5,0c-1.7,0-3.3,0.8-4.5,2
|
|
||||||
c-1.2,1.2-1.8,2.9-1.7,4.6c0.1,3.5,3,6.3,6.6,6.2C31.8,35.2,32.5,35.2,33.2,35.2z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st3" d="M33.2,60.5c26.7,0,48.5,21.7,48.5,48.5c0,0.6,0,1.3,0,2c-0.1,1.7,0.5,3.3,1.7,4.6c1.2,1.3,2.7,2,4.4,2.1
|
|
||||||
c1.7,0.1,3.3-0.5,4.6-1.7c1.2-1.2,2-2.7,2-4.4c0-0.9,0.1-1.8,0.1-2.6c0-33.8-27.5-61.2-61.2-61.2c-0.8,0-1.6,0-2.6,0.1
|
|
||||||
c-1.7,0.1-3.3,0.8-4.4,2.1c-1.2,1.3-1.8,2.9-1.7,4.6s0.8,3.3,2.1,4.4c1.3,1.2,2.9,1.8,4.6,1.7C31.9,60.5,32.6,60.5,33.2,60.5z"
|
|
||||||
/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<g>
|
|
||||||
<path class="st4" d="M33.2,86.7c12.3,0,22.3,10,22.3,22.3c0,0.5,0,1.1-0.1,1.8c-0.3,3.5,2.3,6.6,5.8,6.9
|
|
||||||
c3.5,0.3,6.6-2.3,6.9-5.8c0.1-1,0.1-1.9,0.1-2.8c0-19.3-15.7-35.1-35.1-35.1c-0.9,0-1.8,0-2.8,0.1c-1.7,0.1-3.2,0.9-4.3,2.2
|
|
||||||
c-1.1,1.3-1.6,2.9-1.5,4.6c0.1,1.7,0.9,3.2,2.2,4.3c1.3,1.1,2.9,1.6,4.6,1.5C32.1,86.7,32.7,86.7,33.2,86.7z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path class="st1" d="M35.8,130.4c1.1,0.6,2.1,1.5,2.7,2.6c0.7,1.1,1,2.3,1,3.7s-0.3,2.6-1,3.7c-0.7,1.1-1.6,2-2.7,2.6
|
|
||||||
c-1.1,0.6-2.4,1-3.8,1s-2.7-0.3-3.8-1c-1.1-0.6-2.1-1.5-2.7-2.6c-0.7-1.1-1-2.3-1-3.7c0-1.3,0.3-2.6,1-3.7c0.7-1.1,1.6-2,2.7-2.6
|
|
||||||
c1.1-0.6,2.4-0.9,3.8-0.9C33.4,129.5,34.7,129.8,35.8,130.4z M29.9,132.9c-0.7,0.4-1.2,0.9-1.6,1.6s-0.6,1.4-0.6,2.2
|
|
||||||
c0,0.8,0.2,1.6,0.6,2.3c0.4,0.7,0.9,1.2,1.6,1.6c0.7,0.4,1.4,0.6,2.1,0.6c0.8,0,1.5-0.2,2.1-0.6c0.6-0.4,1.2-0.9,1.5-1.6
|
|
||||||
c0.4-0.7,0.6-1.4,0.6-2.3c0-0.8-0.2-1.6-0.6-2.2s-0.9-1.2-1.5-1.6c-0.6-0.4-1.4-0.6-2.1-0.6C31.3,132.3,30.6,132.5,29.9,132.9z"/>
|
|
||||||
<path class="st1" d="M50.6,133.6c0.8,0.5,1.4,1.1,1.8,2c0.4,0.8,0.6,1.8,0.6,2.9c0,1.1-0.2,2-0.6,2.8c-0.4,0.8-1,1.5-1.8,1.9
|
|
||||||
c-0.8,0.5-1.6,0.7-2.6,0.7c-0.7,0-1.4-0.1-2-0.4s-1.1-0.7-1.5-1.2v5.4h-3.1V133h3.1v1.6c0.4-0.5,0.9-1,1.4-1.2s1.2-0.4,2-0.4
|
|
||||||
C48.9,132.9,49.8,133.1,50.6,133.6z M49.1,140.5c0.5-0.6,0.7-1.3,0.7-2.2c0-0.9-0.2-1.6-0.7-2.1c-0.5-0.6-1.1-0.8-1.9-0.8
|
|
||||||
s-1.4,0.3-1.9,0.8c-0.5,0.6-0.8,1.3-0.8,2.1c0,0.9,0.2,1.6,0.8,2.2s1.1,0.8,1.9,0.8S48.6,141,49.1,140.5z"/>
|
|
||||||
<path class="st1" d="M63.4,134.4c0.9,1,1.4,2.4,1.4,4.2c0,0.3,0,0.6,0,0.7H57c0.2,0.7,0.5,1.2,1,1.6c0.5,0.4,1.1,0.6,1.8,0.6
|
|
||||||
c0.5,0,1-0.1,1.5-0.3s0.9-0.5,1.3-0.9l1.6,1.6c-0.5,0.6-1.2,1.1-2,1.4c-0.8,0.3-1.6,0.5-2.6,0.5c-1.1,0-2.1-0.2-3-0.7
|
|
||||||
s-1.5-1.1-2-1.9c-0.5-0.8-0.7-1.8-0.7-2.9c0-1.1,0.2-2.1,0.7-2.9s1.1-1.5,2-1.9c0.8-0.5,1.8-0.7,2.9-0.7
|
|
||||||
C61.2,132.9,62.5,133.4,63.4,134.4z M61.8,137.5c0-0.7-0.3-1.3-0.7-1.7s-1-0.6-1.7-0.6c-0.7,0-1.2,0.2-1.7,0.6
|
|
||||||
c-0.4,0.4-0.7,1-0.9,1.7H61.8z"/>
|
|
||||||
<path class="st1" d="M76.2,134c0.7,0.7,1.1,1.7,1.1,3v6.8h-3.1v-5.9c0-0.7-0.2-1.2-0.6-1.6s-0.9-0.6-1.5-0.6
|
|
||||||
c-0.8,0-1.4,0.3-1.8,0.8c-0.4,0.5-0.7,1.2-0.7,2v5.3h-3.1V133h3.1v1.9c0.7-1.3,2-2,3.7-2C74.6,132.8,75.5,133.2,76.2,134z"/>
|
|
||||||
<path class="st1" d="M96,129.7h3.3l-4.7,14h-3.3l-2.9-10.1l-3,10.1h-3.2l-4.7-14h3.4l3,10.7l3-10.7H90l3.1,10.7L96,129.7z"/>
|
|
||||||
<path class="st1" d="M103.3,128.7c0.3,0.3,0.5,0.7,0.5,1.2s-0.2,0.9-0.5,1.2c-0.3,0.3-0.7,0.5-1.2,0.5c-0.5,0-0.9-0.2-1.2-0.5
|
|
||||||
c-0.3-0.3-0.5-0.7-0.5-1.2c0-0.5,0.2-0.9,0.5-1.2c0.3-0.3,0.7-0.5,1.2-0.5C102.6,128.2,103,128.3,103.3,128.7z M100.6,133h3.1
|
|
||||||
v10.8h-3.1V133z"/>
|
|
||||||
<path class="st1" d="M106.5,129.7h10.1l0,2.6h-6.9v3.4h6.3v2.6h-6.3v5.3h-3.2V129.7z"/>
|
|
||||||
<path class="st1" d="M120.9,128.7c0.3,0.3,0.5,0.7,0.5,1.2s-0.2,0.9-0.5,1.2c-0.3,0.3-0.7,0.5-1.2,0.5c-0.5,0-0.9-0.2-1.2-0.5
|
|
||||||
c-0.3-0.3-0.5-0.7-0.5-1.2c0-0.5,0.2-0.9,0.5-1.2c0.3-0.3,0.7-0.5,1.2-0.5C120.1,128.2,120.5,128.3,120.9,128.7z M118.1,133h3.1
|
|
||||||
v10.8h-3.1V133z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 8.0 KiB |
@@ -1,2 +0,0 @@
|
|||||||
# https://www.robotstxt.org/robotstxt.html
|
|
||||||
User-agent: *
|
|
||||||
32
src/App.js
32
src/App.js
@@ -1,7 +1,9 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { HashRouter, Route, Switch } from 'react-router-dom';
|
import { HashRouter, Switch } from 'react-router-dom';
|
||||||
import 'scss/style.scss';
|
import 'scss/style.scss';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import Router from 'router';
|
||||||
|
import { AuthProvider } from 'contexts/AuthProvider';
|
||||||
|
import { checkIfJson } from 'utils/helper';
|
||||||
|
|
||||||
const loading = (
|
const loading = (
|
||||||
<div className="pt-3 text-center">
|
<div className="pt-3 text-center">
|
||||||
@@ -9,32 +11,22 @@ const loading = (
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
const TheLayout = React.lazy(() => import('layout'));
|
|
||||||
const Login = React.lazy(() => import('pages/LoginPage'));
|
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const isLoggedIn = useSelector((state) => state.connected);
|
const storageToken = sessionStorage.getItem('access_token');
|
||||||
const dispatch = useDispatch();
|
const apiEndpoints = checkIfJson(sessionStorage.getItem('gateway_endpoints'))
|
||||||
|
? JSON.parse(sessionStorage.getItem('gateway_endpoints'))
|
||||||
useEffect(() => {
|
: {};
|
||||||
const token = sessionStorage.getItem('access_token');
|
|
||||||
if (token !== undefined && token !== null) {
|
|
||||||
dispatch({ type: 'set', connected: true });
|
|
||||||
}
|
|
||||||
}, [dispatch]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<AuthProvider token={storageToken ?? ''} apiEndpoints={apiEndpoints}>
|
||||||
<HashRouter>
|
<HashRouter>
|
||||||
<React.Suspense fallback={loading}>
|
<React.Suspense fallback={loading}>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route
|
<Router />
|
||||||
path="/"
|
|
||||||
name="Devices"
|
|
||||||
render={(props) => (isLoggedIn ? <TheLayout {...props} /> : <Login {...props} />)}
|
|
||||||
/>
|
|
||||||
</Switch>
|
</Switch>
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</HashRouter>
|
</HashRouter>
|
||||||
|
</AuthProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 24 KiB |
@@ -122,14 +122,11 @@ import {
|
|||||||
cilXCircle,
|
cilXCircle,
|
||||||
cilWarning,
|
cilWarning,
|
||||||
} from '@coreui/icons';
|
} from '@coreui/icons';
|
||||||
import { sygnet } from './sygnet';
|
|
||||||
import { logo } from './logo';
|
import { logo } from './CoreuiLogo';
|
||||||
import { logoNegative } from './logo-negative';
|
|
||||||
|
|
||||||
export const icons = {
|
export const icons = {
|
||||||
sygnet,
|
|
||||||
logo,
|
logo,
|
||||||
logoNegative,
|
|
||||||
cilAlignCenter,
|
cilAlignCenter,
|
||||||
cilAlignLeft,
|
cilAlignLeft,
|
||||||
cilAlignRight,
|
cilAlignRight,
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
export const logoNegative = [
|
|
||||||
'608 134',
|
|
||||||
`
|
|
||||||
<title>coreui react pro logo</title>
|
|
||||||
<g>
|
|
||||||
<g style="fill:#80d0ff;">
|
|
||||||
<path d="M362.0177,90.1512,353.25,69.4149a.2507.2507,0,0,0-.2559-.1914H343.01a.2263.2263,0,0,0-.2559.2559V90.0233a.5657.5657,0,0,1-.64.64h-1.2163a.5652.5652,0,0,1-.64-.64V46.5028a.5655.5655,0,0,1,.64-.64H353.442a9.9792,9.9792,0,0,1,7.7437,3.2324A12.2,12.2,0,0,1,364.13,57.64a12.4389,12.4389,0,0,1-2.24,7.584,9.37,9.37,0,0,1-6.08,3.7441c-.1709.086-.2139.1915-.128.3194l8.7041,20.6084.064.2558q0,.5127-.5757.5118h-1.1523A.703.703,0,0,1,362.0177,90.1512ZM342.754,48.3593v18.496a.2259.2259,0,0,0,.2559.2559h10.3037a7.6713,7.6713,0,0,0,6.0166-2.5918,9.8807,9.8807,0,0,0,2.3037-6.8164,10.2875,10.2875,0,0,0-2.272-6.9756,7.6033,7.6033,0,0,0-6.0483-2.624H343.01A.2263.2263,0,0,0,342.754,48.3593Z"/>
|
|
||||||
<path d="M401.3263,48.1034H381.2945a.2262.2262,0,0,0-.2558.2559v18.496a.2259.2259,0,0,0,.2558.2559h13.8238a.5664.5664,0,0,1,.6406.64v.96a.5663.5663,0,0,1-.6406.6406H381.2945a.2263.2263,0,0,0-.2558.2559v18.56a.2258.2258,0,0,0,.2558.2558h20.0318a.5671.5671,0,0,1,.6406.6407v.96a.566.566,0,0,1-.6406.64H379.1827a.5653.5653,0,0,1-.64-.64V46.5028a.5656.5656,0,0,1,.64-.64h22.1436a.5664.5664,0,0,1,.6406.64v.96A.5663.5663,0,0,1,401.3263,48.1034Z"/>
|
|
||||||
<path d="M439.047,90.1512l-2.4317-8.832a.2971.2971,0,0,0-.32-.1924H419.5274a.2957.2957,0,0,0-.32.1924l-2.3681,8.7676a.6577.6577,0,0,1-.7036.5762H414.919a.5385.5385,0,0,1-.5756-.7041l12.0317-43.584a.6436.6436,0,0,1,.7041-.5117h1.6a.6442.6442,0,0,1,.7041.5117l12.16,43.584.0644.1923q0,.5127-.64.5118h-1.2163A.6428.6428,0,0,1,439.047,90.1512ZM419.9435,78.9188a.3031.3031,0,0,0,.2236.0967h15.4883a.3048.3048,0,0,0,.2236-.0967c.0645-.0635.0742-.1162.0322-.1592l-7.872-28.9287c-.043-.0849-.086-.1279-.128-.1279s-.0859.043-.1279.1279L419.9112,78.76C419.8683,78.8026,419.879,78.8553,419.9435,78.9188Z"/>
|
|
||||||
<path d="M456.6017,87.911a11.6372,11.6372,0,0,1-3.3277-8.7041V57.1913a11.4158,11.4158,0,0,1,3.36-8.5762,12.0941,12.0941,0,0,1,8.8-3.2637,12.2566,12.2566,0,0,1,8.8643,3.2315,11.3927,11.3927,0,0,1,3.36,8.6084v.64a.5663.5663,0,0,1-.6406.6407l-1.28.0634q-.6408,0-.64-.5761v-.8321a9.289,9.289,0,0,0-2.6558-6.9121,10.6734,10.6734,0,0,0-14.0161,0,9.2854,9.2854,0,0,0-2.6563,6.9121V79.3993a9.2808,9.2808,0,0,0,2.6563,6.9121,10.67,10.67,0,0,0,14.0161,0,9.2843,9.2843,0,0,0,2.6558-6.9121v-.7686q0-.5757.64-.5752l1.28.0635a.5667.5667,0,0,1,.6406.6406v.5118a11.4952,11.4952,0,0,1-3.36,8.64,13.6227,13.6227,0,0,1-17.6963,0Z"/>
|
|
||||||
<path d="M514.4376,46.5028v.96a.5658.5658,0,0,1-.64.6406H503.046a.2263.2263,0,0,0-.2559.2559v41.664a.566.566,0,0,1-.6406.64h-1.2158a.5652.5652,0,0,1-.64-.64V48.3593a.2266.2266,0,0,0-.2558-.2559H489.8619a.5656.5656,0,0,1-.64-.6406v-.96a.5656.5656,0,0,1,.64-.64H513.798A.5658.5658,0,0,1,514.4376,46.5028Z"/>
|
|
||||||
<path d="M522.0665,89.5116a2.8385,2.8385,0,0,1-.8-2.0488,2.9194,2.9194,0,0,1,.8-2.1114,2.7544,2.7544,0,0,1,2.08-.832,2.8465,2.8465,0,0,1,2.9438,2.9434,2.7541,2.7541,0,0,1-.832,2.08,2.9221,2.9221,0,0,1-2.1118.8008A2.754,2.754,0,0,1,522.0665,89.5116Z"/>
|
|
||||||
<path d="M542.4054,88.0077a11.3123,11.3123,0,0,1-3.2-8.416v-5.44a.5656.5656,0,0,1,.64-.64h1.2158a.5661.5661,0,0,1,.64.64v5.5039a9.1424,9.1424,0,0,0,2.5283,6.72,8.9745,8.9745,0,0,0,6.6875,2.5605,8.7908,8.7908,0,0,0,9.28-9.28V46.5028a.5655.5655,0,0,1,.64-.64h1.2163a.566.566,0,0,1,.64.64V79.5917a11.2545,11.2545,0,0,1-3.2325,8.416,13.0618,13.0618,0,0,1-17.0556,0Z"/>
|
|
||||||
<path d="M580.35,88.1034a10.4859,10.4859,0,0,1-3.36-8.1279v-1.792a.5663.5663,0,0,1,.64-.6407h1.0884a.5668.5668,0,0,1,.64.6407v1.6a8.5459,8.5459,0,0,0,2.752,6.6562,10.5353,10.5353,0,0,0,7.36,2.4961,9.8719,9.8719,0,0,0,6.9761-2.3681,8.2161,8.2161,0,0,0,2.56-6.336,8.4,8.4,0,0,0-1.12-4.416,11.3812,11.3812,0,0,0-3.3281-3.3926,71.6714,71.6714,0,0,0-6.1763-3.7119,71.0479,71.0479,0,0,1-6.24-3.84,12.1711,12.1711,0,0,1-3.4238-3.68,10.2614,10.2614,0,0,1-1.28-5.3438,9.8579,9.8579,0,0,1,3.0718-7.7441,12.0122,12.0122,0,0,1,8.32-2.752q5.6954,0,8.96,3.1036a10.8251,10.8251,0,0,1,3.2642,8.2246v1.6a.5658.5658,0,0,1-.64.64h-1.1519a.5652.5652,0,0,1-.64-.64V56.8075a8.8647,8.8647,0,0,0-2.624-6.6885,9.9933,9.9933,0,0,0-7.232-2.5273,9.37,9.37,0,0,0-6.5278,2.1435,7.8224,7.8224,0,0,0-2.3682,6.1123,7.8006,7.8006,0,0,0,1.0244,4.16,10.387,10.387,0,0,0,3.0078,3.0391,62.8714,62.8714,0,0,0,5.9522,3.4882,71.0575,71.0575,0,0,1,6.72,4.2559,13.4674,13.4674,0,0,1,3.648,3.9365,10.049,10.049,0,0,1,1.28,5.1836,10.7177,10.7177,0,0,1-3.2637,8.1924q-3.2637,3.0717-8.832,3.0723Q583.71,91.1757,580.35,88.1034Z"/>
|
|
||||||
</g>
|
|
||||||
|
|
||||||
<g style="fill:#fff;">
|
|
||||||
<g>
|
|
||||||
<path d="M99.835,36.0577l-39-22.5167a12,12,0,0,0-12,0l-39,22.5166a12.0339,12.0339,0,0,0-6,10.3924V91.4833a12.0333,12.0333,0,0,0,6,10.3923l39,22.5167a12,12,0,0,0,12,0l39-22.5167a12.0331,12.0331,0,0,0,6-10.3923V46.45A12.0334,12.0334,0,0,0,99.835,36.0577Zm-2,55.4256a4,4,0,0,1-2,3.4641l-39,22.5167a4.0006,4.0006,0,0,1-4,0l-39-22.5167a4,4,0,0,1-2-3.4641V46.45a4,4,0,0,1,2-3.4642l39-22.5166a4,4,0,0,1,4,0l39,22.5166a4,4,0,0,1,2,3.4642Z"/>
|
|
||||||
<path d="M77.8567,82.0046h-2.866a4,4,0,0,0-1.9247.4934L55.7852,91.9833,35.835,80.4648V57.4872l19.95-11.5185,17.2893,9.4549a3.9993,3.9993,0,0,0,1.9192.4906h2.8632a2,2,0,0,0,2-2V51.2024a2,2,0,0,0-1.04-1.7547L59.628,38.9521a8.0391,8.0391,0,0,0-7.8428.09L31.8346,50.56a8.0246,8.0246,0,0,0-4,6.9287v22.976a8,8,0,0,0,4,6.9283l19.95,11.5186a8.0429,8.0429,0,0,0,7.8433.0879l19.19-10.5312a2,2,0,0,0,1.0378-1.7533v-2.71A2,2,0,0,0,77.8567,82.0046Z"/>
|
|
||||||
</g>
|
|
||||||
<g>
|
|
||||||
<path d="M172.58,45.3618a15.0166,15.0166,0,0,0-15,14.9995V77.6387a15,15,0,0,0,30,0V60.3613A15.0166,15.0166,0,0,0,172.58,45.3618Zm7,32.2769a7,7,0,0,1-14,0V60.3613a7,7,0,0,1,14,0Z"/>
|
|
||||||
<path d="M135.9138,53.4211a7.01,7.01,0,0,1,7.8681,6.0752.9894.9894,0,0,0,.9843.865h6.03a1.0108,1.0108,0,0,0,.9987-1.0971,15.0182,15.0182,0,0,0-15.7162-13.8837,15.2881,15.2881,0,0,0-14.2441,15.4163V77.2037A15.288,15.288,0,0,0,136.0792,92.62a15.0183,15.0183,0,0,0,15.7162-13.8842,1.0107,1.0107,0,0,0-.9987-1.0971h-6.03a.9894.9894,0,0,0-.9843.865,7.01,7.01,0,0,1-7.8679,6.0757,7.1642,7.1642,0,0,1-6.0789-7.1849V60.6057A7.1638,7.1638,0,0,1,135.9138,53.4211Z"/>
|
|
||||||
<path d="M218.7572,72.9277a12.1585,12.1585,0,0,0,7.1843-11.0771V58.1494A12.1494,12.1494,0,0,0,213.7921,46H196.835a1,1,0,0,0-1,1V91a1,1,0,0,0,1,1h6a1,1,0,0,0,1-1V74h6.6216l7.9154,17.4138a1,1,0,0,0,.91.5862h6.5911a1,1,0,0,0,.91-1.4138Zm-.8157-11.0771A4.1538,4.1538,0,0,1,213.7926,66h-9.8511V54h9.8511a4.1538,4.1538,0,0,1,4.1489,4.1494Z"/>
|
|
||||||
<path d="M260.835,46h-26a1,1,0,0,0-1,1V91a1,1,0,0,0,1,1h26a1,1,0,0,0,1-1V85a1,1,0,0,0-1-1h-19V72h13a1,1,0,0,0,1-1V65a1,1,0,0,0-1-1h-13V54h19a1,1,0,0,0,1-1V47A1,1,0,0,0,260.835,46Z"/>
|
|
||||||
<path d="M298.835,46h-6a1,1,0,0,0-1,1V69.6475a7.0066,7.0066,0,1,1-14,0V47a1,1,0,0,0-1-1h-6a1,1,0,0,0-1,1V69.6475a15.0031,15.0031,0,1,0,30,0V47A1,1,0,0,0,298.835,46Z"/>
|
|
||||||
<rect x="307.835" y="46" width="8" height="38" rx="1"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB |
@@ -1,12 +0,0 @@
|
|||||||
export const sygnet = [
|
|
||||||
'160 160',
|
|
||||||
`
|
|
||||||
<title>coreui logo</title>
|
|
||||||
<g>
|
|
||||||
<g style="fill:#fff;">
|
|
||||||
<path d="M125,47.091,86,24.5743a12,12,0,0,0-12,0L35,47.091a12.0336,12.0336,0,0,0-6,10.3923v45.0334a12.0335,12.0335,0,0,0,6,10.3923l39,22.5166a11.9993,11.9993,0,0,0,12,0l39-22.5166a12.0335,12.0335,0,0,0,6-10.3923V57.4833A12.0336,12.0336,0,0,0,125,47.091Zm-2,55.4257a4,4,0,0,1-2,3.464L82,128.4974a4,4,0,0,1-4,0L39,105.9807a4,4,0,0,1-2-3.464V57.4833a4,4,0,0,1,2-3.4641L78,31.5025a4,4,0,0,1,4,0l39,22.5167a4,4,0,0,1,2,3.4641Z"/>
|
|
||||||
<path d="M103.0216,93.0379h-2.866a4,4,0,0,0-1.9246.4935L80.95,103.0167,61,91.4981V68.5206L80.95,57.002l17.2894,9.455a4,4,0,0,0,1.9192.4905h2.8632a2,2,0,0,0,2-2V62.2357a2,2,0,0,0-1.04-1.7547L84.793,49.9854a8.0391,8.0391,0,0,0-7.8428.09L57,61.5929A8.0243,8.0243,0,0,0,53,68.5216v22.976a8,8,0,0,0,4,6.9283l19.95,11.5185a8.0422,8.0422,0,0,0,7.8433.0879l19.19-10.5311a2,2,0,0,0,1.0378-1.7534v-2.71A2,2,0,0,0,103.0216,93.0379Z"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
`,
|
|
||||||
];
|
|
||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
CSwitch,
|
CSwitch,
|
||||||
CCol,
|
CCol,
|
||||||
CRow,
|
CRow,
|
||||||
CForm,
|
|
||||||
CFormGroup,
|
CFormGroup,
|
||||||
CInputRadio,
|
CInputRadio,
|
||||||
CLabel,
|
CLabel,
|
||||||
@@ -17,10 +16,10 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { dateToUnix } from 'utils/helper';
|
import { dateToUnix } from 'utils/helper';
|
||||||
import 'react-widgets/styles.css';
|
import 'react-widgets/styles.css';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import SuccessfulActionModalBody from 'components/SuccessfulActionModalBody';
|
import SuccessfulActionModalBody from 'components/SuccessfulActionModalBody';
|
||||||
@@ -30,16 +29,17 @@ import styles from './index.module.scss';
|
|||||||
|
|
||||||
const BlinkModal = ({ show, toggleModal }) => {
|
const BlinkModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [isNow, setIsNow] = useState(false);
|
const [isNow, setIsNow] = useState(false);
|
||||||
const [waiting, setWaiting] = useState(false);
|
const [waiting, setWaiting] = useState(false);
|
||||||
const [chosenDate, setChosenDate] = useState(new Date().toString());
|
const [chosenDate, setChosenDate] = useState(new Date().toString());
|
||||||
const [chosenPattern, setPattern] = useState('on');
|
const [chosenPattern, setPattern] = useState('on');
|
||||||
const [result, setResult] = useState(null);
|
const [result, setResult] = useState(null);
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
const toggleNow = () => {
|
const toggleNow = () => {
|
||||||
setIsNow(!isNow);
|
setIsNow(!isNow);
|
||||||
}
|
};
|
||||||
|
|
||||||
const setDate = (date) => {
|
const setDate = (date) => {
|
||||||
if (date) {
|
if (date) {
|
||||||
@@ -58,12 +58,10 @@ const BlinkModal = ({ show, toggleModal }) => {
|
|||||||
|
|
||||||
const doAction = () => {
|
const doAction = () => {
|
||||||
setWaiting(true);
|
setWaiting(true);
|
||||||
|
|
||||||
const token = getToken();
|
|
||||||
const utcDate = new Date(chosenDate);
|
const utcDate = new Date(chosenDate);
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
when: isNow ? 0 : dateToUnix(utcDate),
|
when: isNow ? 0 : dateToUnix(utcDate),
|
||||||
pattern: chosenPattern,
|
pattern: chosenPattern,
|
||||||
duration: 30,
|
duration: 30,
|
||||||
@@ -71,11 +69,15 @@ const BlinkModal = ({ show, toggleModal }) => {
|
|||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/leds`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/leds`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setResult('success');
|
setResult('success');
|
||||||
})
|
})
|
||||||
@@ -98,50 +100,52 @@ const BlinkModal = ({ show, toggleModal }) => {
|
|||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<CModalBody>
|
<CModalBody>
|
||||||
<h6>{t('blink.when_blink_leds')}</h6>
|
<CFormGroup row>
|
||||||
<CRow className={styles.spacedRow}>
|
<CCol md="3">
|
||||||
<CCol md="7">{t('blink.pattern')}</CCol>
|
<CLabel>{t('blink.pattern')}</CLabel>
|
||||||
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CForm disabled={waiting}>
|
<CFormGroup variant="custom-radio" onClick={() => setPattern('on')} inline>
|
||||||
<CFormGroup variant="checkbox" onClick={() => setPattern('on')}>
|
|
||||||
<CInputRadio
|
<CInputRadio
|
||||||
|
custom
|
||||||
defaultChecked={chosenPattern === 'on'}
|
defaultChecked={chosenPattern === 'on'}
|
||||||
id="radio1"
|
id="radio1"
|
||||||
name="radios"
|
name="radios"
|
||||||
value="option1"
|
value="option1"
|
||||||
/>
|
/>
|
||||||
<CLabel variant="checkbox" htmlFor="radio1">
|
<CLabel variant="custom-checkbox" htmlFor="radio1">
|
||||||
{t('common.on')}
|
{t('common.on')}
|
||||||
</CLabel>
|
</CLabel>
|
||||||
</CFormGroup>
|
</CFormGroup>
|
||||||
<CFormGroup variant="checkbox" onClick={() => setPattern('off')}>
|
<CFormGroup variant="custom-radio" onClick={() => setPattern('off')} inline>
|
||||||
<CInputRadio
|
<CInputRadio
|
||||||
|
custom
|
||||||
defaultChecked={chosenPattern === 'off'}
|
defaultChecked={chosenPattern === 'off'}
|
||||||
id="radio2"
|
id="radio2"
|
||||||
name="radios"
|
name="radios"
|
||||||
value="option2"
|
value="option2"
|
||||||
/>
|
/>
|
||||||
<CLabel variant="checkbox" htmlFor="radio2">
|
<CLabel variant="custom-checkbox" htmlFor="radio2">
|
||||||
{t('common.off')}
|
{t('common.off')}
|
||||||
</CLabel>
|
</CLabel>
|
||||||
</CFormGroup>
|
</CFormGroup>
|
||||||
<CFormGroup variant="checkbox" onClick={() => setPattern('blink')}>
|
<CFormGroup variant="custom-radio" onClick={() => setPattern('blink')} inline>
|
||||||
<CInputRadio
|
<CInputRadio
|
||||||
|
custom
|
||||||
defaultChecked={chosenPattern === 'blink'}
|
defaultChecked={chosenPattern === 'blink'}
|
||||||
id="radio3"
|
id="radio3"
|
||||||
name="radios"
|
name="radios"
|
||||||
value="option3"
|
value="option3"
|
||||||
/>
|
/>
|
||||||
<CLabel variant="checkbox" htmlFor="radio3">
|
<CLabel variant="custom-checkbox" htmlFor="radio3">
|
||||||
{t('blink.blink')}
|
{t('blink.blink')}
|
||||||
</CLabel>
|
</CLabel>
|
||||||
</CFormGroup>
|
</CFormGroup>
|
||||||
</CForm>
|
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CFormGroup>
|
||||||
<CRow className={styles.spacedRow}>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="8">
|
<CCol md="8">
|
||||||
<p className={styles.spacedText}>{t('common.execute_now')}</p>
|
<p className={styles.spacedText}>{t('blink.execute_now')}</p>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CSwitch
|
<CSwitch
|
||||||
@@ -156,7 +160,7 @@ const BlinkModal = ({ show, toggleModal }) => {
|
|||||||
</CRow>
|
</CRow>
|
||||||
<CRow hidden={isNow} className={styles.spacedRow}>
|
<CRow hidden={isNow} className={styles.spacedRow}>
|
||||||
<CCol md="4" className={styles.spacedDate}>
|
<CCol md="4" className={styles.spacedDate}>
|
||||||
<p>{t('common.date')}</p>
|
<p>{t('common.custom_date')}</p>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="8">
|
<CCol xs="12" md="8">
|
||||||
<DatePicker
|
<DatePicker
|
||||||
@@ -173,7 +177,7 @@ const BlinkModal = ({ show, toggleModal }) => {
|
|||||||
</CModalBody>
|
</CModalBody>
|
||||||
<CModalFooter>
|
<CModalFooter>
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
label={isNow ? t('blink.blink') : t('common.schedule')}
|
label={isNow ? t('blink.set_leds') : t('common.schedule')}
|
||||||
isLoadingLabel={t('common.loading_ellipsis')}
|
isLoadingLabel={t('common.loading_ellipsis')}
|
||||||
isLoading={waiting}
|
isLoading={waiting}
|
||||||
action={doAction}
|
action={doAction}
|
||||||
|
|||||||
@@ -13,13 +13,11 @@ import {
|
|||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import { cilCloudDownload, cilSync } from '@coreui/icons';
|
import { cilCloudDownload, cilSync, cilCalendarCheck } from '@coreui/icons';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
||||||
import { faClipboardCheck } from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import { prettyDate, dateToUnix } from 'utils/helper';
|
import { prettyDate, dateToUnix } from 'utils/helper';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import ConfirmModal from 'components/ConfirmModal';
|
import ConfirmModal from 'components/ConfirmModal';
|
||||||
import LoadingButton from 'components/LoadingButton';
|
import LoadingButton from 'components/LoadingButton';
|
||||||
@@ -27,8 +25,10 @@ import WifiScanResultModalWidget from 'components/WifiScanResultModal';
|
|||||||
import DeviceCommandsCollapse from './DeviceCommandsCollapse';
|
import DeviceCommandsCollapse from './DeviceCommandsCollapse';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeviceCommands = ({ selectedDeviceId }) => {
|
const DeviceCommands = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
// Wifiscan result related
|
// Wifiscan result related
|
||||||
const [chosenWifiScan, setChosenWifiScan] = useState(null);
|
const [chosenWifiScan, setChosenWifiScan] = useState(null);
|
||||||
const [showScanModal, setShowScanModal] = useState(false);
|
const [showScanModal, setShowScanModal] = useState(false);
|
||||||
@@ -92,7 +92,7 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
limit: commandLimit,
|
limit: commandLimit,
|
||||||
@@ -109,7 +109,12 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/commands?serialNumber=${encodeURIComponent(selectedDeviceId)}${extraParams}`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/commands?serialNumber=${encodeURIComponent(
|
||||||
|
deviceSerialNumber,
|
||||||
|
)}${extraParams}`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setCommands(response.data.commands);
|
setCommands(response.data.commands);
|
||||||
})
|
})
|
||||||
@@ -124,13 +129,16 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/octet-stream',
|
Accept: 'application/octet-stream',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/file/${uuid}?serialNumber=${selectedDeviceId}`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/file/${uuid}?serialNumber=${deviceSerialNumber}`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const blob = new Blob([response.data], { type: 'application/octet-stream' });
|
const blob = new Blob([response.data], { type: 'application/octet-stream' });
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
@@ -147,11 +155,11 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return axiosInstance
|
return axiosInstance
|
||||||
.delete(`/command/${uuidDelete}`, options)
|
.delete(`${endpoints.ucentralgw}/api/v1/command/${uuidDelete}`, options)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
deleteCommandFromList(uuidDelete);
|
deleteCommandFromList(uuidDelete);
|
||||||
setUuidDelete('');
|
setUuidDelete('');
|
||||||
@@ -233,12 +241,12 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId && start !== '' && end !== '') {
|
if (deviceSerialNumber && start !== '' && end !== '') {
|
||||||
getCommands();
|
getCommands();
|
||||||
} else if (selectedDeviceId && start === '' && end === '') {
|
} else if (deviceSerialNumber && start === '' && end === '') {
|
||||||
getCommands();
|
getCommands();
|
||||||
}
|
}
|
||||||
}, [selectedDeviceId, start, end]);
|
}, [deviceSerialNumber, start, end]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventBus.on('actionCompleted', () => refreshCommands());
|
eventBus.on('actionCompleted', () => refreshCommands());
|
||||||
@@ -249,7 +257,7 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId) {
|
if (deviceSerialNumber) {
|
||||||
setCommandLimit(25);
|
setCommandLimit(25);
|
||||||
setLoadingMore(false);
|
setLoadingMore(false);
|
||||||
setShowLoadingMore(true);
|
setShowLoadingMore(true);
|
||||||
@@ -257,7 +265,7 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
setEnd('');
|
setEnd('');
|
||||||
getCommands();
|
getCommands();
|
||||||
}
|
}
|
||||||
}, [selectedDeviceId]);
|
}, [deviceSerialNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (commandLimit !== 25) {
|
if (commandLimit !== 25) {
|
||||||
@@ -313,9 +321,7 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
items={commands ?? []}
|
items={commands ?? []}
|
||||||
fields={columns}
|
fields={columns}
|
||||||
className={styles.whiteIcon}
|
className={styles.whiteIcon}
|
||||||
columnFilter
|
sorterValue={{ column: 'created', desc: 'true' }}
|
||||||
sorter
|
|
||||||
sorterValue={{ column: 'submitted', desc: 'true' }}
|
|
||||||
scopedSlots={{
|
scopedSlots={{
|
||||||
completed: (item) => (
|
completed: (item) => (
|
||||||
<td>
|
<td>
|
||||||
@@ -363,12 +369,7 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
{item.command === 'trace' ? (
|
{item.command === 'trace' ? (
|
||||||
<CIcon content={cilCloudDownload} size="lg" />
|
<CIcon content={cilCloudDownload} size="lg" />
|
||||||
) : (
|
) : (
|
||||||
<FontAwesomeIcon
|
<CIcon content={cilCalendarCheck} size="lg" />
|
||||||
icon={faClipboardCheck}
|
|
||||||
className={[styles.customIconHeight, 'c-icon c-icon-lg'].join(
|
|
||||||
' ',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</CButton>
|
</CButton>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
@@ -453,8 +454,4 @@ const DeviceCommands = ({ selectedDeviceId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceCommands.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeviceCommands;
|
export default DeviceCommands;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.scrollableBox {
|
.scrollableBox {
|
||||||
height: 400px;
|
height: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.whiteIcon {
|
.whiteIcon {
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ import {
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import 'react-widgets/styles.css';
|
import 'react-widgets/styles.css';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import { checkIfJson } from 'utils/helper';
|
import { checkIfJson } from 'utils/helper';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
@@ -27,6 +27,8 @@ import styles from './index.module.scss';
|
|||||||
|
|
||||||
const ConfigureModal = ({ show, toggleModal }) => {
|
const ConfigureModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [hadSuccess, setHadSuccess] = useState(false);
|
const [hadSuccess, setHadSuccess] = useState(false);
|
||||||
const [hadFailure, setHadFailure] = useState(false);
|
const [hadFailure, setHadFailure] = useState(false);
|
||||||
const [doingNow, setDoingNow] = useState(false);
|
const [doingNow, setDoingNow] = useState(false);
|
||||||
@@ -36,7 +38,7 @@ const ConfigureModal = ({ show, toggleModal }) => {
|
|||||||
const [checkingIfSure, setCheckingIfSure] = useState(false);
|
const [checkingIfSure, setCheckingIfSure] = useState(false);
|
||||||
const [errorJson, setErrorJson] = useState(false);
|
const [errorJson, setErrorJson] = useState(false);
|
||||||
const [inputKey, setInputKey] = useState(0);
|
const [inputKey, setInputKey] = useState(0);
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
let fileReader;
|
let fileReader;
|
||||||
|
|
||||||
const confirmingIfSure = () => {
|
const confirmingIfSure = () => {
|
||||||
@@ -69,10 +71,8 @@ const ConfigureModal = ({ show, toggleModal }) => {
|
|||||||
setHadSuccess(false);
|
setHadSuccess(false);
|
||||||
setWaiting(true);
|
setWaiting(true);
|
||||||
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
when: 0,
|
when: 0,
|
||||||
UUID: 1,
|
UUID: 1,
|
||||||
configuration: JSON.parse(newConfig),
|
configuration: JSON.parse(newConfig),
|
||||||
@@ -80,11 +80,15 @@ const ConfigureModal = ({ show, toggleModal }) => {
|
|||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/configure`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/configure`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setHadSuccess(true);
|
setHadSuccess(true);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -5,28 +5,29 @@ import { cilClone } from '@coreui/icons';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { CButton, CPopover } from '@coreui/react';
|
import { CButton, CPopover } from '@coreui/react';
|
||||||
|
|
||||||
const CopyToClipboardButton = ({content, size}) => {
|
const CopyToClipboardButton = ({ content, size }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [result, setResult] = useState('');
|
const [result, setResult] = useState('');
|
||||||
|
|
||||||
const copyToClipboard = () => {
|
const copyToClipboard = () => {
|
||||||
navigator.clipboard.writeText(content);
|
navigator.clipboard.writeText(content);
|
||||||
setResult(t('common.copied'));
|
setResult(t('common.copied'));
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CPopover content={t('common.copy_to_clipboard')}>
|
<CPopover content={t('common.copy_to_clipboard')}>
|
||||||
<CButton onClick={copyToClipboard} size={size}>
|
<CButton onClick={copyToClipboard} size={size}>
|
||||||
<CIcon content={cilClone} />
|
<CIcon content={cilClone} />
|
||||||
{' '}{result || ''}
|
{' '}
|
||||||
|
{result || ''}
|
||||||
</CButton>
|
</CButton>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
CopyToClipboardButton.propTypes = {
|
CopyToClipboardButton.propTypes = {
|
||||||
content: PropTypes.string.isRequired,
|
content: PropTypes.string.isRequired,
|
||||||
size: PropTypes.string
|
size: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
CopyToClipboardButton.defaultProps = {
|
CopyToClipboardButton.defaultProps = {
|
||||||
|
|||||||
@@ -6,12 +6,15 @@ import PropTypes from 'prop-types';
|
|||||||
import ConfirmFooter from 'components/ConfirmFooter';
|
import ConfirmFooter from 'components/ConfirmFooter';
|
||||||
import { dateToUnix } from 'utils/helper';
|
import { dateToUnix } from 'utils/helper';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeleteLogModal = ({ serialNumber, show, toggle, object }) => {
|
const DeleteLogModal = ({ show, toggle, object }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [maxDate, setMaxDate] = useState(new Date().toString());
|
const [maxDate, setMaxDate] = useState(new Date().toString());
|
||||||
|
|
||||||
@@ -27,14 +30,14 @@ const DeleteLogModal = ({ serialNumber, show, toggle, object }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
endDate: dateToUnix(maxDate),
|
endDate: dateToUnix(maxDate),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return axiosInstance
|
return axiosInstance
|
||||||
.delete(`/device/${serialNumber}/${object}`, options)
|
.delete(`${endpoints.ucentralgw}/api/v1/device/${deviceSerialNumber}/${object}`, options)
|
||||||
.then(() => {})
|
.then(() => {})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
@@ -94,7 +97,6 @@ DeleteLogModal.propTypes = {
|
|||||||
show: PropTypes.bool.isRequired,
|
show: PropTypes.bool.isRequired,
|
||||||
toggle: PropTypes.func.isRequired,
|
toggle: PropTypes.func.isRequired,
|
||||||
object: PropTypes.string.isRequired,
|
object: PropTypes.string.isRequired,
|
||||||
serialNumber: PropTypes.string.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DeleteLogModal;
|
export default DeleteLogModal;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { CButton, CCard, CCardHeader, CCardBody, CRow, CCol } from '@coreui/react';
|
import { CButton, CCard, CCardHeader, CCardBody, CRow, CCol } from '@coreui/react';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import LoadingButton from 'components/LoadingButton';
|
import LoadingButton from 'components/LoadingButton';
|
||||||
import RebootModal from 'components/RebootModal';
|
import RebootModal from 'components/RebootModal';
|
||||||
import FirmwareUpgradeModal from 'components/FirmwareUpgradeModal';
|
import FirmwareUpgradeModal from 'components/FirmwareUpgradeModal';
|
||||||
@@ -15,8 +15,10 @@ import FactoryResetModal from 'components/FactoryResetModal';
|
|||||||
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeviceActions = ({ selectedDeviceId }) => {
|
const DeviceActions = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [showRebootModal, setShowRebootModal] = useState(false);
|
const [showRebootModal, setShowRebootModal] = useState(false);
|
||||||
const [showBlinkModal, setShowBlinkModal] = useState(false);
|
const [showBlinkModal, setShowBlinkModal] = useState(false);
|
||||||
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
const [showUpgradeModal, setShowUpgradeModal] = useState(false);
|
||||||
@@ -59,12 +61,15 @@ const DeviceActions = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(selectedDeviceId)}/rtty`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/rtty`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const url = `https://${response.data.server}:${response.data.viewport}/connect/${response.data.connectionId}`;
|
const url = `https://${response.data.server}:${response.data.viewport}/connect/${response.data.connectionId}`;
|
||||||
const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
|
const newWindow = window.open(url, '_blank', 'noopener,noreferrer');
|
||||||
@@ -78,7 +83,9 @@ const DeviceActions = ({ selectedDeviceId }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CCard>
|
<CCard>
|
||||||
<CCardHeader><div className="text-value-lg">{t('actions.title')}</div></CCardHeader>
|
<CCardHeader>
|
||||||
|
<div className="text-value-lg">{t('actions.title')}</div>
|
||||||
|
</CCardHeader>
|
||||||
<CCardBody>
|
<CCardBody>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol>
|
<CCol>
|
||||||
@@ -143,8 +150,4 @@ const DeviceActions = ({ selectedDeviceId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceActions.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeviceActions;
|
export default DeviceActions;
|
||||||
|
|||||||
@@ -4,11 +4,8 @@ import {
|
|||||||
CCard,
|
CCard,
|
||||||
CCardHeader,
|
CCardHeader,
|
||||||
CCardBody,
|
CCardBody,
|
||||||
CFormGroup,
|
|
||||||
CCol,
|
CCol,
|
||||||
CLabel,
|
CLabel,
|
||||||
CForm,
|
|
||||||
CInput,
|
|
||||||
CCollapse,
|
CCollapse,
|
||||||
CCardFooter,
|
CCardFooter,
|
||||||
CButton,
|
CButton,
|
||||||
@@ -16,17 +13,20 @@ import {
|
|||||||
CPopover,
|
CPopover,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { cilWindowMaximize } from '@coreui/icons';
|
import { cilWindowMaximize } from '@coreui/icons';
|
||||||
import { prettyDate } from 'utils/helper';
|
import { prettyDate } from 'utils/helper';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import CopyToClipboardButton from 'components/CopyToClipboardButton';
|
import CopyToClipboardButton from 'components/CopyToClipboardButton';
|
||||||
|
import DeviceNotes from 'components/DeviceNotes';
|
||||||
import DeviceConfigurationModal from './DeviceConfigurationModal';
|
import DeviceConfigurationModal from './DeviceConfigurationModal';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeviceConfiguration = ({ selectedDeviceId }) => {
|
const DeviceConfiguration = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [collapse, setCollapse] = useState(false);
|
const [collapse, setCollapse] = useState(false);
|
||||||
const [showModal, setShowModal] = useState(false);
|
const [showModal, setShowModal] = useState(false);
|
||||||
const [device, setDevice] = useState(null);
|
const [device, setDevice] = useState(null);
|
||||||
@@ -44,12 +44,15 @@ const DeviceConfiguration = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(selectedDeviceId)}`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setDevice(response.data);
|
setDevice(response.data);
|
||||||
})
|
})
|
||||||
@@ -57,8 +60,8 @@ const DeviceConfiguration = ({ selectedDeviceId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId) getDevice();
|
if (deviceSerialNumber) getDevice();
|
||||||
}, [selectedDeviceId]);
|
}, [deviceSerialNumber]);
|
||||||
|
|
||||||
if (device) {
|
if (device) {
|
||||||
return (
|
return (
|
||||||
@@ -66,7 +69,9 @@ const DeviceConfiguration = ({ selectedDeviceId }) => {
|
|||||||
<CCard>
|
<CCard>
|
||||||
<CCardHeader>
|
<CCardHeader>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol><div className="text-value-lg">{t('configuration.title')}</div></CCol>
|
<CCol>
|
||||||
|
<div className="text-value-lg">{t('configuration.title')}</div>
|
||||||
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
<div className={styles.alignRight}>
|
<div className={styles.alignRight}>
|
||||||
<CPopover content={t('configuration.view_json')}>
|
<CPopover content={t('configuration.view_json')}>
|
||||||
@@ -79,111 +84,105 @@ const DeviceConfiguration = ({ selectedDeviceId }) => {
|
|||||||
</CRow>
|
</CRow>
|
||||||
</CCardHeader>
|
</CCardHeader>
|
||||||
<CCardBody>
|
<CCardBody>
|
||||||
<CForm
|
<CRow className={styles.spacedRow}>
|
||||||
action=""
|
|
||||||
method="post"
|
|
||||||
encType="multipart/form-data"
|
|
||||||
className="form-horizontal"
|
|
||||||
>
|
|
||||||
<CFormGroup row>
|
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('common.uuid')} : </CLabel>
|
<CLabel>{t('common.uuid')} : </CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.UUID}
|
{device.UUID}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('common.serial_number')} : </CLabel>
|
<CLabel>{t('common.serial_number')} : </CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.serialNumber}
|
{device.serialNumber}
|
||||||
<CopyToClipboardButton size="sm" content={device.serialNumber}/>
|
<CopyToClipboardButton size="sm" content={device.serialNumber} />
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('configuration.type')} : </CLabel>
|
<CLabel>{t('configuration.type')} : </CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.deviceType}
|
{device.deviceType}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('configuration.last_configuration_change')} : </CLabel>
|
<CLabel>{t('configuration.last_configuration_change')} : </CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{prettyDate(device.lastConfigurationChange)}
|
{prettyDate(device.lastConfigurationChange)}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('common.mac')} :</CLabel>
|
<CLabel>{t('common.mac')} :</CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.macAddress}
|
{device.macAddress}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('configuration.created')} : </CLabel>
|
<CLabel>{t('configuration.created')} : </CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{prettyDate(device.createdTimestamp)}
|
{prettyDate(device.createdTimestamp)}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="3" className={styles.topPadding}>
|
||||||
|
<CLabel>{t('configuration.device_password')} : </CLabel>
|
||||||
|
</CCol>
|
||||||
|
<CCol xs="12" md="9">
|
||||||
|
{device.devicePassword === '' ? 'openwifi' : device.devicePassword}
|
||||||
|
<CopyToClipboardButton
|
||||||
|
size="sm"
|
||||||
|
content={device?.devicePassword === '' ? 'openwifi' : device.devicePassword}
|
||||||
|
/>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<DeviceNotes
|
||||||
|
notes={device.notes}
|
||||||
|
refreshNotes={getDevice}
|
||||||
|
serialNumber={deviceSerialNumber}
|
||||||
|
/>
|
||||||
|
<CCollapse show={collapse}>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('configuration.last_configuration_download')} : </CLabel>
|
<CLabel>{t('configuration.last_configuration_download')} : </CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{prettyDate(device.lastConfigurationDownload)}
|
{prettyDate(device.lastConfigurationDownload)}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3" className={styles.topPadding}>
|
|
||||||
<CLabel>{t('configuration.device_password')} : </CLabel>
|
|
||||||
</CCol>
|
|
||||||
<CCol xs="12" md="9">
|
|
||||||
{device.devicePassword === '' ? 'openwifi' : device.devicePassword}
|
|
||||||
<CopyToClipboardButton size="sm" content={device?.devicePassword === '' ? 'openwifi' : device.devicePassword}/>
|
|
||||||
</CCol>
|
|
||||||
</CFormGroup>
|
|
||||||
<CCollapse show={collapse}>
|
|
||||||
<CFormGroup row>
|
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('common.manufacturer')} :</CLabel>
|
<CLabel>{t('common.manufacturer')} :</CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.manufacturer}
|
{device.manufacturer}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
|
||||||
<CLabel htmlFor="text-input">{t('configuration.notes')} :</CLabel>
|
|
||||||
</CCol>
|
|
||||||
<CCol xs="12" md="9">
|
|
||||||
<CInput id="text-input" name="text-input" placeholder={device.notes} />
|
|
||||||
</CCol>
|
|
||||||
</CFormGroup>
|
|
||||||
<CFormGroup row>
|
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('configuration.owner')} :</CLabel>
|
<CLabel>{t('configuration.owner')} :</CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.owner}
|
{device.owner}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
<CFormGroup row>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol md="3">
|
<CCol md="3">
|
||||||
<CLabel>{t('configuration.location')} :</CLabel>
|
<CLabel>{t('configuration.location')} :</CLabel>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="9">
|
<CCol xs="12" md="9">
|
||||||
{device.location}
|
{device.location}
|
||||||
</CCol>
|
</CCol>
|
||||||
</CFormGroup>
|
</CRow>
|
||||||
</CCollapse>
|
</CCollapse>
|
||||||
<CCardFooter>
|
<CCardFooter>
|
||||||
<CButton show={collapse ? 'true' : 'false'} onClick={toggle} block>
|
<CButton show={collapse ? 'true' : 'false'} onClick={toggle} block>
|
||||||
@@ -194,7 +193,6 @@ const DeviceConfiguration = ({ selectedDeviceId }) => {
|
|||||||
/>
|
/>
|
||||||
</CButton>
|
</CButton>
|
||||||
</CCardFooter>
|
</CCardFooter>
|
||||||
</CForm>
|
|
||||||
</CCardBody>
|
</CCardBody>
|
||||||
</CCard>
|
</CCard>
|
||||||
<DeviceConfigurationModal show={showModal} toggle={toggleModal} configuration={device} />
|
<DeviceConfigurationModal show={showModal} toggle={toggleModal} configuration={device} />
|
||||||
@@ -210,8 +208,4 @@ const DeviceConfiguration = ({ selectedDeviceId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceConfiguration.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeviceConfiguration;
|
export default DeviceConfiguration;
|
||||||
|
|||||||
@@ -13,3 +13,8 @@
|
|||||||
.topPadding {
|
.topPadding {
|
||||||
padding-top: 5px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spacedRow {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,17 +15,19 @@ import {
|
|||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { prettyDate, dateToUnix } from 'utils/helper';
|
import { prettyDate, dateToUnix } from 'utils/helper';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import LoadingButton from 'components/LoadingButton';
|
import LoadingButton from 'components/LoadingButton';
|
||||||
import DeleteLogModal from 'components/DeleteLogModal';
|
import DeleteLogModal from 'components/DeleteLogModal';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeviceHealth = ({ selectedDeviceId }) => {
|
const DeviceHealth = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [collapse, setCollapse] = useState(false);
|
const [collapse, setCollapse] = useState(false);
|
||||||
const [details, setDetails] = useState([]);
|
const [details, setDetails] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -68,7 +70,7 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
limit: logLimit,
|
limit: logLimit,
|
||||||
@@ -85,7 +87,12 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(selectedDeviceId)}/healthchecks${extraParams}`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(
|
||||||
|
deviceSerialNumber,
|
||||||
|
)}/healthchecks${extraParams}`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setHealthChecks(response.data.values);
|
setHealthChecks(response.data.values);
|
||||||
})
|
})
|
||||||
@@ -128,7 +135,7 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId) {
|
if (deviceSerialNumber) {
|
||||||
setLogLimit(25);
|
setLogLimit(25);
|
||||||
setLoadingMore(false);
|
setLoadingMore(false);
|
||||||
setShowLoadingMore(true);
|
setShowLoadingMore(true);
|
||||||
@@ -136,7 +143,7 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
setEnd('');
|
setEnd('');
|
||||||
getDeviceHealth();
|
getDeviceHealth();
|
||||||
}
|
}
|
||||||
}, [selectedDeviceId]);
|
}, [deviceSerialNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (logLimit !== 25) {
|
if (logLimit !== 25) {
|
||||||
@@ -168,12 +175,12 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
}, [healthChecks]);
|
}, [healthChecks]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId && start !== '' && end !== '') {
|
if (deviceSerialNumber && start !== '' && end !== '') {
|
||||||
getDeviceHealth();
|
getDeviceHealth();
|
||||||
} else if (selectedDeviceId && start === '' && end === '') {
|
} else if (deviceSerialNumber && start === '' && end === '') {
|
||||||
getDeviceHealth();
|
getDeviceHealth();
|
||||||
}
|
}
|
||||||
}, [start, end, selectedDeviceId]);
|
}, [start, end, deviceSerialNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventBus.on('deletedHealth', () => getDeviceHealth());
|
eventBus.on('deletedHealth', () => getDeviceHealth());
|
||||||
@@ -185,8 +192,8 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<CWidgetDropdown
|
<CWidgetDropdown
|
||||||
header={sanityLevel ? `${sanityLevel}%` : t('common.unknown')}
|
header={t('health.title')}
|
||||||
text={t('health.title')}
|
text={sanityLevel ? `${sanityLevel}%` : t('common.unknown')}
|
||||||
value={sanityLevel ?? 100}
|
value={sanityLevel ?? 100}
|
||||||
color={barColor}
|
color={barColor}
|
||||||
inverse="true"
|
inverse="true"
|
||||||
@@ -210,11 +217,13 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
</div>
|
</div>
|
||||||
<CRow className={styles.spacedRow}>
|
<CRow className={styles.spacedRow}>
|
||||||
<CCol>
|
<CCol>
|
||||||
{t('common.from')}:
|
{t('common.from')}
|
||||||
|
:
|
||||||
<DatePicker includeTime onChange={(date) => modifyStart(date)} />
|
<DatePicker includeTime onChange={(date) => modifyStart(date)} />
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
{t('common.to')}:
|
{t('common.to')}
|
||||||
|
:
|
||||||
<DatePicker includeTime onChange={(date) => modifyEnd(date)} />
|
<DatePicker includeTime onChange={(date) => modifyEnd(date)} />
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
@@ -281,7 +290,7 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
/>
|
/>
|
||||||
</CButton>
|
</CButton>
|
||||||
<DeleteLogModal
|
<DeleteLogModal
|
||||||
serialNumber={selectedDeviceId}
|
serialNumber={deviceSerialNumber}
|
||||||
object="healthchecks"
|
object="healthchecks"
|
||||||
show={showDeleteModal}
|
show={showDeleteModal}
|
||||||
toggle={toggleDeleteModal}
|
toggle={toggleDeleteModal}
|
||||||
@@ -292,8 +301,4 @@ const DeviceHealth = ({ selectedDeviceId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceHealth.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeviceHealth;
|
export default DeviceHealth;
|
||||||
|
|||||||
@@ -10,14 +10,14 @@ import {
|
|||||||
CRow,
|
CRow,
|
||||||
CCol,
|
CCol,
|
||||||
CPopover,
|
CPopover,
|
||||||
|
CSelect,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import ReactPaginate from 'react-paginate';
|
import ReactPaginate from 'react-paginate';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import Select from 'react-select';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { cilSync, cilInfo, cilBadge, cilBan } from '@coreui/icons';
|
import { cilSync, cilInfo, cilBadge, cilBan } from '@coreui/icons';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { cleanBytesString } from 'utils/helper';
|
import { cleanBytesString } from 'utils/helper';
|
||||||
import meshIcon from 'assets/icons/Mesh.png';
|
import meshIcon from 'assets/icons/Mesh.png';
|
||||||
@@ -29,6 +29,7 @@ import styles from './index.module.scss';
|
|||||||
|
|
||||||
const DeviceList = () => {
|
const DeviceList = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
const [loadedSerials, setLoadedSerials] = useState(false);
|
const [loadedSerials, setLoadedSerials] = useState(false);
|
||||||
const [serialNumbers, setSerialNumbers] = useState([]);
|
const [serialNumbers, setSerialNumbers] = useState([]);
|
||||||
const [page, setPage] = useState(0);
|
const [page, setPage] = useState(0);
|
||||||
@@ -38,16 +39,15 @@ const DeviceList = () => {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
const getSerialNumbers = () => {
|
const getSerialNumbers = () => {
|
||||||
const token = getToken();
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get('/devices?serialOnly=true', {
|
.get(`${endpoints.ucentralgw}/api/v1/devices?serialOnly=true`, {
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -60,12 +60,11 @@ const DeviceList = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getDeviceInformation = () => {
|
const getDeviceInformation = () => {
|
||||||
const token = getToken();
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
const startIndex = page * devicesPerPage;
|
const startIndex = page * devicesPerPage;
|
||||||
@@ -76,7 +75,7 @@ const DeviceList = () => {
|
|||||||
.join(',');
|
.join(',');
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/devices?deviceWithStatus=true&select=${serialsToGet}`, {
|
.get(`${endpoints.ucentralgw}/api/v1/devices?deviceWithStatus=true&select=${serialsToGet}`, {
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
@@ -89,18 +88,22 @@ const DeviceList = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const refreshDevice = (serialNumber) => {
|
const refreshDevice = (serialNumber) => {
|
||||||
const token = getToken();
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/devices?deviceWithStatus=true&select=${encodeURIComponent(serialNumber)}`, {
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/devices?deviceWithStatus=true&select=${encodeURIComponent(
|
||||||
|
serialNumber,
|
||||||
|
)}`,
|
||||||
|
{
|
||||||
headers,
|
headers,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const device = response.data.devicesWithStatus[0];
|
const device = response.data.devicesWithStatus[0];
|
||||||
const foundIndex = devices.findIndex((obj) => obj.serialNumber === serialNumber);
|
const foundIndex = devices.findIndex((obj) => obj.serialNumber === serialNumber);
|
||||||
@@ -189,12 +192,6 @@ const DeviceListDisplay = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const selectOptions = [
|
|
||||||
{ value: '10', label: '10' },
|
|
||||||
{ value: '25', label: '25' },
|
|
||||||
{ value: '50', label: '50' },
|
|
||||||
];
|
|
||||||
|
|
||||||
const getDeviceIcon = (deviceType) => {
|
const getDeviceIcon = (deviceType) => {
|
||||||
if (deviceType === 'AP_Default' || deviceType === 'AP') {
|
if (deviceType === 'AP_Default' || deviceType === 'AP') {
|
||||||
return <img src={apIcon} className={styles.icon} alt="AP" />;
|
return <img src={apIcon} className={styles.icon} alt="AP" />;
|
||||||
@@ -281,13 +278,17 @@ const DeviceListDisplay = ({
|
|||||||
<CCardHeader>
|
<CCardHeader>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol />
|
<CCol />
|
||||||
<CCol xs={2}>
|
<CCol xs={1}>
|
||||||
<Select
|
<CSelect
|
||||||
isClearable={false}
|
custom
|
||||||
options={selectOptions}
|
defaultValue={devicesPerPage}
|
||||||
defaultValue={{ value: devicesPerPage, label: devicesPerPage }}
|
onChange={(e) => updateDevicesPerPage(e.target.value)}
|
||||||
onChange={(value) => updateDevicesPerPage(value.value)}
|
disabled={loading}
|
||||||
/>
|
>
|
||||||
|
<option value="10">10</option>
|
||||||
|
<option value="25">25</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
</CSelect>
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
</CCardHeader>
|
</CCardHeader>
|
||||||
@@ -296,6 +297,7 @@ const DeviceListDisplay = ({
|
|||||||
items={devices ?? []}
|
items={devices ?? []}
|
||||||
fields={columns}
|
fields={columns}
|
||||||
hover
|
hover
|
||||||
|
border
|
||||||
loading={loading}
|
loading={loading}
|
||||||
scopedSlots={{
|
scopedSlots={{
|
||||||
serialNumber: (item) => (
|
serialNumber: (item) => (
|
||||||
@@ -337,7 +339,9 @@ const DeviceListDisplay = ({
|
|||||||
content={item.firmware ? item.firmware : t('common.na')}
|
content={item.firmware ? item.firmware : t('common.na')}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<p style={{width: '225px'}} className="text-truncate">{item.firmware}</p>
|
<p style={{ width: '225px' }} className="text-truncate">
|
||||||
|
{item.firmware}
|
||||||
|
</p>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
</td>
|
</td>
|
||||||
),
|
),
|
||||||
@@ -347,7 +351,9 @@ const DeviceListDisplay = ({
|
|||||||
content={item.compatible ? item.compatible : t('common.na')}
|
content={item.compatible ? item.compatible : t('common.na')}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<p style={{width: '150px'}} className="text-truncate">{item.compatible}</p>
|
<p style={{ width: '150px' }} className="text-truncate">
|
||||||
|
{item.compatible}
|
||||||
|
</p>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
</td>
|
</td>
|
||||||
),
|
),
|
||||||
@@ -359,7 +365,9 @@ const DeviceListDisplay = ({
|
|||||||
content={item.ipAddress ? item.ipAddress : t('common.na')}
|
content={item.ipAddress ? item.ipAddress : t('common.na')}
|
||||||
placement="top"
|
placement="top"
|
||||||
>
|
>
|
||||||
<p style={{width: '150px'}} className="text-truncate">{item.ipAddress}</p>
|
<p style={{ width: '150px' }} className="text-truncate">
|
||||||
|
{item.ipAddress}
|
||||||
|
</p>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
</td>
|
</td>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -14,17 +14,19 @@ import {
|
|||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { prettyDate, dateToUnix } from 'utils/helper';
|
import { prettyDate, dateToUnix } from 'utils/helper';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import LoadingButton from 'components/LoadingButton';
|
import LoadingButton from 'components/LoadingButton';
|
||||||
import DeleteLogModal from 'components/DeleteLogModal';
|
import DeleteLogModal from 'components/DeleteLogModal';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeviceLogs = ({ selectedDeviceId }) => {
|
const DeviceLogs = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [collapse, setCollapse] = useState(false);
|
const [collapse, setCollapse] = useState(false);
|
||||||
const [details, setDetails] = useState([]);
|
const [details, setDetails] = useState([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -65,7 +67,7 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
limit: logLimit,
|
limit: logLimit,
|
||||||
@@ -82,7 +84,12 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(selectedDeviceId)}/logs${extraParams}`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(
|
||||||
|
deviceSerialNumber,
|
||||||
|
)}/logs${extraParams}`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setLogs(response.data.values);
|
setLogs(response.data.values);
|
||||||
})
|
})
|
||||||
@@ -125,7 +132,7 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId) {
|
if (deviceSerialNumber) {
|
||||||
setLogLimit(25);
|
setLogLimit(25);
|
||||||
setLoadingMore(false);
|
setLoadingMore(false);
|
||||||
setShowLoadingMore(true);
|
setShowLoadingMore(true);
|
||||||
@@ -133,7 +140,7 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
setEnd('');
|
setEnd('');
|
||||||
getLogs();
|
getLogs();
|
||||||
}
|
}
|
||||||
}, [selectedDeviceId]);
|
}, [deviceSerialNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (logLimit !== 25) {
|
if (logLimit !== 25) {
|
||||||
@@ -150,12 +157,12 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
}, [logs]);
|
}, [logs]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId && start !== '' && end !== '') {
|
if (deviceSerialNumber && start !== '' && end !== '') {
|
||||||
getLogs();
|
getLogs();
|
||||||
} else if (selectedDeviceId && start === '' && end === '') {
|
} else if (deviceSerialNumber && start === '' && end === '') {
|
||||||
getLogs();
|
getLogs();
|
||||||
}
|
}
|
||||||
}, [start, end, selectedDeviceId]);
|
}, [start, end, deviceSerialNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventBus.on('deletedLogs', () => getLogs());
|
eventBus.on('deletedLogs', () => getLogs());
|
||||||
@@ -258,7 +265,7 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<DeleteLogModal
|
<DeleteLogModal
|
||||||
serialNumber={selectedDeviceId}
|
serialNumber={deviceSerialNumber}
|
||||||
object="logs"
|
object="logs"
|
||||||
show={showDeleteModal}
|
show={showDeleteModal}
|
||||||
toggle={toggleDeleteModal}
|
toggle={toggleDeleteModal}
|
||||||
@@ -267,8 +274,4 @@ const DeviceLogs = ({ selectedDeviceId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceLogs.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeviceLogs;
|
export default DeviceLogs;
|
||||||
|
|||||||
111
src/components/DeviceNotes/index.js
Normal file
111
src/components/DeviceNotes/index.js
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { CDataTable, CRow, CCol, CLabel, CInput } from '@coreui/react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { prettyDate } from 'utils/helper';
|
||||||
|
import LoadingButton from 'components/LoadingButton';
|
||||||
|
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
const DeviceNotes = ({ serialNumber, notes, refreshNotes }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const [currentNote, setCurrentNote] = useState('');
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const saveNote = () => {
|
||||||
|
setLoading(true);
|
||||||
|
|
||||||
|
const parameters = {
|
||||||
|
serialNumber,
|
||||||
|
notes: [{ note: currentNote }],
|
||||||
|
};
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
Accept: 'application/json',
|
||||||
|
Authorization: `Bearer ${currentToken}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
axiosInstance
|
||||||
|
.put(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(serialNumber)}`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
setCurrentNote('');
|
||||||
|
refreshNotes();
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const columns = [
|
||||||
|
{ key: 'created', label: t('common.date'), _style: { width: '30%' } },
|
||||||
|
{ key: 'createdBy', label: t('common.created_by'), _style: { width: '20%' } },
|
||||||
|
{ key: 'note', label: t('configuration.note'), _style: { width: '50%' } },
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="3">
|
||||||
|
<CLabel>{t('configuration.notes')} :</CLabel>
|
||||||
|
</CCol>
|
||||||
|
<CCol xs="9" md="7">
|
||||||
|
<CInput
|
||||||
|
id="notes-input"
|
||||||
|
name="text-input"
|
||||||
|
value={currentNote}
|
||||||
|
onChange={(e) => setCurrentNote(e.target.value)}
|
||||||
|
/>
|
||||||
|
</CCol>
|
||||||
|
<CCol>
|
||||||
|
<LoadingButton
|
||||||
|
label={t('common.add')}
|
||||||
|
isLoadingLabel={t('common.adding_ellipsis')}
|
||||||
|
isLoading={loading}
|
||||||
|
action={saveNote}
|
||||||
|
disabled={loading || currentNote === ''}
|
||||||
|
/>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow>
|
||||||
|
<CCol md="3" />
|
||||||
|
<CCol xs="12" md="9">
|
||||||
|
<div className={['overflow-auto', styles.scrollableBox].join(' ')}>
|
||||||
|
<CDataTable
|
||||||
|
striped
|
||||||
|
responsive
|
||||||
|
border
|
||||||
|
loading={loading}
|
||||||
|
fields={columns}
|
||||||
|
className={styles.table}
|
||||||
|
items={notes || []}
|
||||||
|
noItemsView={{ noItems: t('common.no_items') }}
|
||||||
|
sorterValue={{ column: 'created', desc: 'true' }}
|
||||||
|
scopedSlots={{
|
||||||
|
created: (item) => (
|
||||||
|
<td>
|
||||||
|
{item.created && item.created !== 0 ? prettyDate(item.created) : t('common.na')}
|
||||||
|
</td>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
DeviceNotes.propTypes = {
|
||||||
|
serialNumber: PropTypes.string.isRequired,
|
||||||
|
notes: PropTypes.arrayOf(PropTypes.instanceOf(Object)).isRequired,
|
||||||
|
refreshNotes: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeviceNotes;
|
||||||
15
src/components/DeviceNotes/index.module.scss
Normal file
15
src/components/DeviceNotes/index.module.scss
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
.scrollableBox {
|
||||||
|
height: 200px;
|
||||||
|
border-style: solid;
|
||||||
|
border-color: #ced2d8;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacedRow {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
36
src/components/DeviceStatusCard/MemoryBar.js
Normal file
36
src/components/DeviceStatusCard/MemoryBar.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { CPopover, CProgress, CProgressBar } from '@coreui/react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { cleanBytesString } from 'utils/helper';
|
||||||
|
|
||||||
|
const MemoryBar = ({ usedBytes, totalBytes }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const used = cleanBytesString(usedBytes);
|
||||||
|
const total = cleanBytesString(totalBytes);
|
||||||
|
const percentage = Math.floor((usedBytes / totalBytes) * 100);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CPopover content={t('status.used_total_memory', { used, total })}>
|
||||||
|
<CProgress>
|
||||||
|
<CProgressBar value={percentage}>
|
||||||
|
{percentage >= 25 ? t('status.percentage_used', { percentage, total }) : ''}
|
||||||
|
</CProgressBar>
|
||||||
|
<CProgressBar value={100 - percentage} color="transparent">
|
||||||
|
<div style={{ color: 'black' }}>
|
||||||
|
{percentage < 25
|
||||||
|
? t('status.percentage_free', { percentage: 100 - percentage, total })
|
||||||
|
: ''}
|
||||||
|
</div>
|
||||||
|
</CProgressBar>
|
||||||
|
</CProgress>
|
||||||
|
</CPopover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
MemoryBar.propTypes = {
|
||||||
|
usedBytes: PropTypes.number.isRequired,
|
||||||
|
totalBytes: PropTypes.number.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(MemoryBar);
|
||||||
197
src/components/DeviceStatusCard/index.js
Normal file
197
src/components/DeviceStatusCard/index.js
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
CCard,
|
||||||
|
CCardHeader,
|
||||||
|
CRow,
|
||||||
|
CCol,
|
||||||
|
CCardBody,
|
||||||
|
CBadge,
|
||||||
|
CModalBody,
|
||||||
|
CAlert,
|
||||||
|
CPopover,
|
||||||
|
CButton,
|
||||||
|
CSpinner,
|
||||||
|
} from '@coreui/react';
|
||||||
|
import CIcon from '@coreui/icons-react';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
|
import { cilSync } from '@coreui/icons';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
|
import { prettyDate, secondsToDetailed } from 'utils/helper';
|
||||||
|
import MemoryBar from './MemoryBar';
|
||||||
|
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
const DeviceStatusCard = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
|
const [lastStats, setLastStats] = useState(null);
|
||||||
|
const [status, setStatus] = useState(null);
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const transformLoad = (load) => {
|
||||||
|
if (load === undefined) return t('common.na');
|
||||||
|
return `${((load / 65536) * 100).toFixed(2)}%`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getData = () => {
|
||||||
|
setLoading(true);
|
||||||
|
const options = {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
Authorization: `Bearer ${currentToken}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const lastStatsRequest = axiosInstance.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(
|
||||||
|
deviceSerialNumber,
|
||||||
|
)}/statistics?lastOnly=true`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
const statusRequest = axiosInstance.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/status`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
|
||||||
|
Promise.all([lastStatsRequest, statusRequest])
|
||||||
|
.then(([newStats, newStatus]) => {
|
||||||
|
setLastStats(newStats.data);
|
||||||
|
setStatus(newStatus.data);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setError(true);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
setLoading(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setError(false);
|
||||||
|
if (deviceSerialNumber) getData();
|
||||||
|
}, [deviceSerialNumber]);
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
return (
|
||||||
|
<CCard>
|
||||||
|
<CCardHeader>
|
||||||
|
<CRow>
|
||||||
|
<CCol>
|
||||||
|
<div className="text-value-lg">
|
||||||
|
{t('status.title', { serialNumber: deviceSerialNumber })}
|
||||||
|
</div>
|
||||||
|
</CCol>
|
||||||
|
<CCol>
|
||||||
|
<div className={styles.alignRight}>
|
||||||
|
<CPopover content={t('common.refresh')}>
|
||||||
|
<CButton color="secondary" onClick={getData} size="sm">
|
||||||
|
<CIcon content={cilSync} />
|
||||||
|
</CButton>
|
||||||
|
</CPopover>
|
||||||
|
</div>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</CCardHeader>
|
||||||
|
<CCardBody>
|
||||||
|
{(!lastStats || !status) && loading ? (
|
||||||
|
<div className={styles.centerContainer}>
|
||||||
|
<CSpinner className={styles.spinner} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div style={{ position: 'relative' }}>
|
||||||
|
<div className={styles.overlayContainer} hidden={!loading}>
|
||||||
|
<CSpinner className={styles.spinner} />
|
||||||
|
</div>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="5">{t('status.connection_status')} :</CCol>
|
||||||
|
<CCol xs="10" md="7">
|
||||||
|
{status?.connected ? (
|
||||||
|
<CBadge color="success">{t('common.connected')}</CBadge>
|
||||||
|
) : (
|
||||||
|
<CBadge color="danger">{t('common.not_connected')}</CBadge>
|
||||||
|
)}
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="5">{t('status.uptime')} :</CCol>
|
||||||
|
<CCol xs="10" md="7">
|
||||||
|
{secondsToDetailed(
|
||||||
|
lastStats?.unit?.uptime,
|
||||||
|
t('common.day'),
|
||||||
|
t('common.days'),
|
||||||
|
t('common.hour'),
|
||||||
|
t('common.hours'),
|
||||||
|
t('common.minute'),
|
||||||
|
t('common.minutes'),
|
||||||
|
t('common.second'),
|
||||||
|
t('common.seconds'),
|
||||||
|
)}
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="5">{t('status.last_contact')} :</CCol>
|
||||||
|
<CCol xs="10" md="7">
|
||||||
|
{prettyDate(status?.lastContact)}
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="5">{t('status.localtime')} :</CCol>
|
||||||
|
<CCol xs="10" md="7">
|
||||||
|
{prettyDate(lastStats?.unit?.localtime)}
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="5">{t('status.load_averages')} :</CCol>
|
||||||
|
<CCol xs="10" md="7">
|
||||||
|
{transformLoad(lastStats?.unit?.load[0])}
|
||||||
|
{' / '}
|
||||||
|
{transformLoad(lastStats?.unit?.load[1])}
|
||||||
|
{' / '}
|
||||||
|
{transformLoad(lastStats?.unit?.load[2])}
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
<CRow className={styles.spacedRow}>
|
||||||
|
<CCol md="5">{t('status.memory')} :</CCol>
|
||||||
|
<CCol xs="9" md="6" style={{ paddingTop: '5px' }}>
|
||||||
|
<MemoryBar
|
||||||
|
usedBytes={
|
||||||
|
lastStats?.unit?.memory?.total && lastStats?.unit?.memory?.free
|
||||||
|
? lastStats?.unit?.memory?.total - lastStats?.unit?.memory?.free
|
||||||
|
: 0
|
||||||
|
}
|
||||||
|
totalBytes={lastStats?.unit?.memory?.total ?? 0}
|
||||||
|
/>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CCardBody>
|
||||||
|
</CCard>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CCard>
|
||||||
|
<CCardHeader>
|
||||||
|
<CRow>
|
||||||
|
<CCol>
|
||||||
|
<div className="text-value-lg">
|
||||||
|
{t('status.title', { serialNumber: deviceSerialNumber })}
|
||||||
|
</div>
|
||||||
|
</CCol>
|
||||||
|
</CRow>
|
||||||
|
</CCardHeader>
|
||||||
|
<CModalBody>
|
||||||
|
<CAlert hidden={!error} color="danger" className={styles.centerContainer}>
|
||||||
|
{t('status.error')}
|
||||||
|
</CAlert>
|
||||||
|
</CModalBody>
|
||||||
|
</CCard>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default React.memo(DeviceStatusCard);
|
||||||
29
src/components/DeviceStatusCard/index.module.scss
Normal file
29
src/components/DeviceStatusCard/index.module.scss
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
.centerContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlayContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacedRow {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alignRight {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
@@ -14,15 +14,17 @@ import {
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import 'react-widgets/styles.css';
|
import 'react-widgets/styles.css';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import SuccessfulActionModalBody from 'components/SuccessfulActionModalBody';
|
import SuccessfulActionModalBody from 'components/SuccessfulActionModalBody';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const ConfigureModal = ({ show, toggleModal }) => {
|
const ConfigureModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [hadSuccess, setHadSuccess] = useState(false);
|
const [hadSuccess, setHadSuccess] = useState(false);
|
||||||
const [hadFailure, setHadFailure] = useState(false);
|
const [hadFailure, setHadFailure] = useState(false);
|
||||||
const [doingNow, setDoingNow] = useState(false);
|
const [doingNow, setDoingNow] = useState(false);
|
||||||
@@ -30,7 +32,6 @@ const ConfigureModal = ({ show, toggleModal }) => {
|
|||||||
const [keepRedirector, setKeepRedirector] = useState(true);
|
const [keepRedirector, setKeepRedirector] = useState(true);
|
||||||
const [responseBody, setResponseBody] = useState('');
|
const [responseBody, setResponseBody] = useState('');
|
||||||
const [checkingIfSure, setCheckingIfSure] = useState(false);
|
const [checkingIfSure, setCheckingIfSure] = useState(false);
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
const toggleRedirector = () => {
|
const toggleRedirector = () => {
|
||||||
setKeepRedirector(!keepRedirector);
|
setKeepRedirector(!keepRedirector);
|
||||||
@@ -54,17 +55,21 @@ const ConfigureModal = ({ show, toggleModal }) => {
|
|||||||
setWaiting(true);
|
setWaiting(true);
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
keepRedirector,
|
keepRedirector,
|
||||||
};
|
};
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/factory`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/factory`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setHadSuccess(true);
|
setHadSuccess(true);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,16 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { CButton, CSpinner, CModalFooter } from '@coreui/react';
|
import { CButton, CSpinner, CModalFooter } from '@coreui/react';
|
||||||
|
|
||||||
const UpgradeFooter = ({ isNow, isShown, isLoading, action, color, variant, block, toggleParent }) => {
|
const UpgradeFooter = ({
|
||||||
|
isNow,
|
||||||
|
isShown,
|
||||||
|
isLoading,
|
||||||
|
action,
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
block,
|
||||||
|
toggleParent,
|
||||||
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [askingIfSure, setAskingIfSure] = useState(false);
|
const [askingIfSure, setAskingIfSure] = useState(false);
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { CModalBody } from '@coreui/react';
|
import { CModalBody } from '@coreui/react';
|
||||||
import { v4 as createUuid } from 'uuid';
|
import { v4 as createUuid } from 'uuid';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
|
|
||||||
const UpgradeWaitingBody = ({ serialNumber }) => {
|
const UpgradeWaitingBody = ({ serialNumber }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
const [currentStep, setCurrentStep] = useState(0);
|
const [currentStep, setCurrentStep] = useState(0);
|
||||||
const [secondsElapsed, setSecondsElapsed] = useState(0);
|
const [secondsElapsed, setSecondsElapsed] = useState(0);
|
||||||
const [labelsToShow, setLabelsToShow] = useState(['upgrade.command_submitted']);
|
const [labelsToShow, setLabelsToShow] = useState(['upgrade.command_submitted']);
|
||||||
@@ -16,12 +17,15 @@ const UpgradeWaitingBody = ({ serialNumber }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(serialNumber)}/status`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(serialNumber)}/status`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => response.data.connected)
|
.then((response) => response.data.connected)
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
@@ -30,12 +34,12 @@ const UpgradeWaitingBody = ({ serialNumber }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(serialNumber)}`, options)
|
.get(`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(serialNumber)}`, options)
|
||||||
.then((response) => response.data.firmware)
|
.then((response) => response.data.firmware)
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
};
|
};
|
||||||
@@ -80,11 +84,11 @@ const UpgradeWaitingBody = ({ serialNumber }) => {
|
|||||||
<div className="consoleBox">
|
<div className="consoleBox">
|
||||||
{labelsToShow.map((label) => (
|
{labelsToShow.map((label) => (
|
||||||
<p key={createUuid()}>
|
<p key={createUuid()}>
|
||||||
{new Date().toString()}: {label}
|
{new Date().toString()}:{label}
|
||||||
</p>
|
</p>
|
||||||
))}
|
))}
|
||||||
<p>
|
<p>
|
||||||
{t('common.seconds_elapsed')}: {secondsElapsed}
|
{t('common.seconds_elapsed')}:{secondsElapsed}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</CModalBody>
|
</CModalBody>
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { dateToUnix } from 'utils/helper';
|
import { dateToUnix } from 'utils/helper';
|
||||||
import 'react-widgets/styles.css';
|
import 'react-widgets/styles.css';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import getDeviceConnection from 'utils/deviceHelper';
|
import getDeviceConnection from 'utils/deviceHelper';
|
||||||
@@ -28,6 +28,8 @@ import UpgradeWaitingBody from './UpgradeWaitingBody';
|
|||||||
|
|
||||||
const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [isNow, setIsNow] = useState(true);
|
const [isNow, setIsNow] = useState(true);
|
||||||
const [waitForUpgrade, setWaitForUpgrade] = useState(false);
|
const [waitForUpgrade, setWaitForUpgrade] = useState(false);
|
||||||
const [date, setDate] = useState(new Date().toString());
|
const [date, setDate] = useState(new Date().toString());
|
||||||
@@ -39,14 +41,12 @@ const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
|||||||
const [waitingForUpgrade, setWaitingForUpgrade] = useState(false);
|
const [waitingForUpgrade, setWaitingForUpgrade] = useState(false);
|
||||||
const [showWaitingConsole, setShowWaitingConsole] = useState(false);
|
const [showWaitingConsole, setShowWaitingConsole] = useState(false);
|
||||||
const [deviceConnected, setDeviceConnected] = useState(true);
|
const [deviceConnected, setDeviceConnected] = useState(true);
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
const toggleNow = () => {
|
const toggleNow = () => {
|
||||||
if(isNow){
|
if (isNow) {
|
||||||
setWaitForUpgrade(false);
|
setWaitForUpgrade(false);
|
||||||
setDisableWaiting(true);
|
setDisableWaiting(true);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
setDisableWaiting(false);
|
setDisableWaiting(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,9 +82,13 @@ const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
|||||||
}, [firmware, date]);
|
}, [firmware, date]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId !== null && show) {
|
if (deviceSerialNumber !== null && show) {
|
||||||
const asyncGet = async () => {
|
const asyncGet = async () => {
|
||||||
const isConnected = await getDeviceConnection(selectedDeviceId);
|
const isConnected = await getDeviceConnection(
|
||||||
|
deviceSerialNumber,
|
||||||
|
currentToken,
|
||||||
|
endpoints.ucentralgw,
|
||||||
|
);
|
||||||
setDisableWaiting(!isConnected);
|
setDisableWaiting(!isConnected);
|
||||||
setDeviceConnected(isConnected);
|
setDeviceConnected(isConnected);
|
||||||
};
|
};
|
||||||
@@ -98,24 +102,27 @@ const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
|||||||
setBlockFields(true);
|
setBlockFields(true);
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
};
|
};
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
when: isNow ? 0 : dateToUnix(date),
|
when: isNow ? 0 : dateToUnix(date),
|
||||||
uri: firmware,
|
uri: firmware,
|
||||||
};
|
};
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/upgrade`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/upgrade`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (waitForUpgrade) {
|
if (waitForUpgrade) {
|
||||||
setShowWaitingConsole(true);
|
setShowWaitingConsole(true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {})
|
||||||
})
|
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
setBlockFields(false);
|
setBlockFields(false);
|
||||||
setWaitingForUpgrade(false);
|
setWaitingForUpgrade(false);
|
||||||
@@ -131,7 +138,7 @@ const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
|||||||
<CModalTitle>{t('upgrade.title')}</CModalTitle>
|
<CModalTitle>{t('upgrade.title')}</CModalTitle>
|
||||||
</CModalHeader>
|
</CModalHeader>
|
||||||
<CModalBody>
|
<CModalBody>
|
||||||
<UpgradeWaitingBody serialNumber={selectedDeviceId} />
|
<UpgradeWaitingBody serialNumber={deviceSerialNumber} />
|
||||||
</CModalBody>
|
</CModalBody>
|
||||||
<CModalFooter>
|
<CModalFooter>
|
||||||
<CButton color="secondary" onClick={toggleModal}>
|
<CButton color="secondary" onClick={toggleModal}>
|
||||||
@@ -198,7 +205,10 @@ const FirmwareUpgradeModal = ({ show, toggleModal }) => {
|
|||||||
<CInvalidFeedback>{t('common.need_date')}</CInvalidFeedback>
|
<CInvalidFeedback>{t('common.need_date')}</CInvalidFeedback>
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
<CRow className={styles.spacedRow} hidden={true || !isNow || disabledWaiting || !deviceConnected}>
|
<CRow
|
||||||
|
className={styles.spacedRow}
|
||||||
|
hidden={true || !isNow || disabledWaiting || !deviceConnected}
|
||||||
|
>
|
||||||
<CCol md="8">
|
<CCol md="8">
|
||||||
<p className={styles.spacedText}>
|
<p className={styles.spacedText}>
|
||||||
{t('upgrade.wait_for_upgrade')}
|
{t('upgrade.wait_for_upgrade')}
|
||||||
|
|||||||
@@ -10,23 +10,29 @@ import {
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const LatestStatisticsModal = ({ show, toggle, serialNumber }) => {
|
const LatestStatisticsModal = ({ show, toggle }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [latestStats, setLatestStats] = useState('');
|
const [latestStats, setLatestStats] = useState('');
|
||||||
|
|
||||||
const getLatestStats = () => {
|
const getLatestStats = () => {
|
||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${serialNumber}/statistics?lastOnly=true`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${deviceSerialNumber}/statistics?lastOnly=true`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setLatestStats(response.data);
|
setLatestStats(response.data);
|
||||||
})
|
})
|
||||||
@@ -57,7 +63,6 @@ const LatestStatisticsModal = ({ show, toggle, serialNumber }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
LatestStatisticsModal.propTypes = {
|
LatestStatisticsModal.propTypes = {
|
||||||
serialNumber: PropTypes.string.isRequired,
|
|
||||||
toggle: PropTypes.func.isRequired,
|
toggle: PropTypes.func.isRequired,
|
||||||
show: PropTypes.bool.isRequired,
|
show: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { v4 as createUuid } from 'uuid';
|
import { v4 as createUuid } from 'uuid';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import { unixToTime, capitalizeFirstLetter } from 'utils/helper';
|
import { unixToTime, capitalizeFirstLetter } from 'utils/helper';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import DeviceStatisticsChart from './DeviceStatisticsChart';
|
import DeviceStatisticsChart from './DeviceStatisticsChart';
|
||||||
|
|
||||||
const StatisticsChartList = ({ selectedDeviceId }) => {
|
const StatisticsChartList = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [statOptions, setStatOptions] = useState({
|
const [statOptions, setStatOptions] = useState({
|
||||||
interfaceList: [],
|
interfaceList: [],
|
||||||
settings: {},
|
settings: {},
|
||||||
@@ -60,10 +62,10 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
// Looping through the interfaces of the log
|
// Looping through the interfaces of the log
|
||||||
for (const inter of log.data.interfaces) {
|
for (const inter of log.data.interfaces) {
|
||||||
interfaceList[interfaceTypes[inter.name]][0].data.push(
|
interfaceList[interfaceTypes[inter.name]][0].data.push(
|
||||||
inter.counters?.tx_bytes? Math.floor(inter.counters.tx_bytes / 1024) : 0
|
inter.counters?.tx_bytes ? Math.floor(inter.counters.tx_bytes / 1024) : 0,
|
||||||
);
|
);
|
||||||
interfaceList[interfaceTypes[inter.name]][1].data.push(
|
interfaceList[interfaceTypes[inter.name]][1].data.push(
|
||||||
inter.counters?.rx_bytes? Math.floor(inter.counters.rx_bytes / 1024) : 0
|
inter.counters?.rx_bytes ? Math.floor(inter.counters.rx_bytes / 1024) : 0,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +76,7 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
group: 'txrx',
|
group: 'txrx',
|
||||||
},
|
},
|
||||||
stroke: {
|
stroke: {
|
||||||
curve: 'smooth'
|
curve: 'smooth',
|
||||||
},
|
},
|
||||||
xaxis: {
|
xaxis: {
|
||||||
title: {
|
title: {
|
||||||
@@ -118,7 +120,7 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
params: {
|
params: {
|
||||||
serialNumber: '24f5a207a130',
|
serialNumber: '24f5a207a130',
|
||||||
@@ -126,7 +128,10 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/device/${selectedDeviceId}/statistics?newest=true&limit=50`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${deviceSerialNumber}/statistics?newest=true&limit=50`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
transformIntoDataset(response.data.data);
|
transformIntoDataset(response.data.data);
|
||||||
})
|
})
|
||||||
@@ -134,10 +139,10 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId) {
|
if (deviceSerialNumber) {
|
||||||
getStatistics();
|
getStatistics();
|
||||||
}
|
}
|
||||||
}, [selectedDeviceId]);
|
}, [deviceSerialNumber]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
eventBus.on('refreshInterfaceStatistics', () => getStatistics());
|
eventBus.on('refreshInterfaceStatistics', () => getStatistics());
|
||||||
@@ -161,11 +166,11 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
fontSize: '25px',
|
fontSize: '25px',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
return (
|
return (
|
||||||
<div key={createUuid()}>
|
<div key={createUuid()}>
|
||||||
<DeviceStatisticsChart chart={ options } />
|
<DeviceStatisticsChart chart={options} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -173,8 +178,4 @@ const StatisticsChartList = ({ selectedDeviceId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
StatisticsChartList.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default React.memo(StatisticsChartList);
|
export default React.memo(StatisticsChartList);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
import {
|
||||||
CDropdown,
|
CDropdown,
|
||||||
CDropdownToggle,
|
CDropdownToggle,
|
||||||
@@ -19,7 +18,7 @@ import StatisticsChartList from './StatisticsChartList';
|
|||||||
import LatestStatisticsModal from './LatestStatisticsModal';
|
import LatestStatisticsModal from './LatestStatisticsModal';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const DeviceStatisticsCard = ({ selectedDeviceId }) => {
|
const DeviceStatisticsCard = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showLatestModal, setShowLatestModal] = useState(false);
|
const [showLatestModal, setShowLatestModal] = useState(false);
|
||||||
|
|
||||||
@@ -37,7 +36,9 @@ const DeviceStatisticsCard = ({ selectedDeviceId }) => {
|
|||||||
<CCardHeader>
|
<CCardHeader>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol>
|
<CCol>
|
||||||
<div className={["text-value-lg", styles.cardTitle].join(" ")}>{t('statistics.title')}</div>
|
<div className={['text-value-lg', styles.cardTitle].join(' ')}>
|
||||||
|
{t('statistics.title')}
|
||||||
|
</div>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol className={styles.cardOptions}>
|
<CCol className={styles.cardOptions}>
|
||||||
<CDropdown className="m-1 btn-group">
|
<CDropdown className="m-1 btn-group">
|
||||||
@@ -55,20 +56,12 @@ const DeviceStatisticsCard = ({ selectedDeviceId }) => {
|
|||||||
</CRow>
|
</CRow>
|
||||||
</CCardHeader>
|
</CCardHeader>
|
||||||
<CCardBody className={styles.statsBody}>
|
<CCardBody className={styles.statsBody}>
|
||||||
<StatisticsChartList selectedDeviceId={selectedDeviceId} />
|
<StatisticsChartList />
|
||||||
</CCardBody>
|
</CCardBody>
|
||||||
</CCard>
|
</CCard>
|
||||||
<LatestStatisticsModal
|
<LatestStatisticsModal show={showLatestModal} toggle={toggleLatestModal} />
|
||||||
show={showLatestModal}
|
|
||||||
toggle={toggleLatestModal}
|
|
||||||
serialNumber={selectedDeviceId}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
DeviceStatisticsCard.propTypes = {
|
|
||||||
selectedDeviceId: PropTypes.string.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default DeviceStatisticsCard;
|
export default DeviceStatisticsCard;
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import DatePicker from 'react-widgets/DatePicker';
|
import DatePicker from 'react-widgets/DatePicker';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { dateToUnix } from 'utils/helper';
|
import { dateToUnix } from 'utils/helper';
|
||||||
import 'react-widgets/styles.css';
|
import 'react-widgets/styles.css';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import LoadingButton from 'components/LoadingButton';
|
import LoadingButton from 'components/LoadingButton';
|
||||||
@@ -25,15 +25,16 @@ import styles from './index.module.scss';
|
|||||||
|
|
||||||
const ActionModal = ({ show, toggleModal }) => {
|
const ActionModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [waiting, setWaiting] = useState(false);
|
const [waiting, setWaiting] = useState(false);
|
||||||
const [result, setResult] = useState(null);
|
const [result, setResult] = useState(null);
|
||||||
const [chosenDate, setChosenDate] = useState(new Date().toString());
|
const [chosenDate, setChosenDate] = useState(new Date().toString());
|
||||||
const [isNow, setIsNow] = useState(false);
|
const [isNow, setIsNow] = useState(false);
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
const toggleNow = () => {
|
const toggleNow = () => {
|
||||||
setIsNow(!isNow);
|
setIsNow(!isNow);
|
||||||
}
|
};
|
||||||
|
|
||||||
const setDate = (date) => {
|
const setDate = (date) => {
|
||||||
if (date) {
|
if (date) {
|
||||||
@@ -52,21 +53,24 @@ const ActionModal = ({ show, toggleModal }) => {
|
|||||||
const doAction = () => {
|
const doAction = () => {
|
||||||
setWaiting(true);
|
setWaiting(true);
|
||||||
|
|
||||||
const token = getToken();
|
|
||||||
const utcDate = new Date(chosenDate);
|
const utcDate = new Date(chosenDate);
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
when: isNow ? 0 : dateToUnix(utcDate),
|
when: isNow ? 0 : dateToUnix(utcDate),
|
||||||
};
|
};
|
||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/reboot`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/reboot`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setResult('success');
|
setResult('success');
|
||||||
})
|
})
|
||||||
@@ -89,10 +93,9 @@ const ActionModal = ({ show, toggleModal }) => {
|
|||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<CModalBody>
|
<CModalBody>
|
||||||
<h6>{t('reboot.directions')}</h6>
|
<CRow>
|
||||||
<CRow className={styles.spacedRow}>
|
|
||||||
<CCol md="8">
|
<CCol md="8">
|
||||||
<p className={styles.spacedText}>{t('common.execute_now')}</p>
|
<p>{t('reboot.now')}</p>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CSwitch
|
<CSwitch
|
||||||
@@ -107,7 +110,7 @@ const ActionModal = ({ show, toggleModal }) => {
|
|||||||
</CRow>
|
</CRow>
|
||||||
<CRow hidden={isNow} className={styles.spacedRow}>
|
<CRow hidden={isNow} className={styles.spacedRow}>
|
||||||
<CCol md="4" className={styles.spacedDate}>
|
<CCol md="4" className={styles.spacedDate}>
|
||||||
<p>{t('common.date')}</p>
|
<p>{t('common.custom_date')}:</p>
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="8">
|
<CCol xs="12" md="8">
|
||||||
<DatePicker
|
<DatePicker
|
||||||
|
|||||||
@@ -7,5 +7,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.spacedDate {
|
.spacedDate {
|
||||||
margin-top: 7px;
|
padding-top: 5px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { CModalBody, CButton, CSpinner, CModalFooter } from '@coreui/react';
|
import { CModalBody, CButton, CSpinner, CModalFooter } from '@coreui/react';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const WaitingForTraceBody = ({serialNumber, commandUuid, toggle}) => {
|
const WaitingForTraceBody = ({ serialNumber, commandUuid, toggle }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
const [secondsElapsed, setSecondsElapsed] = useState(0);
|
const [secondsElapsed, setSecondsElapsed] = useState(0);
|
||||||
const [waitingForFile, setWaitingForFile] = useState(true);
|
const [waitingForFile, setWaitingForFile] = useState(true);
|
||||||
|
|
||||||
@@ -16,31 +17,34 @@ const WaitingForTraceBody = ({serialNumber, commandUuid, toggle}) => {
|
|||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/command/${encodeURIComponent(commandUuid)}`, options)
|
.get(`${endpoints.ucentralgw}/api/v1/command/${encodeURIComponent(commandUuid)}`, options)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if(response.data.waitingForFile === 0){
|
if (response.data.waitingForFile === 0) {
|
||||||
setWaitingForFile(false);
|
setWaitingForFile(false);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
};
|
||||||
|
|
||||||
const downloadTrace = () => {
|
const downloadTrace = () => {
|
||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/octet-stream',
|
Accept: 'application/octet-stream',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
},
|
},
|
||||||
responseType: 'arraybuffer',
|
responseType: 'arraybuffer',
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.get(`/file/${commandUuid}?serialNumber=${serialNumber}`, options)
|
.get(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/file/${commandUuid}?serialNumber=${serialNumber}`,
|
||||||
|
options,
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const blob = new Blob([response.data], { type: 'application/octet-stream' });
|
const blob = new Blob([response.data], { type: 'application/octet-stream' });
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
@@ -48,49 +52,48 @@ const WaitingForTraceBody = ({serialNumber, commandUuid, toggle}) => {
|
|||||||
link.download = `Trace_${commandUuid}.pcap`;
|
link.download = `Trace_${commandUuid}.pcap`;
|
||||||
link.click();
|
link.click();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setInterval(() => {
|
const timer = setInterval(() => {
|
||||||
setSecondsElapsed(secondsElapsed + 1);
|
setSecondsElapsed(secondsElapsed + 1);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
if(!waitingForFile){
|
if (!waitingForFile) {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(timer);
|
clearInterval(timer);
|
||||||
}
|
};
|
||||||
}, [waitingForFile, secondsElapsed]);
|
}, [waitingForFile, secondsElapsed]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const refreshStatus = setInterval(() => {
|
const refreshStatus = setInterval(() => {
|
||||||
getTraceResult();
|
getTraceResult();
|
||||||
}, 5000);
|
}, 5000);
|
||||||
if(!waitingForFile){
|
if (!waitingForFile) {
|
||||||
clearInterval(refreshStatus);
|
clearInterval(refreshStatus);
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(refreshStatus);
|
clearInterval(refreshStatus);
|
||||||
}
|
};
|
||||||
}, [waitingForFile]);
|
}, [waitingForFile]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CModalBody>
|
<CModalBody>
|
||||||
<h6>{t('trace.waiting_seconds', {seconds: secondsElapsed})}</h6>
|
<h6>{t('trace.waiting_seconds', { seconds: secondsElapsed })}</h6>
|
||||||
<p>{t('trace.waiting_directions')}</p>
|
<p>{t('trace.waiting_directions')}</p>
|
||||||
<div className={styles.centerDiv}>
|
<div className={styles.centerDiv}>
|
||||||
<CSpinner hidden={!waitingForFile} />
|
<CSpinner hidden={!waitingForFile} />
|
||||||
</div>
|
|
||||||
<CButton
|
<CButton
|
||||||
hidden={waitingForFile}
|
hidden={waitingForFile}
|
||||||
onClick={downloadTrace}
|
onClick={downloadTrace}
|
||||||
disabled={waitingForFile}
|
disabled={waitingForFile}
|
||||||
color="link"
|
color="primary"
|
||||||
block
|
|
||||||
>
|
>
|
||||||
{t('trace.download_trace')}
|
{t('trace.download_trace')}
|
||||||
</CButton>
|
</CButton>
|
||||||
|
</div>
|
||||||
</CModalBody>
|
</CModalBody>
|
||||||
<CModalFooter>
|
<CModalFooter>
|
||||||
<CButton color="secondary" block onClick={toggle}>
|
<CButton color="secondary" block onClick={toggle}>
|
||||||
@@ -98,14 +101,13 @@ const WaitingForTraceBody = ({serialNumber, commandUuid, toggle}) => {
|
|||||||
</CButton>
|
</CButton>
|
||||||
</CModalFooter>
|
</CModalFooter>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
WaitingForTraceBody.propTypes = {
|
WaitingForTraceBody.propTypes = {
|
||||||
serialNumber: PropTypes.string.isRequired,
|
serialNumber: PropTypes.string.isRequired,
|
||||||
commandUuid: PropTypes.string.isRequired,
|
commandUuid: PropTypes.string.isRequired,
|
||||||
toggle: PropTypes.func.isRequired
|
toggle: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default WaitingForTraceBody;
|
export default WaitingForTraceBody;
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import {
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import 'react-widgets/styles.css';
|
import 'react-widgets/styles.css';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import getDeviceConnection from 'utils/deviceHelper';
|
import getDeviceConnection from 'utils/deviceHelper';
|
||||||
@@ -30,6 +30,8 @@ import styles from './index.module.scss';
|
|||||||
|
|
||||||
const TraceModal = ({ show, toggleModal }) => {
|
const TraceModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [hadSuccess, setHadSuccess] = useState(false);
|
const [hadSuccess, setHadSuccess] = useState(false);
|
||||||
const [hadFailure, setHadFailure] = useState(false);
|
const [hadFailure, setHadFailure] = useState(false);
|
||||||
const [blockFields, setBlockFields] = useState(false);
|
const [blockFields, setBlockFields] = useState(false);
|
||||||
@@ -43,11 +45,9 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
const [waitingForTrace, setWaitingForTrace] = useState(false);
|
const [waitingForTrace, setWaitingForTrace] = useState(false);
|
||||||
const [commandUuid, setCommandUuid] = useState(null);
|
const [commandUuid, setCommandUuid] = useState(null);
|
||||||
|
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
const toggleWaitForTrace = () => {
|
const toggleWaitForTrace = () => {
|
||||||
setWaitForTrace(!waitForTrace);
|
setWaitForTrace(!waitForTrace);
|
||||||
}
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setWaitForTrace(false);
|
setWaitForTrace(false);
|
||||||
@@ -65,10 +65,8 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
setHadFailure(false);
|
setHadFailure(false);
|
||||||
setHadSuccess(false);
|
setHadSuccess(false);
|
||||||
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
when: 0,
|
when: 0,
|
||||||
network: chosenInterface,
|
network: chosenInterface,
|
||||||
};
|
};
|
||||||
@@ -81,14 +79,18 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
|
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/trace`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/trace`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
setHadSuccess(true);
|
setHadSuccess(true);
|
||||||
if(waitForTrace) {
|
if (waitForTrace) {
|
||||||
setCommandUuid(response.data.UUID);
|
setCommandUuid(response.data.UUID);
|
||||||
setWaitingForTrace(true);
|
setWaitingForTrace(true);
|
||||||
}
|
}
|
||||||
@@ -105,26 +107,31 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedDeviceId !== null && show) {
|
if (deviceSerialNumber !== null && show) {
|
||||||
const asyncGet = async () => {
|
const asyncGet = async () => {
|
||||||
const isConnected = await getDeviceConnection(selectedDeviceId);
|
const isConnected = await getDeviceConnection(
|
||||||
|
deviceSerialNumber,
|
||||||
|
currentToken,
|
||||||
|
endpoints.ucentralgw,
|
||||||
|
);
|
||||||
setIsDeviceConnected(isConnected);
|
setIsDeviceConnected(isConnected);
|
||||||
};
|
};
|
||||||
asyncGet();
|
asyncGet();
|
||||||
}
|
}
|
||||||
}, [show]);
|
}, [show]);
|
||||||
|
|
||||||
|
|
||||||
const getBody = () => {
|
const getBody = () => {
|
||||||
if(waitingForTrace){
|
if (waitingForTrace) {
|
||||||
return (
|
return (
|
||||||
<WaitingForTraceBody toggle={toggleModal} serialNumber={selectedDeviceId} commandUuid={commandUuid}/>
|
<WaitingForTraceBody
|
||||||
|
toggle={toggleModal}
|
||||||
|
serialNumber={deviceSerialNumber}
|
||||||
|
commandUuid={commandUuid}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if(hadSuccess){
|
if (hadSuccess) {
|
||||||
return(
|
return <SuccessfulActionModalBody toggleModal={toggleModal} />;
|
||||||
<SuccessfulActionModalBody toggleModal={toggleModal} />
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -158,34 +165,28 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" md="8">
|
<CCol xs="12" md="8">
|
||||||
{usingDuration ? (
|
{usingDuration ? (
|
||||||
<CSelect defaultValue="duration" disabled={blockFields}>
|
<CSelect
|
||||||
<option value="20" onClick={() => setDuration(20)}>
|
custom
|
||||||
20s
|
defaultValue={duration}
|
||||||
</option>
|
disabled={blockFields}
|
||||||
<option value="40" onClick={() => setDuration(40)}>
|
onChange={(e) => setDuration(e.target.value)}
|
||||||
40s
|
>
|
||||||
</option>
|
<option value="20">20s</option>
|
||||||
<option value="60" onClick={() => setDuration(60)}>
|
<option value="40">40s</option>
|
||||||
60s
|
<option value="60">60s</option>
|
||||||
</option>
|
<option value="120">120s</option>
|
||||||
<option value="120" onClick={() => setDuration(120)}>
|
|
||||||
120s
|
|
||||||
</option>
|
|
||||||
</CSelect>
|
</CSelect>
|
||||||
) : (
|
) : (
|
||||||
<CSelect defaultValue={packets} disabled={blockFields}>
|
<CSelect
|
||||||
<option value="100" onClick={() => setPackets(100)}>
|
custom
|
||||||
100
|
defaultValue={packets}
|
||||||
</option>
|
disabled={blockFields}
|
||||||
<option value="250" onClick={() => setPackets(250)}>
|
onChange={(e) => setPackets(e.target.value)}
|
||||||
250
|
>
|
||||||
</option>
|
<option value="100">100</option>
|
||||||
<option value="500" onClick={() => setPackets(500)}>
|
<option value="250">250</option>
|
||||||
500
|
<option value="500">500</option>
|
||||||
</option>
|
<option value="1000">1000</option>
|
||||||
<option value="1000" onClick={() => setPackets(1000)}>
|
|
||||||
1000
|
|
||||||
</option>
|
|
||||||
</CSelect>
|
</CSelect>
|
||||||
)}
|
)}
|
||||||
</CCol>
|
</CCol>
|
||||||
@@ -221,9 +222,7 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
</CRow>
|
</CRow>
|
||||||
<CRow className={styles.spacedRow} hidden={!isDeviceConnected}>
|
<CRow className={styles.spacedRow} hidden={!isDeviceConnected}>
|
||||||
<CCol md="8">
|
<CCol md="8">
|
||||||
<p className={styles.spacedText}>
|
<p className={styles.spacedText}>{t('trace.wait_for_file')}</p>
|
||||||
{t('trace.wait_for_file')}
|
|
||||||
</p>
|
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol>
|
<CCol>
|
||||||
<CSwitch
|
<CSwitch
|
||||||
@@ -257,7 +256,7 @@ const TraceModal = ({ show, toggleModal }) => {
|
|||||||
</CModalFooter>
|
</CModalFooter>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CModal show={show} onClose={toggleModal}>
|
<CModal show={show} onClose={toggleModal}>
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ import {
|
|||||||
CForm,
|
CForm,
|
||||||
CSwitch,
|
CSwitch,
|
||||||
CCol,
|
CCol,
|
||||||
CSpinner
|
CSpinner,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { getToken } from 'utils/authHelper';
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { useDevice } from 'contexts/DeviceProvider';
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import eventBus from 'utils/eventBus';
|
import eventBus from 'utils/eventBus';
|
||||||
import LoadingButton from 'components/LoadingButton';
|
import LoadingButton from 'components/LoadingButton';
|
||||||
@@ -25,6 +25,8 @@ import styles from './index.module.scss';
|
|||||||
|
|
||||||
const WifiScanModal = ({ show, toggleModal }) => {
|
const WifiScanModal = ({ show, toggleModal }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
const { deviceSerialNumber } = useDevice();
|
||||||
const [hadSuccess, setHadSuccess] = useState(false);
|
const [hadSuccess, setHadSuccess] = useState(false);
|
||||||
const [hadFailure, setHadFailure] = useState(false);
|
const [hadFailure, setHadFailure] = useState(false);
|
||||||
const [waiting, setWaiting] = useState(false);
|
const [waiting, setWaiting] = useState(false);
|
||||||
@@ -32,7 +34,6 @@ const WifiScanModal = ({ show, toggleModal }) => {
|
|||||||
const [activeScan, setActiveScan] = useState(false);
|
const [activeScan, setActiveScan] = useState(false);
|
||||||
const [hideOptions, setHideOptions] = useState(false);
|
const [hideOptions, setHideOptions] = useState(false);
|
||||||
const [channelList, setChannelList] = useState([]);
|
const [channelList, setChannelList] = useState([]);
|
||||||
const selectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
const toggleVerbose = () => {
|
const toggleVerbose = () => {
|
||||||
setVerbose(!choseVerbose);
|
setVerbose(!choseVerbose);
|
||||||
@@ -88,20 +89,22 @@ const WifiScanModal = ({ show, toggleModal }) => {
|
|||||||
setHadSuccess(false);
|
setHadSuccess(false);
|
||||||
setWaiting(true);
|
setWaiting(true);
|
||||||
|
|
||||||
const token = getToken();
|
|
||||||
|
|
||||||
const parameters = {
|
const parameters = {
|
||||||
serialNumber: selectedDeviceId,
|
serialNumber: deviceSerialNumber,
|
||||||
verbose: choseVerbose,
|
verbose: choseVerbose,
|
||||||
activeScan,
|
activeScan,
|
||||||
};
|
};
|
||||||
const headers = {
|
const headers = {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${currentToken}`,
|
||||||
};
|
};
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`/device/${encodeURIComponent(selectedDeviceId)}/wifiscan`, parameters, { headers })
|
.post(
|
||||||
|
`${endpoints.ucentralgw}/api/v1/device/${encodeURIComponent(deviceSerialNumber)}/wifiscan`,
|
||||||
|
parameters,
|
||||||
|
{ headers },
|
||||||
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
const scanList = response?.data?.results?.status?.scan;
|
const scanList = response?.data?.results?.status?.scan;
|
||||||
|
|
||||||
@@ -186,7 +189,7 @@ const WifiScanModal = ({ show, toggleModal }) => {
|
|||||||
</CModalBody>
|
</CModalBody>
|
||||||
<CModalFooter>
|
<CModalFooter>
|
||||||
<LoadingButton
|
<LoadingButton
|
||||||
label={(!hadSuccess && !hadFailure) ? t('scan.scan') : t('scan.re_scan')}
|
label={!hadSuccess && !hadFailure ? t('scan.scan') : t('scan.re_scan')}
|
||||||
isLoadingLabel={t('scan.scanning')}
|
isLoadingLabel={t('scan.scanning')}
|
||||||
isLoading={waiting}
|
isLoading={waiting}
|
||||||
action={doAction}
|
action={doAction}
|
||||||
@@ -195,7 +198,7 @@ const WifiScanModal = ({ show, toggleModal }) => {
|
|||||||
disabled={waiting}
|
disabled={waiting}
|
||||||
/>
|
/>
|
||||||
<CButton color="secondary" onClick={toggleModal}>
|
<CButton color="secondary" onClick={toggleModal}>
|
||||||
{(!hadSuccess && !hadFailure) ? t('common.cancel') : t('common.exit')}
|
{!hadSuccess && !hadFailure ? t('common.cancel') : t('common.exit')}
|
||||||
</CButton>
|
</CButton>
|
||||||
</CModalFooter>
|
</CModalFooter>
|
||||||
</CModal>
|
</CModal>
|
||||||
|
|||||||
27
src/contexts/AuthProvider/index.js
Normal file
27
src/contexts/AuthProvider/index.js
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const AuthContext = React.createContext();
|
||||||
|
|
||||||
|
export const AuthProvider = ({ token, apiEndpoints, children }) => {
|
||||||
|
const [currentToken, setCurrentToken] = useState(token);
|
||||||
|
const [endpoints, setEndpoints] = useState(apiEndpoints);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthContext.Provider value={{ currentToken, setCurrentToken, endpoints, setEndpoints }}>
|
||||||
|
{children}
|
||||||
|
</AuthContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthProvider.propTypes = {
|
||||||
|
token: PropTypes.string.isRequired,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
apiEndpoints: PropTypes.instanceOf(Object),
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthProvider.defaultProps = {
|
||||||
|
apiEndpoints: {},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAuth = () => React.useContext(AuthContext);
|
||||||
21
src/contexts/DeviceProvider/index.js
Normal file
21
src/contexts/DeviceProvider/index.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
const DeviceContext = React.createContext();
|
||||||
|
|
||||||
|
export const DeviceProvider = ({ serialNumber, children }) => {
|
||||||
|
const [deviceSerialNumber, setDeviceSerialNumber] = useState(serialNumber);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DeviceContext.Provider value={{ deviceSerialNumber, setDeviceSerialNumber }}>
|
||||||
|
{children}
|
||||||
|
</DeviceContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
DeviceProvider.propTypes = {
|
||||||
|
serialNumber: PropTypes.string.isRequired,
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDevice = () => React.useContext(DeviceContext);
|
||||||
@@ -1,19 +1,17 @@
|
|||||||
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import 'index.css';
|
import 'index.css';
|
||||||
import { Provider } from 'react-redux';
|
|
||||||
import App from 'App';
|
import App from 'App';
|
||||||
import store from 'store';
|
|
||||||
import { icons } from 'assets/icons';
|
import { icons } from 'assets/icons';
|
||||||
|
import '@babel/polyfill';
|
||||||
import 'i18n';
|
import 'i18n';
|
||||||
|
|
||||||
React.icons = icons;
|
React.icons = icons;
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<Provider store={store}>
|
|
||||||
<App />
|
<App />
|
||||||
</Provider>
|
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root'),
|
document.getElementById('root'),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const TheFooter = () => (
|
|||||||
<Translation>
|
<Translation>
|
||||||
{(t) => (
|
{(t) => (
|
||||||
<CFooter fixed={false}>
|
<CFooter fixed={false}>
|
||||||
<div>{t('footer.version')} 0.9.5</div>
|
<div>{t('footer.version')} 0.9.13</div>
|
||||||
<div className="mfs-auto">
|
<div className="mfs-auto">
|
||||||
<span className="mr-1">{t('footer.powered_by')}</span>
|
<span className="mr-1">{t('footer.powered_by')}</span>
|
||||||
<a href="https://coreui.io/react" target="_blank" rel="noopener noreferrer">
|
<a href="https://coreui.io/react" target="_blank" rel="noopener noreferrer">
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import {
|
import {
|
||||||
CHeader,
|
CHeader,
|
||||||
@@ -11,26 +10,27 @@ import {
|
|||||||
CLink,
|
CLink,
|
||||||
CPopover,
|
CPopover,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
import { cilAccountLogout } from '@coreui/icons';
|
import { cilAccountLogout } from '@coreui/icons';
|
||||||
import { logout } from 'utils/authHelper';
|
import { logout } from 'utils/authHelper';
|
||||||
import routes from 'routes';
|
import routes from 'routes';
|
||||||
import LanguageSwitcher from 'components/LanguageSwitcher';
|
import { LanguageSwitcher } from 'ucentral-libs';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
|
||||||
const TheHeader = () => {
|
const TheHeader = ({ showSidebar, setShowSidebar }) => {
|
||||||
const { t, i18n } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const dispatch = useDispatch();
|
const { currentToken, endpoints } = useAuth();
|
||||||
const [translatedRoutes, setTranslatedRoutes] = useState(routes);
|
const [translatedRoutes, setTranslatedRoutes] = useState(routes);
|
||||||
const sidebarShow = useSelector((state) => state.sidebarShow);
|
|
||||||
|
|
||||||
const toggleSidebar = () => {
|
const toggleSidebar = () => {
|
||||||
const val = [true, 'responsive'].includes(sidebarShow) ? false : 'responsive';
|
const val = [true, 'responsive'].includes(showSidebar) ? false : 'responsive';
|
||||||
dispatch({ type: 'set', sidebarShow: val });
|
setShowSidebar(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toggleSidebarMobile = () => {
|
const toggleSidebarMobile = () => {
|
||||||
const val = [false, 'responsive'].includes(sidebarShow) ? true : 'responsive';
|
const val = [false, 'responsive'].includes(showSidebar) ? true : 'responsive';
|
||||||
dispatch({ type: 'set', sidebarShow: val });
|
setShowSidebar(val);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -48,13 +48,18 @@ const TheHeader = () => {
|
|||||||
<CHeaderNav className="d-md-down-none mr-auto" />
|
<CHeaderNav className="d-md-down-none mr-auto" />
|
||||||
|
|
||||||
<CHeaderNav className="px-3">
|
<CHeaderNav className="px-3">
|
||||||
<LanguageSwitcher />
|
<LanguageSwitcher i18n={i18n} />
|
||||||
</CHeaderNav>
|
</CHeaderNav>
|
||||||
|
|
||||||
<CHeaderNav className="px-3">
|
<CHeaderNav className="px-3">
|
||||||
<CPopover content={t('common.logout')}>
|
<CPopover content={t('common.logout')}>
|
||||||
<CLink className="c-subheader-nav-link">
|
<CLink className="c-subheader-nav-link">
|
||||||
<CIcon name="cilAccountLogout" content={cilAccountLogout} size="2xl" onClick={logout} />
|
<CIcon
|
||||||
|
name="cilAccountLogout"
|
||||||
|
content={cilAccountLogout}
|
||||||
|
size="2xl"
|
||||||
|
onClick={() => logout(currentToken, endpoints.ucentralsec)}
|
||||||
|
/>
|
||||||
</CLink>
|
</CLink>
|
||||||
</CPopover>
|
</CPopover>
|
||||||
</CHeaderNav>
|
</CHeaderNav>
|
||||||
@@ -69,4 +74,9 @@ const TheHeader = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TheHeader.propTypes = {
|
||||||
|
showSidebar: PropTypes.string.isRequired,
|
||||||
|
setShowSidebar: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default TheHeader;
|
export default TheHeader;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
import {
|
import {
|
||||||
CCreateElement,
|
CCreateElement,
|
||||||
CSidebar,
|
CSidebar,
|
||||||
@@ -11,14 +10,12 @@ import {
|
|||||||
CSidebarNavDropdown,
|
CSidebarNavDropdown,
|
||||||
CSidebarNavItem,
|
CSidebarNavItem,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import logoBar from 'assets/OpenWiFi_LogoLockup_WhiteColour.svg';
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const TheSidebar = () => {
|
const TheSidebar = ({ showSidebar, setShowSidebar }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const dispatch = useDispatch();
|
|
||||||
const show = useSelector((state) => state.sidebarShow);
|
|
||||||
|
|
||||||
const navigation = [
|
const navigation = [
|
||||||
{
|
{
|
||||||
@@ -30,16 +27,16 @@ const TheSidebar = () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CSidebar show={show} onShowChange={(val) => dispatch({ type: 'set', sidebarShow: val })}>
|
<CSidebar show={showSidebar} onShowChange={(val) => setShowSidebar(val)}>
|
||||||
<CSidebarBrand className="d-md-down-none" to="/devices">
|
<CSidebarBrand className="d-md-down-none" to="/devices">
|
||||||
<img
|
<img
|
||||||
className={[styles.sidebarImgFull, 'c-sidebar-brand-full'].join(' ')}
|
className={[styles.sidebarImgFull, 'c-sidebar-brand-full'].join(' ')}
|
||||||
src={logoBar}
|
src="assets/OpenWiFi_LogoLockup_WhiteColour.svg"
|
||||||
alt="OpenWifi"
|
alt="OpenWifi"
|
||||||
/>
|
/>
|
||||||
<img
|
<img
|
||||||
className={[styles.sidebarImgMinimized, 'c-sidebar-brand-minimized'].join(' ')}
|
className={[styles.sidebarImgMinimized, 'c-sidebar-brand-minimized'].join(' ')}
|
||||||
src={logoBar}
|
src="assets/OpenWiFi_LogoLockup_WhiteColour.svg"
|
||||||
alt="OpenWifi"
|
alt="OpenWifi"
|
||||||
/>
|
/>
|
||||||
</CSidebarBrand>
|
</CSidebarBrand>
|
||||||
@@ -59,4 +56,9 @@ const TheSidebar = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TheSidebar.propTypes = {
|
||||||
|
showSidebar: PropTypes.string.isRequired,
|
||||||
|
setShowSidebar: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default React.memo(TheSidebar);
|
export default React.memo(TheSidebar);
|
||||||
|
|||||||
@@ -1,21 +1,37 @@
|
|||||||
import React from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useSelector } from 'react-redux';
|
import { useTranslation } from 'react-i18next';
|
||||||
import PropTypes from 'prop-types';
|
import { logout } from 'utils/authHelper';
|
||||||
|
import routes from 'routes';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { Header } from 'ucentral-libs';
|
||||||
|
import Sidebar from './Sidebar';
|
||||||
import TheContent from './Content';
|
import TheContent from './Content';
|
||||||
import TheSidebar from './Sidebar';
|
|
||||||
import TheFooter from './Footer';
|
import TheFooter from './Footer';
|
||||||
import TheHeader from './Header';
|
|
||||||
|
|
||||||
const TheLayout = (props) => {
|
const TheLayout = () => {
|
||||||
const { isLoggedIn } = useSelector((state) => state.connected);
|
const [showSidebar, setShowSidebar] = useState('responsive');
|
||||||
if (isLoggedIn) {
|
const { endpoints, currentToken } = useAuth();
|
||||||
return <div>{props.children}</div>;
|
const { t, i18n } = useTranslation();
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className="c-app c-default-layout">
|
<div className="c-app c-default-layout">
|
||||||
<TheSidebar />
|
<Sidebar
|
||||||
|
showSidebar={showSidebar}
|
||||||
|
setShowSidebar={setShowSidebar}
|
||||||
|
t={t}
|
||||||
|
logo="assets/OpenWiFi_LogoLockup_DarkGreyColour.svg"
|
||||||
|
/>
|
||||||
<div className="c-wrapper">
|
<div className="c-wrapper">
|
||||||
<TheHeader />
|
<Header
|
||||||
|
showSidebar={showSidebar}
|
||||||
|
setShowSidebar={setShowSidebar}
|
||||||
|
routes={routes}
|
||||||
|
t={t}
|
||||||
|
i18n={i18n}
|
||||||
|
logout={logout}
|
||||||
|
authToken={currentToken}
|
||||||
|
endpoints={endpoints}
|
||||||
|
/>
|
||||||
<div className="c-body">
|
<div className="c-body">
|
||||||
<TheContent />
|
<TheContent />
|
||||||
</div>
|
</div>
|
||||||
@@ -25,12 +41,4 @@ const TheLayout = (props) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
TheLayout.propTypes = {
|
|
||||||
children: PropTypes.instanceOf(Object),
|
|
||||||
};
|
|
||||||
|
|
||||||
TheLayout.defaultProps = {
|
|
||||||
children: {},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default TheLayout;
|
export default TheLayout;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { CRow, CCol } from '@coreui/react';
|
import { CRow, CCol } from '@coreui/react';
|
||||||
import DeviceHealth from 'components/DeviceHealth';
|
import DeviceHealth from 'components/DeviceHealth';
|
||||||
@@ -7,40 +6,35 @@ import DeviceConfiguration from 'components/DeviceConfiguration';
|
|||||||
import CommandHistory from 'components/CommandHistory';
|
import CommandHistory from 'components/CommandHistory';
|
||||||
import DeviceLogs from 'components/DeviceLogs';
|
import DeviceLogs from 'components/DeviceLogs';
|
||||||
import DeviceStatisticsCard from 'components/InterfaceStatistics';
|
import DeviceStatisticsCard from 'components/InterfaceStatistics';
|
||||||
import DeviceActionCard from '../../components/DeviceActionCard';
|
import DeviceActionCard from 'components/DeviceActionCard';
|
||||||
|
import DeviceStatusCard from 'components/DeviceStatusCard';
|
||||||
|
import { DeviceProvider } from 'contexts/DeviceProvider';
|
||||||
|
|
||||||
const DevicePage = () => {
|
const DevicePage = () => {
|
||||||
const dispatch = useDispatch();
|
|
||||||
|
|
||||||
const { deviceId } = useParams();
|
const { deviceId } = useParams();
|
||||||
const previouslySelectedDeviceId = useSelector((state) => state.selectedDeviceId);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (deviceId && deviceId !== previouslySelectedDeviceId)
|
|
||||||
dispatch({ type: 'set', selectedDeviceId: deviceId });
|
|
||||||
}, [deviceId]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<div className="App">
|
<div className="App">
|
||||||
|
<DeviceProvider serialNumber={deviceId}>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol xs="12" sm="6">
|
<CCol xs="12" sm="6">
|
||||||
<DeviceConfiguration selectedDeviceId={deviceId} />
|
<DeviceStatusCard />
|
||||||
|
<DeviceConfiguration />
|
||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="12" sm="6">
|
<CCol xs="12" sm="6">
|
||||||
<DeviceLogs selectedDeviceId={deviceId} />
|
<DeviceLogs />
|
||||||
<DeviceHealth selectedDeviceId={deviceId} />
|
<DeviceHealth />
|
||||||
<DeviceActionCard selectedDeviceId={deviceId} />
|
<DeviceActionCard />
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
<CRow>
|
<CRow>
|
||||||
<CCol>
|
<CCol>
|
||||||
<DeviceStatisticsCard selectedDeviceId={deviceId} />
|
<DeviceStatisticsCard />
|
||||||
<CommandHistory selectedDeviceId={deviceId} />
|
<CommandHistory />
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
|
</DeviceProvider>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,26 +18,25 @@ import {
|
|||||||
CInvalidFeedback,
|
CInvalidFeedback,
|
||||||
} from '@coreui/react';
|
} from '@coreui/react';
|
||||||
import CIcon from '@coreui/icons-react';
|
import CIcon from '@coreui/icons-react';
|
||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
import { cilUser, cilLockLocked, cilLink } from '@coreui/icons';
|
import { cilUser, cilLockLocked, cilLink } from '@coreui/icons';
|
||||||
import { useDispatch } from 'react-redux';
|
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
import logo from 'assets/OpenWiFi_LogoLockup_DarkGreyColour.svg';
|
import { LanguageSwitcher } from 'ucentral-libs';
|
||||||
import LanguageSwitcher from 'components/LanguageSwitcher';
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const Login = () => {
|
const Login = () => {
|
||||||
const { t } = useTranslation();
|
const { t, i18n } = useTranslation();
|
||||||
const dispatch = useDispatch();
|
const { setCurrentToken, setEndpoints } = useAuth();
|
||||||
const [userId, setUsername] = useState('');
|
const [userId, setUsername] = useState('');
|
||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [gatewayUrl, setGatewayUrl] = useState('');
|
const [uCentralSecUrl, setUCentralSecUrl] = useState('');
|
||||||
const [hadError, setHadError] = useState(false);
|
const [hadError, setHadError] = useState(false);
|
||||||
const [emptyUsername, setEmptyUsername] = useState(false);
|
const [emptyUsername, setEmptyUsername] = useState(false);
|
||||||
const [emptyPassword, setEmptyPassword] = useState(false);
|
const [emptyPassword, setEmptyPassword] = useState(false);
|
||||||
const [emptyGateway, setEmptyGateway] = useState(false);
|
const [emptyGateway, setEmptyGateway] = useState(false);
|
||||||
const [defaultConfig, setDefaultConfig] = useState({
|
const [defaultConfig, setDefaultConfig] = useState({
|
||||||
DEFAULT_GATEWAY_URL: '',
|
DEFAULT_UCENTRALSEC_URL: '',
|
||||||
ALLOW_GATEWAY_CHANGE: true,
|
ALLOW_UCENTRALSEC_CHANGE: true,
|
||||||
});
|
});
|
||||||
const placeholderUrl = 'Gateway URL (ex: https://your-url:port)';
|
const placeholderUrl = 'Gateway URL (ex: https://your-url:port)';
|
||||||
|
|
||||||
@@ -70,7 +69,7 @@ const Login = () => {
|
|||||||
isSuccessful = false;
|
isSuccessful = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gatewayUrl.trim() === '') {
|
if (uCentralSecUrl.trim() === '') {
|
||||||
setEmptyGateway(true);
|
setEmptyGateway(true);
|
||||||
isSuccessful = false;
|
isSuccessful = false;
|
||||||
}
|
}
|
||||||
@@ -78,16 +77,33 @@ const Login = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const SignIn = (credentials) => {
|
const SignIn = (credentials) => {
|
||||||
const gatewayUrlToUse = defaultConfig.ALLOW_GATEWAY_CHANGE
|
let token = '';
|
||||||
? gatewayUrl
|
const finalUCentralSecUrl = defaultConfig.ALLOW_UCENTRALSEC_CHANGE
|
||||||
: defaultConfig.DEFAULT_GATEWAY_URL;
|
? uCentralSecUrl
|
||||||
|
: defaultConfig.DEFAULT_UCENTRALSEC_URL;
|
||||||
|
|
||||||
axiosInstance
|
axiosInstance
|
||||||
.post(`${gatewayUrlToUse}/api/v1/oauth2`, credentials)
|
.post(`${finalUCentralSecUrl}/api/v1/oauth2`, credentials)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
sessionStorage.setItem('gw_url', `${gatewayUrlToUse}/api/v1`);
|
|
||||||
sessionStorage.setItem('access_token', response.data.access_token);
|
sessionStorage.setItem('access_token', response.data.access_token);
|
||||||
dispatch({ type: 'set', connected: true });
|
token = response.data.access_token;
|
||||||
|
return axiosInstance.get(`${finalUCentralSecUrl}/api/v1/systemEndpoints`, {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
Authorization: `Bearer ${response.data.access_token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
const endpoints = {
|
||||||
|
ucentralsec: finalUCentralSecUrl,
|
||||||
|
};
|
||||||
|
for (const endpoint of response.data.endpoints) {
|
||||||
|
endpoints[endpoint.type] = endpoint.uri;
|
||||||
|
}
|
||||||
|
sessionStorage.setItem('gateway_endpoints', JSON.stringify(endpoints));
|
||||||
|
setEndpoints(endpoints);
|
||||||
|
setCurrentToken(token);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setHadError(true);
|
setHadError(true);
|
||||||
@@ -108,12 +124,12 @@ const Login = () => {
|
|||||||
}, [password]);
|
}, [password]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (emptyGateway) setEmptyGateway(false);
|
if (emptyGateway) setEmptyGateway(false);
|
||||||
}, [gatewayUrl]);
|
}, [uCentralSecUrl]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getDefaultConfig();
|
getDefaultConfig();
|
||||||
}, []);
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setGatewayUrl(defaultConfig.DEFAULT_GATEWAY_URL);
|
setUCentralSecUrl(defaultConfig.DEFAULT_UCENTRALSEC_URL);
|
||||||
}, [defaultConfig]);
|
}, [defaultConfig]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -123,7 +139,7 @@ const Login = () => {
|
|||||||
<CCol md="8">
|
<CCol md="8">
|
||||||
<img
|
<img
|
||||||
className={[styles.logo, 'c-sidebar-brand-full'].join(' ')}
|
className={[styles.logo, 'c-sidebar-brand-full'].join(' ')}
|
||||||
src={logo}
|
src="assets/OpenWiFi_LogoLockup_DarkGreyColour.svg"
|
||||||
alt="OpenWifi"
|
alt="OpenWifi"
|
||||||
/>
|
/>
|
||||||
<CCardGroup>
|
<CCardGroup>
|
||||||
@@ -133,7 +149,7 @@ const Login = () => {
|
|||||||
<h1>{t('login.login')}</h1>
|
<h1>{t('login.login')}</h1>
|
||||||
<p className="text-muted">{t('login.sign_in_to_account')}</p>
|
<p className="text-muted">{t('login.sign_in_to_account')}</p>
|
||||||
<CInputGroup className="mb-3">
|
<CInputGroup className="mb-3">
|
||||||
<CPopover content="Username">
|
<CPopover content={t('login.username')}>
|
||||||
<CInputGroupPrepend>
|
<CInputGroupPrepend>
|
||||||
<CInputGroupText>
|
<CInputGroupText>
|
||||||
<CIcon name="cilUser" content={cilUser} />
|
<CIcon name="cilUser" content={cilUser} />
|
||||||
@@ -154,7 +170,7 @@ const Login = () => {
|
|||||||
</CInvalidFeedback>
|
</CInvalidFeedback>
|
||||||
</CInputGroup>
|
</CInputGroup>
|
||||||
<CInputGroup className="mb-4">
|
<CInputGroup className="mb-4">
|
||||||
<CPopover content="Password">
|
<CPopover content={t('login.password')}>
|
||||||
<CInputGroupPrepend>
|
<CInputGroupPrepend>
|
||||||
<CInputGroupText>
|
<CInputGroupText>
|
||||||
<CIcon content={cilLockLocked} />
|
<CIcon content={cilLockLocked} />
|
||||||
@@ -173,8 +189,8 @@ const Login = () => {
|
|||||||
{t('login.please_enter_password')}
|
{t('login.please_enter_password')}
|
||||||
</CInvalidFeedback>
|
</CInvalidFeedback>
|
||||||
</CInputGroup>
|
</CInputGroup>
|
||||||
<CInputGroup className="mb-4" hidden={!defaultConfig.ALLOW_GATEWAY_CHANGE}>
|
<CInputGroup className="mb-4" hidden={!defaultConfig.ALLOW_UCENTRALSEC_CHANGE}>
|
||||||
<CPopover content="Gateway URL">
|
<CPopover content={t('login.url')}>
|
||||||
<CInputGroupPrepend>
|
<CInputGroupPrepend>
|
||||||
<CInputGroupText>
|
<CInputGroupText>
|
||||||
<CIcon name="cilLink" content={cilLink} />
|
<CIcon name="cilLink" content={cilLink} />
|
||||||
@@ -186,9 +202,9 @@ const Login = () => {
|
|||||||
type="text"
|
type="text"
|
||||||
required
|
required
|
||||||
placeholder={placeholderUrl}
|
placeholder={placeholderUrl}
|
||||||
value={gatewayUrl}
|
value={uCentralSecUrl}
|
||||||
autoComplete="gateway-url"
|
autoComplete="gateway-url"
|
||||||
onChange={(event) => setGatewayUrl(event.target.value)}
|
onChange={(event) => setUCentralSecUrl(event.target.value)}
|
||||||
/>
|
/>
|
||||||
<CInvalidFeedback className="help-block">
|
<CInvalidFeedback className="help-block">
|
||||||
{t('login.please_enter_gateway')}
|
{t('login.please_enter_gateway')}
|
||||||
@@ -213,7 +229,7 @@ const Login = () => {
|
|||||||
</CCol>
|
</CCol>
|
||||||
<CCol xs="6">
|
<CCol xs="6">
|
||||||
<div className={styles.languageSwitcher}>
|
<div className={styles.languageSwitcher}>
|
||||||
<LanguageSwitcher />
|
<LanguageSwitcher i18n={i18n} />
|
||||||
</div>
|
</div>
|
||||||
</CCol>
|
</CCol>
|
||||||
</CRow>
|
</CRow>
|
||||||
|
|||||||
26
src/router/index.js
Normal file
26
src/router/index.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { useAuth } from 'contexts/AuthProvider';
|
||||||
|
import { Route } from 'react-router-dom';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const TheLayout = React.lazy(() => import('layout'));
|
||||||
|
const Login = React.lazy(() => import('pages/LoginPage'));
|
||||||
|
|
||||||
|
const Routes = () => {
|
||||||
|
const { currentToken, endpoints } = useAuth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Route
|
||||||
|
path="/"
|
||||||
|
name="Devices"
|
||||||
|
render={(props) =>
|
||||||
|
currentToken !== '' && Object.keys(endpoints).length !== 0 ? (
|
||||||
|
<TheLayout {...props} />
|
||||||
|
) : (
|
||||||
|
<Login {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Routes;
|
||||||
@@ -3,9 +3,7 @@ import React from 'react';
|
|||||||
const DevicePage = React.lazy(() => import('pages/DevicePage'));
|
const DevicePage = React.lazy(() => import('pages/DevicePage'));
|
||||||
const DeviceListPage = React.lazy(() => import('pages/DeviceListPage'));
|
const DeviceListPage = React.lazy(() => import('pages/DeviceListPage'));
|
||||||
|
|
||||||
const routes = [
|
export default [
|
||||||
{ path: '/devices', exact: true, name: 'common.devices', component: DeviceListPage },
|
{ path: '/devices', exact: true, name: 'common.devices', component: DeviceListPage },
|
||||||
{ path: '/devices/:deviceId', name: 'common.device_page', component: DevicePage },
|
{ path: '/devices/:deviceId', name: 'common.device_page', component: DevicePage },
|
||||||
];
|
];
|
||||||
|
|
||||||
export default routes;
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
pre.ignore {
|
pre.ignore {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.custom-select {
|
||||||
|
appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|||||||
19
src/store.js
19
src/store.js
@@ -1,19 +0,0 @@
|
|||||||
import { createStore } from 'redux';
|
|
||||||
|
|
||||||
const initialState = {
|
|
||||||
sidebarShow: 'responsive',
|
|
||||||
connected: false,
|
|
||||||
selectedDeviceId: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const changeState = (state = initialState, { type, ...rest }) => {
|
|
||||||
switch (type) {
|
|
||||||
case 'set':
|
|
||||||
return { ...state, ...rest };
|
|
||||||
default:
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const store = createStore(changeState);
|
|
||||||
export default store;
|
|
||||||
@@ -1,6 +1,19 @@
|
|||||||
export const logout = () => {
|
import axiosInstance from './axiosInstance';
|
||||||
|
|
||||||
|
export const logout = (token, endpoint) => {
|
||||||
|
axiosInstance
|
||||||
|
.delete(`${endpoint}/api/v1/oauth2/${token}`, {
|
||||||
|
headers: {
|
||||||
|
Accept: 'application/json',
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(() => {})
|
||||||
|
.catch(() => {})
|
||||||
|
.finally(() => {
|
||||||
sessionStorage.clear();
|
sessionStorage.clear();
|
||||||
window.location.replace('/');
|
window.location.replace('/');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getToken = () => {
|
export const getToken = () => {
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
import * as axios from 'axios';
|
import * as axios from 'axios';
|
||||||
import axiosRetry from 'axios-retry';
|
import axiosRetry from 'axios-retry';
|
||||||
import http from 'http';
|
|
||||||
import https from 'https';
|
|
||||||
|
|
||||||
const httpAgent = new http.Agent({ keepAlive: true });
|
const axiosInstance = axios.create();
|
||||||
const httpsAgent = new https.Agent({ keepAlive: true });
|
|
||||||
const axiosInstance = axios.create(httpAgent, httpsAgent);
|
|
||||||
|
|
||||||
axiosRetry(axiosInstance, {
|
axiosRetry(axiosInstance, {
|
||||||
retries: 3,
|
retries: 3,
|
||||||
@@ -16,15 +12,6 @@ axiosInstance.defaults.timeout = 30000;
|
|||||||
axiosInstance.defaults.headers.get.Accept = 'application/json';
|
axiosInstance.defaults.headers.get.Accept = 'application/json';
|
||||||
axiosInstance.defaults.headers.post.Accept = 'application/json';
|
axiosInstance.defaults.headers.post.Accept = 'application/json';
|
||||||
|
|
||||||
axiosInstance.interceptors.request.use((config) => {
|
|
||||||
const newConfig = config;
|
|
||||||
const url = sessionStorage.getItem('gw_url');
|
|
||||||
if (url !== undefined && url !== null && !newConfig.url.includes(url)) {
|
|
||||||
newConfig.url = url + newConfig.url;
|
|
||||||
}
|
|
||||||
return newConfig;
|
|
||||||
});
|
|
||||||
|
|
||||||
axiosInstance.interceptors.response.use(
|
axiosInstance.interceptors.response.use(
|
||||||
// Success actions
|
// Success actions
|
||||||
undefined,
|
undefined,
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import { getToken } from 'utils/authHelper';
|
|
||||||
import axiosInstance from 'utils/axiosInstance';
|
import axiosInstance from 'utils/axiosInstance';
|
||||||
|
|
||||||
export default async (deviceId) => {
|
export default async (deviceId, token, endpoint) => {
|
||||||
const options = {
|
const options = {
|
||||||
headers: {
|
headers: {
|
||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
Authorization: `Bearer ${getToken()}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return axiosInstance
|
return axiosInstance
|
||||||
.get(`/device/${encodeURIComponent(deviceId)}/status`, options)
|
.get(`${endpoint}/api/v1/device/${encodeURIComponent(deviceId)}/status`, options)
|
||||||
.then((response) => response.data.connected)
|
.then((response) => response.data.connected)
|
||||||
.catch(() => false);
|
.catch(() => false);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -66,3 +66,47 @@ export const checkIfJson = (string) => {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const secondsToDetailed = (
|
||||||
|
seconds,
|
||||||
|
dayLabel,
|
||||||
|
daysLabel,
|
||||||
|
hourLabel,
|
||||||
|
hoursLabel,
|
||||||
|
minuteLabel,
|
||||||
|
minutesLabel,
|
||||||
|
secondLabel,
|
||||||
|
secondsLabel,
|
||||||
|
) => {
|
||||||
|
if (!seconds || seconds === 0) return `0 ${secondsLabel}`;
|
||||||
|
let secondsLeft = seconds;
|
||||||
|
const days = Math.floor(secondsLeft / (3600 * 24));
|
||||||
|
secondsLeft -= days * (3600 * 24);
|
||||||
|
const hours = Math.floor(secondsLeft / 3600);
|
||||||
|
secondsLeft -= hours * 3600;
|
||||||
|
const minutes = Math.floor(secondsLeft / 60);
|
||||||
|
secondsLeft -= minutes * 60;
|
||||||
|
|
||||||
|
let finalString = '';
|
||||||
|
|
||||||
|
if (days > 0)
|
||||||
|
finalString =
|
||||||
|
days === 1 ? `${finalString}${days} ${dayLabel}, ` : `${finalString}${days} ${daysLabel}, `;
|
||||||
|
if (hours > 0)
|
||||||
|
finalString =
|
||||||
|
hours === 1
|
||||||
|
? `${finalString}${hours} ${hourLabel}, `
|
||||||
|
: `${finalString}${hours} ${hoursLabel}, `;
|
||||||
|
if (minutes > 0)
|
||||||
|
finalString =
|
||||||
|
minutes === 1
|
||||||
|
? `${finalString}${minutes} ${minuteLabel}, `
|
||||||
|
: `${finalString}${minutes} ${minutesLabel}, `;
|
||||||
|
if (secondsLeft > 0)
|
||||||
|
finalString =
|
||||||
|
secondsLeft === 1
|
||||||
|
? `${finalString}${secondsLeft} ${secondLabel}`
|
||||||
|
: `${finalString}${secondsLeft} ${secondsLabel}`;
|
||||||
|
|
||||||
|
return finalString;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user