ag visual farm added to the dev branch field related stuff not imported yet, and the geocoder has some bugs with the new version
This commit is contained in:
parent
b4da0d6859
commit
022925d7d7
41 changed files with 8895 additions and 79 deletions
326
src/maps/mapDrawers/FieldDrawer.tsx
Normal file
326
src/maps/mapDrawers/FieldDrawer.tsx
Normal file
|
|
@ -0,0 +1,326 @@
|
|||
import {
|
||||
Box,
|
||||
Divider,
|
||||
Drawer,
|
||||
Grid2 as Grid,
|
||||
IconButton,
|
||||
Tab,
|
||||
Tabs,
|
||||
Theme,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
import { Notes } from "@mui/icons-material";
|
||||
import DisplayDrawer from "common/DisplayDrawer";
|
||||
//import HarvestPlanDisplay from "harvestPlan/HarvestPlanDisplay";
|
||||
import { Field, fieldScope, /*HarvestPlan,*/ teamScope } from "models";
|
||||
import React, { useEffect, useState } from "react";
|
||||
//import TaskViewer from "tasks/TaskViewer";
|
||||
import Weather from "weather/weather";
|
||||
import { getThemeType } from "theme";
|
||||
import GrainDescriber from "grain/GrainDescriber";
|
||||
import Chat from "chat/Chat";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useMobile } from "hooks";
|
||||
import { useGlobalState, /*useHarvestPlanAPI,*/ useUserAPI } from "providers";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
//import FieldActions from "field/FieldActions";
|
||||
|
||||
interface TabPanelProps {
|
||||
children?: React.ReactNode;
|
||||
index: any;
|
||||
value: any;
|
||||
}
|
||||
|
||||
function TabPanelMine(props: TabPanelProps) {
|
||||
const { children, value, index, ...other } = props;
|
||||
|
||||
return (
|
||||
<div
|
||||
role="tabpanel"
|
||||
hidden={value !== index}
|
||||
aria-labelledby={`simple-tab-${index}`}
|
||||
style={{ height: "94%", paddingTop: "15px" }}
|
||||
{...other}>
|
||||
{value === index && <React.Fragment>{children}</React.Fragment>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
interface Props {
|
||||
open: boolean;
|
||||
closeDrawer: () => void;
|
||||
selectedFieldKey: string;
|
||||
fields: Map<string, Field>;
|
||||
openSettings: (fieldKey: string) => void;
|
||||
moveMap: (long: number, lat: number) => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
avatar: {
|
||||
color: getThemeType() === "light" ? theme.palette.common.black : theme.palette.common.white,
|
||||
backgroundColor: "transparent",
|
||||
width: theme.spacing(5),
|
||||
height: theme.spacing(5),
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.divider
|
||||
},
|
||||
dark: {
|
||||
backgroundColor: getThemeType() === "light" ? "rgb(245, 245, 245)" : "rgb(50, 50, 50)",
|
||||
padding: 5
|
||||
},
|
||||
light: {
|
||||
backgroundColor: getThemeType() === "light" ? "rgb(235, 235, 235)" : "rgb(60, 60, 60)",
|
||||
padding: 5
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
export default function FieldDrawer(props: Props) {
|
||||
const { open, closeDrawer, selectedFieldKey, fields, moveMap } = props;
|
||||
const [field, setField] = useState<Field>(Field.create());
|
||||
//const [hPlan, setHPlan] = useState<HarvestPlan>(HarvestPlan.create());
|
||||
const [value, setValue] = useState(0);
|
||||
const classes = useStyles();
|
||||
const [openNote, setOpenNote] = useState(false);
|
||||
const isMobile = useMobile();
|
||||
const [{ as, user }] = useGlobalState();
|
||||
//const hPlanAPI = useHarvestPlanAPI();
|
||||
const [planLoading, setPlanLoading] = useState(false);
|
||||
const userAPI = useUserAPI();
|
||||
const [permissions, setPermissions] = useState<pond.Permission[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
let field = fields.get(selectedFieldKey);
|
||||
if (field) {
|
||||
setField(field);
|
||||
}
|
||||
}, [selectedFieldKey, fields]);
|
||||
|
||||
useEffect(() => {
|
||||
let scope;
|
||||
if (as) {
|
||||
//if they are viewing as a team regardless of whether the field is adaptive or external (from JD or CNH) get the users permission to the team
|
||||
scope = teamScope(as);
|
||||
} else if (
|
||||
field.settings.fieldGeoData &&
|
||||
field.settings.fieldGeoData.origin === pond.DataOrigin.DATA_ORIGIN_ADAPTIVE
|
||||
) {
|
||||
//if they are viewing as a user and the field is an adaptive field get the users permission to the field
|
||||
scope = fieldScope(field.key());
|
||||
}
|
||||
|
||||
//if the scope was set get the permissions the user has in that scope
|
||||
if (scope) {
|
||||
userAPI.getUser(user.id(), scope).then(resp => {
|
||||
field.permissions = resp.permissions;
|
||||
setPermissions(resp.permissions);
|
||||
});
|
||||
} else {
|
||||
//if scope wasn't set that means that they are viewing an external field as a user and so will have full permissions
|
||||
//because they would have full permissions to the organization that the field is linked to since users cannot share organizations
|
||||
//and they are only linked to team/user combinations during creation and cannot be shared afterward
|
||||
let perms = [
|
||||
pond.Permission.PERMISSION_READ,
|
||||
pond.Permission.PERMISSION_WRITE,
|
||||
pond.Permission.PERMISSION_SHARE,
|
||||
pond.Permission.PERMISSION_USERS
|
||||
];
|
||||
field.permissions = perms;
|
||||
setPermissions(perms);
|
||||
}
|
||||
}, [as, user, userAPI, field]); //eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
// useEffect(() => {
|
||||
// if (field.key() !== "") {
|
||||
// hPlanAPI
|
||||
// .listHarvestPlans(1, 0, "desc", "createDate", field.key(), as)
|
||||
// .then(resp => {
|
||||
// if (resp.data.harvestPlan.length > 0) {
|
||||
// let plan = resp.data.harvestPlan[0];
|
||||
// setHPlan(HarvestPlan.any(plan));
|
||||
// } else {
|
||||
// setHPlan(HarvestPlan.create());
|
||||
// }
|
||||
// setPlanLoading(false);
|
||||
// })
|
||||
// .catch(err => {
|
||||
// //openSnack("Failed to load plan");
|
||||
// });
|
||||
// }
|
||||
// }, [field, as, hPlanAPI]);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
const displayNext = () => {
|
||||
let arr = Array.from(fields.values());
|
||||
let index = arr.indexOf(field);
|
||||
let found = false;
|
||||
do {
|
||||
if (index === arr.length - 1) {
|
||||
index = 0;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
let nextField = arr[index];
|
||||
let location = nextField.center();
|
||||
if (
|
||||
location !== null &&
|
||||
location !== undefined &&
|
||||
location.longitude !== 0 &&
|
||||
location.longitude !== 0
|
||||
) {
|
||||
setField(nextField);
|
||||
moveMap(location.longitude, location.latitude);
|
||||
found = true;
|
||||
}
|
||||
} while (!found);
|
||||
};
|
||||
|
||||
const displayPrev = () => {
|
||||
let arr = Array.from(fields.values());
|
||||
let index = arr.indexOf(field);
|
||||
let found = false;
|
||||
do {
|
||||
if (index === 0) {
|
||||
index = arr.length - 1;
|
||||
} else {
|
||||
index--;
|
||||
}
|
||||
let nextField = arr[index];
|
||||
let location = nextField.center();
|
||||
if (
|
||||
location !== null &&
|
||||
location !== undefined &&
|
||||
location.longitude !== 0 &&
|
||||
location.longitude !== 0
|
||||
) {
|
||||
setField(nextField);
|
||||
moveMap(location.longitude, location.latitude);
|
||||
found = true;
|
||||
}
|
||||
} while (!found);
|
||||
};
|
||||
|
||||
const drawerBody = () => {
|
||||
let taskLoadKeys: string[] = [];
|
||||
if (!planLoading) {
|
||||
field.key() !== "" && taskLoadKeys.push(field.key());
|
||||
//hPlan.key() !== "" && taskLoadKeys.push(hPlan.key());
|
||||
}
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Tabs
|
||||
style={{ position: "sticky" }}
|
||||
value={value}
|
||||
centered
|
||||
onChange={handleChange}
|
||||
TabIndicatorProps={{ style: { background: "rgba(255,255,0,255)" } }}>
|
||||
<Tab label="Field Overview" />
|
||||
<Tab label="Weather" />
|
||||
<Tab label="Field Activities" />
|
||||
</Tabs>
|
||||
<TabPanelMine value={value} index={0}>
|
||||
<Box paddingLeft={2} paddingRight={2} paddingBottom={5}>
|
||||
<IconButton className={classes.avatar} onClick={() => setOpenNote(true)}>
|
||||
<Notes />
|
||||
</IconButton>
|
||||
<Box>
|
||||
<Typography variant="h5" style={{ fontWeight: 700 }}>
|
||||
{field.fieldName()} Details
|
||||
</Typography>
|
||||
</Box>
|
||||
<Grid container direction="column" alignItems="center">
|
||||
<Grid container direction="row" className={classes.dark}>
|
||||
<Grid>Approximate Area:</Grid>
|
||||
<Grid>{field.acres()}ac</Grid>
|
||||
</Grid>
|
||||
<Grid container direction="row" className={classes.light}>
|
||||
<Grid>Grain:</Grid>
|
||||
<Grid>
|
||||
{field.grain() === pond.Grain.GRAIN_CUSTOM
|
||||
? field.customType()
|
||||
: GrainDescriber(field.crop()).name}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container direction="row" className={classes.dark}>
|
||||
<Grid>Grain Variant:</Grid>
|
||||
<Grid>{field.settings.grainSubtype}</Grid>
|
||||
</Grid>
|
||||
<Grid container direction="row" className={classes.light}>
|
||||
<Grid>Land Location:</Grid>
|
||||
<Grid>{field.landLoc()}</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Box padding={3}>
|
||||
<Divider style={{ padding: 2 }} />
|
||||
</Box>
|
||||
{/* <HarvestPlanDisplay
|
||||
plan={hPlan}
|
||||
permissions={permissions}
|
||||
planField={field}
|
||||
loading={planLoading}
|
||||
fieldList={Array.from(fields.values())}
|
||||
changePlan={updatedPlan => {
|
||||
if (updatedPlan) {
|
||||
setHPlan(updatedPlan);
|
||||
}
|
||||
}}
|
||||
/> */}
|
||||
</Box>
|
||||
</TabPanelMine>
|
||||
<TabPanelMine value={value} index={1}>
|
||||
<Weather longitude={field.center().longitude} latitude={field.center().latitude} />
|
||||
</TabPanelMine>
|
||||
<TabPanelMine value={value} index={2}>
|
||||
{/* <TaskViewer drawerView objectKey={field.key()} loadKeys={taskLoadKeys} /> */}
|
||||
</TabPanelMine>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const noteDrawer = () => {
|
||||
return (
|
||||
<Drawer
|
||||
anchor={isMobile ? "bottom" : "right"}
|
||||
open={openNote}
|
||||
onClose={() => setOpenNote(false)}>
|
||||
<Box height={isMobile ? "50vh" : "100vh"} padding={2}>
|
||||
<Typography style={{ fontWeight: 650 }}>Notes</Typography>
|
||||
<Chat type={pond.NoteType.NOTE_TYPE_FIELD} objectKey={field.key()} />
|
||||
</Box>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DisplayDrawer
|
||||
open={open}
|
||||
onClose={closeDrawer}
|
||||
displayNext={displayNext}
|
||||
displayPrev={displayPrev}
|
||||
title={field.name()}
|
||||
width={"40vw"}
|
||||
drawerBody={drawerBody()}
|
||||
updateElement={
|
||||
field.settings.fieldGeoData &&
|
||||
field.settings.fieldGeoData.origin === pond.DataOrigin.DATA_ORIGIN_ADAPTIVE
|
||||
? () => {
|
||||
props.openSettings(selectedFieldKey);
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
// objectActions={
|
||||
// field.settings.fieldGeoData &&
|
||||
// field.settings.fieldGeoData.origin === pond.DataOrigin.DATA_ORIGIN_ADAPTIVE ? (
|
||||
// <FieldActions field={field} permissions={permissions} refreshCallback={() => {}} />
|
||||
// ) : (
|
||||
// undefined
|
||||
// )
|
||||
// }
|
||||
/>
|
||||
{noteDrawer()}
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue