Many changes

Added odin logger
Used macwire and tagging for DI
JS libs now embedded with webpack instead of server from CDN
Refactored the application into components and pages
Added Chartjs and Fusejs demo with scalablytyped typings
This commit is contained in:
Rohan Sircar 2020-12-29 12:27:37 +05:30
parent 4b7c3e633b
commit e5c3802e92
17 changed files with 1023 additions and 334 deletions

View File

@ -5,15 +5,8 @@
<meta charset="UTF-8">
<title>Outwatch App</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/js/bootstrap.bundle.min.js" integrity="sha512-iceXjjbmB2rwoX93Ka6HAHP+B76IY1z0o3h+N1PeDtRSsyeetU3/0QKJqGyPJcX63zysNehggFwMC/bi7dvMig==" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/blk-design-system@1.0.2/assets/js/blk-design-system.min.js" integrity="sha256-0+0XIgwF6mAu4/UMvl0Eh9tvz2CLhNCo1taXQlpeyqg=" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" integrity="sha512-oc9+XSs1H243/FRN9Rw62Fn8EtxjEYWHXRvjS43YtueEewbS6ObfXcJNyohjHqVKFPoXXUxwc+q1K7Dee6vv9g==" crossorigin="anonymous" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/blk-design-system@1.0.2/assets/css/blk-design-system.min.css" integrity="sha256-6HRu9ZigEQ/feV+C1JxZyZSmMcqQ8Hymukmjdk4nl9A=" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/blk-design-system@1.0.2/assets/css/nucleo-icons.css" integrity="sha256-03+9B37/His+rzjhgA6Y1+ByU9DGN2ZPWjjA5CJJF2w=" crossorigin="anonymous">
<!-- <link rel="stylesheet" href="../css/demo.css"> -->
</head>
<body>

View File

@ -24,33 +24,43 @@ libraryDependencies ++= Seq(
"com.softwaremill.sttp.client" %%% "circe" % "2.2.5",
// "com.softwaremill.sttp.client" %%% "async-http-client-backend-monix" % "2.2.5",
// "com.softwaremill.sttp.client3" %%% "httpclient-backend-monix" % "2.2.5",
// "com.softwaremill.macwire" %%% "util" % "2.3.7",
// "com.softwaremill.macwire" %% "util" % "2.3.7" % "provided",
"com.softwaremill.common" %%% "tagging" % "2.2.1",
"com.softwaremill.macwire" %% "macros" % "2.3.7" % "provided",
// "com.softwaremill.macwire" %%% "macrosakka" % "2.3.6" % "provided",
"com.softwaremill.quicklens" %%% "quicklens" % "1.6.1",
// "com.typesafe.scala-logging" %%% "scala-logging" % "3.9.2",
// "io.circe" %%% "circe-config" % "0.8.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.clovellytech" %%% "outwatch-router" % "0.0.9+7-5be0b1a2+20201227-2019-SNAPSHOT"
)
Compile / npmDependencies ++= Seq(
// "jquery" -> "1.9.1",
// "popper.js" -> "1.16.1",
"jquery" -> "3.3.1",
"popper.js" -> "1.16.1",
// // "@popperjs/core" -> "2.6.0",
// "blk-design-system" -> "1.0.2",
// "bootstrap" -> "4.5.3"
"snabbdom" -> "git://github.com/outwatch/snabbdom.git#semver:0.7.5"
"blk-design-system" -> "1.0.2",
"bootstrap" -> "4.5.3",
"@types/chart.js" -> "2.9.11",
"chart.js" -> "2.9.3",
"snabbdom" -> "git://github.com/outwatch/snabbdom.git#semver:0.7.5",
"fuse.js" -> "6.4.3"
)
// Compile / npmDevDependencies ++= Seq(
// "css-loader" -> "5.0.1",
// "style-loader" -> "2.0.0"
// )
Compile / npmDevDependencies ++= Seq(
"css-loader" -> "5.0.1",
"style-loader" -> "2.0.0",
"webpack-merge" -> "4.1",
"file-loader" -> "3.0.1",
"url-loader" -> "1.1.2"
)
// stIgnore ++= List("jquery", "blk-design-system", "bootstrap")
stIgnore ++= List("jquery", "blk-design-system", "bootstrap")
stIgnore ++= List("snabbdom")
stStdlib := List("es6")
stUseScalaJsDom := false
enablePlugins(ScalaJSBundlerPlugin)
enablePlugins(ScalablyTypedConverterPlugin)
@ -59,7 +69,11 @@ requireJsDomEnv in Test := true
scalaJSUseMainModuleInitializer := true
// configure Scala.js to emit a JavaScript module instead of a top-level script
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule))
scalaJSLinkerConfig ~= (
/*hmm*/
_.withSourceMap(false)
.withModuleKind(ModuleKind.CommonJSModule)
)
scalacOptions ++=
Seq(
"-encoding",
@ -113,8 +127,8 @@ copyFastOptJS := {
val outDir = (crossTarget in (Compile, fastOptJS)).value / "dev"
val files = Seq(
name.value.toLowerCase + "-fastopt-loader.js",
name.value.toLowerCase + "-fastopt.js",
name.value.toLowerCase + "-fastopt.js.map"
name.value.toLowerCase + "-fastopt.js"
// name.value.toLowerCase + "-fastopt.js.map"
) map { p => (inDir / p, outDir / p) }
IO.copy(
files,

View File

@ -0,0 +1,12 @@
package outwatchapp
import java.nio.ByteBuffer
import monix.reactive.Observable
import sttp.client.SttpBackend
object AppTypes {
type Backend = SttpBackend[monix.eval.Task, Observable[
ByteBuffer
], sttp.client.NothingT]
}

View File

@ -0,0 +1,50 @@
package outwatchapp
import com.softwaremill.macwire._
import monix.bio.Task
import org.scalajs.dom.raw.Element
import outwatch._
import outwatch.dsl._
import outwatch.router._
import outwatchapp.components.CounterDemo
import outwatchapp.components.RequestDemo
import outwatchapp.components.todo.ChartjsDemo
import outwatchapp.pages.HomePage
import nova.monadic_sfx.ui.components.todo.TodoListStore
class MainApp(el: Element)(implicit
backend: AppTypes.Backend,
store: RouterStore[Page]
) {
def run: Task[Unit] = for {
resolver <- resolver
_ <- OutWatch.renderInto[Task](el, Router(resolver))
} yield ()
def resolver: Task[PartialFunction[Page, VDomModifier]] =
Task.deferAction(implicit s =>
for {
counterDemo <- CounterDemo()
chartDemo <- ChartjsDemo()
todoStore <- TodoListStore()
requestDemo <- RequestDemo(todoStore)
resolver: PartialFunction[Page, VDomModifier] = {
case Page.Home => wire[HomePage].render
case Page.SomePage =>
div(
div(cls := "title", "SomePage"),
// RequestDemo(todoStore),
requestDemo,
div(cls := "slider")
)
case Page.UserHome(id) =>
div(div(cls := "title", "UserHome"), s"User id: $id")
case Page.NotFound =>
div(
div(cls := "title", "NotFound"),
p(cls := "profile-description", "notfound")
)
}
} yield resolver
)
}

View File

@ -1,290 +1,44 @@
package outwatchapp
import scala.concurrent.duration._
import cats.effect.ExitCode
import cats.implicits._
import colibri.ext.monix._
import monix.bio._
import monix.eval.Coeval
import monix.reactive.Observable
import monix.{eval => me}
import nova.monadic_sfx.ui.components.todo.Todo
import nova.monadic_sfx.ui.components.todo.TodoListStore
import outwatch._
import outwatch.dsl._
import outwatch.reactive.handlers.monix._
import outwatch.router.AppRouter
import outwatch.router.dsl._
import outwatchapp.implicits._
import sttp.client._
import org.scalajs.dom.raw.Element
import sttp.client.impl.monix.FetchMonixBackend
import org.scalajs.dom.document
import scala.scalajs.js.annotation.JSImport
import scalajs.js
@JSImport("bootstrap/dist/css/bootstrap.min.css", JSImport.Namespace)
@js.native
object BootstrapBundleCss extends js.Object
@JSImport("bootstrap", JSImport.Namespace)
@js.native
object BootstrapBundleJs extends js.Object
@JSImport(
"blk-design-system/assets/css/blk-design-system.min.css",
JSImport.Namespace
)
@js.native
object BlkDesignSys extends js.Object
object OutwatchApp extends BIOApp {
val counter2 = Observable.interval(1.second)
val counter = div(
"Hmm",
button(
onClick
.useScan(0)(_ + 1)
.handled(source => VDomModifier("Counter: ", source))
)
)
implicit val backend = FetchMonixBackend()
val handlerTask = Handler.createF[Task, String]("empty")
def request(query: String) = basicRequest
.get(
uri"https://jsonplaceholder.typicode.com/todos/${query.toIntOption.getOrElse(0)}"
)
.send()
.flatMap {
_.body match {
case Right(value) =>
me.Task(println(value)) >>
me.Task(value)
case Left(error) =>
me.Task(println(error)) >>
me.Task(error)
}
}
val component = Task.deferAction(implicit s =>
for {
handler <- handlerTask
todoContent <- Handler.createF[Task, String]
todoStore <- TodoListStore()
res <- Task(
div(
// cls := "col-lg-8 bd-example",
div(cls := "alert alert-danger", "Some Error Occured!"),
div(
form(
h4(cls := "form-title", "User Finder"),
div(
cls := "form-group",
label(
color := "hsla(0,0%,100%,0.8)",
forId := "httpInput",
"Enter an id: "
),
input(
idAttr := "httpInput",
typ := "text",
cls := "form-control",
placeholder := "0",
onInput.value --> handler
),
label(
color := "hsla(0,0%,100%,0.8)",
"Enter content for todo"
),
small(cls := "form-text text-muted", "default is 0")
),
div(
cls := "form-group",
input(
cls := "form-control",
onInput.value --> todoContent
),
button(
cls := "btn",
cls := "btn-info form-control",
"Add Todo",
onClick.preventDefault(
todoContent.map(TodoListStore.Add)
) --> todoStore.sink
)
)
)
),
div(
p(
cls := "profile-description",
handler
.doOnNext(str => me.Task(println(str)))
.mapEval(request)
.map(div(_)),
div(
"Todos: ",
todoStore.doOnNextF { case (a, s) => Coeval(println(s)) }.map {
case (a, s) => div(renderTodos(s.todos))
}
)
)
)
)
)
} yield res
)
def renderTodos(todos: Seq[Todo]) = div(
ul(
todos.map(todo => li(div(s"id: ${todo.id} content: ${todo.content}")))
)
)
sealed trait Page
case object Home extends Page
case object SomePage extends Page
case class UserHome(id: Int) extends Page
case object NotFound extends Page
val router = AppRouter.create[Task, Page](NotFound) {
case Root => Home
case Root / "user" / IntVar(id) => UserHome(id)
case Root / "some-page" => SomePage
}
val counterComponent =
Task.deferAction(implicit s =>
Task(div(p(cls := "profile-description", "count: ", counter2)))
)
def resolver: PartialFunction[Page, VDomModifier] = {
case Home =>
div(
div(cls := "title", "Home"),
div(
cls := "card",
div(
cls := "card-body",
counterComponent,
p(
cls := "profile-description",
div(
"hm",
htmlTag("blockQuote")(
cls := "blockquote",
p(
cls := "mb-0",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante."
),
footer(
cls := "blockquote-footer",
"Someone famous in ",
cite(title := "Source Title", "Source Title")
)
)
)
)
)
)
)
case SomePage =>
div(div(cls := "title", "SomePage"), component, div(cls := "slider"))
case UserHome(id) => div(div(cls := "title", "UserHome"), s"User id: $id")
case NotFound =>
div(
div(cls := "title", "NotFound"),
p(cls := "profile-description", "notfound")
)
}
val router = Router.router
def app(el: Element) = for {
store <- router.store
backend = FetchMonixBackend()
} yield new MainApp(el)(backend, store)
def run(args: List[String]): UIO[ExitCode] = {
// div(h1("Hello World"), counterComponent, Task(1))
import org.scalajs.dom.document
val el =
document.createElement("div")
BootstrapBundleCss
BootstrapBundleJs
BlkDesignSys
val el = document.createElement("div")
el.setAttribute("id", "#app")
document.body.appendChild(el)
router.store
.flatMap(implicit store =>
OutWatch
.renderInto(
el,
div(
htmlTag("nav")(
cls := "navbar navbar-expand-lg bg-primary ",
attr("color-on-scroll") := "100",
div(
cls := "container",
div(
cls := "navbar-translate",
a(
cls := "navbar-brand",
href := "https://demos.creative-tim.com/blk-design-system/index.html",
rel := "tooltip",
title := "",
attr("data-placement") := "bottom",
target := "_blank",
div("OutwatchApp")
),
button(
cls := "navbar-toggler navbar-toggler toggled collapsed",
attr("data-toggle") := "collapse",
attr("data-target") := "#navigation",
attr("aria-controls") := "navigation-index",
attr("aria-expanded") := "false",
attr("aria-label") := "Toggle navigation",
div(cls := "navbar-toggler-bar bar1"),
div(cls := "navbar-toggler-bar bar2"),
div(cls := "navbar-toggler-bar bar3")
)
),
div(
cls := "navbar-collapse justify-content-end collapse",
idAttr := "navigation",
div(
cls := "navbar-collapse-header",
div(
cls := "row",
div(
cls := "col-6 collapse-brand",
a("BLK•")
),
div(
cls := "col-6 collapse-close text-right",
button(
`type` := "button",
cls := "navbar-toggler collapsed",
attr("data-toggle") := "collapse",
attr("data-target") := "#navigation",
attr("aria-controls") := "navigation-index",
attr("aria-expanded") := "false",
attr("aria-label") := "Toggle navigation",
i(cls := "tim-icons icon-simple-remove")
)
)
)
),
ul(
cls := "navbar-nav",
li(
cls := "nav-item active",
router.link("/")(
cls := "nav-link",
"Home",
div(cls := "sr-only", "(current)")
)
),
li(
cls := "nav-item",
router
.link("/some-page")(cls := "nav-link", "SomePage")
),
li(
cls := "nav-item",
router.link("/user/1")(cls := "nav-link", "User Home")
),
li(
cls := "nav-item",
router.link("/todomvc")(cls := "nav-link", "TodoMvc")
)
)
)
)
),
div(
cls := "container",
router.render(resolver),
router.watch()
)
)
)
)
app(el)
.flatMap(_.run)
.onErrorHandle(ex => UIO(ex.printStackTrace()))
.as(ExitCode.Success)
}

View File

@ -0,0 +1,9 @@
package outwatchapp
sealed trait Page
object Page {
case object Home extends Page
case object SomePage extends Page
case class UserHome(id: Int) extends Page
case object NotFound extends Page
}

View File

@ -0,0 +1,117 @@
package outwatchapp
import colibri.ext.monix._
import monix.bio.Task
import monix.eval.Coeval
import outwatch._
import outwatch.dsl._
import outwatch.router.AppRouter
import outwatch.router._
import outwatch.router.dsl._
import outwatchapp.components.todo.FusejsDemo
import Page._
object Router {
val router = AppRouter.create[Task, Page](NotFound) {
case Root => Home
case Root / "user" / IntVar(id) => UserHome(id)
case Root / "some-page" => SomePage
}
def apply(resolver: PartialFunction[Page, VDomModifier])(implicit
store: RouterStore[Page]
) = div(
htmlTag("nav")(
cls := "navbar navbar-expand-lg bg-primary ",
attr("color-on-scroll") := "100",
div(
cls := "container",
div(
cls := "navbar-translate",
a(
cls := "navbar-brand",
href := "https://demos.creative-tim.com/blk-design-system/index.html",
rel := "tooltip",
title := "",
attr("data-placement") := "bottom",
target := "_blank",
div("OutwatchApp")
),
button(
cls := "navbar-toggler navbar-toggler toggled collapsed",
attr("data-toggle") := "collapse",
attr("data-target") := "#navigation",
attr("aria-controls") := "navigation-index",
attr("aria-expanded") := "false",
attr("aria-label") := "Toggle navigation",
div(cls := "navbar-toggler-bar bar1"),
div(cls := "navbar-toggler-bar bar2"),
div(cls := "navbar-toggler-bar bar3")
)
),
div(
cls := "navbar-collapse justify-content-end collapse",
idAttr := "navigation",
div(
cls := "navbar-collapse-header",
div(
cls := "row",
div(
cls := "col-6 collapse-brand",
a("BLK•")
),
div(
cls := "col-6 collapse-close text-right",
button(
tpe := "button",
cls := "navbar-toggler collapsed",
attr("data-toggle") := "collapse",
attr("data-target") := "#navigation",
attr("aria-controls") := "navigation-index",
attr("aria-expanded") := "false",
attr("aria-label") := "Toggle navigation",
i(cls := "tim-icons icon-simple-remove")
)
)
)
),
ul(
cls := "navbar-nav",
li(
cls := "nav-item active",
router.link("/")(
cls := "nav-link",
"Home",
div(cls := "sr-only", "(current)")
)
),
li(
cls := "nav-item",
router
.link("/some-page")(cls := "nav-link", "SomePage")
),
li(
cls := "nav-item",
router.link("/user/1")(cls := "nav-link", "User Home")
),
li(
cls := "nav-item",
router.link("/todomvc")(cls := "nav-link", "TodoMvc")
)
)
)
)
),
div(
cls := "container",
Coeval(
println("Result = " + FusejsDemo.y.toString())
) >> Coeval(
FusejsDemo.y.foreach(o => println(o.item))
) >> Coeval(div()),
router.render(resolver),
router.watch()
)
)
}

View File

@ -0,0 +1,22 @@
package outwatchapp.components
import scala.concurrent.duration._
import colibri.ext.monix._
import com.softwaremill.tagging._
import monix.bio._
import monix.reactive.Observable
import outwatch.HtmlVNode
import outwatch.dsl._
sealed trait CounterDemo
object CounterDemo {
val counter2 = Observable.interval(1.second)
def apply(): Task[HtmlVNode @@ CounterDemo] =
Task.deferAction(implicit s =>
Task(
div(p(cls := "profile-description", "count: ", counter2))
.taggedWith[CounterDemo]
)
)
}

View File

@ -0,0 +1,113 @@
package outwatchapp.components
import colibri.ext.monix._
import com.softwaremill.tagging._
import monix.bio._
import monix.eval.Coeval
import monix.{eval => me}
import nova.monadic_sfx.ui.components.todo.Todo
import nova.monadic_sfx.ui.components.todo.TodoListStore
import outwatch._
import outwatch.dsl._
import outwatch.reactive.handlers.monix._
import outwatchapp.AppTypes
import outwatchapp.implicits._
import sttp.client._
import nova.monadic_sfx.util.reactive.store.Store
sealed trait RequestDemo
object RequestDemo {
def request(query: String)(implicit backend: AppTypes.Backend) = basicRequest
.get(
uri"https://jsonplaceholder.typicode.com/todos/${query.toIntOption.getOrElse(0)}"
)
.send()
.flatMap {
_.body match {
case Right(value) =>
me.Task(println(value)) >> me.Task(value)
case Left(error) =>
me.Task(println(error)) >> me.Task(error)
}
}
def apply(todoStore: Store[TodoListStore.Action, TodoListStore.State])(
implicit backend: AppTypes.Backend
): Task[HtmlVNode @@ RequestDemo] =
Task.deferAction(implicit s =>
for {
requestSub <- Handler.createF[Task, String]("empty")
todoContent <- Handler.createF[Task, String]
} yield div(
// cls := "col-lg-8 bd-example",
div(cls := "alert alert-danger", "Some Error Occured!"),
div(
form(
h4(cls := "form-title", "User Finder"),
div(
cls := "form-group",
label(
color := "hsla(0,0%,100%,0.8)",
forId := "httpInput",
"Enter an id: "
),
input(
idAttr := "httpInput",
typ := "text",
cls := "form-control",
placeholder := "0",
onInput.value --> requestSub
),
label(
color := "hsla(0,0%,100%,0.8)",
"Enter content for todo"
),
small(cls := "form-text text-muted", "default is 0")
),
div(
cls := "form-group",
input(
cls := "form-control",
onInput.value --> todoContent
),
button(
cls := "btn",
cls := "btn-info form-control",
"Add Todo",
onClick.preventDefault.foreachSync(_ =>
Coeval(println("Clicked"))
),
onClick(
todoContent
.map(TodoListStore.Add)
) --> todoStore.sink
)
)
)
),
div(
p(
cls := "profile-description",
requestSub
.doOnNext(str => me.Task(println(str)))
.mapEval(request)
.map(div(_)),
div(
"Todos: ",
todoStore
.map { case (a, s) => s.todos }
// .doOnNextF { case (a, s) => Coeval(println(s)) }
.distinctUntilChanged
.map(renderTodos)
)
)
)
).taggedWith[RequestDemo]
)
def renderTodos(todos: Seq[Todo]) = div(
ul(
todos.map(todo => li(div(s"id: ${todo.id} content: ${todo.content}")))
)
)
}

View File

@ -0,0 +1,151 @@
// package outwatchapp.components.todo
// import typings.chartJs.mod.{^ => Chart, _}
// import typings.moment.mod.Moment
// import typings.std.global.document
// import typings.std.{
// stdStrings,
// Date,
// HTMLButtonElement,
// HTMLCanvasElement,
// HTMLDivElement,
// MouseEvent
// }
// import scala.scalajs.js
// import scala.scalajs.js.|
// import scala.util.Random
// object Chartjs {
// val random = new Random()
// // def main(argv: scala.Array[String]): Unit = {
// // val section = document.createElement_section(stdStrings.section)
// // section.className = "w"
// // section.append(
// // chart(chartConfig(ChartType.bar, randomData(100, random.nextInt()))),
// // chart(chartConfig(ChartType.pie, randomData(100, random.nextInt()))),
// // chart(
// // chartConfig(ChartType.polarArea, randomData(100, random.nextInt()))
// // ),
// // chart(chartConfig(ChartType.line, randomData(100, random.nextInt())))
// // )
// // document.body.append(section)
// // }
// def chartConfig(
// tpe: ChartType,
// Data: js.Array[js.UndefOr[ChartPoint | Double | Null]]
// ): ChartConfiguration =
// ChartConfiguration()
// .setType(tpe)
// .setData(
// ChartData()
// .setLabels(Labels)
// .setDatasets(
// js.Array(
// ChartDataSets()
// .setLabel("Dataset 1")
// .setData(Data)
// .setBorderWidth(1)
// .setBackgroundColor(BackgroundColor)
// .setBorderColor(BorderColor)
// )
// )
// )
// .setOptions(ChartOptions().setResponsive(true))
// def chart(
// divElem: HTMLDivElement,
// canvas: HTMLCanvasElement,
// config: ChartConfiguration
// ): HTMLDivElement = {
// val div2: HTMLDivElement = document.createElement_div(stdStrings.div)
// // val canvas: HTMLCanvasElement =
// // document.createElement_canvas(stdStrings.canvas)
// val chart: Chart = new Chart(canvas, config)
// def dataSetsU: js.UndefOr[js.Array[ChartDataSets]] =
// config.data.flatMap(_.datasets)
// val randomizeBtn = button("Randomize Data") { (_, _) =>
// dataSetsU.foreach(
// _.foreach(dataset => dataset.data = randomData(100, random.nextInt()))
// )
// chart.update()
// }
// val addDataSet = button("Add Dataset") { (_, _) =>
// val newDataset = ChartDataSets()
// .setLabel("Dataset " + dataSetsU.fold(0)(_.length + 1))
// .setData(randomData(100, random.nextInt()))
// .setBorderWidth(1)
// .setBackgroundColor(BackgroundColor)
// .setBorderColor(BorderColor)
// dataSetsU.foreach(_.push(newDataset))
// chart.update()
// }
// val removeDataset = button("Remove dataset") { (_, _) =>
// dataSetsU.foreach(_.splice(0, 1))
// chart.update()
// }
// divElem.append(canvas, randomizeBtn, addDataSet, removeDataset)
// divElem
// }
// def button(title: String)(
// onClick: js.ThisFunction1[HTMLButtonElement, MouseEvent, Unit]
// ): HTMLButtonElement = {
// val btn = document.createElement_button(stdStrings.button)
// btn.textContent = title
// btn.addEventListener_click(stdStrings.click, onClick)
// btn
// }
// def randomData(
// max: Int,
// seed: Int
// ): js.Array[js.UndefOr[ChartPoint | Double | scala.Null]] = {
// val random = new Random(seed)
// js.Array[js.UndefOr[ChartPoint | Double | Null]](
// random.nextInt(max),
// random.nextInt(max),
// random.nextInt(max),
// random.nextInt(max),
// random.nextInt(max),
// random.nextInt(max)
// )
// }
// val Labels: js.Array[
// String | js.Array[Date | Double | Moment | String] | Double | Date | Moment
// ] =
// js.Array("Red", "Blue", "Yellow", "Green", "Purple", "Orange")
// val BackgroundColor: ChartColor =
// js.Array(
// color(54, 162, 235, 0.2),
// color(255, 206, 86, 0.2),
// color(75, 192, 192, 0.2),
// color(153, 102, 255, 0.2),
// color(255, 159, 64, 0.2)
// )
// val BorderColor: ChartColor =
// js.Array(
// color(255, 99, 132, 1),
// color(54, 162, 235, 1),
// color(255, 206, 86, 1),
// color(75, 192, 192, 1),
// color(153, 102, 255, 1),
// color(255, 159, 64, 1)
// )
// def color(r: Int, g: Int, b: Int, a: Double): String =
// s"rgba($r, $g, $b, $a)"
// }

View File

@ -0,0 +1,111 @@
package outwatchapp.components.todo
import scala.scalajs.js.|
import scala.util.Random
import colibri.ext.monix._
import com.softwaremill.tagging._
import monix.bio.Task
import monix.eval.Coeval
import outwatch.HtmlVNode
import outwatch.dsl._
import outwatch.reactive.handlers.monix._
import typings.chartJs.mod._
import typings.chartJs.mod.{^ => Chart}
import typings.moment.mod.Moment
import typings.std.Date
import typings.std.HTMLCanvasElement
import scalajs.js
sealed trait ChartjsDemo
object ChartjsDemo {
val random = new Random()
def apply(): Task[HtmlVNode @@ ChartjsDemo] = Task.deferAction(implicit s =>
for {
canvasH <- Handler.createF[Task, HTMLCanvasElement]
} yield div(
canvas(
onDomMount.asHtml.map(a =>
a.asInstanceOf[HTMLCanvasElement]
) --> canvasH
),
div(
canvasH
.doOnNextF(el =>
Coeval(
new Chart(
el,
chartConfig(ChartType.bar, randomData(100, random.nextInt()))
)
) >> Coeval.unit
)
.map(_ => div())
)
).taggedWith[ChartjsDemo]
)
def randomData(
max: Int,
seed: Int
): js.Array[js.UndefOr[ChartPoint | Double | scala.Null]] = {
val random = new Random(seed)
js.Array[js.UndefOr[ChartPoint | Double | Null]](
random.nextInt(max),
random.nextInt(max),
random.nextInt(max),
random.nextInt(max),
random.nextInt(max),
random.nextInt(max)
)
}
def chartConfig(
tpe: ChartType,
Data: js.Array[js.UndefOr[ChartPoint | Double | Null]]
): ChartConfiguration =
ChartConfiguration()
.setType(tpe)
.setData(
ChartData()
.setLabels(Labels)
.setDatasets(
js.Array(
ChartDataSets()
.setLabel("Dataset 1")
.setData(Data)
.setBorderWidth(1)
.setBackgroundColor(BackgroundColor)
.setBorderColor(BorderColor)
)
)
)
.setOptions(ChartOptions().setResponsive(true))
val Labels: js.Array[
String | js.Array[Date | Double | Moment | String] | Double | Date | Moment
] =
js.Array("Red", "Blue", "Yellow", "Green", "Purple", "Orange")
val BackgroundColor: ChartColor =
js.Array(
color(54, 162, 235, 0.2),
color(255, 206, 86, 0.2),
color(75, 192, 192, 0.2),
color(153, 102, 255, 0.2),
color(255, 159, 64, 0.2)
)
val BorderColor: ChartColor =
js.Array(
color(255, 99, 132, 1),
color(54, 162, 235, 1),
color(255, 206, 86, 1),
color(75, 192, 192, 1),
color(153, 102, 255, 1),
color(255, 159, 64, 1)
)
def color(r: Int, g: Int, b: Int, a: Double): String =
s"rgba($r, $g, $b, $a)"
}

View File

@ -0,0 +1,19 @@
package outwatchapp.components.todo
import nova.monadic_sfx.ui.components.todo.Todo
import typings.fuseJs.mod.Fuse.IFuseOptions
import typings.fuseJs.mod._
import typings.fuseJs.mod.{default => FuseC}
import scalajs.js
object FusejsDemo {
val x: Fuse[Todo] = new FuseC[Todo](
js.Array(Todo(1, "fuse")),
IFuseOptions().setKeys(js.Array("id", "content"))
)
val y = x.search[Todo]("fuse")
val mySeq = Seq(1, 2, 3)
val jsArr = js.Array(mySeq: _*)
val seq2 = jsArr.toSeq
}

View File

@ -1,5 +1,7 @@
package nova.monadic_sfx.ui.components.todo
import scala.scalajs.js.annotation.JSExportAll
import cats.kernel.Eq
import com.softwaremill.quicklens._
import io.circe.generic.JsonCodec
@ -7,9 +9,11 @@ import monix.bio.Task
import nova.monadic_sfx.util.reactive.store.Reducer
import nova.monadic_sfx.util.reactive.store.Store
@JSExportAll
case class Todo(id: Int, content: String)
object Todo {
implicit val eqForTodo = Eq.fromUniversalEquals[Todo]
}
object TodoListStore {

View File

@ -0,0 +1,41 @@
package outwatchapp.pages
import com.softwaremill.tagging._
import outwatch._
import outwatch.dsl._
import outwatchapp.components.CounterDemo
import outwatchapp.components.todo.ChartjsDemo
class HomePage(
counterDemo: VNode @@ CounterDemo,
chartDemo: VNode @@ ChartjsDemo
) {
def render = div(
div(cls := "title", "Home"),
div(
cls := "card",
div(
cls := "card-body",
counterDemo,
chartDemo,
p(
cls := "profile-description",
div(
"hm",
htmlTag("blockQuote")(
cls := "blockquote",
p(
cls := "mb-0",
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante."
),
footer(
cls := "blockquote-footer",
"Someone famous in ",
cite(title := "Source Title", "Source Title")
)
)
)
)
)
)
)
}

View File

@ -4,6 +4,7 @@ import monix.bio.Task
import monix.eval.Coeval
import monix.reactive.OverflowStrategy
import monix.reactive.subjects.ConcurrentSubject
import monix.reactive.Observer
object Store {
def createL[A, M](
@ -18,15 +19,14 @@ object Store {
Task {
val subject = ConcurrentSubject.publish[A](overflowStrategy)
val fold: ((A, M), A) => Coeval[(A, M)] = {
case ((_, state), action) =>
Coeval {
val (newState, effects) = reducer(state, action)
val fold: ((A, M), A) => Coeval[(A, M)] = { case ((_, state), action) =>
Coeval {
val (newState, effects) = reducer(state, action)
effects.subscribe(subject.onNext _)
effects.subscribe(subject.onNext _)
action -> newState
}
action -> newState
}
}
val obs = subject
@ -35,13 +35,15 @@ object Store {
)(fold)
val res = middlewares
.foldLeft(obs) {
case (obs, middleware) => middleware(obs)
.foldLeft(obs) { case (obs, middleware) =>
middleware(obs)
}
.doOnNextF(i => Coeval(println(s"Emitted item 1: $i")))
.behavior(initialAction -> initialState)
.refCount
res.subscribe(Observer.empty)
// .doOnNextF(i => Coeval(println(s"Emitted item 2: $i")))
MonixProSubject.from(

View File

@ -1,25 +1,46 @@
var webpack = require('webpack');
module.exports = require('./scalajs.webpack.config');
const Path = require('path');
var merge = require('webpack-merge');
var generated = require('./scalajs.webpack.config');
var Path = require('path');
const rootDir = Path.resolve(__dirname, '../../../..');
// module.exports.module = {
// ...module.exports.module,
// rules: module.exports.module.rules.concat([
// {
// test: /\.css$/i,
// use: ['style-loader', 'css-loader'],
// },
// ]),
// };
module.exports.devServer = {
contentBase: [
Path.resolve(__dirname, 'dev'), // fastOptJS output
Path.resolve(rootDir, 'assets') // project root containing index.html
],
watchContentBase: true,
hot: false,
hotOnly: false, // only reload when build is successful
inline: true // live reloading
var local = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(ttf|eot|woff|png|glb|jpeg|jpg|mp4|jsn)$/,
use: 'file-loader'
},
{
test: /\.(eot)$/,
use: 'url-loader'
}
]
},
devServer: {
contentBase: [
Path.resolve(__dirname, 'dev'), // fastOptJS output
Path.resolve(rootDir, 'assets') // project root containing index.html
],
watchContentBase: true,
hot: false,
hotOnly: false, // only reload when build is successful
inline: true, // live reloading
watchOptions: {
poll: 1000,
ignored: ["node_modules"]
}
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery/src/jquery',
jquery: 'jquery/src/jquery'
})
]
};
module.exports = merge(generated, local);

268
yarn.lock
View File

@ -2,6 +2,13 @@
# yarn lockfile v1
"@types/chart.js@2.9.11":
version "2.9.11"
resolved "https://registry.yarnpkg.com/@types/chart.js/-/chart.js-2.9.11.tgz#2b73fe59e78dfe31c2f8d6c6d0c169e98e65c16b"
integrity sha512-xuDh5pZWci1Z5DUkiGTTLIBymxUe8KMfo1JYM5HTY7LXURSCej458uMrD4eYn4v+BTYTZfKlTRNIk8jW4nTaOg==
dependencies:
moment "^2.10.2"
"@types/glob@^7.1.1":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
@ -10,6 +17,11 @@
"@types/minimatch" "*"
"@types/node" "*"
"@types/json-schema@^7.0.6":
version "7.0.6"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
"@types/minimatch@*":
version "3.0.3"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"
@ -193,12 +205,12 @@ ajv-errors@^1.0.0:
resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d"
integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==
ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
ajv-keywords@^3.1.0, ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
ajv@^6.1.0, ajv@^6.10.2:
ajv@^6.1.0, ajv@^6.10.2, ajv@^6.12.5:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
@ -403,6 +415,11 @@ bindings@^1.5.0:
dependencies:
file-uri-to-path "1.0.0"
blk-design-system@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/blk-design-system/-/blk-design-system-1.0.2.tgz#516a1fdf8eff7f08e04e66bdb88fa848ab243534"
integrity sha512-vhqb6s4qbPh/AXsd1vNwRMKvLToH/K3l+BK8RC6h1Lkn50kg8494NM+NDQr+F8q8LSwwHklBOChQLFjNf9k0eQ==
bluebird@^3.5.5:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@ -446,6 +463,11 @@ bonjour@^3.5.0:
multicast-dns "^6.0.1"
multicast-dns-service-types "^1.1.0"
bootstrap@4.5.3:
version "4.5.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@ -631,6 +653,11 @@ camelcase@^5.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
camelcase@^6.2.0:
version "6.2.0"
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
chalk@^2.4.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
@ -640,6 +667,29 @@ chalk@^2.4.1:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chart.js@2.9.3:
version "2.9.3"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.3.tgz#ae3884114dafd381bc600f5b35a189138aac1ef7"
integrity sha512-+2jlOobSk52c1VU6fzkh3UwqHMdSlgH1xFv9FKMqHiNCpXsGPQa/+81AFa+i3jZ253Mq9aAycPwDjnn1XbRNNw==
dependencies:
chartjs-color "^2.1.0"
moment "^2.10.2"
chartjs-color-string@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
dependencies:
color-name "^1.0.0"
chartjs-color@^2.1.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0"
integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==
dependencies:
chartjs-color-string "^0.6.0"
color-convert "^1.9.3"
chokidar@^2.1.8:
version "2.1.8"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917"
@ -735,7 +785,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
color-convert@^1.9.0:
color-convert@^1.9.0, color-convert@^1.9.3:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@ -747,6 +797,16 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
color-name@^1.0.0:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
colorette@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b"
integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==
commander@^2.20.0:
version "2.20.3"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
@ -922,6 +982,29 @@ crypto-browserify@^3.11.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
css-loader@5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.0.1.tgz#9e4de0d6636a6266a585bd0900b422c85539d25f"
integrity sha512-cXc2ti9V234cq7rJzFKhirb2L2iPy8ZjALeVJAozXYz9te3r4eqLSixNAbMDJSgJEQywqXzs8gonxaboeKqwiw==
dependencies:
camelcase "^6.2.0"
cssesc "^3.0.0"
icss-utils "^5.0.0"
loader-utils "^2.0.0"
postcss "^8.1.4"
postcss-modules-extract-imports "^3.0.0"
postcss-modules-local-by-default "^4.0.0"
postcss-modules-scope "^3.0.0"
postcss-modules-values "^4.0.0"
postcss-value-parser "^4.1.0"
schema-utils "^3.0.0"
semver "^7.3.2"
cssesc@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
cyclist@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
@ -1371,6 +1454,14 @@ figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e"
integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
file-loader@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-3.0.1.tgz#f8e0ba0b599918b51adfe45d66d1e771ad560faa"
integrity sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==
dependencies:
loader-utils "^1.0.2"
schema-utils "^1.0.0"
file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
@ -1508,6 +1599,11 @@ function-bind@^1.1.1:
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
fuse.js@6.4.3:
version "6.4.3"
resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.4.3.tgz#aadd6ac34aab5b1d6e6c60462fcb4d1c3f53bb01"
integrity sha512-JNgngolukIrqwayWnvy6NLH63hmwKPhm63o0uyBg51jPD0j09IvAzlV1rTXfAsgxpghI7khAo6Mv+EmvjDWXig==
get-caller-file@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
@ -1776,6 +1872,11 @@ iconv-lite@0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
icss-utils@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
ieee754@^1.1.4:
version "1.2.1"
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
@ -1799,6 +1900,11 @@ imurmurhash@^0.1.4:
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
indexes-of@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607"
integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc=
infer-owner@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
@ -2084,6 +2190,11 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
jquery@3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.3.1.tgz#958ce29e81c9790f31be7792df5d4d95fc57fbca"
integrity sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg==
json-parse-better-errors@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
@ -2111,6 +2222,13 @@ json5@^1.0.1:
dependencies:
minimist "^1.2.0"
json5@^2.1.2:
version "2.1.3"
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
dependencies:
minimist "^1.2.5"
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@ -2152,7 +2270,7 @@ loader-runner@^2.4.0:
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357"
integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==
loader-utils@^1.1.0, loader-utils@^1.2.3:
loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==
@ -2161,6 +2279,15 @@ loader-utils@^1.1.0, loader-utils@^1.2.3:
emojis-list "^3.0.0"
json5 "^1.0.1"
loader-utils@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==
dependencies:
big.js "^5.2.2"
emojis-list "^3.0.0"
json5 "^2.1.2"
loader-utils@~0.2.2:
version "0.2.17"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
@ -2179,7 +2306,7 @@ locate-path@^3.0.0:
p-locate "^3.0.0"
path-exists "^3.0.0"
lodash@^4.17.11, lodash@^4.17.14:
lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.5:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
@ -2196,6 +2323,13 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
yallist "^4.0.0"
make-dir@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@ -2321,6 +2455,11 @@ mime@1.6.0:
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
mime@^2.0.3:
version "2.4.7"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.7.tgz#962aed9be0ed19c91fd7dc2ece5d7f4e89a90d74"
integrity sha512-dhNd1uA2u397uQk3Nv5LM4lm93WYDUXFn3Fu291FJerns4jyTudqhIWe4W04YLy7Uk1tm1Ore04NpjRvQp/NPA==
mime@^2.4.4:
version "2.4.6"
resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1"
@ -2384,6 +2523,11 @@ mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5:
dependencies:
minimist "^1.2.5"
moment@^2.10.2:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@ -2429,6 +2573,11 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==
nanoid@^3.1.20:
version "3.1.20"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==
nanomatch@^1.2.9:
version "1.2.13"
resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
@ -2793,6 +2942,11 @@ pkg-dir@^3.0.0:
dependencies:
find-up "^3.0.0"
popper.js@1.16.1:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
portfinder@^1.0.26:
version "1.0.28"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
@ -2807,6 +2961,58 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
postcss-modules-extract-imports@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
postcss-modules-local-by-default@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c"
integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==
dependencies:
icss-utils "^5.0.0"
postcss-selector-parser "^6.0.2"
postcss-value-parser "^4.1.0"
postcss-modules-scope@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
dependencies:
postcss-selector-parser "^6.0.4"
postcss-modules-values@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
dependencies:
icss-utils "^5.0.0"
postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4:
version "6.0.4"
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz#56075a1380a04604c38b063ea7767a129af5c2b3"
integrity sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==
dependencies:
cssesc "^3.0.0"
indexes-of "^1.0.1"
uniq "^1.0.1"
util-deprecate "^1.0.2"
postcss-value-parser@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
postcss@^8.1.4:
version "8.2.1"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.1.tgz#eabc5557c4558059b9d9e5b15bce7ffa9089c2a8"
integrity sha512-RhsqOOAQzTgh1UB/IZdca7F9WDb7SUCR2Vnv1x7DbvuuggQIpoDwjK+q0rzoPffhYvWNKX5JSwS4so4K3UC6vA==
dependencies:
colorette "^1.2.1"
nanoid "^3.1.20"
source-map "^0.6.1"
process-nextick-args@~2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
@ -3119,6 +3325,15 @@ schema-utils@^1.0.0:
ajv-errors "^1.0.0"
ajv-keywords "^3.1.0"
schema-utils@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.0.0.tgz#67502f6aa2b66a2d4032b4279a2944978a0913ef"
integrity sha512-6D82/xSzO094ajanoOSbe4YvXWMfn2A//8Y1+MUqFAJul5Bs+yn36xbK9OtNDcRVSBJ9jjeoXftM6CfztsjOAA==
dependencies:
"@types/json-schema" "^7.0.6"
ajv "^6.12.5"
ajv-keywords "^3.5.2"
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
@ -3141,6 +3356,13 @@ semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
semver@^7.3.2:
version "7.3.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
dependencies:
lru-cache "^6.0.0"
send@0.17.1:
version "0.17.1"
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
@ -3512,6 +3734,14 @@ strip-eof@^1.0.0:
resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf"
integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=
style-loader@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c"
integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==
dependencies:
loader-utils "^2.0.0"
schema-utils "^3.0.0"
supports-color@^5.3.0, supports-color@^5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@ -3655,6 +3885,11 @@ union-value@^1.0.0:
is-extendable "^0.1.1"
set-value "^2.0.1"
uniq@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff"
integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=
unique-filename@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230"
@ -3699,6 +3934,15 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
url-loader@1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/url-loader/-/url-loader-1.1.2.tgz#b971d191b83af693c5e3fea4064be9e1f2d7f8d8"
integrity sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==
dependencies:
loader-utils "^1.1.0"
mime "^2.0.3"
schema-utils "^1.0.0"
url-parse@^1.4.3:
version "1.4.7"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
@ -3720,7 +3964,7 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
@ -3864,6 +4108,13 @@ webpack-log@^2.0.0:
ansi-colors "^3.0.0"
uuid "^3.3.2"
webpack-merge@4.1:
version "4.1.5"
resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.1.5.tgz#2be31e846c20767d1bef56bdca64c328a681190a"
integrity sha512-sVcM+MMJv6DO0C0GLLltx8mUlGMKXE0zBsuMqZ9jz2X9gsekALw6Rs0cAfTWc97VuWS6NpVUa78959zANnMMLQ==
dependencies:
lodash "^4.17.5"
webpack-sources@^1.4.0, webpack-sources@^1.4.1:
version "1.4.3"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
@ -3985,6 +4236,11 @@ yallist@^3.0.2:
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yargs-parser@^11.1.1:
version "11.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4"