From 186604dccfb1ebbde48cc08c508ace121f98f55e Mon Sep 17 00:00:00 2001 From: csawatzky Date: Tue, 31 Mar 2026 13:37:49 -0600 Subject: [PATCH] final adjustments to the field task list and the field drawer and field page using the tasks with the permissions in the correct way --- src/field/FieldTaskList.tsx | 43 +++++++++++------- src/maps/mapDrawers/FieldDrawer.tsx | 3 +- src/pages/Bin.tsx | 4 +- src/pages/Field.tsx | 11 ++--- src/providers/pond/permissionAPI.tsx | 29 ++++++++++++ src/tasks/TaskCard.tsx | 1 - src/tasks/TaskDrawer.tsx | 45 ++++--------------- src/tasks/TaskList.tsx | 67 ---------------------------- src/tasks/TaskViewer.tsx | 45 +------------------ src/tasks/taskActions.tsx | 1 + src/teams/ObjectTeams.tsx | 25 +++++++++-- 11 files changed, 97 insertions(+), 177 deletions(-) diff --git a/src/field/FieldTaskList.tsx b/src/field/FieldTaskList.tsx index 3b0d1e3..66a32c3 100644 --- a/src/field/FieldTaskList.tsx +++ b/src/field/FieldTaskList.tsx @@ -7,6 +7,8 @@ import TaskList from "tasks/TaskList" import TaskSettings from "tasks/TaskSettings" import AddIcon from "@mui/icons-material/Add"; import { makeStyles } from "@mui/styles"; +import { openSnackbar } from "providers/Snackbar" +import { cloneDeep } from "lodash" @@ -70,8 +72,10 @@ export default function FieldTaskList(props: Props) { const [openTaskDrawer, setOpenTaskDrawer] = useState(false) const [opentaskSettings, setOpenTaskSettings] = useState(false) const [taskMap, setTaskMap] = useState>(new Map()) + //load the tasks const loadTasks = useCallback(() => { + console.log("loading tasks") taskAPI.listTasks(50, 0, "asc", "start", undefined, undefined, undefined, undefined, undefined, [field], ["field"]).then(resp => { if(resp.data.tasks){ let newMap: Map = new Map() @@ -89,20 +93,24 @@ export default function FieldTaskList(props: Props) { loadTasks() },[loadTasks]) - const addNewTask = (task: Task) => { - console.log() + const deleteTask = (task: Task) => { + taskAPI.removeTask(task.key).then(resp => { + openSnackbar("success", "Task has been removed") + loadTasks() + }).catch(err => { + openSnackbar("error", "There was a problem removing the task") + }) } - const deleteTask = () => { - - } - - const markComplete = () => { - - } - - const updateTask = () => { - + const markComplete = (task: Task) => { + let settings = cloneDeep(task.settings) + settings.complete = !task.settings.complete + taskAPI.updateTask(task.key, settings).then(resp => { + openSnackbar("success", "Task has been updated") + loadTasks() + }).catch(err => { + openSnackbar("error", "There was a problem updating the task") + }) } //return the task list return ( @@ -113,9 +121,12 @@ export default function FieldTaskList(props: Props) { open={openTaskDrawer} deleteTask={deleteTask} completeTask={markComplete} - closeCallback={() => { + closeCallback={(refresh) => { setOpenTaskDrawer(false) setSelectedTask(undefined) + if (refresh) { + loadTasks() + } }} keys={[field]} types={["field"]} @@ -123,7 +134,6 @@ export default function FieldTaskList(props: Props) { } { let task = taskMap.get(id) @@ -141,8 +151,11 @@ export default function FieldTaskList(props: Props) { /> { + onClose={(reload) => { setOpenTaskSettings(false) + if(reload){ + loadTasks() + } }} keys={[field]} types={["field"]} diff --git a/src/maps/mapDrawers/FieldDrawer.tsx b/src/maps/mapDrawers/FieldDrawer.tsx index f6e864b..07adbf9 100644 --- a/src/maps/mapDrawers/FieldDrawer.tsx +++ b/src/maps/mapDrawers/FieldDrawer.tsx @@ -14,7 +14,6 @@ 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"; @@ -219,7 +218,7 @@ export default function FieldDrawer(props: Props) { TabIndicatorProps={{ style: { background: "rgba(255,255,0,255)" } }}> - + diff --git a/src/pages/Bin.tsx b/src/pages/Bin.tsx index 48bba18..4cbbba7 100644 --- a/src/pages/Bin.tsx +++ b/src/pages/Bin.tsx @@ -512,7 +512,7 @@ export default function Bin(props: Props) { if (showTasks()) { return ( - + ); } @@ -1156,7 +1156,7 @@ export default function Bin(props: Props) { setTaskDrawer(false)}> - + )} diff --git a/src/pages/Field.tsx b/src/pages/Field.tsx index 15c29db..94159fc 100644 --- a/src/pages/Field.tsx +++ b/src/pages/Field.tsx @@ -10,12 +10,12 @@ 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"; import { cloneDeep } from "lodash"; import HarvestPlanTable from "harvestPlan/HarvestPlanTable"; import { makeStyles } from "@mui/styles"; import FieldSettings from "field/FieldSettings"; +import FieldTaskList from "field/FieldTaskList"; const useStyles = makeStyles((theme: Theme) => { return ({ @@ -185,12 +185,9 @@ export default function FieldPage() { } const tasks = () => { - let taskLoadKeys: string[] = []; - if (!planLoading) { - field.key() !== "" && taskLoadKeys.push(field.key()); - //hPlan.key() !== "" && taskLoadKeys.push(hPlan.key()); - } - return () + return ( + + ) } const desktopView = () => { diff --git a/src/providers/pond/permissionAPI.tsx b/src/providers/pond/permissionAPI.tsx index 3005599..68fa5c9 100644 --- a/src/providers/pond/permissionAPI.tsx +++ b/src/providers/pond/permissionAPI.tsx @@ -7,10 +7,16 @@ import { useGlobalState } from "providers"; import { createContext, PropsWithChildren, useContext } from "react"; import { objectQueryParams, pondURL } from "./pond"; +export interface PermissionChanges { + key: string; //the key of the object having its permissions changed (parent) + permissions: string[] //the new permissions the parent will have to the child +} + export interface IPermissionAPIContext { getPermissions: (user: string, keys: string[], types: string[]) => Promise>; removePermissions: (user: string, scope: Scope) => Promise>; updatePermissions: (scope: Scope, users: User[] | Team[]) => Promise>; + updateObjectPermissions: (key: string, type: string, parentType: string, changes: PermissionChanges[], keys: string[], types: string[]) => Promise>; updateRelativePermissions: ( parentScope: Scope, childScope: Scope, @@ -96,6 +102,28 @@ export default function PermissionProvider(props: PropsWithChildren) { }) }; + const updateObjectPermissions = (key: string, type: string, parentType: string, changes: PermissionChanges[], keys: string[], types: string[]) => { + let body = { + childKey: key, + childType: type, + parentType: parentType, + permissionChanges: changes + }; + + if (as) { + keys.unshift(as) + types.unshift("team") + } + + return new Promise((resolve, reject) => { + put(pondURL("/" + type + "s/" + key + "/objectPermissions?keys=" + keys + "&types=" + types ), body).then(resp => { + return resolve(resp) + }).catch(err => { + return reject(err) + }) + }) + } + const shareObject = ( scope: Scope, email: string, @@ -207,6 +235,7 @@ export default function PermissionProvider(props: PropsWithChildren) { getPermissions, removePermissions, updatePermissions, + updateObjectPermissions, updateRelativePermissions, shareObject, shareObjectByKey, diff --git a/src/tasks/TaskCard.tsx b/src/tasks/TaskCard.tsx index 281bbb2..2cae4d3 100644 --- a/src/tasks/TaskCard.tsx +++ b/src/tasks/TaskCard.tsx @@ -18,7 +18,6 @@ import TaskActions from "./taskActions"; interface Props { task: Task; reLoad: () => void; - editTaskMethod: (task: Task) => void; markComplete: (task: Task) => void; deleteTask: (task: Task) => void; openTaskPage: (taskId: string) => void; diff --git a/src/tasks/TaskDrawer.tsx b/src/tasks/TaskDrawer.tsx index 3c206fb..0eade2d 100644 --- a/src/tasks/TaskDrawer.tsx +++ b/src/tasks/TaskDrawer.tsx @@ -32,7 +32,7 @@ import { useGlobalState } from "providers"; interface Props { task: Task; open: boolean; - closeCallback: () => void; + closeCallback: (refresh: boolean) => void; deleteTask: (task: Task) => void; completeTask: (task: Task) => void; keys: string[] @@ -121,7 +121,7 @@ export default function TaskDrawer(props: Props) { const [worker, setWorker] = useState(); useEffect(() => { - permissionAPI.getPermissions(user.id(), [task.key], ["task"]).then(resp => { + permissionAPI.getPermissions(user.id(), props.keys, props.types).then(resp => { setPermissions(pond.EvaluatePermissionsResponse.fromObject(resp.data).permissions) }) if (task.start()) { @@ -134,39 +134,6 @@ export default function TaskDrawer(props: Props) { }); }, [user, task, userAPI, permissionAPI]); - // const taskActions = () => { - // return ( - // setMenuAnchorEl(null)} - // disableAutoFocusItem> - // { - // editTask(props.task); - // setMenuAnchorEl(null); - // }}> - // - // - // - // - // - // { - // deleteTask(props.task); - // setMenuAnchorEl(null); - // closeCallback(); - // }}> - // - // - // - // - // - // - // ); - // }; - const bodyButtons = () => { return ( @@ -195,7 +162,9 @@ export default function TaskDrawer(props: Props) { permissions={permissions} task={task} removeTask={deleteTask} - refreshCallback={closeCallback} + refreshCallback={() => { + closeCallback(true) + }} keys={props.keys} types={props.types} /> @@ -335,7 +304,9 @@ export default function TaskDrawer(props: Props) { displayNext={() => {}} displayPrev={() => {}} drawerBody={drawerBody()} - onClose={closeCallback} + onClose={() => { + closeCallback(false)} + } open={open} /> ); diff --git a/src/tasks/TaskList.tsx b/src/tasks/TaskList.tsx index 8f367ef..f94f838 100644 --- a/src/tasks/TaskList.tsx +++ b/src/tasks/TaskList.tsx @@ -12,7 +12,6 @@ import ButtonGroup from "common/ButtonGroup"; interface Props { tasks: Task[]; - editTaskMethod: (task: Task) => void; markComplete: (task: Task) => void; deleteTask: (task: Task) => void; openTask: (taskId: string) => void; @@ -26,7 +25,6 @@ interface Props { export default function TaskList(props: Props) { const { - editTaskMethod, markComplete, deleteTask, openTask, @@ -74,60 +72,10 @@ export default function TaskList(props: Props) { setComplete(complete); }, [tasks, dateToView]); - // const StyledToggleButtonGroup = withStyles(theme => ({ - // grouped: { - // margin: theme.spacing(-0.5), - // border: "none", - // padding: theme.spacing(1), - // "&:not(:first-child):not(:last-child)": { - // borderRadius: 24, - // marginRight: theme.spacing(0.5), - // marginLeft: theme.spacing(0.5) - // }, - // "&:first-child": { - // borderRadius: 24, - // marginLeft: theme.spacing(0.25) - // }, - // "&:last-child": { - // borderRadius: 24, - // marginRight: theme.spacing(0.25) - // } - // }, - // root: { - // backgroundColor: darken( - // theme.palette.background.paper, - // getThemeType() === "light" ? 0.05 : 0.25 - // ), - // borderRadius: 24, - // content: "border-box" - // } - // }))(ToggleButtonGroup); - - // const StyledToggle = withStyles({ - // root: { - // backgroundColor: "transparent", - // overflow: "visible", - // content: "content-box", - // "&$selected": { - // backgroundColor: "gold", - // color: "black", - // borderRadius: 24, - // fontWeight: "bold" - // }, - // "&$selected:hover": { - // backgroundColor: "rgb(255, 255, 0)", - // color: "black", - // borderRadius: 24 - // } - // }, - // selected: {} - // })(ToggleButton); - const incompleteTasks = incomplete.map((task, index) => ( markComplete(task)} deleteTask={(task: Task) => deleteTask(task)} reLoad={reLoad} @@ -142,7 +90,6 @@ export default function TaskList(props: Props) { markComplete(task)} deleteTask={(task: Task) => deleteTask(task)} reLoad={reLoad} @@ -170,20 +117,6 @@ export default function TaskList(props: Props) { } ]} /> - {/* - setViewing("upcoming")}> - Upcoming - - setViewing("complete")} - value={"complete"} - aria-label="complete"> - Complete - - */} {location !== "/tasks" && ( diff --git a/src/tasks/TaskViewer.tsx b/src/tasks/TaskViewer.tsx index 00fed3c..b283c5f 100644 --- a/src/tasks/TaskViewer.tsx +++ b/src/tasks/TaskViewer.tsx @@ -99,7 +99,6 @@ export default function TaskViewer(props: ViewProps) { overlayButton } = props; const [{ user, as }] = useGlobalState(); - //const [{ as }] = useGlobalState(); const taskAPI = useTaskAPI(); const { openSnack } = useSnackbar(); const [tasks, setTasks] = useState>(new Map([])); @@ -147,36 +146,6 @@ export default function TaskViewer(props: ViewProps) { } }; - const setTaskToEdit = (task: Task) => { - setEditTask(task); - openDialog(); - }; - - - // const loadMultitask = useCallback(() => { - // if (!loadKeys) return; - // if (loadKeys.length > 0) { - // let temp = new Map(); - // setLoaded(false); - // taskAPI - // .getMultiTasks(loadKeys, as) - // .then(resp => { - // if(resp.data.tasks){ - // resp.data.tasks.forEach(task => { - // if (task.settings) { - // temp.set(task.key, Task.any(task)); - // } - // }); - // } - // setTasks(temp); - // setLoaded(true); - // }) - // .catch(err => { - // openSnack("Failed to load"); - // }); - // } - // }, [loadKeys, openSnack, taskAPI, as]); - //loads tasks from the backend database const loadTasks = useCallback(() => { if (!user.id()) return; @@ -324,7 +293,6 @@ export default function TaskViewer(props: ViewProps) { loadTasks()} @@ -385,7 +353,6 @@ export default function TaskViewer(props: ViewProps) { loadTasks()} @@ -437,18 +404,10 @@ export default function TaskViewer(props: ViewProps) { { - // if (r) { - // if (drawerView) { - // loadMultitask(); - // } else { - // loadTasks(); - // } - // } loadTasks(); setEditTask(undefined); setNewTaskDialog(false); @@ -464,8 +423,8 @@ export default function TaskViewer(props: ViewProps) { }} completeTask={markComplete} deleteTask={deleteTask} - keys={[]} - types={[]} + keys={keys ?? []} + types={types ?? []} /> } diff --git a/src/tasks/taskActions.tsx b/src/tasks/taskActions.tsx index d55590b..116cdec 100644 --- a/src/tasks/taskActions.tsx +++ b/src/tasks/taskActions.tsx @@ -224,6 +224,7 @@ export default function TaskActions(props: Props) { return ( ) => setAnchorEl(event.currentTarget)}> diff --git a/src/teams/ObjectTeams.tsx b/src/teams/ObjectTeams.tsx index 595143f..9c80fbc 100644 --- a/src/teams/ObjectTeams.tsx +++ b/src/teams/ObjectTeams.tsx @@ -41,6 +41,8 @@ import { useNavigate } from "react-router-dom"; import { makeStyles } from "@mui/styles"; import { Share, RemoveCircle as RemoveUserIcon } from "@mui/icons-material"; import CancelSubmit from "common/CancelSubmit"; +import { permissionToString } from "pbHelpers/Permission"; +import { PermissionChanges } from "providers/pond/permissionAPI"; const useStyles = makeStyles((theme: Theme) => { const avatarBG = theme.palette.secondary["700" as keyof PaletteColor]; @@ -188,7 +190,21 @@ export default function ObjectTeams(props: Props) { }; const submit = () => { - permissionAPI + if(keys && types){ + let changes: PermissionChanges[] = [] + users.forEach((user: Team) => { + changes.push({ + key: user.id(), + permissions: user.permissions.map(permission => permissionToString(permission)) + }); + }); + permissionAPI.updateObjectPermissions(scope.key, scope.kind, "team", changes, keys, types).then(resp => { + console.log("no error") + }).catch(err => { + console.log("error") + }) + }else{ + permissionAPI .updatePermissions(scope, users) .then((_response: any) => { success("Users were sucessfully updated for " + label); @@ -201,10 +217,13 @@ export default function ObjectTeams(props: Props) { }) .catch((err: any) => { err.response.data.error - ? warning(err.response.data.error) - : error("Error occured when updating users for " + label); + ? warning(err.response.data.error) + : error("Error occured when updating users for " + label); close(); }); + + } + }; const changeUserPermissions = (user: pond.ITeam) => (event: any) => {