CMS API update
authorTomas Zeman <tomas@functionals.cz>
Tue, 29 Dec 2020 16:46:47 +0100
changeset 33 fa0f19a74283
parent 32 2d14f02ba3bd
child 34 775d6da26993
CMS API update
base/resources/config.conf
base/src/sqwl/cms/Server.scala
base/src/sqwl/cms/config.scala
base/src/sqwl/cms/datamodel.scala
base/src/sqwl/cms/layout/PrimaryView.scala
build.sc
example/src/sqwl/cms/Articles.scala
example/src/sqwl/cms/Content.scala
example/src/sqwl/cms/ContentHolder.scala
--- a/base/resources/config.conf	Tue Nov 24 13:15:49 2020 +0100
+++ b/base/resources/config.conf	Tue Dec 29 16:46:47 2020 +0100
@@ -1,10 +1,10 @@
 config {
+  cms {
+    root = example/content
+  }
   http {
     interface = localhost
     port = 8080
     prefix = cms
   }
-  run {
-    mode = devel
-  }
 }
--- a/base/src/sqwl/cms/Server.scala	Tue Nov 24 13:15:49 2020 +0100
+++ b/base/src/sqwl/cms/Server.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -24,7 +24,6 @@
 
 import scala.collection.immutable
 import scala.concurrent.ExecutionContextExecutor
-import scala.io.StdIn
 
 trait Server extends App with Service[Nothing] with config with UrlScheme {
 
@@ -54,7 +53,7 @@
       } ~ pathPrefix(asArticle) { article =>
         pathEnd {
           complete(asHtml(ViewArticle(article)))
-        } ~ getFromDirectory(article.assets.toString)
+        } ~ getFromDirectory(content.articleAssets(article).toString)
       } ~ path(asCategory) { category =>
         complete(asHtml(ViewCategory(category)))
       } ~ path(TAG / asTag) { tag =>
@@ -72,10 +71,5 @@
   }
 
   Http().newServerAt(http.interface, http.port).bind(routes)
-  if (run.mode == "devel") {
-    system.log.info("Click `Enter` to close application...")
-    StdIn.readLine()
-    system.terminate()
-  }
 
 }
--- a/base/src/sqwl/cms/config.scala	Tue Nov 24 13:15:49 2020 +0100
+++ b/base/src/sqwl/cms/config.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -4,13 +4,14 @@
 
 @conf trait config {
 
+  final val cms = new {
+    val root = "example/content"
+  }
+
   final val http = new {
     val interface = "localhost"
     val port = 8080
     val prefix = "cms"
   }
 
-  final val run = new {
-    val mode = "devel"
-  }
 }
--- a/base/src/sqwl/cms/datamodel.scala	Tue Nov 24 13:15:49 2020 +0100
+++ b/base/src/sqwl/cms/datamodel.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -1,7 +1,24 @@
+/*
+ * Copyright 2018-2020 Tomas Zeman <tomas@functionals.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package sqwl.cms
 
 import java.nio.file.Path
 
+import scalatags.Text.all._
+
 trait Named {
   def name: String
 }
@@ -16,10 +33,9 @@
 
 trait iArticle extends Navigable {
   def title: String
-  def htmlContent: String
+  def htmlContent: SeqFrag[Frag]
   def category: Option[iCategory]
   def tags: Seq[iTag]
-  def assets: Path
   def rank: Int
 }
 
@@ -36,4 +52,5 @@
   def articleByPath(path: String): Option[iArticle]
   def categoryByPath(path: String): Option[iCategory]
   def tagByPath(path: String): Option[iTag]
+  def articleAssets(a: iArticle): Path
 }
--- a/base/src/sqwl/cms/layout/PrimaryView.scala	Tue Nov 24 13:15:49 2020 +0100
+++ b/base/src/sqwl/cms/layout/PrimaryView.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -1,3 +1,18 @@
+/*
+ * Copyright 2018-2020 Tomas Zeman <tomas@functionals.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package sqwl.cms.layout
 
 import scalatags.Text.all._
@@ -12,7 +27,7 @@
         div(cls:="row", div(cls:="col-md-12", art.tags.map(t =>
           a(href:=s"/${http.prefix}/$TAG/${t.pathSegment}", cls:="tag",
             t.name)))),
-        raw(art.htmlContent)
+        art.htmlContent
       ))
       case _ => None
     }
--- a/build.sc	Tue Nov 24 13:15:49 2020 +0100
+++ b/build.sc	Tue Dec 29 16:46:47 2020 +0100
@@ -13,6 +13,8 @@
 val akkaVer = "2.6.10"
 val akkaHttp = "10.2.1"
 
+val topLevelDir: Path = build.millSourcePath
+
 trait Common extends ScalaModule with PublishModule {
   val scalaVersion = scalaVer
 
@@ -135,9 +137,9 @@
           | import sqwl.cms.Category._
           | import sqwl.cms.Tag._
           | import sqwl.cms.Articles.article
-          | object `$aid` {
+          | object `$aid` extends ContentHolder {
           |   implicit val id = Articles.Id("$id")
-          |   twf("${p.toString}")
+          |   val content = twf("${p.toString}")
           | }
           |
           |/*
@@ -160,8 +162,10 @@
     write(dir / "main.scala",
       """
         | package sqwl.cms
-        | object Main extends Server {
-        |   override def content: iContent = Content
+        | import java.nio.file.Paths
+        | object Main extends Server with config {
+        |   override def content: iContent =
+        |     new Content(Paths.get(cms.root).toAbsolutePath)
         | }
       """.stripMargin)
 
@@ -193,20 +197,6 @@
     T.sources{ millSourcePath / up / 'example / 'content }
 }
 
-object production extends Content {
-  def contentSources: Sources =
-    T.sources{ millSourcePath / up / 'production / 'content }
-
-  def hgProdId: Input[String] = T.input {
-    os.proc("hg", "id", "-i", "--cwd", "production").call().out.trim
-  }
-
-  override def assemblyName: Target[String] = T{
-    s"${super.assemblyName()}-${hgProdId()}"
-  }
-}
-
-
 object js extends Common with ScalaJSModule {
   def scalaJSVersion: Target[String] = scalaJsVer
 }
--- a/example/src/sqwl/cms/Articles.scala	Tue Nov 24 13:15:49 2020 +0100
+++ b/example/src/sqwl/cms/Articles.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -1,8 +1,23 @@
+/*
+ * Copyright 2018-2020 Tomas Zeman <tomas@functionals.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package sqwl.cms
 
-import java.nio.file.{Path, Paths}
+import scalatags.Text.all._
+
 import scala.collection.mutable
-import scalatags.Text.all._
 
 object Articles {
   case class Id(v: String)
@@ -11,10 +26,9 @@
     title: String,
     category: Option[iCategory],
     tags: Seq[iTag] = Seq(),
-    htmlContent: String,
+    htmlContent: SeqFrag[Frag],
     rank: Int = 0
   ) extends iArticle {
-    override def assets: Path = Paths.get(s"example/content/${id.v}")
     override def pathSegment: String = id.v
   }
   private val all = mutable.ArrayBuffer[iArticle]()
@@ -24,7 +38,7 @@
   def article(title: String, cat: iCategory, tags: Seq[iTag] = Seq(),
     rank: Int = 0)(body: Frag*)(implicit articleId: Id): SeqFrag[Frag] = {
 
-    all += Article(articleId, title, Option(cat), tags, body.render, rank)
+    all += Article(articleId, title, Option(cat), tags, body, rank)
     body
   }
 }
--- a/example/src/sqwl/cms/Content.scala	Tue Nov 24 13:15:49 2020 +0100
+++ b/example/src/sqwl/cms/Content.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -1,7 +1,7 @@
 
 package sqwl.cms
 
-import java.nio.file.{Path, Paths}
+import java.nio.file.Path
 
 import enumeratum.EnumEntry.Hyphencase
 import enumeratum._
@@ -38,7 +38,7 @@
   case object Tag6 extends Tag("Tag 6")
 }
 
-object Content extends iContent {
+class Content(val root: Path) extends iContent {
   InitializeContent()
 
   def appTitle: String = "Content management system example"
@@ -46,12 +46,12 @@
   def appTitleShort: String = "CMS"
 
   def icon: (String, Path) =
-    ("icon.png", Paths.get("example/content/public/images/icon.png"))
+    ("icon.png", root.resolve("public/images/icon.png"))
 
-  def publicAssets: Path = Paths.get("example/content/public")
+  def publicAssets: Path = root.resolve("public")
 
   def styleSheet: (String, Path) =
-    ("site.css", Paths.get("example/content/public/css/site.css"))
+    ("site.css", root.resolve("public/css/site.css"))
 
   def articlesByTag(t: iTag): Seq[iArticle] =
     Articles.values filter(_.tags contains t) sortBy(_.rank)
@@ -70,4 +70,6 @@
     Category.withNameOption(path)
 
   def tagByPath(path: String): Option[iTag] = Tag.withNameOption(path)
+
+  def articleAssets(a: iArticle): Path = root.resolve(a.pathSegment)
 }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example/src/sqwl/cms/ContentHolder.scala	Tue Dec 29 16:46:47 2020 +0100
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020 Tomas Zeman <tomas@functionals.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package sqwl.cms
+
+import scalatags.Text.all._
+
+trait ContentHolder {
+  def id: Articles.Id
+  def content: SeqFrag[Frag]
+}