Initial commit

This commit is contained in:
rasta5man 2024-04-15 19:28:54 +02:00
commit a589741ec6
33 changed files with 4388 additions and 0 deletions

View 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>
);
}

View 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>
);
}

View 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;

View 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>
);
}

View 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;

View 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>
);
}

View 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>
);
}

View 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;