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