Source

Header/Elements/ProjectMenu.js

import React, { useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from "@material-ui/core/styles";
import FilesDetails from "./FilesDetails";
import CustomTooltip from "../../Utils/DataDisplay/CustomTooltip";
import { StyledIconButton } from "../../Utils/Buttons";
import StyledDivider from "../../Utils/DataDisplay/StyledDivider";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import Typography from "@material-ui/core/Typography";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import DeleteIcon from "@material-ui/icons/Delete";
import RenameBox from "mdi-material-ui/RenameBox";
import SaveAlt from "@material-ui/icons/SaveAlt";
import SvgIcon from "@material-ui/core/SvgIcon";
import {mdiCog} from "@mdi/js";
import styles from "../styles/ProjectMenu.module.css";

const menuStyles = makeStyles(theme => ({
    list: {
        backgroundColor: theme.palette.background.sub,
        color: theme.palette.text.main2
    }
}), {name: "ProjectMenu"});

/**
 * <h3>Overview</h3>
 * The middle part of the {@link Header} that allows user to perform actions on selected project such as:
 * <ul>
 *     <li>changing settings</li>
 *     <li>renaming</li>
 *     <li>downloading</li>
 *     <li>deleting</li>
 * </ul>
 *
 * @constructor
 * @category Header
 * @subcategory Elements
 * @param {Object} props
 * @param {number} props.currentProject - The id of current project.
 * @param {function} props.onProjectClick - Callback fired when one of the projects from the list was clicked on.
 * @param {function} props.onDialogOpen - Callback fired when one of the dialogs requests to be opened.
 * @param {function} props.onSaveProject - Callback fired when user requests to save project.
 * @param {function} props.onSnackbarOpen - Callback fired when the component requests to display an error.
 * @param {Object[]} props.projects - The list of all projects.
 * @param {string} props.serverBase - The host and port in the URL of an API call.
 * @returns {React.ReactElement}
 */
function ProjectMenu(props) {
    const [anchorE1, setAnchorE1] = useState(null);
    const list = useRef(null);
    const menuClasses = menuStyles();

    const { currentProject, projects, serverBase } = props;

    const primaryText = currentProject > 0 ?  "Active project -" : projects[0];
    const displayedProjects = projects.slice(1);

    const onListItemClick = (event) => {
        setAnchorE1(event.currentTarget);
    };

    const onMenuItemClick = (event, index) => {
        setAnchorE1(null);
        const url = window.location.href.toString();
        const urlSplitted = url.split('/');

        if (urlSplitted.length >= 5) {
            props.onProjectClick(index, url.split('/')[4]);
        } else {
            props.onProjectClick(index, "");
        }
    };

    const onMenuClose = () => {
        setAnchorE1(null);
    };

    return (
        <section id={"project-panel"} className={styles.Root}>
            <StyledDivider margin={16} />
            <List component={"div"} disablePadding={true}>
                <ListItem
                    aria-controls={"project-menu"}
                    aria-haspopup={"true"}
                    button={true}
                    disableGutters={true}
                    onClick={onListItemClick}
                    ref={list}
                    style={{
                        borderRadius: 4,
                        paddingLeft: 8,
                        paddingRight: 8
                    }}
                >
                    <Typography style={{marginRight: "0.25em"}} color={"inherit"} variant={"button"}>
                        {primaryText}
                    </Typography>
                    {currentProject > 0 &&
                        <Typography color={"inherit"}>
                            {projects[currentProject].name}
                        </Typography>
                    }
                </ListItem>
            </List>
            {displayedProjects.length > 0 &&
                <Menu
                    anchorEl={anchorE1}
                    anchorOrigin={{
                        horizontal: "center",
                        vertical: "bottom"
                    }}
                    classes={{
                        list: menuClasses.list
                    }}
                    getContentAnchorEl={null}
                    id={"project-menu"}
                    keepMounted={true}
                    onClose={onMenuClose}
                    open={Boolean(anchorE1)}
                    PaperProps={{
                        style: {minWidth: list.current.offsetWidth}
                    }}
                    transformOrigin={{
                        horizontal: "center",
                        vertical: "top",
                    }}
                >
                    {displayedProjects.map((project, index) => (
                        <MenuItem
                            key={index}
                            selected={index === currentProject}
                            onClick={event => onMenuItemClick(event, index)}
                        >
                            {project.name}
                        </MenuItem>
                    ))}
                </Menu>
            }
            {currentProject > 0 ?
                <section className={styles.Buttons}>
                    <FilesDetails
                        onSnackbarOpen={props.onSnackbarOpen}
                        projectId={projects[currentProject].id}
                        serverBase={serverBase}
                        WrapperProps={{ id: "files-details-button" }}
                    />
                    <CustomTooltip
                        title={"Project settings"}
                        WrapperProps={{ id: "project-settings-button" }}
                    >
                        <StyledIconButton
                            aria-label={"project-settings-button"}
                            onClick={() => props.onDialogOpen("settingsDialog")}
                        >
                            <SvgIcon><path d={mdiCog} /></SvgIcon>
                        </StyledIconButton>
                    </CustomTooltip>
                    <CustomTooltip
                        title={"Rename project"}
                        WrapperProps={{ id: "rename-project-button" }}
                    >
                        <StyledIconButton
                            aria-label={"rename-project-button"}
                            onClick={() => props.onDialogOpen("renameDialog")}
                        >
                            <RenameBox />
                        </StyledIconButton>
                    </CustomTooltip>
                    <CustomTooltip
                        title={"Save project to ZIP file"}
                        WrapperProps={{ id: "save-project-button" }}
                    >
                        <StyledIconButton
                            aria-label={"save-project-button"}
                            onClick={props.onSaveProject}
                        >
                            <SaveAlt />
                        </StyledIconButton>
                    </CustomTooltip>
                    <CustomTooltip
                        title={"Delete project"}
                        WrapperProps={{
                            id: "delete-project-button",
                            style: { marginLeft: "auto" }
                        }}
                    >
                        <StyledIconButton
                            aria-label={"delete-project-button"}
                            onClick={() => props.onDialogOpen("deleteDialog")}>
                            <DeleteIcon />
                        </StyledIconButton>
                    </CustomTooltip>
                </section>
                :
                <span style={{ flexGrow: 1 }} />
            }
            <StyledDivider margin={16} />
        </section>
    );
}

ProjectMenu.propTypes = {
    currentProject: PropTypes.number,
    onProjectClick: PropTypes.func,
    onDialogOpen: PropTypes.func,
    onSaveProject: PropTypes.func,
    onSnackbarOpen: PropTypes.func,
    projects: PropTypes.arrayOf(PropTypes.oneOfType([
        PropTypes.string,
        PropTypes.shape({
            result: PropTypes.object,
        })
    ])),
    serverBase: PropTypes.string
};

export default ProjectMenu;