diff --git a/src/bin/BinSettings.tsx b/src/bin/BinSettings.tsx index f970b2b..237a540 100644 --- a/src/bin/BinSettings.tsx +++ b/src/bin/BinSettings.tsx @@ -741,7 +741,7 @@ export default function BinSettings(props: Props) { case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR: return "Hybrid (lidar)" case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART: - return "Auto (LibraCart)" + return "Auto (Libra Cart)" default: return "Manual" } @@ -905,7 +905,7 @@ export default function BinSettings(props: Props) { } - label={"Auto (LibraCart)"} + label={"Auto (Libra Cart)"} /> } @@ -951,7 +951,7 @@ export default function BinSettings(props: Props) { {inventoryControl === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_LIBRACART && { let newForm = form; @@ -963,7 +963,7 @@ export default function BinSettings(props: Props) { options={lcDestinationOptions} /> - The linked bins inventory will be adjusted When the LibraCart Destination data is synced every 6 hours + The linked bins inventory will be adjusted When the Libra Cart Destination data is synced every 6 hours } diff --git a/src/field/FieldActions.tsx b/src/field/FieldActions.tsx index 7e0cb44..fbaf090 100644 --- a/src/field/FieldActions.tsx +++ b/src/field/FieldActions.tsx @@ -63,8 +63,6 @@ export default function FieldActions(props: Props) { removeSelf: false }); - console.log(permissions) - const groupMenu = () => { const canShare = permissions.includes(pond.Permission.PERMISSION_SHARE); const canManageUsers = permissions.includes(pond.Permission.PERMISSION_USERS); diff --git a/src/harvestPlan/DuplicateHarvestPlan.tsx b/src/harvestPlan/DuplicateHarvestPlan.tsx index 5f083af..6e910c0 100644 --- a/src/harvestPlan/DuplicateHarvestPlan.tsx +++ b/src/harvestPlan/DuplicateHarvestPlan.tsx @@ -7,16 +7,17 @@ import { TextField } from "@mui/material"; import ResponsiveDialog from "common/ResponsiveDialog"; +import { Option } from "common/SearchSelect"; import { Field, HarvestPlan, Task } from "models"; import moment from "moment"; import { pond } from "protobuf-ts/pond"; -import { useGlobalState, useHarvestPlanAPI, useTaskAPI } from "providers"; +import { useFieldAPI, useGlobalState, useHarvestPlanAPI, useTaskAPI } from "providers"; import { useCallback, useEffect, useState } from "react"; interface Props { open: boolean; close: () => void; - fields: Field[]; + fields?: Field[]; plan: HarvestPlan; } @@ -29,6 +30,8 @@ export default function DuplicateHarvestPlan(props: Props) { const harvestPlanAPI = useHarvestPlanAPI(); const taskAPI = useTaskAPI(); const [ready, setReady] = useState(false); + const [fieldOptions, setFieldOptions] = useState([]) + const fieldAPI = useFieldAPI(); const loadTasks = useCallback(() => { taskAPI.listTasks(50, 0, "asc", "start", plan.key(), undefined).then(resp => { @@ -41,9 +44,25 @@ export default function DuplicateHarvestPlan(props: Props) { loadTasks(); }, [loadTasks]); + useEffect(()=>{ + if(fields){ + //if fields were passed in use those + setFieldOptions(fields) + }else{ + //otherwise load them + fieldAPI.listFields(50, 0, "asc", "fieldName").then(resp => { + setFieldOptions(resp.data.fields.map(f => Field.create(f))) + }).catch(err => { + + }) + } + },[fields]) + + //this should load the fields here + const duplicate = () => { let planSettings = HarvestPlan.clone(plan).settings; - planSettings.field = fields[newFieldIndex].key(); + planSettings.field = fieldOptions[newFieldIndex].key(); planSettings.createDate = moment.now(); if (title !== "") { planSettings.title = title; @@ -69,7 +88,7 @@ export default function DuplicateHarvestPlan(props: Props) { value={newFieldIndex} onChange={e => setNewFieldIndex(+e.target.value)} color="primary"> - {fields.map((option, i) => ( + {fieldOptions.map((option, i) => ( {option.fieldName()} @@ -98,8 +117,8 @@ export default function DuplicateHarvestPlan(props: Props) { color="primary" disabled={ !ready || - (fields[newFieldIndex] && - !fields[newFieldIndex].permissions.includes(pond.Permission.PERMISSION_WRITE)) + (fieldOptions[newFieldIndex] && + !fieldOptions[newFieldIndex].permissions.includes(pond.Permission.PERMISSION_WRITE)) }> Duplicate diff --git a/src/harvestPlan/HarvestPlanActions.tsx b/src/harvestPlan/HarvestPlanActions.tsx index 441446a..f29c1e4 100644 --- a/src/harvestPlan/HarvestPlanActions.tsx +++ b/src/harvestPlan/HarvestPlanActions.tsx @@ -13,7 +13,7 @@ import ShareObjectIcon from "@mui/icons-material/Share"; import ObjectUsersIcon from "@mui/icons-material/AccountCircle"; import ObjectTeamsIcon from "@mui/icons-material/SupervisedUserCircle"; import { pond } from "protobuf-ts/pond"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import ObjectUsers from "user/ObjectUsers"; import ShareObject from "user/ShareObject"; import { isOffline } from "utils/environment"; @@ -43,7 +43,7 @@ const useStyles = makeStyles((theme: Theme) => ({ interface Props { plan: HarvestPlan; planField: Field; - fieldList: Field[]; + fieldList?: Field[]; permissions: pond.Permission[]; refreshCallback: (updatedPlan?: HarvestPlan) => void; hideNew?: boolean; @@ -215,7 +215,7 @@ export default function HarvestPlanActions(props: Props) { setUpdatePlan(true); setOpenState({ ...openState, settings: true }); }}> - Edit or Add Activity + Activities )} void; } @@ -175,7 +175,7 @@ export default function HarvestPlanDisplay(props: Props) { - Crop Plan{plan.key() !== "" ? " - " + plan.settings.title : " - None Found"} + {plan.key() !== "" ? plan.settings.title : "None Found"} {!isMobile && permissions.includes(pond.Permission.PERMISSION_WRITE) && ( { + harvestAPI.listHarvestPlans(pageSize, page*pageSize, "asc", "name", field).then(resp => { + console.log(resp) + }) + },[page, pageSize, field]) + + return ( + + + + ) +} \ No newline at end of file diff --git a/src/pages/Field.tsx b/src/pages/Field.tsx index 9302a3b..b204f4a 100644 --- a/src/pages/Field.tsx +++ b/src/pages/Field.tsx @@ -1,10 +1,10 @@ -import { Field, HarvestPlan } from "models"; -import { useGlobalState } from "providers"; -import { useEffect, useState } from "react"; -import { useLocation } from "react-router-dom"; +import { Field, fieldScope, HarvestPlan, teamScope } from "models"; +import { useFieldAPI, useGlobalState, useHarvestPlanAPI } from "providers"; +import { useCallback, useEffect, useState } from "react"; +import { useLocation, useParams } from "react-router-dom"; import PageContainer from "./PageContainer"; -import { useMobile } from "hooks"; -import { Box, Grid2, IconButton } from "@mui/material"; +import { useMobile, useSnackbar, useUserAPI } from "hooks"; +import { Box, Card, Grid2, IconButton } from "@mui/material"; import FieldActions from "field/FieldActions"; import { Settings } from "@mui/icons-material"; import { pond } from "protobuf-ts/pond"; @@ -12,28 +12,82 @@ import FieldMinimap from "field/Fieldminimap"; import Weather from "weather/weather"; import TaskViewer from "tasks/TaskViewer"; import HarvestPlanDisplay from "harvestPlan/HarvestPlanDisplay"; +import { cloneDeep } from "lodash"; +import HarvestPlanTable from "harvestPlan/HarvestPlanTable"; export default function FieldPage() { const { state } = useLocation(); //const [{ as }] = useGlobalState() + const fieldAPI = useFieldAPI(); + const userAPI = useUserAPI(); + const [{as, user}] = useGlobalState(); + const {openSnack} = useSnackbar(); + const fieldID = useParams<{ fieldID: string }>()?.fieldID ?? ""; const [field, setField] = useState(state?.field ? Field.create(state.field) : Field.create()) const [permissions, setPermissions] = useState(state?.permissions ? state.permissions : []) const isMobile = useMobile() const [openFieldSettings, setOpenFieldSettings] = useState(false) const [planLoading, setPlanLoading] = useState(false) const [hPlan, setHPlan] = useState(HarvestPlan.create()); + const [loading, setLoading] = useState(false) + const hPlanAPI = useHarvestPlanAPI(); - const loadField = () => { + const loadField = useCallback(() => { - } + },[as]) useEffect(()=>{ - if(state.field){ + // if already loading do nothing + if(loading) return + //if the field is passed through in the state just use it + if(state?.field){ let field = Field.create(state.field) + field.permissions = state.permissions setField(field) setPermissions(state.permissions) + return } - },[state.field]) + //otherwise load the field + setLoading(true) + fieldAPI.getField(fieldID, as).then(resp => { + setField(Field.create(resp.data)) + + }).catch(err => { + openSnack("Failed to load Field") + }).finally(() => { + setLoading(false) + }) + //also get the permissions + let scope = fieldScope(fieldID); + if (as) { + scope = teamScope(as) + } + userAPI.getUser(user.id(), scope).then(resp => { + let f = cloneDeep(field) + f.permissions = resp.permissions + setField(f) + setPermissions(resp.permissions); + }); + },[loadField, fieldID, as]) + + 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 fieldActions = () => { return ( @@ -60,14 +114,12 @@ export default function FieldPage() { } const harvestPlans = () => { - console.log(permissions) return ( { if (updatedPlan) { setHPlan(updatedPlan); @@ -87,18 +139,31 @@ export default function FieldPage() { const desktopView = () => { return ( - + - {map()} + + {map()} + + {weather()} + + {tasks()} + - + + {harvestPlans()} + + + + + + ) @@ -116,8 +181,10 @@ export default function FieldPage() { return ( + {fieldActions()} {isMobile ? mobileView() : desktopView()} + ) } \ No newline at end of file diff --git a/src/providers/pond/fieldAPI.tsx b/src/providers/pond/fieldAPI.tsx index 803be77..be980eb 100644 --- a/src/providers/pond/fieldAPI.tsx +++ b/src/providers/pond/fieldAPI.tsx @@ -9,7 +9,7 @@ import { permissionToString } from "pbHelpers/Permission"; export interface IFieldAPIContext { addField: (field: pond.FieldSettings, otherTeam?: string) => Promise; - getField: (fieldId: string, otherTeam?: string) => Promise; + getField: (fieldId: string, otherTeam?: string) => Promise>; listFields: ( limit: number, offset: number, @@ -53,8 +53,8 @@ export default function FieldProvider(props: PropsWithChildren) { const getField = (fieldId: string, otherTeam?: string) => { const view = otherTeam ? otherTeam : as - if (view) return get(pondURL("/field/" + fieldId + "?as=" + view)); - return get(pondURL("/field/" + fieldId)); + if (view) return get(pondURL("/field/" + fieldId + "?as=" + view)); + return get(pondURL("/field/" + fieldId)); }; const removeField = (key: string, otherTeam?: string) => {