Polish route creation (#2222)

# What this PR does
polished route creation
route is now created empty by default
added placeholder text to route template
added warning for route w/o template
made text same size in warnings
changed texts a bit for more consistency with grafana alerting
## Which issue(s) this PR fixes

## Checklist

- [ ] Unit, integration, and e2e (if applicable) tests updated
- [ ] Documentation added (or `pr:no public docs` PR label added if not
required)
- [ ] `CHANGELOG.md` updated (or `pr:no changelog` PR label added if not
required)
This commit is contained in:
Ildar Iskhakov 2023-06-14 15:09:32 +08:00 committed by GitHub
parent 51b054fd31
commit 72c9a476d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 31 additions and 23 deletions

View file

@ -27,6 +27,7 @@ class ChannelFilterSerializer(OrderedModelSerializerMixin, EagerLoadingMixin, se
)
order = serializers.IntegerField(required=False)
filtering_term_as_jinja2 = serializers.SerializerMethodField()
filtering_term = serializers.CharField(required=False, allow_null=True, allow_blank=True)
SELECT_RELATED = ["escalation_chain", "alert_receive_channel"]
@ -49,7 +50,6 @@ class ChannelFilterSerializer(OrderedModelSerializerMixin, EagerLoadingMixin, se
"filtering_term_as_jinja2",
]
read_only_fields = ["created_at", "is_default"]
extra_kwargs = {"filtering_term": {"required": True, "allow_null": False}}
def validate(self, data):
filtering_term = data.get("filtering_term")
@ -123,6 +123,7 @@ class ChannelFilterSerializer(OrderedModelSerializerMixin, EagerLoadingMixin, se
class ChannelFilterCreateSerializer(ChannelFilterSerializer):
alert_receive_channel = OrganizationFilteredPrimaryKeyRelatedField(queryset=AlertReceiveChannel.objects)
slack_channel = serializers.CharField(allow_null=True, required=False, source="slack_channel_id")
filtering_term = serializers.CharField(required=False, allow_null=True, allow_blank=True)
class Meta:
model = ChannelFilter
@ -142,7 +143,6 @@ class ChannelFilterCreateSerializer(ChannelFilterSerializer):
"notification_backends",
]
read_only_fields = ["created_at", "is_default"]
extra_kwargs = {"filtering_term": {"required": True, "allow_null": False}}
def to_representation(self, obj):
"""add correct slack channel data to result after instance creation/update"""

View file

@ -67,11 +67,21 @@ const CollapsedIntegrationRouteDisplay: React.FC<CollapsedIntegrationRouteDispla
tooltipContent={undefined}
/>
{routeWording === 'Default' && <Text type="secondary">Unmatched alerts routed to default route</Text>}
{routeWording !== 'Default' && channelFilter.filtering_term && (
<Text type="primary" className={cx('heading-container__text')}>
{channelFilter.filtering_term}
</Text>
)}
{routeWording !== 'Default' &&
(channelFilter.filtering_term ? (
<Text type="primary" className={cx('heading-container__text')}>
{channelFilter.filtering_term}
</Text>
) : (
<>
<div className={cx('icon-exclamation')}>
<Icon name="exclamation-triangle" />
</div>
<Text type="primary" className={cx('heading-container__text')}>
Routing template not set
</Text>
</>
))}
</div>
<div className={cx('heading-container__item')}>
@ -100,8 +110,10 @@ const CollapsedIntegrationRouteDisplay: React.FC<CollapsedIntegrationRouteDispla
))}
<HorizontalGroup>
<Icon name="list-ui-alt" />
<Text type="secondary">Trigger escalation chain:</Text>
<HorizontalGroup spacing={'xs'}>
<Icon name="list-ui-alt" />
<Text type="secondary">Trigger escalation chain</Text>
</HorizontalGroup>
{escalationChain?.name && (
<PluginLink
@ -109,9 +121,7 @@ const CollapsedIntegrationRouteDisplay: React.FC<CollapsedIntegrationRouteDispla
target="_blank"
query={{ page: 'escalations', id: channelFilter.escalation_chain }}
>
<Text type="primary" strong>
{escalationChain?.name}
</Text>
<Text type="primary">{escalationChain?.name}</Text>
</PluginLink>
)}
@ -120,7 +130,7 @@ const CollapsedIntegrationRouteDisplay: React.FC<CollapsedIntegrationRouteDispla
<div className={cx('icon-exclamation')}>
<Icon name="exclamation-triangle" />
</div>
<Text type="primary">No Escalation chain selected</Text>
<Text type="primary">Not selected</Text>
</HorizontalGroup>
)}
</HorizontalGroup>

View file

@ -104,6 +104,9 @@ const ExpandedIntegrationRouteDisplay: React.FC<ExpandedIntegrationRouteDisplayP
const channelFilterIds = alertReceiveChannelStore.channelFilterIds[alertReceiveChannelId];
const isDefault = IntegrationHelper.getRouteConditionWording(channelFilterIds, routeIndex) === 'Default';
const channelFilterTemplate = channelFilter.filtering_term
? IntegrationHelper.getFilteredTemplate(channelFilter.filtering_term, false)
: '{# Add Routing Template, e.g. {{ payload.severity == "critical" }} #}';
if (isLoading) {
return <LoadingPlaceholder text="Loading..." />;
@ -153,7 +156,7 @@ const ExpandedIntegrationRouteDisplay: React.FC<ExpandedIntegrationRouteDisplayP
<InlineLabel width={20}>Routing Template</InlineLabel>
<div className={cx('input', 'input--short')}>
<MonacoEditor
value={IntegrationHelper.getFilteredTemplate(channelFilter.filtering_term, false)}
value={channelFilterTemplate}
disabled={true}
height={MONACO_INPUT_HEIGHT_SMALL}
data={templates}

View file

@ -21,7 +21,6 @@ import { AlertReceiveChannel } from 'models/alert_receive_channel/alert_receive_
import { AlertTemplatesDTO } from 'models/alert_templates';
import { Alert } from 'models/alertgroup/alertgroup.types';
import { ChannelFilter } from 'models/channel_filter/channel_filter.types';
import { openErrorNotification } from 'utils';
import { waitForElement } from 'utils/DOM';
import LocationHelper from 'utils/LocationHelper';
@ -119,12 +118,8 @@ const IntegrationTemplate = observer((props: IntegrationTemplateProps) => {
const handleSubmit = useCallback(() => {
if (template.isRoute) {
if (changedTemplateBody) {
onUpdateRoute({ [template.name]: changedTemplateBody }, channelFilterId);
onHide();
} else {
openErrorNotification('Route template body can not be empty');
}
onUpdateRoute({ [template.name]: changedTemplateBody }, channelFilterId);
onHide();
} else {
onUpdateTemplates({ [template.name]: changedTemplateBody });
onHide();
@ -136,7 +131,7 @@ const IntegrationTemplate = observer((props: IntegrationTemplateProps) => {
case 'Grouping':
case 'Autoresolve':
return groupingTemplateCheatSheet;
case 'Web titile':
case 'Web title':
case 'Web message':
case 'Web image':
return webTitleTemplateCheatSheet;

View file

@ -86,7 +86,7 @@ interface Integration2State extends PageBaseState {
const ACTIONS_LIST_WIDTH = 200;
const ACTIONS_LIST_BORDER = 2;
const NEW_ROUTE_DEFAULT = '{# (payload.severity == "foo" and "bar" in payload.region) or True #}';
const NEW_ROUTE_DEFAULT = '';
@observer
class Integration2 extends React.Component<Integration2Props, Integration2State> {