Added odin logging + store middleware
This commit is contained in:
parent
f294ab7009
commit
d455175044
@ -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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -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.pages.HomePage
|
|
||||||
import outwatchapp.util.reactive.WorkerData
|
|
||||||
import outwatchapp.util.reactive.WebWorker
|
|
||||||
import outwatchapp.components.todo.FusejsDemo
|
import outwatchapp.components.todo.FusejsDemo
|
||||||
|
import outwatchapp.pages.HomePage
|
||||||
|
import outwatchapp.ui.components.todo.TodoListStore
|
||||||
|
import outwatchapp.util.reactive.WebWorker
|
||||||
|
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 {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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 outwatchapp.util.reactive.store.Middlewares.actionLoggerMiddleware
|
||||||
import nova.monadic_sfx.util.reactive.store.Store
|
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
|
||||||
)
|
)
|
||||||
|
@ -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 {
|
import io.circe.syntax._
|
||||||
// def apply[A,M,T](ob: Observable[(A,M)], cb: (A,M) => T): Observable[(A,M)] = ob
|
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…
Reference in New Issue
Block a user