Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added material-ui-popup-state library #995

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 53 additions & 105 deletions frontend/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,12 @@ import {
} from "@mui/material";
import { OverridableComponent } from "@mui/material/OverridableComponent";
import { styled } from "@mui/material/styles";
import PopupState, { bindHover, bindMenu } from "material-ui-popup-state";
import HoverMenu from "material-ui-popup-state/HoverMenu";
import React, { FC, MouseEvent, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { useInterval } from "react-use";

import { useSimpleSearch } from "../hooks/useSimpleSearch";
import { aironeApiClientV2 } from "../repository/AironeApiClientV2";
import {
JobOperations,
JobRefreshIntervalMilliSec,
JobStatuses,
} from "../services/Constants";
import {
getLatestCheckDate,
jobTargetLabel,
updateLatestCheckDate,
} from "../services/JobUtil";

import { SearchBox } from "./common/SearchBox";

import {
jobsPath,
userPath,
Expand All @@ -47,8 +34,21 @@ import {
rolesPath,
topPath,
} from "Routes";
import { SearchBox } from "components/common/SearchBox";
import { useSimpleSearch } from "hooks/useSimpleSearch";
import { postLogout } from "repository/AironeAPIClient";
import { aironeApiClientV2 } from "repository/AironeApiClientV2";
import {
JobOperations,
JobRefreshIntervalMilliSec,
JobStatuses,
} from "services/Constants";
import { DjangoContext } from "services/DjangoContext";
import {
getLatestCheckDate,
jobTargetLabel,
updateLatestCheckDate,
} from "services/JobUtil";

const Frame = styled(Box)(({}) => ({
width: "100%",
Expand Down Expand Up @@ -117,12 +117,6 @@ export const Header: FC = () => {

const [query, submitQuery] = useSimpleSearch();

const timerDict: any = {};
const [anchorDict, setAnchorDict] = useState<
Record<string, HTMLButtonElement | null>
>({});
const [settingAnchorEl, setSettingAnchorEl] =
useState<HTMLButtonElement | null>();
const [userAnchorEl, setUserAnchorEl] = useState<HTMLButtonElement | null>();
const [jobAnchorEl, setJobAnchorEl] = useState<HTMLButtonElement | null>();
const [latestCheckDate, setLatestCheckDate] = useState<Date | null>(
Expand Down Expand Up @@ -162,29 +156,6 @@ export const Header: FC = () => {
setLatestCheckDate(getLatestCheckDate());
};

// These processings are compromised ones to close Header menus when mouse leave from Menu-button.
// There would be more good solution. please fix it.
const handleCloseMenu = (anchorKey: string) => {
if (timerDict[anchorKey]) {
setAnchorDict({ ...anchorDict, [anchorKey]: null });
timerDict[anchorKey] = null;
}
};
const setCloseTimer = (anchorKey: string) => {
if (!timerDict[anchorKey]) {
const timerId = setTimeout(() => {
handleCloseMenu(anchorKey);
}, 1500);
timerDict[anchorKey] = timerId;
}
};
const clearCloseTimer = (anchorKey: string) => {
if (timerDict[anchorKey]) {
clearTimeout(timerDict[anchorKey]);
timerDict[anchorKey] = null;
}
};

return (
<Frame>
<Fixed>
Expand All @@ -206,71 +177,48 @@ export const Header: FC = () => {
<Button component={Link} to={advancedSearchPath()}>
高度な検索
</Button>
<Button
onMouseOver={(e) => setAnchorDict({ basic: e.currentTarget })}
onMouseLeave={() => setCloseTimer("basic")}
>
管理機能
<KeyboardArrowDownIcon fontSize="small" />
</Button>
<Menu
id="setting-menu"
anchorEl={anchorDict.basic}
open={Boolean(anchorDict.basic)}
onClose={() => setAnchorDict({ ...anchorDict, basic: null })}
MenuListProps={{
onMouseLeave: () =>
setAnchorDict({ ...anchorDict, basic: null }),
onMouseOver: () => clearCloseTimer("basic"),
}}
autoFocus={false}
keepMounted
>
<MenuItem component={Link} to={usersPath()}>
ユーザ管理
</MenuItem>
<MenuItem component={Link} to={groupsPath()}>
グループ管理
</MenuItem>
<MenuItem component={Link} to={rolesPath()}>
ロール管理
</MenuItem>
</Menu>
<PopupState variant="popover" popupId="basic">
{(popupState) => (
<React.Fragment>
<Button {...bindHover(popupState)}>
管理機能
<KeyboardArrowDownIcon fontSize="small" />
</Button>
<HoverMenu {...bindMenu(popupState)}>
<MenuItem component={Link} to={usersPath()}>
ユーザ管理
</MenuItem>
<MenuItem component={Link} to={groupsPath()}>
グループ管理
</MenuItem>
<MenuItem component={Link} to={rolesPath()}>
ロール管理
</MenuItem>
</HoverMenu>
</React.Fragment>
)}
</PopupState>

{/* If there is another menu settings are passed from Server,
this represent another menu*/}
{djangoContext?.extendedHeaderMenus.map((menu, index) => (
<Box key={index}>
<Button
onMouseOver={(e) =>
setAnchorDict({ [menu.name]: e.currentTarget })
}
onMouseLeave={() => setCloseTimer(menu.name)}
>
{menu.name}
<KeyboardArrowDownIcon fontSize="small" />
</Button>
<Menu
anchorEl={anchorDict[menu.name]}
open={Boolean(anchorDict[menu.name])}
onClose={() =>
setAnchorDict({ ...anchorDict, [menu.name]: null })
}
MenuListProps={{
onMouseLeave: () =>
setAnchorDict({ ...anchorDict, [menu.name]: null }),
onMouseOver: () => clearCloseTimer(menu.name),
}}
autoFocus={false}
keepMounted
>
{menu.children.map((child, index) => (
<MenuItem key={index} component="a" href={child.url}>
{child.name}
</MenuItem>
))}
</Menu>
</Box>
<PopupState variant="popover" popupId={menu.name} key={index}>
{(popupState) => (
<React.Fragment>
<Button {...bindHover(popupState)}>
{menu.name}
<KeyboardArrowDownIcon fontSize="small" />
</Button>
<HoverMenu {...bindMenu(popupState)}>
{menu.children.map((child, index) => (
<MenuItem key={index} component="a" href={child.url}>
{child.name}
</MenuItem>
))}
</HoverMenu>
</React.Fragment>
)}
</PopupState>
))}
</MenuBox>

Expand Down
26 changes: 26 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
"ip-num": "^1.4.0",
"js-cookie": "^2.2.1",
"js-file-download": "^0.4.12",
"material-ui-popup-state": "^5.0.10",
"notistack": "^2.0.3",
"react-beautiful-dnd": "^13.1.1",
"react-copy-to-clipboard": "^5.1.0",
Expand Down
Loading