added bins page (mostly stubbed)
This commit is contained in:
parent
044b2ad8f4
commit
3bab272744
6 changed files with 1694 additions and 5 deletions
238
src/models/Bin.ts
Normal file
238
src/models/Bin.ts
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
import GrainDescriber from "grain/GrainDescriber";
|
||||
import { cloneDeep } from "lodash";
|
||||
// import { MarkerData } from "Maps/mapMarkers/Markers";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { stringToMaterialColour } from "utils/strings";
|
||||
import { or } from "utils/types";
|
||||
|
||||
export class Bin {
|
||||
public settings: pond.BinSettings = pond.BinSettings.create();
|
||||
public status: pond.BinStatus = pond.BinStatus.create();
|
||||
public permissions: pond.Permission[] = [];
|
||||
|
||||
public static create(pb?: pond.Bin): Bin {
|
||||
let my = new Bin();
|
||||
if (pb) {
|
||||
my.settings = pond.BinSettings.fromObject(cloneDeep(or(pb.settings, {})));
|
||||
my.status = pond.BinStatus.fromObject(cloneDeep(or(pb.status, {})));
|
||||
my.permissions = pb.binPermissions;
|
||||
}
|
||||
return my;
|
||||
}
|
||||
|
||||
public static clone(other?: Bin): Bin {
|
||||
if (other) {
|
||||
return Bin.create(
|
||||
pond.Bin.fromObject({
|
||||
settings: cloneDeep(other.settings),
|
||||
status: cloneDeep(other.status),
|
||||
binPermissions: cloneDeep(other.permissions)
|
||||
})
|
||||
);
|
||||
}
|
||||
return Bin.create();
|
||||
}
|
||||
|
||||
public static any(data: any): Bin {
|
||||
return Bin.create(pond.Bin.fromObject(cloneDeep(data)));
|
||||
}
|
||||
|
||||
public setLocation(long: number, lat: number): void {
|
||||
this.settings.location = pond.Location.create();
|
||||
this.settings.location.longitude = long;
|
||||
this.settings.location.latitude = lat;
|
||||
}
|
||||
|
||||
public removeLocation(): void {
|
||||
this.settings.location = null;
|
||||
}
|
||||
|
||||
public binShape(): pond.BinShape | undefined {
|
||||
return this.settings.specs?.shape;
|
||||
}
|
||||
|
||||
public key(): string {
|
||||
return this.settings.key;
|
||||
}
|
||||
|
||||
public name(): string {
|
||||
return this.settings.name !== "" ? this.settings.name : "Bin " + this.key();
|
||||
}
|
||||
|
||||
public grain(): pond.Grain {
|
||||
let g: pond.Grain = pond.Grain.GRAIN_NONE;
|
||||
if (this.settings.inventory) {
|
||||
g = this.settings.inventory.grainType;
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
public getLocation(): pond.Location | null | undefined {
|
||||
return this.settings.location;
|
||||
}
|
||||
|
||||
public binMapped(): boolean {
|
||||
let location = this.getLocation();
|
||||
return (
|
||||
location !== undefined &&
|
||||
location !== null &&
|
||||
location.latitude !== 0 &&
|
||||
location.longitude !== 0
|
||||
);
|
||||
}
|
||||
|
||||
public storage(): pond.BinStorage {
|
||||
return !this.settings.storage
|
||||
? pond.BinStorage.BIN_STORAGE_SUPPORTED_GRAIN
|
||||
: this.settings.storage;
|
||||
}
|
||||
|
||||
public customType(): string {
|
||||
let c = "";
|
||||
if (this.settings.inventory) {
|
||||
c = this.settings.inventory.customTypeName;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
public empty(): boolean {
|
||||
return this.settings.inventory?.empty || this.settings.inventory?.grainBushels === 0;
|
||||
}
|
||||
|
||||
public objectType(): pond.ObjectType {
|
||||
return pond.ObjectType.OBJECT_TYPE_BIN;
|
||||
}
|
||||
|
||||
public objectTypeString(): string {
|
||||
return "Bin";
|
||||
}
|
||||
|
||||
public subtype(): string {
|
||||
return this.settings.inventory?.grainSubtype ?? "";
|
||||
}
|
||||
|
||||
public grainColour(): string {
|
||||
let colour = "";
|
||||
if (this.settings.inventory) {
|
||||
if (this.grain() === pond.Grain.GRAIN_CUSTOM) {
|
||||
if (this.customType() !== "") {
|
||||
colour = stringToMaterialColour(this.customType());
|
||||
}
|
||||
} else {
|
||||
colour = GrainDescriber(this.grain()).colour;
|
||||
}
|
||||
}
|
||||
return colour;
|
||||
}
|
||||
|
||||
public fillPercent(): number {
|
||||
let fill = 0;
|
||||
if (this.settings.inventory && this.settings.specs) {
|
||||
fill = Math.round(
|
||||
(this.settings.inventory.grainBushels / this.settings.specs.bushelCapacity) * 100
|
||||
);
|
||||
}
|
||||
return fill;
|
||||
}
|
||||
|
||||
public grainName(): string {
|
||||
if (this.grain() !== pond.Grain.GRAIN_INVALID) {
|
||||
if (this.grain() === pond.Grain.GRAIN_CUSTOM) {
|
||||
return this.customType();
|
||||
} else {
|
||||
return GrainDescriber(this.grain()).name;
|
||||
}
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public binFillCap(): string {
|
||||
let fillCap = "";
|
||||
if (this.settings.specs && this.settings.inventory) {
|
||||
fillCap = this.settings.inventory.grainBushels + "/" + this.settings.specs.bushelCapacity;
|
||||
}
|
||||
return fillCap;
|
||||
}
|
||||
|
||||
public location(): pond.Location | undefined | null {
|
||||
let loc = this.settings.location;
|
||||
return loc;
|
||||
}
|
||||
|
||||
public fanID(): number {
|
||||
return this.settings.fanId;
|
||||
}
|
||||
|
||||
public supportedGrain(): boolean {
|
||||
let s = false;
|
||||
if (
|
||||
this.grain() !== pond.Grain.GRAIN_NONE &&
|
||||
this.grain() !== pond.Grain.GRAIN_CUSTOM &&
|
||||
this.grain() !== pond.Grain.GRAIN_INVALID
|
||||
) {
|
||||
s = true;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// public getMarkerData(
|
||||
// clickFunc?: (event: React.PointerEvent<HTMLElement>, index: number, isMobile: boolean) => void,
|
||||
// updateFunc?: (location: pond.Location) => void
|
||||
// ): MarkerData {
|
||||
// let m: MarkerData = {
|
||||
// centered: true,
|
||||
// longitude: this.location()?.longitude ?? 0,
|
||||
// latitude: this.location()?.latitude ?? 0,
|
||||
// title: this.name(),
|
||||
// colour: this.grainColour(),
|
||||
// visibleLevels: { min: 17 },
|
||||
// graphPercent: this.fillPercent(),
|
||||
// customSize: this.settings.theme?.height,
|
||||
// details: [this.name() + ", " + this.binFillCap()],
|
||||
// clickFunc: clickFunc,
|
||||
// updateFunc: updateFunc
|
||||
// };
|
||||
// return m;
|
||||
// }
|
||||
|
||||
/**
|
||||
* returns the bushels per tonne set in the bins settings, if not set will return 1
|
||||
* @returns 1 or bushels per tonne
|
||||
*/
|
||||
public bushelsPerTonne(): number {
|
||||
//trying to avoid a divide by 0 error by only returning a value greater than 0
|
||||
//since to get the weight you divide the current bushels by the bushels per tonne
|
||||
let bpt = 1;
|
||||
if (this.settings.inventory) {
|
||||
if (this.settings.inventory.bushelsPerTonne > 0) {
|
||||
bpt = this.settings.inventory.bushelsPerTonne;
|
||||
}
|
||||
}
|
||||
return bpt;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the weight in tonnes for the grain inventory provided the bushels per tonne is set
|
||||
* if it is not set it will divide by 1 effectively returning the bushels
|
||||
* @returns grain weight
|
||||
*/
|
||||
public grainTonnes(): number {
|
||||
let weight = 0;
|
||||
if (this.settings.inventory) {
|
||||
weight = this.settings.inventory.grainBushels / this.bushelsPerTonne();
|
||||
}
|
||||
return Math.round(weight * 100) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the enum value for the inventory control in the bins inventory
|
||||
*/
|
||||
public inventoryControl(): pond.BinInventoryControl {
|
||||
let c = pond.BinInventoryControl.BIN_INVENTORY_CONTROL_UNKNOWN;
|
||||
if (this.settings.inventory) {
|
||||
return this.settings.inventory.inventoryControl;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
export * from "./Backpack";
|
||||
// export * from "./Bin";
|
||||
export * from "./Bin";
|
||||
// export * from "./BinYard";
|
||||
export * from "./Component";
|
||||
export * from "./Device";
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import GroupsPage from "pages/Groups";
|
|||
import GroupPage from "pages/Group";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import DeviceComponent from "pages/DeviceComponent";
|
||||
import Bins from "pages/Bins";
|
||||
|
||||
const DeviceHistory = lazy(() => import("pages/DeviceHistory"));
|
||||
|
||||
|
|
@ -37,6 +38,7 @@ export default function Router(props: Props) {
|
|||
<Route path="teams/*" element={<TeamsRoute/>} />
|
||||
<Route path="devices/*" element={<DevicesRoute/>} />
|
||||
<Route path="groups/*" element={<GroupsRoute/>} />
|
||||
<Route path="bins/*" element={<BinsRoute/>} />
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
|
|
@ -90,6 +92,37 @@ export default function Router(props: Props) {
|
|||
);
|
||||
};
|
||||
|
||||
const BinsRoute = () => {
|
||||
return (
|
||||
<div>
|
||||
<Routes>
|
||||
<Route
|
||||
key="Bins page route"
|
||||
path="" // "/settings/basic"
|
||||
element={<Bins key={"Bins page"} />}
|
||||
/>
|
||||
{/* <Route
|
||||
path="/:binID" // "/settings/basic"
|
||||
element={<Bin />}
|
||||
/>
|
||||
<Route
|
||||
path="/:deviceID/components/:componentID" // "/settings/basic"
|
||||
element={<DeviceComponent />}
|
||||
/>
|
||||
<Route
|
||||
path="/:deviceID/history" // "/settings/basic"
|
||||
element={<DeviceHistory />}
|
||||
/>
|
||||
<Route
|
||||
path="/:deviceID/*" // "/settings/basic"
|
||||
element={<RelativeRoutes />}
|
||||
/> */}
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const GroupsRoute = () => {
|
||||
return (
|
||||
<div>
|
||||
|
|
@ -154,9 +187,10 @@ export default function Router(props: Props) {
|
|||
<Route path="/callback" element={<Navigate to="/" />} />
|
||||
{/* <Route path="/team/:teamID" element={<Navigate to="/teams/:teamID" />} /> */}
|
||||
{/* <Route path="/device/:deviceID" element={<Navigate to="/devices/:devicesID" />} /> */}
|
||||
<Route path="" element={<Navigate to="/devices" />} />
|
||||
|
||||
{/* Page routes */}
|
||||
<Route index element={<Typography>Hello!</Typography>} />
|
||||
{/* <Route index element={<Typography>Hello!</Typography>} /> */}
|
||||
<Route path="users" element={<Users/>} />
|
||||
<Route path="/logout" element={<Logout />} />
|
||||
{/*
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { useWidth } from "../hooks/useWidth";
|
|||
import { makeStyles } from "@mui/styles";
|
||||
import BindaptIcon from "../products/Bindapt/BindaptIcon";
|
||||
import { Link, useLocation } from "react-router-dom";
|
||||
import BinsIcon from "products/Bindapt/BinsIcon";
|
||||
|
||||
const drawerWidth = 230;
|
||||
|
||||
|
|
@ -103,6 +104,20 @@ export default function SideNavigator(props: Props) {
|
|||
|
||||
return (
|
||||
<List className={classes.list} component="nav">
|
||||
<Tooltip title="Bins" placement="right">
|
||||
<ListItemButton
|
||||
id="tour-dashboard"
|
||||
component={Link}
|
||||
to="/bins"
|
||||
onClick={onClose}
|
||||
classes={getClasses("/bin")}
|
||||
>
|
||||
<ListItemIcon>
|
||||
<BinsIcon />
|
||||
</ListItemIcon>
|
||||
{open && <ListItemText primary="Devices" />}
|
||||
</ListItemButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Devices" placement="right">
|
||||
<ListItemButton
|
||||
id="tour-dashboard"
|
||||
|
|
|
|||
1400
src/pages/Bins.tsx
Normal file
1400
src/pages/Bins.tsx
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -5,7 +5,7 @@ import { makeStyles } from "@mui/styles";
|
|||
import ResponsiveTable, { Column } from "common/ResponsiveTable";
|
||||
import ProvisionDevice from "device/ProvisionDevice";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useDeviceAPI, useGroupAPI } from "providers";
|
||||
import { useDeviceAPI, useGlobalState, useGroupAPI } from "providers";
|
||||
import { useEffect, useState } from "react";
|
||||
import PageContainer from "./PageContainer";
|
||||
import { useMobile } from "hooks";
|
||||
|
|
@ -112,6 +112,8 @@ export default function Devices() {
|
|||
|
||||
const [fieldContains, setFieldContains] = useState<Map<string, string>>(new Map<string, string>())
|
||||
|
||||
const [{ as }] = useGlobalState()
|
||||
|
||||
const updateGroups = (newGroups: Group[]) => {
|
||||
setGroups(newGroups);
|
||||
};
|
||||
|
|
@ -226,11 +228,11 @@ export default function Devices() {
|
|||
|
||||
useEffect(() => {
|
||||
loadDevices()
|
||||
}, [limit, page, order, orderBy, fieldContains, search, tab])
|
||||
}, [limit, page, order, orderBy, fieldContains, search, tab, as])
|
||||
|
||||
useEffect(() => {
|
||||
loadGroups()
|
||||
}, [groupLimit, groupPage, orderGroup, orderGroupBy, searchGroup])
|
||||
}, [groupLimit, groupPage, orderGroup, orderGroupBy, searchGroup, as])
|
||||
|
||||
const handleChange = (event: any) => {
|
||||
setLimit(event.target.value);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue