Plot.hs
module Frontend.Component.Plot where
import Prelude
import Data.Foldable (sequence_, traverse_)
import Data.Maybe (Maybe(..))
import Data.Traversable (for_)
import Effect.Aff.Class (class MonadAff)
import Effect.Class (class MonadEffect)
import Effect.Class.Console (log)
import Frontend.UPlot as UPlot
import Halogen (liftEffect)
import Halogen as H
import Halogen.HTML as HH
import Halogen.HTML.Properties as HP
import Halogen.Query.EventSource (eventListenerEventSource)
import Web.Event.Event (EventType(..))
import Web.HTML (window)
import Web.HTML.HTMLElement (getBoundingClientRect)
import Web.HTML.Window (document, toEventTarget)
type State =
{ plot :: Maybe UPlot.Plot
, opts :: UPlot.Opts
}
type Data = Array (Array (Maybe Number))
data Query a =
SetData Data a
data Action
= Initialize
| Finalize
| Resize
-- | SetOpts UPlot.Opts
component :: forall o m. MonadAff m => H.Component HH.HTML Query UPlot.Opts o m
component =
H.mkComponent
{ initialState: \opts -> { plot: Nothing, opts }
, render
, eval: H.mkEval $ H.defaultEval
{ handleAction = handleAction
, handleQuery = handleQuery
, initialize = Just Initialize
, finalize = Just Finalize
, receive = const Nothing -- Just <<< SetOpts
}
}
render :: forall m. State -> H.ComponentHTML Action () m
render state = HH.div [ HP.ref (H.RefLabel "plot") ] []
handleQuery :: forall a o m. MonadEffect m => Query a -> H.HalogenM State Action () o m (Maybe a)
handleQuery = case _ of
SetData d a -> do
plot' <- H.get <#> _.plot
for_ plot' \plot -> do
liftEffect $ UPlot.setData plot d
pure (Just a)
handleAction ∷ forall o m. MonadAff m => Action → H.HalogenM State Action () o m Unit
handleAction = case _ of
Initialize -> do
log "Initializing"
div <- H.getHTMLElementRef (H.RefLabel "plot")
opts <- H.get <#> _.opts
for_ div \element -> do
plot <- liftEffect $ UPlot.initialize element opts
-- liftEffect $ setData plot [[1.0, 2.0, 3.0], [10.0, 12.0, 11.0], [20.0, 12.0, 11.0], [30.0, 12.0, 11.0]]
H.modify_ _ { plot = Just plot }
-- Register resize handler
document <- H.liftEffect $ document =<< window
window <- liftEffect window
H.subscribe' \sid ->
eventListenerEventSource
(EventType "resize")
(toEventTarget window)
\ev -> Just Resize
handleAction Resize
-- log $ show element
Finalize -> do
plot <- H.get <#> _.plot
liftEffect $ traverse_ UPlot.destroy plot
Resize -> do
div <- H.getHTMLElementRef (H.RefLabel "plot")
state <- H.get
sequence_ do
div' <- div
plot <- state.plot :: Maybe UPlot.Plot
pure $ do
rect <- liftEffect $ getBoundingClientRect div'
liftEffect $ UPlot.setSize plot rect.width state.opts.height
-- SetOpts opts -> do
-- H.modify_ _ { opts = opts }
-- log "Setting opts"
-- handleAction Initialize