Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix the slowness of the Silence UI #1235

Merged
merged 2 commits into from
Feb 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions ui/app/src/Utils/Api.elm
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,22 @@ import Utils.Date
import Utils.Types exposing (ApiData(..))


map : (a -> b) -> ApiData a -> ApiData b
map fn response =
case response of
Success value ->
Success (fn value)

Initial ->
Initial

Loading ->
Loading

Failure a ->
Failure a


withDefault : a -> ApiData a -> a
withDefault default response =
case response of
Expand Down
5 changes: 4 additions & 1 deletion ui/app/src/Views/AlertList/AlertView.elm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ view labels maybeActiveId alert =
|> uncurry (++)
in
li
[ class "align-items-start list-group-item border-0 alert-list-item p-0 mb-4"
[ -- speedup rendering in Chrome, because list-group-item className
-- creates a new layer in the rendering engine
style [ ( "position", "static" ) ]
, class "align-items-start list-group-item border-0 p-0 mb-4"
]
[ div
[ class "w-100 mb-2 d-flex align-items-start" ]
Expand Down
8 changes: 6 additions & 2 deletions ui/app/src/Views/SilenceList/SilenceView.elm
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ import Utils.List
import Utils.Types exposing (Matcher)
import Utils.Views exposing (buttonLink)
import Views.FilterBar.Types as FilterBarTypes
import Views.SilenceForm.Types exposing (SilenceFormMsg(NewSilenceFromMatchers))
import Views.SilenceList.Types exposing (SilenceListMsg(ConfirmDestroySilence, DestroySilence, FetchSilences, MsgForFilterBar))
import Views.SilenceForm.Parsing exposing (newSilenceFromAlertLabels)


view : Bool -> Silence -> Html Msg
view showConfirmationDialog silence =
li [ class "align-items-start list-group-item border-0 alert-list-item p-0 mb-4" ]
li
[ -- speedup rendering in Chrome, because list-group-item className
-- creates a new layer in the rendering engine
style [ ( "position", "static" ) ]
, class "align-items-start list-group-item border-0 p-0 mb-4"
]
[ div [ class "w-100 mb-2 d-flex align-items-start" ]
[ case silence.status.state of
Active ->
Expand Down
11 changes: 9 additions & 2 deletions ui/app/src/Views/SilenceList/Types.elm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Views.SilenceList.Types exposing (Model, SilenceListMsg(..), initSilenceList)
module Views.SilenceList.Types exposing (Model, SilenceTab, SilenceListMsg(..), initSilenceList)

import Silences.Types exposing (Silence, State(Active), SilenceId)
import Utils.Types exposing (ApiData(Initial))
Expand All @@ -14,8 +14,15 @@ type SilenceListMsg
| SetTab State


type alias SilenceTab =
{ silences : List Silence
, tab : State
, count : Int
}


type alias Model =
{ silences : ApiData (List Silence)
{ silences : ApiData (List SilenceTab)
, filterBar : FilterBar.Model
, tab : State
, showConfirmationDialog : Maybe SilenceId
Expand Down
37 changes: 34 additions & 3 deletions ui/app/src/Views/SilenceList/Updates.elm
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@ module Views.SilenceList.Updates exposing (update, urlUpdate)

import Navigation
import Silences.Api as Api
import Utils.Api as ApiData
import Utils.Filter exposing (Filter, generateQueryString)
import Utils.Types as Types exposing (ApiData(Failure, Loading, Success), Matchers, Time)
import Views.FilterBar.Updates as FilterBar
import Views.SilenceList.Types exposing (Model, SilenceListMsg(..))
import Views.SilenceList.Types exposing (Model, SilenceTab, SilenceListMsg(..))
import Silences.Types exposing (Silence, State(..))


update : SilenceListMsg -> Model -> Filter -> String -> String -> ( Model, Cmd SilenceListMsg )
update msg model filter basePath apiUrl =
case msg of
SilencesFetch sils ->
( { model | silences = sils }, Cmd.none )
SilencesFetch fetchedSilences ->
( { model
| silences =
ApiData.map
(\silences -> List.map (groupSilencesByState silences) states)
fetchedSilences
}
, Cmd.none
)

FetchSilences ->
( { model
Expand Down Expand Up @@ -50,6 +59,28 @@ update msg model filter basePath apiUrl =
( { model | tab = tab }, Cmd.none )


groupSilencesByState : List Silence -> State -> SilenceTab
groupSilencesByState silences state =
let
silencesInTab =
filterSilencesByState state silences
in
{ tab = state
, silences = silencesInTab
, count = List.length silencesInTab
}


states : List State
states =
[ Active, Pending, Expired ]


filterSilencesByState : State -> List Silence -> List Silence
filterSilencesByState state =
List.filter (.status >> .state >> (==) state)


urlUpdate : Maybe String -> ( SilenceListMsg, Filter )
urlUpdate maybeString =
( FetchSilences, updateFilter maybeString )
Expand Down
85 changes: 53 additions & 32 deletions ui/app/src/Views/SilenceList/Views.elm
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import Html exposing (..)
import Html.Attributes exposing (..)
import Silences.Types exposing (Silence, State(..), stateToString, SilenceId)
import Types exposing (Msg(MsgForSilenceList, Noop, UpdateFilter))
import Utils.Api exposing (withDefault)
import Utils.String as StringUtils
import Utils.Types exposing (ApiData(..), Matcher)
import Utils.Views exposing (buttonLink, checkbox, error, formField, formInput, iconButtonMsg, loading, textField)
import Views.FilterBar.Views as FilterBar
import Views.SilenceList.SilenceView
import Views.SilenceList.Types exposing (Model, SilenceListMsg(..))
import Views.SilenceList.Types exposing (Model, SilenceListMsg(..), SilenceTab)
import Html.Lazy exposing (lazy, lazy2, lazy3)
import Html.Keyed


view : Model -> Html Msg
Expand All @@ -20,49 +21,69 @@ view { filterBar, tab, silences, showConfirmationDialog } =
[ label [ class "mb-2", for "filter-bar-matcher" ] [ text "Filter" ]
, Html.map (MsgForFilterBar >> MsgForSilenceList) (FilterBar.view filterBar)
]
, ul [ class "nav nav-tabs mb-4" ]
(List.map (tabView tab) (groupSilencesByState (withDefault [] silences)))
, case silences of
Success sils ->
silencesView showConfirmationDialog (filterSilencesByState tab sils)
, lazy2 tabsView tab silences
, lazy3 silencesView showConfirmationDialog tab silences
]

Failure msg ->
error msg

_ ->
loading
]
tabsView : State -> ApiData (List SilenceTab) -> Html Msg
tabsView currentTab tabs =
case tabs of
Success silencesTabs ->
List.map (\{ tab, count } -> tabView currentTab count tab) silencesTabs
|> ul [ class "nav nav-tabs mb-4" ]

_ ->
List.map (tabView currentTab 0) states
|> ul [ class "nav nav-tabs mb-4" ]


tabView : State -> ( State, List a ) -> Html Msg
tabView currentState ( state, silences ) =
Utils.Views.tab state currentState (SetTab >> MsgForSilenceList) <|
case List.length silences of
tabView : State -> Int -> State -> Html Msg
tabView currentTab count tab =
Utils.Views.tab tab currentTab (SetTab >> MsgForSilenceList) <|
case count of
0 ->
[ text (StringUtils.capitalizeFirst (stateToString state)) ]
[ text (StringUtils.capitalizeFirst (stateToString tab)) ]

n ->
[ text (StringUtils.capitalizeFirst (stateToString state))
[ text (StringUtils.capitalizeFirst (stateToString tab))
, span
[ class "badge badge-pillow badge-default align-text-top ml-2" ]
[ text (toString n) ]
]


silencesView : Maybe SilenceId -> List Silence -> Html Msg
silencesView showConfirmationDialog silences =
if List.isEmpty silences then
Utils.Views.error "No silences found"
else
ul [ class "list-group" ]
(List.map
(\silence ->
Views.SilenceList.SilenceView.view
(showConfirmationDialog == Just silence.id)
silence
)
silences
)
silencesView : Maybe SilenceId -> State -> ApiData (List SilenceTab) -> Html Msg
silencesView showConfirmationDialog tab silencesTab =
case silencesTab of
Success tabs ->
tabs
|> List.filter (.tab >> (==) tab)
|> List.head
|> Maybe.map .silences
|> Maybe.withDefault []
|> (\silences ->
if List.isEmpty silences then
Utils.Views.error "No silences found"
else
Html.Keyed.ul [ class "list-group" ]
(List.map
(\silence ->
( silence.id
, Views.SilenceList.SilenceView.view
(showConfirmationDialog == Just silence.id)
silence
)
)
silences
)
)

Failure msg ->
error msg

_ ->
loading


groupSilencesByState : List Silence -> List ( State, List Silence )
Expand Down
4 changes: 2 additions & 2 deletions ui/bindata.go

Large diffs are not rendered by default.