Commit 8d56f874 by Tobias Skarhed Committed by GitHub

Migration: Alerting - notifications list (#22548)

* Handle empty list

* Connect to redux

* Finish migration

* Remove comments

* Remove old files

* Remove console log

* Remove old import

* Forgot to add the new button

* Fix href

* Fix feedback
parent 1f2a7011
import { useSelector } from 'react-redux';
import { StoreState } from 'app/types/store';
import { getNavModel } from '../selectors/navModel';
import { NavModel } from '../core';
export const useNavModel = (id: string): NavModel => {
const navIndex = useSelector((state: StoreState) => state.navIndex);
return getNavModel(navIndex, id);
};
import { IScope } from 'angular';
import { getBackendSrv } from '@grafana/runtime';
import { coreModule, NavModelSrv } from 'app/core/core';
import { promiseToDigest } from '../../core/utils/promiseToDigest';
export class AlertNotificationsListCtrl {
notifications: any;
navModel: any;
/** @ngInject */
constructor(private $scope: IScope, navModelSrv: NavModelSrv) {
this.loadNotifications();
this.navModel = navModelSrv.getNav('alerting', 'channels', 0);
}
loadNotifications() {
promiseToDigest(this.$scope)(
getBackendSrv()
.get(`/api/alert-notifications`)
.then((result: any) => {
this.notifications = result;
})
);
}
deleteNotification(id: number) {
promiseToDigest(this.$scope)(
getBackendSrv()
.delete(`/api/alert-notifications/${id}`)
.then(() => {
this.notifications = this.notifications.filter((notification: any) => {
return notification.id !== id;
});
})
);
}
}
coreModule.controller('AlertNotificationsListCtrl', AlertNotificationsListCtrl);
import React, { useState, FC, useEffect } from 'react';
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
import Page from 'app/core/components/Page/Page';
import { getBackendSrv } from '@grafana/runtime';
import { useAsyncFn } from 'react-use';
import { useNavModel } from 'app/core/hooks/useNavModel';
import { HorizontalGroup, Button, LinkButton } from '@grafana/ui';
import { AlertNotification } from 'app/types/alerting';
const deleteNotification = async (id: number) => {
return await getBackendSrv().delete(`/api/alert-notifications/${id}`);
};
const getNotifications = async () => {
return await getBackendSrv().get(`/api/alert-notifications`);
};
const NotificationsListPage: FC = () => {
const navModel = useNavModel('channels');
const [notifications, setNotifications] = useState<AlertNotification[]>([]);
const [state, fetchNotifications] = useAsyncFn(getNotifications);
useEffect(() => {
fetchNotifications().then(res => {
setNotifications(res);
});
}, []);
return (
<Page navModel={navModel}>
<Page.Contents>
{state.error && <p>{state.error}</p>}
{!!notifications.length && (
<>
<div className="page-action-bar">
<div className="page-action-bar__spacer" />
<LinkButton icon="channel-add" href="alerting/notification/new">
New channel
</LinkButton>
</div>
<table className="filter-table filter-table--hover">
<thead>
<tr>
<th style={{ minWidth: '200px' }}>
<strong>Name</strong>
</th>
<th style={{ minWidth: '100px' }}>Type</th>
<th style={{ width: '1%' }}></th>
</tr>
</thead>
<tbody>
{notifications.map(notification => (
<tr key={notification.id}>
<td className="link-td">
<a href={`alerting/notification/${notification.id}/edit`}>{notification.name}</a>
</td>
<td className="link-td">
<a href={`alerting/notification/${notification.id}/edit`}>{notification.type}</a>
</td>
<td className="text-right">
<HorizontalGroup justify="flex-end">
{notification.isDefault && (
<Button disabled variant="secondary" size="sm">
default
</Button>
)}
<Button
variant="destructive"
icon="times"
size="sm"
onClick={() => {
deleteNotification(notification.id);
setNotifications(notifications.filter(notify => notify.id !== notification.id));
fetchNotifications();
}}
/>
</HorizontalGroup>
</td>
</tr>
))}
</tbody>
</table>
</>
)}
{!(notifications.length || state.loading) && (
<EmptyListCTA
title="There are no notification channels defined yet"
buttonIcon="channel-add"
buttonLink="alerting/notification/new"
buttonTitle="Add channel"
proTip="You can include images in your alert notifications."
proTipLink="http://docs.grafana.org/alerting/notifications/"
proTipLinkTitle="Learn more"
proTipTarget="_blank"
/>
)}
</Page.Contents>
</Page>
);
};
export default NotificationsListPage;
<page-header model="ctrl.navModel"></page-header>
<div class="page-container page-body">
<div ng-if="ctrl.notifications.length">
<div class="page-action-bar">
<div class="page-action-bar__spacer"></div>
<a href="alerting/notification/new" class="btn btn-primary">
New channel
</a>
</div>
<table class="filter-table filter-table--hover">
<thead>
<th style="min-width: 200px">
<strong>Name</strong>
</th>
<th style="min-width: 100px">Type</th>
<th style="width: 1%"></th>
</thead>
<tbody>
<tr ng-repeat="notification in ctrl.notifications">
<td class="link-td">
<a href="alerting/notification/{{notification.id}}/edit">
{{notification.name}}
</a>
</td>
<td class="link-td">
<a href="alerting/notification/{{notification.id}}/edit">
{{notification.type}}
</a>
</td>
<td class="text-right">
<span class="btn btn-secondary btn-small" ng-show="notification.isDefault == true">
default
</span>
<a ng-click="ctrl.deleteNotification(notification.id)" class="btn btn-danger btn-small">
<icon name="'times'" style="margin-top: 2px"></icon>
</a>
</td>
</tr>
</tbody>
</table>
</div>
<div ng-if="ctrl.notifications.length === 0">
<empty-list-cta
title="'There are no notification channels defined yet'"
buttonIcon="'channel-add'"
buttonLink="'alerting/notification/new'"
buttonTitle="'Add channel'"
proTip="'You can include images in your alert notifications.'"
proTipLink="'http://docs.grafana.org/alerting/notifications/'"
proTipLinkTitle="'Learn more'"
proTipTarget="'_blank'"
/>
</div>
</div>
<footer />
...@@ -7,7 +7,6 @@ import './panel/all'; ...@@ -7,7 +7,6 @@ import './panel/all';
import './org/all'; import './org/all';
import './admin'; import './admin';
import './alerting/NotificationsEditCtrl'; import './alerting/NotificationsEditCtrl';
import './alerting/NotificationsListCtrl';
import './manage-dashboards'; import './manage-dashboards';
import './profile/all'; import './profile/all';
import './datasources/settings/HttpSettingsCtrl'; import './datasources/settings/HttpSettingsCtrl';
......
...@@ -436,9 +436,13 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati ...@@ -436,9 +436,13 @@ export function setupAngularRoutes($routeProvider: route.IRouteProvider, $locati
}, },
}) })
.when('/alerting/notifications', { .when('/alerting/notifications', {
templateUrl: 'public/app/features/alerting/partials/notifications_list.html', template: '<react-container />',
controller: 'AlertNotificationsListCtrl', resolve: {
controllerAs: 'ctrl', component: () =>
SafeDynamicImport(
import(/* webpackChunkName: "NotificationsListPage" */ 'app/features/alerting/NotificationsListPage')
),
},
}) })
.when('/alerting/notification/new', { .when('/alerting/notification/new', {
templateUrl: 'public/app/features/alerting/partials/notification_edit.html', templateUrl: 'public/app/features/alerting/partials/notification_edit.html',
......
...@@ -38,3 +38,10 @@ export interface AlertRulesState { ...@@ -38,3 +38,10 @@ export interface AlertRulesState {
searchQuery: string; searchQuery: string;
isLoading: boolean; isLoading: boolean;
} }
export interface AlertNotification {
isDefault: boolean;
name: string;
id: number;
type: string;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment