putting the grain form in the component form and adding a custom grain toggle, also tweaked the form to be just the form when no grains are saved and to use a search select and put the form in an accordion when there are saved custom grains

This commit is contained in:
csawatzky 2025-12-15 16:29:54 -06:00
parent d6c670fb78
commit fb1434f817
3 changed files with 116 additions and 45 deletions

View file

@ -4,6 +4,7 @@ import {
AccordionSummary, AccordionSummary,
Alert, Alert,
AlertTitle, AlertTitle,
Box,
Button, Button,
Collapse, Collapse,
FormControl, FormControl,
@ -47,6 +48,7 @@ import { getDistanceUnit } from "utils";
import { GrainOptions } from "grain"; import { GrainOptions } from "grain";
import CompModes from "component/ComponentMode.json"; import CompModes from "component/ComponentMode.json";
import FanPicker from "fans/fanPicker"; import FanPicker from "fans/fanPicker";
import CustomGrainForm from "grain/CustomGrainForm";
const useStyles = makeStyles((theme: Theme) => { const useStyles = makeStyles((theme: Theme) => {
return ({ return ({
@ -136,6 +138,7 @@ export default function ComponentForm(props: Props) {
sensorDistance: "0", sensorDistance: "0",
}); });
const [compMode, setCompMode] = useState<any>(); const [compMode, setCompMode] = useState<any>();
const [useCustomGrain, setUseCustomGrain] = useState<boolean>(false)
//const [numCalibrations, setNumCalibrations] = useState(0) //const [numCalibrations, setNumCalibrations] = useState(0)
useEffect(() => { useEffect(() => {
@ -192,6 +195,10 @@ export default function ComponentForm(props: Props) {
sensorDistance = sensorDistance / 30.48; sensorDistance = sensorDistance / 30.48;
} }
if(formComponent.settings.customGrain){
setUseCustomGrain(true)
}
setForm({ setForm({
component: formComponent, component: formComponent,
measure: formComponent.settings.measurementPeriodMs > 0, measure: formComponent.settings.measurementPeriodMs > 0,
@ -383,6 +390,14 @@ export default function ComponentForm(props: Props) {
setForm(f); setForm(f);
}; };
const updateCustomGrain = (grainSettings?: pond.GrainSettings) => {
console.log("update custom grain")
let f = cloneDeep(form)
f.component.settings.customGrain = grainSettings
f.component.settings.grainType = pond.Grain.GRAIN_CUSTOM
setForm(f)
}
const updateGrainType = (option: Option | null) => { const updateGrainType = (option: Option | null) => {
let f = cloneDeep(form); let f = cloneDeep(form);
@ -622,6 +637,27 @@ export default function ComponentForm(props: Props) {
const grainSelect = () => { const grainSelect = () => {
let selected = findSelectedGrain(grainOptions); let selected = findSelectedGrain(grainOptions);
return ( return (
<React.Fragment>
<FormControlLabel
control={
<Switch
value={useCustomGrain}
checked={useCustomGrain}
title="Custom Grain"
onClick={() => {
setUseCustomGrain(!useCustomGrain);
updateCustomGrain()
}}
/>
}
label="Custom Grain"
labelPlacement="start"
/>
{useCustomGrain ?
<Box sx={{border: "1px solid white", borderRadius: 2, padding: 2, marginBottom: 2}}>
<CustomGrainForm onGrainSettingsChange={updateCustomGrain} grainSettings={form.component.customGrainProps()}/>
</Box>
:
<SearchSelect <SearchSelect
selected={selected} selected={selected}
changeSelection={updateGrainType} changeSelection={updateGrainType}
@ -629,6 +665,8 @@ export default function ComponentForm(props: Props) {
options={grainOptions} options={grainOptions}
group group
/> />
}
</React.Fragment>
); );
}; };

View file

@ -1,4 +1,5 @@
import { Box, Button, MenuItem, TextField, Typography } from "@mui/material" import { ExpandMore } from "@mui/icons-material"
import { Accordion, AccordionDetails, AccordionSummary, Box, Button, MenuItem, TextField, Typography } from "@mui/material"
import SearchSelect, { Option } from "common/SearchSelect" import SearchSelect, { Option } from "common/SearchSelect"
import { cloneDeep } from "lodash" import { cloneDeep } from "lodash"
import { pond } from "protobuf-ts/pond" import { pond } from "protobuf-ts/pond"
@ -45,9 +46,9 @@ export default function CustomGrainForm(props: Props) {
useEffect(()=>{ useEffect(()=>{
grainAPI.listGrains(0, 0, "asc", "name", undefined, undefined, undefined, as).then(resp => { grainAPI.listGrains(0, 0, "asc", "name", undefined, undefined, undefined, as).then(resp => {
if (resp.data.grains){
let map: Map<string, pond.GrainObject> = new Map()
let options: Option[] = [] let options: Option[] = []
let map: Map<string, pond.GrainObject> = new Map()
if (resp.data.grains){
resp.data.grains.forEach(grain => { resp.data.grains.forEach(grain => {
map.set(grain.key, grain) map.set(grain.key, grain)
options.push({ options.push({
@ -56,9 +57,9 @@ export default function CustomGrainForm(props: Props) {
group: grain.settings?.group, group: grain.settings?.group,
}) })
}) })
}
setGrainOptions(options) setGrainOptions(options)
setGrainMap(map) setGrainMap(map)
}
}) })
},[grainAPI]) },[grainAPI])
@ -83,43 +84,13 @@ export default function CustomGrainForm(props: Props) {
} }
const settingsChanged = (newSettings: pond.GrainSettings) => { const settingsChanged = (newSettings: pond.GrainSettings) => {
setSelectedOption(null)
setNewGrainSettings(newSettings) setNewGrainSettings(newSettings)
onGrainSettingsChange(newSettings) onGrainSettingsChange(newSettings)
} }
const newGrain = () => {
return ( return (
<React.Fragment> <React.Fragment>
<Box sx={{marginBottom: 2}}>
<SearchSelect
label="My Grains"
selected={selectedOption}
changeSelection={option => {
setIsNew(false)
setSelectedOption(option)
//when an option is selected set all of the state variables controlling the form entries
let grain = grainMap.get(option?.value)
if(grain && grain.settings){
//set the form values
setName(grain.name)
setGroup(grain.settings.group)
setEquation(grain.settings.equation)
setConstantA(grain.settings.a.toString())
setConstantB(grain.settings.b.toString())
setConstantC(grain.settings.c.toString())
setKgPerBushel(grain.settings.kgPerBushel.toString())
setBushelsPerTonne(grain.settings.bushelsPerTonne.toString())
//the the new grain settings object
setNewGrainSettings(grain.settings)
//pass that settings object back up
settingsChanged(grain.settings)
}
}}
group
options={grainOptions}
/>
</Box>
<Typography sx={{marginBottom: 1}}>Custom Grain Properties</Typography>
<TextField <TextField
sx={{marginBottom: 2}} sx={{marginBottom: 2}}
fullWidth fullWidth
@ -283,4 +254,61 @@ export default function CustomGrainForm(props: Props) {
} }
</React.Fragment> </React.Fragment>
) )
}
const grainAccordion = () => {
return (
<Accordion>
<AccordionSummary expandIcon={<ExpandMore />}>Custom Grain Properties</AccordionSummary>
<AccordionDetails>
{newGrain()}
</AccordionDetails>
</Accordion>
)
}
return (
<React.Fragment>
{grainOptions.length === 0 ?
<Box>
<Typography sx={{marginBottom: 1}}>Custom Grain Properties</Typography>
{newGrain()}
</Box>
:
<Box>
<Box sx={{marginBottom: 2}}>
<SearchSelect
label="My Grains"
selected={selectedOption}
changeSelection={option => {
setIsNew(false)
setSelectedOption(option)
//when an option is selected set all of the state variables controlling the form entries
let grain = grainMap.get(option?.value)
if(grain && grain.settings){
//set the form values
setName(grain.name)
setGroup(grain.settings.group)
setEquation(grain.settings.equation)
setConstantA(grain.settings.a.toString())
setConstantB(grain.settings.b.toString())
setConstantC(grain.settings.c.toString())
setKgPerBushel(grain.settings.kgPerBushel.toString())
setBushelsPerTonne(grain.settings.bushelsPerTonne.toString())
//the the new grain settings object
setNewGrainSettings(grain.settings)
//pass that settings object back up
settingsChanged(grain.settings)
}
}}
group
options={grainOptions}
/>
</Box>
{grainAccordion()}
</Box>
}
</React.Fragment>
)
} }

View file

@ -142,4 +142,9 @@ export class Component {
return getFriendlyAddressTypeName(this.settings.addressType); return getFriendlyAddressTypeName(this.settings.addressType);
} }
}; };
public customGrainProps(): pond.GrainSettings | undefined {
if(this.settings.customGrain) return this.settings.customGrain
return
}
} }