mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-17 09:37:02 +00:00
* WIP: msghub handles deletes, UI does not yet display them Signed-off-by: James Hillyerd <james@hillyerd.com> * socket and UI support message deletes Signed-off-by: James Hillyerd <james@hillyerd.com> * use Delete naming for consistency Signed-off-by: James Hillyerd <james@hillyerd.com> --------- Signed-off-by: James Hillyerd <james@hillyerd.com>
207 lines
5.4 KiB
Elm
207 lines
5.4 KiB
Elm
module Page.Monitor exposing (Model, Msg, init, update, view)
|
|
|
|
import Api
|
|
import Data.MessageHeader exposing (MessageHeader)
|
|
import Data.MonitorEvent as MonitorEvent
|
|
import Data.Session exposing (Session)
|
|
import DateFormat as DF
|
|
import Effect exposing (Effect)
|
|
import Html
|
|
exposing
|
|
( Attribute
|
|
, Html
|
|
, button
|
|
, div
|
|
, em
|
|
, h1
|
|
, node
|
|
, span
|
|
, table
|
|
, tbody
|
|
, td
|
|
, text
|
|
, th
|
|
, thead
|
|
, tr
|
|
)
|
|
import Html.Attributes exposing (class, src, tabindex)
|
|
import Html.Events as Events
|
|
import Json.Decode as D
|
|
import Route
|
|
import Time exposing (Posix)
|
|
|
|
|
|
|
|
-- MODEL
|
|
|
|
|
|
type alias Model =
|
|
{ session : Session
|
|
, connected : Bool
|
|
, messages : List MessageHeader
|
|
}
|
|
|
|
|
|
init : Session -> ( Model, Effect Msg )
|
|
init session =
|
|
( Model session False [], Effect.none )
|
|
|
|
|
|
|
|
-- UPDATE
|
|
|
|
|
|
type Msg
|
|
= Connected Bool
|
|
| MessageReceived D.Value
|
|
| Clear
|
|
| OpenMessage MessageHeader
|
|
| MessageKeyPress MessageHeader Int
|
|
|
|
|
|
update : Msg -> Model -> ( Model, Effect Msg )
|
|
update msg model =
|
|
case msg of
|
|
Connected True ->
|
|
( { model | connected = True, messages = [] }, Effect.none )
|
|
|
|
Connected False ->
|
|
( { model | connected = False }, Effect.none )
|
|
|
|
MessageReceived value ->
|
|
case D.decodeValue (MonitorEvent.decoder |> D.at [ "detail" ]) value of
|
|
Ok event ->
|
|
case event of
|
|
MonitorEvent.MessageDeleted deleted ->
|
|
( { model
|
|
| messages =
|
|
List.filter
|
|
(\x -> x.mailbox /= deleted.mailbox || x.id /= deleted.id)
|
|
model.messages
|
|
}
|
|
, Effect.none
|
|
)
|
|
|
|
MonitorEvent.MessageStored header ->
|
|
( { model | messages = header :: List.take 500 model.messages }
|
|
, Effect.none
|
|
)
|
|
|
|
Err err ->
|
|
let
|
|
flash =
|
|
{ title = "Message decoding failed"
|
|
, table = [ ( "Error", D.errorToString err ) ]
|
|
}
|
|
in
|
|
( model, Effect.showFlash flash )
|
|
|
|
Clear ->
|
|
( { model | messages = [] }, Effect.none )
|
|
|
|
OpenMessage header ->
|
|
openMessage header model
|
|
|
|
MessageKeyPress header keyCode ->
|
|
case keyCode of
|
|
13 ->
|
|
openMessage header model
|
|
|
|
_ ->
|
|
( model, Effect.none )
|
|
|
|
|
|
openMessage : MessageHeader -> Model -> ( Model, Effect Msg )
|
|
openMessage header model =
|
|
( model
|
|
, Effect.navigateRoute True (Route.Message header.mailbox header.id)
|
|
)
|
|
|
|
|
|
|
|
-- VIEW
|
|
|
|
|
|
view : Model -> { title : String, modal : Maybe (Html msg), content : List (Html Msg) }
|
|
view model =
|
|
{ title = "Inbucket Monitor"
|
|
, modal = Nothing
|
|
, content =
|
|
[ h1 [] [ text "Monitor" ]
|
|
, div [ class "monitor-header" ]
|
|
[ span [ class "monitor-description" ]
|
|
[ text "Messages will be listed here shortly after delivery. "
|
|
, em []
|
|
[ text
|
|
(if model.connected then
|
|
"Connected."
|
|
|
|
else
|
|
"Disconnected!"
|
|
)
|
|
]
|
|
]
|
|
, span [ class "button-bar monitor-buttons" ]
|
|
[ button [ Events.onClick Clear ] [ text "Clear" ]
|
|
]
|
|
]
|
|
|
|
-- monitor-messages maintains a websocket connection to the Inbucket daemon at the path
|
|
-- specified by `src`.
|
|
, node "monitor-messages"
|
|
[ src (Api.monitorUri model.session)
|
|
, Events.on "connected" (D.map Connected <| D.at [ "detail" ] <| D.bool)
|
|
, Events.on "message" (D.map MessageReceived D.value)
|
|
]
|
|
[]
|
|
, table [ class "monitor" ]
|
|
[ thead []
|
|
[ th [] [ text "Date" ]
|
|
, th [ class "desktop" ] [ text "From" ]
|
|
, th [] [ text "Mailbox" ]
|
|
, th [] [ text "Subject" ]
|
|
]
|
|
, tbody [] (List.map (viewMessage model.session.zone) model.messages)
|
|
]
|
|
]
|
|
}
|
|
|
|
|
|
viewMessage : Time.Zone -> MessageHeader -> Html Msg
|
|
viewMessage zone message =
|
|
tr
|
|
[ tabindex 0
|
|
, Events.onClick (OpenMessage message)
|
|
, onKeyUp (MessageKeyPress message)
|
|
]
|
|
[ td [] [ shortDate zone message.date ]
|
|
, td [ class "desktop" ] [ text message.from ]
|
|
, td [] [ text message.mailbox ]
|
|
, td [] [ text message.subject ]
|
|
]
|
|
|
|
|
|
shortDate : Time.Zone -> Posix -> Html Msg
|
|
shortDate zone date =
|
|
DF.format
|
|
[ DF.dayOfMonthFixed
|
|
, DF.text "-"
|
|
, DF.monthNameAbbreviated
|
|
, DF.text " "
|
|
, DF.hourNumber
|
|
, DF.text ":"
|
|
, DF.minuteFixed
|
|
, DF.text ":"
|
|
, DF.secondFixed
|
|
, DF.text " "
|
|
, DF.amPmUppercase
|
|
]
|
|
zone
|
|
date
|
|
|> text
|
|
|
|
|
|
onKeyUp : (Int -> msg) -> Attribute msg
|
|
onKeyUp tagger =
|
|
Events.on "keyup" (D.map tagger Events.keyCode)
|