You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

187 lines
6.2 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package outwatchapp
  2. import scala.concurrent.duration._
  3. import colibri.ext.monix._
  4. import com.softwaremill.macwire._
  5. import io.odin.consoleLogger
  6. import monix.bio.Task
  7. import monix.eval.Coeval
  8. import monix.reactive.Observable
  9. import monix.{eval => me}
  10. import org.scalajs.dom.raw.Element
  11. import outwatch._
  12. import outwatch.dsl._
  13. import outwatch.router._
  14. import outwatchapp.components.ChartjsDemo
  15. import outwatchapp.components.CounterDemo
  16. import outwatchapp.components.DatatablesDemo
  17. import outwatchapp.components.FusejsDemo
  18. import outwatchapp.components.RequestDemo
  19. import outwatchapp.pages.HomePage
  20. import outwatchapp.ui.components.todo.TodoListStore
  21. import outwatchapp.util.IOUtils
  22. import outwatchapp.util.reactive.WebSocket
  23. import outwatchapp.util.reactive.WebWorker
  24. import outwatchapp.util.reactive.WebsocketData
  25. import outwatchapp.util.reactive.WorkerData
  26. import outwatchapp.util.reactive.ReconnectingWebSocket
  27. import cats.syntax.eq._
  28. import monix.execution.Ack
  29. import monix.reactive.Observer
  30. class MainApp(el: Element)(implicit
  31. backend: AppTypes.Backend,
  32. store: RouterStore[Page]
  33. ) {
  34. import MainApp._
  35. def run: Task[Unit] = for {
  36. resolver <- resolver
  37. _ <- OutWatch.renderInto[Task](el, Router(resolver))
  38. } yield ()
  39. def producer(data: Long, ws: Observer[WebsocketData]): me.Task[Unit] =
  40. me.Task.deferFuture(ws.onNext(WebsocketData(data))).flatMap {
  41. case Ack.Continue => producer(data + 1, ws)
  42. // .delayExecution(3.seconds)
  43. case Ack.Stop => me.Task.unit
  44. }
  45. def resolver: Task[PartialFunction[Page, VDomModifier]] =
  46. Task.deferAction(implicit s =>
  47. for {
  48. counterDemo <- CounterDemo()
  49. chartDemo <- ChartjsDemo()
  50. todoStore <- TodoListStore(consoleLogger[Task]())
  51. requestDemo <- RequestDemo(todoStore)
  52. demoWorker <- WebWorker[WorkerData]("/worker.js")
  53. dtDemo <- DatatablesDemo()
  54. _ <- IOUtils
  55. .toIO(
  56. Observable
  57. .interval(1.second)
  58. .take(2)
  59. .doOnNextF(i => Coeval(println(s"Producer emitted $i")))
  60. .doOnNextF(i =>
  61. me.Task.deferFuture(demoWorker.onNext(WorkerData(i))).void
  62. )
  63. .completedL >>
  64. me.Task.deferFuture(demoWorker.onNext(WorkerData(999)))
  65. // .delayExecution(6.seconds)
  66. )
  67. .startAndForget
  68. _ <-
  69. ReconnectingWebSocket[WebsocketData]("ws://localhost:6789").flatMap {
  70. case (source, sink) =>
  71. IOUtils
  72. .toIO(
  73. me.Task.parZip2(
  74. // Observable
  75. // .interval(3.seconds)
  76. // .doOnNext(_ => me.Task(println("Sending websocket data")))
  77. // .doOnNext(i =>
  78. // me.Task.deferFuture(
  79. // ws.onNext(WebsocketData(i))
  80. // ) >> me.Task.unit
  81. // )
  82. // .completedL,
  83. producer(0, sink.value),
  84. source.value
  85. .doOnNext(data => me.Task(println(s"Received : $data")))
  86. .completedL
  87. )
  88. )
  89. }
  90. // .onErrorRestartIf {
  91. // case e: Exception =>
  92. // e.getMessage() === "Websocket closed"
  93. // case _ => false
  94. // }
  95. // .onErrorRestartLoop(Backoff(3, 1.second)) { (err, state, retry) =>
  96. // val Backoff(maxRetries, delay) = state
  97. // if (maxRetries > 0)
  98. // retry(Backoff(maxRetries - 1, delay * 2)).delayExecution(delay)
  99. // else
  100. // // No retries left, rethrow the error
  101. // Task.raiseError(err)
  102. // }
  103. .startAndForget
  104. // .start
  105. // .startAndForget
  106. // _ <- SweetAlertDemo.dumbNotif
  107. // _ <- Task(println(s"Notif result: $notifRes"))
  108. } yield {
  109. case Page.Home => wire[HomePage].render
  110. case Page.SomePage =>
  111. div(
  112. div(cls := "title", "SomePage"),
  113. // RequestDemo(todoStore),
  114. // Observable
  115. // .interval(1.second)
  116. // .doOnNextF(i => Coeval(println(s"Producer emitted $i")))
  117. // .doOnNextF(i =>
  118. // Coeval(demoWorker.onNext(WorkerData(i))) >> Coeval.unit
  119. // )
  120. // .take(2)
  121. // .map(_ => div()),
  122. demoWorker.map(_.toString).map(v => p(cls := "text-white", v)),
  123. requestDemo,
  124. div(cls := "slider")
  125. )
  126. case Page.UserHome(id) =>
  127. div(
  128. // cls := "text-white",
  129. div(cls := "title", "UserHome"),
  130. s"User id: $id",
  131. div(FusejsDemo.y.map(_.item.toString).mkString(" ")),
  132. // ExampleDataTable.value(
  133. // onDomMount.asHtml.foreachSync(el =>
  134. // Coeval(DatatablesDemo.init(el)) >> Coeval.unit
  135. // )
  136. // )
  137. dtDemo
  138. )
  139. case Page.NotFound =>
  140. Task(
  141. div(
  142. cls := "page-header error-page header-filter",
  143. div(
  144. cls := "page-header-image"
  145. // style := js.Dictionary(
  146. // "background-image" -> "url('../assets/img/braden-collum.jpg')"
  147. // )
  148. ),
  149. div(
  150. cls := "container",
  151. cls := "text-center",
  152. div(
  153. cls := "row",
  154. div(
  155. cls := "col-md-12",
  156. h1(
  157. fontSize := "12em",
  158. color := "#fff",
  159. letterSpacing := "14px",
  160. fontWeight := 700,
  161. cls := "title",
  162. "404"
  163. ),
  164. h2(cls := "description", "Page not found :("),
  165. h4(
  166. cls := "description",
  167. "Ooooups! Looks like you got lost."
  168. )
  169. )
  170. )
  171. )
  172. )
  173. )
  174. }
  175. )
  176. }
  177. object MainApp {
  178. final case class Backoff(maxRetries: Long, delay: FiniteDuration)
  179. }