import { Gate } from "models/Gate"; import { Box, Card, IconButton, List, ListItem, ListItemText, Theme, Typography } from "@mui/material"; import React, { useCallback, useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { useMobile } from "hooks"; //import MaterialTable from "material-table"; //import { getTableIcons } from "common/ResponsiveTable"; import { Terminal } from "models/Terminal"; import { makeStyles } from "@mui/styles"; import ResponsiveTable, { Column } from "common/ResponsiveTable"; import AddGateFab from "./AddGateFab"; import GateSettings from "./GateSettings"; import { useGateAPI, useGlobalState } from "providers"; import { CheckCircleOutline, DoNotDisturb, ErrorOutline, HelpOutlineOutlined, Settings } from "@mui/icons-material"; import { cloneDeep } from "lodash"; import moment from "moment"; import { pond } from "protobuf-ts/pond"; import { UnitMeasurement } from "models/UnitMeasurement"; import { quack } from "protobuf-ts/quack"; import { getTemperatureUnit } from "utils"; import { teal } from "@mui/material/colors"; import { react } from "@babel/types"; interface Props { //gates: Gate[]; terminals: Terminal[]; currentTerminal?: string; //the key of the terminal for the currently selected tab useMobile: boolean; //duplicateGate: (gate: Gate) => void; } const useStyles = makeStyles((theme: Theme) => ({ gridListTile: { minHeight: "184px", height: "auto !important", width: "184px", padding: 2 }, hidden: { visibility: "hidden" }, gateCard: { marginBottom: 10, paddingLeft: 15 } })); export default function GateList(props: Props) { const {terminals, currentTerminal } = props; const [{as}] = useGlobalState(); // const history = useHistory(); const navigate = useNavigate(); const isMobile = useMobile(); const classes = useStyles(); const [{user}] = useGlobalState() const [gateDialog, setGateDialog] = useState(false); const [tablePage, setTablePage] = useState(0) const [pageSize, setPageSize] = useState(10) const [total, setTotal] = useState(0) const [terminalMap, setTerminalMap] = useState>(new Map()); const gateAPI = useGateAPI(); const [gates, setGates] = useState([]) const [selectedGate, setSelectedGate] = useState() const [search, setSearch] = useState("") const goToGate = (gate: Gate) => { let path = "/terminals/" + gate.key; navigate(path, { state: gate }) }; useEffect(() => { let map = new Map(); terminals.forEach(t => { map.set(t.key, t.name); }); setTerminalMap(map); }, [terminals]); const loadGates = useCallback(() => { let keys = undefined let types = undefined if(currentTerminal) { keys = [currentTerminal] types = ["terminal"] } gateAPI.listGates(pageSize, pageSize * tablePage, "asc", "name", search, undefined, keys, types, undefined, undefined, as).then(resp => { setGates(resp.data.gates.map(gate => Gate.create(gate))) setTotal(resp.data.total) }) },[currentTerminal, search, pageSize, tablePage, as]) useEffect(() => { loadGates() },[loadGates]) const handleChange = (event: any) => { setPageSize(event.target.value); }; const displayPCAStatus = (state: pond.PCAState) => { switch(state){ case pond.PCAState.PCA_STATE_IN_BOUNDS: return case pond.PCAState.PCA_STATE_OUT_BOUNDS: return case pond.PCAState.PCA_STATE_OFF: return default: return } } // const lastOutletReading = (reading: pond.UnitMeasurementsForComponent[]) => { // let outletDisplay = "--" // let timeSince = "No Reading Yet" // let color = "" // reading.forEach(um => { // let clone = cloneDeep(um) // let measurement = UnitMeasurement.create(clone, user) // if(measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE || measurement.type === quack.MeasurementType.MEASUREMENT_TYPE_PRESSURE){ // let nodes = measurement.values[measurement.values.length-1].values // outletDisplay = nodes[nodes.length-1].toFixed(2) + " " + measurement.unit // timeSince = moment(measurement.timestamps[measurement.timestamps.length-1]).fromNow() // color = measurement.colour // } // }) // if(isMobile){ // return ( // // {outletDisplay} // {timeSince} // // ) // } // return ( // // // Value: // {outletDisplay} // // // Time: // {timeSince} // // // ) // } // const tempDisplay = (gate: Gate) => { // let display = "--" // if(gate.status.pcaState !== pond.PCAState.PCA_STATE_OFF){ // //only display it if the final temp is between -4 and 60 C, is a valid number, and is not exactly 0 // //0 is technically a valid number but the likely hood of the calculation being exactly 0 is negligible // if (gate.status.finalTemp < 60 && gate.status.finalTemp > -40 && !isNaN(gate.status.finalTemp) && gate.status.finalTemp !== 0){ // display = getTemperatureUnit() === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT ? CtoF(gate.status.finalTemp).toFixed(2) + "°F" : gate.status.finalTemp.toFixed(2) + "°C" // } // } // return ( // // {display} // // ) // } const conditionDisplay = (gate: Gate) => { let display = "" if(gate.status.pcaState === pond.PCAState.PCA_STATE_OFF){ display = "Inactive" } else if (gate.status.pcaState === pond.PCAState.PCA_STATE_UNKNOWN){ display = "--" } else { //the pca is currently active calulate the delta temp (outlet - ambient) let ambient = cloneDeep(gate.status.lastAmbientReading) let temp = cloneDeep(gate.status.lastTempReading) if(ambient.length > 0 && temp.length > 0){ let ambientTemp: number | undefined let outletTemp: number | undefined ambient.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){ 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" } } } return ( {display} ) } // const CtoF = (celsius: number) => { // return Math.round((celsius * (9 / 5) + 32) * 100) / 100; // }; const desktopCols = (): Column[] => { return [ { title: "Gate", render: gate => ( {gate.name} ) }, { title: "Terminal", render: gate => ( {terminalMap.get(gate.terminal())} ) }, { title: "PCA Status", render: gate => { return ( {displayPCAStatus(gate.status.pcaState)} ) } }, { title: "Delta Temperature", render: gate => { return ( {conditionDisplay(gate)} )} }, //taking out these columns for now because were not sure if the customer actually wants them // { // title: "Estimated Temp", // render: gate => { // return ( // // {tempDisplay(gate)} // // ) // } // }, // { // title: "Last FLow", // render: gate => ( // // // Flow: // {gate.status.lastMassAirflow.toFixed(2)} kg/s // // // Read: // {gate.status.lastUpdate !== "" ? moment(gate.status.lastUpdate).fromNow() : "No Reading Yet"} // // // ) // }, // { // title: "Outlet Temperature", // render: gate => ( // {lastOutletReading(gate.status.lastTempReading)} // ) // }, // { // title: "Outlet Pressure", // render: gate => ( // {lastOutletReading(gate.status.lastPressureReading)} // ) // } ] } const mobileCols = (): Column[] => { return [{ title: "", render: gate => { return ( {gate.name} {displayPCAStatus(gate.status.pcaState)} { event.stopPropagation() setSelectedGate(gate) setGateDialog(true) }}> ) } }] } const gutter = (gate: Gate) => { return( Terminal: {terminalMap.get(gate.terminal()) ?? "None"} Delta Temperature: {conditionDisplay(gate)} {/* taking these out for now because we are not sure if the customer wants them */} {/* Estimated Temp: {tempDisplay(gate)} Last Flow: {gate.status.lastMassAirflow.toFixed(2)} kg/s {gate.status.lastUpdate !== "" ? moment(gate.status.lastUpdate).fromNow() : "No PCA reading yet"} Outlet Temp: {lastOutletReading(gate.status.lastTempReading)} Outlet Pressure: {lastOutletReading(gate.status.lastPressureReading)} */} ) } const gateTable = () => { return ( page={tablePage} pageSize={pageSize} columns={isMobile || props.useMobile ? mobileCols() : desktopCols()} handleRowsPerPageChange={handleChange} renderGutter={isMobile || props.useMobile ? gutter : undefined} gutterPadding={0} rows={gates} setPage={(page) => {setTablePage(page)}} total={total} onRowClick={(gate) => {goToGate(gate)}} hideKeys={isMobile || props.useMobile} setSearchText={(search) => setSearch(search)} loadMore={()=>{ let current = cloneDeep(gates) let keys = undefined let types = undefined if(currentTerminal) { keys = [currentTerminal] types = ["terminal"] } gateAPI.listGates(pageSize, current.length , "asc", "name", search, undefined, keys, types, undefined, undefined, as).then(resp => { let newGates = resp.data.gates.map(gate => Gate.create(gate)) setGates(current.concat(newGates)) }) }} /> ) }; return { if (newGate) { gates.push(newGate) } setGateDialog(false); }} terminals={terminals} /> { setGateDialog(true); }} pulse={gates.length < 1} /> {gateTable()} }