diff --git a/assets/app/index.html b/assets/app/index.html index 2ac9b89..396b535 100644 --- a/assets/app/index.html +++ b/assets/app/index.html @@ -5,15 +5,8 @@ Outwatch App - - - - - - - diff --git a/build.sbt b/build.sbt index b348fb9..517c9f9 100644 --- a/build.sbt +++ b/build.sbt @@ -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, diff --git a/src/main/scala/outwatchapp/AppTypes.scala b/src/main/scala/outwatchapp/AppTypes.scala new file mode 100644 index 0000000..41043ef --- /dev/null +++ b/src/main/scala/outwatchapp/AppTypes.scala @@ -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] +} diff --git a/src/main/scala/outwatchapp/MainApp.scala b/src/main/scala/outwatchapp/MainApp.scala new file mode 100644 index 0000000..0d7c6c7 --- /dev/null +++ b/src/main/scala/outwatchapp/MainApp.scala @@ -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 + ) +} diff --git a/src/main/scala/outwatchapp/OutwatchApp.scala b/src/main/scala/outwatchapp/OutwatchApp.scala index 36954cf..61961ef 100644 --- a/src/main/scala/outwatchapp/OutwatchApp.scala +++ b/src/main/scala/outwatchapp/OutwatchApp.scala @@ -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) } diff --git a/src/main/scala/outwatchapp/Page.scala b/src/main/scala/outwatchapp/Page.scala new file mode 100644 index 0000000..cfb6bab --- /dev/null +++ b/src/main/scala/outwatchapp/Page.scala @@ -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 +} diff --git a/src/main/scala/outwatchapp/Router.scala b/src/main/scala/outwatchapp/Router.scala new file mode 100644 index 0000000..9a6cab5 --- /dev/null +++ b/src/main/scala/outwatchapp/Router.scala @@ -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() + ) + ) + +} diff --git a/src/main/scala/outwatchapp/components/CounterDemo.scala b/src/main/scala/outwatchapp/components/CounterDemo.scala new file mode 100644 index 0000000..710a17f --- /dev/null +++ b/src/main/scala/outwatchapp/components/CounterDemo.scala @@ -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] + ) + ) +} diff --git a/src/main/scala/outwatchapp/components/RequestDemo.scala b/src/main/scala/outwatchapp/components/RequestDemo.scala new file mode 100644 index 0000000..91ec769 --- /dev/null +++ b/src/main/scala/outwatchapp/components/RequestDemo.scala @@ -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}"))) + ) + ) +} diff --git a/src/main/scala/outwatchapp/components/todo/Chartjs.scala b/src/main/scala/outwatchapp/components/todo/Chartjs.scala new file mode 100644 index 0000000..c6143ab --- /dev/null +++ b/src/main/scala/outwatchapp/components/todo/Chartjs.scala @@ -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)" +// } diff --git a/src/main/scala/outwatchapp/components/todo/ChartjsDemo.scala b/src/main/scala/outwatchapp/components/todo/ChartjsDemo.scala new file mode 100644 index 0000000..d400f0f --- /dev/null +++ b/src/main/scala/outwatchapp/components/todo/ChartjsDemo.scala @@ -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)" + +} diff --git a/src/main/scala/outwatchapp/components/todo/Fusejs.scala b/src/main/scala/outwatchapp/components/todo/Fusejs.scala new file mode 100644 index 0000000..0c815f0 --- /dev/null +++ b/src/main/scala/outwatchapp/components/todo/Fusejs.scala @@ -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 +} diff --git a/src/main/scala/outwatchapp/components/todo/TodoListStore.scala b/src/main/scala/outwatchapp/components/todo/TodoListStore.scala index d7422a3..9b2fdb3 100644 --- a/src/main/scala/outwatchapp/components/todo/TodoListStore.scala +++ b/src/main/scala/outwatchapp/components/todo/TodoListStore.scala @@ -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 { diff --git a/src/main/scala/outwatchapp/pages/HomePage.scala b/src/main/scala/outwatchapp/pages/HomePage.scala new file mode 100644 index 0000000..7efaef9 --- /dev/null +++ b/src/main/scala/outwatchapp/pages/HomePage.scala @@ -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") + ) + ) + ) + ) + ) + ) + ) +} diff --git a/src/main/scala/outwatchapp/util/reactive/store/Store.scala b/src/main/scala/outwatchapp/util/reactive/store/Store.scala index 5fb6e13..f77ab1e 100644 --- a/src/main/scala/outwatchapp/util/reactive/store/Store.scala +++ b/src/main/scala/outwatchapp/util/reactive/store/Store.scala @@ -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( diff --git a/webpack.config.dev.js b/webpack.config.dev.js index d8d44d3..dcb9cf1 100644 --- a/webpack.config.dev.js +++ b/webpack.config.dev.js @@ -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); diff --git a/yarn.lock b/yarn.lock index 7fe06ed..384fb34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"