imported binyard stuff
This commit is contained in:
parent
8d2d9ea0e7
commit
906fe44ab5
5 changed files with 806 additions and 12 deletions
792
src/bin/BinYards.tsx
Normal file
792
src/bin/BinYards.tsx
Normal file
|
|
@ -0,0 +1,792 @@
|
|||
import {
|
||||
AppBar,
|
||||
Button,
|
||||
CircularProgress,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Grid,
|
||||
ListItemIcon,
|
||||
ListItemText,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Tab,
|
||||
Tabs,
|
||||
TextField,
|
||||
Theme,
|
||||
Tooltip,
|
||||
Typography,
|
||||
useTheme
|
||||
} from "@mui/material";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import {
|
||||
useBinYardAPI,
|
||||
useSnackbar,
|
||||
//useUserAPI,
|
||||
usePermissionAPI,
|
||||
useBinAPI,
|
||||
useGlobalState
|
||||
//useTeamAPI
|
||||
} from "providers";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import AddIcon from "@mui/icons-material/LibraryAdd";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import { MoreVert, Search } from "@mui/icons-material";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import RemoveSelfIcon from "@mui/icons-material/ExitToApp";
|
||||
import KeyboardArrowLeftIcon from "@mui/icons-material/KeyboardArrowLeft";
|
||||
import KeyboardArrowRightIcon from "@mui/icons-material/KeyboardArrowRight";
|
||||
import ObjectUsersIcon from "@mui/icons-material/SupervisedUserCircle";
|
||||
import EditIcon from "@mui/icons-material/Edit";
|
||||
import ShareIcon from "@mui/icons-material/Share";
|
||||
import { red, blue, green } from "@mui/material/colors";
|
||||
import { openSnackbar } from "providers/Snackbar";
|
||||
// import { Status } from "@sentry/react";
|
||||
import { binScope, binYardScope } from "models/Scope";
|
||||
import ShareObject from "user/ShareObject";
|
||||
import { Bin, Team, User } from "models";
|
||||
import { Dictionary } from "lodash";
|
||||
import ObjectUsers from "user/ObjectUsers";
|
||||
import ObjectTeams from "teams/ObjectTeams";
|
||||
import { GrainBag } from "models/GrainBag";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
|
||||
const parentTab = {
|
||||
"&": {
|
||||
margin: "0px",
|
||||
marginTop: "4px",
|
||||
marginLeft: "4px",
|
||||
animationDuration: "10s",
|
||||
background: "rgba(150, 150, 150, 0)",
|
||||
|
||||
borderRadius: "-5px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px"
|
||||
},
|
||||
"&:hover": {
|
||||
background: "linear-gradient(rgba(150, 150, 150, 0.2), rgba(150, 150, 150, 0))"
|
||||
}
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
red: {
|
||||
marginRight: 0,
|
||||
paddingRight: 0,
|
||||
color: red["500"],
|
||||
"&:hover": {
|
||||
color: red["600"]
|
||||
}
|
||||
},
|
||||
blue: {
|
||||
marginRight: 0,
|
||||
paddingRight: 0,
|
||||
color: blue["500"],
|
||||
"&:hover": {
|
||||
color: blue["600"]
|
||||
}
|
||||
},
|
||||
green: {
|
||||
marginRight: 0,
|
||||
paddingRight: 0,
|
||||
color: green["500"],
|
||||
"&:hover": {
|
||||
color: green["600"]
|
||||
}
|
||||
},
|
||||
searchTab: {
|
||||
...parentTab,
|
||||
width: theme.spacing(8),
|
||||
minWidth: theme.spacing(8),
|
||||
left: 0,
|
||||
height: "100%",
|
||||
background: theme.palette.background.paper
|
||||
},
|
||||
searchTabExpanded: {
|
||||
...parentTab,
|
||||
width: theme.spacing(30),
|
||||
minWidth: theme.spacing(30),
|
||||
left: 0,
|
||||
height: "100%",
|
||||
background: theme.palette.background.paper
|
||||
},
|
||||
tab: {
|
||||
...parentTab,
|
||||
width: theme.spacing(20),
|
||||
minWidth: theme.spacing(20),
|
||||
left: 0,
|
||||
height: "100%",
|
||||
background: theme.palette.background.paper
|
||||
},
|
||||
smallTab: {
|
||||
...parentTab,
|
||||
width: theme.spacing(8),
|
||||
minWidth: theme.spacing(8),
|
||||
background: theme.palette.background.paper
|
||||
},
|
||||
selectedTab: {
|
||||
borderRadius: "-5px",
|
||||
borderTopLeftRadius: "6px",
|
||||
borderTopRightRadius: "6px",
|
||||
background: theme.palette.background.default,
|
||||
"&:hover": {
|
||||
background:
|
||||
"linear-gradient(rgba(150, 150, 150, 0.3)," + theme.palette.background.default + " 80%)"
|
||||
}
|
||||
},
|
||||
icon: {
|
||||
display: "flex",
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
top: 6,
|
||||
padding: 6,
|
||||
marginRight: "2px",
|
||||
width: 36,
|
||||
height: 36,
|
||||
borderRadius: "18px",
|
||||
background: "rgba(0,0,0,0)",
|
||||
"&:hover": {
|
||||
background:
|
||||
"radial-gradient(closest-side, rgba(150, 150, 150, 0.5) 50%, rgba(150, 150, 150, 0.5))"
|
||||
}
|
||||
},
|
||||
tabText: {
|
||||
position: "absolute",
|
||||
left: theme.spacing(2),
|
||||
color: "transparent",
|
||||
textAlign: "left",
|
||||
width: "80%",
|
||||
backgroundImage: "linear-gradient(to right, white 70%, rgba(200, 200, 200, 0) 87.5%)",
|
||||
backgroundClip: "text",
|
||||
WebkitBackgroundClip: "text",
|
||||
overflowX: "hidden",
|
||||
whiteSpace: "nowrap",
|
||||
top: 12
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
interface Props {
|
||||
setYardFilter: React.Dispatch<React.SetStateAction<string>>;
|
||||
|
||||
loadBins: () => void;
|
||||
loadYards: (search?: string, limit?: number, offset?: number) => void;
|
||||
yardsLoading: boolean;
|
||||
tab?: number;
|
||||
yards?: pond.BinYardSettings[];
|
||||
yardPerms?: Dictionary<pond.Permission[]>;
|
||||
showTabs?: boolean;
|
||||
bins: Bin[];
|
||||
grainBags: GrainBag[];
|
||||
setShowing: (showing: "all" | "bins" | "bags") => void;
|
||||
}
|
||||
|
||||
export default function BinYard(props: Props) {
|
||||
const { setYardFilter, loadBins, loadYards, grainBags, setShowing, yardsLoading } = props;
|
||||
const binYardAPI = useBinYardAPI();
|
||||
const binAPI = useBinAPI();
|
||||
// const userAPI = useUserAPI();
|
||||
// const teamAPI = useTeamAPI();
|
||||
const [tab, setTab] = useState<number>(props.tab ? props.tab : 1);
|
||||
const [showAddYard, setShowAddYard] = useState<boolean>(false);
|
||||
const [addYardName, setAddYardName] = useState<string>("");
|
||||
const [addYardDescription, setAddYardDescription] = useState<string>("");
|
||||
const [binYards, setBinYards] = useState<pond.BinYardSettings[]>(props.yards ? props.yards : []);
|
||||
const [menuAnchorEl, setMenuAnchorEl] = useState<Element | null>(null);
|
||||
const [yardIndex, setYardIndex] = useState<number>(0);
|
||||
const [tabClick, setTabClick] = useState<boolean>(true);
|
||||
const [shareDialog, setShareDialog] = useState<boolean>(false);
|
||||
const [userDialog, setUserDialog] = useState<boolean>(false);
|
||||
const [teamDialog, setTeamDialog] = useState<boolean>(false);
|
||||
const [openUpdateYardDialog, setOpenUpdateYardDialog] = useState(false);
|
||||
const { error, warning, success } = useSnackbar();
|
||||
const theme = useTheme();
|
||||
const classes = useStyles();
|
||||
const [leaveYardDialogOpen, setLeaveYardDialogOpen] = useState<boolean>(false);
|
||||
const permissionAPI = usePermissionAPI();
|
||||
const [leaving, setLeaving] = useState<boolean>(false);
|
||||
const [yardPermissions, setYardPermissions] = useState<Dictionary<pond.Permission[]>>({});
|
||||
const [searchSelected, setSearchSelected] = useState(false);
|
||||
const [{ user, as }] = useGlobalState();
|
||||
|
||||
useEffect(() => {
|
||||
if (props.yards && props.yardPerms) {
|
||||
setBinYards(props.yards);
|
||||
setYardPermissions(props.yardPerms);
|
||||
return;
|
||||
}
|
||||
}, [props.yards, props.yardPerms]);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (props.tab && binYards.length > 1) {
|
||||
// setYardFilter(binYards[props.tab - 1].key);
|
||||
// }
|
||||
// }, [props.tab, binYards, setYardFilter, loadYards]);
|
||||
|
||||
const tabChange = (i: number) => {
|
||||
if (tab === i) return;
|
||||
if (i === binYards.length + 2) return;
|
||||
if (tabClick !== true) return;
|
||||
setTab(i);
|
||||
setYardFilter("");
|
||||
if (i > 1 && i <= binYards.length + 1) {
|
||||
setYardFilter(binYards[i - 2].key);
|
||||
}
|
||||
};
|
||||
|
||||
const submitYard = () => {
|
||||
let newBinYard = pond.BinYardSettings.create();
|
||||
newBinYard.name = addYardName;
|
||||
newBinYard.description = addYardDescription;
|
||||
newBinYard.owner = user.id();
|
||||
newBinYard.userSort[user.id()] = binYards.length + 1;
|
||||
binYardAPI
|
||||
.addBinYard(newBinYard)
|
||||
.then(_resp => {
|
||||
loadYards();
|
||||
setShowAddYard(false);
|
||||
openSnackbar("success", "Bin Yard created :)");
|
||||
})
|
||||
.catch(_err => {
|
||||
error("Could not add bin yard");
|
||||
});
|
||||
};
|
||||
|
||||
const updateYard = () => {
|
||||
let newBinYard = binYards[yardIndex];
|
||||
newBinYard.name = addYardName;
|
||||
newBinYard.description = addYardDescription;
|
||||
binYardAPI
|
||||
.updateBinYard(newBinYard.key, newBinYard)
|
||||
.then(_resp => {
|
||||
loadYards();
|
||||
openSnackbar("success", "Bin Yard updated");
|
||||
setOpenUpdateYardDialog(false);
|
||||
})
|
||||
.catch(_err => {
|
||||
error("Could not update bin yard");
|
||||
setOpenUpdateYardDialog(false);
|
||||
});
|
||||
};
|
||||
|
||||
const yardForm = () => {
|
||||
return (
|
||||
<DialogContent>
|
||||
<DialogContentText style={{ paddingBottom: theme.spacing(0) }}>
|
||||
Bin yards allow you to organise your bins by tab. Bins created while a bin yard tab is
|
||||
opened will automatically be added to that bin yard. You may also choose a yard for a bin
|
||||
in the bin settings page.
|
||||
</DialogContentText>
|
||||
<TextField
|
||||
label={"Yard Name"}
|
||||
value={addYardName}
|
||||
onChange={event => setAddYardName(event.target.value)}
|
||||
style={{ marginTop: theme.spacing(0) }}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
/>
|
||||
<DialogContentText
|
||||
style={{ paddingBottom: theme.spacing(0), paddingTop: theme.spacing(3) }}>
|
||||
Bin yard description (optional):
|
||||
</DialogContentText>
|
||||
<TextField
|
||||
label={"Description"}
|
||||
value={addYardDescription}
|
||||
onChange={event => setAddYardDescription(event.target.value)}
|
||||
style={{ marginTop: theme.spacing(0) }}
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
/>
|
||||
</DialogContent>
|
||||
);
|
||||
};
|
||||
|
||||
const addYardDialog = () => {
|
||||
return (
|
||||
<ResponsiveDialog open={showAddYard} onClose={() => setShowAddYard(false)}>
|
||||
<DialogTitle>Create New Bin Yard</DialogTitle>
|
||||
{yardForm()}
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setShowAddYard(false);
|
||||
}}
|
||||
color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={submitYard} color="primary">
|
||||
Submit
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
};
|
||||
|
||||
const updateYardDialog = () => {
|
||||
return (
|
||||
<ResponsiveDialog open={openUpdateYardDialog} onClose={() => setOpenUpdateYardDialog(false)}>
|
||||
<DialogTitle>Update Bin Yard</DialogTitle>
|
||||
{yardForm()}
|
||||
<DialogActions>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setOpenUpdateYardDialog(false);
|
||||
}}
|
||||
color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={updateYard} color="primary">
|
||||
Update
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
};
|
||||
|
||||
const deleteYard = (index: number) => {
|
||||
let newBinYards = binYards;
|
||||
binYardAPI
|
||||
.removeBinYard(binYards[index].key)
|
||||
.then(resp => {
|
||||
newBinYards.splice(index, 1);
|
||||
if (index + 1 === tab) {
|
||||
tabChange(0);
|
||||
} else if (index + 1 < tab) {
|
||||
tabChange(tab - 1);
|
||||
}
|
||||
setBinYards([...newBinYards]);
|
||||
})
|
||||
.catch(err => {
|
||||
error("Failed to delete bin yard");
|
||||
});
|
||||
};
|
||||
|
||||
const moveLeft = (index: number) => {
|
||||
let key = as ? as : user.id();
|
||||
if (binYards[index - 1]) {
|
||||
let left = binYards[index - 1].userSort[key] ?? index - 1;
|
||||
let right = binYards[index].userSort[key] ?? index;
|
||||
let binLeft = binYards[index - 1];
|
||||
let binRight = binYards[index];
|
||||
binLeft.userSort[key] = right;
|
||||
binRight.userSort[key] = left;
|
||||
if (binRight.userSort[key] >= binLeft.userSort[key]) {
|
||||
binLeft.userSort[key] = binRight.userSort[key] + 1;
|
||||
}
|
||||
let leftPromise = binYardAPI.updateBinYard(binLeft.key, binLeft, true);
|
||||
let rightPromise = binYardAPI.updateBinYard(binRight.key, binRight, true);
|
||||
Promise.all([leftPromise, rightPromise]).then((/*[leftResp, rightResp]*/) => {
|
||||
loadYards();
|
||||
if (index === tab - 1) setTab(tab - 1);
|
||||
if (index === tab) setTab(tab + 1);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const moveRight = (index: number) => {
|
||||
let key = as ? as : user.id();
|
||||
if (binYards[index + 1]) {
|
||||
let left = binYards[index].userSort[key] ?? index;
|
||||
let right = binYards[index + 1].userSort[key] ?? index + 1;
|
||||
let binLeft = binYards[index];
|
||||
let binRight = binYards[index + 1];
|
||||
binLeft.userSort[key] = right;
|
||||
binRight.userSort[key] = left;
|
||||
if (binRight.userSort[key] <= binLeft.userSort[key]) {
|
||||
binRight.userSort[key] = binLeft.userSort[key] - 1;
|
||||
}
|
||||
let leftPromise = binYardAPI.updateBinYard(binLeft.key, binLeft, true);
|
||||
let rightPromise = binYardAPI.updateBinYard(binRight.key, binRight, true);
|
||||
Promise.all([leftPromise, rightPromise]).then((/*[leftResp, rightResp]*/) => {
|
||||
loadYards();
|
||||
if (index === tab - 1) setTab(tab + 1);
|
||||
if (index === tab - 2) setTab(tab - 1);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const openShareDialog = () => {
|
||||
setShareDialog(true);
|
||||
};
|
||||
|
||||
const leaveYardDialog = () => {
|
||||
if (!binYards[yardIndex]) return;
|
||||
let label = binYards[yardIndex].name;
|
||||
return (
|
||||
<Dialog
|
||||
open={leaveYardDialogOpen}
|
||||
onClose={() => setLeaveYardDialogOpen(false)}
|
||||
aria-labelledby="remove-self-from-object">
|
||||
<DialogTitle id="remove-self-from-object">{"Leave " + label + "?"}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography color="textSecondary" align="left" variant="subtitle1">
|
||||
You will no longer be able to access {label}. You will also lose access to all bins in{" "}
|
||||
{label} that you do not own.
|
||||
</Typography>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setLeaveYardDialogOpen(false)} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button onClick={leaveYard} color="primary" autoFocus>
|
||||
Leave
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
const leaveYard = () => {
|
||||
updateYardPermissions();
|
||||
};
|
||||
|
||||
const updateYardPermissions = (users?: User[] | Team[]) => {
|
||||
if (leaving) return;
|
||||
setLeaving(true);
|
||||
let binSuccess = true;
|
||||
setLeaving(true);
|
||||
binAPI.listBins(150, 0, "asc", "name", binYards[yardIndex].key).then(resp => {
|
||||
resp.data.bins.forEach(bin => {
|
||||
if (bin.settings) {
|
||||
let scope = binScope(bin.settings?.key);
|
||||
users = users
|
||||
? users
|
||||
: [
|
||||
User.create(
|
||||
pond.User.create({
|
||||
settings: pond.UserSettings.create({
|
||||
id: user.id()
|
||||
}),
|
||||
permissions: []
|
||||
})
|
||||
)
|
||||
];
|
||||
permissionAPI.updatePermissions(scope, users).catch(_ => {
|
||||
binSuccess = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
if (binSuccess) {
|
||||
let scope = binYardScope(binYards[yardIndex].key);
|
||||
let label = binYards[yardIndex].name;
|
||||
users = users
|
||||
? users
|
||||
: [
|
||||
User.create(
|
||||
pond.User.create({
|
||||
settings: pond.UserSettings.create({
|
||||
id: user.id()
|
||||
}),
|
||||
permissions: []
|
||||
})
|
||||
)
|
||||
];
|
||||
permissionAPI
|
||||
.updatePermissions(scope, users)
|
||||
.then((response: any) => {
|
||||
success("Successfully updated permissions for " + label);
|
||||
setLeaveYardDialogOpen(false);
|
||||
loadYards();
|
||||
loadBins();
|
||||
tabChange(0);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
err.response.data.error
|
||||
? warning(err.response.data.error)
|
||||
: error("Error occured when updating permissions for " + label);
|
||||
setLeaveYardDialogOpen(false);
|
||||
})
|
||||
.finally(() => {
|
||||
setLeaving(false);
|
||||
});
|
||||
} else {
|
||||
error("Error updating permissions on one or more bins");
|
||||
setLeaving(false);
|
||||
}
|
||||
};
|
||||
|
||||
const yardMenu = () => {
|
||||
let permissions: pond.Permission[] = [];
|
||||
if (binYards[yardIndex] === undefined) return;
|
||||
if (yardPermissions[binYards[yardIndex].key] !== undefined) {
|
||||
permissions = yardPermissions[binYards[yardIndex].key];
|
||||
}
|
||||
return (
|
||||
<Menu
|
||||
id="yardMenu"
|
||||
anchorEl={menuAnchorEl ? menuAnchorEl : null}
|
||||
open={menuAnchorEl !== null}
|
||||
onClose={() => {
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
disableAutoFocusItem>
|
||||
{permissions.includes(pond.Permission.PERMISSION_WRITE) && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setOpenUpdateYardDialog(true);
|
||||
setAddYardName(binYards[yardIndex].name);
|
||||
setAddYardDescription(binYards[yardIndex].description);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Edit Yard"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<EditIcon className={classes.green} />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Edit Yard" />
|
||||
</MenuItem>
|
||||
)}
|
||||
{permissions.includes(pond.Permission.PERMISSION_SHARE) && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setMenuAnchorEl(null);
|
||||
openShareDialog();
|
||||
}}
|
||||
aria-label="Share Yard"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<ShareIcon className={classes.blue} />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Share Yard" />
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
moveLeft(yardIndex);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Move Left"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<KeyboardArrowLeftIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Move Left" />
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
moveRight(yardIndex);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Move Right"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<KeyboardArrowRightIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Move Right" />
|
||||
</MenuItem>
|
||||
{permissions.includes(pond.Permission.PERMISSION_USERS) && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setUserDialog(true);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Users"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<ObjectUsersIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Users" />
|
||||
</MenuItem>
|
||||
)}
|
||||
{permissions.includes(pond.Permission.PERMISSION_USERS) && (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setTeamDialog(true);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Teams"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<ObjectUsersIcon />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Teams" />
|
||||
</MenuItem>
|
||||
)}
|
||||
{permissions.includes(pond.Permission.PERMISSION_SHARE) &&
|
||||
permissions.includes(pond.Permission.PERMISSION_READ) &&
|
||||
permissions.includes(pond.Permission.PERMISSION_USERS) &&
|
||||
permissions.includes(pond.Permission.PERMISSION_WRITE) ? (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
deleteYard(yardIndex);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Delete Yard"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<DeleteIcon className={classes.red} />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Delete Yard" />
|
||||
</MenuItem>
|
||||
) : (
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setLeaveYardDialogOpen(true);
|
||||
setMenuAnchorEl(null);
|
||||
}}
|
||||
aria-label="Leave Yard"
|
||||
dense>
|
||||
<ListItemIcon>
|
||||
<RemoveSelfIcon className={classes.red} />
|
||||
</ListItemIcon>
|
||||
<ListItemText secondary="Leave Yard" />
|
||||
</MenuItem>
|
||||
)}
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
||||
let permissions: pond.Permission[] = [];
|
||||
if (binYards[yardIndex] !== undefined) {
|
||||
permissions = yardPermissions[binYards[yardIndex].key] || [];
|
||||
}
|
||||
return (
|
||||
<AppBar
|
||||
position="sticky"
|
||||
elevation={0}
|
||||
style={props.showTabs ? {} : { visibility: "hidden", height: 0 }}>
|
||||
{addYardDialog()}
|
||||
{updateYardDialog()}
|
||||
{yardMenu()}
|
||||
{leaveYardDialog()}
|
||||
{binYards[yardIndex] && (
|
||||
<ShareObject
|
||||
scope={binYardScope(binYards[yardIndex].key)}
|
||||
label={binYards[yardIndex].name}
|
||||
permissions={permissions}
|
||||
isDialogOpen={shareDialog}
|
||||
closeDialogCallback={() => setShareDialog(false)}
|
||||
/>
|
||||
)}
|
||||
{binYards[yardIndex] && (
|
||||
<ObjectUsers
|
||||
scope={binYardScope(binYards[yardIndex].key)}
|
||||
label={binYards[yardIndex].name}
|
||||
permissions={permissions}
|
||||
isDialogOpen={userDialog}
|
||||
closeDialogCallback={() => setUserDialog(false)}
|
||||
refreshCallback={() => {}}
|
||||
userCallback={updateYardPermissions}
|
||||
dialog={
|
||||
"Updating a user's permissions for this bin yard will update the same permissions for all corresponding bins."
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{binYards[yardIndex] && (
|
||||
<ObjectTeams
|
||||
scope={binYardScope(binYards[yardIndex].key)}
|
||||
label={binYards[yardIndex].name}
|
||||
permissions={permissions}
|
||||
isDialogOpen={teamDialog}
|
||||
closeDialogCallback={() => setTeamDialog(false)}
|
||||
refreshCallback={() => {}}
|
||||
userCallback={updateYardPermissions}
|
||||
dialog={
|
||||
"Updating a user's permissions for this bin yard will update the same permissions for all corresponding bins."
|
||||
}
|
||||
/>
|
||||
)}
|
||||
<Tabs
|
||||
variant="scrollable"
|
||||
scrollButtons="auto"
|
||||
value={tab}
|
||||
TabIndicatorProps={{ style: { background: "rgba(0,0,0,0)" } }}
|
||||
onChange={(_, newValue) => {
|
||||
if (+newValue > 0) {
|
||||
tabChange(newValue);
|
||||
}
|
||||
}}>
|
||||
<Tab
|
||||
className={searchSelected ? classes.searchTabExpanded : classes.searchTab}
|
||||
disableTouchRipple
|
||||
disableFocusRipple
|
||||
label={
|
||||
<Grid container direction="row" wrap="nowrap" spacing={2}>
|
||||
<Grid item>{yardsLoading ? <CircularProgress size={20} /> : <Search />}</Grid>
|
||||
{searchSelected && (
|
||||
<Grid item>
|
||||
<TextField
|
||||
onChange={e => {
|
||||
loadYards(e.target.value);
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
)}
|
||||
</Grid>
|
||||
}
|
||||
onClick={e => {
|
||||
setSearchSelected(true);
|
||||
}}
|
||||
/>
|
||||
<Tab
|
||||
classes={{ root: classes.smallTab, selected: classes.selectedTab }}
|
||||
style={{ marginLeft: theme.spacing(1) }}
|
||||
label="All"
|
||||
disableTouchRipple={true}
|
||||
onClick={() => {
|
||||
setShowing("all");
|
||||
}}
|
||||
/>
|
||||
{binYards.map((n, index) => (
|
||||
<Tooltip
|
||||
title={
|
||||
n.description ? (
|
||||
<React.Fragment>
|
||||
<div style={{ fontWeight: "bold" }}>{n.name}</div>
|
||||
<div style={{ marginTop: theme.spacing(0.25) }}>{n.description}</div>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
n.name
|
||||
)
|
||||
}
|
||||
key={index}>
|
||||
<Tab
|
||||
classes={{ root: classes.tab, selected: classes.selectedTab }}
|
||||
key={index}
|
||||
disableTouchRipple={true}
|
||||
onClick={() => {
|
||||
setShowing("bins");
|
||||
}}
|
||||
label={
|
||||
<span>
|
||||
<div className={classes.tabText}>{n.name}</div>
|
||||
<MoreVert
|
||||
onMouseEnter={() => setTabClick(false)}
|
||||
onMouseLeave={() => setTabClick(true)}
|
||||
className={classes.icon}
|
||||
onClick={event => {
|
||||
let target = event.currentTarget;
|
||||
setMenuAnchorEl(target);
|
||||
setYardIndex(index);
|
||||
}}
|
||||
/>
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
))}
|
||||
<Tab
|
||||
classes={{ root: classes.smallTab, selected: classes.selectedTab }}
|
||||
// fullWidth={false}
|
||||
label={<AddIcon color="primary"/>}
|
||||
onClick={() => setShowAddYard(true)}
|
||||
disableTouchRipple={true}
|
||||
/>
|
||||
{/* {grainBags.length > 0 && (
|
||||
<Tab
|
||||
classes={{ root: classes.smallTab, selected: classes.selectedTab }}
|
||||
style={{ marginLeft: theme.spacing(1) }}
|
||||
label="Bags"
|
||||
disableTouchRipple={true}
|
||||
onClick={() => {
|
||||
setShowing("bags");
|
||||
}}
|
||||
/>
|
||||
)} */}
|
||||
</Tabs>
|
||||
</AppBar>
|
||||
);
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ export function ImgIcon(props: Props) {
|
|||
src={src}
|
||||
color="transparent"
|
||||
style={style}
|
||||
loading="lazy"
|
||||
/>
|
||||
</Icon>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ import { GrainBag } from "models/GrainBag";
|
|||
import { getThemeType } from "theme/themeType";
|
||||
import GrainBagSettings from "grainBag/grainBagSettings";
|
||||
import GrainBagList from "grainBag/grainBagList";
|
||||
import BinYards from "bin/BinYards";
|
||||
// import { useHistory } from "react-router";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
|
|
@ -1315,7 +1316,7 @@ export default function Bins(props: Props) {
|
|||
return (
|
||||
<Box>
|
||||
{addALertsDialog()}
|
||||
{/* <BinYard
|
||||
<BinYards
|
||||
yards={yards}
|
||||
yardsLoading={yardsLoading}
|
||||
yardPerms={yardPermissions}
|
||||
|
|
@ -1330,7 +1331,7 @@ export default function Bins(props: Props) {
|
|||
setShowing={(val: "all" | "bins" | "bags") => {
|
||||
setShowing(val);
|
||||
}}
|
||||
/> */}
|
||||
/>
|
||||
<Box height={1}>
|
||||
<Box
|
||||
paddingY={isMobile || props.insert ? 0.5 : 1}
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ export default function ShareObject(props: Props) {
|
|||
resp.data.bins.forEach(bin => {
|
||||
if (bin.settings) {
|
||||
let newScope = binScope(bin.settings?.key);
|
||||
permissionAPI.shareObjectByKey(newScope, teamKey, sharedPermissions).catch(err => {
|
||||
permissionAPI.shareObjectByKey(newScope, teamKey, sharedPermissions).catch(_err => {
|
||||
successBins = false;
|
||||
});
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ export default function ShareObject(props: Props) {
|
|||
resp.data.gates.forEach(gate => {
|
||||
if (gate) {
|
||||
let newScope = { key: gate.key, kind: "gate" } as Scope;
|
||||
permissionAPI.shareObjectByKey(newScope, teamKey, sharedPermissions).catch(err => {
|
||||
permissionAPI.shareObjectByKey(newScope, teamKey, sharedPermissions).catch(_err => {
|
||||
successGates = false;
|
||||
});
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ export default function ShareObject(props: Props) {
|
|||
);
|
||||
setShareableLinks(rShareableLinks);
|
||||
})
|
||||
.catch((error: any) => {
|
||||
.catch((_error: any) => {
|
||||
setShareableLinks([]);
|
||||
console.log("Error occured while loading shareable links");
|
||||
})
|
||||
|
|
@ -228,10 +228,10 @@ export default function ShareObject(props: Props) {
|
|||
const expiration = isNewLinkInfinite ? getNeverExpires() : newLinkExpiration.toISOString();
|
||||
permissionAPI
|
||||
.addShareableLink(scope, expiration)
|
||||
.then((response: any) => {
|
||||
.then((_response: any) => {
|
||||
loadShareableLinks();
|
||||
})
|
||||
.catch((error: any) => {
|
||||
.catch((_error: any) => {
|
||||
console.log("Error occured while creating shareable link");
|
||||
});
|
||||
};
|
||||
|
|
@ -239,10 +239,10 @@ export default function ShareObject(props: Props) {
|
|||
const revokeShareableLink = (code: string) => {
|
||||
permissionAPI
|
||||
.removeShareableLink(scope, code)
|
||||
.then((response: any) => {
|
||||
.then((_response: any) => {
|
||||
loadShareableLinks();
|
||||
})
|
||||
.catch((error: any) => {
|
||||
.catch((_error: any) => {
|
||||
console.log("Error occured while removing the shareable link");
|
||||
});
|
||||
};
|
||||
|
|
@ -297,7 +297,7 @@ export default function ShareObject(props: Props) {
|
|||
setSharedPermissions(updatedSharedPermissions);
|
||||
};
|
||||
|
||||
const changeTab = (event: any, newTab: number) => {
|
||||
const changeTab = (_event: any, newTab: number) => {
|
||||
setTab(newTab);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ export default function Editor(props: Props) {
|
|||
setMouseDown(true);
|
||||
};
|
||||
|
||||
const mouseUp = (e: any) => {
|
||||
const mouseUp = (_e: any) => {
|
||||
setMouseDown(false);
|
||||
if (mode === Mode.NORMAL && selected !== undefined) {
|
||||
let state = [...moveOrigin];
|
||||
|
|
@ -522,7 +522,7 @@ export default function Editor(props: Props) {
|
|||
};
|
||||
|
||||
const drawBlocks = (context: CanvasRenderingContext2D) => {
|
||||
blocks.forEach((block, index) => {
|
||||
blocks.forEach(block => {
|
||||
if (block.draw) block.draw(context, cameraOffsetX, cameraOffsetY, scale);
|
||||
});
|
||||
selected.forEach(block => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue