put the first components into the field page
This commit is contained in:
parent
1588905a04
commit
1fbc817abe
4 changed files with 159 additions and 5 deletions
|
|
@ -63,6 +63,8 @@ export default function FieldActions(props: Props) {
|
||||||
removeSelf: false
|
removeSelf: false
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(permissions)
|
||||||
|
|
||||||
const groupMenu = () => {
|
const groupMenu = () => {
|
||||||
const canShare = permissions.includes(pond.Permission.PERMISSION_SHARE);
|
const canShare = permissions.includes(pond.Permission.PERMISSION_SHARE);
|
||||||
const canManageUsers = permissions.includes(pond.Permission.PERMISSION_USERS);
|
const canManageUsers = permissions.includes(pond.Permission.PERMISSION_USERS);
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,11 @@ import ResponsiveTable, { Column } from "common/ResponsiveTable";
|
||||||
import FieldMinimap from "./Fieldminimap";
|
import FieldMinimap from "./Fieldminimap";
|
||||||
import FieldActions from "./FieldActions";
|
import FieldActions from "./FieldActions";
|
||||||
import FieldSettings from "./FieldSettings";
|
import FieldSettings from "./FieldSettings";
|
||||||
import { ExpandMore, Settings } from "@mui/icons-material";
|
import { ArrowForward, ExpandMore, Settings } from "@mui/icons-material";
|
||||||
import { cloneDeep } from "lodash";
|
import { cloneDeep } from "lodash";
|
||||||
import ShareAllFields from "./ShareAllFields";
|
import ShareAllFields from "./ShareAllFields";
|
||||||
|
import EventBlocker from "common/EventBlocker";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
interface TabPanelProps {
|
interface TabPanelProps {
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
|
@ -57,6 +59,7 @@ export default function FieldList() {
|
||||||
const [selectedField, setSelectedField] = useState<Field>()
|
const [selectedField, setSelectedField] = useState<Field>()
|
||||||
const [openFieldSettings, setOpenFieldSettings] = useState(false)
|
const [openFieldSettings, setOpenFieldSettings] = useState(false)
|
||||||
const [shareOpen, setShareOpen] = useState(false)
|
const [shareOpen, setShareOpen] = useState(false)
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||||
setTabValue(newValue);
|
setTabValue(newValue);
|
||||||
|
|
@ -117,16 +120,22 @@ export default function FieldList() {
|
||||||
return totalAcres;
|
return totalAcres;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const goTo = (field: Field) => {
|
||||||
|
let path = field.key();
|
||||||
|
navigate(path, { state: {field: field, permissions: field.permissions} });
|
||||||
|
}
|
||||||
|
|
||||||
const fieldActions = (field: Field) => {
|
const fieldActions = (field: Field) => {
|
||||||
return (
|
return (
|
||||||
<Box>
|
<EventBlocker>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedField(field)
|
setSelectedField(field)
|
||||||
setOpenFieldSettings(true)
|
setOpenFieldSettings(true)
|
||||||
}}><Settings /></IconButton>
|
}}><Settings /></IconButton>
|
||||||
<FieldActions field={field} permissions={field.permissions} refreshCallback={()=>{}}/>
|
<FieldActions field={field} permissions={field.permissions} refreshCallback={()=>{}}/>
|
||||||
</Box>
|
{isMobile && <IconButton onClick={() => {goTo(field)}}><ArrowForward /></IconButton>}
|
||||||
|
</EventBlocker>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,6 +180,9 @@ const columns: Column<Field>[] = [
|
||||||
<ResponsiveTable<Field>
|
<ResponsiveTable<Field>
|
||||||
columns={columns}
|
columns={columns}
|
||||||
rows={fields}
|
rows={fields}
|
||||||
|
onRowClick={(row) => {
|
||||||
|
!isMobile && goTo(row)
|
||||||
|
}}
|
||||||
setPage={(newPage)=>{
|
setPage={(newPage)=>{
|
||||||
setPage(newPage)
|
setPage(newPage)
|
||||||
}}
|
}}
|
||||||
|
|
@ -224,7 +236,7 @@ const columns: Column<Field>[] = [
|
||||||
<Grid2 alignItems="center" width="100%" container direction={"row"} justifyContent="space-between" wrap="nowrap">
|
<Grid2 alignItems="center" width="100%" container direction={"row"} justifyContent="space-between" wrap="nowrap">
|
||||||
<Grid2 size={6}>
|
<Grid2 size={6}>
|
||||||
<Box height={150} width="100%">
|
<Box height={150} width="100%">
|
||||||
<FieldMinimap field={row} />
|
<FieldMinimap field={row} borderSpacing={0.001} squared />
|
||||||
</Box>
|
</Box>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
<Grid2 size={6}>
|
<Grid2 size={6}>
|
||||||
|
|
@ -232,6 +244,7 @@ const columns: Column<Field>[] = [
|
||||||
<Typography textAlign="center">{row.grainName()}</Typography>
|
<Typography textAlign="center">{row.grainName()}</Typography>
|
||||||
<Typography textAlign="center">{row.acres()} Acres</Typography>
|
<Typography textAlign="center">{row.acres()} Acres</Typography>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
<Button variant="contained" color="primary">Go</Button>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
</Grid2>
|
</Grid2>
|
||||||
</AccordionDetails>
|
</AccordionDetails>
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ const Contract = lazy(() => import("pages/Contract"));
|
||||||
const JohnDeere = lazy(() => import("pages/JohnDeere"));
|
const JohnDeere = lazy(() => import("pages/JohnDeere"));
|
||||||
const CNHi = lazy(() => import("pages/CNHi"));
|
const CNHi = lazy(() => import("pages/CNHi"));
|
||||||
const LibraCart = lazy(() => import("pages/LibraCart"));
|
const LibraCart = lazy(() => import("pages/LibraCart"));
|
||||||
|
const FieldPage = lazy(()=>import("pages/Field"));
|
||||||
|
|
||||||
export const appendToUrl = (appendage: number | string) => {
|
export const appendToUrl = (appendage: number | string) => {
|
||||||
const basePath = location.pathname.replace(/\/$/, "");
|
const basePath = location.pathname.replace(/\/$/, "");
|
||||||
|
|
@ -70,6 +71,7 @@ export default function Router() {
|
||||||
<Route path="terminals/*" element={<TerminalGatesRoute />} />
|
<Route path="terminals/*" element={<TerminalGatesRoute />} />
|
||||||
<Route path="jobsites/*" element={<JobsitesRoute />} />
|
<Route path="jobsites/*" element={<JobsitesRoute />} />
|
||||||
<Route path="heaters/*" element={<ObjectHeatersRoute />} />
|
<Route path="heaters/*" element={<ObjectHeatersRoute />} />
|
||||||
|
<Route path="fields/*" element={<FieldsRoute />} />
|
||||||
</Routes>
|
</Routes>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -284,6 +286,21 @@ export default function Router() {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const FieldsRoute = () => {
|
||||||
|
return (
|
||||||
|
<Routes>
|
||||||
|
<Route
|
||||||
|
path=""
|
||||||
|
element={<Fields />}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path="/:fieldID"
|
||||||
|
element={<FieldPage />}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isLoading) return null;
|
if (isLoading) return null;
|
||||||
// if (!isAuthenticated) {
|
// if (!isAuthenticated) {
|
||||||
// loginWithRedirect()
|
// loginWithRedirect()
|
||||||
|
|
@ -325,7 +342,6 @@ export default function Router() {
|
||||||
{user.hasFeature("admin") &&
|
{user.hasFeature("admin") &&
|
||||||
<Route path="logs" element={<Logs />} />
|
<Route path="logs" element={<Logs />} />
|
||||||
}
|
}
|
||||||
<Route path="fields" element={<Fields />} />
|
|
||||||
<Route path="marketplace" element={<Marketplace />} />
|
<Route path="marketplace" element={<Marketplace />} />
|
||||||
{user.hasFeature("admin") && (
|
{user.hasFeature("admin") && (
|
||||||
<Route path="firmware" element={<Firmware />} />
|
<Route path="firmware" element={<Firmware />} />
|
||||||
|
|
|
||||||
123
src/pages/Field.tsx
Normal file
123
src/pages/Field.tsx
Normal file
|
|
@ -0,0 +1,123 @@
|
||||||
|
import { Field, HarvestPlan } from "models";
|
||||||
|
import { useGlobalState } from "providers";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
|
import PageContainer from "./PageContainer";
|
||||||
|
import { useMobile } from "hooks";
|
||||||
|
import { Box, Grid2, IconButton } from "@mui/material";
|
||||||
|
import FieldActions from "field/FieldActions";
|
||||||
|
import { Settings } from "@mui/icons-material";
|
||||||
|
import { pond } from "protobuf-ts/pond";
|
||||||
|
import FieldMinimap from "field/Fieldminimap";
|
||||||
|
import Weather from "weather/weather";
|
||||||
|
import TaskViewer from "tasks/TaskViewer";
|
||||||
|
import HarvestPlanDisplay from "harvestPlan/HarvestPlanDisplay";
|
||||||
|
|
||||||
|
export default function FieldPage() {
|
||||||
|
const { state } = useLocation();
|
||||||
|
//const [{ as }] = useGlobalState()
|
||||||
|
const [field, setField] = useState<Field>(state?.field ? Field.create(state.field) : Field.create())
|
||||||
|
const [permissions, setPermissions] = useState<pond.Permission[]>(state?.permissions ? state.permissions : [])
|
||||||
|
const isMobile = useMobile()
|
||||||
|
const [openFieldSettings, setOpenFieldSettings] = useState(false)
|
||||||
|
const [planLoading, setPlanLoading] = useState(false)
|
||||||
|
const [hPlan, setHPlan] = useState<HarvestPlan>(HarvestPlan.create());
|
||||||
|
|
||||||
|
const loadField = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(state.field){
|
||||||
|
let field = Field.create(state.field)
|
||||||
|
setField(field)
|
||||||
|
setPermissions(state.permissions)
|
||||||
|
}
|
||||||
|
},[state.field])
|
||||||
|
|
||||||
|
const fieldActions = () => {
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<IconButton
|
||||||
|
onClick={() => {
|
||||||
|
setOpenFieldSettings(true)
|
||||||
|
}}><Settings /></IconButton>
|
||||||
|
<FieldActions field={field} permissions={permissions} refreshCallback={()=>{}}/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = () => {
|
||||||
|
return (
|
||||||
|
<Box height={550}>
|
||||||
|
<FieldMinimap field={field} borderSpacing={0.001} squared/>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const weather = () => {
|
||||||
|
return (<Weather longitude={field.center().longitude} latitude={field.center().latitude} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
const harvestPlans = () => {
|
||||||
|
console.log(permissions)
|
||||||
|
return (
|
||||||
|
<HarvestPlanDisplay
|
||||||
|
plan={hPlan}
|
||||||
|
permissions={permissions}
|
||||||
|
planField={field}
|
||||||
|
loading={planLoading}
|
||||||
|
fieldList={[field]}
|
||||||
|
changePlan={updatedPlan => {
|
||||||
|
if (updatedPlan) {
|
||||||
|
setHPlan(updatedPlan);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>)
|
||||||
|
}
|
||||||
|
|
||||||
|
const tasks = () => {
|
||||||
|
let taskLoadKeys: string[] = [];
|
||||||
|
if (!planLoading) {
|
||||||
|
field.key() !== "" && taskLoadKeys.push(field.key());
|
||||||
|
//hPlan.key() !== "" && taskLoadKeys.push(hPlan.key());
|
||||||
|
}
|
||||||
|
return (<TaskViewer drawerView objectKey={field.key()} loadKeys={taskLoadKeys} />)
|
||||||
|
}
|
||||||
|
|
||||||
|
const desktopView = () => {
|
||||||
|
return (
|
||||||
|
<Grid2 container>
|
||||||
|
<Grid2 size={4}>
|
||||||
|
{map()}
|
||||||
|
</Grid2>
|
||||||
|
<Grid2 size={3}>
|
||||||
|
{weather()}
|
||||||
|
</Grid2>
|
||||||
|
<Grid2 size={5}>
|
||||||
|
{tasks()}
|
||||||
|
</Grid2>
|
||||||
|
<Grid2 size={12}>
|
||||||
|
{harvestPlans()}
|
||||||
|
</Grid2>
|
||||||
|
</Grid2>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mobileView = () => {
|
||||||
|
return (
|
||||||
|
<Box>Mobile will just be the drawer view</Box>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldSettings = () => {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContainer>
|
||||||
|
{fieldActions()}
|
||||||
|
{isMobile ? mobileView() : desktopView()}
|
||||||
|
</PageContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue