Initial commit
This commit is contained in:
commit
a589741ec6
33 changed files with 4388 additions and 0 deletions
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
test.js
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
9
README.md
Normal file
9
README.md
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
This is a terminal for citysys project.
|
||||||
|
|
||||||
|
Download the project. Install it with `npm install`.
|
||||||
|
|
||||||
|
Start the project: `npm start`
|
||||||
|
View the project in browser: http://localhost:3000
|
||||||
|
Run tests: `npm test`
|
||||||
|
Build project: `npm run build`
|
||||||
|
|
||||||
BIN
doc/LM Terminal zadanie-1.docx
Normal file
BIN
doc/LM Terminal zadanie-1.docx
Normal file
Binary file not shown.
6
jsconfig.json
Normal file
6
jsconfig.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "src"
|
||||||
|
},
|
||||||
|
"include": ["src"]
|
||||||
|
}
|
||||||
49
package.json
Normal file
49
package.json
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "terminal-oms.app",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@material-ui/core": "^4.11.3",
|
||||||
|
"@material-ui/icons": "^4.11.2",
|
||||||
|
"@testing-library/jest-dom": "^5.11.9",
|
||||||
|
"@testing-library/react": "^11.2.5",
|
||||||
|
"@testing-library/user-event": "^12.7.0",
|
||||||
|
"axios": "^0.21.1",
|
||||||
|
"bitwise": "^2.1.0",
|
||||||
|
"easy-crc": "0.0.2",
|
||||||
|
"lodash.clonedeep": "^4.5.0",
|
||||||
|
"material-ui-icons": "^1.0.0-beta.36",
|
||||||
|
"moment": "^2.29.1",
|
||||||
|
"react": "^17.0.1",
|
||||||
|
"react-animated-list": "^0.1.4",
|
||||||
|
"react-dom": "^17.0.1",
|
||||||
|
"react-draggable": "^4.4.4",
|
||||||
|
"react-redux": "^7.2.2",
|
||||||
|
"react-scripts": "4.0.2",
|
||||||
|
"redux": "^4.0.5",
|
||||||
|
"web-vitals": "^1.1.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "react-scripts start",
|
||||||
|
"build": "react-scripts build",
|
||||||
|
"test": "react-scripts test",
|
||||||
|
"eject": "react-scripts eject"
|
||||||
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": [
|
||||||
|
"react-app"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browserslist": {
|
||||||
|
"production": [
|
||||||
|
">0.2%",
|
||||||
|
"not dead",
|
||||||
|
"not op_mini all"
|
||||||
|
],
|
||||||
|
"development": [
|
||||||
|
"last 1 chrome version",
|
||||||
|
"last 1 firefox version",
|
||||||
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
43
public/index.html
Normal file
43
public/index.html
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<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>React App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
<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>
|
||||||
|
</html>
|
||||||
38
src/App.css
Normal file
38
src/App.css
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
.App {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-logo {
|
||||||
|
height: 40vmin;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
.App-logo {
|
||||||
|
animation: App-logo-spin infinite 20s linear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-header {
|
||||||
|
background-color: #282c34;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: calc(10px + 2vmin);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.App-link {
|
||||||
|
color: #61dafb;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes App-logo-spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
683
src/App.js
Normal file
683
src/App.js
Normal file
|
|
@ -0,0 +1,683 @@
|
||||||
|
import React, { useState, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
|
||||||
|
import Controls from './controls'
|
||||||
|
import Output from './output'
|
||||||
|
|
||||||
|
import Dialog from '@material-ui/core/Dialog';
|
||||||
|
import DialogActions from '@material-ui/core/DialogActions';
|
||||||
|
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||||
|
import DialogContent from '@material-ui/core/DialogContent';
|
||||||
|
import TextField from '@material-ui/core/TextField';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import Box from '@material-ui/core/Box';
|
||||||
|
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||||
|
|
||||||
|
import Tabs from '@material-ui/core/Tabs';
|
||||||
|
import Tab from '@material-ui/core/Tab';
|
||||||
|
|
||||||
|
import AppBar from '@material-ui/core/AppBar';
|
||||||
|
import Toolbar from '@material-ui/core/Toolbar';
|
||||||
|
import CloseIcon from '@material-ui/icons/Close';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
|
||||||
|
import logo from './assets/img/business-manager.svg'
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
import Nodes from './components/nodes/nodes';
|
||||||
|
import Relays from './components/relays/relays';
|
||||||
|
import DB from './util/db/db'
|
||||||
|
import findGetParameterInUrl from './util/findGetParameterInUrl';
|
||||||
|
|
||||||
|
import FormGroup from '@material-ui/core/FormGroup';
|
||||||
|
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||||
|
import Checkbox from '@material-ui/core/Checkbox';
|
||||||
|
|
||||||
|
import Radio from '@material-ui/core/Radio';
|
||||||
|
import RadioGroup from '@material-ui/core/RadioGroup';
|
||||||
|
import FormControl from '@material-ui/core/FormControl';
|
||||||
|
import FormLabel from '@material-ui/core/FormLabel';
|
||||||
|
|
||||||
|
const divOutputStyle = {
|
||||||
|
backgroundColor: 'black',
|
||||||
|
overflow: "auto",
|
||||||
|
alignItems: "left",
|
||||||
|
display: "flex",
|
||||||
|
textAlign: "left",
|
||||||
|
height: "100vh",
|
||||||
|
};
|
||||||
|
|
||||||
|
function TabPanel(props) {
|
||||||
|
const { children, value, index, ...other } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
role="tabpanel"
|
||||||
|
hidden={value !== index}
|
||||||
|
id={`simple-tabpanel-${index}`}
|
||||||
|
aria-labelledby={`simple-tab-${index}`}
|
||||||
|
{...other}
|
||||||
|
>
|
||||||
|
{value === index && (
|
||||||
|
<Box p={3}>
|
||||||
|
<Typography>{children}</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
TabPanel.propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
index: PropTypes.any.isRequired,
|
||||||
|
value: PropTypes.any.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
function a11yProps(index) {
|
||||||
|
return {
|
||||||
|
id: `simple-tab-${index}`,
|
||||||
|
'aria-controls': `simple-tabpanel-${index}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
flexGrow: 1,
|
||||||
|
backgroundColor: theme.palette.background.paper,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const App = (props) => {
|
||||||
|
|
||||||
|
document.title = 'IoT Terminal 2.0.4';
|
||||||
|
// ver 2.0.4 - pridany cct do config.js
|
||||||
|
|
||||||
|
|
||||||
|
const controlsRef = useRef(null);
|
||||||
|
const outputRef = useRef(null);
|
||||||
|
|
||||||
|
const [tabValue, setTabValue] = useState(0);
|
||||||
|
const [loggedIn, setLoggedIn] = useState(false);
|
||||||
|
const [username, setUserName] = useState("");
|
||||||
|
const [password, setPassword] = useState("");
|
||||||
|
const [baseUrl, setBaseUrl] = useState("");
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const [showprogress, setShowprogress] = useState(false);
|
||||||
|
const [showDialog, setShowDialog] = useState(false);
|
||||||
|
const [autoLogin, setAutoLogin] = useState(false);
|
||||||
|
const [formType, setFormType] = useState("");
|
||||||
|
|
||||||
|
// if inputError[key] == null, we disable button so we can not send new settings
|
||||||
|
const [settings, setSettings] = useState({});
|
||||||
|
const [disableButton, setDisableButton] = useState(false);
|
||||||
|
const [inputError, setInputError] = useState({});
|
||||||
|
|
||||||
|
const size = useWindowSize();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
if(username !== "" & password !== "")
|
||||||
|
{
|
||||||
|
login();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [autoLogin, username, password, baseUrl]);
|
||||||
|
|
||||||
|
const validate = (event) =>{
|
||||||
|
|
||||||
|
if(username === "" || password === "") return true;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCloseDialog = () =>{
|
||||||
|
setShowDialog(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCommand = (command) =>{
|
||||||
|
setFormType(command);
|
||||||
|
setShowDialog(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSettingsChange = (event) =>
|
||||||
|
{
|
||||||
|
let { name, value } = event.target;
|
||||||
|
|
||||||
|
if(event.target.type == "number")
|
||||||
|
{
|
||||||
|
if(isNaN(parseInt(value)) || parseInt(value) < 0 )
|
||||||
|
{
|
||||||
|
setDisableButton(true);
|
||||||
|
setInputError({
|
||||||
|
...inputError,
|
||||||
|
[name]: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setDisableButton(false);
|
||||||
|
setInputError({
|
||||||
|
...inputError,
|
||||||
|
[name]: value
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event.target.type == "checkbox")
|
||||||
|
{
|
||||||
|
value = event.target.checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
setSettings({
|
||||||
|
...settings,
|
||||||
|
[name]: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const makeAxiosRequest = (url, table, action, body) =>
|
||||||
|
{
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
let instance = axios.create();
|
||||||
|
instance(url,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'no-cors',
|
||||||
|
data:{
|
||||||
|
hostname: "localhost",
|
||||||
|
table: table,
|
||||||
|
//where: ["error_type", "MANUAL"],
|
||||||
|
action: action,
|
||||||
|
body: body
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
//"Content-Type": "text/html;charset=UTF-8"
|
||||||
|
},
|
||||||
|
withCredentials: false,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
})
|
||||||
|
.then(response => {resolve(response)})
|
||||||
|
.catch(error => {
|
||||||
|
const message = error + "";
|
||||||
|
console.error(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const loadSettings = () =>
|
||||||
|
{
|
||||||
|
let url = baseUrl + `/db`;
|
||||||
|
|
||||||
|
makeAxiosRequest(url, "settings", "read","")
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
|
if(!response.data.success)
|
||||||
|
{
|
||||||
|
//throw response.data.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = response.data;
|
||||||
|
console.log("loadSettings", a);
|
||||||
|
|
||||||
|
setSettings(a[0]);
|
||||||
|
setInputError(a[0]);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const message = error + "";
|
||||||
|
console.error(message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleSetNewSettings = () =>
|
||||||
|
{
|
||||||
|
let url = baseUrl + `/db`;
|
||||||
|
|
||||||
|
makeAxiosRequest(url, "settings", "update", settings)
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
|
if(!response.data.sucess)
|
||||||
|
{
|
||||||
|
//throw response.data.message;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(response.data === 1)
|
||||||
|
// if(response.data.data === 1)
|
||||||
|
{
|
||||||
|
alert("Nove nastavenia uspesne zapisane do databazy")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const message = error + "";
|
||||||
|
console.error(message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const login = (event) =>{
|
||||||
|
|
||||||
|
axios(baseUrl + "/validate",
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'no-cors',
|
||||||
|
data:{
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
withCredentials: false,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
|
||||||
|
if(response.data.valid)
|
||||||
|
{
|
||||||
|
setLoggedIn(true);
|
||||||
|
setShowprogress(false);
|
||||||
|
setError("");
|
||||||
|
|
||||||
|
loadSettings();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setError("Nesprávne meno, alebo heslo");
|
||||||
|
setShowprogress(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const message = error + "";
|
||||||
|
|
||||||
|
setError(message);
|
||||||
|
setShowprogress(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleLogin = (event) =>{
|
||||||
|
|
||||||
|
if(username === "" || password === "")
|
||||||
|
{
|
||||||
|
setError("Nie je zadané meno a heslo");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setShowprogress(true);
|
||||||
|
login();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTabChange = (event, newValue) => {
|
||||||
|
setTabValue(newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = event => {
|
||||||
|
|
||||||
|
if(event.target.name === "username") setUserName(event.target.value);
|
||||||
|
if(event.target.name === "password") setPassword(event.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const buildUi = () =>
|
||||||
|
{
|
||||||
|
if(loggedIn)
|
||||||
|
{
|
||||||
|
let widgets = [];
|
||||||
|
let mainUi = (
|
||||||
|
<Grid container spacing={0}>
|
||||||
|
|
||||||
|
<Grid item xs={12} sm={4}>
|
||||||
|
<div ref={controlsRef} style={{backgroundColor: 'white', textAlign: "left"}}>
|
||||||
|
<Controls handleCommand = {handleCommand} username = {username} password = {password} title = {document.title}/>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={12} sm={8}>
|
||||||
|
<div ref={outputRef} style={divOutputStyle}>
|
||||||
|
<div style ={{padding: "10px", width: "100%"}}>
|
||||||
|
<Output/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
)
|
||||||
|
|
||||||
|
widgets.push(mainUi);
|
||||||
|
|
||||||
|
if(showDialog)
|
||||||
|
{
|
||||||
|
|
||||||
|
// push all data from settings.table to grid
|
||||||
|
let allSettings = [];
|
||||||
|
|
||||||
|
if(settings !== undefined)
|
||||||
|
{
|
||||||
|
Object.keys(settings).forEach(function(key) {
|
||||||
|
// console.log(key, settings[key]);
|
||||||
|
|
||||||
|
if(key == "backup_on_failure" || key == "maintanace_mode")
|
||||||
|
{
|
||||||
|
allSettings.push(
|
||||||
|
(<Grid key={key} item>
|
||||||
|
<FormGroup>
|
||||||
|
<FormControlLabel
|
||||||
|
control={<Checkbox checked={settings[key]} onChange={handleSettingsChange}/>}
|
||||||
|
name={key}
|
||||||
|
label={key}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</Grid>)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if(key == "controller_type")
|
||||||
|
{
|
||||||
|
allSettings.push(
|
||||||
|
(<Grid key={key} item>
|
||||||
|
<FormControl>
|
||||||
|
<FormLabel>{key}</FormLabel>
|
||||||
|
<RadioGroup
|
||||||
|
onChange={handleSettingsChange}
|
||||||
|
row
|
||||||
|
aria-label={key}
|
||||||
|
value={settings[key]}
|
||||||
|
name="controller_type"
|
||||||
|
>
|
||||||
|
<FormControlLabel value="lm" control={<Radio />} label="LM" />
|
||||||
|
<FormControlLabel value="unipi" control={<Radio />} label="Unipi" />
|
||||||
|
</RadioGroup>
|
||||||
|
</FormControl>
|
||||||
|
</Grid>)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else if(['restore_from_backup', 'restore_backup_wait', 'mqtt_port', 'projects_id'].includes(key))
|
||||||
|
{
|
||||||
|
allSettings.push(
|
||||||
|
(<Grid key={key} item>
|
||||||
|
<TextField
|
||||||
|
id={key}
|
||||||
|
label={key}
|
||||||
|
name={key}
|
||||||
|
error={inputError[key] == null? true: false}
|
||||||
|
type="number"
|
||||||
|
value={settings[key]}
|
||||||
|
onChange={handleSettingsChange}
|
||||||
|
helperText={inputError[key] == null? 'Zadaj platné číslo': null}
|
||||||
|
/>
|
||||||
|
</Grid>)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
allSettings.push(
|
||||||
|
(<Grid key={key} item>
|
||||||
|
<TextField
|
||||||
|
id={key}
|
||||||
|
name={key}
|
||||||
|
label={key}
|
||||||
|
onChange={handleSettingsChange}
|
||||||
|
value={settings[key]}
|
||||||
|
/>
|
||||||
|
</Grid>)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let dialog = (
|
||||||
|
<div>
|
||||||
|
<Dialog open={true} fullScreen aria-labelledby="form-dialog-title">
|
||||||
|
|
||||||
|
<AppBar>
|
||||||
|
<Toolbar>
|
||||||
|
<IconButton edge="start" color="inherit" onClick={handleCloseDialog} aria-label="close">
|
||||||
|
<CloseIcon />
|
||||||
|
</IconButton>
|
||||||
|
<Typography variant="h6">
|
||||||
|
Nastavenia FLOW
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
</Toolbar>
|
||||||
|
|
||||||
|
<Tabs value={tabValue} onChange={handleTabChange} aria-label="simple tabs example">
|
||||||
|
<Tab label="Nastavenia" />
|
||||||
|
<Tab label="Zoznam nodov" />
|
||||||
|
<Tab label="Zoznam linii" />
|
||||||
|
</Tabs>
|
||||||
|
</AppBar>
|
||||||
|
|
||||||
|
<DialogTitle id="customized-dialog-title" onClose={handleCloseDialog}>
|
||||||
|
Modal title
|
||||||
|
</DialogTitle>
|
||||||
|
|
||||||
|
<DialogContent>
|
||||||
|
|
||||||
|
<TabPanel style = {{marginTop: 50}} value={tabValue} index={0}>
|
||||||
|
{/* //! tato form robi tuto chybu v konzole: Warning: validateDOMNesting(...): <form> cannot appear as a descendant of <p>. */}
|
||||||
|
<form noValidate autoComplete="off">
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
{allSettings}
|
||||||
|
</Grid>
|
||||||
|
<br></br>
|
||||||
|
<Button
|
||||||
|
onClick={handleSetNewSettings}
|
||||||
|
variant="contained"
|
||||||
|
disabled={disableButton}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Ulož nastavenia
|
||||||
|
</Button>
|
||||||
|
</form>
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel value={tabValue} index={1}>
|
||||||
|
<br/><Nodes/>
|
||||||
|
</TabPanel>
|
||||||
|
<TabPanel value={tabValue} index={2}>
|
||||||
|
<br/><Relays/>
|
||||||
|
</TabPanel>
|
||||||
|
|
||||||
|
</DialogContent>
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button autoFocus onClick={handleCloseDialog} color="primary">
|
||||||
|
Zatvor
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
widgets.push(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
return widgets;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(showprogress)
|
||||||
|
{
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<Dialog open={true} aria-labelledby="form-dialog-title">
|
||||||
|
<Box minWidth="90">
|
||||||
|
<img src={logo} className="App-logo" alt="logo" />
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<DialogContent>
|
||||||
|
|
||||||
|
<div>Prihlasujem...</div>
|
||||||
|
<br></br>
|
||||||
|
|
||||||
|
<CircularProgress />
|
||||||
|
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return loginDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginDialog = () =>
|
||||||
|
{
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Dialog open={true} aria-labelledby="form-dialog-title"
|
||||||
|
|
||||||
|
>
|
||||||
|
<br/><br/>
|
||||||
|
<img style = {{marginTop: "10px", height: "20vmin"}} src={logo} className="App-logo" alt="logo" />
|
||||||
|
|
||||||
|
<DialogContent style={{ overflow: "hidden" }}>
|
||||||
|
|
||||||
|
<Grid container spacing={3}>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<TextField
|
||||||
|
margin="dense"
|
||||||
|
id="username"
|
||||||
|
name="username"
|
||||||
|
label="Prihlasovacie meno"
|
||||||
|
type="text"
|
||||||
|
fullWidth
|
||||||
|
value= {username}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
<div style={{ fontSize: 12, color: "red", textAlign: "left"}}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<TextField
|
||||||
|
margin="dense"
|
||||||
|
id="password"
|
||||||
|
name="password"
|
||||||
|
label="Heslo"
|
||||||
|
type="password"
|
||||||
|
fullWidth
|
||||||
|
value= {password}
|
||||||
|
onChange={handleChange}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<div style={{ fontSize: 12, color: "red", textAlign: "left"}}>
|
||||||
|
{error}
|
||||||
|
</div>
|
||||||
|
<div style={{ fontSize: 12, color: "red", textAlign: "left"}}>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Grid container alignItems="flex-end" spacing={2}>
|
||||||
|
<Grid item sm={12} xs={12}>
|
||||||
|
<Button onClick={handleLogin} color="primary">
|
||||||
|
Prihlásiť
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
{buildUi()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Hook
|
||||||
|
function useWindowSize() {
|
||||||
|
// Initialize state with undefined width/height so server and client renders match
|
||||||
|
// Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
|
||||||
|
|
||||||
|
const [windowSize, setWindowSize] = useState({
|
||||||
|
width: undefined,
|
||||||
|
height: undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
let baseUrl = '';
|
||||||
|
if(window.location.hostname === "localhost")
|
||||||
|
{
|
||||||
|
//baseUrl = "http://localhost:5000";
|
||||||
|
baseUrl = "http://10.0.0.5:5000";
|
||||||
|
}
|
||||||
|
|
||||||
|
setBaseUrl(baseUrl);
|
||||||
|
DB.backendUrl = baseUrl + `/db`;
|
||||||
|
|
||||||
|
let username = findGetParameterInUrl("username");
|
||||||
|
let password = findGetParameterInUrl("password");
|
||||||
|
|
||||||
|
if(username === undefined) username = "";
|
||||||
|
if(username === undefined) username = "";
|
||||||
|
|
||||||
|
if(username !== "" && password !== "")
|
||||||
|
{
|
||||||
|
setUserName(username);
|
||||||
|
setPassword(password);
|
||||||
|
|
||||||
|
setAutoLogin(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Handler to call on window resize
|
||||||
|
function handleResize() {
|
||||||
|
// Set window width/height to state
|
||||||
|
setWindowSize({
|
||||||
|
width: window.innerWidth,
|
||||||
|
height: window.innerHeight,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listener
|
||||||
|
window.addEventListener("resize", handleResize);
|
||||||
|
|
||||||
|
// Call handler right away so state gets updated with initial window size
|
||||||
|
handleResize();
|
||||||
|
|
||||||
|
// Remove event listener on cleanup
|
||||||
|
return () => window.removeEventListener("resize", handleResize);
|
||||||
|
|
||||||
|
}, []); // Empty array ensures that effect is only run on mount
|
||||||
|
|
||||||
|
if(controlsRef.current == null || outputRef == null);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(windowSize.width > 600)
|
||||||
|
{
|
||||||
|
outputRef.current.style.height = "100vh";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outputRef.current.style.height = (windowSize.height - controlsRef.current.clientHeight) + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return windowSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
8
src/App.test.js
Normal file
8
src/App.test.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
test('renders learn react link', () => {
|
||||||
|
render(<App />);
|
||||||
|
const linkElement = screen.getByText(/learn react/i);
|
||||||
|
expect(linkElement).toBeInTheDocument();
|
||||||
|
});
|
||||||
17
src/assets/img/business-manager.svg
Normal file
17
src/assets/img/business-manager.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" ?><svg id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><style type="text/css">
|
||||||
|
.st0{fill:#00B8E9;}
|
||||||
|
.st1{fill:#DCC5A1;}
|
||||||
|
.st2{fill:#EDD9B4;}
|
||||||
|
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#BC9F82;}
|
||||||
|
.st4{fill:#FFFFFF;}
|
||||||
|
.st5{fill:#E5917A;}
|
||||||
|
.st6{fill-rule:evenodd;clip-rule:evenodd;fill:#422F18;}
|
||||||
|
.st7{fill:#342214;}
|
||||||
|
.st8{fill:#3E7EBC;}
|
||||||
|
.st9{fill:#89BCE5;}
|
||||||
|
.st10{fill:#BE1E2D;}
|
||||||
|
.st11{fill:#E6E6E5;}
|
||||||
|
.st12{fill:#1B75BC;}
|
||||||
|
.st13{fill:#314E67;}
|
||||||
|
.st14{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
|
||||||
|
</style><g><path class="st0" d="M83.2,374.5c10-8.9,34.1-27.7,108.8-61.8c0.5-0.2,1-0.5,1.5-0.7l16.7-7.5c0.3-0.1,0.6-0.3,0.9-0.4v20.3 l3.8,32.9c18.1-5.2,41.2-10.7,41.2-10.7l40.4,13.9l4.2-36.2l0-20.2c0.5,0.2,0.9,0.4,1.4,0.6l7.8,3.5c5,2.2,9.7,4.4,14.3,6.5 c9.6,4.4,18.3,8.5,26.2,12.4c51.6,25.3,69.7,39.8,78.3,47.4c3.4,3,6.6,7.8,9.4,13.8c21.2-33.4,33.5-73,33.5-115.5 C471.7,153.6,375.1,57,256,57S40.3,153.6,40.3,272.8c0,42.5,12.3,82.1,33.5,115.5C76.7,382.3,79.8,377.6,83.2,374.5z"/><path class="st1" d="M211.2,222.1v102.4c12.3,14.6,28.6,22.1,44.8,22.3V180.6C233.6,180.6,211.2,194.4,211.2,222.1z"/><path class="st2" d="M256,180.6v166.1c16.3,0.1,32.5-7.2,44.8-22.3V222.1C300.8,194.4,278.4,180.6,256,180.6z"/><path class="st3" d="M300.8,220.2v65.5c-17,11.8-33.3,18.4-44.8,18.4c-11.5,0-27.9-6.6-44.8-18.4v-65.5 C211.2,167.4,300.8,167.4,300.8,220.2"/><path class="st4" d="M204.4,219.2c0,0,43.6,14.7,98.4,0C302.8,219.2,262,268.6,204.4,219.2"/><path class="st5" d="M204.4,219.2c0,0,45.5,15.8,98.4,0C271.2,217.6,277.8,216,204.4,219.2"/><path class="st5" d="M204.4,219.2c0,0,48.6,47.1,98.4,0c0,0-10.7,34.1-46.7,34.2C220.1,253.6,204.4,219.2,204.4,219.2"/><g><path class="st1" d="M256,38.3c-91.4,0-107.3,67.1-103.5,123c-4-3.4-8.3-4.9-12.1-3.6c-7.9,2.6-10.7,15.8-6.2,29.4 c4.5,13.7,14.5,22.6,22.4,20c1-0.3,2-0.9,2.8-1.6c3.7,15.1,7.9,25.9,10,29c10.8,16,62.2,58.3,86.5,58.3h0L256,38.3L256,38.3z"/><path class="st2" d="M371.3,157.7c-3.7-1.2-7.9,0.1-11.7,3.3c3.7-55.9-12.3-122.7-103.6-122.7v254.6c24.3,0,75.7-42.3,86.5-58.3 c2.1-3.1,6.2-13.8,9.9-28.7c0.8,0.6,1.6,1,2.5,1.3c7.9,2.6,18-6.4,22.4-20C381.9,173.5,379.2,160.3,371.3,157.7z"/></g><path class="st6" d="M187.2,99.1c-8.7,47.7-30.6,43.2-28.9,99.2c-7-43.6-17.5-101.7,12.1-139.9c23.7-30.6,102.2-52.4,153-15.8 c56.1,12,38.6,126.3,31.1,147.9c-5.3-35-17-49.6-31.9-90.7C302.5,114.3,213.1,117.5,187.2,99.1"/><g><path class="st7" d="M212.9,158.6c5.8,0,10.6,5.4,10.6,12c0,6.6-4.7,12-10.6,12c-5.8,0-10.6-5.4-10.6-12 C202.3,163.9,207,158.6,212.9,158.6"/><path class="st7" d="M298.7,158.6c5.8,0,10.6,5.4,10.6,12c0,6.6-4.7,12-10.6,12c-5.8,0-10.6-5.4-10.6-12 C288.2,163.9,292.9,158.6,298.7,158.6"/><path class="st4" d="M234,234.5c3.8,8.3,12.1,14.1,21.8,14.1c9.7,0,18.1-5.8,21.8-14.1H234z"/></g><path class="st8" d="M193.5,312l16.7-7.5C204.5,307.1,198.9,309.6,193.5,312z"/><path class="st8" d="M302.2,304.8l7.8,3.5C307.5,307.1,304.9,306,302.2,304.8z"/><path class="st9" d="M192,312.7L192,312.7c0.5-0.2,1-0.5,1.5-0.7L192,312.7z"/><path class="st9" d="M211.2,304.1l-0.9,0.4C210.6,304.4,210.9,304.2,211.2,304.1L211.2,304.1z"/><path class="st9" d="M324.2,314.6l-14.2-6.3c5,2.2,9.7,4.4,14.3,6.5L324.2,314.6z"/><path class="st9" d="M300.8,304.2L300.8,304.2c0.5,0.2,0.9,0.4,1.4,0.6L300.8,304.2z"/><polygon class="st10" points="256,488.5 256,488.5 256,488.5 "/><path class="st8" d="M137.1,452.8c1.2-9.4,2-15.2,2-15.2s0,6.2,0,16.5c15.7,10.2,32.9,18.3,51.1,24.2l-29.9-60.7l35.2-23.5 l-43-20.1l39.5-61.3c-74.7,34.1-98.8,52.9-108.8,61.8c-3.4,3-6.6,7.8-9.4,13.8C90.1,414,111.7,436,137.1,452.8z"/><path class="st8" d="M428.8,374.5c-8.5-7.6-26.7-22.1-78.3-47.4c-7.9-3.9-16.6-8-26.2-12.4l35,59.3l-43,20.1l35.2,23.5l-29.9,60.8 c18.3-5.8,35.5-14,51.3-24.2c0-10.3,0-16.5,0-16.5s0.8,5.7,2,15.2c25.4-16.8,47-38.8,63.3-64.5 C435.3,382.3,432.2,377.6,428.8,374.5z"/><path class="st11" d="M230,486.9l0.1,1.1c0.9,0,1.7,0.1,2.6,0.1l0.1-0.8C231.9,487.2,231,487.1,230,486.9z"/><path class="st11" d="M230,486.9c0.9,0.1,1.9,0.2,2.8,0.3l14.7-103l-12-16.6l20.6-21c0,0-23.1,5.5-41.2,10.7L230,486.9z"/><path class="st11" d="M279.2,487.3l0.1,0.8c0.8,0,1.6-0.1,2.4-0.1l0.1-1C280.9,487.1,280,487.2,279.2,487.3z"/><path class="st11" d="M256.2,346.7l19.9,21l-11.8,16.6h0l14.7,103c0.9-0.1,1.8-0.2,2.7-0.3l14.8-126.4L256.2,346.7z"/><path class="st9" d="M215,357.4l-3.8-32.9v-20.3c-0.3,0.1-0.6,0.3-0.9,0.4l-16.7,7.5c-0.5,0.2-1,0.5-1.5,0.7L152.5,374l43,20.1 l-35.2,23.5l29.9,60.7c8.4,2.7,17,4.9,25.8,6.5c4.6,0.9,9.3,1.6,14,2.2L215,357.4z"/><path class="st9" d="M359.3,374l-35-59.3c-4.6-2.1-9.3-4.3-14.3-6.5l-7.8-3.5c-0.5-0.2-0.9-0.4-1.4-0.6l0,20.2l-4.2,36.2L281.8,487 c7.2-0.9,14.3-2.1,21.3-3.6c6.3-1.4,12.4-3.1,18.5-5l29.9-60.8l-35.2-23.5L359.3,374z"/><path class="st12" d="M264.4,384.3L264.4,384.3l11.8-16.6l-19.9-21l-20.6,21l12,16.6l-14.7,103c7.6,0.8,15.3,1.2,23.1,1.2 c0,0,0,0,0,0c7.8,0,15.5-0.4,23.1-1.2L264.4,384.3z"/><path class="st13" d="M137.1,452.8c0.7,0.4,1.3,0.9,2,1.3c0-10.3,0-16.5,0-16.5S138.3,443.3,137.1,452.8z"/><path class="st13" d="M372.9,454.1c0.7-0.4,1.3-0.9,2-1.3c-1.2-9.4-2-15.2-2-15.2S373,443.8,372.9,454.1z"/><polygon class="st14" points="211.2,290.6 207.2,305.8 218.2,385.2 256.2,346.7 "/><polygon class="st14" points="300.8,290.6 303.9,305.6 293.6,386 256.2,346.7 "/></g></svg>
|
||||||
|
After Width: | Height: | Size: 5.3 KiB |
110
src/components/AlertDialog/AlertDialog.js
Normal file
110
src/components/AlertDialog/AlertDialog.js
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import Dialog from '@material-ui/core/Dialog';
|
||||||
|
import DialogActions from '@material-ui/core/DialogActions';
|
||||||
|
import DialogContent from '@material-ui/core/DialogContent';
|
||||||
|
import DialogContentText from '@material-ui/core/DialogContentText';
|
||||||
|
import DialogTitle from '@material-ui/core/DialogTitle';
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
import Draggable from 'react-draggable';
|
||||||
|
|
||||||
|
import WarningIcon from '@material-ui/icons/Warning';
|
||||||
|
import { green } from '@material-ui/core/colors';
|
||||||
|
import { red } from '@material-ui/core/colors';
|
||||||
|
import { blue } from '@material-ui/core/colors';
|
||||||
|
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem';
|
||||||
|
|
||||||
|
import ListItemText from '@material-ui/core/ListItemText';
|
||||||
|
import ListItem from '@material-ui/core/ListItem';
|
||||||
|
import List from '@material-ui/core/List';
|
||||||
|
import Divider from '@material-ui/core/Divider';
|
||||||
|
|
||||||
|
function PaperComponent(props) {
|
||||||
|
return (
|
||||||
|
<Draggable handle="#draggable-dialog-title" cancel={'[class*="MuiDialogContent-root"]'}>
|
||||||
|
<Paper {...props} />
|
||||||
|
</Draggable>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function AlertDialog(props) {
|
||||||
|
const [open, setOpen] = React.useState(props.open);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOpen(props.open);
|
||||||
|
}, [props.open])
|
||||||
|
|
||||||
|
const handleClickOpen = () => {
|
||||||
|
//setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
//setOpen(false);
|
||||||
|
props.onConfirm();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
PaperComponent={PaperComponent}
|
||||||
|
aria-labelledby="draggable-dialog-title"
|
||||||
|
aria-describedby="alert-dialog-description"
|
||||||
|
>
|
||||||
|
<DialogTitle style={{ cursor: 'move' }} id="draggable-dialog-title">
|
||||||
|
|
||||||
|
<MenuItem>
|
||||||
|
<ListItemIcon>
|
||||||
|
<WarningIcon fontSize="large" style={{ color: red[500] }} />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">{props.title}</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
|
||||||
|
</DialogTitle>
|
||||||
|
|
||||||
|
{
|
||||||
|
Array.isArray(props.content)
|
||||||
|
?
|
||||||
|
(
|
||||||
|
<List>
|
||||||
|
{
|
||||||
|
props.content.map((message) => (
|
||||||
|
<>
|
||||||
|
<ListItem button>
|
||||||
|
<ListItemText primary={message} secondary="" />
|
||||||
|
</ListItem>
|
||||||
|
<Divider />
|
||||||
|
</>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</List>
|
||||||
|
)
|
||||||
|
:
|
||||||
|
(
|
||||||
|
<DialogContent>
|
||||||
|
<DialogContentText id="alert-dialog-description">
|
||||||
|
{props.content}
|
||||||
|
</DialogContentText>
|
||||||
|
</DialogContent>)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={handleClose} color="primary">
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleClose} color="primary" autoFocus>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
106
src/components/nodes/menu.js
Normal file
106
src/components/nodes/menu.js
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
import Menu from '@material-ui/core/Menu';
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem';
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||||
|
|
||||||
|
import MenuList from '@material-ui/core/MenuList';
|
||||||
|
import { grey } from '@material-ui/core/colors';
|
||||||
|
import { green } from '@material-ui/core/colors';
|
||||||
|
import { red } from '@material-ui/core/colors';
|
||||||
|
import { blue } from '@material-ui/core/colors';
|
||||||
|
|
||||||
|
import AddCircleIcon from '@material-ui/icons/AddCircle';
|
||||||
|
import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
|
||||||
|
import EditIcon from '@material-ui/icons/Edit';
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
|
||||||
|
|
||||||
|
const StyledMenu = withStyles({
|
||||||
|
paper: {
|
||||||
|
border: '1px solid #d3d4d5',
|
||||||
|
},
|
||||||
|
})((props) => (
|
||||||
|
<Menu
|
||||||
|
elevation={0}
|
||||||
|
getContentAnchorEl={null}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
/*
|
||||||
|
const StyledMenuItem = withStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
'&:focus': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
|
||||||
|
color: theme.palette.common.white,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))(MenuItem);
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function CustomizedMenus(props) {
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState(props.anchorref);
|
||||||
|
|
||||||
|
const handleClick = (event, menu) => {
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
props.menuClicked(menu);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
props.menuClosed();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<StyledMenu
|
||||||
|
id="customized-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={handleClose}
|
||||||
|
>
|
||||||
|
<MenuList open={Boolean(anchorEl)} id="menu-list-grow" >
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "add")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<AddCircleIcon style={{ color: green[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">pridať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "edit")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<EditIcon style={{ color: blue[300] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">editovat</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "delete")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<DeleteForeverIcon style={{ color: red[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">zmazať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "exit")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<ExitToAppIcon style={{ color: grey[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">logout</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</StyledMenu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
207
src/components/nodes/nodes.js
Normal file
207
src/components/nodes/nodes.js
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import TableDb from 'components/table/tableDb';
|
||||||
|
//import TableDb from '../table/tableDb';
|
||||||
|
import DB from "util/db/db";
|
||||||
|
//import { LogicOperator } from '../../util/db/SqlQueryBuilder';
|
||||||
|
|
||||||
|
//import Find from './find';
|
||||||
|
//import Form from './form';
|
||||||
|
import CustomizedMenus from './menu'
|
||||||
|
|
||||||
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||||
|
|
||||||
|
//import Card from "components/Card/Card.js";
|
||||||
|
//import CardBody from "components/Card/CardBody.js";
|
||||||
|
//import CardHeader from "components/Card/CardHeader.js";
|
||||||
|
|
||||||
|
import Card from '@material-ui/core/Card';
|
||||||
|
import CardContent from '@material-ui/core/CardContent';
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import AddIcon from '@material-ui/icons/Add';
|
||||||
|
import EditIcon from '@material-ui/icons/Edit';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
|
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
|
||||||
|
//-----------------------------------------------------
|
||||||
|
|
||||||
|
class Nodes extends TableDb {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.title = "Zoznam nodov";
|
||||||
|
this.dbTable = "nodes";
|
||||||
|
|
||||||
|
this.state.columns = ["actions", "node", "tbname", "line", "status"];
|
||||||
|
this.state.visibleColumns = ["actions", "node", "tbname", "line", "status"];
|
||||||
|
|
||||||
|
this.renamedColumns = {
|
||||||
|
node: "node",
|
||||||
|
note: "poznámka",
|
||||||
|
num: "počet",
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
menuClicked(menu)
|
||||||
|
{
|
||||||
|
if(menu === "delete")
|
||||||
|
{
|
||||||
|
if(this.selectedRows.length === 0)
|
||||||
|
{
|
||||||
|
this.menuClosed();
|
||||||
|
this.showAlertDialog("Mazanie", "Nie sú označené žiadne riadky");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = window.confirm("Naozaj chcete zmazať?");
|
||||||
|
if (r === false) return;
|
||||||
|
|
||||||
|
let db = new DB();
|
||||||
|
db.dbStartTransaction();
|
||||||
|
|
||||||
|
//default - odstranit z subject
|
||||||
|
let conditions = {"id": this.id};
|
||||||
|
db.dbDelete(this.getTableName(false), conditions);
|
||||||
|
db.dbCommitTransaction();
|
||||||
|
|
||||||
|
let index = this.index;
|
||||||
|
|
||||||
|
db.exec().then(
|
||||||
|
result => {
|
||||||
|
this.deleteRow(index);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
this.showAlertDialog("Chyba", error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(menu === "exit")
|
||||||
|
{
|
||||||
|
this.props.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
let processed = super.menuClicked(menu);
|
||||||
|
if(processed) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableName(withView = false)
|
||||||
|
{
|
||||||
|
//if(withView) return "view_subject";
|
||||||
|
//return this.dbTable;
|
||||||
|
return this.dbTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add or edit
|
||||||
|
/*
|
||||||
|
renderForm()
|
||||||
|
{
|
||||||
|
let data = undefined;
|
||||||
|
if(this.state.data == null);
|
||||||
|
else data = this.state.data[this.index];
|
||||||
|
|
||||||
|
//getIndex
|
||||||
|
//console.log(data);alert();
|
||||||
|
|
||||||
|
let status = TableDb.TABLE_STATUS.EDIT;
|
||||||
|
if(data === undefined)
|
||||||
|
{
|
||||||
|
data = {};
|
||||||
|
status = TableDb.TABLE_STATUS.ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
handleBack={this.handleBack.bind(this)}
|
||||||
|
data = {data}
|
||||||
|
status = {status}
|
||||||
|
parent_id = {this.state.parent_id}
|
||||||
|
ui = {this.state.ui}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
renderUiTable()
|
||||||
|
{
|
||||||
|
return(
|
||||||
|
<Card>
|
||||||
|
|
||||||
|
<CardContent>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Paper style = {{backgroundColor: "#7bd753", padding: 10}} elevation={3}>
|
||||||
|
|
||||||
|
<Grid container justify="space-between">
|
||||||
|
|
||||||
|
<Typography display="inline" variant="body1" align="left">
|
||||||
|
|
||||||
|
<Tooltip title="zobraz menu" arrow>
|
||||||
|
<Button
|
||||||
|
ref={this.anchorMenuRef}
|
||||||
|
aria-controls={this.state.openMenu ? 'menu-list-grow' : undefined}
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={this.handleToggleMenu.bind(this)}
|
||||||
|
startIcon={<MoreVertIcon />}
|
||||||
|
>
|
||||||
|
{this.title}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
{this.renderCancelFilterIcon()}
|
||||||
|
|
||||||
|
<IconButton onClick={() => this.menuClicked("edit")} aria-label="search" color="inherit">
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography display="inline" variant="body1" align="right">
|
||||||
|
<Tooltip title="pridaj" arrow>
|
||||||
|
<IconButton onClick={() => this.menuClicked("add")} aria-label="search" color="inherit">
|
||||||
|
<AddIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Typography>
|
||||||
|
<Button>Csv</Button>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{this.renderTable()}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUiForm()
|
||||||
|
{
|
||||||
|
return this.renderForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMenu()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<CustomizedMenus
|
||||||
|
anchorref={this.anchorMenuRef.current}
|
||||||
|
menuClicked = {this.menuClicked.bind(this)}
|
||||||
|
menuClosed = {this.menuClosed.bind(this)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Nodes;
|
||||||
106
src/components/relays/menu.js
Normal file
106
src/components/relays/menu.js
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
import Menu from '@material-ui/core/Menu';
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem';
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||||
|
|
||||||
|
import MenuList from '@material-ui/core/MenuList';
|
||||||
|
import { grey } from '@material-ui/core/colors';
|
||||||
|
import { green } from '@material-ui/core/colors';
|
||||||
|
import { red } from '@material-ui/core/colors';
|
||||||
|
import { blue } from '@material-ui/core/colors';
|
||||||
|
|
||||||
|
import AddCircleIcon from '@material-ui/icons/AddCircle';
|
||||||
|
import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
|
||||||
|
import EditIcon from '@material-ui/icons/Edit';
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import ExitToAppIcon from '@material-ui/icons/ExitToApp';
|
||||||
|
|
||||||
|
const StyledMenu = withStyles({
|
||||||
|
paper: {
|
||||||
|
border: '1px solid #d3d4d5',
|
||||||
|
},
|
||||||
|
})((props) => (
|
||||||
|
<Menu
|
||||||
|
elevation={0}
|
||||||
|
getContentAnchorEl={null}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
/*
|
||||||
|
const StyledMenuItem = withStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
'&:focus': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
|
||||||
|
color: theme.palette.common.white,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))(MenuItem);
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function CustomizedMenus(props) {
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState(props.anchorref);
|
||||||
|
|
||||||
|
const handleClick = (event, menu) => {
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
props.menuClicked(menu);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
props.menuClosed();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<StyledMenu
|
||||||
|
id="customized-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={handleClose}
|
||||||
|
>
|
||||||
|
<MenuList open={Boolean(anchorEl)} id="menu-list-grow" >
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "add")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<AddCircleIcon style={{ color: green[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">pridať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "edit")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<EditIcon style={{ color: blue[300] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">editovat</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "delete")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<DeleteForeverIcon style={{ color: red[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">zmazať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "exit")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<ExitToAppIcon style={{ color: grey[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">logout</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</StyledMenu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
208
src/components/relays/relays.js
Normal file
208
src/components/relays/relays.js
Normal file
|
|
@ -0,0 +1,208 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import TableDb from 'components/table/tableDb';
|
||||||
|
//import TableDb from '../table/tableDb';
|
||||||
|
import DB from "util/db/db";
|
||||||
|
//import { LogicOperator } from '../../util/db/SqlQueryBuilder';
|
||||||
|
|
||||||
|
//import Find from './find';
|
||||||
|
//import Form from './form';
|
||||||
|
import CustomizedMenus from './menu'
|
||||||
|
|
||||||
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||||
|
|
||||||
|
//import Card from "components/Card/Card.js";
|
||||||
|
//import CardBody from "components/Card/CardBody.js";
|
||||||
|
//import CardHeader from "components/Card/CardHeader.js";
|
||||||
|
|
||||||
|
import Card from '@material-ui/core/Card';
|
||||||
|
import CardContent from '@material-ui/core/CardContent';
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import AddIcon from '@material-ui/icons/Add';
|
||||||
|
import EditIcon from '@material-ui/icons/Edit';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
|
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
|
||||||
|
//-----------------------------------------------------
|
||||||
|
|
||||||
|
class Relays extends TableDb {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.title = "Zoznam línií";
|
||||||
|
this.dbTable = "relays";
|
||||||
|
|
||||||
|
//node:number|tbname:string|line:number|profile:string|processed:boolean|status:boolean
|
||||||
|
|
||||||
|
this.state.columns = ["actions", "line", "tbname", "contactor"];
|
||||||
|
this.state.visibleColumns = ["actions", "line", "tbname", "contactor"];
|
||||||
|
|
||||||
|
this.renamedColumns = {
|
||||||
|
line: "línia",
|
||||||
|
contactor: "spínač",
|
||||||
|
tbname: "tbname",
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
menuClicked(menu)
|
||||||
|
{
|
||||||
|
if(menu === "delete")
|
||||||
|
{
|
||||||
|
if(this.selectedRows.length === 0)
|
||||||
|
{
|
||||||
|
this.menuClosed();
|
||||||
|
this.showAlertDialog("Mazanie", "Nie sú označené žiadne riadky");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var r = window.confirm("Naozaj chcete zmazať?");
|
||||||
|
if (r === false) return;
|
||||||
|
|
||||||
|
let db = new DB();
|
||||||
|
db.dbStartTransaction();
|
||||||
|
|
||||||
|
//default - odstranit z subject
|
||||||
|
let conditions = {"id": this.id};
|
||||||
|
db.dbDelete(this.getTableName(false), conditions);
|
||||||
|
db.dbCommitTransaction();
|
||||||
|
|
||||||
|
let index = this.index;
|
||||||
|
|
||||||
|
db.exec().then(
|
||||||
|
result => {
|
||||||
|
this.deleteRow(index);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
console.log(error);
|
||||||
|
this.showAlertDialog("Chyba", error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(menu === "exit")
|
||||||
|
{
|
||||||
|
this.props.logout();
|
||||||
|
}
|
||||||
|
|
||||||
|
let processed = super.menuClicked(menu);
|
||||||
|
if(processed) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableName(withView = false)
|
||||||
|
{
|
||||||
|
//if(withView) return "view_subject";
|
||||||
|
//return this.dbTable;
|
||||||
|
return this.dbTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add or edit
|
||||||
|
/*
|
||||||
|
renderForm()
|
||||||
|
{
|
||||||
|
let data = undefined;
|
||||||
|
if(this.state.data == null);
|
||||||
|
else data = this.state.data[this.index];
|
||||||
|
|
||||||
|
//getIndex
|
||||||
|
//console.log(data);alert();
|
||||||
|
|
||||||
|
let status = TableDb.TABLE_STATUS.EDIT;
|
||||||
|
if(data === undefined)
|
||||||
|
{
|
||||||
|
data = {};
|
||||||
|
status = TableDb.TABLE_STATUS.ADD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form
|
||||||
|
handleBack={this.handleBack.bind(this)}
|
||||||
|
data = {data}
|
||||||
|
status = {status}
|
||||||
|
parent_id = {this.state.parent_id}
|
||||||
|
ui = {this.state.ui}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
renderUiTable()
|
||||||
|
{
|
||||||
|
return(
|
||||||
|
<Card>
|
||||||
|
|
||||||
|
<CardContent>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Paper style = {{backgroundColor: "#7bd753", padding: 10}} elevation={3}>
|
||||||
|
|
||||||
|
<Grid container justify="space-between">
|
||||||
|
|
||||||
|
<Typography display='inline' variant="body1" align="left">
|
||||||
|
|
||||||
|
<Tooltip title="zobraz menu" arrow>
|
||||||
|
<Button
|
||||||
|
ref={this.anchorMenuRef}
|
||||||
|
aria-controls={this.state.openMenu ? 'menu-list-grow' : undefined}
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={this.handleToggleMenu.bind(this)}
|
||||||
|
startIcon={<MoreVertIcon />}
|
||||||
|
>
|
||||||
|
{this.title}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
{this.renderCancelFilterIcon()}
|
||||||
|
|
||||||
|
<IconButton onClick={() => this.menuClicked("edit")} aria-label="search" color="inherit">
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Typography display='inline' variant="body1" align="right">
|
||||||
|
<Tooltip title="pridaj" arrow>
|
||||||
|
<IconButton onClick={() => this.menuClicked("add")} aria-label="search" color="inherit">
|
||||||
|
<AddIcon />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{this.renderTable()}
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUiForm()
|
||||||
|
{
|
||||||
|
return this.renderForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMenu()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<CustomizedMenus
|
||||||
|
anchorref={this.anchorMenuRef.current}
|
||||||
|
menuClicked = {this.menuClicked.bind(this)}
|
||||||
|
menuClosed = {this.menuClosed.bind(this)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Relays;
|
||||||
106
src/components/table/menu.js
Normal file
106
src/components/table/menu.js
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
/* default menu */
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { withStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
import Menu from '@material-ui/core/Menu';
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem';
|
||||||
|
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
||||||
|
|
||||||
|
import MenuList from '@material-ui/core/MenuList';
|
||||||
|
import { green } from '@material-ui/core/colors';
|
||||||
|
import { red } from '@material-ui/core/colors';
|
||||||
|
import { blue } from '@material-ui/core/colors';
|
||||||
|
|
||||||
|
import AddCircleIcon from '@material-ui/icons/AddCircle';
|
||||||
|
import DeleteForeverIcon from '@material-ui/icons/DeleteForever';
|
||||||
|
import EditIcon from '@material-ui/icons/Edit';
|
||||||
|
import SearchIcon from '@material-ui/icons/Search';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
|
||||||
|
const StyledMenu = withStyles({
|
||||||
|
paper: {
|
||||||
|
border: '1px solid #d3d4d5',
|
||||||
|
},
|
||||||
|
})((props) => (
|
||||||
|
<Menu
|
||||||
|
elevation={0}
|
||||||
|
getContentAnchorEl={null}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'center',
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
|
||||||
|
/*
|
||||||
|
const StyledMenuItem = withStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
'&:focus': {
|
||||||
|
backgroundColor: theme.palette.primary.main,
|
||||||
|
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
|
||||||
|
color: theme.palette.common.white,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))(MenuItem);
|
||||||
|
*/
|
||||||
|
|
||||||
|
export default function CustomizedMenus(props) {
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState(props.anchorref);
|
||||||
|
|
||||||
|
const handleClick = (event, menu) => {
|
||||||
|
setAnchorEl(event.currentTarget);
|
||||||
|
props.menuClicked(menu);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
props.menuClosed();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<StyledMenu
|
||||||
|
id="customized-menu"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={handleClose}
|
||||||
|
>
|
||||||
|
<MenuList open={Boolean(anchorEl)} id="menu-list-grow" >
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "add")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<AddCircleIcon style={{ color: green[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">pridať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "edit")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<EditIcon style={{ color: blue[300] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">editovať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "delete")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<DeleteForeverIcon style={{ color: red[500] }} fontSize="small" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">zmazať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem onClick={(event)=>handleClick(event, "find")}>
|
||||||
|
<ListItemIcon>
|
||||||
|
<SearchIcon style={{ color: blue[200] }} fontSize="default" />
|
||||||
|
</ListItemIcon>
|
||||||
|
<Typography variant="inherit">hľadať</Typography>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</StyledMenu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
401
src/components/table/table.js
Normal file
401
src/components/table/table.js
Normal file
|
|
@ -0,0 +1,401 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { withStyles, makeStyles } from '@material-ui/core/styles';
|
||||||
|
import Paper from '@material-ui/core/Paper';
|
||||||
|
import Table from '@material-ui/core/Table';
|
||||||
|
import TableBody from '@material-ui/core/TableBody';
|
||||||
|
import TableCell from '@material-ui/core/TableCell';
|
||||||
|
import TableContainer from '@material-ui/core/TableContainer';
|
||||||
|
import TableHead from '@material-ui/core/TableHead';
|
||||||
|
import TablePagination from '@material-ui/core/TablePagination';
|
||||||
|
import TableRow from '@material-ui/core/TableRow';
|
||||||
|
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import CircularProgress from '@material-ui/core/CircularProgress';
|
||||||
|
import FormControlLabel from '@material-ui/core/FormControlLabel';
|
||||||
|
import Switch from '@material-ui/core/Switch';
|
||||||
|
|
||||||
|
import { blue } from '@material-ui/core/colors';
|
||||||
|
|
||||||
|
import TableSortLabel from '@material-ui/core/TableSortLabel';
|
||||||
|
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import EditIcon from '@material-ui/icons/Edit';
|
||||||
|
import DeleteIcon from '@material-ui/icons/Delete';
|
||||||
|
|
||||||
|
let sorted = [];
|
||||||
|
|
||||||
|
function getMaxHeight(isMobile = true)
|
||||||
|
{
|
||||||
|
let h = window.innerHeight - 250;
|
||||||
|
if(!isMobile) h = h - 40;//setDense widget
|
||||||
|
|
||||||
|
if(h < 200) h = 200;
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles({
|
||||||
|
root: {
|
||||||
|
width: '100%'
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
maxHeight: getMaxHeight(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const StyledTableCell = withStyles((theme) => ({
|
||||||
|
head: {
|
||||||
|
backgroundColor: '#6bb7fd',
|
||||||
|
color: theme.palette.common.white,
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
fontSize: 14,
|
||||||
|
},
|
||||||
|
}))(TableCell);
|
||||||
|
|
||||||
|
const StyledTableRow = withStyles((theme) => ({
|
||||||
|
root: {
|
||||||
|
'&:nth-of-type(even)': {
|
||||||
|
backgroundColor: 'gainsboro',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}))(TableRow);
|
||||||
|
|
||||||
|
|
||||||
|
function descendingComparator(a, b, orderBy) {
|
||||||
|
if (b[orderBy] < a[orderBy]) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (b[orderBy] > a[orderBy]) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getComparator(order, orderBy) {
|
||||||
|
return order === 'desc'
|
||||||
|
? (a, b) => descendingComparator(a, b, orderBy)
|
||||||
|
: (a, b) => -descendingComparator(a, b, orderBy);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stableSort(array, comparator) {
|
||||||
|
const stabilizedThis = array.map((el, index) => [el, index]);
|
||||||
|
stabilizedThis.sort((a, b) => {
|
||||||
|
const order = comparator(a[0], b[0]);
|
||||||
|
if (order !== 0) return order;
|
||||||
|
return a[1] - b[1];
|
||||||
|
});
|
||||||
|
return stabilizedThis.map((el) => el[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function StickyHeadTable(props) {
|
||||||
|
const classes = useStyles();
|
||||||
|
const [page, setPage] = React.useState(0);
|
||||||
|
const [rowsPerPage, setRowsPerPage] = React.useState(10);
|
||||||
|
const [order, setOrder] = React.useState('asc');
|
||||||
|
const [orderBy, setOrderBy] = React.useState('id');
|
||||||
|
const [dense, setDense] = React.useState(props.dense);
|
||||||
|
const [selectedRows, setSelectedRows] = React.useState([]);
|
||||||
|
const [lastIndex, setLastIndex] = React.useState(-1);
|
||||||
|
const [maxHeight, setMaxHeight] = React.useState(getMaxHeight(props.isMobile));
|
||||||
|
const [selectableText, setSelectableText] = React.useState("none");
|
||||||
|
|
||||||
|
|
||||||
|
const resizeFunction = () => {
|
||||||
|
setMaxHeight(getMaxHeight(props.isMobile));
|
||||||
|
};
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
|
||||||
|
window.addEventListener("resize", resizeFunction);
|
||||||
|
window.addEventListener("orientationchange", resizeFunction);
|
||||||
|
// Specify how to clean up after this effect:
|
||||||
|
return function cleanup() {
|
||||||
|
|
||||||
|
window.removeEventListener("resize", resizeFunction);
|
||||||
|
window.removeEventListener("orientationchange", resizeFunction);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleChangeDense = (event) => {
|
||||||
|
setDense(event.target.checked);
|
||||||
|
|
||||||
|
if(props.handleChangeDense !== undefined)
|
||||||
|
{
|
||||||
|
props.handleChangeDense(dense);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangePage = (event, newPage) => {
|
||||||
|
setPage(newPage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChangeRowsPerPage = (event) => {
|
||||||
|
setRowsPerPage(+event.target.value);
|
||||||
|
setPage(0);
|
||||||
|
};
|
||||||
|
|
||||||
|
const actionStyle={
|
||||||
|
whiteSpace: "nowrap",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
width: "70px",
|
||||||
|
display: "block",
|
||||||
|
overflow: "hidden"
|
||||||
|
}
|
||||||
|
|
||||||
|
const showDataFromColumns = (row) => {
|
||||||
|
|
||||||
|
let result = [];
|
||||||
|
if(props.columns.length > 0){
|
||||||
|
for (let column of props.columns) {
|
||||||
|
if(!props.visibleColumns.includes(column)) continue;
|
||||||
|
|
||||||
|
if(column === "actions")
|
||||||
|
{
|
||||||
|
|
||||||
|
result.push(<TableCell style = {{maxWidth: "30px"}} key={row.id + "_" + column}>
|
||||||
|
<div style = {actionStyle}>
|
||||||
|
<IconButton aria-label="expand row" size="small" onClick={() => handleEditIconClicked(row)}>
|
||||||
|
<EditIcon/>
|
||||||
|
</IconButton>
|
||||||
|
<IconButton aria-label="expand row" size="small" onClick={() => handleDeleteIconClicked(row)}>
|
||||||
|
<DeleteIcon/>
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</TableCell>);
|
||||||
|
// <IconButton aria-label="expand row" size="small" onClick={() => setOpen(!open)}>
|
||||||
|
//{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
|
||||||
|
//</IconButton>
|
||||||
|
}
|
||||||
|
else if(row.hasOwnProperty(column)){
|
||||||
|
result.push(<TableCell key={row.id + "_" + column}>
|
||||||
|
{row[column]}
|
||||||
|
</TableCell>);
|
||||||
|
} else {
|
||||||
|
result.push(<TableCell key={row.id + "_" + column}>
|
||||||
|
{null}
|
||||||
|
</TableCell>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const createSortHandler = (property) => (event) => {
|
||||||
|
handleRequestSort(event, property);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRequestSort = (event, property) => {
|
||||||
|
const isAsc = orderBy === property && order === 'asc';
|
||||||
|
setOrder(isAsc ? 'desc' : 'asc');
|
||||||
|
setOrderBy(property);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renameTableColumn = (column) =>{
|
||||||
|
if(column in props.renamedColumns) return props.renamedColumns[column];
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSelected = (_index) => selectedRows.indexOf(_index) !== -1;
|
||||||
|
|
||||||
|
const handleEditIconClicked = (row) => {
|
||||||
|
|
||||||
|
let newSelected = [];
|
||||||
|
newSelected.push(row._index);
|
||||||
|
setSelectedRows(newSelected);
|
||||||
|
|
||||||
|
props.handleTableClick(newSelected);
|
||||||
|
props.handleTableDoubleClick(null, row.id, row._index)
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteIconClicked = (row) => {
|
||||||
|
|
||||||
|
let newSelected = [];
|
||||||
|
newSelected.push(row._index);
|
||||||
|
setSelectedRows(newSelected);
|
||||||
|
|
||||||
|
props.handleTableClick(newSelected);
|
||||||
|
props.handleTableDeleteClick(null, row.id, row._index);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTableClick = (event, row, index) => {
|
||||||
|
|
||||||
|
let newSelected = [];
|
||||||
|
|
||||||
|
//console.log("table - handleClick", row, row._index, index);
|
||||||
|
|
||||||
|
if (event.ctrlKey) {
|
||||||
|
const indx = selectedRows.indexOf(row._index);
|
||||||
|
|
||||||
|
newSelected = [...selectedRows];
|
||||||
|
|
||||||
|
if (indx === -1) {
|
||||||
|
newSelected.push(row._index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
newSelected.splice(indx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLastIndex(index);
|
||||||
|
|
||||||
|
}else if (event.shiftKey) {
|
||||||
|
|
||||||
|
if(selectedRows.length === 0)
|
||||||
|
{
|
||||||
|
newSelected.push(row._index);
|
||||||
|
}
|
||||||
|
|
||||||
|
let fromValue = lastIndex;
|
||||||
|
let toValue = index;
|
||||||
|
|
||||||
|
if( fromValue > toValue )
|
||||||
|
{
|
||||||
|
fromValue = index;
|
||||||
|
toValue = lastIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(fromValue, toValue);
|
||||||
|
|
||||||
|
newSelected = [...selectedRows];
|
||||||
|
for(let indx = fromValue; indx <= toValue; indx++)
|
||||||
|
{
|
||||||
|
let row = sorted[indx];
|
||||||
|
const t = selectedRows.indexOf(row._index);
|
||||||
|
|
||||||
|
if (t === -1) {
|
||||||
|
newSelected.push(row._index);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}else {
|
||||||
|
|
||||||
|
const indx = selectedRows.indexOf(row._index);
|
||||||
|
|
||||||
|
if (indx === -1) {
|
||||||
|
newSelected.push(row._index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectedRows.splice(indx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
setLastIndex(index);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(newSelected.length === 0) setLastIndex(index);
|
||||||
|
|
||||||
|
setSelectedRows(newSelected);
|
||||||
|
props.handleTableClick(newSelected);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(props.data === undefined || props.data === null)
|
||||||
|
{
|
||||||
|
return <CircularProgress />;
|
||||||
|
}
|
||||||
|
|
||||||
|
sorted = stableSort(props.data, getComparator(order, orderBy)).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
|
||||||
|
|
||||||
|
const handleSelectText = () =>
|
||||||
|
{
|
||||||
|
selectableText == 'none' ? setSelectableText("text"): setSelectableText("none");
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Paper className={classes.root}>
|
||||||
|
<TableContainer className={classes.container} style = {{maxHeight: maxHeight}}>
|
||||||
|
<Table stickyHeader aria-label="sticky table" style={{ tableLayout: 'auto' }} size = {dense ? 'small' : 'medium'}>
|
||||||
|
<TableHead>
|
||||||
|
<TableRow >
|
||||||
|
{Object.keys(props.columns).map((key, index) => {
|
||||||
|
|
||||||
|
let column = props.columns[key];
|
||||||
|
|
||||||
|
//use filter?
|
||||||
|
if(!props.visibleColumns.includes(column)) return null;
|
||||||
|
|
||||||
|
if(column === "actions")
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<StyledTableCell style = {{width: "50px"}} key={column}>
|
||||||
|
</StyledTableCell>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledTableCell
|
||||||
|
key={column}
|
||||||
|
sortDirection={orderBy === column ? order : false}
|
||||||
|
>
|
||||||
|
<TableSortLabel
|
||||||
|
active = {orderBy === column}
|
||||||
|
direction={orderBy === column ? order : 'asc'}
|
||||||
|
onClick={createSortHandler(column)}
|
||||||
|
>
|
||||||
|
{renameTableColumn(column)}
|
||||||
|
</TableSortLabel>
|
||||||
|
</StyledTableCell>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</TableRow>
|
||||||
|
</TableHead>
|
||||||
|
<TableBody>
|
||||||
|
{sorted.map((row, index) => {
|
||||||
|
const isItemSelected = isSelected(row._index);
|
||||||
|
|
||||||
|
let backgroundColor;
|
||||||
|
if(isItemSelected){
|
||||||
|
backgroundColor = blue[200];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledTableRow
|
||||||
|
key={row.id}
|
||||||
|
hover
|
||||||
|
role="checkbox"
|
||||||
|
tabIndex={-1}
|
||||||
|
selected={isItemSelected}
|
||||||
|
style={{backgroundColor: backgroundColor, userSelect: selectableText}}
|
||||||
|
onClick={(event) => handleTableClick(event, row, index)}
|
||||||
|
onDoubleClick={(event) => props.handleTableDoubleClick(event, row.id, row._index)}
|
||||||
|
>
|
||||||
|
{showDataFromColumns(row)}
|
||||||
|
</StyledTableRow>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</TableContainer>
|
||||||
|
<TablePagination
|
||||||
|
rowsPerPageOptions={[10, 25, 100]}
|
||||||
|
component="div"
|
||||||
|
count={props.data.length}
|
||||||
|
rowsPerPage={rowsPerPage}
|
||||||
|
labelRowsPerPage='Riadkov na stránke:'
|
||||||
|
page={page}
|
||||||
|
onPageChange={handleChangePage}
|
||||||
|
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||||
|
style={{ display:"flex" }}
|
||||||
|
/>
|
||||||
|
</Paper>
|
||||||
|
|
||||||
|
{
|
||||||
|
props.isMobile ? null : <FormControlLabel style = {{marginLeft: "5px"}}
|
||||||
|
control={<Switch checked={dense} onChange={handleChangeDense} />}
|
||||||
|
label="Kompaktné zobrazenie"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
|
<FormControlLabel style = {{marginLeft: "5px"}}
|
||||||
|
control={<Switch onChange={handleSelectText} />}
|
||||||
|
label="Oznacovat text ?"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
582
src/components/table/tableDb.js
Normal file
582
src/components/table/tableDb.js
Normal file
|
|
@ -0,0 +1,582 @@
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
|
import DB from 'util/db/db';
|
||||||
|
import cloneDeep from 'lodash.clonedeep'
|
||||||
|
import SqlQueryBuilder, { LogicOperator } from 'util/db/SqlQueryBuilder';
|
||||||
|
import AlertDialog from 'components/AlertDialog/AlertDialog';
|
||||||
|
import StickyHeadTable from 'components/table/table';
|
||||||
|
|
||||||
|
import CancelOutlinedIcon from '@material-ui/icons/CancelOutlined';
|
||||||
|
import { red } from '@material-ui/core/colors';
|
||||||
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
import isMobile from 'util/isMobile';
|
||||||
|
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import Tooltip from '@material-ui/core/Tooltip';
|
||||||
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
|
||||||
|
// card core components
|
||||||
|
//import Card from './../Card/Card';
|
||||||
|
//import CardBody from './../Card/CardBody.js';
|
||||||
|
//import CardHeader from './../Card/CardHeader.js';
|
||||||
|
|
||||||
|
import Card from '@material-ui/core/Card';
|
||||||
|
import CardBody from '@material-ui/core/CardContent';
|
||||||
|
import CardHeader from '@material-ui/core/CardHeader';
|
||||||
|
|
||||||
|
import ArrowBackIcon from '@material-ui/icons/ArrowBack';
|
||||||
|
//-----------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
data: null,
|
||||||
|
columns: [],
|
||||||
|
visibleColumns: [],
|
||||||
|
usePagination: true,
|
||||||
|
index: null,
|
||||||
|
deleteConfirmed: false,
|
||||||
|
showFindDialog: false,
|
||||||
|
showFilter: false,
|
||||||
|
showAlert: false,
|
||||||
|
alertTitle: "",
|
||||||
|
alertType: "warning",
|
||||||
|
alertContent: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TableDb extends React.Component {
|
||||||
|
|
||||||
|
static TABLE_STATUS = {
|
||||||
|
EDIT: 'EDIT',
|
||||||
|
ADD: 'ADD',
|
||||||
|
SHOWTABLE: 'SHOWTABLE',
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.state = initialState;
|
||||||
|
this.state.status = TableDb.TABLE_STATUS.SHOWTABLE;
|
||||||
|
|
||||||
|
this.db = new DB();
|
||||||
|
this.dbTable = "";
|
||||||
|
this.selectedRows = [];//list of indexes
|
||||||
|
|
||||||
|
this.showFormInDialog = false;
|
||||||
|
this.fullscreen = false;
|
||||||
|
|
||||||
|
this.id = null;
|
||||||
|
this.index = null;
|
||||||
|
|
||||||
|
this.anchorMenuRef = React.createRef();
|
||||||
|
|
||||||
|
if(props.isMobile !== undefined) this.setDense(!props.isMobile);
|
||||||
|
else this.setDense(!isMobile());
|
||||||
|
}
|
||||||
|
|
||||||
|
display(type)
|
||||||
|
{
|
||||||
|
//to prevent rendering when add/edit is finished
|
||||||
|
if(type === "EDIT")
|
||||||
|
{
|
||||||
|
//if(this.state.rowID > 0) return null;
|
||||||
|
//if(this.state.status === "EDIT") return null;
|
||||||
|
if(this.state.status === TableDb.TABLE_STATUS.ADD) return null;
|
||||||
|
if(this.state.status === TableDb.TABLE_STATUS.EDIT) return null;
|
||||||
|
|
||||||
|
return "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type === "TABLE")
|
||||||
|
{
|
||||||
|
//if(this.state.status === "EDIT") return "none";
|
||||||
|
if(this.state.status === TableDb.TABLE_STATUS.ADD) return "none";
|
||||||
|
if(this.state.status === TableDb.TABLE_STATUS.EDIT) return "none";
|
||||||
|
return null;
|
||||||
|
|
||||||
|
//if(this.state.rowID > 0) return "none";
|
||||||
|
//return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDense(dense)
|
||||||
|
{
|
||||||
|
this.dense = dense;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(status)
|
||||||
|
{
|
||||||
|
this.setState({"status": status});
|
||||||
|
}
|
||||||
|
|
||||||
|
getStatus()
|
||||||
|
{
|
||||||
|
if(this.state.status === TableDb.TABLE_STATUS.EDIT || this.state.status === TableDb.TABLE_STATUS.ADD) return "EDIT";
|
||||||
|
else return "SHOWTABLE";
|
||||||
|
}
|
||||||
|
|
||||||
|
renderForm()
|
||||||
|
{
|
||||||
|
return <h1>Editacia riadku</h1>;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderTable()
|
||||||
|
{
|
||||||
|
//console.log(this.state.data);
|
||||||
|
//alert("render table");
|
||||||
|
return(
|
||||||
|
<StickyHeadTable
|
||||||
|
data={this.state.data}
|
||||||
|
columns={this.state.columns}
|
||||||
|
visibleColumns={this.state.visibleColumns}
|
||||||
|
renamedColumns={this.renamedColumns}
|
||||||
|
isMobile = {this.state.isMobile}
|
||||||
|
pagination = {this.state.usePagination}
|
||||||
|
handleTableDoubleClick = {this.handleTableDoubleClick.bind(this)}
|
||||||
|
handleTableDeleteClick = {this.handleTableDeleteClick.bind(this)}
|
||||||
|
handleBack={this.handleBack}
|
||||||
|
handleChangeDense = {this.setDense.bind(this)}
|
||||||
|
dense = {this.dense}
|
||||||
|
handleTableClick={this.handleTableClick.bind(this)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUiForm(status)
|
||||||
|
{
|
||||||
|
|
||||||
|
let form = this.renderForm();
|
||||||
|
|
||||||
|
let txt = "editácia";
|
||||||
|
if(this.state.status === TableDb.TABLE_STATUS.ADD) txt = "nový záznam";
|
||||||
|
//TODO set vytvorenie
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardHeader color="success">
|
||||||
|
|
||||||
|
<Typography align="left">
|
||||||
|
<Tooltip title="návrat na hlavnú stránku" arrow>
|
||||||
|
<Button
|
||||||
|
onClick = {event => this.handleBack(event)}
|
||||||
|
startIcon={<ArrowBackIcon />}
|
||||||
|
>
|
||||||
|
{this.title}: {txt}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
<div>
|
||||||
|
{form}
|
||||||
|
</div>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUiTable()
|
||||||
|
{
|
||||||
|
return(
|
||||||
|
<Card>
|
||||||
|
<CardHeader color="success">
|
||||||
|
<Tooltip title="zobraz menu" arrow>
|
||||||
|
<Button
|
||||||
|
ref={this.anchorMenuRef}
|
||||||
|
aria-controls={this.state.openMenu ? 'menu-list-grow' : undefined}
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={this.handleToggleMenu.bind(this)}
|
||||||
|
startIcon={<MoreVertIcon />}
|
||||||
|
>
|
||||||
|
{this.title}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
{this.renderCancelFilterIcon()}
|
||||||
|
</CardHeader>
|
||||||
|
<CardBody>
|
||||||
|
<div>
|
||||||
|
{this.renderTable()}
|
||||||
|
</div>
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderUi()
|
||||||
|
{
|
||||||
|
let status = this.getStatus();
|
||||||
|
let form = null;
|
||||||
|
|
||||||
|
//add or edit record
|
||||||
|
if(status !== TableDb.TABLE_STATUS.SHOWTABLE)
|
||||||
|
{
|
||||||
|
form = this.renderUiForm();
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<div style={{ display: this.display("EDIT") }}>
|
||||||
|
{form}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: this.display("TABLE") }}>
|
||||||
|
{this.renderUiTable()}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let findDialog = null;
|
||||||
|
|
||||||
|
if(this.state.showFindDialog)
|
||||||
|
{
|
||||||
|
findDialog = this.renderFindDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ width: '100%'}}>
|
||||||
|
{this.renderUi()}
|
||||||
|
{this.renderMainMenu()}
|
||||||
|
{findDialog}
|
||||||
|
{this.renderAlertDialog()}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount()
|
||||||
|
{
|
||||||
|
this.showTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderCancelFilterIcon()
|
||||||
|
{
|
||||||
|
if (this.state.showFilter) return <Tooltip title="zrušiť filter" arrow><Button size="large" style={{ color: red[500] }} onClick={this.handleCancelFilter.bind(this)} startIcon={<CancelOutlinedIcon />}></Button></Tooltip>;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancelFilter()
|
||||||
|
{
|
||||||
|
//let newState = {...this.state};
|
||||||
|
//newState.showFilter = false;
|
||||||
|
//this.setState(newState);
|
||||||
|
//this.state.showFilter = false;
|
||||||
|
|
||||||
|
this.setState(prevstate => ({ showFilter: false}));
|
||||||
|
|
||||||
|
this.showTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
setRow(row)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
showTable(sqlQueryBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(sqlQueryBuilder === undefined) sqlQueryBuilder = this.getDefaultQueryBuilder();
|
||||||
|
|
||||||
|
//!force to show progress
|
||||||
|
this.setState(prevstate => ({ showFilter: prevstate.showFilter, data: null}));
|
||||||
|
|
||||||
|
this.db.dbSelect(sqlQueryBuilder, true).then(
|
||||||
|
result => {
|
||||||
|
result = this.db.updateJsonTypes(result, this.getTableName(true));
|
||||||
|
//console.log(result);
|
||||||
|
|
||||||
|
//modify data
|
||||||
|
for(let i = 0; i < result.length; ++i)
|
||||||
|
{
|
||||||
|
this.setRow(result[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
let newState = {...this.state};
|
||||||
|
newState.data = result;
|
||||||
|
this.setState(newState);
|
||||||
|
//this.showAlertDialog("Info", "Data boli načítané")
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
//alert(error);
|
||||||
|
this.showAlertDialog("Chyba", error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTableName(withView = false)
|
||||||
|
{
|
||||||
|
return this.dbTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
getDefaultQueryBuilder()
|
||||||
|
{
|
||||||
|
|
||||||
|
let table = this.getTableName(true);
|
||||||
|
if(table === "") new Error("table name or view is not specified");
|
||||||
|
|
||||||
|
let sqlQueryBuilder = new SqlQueryBuilder();
|
||||||
|
sqlQueryBuilder.from( table );
|
||||||
|
|
||||||
|
return sqlQueryBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildFindSqlQuery(findDialogParams)
|
||||||
|
{
|
||||||
|
if(_.isEmpty(findDialogParams))
|
||||||
|
{
|
||||||
|
this.setState(prevstate => ({ showFindDialog: false, showFilter: false}));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(prevstate => ({ showFindDialog: false, showFilter: true}));
|
||||||
|
|
||||||
|
return this.getDefaultQueryBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleToggleMenu()
|
||||||
|
{
|
||||||
|
this.setState(prevstate => ({ openMenu: true}));
|
||||||
|
}
|
||||||
|
|
||||||
|
//run edit mode
|
||||||
|
handleTableDoubleClick(event, id, index){
|
||||||
|
console.log("handleTableDoubleClick:", id, index);
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
this.index = index;
|
||||||
|
|
||||||
|
this.setStatus(TableDb.TABLE_STATUS.EDIT);
|
||||||
|
|
||||||
|
//this.setState(prevstate => ({ rowID: id, index: index}));
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTableClick(selectedRows){
|
||||||
|
//console.log("tableDb::handleTableClick", selectedRows);
|
||||||
|
this.selectedRows = selectedRows;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
handleTableDeleteClick(event, id, index){
|
||||||
|
|
||||||
|
this.id = id;
|
||||||
|
this.index = index;
|
||||||
|
|
||||||
|
this.menuClicked("delete");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//end of AddRecord/EditRecord
|
||||||
|
handleBack(params){
|
||||||
|
|
||||||
|
//TODO refactor it
|
||||||
|
|
||||||
|
//console.log(params, this.selectedRows);
|
||||||
|
|
||||||
|
if(params === undefined)
|
||||||
|
{
|
||||||
|
this.setState({"status": TableDb.TABLE_STATUS.SHOWTABLE});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = this.index;
|
||||||
|
//if(this.selectedRows.length === 1) index = this.selectedRows[0];
|
||||||
|
|
||||||
|
if(index === undefined || index === null)
|
||||||
|
{
|
||||||
|
for(let i = 0; i < this.state.data.length; i++)
|
||||||
|
{
|
||||||
|
if(this.state.data[i]["id"] === this.id)
|
||||||
|
{
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO clone???
|
||||||
|
let newState = this.state;//{...this.state};
|
||||||
|
//let newState = {};
|
||||||
|
newState.status = TableDb.TABLE_STATUS.SHOWTABLE;
|
||||||
|
//
|
||||||
|
//update current row;
|
||||||
|
if(index !== null)
|
||||||
|
{
|
||||||
|
//newState.data = {...this.state.data[index]};
|
||||||
|
for (var prop in params) {
|
||||||
|
newState.data[index][prop] = params[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//console.log("handle back - index is null");
|
||||||
|
|
||||||
|
//TODO fix get last element and it's _index!!!!!
|
||||||
|
var last_element = this.state.data[this.state.data.length - 1];
|
||||||
|
if(last_element === undefined)
|
||||||
|
{
|
||||||
|
//WHAT
|
||||||
|
//alert("tableDb.js fix");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
params["_index"] = last_element._index + 1;
|
||||||
|
newState.data.push(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
newState.status = TableDb.TABLE_STATUS.SHOWTABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState(newState);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//reimplement it
|
||||||
|
renderMenu()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMainMenu()
|
||||||
|
{
|
||||||
|
if(this.anchorMenuRef == null) return null;
|
||||||
|
if(this.anchorMenuRef.current == null) return null;
|
||||||
|
if(!this.state.openMenu) return null;
|
||||||
|
|
||||||
|
return this.renderMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFindDialog()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderAlertDialog()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<AlertDialog
|
||||||
|
open = {this.state.showAlert}
|
||||||
|
title = {this.state.alertTitle}
|
||||||
|
content = {this.state.alertContent}
|
||||||
|
onConfirm ={this.hideAlertDialog.bind(this)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
hideAlertDialog()
|
||||||
|
{
|
||||||
|
this.setState({showAlert: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
showAlertDialog(title, message, type)
|
||||||
|
{
|
||||||
|
if(type === undefined) type = "warning";
|
||||||
|
this.setState(prevstate => ({showAlert: true, alertTitle: title, alertContent: message, alertType: type}));
|
||||||
|
}
|
||||||
|
|
||||||
|
menuClicked(menu)
|
||||||
|
{
|
||||||
|
this.menuClosed();
|
||||||
|
|
||||||
|
if(menu === "add")
|
||||||
|
{
|
||||||
|
this.index = null;
|
||||||
|
this.id = null;
|
||||||
|
|
||||||
|
this.setState(prevstate => ({
|
||||||
|
openMenu: false,
|
||||||
|
index: null,
|
||||||
|
status: TableDb.TABLE_STATUS.ADD
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(menu === "find")
|
||||||
|
{
|
||||||
|
this.setState(prevstate => ({ showFindDialog: true}));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(menu === "edit")
|
||||||
|
{
|
||||||
|
if(this.selectedRows.length === 0)
|
||||||
|
{
|
||||||
|
this.showAlertDialog("Editácia", "Nie sú označené žiadne riadky");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(this.selectedRows.length > 1)
|
||||||
|
{
|
||||||
|
this.showAlertDialog("Editácia", "Označte jeden riadkok");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = this.selectedRows[0];
|
||||||
|
if(index === undefined)
|
||||||
|
{
|
||||||
|
alert("menuClicked index is undefined");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.id = this.state.data[index].id;
|
||||||
|
this.index = index;
|
||||||
|
|
||||||
|
this.setStatus(TableDb.TABLE_STATUS.EDIT);
|
||||||
|
}
|
||||||
|
else if(menu === "delete")
|
||||||
|
{
|
||||||
|
if(this.selectedRows.length === 0)
|
||||||
|
{
|
||||||
|
this.showAlertDialog("Mazanie", "Nie sú označené žiadne riadky");
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = cloneDeep(this.state.data);
|
||||||
|
data.splice(this.index, 1)
|
||||||
|
|
||||||
|
//update _index!!!
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
data[i]._index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this.setState(prevstate => ({ data: this.state.data.splice(this.index, 1)}));
|
||||||
|
|
||||||
|
this.setState({data: data});
|
||||||
|
//this.showAlertDialog("Mazanie", "pripravujeme...");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRow(index)
|
||||||
|
{
|
||||||
|
let data = cloneDeep(this.state.data);
|
||||||
|
data.splice(index, 1)
|
||||||
|
|
||||||
|
//update _index!!!
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
data[i]._index = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({data: data});
|
||||||
|
}
|
||||||
|
|
||||||
|
menuClosed()
|
||||||
|
{
|
||||||
|
let newState = this.state;
|
||||||
|
newState.openMenu = false;
|
||||||
|
|
||||||
|
this.setState(newState);
|
||||||
|
|
||||||
|
//this.setState(prevstate => ({ openMenu: false}));
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TableDb;
|
||||||
138
src/config/config.js
Normal file
138
src/config/config.js
Normal file
|
|
@ -0,0 +1,138 @@
|
||||||
|
/*
|
||||||
|
0 - cislo registra / prikaz
|
||||||
|
1 - recepient - 0 = master, 1 = slave (slave je automaticky group a broadcast)
|
||||||
|
2 - r/rw - read/write
|
||||||
|
3- register name - nazov registra / prikazu (len pre info - zobrazenie v aplikacii)
|
||||||
|
|
||||||
|
4,5,6,7, - jednotlive byte-y - nazov byte-u
|
||||||
|
4-7 - RES. a prazdny string "" sa nezobrazia!!!
|
||||||
|
*/
|
||||||
|
|
||||||
|
//124 zaznamov
|
||||||
|
export const config = [
|
||||||
|
["0","1","R","Status","","",""],
|
||||||
|
["1","1","RW","Dimming","R-Channel ","G-Channel","B-Channel ","W - Channel"],
|
||||||
|
["2","1","RW","Device types","","","",""],
|
||||||
|
["3","1","RW","Group addresses 1-4","Groups Add. 4","Groups Add. 3","Groups Add. 2","Groups Add. 1"],
|
||||||
|
["4","1","RW","Group addresses 5-8","Groups Add. 8","Groups Add. 7","Groups Add. 6","Groups Add. 5"],
|
||||||
|
["5","1","RW","Serial number (MAC)","","","",""],
|
||||||
|
["6","1","RW","Time of dusk","HH","MM","SS","EXTRA"],
|
||||||
|
["7","1","RW","Time of dawn","HH","MM","SS","EXTRA"],
|
||||||
|
["8","1","RW","Time Schedule settings","TBD","TBD","Movement sensor","Time Schedule"],
|
||||||
|
["9","1","RW","TS1 Time point 1","HH","MM","SS","Ext. Device"],
|
||||||
|
["10","1","RW","TS1 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["11","1","RW","TS1 Time point 2","HH","MM","SS","Ext. Device"],
|
||||||
|
["12","1","RW","TS1 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["13","1","RW","TS1 Time point 3","HH","MM","SS","Ext. Device"],
|
||||||
|
["14","1","RW","TS1 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["15","1","RW","TS1 Time point 4","HH","MM","SS","Ext. Device"],
|
||||||
|
["16","1","RW","TS1 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["17","1","RW","TS1 Time point 5","HH","MM","SS","Ext. Device"],
|
||||||
|
["18","1","RW","TS1 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["19","1","RW","TS1 Time point 6","HH","MM","SS","Ext. Device"],
|
||||||
|
["20","1","RW","TS1 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["21","1","RW","TS1 Time point 7","HH","MM","SS","Ext. Device"],
|
||||||
|
["22","1","RW","TS1 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["23","1","RW","TS1 Time point 8","HH","MM","SS","Ext. Device"],
|
||||||
|
["24","1","RW","TS1 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["25","1","RW","TS1 Time point 9","HH","MM","SS","Ext. Device"],
|
||||||
|
["26","1","RW","TS1 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["27","1","RW","TS1 Time point 10","HH","MM","SS","Ext. Device"],
|
||||||
|
["28","1","RW","TS1 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["29","1","RW","TS1 Time point 11","HH","MM","SS","Ext. Device"],
|
||||||
|
["30","1","RW","TS1 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["31","1","RW","TS1 Time point 12","HH","MM","SS","Ext. Device"],
|
||||||
|
["32","1","RW","TS1 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["33","1","RW","TS1 Time point 13","HH","MM","SS","Ext. Device"],
|
||||||
|
["34","1","RW","TS1 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["35","1","RW","TS1 Time point 14","HH","MM","SS","Ext. Device"],
|
||||||
|
["36","1","RW","TS1 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["37","1","RW","TS1 Time point 15","HH","MM","SS","Ext. Device"],
|
||||||
|
["38","1","RW","TS1 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["39","1","RW","TS1 Time point 16","HH","MM","SS","Ext. Device"],
|
||||||
|
["40","1","RW","TS1 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["41","1","RW","TS2 Time point 1","HH","MM","SS","Ext. Device"],
|
||||||
|
["42","1","RW","TS2 Time point 1 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["43","1","RW","TS2 Time point 2","HH","MM","SS","Ext. Device"],
|
||||||
|
["44","1","RW","TS2 Time point 2 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["45","1","RW","TS2 Time point 3","HH","MM","SS","Ext. Device"],
|
||||||
|
["46","1","RW","TS2 Time point 3 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["47","1","RW","TS2 Time point 4","HH","MM","SS","Ext. Device"],
|
||||||
|
["48","1","RW","TS2 Time point 4 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["49","1","RW","TS2 Time point 5","HH","MM","SS","Ext. Device"],
|
||||||
|
["50","1","RW","TS2 Time point 5 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["51","1","RW","TS2 Time point 6","HH","MM","SS","Ext. Device"],
|
||||||
|
["52","1","RW","TS2 Time point 6 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["53","1","RW","TS2 Time point 7","HH","MM","SS","Ext. Device"],
|
||||||
|
["54","1","RW","TS2 Time point 7 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["55","1","RW","TS2 Time point 8","HH","MM","SS","Ext. Device"],
|
||||||
|
["56","1","RW","TS2 Time point 8 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["57","1","RW","TS2 Time point 9","HH","MM","SS","Ext. Device"],
|
||||||
|
["58","1","RW","TS2 Time point 9 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["59","1","RW","TS2 Time point 10","HH","MM","SS","Ext. Device"],
|
||||||
|
["60","1","RW","TS2 Time point 10 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["61","1","RW","TS2 Time point 11","HH","MM","SS","Ext. Device"],
|
||||||
|
["62","1","RW","TS2 Time point 11 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["63","1","RW","TS2 Time point 12","HH","MM","SS","Ext. Device"],
|
||||||
|
["64","1","RW","TS2 Time point 12 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["65","1","RW","TS2 Time point 13","HH","MM","SS","Ext. Device"],
|
||||||
|
["66","1","RW","TS2 Time point 13 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["67","1","RW","TS2 Time point 14","HH","MM","SS","Ext. Device"],
|
||||||
|
["68","1","RW","TS2 Time point 14 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["69","1","RW","TS2 Time point 15","HH","MM","SS","Ext. Device"],
|
||||||
|
["70","1","RW","TS2 Time point 15 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["71","1","RW","TS2 Time point 16","HH","MM","SS","Ext. Device"],
|
||||||
|
["72","1","RW","TS2 Time point 16 Levels","R-Channel","G-Channel","B-Channel","W - Channel"],
|
||||||
|
["73","1","RW","Power meter status","TBD","","",""],
|
||||||
|
["74","1","R","Input Voltage","","","",""],
|
||||||
|
["75","1","R","Input Current","","","",""],
|
||||||
|
["76","1","R","Input Power","","","",""],
|
||||||
|
["77","1","R","Cos phi","","","",""],
|
||||||
|
["78","1","R","Frequency","","","",""],
|
||||||
|
["79","1","RW","Energy","","","",""],
|
||||||
|
["80","1","RW","Lifetime","","","",""],
|
||||||
|
["81","1","RW","Power on cycles (input)","","","",""],
|
||||||
|
["82","1","RW","Power on cycles (relay)","","","",""],
|
||||||
|
["83","1","R","Time since last power on","","","",""],
|
||||||
|
["84","1","R","Accelerometer data","","","",""],
|
||||||
|
["85","1","RW","GPS latitude","pos/neg","deg","min ","sec"],
|
||||||
|
["86","1","RW","GPS longitude","pos/neg","deg","min ","sec"],
|
||||||
|
["87","1","RW","Actual time","HH","MM","SS","RES."],
|
||||||
|
["88","1","RW","Actual date","Day of week","Day","Month","Year"],
|
||||||
|
["89","1","R","Production data 1","","","",""],
|
||||||
|
["90","1","R","Production data 2","","","",""],
|
||||||
|
["91","1","RW","Network ID","NID3","NID2","NID1","NID0"],
|
||||||
|
["95","1","RW","Actual Lux level from cabinet","RES.","RES.","HB","LB"],
|
||||||
|
["96","1","RW","Threshold lux level","Dusk HB","Dusk LB","Dawn HB","Dawn LB"],
|
||||||
|
["97","1","RW","Adjust period","Dusk HB","Dusk LB","Dawn HB","Dawn LB"],
|
||||||
|
["98","1","RW","Offset","RES.","RES.","Dusk","Dawn"],
|
||||||
|
["99","1","RW","CCT min/max range","max-H","max-L","min-H","min-L"],
|
||||||
|
["100","1","RW","DALI interface","Cmd ID","Add","Cmd","Resp"],
|
||||||
|
["101","1","RW","Module FW ver","v1","v2","v3","v4"],
|
||||||
|
["102","1","RW","Module MAC-H","unused","unused","M1","M2"],
|
||||||
|
["103","1","RW","Module MAC-L","M3","M4","M5","M6"],
|
||||||
|
["104","1","RW","Sensor timeout","","","Timeout H","Timeout L"],
|
||||||
|
["122","1","R","FW update status/control register","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["123","1","R","FW update - data index","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["124","1","R","FW update - data","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["0","0","R","Status","","","",""],
|
||||||
|
["1","0","RW","Control register","RES.","RES.","RES.","init mode enable"],
|
||||||
|
["2","0","R","Device types","","","",""],
|
||||||
|
["3","0","R","Serial number (MAC)","","","",""],
|
||||||
|
["4","0","R","Production data 1","","","",""],
|
||||||
|
["5","0","R","Production data 2","","","",""],
|
||||||
|
["6","0","RW","Network ID","NID3","NID2","NID1","NID0"],
|
||||||
|
["7","0","RW","RS232 settings","param.","param.","Baudrate H","Baudrate L"],
|
||||||
|
["8","0","R","Accelerometer data","","","",""],
|
||||||
|
["9","0","RW","Module FW ver","v1","v2","v3","v4"],
|
||||||
|
["10","0","RW","Module MAC-H","unused","unused","M1","M2"],
|
||||||
|
["11","0","RW","Module MAC-L","M3","M4","M5","M6"],
|
||||||
|
["32","0","RW","FW update status/control register","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["33","0","RW","FW update - data index","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["34","0","RW","FW update - data","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["125","0","RW","Debug Register","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["126","0","RW","Network Control Register","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["127","0","R","Network Status Register","Byte3","Byte2","Byte1","Byte0"],
|
||||||
|
["128","0","RW","Node XX Serial Number Register","SER3","SER2","SER1","SER0"],
|
||||||
|
["256","0","R","Node XX Network Status Register","","","",""]
|
||||||
|
];
|
||||||
770
src/controls.js
vendored
Normal file
770
src/controls.js
vendored
Normal file
|
|
@ -0,0 +1,770 @@
|
||||||
|
import React, {Component} from 'react'
|
||||||
|
|
||||||
|
import Grid from '@material-ui/core/Grid';
|
||||||
|
import Select from '@material-ui/core/Select';
|
||||||
|
import InputLabel from '@material-ui/core/InputLabel';
|
||||||
|
import MenuItem from '@material-ui/core/MenuItem';
|
||||||
|
import Button from '@material-ui/core/Button';
|
||||||
|
import Card from '@material-ui/core/Card';
|
||||||
|
import CardActions from '@material-ui/core/CardActions';
|
||||||
|
import CardContent from '@material-ui/core/CardContent';
|
||||||
|
import Typography from '@material-ui/core/Typography';
|
||||||
|
import TextField from '@material-ui/core/TextField';
|
||||||
|
|
||||||
|
import IconButton from '@material-ui/core/IconButton';
|
||||||
|
import Menu from '@material-ui/core/Menu';
|
||||||
|
import MoreVertIcon from '@material-ui/icons/MoreVert';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
|
||||||
|
import { crc8, crc16, crc32 } from 'easy-crc';
|
||||||
|
|
||||||
|
import {connect} from 'react-redux'
|
||||||
|
import * as actionTypes from './store/actions';
|
||||||
|
|
||||||
|
import * as data from './config/config';
|
||||||
|
|
||||||
|
//axios.defaults.baseURL = 'http://localhost:5000/';
|
||||||
|
|
||||||
|
function getParams()
|
||||||
|
{
|
||||||
|
let params = {};
|
||||||
|
|
||||||
|
//core rpc values
|
||||||
|
params.address = 0;//if(recipient === 0) address = 0;
|
||||||
|
params.byte1 = 0;
|
||||||
|
params.byte2 = 0;
|
||||||
|
params.byte3 = 0;
|
||||||
|
params.byte4 = 0;
|
||||||
|
params.recipient = 0;//0: Master, 1: Slave, 2: Broadcast
|
||||||
|
params.register = 0;//register number
|
||||||
|
params.rw = 0;//0: read, 1: write
|
||||||
|
|
||||||
|
//other values
|
||||||
|
//params.type = "rpc";
|
||||||
|
//params.tbname = tbname;
|
||||||
|
//params.timestamp = 0;//execution time
|
||||||
|
//params.addMinutesToTimestamp = 0;//repeat if > 0,
|
||||||
|
//params.debug = "";
|
||||||
|
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Controls extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
|
||||||
|
//default values
|
||||||
|
let tasks = this.buildTasks("R", 0);
|
||||||
|
let registerNumber = tasks[0].registerNumber;
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
rw: "R",
|
||||||
|
recipient: 0,
|
||||||
|
registerNumber: registerNumber,
|
||||||
|
index: 0,
|
||||||
|
|
||||||
|
anchorEl: null,
|
||||||
|
|
||||||
|
requestToHost: "",
|
||||||
|
responsefromHost: "",
|
||||||
|
tasks: tasks,
|
||||||
|
showAddress: false,
|
||||||
|
address: "",
|
||||||
|
byte1Text: "",
|
||||||
|
byte2Text: "",
|
||||||
|
byte3Text: "",
|
||||||
|
byte4Text: "",
|
||||||
|
byte1: "",
|
||||||
|
byte2: "",
|
||||||
|
byte3: "",
|
||||||
|
byte4: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForm = () =>{
|
||||||
|
|
||||||
|
let errors = [];
|
||||||
|
if(this.state.showAddress)
|
||||||
|
{
|
||||||
|
if(this.state.address === "")
|
||||||
|
{
|
||||||
|
errors.push("Address can not be empty");
|
||||||
|
}
|
||||||
|
else if (!Number.isInteger( parseInt(this.state.address) )) {
|
||||||
|
errors.push("Address is not integer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(errors.length > 0)
|
||||||
|
{
|
||||||
|
alert(errors.join("\n"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//test
|
||||||
|
handleResponse = (bytes) =>
|
||||||
|
{
|
||||||
|
//local add = bit.bor(bit.lshift(bytes[1], 24), bit.lshift(bytes[2], 16), bit.lshift(bytes[3], 8), bytes[4]);
|
||||||
|
|
||||||
|
//https://www.w3schools.com/js/js_bitwise.asp
|
||||||
|
|
||||||
|
let type = "RESPONSE";
|
||||||
|
if(bytes[4] === 0) type = "RESPONSE";
|
||||||
|
else if(bytes[4] === 1) type = "ERROR";
|
||||||
|
else if(bytes[4] === 2) type = "EVENT";
|
||||||
|
else type = "UNKNOWN";
|
||||||
|
|
||||||
|
let crc = crc16('ARC', bytes.slice(0, 9));
|
||||||
|
let c1 = (crc >> 8) & 0xFF;
|
||||||
|
let c2 = crc & 0xFF;
|
||||||
|
|
||||||
|
|
||||||
|
console.log("crc", bytes, c1, c2);
|
||||||
|
|
||||||
|
//let add = (bytes[1] >> 24)
|
||||||
|
}
|
||||||
|
|
||||||
|
//test
|
||||||
|
com_generic = (adresa, rec, rw, register, name, byte1, byte2, byte3, byte4) =>{
|
||||||
|
let resp = [];
|
||||||
|
|
||||||
|
let cmd = register;
|
||||||
|
|
||||||
|
if (rw === 0)
|
||||||
|
{
|
||||||
|
cmd = cmd + 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec === 3)
|
||||||
|
{
|
||||||
|
resp.push(0xFF);
|
||||||
|
resp.push(0xFF);
|
||||||
|
resp.push(0xFF);
|
||||||
|
resp.push(0xFF);
|
||||||
|
resp.push( adresa & 0xFF );//band
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resp.push( (adresa >> 24) & 0xFF);//rshift
|
||||||
|
resp.push( (adresa >> 16) & 0xFF);
|
||||||
|
resp.push( (adresa >> 8) & 0xFF);
|
||||||
|
resp.push( adresa & 0xFF );
|
||||||
|
|
||||||
|
if (rec === 2)
|
||||||
|
{
|
||||||
|
resp.push(0xFF);
|
||||||
|
}
|
||||||
|
else resp.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.push( (cmd >> 8) & 0xFF);//rshift
|
||||||
|
resp.push( cmd & 0xFF );//band
|
||||||
|
resp.push( byte1 & 0xFF );//band
|
||||||
|
resp.push( byte2 & 0xFF );//band
|
||||||
|
resp.push( byte3 & 0xFF );//band
|
||||||
|
resp.push( byte4 & 0xFF );//band
|
||||||
|
|
||||||
|
//let data = '12345';
|
||||||
|
let crc = crc16('ARC', resp);
|
||||||
|
let c1 = (crc >> 8) & 0xFF;
|
||||||
|
let c2 = crc & 0xFF;
|
||||||
|
|
||||||
|
resp.push(c1);
|
||||||
|
resp.push(c2);
|
||||||
|
|
||||||
|
|
||||||
|
console.log("checksum", crc);
|
||||||
|
console.log("resp", resp);
|
||||||
|
|
||||||
|
return resp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//send DATA
|
||||||
|
handleClick = event => {
|
||||||
|
|
||||||
|
//this.com_generic(100, 1, 80, 'Control register', 0, 0, 0, 0);return;
|
||||||
|
|
||||||
|
//let bytes = [0,0,0,0,0,128,1,0,0,0,0];
|
||||||
|
//this.handleResponse(bytes);
|
||||||
|
//return;
|
||||||
|
|
||||||
|
if(!this.checkForm())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const found = this.state.tasks.find(element => element.registerNumber === this.state.registerNumber);
|
||||||
|
if(found === undefined)
|
||||||
|
{
|
||||||
|
alert("Invalid register number: " + this.state.registerNumber);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let address = parseInt(this.state.address);
|
||||||
|
if (isNaN(address)) address = 0;
|
||||||
|
|
||||||
|
let recipient = parseInt(this.state.recipient);
|
||||||
|
if (isNaN(recipient)) recipient = 0;
|
||||||
|
|
||||||
|
//master
|
||||||
|
if(recipient === 0) address = 0;
|
||||||
|
|
||||||
|
if(recipient === 2)
|
||||||
|
{
|
||||||
|
address = 0xffffffff;//Broadcast
|
||||||
|
}
|
||||||
|
|
||||||
|
let byte1 = parseInt(this.state.byte1);
|
||||||
|
if (isNaN(byte1)) byte1 = 0;
|
||||||
|
|
||||||
|
let byte2 = parseInt(this.state.byte2);
|
||||||
|
if (isNaN(byte2)) byte2 = 0;
|
||||||
|
|
||||||
|
let byte3 = parseInt(this.state.byte3);
|
||||||
|
if (isNaN(byte3)) byte3 = 0;
|
||||||
|
|
||||||
|
let byte4 = parseInt(this.state.byte4);
|
||||||
|
if (isNaN(byte4)) byte4 = 0;
|
||||||
|
|
||||||
|
let register = parseInt(this.state.registerNumber);
|
||||||
|
|
||||||
|
//Zadaný index potom prirátaš k registru 128. Takže napríklad pri indexe 1 sa vyčítava z registra 129. Pri indexe 20, by sa vyčítalo z registra 148..
|
||||||
|
if(this.state.rw === "R" && this.state.registerNumber === "128")
|
||||||
|
{
|
||||||
|
register = 128 + parseInt(this.state.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rw = 0;//read
|
||||||
|
if(this.state.rw === "W") rw = 1;
|
||||||
|
|
||||||
|
let cmd = register;
|
||||||
|
if (rw === 0)
|
||||||
|
{
|
||||||
|
//cmd = cmd + 0x8000;
|
||||||
|
}
|
||||||
|
|
||||||
|
let paramsToSend = {
|
||||||
|
command: {
|
||||||
|
register: cmd,
|
||||||
|
name: found.registerName,
|
||||||
|
recipient: recipient,
|
||||||
|
rw: rw,
|
||||||
|
address: address,
|
||||||
|
byte1: byte1,
|
||||||
|
byte2: byte2,
|
||||||
|
byte3: byte3,
|
||||||
|
byte4: byte4,
|
||||||
|
},
|
||||||
|
username: this.props.username,
|
||||||
|
password: this.props.password,
|
||||||
|
};
|
||||||
|
|
||||||
|
//adresa, rec, cmd, name, byte3, byte2, byte1, byte0
|
||||||
|
console.log(paramsToSend.command);
|
||||||
|
|
||||||
|
//com generic is modifying cmd!!! use only for debug / info
|
||||||
|
let result = this.com_generic(
|
||||||
|
paramsToSend.command.address,
|
||||||
|
paramsToSend.command.recipient,
|
||||||
|
paramsToSend.command.rw,
|
||||||
|
paramsToSend.command.register,
|
||||||
|
'Control register',
|
||||||
|
byte1,
|
||||||
|
byte2,
|
||||||
|
byte3,
|
||||||
|
byte4
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
let registerNames = [];// = + " from " ;// + " (WRITE: " + result.join(", ") + ")";
|
||||||
|
registerNames.push(found.registerName);
|
||||||
|
if (recipient === 0)
|
||||||
|
{
|
||||||
|
registerNames.push("from");
|
||||||
|
registerNames.push("Master");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recipient === 1)
|
||||||
|
{
|
||||||
|
registerNames.push("from");
|
||||||
|
//let slave = 2*256 + result[3];
|
||||||
|
let slave = address;
|
||||||
|
|
||||||
|
registerNames.push( slave );
|
||||||
|
}
|
||||||
|
|
||||||
|
registerNames.push( "(WRITE: " + result.join(", ") + ")" );
|
||||||
|
|
||||||
|
let registerName = registerNames.join(" ");
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
command: {
|
||||||
|
//registerNumber: this.state.registerNumber,
|
||||||
|
//registerName: found.registerName + " (WRITE: " + result.join(", ") + ")",
|
||||||
|
registerName: registerName,
|
||||||
|
direction: "in",
|
||||||
|
type: "command",
|
||||||
|
date: new Date()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//co zapisujeme?
|
||||||
|
this.props.addCommand(params);
|
||||||
|
|
||||||
|
let url = '/cmd';
|
||||||
|
//if(window.location.hostname === "localhost") url = "http://localhost:5000/cmd";
|
||||||
|
if(window.location.hostname === "localhost")
|
||||||
|
{
|
||||||
|
//url = "http://localhost:5000/cmd";
|
||||||
|
url = "http://10.0.0.5:5000/cmd";
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
requestToHost: url
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(url);
|
||||||
|
|
||||||
|
//make http request
|
||||||
|
axios(url,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'no-cors',
|
||||||
|
data: paramsToSend,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
//"Content-Type": "text/html;charset=UTF-8"
|
||||||
|
},
|
||||||
|
withCredentials: false,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
//HANDLE response
|
||||||
|
console.log("RESPONSE", response.data.messages);
|
||||||
|
//alert(response.data.hostname);
|
||||||
|
|
||||||
|
//multiple messages
|
||||||
|
if(Array.isArray(response.data.messages))
|
||||||
|
{
|
||||||
|
|
||||||
|
for(let i = 0; i < response.data.messages.length; i++)
|
||||||
|
{
|
||||||
|
let date = null;
|
||||||
|
let m = response.data.messages[i];
|
||||||
|
let message;
|
||||||
|
let type;
|
||||||
|
|
||||||
|
if(typeof m === 'object')
|
||||||
|
{
|
||||||
|
if ("date" in m)
|
||||||
|
{
|
||||||
|
date = new Date(m.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
message = m.message;
|
||||||
|
type = m.type;
|
||||||
|
|
||||||
|
if(typeof message === 'object')
|
||||||
|
{
|
||||||
|
message = message.message;
|
||||||
|
type = message.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
message = m;
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
command: {
|
||||||
|
responsefromHost: response.data.hostname,
|
||||||
|
direction: "out",
|
||||||
|
type: type,
|
||||||
|
message: message,
|
||||||
|
date: date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.addCommand(params);
|
||||||
|
|
||||||
|
let hostInfo = response.data.hostname;
|
||||||
|
if(hostInfo === "localhost") hostInfo = <span style = {{color: "green"}}>{hostInfo}</span>
|
||||||
|
else if(hostInfo !== "localhost") hostInfo = <span style = {{color: "red"}}>{hostInfo}</span>
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
responsefromHost: hostInfo
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
command: {
|
||||||
|
direction: "out",
|
||||||
|
type: response.data.type,
|
||||||
|
message: response.data.message,
|
||||||
|
date: new Date()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.addCommand(params);
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
|
||||||
|
//http request err
|
||||||
|
const message = error + "";
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
command: {
|
||||||
|
direction: "out",
|
||||||
|
type: "error",
|
||||||
|
message: message,
|
||||||
|
date: new Date()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.addCommand(params);
|
||||||
|
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleClear = event => {
|
||||||
|
this.props.clearState();
|
||||||
|
};
|
||||||
|
|
||||||
|
buildTasks = (rw, recipient) =>{
|
||||||
|
|
||||||
|
let tasks = [];
|
||||||
|
for (let i = 0; i < data.config.length; i++) {
|
||||||
|
|
||||||
|
let registerNumber = data.config[i][0];
|
||||||
|
let masterSlaveFlag = data.config[i][1];
|
||||||
|
let rwFlag = data.config[i][2];
|
||||||
|
let registerName = data.config[i][3];
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (rwFlag.includes(rw)) {
|
||||||
|
if (recipient === masterSlaveFlag){
|
||||||
|
tasks.push({registerNumber: registerNumber, registerName: registerName});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
if (rwFlag.includes(rw)) {
|
||||||
|
//master
|
||||||
|
if (recipient === 0){
|
||||||
|
if (masterSlaveFlag === "0"){
|
||||||
|
tasks.push({registerNumber: registerNumber, registerName: registerName});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//slave / Broadcast 1, 2
|
||||||
|
if (masterSlaveFlag === "1"){
|
||||||
|
tasks.push({registerNumber: registerNumber, registerName: registerName});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
menuItemSelected = item =>{
|
||||||
|
this.props.handleCommand(item);
|
||||||
|
this.handleMenuClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMenuClose = event =>{
|
||||||
|
this.setState({
|
||||||
|
anchorEl: null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMenuClick = event =>{
|
||||||
|
//this.anchorEl = event.currentTarget;
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
anchorEl: event.currentTarget
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleTextFieldChange = event =>{
|
||||||
|
this.setState({
|
||||||
|
[event.target.name]: event.target.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
handleChange = event => {
|
||||||
|
|
||||||
|
let name = event.target.name;
|
||||||
|
let value = event.target.value;
|
||||||
|
|
||||||
|
let rw = this.state.rw;
|
||||||
|
let recipient = this.state.recipient;
|
||||||
|
let registerNumber = this.state.registerNumber;
|
||||||
|
|
||||||
|
let obj = {
|
||||||
|
...this.state,
|
||||||
|
[name]: value,
|
||||||
|
}
|
||||||
|
|
||||||
|
if(name === "rw") rw = value;
|
||||||
|
if(name === "registerNumber") registerNumber = value;
|
||||||
|
if(name === "recipient")
|
||||||
|
{
|
||||||
|
//slave
|
||||||
|
if(value === 1) obj.showAddress = true;
|
||||||
|
else obj.showAddress = false;
|
||||||
|
|
||||||
|
recipient = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let tasks = this.buildTasks(rw, recipient);
|
||||||
|
|
||||||
|
if(name !== "registerNumber")
|
||||||
|
{
|
||||||
|
//tasks was rebuil, set first element
|
||||||
|
console.log(tasks);
|
||||||
|
|
||||||
|
if(tasks.length > 0)
|
||||||
|
{
|
||||||
|
registerNumber = tasks[0].registerNumber;
|
||||||
|
obj.registerNumber = registerNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//clear bit values and set labels
|
||||||
|
if(this.state.registerNumber !== registerNumber)
|
||||||
|
{
|
||||||
|
|
||||||
|
for(let i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
let key = "byte" + (i + 1);
|
||||||
|
|
||||||
|
obj[key] = "";
|
||||||
|
obj[key + "Text"] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const found = data.config.find(element => element[0] === registerNumber);
|
||||||
|
if(found && rw === "W")
|
||||||
|
{
|
||||||
|
var bytes = found.slice(4, 8);
|
||||||
|
|
||||||
|
for(let i = 0; i < bytes.length; i++)
|
||||||
|
{
|
||||||
|
let key = "byte" + (i + 1);
|
||||||
|
let value = bytes[i];
|
||||||
|
|
||||||
|
if(value === "RES.") value = "";
|
||||||
|
|
||||||
|
obj[key] = "";
|
||||||
|
obj[key + "Text"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.log(obj);
|
||||||
|
|
||||||
|
obj.tasks = tasks;
|
||||||
|
|
||||||
|
this.setState(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let MenuItemTasks = [];
|
||||||
|
for (var i = 0; i < this.state.tasks.length; i++) {
|
||||||
|
MenuItemTasks.push( <MenuItem value={this.state.tasks[i].registerNumber}>{this.state.tasks[i].registerName}</MenuItem> );
|
||||||
|
}
|
||||||
|
|
||||||
|
let address;
|
||||||
|
if(this.state.showAddress)
|
||||||
|
{
|
||||||
|
address = <TextField onChange={this.handleTextFieldChange} name = "address" value={this.state.address} style = {{display: 'flex'}} label="Address" variant="outlined" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = [];
|
||||||
|
const found = this.state.tasks.find(element => element.registerNumber === this.state.registerNumber);
|
||||||
|
if(found !== undefined && this.state.rw === "W")
|
||||||
|
{
|
||||||
|
for(i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
let key = "byte" + (i + 1);
|
||||||
|
|
||||||
|
//byte1 MSB = data3, byte2 = data2, byte3 = data1, byte4 = data0 LSB
|
||||||
|
|
||||||
|
let byteDescription = "byte" + (i + 1);
|
||||||
|
if(i === 0) byteDescription = byteDescription + " (MSB)";
|
||||||
|
if(i === 3) byteDescription = byteDescription + " (LSB)";
|
||||||
|
|
||||||
|
let str = this.state[key + "Text"] + ": " + byteDescription;
|
||||||
|
|
||||||
|
if(str !== "")
|
||||||
|
{
|
||||||
|
let byte = <TextField name = {key} onChange={this.handleTextFieldChange} value={this.state[key]} style = {{display: 'flex'}} id="outlined-basic" label={str} variant="outlined" />;
|
||||||
|
bytes.push(<Grid item xs={12} sm={12} md={12} lg={6}>{byte}</Grid>);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let index;
|
||||||
|
//Node XX Serial Number Register
|
||||||
|
//console.log(this.state.registerNumber);
|
||||||
|
if(this.state.rw === "R" && this.state.registerNumber === "128")
|
||||||
|
{
|
||||||
|
let key = "index";
|
||||||
|
let str = "Index";
|
||||||
|
//console.log(this.state.registerNumber);
|
||||||
|
index = <TextField name = {key} onChange={this.handleTextFieldChange} value={this.state[key]} style = {{display: 'flex'}} id="outlined-basic" label={str} variant="outlined" />;
|
||||||
|
index = <Grid item xs={12} sm={12} md={12} lg={12}>{index}</Grid>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={ (divElement) => { this.divElement = divElement } }>
|
||||||
|
<Card variant="outlined">
|
||||||
|
<CardContent>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
aria-label="more"
|
||||||
|
aria-controls="long-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={this.handleMenuClick}
|
||||||
|
>
|
||||||
|
<MoreVertIcon />
|
||||||
|
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
<Menu
|
||||||
|
id="simple-menu"
|
||||||
|
anchorEl={this.state.anchorEl}
|
||||||
|
keepMounted
|
||||||
|
open={Boolean(this.state.anchorEl)}
|
||||||
|
onClose={this.handleMenuClose}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={ () =>this.menuItemSelected('settings')}>Nastavenia</MenuItem>
|
||||||
|
<MenuItem onClick={this.handleMenuClose}>Logout</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
aria-label="more"
|
||||||
|
aria-controls="long-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
|
||||||
|
>
|
||||||
|
|
||||||
|
{this.props.title}
|
||||||
|
</IconButton>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Typography color="textSecondary">
|
||||||
|
|
||||||
|
</Typography>
|
||||||
|
<>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item xs={12} sm={12} md={6} lg={4}>
|
||||||
|
<InputLabel id="rw-select-label">Read/Write</InputLabel>
|
||||||
|
<Select
|
||||||
|
style = {{display: 'flex'}}
|
||||||
|
labelId="rw-select-label"
|
||||||
|
id="rw"
|
||||||
|
name="rw"
|
||||||
|
value = {this.state.rw}
|
||||||
|
//value={this.state.doba_uveru_v_mesiacoch}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem value={"R"}>Read</MenuItem>
|
||||||
|
<MenuItem value={"W"}>Write</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={12} md={6} lg={4}>
|
||||||
|
<InputLabel id="recipient-select-label">Recip.</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="recipient-select-label"
|
||||||
|
id="recipient"
|
||||||
|
name ="recipient"
|
||||||
|
value = {this.state.recipient}
|
||||||
|
style = {{display: 'flex'}}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
>
|
||||||
|
<MenuItem value={0}>Master</MenuItem>
|
||||||
|
<MenuItem value={1}>Slave</MenuItem>
|
||||||
|
<MenuItem value={2}>Broadcast</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12} sm={12} md={12} lg={4}>
|
||||||
|
<InputLabel id="demo-controlled-open-select-label">Task</InputLabel>
|
||||||
|
<Select
|
||||||
|
labelId="demo-controlled-open-select-label"
|
||||||
|
style = {{display: 'flex'}}
|
||||||
|
id="registerNumber"
|
||||||
|
name="registerNumber"
|
||||||
|
value = {this.state.registerNumber}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
>
|
||||||
|
{MenuItemTasks}
|
||||||
|
</Select>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={12} sm={12} md={12} lg={12}>
|
||||||
|
Request to: {this.state.requestToHost} <br/> response from: {this.state.responsefromHost}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
{bytes}
|
||||||
|
|
||||||
|
{index}
|
||||||
|
|
||||||
|
<Grid item xs={12} sm={12} md={12} lg={12}>
|
||||||
|
{address}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</>
|
||||||
|
</CardContent>
|
||||||
|
<CardActions>
|
||||||
|
<Button onClick = {this.handleClick} variant="contained" color="primary" style = {{display: 'flex'}} component="span">
|
||||||
|
Send
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button onClick = {this.handleClear} variant="contained" color="primary" style = {{display: 'flex'}} component="span">
|
||||||
|
Clear
|
||||||
|
</Button>
|
||||||
|
</CardActions>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
addCommand: (params) => dispatch ({
|
||||||
|
type: actionTypes.ADD_COMMAND,
|
||||||
|
payload: {
|
||||||
|
command: params.command
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
clearState: (params) => dispatch ({
|
||||||
|
type: actionTypes.CLEAR_STATE,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(Controls);
|
||||||
13
src/index.css
Normal file
13
src/index.css
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
|
monospace;
|
||||||
|
}
|
||||||
22
src/index.js
Normal file
22
src/index.js
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import './index.css';
|
||||||
|
import App from './App';
|
||||||
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
|
||||||
|
import { createStore } from 'redux';
|
||||||
|
import { Provider } from 'react-redux'
|
||||||
|
import reducer from './store/reducer'
|
||||||
|
const store = createStore(reducer);
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<Provider store = {store}>
|
||||||
|
<App />
|
||||||
|
</Provider>,
|
||||||
|
document.getElementById('root')
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
|
reportWebVitals();
|
||||||
1
src/logo.svg
Normal file
1
src/logo.svg
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
108
src/output.js
Normal file
108
src/output.js
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
import React, {Component} from 'react'
|
||||||
|
import {connect} from 'react-redux'
|
||||||
|
import { AnimatedList } from 'react-animated-list';
|
||||||
|
import * as actionTypes from './store/actions'
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
class Output extends Component {
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = { commands: [] }
|
||||||
|
|
||||||
|
this.messagesEndRef = React.createRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount () {
|
||||||
|
this.scrollToBottom()
|
||||||
|
}
|
||||||
|
componentDidUpdate () {
|
||||||
|
this.scrollToBottom()
|
||||||
|
}
|
||||||
|
scrollToBottom = () => {
|
||||||
|
this.messagesEndRef.current.scrollIntoView({ behavior: 'smooth' })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
let responsefromHostWasShow = true;//obsolete
|
||||||
|
const items = this.props.commands.map(item => {
|
||||||
|
|
||||||
|
let dateString = "";
|
||||||
|
if("date" in item)
|
||||||
|
{
|
||||||
|
if(item.date != null) dateString = "[" + moment(item.date).format('DD.MM.YYYY hh.mm.ss') + "] ";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item.direction === "in")
|
||||||
|
{
|
||||||
|
const container = <div key={index} style={{color: "white", backgroundColor: '#484848', width: "100%", padding: "5px"}}>[{dateString}] COMMAND: {item.registerName}</div>;
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
else if (item.direction === "out")
|
||||||
|
{
|
||||||
|
//RESPONSE, ERROR, EVENT, UNKNOWN
|
||||||
|
|
||||||
|
let color = '#95FE35';//RESPONSE
|
||||||
|
if(item.type === "ERROR") color = 'red';
|
||||||
|
|
||||||
|
let responsefromHost;
|
||||||
|
if(!responsefromHostWasShow)
|
||||||
|
{
|
||||||
|
responsefromHost = (<div key={index} style={{color: "#0066ff", backgroundColor: '#00ffff', width: "100%", padding: "5px"}}><b>RESPONSE FROM HOST: {item.responsefromHost}</b></div>);
|
||||||
|
responsefromHostWasShow = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const container = (
|
||||||
|
<>
|
||||||
|
{responsefromHost}
|
||||||
|
<div key={index} style={{color: "yellow", backgroundColor: '#484848', width: "100%", padding: "5px"}}>
|
||||||
|
{dateString}
|
||||||
|
<span style = {{color: color}}>RESPONSE:</span> {item.message}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
index++;
|
||||||
|
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AnimatedList animation={"grow"}>
|
||||||
|
{items}
|
||||||
|
</AnimatedList>
|
||||||
|
<div ref={this.messagesEndRef} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
addCommand: (params) => dispatch ({
|
||||||
|
type: actionTypes.ADD_COMMAND,
|
||||||
|
payload: {
|
||||||
|
command: params.command
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
clearState: (params) => dispatch ({
|
||||||
|
type: actionTypes.CLEAR_STATE,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return{
|
||||||
|
commands: state.commands,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(Output);
|
||||||
13
src/reportWebVitals.js
Normal file
13
src/reportWebVitals.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
const reportWebVitals = onPerfEntry => {
|
||||||
|
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||||
|
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||||
|
getCLS(onPerfEntry);
|
||||||
|
getFID(onPerfEntry);
|
||||||
|
getFCP(onPerfEntry);
|
||||||
|
getLCP(onPerfEntry);
|
||||||
|
getTTFB(onPerfEntry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reportWebVitals;
|
||||||
5
src/setupTests.js
Normal file
5
src/setupTests.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||||
|
// allows you to do things like:
|
||||||
|
// expect(element).toHaveTextContent(/react/i)
|
||||||
|
// learn more: https://github.com/testing-library/jest-dom
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
2
src/store/actions.js
Normal file
2
src/store/actions.js
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
export const ADD_COMMAND = 'ADD_COMMAND';
|
||||||
|
export const CLEAR_STATE = 'CLEAR_STATE';
|
||||||
23
src/store/reducer.js
Normal file
23
src/store/reducer.js
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import * as actionTypes from './actions';
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
commands: [],
|
||||||
|
}
|
||||||
|
|
||||||
|
const reducer = (state = initialState, action) =>{
|
||||||
|
//console.log(action.type, action.payload );
|
||||||
|
if(action.type === actionTypes.ADD_COMMAND){
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
commands: state.commands.concat(action.payload.command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(action.type === actionTypes.CLEAR_STATE){
|
||||||
|
return {commands: []};
|
||||||
|
}
|
||||||
|
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reducer;
|
||||||
248
src/util/db/SqlQueryBuilder.js
Normal file
248
src/util/db/SqlQueryBuilder.js
Normal file
|
|
@ -0,0 +1,248 @@
|
||||||
|
|
||||||
|
export const LogicOperator = {
|
||||||
|
UndefOperator: '',
|
||||||
|
And: "AND",
|
||||||
|
Or: "OR"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Function = {
|
||||||
|
UndefFn: 'UndefFn',
|
||||||
|
Min: "Min",
|
||||||
|
Max: "Max",
|
||||||
|
Avg: "Avg"
|
||||||
|
}
|
||||||
|
|
||||||
|
class SqlQueryBuilder{
|
||||||
|
|
||||||
|
className = "SqlQueryBuilder";
|
||||||
|
type = "SELECT";
|
||||||
|
|
||||||
|
queryData = {
|
||||||
|
columns: [],
|
||||||
|
tables: [],
|
||||||
|
wheres: [],
|
||||||
|
variables: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
select(column, alias, fn)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
SqlQueryData::Column col;
|
||||||
|
col.column = column;
|
||||||
|
col.alias = alias;
|
||||||
|
col.func = fn;
|
||||||
|
|
||||||
|
queryData.columns.append(col);
|
||||||
|
return this;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(Array.isArray(column))
|
||||||
|
{
|
||||||
|
for(let i = 0; i < column.length; i++)
|
||||||
|
{
|
||||||
|
let c = column[i];
|
||||||
|
|
||||||
|
let col;
|
||||||
|
let alias;
|
||||||
|
let fn;
|
||||||
|
|
||||||
|
if(typeof c == "string") col = c;
|
||||||
|
if(col === undefined) continue;
|
||||||
|
|
||||||
|
this.select(col, alias, fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SqlQueryData_Column = {
|
||||||
|
column: column,
|
||||||
|
alias: alias,
|
||||||
|
func: fn
|
||||||
|
};
|
||||||
|
|
||||||
|
this.queryData.columns.push(SqlQueryData_Column);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
from(table, alias)
|
||||||
|
{
|
||||||
|
|
||||||
|
const SqlQueryData_Table = {
|
||||||
|
table: table,
|
||||||
|
alias: alias
|
||||||
|
};
|
||||||
|
|
||||||
|
this.queryData.tables.push(SqlQueryData_Table);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
where(cond, op = LogicOperator.And)
|
||||||
|
{
|
||||||
|
//queryBuilderTmp->where("`date` >= :date1", SqlQueryBuilder::And);
|
||||||
|
if(LogicOperator === undefined) op = LogicOperator.And;
|
||||||
|
|
||||||
|
const SqlQueryData_Where = {
|
||||||
|
cond: cond,
|
||||||
|
operation: op
|
||||||
|
};
|
||||||
|
|
||||||
|
this.queryData.wheres.push(SqlQueryData_Where);
|
||||||
|
}
|
||||||
|
|
||||||
|
setParameter(key, value)
|
||||||
|
{
|
||||||
|
this.queryData.variables[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSql()
|
||||||
|
{
|
||||||
|
let sql = this.type + " ";
|
||||||
|
|
||||||
|
if(this.queryData.tables.length === 0)
|
||||||
|
{
|
||||||
|
throw "SqlQueryBuilder::queryData.tables.length === 0";
|
||||||
|
}
|
||||||
|
|
||||||
|
// blok stlpcov
|
||||||
|
if(this.type === "SELECT")
|
||||||
|
{
|
||||||
|
if(this.queryData.columns.length === 0) sql = sql + "*";
|
||||||
|
}
|
||||||
|
|
||||||
|
let params = [];
|
||||||
|
for(let i = 0; i < this.queryData.columns.length; i++)
|
||||||
|
{
|
||||||
|
let col = this.queryData.columns[i];
|
||||||
|
|
||||||
|
let column = col.column;
|
||||||
|
|
||||||
|
params.push("`" + column + "`");
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = sql + params.join(',');
|
||||||
|
|
||||||
|
sql = sql + " FROM ";
|
||||||
|
|
||||||
|
params = [];
|
||||||
|
for(let i = 0; i < this.queryData.tables.length; i++)
|
||||||
|
{
|
||||||
|
let table = this.queryData.tables[i];
|
||||||
|
|
||||||
|
params.push("`" + table.table + "`");
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = sql + params.join(',');
|
||||||
|
|
||||||
|
//WHERE
|
||||||
|
if(this.queryData.wheres.length > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
let size = this.queryData.wheres.length;
|
||||||
|
|
||||||
|
sql = sql + " WHERE ";
|
||||||
|
|
||||||
|
for(let i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
let where = this.queryData.wheres[i];
|
||||||
|
sql = sql + where.cond;
|
||||||
|
|
||||||
|
if (where.operation !== LogicOperator.UndefOperator)
|
||||||
|
{
|
||||||
|
if(i < (size - 1))
|
||||||
|
{
|
||||||
|
if (where.operation === LogicOperator.And)
|
||||||
|
{
|
||||||
|
sql = sql + " AND ";
|
||||||
|
}
|
||||||
|
else if (where.operation === LogicOperator.Or)
|
||||||
|
{
|
||||||
|
sql = sql + " OR ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sql;
|
||||||
|
}
|
||||||
|
|
||||||
|
serializeToJson()
|
||||||
|
{
|
||||||
|
return JSON.stringify({
|
||||||
|
className: "SqlQueryBuilder",
|
||||||
|
type: this.type,
|
||||||
|
queryData: this.queryData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//SqlQueryBuilder* select(const QString &column, const QString &alias = QString(), Function fn = UndefFn);
|
||||||
|
//SqlQueryBuilder* from(const QString &table, const QString &alias = QString());
|
||||||
|
//SqlQueryBuilder* where(const QString &cond, LogicOperator op = UndefOperator);
|
||||||
|
//SqlQueryBuilder* join(const QString &joinWhat, const QString &cond = QString(), JoinType type = LeftJoin);
|
||||||
|
//SqlQueryBuilder* orderBy(const QString &name);
|
||||||
|
//SqlQueryBuilder* groupBy(const QString &name);
|
||||||
|
//SqlQueryBuilder* limit(int count);
|
||||||
|
//SqlQueryBuilder* limit(int from, int to);
|
||||||
|
//SqlQueryBuilder* ascend(Ascend asc = Ascending);
|
||||||
|
//SqlQueryBuilder* setParameters(const QMap<QString, QVariant> ¶ms);
|
||||||
|
//void clearParameters();
|
||||||
|
//QMap<QString, QVariant> getParameters();
|
||||||
|
//SqlQueryBuilder* setParameter(const QString &key, const QVariant &value);
|
||||||
|
//SqlQueryBuilder* removeParameter(const QString &key);
|
||||||
|
//void clear();
|
||||||
|
//void clear(SqlPart);
|
||||||
|
//QString getSql(bool showError = true) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Query data storage,
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct SqlQueryData
|
||||||
|
{
|
||||||
|
SqlQueryData() = default;
|
||||||
|
SqlQueryData(const SqlQueryData& other)
|
||||||
|
{
|
||||||
|
hasLimit = other.hasLimit;
|
||||||
|
asc = other.asc;
|
||||||
|
columns = other.columns;
|
||||||
|
tables = other.tables;
|
||||||
|
wheres = other.wheres;
|
||||||
|
joins = other.joins;
|
||||||
|
orderByes = other.orderByes;
|
||||||
|
groupByes = other.groupByes;
|
||||||
|
connectionName = other.connectionName;
|
||||||
|
variables = other.variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Column { QString column, alias; SqlQueryBuilder::Function func; };
|
||||||
|
struct Table { QString table, alias; };
|
||||||
|
struct Join { SqlQueryBuilder::JoinType type; QString cond, what; };
|
||||||
|
struct Where { QString cond; SqlQueryBuilder::LogicOperator operation; };
|
||||||
|
|
||||||
|
struct Limit { bool range; int from, to, count; } limit;
|
||||||
|
bool hasLimit = false;
|
||||||
|
|
||||||
|
SqlQueryBuilder::Ascend asc;
|
||||||
|
|
||||||
|
QList<Column> columns;
|
||||||
|
QList<Table> tables;
|
||||||
|
QList<Where> wheres;
|
||||||
|
QList<Join> joins;
|
||||||
|
QStringList orderByes;
|
||||||
|
QStringList groupByes;
|
||||||
|
|
||||||
|
QString connectionName = "";
|
||||||
|
|
||||||
|
QMap<QString, QVariant> variables;
|
||||||
|
} queryData;
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SqlQueryBuilder;
|
||||||
300
src/util/db/db.js
Normal file
300
src/util/db/db.js
Normal file
|
|
@ -0,0 +1,300 @@
|
||||||
|
import axios from 'axios'
|
||||||
|
//import moment from 'moment'
|
||||||
|
|
||||||
|
class DB{
|
||||||
|
static token = "";
|
||||||
|
static company = "";
|
||||||
|
static connectionName = "";
|
||||||
|
static db_structure = "";
|
||||||
|
static backendUrl = '/backend/db_connector.php';
|
||||||
|
|
||||||
|
data = [];
|
||||||
|
transaction = false;
|
||||||
|
|
||||||
|
updateJsonTypes(arr, table)
|
||||||
|
{
|
||||||
|
let table_structure;
|
||||||
|
if(DB.db_structure !== undefined)
|
||||||
|
{
|
||||||
|
table_structure = DB.db_structure[table];
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = [];
|
||||||
|
let index = 0;
|
||||||
|
for(let i = 0; i < arr.length; ++i)
|
||||||
|
{
|
||||||
|
let record = arr[i];
|
||||||
|
|
||||||
|
|
||||||
|
if(table_structure !== undefined)
|
||||||
|
{
|
||||||
|
let keys = Object.keys(record);
|
||||||
|
for(let ii = 0; ii < keys.length; ii++)
|
||||||
|
{
|
||||||
|
let key = keys[ii];
|
||||||
|
if(table_structure[key] === undefined)
|
||||||
|
{
|
||||||
|
console.log("updateJsonTypes - undefined key", table, key);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(table_structure[key]["type"] === "uint" || table_structure[key]["type"] === "int")
|
||||||
|
{
|
||||||
|
record[key] = parseInt(record[key]);
|
||||||
|
}
|
||||||
|
else if(table_structure[key]["type"] === "double")
|
||||||
|
{
|
||||||
|
record[key] = parseFloat(record[key]);
|
||||||
|
}
|
||||||
|
else if(table_structure[key]["type"] === "QDateTime")
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(table_structure[key]["type"] === "char")
|
||||||
|
{
|
||||||
|
if(table_structure[key]["length"] === 1)
|
||||||
|
{
|
||||||
|
//boolean
|
||||||
|
let value = parseInt(record[key]);
|
||||||
|
//TODO use translation
|
||||||
|
if(value === 0) record[key] = "nie";
|
||||||
|
else record[key] = "áno";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(table_structure[key]["type"] === "QDate")
|
||||||
|
{
|
||||||
|
let d = new Date(record[key]);
|
||||||
|
record["_" + key] = record[key];//to preserve original value
|
||||||
|
//record[key] = moment(d).format('DD.MM.YYYY');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("no table structure provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
record._index = index;
|
||||||
|
result.push(record);
|
||||||
|
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbSelect(data, exec = false, error_message = "")
|
||||||
|
{
|
||||||
|
//
|
||||||
|
//let obj = {type: "select", error_message: error_message};
|
||||||
|
//this.data.push(obj);
|
||||||
|
|
||||||
|
//data can be string, or object SqlQueryBuilder!!!
|
||||||
|
//TODO push
|
||||||
|
|
||||||
|
//or sql as string
|
||||||
|
if((typeof data) == "object")
|
||||||
|
{
|
||||||
|
if(data.className === "SqlQueryBuilder")
|
||||||
|
{
|
||||||
|
//if(error_message === undefined) error_message = "update pre tabulku " + table + " zlyhal";
|
||||||
|
|
||||||
|
//run later
|
||||||
|
if(exec === false)
|
||||||
|
{
|
||||||
|
let obj = {type: "select", className: "SqlQueryBuilder", obj: data, error_message: error_message};
|
||||||
|
this.data.push(obj);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((typeof data) == "string")
|
||||||
|
{
|
||||||
|
//alert("str");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let obj = {
|
||||||
|
token: DB.token,
|
||||||
|
company: DB.company,
|
||||||
|
connectionName: DB.connectionName,
|
||||||
|
type: "select",
|
||||||
|
data: data,
|
||||||
|
error_message: error_message
|
||||||
|
}
|
||||||
|
|
||||||
|
let json = JSON.stringify(obj);
|
||||||
|
|
||||||
|
if(DB.backendUrl === undefined || DB.backendUrl === "")
|
||||||
|
{
|
||||||
|
reject("Nie je definovaný endpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
axios(DB.backendUrl,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'no-cors',
|
||||||
|
data: json,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
withCredentials: false,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
|
||||||
|
let success = response.data.success;
|
||||||
|
|
||||||
|
if(!success)
|
||||||
|
{
|
||||||
|
//console.log(response.data);
|
||||||
|
let message = response.data.message;
|
||||||
|
if(message === undefined) message = "nedefinovaná chyba";
|
||||||
|
|
||||||
|
throw message;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(success)
|
||||||
|
{
|
||||||
|
resolve( response.data.result );
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const message = error + "";
|
||||||
|
|
||||||
|
reject(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dbStartTransaction()
|
||||||
|
{
|
||||||
|
let obj = {type: "START TRANSACTION"};
|
||||||
|
this.data.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbCommitTransaction()
|
||||||
|
{
|
||||||
|
let obj = {type: "COMMIT"};
|
||||||
|
this.data.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbDelete(table, conditions, error_message)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(Number.isInteger(conditions))
|
||||||
|
{
|
||||||
|
conditions = {"id": conditions};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error_message === undefined) error_message = "zlyhalo zmazanie z tabulky " + table;
|
||||||
|
let obj = {type: "delete", table: table, conditions: conditions, error_message: error_message};
|
||||||
|
this.data.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbInsert(data, table, foreign_keys, error_message) {
|
||||||
|
//console.log(data, table, condition);
|
||||||
|
|
||||||
|
//foreign key: table: lastInsertedId
|
||||||
|
//foreign_keys: {"subject_id": {"subject": "id"}}
|
||||||
|
if(foreign_keys === undefined) foreign_keys = {};
|
||||||
|
|
||||||
|
//token
|
||||||
|
if(error_message === undefined) error_message = "insert pre tabulku " + table + " zlyhal";
|
||||||
|
let obj = {type: "insert", foreign_keys: foreign_keys, table: table, params: {...data}, error_message: error_message};
|
||||||
|
this.data.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbUpdate(data, table, condition, error_message) {
|
||||||
|
//console.log(data, table, condition);
|
||||||
|
|
||||||
|
//token
|
||||||
|
if(error_message === undefined) error_message = "update pre tabulku " + table + " zlyhal";
|
||||||
|
let obj = {type: "update", table: table, params: {...data}, condition: condition, error_message: error_message};
|
||||||
|
this.data.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
exec()
|
||||||
|
{
|
||||||
|
//build json and send to server
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
let obj = {
|
||||||
|
token: DB.token,
|
||||||
|
company: DB.company,
|
||||||
|
connectionName: DB.connectionName,
|
||||||
|
data: this.data
|
||||||
|
}
|
||||||
|
|
||||||
|
let json = JSON.stringify(obj);
|
||||||
|
|
||||||
|
if(DB.backendUrl === undefined)
|
||||||
|
{
|
||||||
|
reject("Nie je definovaný endpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
axios(DB.backendUrl,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'no-cors',
|
||||||
|
data: json,
|
||||||
|
headers: {
|
||||||
|
'Access-Control-Allow-Origin': '*',
|
||||||
|
"Content-Type": "text/html;charset=UTF-8"
|
||||||
|
},
|
||||||
|
withCredentials: false,
|
||||||
|
credentials: 'same-origin',
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
|
||||||
|
//console.log(response);
|
||||||
|
|
||||||
|
if(!response.data.sucess)
|
||||||
|
{
|
||||||
|
//alert(response.data.error_message);
|
||||||
|
console.log(response);
|
||||||
|
|
||||||
|
let errors = [];
|
||||||
|
if("data" in response)
|
||||||
|
{
|
||||||
|
if(Array.isArray(response.data.result))
|
||||||
|
{
|
||||||
|
for(let i = 0; i < response.data.result.length; ++i)
|
||||||
|
{
|
||||||
|
if(!response.data.result[i].sucess) errors.push(response.data.result[i].error_message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(response.data.sucess)
|
||||||
|
{
|
||||||
|
resolve(response.data.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
const message = error + "";
|
||||||
|
|
||||||
|
console.log("catsh", message, error);
|
||||||
|
|
||||||
|
reject(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DB;
|
||||||
14
src/util/findGetParameterInUrl.js
Normal file
14
src/util/findGetParameterInUrl.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
function findGetParameterInUrl(parameterName) {
|
||||||
|
var result = null,
|
||||||
|
tmp = [];
|
||||||
|
window.location.search
|
||||||
|
.substr(1)
|
||||||
|
.split("&")
|
||||||
|
.forEach(function (item) {
|
||||||
|
tmp = item.split("=");
|
||||||
|
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default findGetParameterInUrl
|
||||||
11
src/util/isLocalhost.js
Normal file
11
src/util/isLocalhost.js
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
const isLocalhost = Boolean(
|
||||||
|
window.location.hostname === 'localhost' ||
|
||||||
|
// [::1] is the IPv6 localhost address.
|
||||||
|
window.location.hostname === '[::1]' ||
|
||||||
|
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||||
|
window.location.hostname.match(
|
||||||
|
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
export default isLocalhost;
|
||||||
15
src/util/isMobile.js
Normal file
15
src/util/isMobile.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
function isMobile()
|
||||||
|
{
|
||||||
|
var isMobile = false; //initiate as false
|
||||||
|
// device detection
|
||||||
|
if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)
|
||||||
|
|| /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4))) {
|
||||||
|
isMobile = true;
|
||||||
|
|
||||||
|
return isMobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return isMobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default isMobile;
|
||||||
Loading…
Add table
Add a link
Reference in a new issue