aboutsummaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
authorJakob Odersky <jakob@inpher.io>2019-11-26 00:03:43 -0500
committerJakob Odersky <jakob@inpher.io>2019-11-26 13:40:36 -0500
commitf38dd59d93f56213a8400841c7ebb0a7202144a7 (patch)
treea697acc765cf6203eb0a499601185d1303da8939 /shared
parent2f298c65846b2f62b9b40cd23f11971b301829f3 (diff)
downloadscala-tutorial-f38dd59d93f56213a8400841c7ebb0a7202144a7.tar.gz
scala-tutorial-f38dd59d93f56213a8400841c7ebb0a7202144a7.tar.bz2
scala-tutorial-f38dd59d93f56213a8400841c7ebb0a7202144a7.zip
Share model across fe and be and add websocket support
Diffstat (limited to 'shared')
-rw-r--r--shared/Message.scala26
-rw-r--r--shared/Templates.scala70
2 files changed, 96 insertions, 0 deletions
diff --git a/shared/Message.scala b/shared/Message.scala
new file mode 100644
index 0000000..55b4602
--- /dev/null
+++ b/shared/Message.scala
@@ -0,0 +1,26 @@
+import java.time.Instant
+
+case class Message(
+ author: String,
+ date: Long, // seconds since epoch
+ content: String
+)
+
+object Message {
+
+ // A ReadWriter is used to serialize a message to JSON.
+ // The call to macroRW will generate a readwriter through compiler-time
+ // introspection. By default, the mapping of a case class to JSON is pretty
+ // straightforward. A message:
+ // Message("John Smith", 0, "Hello, World!")
+ // will get rendered as
+ // {
+ // "author": "John Smith",
+ // "date": 0,
+ // "message": "Hello, World!"
+ // }
+ //
+ implicit def messageRW: upickle.default.ReadWriter[Message] =
+ upickle.default.macroRW[Message]
+
+}
diff --git a/shared/Templates.scala b/shared/Templates.scala
new file mode 100644
index 0000000..9c3c292
--- /dev/null
+++ b/shared/Templates.scala
@@ -0,0 +1,70 @@
+import scalatags.generic.Bundle
+
+class Templates[Builder, Output <: FragT, FragT](val backend: Bundle[Builder, Output, FragT]) {
+ import backend.all._
+
+ def message(msg: Message): Tag = {
+ div(cls := "col-xs-12 col-sm-6 col-md-3 col-lg-2")(
+ div(cls := s"card text-white mb-3 bg-primary")(
+ div(cls := "card-header")(
+ msg.author
+ ),
+ div(`class` := "card-body")(
+ div(`class` := "card-text")(
+ msg.content
+ )
+ )
+ )
+ )
+ }
+
+ def conversation(messages: Seq[Message]): Tag =
+ div(`class` := "container-fluid")(
+ div(id := "conversation", `class` := "row")(
+ for (msg <- messages.sortBy(_.date)) yield message(msg)
+ )
+ )
+
+ def page(messages: Seq[Message]): Tag = html(
+ head(
+ link(
+ rel := "stylesheet",
+ `type` := "text/css",
+ href := "/assets/lib/bootstrap-4.1.0/css/bootstrap-reboot.min.css"
+ ),
+ link(
+ rel := "stylesheet",
+ `type` := "text/css",
+ href := "/assets/lib/bootstrap-4.1.0/css/bootstrap-grid.min.css"
+ ),
+ link(
+ rel := "stylesheet",
+ `type` := "text/css",
+ href := "/assets/lib/bootstrap-4.1.0/css/bootstrap.min.css"
+ ),
+ link(
+ rel := "stylesheet",
+ `type` := "text/css",
+ href := "/assets/main.css"
+ ),
+ meta(
+ name := "viewport",
+ content := "width=device-width, initial-scale=1, shrink-to-fit=no"
+ ),
+ script(`type` := "text/javascript", src := "/assets/app.js")
+ ),
+ body(
+ conversation(messages),
+ script(`type` := "text/javascript")(
+ raw(
+ """|document.addEventListener("DOMContentLoaded", function(event) {
+ | console.info("Starting ScalaJS application...")
+ | Main.main() // run ScalaJS application
+ |})
+ |""".stripMargin
+ )
+ )
+ )
+ )
+
+}