merged websocket implementation
This commit is contained in:
commit
06c26f3262
41 changed files with 1181 additions and 468 deletions
246
package-lock.json
generated
246
package-lock.json
generated
|
|
@ -43,11 +43,7 @@
|
||||||
"mui-tel-input": "^7.0.0",
|
"mui-tel-input": "^7.0.0",
|
||||||
"notistack": "^3.0.1",
|
"notistack": "^3.0.1",
|
||||||
"openweathermap-ts": "^1.2.10",
|
"openweathermap-ts": "^1.2.10",
|
||||||
<<<<<<< HEAD
|
|
||||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#dev",
|
|
||||||
=======
|
|
||||||
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#staging",
|
"protobuf-ts": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#staging",
|
||||||
>>>>>>> messages_overhaul
|
|
||||||
"query-string": "^9.2.1",
|
"query-string": "^9.2.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-beautiful-dnd": "^13.1.1",
|
"react-beautiful-dnd": "^13.1.1",
|
||||||
|
|
@ -3747,9 +3743,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
|
||||||
"integrity": "sha512-mr0tmS/4FoVk1cnaeN244A/wjvGDNItZKR8hRhnmCzygyRXYtKF5jVDSIILR1U97CTzAYmbgIj/Dukg62ggG5w==",
|
"integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -3761,9 +3757,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-android-arm64": {
|
"node_modules/@rollup/rollup-android-arm64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-+s++dbp+/RTte62mQD9wLSbiMTV+xr/PeRJEc/sFZFSBRlHPNPVaf5FXlzAL77Mr8FtSfQqCN+I598M8U41ccQ==",
|
"integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -3775,9 +3771,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-MFWBwTcYs0jZbINQBXHfSrpSQJq3IUOakcKPzfeSznONop14Pxuqa0Kg19GD0rNBMPQI2tFtu3UzapZpH0Uc1Q==",
|
"integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -3789,9 +3785,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-darwin-x64": {
|
"node_modules/@rollup/rollup-darwin-x64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-yiKJY7pj9c9JwzuKYLFaDZw5gma3fI9bkPEIyofvVfsPqjCWPglSHdpdwXpKGvDeYDms3Qal8qGMEHZ1M/4Udg==",
|
"integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -3803,9 +3799,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-x97kCoBh5MOevpn/CNK9W1x8BEzO238541BGWBc315uOlN0AD/ifZ1msg+ZQB05Ux+VF6EcYqpiagfLJ8U3LvQ==",
|
"integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -3817,9 +3813,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-Aa8jPoZ6IQAG2eIrcXPpjRcMjROMFxCt1UYPZZtCxRV68WkuSigYtQ/7Zwrcr2IvtNJo7T2JfDXyMLxq5L4Jlg==",
|
"integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -3831,9 +3827,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
|
||||||
"integrity": "sha512-Ob8YgT5kD/lSIYW2Rcngs5kNB/44Q2RzBSPz9brf2WEtcGR7/f/E9HeHn1wYaAwKBni+bdXEwgHvUd0x12lQSA==",
|
"integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -3845,9 +3841,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
|
||||||
"integrity": "sha512-K+RI5oP1ceqoadvNt1FecL17Qtw/n9BgRSzxif3rTL2QlIu88ccvY+Y9nnHe/cmT5zbH9+bpiJuG1mGHRVwF4Q==",
|
"integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
|
|
@ -3859,9 +3855,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-T+17JAsCKUjmbopcKepJjHWHXSjeW7O5PL7lEFaeQmiVyw4kkc5/lyYKzrv6ElWRX/MrEWfPiJWqbTvfIvjM1Q==",
|
"integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -3873,9 +3869,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-cCePktb9+6R9itIJdeCFF9txPU7pQeEHB5AbHu/MKsfH/k70ZtOeq1k4YAtBv9Z7mmKI5/wOLYjQ+B9QdxR6LA==",
|
"integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -3887,9 +3883,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
"node_modules/@rollup/rollup-linux-loong64-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-iekUaLkfliAsDl4/xSdoCJ1gnnIXvoNz85C8U8+ZxknM5pBStfZjeXgB8lXobDQvvPRCN8FPmmuTtH+z95HTmg==",
|
"integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
|
|
@ -3901,9 +3897,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
"node_modules/@rollup/rollup-linux-loong64-musl": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-68ofRgJNl/jYJbxFjCKE7IwhbfxOl1muPN4KbIqAIe32lm22KmU7E8OPvyy68HTNkI2iV/c8y2kSPSm2mW/Q9Q==",
|
"integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
|
|
@ -3915,9 +3911,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-dpz8vT0i+JqUKuSNPCP5SYyIV2Lh0sNL1+FhM7eLC457d5B9/BC3kDPp5BBftMmTNsBarcPcoz5UGSsnCiw4XQ==",
|
"integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
|
@ -3929,9 +3925,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
"node_modules/@rollup/rollup-linux-ppc64-musl": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-4gdkkf9UJ7tafnweBCR/mk4jf3Jfl0cKX9Np80t5i78kjIH0ZdezUv/JDI2VtruE5lunfACqftJ8dIMGN4oHew==",
|
"integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
|
|
@ -3943,9 +3939,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-YFS4vPnOkDTD/JriUeeZurFYoJhPf9GQQEF/v4lltp3mVcBmnsAdjEWhr2cjUCZzZNzxCG0HZOvJU44UGHSdzw==",
|
"integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
|
@ -3957,9 +3953,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-x2xgZlFne+QVNKV8b4wwaCS8pwq3y14zedZ5DqLzjdRITvreBk//4Knbcvm7+lWmms9V9qFp60MtUd0/t/PXPw==",
|
"integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
|
|
@ -3971,9 +3967,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-jIhrujyn4UnWF8S+DHSkAkDEO3hLX0cjzxJZPLF80xFyzyUIYgSMRcYQ3+uqEoyDD2beGq7Dj7edi8OnJcS/hg==",
|
"integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
|
|
@ -3985,9 +3981,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-+410Srdoh78MKSJxTQ+hZ/Mx+ajd6RjjPwBPNd0R3J9FtL6ZA0GqiiyNjCO9In0IzZkCNrpGymSfn+kgyPQocg==",
|
"integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -3999,9 +3995,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
|
||||||
"integrity": "sha512-ZjMyby5SICi227y1MTR3VYBpFTdZs823Rs/hpakufleBoufoOIB6jtm9FEoxn/cgO7l6PM2rCEl5Kre5vX0QrQ==",
|
"integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -4013,9 +4009,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-openbsd-x64": {
|
"node_modules/@rollup/rollup-openbsd-x64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
|
||||||
"integrity": "sha512-ds4iwfYkSQ0k1nb8LTcyXw//ToHOnNTJtceySpL3fa7tc/AsE+UpUFphW126A6fKBGJD5dhRvg8zw1rvoGFxmw==",
|
"integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -4027,9 +4023,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-openharmony-arm64": {
|
"node_modules/@rollup/rollup-openharmony-arm64": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
|
||||||
"integrity": "sha512-fd/zpJniln4ICdPkjWFhZYeY/bpnaN9pGa6ko+5WD38I0tTqk9lXMgXZg09MNdhpARngmxiCg0B0XUamNw/5BQ==",
|
"integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -4041,9 +4037,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-YpG8dUOip7DCz3nr/JUfPbIUo+2d/dy++5bFzgi4ugOGBIox+qMbbqt/JoORwvI/C9Kn2tz6+Bieoqd5+B1CjA==",
|
"integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
|
|
@ -4055,9 +4051,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-b9DI8jpFQVh4hIXFr0/+N/TzLdpBIoPzjt0Rt4xJbW3mzguV3mduR9cNgiuFcuL/TeORejJhCWiAXe3E/6PxWA==",
|
"integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
|
|
@ -4069,9 +4065,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
"node_modules/@rollup/rollup-win32-x64-gnu": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
|
||||||
"integrity": "sha512-CSrVpmoRJFN06LL9xhkitkwUcTZtIotYAF5p6XOR2zW0Zz5mzb3IPpcoPhB02frzMHFNo1reQ9xSF5fFm3hUsQ==",
|
"integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -4083,9 +4079,9 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
|
||||||
"integrity": "sha512-QFsBgQNTnh5K0t/sBsjJLq24YVqEIVkGpfN2VHsnN90soZyhaiA9UUHufcctVNL4ypJY0wrwad0wslx2KJQ1/w==",
|
"integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
|
||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
|
|
@ -6960,13 +6956,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
|
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
|
||||||
"version": "9.0.5",
|
"version": "9.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz",
|
||||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
|
@ -9171,9 +9167,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/filelist/node_modules/minimatch": {
|
"node_modules/filelist/node_modules/minimatch": {
|
||||||
"version": "5.1.6",
|
"version": "5.1.9",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz",
|
||||||
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
|
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -9668,9 +9664,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob/node_modules/minimatch": {
|
"node_modules/glob/node_modules/minimatch": {
|
||||||
"version": "10.2.2",
|
"version": "10.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
|
||||||
"integrity": "sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==",
|
"integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BlueOak-1.0.0",
|
"license": "BlueOak-1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -11220,9 +11216,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -11971,11 +11967,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#bcf085706791036841f7047a5b37f00c18e54574",
|
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#bcf085706791036841f7047a5b37f00c18e54574",
|
||||||
=======
|
|
||||||
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#ab9e8d4fd38f9af7802398403d38fddda5eb01da",
|
|
||||||
>>>>>>> messages_overhaul
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"protobufjs": "^6.8.8"
|
"protobufjs": "^6.8.8"
|
||||||
}
|
}
|
||||||
|
|
@ -12931,9 +12923,9 @@
|
||||||
"license": "Unlicense"
|
"license": "Unlicense"
|
||||||
},
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "4.58.0",
|
"version": "4.59.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.58.0.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
|
||||||
"integrity": "sha512-wbT0mBmWbIvvq8NeEYWWvevvxnOyhKChir47S66WCxw1SXqhw7ssIYejnQEVt7XYQpsj2y8F9PM+Cr3SNEa0gw==",
|
"integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -12947,31 +12939,31 @@
|
||||||
"npm": ">=8.0.0"
|
"npm": ">=8.0.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@rollup/rollup-android-arm-eabi": "4.58.0",
|
"@rollup/rollup-android-arm-eabi": "4.59.0",
|
||||||
"@rollup/rollup-android-arm64": "4.58.0",
|
"@rollup/rollup-android-arm64": "4.59.0",
|
||||||
"@rollup/rollup-darwin-arm64": "4.58.0",
|
"@rollup/rollup-darwin-arm64": "4.59.0",
|
||||||
"@rollup/rollup-darwin-x64": "4.58.0",
|
"@rollup/rollup-darwin-x64": "4.59.0",
|
||||||
"@rollup/rollup-freebsd-arm64": "4.58.0",
|
"@rollup/rollup-freebsd-arm64": "4.59.0",
|
||||||
"@rollup/rollup-freebsd-x64": "4.58.0",
|
"@rollup/rollup-freebsd-x64": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm-gnueabihf": "4.58.0",
|
"@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm-musleabihf": "4.58.0",
|
"@rollup/rollup-linux-arm-musleabihf": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm64-gnu": "4.58.0",
|
"@rollup/rollup-linux-arm64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-arm64-musl": "4.58.0",
|
"@rollup/rollup-linux-arm64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-loong64-gnu": "4.58.0",
|
"@rollup/rollup-linux-loong64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-loong64-musl": "4.58.0",
|
"@rollup/rollup-linux-loong64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-ppc64-gnu": "4.58.0",
|
"@rollup/rollup-linux-ppc64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-ppc64-musl": "4.58.0",
|
"@rollup/rollup-linux-ppc64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-riscv64-gnu": "4.58.0",
|
"@rollup/rollup-linux-riscv64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-riscv64-musl": "4.58.0",
|
"@rollup/rollup-linux-riscv64-musl": "4.59.0",
|
||||||
"@rollup/rollup-linux-s390x-gnu": "4.58.0",
|
"@rollup/rollup-linux-s390x-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-x64-gnu": "4.58.0",
|
"@rollup/rollup-linux-x64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-linux-x64-musl": "4.58.0",
|
"@rollup/rollup-linux-x64-musl": "4.59.0",
|
||||||
"@rollup/rollup-openbsd-x64": "4.58.0",
|
"@rollup/rollup-openbsd-x64": "4.59.0",
|
||||||
"@rollup/rollup-openharmony-arm64": "4.58.0",
|
"@rollup/rollup-openharmony-arm64": "4.59.0",
|
||||||
"@rollup/rollup-win32-arm64-msvc": "4.58.0",
|
"@rollup/rollup-win32-arm64-msvc": "4.59.0",
|
||||||
"@rollup/rollup-win32-ia32-msvc": "4.58.0",
|
"@rollup/rollup-win32-ia32-msvc": "4.59.0",
|
||||||
"@rollup/rollup-win32-x64-gnu": "4.58.0",
|
"@rollup/rollup-win32-x64-gnu": "4.59.0",
|
||||||
"@rollup/rollup-win32-x64-msvc": "4.58.0",
|
"@rollup/rollup-win32-x64-msvc": "4.59.0",
|
||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -15786,9 +15778,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/workbox-build/node_modules/rollup": {
|
"node_modules/workbox-build/node_modules/rollup": {
|
||||||
"version": "2.79.2",
|
"version": "2.80.0",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz",
|
||||||
"integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==",
|
"integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ const useStyles = makeStyles((theme: Theme) => {
|
||||||
},
|
},
|
||||||
position: "fixed",
|
position: "fixed",
|
||||||
bottom: theme.spacing(8), //for mobile navigator
|
bottom: theme.spacing(8), //for mobile navigator
|
||||||
right: theme.spacing(10.25),
|
right: theme.spacing(2),
|
||||||
[theme.breakpoints.up("sm")]: {
|
[theme.breakpoints.up("sm")]: {
|
||||||
bottom: theme.spacing(1.75)
|
bottom: theme.spacing(1.75)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -443,14 +443,24 @@ export default function BinCard(props: Props) {
|
||||||
" L"
|
" L"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1) {
|
||||||
return (
|
return (
|
||||||
bin.grainTonnes().toLocaleString() +
|
bin.grainInventory().toLocaleString() +
|
||||||
" mT " +
|
" mT " +
|
||||||
bin.fillPercent() +
|
bin.fillPercent() +
|
||||||
"%"
|
"%"
|
||||||
);
|
);
|
||||||
|
} else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1) {
|
||||||
|
return (
|
||||||
|
bin.grainInventory().toLocaleString() +
|
||||||
|
" t " +
|
||||||
|
bin.fillPercent() +
|
||||||
|
"%"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
current.toLocaleString() +
|
current.toLocaleString() +
|
||||||
"/" +
|
"/" +
|
||||||
|
|
|
||||||
|
|
@ -126,14 +126,13 @@ interface BinFormExtension {
|
||||||
hopperHeight: string;
|
hopperHeight: string;
|
||||||
diameter: string;
|
diameter: string;
|
||||||
grainBushels: string;
|
grainBushels: string;
|
||||||
grainTonnes: string;
|
grainWeight: string;
|
||||||
grainType: Option | null;
|
grainType: Option | null;
|
||||||
grainUse: Option | null;
|
grainUse: Option | null;
|
||||||
grainSubtype: string;
|
grainSubtype: string;
|
||||||
customTypeName: string;
|
customTypeName: string;
|
||||||
highTemp: number;
|
highTemp: number;
|
||||||
lowTemp: number;
|
lowTemp: number;
|
||||||
bushelsPerTonne: string;
|
|
||||||
tempTarget: number;
|
tempTarget: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -160,14 +159,13 @@ export default function BinSettings(props: Props) {
|
||||||
hopperHeight: "",
|
hopperHeight: "",
|
||||||
diameter: "",
|
diameter: "",
|
||||||
grainBushels: "",
|
grainBushels: "",
|
||||||
grainTonnes: "",
|
grainWeight: "",
|
||||||
grainType: null,
|
grainType: null,
|
||||||
grainUse: null,
|
grainUse: null,
|
||||||
grainSubtype: "",
|
grainSubtype: "",
|
||||||
customTypeName: "",
|
customTypeName: "",
|
||||||
highTemp: 20,
|
highTemp: 20,
|
||||||
lowTemp: 10,
|
lowTemp: 10,
|
||||||
bushelsPerTonne: "",
|
|
||||||
tempTarget: 15
|
tempTarget: 15
|
||||||
});
|
});
|
||||||
const [initialized, setInitialized] = useState(false);
|
const [initialized, setInitialized] = useState(false);
|
||||||
|
|
@ -194,6 +192,7 @@ export default function BinSettings(props: Props) {
|
||||||
const [isCustomBin, setIsCustomBin] = useState(false);
|
const [isCustomBin, setIsCustomBin] = useState(false);
|
||||||
const [binModelOps, setBinModelOptions] = useState<Option[]>([]);
|
const [binModelOps, setBinModelOptions] = useState<Option[]>([]);
|
||||||
const [selectedBinModel, setSelectedBinModel] = useState<Option | null>(null);
|
const [selectedBinModel, setSelectedBinModel] = useState<Option | null>(null);
|
||||||
|
const [bushelConversion, setBushelConversion] = useState(0) //the number used to convert the bushels to either tonne or ton based on user preference
|
||||||
const [modelID, setModelID] = useState(0);
|
const [modelID, setModelID] = useState(0);
|
||||||
const [autoTopNode, setAutoTopNode] = useState(false);
|
const [autoTopNode, setAutoTopNode] = useState(false);
|
||||||
const [inventoryControl, setInventoryControl] = useState<pond.BinInventoryControl>(
|
const [inventoryControl, setInventoryControl] = useState<pond.BinInventoryControl>(
|
||||||
|
|
@ -232,14 +231,27 @@ export default function BinSettings(props: Props) {
|
||||||
|
|
||||||
if (initForm.inventory) {
|
if (initForm.inventory) {
|
||||||
setInventoryControl(initForm.inventory.inventoryControl);
|
setInventoryControl(initForm.inventory.inventoryControl);
|
||||||
//make sure bushels per tonne is set so bins that don't have it in the settings yet can still do it before they get updated properly
|
//make sure bushels per ton/ne is set so bins that don't have it in the settings yet can still do it before they get updated properly
|
||||||
if (!initForm.inventory.bushelsPerTonne) {
|
const grain = GrainDescriber(
|
||||||
initForm.inventory.bushelsPerTonne = GrainDescriber(
|
|
||||||
initForm.inventory.grainType
|
initForm.inventory.grainType
|
||||||
).bushelsPerTonne;
|
)
|
||||||
|
|
||||||
|
if (!initForm.inventory.bushelsPerTonne) {
|
||||||
|
initForm.inventory.bushelsPerTonne = grain.bushelsPerTonne;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
setBushelConversion(initForm.inventory.bushelsPerTonne)
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
setBushelConversion(initForm.inventory.bushelsPerTonne * 0.907)
|
||||||
}
|
}
|
||||||
if (initForm.inventory.customGrain){
|
if (initForm.inventory.customGrain){
|
||||||
setCustomGrain(initForm.inventory.customGrain)
|
setCustomGrain(initForm.inventory.customGrain)
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
setBushelConversion(initForm.inventory.customGrain.bushelsPerTonne)
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
setBushelConversion(initForm.inventory.customGrain.bushelsPerTonne * 0.907)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//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) {
|
||||||
|
|
@ -290,6 +302,21 @@ export default function BinSettings(props: Props) {
|
||||||
? initForm.inventory.grainBushels * 35.239
|
? initForm.inventory.grainBushels * 35.239
|
||||||
: 0
|
: 0
|
||||||
: initForm.inventory?.grainBushels ?? 0;
|
: initForm.inventory?.grainBushels ?? 0;
|
||||||
|
let weight = ""
|
||||||
|
if(initForm.inventory){
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
weight = (gb/initForm.inventory.bushelsPerTonne).toFixed(2)
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
weight = (gb/(initForm.inventory.bushelsPerTonne * 0.907)).toFixed(2)
|
||||||
|
}
|
||||||
|
if(initForm.inventory.customGrain){
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
weight = (gb/initForm.inventory.customGrain.bushelsPerTonne).toFixed(2)
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
weight = (gb/(initForm.inventory.customGrain.bushelsPerTonne * 0.907)).toFixed(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setForm(initForm);
|
setForm(initForm);
|
||||||
setHighTempC(initForm.highTemp ?? 20);
|
setHighTempC(initForm.highTemp ?? 20);
|
||||||
|
|
@ -299,9 +326,10 @@ export default function BinSettings(props: Props) {
|
||||||
height: h,
|
height: h,
|
||||||
diameter: d,
|
diameter: d,
|
||||||
grainBushels: gb.toFixed(2),
|
grainBushels: gb.toFixed(2),
|
||||||
grainTonnes: initForm.inventory?.bushelsPerTonne
|
grainWeight: weight,
|
||||||
? (gb / initForm.inventory.bushelsPerTonne).toFixed(2)
|
// grainTons: initForm.inventory?.bushelsPerTon
|
||||||
: "",
|
// ? (gb / initForm.inventory.bushelsPerTon).toFixed(2)
|
||||||
|
// : "",
|
||||||
grainType: initForm.inventory?.grainType
|
grainType: initForm.inventory?.grainType
|
||||||
? ToGrainOption(initForm.inventory.grainType)
|
? ToGrainOption(initForm.inventory.grainType)
|
||||||
: null,
|
: null,
|
||||||
|
|
@ -315,8 +343,7 @@ export default function BinSettings(props: Props) {
|
||||||
tempTarget: target,
|
tempTarget: target,
|
||||||
hopperHeight: hopperHeight,
|
hopperHeight: hopperHeight,
|
||||||
topConeHeight: topconeHeight,
|
topConeHeight: topconeHeight,
|
||||||
sidewallHeight: sidewallHeight,
|
sidewallHeight: sidewallHeight
|
||||||
bushelsPerTonne: initForm.inventory?.bushelsPerTonne.toString() ?? "0"
|
|
||||||
});
|
});
|
||||||
setInMoistureString(initForm.inventory?.initialMoisture.toString() ?? "0");
|
setInMoistureString(initForm.inventory?.initialMoisture.toString() ?? "0");
|
||||||
setTMoistureString(initForm.inventory?.targetMoisture.toString() ?? "0");
|
setTMoistureString(initForm.inventory?.targetMoisture.toString() ?? "0");
|
||||||
|
|
@ -771,12 +798,103 @@ export default function BinSettings(props: Props) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const inventoryAmount = () => {
|
||||||
|
const grainWeight = formExtension.grainWeight;
|
||||||
|
const binQuantity = formExtension.grainBushels;
|
||||||
|
|
||||||
|
//as long as the storage type is not fertilizer it is some sort of grain, whether it is supported or custom is not important in this instance so we do not need to check for unknown
|
||||||
|
if(storageType !== pond.BinStorage.BIN_STORAGE_FERTILIZER && ((getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE || getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON) && bushelConversion !== 0 && grainWeight !== "")){
|
||||||
|
return (
|
||||||
|
<TextField
|
||||||
|
label="Amount"
|
||||||
|
value={grainWeight}
|
||||||
|
type="number"
|
||||||
|
onChange={event => {
|
||||||
|
let newWeight = event.target.value;
|
||||||
|
//get the bushel amount
|
||||||
|
if (!isNaN(+newWeight)) {
|
||||||
|
let newBushels = Math.round(+newWeight * bushelConversion * 100) / 100;
|
||||||
|
updateForm(
|
||||||
|
"inventory",
|
||||||
|
pond.BinInventory.create({
|
||||||
|
...form.inventory,
|
||||||
|
grainBushels: newBushels
|
||||||
|
})
|
||||||
|
);
|
||||||
|
//updateFormExtension("grainBushels", newBushels.toString())
|
||||||
|
updateFormExtension("grainWeight", newWeight);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
disabled={!canEdit}
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: <InputAdornment position="end">{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE ? "mT" : "t"}</InputAdornment>
|
||||||
|
}}
|
||||||
|
className={classes.bottomSpacing}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}else{
|
||||||
|
return (
|
||||||
|
<TextField
|
||||||
|
label="Amount"
|
||||||
|
value={binQuantity}
|
||||||
|
type="number"
|
||||||
|
onChange={event => {
|
||||||
|
let capacity =
|
||||||
|
bin?.settings.storage === pond.BinStorage.BIN_STORAGE_FERTILIZER
|
||||||
|
? +inputCapacity * 35.239
|
||||||
|
: inputCapacity;
|
||||||
|
let value = event?.target.value;
|
||||||
|
let v =
|
||||||
|
value === ""
|
||||||
|
? 0
|
||||||
|
: isNaN(parseFloat(value))
|
||||||
|
? 0
|
||||||
|
: parseFloat(value) >= +capacity
|
||||||
|
? +capacity
|
||||||
|
: parseFloat(value) <= 0
|
||||||
|
? 0
|
||||||
|
: parseFloat(value);
|
||||||
|
if (bin?.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER && v) {
|
||||||
|
v = v / 35.239;
|
||||||
|
}
|
||||||
|
//setNewGrainQuantity(v);
|
||||||
|
updateForm(
|
||||||
|
"inventory",
|
||||||
|
pond.BinInventory.create({
|
||||||
|
...form.inventory,
|
||||||
|
grainBushels: v
|
||||||
|
})
|
||||||
|
);
|
||||||
|
updateFormExtension("grainBushels", value);
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
endAdornment: (
|
||||||
|
<InputAdornment position="end">
|
||||||
|
{storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER
|
||||||
|
? "Litres"
|
||||||
|
: "Bushels"}
|
||||||
|
</InputAdornment>
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
disabled={
|
||||||
|
!canEdit ||
|
||||||
|
inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC
|
||||||
|
}
|
||||||
|
className={classes.bottomSpacing}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const inventoryForm = () => {
|
const inventoryForm = () => {
|
||||||
const inventory = form.inventory;
|
const inventory = form.inventory;
|
||||||
const empty = inventory ? inventory.empty : false;
|
const empty = inventory ? inventory.empty : false;
|
||||||
const bushPerTonne = formExtension.bushelsPerTonne;
|
|
||||||
const binQuantity = formExtension.grainBushels;
|
const binQuantity = formExtension.grainBushels;
|
||||||
const grainTonnes = formExtension.grainTonnes;
|
|
||||||
const grainType = formExtension.grainType;
|
const grainType = formExtension.grainType;
|
||||||
const grainSubtype = formExtension.grainSubtype;
|
const grainSubtype = formExtension.grainSubtype;
|
||||||
const grainUse = formExtension.grainUse;
|
const grainUse = formExtension.grainUse;
|
||||||
|
|
@ -805,11 +923,11 @@ export default function BinSettings(props: Props) {
|
||||||
pond.BinInventory.create({
|
pond.BinInventory.create({
|
||||||
...form.inventory,
|
...form.inventory,
|
||||||
grainType: pond.Grain.GRAIN_CUSTOM,
|
grainType: pond.Grain.GRAIN_CUSTOM,
|
||||||
bushelsPerTonne: 0
|
bushelsPerTonne: 0,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
updateFormExtension("grainType", null);
|
updateFormExtension("grainType", null);
|
||||||
updateFormExtension("bushelsPerTonne", "");
|
setBushelConversion(0)
|
||||||
} else {
|
} else {
|
||||||
setStorageType(pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
|
setStorageType(pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN);
|
||||||
updateForm(
|
updateForm(
|
||||||
|
|
@ -859,7 +977,8 @@ export default function BinSettings(props: Props) {
|
||||||
let storageType = parseFloat(value) as pond.BinStorage;
|
let storageType = parseFloat(value) as pond.BinStorage;
|
||||||
setStorageType(storageType);
|
setStorageType(storageType);
|
||||||
if (storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
if (storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||||
formExtension.bushelsPerTonne = "";
|
// formExtension.bushelsPerTonne = "";
|
||||||
|
setBushelConversion(0)
|
||||||
formExtension.grainBushels = (
|
formExtension.grainBushels = (
|
||||||
parseFloat(formExtension.grainBushels) * 35.239
|
parseFloat(formExtension.grainBushels) * 35.239
|
||||||
).toFixed(0);
|
).toFixed(0);
|
||||||
|
|
@ -1054,7 +1173,29 @@ export default function BinSettings(props: Props) {
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
:
|
:
|
||||||
<Box sx={{border: "1px solid white", borderRadius: 2, padding: 2, marginBottom: 2}}>
|
<Box sx={{border: "1px solid white", borderRadius: 2, padding: 2, marginBottom: 2}}>
|
||||||
<CustomGrainSelector initialGrain={customGrain} onGrainSettingsChange={(newGrainSettings) => {setCustomGrain(newGrainSettings)}}/>
|
<CustomGrainSelector
|
||||||
|
initialGrain={customGrain}
|
||||||
|
onGrainSettingsChange={(newGrainSettings) => {
|
||||||
|
setCustomGrain(newGrainSettings)
|
||||||
|
let conversion = 0
|
||||||
|
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
conversion = newGrainSettings.bushelsPerTonne
|
||||||
|
}else if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
conversion = newGrainSettings.bushelsPerTonne * 0.907
|
||||||
|
}
|
||||||
|
updateForm(
|
||||||
|
"inventory",
|
||||||
|
pond.BinInventory.create({
|
||||||
|
...form.inventory,
|
||||||
|
bushelsPerTonne: newGrainSettings.bushelsPerTonne,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
setBushelConversion(conversion)
|
||||||
|
if(conversion !== 0 && !isNaN(+binQuantity)){
|
||||||
|
updateFormExtension("grainWeight", (+binQuantity/conversion).toFixed(2))
|
||||||
|
}
|
||||||
|
}}/>
|
||||||
</Box>
|
</Box>
|
||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
@ -1073,11 +1214,21 @@ export default function BinSettings(props: Props) {
|
||||||
pond.BinInventory.create({
|
pond.BinInventory.create({
|
||||||
...form.inventory,
|
...form.inventory,
|
||||||
grainType: newGrainType,
|
grainType: newGrainType,
|
||||||
bushelsPerTonne: GrainDescriber(newGrainType).bushelsPerTonne
|
bushelsPerTonne: GrainDescriber(newGrainType).bushelsPerTonne,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
//doesn't need to update the form extension to display the bushels per tonne as it is not changeable for the supported grain
|
let conversion = 0
|
||||||
//and is reset whenever the user switches between custom or not
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
conversion = GrainDescriber(newGrainType).bushelsPerTonne
|
||||||
|
}else if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
conversion = GrainDescriber(newGrainType).bushelsPerTon
|
||||||
|
}
|
||||||
|
setBushelConversion(conversion)
|
||||||
|
if(conversion !== 0 && !isNaN(+binQuantity)){
|
||||||
|
//updateFormExtension("grainWeight", (+binQuantity/conversion).toFixed(2))
|
||||||
|
let newWeight = (+binQuantity/conversion).toFixed(2)
|
||||||
|
formExtension.grainWeight = newWeight
|
||||||
|
}
|
||||||
updateFormExtension("grainType", option);
|
updateFormExtension("grainType", option);
|
||||||
}}
|
}}
|
||||||
group
|
group
|
||||||
|
|
@ -1106,7 +1257,8 @@ export default function BinSettings(props: Props) {
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_BUSHELS ||
|
{inventoryAmount()}
|
||||||
|
{/* {getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_BUSHELS ||
|
||||||
storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ||
|
storageType === pond.BinStorage.BIN_STORAGE_FERTILIZER ||
|
||||||
formExtension.bushelsPerTonne === "0" ||
|
formExtension.bushelsPerTonne === "0" ||
|
||||||
formExtension.bushelsPerTonne === "" ? (
|
formExtension.bushelsPerTonne === "" ? (
|
||||||
|
|
@ -1163,7 +1315,7 @@ export default function BinSettings(props: Props) {
|
||||||
) : (
|
) : (
|
||||||
<TextField
|
<TextField
|
||||||
label="Amount"
|
label="Amount"
|
||||||
value={grainTonnes}
|
value={grainWeight}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
let newWeight = event.target.value;
|
let newWeight = event.target.value;
|
||||||
|
|
@ -1180,7 +1332,7 @@ export default function BinSettings(props: Props) {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
//updateFormExtension("grainBushels", newBushels.toString())
|
//updateFormExtension("grainBushels", newBushels.toString())
|
||||||
updateFormExtension("grainTonnes", newWeight);
|
updateFormExtension("grainWeight", newWeight);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
|
|
@ -1191,7 +1343,7 @@ export default function BinSettings(props: Props) {
|
||||||
}}
|
}}
|
||||||
className={classes.bottomSpacing}
|
className={classes.bottomSpacing}
|
||||||
/>
|
/>
|
||||||
)}
|
)} */}
|
||||||
{!isCustomInventory && (
|
{!isCustomInventory && (
|
||||||
<SearchSelect
|
<SearchSelect
|
||||||
label="Use"
|
label="Use"
|
||||||
|
|
|
||||||
|
|
@ -196,14 +196,27 @@ export default function BinTransactions(props: Props){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const grainQuantityDisplay = (bushels: number) => {
|
||||||
|
const grainTransaction = selectedTransaction?.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && grainTransaction.bushelsPerTonne > 1){
|
||||||
|
let tonneWeight = bushels / grainTransaction.bushelsPerTonne
|
||||||
|
return tonneWeight + " mT"
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && grainTransaction.bushelsPerTonne > 1){
|
||||||
|
let tonneWeight = bushels / (grainTransaction.bushelsPerTonne * 0.907)
|
||||||
|
return tonneWeight + " t"
|
||||||
|
}
|
||||||
|
return bushels + " bushels"
|
||||||
|
}
|
||||||
|
|
||||||
// dialog for approving a transaction
|
// dialog for approving a transaction
|
||||||
const approvalDialog = () => {
|
const approvalDialog = () => {
|
||||||
// get the display information for the transaction
|
// get the display information for the transaction
|
||||||
const grainTransaction = selectedTransaction?.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
const grainTransaction = selectedTransaction?.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
||||||
const bushels = grainTransaction.bushels ?? 0
|
const bushels = grainTransaction.bushels ?? 0
|
||||||
const weight = bushels / grainTransaction.bushelsPerTonne
|
//const weight = bushels / grainTransaction.bushelsPerTonne
|
||||||
let graintype = grainTransaction.grainType ?? pond.Grain.GRAIN_INVALID
|
let graintype = grainTransaction.grainType ?? pond.Grain.GRAIN_INVALID
|
||||||
const grainDisplay = graintype === pond.Grain.GRAIN_CUSTOM
|
const grainTypeDisplay = graintype === pond.Grain.GRAIN_CUSTOM
|
||||||
? grainTransaction.customGrain
|
? grainTransaction.customGrain
|
||||||
: GrainDescriber(grainTransaction.grainType).name
|
: GrainDescriber(grainTransaction.grainType).name
|
||||||
|
|
||||||
|
|
@ -215,7 +228,7 @@ export default function BinTransactions(props: Props){
|
||||||
<DialogTitle>Accept Transaction</DialogTitle>
|
<DialogTitle>Accept Transaction</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography>{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? weight + " mT" : bushels + " bushels"} of {grainTransaction.subtype} {grainDisplay} moved</Typography>
|
<Typography>{grainQuantityDisplay(bushels)} of {grainTransaction.subtype} {grainTypeDisplay} moved</Typography>
|
||||||
<Typography margin={1} fontWeight={650}>From:</Typography>
|
<Typography margin={1} fontWeight={650}>From:</Typography>
|
||||||
{/*Object type selection*/}
|
{/*Object type selection*/}
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
|
|
@ -378,9 +391,9 @@ export default function BinTransactions(props: Props){
|
||||||
// get the display information for the transaction
|
// get the display information for the transaction
|
||||||
const grainTransaction = t.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
const grainTransaction = t.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
||||||
const bushels = grainTransaction.bushels ?? 0
|
const bushels = grainTransaction.bushels ?? 0
|
||||||
const weight = bushels / grainTransaction.bushelsPerTonne
|
// const weight = bushels / grainTransaction.bushelsPerTonne
|
||||||
let graintype = grainTransaction.grainType ?? pond.Grain.GRAIN_INVALID
|
let graintype = grainTransaction.grainType ?? pond.Grain.GRAIN_INVALID
|
||||||
const grainDisplay = graintype === pond.Grain.GRAIN_CUSTOM
|
const grainTypeDisplay = graintype === pond.Grain.GRAIN_CUSTOM
|
||||||
? grainTransaction.customGrain
|
? grainTransaction.customGrain
|
||||||
: GrainDescriber(grainTransaction.grainType).name
|
: GrainDescriber(grainTransaction.grainType).name
|
||||||
return (
|
return (
|
||||||
|
|
@ -394,7 +407,7 @@ export default function BinTransactions(props: Props){
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box display="flex" justifyContent="space-between">
|
<Box display="flex" justifyContent="space-between">
|
||||||
<Typography sx={{margin: "auto", marginLeft: 0}}>{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? weight + " mT" : bushels + " bushels"} of {grainTransaction.subtype} {grainDisplay} moved</Typography>
|
<Typography sx={{margin: "auto", marginLeft: 0}}>{grainQuantityDisplay(bushels)} of {grainTransaction.subtype} {grainTypeDisplay} moved</Typography>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
disabled={selectedMatch?.transaction.key === t.transaction.key}
|
disabled={selectedMatch?.transaction.key === t.transaction.key}
|
||||||
|
|
|
||||||
|
|
@ -270,7 +270,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
const [storageType, setStorageType] = useState<pond.BinStorage>(
|
const [storageType, setStorageType] = useState<pond.BinStorage>(
|
||||||
pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN
|
pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN
|
||||||
);
|
);
|
||||||
const [bushPerTonne, setBushPerTonne] = useState("0");
|
//const [bushPerTonne, setBushPerTonne] = useState("0");
|
||||||
const [grainSubtype, setGrainSubtype] = useState("");
|
const [grainSubtype, setGrainSubtype] = useState("");
|
||||||
|
|
||||||
const [loadingTrend, setLoadingTrend] = useState(false);
|
const [loadingTrend, setLoadingTrend] = useState(false);
|
||||||
|
|
@ -326,7 +326,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
setCustomTypeName(bin.settings.inventory.customTypeName);
|
setCustomTypeName(bin.settings.inventory.customTypeName);
|
||||||
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));
|
||||||
setGrainSubtype(bin.subtype());
|
setGrainSubtype(bin.subtype());
|
||||||
setNewBinMode(bin.settings.mode);
|
setNewBinMode(bin.settings.mode);
|
||||||
setNewGrainSettings(bin.customGrain());
|
setNewGrainSettings(bin.customGrain());
|
||||||
|
|
@ -495,8 +495,10 @@ export default function BinVisualizer(props: Props) {
|
||||||
if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||||
return Math.round(val * 35.239 * 100) / 100;
|
return Math.round(val * 35.239 * 100) / 100;
|
||||||
} else {
|
} else {
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1) {
|
||||||
return Math.round((val / bin.bushelsPerTonne()) * 100) / 100;
|
return Math.round((val / bin.bushelsPerTonne()) * 100) / 100;
|
||||||
|
} else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1) {
|
||||||
|
return Math.round((val / (bin.bushelsPerTonne()*0.907)) * 100) / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
|
|
@ -511,17 +513,19 @@ export default function BinVisualizer(props: Props) {
|
||||||
if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
if (bin.storage() === pond.BinStorage.BIN_STORAGE_FERTILIZER) {
|
||||||
return " / " + capacity.toLocaleString() + " L";
|
return " / " + capacity.toLocaleString() + " L";
|
||||||
}
|
}
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1) {
|
||||||
return "mT (" + bin.fillPercent() + "%)";
|
return "mT (" + bin.fillPercent() + "%)";
|
||||||
|
} else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1) {
|
||||||
|
return "t (" + bin.fillPercent() + "%)";
|
||||||
} else {
|
} else {
|
||||||
return " / " + capacity.toLocaleString() + " bu";
|
return " / " + capacity.toLocaleString() + " bu";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const grainErrorCheck = () => {
|
// const grainErrorCheck = () => {
|
||||||
if (isNaN(parseFloat(bushPerTonne))) return true;
|
// if (isNaN(parseFloat(bushPerTonne))) return true;
|
||||||
return false;
|
// return false;
|
||||||
};
|
// };
|
||||||
|
|
||||||
const inventoryOverview = () => {
|
const inventoryOverview = () => {
|
||||||
const capacity = bin.settings.specs?.bushelCapacity ?? 0;
|
const capacity = bin.settings.specs?.bushelCapacity ?? 0;
|
||||||
|
|
@ -774,7 +778,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
setCustomTypeName(bin.settings.inventory.customTypeName);
|
setCustomTypeName(bin.settings.inventory.customTypeName);
|
||||||
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())
|
setNewGrainSettings(bin.customGrain())
|
||||||
setGrainSubtype(bin.subtype());
|
setGrainSubtype(bin.subtype());
|
||||||
}
|
}
|
||||||
|
|
@ -802,7 +806,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
checked={isCustomInventory}
|
checked={isCustomInventory}
|
||||||
onChange={(_, checked) => {
|
onChange={(_, checked) => {
|
||||||
setIsCustomInventory(checked);
|
setIsCustomInventory(checked);
|
||||||
setBushPerTonne("0");
|
//setBushPerTonne("0");
|
||||||
setGrainSubtype("");
|
setGrainSubtype("");
|
||||||
setCustomTypeName("");
|
setCustomTypeName("");
|
||||||
setGrainOption(ToGrainOption(pond.Grain.GRAIN_NONE));
|
setGrainOption(ToGrainOption(pond.Grain.GRAIN_NONE));
|
||||||
|
|
@ -834,7 +838,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
: pond.Grain.GRAIN_INVALID;
|
: pond.Grain.GRAIN_INVALID;
|
||||||
setGrainOption(ToGrainOption(newGrainType));
|
setGrainOption(ToGrainOption(newGrainType));
|
||||||
setGrainType(newGrainType);
|
setGrainType(newGrainType);
|
||||||
setBushPerTonne(GrainDescriber(newGrainType).bushelsPerTonne.toFixed(2));
|
//setBushPerTonne(GrainDescriber(newGrainType).bushelsPerTonne.toFixed(2));
|
||||||
}}
|
}}
|
||||||
group
|
group
|
||||||
disabled={!canEdit}
|
disabled={!canEdit}
|
||||||
|
|
@ -897,7 +901,7 @@ export default function BinVisualizer(props: Props) {
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
color="primary"
|
color="primary"
|
||||||
disabled={grainErrorCheck()}
|
// disabled={grainErrorCheck()}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
updateBin();
|
updateBin();
|
||||||
setGrainChangeDialog(false);
|
setGrainChangeDialog(false);
|
||||||
|
|
@ -1321,13 +1325,20 @@ export default function BinVisualizer(props: Props) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bin.bushelsPerTonne() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1) {
|
||||||
diffDisplay = diffDisplay / bin.bushelsPerTonne();
|
diffDisplay = diffDisplay / bin.bushelsPerTonne();
|
||||||
if (pendingDisplay) {
|
if (pendingDisplay) {
|
||||||
pendingDisplay = pendingDisplay / bin.bushelsPerTonne();
|
pendingDisplay = pendingDisplay / bin.bushelsPerTonne();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1) {
|
||||||
|
diffDisplay = diffDisplay / (bin.bushelsPerTonne()*0.907);
|
||||||
|
if (pendingDisplay) {
|
||||||
|
pendingDisplay = pendingDisplay / (bin.bushelsPerTonne()*0.907);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box display="flex" width={1} justifyContent="flex-end">
|
<Box display="flex" width={1} justifyContent="flex-end">
|
||||||
<FullScreen handle={fullScreenHandler}>
|
<FullScreen handle={fullScreenHandler}>
|
||||||
|
|
@ -1987,9 +1998,10 @@ export default function BinVisualizer(props: Props) {
|
||||||
//update all the grain stuff
|
//update all the grain stuff
|
||||||
b.settings.inventory.grainType = grainType;
|
b.settings.inventory.grainType = grainType;
|
||||||
b.settings.inventory.customTypeName = customTypeName;
|
b.settings.inventory.customTypeName = customTypeName;
|
||||||
b.settings.inventory.bushelsPerTonne = isNaN(parseFloat(bushPerTonne))
|
b.settings.inventory.bushelsPerTonne = GrainDescriber(grainType).bushelsPerTonne
|
||||||
? 0
|
// b.settings.inventory.bushelsPerTonne = isNaN(parseFloat(bushPerTonne))
|
||||||
: parseFloat(bushPerTonne);
|
// ? 0
|
||||||
|
// : parseFloat(bushPerTonne);
|
||||||
b.settings.inventory.grainSubtype = grainSubtype;
|
b.settings.inventory.grainSubtype = grainSubtype;
|
||||||
b.settings.inventory.customGrain = newGrainSettings
|
b.settings.inventory.customGrain = newGrainSettings
|
||||||
}
|
}
|
||||||
|
|
@ -2010,7 +2022,6 @@ export default function BinVisualizer(props: Props) {
|
||||||
}
|
}
|
||||||
b.settings.mode = newBinMode;
|
b.settings.mode = newBinMode;
|
||||||
}
|
}
|
||||||
console.log(b.settings)
|
|
||||||
binAPI.updateBin(bin.key(), b.settings, as).then(resp => {
|
binAPI.updateBin(bin.key(), b.settings, as).then(resp => {
|
||||||
refresh();
|
refresh();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -652,9 +652,47 @@ export default function BinyardDisplay(props: Props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const grainUnitDisplay = (custom?: pond.CustomInventory) => {
|
||||||
|
// If custom and not convertible, always bushels
|
||||||
|
if (custom && custom.bushelsPerTonne <= 1) {
|
||||||
|
return " bu";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (getGrainUnit()) {
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TONNE:
|
||||||
|
return " mT";
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TON:
|
||||||
|
return " t";
|
||||||
|
default:
|
||||||
|
return " bu";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const customQuantityDisplay = (customInventory: pond.CustomInventory, bushels: number) => {
|
||||||
|
let amount = bushels
|
||||||
|
if(customInventory.bushelsPerTonne > 1){
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
amount = bushels/customInventory.bushelsPerTonne
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
amount = bushels/(customInventory.bushelsPerTonne*0.907)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Math.round(amount*100)/100
|
||||||
|
}
|
||||||
|
|
||||||
|
const supportedGrainDisplay = (grain: pond.Grain, bushels: number) => {
|
||||||
|
const describer = GrainDescriber(grain)
|
||||||
|
let amount = bushels
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
amount = bushels/describer.bushelsPerTonne
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
amount = bushels/describer.bushelsPerTon
|
||||||
|
}
|
||||||
|
return Math.round(amount*100)/100
|
||||||
|
}
|
||||||
|
|
||||||
const binUtilizationList = () => {
|
const binUtilizationList = () => {
|
||||||
const hasInventory = binMetrics && binMetrics.grainInventory.length > 0;
|
const hasInventory = binMetrics && binMetrics.grainInventory.length > 0;
|
||||||
const useWeight = getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT;
|
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
className={classes.accordion}
|
className={classes.accordion}
|
||||||
|
|
@ -695,17 +733,9 @@ export default function BinyardDisplay(props: Props) {
|
||||||
<GridListTile key={key}>
|
<GridListTile key={key}>
|
||||||
<BinUtilizationChart
|
<BinUtilizationChart
|
||||||
grain={inv.grainType}
|
grain={inv.grainType}
|
||||||
customUnit={useWeight ? " mT" : " bu"}
|
customUnit={grainUnitDisplay()}
|
||||||
bushelAmount={
|
bushelAmount={supportedGrainDisplay(inv.grainType, inv.bushelAmount)}
|
||||||
useWeight
|
bushelCapacity={supportedGrainDisplay(inv.grainType, inv.bushelCapacity)}
|
||||||
? inv.bushelAmount / GrainDescriber(inv.grainType).bushelsPerTonne
|
|
||||||
: inv.bushelAmount
|
|
||||||
}
|
|
||||||
bushelCapacity={
|
|
||||||
useWeight
|
|
||||||
? inv.bushelCapacity / GrainDescriber(inv.grainType).bushelsPerTonne
|
|
||||||
: inv.bushelCapacity
|
|
||||||
}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setContentFilter(pond.Grain[inv.grainType]);
|
setContentFilter(pond.Grain[inv.grainType]);
|
||||||
loadMoreBins(pond.Grain[inv.grainType]);
|
loadMoreBins(pond.Grain[inv.grainType]);
|
||||||
|
|
@ -724,11 +754,10 @@ export default function BinyardDisplay(props: Props) {
|
||||||
amount = amount * 35.239;
|
amount = amount * 35.239;
|
||||||
cap = cap * 35.239;
|
cap = cap * 35.239;
|
||||||
unit = " L";
|
unit = " L";
|
||||||
}
|
}else{
|
||||||
if (useWeight && inv.bushelsPerTonne > 1) {
|
amount = customQuantityDisplay(inv, amount)
|
||||||
amount = amount / inv.bushelsPerTonne;
|
cap = customQuantityDisplay(inv, cap)
|
||||||
cap = cap / inv.bushelsPerTonne;
|
unit = grainUnitDisplay(inv)
|
||||||
unit = " mT";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -69,9 +69,12 @@ export default function BinLevelOverTime(props: Props) {
|
||||||
if (fertilizerBin && cap) {
|
if (fertilizerBin && cap) {
|
||||||
cap = cap * 35.239;
|
cap = cap * 35.239;
|
||||||
}
|
}
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && cap) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && cap) {
|
||||||
cap = cap / bin.bushelsPerTonne();
|
cap = cap / bin.bushelsPerTonne();
|
||||||
}
|
}
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && cap) {
|
||||||
|
cap = cap / (bin.bushelsPerTonne()*0.907);
|
||||||
|
}
|
||||||
setCapacity(cap);
|
setCapacity(cap);
|
||||||
binAPI
|
binAPI
|
||||||
.listHistoryBetween(bin.key(), 500, startDate.toISOString(), endDate.toISOString())
|
.listHistoryBetween(bin.key(), 500, startDate.toISOString(), endDate.toISOString())
|
||||||
|
|
@ -85,13 +88,18 @@ export default function BinLevelOverTime(props: Props) {
|
||||||
if (hist.settings?.inventory) {
|
if (hist.settings?.inventory) {
|
||||||
let bushels = hist.settings.inventory.grainBushels ?? 0;
|
let bushels = hist.settings.inventory.grainBushels ?? 0;
|
||||||
if (bushels !== lastBushels) {
|
if (bushels !== lastBushels) {
|
||||||
|
let grainDisplay = bushels
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((bushels / bin.bushelsPerTonne()) * 100) / 100;
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((bushels / (bin.bushelsPerTonne()*0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
let newData: InventoryAt = {
|
let newData: InventoryAt = {
|
||||||
timestamp: moment(hist.timestamp).valueOf(),
|
timestamp: moment(hist.timestamp).valueOf(),
|
||||||
value: fertilizerBin
|
value: fertilizerBin
|
||||||
? Math.round(bushels * 35.239)
|
? Math.round(bushels * 35.239)
|
||||||
: getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT
|
: grainDisplay
|
||||||
? Math.round((bushels / bin.bushelsPerTonne()) * 100) / 100
|
|
||||||
: bushels
|
|
||||||
};
|
};
|
||||||
data.push(newData);
|
data.push(newData);
|
||||||
lastBushels = bushels;
|
lastBushels = bushels;
|
||||||
|
|
@ -112,12 +120,17 @@ export default function BinLevelOverTime(props: Props) {
|
||||||
let currentTime = moment().valueOf();
|
let currentTime = moment().valueOf();
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
let bushels = bin.bushels();
|
let bushels = bin.bushels();
|
||||||
|
let grainDisplay = bushels
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((bushels / bin.bushelsPerTonne()) * 100) / 100;
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((bushels / (bin.bushelsPerTonne()*0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
data.push({
|
data.push({
|
||||||
value: fertilizerBin
|
value: fertilizerBin
|
||||||
? Math.round(bushels * 35.239)
|
? Math.round(bushels * 35.239)
|
||||||
: getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT
|
: grainDisplay,
|
||||||
? Math.round((bushels / bin.bushelsPerTonne()) * 100) / 100
|
|
||||||
: bushels,
|
|
||||||
timestamp: currentTime
|
timestamp: currentTime
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -143,9 +156,12 @@ export default function BinLevelOverTime(props: Props) {
|
||||||
if (fertilizerBin && cap) {
|
if (fertilizerBin && cap) {
|
||||||
cap = cap * 35.239;
|
cap = cap * 35.239;
|
||||||
}
|
}
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && cap) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && cap) {
|
||||||
cap = cap / bin.bushelsPerTonne();
|
cap = cap / bin.bushelsPerTonne();
|
||||||
}
|
}
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && cap) {
|
||||||
|
cap = cap / (bin.bushelsPerTonne()*0.907);
|
||||||
|
}
|
||||||
setCapacity(cap);
|
setCapacity(cap);
|
||||||
let autoBarData: BarData[] = [];
|
let autoBarData: BarData[] = [];
|
||||||
|
|
||||||
|
|
@ -163,8 +179,15 @@ export default function BinLevelOverTime(props: Props) {
|
||||||
m.values.forEach((val, i) => {
|
m.values.forEach((val, i) => {
|
||||||
if (val.values[0] && m.timestamps[i]) {
|
if (val.values[0] && m.timestamps[i]) {
|
||||||
if (lastBushels !== val.values[0]) {
|
if (lastBushels !== val.values[0]) {
|
||||||
|
let grainDisplay = val.values[0]
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((grainDisplay / bin.bushelsPerTonne()) * 100) / 100;
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((grainDisplay / (bin.bushelsPerTonne()*0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
autoBarData.push({
|
autoBarData.push({
|
||||||
value: val.values[0],
|
value: grainDisplay,
|
||||||
timestamp: moment(m.timestamps[i]).valueOf(),
|
timestamp: moment(m.timestamps[i]).valueOf(),
|
||||||
});
|
});
|
||||||
lastBushels = val.values[0];
|
lastBushels = val.values[0];
|
||||||
|
|
@ -175,12 +198,17 @@ export default function BinLevelOverTime(props: Props) {
|
||||||
if (autoBarData.length === 0) {
|
if (autoBarData.length === 0) {
|
||||||
let bushels = bin.bushels();
|
let bushels = bin.bushels();
|
||||||
let currentTime = moment().valueOf();
|
let currentTime = moment().valueOf();
|
||||||
|
let grainDisplay = bushels
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((bushels / bin.bushelsPerTonne()) * 100) / 100;
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && bin.bushelsPerTonne() > 1){
|
||||||
|
grainDisplay = Math.round((bushels / (bin.bushelsPerTonne()*0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
autoBarData.push({
|
autoBarData.push({
|
||||||
value: fertilizerBin
|
value: fertilizerBin
|
||||||
? Math.round(bushels * 35.239)
|
? Math.round(bushels * 35.239)
|
||||||
: getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT
|
: grainDisplay,
|
||||||
? Math.round((bushels / bin.bushelsPerTonne()) * 100) / 100
|
|
||||||
: bushels,
|
|
||||||
timestamp: currentTime
|
timestamp: currentTime
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ChevronRight } from "@mui/icons-material";
|
import { ChevronRight } from "@mui/icons-material";
|
||||||
import { Avatar, Box, Divider, Drawer, IconButton, Theme, Tooltip, Typography } from "@mui/material";
|
import { Avatar, Box, Drawer, IconButton, Theme, Tooltip, Typography } from "@mui/material";
|
||||||
import { makeStyles } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
import { useMobile } from "hooks";
|
import { useMobile } from "hooks";
|
||||||
import { Team } from "models";
|
import { Team } from "models";
|
||||||
|
|
@ -7,7 +7,7 @@ import Chat from "./Chat";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useTeamAPI } from "providers";
|
import { useTeamAPI } from "providers";
|
||||||
import { openCrispChat } from './CrispChat';
|
import { closeCrispChat, openCrispChat } from './CrispChat';
|
||||||
import RobotIcon from "products/CommonIcons/robotIcon";
|
import RobotIcon from "products/CommonIcons/robotIcon";
|
||||||
|
|
||||||
const useStyles = makeStyles<Theme>((theme: Theme) => ({
|
const useStyles = makeStyles<Theme>((theme: Theme) => ({
|
||||||
|
|
@ -67,6 +67,12 @@ export function ChatDrawer(props: Props) {
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
closeCrispChat()
|
||||||
|
}
|
||||||
|
}, [open])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer
|
<Drawer
|
||||||
open={open}
|
open={open}
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,14 @@ export default function ContractSettings(props: Props) {
|
||||||
setContractValue(contract.settings.totalValue.toString());
|
setContractValue(contract.settings.totalValue.toString());
|
||||||
setCommodity(contract.settings.commodity);
|
setCommodity(contract.settings.commodity);
|
||||||
setContractDate(contract.settings.contractDate);
|
setContractDate(contract.settings.contractDate);
|
||||||
setConversionValue(
|
let conv = 1
|
||||||
contract.settings.conversionValue > 0 ? contract.settings.conversionValue.toString() : "1"
|
if(contract.settings.conversionValue > 1){
|
||||||
);
|
conv = contract.settings.conversionValue
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
conv = conv * 0.907
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setConversionValue(conv.toFixed(2));
|
||||||
setUseCustom(contract.isCustom());
|
setUseCustom(contract.isCustom());
|
||||||
}
|
}
|
||||||
}, [contract]);
|
}, [contract]);
|
||||||
|
|
@ -102,12 +107,21 @@ export default function ContractSettings(props: Props) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
switch (contractType) {
|
switch (contractType) {
|
||||||
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
||||||
|
let conversionLabel = "Bushels Per Tonne"
|
||||||
|
let adornment = "bu"
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
adornment = "mT"
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
conversionLabel = "Bushels Per Ton"
|
||||||
|
adornment = "t"
|
||||||
|
}
|
||||||
setLabels({
|
setLabels({
|
||||||
sizeLabel: "Total Grain on Contract",
|
sizeLabel: "Total Grain on Contract",
|
||||||
commodityLabel: "Select Grain Type",
|
commodityLabel: "Select Grain Type",
|
||||||
conversionLabel: "Bushels Per Tonne",
|
conversionLabel: conversionLabel,
|
||||||
deliveryLabel: "Grain Delivered",
|
deliveryLabel: "Grain Delivered",
|
||||||
adornment: getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? "mT" : "bu"
|
adornment: adornment
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -148,13 +162,22 @@ export default function ContractSettings(props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
const conVal = isNaN(parseFloat(conversionValue)) ? 1 : parseFloat(conversionValue);
|
let conVal = isNaN(parseFloat(conversionValue)) ? 1 : parseFloat(conversionValue);
|
||||||
|
//the toStoredUnit will convert what they entered for amount and size using the conversion that they entered
|
||||||
|
//we will assume that both of those entries are using the same unit ie both US ton or both metric tonne
|
||||||
const deliveredVal = isNaN(parseFloat(deliveredAmount))
|
const deliveredVal = isNaN(parseFloat(deliveredAmount))
|
||||||
? 0
|
? 0
|
||||||
: Math.round(Contract.toStoredUnit(parseFloat(deliveredAmount), contractType, conVal));
|
: Math.round(Contract.toStoredUnit(parseFloat(deliveredAmount), contractType, conVal));
|
||||||
const sizeVal = isNaN(parseFloat(contractSize))
|
const sizeVal = isNaN(parseFloat(contractSize))
|
||||||
? 0
|
? 0
|
||||||
: Math.round(Contract.toStoredUnit(parseFloat(contractSize), contractType, conVal));
|
: Math.round(Contract.toStoredUnit(parseFloat(contractSize), contractType, conVal));
|
||||||
|
|
||||||
|
//then after the conversion to bushels change the conversion value to metric to be stored in the contract
|
||||||
|
if(contractType === pond.ContractType.CONTRACT_TYPE_GRAIN){
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
conVal = conVal / 0.907 //convert the ton they entered to mT to be stored in the contracts conversion value
|
||||||
|
}
|
||||||
|
}
|
||||||
if (contract) {
|
if (contract) {
|
||||||
let settings: pond.ContractSettings = contract.settings;
|
let settings: pond.ContractSettings = contract.settings;
|
||||||
settings.commodity = commodity;
|
settings.commodity = commodity;
|
||||||
|
|
@ -201,7 +224,6 @@ export default function ContractSettings(props: Props) {
|
||||||
settings.type = contractType;
|
settings.type = contractType;
|
||||||
settings.conversionValue = conVal;
|
settings.conversionValue = conVal;
|
||||||
settings.contractDate = contractDate;
|
settings.contractDate = contractDate;
|
||||||
|
|
||||||
contractAPI
|
contractAPI
|
||||||
.addContract(name, settings, as)
|
.addContract(name, settings, as)
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
|
|
@ -490,7 +512,9 @@ export default function ContractSettings(props: Props) {
|
||||||
InputLabelProps={{ shrink: true }}
|
InputLabelProps={{ shrink: true }}
|
||||||
error={isNaN(parseFloat(conversionValue))}
|
error={isNaN(parseFloat(conversionValue))}
|
||||||
helperText={isNaN(parseFloat(conversionValue)) ? "Must be a valid number" : ""}
|
helperText={isNaN(parseFloat(conversionValue)) ? "Must be a valid number" : ""}
|
||||||
onChange={e => setConversionValue(e.target.value)}
|
onChange={e => {
|
||||||
|
setConversionValue(e.target.value)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,17 @@ export default function ContractTransactionGraph(props: Props) {
|
||||||
if (transaction?.grainTransaction) {
|
if (transaction?.grainTransaction) {
|
||||||
value = transaction.grainTransaction.bushels;
|
value = transaction.grainTransaction.bushels;
|
||||||
if (
|
if (
|
||||||
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT &&
|
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE &&
|
||||||
transaction.grainTransaction.bushelsPerTonne > 1
|
transaction.grainTransaction.bushelsPerTonne > 1
|
||||||
) {
|
) {
|
||||||
value = value / transaction.grainTransaction.bushelsPerTonne;
|
value = value / transaction.grainTransaction.bushelsPerTonne;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON &&
|
||||||
|
transaction.grainTransaction.bushelsPerTonne > 1
|
||||||
|
) {
|
||||||
|
value = value / (transaction.grainTransaction.bushelsPerTonne * 0.907);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
d.push({
|
d.push({
|
||||||
timestamp: time.valueOf(),
|
timestamp: time.valueOf(),
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import React, { useCallback, useEffect, useState } from "react";
|
||||||
//import { Redirect } from "react-router";
|
//import { Redirect } from "react-router";
|
||||||
import { or } from "utils/types";
|
import { or } from "utils/types";
|
||||||
import DeviceActions from "./DeviceActions";
|
import DeviceActions from "./DeviceActions";
|
||||||
|
import { getContextKeys, getContextTypes } from "pbHelpers/Context";
|
||||||
|
|
||||||
const useStyles = makeStyles((theme: Theme) => ({
|
const useStyles = makeStyles((theme: Theme) => ({
|
||||||
title: {
|
title: {
|
||||||
|
|
@ -97,45 +98,28 @@ export default function Device(props: Props) {
|
||||||
const load = useCallback(() => {
|
const load = useCallback(() => {
|
||||||
if (user.id() === "") return;
|
if (user.id() === "") return;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
//let devicePromise = deviceAPI.get(deviceID);
|
deviceAPI.getPageData(deviceID, getContextKeys(), getContextTypes(), as).then(resp => {
|
||||||
let userPromise = userAPI.getUser(user.id(), deviceScope(deviceID.toString()));
|
console.log(resp)
|
||||||
let componentsPromise = componentAPI.list(
|
let rawComponents: Array<any> = or(resp.data.components, []);
|
||||||
deviceID,
|
let rComponents: Map<string, Component> = new Map();
|
||||||
undefined,
|
rawComponents.forEach((rawComponent: any) => {
|
||||||
[deviceID.toString()],
|
let component = Component.any(rawComponent);
|
||||||
["device"],
|
rComponents.set(component.key(), component);
|
||||||
true,
|
});
|
||||||
as
|
setComponents(rComponents);
|
||||||
);
|
|
||||||
let interactionsPromise = interactionsAPI.listInteractionsByDevice(deviceID, undefined, as);
|
|
||||||
let groupPromise: Promise<any> = Promise.resolve(undefined);
|
|
||||||
Promise.all([userPromise, componentsPromise, interactionsPromise, groupPromise])
|
|
||||||
.then(([userRes, componentsRes, interactionsRes]) => {
|
|
||||||
//let rDevice = DeviceModel.any(deviceRes.data);
|
|
||||||
let rawComponents: Array<any> = or(componentsRes.data.components, []);
|
|
||||||
let rComponents: Map<string, Component> = new Map();
|
|
||||||
rawComponents.forEach((rawComponent: any) => {
|
|
||||||
let component = Component.any(rawComponent);
|
|
||||||
rComponents.set(component.key(), component);
|
|
||||||
});
|
|
||||||
|
|
||||||
setComponents(rComponents);
|
setInteractions(resp.data.interactions.map(i => Interaction.create(i)))
|
||||||
|
setPermissions(resp.data.permissions)
|
||||||
setInteractions(interactionsRes);
|
setDevice(props.device);
|
||||||
setPermissions(userRes.permissions);
|
setLongitude(props.device.status.longitude ? props.device.status.longitude : NaN);
|
||||||
setPreferences(userRes.preferences);
|
setLatitude(props.device.status.latitude ? props.device.status.latitude : NaN);
|
||||||
|
let available = FindAvailablePositions(
|
||||||
setDevice(props.device);
|
Array.from(rComponents.values()),
|
||||||
setLongitude(props.device.status.longitude ? props.device.status.longitude : NaN);
|
props.device.settings.product
|
||||||
setLatitude(props.device.status.latitude ? props.device.status.latitude : NaN);
|
);
|
||||||
let available = FindAvailablePositions(
|
setAvailablePositions(available.GetAvailability());
|
||||||
Array.from(rComponents.values()),
|
setAvailableOffsets(available.offsetAvailability);
|
||||||
props.device.settings.product
|
}).catch(err => {
|
||||||
);
|
|
||||||
setAvailablePositions(available.GetAvailability());
|
|
||||||
setAvailableOffsets(available.offsetAvailability);
|
|
||||||
})
|
|
||||||
.catch((err: any) => {
|
|
||||||
setDevice(DeviceModel.create());
|
setDevice(DeviceModel.create());
|
||||||
setComponents(new Map());
|
setComponents(new Map());
|
||||||
setInteractions([]);
|
setInteractions([]);
|
||||||
|
|
@ -145,8 +129,9 @@ export default function Device(props: Props) {
|
||||||
setPreferences(pond.UserPreferences.create());
|
setPreferences(pond.UserPreferences.create());
|
||||||
setInvalidDevice(true);
|
setInvalidDevice(true);
|
||||||
error(err);
|
error(err);
|
||||||
})
|
}).finally(() => {
|
||||||
.finally(() => setIsLoading(false));
|
setIsLoading(false)
|
||||||
|
})
|
||||||
usageAPI
|
usageAPI
|
||||||
.getUsage(deviceID, moment().subtract(1, "days"))
|
.getUsage(deviceID, moment().subtract(1, "days"))
|
||||||
.then((res: any) => {
|
.then((res: any) => {
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,7 @@ export default function FieldSettings(props: Props) {
|
||||||
settings.grainSubtype = grainSubtype;
|
settings.grainSubtype = grainSubtype;
|
||||||
settings.landLocation = landLocation;
|
settings.landLocation = landLocation;
|
||||||
settings.acres = acres;
|
settings.acres = acres;
|
||||||
|
settings.bushelsPerTonne = isNaN(parseFloat(bushelsPerTonne)) ? 1 : parseFloat(bushelsPerTonne);
|
||||||
|
|
||||||
fieldAPI
|
fieldAPI
|
||||||
.updateField(selectedField.key(), settings, undefined, as)
|
.updateField(selectedField.key(), settings, undefined, as)
|
||||||
|
|
@ -121,6 +122,7 @@ export default function FieldSettings(props: Props) {
|
||||||
geo.shapes = borders;
|
geo.shapes = borders;
|
||||||
}
|
}
|
||||||
settings.fieldGeoData = geo;
|
settings.fieldGeoData = geo;
|
||||||
|
settings.bushelsPerTonne = isNaN(parseFloat(bushelsPerTonne)) ? 1 : parseFloat(bushelsPerTonne);
|
||||||
fieldAPI
|
fieldAPI
|
||||||
.addField(settings, as)
|
.addField(settings, as)
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
|
|
@ -226,6 +228,7 @@ export default function FieldSettings(props: Props) {
|
||||||
if (option) {
|
if (option) {
|
||||||
let grainType = pond.Grain[option.value as keyof typeof pond.Grain];
|
let grainType = pond.Grain[option.value as keyof typeof pond.Grain];
|
||||||
setCropType(grainType);
|
setCropType(grainType);
|
||||||
|
console.log("set bpt here")
|
||||||
setBushelsPerTonne(GrainDescriber(grainType).bushelsPerTonne.toString());
|
setBushelsPerTonne(GrainDescriber(grainType).bushelsPerTonne.toString());
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Box, Card, CardHeader, Grid2, Typography } from "@mui/material"
|
import { Card, CardHeader, Grid2, Typography } from "@mui/material"
|
||||||
import { blue, orange } from "@mui/material/colors"
|
import { blue, orange } from "@mui/material/colors"
|
||||||
import SingleSetAreaChart, { SSAreaDataPoint } from "charts/SingleSetAreaChart"
|
import SingleSetAreaChart, { SSAreaDataPoint } from "charts/SingleSetAreaChart"
|
||||||
import { useComponentAPI } from "hooks"
|
import { useComponentAPI } from "hooks"
|
||||||
|
|
@ -38,11 +38,68 @@ export default function GateDeltaTempGraph(props: Props){
|
||||||
const warmingColour = orange["500"]
|
const warmingColour = orange["500"]
|
||||||
const coolingColour = blue["500"]
|
const coolingColour = blue["500"]
|
||||||
|
|
||||||
|
const getUnitByType = (unitMeasurements: UnitMeasurement[], type: quack.MeasurementType) => {
|
||||||
|
return unitMeasurements.find(u => u.type === type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const buildDeltas = (ambientMeasurements: UnitMeasurement[], tempCompMeasurements: UnitMeasurement[], measurementType: quack.MeasurementType) => {
|
||||||
|
const ambient = getUnitByType(ambientMeasurements, measurementType);
|
||||||
|
const outlet = getUnitByType(tempCompMeasurements, measurementType);
|
||||||
|
|
||||||
|
if (!ambient || !outlet) return [];
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
let j = 0;
|
||||||
|
|
||||||
|
let lastAmbient: number | null = null;
|
||||||
|
let lastOutlet: number | null = null;
|
||||||
|
|
||||||
|
const deltas: SSAreaDataPoint[] = [];
|
||||||
|
|
||||||
|
const ambientTimes = ambient.timestamps.map(t => moment(t).valueOf()).reverse();
|
||||||
|
const outletTimes = outlet.timestamps.map(t => moment(t).valueOf()).reverse();
|
||||||
|
const ambientValues = [...ambient.values].reverse();
|
||||||
|
const outletValues = [...outlet.values].reverse();
|
||||||
|
|
||||||
|
while (i < ambientTimes.length || j < outletTimes.length) {
|
||||||
|
|
||||||
|
const aTime = i < ambientTimes.length ? ambientTimes[i] : Infinity;
|
||||||
|
const bTime = j < outletTimes.length ? outletTimes[j] : Infinity;
|
||||||
|
|
||||||
|
if (aTime <= bTime) {
|
||||||
|
const valueArray = ambientValues[i++];
|
||||||
|
if (!valueArray.error && valueArray.values.length > 0) {
|
||||||
|
lastAmbient = valueArray.values[valueArray.values.length -1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastAmbient !== null && lastOutlet !== null) {
|
||||||
|
deltas.push({
|
||||||
|
timestamp: aTime,
|
||||||
|
value: Math.round((lastOutlet - lastAmbient)*100)/100
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const valueArray = outletValues[j++];
|
||||||
|
if (!valueArray.error && valueArray.values.length > 0) {
|
||||||
|
lastOutlet = valueArray.values[valueArray.values.length -1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastAmbient !== null && lastOutlet !== null) {
|
||||||
|
deltas.push({
|
||||||
|
timestamp: bTime,
|
||||||
|
value: Math.round((lastOutlet - lastAmbient)*100)/100
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deltas
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the use effect will use the temp component passed in get the measurements, then use the first node and the last node to determine the difference,
|
* the use effect will use the temp component passed in get the measurements, then use the first node and the last node to determine the difference,
|
||||||
* if there is only one node, or only one node is reading due to errors, then it will use that as both the inlet and outlet so the delta will be 0,
|
* if there is only one node, or only one node is reading due to errors, then it will use that as both the inlet and outlet so the delta will be 0,
|
||||||
*
|
*
|
||||||
* //NOT IMPLEMENTED YET//
|
|
||||||
* if an ambient is passed in it will use the readings from the ambient as the inlet and the temp component as the outlet
|
* if an ambient is passed in it will use the readings from the ambient as the inlet and the temp component as the outlet
|
||||||
*/
|
*/
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
|
@ -52,7 +109,7 @@ export default function GateDeltaTempGraph(props: Props){
|
||||||
tempComponent.key(),
|
tempComponent.key(),
|
||||||
start.toISOString(),
|
start.toISOString(),
|
||||||
end.toISOString(),
|
end.toISOString(),
|
||||||
500,
|
500,
|
||||||
0,
|
0,
|
||||||
"timestamp",
|
"timestamp",
|
||||||
).then(resp => {
|
).then(resp => {
|
||||||
|
|
@ -60,7 +117,24 @@ export default function GateDeltaTempGraph(props: Props){
|
||||||
let tempCompMeasurements = resp.data.measurements.map(um => UnitMeasurement.any(um, user));
|
let tempCompMeasurements = resp.data.measurements.map(um => UnitMeasurement.any(um, user));
|
||||||
//if there is an ambient component, then treat the temp component like a single sensor and not a chain, and use the ambient measurements as the inlet
|
//if there is an ambient component, then treat the temp component like a single sensor and not a chain, and use the ambient measurements as the inlet
|
||||||
if(ambient){
|
if(ambient){
|
||||||
//TODO: this is just an idea of how to handle a possible path for the overhaul of gates, if that is the route we take then this needs to be coded
|
//need to then load the measurements for the ambient component
|
||||||
|
componentAPI.listUnitMeasurements(
|
||||||
|
deviceID,
|
||||||
|
ambient.key(),
|
||||||
|
start.toISOString(),
|
||||||
|
end.toISOString(),
|
||||||
|
500,
|
||||||
|
0,
|
||||||
|
"timestamp",
|
||||||
|
).then(resp => {
|
||||||
|
let ambientMeasurements = resp.data.measurements.map(um => UnitMeasurement.any(um, user));
|
||||||
|
//now loop through each of them to 'combine' them into a single array
|
||||||
|
const deltas = buildDeltas(ambientMeasurements, tempCompMeasurements, quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE)
|
||||||
|
if(deltas.length > 0){
|
||||||
|
setData(deltas)
|
||||||
|
setRecent(deltas[deltas.length-1])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
}else{//else no ambient is passed in treat the temp component like a chain
|
}else{//else no ambient is passed in treat the temp component like a chain
|
||||||
let deltas: SSAreaDataPoint[] = []
|
let deltas: SSAreaDataPoint[] = []
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import GateGraphs from "./GateGraphs";
|
||||||
//import { ToggleButton, ToggleButtonGroup } from "@material-ui/lab";
|
//import { ToggleButton, ToggleButtonGroup } from "@material-ui/lab";
|
||||||
import { getThemeType } from "theme";
|
import { getThemeType } from "theme";
|
||||||
import ButtonGroup from "common/ButtonGroup";
|
import ButtonGroup from "common/ButtonGroup";
|
||||||
|
import { cloneDeep } from "lodash";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
gate: Gate;
|
gate: Gate;
|
||||||
|
|
@ -55,8 +56,11 @@ export default function GateDevice(props: Props) {
|
||||||
// const [pcaFanOn, setPCAFanOn] = useState(false);
|
// const [pcaFanOn, setPCAFanOn] = useState(false);
|
||||||
const [detail, setDetail] = useState<"sensors" | "analytics">("analytics");
|
const [detail, setDetail] = useState<"sensors" | "analytics">("analytics");
|
||||||
const [lastAmbient, setLastAmbient] = useState(0);
|
const [lastAmbient, setLastAmbient] = useState(0);
|
||||||
const [lastTemps, setLastTemps] = useState({ t1: 0, t2: 0 });
|
//const [lastTemps, setLastTemps] = useState({ t1: 0, t2: 0 });
|
||||||
const [lastPressures, setLastPressures] = useState({ p1: 0, p2: 0 });
|
const [ductTemp, setDuctTemp] = useState<number | undefined>()
|
||||||
|
//const [lastPressures, setLastPressures] = useState({ p1: 0, p2: 0 });
|
||||||
|
const [ductPressure, setDuctPressure] = useState<number | undefined>()
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
//addresses of controller LEDs on a V1 device
|
//addresses of controller LEDs on a V1 device
|
||||||
|
|
@ -142,24 +146,20 @@ export default function GateDevice(props: Props) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let tempComponent = componentOptions.get(tempKey);
|
let tempComponent = componentOptions.get(tempKey);
|
||||||
let t1 = 0;
|
if(tempComponent){
|
||||||
let t2 = 0;
|
|
||||||
if (tempComponent) {
|
|
||||||
tempComponent.status.measurement.forEach(um => {
|
tempComponent.status.measurement.forEach(um => {
|
||||||
let measurement = UnitMeasurement.any(um, user);
|
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE){
|
||||||
if (
|
let clone = cloneDeep(um)
|
||||||
measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE &&
|
let measurement = UnitMeasurement.any(clone, user)
|
||||||
measurement.values.length > 0
|
if(measurement.values.length > 0){
|
||||||
) {
|
let readings = measurement.values[measurement.values.length -1]
|
||||||
let nodeVals = measurement.values[0].values;
|
if(readings.values.length > 0){
|
||||||
if (nodeVals.length > 1) {
|
setDuctTemp(readings.values[readings.values.length -1])
|
||||||
t1 = nodeVals[0]; //uses the first node
|
}
|
||||||
t2 = nodeVals[1]; //uses second node node
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setLastTemps({ t1, t2 });
|
|
||||||
}, [componentOptions, tempKey, user]);
|
}, [componentOptions, tempKey, user]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -180,24 +180,20 @@ export default function GateDevice(props: Props) {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let pressureComponent = componentOptions.get(pressureKey);
|
let pressureComponent = componentOptions.get(pressureKey);
|
||||||
let p1 = 0;
|
if(pressureComponent){
|
||||||
let p2 = 0;
|
|
||||||
if (pressureComponent) {
|
|
||||||
pressureComponent.status.measurement.forEach(um => {
|
pressureComponent.status.measurement.forEach(um => {
|
||||||
let measurement = UnitMeasurement.any(um, user);
|
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE){
|
||||||
if (
|
let clone = cloneDeep(um)
|
||||||
measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE &&
|
let measurement = UnitMeasurement.any(clone, user)
|
||||||
measurement.values.length > 0
|
if(measurement.values.length > 0){
|
||||||
) {
|
let readings = measurement.values[measurement.values.length -1]
|
||||||
let nodeVals = measurement.values[0].values;
|
if(readings.values.length > 0){
|
||||||
if (nodeVals.length > 1) {
|
setDuctPressure(readings.values[readings.values.length -1])
|
||||||
p1 = nodeVals[0];
|
}
|
||||||
p2 = nodeVals[1];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
setLastPressures({ p1, p2 });
|
|
||||||
}, [componentOptions, pressureKey, user]);
|
}, [componentOptions, pressureKey, user]);
|
||||||
|
|
||||||
const ambientSelector = () => {
|
const ambientSelector = () => {
|
||||||
|
|
@ -340,8 +336,10 @@ export default function GateDevice(props: Props) {
|
||||||
: 0
|
: 0
|
||||||
}
|
}
|
||||||
ambientTemp={lastAmbient}
|
ambientTemp={lastAmbient}
|
||||||
innerTemps={lastTemps}
|
//innerTemps={lastTemps}
|
||||||
innerPressures={lastPressures}
|
//innerPressures={lastPressures}
|
||||||
|
ductTemp={ductTemp}
|
||||||
|
ductPressure={ductPressure}
|
||||||
ambientSelector={ambientSelector}
|
ambientSelector={ambientSelector}
|
||||||
tempChainSelector={tempSelector}
|
tempChainSelector={tempSelector}
|
||||||
pressureChainSelector={pressureSelector}
|
pressureChainSelector={pressureSelector}
|
||||||
|
|
@ -374,9 +372,6 @@ export default function GateDevice(props: Props) {
|
||||||
gate={gate}
|
gate={gate}
|
||||||
display={detail}
|
display={detail}
|
||||||
compMap={componentOptions}
|
compMap={componentOptions}
|
||||||
// setPCAState={(state: boolean) => {
|
|
||||||
// setPCAState(state);
|
|
||||||
// }}
|
|
||||||
ambient={ambientKey}
|
ambient={ambientKey}
|
||||||
pressure={pressureKey}
|
pressure={pressureKey}
|
||||||
tempChain={tempKey}
|
tempChain={tempKey}
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,7 @@ export default function GateGraphs(props: Props) {
|
||||||
*/
|
*/
|
||||||
const sensorGraphs = () => {
|
const sensorGraphs = () => {
|
||||||
const tempComp = compMap.get(tempChain)
|
const tempComp = compMap.get(tempChain)
|
||||||
|
const ambientComp = compMap.get(ambient)
|
||||||
let graphs: JSX.Element[] = []
|
let graphs: JSX.Element[] = []
|
||||||
|
|
||||||
//pressure
|
//pressure
|
||||||
|
|
@ -314,7 +315,7 @@ export default function GateGraphs(props: Props) {
|
||||||
|
|
||||||
if(tempComp){
|
if(tempComp){
|
||||||
graphs.push(
|
graphs.push(
|
||||||
<GateDeltaTempGraph deviceID={device} start={startDate} end={endDate} tempComponent={tempComp}/>
|
<GateDeltaTempGraph deviceID={device} start={startDate} end={endDate} tempComponent={tempComp} ambient={ambientComp}/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
//T/H chain
|
//T/H chain
|
||||||
|
|
@ -323,7 +324,6 @@ export default function GateGraphs(props: Props) {
|
||||||
graphs.push(graphCard(tempComp, tempReadings))
|
graphs.push(graphCard(tempComp, tempReadings))
|
||||||
}
|
}
|
||||||
//ambient
|
//ambient
|
||||||
let ambientComp = compMap.get(ambient)
|
|
||||||
let ambientReadings = compMeasurements.get(ambient)
|
let ambientReadings = compMeasurements.get(ambient)
|
||||||
if (ambientComp && ambientReadings){
|
if (ambientComp && ambientReadings){
|
||||||
graphs.push(graphCard(ambientComp, ambientReadings))
|
graphs.push(graphCard(ambientComp, ambientReadings))
|
||||||
|
|
@ -345,6 +345,7 @@ export default function GateGraphs(props: Props) {
|
||||||
|
|
||||||
const analyticGraphs = () => {
|
const analyticGraphs = () => {
|
||||||
let tempComp = compMap.get(tempChain)
|
let tempComp = compMap.get(tempChain)
|
||||||
|
let ambientComp = compMap.get(ambient)
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<GateFlowGraph
|
<GateFlowGraph
|
||||||
|
|
@ -365,7 +366,7 @@ export default function GateGraphs(props: Props) {
|
||||||
/>
|
/>
|
||||||
{/* add a new chart here for the delta temp over time */}
|
{/* add a new chart here for the delta temp over time */}
|
||||||
{tempComp &&
|
{tempComp &&
|
||||||
<GateDeltaTempGraph deviceID={device} start={startDate} end={endDate} tempComponent={tempComp}/>
|
<GateDeltaTempGraph deviceID={device} start={startDate} end={endDate} tempComponent={tempComp} ambient={ambientComp}/>
|
||||||
}
|
}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -164,29 +164,49 @@ export default function GateList(props: Props) {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const conditionDisplay = (gate: Gate) => {
|
const conditionDisplay = (gate: Gate) => {
|
||||||
console.log(gate)
|
|
||||||
let display = ""
|
let display = ""
|
||||||
let deltaTemp = 0
|
|
||||||
if(gate.status.pcaState === pond.PCAState.PCA_STATE_OFF){
|
if(gate.status.pcaState === pond.PCAState.PCA_STATE_OFF){
|
||||||
display = "Inactive"
|
display = "Inactive"
|
||||||
} else if (gate.status.pcaState === pond.PCAState.PCA_STATE_UNKNOWN){
|
} else if (gate.status.pcaState === pond.PCAState.PCA_STATE_UNKNOWN){
|
||||||
display = "--"
|
display = "--"
|
||||||
} else { //the pca is currently active calulate the delta temp (T2 - T1) provided there are two temps
|
} else { //the pca is currently active calulate the delta temp (outlet - ambient)
|
||||||
//loop to find the temp readings
|
let ambient = cloneDeep(gate.status.lastAmbientReading)
|
||||||
let clone = cloneDeep(gate.status.lastTempReading)
|
let temp = cloneDeep(gate.status.lastTempReading)
|
||||||
clone.forEach(unitMeasurement => {
|
|
||||||
let um = UnitMeasurement.create(unitMeasurement, user)
|
if(ambient.length > 0 && temp.length > 0){
|
||||||
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE){
|
let ambientTemp: number | undefined
|
||||||
if(um.values.length > 0){ //as long as there is at least on thing in the measurements
|
let outletTemp: number | undefined
|
||||||
let lastReading = um.values[um.values.length-1] //there should only be one measurement in here but just make sure to get the end of the array
|
ambient.forEach(um => {
|
||||||
if(lastReading.values.length > 1){ //make sure there are at least two values in the array
|
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE){
|
||||||
console.log(lastReading.values)
|
let clone = cloneDeep(um)
|
||||||
deltaTemp = lastReading.values[lastReading.values.length -1] - lastReading.values[0] //subtract the first value from the last value to get the delta
|
let measurement = UnitMeasurement.any(clone, user)
|
||||||
|
if(measurement.values.length > 0){
|
||||||
|
let readings = measurement.values[measurement.values.length -1]
|
||||||
|
if(readings.values.length > 0){
|
||||||
|
ambientTemp = readings.values[readings.values.length -1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
temp.forEach(um => {
|
||||||
|
if(um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE){
|
||||||
|
let clone = cloneDeep(um)
|
||||||
|
let measurement = UnitMeasurement.any(clone, user)
|
||||||
|
if(measurement.values.length > 0){
|
||||||
|
let readings = measurement.values[measurement.values.length -1]
|
||||||
|
if(readings.values.length > 0){
|
||||||
|
outletTemp = readings.values[readings.values.length -1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(ambientTemp && outletTemp){
|
||||||
|
let deltaTemp = outletTemp - ambientTemp
|
||||||
|
display = deltaTemp.toFixed(2) + (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT ? "°F" : "°C")
|
||||||
|
}else{
|
||||||
|
display = "Sensor Missing"
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
display = deltaTemp.toFixed(2) + (getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT ? "°F" : "°C")
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Typography>
|
<Typography>
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,10 @@ const useStyles = makeStyles(() => ({
|
||||||
interface Props {
|
interface Props {
|
||||||
finalTemp: number;
|
finalTemp: number;
|
||||||
ambientTemp: number;
|
ambientTemp: number;
|
||||||
innerTemps: { t1: number; t2: number };
|
//innerTemps: { t1: number; t2: number };
|
||||||
innerPressures: { p1: number; p2: number };
|
//innerPressures: { p1: number; p2: number };
|
||||||
|
ductTemp?: number;
|
||||||
|
ductPressure?: number;
|
||||||
ambientSelector: () => JSX.Element;
|
ambientSelector: () => JSX.Element;
|
||||||
tempChainSelector: () => JSX.Element;
|
tempChainSelector: () => JSX.Element;
|
||||||
pressureChainSelector: () => JSX.Element;
|
pressureChainSelector: () => JSX.Element;
|
||||||
|
|
@ -57,8 +59,10 @@ export default function GateSVG(props: Props) {
|
||||||
const {
|
const {
|
||||||
finalTemp,
|
finalTemp,
|
||||||
ambientTemp,
|
ambientTemp,
|
||||||
innerTemps,
|
//innerTemps,
|
||||||
innerPressures,
|
//innerPressures,
|
||||||
|
ductTemp,
|
||||||
|
ductPressure,
|
||||||
ambientSelector,
|
ambientSelector,
|
||||||
tempChainSelector,
|
tempChainSelector,
|
||||||
pressureChainSelector,
|
pressureChainSelector,
|
||||||
|
|
@ -277,12 +281,15 @@ export default function GateSVG(props: Props) {
|
||||||
values.push(
|
values.push(
|
||||||
<g key={"tempChain"} id={"tempChain"} data-name={"tempChain"}>
|
<g key={"tempChain"} id={"tempChain"} data-name={"tempChain"}>
|
||||||
<text fontSize={7} className={classes.fontBase} x={30} y={149}>
|
<text fontSize={7} className={classes.fontBase} x={30} y={149}>
|
||||||
T1: {innerTemps.t1}
|
{/* T1: {innerTemps.t1}
|
||||||
{user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
{user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
||||||
? "°F"
|
? "°F"
|
||||||
: "°C"}
|
: "°C"}
|
||||||
, T2: {innerTemps.t2}
|
, T1: {innerTemps.t2}
|
||||||
{user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
{user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
||||||
|
? "°F"
|
||||||
|
: "°C"} */}
|
||||||
|
Temperature: {ductTemp ?? "N/A"} {user.settings.temperatureUnit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT
|
||||||
? "°F"
|
? "°F"
|
||||||
: "°C"}
|
: "°C"}
|
||||||
</text>
|
</text>
|
||||||
|
|
@ -292,12 +299,15 @@ export default function GateSVG(props: Props) {
|
||||||
values.push(
|
values.push(
|
||||||
<g key={"pressureChain"} id={"pressureChain"} data-name={"pressureChain"}>
|
<g key={"pressureChain"} id={"pressureChain"} data-name={"pressureChain"}>
|
||||||
<text fontSize={7} className={classes.fontBase} x={30} y={184}>
|
<text fontSize={7} className={classes.fontBase} x={30} y={184}>
|
||||||
P1: {innerPressures.p1}{" "}
|
{/* P1: {innerPressures.p1}{" "}
|
||||||
{user.settings.pressureUnit === pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER
|
{user.settings.pressureUnit === pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER
|
||||||
? "iwg"
|
? "iwg"
|
||||||
: "kPa"}
|
: "kPa"}
|
||||||
, P2: {innerPressures.p2}{" "}
|
, P2: {innerPressures.p2}{" "}
|
||||||
{user.settings.pressureUnit === pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER
|
{user.settings.pressureUnit === pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER
|
||||||
|
? "iwg"
|
||||||
|
: "kPa"} */}
|
||||||
|
Pressure: {ductPressure ?? "N/A"} {user.settings.pressureUnit === pond.PressureUnit.PRESSURE_UNIT_INCHES_OF_WATER
|
||||||
? "iwg"
|
? "iwg"
|
||||||
: "kPa"}
|
: "kPa"}
|
||||||
</text>
|
</text>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import {MenuItem, TextField } from "@mui/material"
|
||||||
import { cloneDeep } from "lodash"
|
import { cloneDeep } from "lodash"
|
||||||
import { pond } from "protobuf-ts/pond"
|
import { pond } from "protobuf-ts/pond"
|
||||||
import React, { useEffect, useRef, useState } from "react"
|
import React, { useEffect, useRef, useState } from "react"
|
||||||
|
import { getGrainUnit } from "utils"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
grainSettings?: pond.GrainSettings
|
grainSettings?: pond.GrainSettings
|
||||||
|
|
@ -18,7 +19,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
const [constantB, setConstantB] = useState("0")
|
const [constantB, setConstantB] = useState("0")
|
||||||
const [constantC, setConstantC] = useState("0")
|
const [constantC, setConstantC] = useState("0")
|
||||||
const [kgPerBushel, setKgPerBushel] = useState("0")
|
const [kgPerBushel, setKgPerBushel] = useState("0")
|
||||||
const [bushelsPerTonne, setBushelsPerTonne] = useState("0")
|
const [bushelsConversion, setBushelConversion] = useState("0")//this is either per tonne or per US ton depending on user preferences
|
||||||
const valid = useRef(false)
|
const valid = useRef(false)
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
|
@ -30,12 +31,19 @@ export default function CustomGrainForm(props: Props) {
|
||||||
setConstantB(grainSettings.b.toString())
|
setConstantB(grainSettings.b.toString())
|
||||||
setConstantC(grainSettings.c.toString())
|
setConstantC(grainSettings.c.toString())
|
||||||
setKgPerBushel(grainSettings.kgPerBushel.toString())
|
setKgPerBushel(grainSettings.kgPerBushel.toString())
|
||||||
setBushelsPerTonne(grainSettings.bushelsPerTonne.toString())
|
setBushelConversion(grainSettings.bushelsPerTonne.toString())
|
||||||
setNewGrainSettings(grainSettings)
|
setNewGrainSettings(grainSettings)
|
||||||
}
|
}
|
||||||
},[grainSettings])
|
},[grainSettings])
|
||||||
|
|
||||||
const validate = (name: string, group: string, constA: string, constB: string, constC: string, kgPerBushel: string, bushelsPerTonne: string) => {
|
const validate = (
|
||||||
|
name: string,
|
||||||
|
group: string,
|
||||||
|
constA: string,
|
||||||
|
constB: string,
|
||||||
|
constC: string,
|
||||||
|
kgPerBushel: string,
|
||||||
|
bushelsPerTonne: string) => {
|
||||||
if (name === "") return false
|
if (name === "") return false
|
||||||
if (group === "") return false
|
if (group === "") return false
|
||||||
if (isNaN(parseFloat(constA))) return false
|
if (isNaN(parseFloat(constA))) return false
|
||||||
|
|
@ -64,7 +72,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
setName(name)
|
setName(name)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
settings.name = name
|
settings.name = name
|
||||||
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsPerTonne)
|
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsConversion)
|
||||||
settingsChanged(settings)
|
settingsChanged(settings)
|
||||||
}}/>
|
}}/>
|
||||||
<TextField
|
<TextField
|
||||||
|
|
@ -77,7 +85,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
setGroup(group)
|
setGroup(group)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
settings.group = group
|
settings.group = group
|
||||||
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsPerTonne)
|
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsConversion)
|
||||||
settingsChanged(settings)
|
settingsChanged(settings)
|
||||||
}}/>
|
}}/>
|
||||||
<TextField
|
<TextField
|
||||||
|
|
@ -91,7 +99,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
setEquation(enumVal)
|
setEquation(enumVal)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
settings.equation = enumVal
|
settings.equation = enumVal
|
||||||
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsPerTonne)
|
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, bushelsConversion)
|
||||||
settingsChanged(settings)
|
settingsChanged(settings)
|
||||||
}}
|
}}
|
||||||
select>
|
select>
|
||||||
|
|
@ -121,7 +129,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
let val = e.target.value
|
let val = e.target.value
|
||||||
setConstantA(val)
|
setConstantA(val)
|
||||||
valid.current = validate(name, group, val, constantB, constantC, kgPerBushel, bushelsPerTonne)
|
valid.current = validate(name, group, val, constantB, constantC, kgPerBushel, bushelsConversion)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
if(!isNaN(parseFloat(val))){
|
if(!isNaN(parseFloat(val))){
|
||||||
settings.a = parseFloat(val)
|
settings.a = parseFloat(val)
|
||||||
|
|
@ -139,7 +147,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
let val = e.target.value
|
let val = e.target.value
|
||||||
setConstantB(val)
|
setConstantB(val)
|
||||||
valid.current = validate(name, group, constantA, val, constantC, kgPerBushel, bushelsPerTonne)
|
valid.current = validate(name, group, constantA, val, constantC, kgPerBushel, bushelsConversion)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
if(!isNaN(parseFloat(val))){
|
if(!isNaN(parseFloat(val))){
|
||||||
settings.b = parseFloat(val)
|
settings.b = parseFloat(val)
|
||||||
|
|
@ -157,7 +165,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
let val = e.target.value
|
let val = e.target.value
|
||||||
setConstantC(val)
|
setConstantC(val)
|
||||||
valid.current = validate(name, group, constantA, constantB, val, kgPerBushel, bushelsPerTonne)
|
valid.current = validate(name, group, constantA, constantB, val, kgPerBushel, bushelsConversion)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
if(!isNaN(parseFloat(val))){
|
if(!isNaN(parseFloat(val))){
|
||||||
settings.c = parseFloat(val)
|
settings.c = parseFloat(val)
|
||||||
|
|
@ -175,7 +183,7 @@ export default function CustomGrainForm(props: Props) {
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
let val = e.target.value
|
let val = e.target.value
|
||||||
setKgPerBushel(val)
|
setKgPerBushel(val)
|
||||||
valid.current = validate(name, group, constantA, constantB, constantC, val, bushelsPerTonne)
|
valid.current = validate(name, group, constantA, constantB, constantC, val, bushelsConversion)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
if(!isNaN(parseFloat(val))){
|
if(!isNaN(parseFloat(val))){
|
||||||
settings.kgPerBushel = parseFloat(val)
|
settings.kgPerBushel = parseFloat(val)
|
||||||
|
|
@ -187,20 +195,24 @@ export default function CustomGrainForm(props: Props) {
|
||||||
sx={{marginBottom: 2}}
|
sx={{marginBottom: 2}}
|
||||||
fullWidth
|
fullWidth
|
||||||
type="number"
|
type="number"
|
||||||
value={bushelsPerTonne}
|
value={bushelsConversion}
|
||||||
error={isNaN(parseFloat(bushelsPerTonne))}
|
error={isNaN(parseFloat(bushelsConversion))}
|
||||||
helperText={isNaN(parseFloat(bushelsPerTonne)) ? "Must be a valid number" : ""}
|
helperText={isNaN(parseFloat(bushelsConversion)) ? "Must be a valid number" : ""}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
let val = e.target.value
|
let val = e.target.value
|
||||||
setBushelsPerTonne(val)
|
setBushelConversion(val)
|
||||||
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, val)
|
valid.current = validate(name, group, constantA, constantB, constantC, kgPerBushel, val)
|
||||||
let settings = cloneDeep(newGrainSettings)
|
let settings = cloneDeep(newGrainSettings)
|
||||||
if(!isNaN(parseFloat(val))){
|
if(!isNaN(parseFloat(val))){
|
||||||
settings.bushelsPerTonne = parseFloat(val)
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
settings.bushelsPerTonne = parseFloat(val)/0.907
|
||||||
|
}else{
|
||||||
|
settings.bushelsPerTonne = parseFloat(val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
settingsChanged(settings)
|
settingsChanged(settings)
|
||||||
}}
|
}}
|
||||||
label="Bushels per Tonne"/>
|
label={"Bushels per " + (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE ? " Tonne" : "Ton")}/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export interface GrainExtension {
|
||||||
colour: string;
|
colour: string;
|
||||||
weightConversionKg: number;
|
weightConversionKg: number;
|
||||||
bushelsPerTonne: number;
|
bushelsPerTonne: number;
|
||||||
|
bushelsPerTon: number; //NOTE: this is US tons (2000lB/t)
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultSetTemp = 30.0;
|
const defaultSetTemp = 30.0;
|
||||||
|
|
@ -45,7 +46,8 @@ const defaultGrain: GrainExtension = {
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "#424242",
|
colour: "#424242",
|
||||||
weightConversionKg: 0,
|
weightConversionKg: 0,
|
||||||
bushelsPerTonne: 0
|
bushelsPerTonne: 0,
|
||||||
|
bushelsPerTon: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
|
|
@ -64,7 +66,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "yellow",
|
colour: "yellow",
|
||||||
weightConversionKg: 0,
|
weightConversionKg: 0,
|
||||||
bushelsPerTonne: 0
|
bushelsPerTonne: 0,
|
||||||
|
bushelsPerTon: 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -81,7 +84,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: BarleyImg,
|
img: BarleyImg,
|
||||||
colour: "#27632a",
|
colour: "#27632a",
|
||||||
weightConversionKg: 21.772657171369,
|
weightConversionKg: 21.772657171369,
|
||||||
bushelsPerTonne: 45.93
|
bushelsPerTonne: 45.93,
|
||||||
|
bushelsPerTon: 41.66
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -98,7 +102,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 16.1,
|
targetMC: 16.1,
|
||||||
colour: "#46b298",
|
colour: "#46b298",
|
||||||
weightConversionKg: 1,
|
weightConversionKg: 1,
|
||||||
bushelsPerTonne: 45.93
|
bushelsPerTonne: 45.93,
|
||||||
|
bushelsPerTon: 50.63
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -116,7 +121,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
// colour: "#cddc39",
|
// colour: "#cddc39",
|
||||||
colour: "#ffff00",
|
colour: "#ffff00",
|
||||||
weightConversionKg: 22.67961461,
|
weightConversionKg: 22.67961461,
|
||||||
bushelsPerTonne: 44.092
|
bushelsPerTonne: 44.092,
|
||||||
|
bushelsPerTon: 39.99
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -133,7 +139,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: CanolaImg,
|
img: CanolaImg,
|
||||||
colour: "#cddc39",
|
colour: "#cddc39",
|
||||||
weightConversionKg: 27.215537532,
|
weightConversionKg: 27.215537532,
|
||||||
bushelsPerTonne: 44.092
|
bushelsPerTonne: 44.092,
|
||||||
|
bushelsPerTon: 39.9
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -150,7 +157,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: CornImg,
|
img: CornImg,
|
||||||
colour: "#ffef62",
|
colour: "#ffef62",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -167,7 +175,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: CornImg,
|
img: CornImg,
|
||||||
colour: "#ffef62",
|
colour: "#ffef62",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -184,7 +193,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: CornImg,
|
img: CornImg,
|
||||||
colour: "#ffef62",
|
colour: "#ffef62",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -201,7 +211,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: CornImg,
|
img: CornImg,
|
||||||
colour: "#ffef62",
|
colour: "#ffef62",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -218,7 +229,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: CornImg,
|
img: CornImg,
|
||||||
colour: "#ffef62",
|
colour: "#ffef62",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -235,7 +247,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: OatImg,
|
img: OatImg,
|
||||||
colour: "#79955a",
|
colour: "#79955a",
|
||||||
weightConversionKg: 15.4222988297197,
|
weightConversionKg: 15.4222988297197,
|
||||||
bushelsPerTonne: 64.842
|
bushelsPerTonne: 64.842,
|
||||||
|
bushelsPerTon: 58.81
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -252,7 +265,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: OatImg,
|
img: OatImg,
|
||||||
colour: "#79955a",
|
colour: "#79955a",
|
||||||
weightConversionKg: 15.4222988297197,
|
weightConversionKg: 15.4222988297197,
|
||||||
bushelsPerTonne: 64.842
|
bushelsPerTonne: 64.842,
|
||||||
|
bushelsPerTon: 58.81
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -269,7 +283,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: OatImg,
|
img: OatImg,
|
||||||
colour: "#79955a",
|
colour: "#79955a",
|
||||||
weightConversionKg: 15.4222988297197,
|
weightConversionKg: 15.4222988297197,
|
||||||
bushelsPerTonne: 64.842
|
bushelsPerTonne: 64.842,
|
||||||
|
bushelsPerTon: 58.81
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -286,7 +301,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: PeanutImg,
|
img: PeanutImg,
|
||||||
colour: "#b2a058",
|
colour: "#b2a058",
|
||||||
weightConversionKg: 23.3124,
|
weightConversionKg: 23.3124,
|
||||||
bushelsPerTonne: 105.263
|
bushelsPerTonne: 105.263,
|
||||||
|
bushelsPerTon: 95.47
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -303,7 +319,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: RiceImg,
|
img: RiceImg,
|
||||||
colour: "#7c9c99",
|
colour: "#7c9c99",
|
||||||
weightConversionKg: 28.439,
|
weightConversionKg: 28.439,
|
||||||
bushelsPerTonne: 49.02
|
bushelsPerTonne: 49.02,
|
||||||
|
bushelsPerTon: 44.46
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -320,7 +337,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: RiceImg,
|
img: RiceImg,
|
||||||
colour: "#7c9c99",
|
colour: "#7c9c99",
|
||||||
weightConversionKg: 29.979,
|
weightConversionKg: 29.979,
|
||||||
bushelsPerTonne: 49.02
|
bushelsPerTonne: 49.02,
|
||||||
|
bushelsPerTon: 44.46
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -337,7 +355,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: RiceImg,
|
img: RiceImg,
|
||||||
colour: "#7c9c99",
|
colour: "#7c9c99",
|
||||||
weightConversionKg: 30.744,
|
weightConversionKg: 30.744,
|
||||||
bushelsPerTonne: 49.02
|
bushelsPerTonne: 49.02,
|
||||||
|
bushelsPerTon: 44.46
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -354,7 +373,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: SorghumImg,
|
img: SorghumImg,
|
||||||
colour: "#829baf",
|
colour: "#829baf",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -371,7 +391,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: SoybeanImg,
|
img: SoybeanImg,
|
||||||
colour: "#7d6d99",
|
colour: "#7d6d99",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -388,7 +409,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: SunflowerImg,
|
img: SunflowerImg,
|
||||||
colour: "#ffab40",
|
colour: "#ffab40",
|
||||||
weightConversionKg: 13.6079107321056,
|
weightConversionKg: 13.6079107321056,
|
||||||
bushelsPerTonne: 73.487
|
bushelsPerTonne: 73.487,
|
||||||
|
bushelsPerTon: 66.65
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -405,7 +427,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: WheatImg,
|
img: WheatImg,
|
||||||
colour: "#46b298",
|
colour: "#46b298",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -422,7 +445,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: WheatImg,
|
img: WheatImg,
|
||||||
colour: "#46b298",
|
colour: "#46b298",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -439,7 +463,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: WheatImg,
|
img: WheatImg,
|
||||||
colour: "#46b298",
|
colour: "#46b298",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -456,7 +481,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: FlaxImg,
|
img: FlaxImg,
|
||||||
colour: "#6e6d19",
|
colour: "#6e6d19",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -473,7 +499,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: FlaxImg,
|
img: FlaxImg,
|
||||||
colour: "#6e6d19",
|
colour: "#6e6d19",
|
||||||
weightConversionKg: 25.4014333665971,
|
weightConversionKg: 25.4014333665971,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -490,7 +517,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: PeaImg,
|
img: PeaImg,
|
||||||
colour: "#ffe100",
|
colour: "#ffe100",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -507,7 +535,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: LentilImg,
|
img: LentilImg,
|
||||||
colour: "#cb5e3c",
|
colour: "#cb5e3c",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -524,7 +553,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: LentilImg,
|
img: LentilImg,
|
||||||
colour: "#cb5e3c",
|
colour: "#cb5e3c",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -541,7 +571,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
img: LentilImg,
|
img: LentilImg,
|
||||||
colour: "#cb5e3c",
|
colour: "#cb5e3c",
|
||||||
weightConversionKg: 27.2158214642112,
|
weightConversionKg: 27.2158214642112,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
@ -557,7 +588,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "red",
|
colour: "red",
|
||||||
weightConversionKg: 27.2155,
|
weightConversionKg: 27.2155,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],[
|
],[
|
||||||
pond.Grain.GRAIN_DRY_BEANS_BLACK,
|
pond.Grain.GRAIN_DRY_BEANS_BLACK,
|
||||||
|
|
@ -572,7 +604,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "grey",
|
colour: "grey",
|
||||||
weightConversionKg: 27.2155,
|
weightConversionKg: 27.2155,
|
||||||
bushelsPerTonne: 36.744
|
bushelsPerTonne: 36.744,
|
||||||
|
bushelsPerTon: 33.33
|
||||||
}
|
}
|
||||||
],[
|
],[
|
||||||
pond.Grain.GRAIN_RYE_A,
|
pond.Grain.GRAIN_RYE_A,
|
||||||
|
|
@ -587,7 +620,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "grey",
|
colour: "grey",
|
||||||
weightConversionKg: 25.4,
|
weightConversionKg: 25.4,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
],[
|
],[
|
||||||
pond.Grain.GRAIN_RYE_B,
|
pond.Grain.GRAIN_RYE_B,
|
||||||
|
|
@ -602,7 +636,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "grey",
|
colour: "grey",
|
||||||
weightConversionKg: 25.4,
|
weightConversionKg: 25.4,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
},
|
},
|
||||||
],[
|
],[
|
||||||
pond.Grain.GRAIN_RYE_C,
|
pond.Grain.GRAIN_RYE_C,
|
||||||
|
|
@ -617,7 +652,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "grey",
|
colour: "grey",
|
||||||
weightConversionKg: 25.4,
|
weightConversionKg: 25.4,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
},
|
},
|
||||||
],[
|
],[
|
||||||
pond.Grain.GRAIN_RYE_D,
|
pond.Grain.GRAIN_RYE_D,
|
||||||
|
|
@ -632,7 +668,8 @@ export const GrainExtensions: Map<pond.Grain, GrainExtension> = new Map([
|
||||||
targetMC: 15.0,
|
targetMC: 15.0,
|
||||||
colour: "grey",
|
colour: "grey",
|
||||||
weightConversionKg: 25.4,
|
weightConversionKg: 25.4,
|
||||||
bushelsPerTonne: 39.368
|
bushelsPerTonne: 39.368,
|
||||||
|
bushelsPerTon: 35.71
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -225,12 +225,13 @@ export default function GrainTransaction(props: Props) {
|
||||||
const createTransaction = (finalVal: number) => {
|
const createTransaction = (finalVal: number) => {
|
||||||
let dest = selectedDestination;
|
let dest = selectedDestination;
|
||||||
let source = selectedSource;
|
let source = selectedSource;
|
||||||
let bpt = 1;
|
let bPerTonne = 1;
|
||||||
|
let bPerTon = 1;
|
||||||
//use the sources bushel per tonne if one was selected otherwise use the destination
|
//use the sources bushel per tonne if one was selected otherwise use the destination
|
||||||
if (source) {
|
if (source) {
|
||||||
bpt = source.value.bushelsPerTonne();
|
bPerTonne = source.value.bushelsPerTonne();
|
||||||
} else if (dest) {
|
} else if (dest) {
|
||||||
bpt = dest.value.bushelsPerTonne();
|
bPerTonne = dest.value.bushelsPerTonne();
|
||||||
}
|
}
|
||||||
|
|
||||||
let newTransaction = pond.Transaction.create({
|
let newTransaction = pond.Transaction.create({
|
||||||
|
|
@ -239,7 +240,7 @@ export default function GrainTransaction(props: Props) {
|
||||||
grainTransaction: pond.GrainTransaction.create({
|
grainTransaction: pond.GrainTransaction.create({
|
||||||
bushels: finalVal,
|
bushels: finalVal,
|
||||||
message: grainMessage,
|
message: grainMessage,
|
||||||
bushelsPerTonne: bpt
|
bushelsPerTonne: bPerTonne,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
@ -449,6 +450,17 @@ export default function GrainTransaction(props: Props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const grainUnitDisplay = () => {
|
||||||
|
switch (getGrainUnit()){
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TONNE:
|
||||||
|
return "mT"
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TON:
|
||||||
|
return "t"
|
||||||
|
default:
|
||||||
|
return "bu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ResponsiveDialog
|
<ResponsiveDialog
|
||||||
open={open}
|
open={open}
|
||||||
|
|
@ -506,14 +518,14 @@ export default function GrainTransaction(props: Props) {
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? "mT" : "bu"}
|
{grainUnitDisplay()}
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
//if the user is viewing the grain in weight
|
//if the user is viewing the grain in weight
|
||||||
let grainVal = e.target.value;
|
let grainVal = e.target.value;
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE) {
|
||||||
//need to convert what the user input (weight) into what is actually stored (bushels)
|
//need to convert what the user input (weight) into what is actually stored (bushels)
|
||||||
//use source of the conversion value if it was selected, otherwise use the destination
|
//use source of the conversion value if it was selected, otherwise use the destination
|
||||||
if (!isNaN(parseFloat(e.target.value))) {
|
if (!isNaN(parseFloat(e.target.value))) {
|
||||||
|
|
@ -523,6 +535,18 @@ export default function GrainTransaction(props: Props) {
|
||||||
grainVal = (+grainVal * selectedDestination.value.bushelsPerTonne()).toFixed(2);
|
grainVal = (+grainVal * selectedDestination.value.bushelsPerTonne()).toFixed(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON) {
|
||||||
|
if (!isNaN(parseFloat(e.target.value))) {
|
||||||
|
if (selectedSource) {
|
||||||
|
if(selectedSource.value.bushelsPerTonne){
|
||||||
|
grainVal = (+grainVal * (selectedSource.value.bushelsPerTonne() * 0.907)).toFixed(2);
|
||||||
|
}
|
||||||
|
} else if (selectedDestination) {
|
||||||
|
if(selectedDestination.value.bushelsPerTonne){
|
||||||
|
grainVal = (+grainVal * (selectedDestination.value.bushelsPerTonne() * 0.907)).toFixed(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setGrainEntry(e.target.value);
|
setGrainEntry(e.target.value);
|
||||||
setGrainChangeVal(grainVal);
|
setGrainChangeVal(grainVal);
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,14 @@ export default function GrainBagInventoryGraph(props: Props) {
|
||||||
//let time = hist.timestamp;
|
//let time = hist.timestamp;
|
||||||
let val = hist.object.grainBagSettings.currentBushels ?? 0;
|
let val = hist.object.grainBagSettings.currentBushels ?? 0;
|
||||||
if (
|
if (
|
||||||
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT &&
|
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE &&
|
||||||
grainBag.bushelsPerTonne() > 1
|
grainBag.bushelsPerTonne() > 1
|
||||||
) {
|
) {
|
||||||
val = Math.round((val / grainBag.bushelsPerTonne()) * 100) / 100;
|
val = Math.round((val / grainBag.bushelsPerTonne()) * 100) / 100;
|
||||||
}
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && grainBag.bushelsPerTonne() > 1){
|
||||||
|
val = Math.round((val / (grainBag.bushelsPerTonne() * 0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
if (val !== lastBushels) {
|
if (val !== lastBushels) {
|
||||||
lastBushels = val;
|
lastBushels = val;
|
||||||
barData.push({
|
barData.push({
|
||||||
|
|
@ -51,13 +54,16 @@ export default function GrainBagInventoryGraph(props: Props) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (barData.length === 0) {
|
if (barData.length === 0) {
|
||||||
|
let val = grainBag.bushels()
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && grainBag.bushelsPerTonne() > 1){
|
||||||
|
val = grainBag.bushels() / grainBag.bushelsPerTonne()
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && grainBag.bushelsPerTonne() > 1){
|
||||||
|
val = grainBag.bushels() / (grainBag.bushelsPerTonne() * 0.907)
|
||||||
|
}
|
||||||
barData.push({
|
barData.push({
|
||||||
timestamp: moment.now().valueOf(),
|
timestamp: moment.now().valueOf(),
|
||||||
value:
|
value: Math.round(val*100)/100
|
||||||
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT &&
|
|
||||||
grainBag.bushelsPerTonne() > 1
|
|
||||||
? Math.round((grainBag.bushels() / grainBag.bushelsPerTonne()) * 100) / 100
|
|
||||||
: grainBag.bushels()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
setData(barData);
|
setData(barData);
|
||||||
|
|
@ -71,6 +77,17 @@ export default function GrainBagInventoryGraph(props: Props) {
|
||||||
}
|
}
|
||||||
}, [grainBagAPI, grainBag, startDate, endDate, openSnack]); //eslint-disable-line react-hooks/exhaustive-deps
|
}, [grainBagAPI, grainBag, startDate, endDate, openSnack]); //eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
|
const maxYAxis = () => {
|
||||||
|
let val = grainBag.capacity()
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
val = Math.round((val / grainBag.bushelsPerTonne()) * 100) / 100;
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && grainBag.bushelsPerTonne() > 1){
|
||||||
|
val = Math.round((val / (grainBag.bushelsPerTonne() * 0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card raised>
|
<Card raised>
|
||||||
<Box padding={2}>
|
<Box padding={2}>
|
||||||
|
|
@ -87,11 +104,7 @@ export default function GrainBagInventoryGraph(props: Props) {
|
||||||
}
|
}
|
||||||
data={data}
|
data={data}
|
||||||
yMin={0}
|
yMin={0}
|
||||||
yMax={
|
yMax={maxYAxis()}
|
||||||
getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT
|
|
||||||
? grainBag.capacity() / grainBag.bushelsPerTonne()
|
|
||||||
: grainBag.capacity()
|
|
||||||
}
|
|
||||||
customHeight={customHeight}
|
customHeight={customHeight}
|
||||||
useGradient
|
useGradient
|
||||||
labels
|
labels
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ export default function GrainBagSettings(props: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [grainUpdate, setGrainUpdate] = useState(false);
|
const [grainUpdate, setGrainUpdate] = useState(false);
|
||||||
const [grainDiff, setGrainDiff] = useState(0);
|
const [grainDiff, setGrainDiff] = useState(0);
|
||||||
const [bushelsPerTonne, setBushelsPerTonne] = useState(0);
|
const [bushelConversion, setBushelConversion] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (grainBag) {
|
if (grainBag) {
|
||||||
|
|
@ -84,8 +84,10 @@ export default function GrainBagSettings(props: Props) {
|
||||||
: grainBag.settings.length
|
: grainBag.settings.length
|
||||||
);
|
);
|
||||||
let grainVal = grainBag.bushels();
|
let grainVal = grainBag.bushels();
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE) {
|
||||||
grainVal = grainBag.bushels() / grainBag.bushelsPerTonne();
|
grainVal = grainBag.bushels() / grainBag.bushelsPerTonne();
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON) {
|
||||||
|
grainVal = grainBag.bushels() / (grainBag.bushelsPerTonne() * 0.907)
|
||||||
}
|
}
|
||||||
setGrainFill(grainVal.toFixed(2));
|
setGrainFill(grainVal.toFixed(2));
|
||||||
setBagName(grainBag.name());
|
setBagName(grainBag.name());
|
||||||
|
|
@ -117,6 +119,10 @@ export default function GrainBagSettings(props: Props) {
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
//if a bag was passed in do an update
|
//if a bag was passed in do an update
|
||||||
|
let tonneConversion = bushelConversion
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
tonneConversion = bushelConversion / 0.907
|
||||||
|
}
|
||||||
if (grainBag) {
|
if (grainBag) {
|
||||||
grainBag.title = bagName;
|
grainBag.title = bagName;
|
||||||
grainBag.settings.initialMoisture = initialMoisture;
|
grainBag.settings.initialMoisture = initialMoisture;
|
||||||
|
|
@ -127,7 +133,7 @@ export default function GrainBagSettings(props: Props) {
|
||||||
grainBag.settings.bushelCapacity = grainCapacity;
|
grainBag.settings.bushelCapacity = grainCapacity;
|
||||||
grainBag.settings.grainSubtype = grainSubtype;
|
grainBag.settings.grainSubtype = grainSubtype;
|
||||||
grainBag.settings.fillDate = fillDate;
|
grainBag.settings.fillDate = fillDate;
|
||||||
grainBag.settings.bushelsPerTonne = bushelsPerTonne;
|
grainBag.settings.bushelsPerTonne = tonneConversion;
|
||||||
grainBag.settings.storageType = isCustom
|
grainBag.settings.storageType = isCustom
|
||||||
? pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN
|
? pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN
|
||||||
: pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN;
|
: pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN;
|
||||||
|
|
@ -161,6 +167,7 @@ export default function GrainBagSettings(props: Props) {
|
||||||
settings.currentBushels = grainBushels;
|
settings.currentBushels = grainBushels;
|
||||||
settings.grainSubtype = grainSubtype;
|
settings.grainSubtype = grainSubtype;
|
||||||
settings.fillDate = fillDate;
|
settings.fillDate = fillDate;
|
||||||
|
settings.bushelsPerTonne = tonneConversion;
|
||||||
settings.storageType = isCustom
|
settings.storageType = isCustom
|
||||||
? pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN
|
? pond.BinStorage.BIN_STORAGE_UNSUPPORTED_GRAIN
|
||||||
: pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN;
|
: pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN;
|
||||||
|
|
@ -205,10 +212,10 @@ export default function GrainBagSettings(props: Props) {
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
label="Bushels Per Tonne"
|
label="Bushels Per Tonne"
|
||||||
value={bushelsPerTonne}
|
value={bushelConversion}
|
||||||
type="number"
|
type="number"
|
||||||
onChange={event => {
|
onChange={event => {
|
||||||
setBushelsPerTonne(+event.target.value);
|
setBushelConversion(+event.target.value);
|
||||||
}}
|
}}
|
||||||
fullWidth
|
fullWidth
|
||||||
className={classes.bottomSpacing}
|
className={classes.bottomSpacing}
|
||||||
|
|
@ -227,7 +234,7 @@ export default function GrainBagSettings(props: Props) {
|
||||||
? pond.Grain[option.value as keyof typeof pond.Grain]
|
? pond.Grain[option.value as keyof typeof pond.Grain]
|
||||||
: pond.Grain.GRAIN_INVALID;
|
: pond.Grain.GRAIN_INVALID;
|
||||||
setSupportedGrainType(newGrainType);
|
setSupportedGrainType(newGrainType);
|
||||||
setBushelsPerTonne(GrainDescriber(newGrainType).bushelsPerTonne);
|
setBushelConversion(GrainDescriber(newGrainType).bushelsPerTonne);
|
||||||
setSelectedGrainOp(option);
|
setSelectedGrainOp(option);
|
||||||
}}
|
}}
|
||||||
group
|
group
|
||||||
|
|
@ -246,6 +253,18 @@ export default function GrainBagSettings(props: Props) {
|
||||||
return invalid;
|
return invalid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const grainUnitDisplay = () => {
|
||||||
|
if(bushelConversion > 1){
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
return "mT"
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
return "t"
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return "bu"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<GrainTransaction
|
<GrainTransaction
|
||||||
|
|
@ -389,30 +408,24 @@ export default function GrainBagSettings(props: Props) {
|
||||||
className={classes.bottomSpacing}
|
className={classes.bottomSpacing}
|
||||||
/>
|
/>
|
||||||
<TextField
|
<TextField
|
||||||
label={
|
label={"Current Inventory"}
|
||||||
"Current " +
|
|
||||||
(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bushelsPerTonne > 0
|
|
||||||
? "Weight"
|
|
||||||
: "Bushels")
|
|
||||||
}
|
|
||||||
fullWidth
|
fullWidth
|
||||||
type="number"
|
type="number"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment position="end">
|
<InputAdornment position="end">
|
||||||
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && bushelsPerTonne > 0
|
{grainUnitDisplay()}
|
||||||
? "mT"
|
|
||||||
: "bu"}
|
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
value={grainFill}
|
value={grainFill}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
let bushelVal = +e.target.value;
|
let bushelVal = +e.target.value;
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE || getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON) {
|
||||||
//convert the number as a weight into the bushel value
|
//convert the number as a weight into the bushel value, no changing or conversions necessary
|
||||||
bushelVal = +e.target.value * (bushelsPerTonne > 0 ? bushelsPerTonne : 1);
|
// since these are both user entered fields and should be the same unit (ton or tonne)
|
||||||
|
bushelVal = +e.target.value * (bushelConversion > 0 ? bushelConversion : 1);
|
||||||
}
|
}
|
||||||
if (bushelVal > grainCapacity) {
|
if (bushelVal > grainCapacity) {
|
||||||
bushelVal = grainCapacity;
|
bushelVal = grainCapacity;
|
||||||
|
|
|
||||||
|
|
@ -83,12 +83,19 @@ export default function GrainBagVisualizer(props: Props) {
|
||||||
const grainOverlay = () => {
|
const grainOverlay = () => {
|
||||||
let displayPending = pendingGrainAmount;
|
let displayPending = pendingGrainAmount;
|
||||||
let displayDiff = grainDiff;
|
let displayDiff = grainDiff;
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && grainBag.bushelsPerTonne() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && grainBag.bushelsPerTonne() > 1) {
|
||||||
if (displayPending && displayDiff) {
|
if (displayPending && displayDiff) {
|
||||||
displayPending = Math.round((displayPending / grainBag.bushelsPerTonne()) * 100) / 100;
|
displayPending = Math.round((displayPending / grainBag.bushelsPerTonne()) * 100) / 100;
|
||||||
displayDiff = Math.round((displayDiff / grainBag.bushelsPerTonne()) * 100) / 100;
|
displayDiff = Math.round((displayDiff / grainBag.bushelsPerTonne()) * 100) / 100;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && grainBag.bushelsPerTonne() > 1) {
|
||||||
|
if (displayPending && displayDiff) {
|
||||||
|
displayPending = Math.round((displayPending / (grainBag.bushelsPerTonne() * 0.907)) * 100) / 100;
|
||||||
|
displayDiff = Math.round((displayDiff / (grainBag.bushelsPerTonne()* 0.907)) * 100) / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
{grainDiff !== undefined && grainDiff > 0 && (
|
{grainDiff !== undefined && grainDiff > 0 && (
|
||||||
|
|
@ -141,7 +148,7 @@ export default function GrainBagVisualizer(props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const grainAmountDisplay = () => {
|
const grainAmountDisplay = () => {
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && grainBag.bushelsPerTonne() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && grainBag.bushelsPerTonne() > 1) {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
<Typography variant="body2" style={{ fontWeight: "bold", marginRight: "4px" }}>
|
<Typography variant="body2" style={{ fontWeight: "bold", marginRight: "4px" }}>
|
||||||
|
|
@ -150,6 +157,15 @@ export default function GrainBagVisualizer(props: Props) {
|
||||||
<Typography variant="body2">({grainBag.fillPercent()}%)</Typography>
|
<Typography variant="body2">({grainBag.fillPercent()}%)</Typography>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
} else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && grainBag.bushelsPerTonne() > 1) {
|
||||||
|
return (
|
||||||
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
<Typography variant="body2" style={{ fontWeight: "bold", marginRight: "4px" }}>
|
||||||
|
{(grainBag.bushels() / (grainBag.bushelsPerTonne()*0.907)).toFixed(2) + " t"}
|
||||||
|
</Typography>
|
||||||
|
<Typography variant="body2">({grainBag.fillPercent()}%)</Typography>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: "flex", flexDirection: "row" }}>
|
<div style={{ display: "flex", flexDirection: "row" }}>
|
||||||
|
|
|
||||||
123
src/hooks/useWebSocket.ts
Normal file
123
src/hooks/useWebSocket.ts
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
import { useEffect, useRef, useCallback } from "react";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derives the WebSocket base URL from VITE_APP_API_URL.
|
||||||
|
* e.g. "https://api.brandxtech.ca" -> "wss://api.brandxtech.ca"
|
||||||
|
* Falls back to current page host for local dev.
|
||||||
|
*/
|
||||||
|
function getWsBaseUrl(): string {
|
||||||
|
const apiUrl = import.meta.env.VITE_APP_API_URL;
|
||||||
|
if (apiUrl) {
|
||||||
|
return apiUrl.replace(/^http/, "ws");
|
||||||
|
}
|
||||||
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
||||||
|
return `${protocol}//${window.location.host}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UseWebSocketOptions<T> {
|
||||||
|
/** The API path, e.g. "/v1/live/devices/123/components" */
|
||||||
|
path: string;
|
||||||
|
/** Transform the raw MessageEvent into your domain type */
|
||||||
|
parse: (event: MessageEvent) => T;
|
||||||
|
/** Called whenever a new parsed message arrives */
|
||||||
|
onMessage: (data: T) => void;
|
||||||
|
/** Auth token passed as ?token= query param */
|
||||||
|
token?: string;
|
||||||
|
/** Minimum seconds between updates, passed as ?rate= to the backend */
|
||||||
|
rate?: number;
|
||||||
|
/** Whether the connection should be active. Default true. */
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* useWebSocket manages a WebSocket connection with automatic reconnection.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* useWebSocket({
|
||||||
|
* path: `/v1/live/devices/${deviceID}/components`,
|
||||||
|
* parse: (e) => Component.any(JSON.parse(e.data)),
|
||||||
|
* onMessage: (component) => handleUpdate(component),
|
||||||
|
* token: authToken,
|
||||||
|
* });
|
||||||
|
*/
|
||||||
|
export function useWebSocket<T>(options: UseWebSocketOptions<T>) {
|
||||||
|
const { path, parse, onMessage, token, rate = 0, enabled = true } = options;
|
||||||
|
|
||||||
|
// Keep latest callbacks in refs so reconnects don't use stale closures
|
||||||
|
const onMessageRef = useRef(onMessage);
|
||||||
|
onMessageRef.current = onMessage;
|
||||||
|
const parseRef = useRef(parse);
|
||||||
|
parseRef.current = parse;
|
||||||
|
|
||||||
|
const wsRef = useRef<WebSocket | null>(null);
|
||||||
|
const reconnectTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
||||||
|
const retriesRef = useRef(0);
|
||||||
|
|
||||||
|
const connect = useCallback(() => {
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
params.set("token", token);
|
||||||
|
if (rate > 0) params.set("rate", rate.toString());
|
||||||
|
|
||||||
|
const url = `${getWsBaseUrl()}${path}?${params.toString()}`;
|
||||||
|
const ws = new WebSocket(url);
|
||||||
|
wsRef.current = ws;
|
||||||
|
|
||||||
|
ws.onopen = () => {
|
||||||
|
console.debug(`[ws] connected: ${path}`);
|
||||||
|
retriesRef.current = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onmessage = (event) => {
|
||||||
|
try {
|
||||||
|
const parsed = parseRef.current(event);
|
||||||
|
onMessageRef.current(parsed);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`[ws] parse error on ${path}:`, err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onerror = (err) => {
|
||||||
|
console.warn(`[ws] error on ${path}:`, err);
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = (event) => {
|
||||||
|
console.debug(`[ws] closed: ${path} (code: ${event.code})`);
|
||||||
|
wsRef.current = null;
|
||||||
|
|
||||||
|
// Don't reconnect on clean close or auth rejection
|
||||||
|
if (event.code === 1000 || event.code === 4001 || event.code === 4003) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exponential backoff: 1s, 2s, 4s, 8s, ... capped at 30s
|
||||||
|
const delay = Math.min(1000 * Math.pow(2, retriesRef.current), 30000);
|
||||||
|
retriesRef.current += 1;
|
||||||
|
console.debug(`[ws] reconnecting in ${delay}ms...`);
|
||||||
|
reconnectTimeoutRef.current = setTimeout(connect, delay);
|
||||||
|
};
|
||||||
|
}, [path, token, rate]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!enabled || !token) {
|
||||||
|
if (wsRef.current) {
|
||||||
|
wsRef.current.close(1000, "disabled");
|
||||||
|
wsRef.current = null;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (reconnectTimeoutRef.current) {
|
||||||
|
clearTimeout(reconnectTimeoutRef.current);
|
||||||
|
}
|
||||||
|
if (wsRef.current) {
|
||||||
|
wsRef.current.close(1000, "cleanup");
|
||||||
|
wsRef.current = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [connect, enabled, token]);
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ import GrainDescriber from "grain/GrainDescriber";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import { MarkerData } from "maps/mapMarkers/Markers";
|
import { MarkerData } from "maps/mapMarkers/Markers";
|
||||||
import { pond } from "protobuf-ts/pond";
|
import { pond } from "protobuf-ts/pond";
|
||||||
|
import { getGrainUnit } from "utils";
|
||||||
import { stringToMaterialColour } from "utils/strings";
|
import { stringToMaterialColour } from "utils/strings";
|
||||||
import { or } from "utils/types";
|
import { or } from "utils/types";
|
||||||
|
|
||||||
|
|
@ -235,17 +236,14 @@ export class Bin {
|
||||||
return bpt;
|
return bpt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public grainInventory(): number {
|
||||||
* gets the weight in tonnes for the grain inventory provided the bushels per tonne is set
|
let grain = this.bushels()
|
||||||
* if it is not set it will divide by 1 effectively returning the bushels
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.bushelsPerTonne() > 1){
|
||||||
* @returns grain weight
|
grain = this.bushels() / this.bushelsPerTonne()
|
||||||
*/
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.bushelsPerTonne() > 1){
|
||||||
public grainTonnes(): number {
|
grain = this.bushels() / (this.bushelsPerTonne() * 0.907)
|
||||||
let weight = 0;
|
|
||||||
if (this.settings.inventory) {
|
|
||||||
weight = this.settings.inventory.grainBushels / this.bushelsPerTonne();
|
|
||||||
}
|
}
|
||||||
return Math.round(weight * 100) / 100;
|
return Math.round(grain*100)/100
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,13 @@ export class Contract {
|
||||||
|
|
||||||
private measurementUnit(): string {
|
private measurementUnit(): string {
|
||||||
if (this.settings.type === pond.ContractType.CONTRACT_TYPE_GRAIN) {
|
if (this.settings.type === pond.ContractType.CONTRACT_TYPE_GRAIN) {
|
||||||
return getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? "mT" : "bu";
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.conversionValue() > 1){
|
||||||
|
return "mT"
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.conversionValue() > 1){
|
||||||
|
return "t"
|
||||||
|
}
|
||||||
|
return "bu";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
@ -202,9 +208,12 @@ export class Contract {
|
||||||
let size = this.settings.size;
|
let size = this.settings.size;
|
||||||
switch (this.settings.type) {
|
switch (this.settings.type) {
|
||||||
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && this.conversionValue() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.conversionValue() > 1) {
|
||||||
size = size / this.conversionValue();
|
size = size / this.conversionValue();
|
||||||
}
|
}
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.conversionValue() > 1){
|
||||||
|
size = size / (this.conversionValue() * 0.907); //the conversion for grain will be stored in metric tonnes, this will convert it to US tons
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Math.round(size * 100) / 100;
|
return Math.round(size * 100) / 100;
|
||||||
}
|
}
|
||||||
|
|
@ -213,26 +222,33 @@ export class Contract {
|
||||||
let del = this.settings.delivered;
|
let del = this.settings.delivered;
|
||||||
switch (this.settings.type) {
|
switch (this.settings.type) {
|
||||||
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && this.conversionValue() > 1) {
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && this.conversionValue() > 1) {
|
||||||
del = del / this.conversionValue();
|
del = del / this.conversionValue();
|
||||||
}
|
}
|
||||||
|
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && this.conversionValue() > 1){
|
||||||
|
del = del / (this.conversionValue() * 0.907); //the conversion for grain will be stored in metric tonnes, this will convert it to US tons
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return Math.round(del * 100) / 100;
|
return Math.round(del * 100) / 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static toStoredUnit(
|
public static toStoredUnit(
|
||||||
secondaryUnitVal: number,
|
secondaryUnitVal: number,
|
||||||
contractType: pond.ContractType,
|
contractType: pond.ContractType,
|
||||||
conversionValue: number
|
conversionValue: number
|
||||||
): number {
|
): number {
|
||||||
let storedunitVal = secondaryUnitVal;
|
let storedUnitVal = secondaryUnitVal;
|
||||||
switch (contractType) {
|
switch (contractType) {
|
||||||
|
//use the value and conversion they entered directly, it is safe to assume they are both the same unit (ton vs tonne) so dont need to convert anything
|
||||||
|
//before converting to bushels
|
||||||
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
case pond.ContractType.CONTRACT_TYPE_GRAIN:
|
||||||
if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && conversionValue > 1) {
|
if ((getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE || getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON) && conversionValue > 1) {
|
||||||
storedunitVal = secondaryUnitVal * conversionValue;
|
storedUnitVal = secondaryUnitVal * conversionValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return storedunitVal;
|
return storedUnitVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public grainName(): string {
|
public grainName(): string {
|
||||||
|
|
|
||||||
|
|
@ -278,6 +278,10 @@ export default function Router() {
|
||||||
path="/:groupID/devices/:deviceID"
|
path="/:groupID/devices/:deviceID"
|
||||||
element={<DevicePage />}
|
element={<DevicePage />}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path="/:groupID/devices/:deviceID/components/:componentID"
|
||||||
|
element={<DeviceComponent />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
path="/:groupID/devices/:deviceID/*"
|
path="/:groupID/devices/:deviceID/*"
|
||||||
element={<RelativeRoutes />}
|
element={<RelativeRoutes />}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,7 @@ import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
darken,
|
|
||||||
Typography,
|
Typography,
|
||||||
ToggleButton,
|
|
||||||
ToggleButtonGroup
|
|
||||||
} from "@mui/material";
|
} from "@mui/material";
|
||||||
import BinActions from "bin/BinActions";
|
import BinActions from "bin/BinActions";
|
||||||
import BinHistory from "bin/BinHistory";
|
import BinHistory from "bin/BinHistory";
|
||||||
|
|
@ -60,7 +57,7 @@ import { Ambient } from "models/Ambient";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import BinStorageConditions from "bin/BinStorageConditions";
|
import BinStorageConditions from "bin/BinStorageConditions";
|
||||||
import BinConditioningCard from "bin/BinConditioningCard";
|
import BinConditioningCard from "bin/BinConditioningCard";
|
||||||
import { makeStyles, styled } from "@mui/styles";
|
import { makeStyles } from "@mui/styles";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { Controller } from "models/Controller";
|
import { Controller } from "models/Controller";
|
||||||
import TaskViewer from "tasks/TaskViewer";
|
import TaskViewer from "tasks/TaskViewer";
|
||||||
|
|
|
||||||
|
|
@ -928,9 +928,47 @@ export default function Bins(props: Props) {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const grainUnitDisplay = (custom?: pond.CustomInventory) => {
|
||||||
|
// If custom and not convertible, always bushels
|
||||||
|
if (custom && custom.bushelsPerTonne <= 1) {
|
||||||
|
return " bu";
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (getGrainUnit()) {
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TONNE:
|
||||||
|
return " mT";
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TON:
|
||||||
|
return " t";
|
||||||
|
default:
|
||||||
|
return " bu";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const customQuantityDisplay = (customInventory: pond.CustomInventory, bushels: number) => {
|
||||||
|
let amount = bushels
|
||||||
|
if(customInventory.bushelsPerTonne > 1){
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
amount = bushels/customInventory.bushelsPerTonne
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
amount = bushels/(customInventory.bushelsPerTonne*0.907)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Math.round(amount*100)/100
|
||||||
|
}
|
||||||
|
|
||||||
|
const supportedGrainDisplay = (grain: pond.Grain, bushels: number) => {
|
||||||
|
const describer = GrainDescriber(grain)
|
||||||
|
let amount = bushels
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE){
|
||||||
|
amount = bushels/describer.bushelsPerTonne
|
||||||
|
}else if (getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON){
|
||||||
|
amount = bushels/describer.bushelsPerTon
|
||||||
|
}
|
||||||
|
return Math.round(amount*100)/100
|
||||||
|
}
|
||||||
|
|
||||||
const binUtilizationList = () => {
|
const binUtilizationList = () => {
|
||||||
const hasInventory = binMetrics && binMetrics.grainInventory.length > 0;
|
const hasInventory = binMetrics && binMetrics.grainInventory.length > 0;
|
||||||
const useWeight = getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT;
|
|
||||||
return (
|
return (
|
||||||
<Accordion
|
<Accordion
|
||||||
className={classes.accordion}
|
className={classes.accordion}
|
||||||
|
|
@ -972,17 +1010,9 @@ export default function Bins(props: Props) {
|
||||||
<ImageListItem key={key}>
|
<ImageListItem key={key}>
|
||||||
<BinUtilizationChart
|
<BinUtilizationChart
|
||||||
grain={inv.grainType}
|
grain={inv.grainType}
|
||||||
customUnit={useWeight ? " mT" : " bu"}
|
customUnit={grainUnitDisplay()}
|
||||||
bushelAmount={
|
bushelAmount={supportedGrainDisplay(inv.grainType, inv.bushelAmount)}
|
||||||
useWeight
|
bushelCapacity={supportedGrainDisplay(inv.grainType, inv.bushelCapacity)}
|
||||||
? inv.bushelAmount / GrainDescriber(inv.grainType).bushelsPerTonne
|
|
||||||
: inv.bushelAmount
|
|
||||||
}
|
|
||||||
bushelCapacity={
|
|
||||||
useWeight
|
|
||||||
? inv.bushelCapacity / GrainDescriber(inv.grainType).bushelsPerTonne
|
|
||||||
: inv.bushelCapacity
|
|
||||||
}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setContentFilter(pond.Grain[inv.grainType]);
|
setContentFilter(pond.Grain[inv.grainType]);
|
||||||
loadMoreBins(pond.Grain[inv.grainType]);
|
loadMoreBins(pond.Grain[inv.grainType]);
|
||||||
|
|
@ -1001,11 +1031,10 @@ export default function Bins(props: Props) {
|
||||||
amount = amount * 35.239;
|
amount = amount * 35.239;
|
||||||
cap = cap * 35.239;
|
cap = cap * 35.239;
|
||||||
unit = " L";
|
unit = " L";
|
||||||
}
|
} else {
|
||||||
if (useWeight && inv.bushelsPerTonne > 1) {
|
amount = customQuantityDisplay(inv, amount)
|
||||||
amount = amount / inv.bushelsPerTonne;
|
cap = customQuantityDisplay(inv, cap)
|
||||||
cap = cap / inv.bushelsPerTonne;
|
unit = grainUnitDisplay(inv);
|
||||||
unit = " mT";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { useDeviceAPI, useGlobalState, useSnackbar } from "providers";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useLocation, useParams } from "react-router-dom";
|
import { useLocation, useParams } from "react-router-dom";
|
||||||
import PageContainer from "./PageContainer";
|
import PageContainer from "./PageContainer";
|
||||||
import { useMobile } from "hooks";
|
import { useHTTP, useMobile } from "hooks";
|
||||||
import LoadingScreen from "app/LoadingScreen";
|
import LoadingScreen from "app/LoadingScreen";
|
||||||
import SmartBreadcrumb from "common/SmartBreadcrumb";
|
import SmartBreadcrumb from "common/SmartBreadcrumb";
|
||||||
import DeviceActions from "device/DeviceActions";
|
import DeviceActions from "device/DeviceActions";
|
||||||
|
|
@ -21,6 +21,7 @@ import { or } from "utils";
|
||||||
import ComponentDiagnostics from "component/ComponentDiagnostics";
|
import ComponentDiagnostics from "component/ComponentDiagnostics";
|
||||||
import DeviceWizard from "device/DeviceWizard";
|
import DeviceWizard from "device/DeviceWizard";
|
||||||
import DeviceScannedComponents from "device/autoDetect/DeviceScannedComponents";
|
import DeviceScannedComponents from "device/autoDetect/DeviceScannedComponents";
|
||||||
|
import { useWebSocket } from "hooks/useWebSocket";
|
||||||
|
|
||||||
export interface DevicePageData {
|
export interface DevicePageData {
|
||||||
device: Device;
|
device: Device;
|
||||||
|
|
@ -65,6 +66,8 @@ export default function DevicePage() {
|
||||||
|
|
||||||
// const [devicePageData, setDevicePageData] = useState(pond.GetDevicePageDataResponse.create())
|
// const [devicePageData, setDevicePageData] = useState(pond.GetDevicePageDataResponse.create())
|
||||||
|
|
||||||
|
const { token } = useHTTP();
|
||||||
|
|
||||||
const loadDevice = () => {
|
const loadDevice = () => {
|
||||||
if (loading) return
|
if (loading) return
|
||||||
if (state?.devicePageData) {
|
if (state?.devicePageData) {
|
||||||
|
|
@ -165,6 +168,41 @@ export default function DevicePage() {
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Real-time component updates ---
|
||||||
|
// Streams all component changes for this device.
|
||||||
|
// When the backend receives a new reading and updates a component,
|
||||||
|
// this fires and updates the component in state without a page refresh.
|
||||||
|
useWebSocket<{ key: string; component: Component }>({
|
||||||
|
path: `/live/devices/${deviceID}/components`,
|
||||||
|
parse: (e) => {
|
||||||
|
const raw = JSON.parse(e.data);
|
||||||
|
const comp = Component.any(raw);
|
||||||
|
return { key: comp.key(), component: comp };
|
||||||
|
},
|
||||||
|
onMessage: ({ key, component }) => {
|
||||||
|
// Functional update so we always work with the latest state
|
||||||
|
setComponents((prev) => {
|
||||||
|
const updated = new Map(prev);
|
||||||
|
updated.set(key, component);
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
token,
|
||||||
|
enabled: !!deviceID,
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Real-time device updates (optional) ---
|
||||||
|
// Updates device-level info (name, status, lastActive, etc.)
|
||||||
|
useWebSocket<Device>({
|
||||||
|
path: `/live/devices/${deviceID}`,
|
||||||
|
parse: (e) => Device.any(JSON.parse(e.data)),
|
||||||
|
onMessage: (updatedDevice) => {
|
||||||
|
setDevice(updatedDevice);
|
||||||
|
},
|
||||||
|
token,
|
||||||
|
enabled: !!deviceID,
|
||||||
|
});
|
||||||
|
|
||||||
const loadPortScan = () => {
|
const loadPortScan = () => {
|
||||||
deviceAPI.listFoundComponents(parseInt(deviceID))
|
deviceAPI.listFoundComponents(parseInt(deviceID))
|
||||||
.then(resp => {
|
.then(resp => {
|
||||||
|
|
|
||||||
|
|
@ -168,7 +168,8 @@ export default function SignupCallback () {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
InputLabelProps={{ shrink: true }}>
|
InputLabelProps={{ shrink: true }}>
|
||||||
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_BUSHELS}>Bushels (bu)</MenuItem>
|
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_BUSHELS}>Bushels (bu)</MenuItem>
|
||||||
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_WEIGHT}>Tonnes (mT)</MenuItem>
|
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_TONNE}>Tonnes (mT)</MenuItem>
|
||||||
|
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_TON}>US Tons (t)</MenuItem>
|
||||||
</TextField>
|
</TextField>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,6 @@ export default function GrainBag(props: Props) {
|
||||||
}
|
}
|
||||||
console.log
|
console.log
|
||||||
userAPI.getUser(user.id(), { key: key, kind: kind } as Scope).then(resp => {
|
userAPI.getUser(user.id(), { key: key, kind: kind } as Scope).then(resp => {
|
||||||
console.log(resp)
|
|
||||||
setPermissions(resp.permissions);
|
setPermissions(resp.permissions);
|
||||||
});
|
});
|
||||||
}, [as, bagID, userAPI, user]);
|
}, [as, bagID, userAPI, user]);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ interface IHTTPContext {
|
||||||
) => Promise<AxiosResponse<T>>;
|
) => Promise<AxiosResponse<T>>;
|
||||||
del: <T>(url: string, spreadOptions?: AxiosRequestConfig) => Promise<AxiosResponse<T>>;
|
del: <T>(url: string, spreadOptions?: AxiosRequestConfig) => Promise<AxiosResponse<T>>;
|
||||||
options: (demo?: boolean) => AxiosRequestConfig;
|
options: (demo?: boolean) => AxiosRequestConfig;
|
||||||
|
token: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props extends PropsWithChildren<any>{
|
interface Props extends PropsWithChildren<any>{
|
||||||
|
|
@ -104,7 +105,8 @@ export default function HTTPProvider(props: Props) {
|
||||||
put,
|
put,
|
||||||
post,
|
post,
|
||||||
del,
|
del,
|
||||||
options: defaultOptions
|
options: defaultOptions,
|
||||||
|
token
|
||||||
}}>
|
}}>
|
||||||
{/* <BillingProvider> */}
|
{/* <BillingProvider> */}
|
||||||
<PondProvider>
|
<PondProvider>
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ export default function BinProvider(props: PropsWithChildren<Props>) {
|
||||||
) => {
|
) => {
|
||||||
const view = otherTeam ? otherTeam : as
|
const view = otherTeam ? otherTeam : as
|
||||||
let url = "/bins/" + bin + "/updateComponent/" + component + "/preferences";
|
let url = "/bins/" + bin + "/updateComponent/" + component + "/preferences";
|
||||||
if (view) url = url + "/?as=" + view;
|
if (view) url = url + "?as=" + view;
|
||||||
interface request {
|
interface request {
|
||||||
preferences: Object;
|
preferences: Object;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,6 @@ export default function GateProvider(props: PropsWithChildren<Props>) {
|
||||||
return new Promise<AxiosResponse<pond.ListGatesResponse>>((resolve, reject) => {
|
return new Promise<AxiosResponse<pond.ListGatesResponse>>((resolve, reject) => {
|
||||||
get<pond.ListGatesResponse>(url).then(resp => {
|
get<pond.ListGatesResponse>(url).then(resp => {
|
||||||
resp.data = pond.ListGatesResponse.fromObject(resp.data)
|
resp.data = pond.ListGatesResponse.fromObject(resp.data)
|
||||||
console.log(resp)
|
|
||||||
return resolve(resp)
|
return resolve(resp)
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
return reject(err)
|
return reject(err)
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ export default function GrainBagProvider(props: PropsWithChildren<Props>) {
|
||||||
(end && "&end=" + end)
|
(end && "&end=" + end)
|
||||||
)
|
)
|
||||||
if (view) {
|
if (view) {
|
||||||
url = url + "?as=" + view
|
url = url + "&as=" + view
|
||||||
}
|
}
|
||||||
return get<pond.ListGrainBagHistoryResponse>(url);
|
return get<pond.ListGrainBagHistoryResponse>(url);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -337,7 +337,7 @@ export function getWhitelabel(): WhiteLabel {
|
||||||
return BXT_WHITE_LABEL;
|
return BXT_WHITE_LABEL;
|
||||||
}
|
}
|
||||||
if (window.location.origin.includes("localhost")) {
|
if (window.location.origin.includes("localhost")) {
|
||||||
return MIPCA_WHITE_LABEL;
|
return STREAMLINE_WHITE_LABEL;
|
||||||
}
|
}
|
||||||
if (window.location.origin.includes("staging") || import.meta.env.VITE_LOCAL_STAGING=='true') {
|
if (window.location.origin.includes("staging") || import.meta.env.VITE_LOCAL_STAGING=='true') {
|
||||||
return STAGING_WHITELABEL;
|
return STAGING_WHITELABEL;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,17 @@ interface Props {
|
||||||
|
|
||||||
export default function TransactionDataDisplay(props: Props) {
|
export default function TransactionDataDisplay(props: Props) {
|
||||||
const { transaction } = props;
|
const { transaction } = props;
|
||||||
|
console.log(transaction)
|
||||||
|
|
||||||
|
const grainDisplay = (gt: pond.GrainTransaction) => {
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TONNE && gt.bushelsPerTonne > 1){
|
||||||
|
return "Weight: " + Math.round(gt.bushels / gt.bushelsPerTonne*100)/100 + " mT"
|
||||||
|
}
|
||||||
|
if(getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_TON && gt.bushelsPerTonne > 1){
|
||||||
|
return "Weight: " + Math.round(gt.bushels / (gt.bushelsPerTonne*0.907)*100)/100 + " t"
|
||||||
|
}
|
||||||
|
return "Bushels: " + gt.bushels
|
||||||
|
}
|
||||||
|
|
||||||
const display = () => {
|
const display = () => {
|
||||||
let transactionData = transaction.transaction.transaction;
|
let transactionData = transaction.transaction.transaction;
|
||||||
|
|
@ -27,9 +38,7 @@ export default function TransactionDataDisplay(props: Props) {
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>Variant: {gt.subtype}</Typography>
|
<Typography>Variant: {gt.subtype}</Typography>
|
||||||
<Typography>
|
<Typography>
|
||||||
{getGrainUnit() === pond.GrainUnit.GRAIN_UNIT_WEIGHT && gt.bushelsPerTonne > 1
|
{grainDisplay(gt)}
|
||||||
? "Weight: " + gt.bushels / gt.bushelsPerTonne + " mT"
|
|
||||||
: "Bushels: " + gt.bushels}
|
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography>Message: {gt.message}</Typography>
|
<Typography>Message: {gt.message}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
||||||
|
|
@ -455,8 +455,11 @@ export default function UserSettings(props: Props) {
|
||||||
case 1:
|
case 1:
|
||||||
grainUnit = pond.GrainUnit.GRAIN_UNIT_BUSHELS;
|
grainUnit = pond.GrainUnit.GRAIN_UNIT_BUSHELS;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 3:
|
||||||
grainUnit = pond.GrainUnit.GRAIN_UNIT_WEIGHT;
|
grainUnit = pond.GrainUnit.GRAIN_UNIT_TONNE;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
grainUnit = pond.GrainUnit.GRAIN_UNIT_TON;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
grainUnit = pond.GrainUnit.GRAIN_UNIT_UNKNOWN;
|
grainUnit = pond.GrainUnit.GRAIN_UNIT_UNKNOWN;
|
||||||
|
|
@ -540,7 +543,8 @@ export default function UserSettings(props: Props) {
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
InputLabelProps={{ shrink: true }}>
|
InputLabelProps={{ shrink: true }}>
|
||||||
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_BUSHELS}>Bushels (bu)</MenuItem>
|
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_BUSHELS}>Bushels (bu)</MenuItem>
|
||||||
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_WEIGHT}>Tonnes (mT)</MenuItem>
|
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_TONNE}>Tonnes (mT)</MenuItem>
|
||||||
|
<MenuItem value={pond.GrainUnit.GRAIN_UNIT_TON}>US Tons (t)</MenuItem>
|
||||||
</TextField>
|
</TextField>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -55,13 +55,33 @@ export function setDistanceUnit(unit: pond.DistanceUnit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getGrainUnit(): pond.GrainUnit {
|
export function getGrainUnit(): pond.GrainUnit {
|
||||||
return localStorage.getItem("grainUnit") === "mT"
|
switch(localStorage.getItem("grainUnit")){
|
||||||
? pond.GrainUnit.GRAIN_UNIT_WEIGHT
|
case "mT":
|
||||||
: pond.GrainUnit.GRAIN_UNIT_BUSHELS;
|
return pond.GrainUnit.GRAIN_UNIT_TONNE
|
||||||
|
case "t":
|
||||||
|
return pond.GrainUnit.GRAIN_UNIT_TON
|
||||||
|
default:
|
||||||
|
return pond.GrainUnit.GRAIN_UNIT_BUSHELS
|
||||||
|
}
|
||||||
|
|
||||||
|
// return localStorage.getItem("grainUnit") === "mT"
|
||||||
|
// ? pond.GrainUnit.GRAIN_UNIT_WEIGHT
|
||||||
|
// : pond.GrainUnit.GRAIN_UNIT_BUSHELS;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setGrainUnit(unit: pond.GrainUnit) {
|
export function setGrainUnit(unit: pond.GrainUnit) {
|
||||||
localStorage.setItem("grainUnit", unit === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? "mT" : "bu");
|
switch(unit){
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_WEIGHT:
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TONNE:
|
||||||
|
localStorage.setItem("grainUnit", "mT")
|
||||||
|
break;
|
||||||
|
case pond.GrainUnit.GRAIN_UNIT_TON:
|
||||||
|
localStorage.setItem("grainUnit", "t")
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
localStorage.setItem("grainUnit", "bu")
|
||||||
|
}
|
||||||
|
// localStorage.setItem("grainUnit", unit === pond.GrainUnit.GRAIN_UNIT_WEIGHT ? "mT" : "bu");
|
||||||
}
|
}
|
||||||
|
|
||||||
export const distanceConversion = (val: number) => {
|
export const distanceConversion = (val: number) => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue