diff options
Diffstat (limited to 'vfd-dashboard')
-rw-r--r-- | vfd-dashboard/src/main/scala/vfd/dashboard/RxUtil.scala | 43 | ||||
-rw-r--r-- | vfd-dashboard/src/main/scala/vfd/dashboard/ui/Layout.scala | 194 |
2 files changed, 184 insertions, 53 deletions
diff --git a/vfd-dashboard/src/main/scala/vfd/dashboard/RxUtil.scala b/vfd-dashboard/src/main/scala/vfd/dashboard/RxUtil.scala index 51e2fcd..a73c3ba 100644 --- a/vfd-dashboard/src/main/scala/vfd/dashboard/RxUtil.scala +++ b/vfd-dashboard/src/main/scala/vfd/dashboard/RxUtil.scala @@ -1,6 +1,23 @@ package vfd.dashboard -import rx._ +import scala.language.implicitConversions +import scala.util.Failure +import scala.util.Success + +import org.scalajs.dom.html + +import rx.Obs +import rx.Rx +import rx.Rx +import rx.Var +import rx.Var +import scalatags.JsDom.all.Frag +import scalatags.JsDom.all.HtmlTag +import scalatags.JsDom.all.backgroundColor +import scalatags.JsDom.all.bindNode +import scalatags.JsDom.all.span +import scalatags.JsDom.all.stringFrag +import scalatags.JsDom.all.stringStyle package object rxutil { @@ -14,7 +31,7 @@ package object rxutil { * @param pf the partial function which filters and maps this Rx * @return a new Rx resulting from applying the given partial * function pf to each value on which it is defined and collecting - * the result + * the result */ def collect[B](initial: B)(pf: PartialFunction[Any, B]): Rx[B] = { val result: Var[B] = Var(initial) @@ -28,4 +45,26 @@ package object rxutil { } + /** + * Copied from https://github.com/lihaoyi/workbench-example-app/blob/todomvc/src/main/scala/example/Framework.scala + * + * Sticks some Rx into a Scalatags fragment, which means hooking up an Obs + * to propagate changes into the DOM via the element's ID. Monkey-patches + * the Obs onto the element itself so we have a reference to kill it when + * the element leaves the DOM (e.g. it gets deleted). + */ + implicit def rxMod[T <: html.Element](r: Rx[HtmlTag]): Frag = { + def rSafe = r.toTry match { + case Success(v) => v.render + case Failure(e) => span(e.toString, backgroundColor := "red").render + } + var last = rSafe + Obs(r, skipInitial = true) { + val newLast = rSafe + last.parentElement.replaceChild(newLast, last) + last = newLast + } + bindNode(last) + } + }
\ No newline at end of file diff --git a/vfd-dashboard/src/main/scala/vfd/dashboard/ui/Layout.scala b/vfd-dashboard/src/main/scala/vfd/dashboard/ui/Layout.scala index 1d6090d..b3c9387 100644 --- a/vfd-dashboard/src/main/scala/vfd/dashboard/ui/Layout.scala +++ b/vfd-dashboard/src/main/scala/vfd/dashboard/ui/Layout.scala @@ -31,15 +31,13 @@ class Layout(socket: MavlinkSocket)(implicit env: Environment) { div(style := "float: right")(mode("CRITICAL", "danger", true))) val map = iframe( - width := 100.pct, - height := 350.px, "frameborder".attr := "0", "scrolling".attr := "no", "marginheight".attr := "0", "marginwidth".attr := "0", src := "http://www.openstreetmap.org/export/embed.html?bbox=6.5611016750335684%2C46.51718501017836%2C6.570038795471191%2C46.520577350893525&layer=mapnik") - val feed = div(style := "width: 100%; height: 460px; color: #ffffff; background-color: #c2c2c2; text-align: center;")( + val feed = div(style := "width: 100%; color: #ffffff; background-color: #c2c2c2; text-align: center;")( p(style := "padding-top: 220px")("video feed")) val altimeter = new Altimeter( @@ -78,69 +76,163 @@ class Layout(socket: MavlinkSocket)(implicit env: Environment) { div("UAV " + socket.remoteSystemId) ) - val left = panel( - map, - table(`class` := "table-instrument")( - thead("Motors"), - tbody( - tr( - td(motor1.element), - td(), - td(motor0.element), - td() - ), - tr( - td(), - td(powerDistribution.element), - td(), - td() - ), - tr( - td(motor2.element), - td(), - td(motor3.element), - td() + val left = div( + panel( + table(`class` := "table-instrument")( + thead("Communication"), + tbody( + tr( + td("Uplink RSSI"), + td("89"), + td("Socket"), + td("5ms") + ), + tr( + td("Something else"), + td("unknown"), + td("Heartbeat"), + td(i(`class` := "fa fa-heart heartbeat")) + ) + ) + ), + table(`class` := "table-instrument")( + thead("Packets"), + tbody( + tr( + td("OK"), + Rx{td(socket.stats.packets())}, + td("CRC"), + Rx{td(socket.stats.crcErrors())}, + td("OFLW"), + Rx{td(socket.stats.overflows())}, + td("BID"), + Rx{td(socket.stats.wrongIds())} + ), + tr( + td("Ratio"), + Rx{ + import socket.stats._ + val sum = packets() + crcErrors() + overflows() + wrongIds() + td(1.0 * packets() / sum formatted "%.2f") + }, + td(), + td(), + td(), + td(), + td(), + td() + ) ) ) - ) - ) - - val center = panel(feed) - - val below = panel( - table(`class` := "table-instrument")( - tbody( - tr( - td(compass.element), - td(horizon.element), - td(altimeter.element) + ), + panel( + table(`class` := "table-instrument")( + tbody( + tr( + td(compass.element), + td(horizon.element), + td(altimeter.element), + td(altimeter.element) + ) + ) + ) + ), + panel( + div(style := "width: 50%; display: inline-block;")( + table(`class` := "table-instrument")( + tbody( + tr( + td(motor1.element), + td(), + td(motor0.element) + ), + tr( + td(), + td(powerDistribution.element), + td() + ), + tr( + td(motor2.element), + td(), + td(motor3.element) + ) + ) + ) + ), + div(style := "width: 50%; display: inline-block;")( + table(`class` := "table-instrument")( + thead("Power"), + tbody( + tr( + td("VHIGH"), + td("12.6V"), + td("VLOW"), + td("9V") + ), + tr( + td("Voltage"), + td("11.2V"), + td("Remaining"), + td("80%") + ), + tr( + td("Flight"), + td("05:00"), + td("Endurance"), + td("12:00") + ) + ) + ), + table(`class` := "table-instrument")( + thead("Navigation"), + tbody( + tr( + td("Satellites"), + td("5"), + td("Precision"), + td("10cm") + ), + tr( + td("LON"), + td(""), + td("LAT"), + td("") + ), + tr( + td("GSpeed"), + td("3 m/s"), + td(), + td() + ), + tr( + td("Travelled"), + td("5000m"), + td("Home"), + td("1200m") + ) + ) ) ) ) ) - val right = panel() - val element = div(`class` := "d-container d-column")( div(`class` := "d-above")( - top), + top + ), div(`class` := "d-above d-container d-row")( panel(modes), - panel(infos)), + panel(infos) + ), div(`class` := "d-container d-row")( - div(`class` := "d-container d-details")( - panel("foo")), div(`class` := "d-container d-left")( - left), + left + ), div(`class` := "d-container d-column d-middle")( - div(`class` := "d-container d-center")( - center), - div(`class` := "d-container d-below")( - below) + panel(feed), + panel(map) ), - div(`class` := "d-container d-right")( - right - ) + div(`class` := "d-container d-right")() ) ).render |