diff --git a/package-lock.json b/package-lock.json index 3d72a0e..bb51eb6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10864,7 +10864,7 @@ }, "node_modules/protobuf-ts": { "version": "1.0.0", - "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#cdf642e6e89f16b2deea701552ae73c8296e7c64", + "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#8311cb2928f25950700fa0d3aaacf2ac07ea7f7e", "dependencies": { "protobufjs": "^6.8.8" } diff --git a/src/app/App.css b/src/app/App.css index 3b20b88..89db113 100644 --- a/src/app/App.css +++ b/src/app/App.css @@ -22,6 +22,7 @@ html, body, #root { height: 100%; margin: 0; padding: 0; + overflow-y: hidden; } /* styles.css or a CSS module */ diff --git a/src/bin/BinSettings.tsx b/src/bin/BinSettings.tsx index 19289e3..5558230 100644 --- a/src/bin/BinSettings.tsx +++ b/src/bin/BinSettings.tsx @@ -183,6 +183,7 @@ export default function BinSettings(props: Props) { const [inMoistureString, setInMoistureString] = useState("0"); const [tMoistureString, setTMoistureString] = useState("0"); const [moistureTargetDeviation, setMoistureTargetDeviation] = useState("0"); + const [autoFillThreshold, setAutoFillThreshold] = useState(0); const [validInitial, setValidInitial] = useState(true); const [validTarget, setValidTarget] = useState(true); const [validDeviation, setValidDeviation] = useState(true); @@ -311,6 +312,7 @@ export default function BinSettings(props: Props) { setInMoistureString(initForm.inventory?.initialMoisture.toString() ?? "0"); setTMoistureString(initForm.inventory?.targetMoisture.toString() ?? "0"); setMoistureTargetDeviation(initForm.inventory?.moistureTargetDeviation.toString() ?? "0"); + setAutoFillThreshold(initForm.inventory?.autoThreshold ?? 0) setActiveStep(0); if (bin) { setAutoTopNode(bin.settings.autoGrainNode); @@ -405,7 +407,10 @@ export default function BinSettings(props: Props) { form.highTemp = highTempC; form.lowTemp = lowTempC; form.autoGrainNode = autoTopNode; - if (form.inventory) form.inventory.inventoryControl = inventoryControl; + if (form.inventory) { + form.inventory.inventoryControl = inventoryControl + form.inventory.autoThreshold = autoFillThreshold + } binAPI .addBin(form, as) @@ -449,7 +454,10 @@ export default function BinSettings(props: Props) { form.highTemp = highTempC; form.lowTemp = lowTempC; form.autoGrainNode = autoTopNode; - if (form.inventory) form.inventory.inventoryControl = inventoryControl; + if (form.inventory) { + form.inventory.inventoryControl = inventoryControl + form.inventory.autoThreshold = autoFillThreshold + } binAPI .updateBin(bin.key(), form, as) .then(response => { @@ -698,11 +706,16 @@ export default function BinSettings(props: Props) { }; const inventoryControlLabel = (control: pond.BinInventoryControl) => { - let string = "Manual"; - if (control === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC) { - string = "Auto"; + switch(control){ + case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR: + return "Auto (lidar)" + case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC: + return "Auto (cable)" + case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR: + return "Hybrid (lidar)" + default: + return "Manual" } - return string; }; const inventoryForm = () => { @@ -818,6 +831,7 @@ export default function BinSettings(props: Props) { }> } label={"Auto (Lidar)"} /> + } + label={"Hybrid (Lidar)"} + /> {inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC && @@ -863,6 +882,36 @@ export default function BinSettings(props: Props) { )} + {inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR && ( + + + Hybrid control will submit a transaction that must be approved by the user before inventory is changed + + + )} + {(inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC_LIDAR || + inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR) && + + + % + + ) + }} + type="number" + value={autoFillThreshold} + onChange={e => { + setAutoFillThreshold(+e.target.value) + }} + /> + + } {empty ? ( @@ -1814,8 +1863,9 @@ export default function BinSettings(props: Props) { - - Shape} padding={1}> + + {/* Shape} padding={1}> */} + Shape ))} - + {/* */} Aeration effectiveness varies with bin shape diff --git a/src/bin/BinTransactions.tsx b/src/bin/BinTransactions.tsx new file mode 100644 index 0000000..2a8d6e2 --- /dev/null +++ b/src/bin/BinTransactions.tsx @@ -0,0 +1,522 @@ +import { CheckOutlined } from "@mui/icons-material"; +import { Autocomplete, Box, Button, Card, DialogActions, DialogContent, DialogTitle, TextField, Typography } from "@mui/material"; +import ResponsiveDialog from "common/ResponsiveDialog"; +import ResponsiveTable from "common/ResponsiveTable"; +import { Option } from "common/SearchSelect"; +import GrainDescriber from "grain/GrainDescriber"; +import { cloneDeep } from "lodash"; +import { Bin, Contract, Field, GrainBag } from "models"; +import { Transaction } from "models/Transaction"; +import moment from "moment"; +import ObjectDescriber from "objects/ObjectDescriber"; +import { pond } from "protobuf-ts/pond"; +import { useBinAPI, useContractAPI, useFieldAPI, useGrainBagAPI, useSnackbar, useTransactionAPI } from "providers"; +import React from "react"; +import { useCallback, useEffect, useState } from "react"; +import TransactionDataDisplay from "transactions/transactionDataDisplay"; +import { getGrainUnit } from "utils"; + +interface Props { + bin: Bin + permissions: pond.Permission[] + refresh: () => void +} + +export default function BinTransactions(props: Props){ + const { bin, permissions, refresh } = props + const [state, setState] = useState(pond.TransactionState.TRANSACTION_STATE_APPROVAL_REQUIRED) + const transactionAPI = useTransactionAPI() + const binAPI = useBinAPI() + const grainBagAPI = useGrainBagAPI() + const fieldAPI = useFieldAPI() + const contractAPI = useContractAPI() + const [transactions, setTransactions] = useState([]) + const [possibleTransactionMatches, setPossibleTransactionMatches] = useState([]) + const [tablePage, setTablePage] = useState(0) + const [tablePageSize, setTablePageSize] = useState(10) + const { openSnack } = useSnackbar(); + const [total, setTotal] = useState(0) + const [grainMessage, setGrainMessage] = useState("") + + //only need to do this for the bins since if a bin is picked for the secondary we need to check its inventory control type, + //if it is also hybrid a matching transaction must be selected + const [bins, setBins] = useState>(new Map()) + const [binOptions, setBinOptions] = useState([]) + + const [grainBagOptions, setGrainBagOptions] = useState([]) + + const [fieldOptions, setFieldOptions] = useState([]) + + const [contractOptions, setContractOptions] = useState([]) + + const [openDialog, setOpenDialog] = useState(false) + const [objectNames, setObjectNames] = useState(new Map()) + const [selectedTransaction, setSelectedTransaction] = useState() + const [selectedMatch, setselectedMatch] = useState() + + const [fromType, setFromType] = useState(pond.ObjectType.OBJECT_TYPE_UNKNOWN) + const [fromOption, setFromOption] = useState