Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
N
nexpie-grafana-theme
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Registry
Registry
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Kornkitt Poolsup
nexpie-grafana-theme
Commits
029317ed
Commit
029317ed
authored
Dec 31, 2017
by
Torkel Ödegaard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tech: alert list react migration progress
parent
5a571f47
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
75 deletions
+158
-75
pkg/api/alerting.go
+2
-2
pkg/services/sqlstore/alert.go
+1
-1
public/app/containers/AlertRuleList/AlertRuleList.tsx
+95
-46
public/app/stores/AlertListStore.ts
+58
-24
public/app/stores/RootStore.ts
+2
-2
No files found.
pkg/api/alerting.go
View file @
029317ed
...
@@ -278,7 +278,7 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
...
@@ -278,7 +278,7 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
}
}
var
response
models
.
AlertStateType
=
models
.
AlertStatePending
var
response
models
.
AlertStateType
=
models
.
AlertStatePending
pausedState
:=
"un
paused"
pausedState
:=
"un
-
paused"
if
cmd
.
Paused
{
if
cmd
.
Paused
{
response
=
models
.
AlertStatePaused
response
=
models
.
AlertStatePaused
pausedState
=
"paused"
pausedState
=
"paused"
...
@@ -287,7 +287,7 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
...
@@ -287,7 +287,7 @@ func PauseAlert(c *middleware.Context, dto dtos.PauseAlertCommand) Response {
result
:=
map
[
string
]
interface
{}{
result
:=
map
[
string
]
interface
{}{
"alertId"
:
alertId
,
"alertId"
:
alertId
,
"state"
:
response
,
"state"
:
response
,
"message"
:
"
a
lert "
+
pausedState
,
"message"
:
"
A
lert "
+
pausedState
,
}
}
return
Json
(
200
,
result
)
return
Json
(
200
,
result
)
...
...
pkg/services/sqlstore/alert.go
View file @
029317ed
...
@@ -88,7 +88,7 @@ func HandleAlertsQuery(query *m.GetAlertsQuery) error {
...
@@ -88,7 +88,7 @@ func HandleAlertsQuery(query *m.GetAlertsQuery) error {
params
=
append
(
params
,
query
.
PanelId
)
params
=
append
(
params
,
query
.
PanelId
)
}
}
if
len
(
query
.
State
)
>
0
&&
query
.
State
[
0
]
!=
"
ALL
"
{
if
len
(
query
.
State
)
>
0
&&
query
.
State
[
0
]
!=
"
all
"
{
sql
.
WriteString
(
` AND (`
)
sql
.
WriteString
(
` AND (`
)
for
i
,
v
:=
range
query
.
State
{
for
i
,
v
:=
range
query
.
State
{
if
i
>
0
{
if
i
>
0
{
...
...
public/app/containers/AlertRuleList/AlertRuleList.tsx
View file @
029317ed
...
@@ -2,49 +2,73 @@ import React from 'react';
...
@@ -2,49 +2,73 @@ import React from 'react';
import
classNames
from
'classnames'
;
import
classNames
from
'classnames'
;
import
{
inject
,
observer
}
from
'mobx-react'
;
import
{
inject
,
observer
}
from
'mobx-react'
;
import
PageHeader
from
'app/core/components/PageHeader/PageHeader'
;
import
PageHeader
from
'app/core/components/PageHeader/PageHeader'
;
import
{
IRootStore
}
from
'app/stores/RootStore'
;
import
{
IAlertRule
}
from
'app/stores/AlertListStore'
;
import
appEvents
from
'app/core/app_events'
;
export
interface
I
Props
{
export
interface
AlertRuleList
Props
{
store
:
any
;
store
:
IRootStore
;
}
}
@
inject
(
'store'
)
@
inject
(
'store'
)
@
observer
@
observer
export
class
AlertRuleList
extends
React
.
Component
<
IProps
,
any
>
{
export
class
AlertRuleList
extends
React
.
Component
<
AlertRuleListProps
,
any
>
{
stateFilters
=
[
{
text
:
'All'
,
value
:
'all'
},
{
text
:
'OK'
,
value
:
'ok'
},
{
text
:
'Not OK'
,
value
:
'not_ok'
},
{
text
:
'Alerting'
,
value
:
'alerting'
},
{
text
:
'No Data'
,
value
:
'no_data'
},
{
text
:
'Paused'
,
value
:
'paused'
},
];
constructor
(
props
)
{
constructor
(
props
)
{
super
(
props
);
super
(
props
);
this
.
props
.
store
.
nav
.
load
(
'alerting'
,
'alert-list'
);
this
.
props
.
store
.
nav
.
load
(
'alerting'
,
'alert-list'
);
this
.
props
.
store
.
alert
ing
.
loadRules
();
this
.
props
.
store
.
alert
List
.
loadRules
();
}
}
onStateFilterChanged
=
evt
=>
{
this
.
props
.
store
.
alertList
.
setStateFilter
(
evt
.
target
.
value
);
this
.
props
.
store
.
alertList
.
loadRules
();
};
onOpenHowTo
=
()
=>
{
appEvents
.
emit
(
'show-modal'
,
{
src
:
'public/app/features/alerting/partials/alert_howto.html'
,
modalClass
:
'confirm-modal'
,
model
:
{},
});
};
render
()
{
render
()
{
const
{
nav
,
alertList
}
=
this
.
props
.
store
;
return
(
return
(
<
div
>
<
div
>
<
PageHeader
model=
{
this
.
props
.
store
.
nav
}
/>
<
PageHeader
model=
{
nav
as
any
}
/>
<
div
className=
"page-container page-body"
>
<
div
className=
"page-container page-body"
>
<
div
className=
"page-action-bar"
>
<
div
className=
"page-action-bar"
>
<
div
className=
"gf-form"
>
<
div
className=
"gf-form"
>
<
label
className=
"gf-form-label"
>
Filter by state
</
label
>
<
label
className=
"gf-form-label"
>
Filter by state
</
label
>
<
div
className=
"gf-form-select-wrapper width-13"
>
<
div
className=
"gf-form-select-wrapper width-13"
>
<
select
<
select
className=
"gf-form-input"
onChange=
{
this
.
onStateFilterChanged
}
>
className=
"gf-form-input"
{
this
.
stateFilters
.
map
(
AlertStateFilterOption
)
}
ng
-
model=
"ctrl.filters.state"
</
select
>
ng
-
options=
"f.value as f.text for f in ctrl.stateFilters"
ng
-
change=
"ctrl.filtersChanged()"
/>
</
div
>
</
div
>
</
div
>
</
div
>
<
div
className=
"page-action-bar__spacer"
/>
<
div
className=
"page-action-bar__spacer"
/>
<
a
className=
"btn btn-secondary"
ng
-
click=
"ctrl.openHowTo()"
>
<
a
className=
"btn btn-secondary"
onClick=
{
this
.
onOpenHowTo
}
>
<
i
className=
"fa fa-info-circle"
/>
How to add an alert
<
i
className=
"fa fa-info-circle"
/>
How to add an alert
</
a
>
</
a
>
</
div
>
</
div
>
<
section
className=
"card-section card-list-layout-list"
>
<
section
className=
"card-section card-list-layout-list"
>
<
ol
className=
"card-list"
>
{
this
.
props
.
store
.
alerting
.
rules
.
map
(
AlertRuleItem
)
}
</
ol
>
<
ol
className=
"card-list"
>
{
alertList
.
rules
.
map
(
rule
=>
<
AlertRuleItem
rule=
{
rule
}
key=
{
rule
.
id
}
/>
)
}
</
ol
>
</
section
>
</
section
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -52,43 +76,68 @@ export class AlertRuleList extends React.Component<IProps, any> {
...
@@ -52,43 +76,68 @@ export class AlertRuleList extends React.Component<IProps, any> {
}
}
}
}
function
AlertRuleItem
(
rule
)
{
function
AlertStateFilterOption
({
text
,
value
})
{
let
stateClass
=
classNames
({
return
(
fa
:
true
,
<
option
key=
{
value
}
value=
{
value
}
>
'fa-play'
:
rule
.
state
===
'paused'
,
{
text
}
'fa-pause'
:
rule
.
state
!==
'paused'
,
</
option
>
});
);
}
let
ruleUrl
=
`dashboard/
${
rule
.
dashboardUri
}
?panelId=
${
rule
.
panelId
}
&fullscreen&edit&tab=alert`
;
export
interface
AlertRuleItemProps
{
rule
:
IAlertRule
;
}
return
(
@
observer
<
li
className=
"card-item-wrapper"
key=
{
rule
.
id
}
>
export
class
AlertRuleItem
extends
React
.
Component
<
AlertRuleItemProps
,
any
>
{
<
div
className=
"card-item card-item--alert"
>
toggleState
=
()
=>
{
<
div
className=
"card-item-header"
>
this
.
props
.
rule
.
togglePaused
();
<
div
className=
"card-item-type"
>
};
<
a
className=
"card-item-cog"
title=
"Pausing an alert rule prevents it from executing"
>
<
i
className=
{
stateClass
}
/>
render
()
{
</
a
>
const
{
rule
}
=
this
.
props
;
<
a
className=
"card-item-cog"
href=
{
ruleUrl
}
title=
"Edit alert rule"
>
<
i
className=
"icon-gf icon-gf-settings"
/>
let
stateClass
=
classNames
({
</
a
>
fa
:
true
,
</
div
>
'fa-play'
:
rule
.
isPaused
,
</
div
>
'fa-pause'
:
!
rule
.
isPaused
,
<
div
className=
"card-item-body"
>
});
<
div
className=
"card-item-details"
>
<
div
className=
"card-item-name"
>
let
ruleUrl
=
`dashboard/
${
rule
.
dashboardUri
}
?panelId=
${
rule
.
panelId
}
&fullscreen&edit&tab=alert`
;
<
a
href=
{
ruleUrl
}
>
{
rule
.
name
}
</
a
>
return
(
<
li
className=
"card-item-wrapper"
>
<
div
className=
"card-item card-item--alert"
>
<
div
className=
"card-item-header"
>
<
div
className=
"card-item-type"
>
<
a
className=
"card-item-cog"
title=
"Pausing an alert rule prevents it from executing"
onClick=
{
this
.
toggleState
}
>
<
i
className=
{
stateClass
}
/>
</
a
>
<
a
className=
"card-item-cog"
href=
{
ruleUrl
}
title=
"Edit alert rule"
>
<
i
className=
"icon-gf icon-gf-settings"
/>
</
a
>
</
div
>
</
div
>
<
div
className=
"card-item-sub-name"
>
</
div
>
<
span
className=
{
`alert-list-item-state ${rule.stateClass}`
}
>
<
div
className=
"card-item-body"
>
<
i
className=
{
rule
.
stateIcon
}
/>
{
rule
.
stateText
}
<
div
className=
"card-item-details"
>
</
span
>
<
div
className=
"card-item-name"
>
<
span
>
for
{
rule
.
stateAge
}
</
span
>
<
a
href=
{
ruleUrl
}
>
{
rule
.
name
}
</
a
>
</
div
>
<
div
className=
"card-item-sub-name"
>
<
span
className=
{
`alert-list-item-state ${rule.stateClass}`
}
>
<
i
className=
{
rule
.
stateIcon
}
/>
{
rule
.
stateText
}
</
span
>
<
span
>
for
{
rule
.
stateAge
}
</
span
>
</
div
>
{
rule
.
info
&&
<
div
className=
"small muted"
>
{
rule
.
info
}
</
div
>
}
</
div
>
</
div
>
{
rule
.
info
&&
<
div
className=
"small muted"
>
{
rule
.
info
}
</
div
>
}
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
li
>
</
li
>
);
);
}
}
}
public/app/stores/Alert
ing
Store.ts
→
public/app/stores/Alert
List
Store.ts
View file @
029317ed
...
@@ -2,40 +2,74 @@ import { types, getEnv, flow } from 'mobx-state-tree';
...
@@ -2,40 +2,74 @@ import { types, getEnv, flow } from 'mobx-state-tree';
import
moment
from
'moment'
;
import
moment
from
'moment'
;
import
alertDef
from
'app/features/alerting/alert_def'
;
import
alertDef
from
'app/features/alerting/alert_def'
;
export
const
AlertRule
=
types
.
model
(
'AlertRule'
,
{
function
setStateFields
(
rule
,
state
)
{
id
:
types
.
identifier
(
types
.
number
),
let
stateModel
=
alertDef
.
getStateDisplayModel
(
state
);
dashboardId
:
types
.
number
,
rule
.
state
=
state
;
panelId
:
types
.
number
,
rule
.
stateText
=
stateModel
.
text
;
name
:
types
.
string
,
rule
.
stateIcon
=
stateModel
.
iconClass
;
state
:
types
.
string
,
rule
.
stateClass
=
stateModel
.
stateClass
;
stateText
:
types
.
string
,
rule
.
stateAge
=
moment
(
rule
.
newStateDate
)
stateIcon
:
types
.
string
,
.
fromNow
()
stateClass
:
types
.
string
,
.
replace
(
' ago'
,
''
);
stateAge
:
types
.
string
,
}
info
:
types
.
optional
(
types
.
string
,
''
),
dashboardUri
:
types
.
string
,
export
const
AlertRule
=
types
});
.
model
(
'AlertRule'
,
{
id
:
types
.
identifier
(
types
.
number
),
export
const
AlertingStore
=
types
dashboardId
:
types
.
number
,
.
model
(
'AlertingStore'
,
{
panelId
:
types
.
number
,
name
:
types
.
string
,
state
:
types
.
string
,
stateText
:
types
.
string
,
stateIcon
:
types
.
string
,
stateClass
:
types
.
string
,
stateAge
:
types
.
string
,
info
:
types
.
optional
(
types
.
string
,
''
),
dashboardUri
:
types
.
string
,
})
.
views
(
self
=>
({
get
isPaused
()
{
return
self
.
state
===
'paused'
;
},
}))
.
actions
(
self
=>
({
/**
* will toggle alert rule paused state
*/
togglePaused
:
flow
(
function
*
togglePaused
()
{
let
backendSrv
=
getEnv
(
self
).
backendSrv
;
var
payload
=
{
paused
:
self
.
isPaused
};
let
res
=
yield
backendSrv
.
post
(
`/api/alerts/
${
self
.
id
}
/pause`
,
payload
);
setStateFields
(
self
,
res
.
state
);
self
.
info
=
''
;
}),
}));
type
IAlertRuleType
=
typeof
AlertRule
.
Type
;
export
interface
IAlertRule
extends
IAlertRuleType
{}
export
const
AlertListStore
=
types
.
model
(
'AlertListStore'
,
{
rules
:
types
.
array
(
AlertRule
),
rules
:
types
.
array
(
AlertRule
),
stateFilter
:
types
.
optional
(
types
.
string
,
'all'
),
})
})
.
actions
(
self
=>
({
.
actions
(
self
=>
({
setStateFilter
:
function
(
state
)
{
self
.
stateFilter
=
state
;
},
loadRules
:
flow
(
function
*
load
()
{
loadRules
:
flow
(
function
*
load
()
{
let
backendSrv
=
getEnv
(
self
).
backendSrv
;
let
backendSrv
=
getEnv
(
self
).
backendSrv
;
let
rules
=
yield
backendSrv
.
get
(
'/api/alerts'
);
let
filters
=
{
state
:
self
.
stateFilter
};
let
rules
=
yield
backendSrv
.
get
(
'/api/alerts'
,
filters
);
self
.
rules
.
clear
();
self
.
rules
.
clear
();
for
(
let
rule
of
rules
)
{
for
(
let
rule
of
rules
)
{
let
stateModel
=
alertDef
.
getStateDisplayModel
(
rule
.
state
);
setStateFields
(
rule
,
rule
.
state
);
rule
.
stateText
=
stateModel
.
text
;
rule
.
stateIcon
=
stateModel
.
iconClass
;
rule
.
stateClass
=
stateModel
.
stateClass
;
rule
.
stateAge
=
moment
(
rule
.
newStateDate
)
.
fromNow
()
.
replace
(
' ago'
,
''
);
if
(
rule
.
executionError
)
{
if
(
rule
.
executionError
)
{
rule
.
info
=
'Execution Error: '
+
rule
.
executionError
;
rule
.
info
=
'Execution Error: '
+
rule
.
executionError
;
...
...
public/app/stores/RootStore.ts
View file @
029317ed
...
@@ -2,7 +2,7 @@ import { types } from 'mobx-state-tree';
...
@@ -2,7 +2,7 @@ import { types } from 'mobx-state-tree';
import
{
SearchStore
}
from
'./SearchStore'
;
import
{
SearchStore
}
from
'./SearchStore'
;
import
{
ServerStatsStore
}
from
'./ServerStatsStore'
;
import
{
ServerStatsStore
}
from
'./ServerStatsStore'
;
import
{
NavStore
}
from
'./NavStore'
;
import
{
NavStore
}
from
'./NavStore'
;
import
{
Alert
ingStore
}
from
'./Alerting
Store'
;
import
{
Alert
ListStore
}
from
'./AlertList
Store'
;
export
const
RootStore
=
types
.
model
({
export
const
RootStore
=
types
.
model
({
search
:
types
.
optional
(
SearchStore
,
{
search
:
types
.
optional
(
SearchStore
,
{
...
@@ -12,7 +12,7 @@ export const RootStore = types.model({
...
@@ -12,7 +12,7 @@ export const RootStore = types.model({
stats
:
[],
stats
:
[],
}),
}),
nav
:
types
.
optional
(
NavStore
,
{}),
nav
:
types
.
optional
(
NavStore
,
{}),
alert
ing
:
types
.
optional
(
Alerting
Store
,
{
alert
List
:
types
.
optional
(
AlertList
Store
,
{
rules
:
[],
rules
:
[],
}),
}),
});
});
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment