Rares/templates tweaks 5 (#2116)

# What this PR does

- Removed duplicate copy within Routes
- Made drawer content of templates more responsive
- Fetch telegram info and display it accordingly
- Fixed pagination being reset when going back to table view
- Some other minor things
This commit is contained in:
Rares Mardare 2023-06-07 15:30:05 +03:00 committed by GitHub
parent a865ae1378
commit 6570790442
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 75 additions and 40 deletions

View file

@ -16,5 +16,6 @@
&--collapsedBorder {
border-left: none;
padding-left: 0;
padding-right: 0;
}
}

View file

@ -2,6 +2,7 @@
display: flex;
flex-direction: row;
margin-bottom: 4px;
max-width: 100%;
&__content {
width: 100%;

View file

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { ConfirmModal, HorizontalGroup, Icon, VerticalGroup } from '@grafana/ui';
import cn from 'classnames/bind';
@ -26,8 +26,17 @@ interface CollapsedIntegrationRouteDisplayProps {
const CollapsedIntegrationRouteDisplay: React.FC<CollapsedIntegrationRouteDisplayProps> = observer(
({ channelFilterId, alertReceiveChannelId, routeIndex, toggle }) => {
const { escalationChainStore, alertReceiveChannelStore } = useStore();
const store = useStore();
const { escalationChainStore, alertReceiveChannelStore, telegramChannelStore } = store;
const [routeIdForDeletion, setRouteIdForDeletion] = useState<ChannelFilter['id']>(undefined);
const [telegramInfo, setTelegramInfo] = useState<Array<{ id: string; channel_name: string }>>([]);
useEffect(() => {
(async function () {
const telegram = await telegramChannelStore.getAll();
setTelegramInfo(telegram);
})();
}, [channelFilterId]);
const channelFilter = alertReceiveChannelStore.channelFilters[channelFilterId];
if (!channelFilter) {
@ -84,15 +93,17 @@ const CollapsedIntegrationRouteDisplay: React.FC<CollapsedIntegrationRouteDispla
content={
<div className={cx('spacing')}>
<VerticalGroup>
{IntegrationHelper.getChatOpsChannels(channelFilter).map((chatOpsChannel, key) => (
<HorizontalGroup key={key}>
<Text type="secondary">Publish to ChatOps</Text>
<Icon name={chatOpsChannel.icon} />
<Text type="primary" strong>
{chatOpsChannel.name}
</Text>
</HorizontalGroup>
))}
{IntegrationHelper.getChatOpsChannels(channelFilter, telegramInfo, store)
.filter((it) => it)
.map((chatOpsChannel, key) => (
<HorizontalGroup key={key}>
<Text type="secondary">Publish to ChatOps</Text>
<Icon name={chatOpsChannel.icon} />
<Text type="primary" strong>
{chatOpsChannel.name}
</Text>
</HorizontalGroup>
))}
<HorizontalGroup>
<Icon name="list-ui-alt" />

View file

@ -168,17 +168,6 @@ const ExpandedIntegrationRouteDisplay: React.FC<ExpandedIntegrationRouteDisplayP
</IntegrationBlockItem>
)}
{routeIndex !== channelFiltersTotal.length - 1 && (
<IntegrationBlockItem>
<VerticalGroup>
<Text type="secondary">
If the Routing template evaluates to True, the alert will be grouped with the Grouping template
and proceed to the following steps
</Text>
</VerticalGroup>
</IntegrationBlockItem>
)}
<IntegrationBlockItem>
<VerticalGroup spacing="md">
<Text type="primary">Publish to ChatOps</Text>

View file

@ -18,7 +18,7 @@ interface TeamNameProps {
}
const TeamName = observer((props: TeamNameProps) => {
const { team, size } = props;
const { team, size = 'medium' } = props;
if (!team) {
return null;
}
@ -26,10 +26,10 @@ const TeamName = observer((props: TeamNameProps) => {
return <Badge text={team.name} color={'blue'} tooltip={'Resource is not assigned to any team (ex General team)'} />;
}
return (
<Text type="secondary" size={size ? size : 'medium'}>
<Text type="secondary" size={size}>
<Avatar size="small" src={team.avatar_url} className={cx('avatar')} />
<Tooltip placement="top" content={'Resource is assigned to ' + team.name}>
<span>{team.name}</span>
<Text type="primary">{team.name}</Text>
</Tooltip>
</Text>
);

View file

@ -8,6 +8,8 @@ import dayjs from 'dayjs';
import { MaintenanceMode } from 'models/alert_receive_channel/alert_receive_channel.types';
import { ChannelFilter } from 'models/channel_filter/channel_filter.types';
import { RootStore } from 'state';
import { AppFeature } from 'state/features';
import { MAX_CHARACTERS_COUNT, TEXTAREA_ROWS_COUNT } from './Integration2.config';
@ -70,14 +72,31 @@ const IntegrationHelper = {
return totalDiffString;
},
getChatOpsChannels(channelFilter: ChannelFilter): Array<{ name: string; icon: IconName }> {
getChatOpsChannels(
channelFilter: ChannelFilter,
telegramInfo: Array<{ id: string; channel_name: string }>,
store: RootStore
): Array<{ name: string; icon: IconName }> {
const channels: Array<{ name: string; icon: IconName }> = [];
if (channelFilter.notify_in_slack && channelFilter.slack_channel?.display_name) {
if (
store.hasFeature(AppFeature.Slack) &&
channelFilter.notify_in_slack &&
channelFilter.notify_in_slack &&
channelFilter.slack_channel?.display_name
) {
channels.push({ name: channelFilter.slack_channel.display_name, icon: 'slack' });
}
if (channelFilter.telegram_channel) {
channels.push({ name: channelFilter.telegram_channel, icon: 'telegram-alt' });
const matchingTelegram = telegramInfo?.find((t) => t.id === channelFilter.telegram_channel);
if (
store.hasFeature(AppFeature.Telegram) &&
channelFilter.telegram_channel &&
channelFilter.notify_in_telegram &&
matchingTelegram?.channel_name
) {
channels.push({ name: matchingTelegram.channel_name, icon: 'telegram-alt' });
}
return channels;

View file

@ -116,6 +116,7 @@ $LARGE-MARGIN: 24px;
.input {
flex-grow: 1;
max-width: calc(100% - 80px);
}
.how-to-connect__container {
@ -200,6 +201,7 @@ $LARGE-MARGIN: 24px;
&__item {
display: flex;
flex-direction: row;
align-items: center;
gap: 4px;
}
}

View file

@ -136,6 +136,7 @@ class Integration2 extends React.Component<Integration2Props, Integration2State>
} = this.state;
const {
store: { alertReceiveChannelStore },
query: { p },
match: {
params: { id },
},
@ -165,7 +166,7 @@ class Integration2 extends React.Component<Integration2Props, Integration2State>
<div className={cx('root')}>
{isTemplateSettingsOpen && (
<Drawer
width="640px"
width="75%"
scrollableContent
title="Template Settings"
onClose={() => this.setState({ isTemplateSettingsOpen: false })}
@ -187,7 +188,7 @@ class Integration2 extends React.Component<Integration2Props, Integration2State>
)}
<div className={cx('integration__heading-container')}>
<PluginLink query={{ page: 'integrations_2' }}>
<PluginLink query={{ page: 'integrations_2', p }}>
<IconButton name="arrow-left" size="xxl" />
</PluginLink>
<h1 className={cx('integration__name')}>
@ -600,9 +601,9 @@ const IntegrationSendDemoPayloadModal: React.FC<IntegrationSendDemoPayloadModalP
}) => {
const store = useStore();
const { alertReceiveChannelStore } = store;
const [demoPayload, setDemoPayload] = useState<string>(
JSON.stringify(alertReceiveChannel.demo_alert_payload, null, '\t')
);
const stringifiedJson = JSON.stringify(alertReceiveChannel.demo_alert_payload, null, 2);
const initialDemoJSON = stringifiedJson.substring(1, stringifiedJson.length - 1);
const [demoPayload, setDemoPayload] = useState<string>(alertReceiveChannel.demo_alert_payload);
let onPayloadChangeDebounced = debounce(100, onPayloadChange);
return (
@ -611,7 +612,14 @@ const IntegrationSendDemoPayloadModal: React.FC<IntegrationSendDemoPayloadModalP
closeOnEscape
isOpen={isOpen}
onDismiss={onHideOrCancel}
title={`Send demo alert to ${alertReceiveChannel.verbal_name}`}
title={
<HorizontalGroup>
<Text.Title level={4}>
Send demo alert to {''}
<Emoji text={alertReceiveChannel.verbal_name} />
</Text.Title>
</HorizontalGroup>
}
>
<VerticalGroup>
<HorizontalGroup spacing={'xs'}>
@ -630,7 +638,7 @@ const IntegrationSendDemoPayloadModal: React.FC<IntegrationSendDemoPayloadModalP
<div className={cx('integration__payloadInput')}>
<MonacoEditor
value={JSON.stringify(alertReceiveChannel.demo_alert_payload, null, '\t')}
value={initialDemoJSON}
disabled={true}
height={`200px`}
useAutoCompleteList={false}
@ -1043,7 +1051,7 @@ const IntegrationHeader: React.FC<IntegrationHeaderProps> = ({
</div>
<div className={cx('headerTop__item')}>
<Text type="secondary">Team:</Text>
<TeamName team={grafanaTeamStore.items[alertReceiveChannel.team]} size="small" />
<TeamName team={grafanaTeamStore.items[alertReceiveChannel.team]} />
</div>
<div className={cx('headerTop__item')}>
<Text type="secondary">Created by:</Text>

View file

@ -265,9 +265,13 @@ class Integrations extends React.Component<IntegrationsProps, IntegrationsState>
);
}
renderName(item: AlertReceiveChannel) {
renderName = (item: AlertReceiveChannel) => {
const {
query: { p },
} = this.props;
return (
<PluginLink query={{ page: 'integrations_2', id: item.id }}>
<PluginLink query={{ page: 'integrations_2', id: item.id, p }}>
<Text type="link" size="medium">
<Emoji
className={cx('title')}
@ -280,7 +284,7 @@ class Integrations extends React.Component<IntegrationsProps, IntegrationsState>
</Text>
</PluginLink>
);
}
};
renderDatasource(item: AlertReceiveChannel, alertReceiveChannelStore) {
const alertReceiveChannel = alertReceiveChannelStore.items[item.id];