Browse Source

Added odin logging + store middleware

development
Rohan Sircar 3 years ago
parent
commit
d455175044
  1. 4
      build.sbt
  2. 9
      src/main/scala/outwatchapp/MainApp.scala
  3. 2
      src/main/scala/outwatchapp/OutwatchApp.scala
  4. 21
      src/main/scala/outwatchapp/components/todo/TodoListStore.scala
  5. 50
      src/main/scala/outwatchapp/util/reactive/store/Middlewares.scala

4
build.sbt

@ -33,7 +33,9 @@ libraryDependencies ++= Seq(
// "io.circe" %%% "circe-config" % "0.8.0", // "io.circe" %%% "circe-config" % "0.8.0",
"org.akka-js" %%% "shocon" % "1.0.0", "org.akka-js" %%% "shocon" % "1.0.0",
"com.beachape" %%% "enumeratum-circe" % "1.6.1", "com.beachape" %%% "enumeratum-circe" % "1.6.1",
"com.github.valskalla" %%% "odin-core" % "0.7.0+95-ab4381ae+20201227-1831-SNAPSHOT"
"com.github.valskalla" %%% "odin-core" % "0.7.0+95-ab4381ae+20201227-1831-SNAPSHOT",
"io.github.cquiroz" %%% "scala-java-time" % "2.1.0",
"io.github.cquiroz" %%% "scala-java-time-tzdb" % "2.1.0"
// "com.clovellytech" %%% "outwatch-router" % "0.0.9+7-5be0b1a2+20201227-2019-SNAPSHOT" // "com.clovellytech" %%% "outwatch-router" % "0.0.9+7-5be0b1a2+20201227-2019-SNAPSHOT"
) )

9
src/main/scala/outwatchapp/MainApp.scala

@ -4,10 +4,10 @@ import scala.concurrent.duration._
import colibri.ext.monix._ import colibri.ext.monix._
import com.softwaremill.macwire._ import com.softwaremill.macwire._
import io.odin.consoleLogger
import monix.bio.Task import monix.bio.Task
import monix.eval.Coeval import monix.eval.Coeval
import monix.reactive.Observable import monix.reactive.Observable
import outwatchapp.ui.components.todo.TodoListStore
import org.scalajs.dom.raw.Element import org.scalajs.dom.raw.Element
import outwatch._ import outwatch._
import outwatch.dsl._ import outwatch.dsl._
@ -15,10 +15,11 @@ import outwatch.router._
import outwatchapp.components.CounterDemo import outwatchapp.components.CounterDemo
import outwatchapp.components.RequestDemo import outwatchapp.components.RequestDemo
import outwatchapp.components.todo.ChartjsDemo import outwatchapp.components.todo.ChartjsDemo
import outwatchapp.components.todo.FusejsDemo
import outwatchapp.pages.HomePage import outwatchapp.pages.HomePage
import outwatchapp.util.reactive.WorkerData
import outwatchapp.ui.components.todo.TodoListStore
import outwatchapp.util.reactive.WebWorker import outwatchapp.util.reactive.WebWorker
import outwatchapp.components.todo.FusejsDemo
import outwatchapp.util.reactive.WorkerData
class MainApp(el: Element)(implicit class MainApp(el: Element)(implicit
backend: AppTypes.Backend, backend: AppTypes.Backend,
@ -34,7 +35,7 @@ class MainApp(el: Element)(implicit
for { for {
counterDemo <- CounterDemo() counterDemo <- CounterDemo()
chartDemo <- ChartjsDemo() chartDemo <- ChartjsDemo()
todoStore <- TodoListStore()
todoStore <- TodoListStore(consoleLogger[Task]())
requestDemo <- RequestDemo(todoStore) requestDemo <- RequestDemo(todoStore)
demoWorker <- WebWorker[WorkerData]("/worker.js") demoWorker <- WebWorker[WorkerData]("/worker.js")
} yield { } yield {

2
src/main/scala/outwatchapp/OutwatchApp.scala

@ -14,7 +14,7 @@ import scalajs.js
@JSImport("bootstrap/dist/css/bootstrap.min.css", JSImport.Namespace) @JSImport("bootstrap/dist/css/bootstrap.min.css", JSImport.Namespace)
@js.native @js.native
object BootstrapBundleCss extends js.Object object BootstrapBundleCss extends js.Object
@JSImport("bootstrap", JSImport.Namespace)
@JSImport("bootstrap/dist/js/bootstrap.bundle.min.js", JSImport.Namespace)
@js.native @js.native
object BootstrapBundleJs extends js.Object object BootstrapBundleJs extends js.Object

21
src/main/scala/outwatchapp/components/todo/TodoListStore.scala

@ -1,15 +1,18 @@
package nova.monadic_sfx.ui.components.todo
package outwatchapp.ui.components.todo
import scala.scalajs.js.annotation.JSExportAll import scala.scalajs.js.annotation.JSExportAll
import cats.kernel.Eq import cats.kernel.Eq
import com.softwaremill.quicklens._ import com.softwaremill.quicklens._
import io.circe.generic.JsonCodec import io.circe.generic.JsonCodec
import io.odin.Logger
import monix.bio.Task import monix.bio.Task
import nova.monadic_sfx.util.reactive.store.Reducer
import nova.monadic_sfx.util.reactive.store.Store
import outwatchapp.util.reactive.store.Middlewares.actionLoggerMiddleware
import outwatchapp.util.reactive.store.Reducer
import outwatchapp.util.reactive.store.Store
@JSExportAll @JSExportAll
@JsonCodec
case class Todo(id: Int, content: String) case class Todo(id: Int, content: String)
object Todo { object Todo {
implicit val eqForTodo = Eq.fromUniversalEquals[Todo] implicit val eqForTodo = Eq.fromUniversalEquals[Todo]
@ -37,18 +40,16 @@ object TodoListStore {
implicit val eqForState = Eq.fromUniversalEquals[State] implicit val eqForState = Eq.fromUniversalEquals[State]
} }
def reducer()(
def reducer(logger: Logger[Task])(
state: State, state: State,
action: Action action: Action
): (State, Option[Task[Action]]) = ): (State, Option[Task[Action]]) =
action match { action match {
case Init => (state, None) case Init => (state, None)
case Add(content) => case Add(content) =>
println("hello")
val nextAction = Some(for { val nextAction = Some(for {
// do some validation // do some validation
// _ <- logger.debug(s"Received $content") // _ <- logger.debug(s"Received $content")
_ <- Task(println(s"Received $content"))
res <- Task.pure(InternalAdd(content)) res <- Task.pure(InternalAdd(content))
} yield res) } yield res)
(state, nextAction) (state, nextAction)
@ -68,19 +69,21 @@ object TodoListStore {
.using(_ :+ Todo(state.counter, content)) .using(_ :+ Todo(state.counter, content))
.modify(_.counter) .modify(_.counter)
.using(_ + 1) .using(_ + 1)
(nextState, Some(Task.pure(End)))
(nextState, Some(logger.debug(s"Received $content") >> Task.pure(End)))
case End => (state, None) case End => (state, None)
} }
def apply(): Task[Store[Action, State]] =
def apply(logger: Logger[Task]): Task[Store[Action, State]] =
Task.deferAction(implicit s => Task.deferAction(implicit s =>
for { for {
logMware <- actionLoggerMiddleware[Action, State](logger, "TodoStore")
store <- store <-
Store Store
.createL[Action, State]( .createL[Action, State](
Init, Init,
State(Vector.empty[Todo], 0), State(Vector.empty[Todo], 0),
Reducer.withOptionalEffects(reducer() _)
Reducer.withOptionalEffects(reducer(logger) _),
Seq(logMware)
) )
} yield store } yield store
) )

50
src/main/scala/outwatchapp/util/reactive/store/Middlewares.scala

@ -2,11 +2,17 @@ package outwatchapp.util.reactive.store
import java.time.LocalDateTime import java.time.LocalDateTime
import io.circe.Encoder
import io.circe.Printer import io.circe.Printer
import io.circe.generic.JsonCodec import io.circe.generic.JsonCodec
// object Middleware {
// def apply[A,M,T](ob: Observable[(A,M)], cb: (A,M) => T): Observable[(A,M)] = ob
// }
import io.circe.syntax._
import io.odin.Logger
import io.odin.LoggerMessage
import io.odin.formatter.options.PositionFormat
import io.odin.formatter.options.ThrowableFormat
import io.odin.meta.Render
import monix.bio.Task
import monix.reactive.Observable
@JsonCodec @JsonCodec
final case class StoreInfo[A]( final case class StoreInfo[A](
@ -17,6 +23,42 @@ final case class StoreInfo[A](
object StoreInfo { object StoreInfo {
val printer = Printer.noSpaces val printer = Printer.noSpaces
implicit def render[T: Encoder]: Render[StoreInfo[T]] =
new Render[StoreInfo[T]] {
override def render(m: StoreInfo[T]): String = printer.print(m.asJson)
}
} }
object Middlewares {}
object Middlewares {
val format = create(ThrowableFormat.Default, PositionFormat.Full)
def create(
throwableFormat: ThrowableFormat,
positionFormat: PositionFormat
): io.odin.formatter.Formatter = (msg: LoggerMessage) => msg.message.value
def actionStateLoggerMiddleware[A, M](
logger: Logger[Task]
): Task[Middleware[A, M]] =
Task.deferAction(implicit s =>
Task((obs: Observable[(A, M)]) =>
obs.doOnNextF { case (a, m) =>
logger.debug(s"Received action $a with state $m")
}
)
)
def actionLoggerMiddleware[A: Encoder, M](
logger: Logger[Task],
name: String
): Task[Middleware[A, M]] =
Task.deferAction(implicit s =>
Task((obs: Observable[(A, M)]) =>
obs.doOnNextF { case (a, _) =>
Task(LocalDateTime.now())
.flatMap(curTime => logger.debug(StoreInfo(name, a, curTime)))
}
)
)
}
Loading…
Cancel
Save