Merge branch 'custom_grain' into dev_environment
This commit is contained in:
commit
709d86eef1
20 changed files with 813 additions and 225 deletions
6
package-lock.json
generated
6
package-lock.json
generated
|
|
@ -10953,11 +10953,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/protobuf-ts": {
|
"node_modules/protobuf-ts": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
<<<<<<< HEAD
|
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#fa7ac81420665424e5490346c6a6e871480a1643",
|
||||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#80ad2f8b81afe9e04f10f9b52a8250e6824d2b41",
|
|
||||||
=======
|
|
||||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#c08965a296f2cd0799472fd8b163186cf6885d4c",
|
|
||||||
>>>>>>> tidio
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"protobufjs": "^6.8.8"
|
"protobufjs": "^6.8.8"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -200,25 +200,27 @@ export default function BinCard(props: Props) {
|
||||||
|
|
||||||
const typeDisplay = () => {
|
const typeDisplay = () => {
|
||||||
let grainType = bin.settings.inventory?.grainType ?? pond.Grain.GRAIN_NONE;
|
let grainType = bin.settings.inventory?.grainType ?? pond.Grain.GRAIN_NONE;
|
||||||
if (bin.storage() === pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN) {
|
switch (bin.storage()){
|
||||||
return (
|
case pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN:
|
||||||
<Box>
|
return (
|
||||||
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
<Box>
|
||||||
{GrainDescriber(grainType).name}
|
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
||||||
</Typography>
|
{GrainDescriber(grainType).name}
|
||||||
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
</Typography>
|
||||||
{bin.settings.inventory?.grainSubtype}
|
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
||||||
</Typography>
|
{bin.settings.inventory?.grainSubtype}
|
||||||
</Box>
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
||||||
|
{bin.grainName()}
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Typography variant="subtitle2" style={{ fontSize: "0.7rem", fontWeight: 700 }}>
|
|
||||||
{bin.settings.inventory?.customTypeName}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const tempDisplay = () => {
|
const tempDisplay = () => {
|
||||||
|
|
@ -417,6 +419,7 @@ export default function BinCard(props: Props) {
|
||||||
hottestNodeTemp={valDisplay === "high" ? hotNode?.temp : undefined}
|
hottestNodeTemp={valDisplay === "high" ? hotNode?.temp : undefined}
|
||||||
coldestNodeTemp={valDisplay === "low" ? coldNode?.temp : undefined}
|
coldestNodeTemp={valDisplay === "low" ? coldNode?.temp : undefined}
|
||||||
inventoryControl={bin.inventoryControl()}
|
inventoryControl={bin.inventoryControl()}
|
||||||
|
customGrain={bin.customGrain()}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,12 @@ interface Props {
|
||||||
heaters?: Controller[];
|
heaters?: Controller[];
|
||||||
fans?: Controller[];
|
fans?: Controller[];
|
||||||
grain?: pond.Grain;
|
grain?: pond.Grain;
|
||||||
|
customGrain?: pond.GrainSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BinConditioningCard(props: Props) {
|
export default function BinConditioningCard(props: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const { interactions, interactionDevices, plenums, ambients, heaters, fans, grain, mode } = props;
|
const { interactions, interactionDevices, plenums, ambients, heaters, fans, grain, mode, customGrain } = props;
|
||||||
const [sourceMap, setSourceMap] = useState<Map<string, Component>>(new Map());
|
const [sourceMap, setSourceMap] = useState<Map<string, Component>>(new Map());
|
||||||
const [sinkMap, setSinkMap] = useState<Map<string, Component>>(new Map());
|
const [sinkMap, setSinkMap] = useState<Map<string, Component>>(new Map());
|
||||||
|
|
||||||
|
|
@ -87,6 +88,7 @@ export default function BinConditioningCard(props: Props) {
|
||||||
sink={sink}
|
sink={sink}
|
||||||
source={source}
|
source={source}
|
||||||
grain={grain}
|
grain={grain}
|
||||||
|
customGrain={customGrain}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,10 +84,11 @@ interface Props {
|
||||||
source: Component;
|
source: Component;
|
||||||
sink: Component;
|
sink: Component;
|
||||||
grain?: pond.Grain;
|
grain?: pond.Grain;
|
||||||
|
customGrain?: pond.GrainSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BinConditioningInteraction(props: Props) {
|
export default function BinConditioningInteraction(props: Props) {
|
||||||
const { interaction, source, sink, grain, deviceId } = props;
|
const { interaction, source, sink, grain, deviceId, customGrain } = props;
|
||||||
const [sliderVals, setSliderVals] = useState<Map<quack.MeasurementType, number>>(new Map());
|
const [sliderVals, setSliderVals] = useState<Map<quack.MeasurementType, number>>(new Map());
|
||||||
const [sliderMarks, setSliderMarks] = useState<Map<quack.MeasurementType, number>>(new Map());
|
const [sliderMarks, setSliderMarks] = useState<Map<quack.MeasurementType, number>>(new Map());
|
||||||
//this is the emc value calculated from the interactions temp and humidity conditions
|
//this is the emc value calculated from the interactions temp and humidity conditions
|
||||||
|
|
@ -127,7 +128,6 @@ export default function BinConditioningInteraction(props: Props) {
|
||||||
if (
|
if (
|
||||||
grain !== undefined &&
|
grain !== undefined &&
|
||||||
grain !== pond.Grain.GRAIN_INVALID &&
|
grain !== pond.Grain.GRAIN_INVALID &&
|
||||||
grain !== pond.Grain.GRAIN_CUSTOM &&
|
|
||||||
temp &&
|
temp &&
|
||||||
hum
|
hum
|
||||||
) {
|
) {
|
||||||
|
|
@ -135,8 +135,9 @@ export default function BinConditioningInteraction(props: Props) {
|
||||||
//the emc calc needs the temp to be in celsius
|
//the emc calc needs the temp to be in celsius
|
||||||
temp = fahrenheitToCelsius(temp);
|
temp = fahrenheitToCelsius(temp);
|
||||||
}
|
}
|
||||||
let emc = ExtractMoisture(grain, temp, hum);
|
let emc = ExtractMoisture(grain, temp, hum, customGrain)
|
||||||
setBaseEMC(emc);
|
setBaseEMC(emc === hum ? undefined : emc);
|
||||||
|
|
||||||
}
|
}
|
||||||
}, [sliderVals, grain]);
|
}, [sliderVals, grain]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ interface Props {
|
||||||
hottestNodeTemp?: number;
|
hottestNodeTemp?: number;
|
||||||
coldestNodeTemp?: number;
|
coldestNodeTemp?: number;
|
||||||
inventoryControl?: pond.BinInventoryControl;
|
inventoryControl?: pond.BinInventoryControl;
|
||||||
|
customGrain?: pond.GrainSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GrainNodePoint {
|
interface GrainNodePoint {
|
||||||
|
|
@ -211,7 +212,8 @@ export default function BinSVGV2(props: Props) {
|
||||||
hottestNodeTemp,
|
hottestNodeTemp,
|
||||||
coldestNodeTemp,
|
coldestNodeTemp,
|
||||||
inventoryControl,
|
inventoryControl,
|
||||||
co2Sensors
|
co2Sensors,
|
||||||
|
customGrain
|
||||||
} = props;
|
} = props;
|
||||||
const [{ user }] = useGlobalState();
|
const [{ user }] = useGlobalState();
|
||||||
const [extraDetails, setExtraDetails] = useState<"temps" | "hums">("temps");
|
const [extraDetails, setExtraDetails] = useState<"temps" | "hums">("temps");
|
||||||
|
|
@ -683,7 +685,7 @@ export default function BinSVGV2(props: Props) {
|
||||||
x: cablePos,
|
x: cablePos,
|
||||||
y: nodeY + 10,
|
y: nodeY + 10,
|
||||||
stroke: "green",
|
stroke: "green",
|
||||||
value: ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0).toFixed(1)+"%",
|
value: ExtractMoisture(props.grainType, temp, cable.humidities[index] ?? 0, customGrain).toFixed(1)+"%",
|
||||||
})
|
})
|
||||||
!showTempHum &&
|
!showTempHum &&
|
||||||
nodeClickData.push({
|
nodeClickData.push({
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,7 @@ import { getDistanceUnit, or, getTemperatureUnit, getGrainUnit } from "utils";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import BinSelector from "./BinSelector";
|
import BinSelector from "./BinSelector";
|
||||||
|
import CustomGrainForm from "grain/CustomGrainForm";
|
||||||
// import BinSelector from "./BinSelector";
|
// import BinSelector from "./BinSelector";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
|
|
@ -205,6 +206,7 @@ export default function BinSettings(props: Props) {
|
||||||
const libracartAPI = useLibraCartProxyAPI()
|
const libracartAPI = useLibraCartProxyAPI()
|
||||||
const [lcDestination, setlcDestination] = useState<Option | null>()
|
const [lcDestination, setlcDestination] = useState<Option | null>()
|
||||||
const [lcDestinationOptions, setlcDestinationOptions] = useState<Option[]>([])
|
const [lcDestinationOptions, setlcDestinationOptions] = useState<Option[]>([])
|
||||||
|
const [customGrain, setCustomGrain] = useState<pond.GrainSettings>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
|
|
@ -236,6 +238,9 @@ export default function BinSettings(props: Props) {
|
||||||
initForm.inventory.grainType
|
initForm.inventory.grainType
|
||||||
).bushelsPerTonne;
|
).bushelsPerTonne;
|
||||||
}
|
}
|
||||||
|
if (initForm.inventory.customGrain){
|
||||||
|
setCustomGrain(initForm.inventory.customGrain)
|
||||||
|
}
|
||||||
//if the target temp is not set (older bins) make it the midpoint of the high and low temps assuming they are set otherwise make it 15
|
//if the target temp is not set (older bins) make it the midpoint of the high and low temps assuming they are set otherwise make it 15
|
||||||
if (!initForm.inventory.targetTemperature || initForm.inventory.targetTemperature) {
|
if (!initForm.inventory.targetTemperature || initForm.inventory.targetTemperature) {
|
||||||
if (initForm.highTemp && initForm.lowTemp) {
|
if (initForm.highTemp && initForm.lowTemp) {
|
||||||
|
|
@ -444,6 +449,11 @@ export default function BinSettings(props: Props) {
|
||||||
form.inventory.inventoryControl = inventoryControl
|
form.inventory.inventoryControl = inventoryControl
|
||||||
form.inventory.autoThreshold = autoFillThreshold
|
form.inventory.autoThreshold = autoFillThreshold
|
||||||
form.inventory.lidarDropCm = getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET ? lidarDropDistance * 30.48 : lidarDropDistance
|
form.inventory.lidarDropCm = getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET ? lidarDropDistance * 30.48 : lidarDropDistance
|
||||||
|
if(form.inventory.grainType !== pond.Grain.GRAIN_CUSTOM){
|
||||||
|
form.inventory.customGrain = undefined
|
||||||
|
}else{
|
||||||
|
form.inventory.customGrain = customGrain
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binAPI
|
binAPI
|
||||||
|
|
@ -493,6 +503,11 @@ export default function BinSettings(props: Props) {
|
||||||
form.inventory.autoThreshold = autoFillThreshold
|
form.inventory.autoThreshold = autoFillThreshold
|
||||||
//if the users preferences are in feet convert the distance to cm otherwise it was entered as cm so use that
|
//if the users preferences are in feet convert the distance to cm otherwise it was entered as cm so use that
|
||||||
form.inventory.lidarDropCm = getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET ? lidarDropDistance * 30.48 : lidarDropDistance
|
form.inventory.lidarDropCm = getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_FEET ? lidarDropDistance * 30.48 : lidarDropDistance
|
||||||
|
if(form.inventory.grainType !== pond.Grain.GRAIN_CUSTOM){
|
||||||
|
form.inventory.customGrain = undefined
|
||||||
|
}else{
|
||||||
|
form.inventory.customGrain = customGrain
|
||||||
|
}
|
||||||
}
|
}
|
||||||
binAPI
|
binAPI
|
||||||
.updateBin(bin.key(), form, as)
|
.updateBin(bin.key(), form, as)
|
||||||
|
|
@ -1014,7 +1029,37 @@ export default function BinSettings(props: Props) {
|
||||||
{isCustom ? "Custom" : "Grain"}
|
{isCustom ? "Custom" : "Grain"}
|
||||||
</Typography> */}
|
</Typography> */}
|
||||||
<Box>
|
<Box>
|
||||||
{!isCustomInventory && (
|
{isCustomInventory ?
|
||||||
|
<React.Fragment>
|
||||||
|
{storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ?
|
||||||
|
<React.Fragment>
|
||||||
|
<TextField
|
||||||
|
label="Type"
|
||||||
|
value={customTypeName}
|
||||||
|
type="text"
|
||||||
|
onChange={event => {
|
||||||
|
updateForm(
|
||||||
|
"inventory",
|
||||||
|
pond.BinInventory.create({
|
||||||
|
...form.inventory,
|
||||||
|
customTypeName: event.target.value
|
||||||
|
})
|
||||||
|
);
|
||||||
|
updateFormExtension("customTypeName", event.target.value);
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
className={classes.bottomSpacing}
|
||||||
|
/>
|
||||||
|
</React.Fragment>
|
||||||
|
:
|
||||||
|
<Box sx={{border: "1px solid white", borderRadius: 2, padding: 2, marginBottom: 2}}>
|
||||||
|
<CustomGrainForm initialGrain={customGrain} onGrainSettingsChange={(newGrainSettings) => {setCustomGrain(newGrainSettings)}}/>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
:
|
||||||
|
<React.Fragment>
|
||||||
<Box className={classes.bottomSpacing}>
|
<Box className={classes.bottomSpacing}>
|
||||||
<SearchSelect
|
<SearchSelect
|
||||||
label="Type"
|
label="Type"
|
||||||
|
|
@ -1040,49 +1085,6 @@ export default function BinSettings(props: Props) {
|
||||||
options={grainOptions}
|
options={grainOptions}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
|
||||||
{isCustomInventory ? (
|
|
||||||
<React.Fragment>
|
|
||||||
<TextField
|
|
||||||
label="Type"
|
|
||||||
value={customTypeName}
|
|
||||||
type="text"
|
|
||||||
onChange={event => {
|
|
||||||
updateForm(
|
|
||||||
"inventory",
|
|
||||||
pond.BinInventory.create({
|
|
||||||
...form.inventory,
|
|
||||||
customTypeName: event.target.value
|
|
||||||
})
|
|
||||||
);
|
|
||||||
updateFormExtension("customTypeName", event.target.value);
|
|
||||||
}}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
className={classes.bottomSpacing}
|
|
||||||
/>
|
|
||||||
{storageType !== pond.BinStorage.BIN_STORAGE_FERTILIZER && (
|
|
||||||
<TextField
|
|
||||||
label="Bushels Per Tonne"
|
|
||||||
value={bushPerTonne}
|
|
||||||
type="number"
|
|
||||||
onChange={event => {
|
|
||||||
updateForm(
|
|
||||||
"inventory",
|
|
||||||
pond.BinInventory.create({
|
|
||||||
...form.inventory,
|
|
||||||
bushelsPerTonne: +event.target.value
|
|
||||||
})
|
|
||||||
);
|
|
||||||
updateFormExtension("bushelsPerTonne", event.target.value);
|
|
||||||
}}
|
|
||||||
fullWidth
|
|
||||||
variant="outlined"
|
|
||||||
className={classes.bottomSpacing}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
|
||||||
) : (
|
|
||||||
<TextField
|
<TextField
|
||||||
label="Grain Variant"
|
label="Grain Variant"
|
||||||
value={grainSubtype}
|
value={grainSubtype}
|
||||||
|
|
@ -1102,7 +1104,8 @@ export default function BinSettings(props: Props) {
|
||||||
disabled={!grainType}
|
disabled={!grainType}
|
||||||
className={classes.bottomSpacing}
|
className={classes.bottomSpacing}
|
||||||
/>
|
/>
|
||||||
)}
|
</React.Fragment>
|
||||||
|
}
|
||||||
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_BUSHELS ||
|
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_BUSHELS ||
|
||||||
storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ||
|
storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ||
|
||||||
formExtension.bushelsPerTonne === "0" ||
|
formExtension.bushelsPerTonne === "0" ||
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ import Edit from "@mui/icons-material/Edit";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
import ButtonGroup from "common/ButtonGroup";
|
import ButtonGroup from "common/ButtonGroup";
|
||||||
import ModeChangeDialog from "./conditioning/modeChangeDialog";
|
import ModeChangeDialog from "./conditioning/modeChangeDialog";
|
||||||
|
import CustomGrainForm from "grain/CustomGrainForm";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => {
|
const useStyles = makeStyles((theme: Theme) => {
|
||||||
return ({
|
return ({
|
||||||
|
|
@ -286,6 +287,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
|
|
||||||
const [openModeChange, setOpenModeChange] = useState(false)
|
const [openModeChange, setOpenModeChange] = useState(false)
|
||||||
const [modeChangeInProgress, setModeChangeInProgress] = useState(false)
|
const [modeChangeInProgress, setModeChangeInProgress] = useState(false)
|
||||||
|
const [newGrainSettings, setNewGrainSettings] = useState<pond.GrainSettings>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setModeTime(moment(bin.status.lastModeChange));
|
setModeTime(moment(bin.status.lastModeChange));
|
||||||
|
|
@ -327,6 +329,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
setBushPerTonne(bin.settings.inventory.bushelsPerTonne.toFixed(2));
|
setBushPerTonne(bin.settings.inventory.bushelsPerTonne.toFixed(2));
|
||||||
setGrainSubtype(bin.subtype());
|
setGrainSubtype(bin.subtype());
|
||||||
setNewBinMode(bin.settings.mode);
|
setNewBinMode(bin.settings.mode);
|
||||||
|
setNewGrainSettings(bin.customGrain());
|
||||||
}
|
}
|
||||||
if (bin.settings) {
|
if (bin.settings) {
|
||||||
let t = bin.settings.outdoorTemp;
|
let t = bin.settings.outdoorTemp;
|
||||||
|
|
@ -515,18 +518,13 @@ export default function BinVisualizer(props: Props) {
|
||||||
const capacity = bin.settings.specs?.bushelCapacity ?? 0;
|
const capacity = bin.settings.specs?.bushelCapacity ?? 0;
|
||||||
const grainBushels = bin.bushels();
|
const grainBushels = bin.bushels();
|
||||||
const isEmpty = bin.settings.inventory?.empty === true || !grainBushels || grainBushels <= 0;
|
const isEmpty = bin.settings.inventory?.empty === true || !grainBushels || grainBushels <= 0;
|
||||||
const grainType = bin.settings.inventory?.grainType;
|
|
||||||
const grainTypeName = isEmpty || !grainType ? "" : GrainDescriber(grainType).name;
|
|
||||||
const customTypeName = bin.settings.inventory?.customTypeName;
|
|
||||||
const grainSubtype = bin.settings.inventory?.grainSubtype;
|
const grainSubtype = bin.settings.inventory?.grainSubtype;
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
{/* grain display */}
|
{/* grain display */}
|
||||||
<Box display="flex" justifyContent="space-between">
|
<Box display="flex" justifyContent="space-between">
|
||||||
<Typography variant="subtitle2" color="textPrimary" style={{ fontWeight: 800 }}>
|
<Typography variant="subtitle2" color="textPrimary" style={{ fontWeight: 800 }}>
|
||||||
{bin.storage() === pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN
|
{isEmpty ? "" : bin.grainName()}
|
||||||
? grainTypeName
|
|
||||||
: customTypeName}
|
|
||||||
{grainSubtype !== "" ? " - " + grainSubtype : ""}
|
{grainSubtype !== "" ? " - " + grainSubtype : ""}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Box
|
<Box
|
||||||
|
|
@ -768,6 +766,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
setGrainType(bin.settings.inventory.grainType);
|
setGrainType(bin.settings.inventory.grainType);
|
||||||
setGrainOption(ToGrainOption(bin.settings.inventory.grainType));
|
setGrainOption(ToGrainOption(bin.settings.inventory.grainType));
|
||||||
setBushPerTonne(bin.settings.inventory.bushelsPerTonne.toFixed(2));
|
setBushPerTonne(bin.settings.inventory.bushelsPerTonne.toFixed(2));
|
||||||
|
setNewGrainSettings(bin.customGrain())
|
||||||
setGrainSubtype(bin.subtype());
|
setGrainSubtype(bin.subtype());
|
||||||
}
|
}
|
||||||
setGrainChangeDialog(false);
|
setGrainChangeDialog(false);
|
||||||
|
|
@ -799,11 +798,13 @@ export default function BinVisualizer(props: Props) {
|
||||||
setCustomTypeName("");
|
setCustomTypeName("");
|
||||||
setGrainOption(ToGrainOption(pond.Grain.GRAIN_NONE));
|
setGrainOption(ToGrainOption(pond.Grain.GRAIN_NONE));
|
||||||
if (checked) {
|
if (checked) {
|
||||||
setStorageType(pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
|
|
||||||
setGrainType(pond.Grain.GRAIN_CUSTOM);
|
|
||||||
} else {
|
|
||||||
setStorageType(pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN);
|
setStorageType(pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN);
|
||||||
|
setGrainType(pond.Grain.GRAIN_CUSTOM);
|
||||||
|
setNewGrainSettings(bin.customGrain())
|
||||||
|
} else {
|
||||||
|
setStorageType(pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
|
||||||
setGrainType(pond.Grain.GRAIN_NONE);
|
setGrainType(pond.Grain.GRAIN_NONE);
|
||||||
|
setNewGrainSettings(undefined)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
name="storage"
|
name="storage"
|
||||||
|
|
@ -834,7 +835,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
)}
|
)}
|
||||||
{isCustomInventory ? (
|
{isCustomInventory ? (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<TextField
|
{/* <TextField
|
||||||
label="Type"
|
label="Type"
|
||||||
value={customTypeName}
|
value={customTypeName}
|
||||||
type="text"
|
type="text"
|
||||||
|
|
@ -859,7 +860,8 @@ export default function BinVisualizer(props: Props) {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
className={classes.bottomSpacing}
|
className={classes.bottomSpacing}
|
||||||
/>
|
/>
|
||||||
)}
|
)} */}
|
||||||
|
<CustomGrainForm initialGrain={bin.customGrain()} onGrainSettingsChange={settings => {setNewGrainSettings(settings)}}/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
) : (
|
) : (
|
||||||
<TextField
|
<TextField
|
||||||
|
|
@ -1404,6 +1406,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
inventoryControl={bin.inventoryControl()}
|
inventoryControl={bin.inventoryControl()}
|
||||||
|
customGrain={bin.customGrain()}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1574,6 +1577,12 @@ export default function BinVisualizer(props: Props) {
|
||||||
const fanPerformance = () => {
|
const fanPerformance = () => {
|
||||||
let totalCFM = bin.status.fanCfm;
|
let totalCFM = bin.status.fanCfm;
|
||||||
let bushelCFM = bin.status.cfmPerBushel;
|
let bushelCFM = bin.status.cfmPerBushel;
|
||||||
|
let emc = ExtractMoisture(
|
||||||
|
bin.grain(),
|
||||||
|
activePlenum?.tempHumidity?.temperature ?? 0,
|
||||||
|
activePlenum?.tempHumidity?.humidity ?? 0,
|
||||||
|
bin.customGrain()
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography style={{ fontSize: isMobile ? "0.85rem" : "1.0rem", fontWeight: 650 }}>
|
<Typography style={{ fontSize: isMobile ? "0.85rem" : "1.0rem", fontWeight: 650 }}>
|
||||||
|
|
@ -1616,20 +1625,18 @@ export default function BinVisualizer(props: Props) {
|
||||||
{cfmDryWarning(bushelCFM)}
|
{cfmDryWarning(bushelCFM)}
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid >
|
<Grid>
|
||||||
<Box className={classes.lightBox}>
|
{emc !== activePlenum?.tempHumidity?.humidity &&
|
||||||
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
<Box className={classes.lightBox}>
|
||||||
{ExtractMoisture(
|
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
||||||
bin.grain(),
|
{emc.toFixed(2)}
|
||||||
activePlenum?.tempHumidity?.temperature ?? 0,
|
%
|
||||||
activePlenum?.tempHumidity?.humidity ?? 0
|
</Typography>
|
||||||
).toFixed(2)}
|
<Typography align="center" style={{ fontWeight: 650 }}>
|
||||||
%
|
Plenum EMC
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography align="center" style={{ fontWeight: 650 }}>
|
</Box>
|
||||||
Plenum EMC
|
}
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1638,6 +1645,12 @@ export default function BinVisualizer(props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const ambientDisplay = () => {
|
const ambientDisplay = () => {
|
||||||
|
let emc = ExtractMoisture(
|
||||||
|
bin.grain(),
|
||||||
|
ambient?.temperature ?? 0,
|
||||||
|
ambient?.humidity ?? 0,
|
||||||
|
bin.customGrain()
|
||||||
|
)
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography style={{ fontSize: isMobile ? "0.85rem" : "1.0rem", fontWeight: 650 }}>
|
<Typography style={{ fontSize: isMobile ? "0.85rem" : "1.0rem", fontWeight: 650 }}>
|
||||||
|
|
@ -1677,19 +1690,17 @@ export default function BinVisualizer(props: Props) {
|
||||||
</Box>
|
</Box>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid >
|
<Grid >
|
||||||
<Box className={classes.lightBox}>
|
{emc !== ambient?.humidity &&
|
||||||
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
<Box className={classes.lightBox}>
|
||||||
{ExtractMoisture(
|
<Typography align="center" style={{ fontWeight: 650, color: emcColour }}>
|
||||||
bin.grain(),
|
{emc.toFixed(2)}
|
||||||
ambient?.temperature ?? 0,
|
%
|
||||||
ambient?.humidity ?? 0
|
</Typography>
|
||||||
).toFixed(2)}
|
<Typography align="center" style={{ fontWeight: 650 }}>
|
||||||
%
|
Ambient EMC
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography align="center" style={{ fontWeight: 650 }}>
|
</Box>
|
||||||
Ambient EMC
|
}
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
@ -1966,6 +1977,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
? 0
|
? 0
|
||||||
: parseFloat(bushPerTonne);
|
: parseFloat(bushPerTonne);
|
||||||
b.settings.inventory.grainSubtype = grainSubtype;
|
b.settings.inventory.grainSubtype = grainSubtype;
|
||||||
|
b.settings.inventory.customGrain = newGrainSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b.settings.outdoorTemp !== undefined) {
|
if (b.settings.outdoorTemp !== undefined) {
|
||||||
|
|
|
||||||
|
|
@ -170,18 +170,18 @@ export default function BinGraphs(props: Props) {
|
||||||
setEndDate(newEndDate);
|
setEndDate(newEndDate);
|
||||||
};
|
};
|
||||||
|
|
||||||
const determineGrainColour = () => {
|
// const determineGrainColour = () => {
|
||||||
let col = "yellow";
|
// let col = "yellow";
|
||||||
let binInv = bin.settings.inventory;
|
// let binInv = bin.settings.inventory;
|
||||||
if (binInv) {
|
// if (binInv) {
|
||||||
if (binInv.grainType === pond.Grain.GRAIN_CUSTOM) {
|
// if (binInv.grainType === pond.Grain.GRAIN_CUSTOM) {
|
||||||
col = stringToMaterialColour(binInv.customTypeName);
|
// col = stringToMaterialColour(binInv.customTypeName);
|
||||||
} else if (binInv.grainType !== pond.Grain.GRAIN_NONE) {
|
// } else if (binInv.grainType !== pond.Grain.GRAIN_NONE) {
|
||||||
col = GrainDescriber(binInv.grainType).colour;
|
// col = GrainDescriber(binInv.grainType).colour;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return col;
|
// return col;
|
||||||
};
|
// };
|
||||||
|
|
||||||
const inventoryGraph = () => {
|
const inventoryGraph = () => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -193,7 +193,7 @@ export default function BinGraphs(props: Props) {
|
||||||
endDate={endDate}
|
endDate={endDate}
|
||||||
binLoading={binLoading}
|
binLoading={binLoading}
|
||||||
bin={bin}
|
bin={bin}
|
||||||
colour={determineGrainColour()}
|
colour={bin.grainColour()}
|
||||||
fertilizerBin={bin.settings.storage === pond.BinStorage.BIN_STORAGE_FERTILIZER}
|
fertilizerBin={bin.settings.storage === pond.BinStorage.BIN_STORAGE_FERTILIZER}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,8 @@ export default function BinGraphsTrending(props: Props) {
|
||||||
trend: ExtractMoisture(
|
trend: ExtractMoisture(
|
||||||
bin.grain(),
|
bin.grain(),
|
||||||
val.values[0],
|
val.values[0],
|
||||||
plenumHumidity.values[i].values[0]
|
plenumHumidity.values[i].values[0],
|
||||||
|
bin.customGrain()
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
trendData.push(trendPoint);
|
trendData.push(trendPoint);
|
||||||
|
|
|
||||||
|
|
@ -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,13 @@ export default function ComponentForm(props: Props) {
|
||||||
setForm(f);
|
setForm(f);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateCustomGrain = (grainSettings?: pond.GrainSettings) => {
|
||||||
|
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,13 +636,36 @@ export default function ComponentForm(props: Props) {
|
||||||
const grainSelect = () => {
|
const grainSelect = () => {
|
||||||
let selected = findSelectedGrain(grainOptions);
|
let selected = findSelectedGrain(grainOptions);
|
||||||
return (
|
return (
|
||||||
<SearchSelect
|
<React.Fragment>
|
||||||
selected={selected}
|
<FormControlLabel
|
||||||
changeSelection={updateGrainType}
|
control={
|
||||||
label="Grain Type"
|
<Switch
|
||||||
options={grainOptions}
|
value={useCustomGrain}
|
||||||
group
|
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} initialGrain={form.component.customGrainProps()}/>
|
||||||
|
</Box>
|
||||||
|
:
|
||||||
|
<SearchSelect
|
||||||
|
selected={selected}
|
||||||
|
changeSelection={updateGrainType}
|
||||||
|
label="Grain Type"
|
||||||
|
options={grainOptions}
|
||||||
|
group
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import { Pressure } from "models/Pressure";
|
||||||
import { GrainCable } from "models/GrainCable";
|
import { GrainCable } from "models/GrainCable";
|
||||||
import { extension, Summary } from "pbHelpers/ComponentType";
|
import { extension, Summary } from "pbHelpers/ComponentType";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
|
import { stringToMaterialColour } from "utils";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
component: Component | Plenum | Pressure | GrainCable;
|
component: Component | Plenum | Pressure | GrainCable;
|
||||||
|
|
@ -100,13 +101,26 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const grainName = () => {
|
||||||
|
if(component.settings.grainType === pond.Grain.GRAIN_CUSTOM && component.settings.customGrain?.name){
|
||||||
|
return component.settings.customGrain.name
|
||||||
|
}
|
||||||
|
return GrainDescriber(component.settings.grainType).name
|
||||||
|
}
|
||||||
|
|
||||||
|
const grainColor = () => {
|
||||||
|
if(component.settings.grainType === pond.Grain.GRAIN_CUSTOM && component.settings.customGrain?.name){
|
||||||
|
return stringToMaterialColour(component.settings.customGrain.name)
|
||||||
|
}
|
||||||
|
return GrainDescriber(component.settings.grainType).colour
|
||||||
|
}
|
||||||
|
|
||||||
const getSummaryComponent = (summaries: Summary[]): any => {
|
const getSummaryComponent = (summaries: Summary[]): any => {
|
||||||
if (summaries.length < 1) {
|
if (summaries.length < 1) {
|
||||||
return noSummary();
|
return noSummary();
|
||||||
}
|
}
|
||||||
|
|
||||||
let overlays: JSX.Element[] = [];
|
let overlays: JSX.Element[] = [];
|
||||||
let grain = GrainDescriber(component.settings.grainType);
|
|
||||||
return (
|
return (
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid size={{ xs: 12 }}>
|
<Grid size={{ xs: 12 }}>
|
||||||
|
|
@ -170,7 +184,7 @@ export default function UnitMeasurementSummary(props: Props) {
|
||||||
component.settings.grainType !== pond.Grain.GRAIN_INVALID && (
|
component.settings.grainType !== pond.Grain.GRAIN_INVALID && (
|
||||||
<Typography variant={largeText ? "body1" : "caption"} color="textPrimary">
|
<Typography variant={largeText ? "body1" : "caption"} color="textPrimary">
|
||||||
<span key={"grainType"}>
|
<span key={"grainType"}>
|
||||||
Grain Type: <span style={{ color: grain.colour }}>{grain.name}</span>
|
Grain Type: <span style={{ color: grainColor() }}>{grainName()}</span>
|
||||||
</span>
|
</span>
|
||||||
</Typography>
|
</Typography>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
321
src/grain/CustomGrainForm.tsx
Normal file
321
src/grain/CustomGrainForm.tsx
Normal file
|
|
@ -0,0 +1,321 @@
|
||||||
|
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 { cloneDeep } from "lodash"
|
||||||
|
import { pond } from "protobuf-ts/pond"
|
||||||
|
import { useGlobalState } from "providers"
|
||||||
|
import { useGrainAPI } from "providers/pond/grainAPI"
|
||||||
|
import React, { useEffect, useState } from "react"
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
initialGrain?: pond.GrainSettings
|
||||||
|
onGrainSettingsChange: (settings: pond.GrainSettings) => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CustomGrainForm(props: Props) {
|
||||||
|
const {initialGrain, onGrainSettingsChange} = props
|
||||||
|
const grainAPI = useGrainAPI()
|
||||||
|
const [{as}] = useGlobalState()
|
||||||
|
const [name, setName] = useState(initialGrain ? initialGrain.name : "")
|
||||||
|
const [group, setGroup] = useState(initialGrain ? initialGrain.group : "")
|
||||||
|
const [equation, setEquation] = useState<pond.MoistureEquation>(initialGrain ? initialGrain.equation : pond.MoistureEquation.MOISTURE_EQUATION_NONE)
|
||||||
|
const [constantA, setConstantA] = useState(initialGrain ? initialGrain.a.toString() : "0")
|
||||||
|
const [constantB, setConstantB] = useState(initialGrain ? initialGrain.b.toString() : "0")
|
||||||
|
const [constantC, setConstantC] = useState(initialGrain ? initialGrain.c.toString() : "0")
|
||||||
|
const [kgPerBushel, setKgPerBushel] = useState(initialGrain ? initialGrain.kgPerBushel.toString() : "0")
|
||||||
|
const [bushelsPerTonne, setBushelsPerTonne] = useState(initialGrain ? initialGrain.bushelsPerTonne.toString() : "0")
|
||||||
|
const [newGrainSettings, setNewGrainSettings] = useState(initialGrain ?? pond.GrainSettings.create())
|
||||||
|
const [grainMap, setGrainMap] = useState<Map<string, pond.GrainObject>>(
|
||||||
|
initialGrain ?
|
||||||
|
new Map([
|
||||||
|
["Active", pond.GrainObject.create({key: "Active", name: initialGrain.name, settings: initialGrain})]
|
||||||
|
])
|
||||||
|
:
|
||||||
|
new Map())
|
||||||
|
const [grainOptions, setGrainOptions] = useState<Option[]>(
|
||||||
|
initialGrain ?
|
||||||
|
[
|
||||||
|
{
|
||||||
|
label: initialGrain.name,
|
||||||
|
value: "Active",
|
||||||
|
group: "Active"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
:
|
||||||
|
[]
|
||||||
|
)
|
||||||
|
const [isNew, setIsNew] = useState(false)
|
||||||
|
const [selectedOption, setSelectedOption] = useState<Option | null>(initialGrain ? {
|
||||||
|
label: initialGrain.name,
|
||||||
|
value: "Active",
|
||||||
|
group: "Active"
|
||||||
|
} : null)
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
grainAPI.listGrains(0, 0, "asc", "name", undefined, undefined, undefined, as).then(resp => {
|
||||||
|
let options: Option[] = grainOptions
|
||||||
|
let map: Map<string, pond.GrainObject> = grainMap
|
||||||
|
if (resp.data.grains){
|
||||||
|
resp.data.grains.forEach(grain => {
|
||||||
|
map.set(grain.key, grain)
|
||||||
|
options.push({
|
||||||
|
label: grain.name,
|
||||||
|
value: grain.key,
|
||||||
|
group: grain.settings?.group,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
setGrainOptions([...options])
|
||||||
|
setGrainMap(map)
|
||||||
|
})
|
||||||
|
},[grainAPI])
|
||||||
|
|
||||||
|
const invalid = () => {
|
||||||
|
if (name === "") return true
|
||||||
|
if (group === "") return true
|
||||||
|
if (isNaN(parseFloat(constantA))) return true
|
||||||
|
if (isNaN(parseFloat(constantB))) return true
|
||||||
|
if (isNaN(parseFloat(constantA))) return true
|
||||||
|
if (isNaN(parseFloat(kgPerBushel))) return true
|
||||||
|
if (isNaN(parseFloat(bushelsPerTonne))) return true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveGrain = () => {
|
||||||
|
// console.log(newGrainSettings)
|
||||||
|
grainAPI.addGrain(newGrainSettings, as).then(resp => {
|
||||||
|
console.log("grain added")
|
||||||
|
}).catch(err => {
|
||||||
|
console.log("err")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const settingsChanged = (newSettings: pond.GrainSettings) => {
|
||||||
|
setNewGrainSettings(newSettings)
|
||||||
|
onGrainSettingsChange(newSettings)
|
||||||
|
}
|
||||||
|
|
||||||
|
const newGrain = () => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
label="Name*"
|
||||||
|
value={name}
|
||||||
|
onChange={(e) => {
|
||||||
|
let name = e.target.value
|
||||||
|
setName(name)
|
||||||
|
setIsNew(true)
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.name = name
|
||||||
|
settingsChanged(settings)
|
||||||
|
}}/>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
label="Group*"
|
||||||
|
value={group}
|
||||||
|
onChange={(e) => {
|
||||||
|
let group = e.target.value
|
||||||
|
setGroup(group)
|
||||||
|
setIsNew(true)
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.group = group
|
||||||
|
settingsChanged(settings)
|
||||||
|
}}/>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
value={equation}
|
||||||
|
helperText={"Not selecting an EMC equation to use will return the humidity instead of EMC"}
|
||||||
|
label="EMC Equation"
|
||||||
|
onChange={(e) => {
|
||||||
|
let enumVal = parseFloat(e.target.value)
|
||||||
|
setEquation(enumVal)
|
||||||
|
setIsNew(true)
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.equation = enumVal
|
||||||
|
settingsChanged(settings)
|
||||||
|
}}
|
||||||
|
select>
|
||||||
|
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_NONE} value={pond.MoistureEquation.MOISTURE_EQUATION_NONE}>
|
||||||
|
None
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST} value={pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST}>
|
||||||
|
Chung-Pfost
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON} value={pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON}>
|
||||||
|
Henderson
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_HALSEY} value={pond.MoistureEquation.MOISTURE_EQUATION_HALSEY}>
|
||||||
|
Halsey
|
||||||
|
</MenuItem>
|
||||||
|
<MenuItem key={pond.MoistureEquation.MOISTURE_EQUATION_OSWIN} value={pond.MoistureEquation.MOISTURE_EQUATION_OSWIN}>
|
||||||
|
Oswin
|
||||||
|
</MenuItem>
|
||||||
|
</TextField>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
value={constantA}
|
||||||
|
error={isNaN(parseFloat(constantA))}
|
||||||
|
helperText={isNaN(parseFloat(constantA)) ? "Must be a valid number" : ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
let val = e.target.value
|
||||||
|
setConstantA(val)
|
||||||
|
setIsNew(true)
|
||||||
|
if(!isNaN(parseFloat(val))){
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.a = parseFloat(val)
|
||||||
|
settingsChanged(settings)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
label="Constant A"/>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
value={constantB}
|
||||||
|
error={isNaN(parseFloat(constantB))}
|
||||||
|
helperText={isNaN(parseFloat(constantB)) ? "Must be a valid number" : ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
let val = e.target.value
|
||||||
|
setConstantB(val)
|
||||||
|
setIsNew(true)
|
||||||
|
if(!isNaN(parseFloat(val))){
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.b = parseFloat(val)
|
||||||
|
settingsChanged(settings)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
label="Constant B"/>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
value={constantC}
|
||||||
|
error={isNaN(parseFloat(constantC))}
|
||||||
|
helperText={isNaN(parseFloat(constantC)) ? "Must be a valid number" : ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
let val = e.target.value
|
||||||
|
setConstantC(val)
|
||||||
|
setIsNew(true)
|
||||||
|
if(!isNaN(parseFloat(val))){
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.c = parseFloat(val)
|
||||||
|
settingsChanged(settings)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
label="Constant C"/>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
value={kgPerBushel}
|
||||||
|
error={isNaN(parseFloat(kgPerBushel))}
|
||||||
|
helperText={isNaN(parseFloat(kgPerBushel)) ? "Must be a valid number" : ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
let val = e.target.value
|
||||||
|
setKgPerBushel(val)
|
||||||
|
setIsNew(true)
|
||||||
|
if(!isNaN(parseFloat(val))){
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.kgPerBushel = parseFloat(val)
|
||||||
|
settingsChanged(settings)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
label="kg per Bushel"/>
|
||||||
|
<TextField
|
||||||
|
sx={{marginBottom: 2}}
|
||||||
|
fullWidth
|
||||||
|
type="number"
|
||||||
|
value={bushelsPerTonne}
|
||||||
|
error={isNaN(parseFloat(bushelsPerTonne))}
|
||||||
|
helperText={isNaN(parseFloat(bushelsPerTonne)) ? "Must be a valid number" : ""}
|
||||||
|
onChange={(e) => {
|
||||||
|
let val = e.target.value
|
||||||
|
setBushelsPerTonne(val)
|
||||||
|
setIsNew(true)
|
||||||
|
if(!isNaN(parseFloat(val))){
|
||||||
|
let settings = cloneDeep(newGrainSettings)
|
||||||
|
settings.bushelsPerTonne = parseFloat(val)
|
||||||
|
settingsChanged(settings)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
label="Bushels per Tonne"/>
|
||||||
|
{isNew &&
|
||||||
|
<Box display='flex' justifyContent="flex-end">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
disabled={invalid()}
|
||||||
|
onClick={() => {
|
||||||
|
saveGrain()
|
||||||
|
setIsNew(false)
|
||||||
|
}}
|
||||||
|
color="primary">
|
||||||
|
Save Custom Grain
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
</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>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -14,12 +14,11 @@ import WheatImg from "assets/grain/wheat.jpg";
|
||||||
import { Option } from "common/SearchSelect";
|
import { Option } from "common/SearchSelect";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
import { Equation } from "./GrainMoisture";
|
|
||||||
|
|
||||||
export interface GrainExtension {
|
export interface GrainExtension {
|
||||||
name: string;
|
name: string;
|
||||||
group: string;
|
group: string;
|
||||||
equation: Equation;
|
equation: pond.MoistureEquation;
|
||||||
a: number;
|
a: number;
|
||||||
b: number;
|
b: number;
|
||||||
c: number;
|
c: number;
|
||||||
|
|
@ -37,7 +36,7 @@ const defaultSetTemp = 30.0;
|
||||||
const defaultGrain: GrainExtension = {
|
const defaultGrain: GrainExtension = {
|
||||||
name: "None",
|
name: "None",
|
||||||
group: "",
|
group: "",
|
||||||
equation: Equation.none,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_NONE,
|
||||||
a: 0,
|
a: 0,
|
||||||
b: 0,
|
b: 0,
|
||||||
c: 0,
|
c: 0,
|
||||||
|
|
@ -56,7 +55,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Custom Type",
|
name: "Custom Type",
|
||||||
group: "",
|
group: "",
|
||||||
equation: Equation.none,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_NONE,
|
||||||
a: 0,
|
a: 0,
|
||||||
b: 0,
|
b: 0,
|
||||||
c: 0,
|
c: 0,
|
||||||
|
|
@ -72,7 +71,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Barley",
|
name: "Barley",
|
||||||
group: "Barley",
|
group: "Barley",
|
||||||
equation: Equation.chungPfost,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 475.12,
|
a: 475.12,
|
||||||
b: 0.14843,
|
b: 0.14843,
|
||||||
c: 71.996,
|
c: 71.996,
|
||||||
|
|
@ -89,7 +88,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Buckwheat",
|
name: "Buckwheat",
|
||||||
group: "Buckwheat",
|
group: "Buckwheat",
|
||||||
equation: Equation.chungPfost,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 103540000,
|
a: 103540000,
|
||||||
b: 0.1646,
|
b: 0.1646,
|
||||||
c: 15853000,
|
c: 15853000,
|
||||||
|
|
@ -106,7 +105,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Canola",
|
name: "Canola",
|
||||||
group: "Canola",
|
group: "Canola",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 3.489,
|
a: 3.489,
|
||||||
b: -0.010553,
|
b: -0.010553,
|
||||||
c: 1.86,
|
c: 1.86,
|
||||||
|
|
@ -124,7 +123,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Rapeseed",
|
name: "Rapeseed",
|
||||||
group: "Canola",
|
group: "Canola",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 3.0026,
|
a: 3.0026,
|
||||||
b: -0.0048967,
|
b: -0.0048967,
|
||||||
c: 1.7607,
|
c: 1.7607,
|
||||||
|
|
@ -141,7 +140,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Corn (Henderson)",
|
name: "Corn (Henderson)",
|
||||||
group: "Corn",
|
group: "Corn",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000066612,
|
a: 0.000066612,
|
||||||
b: 1.9677,
|
b: 1.9677,
|
||||||
c: 42.143,
|
c: 42.143,
|
||||||
|
|
@ -158,7 +157,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Corn (Chung-Pfost)",
|
name: "Corn (Chung-Pfost)",
|
||||||
group: "Corn",
|
group: "Corn",
|
||||||
equation: Equation.chungPfost,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 374.34,
|
a: 374.34,
|
||||||
b: 0.18662,
|
b: 0.18662,
|
||||||
c: 31.696,
|
c: 31.696,
|
||||||
|
|
@ -175,7 +174,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Corn (Oswin)",
|
name: "Corn (Oswin)",
|
||||||
group: "Corn",
|
group: "Corn",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 15.303,
|
a: 15.303,
|
||||||
b: -0.10164,
|
b: -0.10164,
|
||||||
c: 3.0358,
|
c: 3.0358,
|
||||||
|
|
@ -192,7 +191,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Maize White",
|
name: "Maize White",
|
||||||
group: "Corn",
|
group: "Corn",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000066612,
|
a: 0.000066612,
|
||||||
b: 1.9677,
|
b: 1.9677,
|
||||||
c: 70.143,
|
c: 70.143,
|
||||||
|
|
@ -209,7 +208,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Maize Yellow",
|
name: "Maize Yellow",
|
||||||
group: "Corn",
|
group: "Corn",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000066612,
|
a: 0.000066612,
|
||||||
b: 1.9677,
|
b: 1.9677,
|
||||||
c: 65.143,
|
c: 65.143,
|
||||||
|
|
@ -226,7 +225,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Oats (Henderson)",
|
name: "Oats (Henderson)",
|
||||||
group: "Oats",
|
group: "Oats",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000085511,
|
a: 0.000085511,
|
||||||
b: 2.0087,
|
b: 2.0087,
|
||||||
c: 37.811,
|
c: 37.811,
|
||||||
|
|
@ -243,7 +242,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Oats (Chung-Pfost)",
|
name: "Oats (Chung-Pfost)",
|
||||||
group: "Oats",
|
group: "Oats",
|
||||||
equation: Equation.chungPfost,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 442.85,
|
a: 442.85,
|
||||||
b: 0.21228,
|
b: 0.21228,
|
||||||
c: 35.803,
|
c: 35.803,
|
||||||
|
|
@ -260,7 +259,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Oats (Oswin)",
|
name: "Oats (Oswin)",
|
||||||
group: "Oats",
|
group: "Oats",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 12.412,
|
a: 12.412,
|
||||||
b: -0.060707,
|
b: -0.060707,
|
||||||
c: 2.9397,
|
c: 2.9397,
|
||||||
|
|
@ -277,7 +276,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Peanuts",
|
name: "Peanuts",
|
||||||
group: "Peanuts",
|
group: "Peanuts",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 8.6588,
|
a: 8.6588,
|
||||||
b: -0.057904,
|
b: -0.057904,
|
||||||
c: 2.6204,
|
c: 2.6204,
|
||||||
|
|
@ -294,7 +293,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Long Grain Rice",
|
name: "Long Grain Rice",
|
||||||
group: "Rice",
|
group: "Rice",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000041276,
|
a: 0.000041276,
|
||||||
b: 2.1191,
|
b: 2.1191,
|
||||||
c: 49.828,
|
c: 49.828,
|
||||||
|
|
@ -311,7 +310,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Medium Grain Rice",
|
name: "Medium Grain Rice",
|
||||||
group: "Rice",
|
group: "Rice",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000035502,
|
a: 0.000035502,
|
||||||
b: 2.31,
|
b: 2.31,
|
||||||
c: 27.396,
|
c: 27.396,
|
||||||
|
|
@ -328,7 +327,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Short Grain Rice",
|
name: "Short Grain Rice",
|
||||||
group: "Rice",
|
group: "Rice",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.000048524,
|
a: 0.000048524,
|
||||||
b: 2.0794,
|
b: 2.0794,
|
||||||
c: 45.646,
|
c: 45.646,
|
||||||
|
|
@ -345,7 +344,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Sorghum",
|
name: "Sorghum",
|
||||||
group: "Sorghum",
|
group: "Sorghum",
|
||||||
equation: Equation.chungPfost,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 797.33,
|
a: 797.33,
|
||||||
b: 0.18159,
|
b: 0.18159,
|
||||||
c: 52.238,
|
c: 52.238,
|
||||||
|
|
@ -362,7 +361,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Soybeans",
|
name: "Soybeans",
|
||||||
group: "Soybeans",
|
group: "Soybeans",
|
||||||
equation: Equation.chungPfost,
|
//equation: Equation.chungPfost,
|
||||||
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 228.2,
|
a: 228.2,
|
||||||
b: 0.2072,
|
b: 0.2072,
|
||||||
c: 30,
|
c: 30,
|
||||||
|
|
@ -379,7 +379,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Sunflower",
|
name: "Sunflower",
|
||||||
group: "Sunflower",
|
group: "Sunflower",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.00031,
|
a: 0.00031,
|
||||||
b: 1.7459,
|
b: 1.7459,
|
||||||
c: 66.603,
|
c: 66.603,
|
||||||
|
|
@ -396,7 +396,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Durum Wheat",
|
name: "Durum Wheat",
|
||||||
group: "Wheat",
|
group: "Wheat",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 13.101,
|
a: 13.101,
|
||||||
b: -0.052626,
|
b: -0.052626,
|
||||||
c: 2.9987,
|
c: 2.9987,
|
||||||
|
|
@ -413,7 +413,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Hard Red Wheat",
|
name: "Hard Red Wheat",
|
||||||
group: "Wheat",
|
group: "Wheat",
|
||||||
equation: Equation.chungPfost,
|
//equation: Equation.chungPfost,
|
||||||
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 610.34,
|
a: 610.34,
|
||||||
b: 0.15526,
|
b: 0.15526,
|
||||||
c: 93.213,
|
c: 93.213,
|
||||||
|
|
@ -430,7 +431,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Wheat SAWOS",
|
name: "Wheat SAWOS",
|
||||||
group: "Wheat",
|
group: "Wheat",
|
||||||
equation: Equation.chungPfost,
|
//equation: Equation.chungPfost,
|
||||||
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 610.34,
|
a: 610.34,
|
||||||
b: 0.15526,
|
b: 0.15526,
|
||||||
c: 93.213,
|
c: 93.213,
|
||||||
|
|
@ -447,7 +449,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Un-retted Flax",
|
name: "Un-retted Flax",
|
||||||
group: "Flax",
|
group: "Flax",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 5.11,
|
a: 5.11,
|
||||||
b: Math.pow(-8.46 * 10, -3),
|
b: Math.pow(-8.46 * 10, -3),
|
||||||
c: 2.26,
|
c: 2.26,
|
||||||
|
|
@ -464,7 +466,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Dew-retted Flax",
|
name: "Dew-retted Flax",
|
||||||
group: "Flax",
|
group: "Flax",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 6.5,
|
a: 6.5,
|
||||||
b: Math.pow(-1.68 * 10, -2),
|
b: Math.pow(-1.68 * 10, -2),
|
||||||
c: 3.2,
|
c: 3.2,
|
||||||
|
|
@ -481,7 +483,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Yellow Peas",
|
name: "Yellow Peas",
|
||||||
group: "Peas",
|
group: "Peas",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 14.81,
|
a: 14.81,
|
||||||
b: -0.109,
|
b: -0.109,
|
||||||
c: 3.019,
|
c: 3.019,
|
||||||
|
|
@ -498,7 +500,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Blaze Lentils",
|
name: "Blaze Lentils",
|
||||||
group: "Lentils",
|
group: "Lentils",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 5.39,
|
a: 5.39,
|
||||||
b: -0.015,
|
b: -0.015,
|
||||||
c: 2.273,
|
c: 2.273,
|
||||||
|
|
@ -515,7 +517,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Redberry Lentils",
|
name: "Redberry Lentils",
|
||||||
group: "Lentils",
|
group: "Lentils",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 4.749,
|
a: 4.749,
|
||||||
b: -0.0116,
|
b: -0.0116,
|
||||||
c: 2.066,
|
c: 2.066,
|
||||||
|
|
@ -532,7 +534,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Robin Lentils",
|
name: "Robin Lentils",
|
||||||
group: "Lentils",
|
group: "Lentils",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 5.176,
|
a: 5.176,
|
||||||
b: -0.0065,
|
b: -0.0065,
|
||||||
c: 2.337,
|
c: 2.337,
|
||||||
|
|
@ -549,7 +551,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Dry Beans Red",
|
name: "Dry Beans Red",
|
||||||
group: "Dry Beans",
|
group: "Dry Beans",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 4.2669,
|
a: 4.2669,
|
||||||
b: -0.013382,
|
b: -0.013382,
|
||||||
c: 1.6933,
|
c: 1.6933,
|
||||||
|
|
@ -564,7 +566,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Dry Beans Black",
|
name: "Dry Beans Black",
|
||||||
group: "Dry Beans",
|
group: "Dry Beans",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 5.2003,
|
a: 5.2003,
|
||||||
b: -0.022685,
|
b: -0.022685,
|
||||||
c: 1.9656,
|
c: 1.9656,
|
||||||
|
|
@ -579,7 +581,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Rye (Henderson)",
|
name: "Rye (Henderson)",
|
||||||
group: "Rye",
|
group: "Rye",
|
||||||
equation: Equation.henderson,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON,
|
||||||
a: 0.00006343,
|
a: 0.00006343,
|
||||||
b: 2.2060,
|
b: 2.2060,
|
||||||
c: 13.1810,
|
c: 13.1810,
|
||||||
|
|
@ -594,7 +596,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Rye (Chung-Pfost)",
|
name: "Rye (Chung-Pfost)",
|
||||||
group: "Rye",
|
group: "Rye",
|
||||||
equation: Equation.chungPfost,
|
//equation: Equation.chungPfost,
|
||||||
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST,
|
||||||
a: 461.0230,
|
a: 461.0230,
|
||||||
b: 0.1840,
|
b: 0.1840,
|
||||||
c: 36.7410,
|
c: 36.7410,
|
||||||
|
|
@ -609,7 +612,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Rye (Halsey)",
|
name: "Rye (Halsey)",
|
||||||
group: "Rye",
|
group: "Rye",
|
||||||
equation: Equation.halsey,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_HALSEY,
|
||||||
a: 4.2970,
|
a: 4.2970,
|
||||||
b: 0.380,
|
b: 0.380,
|
||||||
c: 2.2710,
|
c: 2.2710,
|
||||||
|
|
@ -624,7 +627,7 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
{
|
{
|
||||||
name: "Rye (Oswin)",
|
name: "Rye (Oswin)",
|
||||||
group: "Rye",
|
group: "Rye",
|
||||||
equation: Equation.oswin,
|
equation: pond.MoistureEquation.MOISTURE_EQUATION_OSWIN,
|
||||||
a: 11.8870,
|
a: 11.8870,
|
||||||
b: 0.0210,
|
b: 0.0210,
|
||||||
c: 3.2620,
|
c: 3.2620,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,8 @@ const toERH = (humidity: number): number => {
|
||||||
export function ExtractMoisture(
|
export function ExtractMoisture(
|
||||||
type: pond.Grain | undefined,
|
type: pond.Grain | undefined,
|
||||||
celsius: number,
|
celsius: number,
|
||||||
humidity: number
|
humidity: number,
|
||||||
|
customGrain?: pond.GrainSettings
|
||||||
): number {
|
): number {
|
||||||
if (humidity <= 0) {
|
if (humidity <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -26,20 +27,43 @@ export function ExtractMoisture(
|
||||||
type === undefined ||
|
type === undefined ||
|
||||||
type === pond.Grain.GRAIN_NONE ||
|
type === pond.Grain.GRAIN_NONE ||
|
||||||
type === pond.Grain.GRAIN_INVALID ||
|
type === pond.Grain.GRAIN_INVALID ||
|
||||||
type === pond.Grain.GRAIN_CUSTOM
|
(type === pond.Grain.GRAIN_CUSTOM && customGrain === undefined)
|
||||||
) {
|
) {
|
||||||
return humidity;
|
return humidity;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dry = humidity;
|
let dry = humidity;
|
||||||
let ctx = GrainDescriber(type);
|
let eq: pond.MoistureEquation
|
||||||
dry = toDryMoisture(ctx.equation, celsius, humidity, ctx.a, ctx.b, ctx.c);
|
let constA: number
|
||||||
|
let constB: number
|
||||||
|
let constC: number
|
||||||
|
if(type === pond.Grain.GRAIN_CUSTOM && customGrain){
|
||||||
|
if(customGrain.equation === pond.MoistureEquation.MOISTURE_EQUATION_NONE) return humidity
|
||||||
|
eq = customGrain.equation
|
||||||
|
constA = customGrain.a
|
||||||
|
constB = customGrain.b
|
||||||
|
constC = customGrain.c
|
||||||
|
}else{
|
||||||
|
let ctx = GrainDescriber(type);
|
||||||
|
eq = ctx.equation
|
||||||
|
constA = ctx.a
|
||||||
|
constB = ctx.b
|
||||||
|
constC = ctx.c
|
||||||
|
}
|
||||||
|
|
||||||
|
dry = toDryMoisture(eq, celsius, humidity, constA, constB, constC);
|
||||||
return dryToWet(dry);
|
return dryToWet(dry);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function WaterContent(type: pond.Grain, bushels: number, moistureContent: number): number {
|
export function WaterContent(type: pond.Grain, bushels: number, moistureContent: number, customGrain?: pond.GrainSettings): number {
|
||||||
let grain = GrainDescriber(type);
|
//kg per bushel conversion
|
||||||
return bushels * grain.weightConversionKg * moistureContent;
|
let conversion = 0
|
||||||
|
if(type === pond.Grain.GRAIN_CUSTOM && customGrain){
|
||||||
|
conversion = customGrain.kgPerBushel
|
||||||
|
}else{
|
||||||
|
conversion = GrainDescriber(type).weightConversionKg;
|
||||||
|
}
|
||||||
|
return bushels * conversion * moistureContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MoistureToHumidity(
|
export function MoistureToHumidity(
|
||||||
|
|
@ -69,7 +93,7 @@ function wetToDry(wetMC: number): number {
|
||||||
}
|
}
|
||||||
|
|
||||||
function toDryMoisture(
|
function toDryMoisture(
|
||||||
eq: Equation,
|
eq: pond.MoistureEquation,
|
||||||
T: number,
|
T: number,
|
||||||
RH: number,
|
RH: number,
|
||||||
a: number,
|
a: number,
|
||||||
|
|
@ -78,13 +102,13 @@ function toDryMoisture(
|
||||||
): number {
|
): number {
|
||||||
const ERH: number = toERH(RH);
|
const ERH: number = toERH(RH);
|
||||||
switch (eq) {
|
switch (eq) {
|
||||||
case Equation.chungPfost:
|
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
|
||||||
return chungPfost(T, ERH, a, b, c);
|
return chungPfost(T, ERH, a, b, c);
|
||||||
case Equation.halsey:
|
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
|
||||||
return halsey(T, ERH, a, b, c);
|
return halsey(T, ERH, a, b, c);
|
||||||
case Equation.henderson:
|
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
|
||||||
return henderson(T, ERH, a, b, c);
|
return henderson(T, ERH, a, b, c);
|
||||||
case Equation.oswin:
|
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
|
||||||
return oswin(T, ERH, a, b, c);
|
return oswin(T, ERH, a, b, c);
|
||||||
default:
|
default:
|
||||||
return RH;
|
return RH;
|
||||||
|
|
@ -92,7 +116,7 @@ function toDryMoisture(
|
||||||
}
|
}
|
||||||
|
|
||||||
function dryMoistureToHumidity(
|
function dryMoistureToHumidity(
|
||||||
eq: Equation,
|
eq: pond.MoistureEquation,
|
||||||
celsius: number,
|
celsius: number,
|
||||||
dryMC: number,
|
dryMC: number,
|
||||||
a: number,
|
a: number,
|
||||||
|
|
@ -101,16 +125,16 @@ function dryMoistureToHumidity(
|
||||||
): number {
|
): number {
|
||||||
let ERH = 0;
|
let ERH = 0;
|
||||||
switch (eq) {
|
switch (eq) {
|
||||||
case Equation.chungPfost:
|
case pond.MoistureEquation.MOISTURE_EQUATION_CHUNG_PFOST:
|
||||||
ERH = chungPfostInverse(celsius, dryMC, a, b, c);
|
ERH = chungPfostInverse(celsius, dryMC, a, b, c);
|
||||||
break;
|
break;
|
||||||
case Equation.halsey:
|
case pond.MoistureEquation.MOISTURE_EQUATION_HALSEY:
|
||||||
ERH = halseyInverse(celsius, dryMC, a, b, c);
|
ERH = halseyInverse(celsius, dryMC, a, b, c);
|
||||||
break;
|
break;
|
||||||
case Equation.henderson:
|
case pond.MoistureEquation.MOISTURE_EQUATION_HENDERSON:
|
||||||
ERH = hendersonInverse(celsius, dryMC, a, b, c);
|
ERH = hendersonInverse(celsius, dryMC, a, b, c);
|
||||||
break;
|
break;
|
||||||
case Equation.oswin:
|
case pond.MoistureEquation.MOISTURE_EQUATION_OSWIN:
|
||||||
ERH = oswinInverse(celsius, dryMC, a, b, c);
|
ERH = oswinInverse(celsius, dryMC, a, b, c);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -125,17 +125,19 @@ export default function GrainTransaction(props: Props) {
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
//let sourceOps: Option[] = sourceOptions
|
//let sourceOps: Option[] = sourceOptions
|
||||||
let binOps: Option[] = [];
|
let binOps: Option[] = [];
|
||||||
resp.data.bins.forEach(bin => {
|
if(resp.data.bins){
|
||||||
let b = Bin.create(bin);
|
resp.data.bins.forEach(bin => {
|
||||||
if (mainObject.key() !== b.key()) {
|
let b = Bin.create(bin);
|
||||||
let op: Option = {
|
if (mainObject.key() !== b.key()) {
|
||||||
label: b.name(),
|
let op: Option = {
|
||||||
value: b,
|
label: b.name(),
|
||||||
group: "Bins"
|
value: b,
|
||||||
};
|
group: "Bins"
|
||||||
(!restrictMatching || grainTypesMatch(op.value, mainObject)) && binOps.push(op);
|
};
|
||||||
}
|
(!restrictMatching || grainTypesMatch(op.value, mainObject) || op.value.grainName() === mainObject.grainName()) && binOps.push(op);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
setBinOptions([...binOps]);
|
setBinOptions([...binOps]);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|
@ -151,17 +153,19 @@ export default function GrainTransaction(props: Props) {
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
//let sourceOps: Option[] = sourceOptions
|
//let sourceOps: Option[] = sourceOptions
|
||||||
let bagOps: Option[] = [];
|
let bagOps: Option[] = [];
|
||||||
resp.data.grainBags.forEach(bag => {
|
if(resp.data.grainBags){
|
||||||
let b = GrainBag.create(bag);
|
resp.data.grainBags.forEach(bag => {
|
||||||
if (mainObject.key() !== b.key()) {
|
let b = GrainBag.create(bag);
|
||||||
let op: Option = {
|
if (mainObject.key() !== b.key()) {
|
||||||
label: b.name(),
|
let op: Option = {
|
||||||
value: b,
|
label: b.name(),
|
||||||
group: "Grain Bags"
|
value: b,
|
||||||
};
|
group: "Grain Bags"
|
||||||
(!restrictMatching || grainTypesMatch(op.value, mainObject)) && bagOps.push(op);
|
};
|
||||||
}
|
(!restrictMatching || grainTypesMatch(op.value, mainObject) || op.value.grainName() === mainObject.grainName()) && bagOps.push(op);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
setBagOptions([...bagOps]);
|
setBagOptions([...bagOps]);
|
||||||
})
|
})
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
|
|
@ -184,7 +188,7 @@ export default function GrainTransaction(props: Props) {
|
||||||
value: f,
|
value: f,
|
||||||
group: "Fields"
|
group: "Fields"
|
||||||
};
|
};
|
||||||
(!restrictMatching || grainTypesMatch(op.value, mainObject)) && fieldOps.push(op);
|
(!restrictMatching || grainTypesMatch(op.value, mainObject) || op.value.grainName() === mainObject.grainName()) && fieldOps.push(op);
|
||||||
});
|
});
|
||||||
setFieldOptions([...fieldOps]);
|
setFieldOptions([...fieldOps]);
|
||||||
})
|
})
|
||||||
|
|
@ -356,13 +360,6 @@ export default function GrainTransaction(props: Props) {
|
||||||
if (source.grain() === destination.grain()) {
|
if (source.grain() === destination.grain()) {
|
||||||
matching = true;
|
matching = true;
|
||||||
}
|
}
|
||||||
} else if (source.storage() === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN) {
|
|
||||||
if (
|
|
||||||
source.customType().toLowerCase() === destination.customType().toLowerCase() &&
|
|
||||||
source.bushelsPerTonne() === destination.bushelsPerTonne()
|
|
||||||
) {
|
|
||||||
matching = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matching;
|
return matching;
|
||||||
|
|
@ -373,7 +370,7 @@ export default function GrainTransaction(props: Props) {
|
||||||
if (grainTypesMatch(selectedSource.value, selectedDestination.value)) {
|
if (grainTypesMatch(selectedSource.value, selectedDestination.value)) {
|
||||||
updateInventory();
|
updateInventory();
|
||||||
} else {
|
} else {
|
||||||
//open dialog saying that the destinations grain type will change from this action
|
//open dialog saying that the grain types do not match or because it is a custom type
|
||||||
setGrainChangeDialog(true);
|
setGrainChangeDialog(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -381,6 +378,36 @@ export default function GrainTransaction(props: Props) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the function is used to determine what text to display to the user when the grain types dont match
|
||||||
|
* or when it sees any of the objects involved as having a custom grain type
|
||||||
|
* @param source the source of the grain
|
||||||
|
* @param destination the destination of the grain
|
||||||
|
* @returns the text describing the situation
|
||||||
|
*/
|
||||||
|
const confirmationText = () => {
|
||||||
|
if(selectedSource && selectedDestination){
|
||||||
|
|
||||||
|
let source = selectedSource?.value
|
||||||
|
let destination = selectedDestination?.value
|
||||||
|
//both are custom
|
||||||
|
if(source.storage() === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN && destination.storage() === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN){
|
||||||
|
return "Both source and destination are using custom grain types, they may not match. Would you like to continue with the transaction?"
|
||||||
|
}
|
||||||
|
//source is custom destination is not
|
||||||
|
if(source.storage() === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN){
|
||||||
|
return "The source is using a custom grain type and may not match the destination. Would you like to continue with the transaction?"
|
||||||
|
}
|
||||||
|
//destination is custom source is not
|
||||||
|
if(destination.storage() === pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN){
|
||||||
|
return "The destination is using a custom grain type and may not match the source. Would you like to continue with the transaction?"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//neither are custom
|
||||||
|
return "The Grain types do not match. Are you sure you would like to perform this transaction?"
|
||||||
|
}
|
||||||
|
|
||||||
const grainChange = () => {
|
const grainChange = () => {
|
||||||
return (
|
return (
|
||||||
<ResponsiveDialog
|
<ResponsiveDialog
|
||||||
|
|
@ -389,7 +416,7 @@ export default function GrainTransaction(props: Props) {
|
||||||
setGrainChangeDialog(false);
|
setGrainChangeDialog(false);
|
||||||
}}>
|
}}>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
The grain type of the destination may change as a result of this action.
|
{confirmationText()}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button
|
<Button
|
||||||
|
|
|
||||||
|
|
@ -90,11 +90,19 @@ export class Bin {
|
||||||
public customType(): string {
|
public customType(): string {
|
||||||
let c = "";
|
let c = "";
|
||||||
if (this.settings.inventory) {
|
if (this.settings.inventory) {
|
||||||
c = this.settings.inventory.customTypeName;
|
if (this.settings.inventory.customGrain){
|
||||||
|
c = this.settings.inventory.customGrain.name
|
||||||
|
}else{
|
||||||
|
c = this.settings.inventory.customTypeName;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public customGrain(): pond.GrainSettings | undefined {
|
||||||
|
return this.settings.inventory?.customGrain ?? undefined
|
||||||
|
}
|
||||||
|
|
||||||
public empty(): boolean {
|
public empty(): boolean {
|
||||||
return this.settings.inventory?.empty || (this.settings.inventory !== undefined && this.settings.inventory !== null && this.bushels() < 5);
|
return this.settings.inventory?.empty || (this.settings.inventory !== undefined && this.settings.inventory !== null && this.bushels() < 5);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -819,6 +819,7 @@ export default function Bin(props: Props) {
|
||||||
fans={fans}
|
fans={fans}
|
||||||
heaters={heaters}
|
heaters={heaters}
|
||||||
grain={bin.grain()}
|
grain={bin.grain()}
|
||||||
|
customGrain={bin.customGrain()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Box marginTop={2}>
|
<Box marginTop={2}>
|
||||||
|
|
@ -980,6 +981,7 @@ export default function Bin(props: Props) {
|
||||||
fans={fans}
|
fans={fans}
|
||||||
heaters={heaters}
|
heaters={heaters}
|
||||||
grain={bin.grain()}
|
grain={bin.grain()}
|
||||||
|
customGrain={bin.customGrain()}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
123
src/providers/pond/grainAPI.tsx
Normal file
123
src/providers/pond/grainAPI.tsx
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
import { useHTTP } from "hooks";
|
||||||
|
import { createContext, PropsWithChildren, useContext } from "react";
|
||||||
|
import { pond } from "protobuf-ts/pond";
|
||||||
|
import { pondURL } from "./pond";
|
||||||
|
import { AxiosResponse } from "axios";
|
||||||
|
import { useGlobalState } from "providers";
|
||||||
|
import { or } from "utils";
|
||||||
|
|
||||||
|
export interface IGrainInterface {
|
||||||
|
addGrain: (
|
||||||
|
settings: pond.GrainSettings,
|
||||||
|
otherTeam?: string
|
||||||
|
) => Promise<AxiosResponse<pond.AddGrainResponse>>;
|
||||||
|
getGrain: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.GetGrainResponse>>
|
||||||
|
listGrains: (
|
||||||
|
limit: number,
|
||||||
|
offset: number,
|
||||||
|
order?: "asc" | "desc",
|
||||||
|
orderBy?: string,
|
||||||
|
search?: string,
|
||||||
|
keys?: string[],
|
||||||
|
types?: string[],
|
||||||
|
otherTeam?: string,
|
||||||
|
) => Promise<AxiosResponse<pond.ListGrainsResponse>>;
|
||||||
|
removeGrain: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveGrainResponse>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const GrainAPIcontext = createContext<IGrainInterface>({} as IGrainInterface);
|
||||||
|
|
||||||
|
interface Props {}
|
||||||
|
|
||||||
|
export default function GrainProvider(props: PropsWithChildren<Props>) {
|
||||||
|
const { children } = props;
|
||||||
|
const { get, del, post } = useHTTP();
|
||||||
|
const [{ as }] = useGlobalState();
|
||||||
|
|
||||||
|
//add
|
||||||
|
const addGrain = (settings: pond.GrainSettings, otherTeam?: string) => {
|
||||||
|
const view = otherTeam ? otherTeam : as
|
||||||
|
if (view) {
|
||||||
|
return post<pond.AddGrainResponse>(
|
||||||
|
pondURL("/grains?&as=" + view),
|
||||||
|
settings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return post<pond.AddGrainResponse>(pondURL("/grains"), settings);
|
||||||
|
};
|
||||||
|
|
||||||
|
//get
|
||||||
|
const getGrain = (key: string, otherTeam?: string) => {
|
||||||
|
const view = otherTeam ? otherTeam : as
|
||||||
|
const url = "/grains/" + key + (view ? "?as=" + view : "")
|
||||||
|
return new Promise<AxiosResponse<pond.GetGrainResponse>>((resolve, reject)=>{
|
||||||
|
get<pond.GetGrainResponse>(pondURL(url))
|
||||||
|
.then(resp => {
|
||||||
|
if (resp.data.grain){
|
||||||
|
resp.data.grain = pond.GrainObject.fromObject(resp.data.grain)
|
||||||
|
}
|
||||||
|
resolve(resp)
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//list
|
||||||
|
const listGrains = (
|
||||||
|
limit: number,
|
||||||
|
offset: number,
|
||||||
|
order?: "asc" | "desc",
|
||||||
|
orderBy?: string,
|
||||||
|
search?: string,
|
||||||
|
keys?: string[],
|
||||||
|
types?: string[],
|
||||||
|
otherTeam?: string
|
||||||
|
) => {
|
||||||
|
return new Promise<AxiosResponse<pond.ListGrainsResponse>>((resolve, reject)=>{
|
||||||
|
const view = otherTeam ? otherTeam : as
|
||||||
|
get<pond.ListGrainsResponse>(
|
||||||
|
pondURL(
|
||||||
|
"/grains?limit=" +
|
||||||
|
"?limit=" +
|
||||||
|
limit +
|
||||||
|
"&offset=" +
|
||||||
|
offset +
|
||||||
|
("&order=" + or(order, "asc")) +
|
||||||
|
("&by=" + or(orderBy, "key")) +
|
||||||
|
(search ? "&search=" + search : "") +
|
||||||
|
(keys ? "&keys=" + keys.join(",") : "") +
|
||||||
|
(types ? "&types=" + types.join(",") : "") +
|
||||||
|
(view ? "&as=" + view : "")
|
||||||
|
)
|
||||||
|
).then(resp => {
|
||||||
|
resp.data = pond.ListGrainsResponse.fromObject(resp.data);
|
||||||
|
return resolve(resp)
|
||||||
|
}).catch(err => {
|
||||||
|
return reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
//remove
|
||||||
|
const removeGrain = (key: string, otherTeam?: string) => {
|
||||||
|
const view = otherTeam ? otherTeam : as
|
||||||
|
if (view) {
|
||||||
|
return del<pond.RemoveGrainResponse>(pondURL("/grains/" + key + "?as=" + view));
|
||||||
|
}
|
||||||
|
return del<pond.RemoveGrainResponse>(pondURL("/grains/" + key));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GrainAPIcontext.Provider
|
||||||
|
value={{
|
||||||
|
addGrain,
|
||||||
|
getGrain,
|
||||||
|
listGrains,
|
||||||
|
removeGrain
|
||||||
|
}}>
|
||||||
|
{children}
|
||||||
|
</GrainAPIcontext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useGrainAPI = () => useContext(GrainAPIcontext);
|
||||||
|
|
@ -38,6 +38,7 @@ import JohnDeereProvider, { useJohnDeereProxyAPI } from "./johnDeereProxyAPI";
|
||||||
import LibraCartProvider, { useLibraCartProxyAPI } from "./libracartProxyAPI";
|
import LibraCartProvider, { useLibraCartProxyAPI } from "./libracartProxyAPI";
|
||||||
import CNHiProvider, { useCNHiProxyAPI } from "./cnhiProxyAPI";
|
import CNHiProvider, { useCNHiProxyAPI } from "./cnhiProxyAPI";
|
||||||
import DevicePresetProvider, { useDevicePresetAPI } from "./devicePresetAPI";
|
import DevicePresetProvider, { useDevicePresetAPI } from "./devicePresetAPI";
|
||||||
|
import GrainProvider, { useGrainAPI } from "./grainAPI";
|
||||||
// import NoteProvider from "providers/noteAPI";
|
// import NoteProvider from "providers/noteAPI";
|
||||||
|
|
||||||
export const pondURL = (partial: string, demo: boolean = false): string => {
|
export const pondURL = (partial: string, demo: boolean = false): string => {
|
||||||
|
|
@ -93,7 +94,9 @@ export default function PondProvider(props: PropsWithChildren<any>) {
|
||||||
<KeyManagerProvider>
|
<KeyManagerProvider>
|
||||||
<DevicePresetProvider>
|
<DevicePresetProvider>
|
||||||
<ImagekitProvider>
|
<ImagekitProvider>
|
||||||
{children}
|
<GrainProvider>
|
||||||
|
{children}
|
||||||
|
</GrainProvider>
|
||||||
</ImagekitProvider>
|
</ImagekitProvider>
|
||||||
</DevicePresetProvider>
|
</DevicePresetProvider>
|
||||||
</KeyManagerProvider>
|
</KeyManagerProvider>
|
||||||
|
|
@ -173,5 +176,6 @@ export {
|
||||||
useJohnDeereProxyAPI,
|
useJohnDeereProxyAPI,
|
||||||
useCNHiProxyAPI,
|
useCNHiProxyAPI,
|
||||||
useLibraCartProxyAPI,
|
useLibraCartProxyAPI,
|
||||||
useDevicePresetAPI
|
useDevicePresetAPI,
|
||||||
|
useGrainAPI
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue