Filter silences

1:1 direct match on silences for filtering

Need to fix the reloading.
This commit is contained in:
stuart nelson 2017-02-21 21:04:17 +01:00
parent 95bad7b2d4
commit d0a4fad006
10 changed files with 130 additions and 26 deletions

View File

@ -9,6 +9,7 @@ import Alerts.Update
import Alerts.Types exposing (Route(Receiver))
import Types exposing (..)
import Utils.Types exposing (..)
import Utils.Parsing
import Silences.Api
import Silences.Types exposing (Silence, nullTime, nullSilence)
import Silences.Update
@ -36,6 +37,14 @@ init location =
AlertsRoute alertsRoute ->
Alerts.Update.updateFilter alertsRoute
-- TODO: Extract silences routes to silences namespace
SilencesRoute maybeQuery ->
{ receiver = Nothing
, showSilenced = Nothing
, text = maybeQuery
, matchers = Utils.Parsing.parseLabels maybeQuery
}
_ ->
{ text = Nothing, matchers = Nothing, receiver = Nothing, showSilenced = Nothing }
in
@ -78,12 +87,12 @@ update msg model =
Silences silencesMsg ->
let
( silences, silence, silenceCmd ) =
Silences.Update.update silencesMsg model.silences model.silence
Silences.Update.update silencesMsg model.silences model.silence model.filter
in
( { model | silences = silences, silence = silence }, Cmd.map silenceTranslator silenceCmd )
FetchSilences ->
( { model | silences = Loading, route = SilencesRoute }, Silences.Api.getSilences )
( { model | silences = Loading, route = (SilencesRoute model.filter.text) }, Silences.Api.getSilences )
FetchSilence id ->
( { model | silence = Loading, route = SilenceRoute id }, Silences.Api.getSilence id )
@ -112,6 +121,16 @@ update msg model =
NewUrl url ->
( model, Navigation.newUrl url )
ParseFilterText ->
let
filter =
model.filter
f =
{ filter | matchers = Utils.Parsing.parseLabels filter.text }
in
( { model | filter = f }, Cmd.none )
Noop ->
( model, Cmd.none )
@ -123,7 +142,7 @@ urlUpdate location =
Parsing.urlParser location
in
case route of
SilencesRoute ->
SilencesRoute _ ->
FetchSilences
NewSilenceRoute ->

View File

@ -5,7 +5,7 @@ module Parsing exposing (..)
import Alerts.Parsing exposing (alertsParser)
import Navigation
import Types exposing (Route(..))
import UrlParser exposing ((</>), Parser, int, map, oneOf, parseHash, s, string)
import UrlParser exposing ((</>), (<?>), Parser, int, map, oneOf, parseHash, s, string, stringParam)
import Regex
@ -52,9 +52,9 @@ urlParser location =
NotFound
silencesParser : Parser a a
silencesParser : Parser (Maybe String -> a) a
silencesParser =
s "silences"
s "silences" <?> stringParam "filter"
newSilenceParser : Parser a a

View File

@ -1,19 +1,28 @@
module Silences.Translator exposing (translator)
import Silences.Types exposing (Msg(..), SilencesMsg, OutMsg(NewUrl))
import Silences.Types exposing (Msg(..), SilencesMsg, OutMsg(NewUrl, UpdateFilter, ParseFilterText))
import Utils.Types exposing (Filter)
type alias TranslationDictionary msg =
{ onFormMsg : SilencesMsg -> msg
, onNewUrl : String -> msg
, onUpdateFilter : Filter -> String -> msg
, onParseFilterText : msg
}
translator : TranslationDictionary parentMsg -> Msg -> parentMsg
translator { onFormMsg, onNewUrl } msg =
translator { onFormMsg, onNewUrl, onUpdateFilter, onParseFilterText } msg =
case msg of
ForSelf internal ->
onFormMsg internal
ForParent (NewUrl url) ->
onNewUrl url
ForParent (UpdateFilter filter string) ->
onUpdateFilter filter string
ForParent ParseFilterText ->
onParseFilterText

View File

@ -1,7 +1,7 @@
module Silences.Types exposing (..)
import Http
import Utils.Types exposing (Time, Matcher)
import Utils.Types exposing (Time, Matcher, Filter)
import Utils.Date
import Time
import ISO8601
@ -25,6 +25,8 @@ type Msg
type OutMsg
= NewUrl String
| UpdateFilter Filter String
| ParseFilterText
type SilencesMsg
@ -43,6 +45,7 @@ type SilencesMsg
| SilenceDestroy (Utils.Types.ApiData String)
| CreateSilence Silence
| DestroySilence Silence
| FilterSilences
nullSilence : Silence

View File

@ -4,15 +4,16 @@ import Navigation
import Silences.Api as Api
import Silences.Types exposing (..)
import Task
import Utils.Types as Types exposing (ApiData, ApiResponse(..), Time)
import Utils.Types as Types exposing (ApiData, ApiResponse(..), Time, Filter, Matchers)
import ISO8601
import Time
import Utils.Date
import Utils.List
import Utils.Filter exposing (generateQueryString)
update : SilencesMsg -> ApiData (List Silence) -> ApiData Silence -> ( ApiData (List Silence), ApiData Silence, Cmd Msg )
update msg silences silence =
update : SilencesMsg -> ApiData (List Silence) -> ApiData Silence -> Filter -> ( ApiData (List Silence), ApiData Silence, Cmd Msg )
update msg silences silence filter =
case msg of
CreateSilence silence ->
( silences, Loading, Api.create silence )
@ -130,6 +131,16 @@ update msg silences silence =
in
( silences, Success { sil | startsAt = startsAt, endsAt = endsAt }, Cmd.none )
FilterSilences ->
let
url =
"/#/silences" ++ (generateQueryString filter)
cmds =
Cmd.batch [ generateParentMsg ParseFilterText, generateParentMsg (NewUrl url) ]
in
( silences, silence, cmds )
Noop ->
( silences, silence, Cmd.none )
@ -137,3 +148,21 @@ update msg silences silence =
generateParentMsg : OutMsg -> Cmd Msg
generateParentMsg outMsg =
Task.perform ForParent (Task.succeed outMsg)
filterByMatchers : Maybe Matchers -> List Silence -> List Silence
filterByMatchers maybeMatchers silences =
case maybeMatchers of
Just matchers ->
List.filter
(\s ->
List.all
(\m ->
List.member m s.matchers
)
matchers
)
silences
Nothing ->
silences

View File

@ -9,21 +9,39 @@ import Html.Events exposing (onClick, onInput)
-- Internal Imports
import Silences.Types exposing (Silence, SilencesMsg(..), Msg(..))
import Utils.Types exposing (Matcher, ApiResponse(..))
import Silences.Types exposing (Silence, SilencesMsg(..), Msg(..), OutMsg(UpdateFilter))
import Silences.Update exposing (filterByMatchers)
import Utils.Types exposing (Matcher, ApiResponse(..), Filter)
import Utils.Views exposing (..)
import Utils.Date
silences : List Silence -> Html Msg
silences silences =
ul
[ classList
[ ( "list", True )
, ( "pa0", True )
silences : List Silence -> Filter -> Html Msg
silences silences filter =
let
groups =
filterByMatchers filter.matchers silences
filterText =
Maybe.withDefault "" filter.text
html =
if List.isEmpty groups then
div [ class "mt2" ] [ text "no silences found found" ]
else
ul
[ classList
[ ( "list", True )
, ( "pa0", True )
]
]
(List.map silenceList groups)
in
div []
[ Html.map ForParent (textField "Filter" filterText (UpdateFilter filter))
, a [ class "f6 link br2 ba ph3 pv2 mr2 dib blue", onClick (ForSelf FilterSilences) ] [ text "Filter Silences" ]
, html
]
]
(List.map silenceList silences)
silenceList : Silence -> Html Msg

View File

@ -4,7 +4,7 @@ import Alerts.Types
import Alerts.Translator
import Silences.Types
import Silences.Translator
import Types exposing (Msg(Alerts, CreateSilenceFromAlert, Silences, UpdateFilter, NewUrl))
import Types exposing (Msg(Alerts, CreateSilenceFromAlert, Silences, UpdateFilter, NewUrl, ParseFilterText))
alertTranslator : Alerts.Types.Msg -> Msg
@ -22,4 +22,6 @@ silenceTranslator =
Silences.Translator.translator
{ onFormMsg = Silences
, onNewUrl = NewUrl
, onUpdateFilter = UpdateFilter
, onParseFilterText = ParseFilterText
}

View File

@ -37,11 +37,12 @@ type Msg
| Silences SilencesMsg
| RedirectAlerts
| NewUrl String
| ParseFilterText
| Noop
type Route
= SilencesRoute
= SilencesRoute (Maybe String)
| NewSilenceRoute
| SilenceRoute Int
| EditSilenceRoute Int

23
src/Utils/Filter.elm Normal file
View File

@ -0,0 +1,23 @@
module Utils.Filter exposing (..)
import QueryString exposing (QueryString, empty, add, render)
import Utils.Types exposing (Filter)
generateQueryString : Filter -> String
generateQueryString filter =
empty
|> addMaybe "receiver" filter.receiver identity
|> addMaybe "silenced" filter.showSilenced (toString >> String.toLower)
|> addMaybe "filter" filter.text identity
|> render
addMaybe : String -> Maybe a -> (a -> String) -> QueryString -> QueryString
addMaybe key maybeValue stringFn qs =
case maybeValue of
Just value ->
add key (stringFn value) qs
Nothing ->
qs

View File

@ -47,11 +47,11 @@ view model =
Failure msg ->
error msg
SilencesRoute ->
SilencesRoute _ ->
-- Add buttons at the top to filter Active/Pending/Expired
case model.silences of
Success silences ->
Html.map silenceTranslator (Silences.Views.silences silences)
Html.map silenceTranslator (Silences.Views.silences silences model.filter)
Loading ->
loading