pagination + sql expressions + frontend improvements

This commit is contained in:
2023-01-19 18:12:16 +01:00
parent 878cd62bbe
commit 92c78356ed
16 changed files with 216 additions and 71 deletions

View File

@@ -24,4 +24,13 @@
.data-table-clickable {
cursor: pointer;
}
.pagination-controls {
margin-top: 6px;
}
.pagination-page-size > div {
padding-top: 5px;
padding-bottom: 5px;
}

View File

@@ -85,8 +85,10 @@ export function DataTable(props) {
}
const numColumns = columns.length;
let numRows = 0;
let rows = [];
if (data && data?.length) {
numRows = data.length;
for (const [rowIndex, entry] of data.entries()) {
let row = [];
for (const [index, column] of columns.entries()) {
@@ -96,14 +98,14 @@ export function DataTable(props) {
}
rows.push(<TableRow className={clsx({["data-table-clickable"]: typeof onClick === 'function'})}
onClick={() => onRowClick(rowIndex, entry)}
onClick={(e) => ["tr","td"].includes(e.target.tagName.toLowerCase()) && onRowClick(rowIndex, entry)}
key={"row-" + rowIndex}>
{ row }
</TableRow>);
}
} else if (placeholder) {
rows.push(<TableRow key={"row-placeholder"}>
<TableCell colSpan={numColumns}>
<TableCell colSpan={numColumns} align={"center"}>
{ placeholder }
</TableCell>
</TableRow>);
@@ -126,7 +128,7 @@ export function DataTable(props) {
{ rows }
</TableBody>
</Table>
{pagination.renderPagination(L, rows.length)}
{pagination.renderPagination(L, numRows)}
</Box>
}
@@ -140,7 +142,7 @@ export class DataColumn {
}
renderData(L, entry, index) {
return entry[this.field]
return typeof this.field === 'function' ? this.field(entry) : entry[this.field];
}
renderHead() {
@@ -228,14 +230,33 @@ export class ControlsColumn extends DataColumn {
renderData(L, entry, index) {
let buttonElements = [];
for (const [index, button] of this.buttons.entries()) {
let element = button.element;
let props = {
key: "button-" + index,
onClick: (() => button.onClick(entry)),
className: "data-table-clickable"
let element = typeof button.element === 'function'
? button.element(entry, index)
: button.element;
let buttonProps = {};
if (typeof button.props === 'function') {
buttonProps = button.props(entry, index);
} else {
buttonProps = button.props;
}
if (typeof button.showIf !== 'function' || button.showIf(entry)) {
let props = {
...buttonProps,
key: "button-" + index,
onClick: (e) => { e.stopPropagation(); button.onClick(entry, index); },
className: "data-table-clickable",
}
if (button.hasOwnProperty("disabled")) {
props.disabled = typeof button.disabled === 'function'
? button.disabled(entry, index)
: button.disabled;
}
if ((!button.hasOwnProperty("hidden")) ||
(typeof button.hidden === 'function' && !button.hidden(entry, index)) ||
(!button.hidden)) {
buttonElements.push(React.createElement(element, props))
}
}

View File

@@ -1,8 +1,14 @@
import React, {useContext} from "react";
import {Dialog as MuiDialog, DialogActions, DialogContent, DialogContentText, DialogTitle} from "@mui/material";
import {Button} from "@material-ui/core";
import {LocaleContext} from "../locale";
import "./dialog.css";
import React, {useState} from "react";
import {
Box,
Button,
Dialog as MuiDialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
Input, TextField
} from "@mui/material";
export default function Dialog(props) {
@@ -10,37 +16,55 @@ export default function Dialog(props) {
const onClose = props.onClose || function() { };
const onOption = props.onOption || function() { };
const options = props.options || ["Close"];
const type = props.type || "default";
const {translate: L} = useContext(LocaleContext);
const inputs = props.inputs || [];
const [inputData, setInputData] = useState({});
let buttons = [];
for (let name of options) {
let type = "default";
if (name === "Yes") type = "warning";
else if(name === "No") type = "danger";
for (const [index, name] of options.entries()) {
buttons.push(
<Button variant={"outlined"} size={"small"} type="button" key={"button-" + name}
data-dismiss={"modal"} onClick={() => { onClose(); onOption(name); }}>
<Button variant={"outlined"} size={"small"} key={"button-" + name}
onClick={() => { onClose(); onOption(index, inputData); }}>
{name}
</Button>
)
}
let inputElements = [];
for (const input of inputs) {
let inputProps = { ...input };
delete inputProps.name;
delete inputProps.type;
switch (input.type) {
case 'text':
inputElements.push(<TextField
{...inputProps}
size={"small"} fullWidth={true}
key={"input-" + input.name}
value={inputData[input.name] || ""}
onChange={e => setInputData({ ...inputData, [input.name]: e.target.value })}
/>)
break;
}
}
return <MuiDialog
open={show}
onClose={onClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description">
<DialogTitle>{ props.title }</DialogTitle>
onClose={onClose}>
<DialogTitle>
{ props.title }
</DialogTitle>
<DialogContent>
<DialogContentText>
{ props.message }
</DialogContentText>
<Box mt={2}>
{ inputElements }
</Box>
</DialogContent>
<DialogActions>
{buttons}
{ buttons }
</DialogActions>
</MuiDialog>
}