feat: menu header is controlled from menuList rather than boolean for each menu (#3288)

* feat: create alerts method is added

* feat: method is updated for onClick

* chore: create alerts is udpated

* chore: header menu list is updated

* chore: headerMenuList is made optional

* chore: default props is updated
This commit is contained in:
Palash Gupta 2023-08-10 11:44:36 +05:30 committed by GitHub
parent 900752b6e2
commit 3b22698e35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 70 additions and 127 deletions

View File

@ -53,9 +53,7 @@ function WidgetGraphComponent({
setLayout,
onDragSelect,
onClickHandler,
allowClone = true,
allowDelete = true,
allowEdit = true,
headerMenuList,
}: WidgetGraphComponentProps): JSX.Element {
const [deleteModal, setDeleteModal] = useState(false);
const [modal, setModal] = useState<boolean>(false);
@ -281,9 +279,7 @@ function WidgetGraphComponent({
onClone={onCloneHandler}
queryResponse={queryResponse}
errorMessage={errorMessage}
allowClone={allowClone}
allowDelete={allowDelete}
allowEdit={allowEdit}
headerMenuList={headerMenuList}
/>
</div>
)}
@ -313,9 +309,6 @@ WidgetGraphComponent.defaultProps = {
setLayout: undefined,
onDragSelect: undefined,
onClickHandler: undefined,
allowDelete: true,
allowClone: true,
allowEdit: true,
};
const mapDispatchToProps = (

View File

@ -15,6 +15,7 @@ import { GlobalReducer } from 'types/reducer/globalTime';
import { getSelectedDashboardVariable } from 'utils/dashboard/selectedDashboard';
import EmptyWidget from '../EmptyWidget';
import { MenuItemKeys } from '../WidgetHeader/contants';
import { GridCardGraphProps } from './types';
import WidgetGraphComponent from './WidgetGraphComponent';
@ -26,9 +27,7 @@ function GridCardGraph({
setLayout,
onDragSelect,
onClickHandler,
allowDelete,
allowClone,
allowEdit,
headerMenuList = [MenuItemKeys.View],
isQueryEnabled,
}: GridCardGraphProps): JSX.Element {
const { isAddWidget } = useSelector<AppState, DashboardReducer>(
@ -121,9 +120,7 @@ function GridCardGraph({
yAxisUnit={yAxisUnit}
layout={layout}
setLayout={setLayout}
allowClone={allowClone}
allowDelete={allowDelete}
allowEdit={allowEdit}
headerMenuList={headerMenuList}
/>
)}
</span>
@ -145,9 +142,7 @@ function GridCardGraph({
yAxisUnit={yAxisUnit}
layout={layout}
setLayout={setLayout}
allowClone={allowClone}
allowDelete={allowDelete}
allowEdit={allowEdit}
headerMenuList={headerMenuList}
onClickHandler={onClickHandler}
/>
) : (
@ -170,9 +165,7 @@ function GridCardGraph({
name={name}
yAxisUnit={yAxisUnit}
onDragSelect={onDragSelect}
allowClone={allowClone}
allowDelete={allowDelete}
allowEdit={allowEdit}
headerMenuList={headerMenuList}
onClickHandler={onClickHandler}
/>
)}
@ -185,10 +178,8 @@ function GridCardGraph({
GridCardGraph.defaultProps = {
onDragSelect: undefined,
onClickHandler: undefined,
allowDelete: true,
allowClone: true,
allowEdit: true,
isQueryEnabled: true,
headerMenuList: [MenuItemKeys.View],
};
export default memo(GridCardGraph);

View File

@ -10,6 +10,7 @@ import { Widgets } from 'types/api/dashboard/getAll';
import { MetricRangePayloadProps } from 'types/api/metrics/getQueryRange';
import { LayoutProps } from '..';
import { MenuItemKeys } from '../WidgetHeader/contants';
import { LegendEntryProps } from './FullView/types';
export interface GraphVisibilityLegendEntryProps {
@ -38,25 +39,19 @@ export interface WidgetGraphComponentProps extends DispatchProps {
setLayout?: Dispatch<SetStateAction<LayoutProps[]>>;
onDragSelect?: (start: number, end: number) => void;
onClickHandler?: GraphOnClickHandler;
allowDelete?: boolean;
allowClone?: boolean;
allowEdit?: boolean;
headerMenuList: MenuItemKeys[];
}
export interface GridCardGraphProps {
widget: Widgets;
name: string;
yAxisUnit: string | undefined;
// eslint-disable-next-line react/require-default-props
layout?: Layout[];
// eslint-disable-next-line react/require-default-props
setLayout?: Dispatch<SetStateAction<LayoutProps[]>>;
onDragSelect?: (start: number, end: number) => void;
onClickHandler?: GraphOnClickHandler;
allowDelete?: boolean;
allowClone?: boolean;
allowEdit?: boolean;
isQueryEnabled?: boolean;
headerMenuList?: WidgetGraphComponentProps['headerMenuList'];
isQueryEnabled: boolean;
}
export interface GetGraphVisibilityStateOnLegendClickProps {

View File

@ -3,6 +3,7 @@ export enum MenuItemKeys {
Edit = 'edit',
Delete = 'delete',
Clone = 'clone',
CreateAlerts = 'createAlerts',
}
export const MENUITEM_KEYS_VS_LABELS = {
@ -10,4 +11,5 @@ export const MENUITEM_KEYS_VS_LABELS = {
[MenuItemKeys.Edit]: 'Edit',
[MenuItemKeys.Delete]: 'Delete',
[MenuItemKeys.Clone]: 'Clone',
[MenuItemKeys.CreateAlerts]: 'Create Alerts',
};

View File

@ -7,9 +7,9 @@ import {
FullscreenOutlined,
} from '@ant-design/icons';
import { Dropdown, MenuProps, Tooltip, Typography } from 'antd';
import { MenuItemType } from 'antd/es/menu/hooks/useItems';
import Spinner from 'components/Spinner';
import { queryParamNamesMap } from 'constants/queryBuilderQueryNames';
import ROUTES from 'constants/routes';
import useComponentPermission from 'hooks/useComponentPermission';
import history from 'lib/history';
import { useCallback, useMemo, useState } from 'react';
@ -33,7 +33,7 @@ import {
HeaderContainer,
HeaderContentContainer,
} from './styles';
import { KeyMethodMappingProps, MenuItem, TWidgetOptions } from './types';
import { MenuItem } from './types';
import { generateMenuList, isTWidgetOptions } from './utils';
interface IWidgetHeaderProps {
@ -47,10 +47,9 @@ interface IWidgetHeaderProps {
SuccessResponse<MetricRangePayloadProps> | ErrorResponse
>;
errorMessage: string | undefined;
allowDelete?: boolean;
allowClone?: boolean;
allowEdit?: boolean;
headerMenuList?: MenuItemKeys[];
}
function WidgetHeader({
title,
widget,
@ -60,9 +59,7 @@ function WidgetHeader({
parentHover,
queryResponse,
errorMessage,
allowClone = true,
allowDelete = true,
allowEdit = true,
headerMenuList,
}: IWidgetHeaderProps): JSX.Element {
const [localHover, setLocalHover] = useState(false);
const [isOpen, setIsOpen] = useState<boolean>(false);
@ -78,32 +75,30 @@ function WidgetHeader({
);
}, [widget.id, widget.panelTypes, widget.query]);
const keyMethodMapping: KeyMethodMappingProps<TWidgetOptions> = useMemo(
const onCreateAlertsHandler = useCallback(() => {
history.push(
`${ROUTES.ALERTS_NEW}?${
queryParamNamesMap.compositeQuery
}=${encodeURIComponent(JSON.stringify(widget.query))}`,
);
}, [widget]);
const keyMethodMapping = useMemo(
() => ({
view: {
key: MenuItemKeys.View,
method: onView,
},
edit: {
key: MenuItemKeys.Edit,
method: onEditHandler,
},
delete: {
key: MenuItemKeys.Delete,
method: onDelete,
},
clone: {
key: MenuItemKeys.Clone,
method: onClone,
},
[MenuItemKeys.View]: onView,
[MenuItemKeys.Edit]: onEditHandler,
[MenuItemKeys.Delete]: onDelete,
[MenuItemKeys.Clone]: onClone,
[MenuItemKeys.CreateAlerts]: onCreateAlertsHandler,
}),
[onDelete, onEditHandler, onView, onClone],
[onDelete, onEditHandler, onView, onClone, onCreateAlertsHandler],
);
const onMenuItemSelectHandler: MenuProps['onClick'] = useCallback(
({ key }: { key: string }): void => {
if (isTWidgetOptions(key)) {
const functionToCall = keyMethodMapping[key]?.method;
const functionToCall = keyMethodMapping[key];
if (functionToCall) {
functionToCall();
setIsOpen(false);
@ -125,46 +120,43 @@ function WidgetHeader({
key: MenuItemKeys.View,
icon: <FullscreenOutlined />,
label: MENUITEM_KEYS_VS_LABELS[MenuItemKeys.View],
isVisible: true,
isVisible: headerMenuList?.includes(MenuItemKeys.View) || false,
disabled: queryResponse.isLoading,
},
{
key: MenuItemKeys.Edit,
icon: <EditFilled />,
label: MENUITEM_KEYS_VS_LABELS[MenuItemKeys.Edit],
isVisible: allowEdit,
isVisible: headerMenuList?.includes(MenuItemKeys.Edit) || false,
disabled: !editWidget,
},
{
key: MenuItemKeys.Clone,
icon: <CopyOutlined />,
label: MENUITEM_KEYS_VS_LABELS[MenuItemKeys.Clone],
isVisible: allowClone,
isVisible: headerMenuList?.includes(MenuItemKeys.Clone) || false,
disabled: !editWidget,
},
{
key: MenuItemKeys.Delete,
icon: <DeleteOutlined />,
label: MENUITEM_KEYS_VS_LABELS[MenuItemKeys.Delete],
isVisible: allowDelete,
isVisible: headerMenuList?.includes(MenuItemKeys.Delete) || false,
disabled: !deleteWidget,
danger: true,
},
{
key: MenuItemKeys.CreateAlerts,
icon: <DeleteOutlined />,
label: MENUITEM_KEYS_VS_LABELS[MenuItemKeys.CreateAlerts],
isVisible: headerMenuList?.includes(MenuItemKeys.CreateAlerts) || false,
disabled: false,
},
],
[
allowEdit,
allowClone,
allowDelete,
queryResponse.isLoading,
deleteWidget,
editWidget,
],
[queryResponse.isLoading, headerMenuList, editWidget, deleteWidget],
);
const menuList: MenuItemType[] = useMemo(
(): MenuItemType[] => generateMenuList(actions, keyMethodMapping),
[actions, keyMethodMapping],
);
const updatedMenuList = useMemo(() => generateMenuList(actions), [actions]);
const onClickHandler = useCallback(() => {
setIsOpen((open) => !open);
@ -172,10 +164,10 @@ function WidgetHeader({
const menu = useMemo(
() => ({
items: menuList,
items: updatedMenuList,
onClick: onMenuItemSelectHandler,
}),
[menuList, onMenuItemSelectHandler],
[updatedMenuList, onMenuItemSelectHandler],
);
return (
@ -219,9 +211,7 @@ function WidgetHeader({
WidgetHeader.defaultProps = {
onDelete: undefined,
onClone: undefined,
allowDelete: true,
allowClone: true,
allowEdit: true,
headerMenuList: [MenuItemKeys.View],
};
export default WidgetHeader;

View File

@ -3,23 +3,10 @@ import { ReactNode } from 'react';
import { MenuItemKeys } from './contants';
export interface MenuItem {
key: TWidgetOptions;
key: MenuItemKeys;
icon: ReactNode;
label: string;
isVisible: boolean;
disabled: boolean;
danger?: boolean;
}
export type TWidgetOptions =
| MenuItemKeys.View
| MenuItemKeys.Edit
| MenuItemKeys.Delete
| MenuItemKeys.Clone;
export type KeyMethodMappingProps<T extends TWidgetOptions> = {
[K in T]: {
key: TWidgetOptions;
method?: VoidFunction;
};
};

View File

@ -1,24 +1,22 @@
import { MenuItemType } from 'antd/es/menu/hooks/useItems';
import { MenuItemKeys } from './contants';
import { KeyMethodMappingProps, MenuItem, TWidgetOptions } from './types';
import { MenuItem } from './types';
export const generateMenuList = (
actions: MenuItem[],
keyMethodMapping: KeyMethodMappingProps<TWidgetOptions>,
): MenuItemType[] =>
export const generateMenuList = (actions: MenuItem[]): MenuItemType[] =>
actions
.filter((action: MenuItem) => action.isVisible)
.map(({ key, icon: Icon, label, disabled, ...rest }) => ({
key: keyMethodMapping[key].key,
key,
icon: Icon,
label,
disabled,
...rest,
}));
export const isTWidgetOptions = (value: string): value is TWidgetOptions =>
export const isTWidgetOptions = (value: string): value is MenuItemKeys =>
value === MenuItemKeys.View ||
value === MenuItemKeys.Edit ||
value === MenuItemKeys.Delete ||
value === MenuItemKeys.Clone;
value === MenuItemKeys.Clone ||
value === MenuItemKeys.CreateAlerts;

View File

@ -0,0 +1,8 @@
import { MenuItemKeys } from 'container/GridGraphLayout/WidgetHeader/contants';
export const headerMenuList = [
MenuItemKeys.View,
MenuItemKeys.Clone,
MenuItemKeys.Delete,
MenuItemKeys.Edit,
];

View File

@ -29,6 +29,7 @@ import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
import AppReducer from 'types/reducer/app';
import DashboardReducer from 'types/reducer/dashboards';
import { headerMenuList } from './config';
import Graph from './Graph';
import GraphLayoutContainer from './GraphLayout';
import { UpdateDashboard } from './utils';
@ -49,6 +50,7 @@ export const getPreLayouts = (
yAxisUnit={widget?.yAxisUnit}
layout={layout}
setLayout={setLayout}
headerMenuList={headerMenuList}
/>
);
},
@ -233,6 +235,7 @@ function GridGraph(props: Props): JSX.Element {
layout={layout}
setLayout={setLayout}
onDragSelect={onDragSelect}
headerMenuList={headerMenuList}
/>
),
};

View File

@ -117,9 +117,6 @@ function DBCall(): JSX.Element {
'database_call_rps',
);
}}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
</GraphContainer>
</Card>
@ -153,9 +150,6 @@ function DBCall(): JSX.Element {
'database_call_avg_duration',
);
}}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
</GraphContainer>
</Card>

View File

@ -156,9 +156,6 @@ function External(): JSX.Element {
'external_call_error_percentage',
);
}}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
</GraphContainer>
</Card>
@ -194,9 +191,6 @@ function External(): JSX.Element {
'external_call_duration',
);
}}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
</GraphContainer>
</Card>
@ -233,9 +227,6 @@ function External(): JSX.Element {
'external_call_rps_by_address',
);
}}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
</GraphContainer>
</Card>
@ -271,9 +262,6 @@ function External(): JSX.Element {
'external_call_duration_by_address',
);
}}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
</GraphContainer>
</Card>

View File

@ -75,9 +75,6 @@ function ServiceOverview({
widget={latencyWidget}
yAxisUnit="ns"
onClickHandler={handleGraphClick('Service')}
allowClone={false}
allowDelete={false}
allowEdit={false}
isQueryEnabled={isQueryEnabled}
/>
</GraphContainer>

View File

@ -39,9 +39,6 @@ function TopLevelOperation({
onClickHandler={handleGraphClick(opName)}
yAxisUnit={yAxisUnit}
onDragSelect={onDragSelect}
allowClone={false}
allowDelete={false}
allowEdit={false}
/>
)}
</GraphContainer>