--- 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]
+}