import { Tab, Tabs, Button, Theme, useTheme, Menu, MenuItem, ListItemIcon, ListItemText, DialogTitle, DialogContent, DialogActions } from "@mui/material"; import { Terminal } from "models"; import { useTerminalAPI, useGlobalState } from "providers"; import React, { useCallback, useEffect, useState } from "react"; import PageContainer from "./PageContainer"; import AddIcon from "@mui/icons-material/Add"; import TerminalSettings from "terminal/TerminalSettings"; import { Delete, MoreVert, ExitToApp as RemoveSelfIcon } from "@mui/icons-material"; import EditIcon from "@mui/icons-material/Edit"; import { blue, green, red } from "@mui/material/colors"; import ResponsiveDialog from "common/ResponsiveDialog"; import { useSnackbar, useUserAPI } from "hooks"; import GateList from "gate/GateList"; import { Scope } from "models"; import { pond } from "protobuf-ts/pond"; import ObjectUsers from "user/ObjectUsers"; import ObjectTeams from "teams/ObjectTeams"; import ObjectUsersIcon from "@mui/icons-material/AccountCircle"; import ObjectTeamsIcon from "@mui/icons-material/SupervisedUserCircle"; import ShareObject from "user/ShareObject"; import RemoveSelfFromObject from "user/RemoveSelfFromObject"; 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) => ({ tab: { ...parentTab, minWidth: theme.spacing(25), 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%)" } }, 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 }, 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))" } }, green: { marginRight: 0, paddingRight: 0, color: green["500"], "&:hover": { color: green["600"] } }, red: { marginRight: 0, paddingRight: 0, color: red["500"], "&:hover": { color: red["600"] } }, blueIcon: { color: blue["500"], "&:hover": { color: blue["600"] } }, addGate: { position: "absolute", bottom: 20, right: 20, backgroundColor: theme.palette.primary.main } })); interface Props { terminal?: Terminal; } export default function Terminals(props: Props) { const terminalAPI = useTerminalAPI(); const [value, setValue] = useState(0); const [terminals, setTerminals] = useState([]); const classes = useStyles(); const theme = useTheme(); const [addTerminal, setAddTerminal] = useState(false); const [menuAnchorEl, setMenuAnchorEl] = useState(null); const [currentTerminal, setCurrentTerminal] = useState(); const [removeTerminal, setRemoveTerminal] = useState(false); const { openSnack } = useSnackbar(); const [{ user, as }] = useGlobalState(); const userAPI = useUserAPI(); const [permissions, setPermissions] = useState([]); const [userSharing, setUserSharing] = useState(false); const [teamSharing, setTeamSharing] = useState(false); const [baseShareDialog, setBaseShareDialog] = useState(false); const [removeSelfDialog, setRemoveSelfDialog] = useState(false); const [loading, setLoading] = useState(false) useEffect(() => { if (currentTerminal) { let key = currentTerminal?.key; let kind = "terminal"; if (as) { key = as; kind = "team"; } userAPI.getUser(user.id(), { key: key, kind: kind } as Scope).then(resp => { setPermissions(resp.permissions); }); } }, [as, userAPI, user, currentTerminal]); useEffect(() => { if (props.terminal) { setCurrentTerminal(props.terminal); } }, [props.terminal]); const load = useCallback(() => { if(loading) return setLoading(true) terminalAPI.listTerminals(200, 0, "asc", "name", as).then(resp => { setTerminals(resp.data.terminals.map(a => Terminal.any(a))); }).catch(err => { console.log("There was a problem loading Terminals") }).finally(() => { setLoading(false) }) }, [terminalAPI, openSnack, as]); //eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { load(); }, [load]); const remove = () => { if (currentTerminal) { terminalAPI .removeTerminal(currentTerminal.key, as) .then(resp => { openSnack("Terminal Deleted"); let a = terminals; a.splice(terminals.indexOf(currentTerminal), 1); setTerminals([...a]); }) .catch(err => { openSnack("Failed to delete terminal"); }) .finally(() => { setRemoveTerminal(false); }); } }; const terminalMenu = () => { if (currentTerminal === undefined) return; return ( { setMenuAnchorEl(null); }}> {permissions.includes(pond.Permission.PERMISSION_WRITE) && ( { setAddTerminal(true); setMenuAnchorEl(null); }} aria-label="Edit Terminal" dense> )} {permissions.includes(pond.Permission.PERMISSION_WRITE) && ( { setRemoveTerminal(true); setMenuAnchorEl(null); }} aria-label="Remove Terminal" dense> )} {permissions.includes(pond.Permission.PERMISSION_USERS) && ( { setUserSharing(true); setMenuAnchorEl(null); }}> )} {permissions.includes(pond.Permission.PERMISSION_USERS) && ( { setTeamSharing(true); setMenuAnchorEl(null); }}> )} { setRemoveSelfDialog(true); setMenuAnchorEl(null); }}> ); }; const changeTabs = (newValue: number) => { //TODO: change this to just change the selected tab if (newValue <= terminals.length) { setValue(newValue); if (terminals[newValue - 1]) { setCurrentTerminal(terminals[newValue -1]) } else { setCurrentTerminal(undefined) } } }; const gateDisplay = () => { return ( ); }; //could update the tabs in the same way as the bin yard tabs const terminalTabs = () => { return ( {/* TODO: convert this to use DraggableTabs */} changeTabs(v)} TabIndicatorProps={{ style: { background: "rgba(0,0,0,0)" } }}> {terminals.map((a, index) => (
{a.name}
{ event.stopPropagation() let target = event.currentTarget; setMenuAnchorEl(target); setCurrentTerminal(terminals[index]); }} /> } /> ))} } onClick={() => { setCurrentTerminal(undefined); setAddTerminal(true); }} disableTouchRipple={true} />
); }; const removeDialog = () => { return ( { setRemoveTerminal(false); }}> Delete Terminal Are you sure you wish to delete this Terminal? ); }; const sharingDialogs = () => { if (!currentTerminal) return; return ( { setBaseShareDialog(false); }} /> setUserSharing(false)} refreshCallback={() => {}} /> setTeamSharing(false)} refreshCallback={() => { return true; }} /> { if (removed) { let a = terminals; a.splice(terminals.indexOf(currentTerminal), 1); setTerminals([...a]); } setRemoveSelfDialog(false); }} /> ); }; return ( { if (newTerminal) { let a = terminals; a.push(newTerminal); setTerminals([...a]); } setAddTerminal(false); }} terminal={currentTerminal} /> {!props.terminal && terminalTabs()} {terminalMenu()} {removeDialog()} {sharingDialogs()} {gateDisplay()} ); }