diff --git a/src/common/QrCodeGenerator.tsx b/src/common/QrCodeGenerator.tsx index 8d5ddcb..27eaff0 100644 --- a/src/common/QrCodeGenerator.tsx +++ b/src/common/QrCodeGenerator.tsx @@ -1,4 +1,4 @@ -import { Box, Button, DialogActions, DialogContent, DialogTitle } from "@mui/material"; +import { Box, Button, Checkbox, DialogActions, DialogContent, DialogTitle, Typography } from "@mui/material"; // import MaterialTable from "material-table"; import React, { useEffect, useState } from "react"; import ResponsiveDialog from "./ResponsiveDialog"; @@ -36,7 +36,7 @@ export default function(props: Props) { width: 500 }, viewerMobile: { - height: "100%", + height: 500, width: "100%" }, page: { @@ -103,12 +103,12 @@ export default function(props: Props) { selected.push(row) }else{ //remove the page/index from the map if(pageSelect){ - pageSelect.splice(pageSelect.indexOf(index)) + pageSelect.splice(pageSelect.indexOf(index), 1) } //remove the selected object from the array selected.forEach((codeKey, index) => { if(row.key === codeKey.key){ - selected.splice(index) + selected.splice(index, 1) } }) } @@ -137,35 +137,27 @@ export default function(props: Props) { total={keyList.length} setPage={(page) => {setTablePage(page)}} handleRowsPerPageChange={handleRowsPerPageChange} + loadMore={() => { + let clone: QrCodeKey[] = cloneDeep(keyList) + let current = cloneDeep(displayedRows) + let newRows = clone.splice(current.length, pageSize) + setDisplayedRows(current.concat(newRows)) + }} + renderMobile={(row, index) => { + return ( + + { + rowSelected(row, index, checked) + }} + /> + + {row.name} + + + ) + }} /> - {/* { - setSelectedKeys(data); - }} - columns={[ - { - cellStyle: { - padding: 0 - }, - title: "Name", - field: "name" - } - ]}> */} ); }; diff --git a/src/common/ResponsiveTable.tsx b/src/common/ResponsiveTable.tsx index 628836c..ee1e9dd 100644 --- a/src/common/ResponsiveTable.tsx +++ b/src/common/ResponsiveTable.tsx @@ -85,7 +85,7 @@ interface Props { multiGutter?: boolean; rowsPerPageOptions?: number[]; noDataMessage?: string; - renderMobile?: (row: T) => JSX.Element; + renderMobile?: (row: T, index: number) => JSX.Element; hideKeys?: boolean; onRowClick?: (row: T) => void; actions?: string | JSX.Element; @@ -273,9 +273,9 @@ export default function ResponsiveTable(props: Props) { return String(val).charAt(0).toUpperCase() + String(val).slice(1); } - const renderMobileRow = (row: T) => { + const renderMobileRow = (row: T, index: number) => { if (renderMobile) return ( - renderMobile(row) + renderMobile(row, index) ) if (columns) { return ( @@ -330,7 +330,7 @@ export default function ResponsiveTable(props: Props) { {rows.map((row, index) => { return ( onRowClick&&onRowClick(row)}> - {renderMobileRow(row)} + {renderMobileRow(row, index)} {renderGutter && <> diff --git a/src/contract/contractTransactionTable.tsx b/src/contract/contractTransactionTable.tsx index 4508377..ebee9ba 100644 --- a/src/contract/contractTransactionTable.tsx +++ b/src/contract/contractTransactionTable.tsx @@ -369,6 +369,12 @@ export default function ContractTransactionTable(props: Props) { total={tableData.length} handleRowsPerPageChange={(e)=>{setPageSize(e.target.value)}} setPage={(page)=>{setTablePage(page)}} + loadMore={()=>{ + let clone: Transaction[] = cloneDeep(tableData) + let current = cloneDeep(displayData) + let newRows = clone.splice(current.length, pageSize) + setDisplayData(current.concat(newRows)) + }} /> {/* 1 && data[data.length - 1].value > gate.lowerFlow() && data[data.length - 1].value < gate.upperFlow() ) { diff --git a/src/gate/GateList.tsx b/src/gate/GateList.tsx index 8f0c8bc..5c548e2 100644 --- a/src/gate/GateList.tsx +++ b/src/gate/GateList.tsx @@ -12,6 +12,7 @@ import AddGateFab from "./AddGateFab"; import GateSettings from "./GateSettings"; import { useGateAPI, useGlobalState } from "providers"; import { Settings } from "@mui/icons-material"; +import { cloneDeep } from "lodash"; interface Props { //gates: Gate[]; @@ -219,6 +220,19 @@ export default function GateList(props: Props) { 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)) + }) + }} /> ) }; diff --git a/src/maps/mapDrawers/GroupDrawer.tsx b/src/maps/mapDrawers/GroupDrawer.tsx index 4048245..e9d2768 100644 --- a/src/maps/mapDrawers/GroupDrawer.tsx +++ b/src/maps/mapDrawers/GroupDrawer.tsx @@ -3,6 +3,7 @@ import DisplayDrawer from "common/DisplayDrawer"; import ResponsiveTable from "common/ResponsiveTable"; //import DeviceCardList from "device/DeviceCardList"; import { useGroupAPI, useSnackbar } from "hooks"; +import { cloneDeep } from "lodash"; import { Group } from "models"; import moment from "moment"; import { describePower } from "pbHelpers/Power"; @@ -28,18 +29,19 @@ export default function GroupDrawer(props: Props) { const { openSnack } = useSnackbar(); const [grpDevs, setGrpDevs] = useState([]); const navigate = useNavigate(); - const [tablePage, setTablePage] = useState(0) - const [pageSize, setPageSize] = useState(10) + const loadLimit = 10 + const [groupTotal, setGroupTotal] = useState(0) const loadDevs = useCallback(() => { groupAPI - .listGroupDevices(group.id(), 100, 0, "asc", undefined, true) + .listGroupDevices(group.id(), loadLimit, 0, "asc", undefined, true) .then(resp => { const groupDevices: pond.ComprehensiveDevice[] = or( resp.data.comprehensiveDevices, [] ).map(d => pond.ComprehensiveDevice.fromObject(d)); setGrpDevs(groupDevices); + setGroupTotal(resp.data.total) }) .catch(err => { openSnack("Failed to get devices for group"); @@ -174,21 +176,37 @@ export default function GroupDrawer(props: Props) { } const drawerBody = () => { - // TODO: will need to update the rows and setPage functions if we decide to have the table only show a number of items matching its page size rether than everything passed in return ( - page={tablePage} - pageSize={pageSize} + page={0} + pageSize={loadLimit} onRowClick={toDevice} - handleRowsPerPageChange={()=>{}} - setPage={()=>{}} - total={0} + total={groupTotal} rows={grpDevs} renderMobile={mobile} renderGutter={gutter} gutterPadding={0} mobileView + loadMore={() => { + let current = cloneDeep(grpDevs) + groupAPI + .listGroupDevices(group.id(), loadLimit, current.length, "asc", undefined, true) + .then(resp => { + let newDevices: pond.ComprehensiveDevice[] = or( + resp.data.comprehensiveDevices, + [] + ).map(d => pond.ComprehensiveDevice.fromObject(d)); + setGrpDevs(current.concat(newDevices)); + setGroupTotal(resp.data.total) + }) + .catch(err => { + openSnack("Failed to get devices for group"); + }); + }} + //these two function are uneccessary as this will always be in a list as mobile view + handleRowsPerPageChange={()=>{}} + setPage={()=>{}} /> ) diff --git a/src/objectHeater/ObjectHeaterCard.tsx b/src/objectHeater/ObjectHeaterCard.tsx index 4255b1f..651ae7c 100644 --- a/src/objectHeater/ObjectHeaterCard.tsx +++ b/src/objectHeater/ObjectHeaterCard.tsx @@ -371,7 +371,7 @@ export default function ObjectHeaterCard(props: Props) { }else { return ( - + { setOpenQrGenerator(true); + setBinMenuAnchorEl(null) }}> Generate QR Codes diff --git a/src/pages/Firmware.tsx b/src/pages/Firmware.tsx index ecd628a..b3a7c58 100644 --- a/src/pages/Firmware.tsx +++ b/src/pages/Firmware.tsx @@ -39,6 +39,7 @@ import { useGlobalState } from "providers"; import { useCallback, useEffect, useState } from "react"; import { downloadFile } from "utils/download"; import { or } from "utils/types"; +import { cloneDeep } from "lodash"; const useStyles = makeStyles((theme: Theme) => { const themeType = useThemeType() @@ -463,6 +464,22 @@ export default function Firmware() { columns={columns(width === "xs" || width === "sm")} setPage={(page)=>{setTablePage(page)}} handleRowsPerPageChange={(e)=>{setPageSize(e.target.value)}} + loadMore={() => { + let current = cloneDeep(tableData) + firmwareAPI.listFirmware(pageSize, current.length, "desc", "version", searchText) + .then((response) => { + let newRows: FirmwareModel[] = or(response.data.firmware, []).map( + (firmwareData: any) => { + return FirmwareModel.create(pond.Firmware.fromObject(firmwareData)); + } + ); + setTableData(current.concat(newRows)) + }) + .catch(() => { + //failed to load + error("Failed to load more firmware versions") + }); + }} /> { return ({ @@ -241,6 +242,36 @@ export default function GroupPage() { onRowClick={toDevice} setSearchText={setSearch} isLoading={loadingDevices} + loadMore={()=>{ + let current = cloneDeep(devices) + setLoadingDevices(true) + deviceAPI.list( + limit, + current.length, + order, + orderBy, + search, + undefined, + undefined, + undefined, + undefined, + undefined, + undefined, + getKeys(), + getTypes(), + undefined, + undefined, + as + ).then(resp => { + let newDevices: Device[] = []; + resp.data.devices.forEach(device => { + newDevices.push(Device.create(device)) + }) + setDevices(current.concat(newDevices)) + }).finally(() => { + setLoadingDevices(false) + }) + }} /> ) diff --git a/src/pages/Groups.tsx b/src/pages/Groups.tsx index 0d06947..acc6673 100644 --- a/src/pages/Groups.tsx +++ b/src/pages/Groups.tsx @@ -13,6 +13,7 @@ import { or } from "utils/types"; import PageContainer from "./PageContainer"; import GroupSettings from "group/GroupSettings"; import { green } from "@mui/material/colors"; +import { cloneDeep } from "lodash"; const useStyles = makeStyles((theme: Theme) => { const isMobile = useMobile() @@ -163,6 +164,15 @@ export default function GroupsPage() { isLoading={loading} setSearchText={setSearch} onRowClick={handleRowClick} + loadMore={()=>{ + let current = cloneDeep(groups) + setLoading(true) + groupAPI.listGroups(limit, current.length, order, orderBy, search).then(resp => { + setGroups(or(current.concat(resp.data.groups), current)) + }).finally(() => { + setLoading(false) + }) + }} /> {setTablePage(page)}} handleRowsPerPageChange={handleChange} onRowClick={goToHeater} - /> - ) - }; - - const mobileList = () => { - return ( - - {heaters.map(h => ( - { + let current = cloneDeep(heaters) + objectHeaterAPI + .listObjectHeatersPageData(pageSize, current.length, undefined, undefined, searchText, as) + .then(resp => { + setHeaters(heaters.concat(resp.data.heaterData)); + }); + }} + renderMobile={(row)=>{ + return ( + { setHeaterToLink(heater); setOpenLinkDrawer(true); @@ -131,9 +134,10 @@ export default function Heaters() { setDevices(d); }} /> - ))} - - ); + ) + }} + /> + ) }; return ( @@ -180,7 +184,7 @@ export default function Heaters() { }} pulse={heaters.length < 1} /> - {isMobile ? mobileList() : desktopTable()} + {desktopTable()} ); } diff --git a/src/pages/Mines.tsx b/src/pages/Mines.tsx index 5e73bae..fcaeac6 100644 --- a/src/pages/Mines.tsx +++ b/src/pages/Mines.tsx @@ -14,6 +14,7 @@ import ResponsiveTable, { Column } from "common/ResponsiveTable"; import { useNavigate } from "react-router-dom"; import { or } from "utils"; import { useGlobalState } from "providers"; +import { cloneDeep } from "lodash"; interface MineRow { mine: pond.Mine; @@ -110,6 +111,24 @@ export default function Mines() { hideKeys isLoading={isLoading} onRowClick={onRowClick} + loadMore={()=>{ + let current = cloneDeep(mineTableData) + setIsLoading(true); + mineAPI + .listMines(pageSize, current.length, "desc", undefined, searchValue, false, as) + .then(resp => { + let newMines: MineRow[] = []; + resp.data.mines.forEach(mine => { + newMines.push({ + mine: mine + }); + }); + setMineTableData(current.concat(newMines)); + }) + .finally(() => { + setIsLoading(false); + }); + }} /> diff --git a/src/pages/Sites.tsx b/src/pages/Sites.tsx index e749643..91ac28b 100644 --- a/src/pages/Sites.tsx +++ b/src/pages/Sites.tsx @@ -1,4 +1,4 @@ -import { Avatar, Box, Card, Grid2 as Grid, Switch, Tab, Tabs, Tooltip, Typography } from "@mui/material"; +import { Avatar, Box, Button, Card, Grid2 as Grid, Switch, Tab, Tabs, Tooltip, Typography } from "@mui/material"; import { Group } from "@mui/icons-material"; //import MaterialTable from "material-table"; import { Site, User } from "models"; @@ -12,6 +12,7 @@ import { useMobile } from "hooks"; import JobsiteIcon from "products/Construction/JobSiteIcon"; import ResponsiveTable, { Column } from "common/ResponsiveTable"; import { useNavigate } from "react-router-dom"; +import { cloneDeep } from "lodash"; interface SiteWithData { site: Site; @@ -46,7 +47,7 @@ export default function Sites() { .listSitesPageData(pageSize, tablePage * pageSize, "asc", "siteName", undefined, as) .then(resp => { setTotal(resp.data.total); - buildTableData(resp.data.sites); + setSites(buildTableData(resp.data.sites)); }) .finally(() => { setLoading(false); @@ -71,7 +72,7 @@ export default function Sites() { data.push(newTableData); } }); - setSites([...data]); + return data; }; useEffect(() => { @@ -186,6 +187,19 @@ export default function Sites() { rows={sites} handleRowsPerPageChange={handleTablePage} onRowClick={goToSite} + loadMore={()=>{ + let current = cloneDeep(sites) + setLoading(true); + siteAPI + .listSitesPageData(pageSize, current.length, "asc", "siteName", undefined, as) + .then(resp => { + let newData = buildTableData(resp.data.sites); + setSites(current.concat(newData)) + }) + .finally(() => { + setLoading(false); + }); + }} /> ) }; @@ -208,6 +222,20 @@ export default function Sites() { setCurrentTab(newValue); }; + const loadMore = () => { + let current = cloneDeep(sites) + setLoading(true); + siteAPI + .listSitesPageData(pageSize, current.length, "asc", "siteName", undefined, as) + .then(resp => { + let newData = buildTableData(resp.data.sites); + setSites(current.concat(newData)) + }) + .finally(() => { + setLoading(false); + }); + } + const mobileView = () => { return ( @@ -297,6 +325,9 @@ export default function Sites() { return siteCards; })} + {sites.length < total && + + } ); };