Add QBooleanFieldSwitch

This commit is contained in:
2022-10-04 11:36:11 -05:00
parent 44662d88b8
commit e67301dc4b
3 changed files with 183 additions and 32 deletions

View File

@ -0,0 +1,128 @@
/*
* QQQ - Low-code Application Framework for Engineers.
* Copyright (C) 2021-2022. Kingsrook, LLC
* 651 N Broad St Ste 205 # 6917 | Middletown DE 19709 | United States
* contact@kingsrook.com
* https://github.com/Kingsrook/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {InputAdornment, InputLabel} from "@mui/material";
import Box from "@mui/material/Box";
import Grid from "@mui/material/Grid";
import Stack from "@mui/material/Stack";
import {styled} from "@mui/material/styles";
import Switch from "@mui/material/Switch";
import Typography from "@mui/material/Typography";
import {ErrorMessage, Field, useFormikContext} from "formik";
import React, {SyntheticEvent, useState} from "react";
import MDBox from "qqq/components/Temporary/MDBox";
import MDInput from "qqq/components/Temporary/MDInput";
import MDTypography from "qqq/components/Temporary/MDTypography";
const AntSwitch = styled(Switch)(({theme}) => ({
width: 28,
height: 16,
padding: 0,
display: "flex",
"&:active": {
"& .MuiSwitch-thumb": {
width: 15,
},
"& .MuiSwitch-switchBase.Mui-checked": {
transform: "translateX(9px)",
},
},
"& .MuiSwitch-switchBase": {
padding: 2,
"&.Mui-checked": {
transform: "translateX(12px)",
color: "#fff",
"& + .MuiSwitch-track": {
opacity: 1,
backgroundColor: theme.palette.mode === "dark" ? "#177ddc" : "#1890ff",
},
},
},
"& .MuiSwitch-thumb": {
boxShadow: "0 2px 4px 0 rgb(0 35 11 / 20%)",
width: 12,
height: 12,
borderRadius: 6,
transition: theme.transitions.create([ "width" ], {
duration: 200,
}),
},
"& .MuiSwitch-track": {
borderRadius: 16 / 2,
opacity: 1,
backgroundColor:
theme.palette.mode === "dark" ? "rgba(255,255,255,.35)" : "rgba(0,0,0,.25)",
boxSizing: "border-box",
},
}));
interface Props
{
name: string;
label: string;
value: boolean;
isDisabled: boolean;
}
function QBooleanFieldSwitch({name, label, value, isDisabled}: Props) : JSX.Element
{
const {setFieldValue} = useFormikContext();
const setSwitch = (event: SyntheticEvent, newValue: boolean) =>
{
if(!isDisabled)
{
setFieldValue(name, newValue);
event.stopPropagation();
}
}
const toggleSwitch = () =>
{
setFieldValue(name, !value);
}
return (
<>
<InputLabel shrink={true}>{label}</InputLabel>
<Stack direction="row" spacing={1} alignItems="center">
<Typography
fontSize="0.875rem"
color={value === false ? "auto" : "#bfbfbf" }
onClick={(e) => setSwitch(e, false)}
sx={{cursor: value === false || isDisabled ? "inherit" : "pointer"}}>
No
</Typography>
<AntSwitch name={name} checked={value} onClick={toggleSwitch} disabled={isDisabled} />
<Typography
fontSize="0.875rem"
color={value === true ? "auto" : "#bfbfbf"}
onClick={(e) => setSwitch(e, true)}
sx={{cursor: value === true || isDisabled ? "inherit" : "pointer"}}>
Yes
</Typography>
</Stack>
</>
);
}
export default QBooleanFieldSwitch

View File

@ -19,11 +19,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {InputAdornment} from "@mui/material";
import Grid from "@mui/material/Grid";
import {InputAdornment, InputLabel} from "@mui/material";
import Box from "@mui/material/Box";
import Switch from "@mui/material/Switch";
import {ErrorMessage, Field} from "formik";
import React, {useState} from "react";
import {ErrorMessage, Field, useFormikContext} from "formik";
import React, {SyntheticEvent, useState} from "react";
import QBooleanFieldSwitch from "qqq/components/QDynamicFormField/QBooleanFieldSwitch";
import MDBox from "qqq/components/Temporary/MDBox";
import MDInput from "qqq/components/Temporary/MDInput";
import MDTypography from "qqq/components/Temporary/MDTypography";
@ -34,6 +35,7 @@ interface Props
label: string;
name: string;
displayFormat: string;
value: any;
type: string;
isEditable?: boolean;
[key: string]: any;
@ -42,11 +44,13 @@ interface Props
}
function QDynamicFormField({
label, name, displayFormat, bulkEditMode, bulkEditSwitchChangeHandler, type, isEditable, ...rest
label, name, displayFormat, value, bulkEditMode, bulkEditSwitchChangeHandler, type, isEditable, ...rest
}: Props): JSX.Element
{
const [switchChecked, setSwitchChecked] = useState(false);
const [isDisabled, setIsDisabled] = useState(!isEditable || bulkEditMode);
const [ switchChecked, setSwitchChecked ] = useState(false);
const [ isDisabled, setIsDisabled ] = useState(!isEditable || bulkEditMode);
const {setFieldValue} = useFormikContext();
const inputLabelProps = {};
if (type.toLowerCase().match("(date|time)"))
@ -61,8 +65,15 @@ function QDynamicFormField({
// @ts-ignore
inputProps.startAdornment = <InputAdornment position="start">$</InputAdornment>;
}
if (displayFormat && displayFormat.endsWith("%%"))
{
// @ts-ignore
inputProps.endAdornment = <InputAdornment position="end">%</InputAdornment>;
}
const field = () => (
const field = () =>
(type == "checkbox" ?
<QBooleanFieldSwitch name={name} label={label} value={value} isDisabled={isDisabled} /> :
<>
<Field {...rest} name={name} type={type} as={MDInput} variant="standard" label={label} InputLabelProps={inputLabelProps} InputProps={inputProps} fullWidth disabled={isDisabled} />
<MDBox mt={0.75}>
@ -84,22 +95,24 @@ function QDynamicFormField({
if (bulkEditMode)
{
return (
<MDBox mb={1.5}>
<Grid container>
<Grid item xs={1} alignItems="baseline" pt={1}>
<Box mb={1.5} display="flex" flexDirection="row">
<Box alignItems="baseline" pt={1}>
<Switch
id={`bulkEditSwitch-${name}`}
checked={switchChecked}
onClick={bulkEditSwitchChanged}
/>
</Grid>
<Grid item xs={11}>
</Box>
<Box width="100%">
{/* for checkboxes, if we put the whole thing in a label, we get bad overly aggressive toggling of the outer switch... */}
{(type == "checkbox" ?
field() :
<label htmlFor={`bulkEditSwitch-${name}`}>
{field()}
</label>
</Grid>
</Grid>
</MDBox>
)}
</Box>
</Box>
);
}
else
@ -116,7 +129,8 @@ QDynamicFormField.defaultProps = {
bulkEditMode: false,
isEditable: true,
bulkEditSwitchChangeHandler: () =>
{},
{
},
};
export default QDynamicFormField;

View File

@ -78,7 +78,7 @@ class QFilterUtils
/*******************************************************************************
** Convert a qqq criteria operator to one expected by the grid.
*******************************************************************************/
public static qqqCriteriaOperatorToGrid = (operator: QCriteriaOperator, fieldType: QFieldType = QFieldType.STRING): string =>
public static qqqCriteriaOperatorToGrid = (operator: QCriteriaOperator, fieldType: QFieldType = QFieldType.STRING, criteriaValues: any[]): string =>
{
switch (operator)
{
@ -93,6 +93,15 @@ class QFilterUtils
case QFieldType.DATE_TIME:
return ("equals");
case QFieldType.BOOLEAN:
if (criteriaValues && criteriaValues[0] === true)
{
return "isTrue";
}
else if (criteriaValues && criteriaValues[0] === false)
{
return "isFalse";
}
return "is";
case QFieldType.STRING:
case QFieldType.TEXT:
case QFieldType.HTML: