fix: widget options are now opening (#2141)

This commit is contained in:
Palash Gupta 2023-01-30 18:06:49 +05:30 committed by GitHub
parent b72815ca2f
commit b336a6cb45
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 109 additions and 71 deletions

View File

@ -10,4 +10,13 @@ export const tooltipStyles = {
right: '0.313rem',
color: themeColors.errorColor,
};
export const errorTooltipPosition = 'top';
export const overlayStyles: React.CSSProperties = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
};

View File

@ -5,11 +5,12 @@ import {
ExclamationCircleOutlined,
FullscreenOutlined,
} from '@ant-design/icons';
import { Dropdown, Menu, Tooltip, Typography } from 'antd';
import { Dropdown, MenuProps, Tooltip, Typography } from 'antd';
import { MenuItemType } from 'antd/es/menu/hooks/useItems';
import Spinner from 'components/Spinner';
import useComponentPermission from 'hooks/useComponentPermission';
import history from 'lib/history';
import React, { useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { UseQueryResult } from 'react-query';
import { useSelector } from 'react-redux';
import { AppState } from 'store/reducers';
@ -18,12 +19,16 @@ import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import AppReducer from 'types/reducer/app';
import { errorTooltipPosition, spinnerStyles, tooltipStyles } from './config';
import {
errorTooltipPosition,
overlayStyles,
spinnerStyles,
tooltipStyles,
} from './config';
import {
ArrowContainer,
HeaderContainer,
HeaderContentContainer,
MenuItemContainer,
} from './styles';
type TWidgetOptions = 'view' | 'edit' | 'delete' | string;
@ -48,17 +53,19 @@ function WidgetHeader({
errorMessage,
}: IWidgetHeaderProps): JSX.Element {
const [localHover, setLocalHover] = useState(false);
const [isOpen, setIsOpen] = useState<boolean>(false);
const onEditHandler = (): void => {
const onEditHandler = useCallback((): void => {
const widgetId = widget.id;
history.push(
`${window.location.pathname}/new?widgetId=${widgetId}&graphType=${widget.panelTypes}`,
);
};
}, [widget.id, widget.panelTypes]);
const keyMethodMapping: {
[K in TWidgetOptions]: { key: TWidgetOptions; method: VoidFunction };
} = {
} = useMemo(
() => ({
view: {
key: 'view',
method: onView,
@ -71,10 +78,20 @@ function WidgetHeader({
key: 'delete',
method: onDelete,
},
};
const onMenuItemSelectHandler = ({ key }: { key: TWidgetOptions }): void => {
keyMethodMapping[key]?.method();
};
}),
[onDelete, onEditHandler, onView],
);
const onMenuItemSelectHandler: MenuProps['onClick'] = useCallback(
({ key }: { key: TWidgetOptions }): void => {
const functionToCall = keyMethodMapping[key]?.method;
if (functionToCall) {
functionToCall();
setIsOpen(false);
}
},
[keyMethodMapping],
);
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
const [deleteWidget, editWidget] = useComponentPermission(
@ -82,49 +99,67 @@ function WidgetHeader({
role,
);
const menu = (
<Menu onClick={onMenuItemSelectHandler}>
<Menu.Item key={keyMethodMapping.view.key}>
<MenuItemContainer>
<span>View</span> <FullscreenOutlined />
</MenuItemContainer>
</Menu.Item>
const menuList: MenuItemType[] = useMemo(
() => [
{
key: keyMethodMapping.view.key,
icon: <FullscreenOutlined />,
disabled: queryResponse.isLoading,
label: 'View',
},
{
key: keyMethodMapping.edit.key,
icon: <EditFilled />,
disabled: !editWidget,
label: 'Edit',
},
{
key: keyMethodMapping.delete.key,
icon: <DeleteOutlined />,
disabled: !deleteWidget,
danger: true,
label: 'Delete',
},
],
[
deleteWidget,
editWidget,
keyMethodMapping.delete.key,
keyMethodMapping.edit.key,
keyMethodMapping.view.key,
queryResponse.isLoading,
],
);
{editWidget && (
<Menu.Item key={keyMethodMapping.edit.key}>
<MenuItemContainer>
<span>Edit</span> <EditFilled />
</MenuItemContainer>
</Menu.Item>
)}
const onClickHandler = useCallback(() => {
setIsOpen((open) => !open);
}, []);
{deleteWidget && (
<>
<Menu.Divider />
<Menu.Item key={keyMethodMapping.delete.key} danger>
<MenuItemContainer>
<span>Delete</span> <DeleteOutlined />
</MenuItemContainer>
</Menu.Item>
</>
)}
</Menu>
const menu = useMemo(
() => ({
items: menuList,
onClick: onMenuItemSelectHandler,
}),
[menuList, onMenuItemSelectHandler],
);
return (
<div>
<Dropdown
overlay={menu}
destroyPopupOnHide
open={isOpen}
onOpenChange={setIsOpen}
menu={menu}
trigger={['click']}
overlayStyle={{ minWidth: 100 }}
placement="bottom"
overlayStyle={overlayStyles}
>
<>
<HeaderContainer
onMouseOver={(): void => setLocalHover(true)}
onMouseOut={(): void => setLocalHover(false)}
hover={localHover}
onClick={onClickHandler}
>
<HeaderContentContainer onClick={(e): void => e.preventDefault()}>
<HeaderContentContainer>
<Typography.Text style={{ maxWidth: '80%' }} ellipsis>
{title}
</Typography.Text>
@ -133,6 +168,7 @@ function WidgetHeader({
</ArrowContainer>
</HeaderContentContainer>
</HeaderContainer>
</Dropdown>
{queryResponse.isFetching && !queryResponse.isError && (
<Spinner height="5vh" style={spinnerStyles} />
)}
@ -141,8 +177,7 @@ function WidgetHeader({
<ExclamationCircleOutlined style={tooltipStyles} />
</Tooltip>
)}
</>
</Dropdown>
</div>
);
}

View File

@ -1,12 +1,6 @@
import { grey } from '@ant-design/colors';
import styled from 'styled-components';
export const MenuItemContainer = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`;
export const HeaderContainer = styled.div<{ hover: boolean }>`
width: 100%;
text-align: center;