mirror of
https://git.mirrors.martin98.com/https://github.com/SigNoz/signoz
synced 2025-08-16 17:25:57 +08:00
feat: added an option to create channel when no Channels are available in alert config (#5195)
* feat: added an option to create channel when no Channels are availabel in alert config * feat: added tooltip for the case when nochannel * feat: opened notification channel creation in new tab * feat: added role permission on create-notification-btn and disabled on loading * feat: added admin permission required message in tooltip --------- Co-authored-by: Vishal Sharma <makeavish786@gmail.com>
This commit is contained in:
parent
f391ca8bb1
commit
aa9689e025
@ -1,5 +1,5 @@
|
|||||||
import { PlusOutlined } from '@ant-design/icons';
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
import { Typography } from 'antd';
|
import { Tooltip, Typography } from 'antd';
|
||||||
import getAll from 'api/channels/getAll';
|
import getAll from 'api/channels/getAll';
|
||||||
import Spinner from 'components/Spinner';
|
import Spinner from 'components/Spinner';
|
||||||
import TextToolTip from 'components/TextToolTip';
|
import TextToolTip from 'components/TextToolTip';
|
||||||
@ -52,11 +52,21 @@ function AlertChannels(): JSX.Element {
|
|||||||
url="https://signoz.io/docs/userguide/alerts-management/#setting-notification-channel"
|
url="https://signoz.io/docs/userguide/alerts-management/#setting-notification-channel"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{addNewChannelPermission && (
|
<Tooltip
|
||||||
<Button onClick={onToggleHandler} icon={<PlusOutlined />}>
|
title={
|
||||||
|
!addNewChannelPermission
|
||||||
|
? 'Ask an admin to create alert channel'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={onToggleHandler}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
disabled={!addNewChannelPermission}
|
||||||
|
>
|
||||||
{t('button_new_channel')}
|
{t('button_new_channel')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
</Tooltip>
|
||||||
</RightActionContainer>
|
</RightActionContainer>
|
||||||
</ButtonContainer>
|
</ButtonContainer>
|
||||||
|
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
import { Form, Select, Switch } from 'antd';
|
import './FormAlertRules.styles.scss';
|
||||||
import { useEffect, useState } from 'react';
|
|
||||||
|
import { PlusOutlined } from '@ant-design/icons';
|
||||||
|
import { Button, Form, Select, Switch, Tooltip } from 'antd';
|
||||||
|
import getChannels from 'api/channels/getAll';
|
||||||
|
import ROUTES from 'constants/routes';
|
||||||
|
import useComponentPermission from 'hooks/useComponentPermission';
|
||||||
|
import useFetch from 'hooks/useFetch';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { AppState } from 'store/reducers';
|
||||||
import { AlertDef, Labels } from 'types/api/alerts/def';
|
import { AlertDef, Labels } from 'types/api/alerts/def';
|
||||||
|
import AppReducer from 'types/reducer/app';
|
||||||
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
import { requireErrorMessage } from 'utils/form/requireErrorMessage';
|
||||||
import { popupContainer } from 'utils/selectPopupContainer';
|
import { popupContainer } from 'utils/selectPopupContainer';
|
||||||
|
|
||||||
@ -31,6 +41,13 @@ function BasicInfo({
|
|||||||
}: BasicInfoProps): JSX.Element {
|
}: BasicInfoProps): JSX.Element {
|
||||||
const { t } = useTranslation('alerts');
|
const { t } = useTranslation('alerts');
|
||||||
|
|
||||||
|
const channels = useFetch(getChannels);
|
||||||
|
const { role } = useSelector<AppState, AppReducer>((state) => state.app);
|
||||||
|
const [addNewChannelPermission] = useComponentPermission(
|
||||||
|
['add_new_channel'],
|
||||||
|
role,
|
||||||
|
);
|
||||||
|
|
||||||
const [
|
const [
|
||||||
shouldBroadCastToAllChannels,
|
shouldBroadCastToAllChannels,
|
||||||
setShouldBroadCastToAllChannels,
|
setShouldBroadCastToAllChannels,
|
||||||
@ -54,6 +71,11 @@ function BasicInfo({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const noChannels = channels.payload?.length === 0;
|
||||||
|
const handleCreateNewChannels = useCallback(() => {
|
||||||
|
window.open(ROUTES.CHANNELS_NEW, '_blank');
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StepHeading> {t('alert_form_step3')} </StepHeading>
|
<StepHeading> {t('alert_form_step3')} </StepHeading>
|
||||||
@ -136,14 +158,32 @@ function BasicInfo({
|
|||||||
<FormItemMedium
|
<FormItemMedium
|
||||||
name="alert_all_configured_channels"
|
name="alert_all_configured_channels"
|
||||||
label="Alert all the configured channels"
|
label="Alert all the configured channels"
|
||||||
|
>
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
noChannels
|
||||||
|
? 'No channels. Ask an admin to create a notification channel'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
placement="right"
|
||||||
>
|
>
|
||||||
<Switch
|
<Switch
|
||||||
checked={shouldBroadCastToAllChannels}
|
checked={shouldBroadCastToAllChannels}
|
||||||
onChange={handleBroadcastToAllChannels}
|
onChange={handleBroadcastToAllChannels}
|
||||||
|
disabled={noChannels || !!channels.loading}
|
||||||
/>
|
/>
|
||||||
|
</Tooltip>
|
||||||
</FormItemMedium>
|
</FormItemMedium>
|
||||||
|
|
||||||
{!shouldBroadCastToAllChannels && (
|
{!shouldBroadCastToAllChannels && (
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
noChannels
|
||||||
|
? 'No channels. Ask an admin to create a notification channel'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
<FormItemMedium
|
<FormItemMedium
|
||||||
label="Notification Channels"
|
label="Notification Channels"
|
||||||
name="notification_channels"
|
name="notification_channels"
|
||||||
@ -153,8 +193,11 @@ function BasicInfo({
|
|||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<ChannelSelect
|
<ChannelSelect
|
||||||
disabled={shouldBroadCastToAllChannels}
|
disabled={
|
||||||
|
shouldBroadCastToAllChannels || noChannels || !!channels.loading
|
||||||
|
}
|
||||||
currentValue={alertDef.preferredChannels}
|
currentValue={alertDef.preferredChannels}
|
||||||
|
channels={channels}
|
||||||
onSelectChannels={(preferredChannels): void => {
|
onSelectChannels={(preferredChannels): void => {
|
||||||
setAlertDef({
|
setAlertDef({
|
||||||
...alertDef,
|
...alertDef,
|
||||||
@ -163,6 +206,27 @@ function BasicInfo({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</FormItemMedium>
|
</FormItemMedium>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{noChannels && (
|
||||||
|
<Tooltip
|
||||||
|
title={
|
||||||
|
!addNewChannelPermission
|
||||||
|
? 'Ask an admin to create a notification channel'
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
placement="right"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
onClick={handleCreateNewChannels}
|
||||||
|
icon={<PlusOutlined />}
|
||||||
|
className="create-notification-btn"
|
||||||
|
disabled={!addNewChannelPermission}
|
||||||
|
>
|
||||||
|
Create a notification channel
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
</>
|
</>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Select } from 'antd';
|
import { Select } from 'antd';
|
||||||
import getChannels from 'api/channels/getAll';
|
import { State } from 'hooks/useFetch';
|
||||||
import useFetch from 'hooks/useFetch';
|
|
||||||
import { useNotifications } from 'hooks/useNotifications';
|
import { useNotifications } from 'hooks/useNotifications';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { PayloadProps } from 'types/api/channels/getAll';
|
||||||
|
|
||||||
import { StyledSelect } from './styles';
|
import { StyledSelect } from './styles';
|
||||||
|
|
||||||
@ -11,38 +11,42 @@ export interface ChannelSelectProps {
|
|||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
currentValue?: string[];
|
currentValue?: string[];
|
||||||
onSelectChannels: (s: string[]) => void;
|
onSelectChannels: (s: string[]) => void;
|
||||||
|
channels: State<PayloadProps | undefined>;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ChannelSelect({
|
function ChannelSelect({
|
||||||
disabled,
|
disabled,
|
||||||
currentValue,
|
currentValue,
|
||||||
onSelectChannels,
|
onSelectChannels,
|
||||||
|
channels,
|
||||||
}: ChannelSelectProps): JSX.Element | null {
|
}: ChannelSelectProps): JSX.Element | null {
|
||||||
// init namespace for translations
|
// init namespace for translations
|
||||||
const { t } = useTranslation('alerts');
|
const { t } = useTranslation('alerts');
|
||||||
|
|
||||||
const { loading, payload, error, errorMessage } = useFetch(getChannels);
|
|
||||||
|
|
||||||
const { notifications } = useNotifications();
|
const { notifications } = useNotifications();
|
||||||
|
|
||||||
const handleChange = (value: string[]): void => {
|
const handleChange = (value: string[]): void => {
|
||||||
onSelectChannels(value);
|
onSelectChannels(value);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (error && errorMessage !== '') {
|
if (channels.error && channels.errorMessage !== '') {
|
||||||
notifications.error({
|
notifications.error({
|
||||||
message: 'Error',
|
message: 'Error',
|
||||||
description: errorMessage,
|
description: channels.errorMessage,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const renderOptions = (): ReactNode[] => {
|
const renderOptions = (): ReactNode[] => {
|
||||||
const children: ReactNode[] = [];
|
const children: ReactNode[] = [];
|
||||||
|
|
||||||
if (loading || payload === undefined || payload.length === 0) {
|
if (
|
||||||
|
channels.loading ||
|
||||||
|
channels.payload === undefined ||
|
||||||
|
channels.payload.length === 0
|
||||||
|
) {
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
payload.forEach((o) => {
|
channels.payload.forEach((o) => {
|
||||||
children.push(
|
children.push(
|
||||||
<Select.Option key={o.id} value={o.name}>
|
<Select.Option key={o.id} value={o.name}>
|
||||||
{o.name}
|
{o.name}
|
||||||
@ -55,7 +59,7 @@ function ChannelSelect({
|
|||||||
return (
|
return (
|
||||||
<StyledSelect
|
<StyledSelect
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
status={error ? 'error' : ''}
|
status={channels.error ? 'error' : ''}
|
||||||
mode="multiple"
|
mode="multiple"
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
placeholder={t('placeholder_channel_select')}
|
placeholder={t('placeholder_channel_select')}
|
||||||
|
@ -71,3 +71,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.create-notification-btn {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user