mirror of https://github.com/grafana/grafana.git
				
				
				
			Alert panel filters (#11712)
alert list panel: filter alerts by name, dashboard, folder, tags
This commit is contained in:
		
							parent
							
								
									13a9701581
								
							
						
					
					
						commit
						0c269d64d0
					
				|  | @ -35,10 +35,15 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk | ||||||
| 
 | 
 | ||||||
|   `/api/alerts?dashboardId=1` |   `/api/alerts?dashboardId=1` | ||||||
| 
 | 
 | ||||||
|   - **dashboardId** – Return alerts for a specified dashboard. |   - **dashboardId** – Limit response to alerts in specified dashboard(s). You can specify multiple dashboards, e.g. dashboardId=23&dashboardId=35. | ||||||
|   - **panelId** – Return alerts for a specified panel on a dashboard. |   - **panelId** – Limit response to alert for a specified panel on a dashboard. | ||||||
|   - **limit** - Limit response to x number of alerts. |   - **query** - Limit response to alerts having a name like this value. | ||||||
|   - **state** - Return alerts with one or more of the following alert states: `ALL`,`no_data`, `paused`, `alerting`, `ok`, `pending`. To specify multiple states use the following format: `?state=paused&state=alerting` |   - **state** - Return alerts with one or more of the following alert states: `ALL`,`no_data`, `paused`, `alerting`, `ok`, `pending`. To specify multiple states use the following format: `?state=paused&state=alerting` | ||||||
|  |   - **limit** - Limit response to *X* number of alerts. | ||||||
|  |   - **folderId** – Limit response to alerts of dashboards in specified folder(s). You can specify multiple folders, e.g. folderId=23&folderId=35. | ||||||
|  |   - **dashboardQuery** - Limit response to alerts having a dashboard name like this value. | ||||||
|  |   - **dashboardTag** - Limit response to alerts of dashboards with specified tags. To do an "AND" filtering with multiple tags, specify the tags parameter multiple times e.g. dashboardTag=tag1&dashboardTag=tag2. | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| **Example Response**: | **Example Response**: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,12 +2,14 @@ package api | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"strconv" | ||||||
| 
 | 
 | ||||||
| 	"github.com/grafana/grafana/pkg/api/dtos" | 	"github.com/grafana/grafana/pkg/api/dtos" | ||||||
| 	"github.com/grafana/grafana/pkg/bus" | 	"github.com/grafana/grafana/pkg/bus" | ||||||
| 	m "github.com/grafana/grafana/pkg/models" | 	m "github.com/grafana/grafana/pkg/models" | ||||||
| 	"github.com/grafana/grafana/pkg/services/alerting" | 	"github.com/grafana/grafana/pkg/services/alerting" | ||||||
| 	"github.com/grafana/grafana/pkg/services/guardian" | 	"github.com/grafana/grafana/pkg/services/guardian" | ||||||
|  | 	"github.com/grafana/grafana/pkg/services/search" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func ValidateOrgAlert(c *m.ReqContext) { | func ValidateOrgAlert(c *m.ReqContext) { | ||||||
|  | @ -46,12 +48,64 @@ func GetAlertStatesForDashboard(c *m.ReqContext) Response { | ||||||
| 
 | 
 | ||||||
| // GET /api/alerts
 | // GET /api/alerts
 | ||||||
| func GetAlerts(c *m.ReqContext) Response { | func GetAlerts(c *m.ReqContext) Response { | ||||||
|  | 	dashboardQuery := c.Query("dashboardQuery") | ||||||
|  | 	dashboardTags := c.QueryStrings("dashboardTag") | ||||||
|  | 	stringDashboardIDs := c.QueryStrings("dashboardId") | ||||||
|  | 	stringFolderIDs := c.QueryStrings("folderId") | ||||||
|  | 
 | ||||||
|  | 	dashboardIDs := make([]int64, 0) | ||||||
|  | 	for _, id := range stringDashboardIDs { | ||||||
|  | 		dashboardID, err := strconv.ParseInt(id, 10, 64) | ||||||
|  | 		if err == nil { | ||||||
|  | 			dashboardIDs = append(dashboardIDs, dashboardID) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if dashboardQuery != "" || len(dashboardTags) > 0 || len(stringFolderIDs) > 0 { | ||||||
|  | 		folderIDs := make([]int64, 0) | ||||||
|  | 		for _, id := range stringFolderIDs { | ||||||
|  | 			folderID, err := strconv.ParseInt(id, 10, 64) | ||||||
|  | 			if err == nil { | ||||||
|  | 				folderIDs = append(folderIDs, folderID) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		searchQuery := search.Query{ | ||||||
|  | 			Title:        dashboardQuery, | ||||||
|  | 			Tags:         dashboardTags, | ||||||
|  | 			SignedInUser: c.SignedInUser, | ||||||
|  | 			Limit:        1000, | ||||||
|  | 			OrgId:        c.OrgId, | ||||||
|  | 			DashboardIds: dashboardIDs, | ||||||
|  | 			Type:         string(search.DashHitDB), | ||||||
|  | 			FolderIds:    folderIDs, | ||||||
|  | 			Permission:   m.PERMISSION_EDIT, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		err := bus.Dispatch(&searchQuery) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return Error(500, "List alerts failed", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		for _, d := range searchQuery.Result { | ||||||
|  | 			if d.Type == search.DashHitDB && d.Id > 0 { | ||||||
|  | 				dashboardIDs = append(dashboardIDs, d.Id) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// if we didn't find any dashboards, return empty result
 | ||||||
|  | 		if len(dashboardIDs) == 0 { | ||||||
|  | 			return JSON(200, []*m.AlertListItemDTO{}) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	query := m.GetAlertsQuery{ | 	query := m.GetAlertsQuery{ | ||||||
| 		OrgId:       c.OrgId, | 		OrgId:        c.OrgId, | ||||||
| 		DashboardId: c.QueryInt64("dashboardId"), | 		DashboardIDs: dashboardIDs, | ||||||
| 		PanelId:     c.QueryInt64("panelId"), | 		PanelId:      c.QueryInt64("panelId"), | ||||||
| 		Limit:       c.QueryInt64("limit"), | 		Limit:        c.QueryInt64("limit"), | ||||||
| 		User:        c.SignedInUser, | 		User:         c.SignedInUser, | ||||||
|  | 		Query:        c.Query("query"), | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	states := c.QueryStrings("state") | 	states := c.QueryStrings("state") | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ import ( | ||||||
| 	"github.com/grafana/grafana/pkg/api/dtos" | 	"github.com/grafana/grafana/pkg/api/dtos" | ||||||
| 	"github.com/grafana/grafana/pkg/bus" | 	"github.com/grafana/grafana/pkg/bus" | ||||||
| 	m "github.com/grafana/grafana/pkg/models" | 	m "github.com/grafana/grafana/pkg/models" | ||||||
|  | 	"github.com/grafana/grafana/pkg/services/search" | ||||||
| 
 | 
 | ||||||
| 	. "github.com/smartystreets/goconvey/convey" | 	. "github.com/smartystreets/goconvey/convey" | ||||||
| ) | ) | ||||||
|  | @ -64,6 +65,60 @@ func TestAlertingApiEndpoint(t *testing.T) { | ||||||
| 				}) | 				}) | ||||||
| 			}) | 			}) | ||||||
| 		}) | 		}) | ||||||
|  | 
 | ||||||
|  | 		loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alerts?dashboardId=1", "/api/alerts", m.ROLE_EDITOR, func(sc *scenarioContext) { | ||||||
|  | 			var searchQuery *search.Query | ||||||
|  | 			bus.AddHandler("test", func(query *search.Query) error { | ||||||
|  | 				searchQuery = query | ||||||
|  | 				return nil | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			var getAlertsQuery *m.GetAlertsQuery | ||||||
|  | 			bus.AddHandler("test", func(query *m.GetAlertsQuery) error { | ||||||
|  | 				getAlertsQuery = query | ||||||
|  | 				return nil | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			sc.handlerFunc = GetAlerts | ||||||
|  | 			sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() | ||||||
|  | 
 | ||||||
|  | 			So(searchQuery, ShouldBeNil) | ||||||
|  | 			So(getAlertsQuery, ShouldNotBeNil) | ||||||
|  | 		}) | ||||||
|  | 
 | ||||||
|  | 		loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/alerts?dashboardId=1&dashboardId=2&folderId=3&dashboardTag=abc&dashboardQuery=dbQuery&limit=5&query=alertQuery", "/api/alerts", m.ROLE_EDITOR, func(sc *scenarioContext) { | ||||||
|  | 			var searchQuery *search.Query | ||||||
|  | 			bus.AddHandler("test", func(query *search.Query) error { | ||||||
|  | 				searchQuery = query | ||||||
|  | 				query.Result = search.HitList{ | ||||||
|  | 					&search.Hit{Id: 1}, | ||||||
|  | 					&search.Hit{Id: 2}, | ||||||
|  | 				} | ||||||
|  | 				return nil | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			var getAlertsQuery *m.GetAlertsQuery | ||||||
|  | 			bus.AddHandler("test", func(query *m.GetAlertsQuery) error { | ||||||
|  | 				getAlertsQuery = query | ||||||
|  | 				return nil | ||||||
|  | 			}) | ||||||
|  | 
 | ||||||
|  | 			sc.handlerFunc = GetAlerts | ||||||
|  | 			sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() | ||||||
|  | 
 | ||||||
|  | 			So(searchQuery, ShouldNotBeNil) | ||||||
|  | 			So(searchQuery.DashboardIds[0], ShouldEqual, 1) | ||||||
|  | 			So(searchQuery.DashboardIds[1], ShouldEqual, 2) | ||||||
|  | 			So(searchQuery.FolderIds[0], ShouldEqual, 3) | ||||||
|  | 			So(searchQuery.Tags[0], ShouldEqual, "abc") | ||||||
|  | 			So(searchQuery.Title, ShouldEqual, "dbQuery") | ||||||
|  | 
 | ||||||
|  | 			So(getAlertsQuery, ShouldNotBeNil) | ||||||
|  | 			So(getAlertsQuery.DashboardIDs[0], ShouldEqual, 1) | ||||||
|  | 			So(getAlertsQuery.DashboardIDs[1], ShouldEqual, 2) | ||||||
|  | 			So(getAlertsQuery.Limit, ShouldEqual, 5) | ||||||
|  | 			So(getAlertsQuery.Query, ShouldEqual, "alertQuery") | ||||||
|  | 		}) | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -161,12 +161,13 @@ type SetAlertStateCommand struct { | ||||||
| 
 | 
 | ||||||
| //Queries
 | //Queries
 | ||||||
| type GetAlertsQuery struct { | type GetAlertsQuery struct { | ||||||
| 	OrgId       int64 | 	OrgId        int64 | ||||||
| 	State       []string | 	State        []string | ||||||
| 	DashboardId int64 | 	DashboardIDs []int64 | ||||||
| 	PanelId     int64 | 	PanelId      int64 | ||||||
| 	Limit       int64 | 	Limit        int64 | ||||||
| 	User        *SignedInUser | 	Query        string | ||||||
|  | 	User         *SignedInUser | ||||||
| 
 | 
 | ||||||
| 	Result []*AlertListItemDTO | 	Result []*AlertListItemDTO | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -82,8 +82,16 @@ func HandleAlertsQuery(query *m.GetAlertsQuery) error { | ||||||
| 
 | 
 | ||||||
| 	builder.Write(`WHERE alert.org_id = ?`, query.OrgId) | 	builder.Write(`WHERE alert.org_id = ?`, query.OrgId) | ||||||
| 
 | 
 | ||||||
| 	if query.DashboardId != 0 { | 	if len(strings.TrimSpace(query.Query)) > 0 { | ||||||
| 		builder.Write(` AND alert.dashboard_id = ?`, query.DashboardId) | 		builder.Write(" AND alert.name "+dialect.LikeStr()+" ?", "%"+query.Query+"%") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(query.DashboardIDs) > 0 { | ||||||
|  | 		builder.sql.WriteString(` AND alert.dashboard_id IN (?` + strings.Repeat(",?", len(query.DashboardIDs)-1) + `) `) | ||||||
|  | 
 | ||||||
|  | 		for _, dbID := range query.DashboardIDs { | ||||||
|  | 			builder.AddParams(dbID) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if query.PanelId != 0 { | 	if query.PanelId != 0 { | ||||||
|  |  | ||||||
|  | @ -3,10 +3,11 @@ package sqlstore | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
|  | 	"time" | ||||||
|  | 
 | ||||||
| 	"github.com/grafana/grafana/pkg/components/simplejson" | 	"github.com/grafana/grafana/pkg/components/simplejson" | ||||||
| 	m "github.com/grafana/grafana/pkg/models" | 	m "github.com/grafana/grafana/pkg/models" | ||||||
| 	. "github.com/smartystreets/goconvey/convey" | 	. "github.com/smartystreets/goconvey/convey" | ||||||
| 	"time" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func mockTimeNow() { | func mockTimeNow() { | ||||||
|  | @ -99,7 +100,7 @@ func TestAlertingDataAccess(t *testing.T) { | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		Convey("Can read properties", func() { | 		Convey("Can read properties", func() { | ||||||
| 			alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | 			alertQuery := m.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | ||||||
| 			err2 := HandleAlertsQuery(&alertQuery) | 			err2 := HandleAlertsQuery(&alertQuery) | ||||||
| 
 | 
 | ||||||
| 			alert := alertQuery.Result[0] | 			alert := alertQuery.Result[0] | ||||||
|  | @ -109,7 +110,7 @@ func TestAlertingDataAccess(t *testing.T) { | ||||||
| 		}) | 		}) | ||||||
| 
 | 
 | ||||||
| 		Convey("Viewer cannot read alerts", func() { | 		Convey("Viewer cannot read alerts", func() { | ||||||
| 			alertQuery := m.GetAlertsQuery{DashboardId: testDash.Id, PanelId: 1, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_VIEWER}} | 			alertQuery := m.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_VIEWER}} | ||||||
| 			err2 := HandleAlertsQuery(&alertQuery) | 			err2 := HandleAlertsQuery(&alertQuery) | ||||||
| 
 | 
 | ||||||
| 			So(err2, ShouldBeNil) | 			So(err2, ShouldBeNil) | ||||||
|  | @ -134,7 +135,7 @@ func TestAlertingDataAccess(t *testing.T) { | ||||||
| 			}) | 			}) | ||||||
| 
 | 
 | ||||||
| 			Convey("Alerts should be updated", func() { | 			Convey("Alerts should be updated", func() { | ||||||
| 				query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | 				query := m.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | ||||||
| 				err2 := HandleAlertsQuery(&query) | 				err2 := HandleAlertsQuery(&query) | ||||||
| 
 | 
 | ||||||
| 				So(err2, ShouldBeNil) | 				So(err2, ShouldBeNil) | ||||||
|  | @ -183,7 +184,7 @@ func TestAlertingDataAccess(t *testing.T) { | ||||||
| 			Convey("Should save 3 dashboards", func() { | 			Convey("Should save 3 dashboards", func() { | ||||||
| 				So(err, ShouldBeNil) | 				So(err, ShouldBeNil) | ||||||
| 
 | 
 | ||||||
| 				queryForDashboard := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | 				queryForDashboard := m.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | ||||||
| 				err2 := HandleAlertsQuery(&queryForDashboard) | 				err2 := HandleAlertsQuery(&queryForDashboard) | ||||||
| 
 | 
 | ||||||
| 				So(err2, ShouldBeNil) | 				So(err2, ShouldBeNil) | ||||||
|  | @ -197,7 +198,7 @@ func TestAlertingDataAccess(t *testing.T) { | ||||||
| 				err = SaveAlerts(&cmd) | 				err = SaveAlerts(&cmd) | ||||||
| 
 | 
 | ||||||
| 				Convey("should delete the missing alert", func() { | 				Convey("should delete the missing alert", func() { | ||||||
| 					query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | 					query := m.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | ||||||
| 					err2 := HandleAlertsQuery(&query) | 					err2 := HandleAlertsQuery(&query) | ||||||
| 					So(err2, ShouldBeNil) | 					So(err2, ShouldBeNil) | ||||||
| 					So(len(query.Result), ShouldEqual, 2) | 					So(len(query.Result), ShouldEqual, 2) | ||||||
|  | @ -232,7 +233,7 @@ func TestAlertingDataAccess(t *testing.T) { | ||||||
| 			So(err, ShouldBeNil) | 			So(err, ShouldBeNil) | ||||||
| 
 | 
 | ||||||
| 			Convey("Alerts should be removed", func() { | 			Convey("Alerts should be removed", func() { | ||||||
| 				query := m.GetAlertsQuery{DashboardId: testDash.Id, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | 				query := m.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &m.SignedInUser{OrgRole: m.ROLE_ADMIN}} | ||||||
| 				err2 := HandleAlertsQuery(&query) | 				err2 := HandleAlertsQuery(&query) | ||||||
| 
 | 
 | ||||||
| 				So(testDash.Id, ShouldEqual, 1) | 				So(testDash.Id, ShouldEqual, 1) | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ export class FolderPickerCtrl { | ||||||
|   enterFolderCreation: any; |   enterFolderCreation: any; | ||||||
|   exitFolderCreation: any; |   exitFolderCreation: any; | ||||||
|   enableCreateNew: boolean; |   enableCreateNew: boolean; | ||||||
|  |   enableReset: boolean; | ||||||
|   rootName = 'General'; |   rootName = 'General'; | ||||||
|   folder: any; |   folder: any; | ||||||
|   createNewFolder: boolean; |   createNewFolder: boolean; | ||||||
|  | @ -58,6 +59,10 @@ export class FolderPickerCtrl { | ||||||
|         result.unshift({ title: '-- New Folder --', id: -1 }); |         result.unshift({ title: '-- New Folder --', id: -1 }); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
|  |       if (this.enableReset && query === '' && this.initialTitle !== '') { | ||||||
|  |         result.unshift({ title: this.initialTitle, id: null }); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|       return _.map(result, item => { |       return _.map(result, item => { | ||||||
|         return { text: item.title, value: item.id }; |         return { text: item.title, value: item.id }; | ||||||
|       }); |       }); | ||||||
|  | @ -65,7 +70,9 @@ export class FolderPickerCtrl { | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   onFolderChange(option) { |   onFolderChange(option) { | ||||||
|     if (option.value === -1) { |     if (!option) { | ||||||
|  |       option = { value: 0, text: this.rootName }; | ||||||
|  |     } else if (option.value === -1) { | ||||||
|       this.createNewFolder = true; |       this.createNewFolder = true; | ||||||
|       this.enterFolderCreation(); |       this.enterFolderCreation(); | ||||||
|       return; |       return; | ||||||
|  | @ -134,7 +141,7 @@ export class FolderPickerCtrl { | ||||||
|         this.onFolderLoad(); |         this.onFolderLoad(); | ||||||
|       }); |       }); | ||||||
|     } else { |     } else { | ||||||
|       if (this.initialTitle) { |       if (this.initialTitle && this.initialFolderId === null) { | ||||||
|         this.folder = { text: this.initialTitle, value: null }; |         this.folder = { text: this.initialTitle, value: null }; | ||||||
|       } else { |       } else { | ||||||
|         this.folder = { text: this.rootName, value: 0 }; |         this.folder = { text: this.rootName, value: 0 }; | ||||||
|  | @ -171,6 +178,7 @@ export function folderPicker() { | ||||||
|       enterFolderCreation: '&', |       enterFolderCreation: '&', | ||||||
|       exitFolderCreation: '&', |       exitFolderCreation: '&', | ||||||
|       enableCreateNew: '@', |       enableCreateNew: '@', | ||||||
|  |       enableReset: '@', | ||||||
|     }, |     }, | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -19,6 +19,30 @@ | ||||||
|     </div> |     </div> | ||||||
|     <gf-form-switch class="gf-form" label="Alerts from this dashboard" label-class="width-18" checked="ctrl.panel.onlyAlertsOnDashboard" on-change="ctrl.updateStateFilter()"></gf-form-switch> |     <gf-form-switch class="gf-form" label="Alerts from this dashboard" label-class="width-18" checked="ctrl.panel.onlyAlertsOnDashboard" on-change="ctrl.updateStateFilter()"></gf-form-switch> | ||||||
|   </div> |   </div> | ||||||
|  |   <div class="section gf-form-group" ng-show="ctrl.panel.show === 'current'"> | ||||||
|  |     <h5 class="section-heading">Filter</h5> | ||||||
|  |     <div class="gf-form"> | ||||||
|  |       <span class="gf-form-label width-8">Alert name</span> | ||||||
|  |       <input type="text" class="gf-form-input max-width-15" ng-model="ctrl.panel.nameFilter" placeholder="Alert name query" ng-change="ctrl.onRefresh()" /> | ||||||
|  |     </div> | ||||||
|  |     <div class="gf-form"> | ||||||
|  |       <span class="gf-form-label width-8">Dashboard title</span> | ||||||
|  |       <input type="text" class="gf-form-input" placeholder="Dashboard title query" ng-model="ctrl.panel.dashboardFilter" ng-change="ctrl.onRefresh()" ng-model-onblur> | ||||||
|  |     </div> | ||||||
|  |     <div class="gf-form"> | ||||||
|  |       <folder-picker  initial-folder-id="ctrl.panel.folderId" | ||||||
|  |                       on-change="ctrl.onFolderChange($folder)" | ||||||
|  |                       label-class="width-8" | ||||||
|  |                       initial-title="'All'" | ||||||
|  |                       enable-reset="true" > | ||||||
|  |       </folder-picker> | ||||||
|  |     </div> | ||||||
|  |     <div class="gf-form"> | ||||||
|  |         <span class="gf-form-label width-8">Dashboard tags</span> | ||||||
|  |         <bootstrap-tagsinput ng-model="ctrl.panel.dashboardTags" tagclass="label label-tag" placeholder="add tags" on-tags-updated="ctrl.refresh()"> | ||||||
|  |         </bootstrap-tagsinput> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|   <div class="section gf-form-group" ng-show="ctrl.panel.show === 'current'"> |   <div class="section gf-form-group" ng-show="ctrl.panel.show === 'current'"> | ||||||
|     <h5 class="section-heading">State filter</h5> |     <h5 class="section-heading">State filter</h5> | ||||||
|     <gf-form-switch class="gf-form" label="Ok" label-class="width-10" checked="ctrl.stateFilter['ok']" on-change="ctrl.updateStateFilter()"></gf-form-switch> |     <gf-form-switch class="gf-form" label="Ok" label-class="width-10" checked="ctrl.stateFilter['ok']" on-change="ctrl.updateStateFilter()"></gf-form-switch> | ||||||
|  |  | ||||||
|  | @ -21,6 +21,7 @@ class AlertListPanel extends PanelCtrl { | ||||||
|   currentAlerts: any = []; |   currentAlerts: any = []; | ||||||
|   alertHistory: any = []; |   alertHistory: any = []; | ||||||
|   noAlertsMessage: string; |   noAlertsMessage: string; | ||||||
|  | 
 | ||||||
|   // Set and populate defaults
 |   // Set and populate defaults
 | ||||||
|   panelDefaults = { |   panelDefaults = { | ||||||
|     show: 'current', |     show: 'current', | ||||||
|  | @ -28,6 +29,9 @@ class AlertListPanel extends PanelCtrl { | ||||||
|     stateFilter: [], |     stateFilter: [], | ||||||
|     onlyAlertsOnDashboard: false, |     onlyAlertsOnDashboard: false, | ||||||
|     sortOrder: 1, |     sortOrder: 1, | ||||||
|  |     dashboardFilter: '', | ||||||
|  |     nameFilter: '', | ||||||
|  |     folderId: null, | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   /** @ngInject */ |   /** @ngInject */ | ||||||
|  | @ -89,6 +93,11 @@ class AlertListPanel extends PanelCtrl { | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   onFolderChange(folder: any) { | ||||||
|  |     this.panel.folderId = folder.id; | ||||||
|  |     this.refresh(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   getStateChanges() { |   getStateChanges() { | ||||||
|     var params: any = { |     var params: any = { | ||||||
|       limit: this.panel.limit, |       limit: this.panel.limit, | ||||||
|  | @ -110,6 +119,7 @@ class AlertListPanel extends PanelCtrl { | ||||||
|         al.info = alertDef.getAlertAnnotationInfo(al); |         al.info = alertDef.getAlertAnnotationInfo(al); | ||||||
|         return al; |         return al; | ||||||
|       }); |       }); | ||||||
|  | 
 | ||||||
|       this.noAlertsMessage = this.alertHistory.length === 0 ? 'No alerts in current time range' : ''; |       this.noAlertsMessage = this.alertHistory.length === 0 ? 'No alerts in current time range' : ''; | ||||||
| 
 | 
 | ||||||
|       return this.alertHistory; |       return this.alertHistory; | ||||||
|  | @ -121,10 +131,26 @@ class AlertListPanel extends PanelCtrl { | ||||||
|       state: this.panel.stateFilter, |       state: this.panel.stateFilter, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|  |     if (this.panel.nameFilter) { | ||||||
|  |       params.query = this.panel.nameFilter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (this.panel.folderId >= 0) { | ||||||
|  |       params.folderId = this.panel.folderId; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (this.panel.dashboardFilter) { | ||||||
|  |       params.dashboardQuery = this.panel.dashboardFilter; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     if (this.panel.onlyAlertsOnDashboard) { |     if (this.panel.onlyAlertsOnDashboard) { | ||||||
|       params.dashboardId = this.dashboard.id; |       params.dashboardId = this.dashboard.id; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (this.panel.dashboardTags) { | ||||||
|  |       params.dashboardTag = this.panel.dashboardTags; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return this.backendSrv.get(`/api/alerts`, params).then(res => { |     return this.backendSrv.get(`/api/alerts`, params).then(res => { | ||||||
|       this.currentAlerts = this.sortResult( |       this.currentAlerts = this.sortResult( | ||||||
|         _.map(res, al => { |         _.map(res, al => { | ||||||
|  | @ -135,6 +161,9 @@ class AlertListPanel extends PanelCtrl { | ||||||
|           return al; |           return al; | ||||||
|         }) |         }) | ||||||
|       ); |       ); | ||||||
|  |       if (this.currentAlerts.length > this.panel.limit) { | ||||||
|  |         this.currentAlerts = this.currentAlerts.slice(0, this.panel.limit); | ||||||
|  |       } | ||||||
|       this.noAlertsMessage = this.currentAlerts.length === 0 ? 'No alerts' : ''; |       this.noAlertsMessage = this.currentAlerts.length === 0 ? 'No alerts' : ''; | ||||||
| 
 | 
 | ||||||
|       return this.currentAlerts; |       return this.currentAlerts; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue