mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 18:39:33 +00:00
Minor improvements
- use a one-line log format - load templates only once - fixed typos - fix reset timezone in ui settings - hide bookmarks headline if there are none
This commit is contained in:
parent
27025715f4
commit
a3569598d8
modules
logging/scribe/src/main/scala/docspell/logging/impl
restserver/src/main/scala/docspell/restserver
webapp/src/main/elm
@ -47,7 +47,7 @@ object ScribeConfigure {
|
||||
if (logger.id == scribe.Logger.RootId) {
|
||||
cfg.format match {
|
||||
case Format.Fancy =>
|
||||
l.withHandler(formatter = Formatter.default, writer = SystemOutWriter)
|
||||
l.withHandler(formatter = Formatter.enhanced, writer = SystemOutWriter)
|
||||
case Format.Plain =>
|
||||
l.withHandler(formatter = Formatter.classic, writer = SystemOutWriter)
|
||||
case Format.Json =>
|
||||
|
@ -104,7 +104,7 @@ object RestServer {
|
||||
)(
|
||||
wsB: WebSocketBuilder2[F]
|
||||
) = {
|
||||
val templates = TemplateRoutes[F](cfg)
|
||||
val templates = TemplateRoutes[F](cfg, Templates[F])
|
||||
val httpApp = Router(
|
||||
"/internal" -> InternalHeader(internSettings.internalRouteKey) {
|
||||
internalRoutes(pubSub)
|
||||
|
@ -6,12 +6,8 @@
|
||||
|
||||
package docspell.restserver.webapp
|
||||
|
||||
import java.net.URL
|
||||
import java.util.concurrent.atomic.AtomicReference
|
||||
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
import fs2.text
|
||||
|
||||
import docspell.restserver.{BuildInfo, Config}
|
||||
|
||||
@ -36,22 +32,16 @@ object TemplateRoutes {
|
||||
def serviceWorker: HttpRoutes[F]
|
||||
}
|
||||
|
||||
def apply[F[_]: Async](cfg: Config): InnerRoutes[F] = {
|
||||
val indexTemplate = memo(
|
||||
loadResource("/index.html").flatMap(loadTemplate(_))
|
||||
)
|
||||
val docTemplate = memo(loadResource("/doc.html").flatMap(loadTemplate(_)))
|
||||
val swTemplate = memo(loadResource("/sw.js").flatMap(loadTemplate(_)))
|
||||
|
||||
def apply[F[_]: Async](cfg: Config, templates: Templates[F]): InnerRoutes[F] = {
|
||||
val dsl = new Http4sDsl[F] {}
|
||||
import dsl._
|
||||
new InnerRoutes[F] {
|
||||
def doc =
|
||||
HttpRoutes.of[F] { case GET -> Root =>
|
||||
for {
|
||||
templ <- docTemplate
|
||||
docTemplate <- templates.doc
|
||||
resp <- Ok(
|
||||
DocData().render(templ),
|
||||
DocData().render(docTemplate),
|
||||
`Content-Type`(textHtml, Charset.`UTF-8`)
|
||||
)
|
||||
} yield resp
|
||||
@ -59,9 +49,9 @@ object TemplateRoutes {
|
||||
def app =
|
||||
HttpRoutes.of[F] { case GET -> _ =>
|
||||
for {
|
||||
templ <- indexTemplate
|
||||
indexTemplate <- templates.index
|
||||
resp <- Ok(
|
||||
IndexData(cfg).render(templ),
|
||||
IndexData(cfg).render(indexTemplate),
|
||||
`Content-Type`(textHtml, Charset.`UTF-8`)
|
||||
)
|
||||
} yield resp
|
||||
@ -70,9 +60,9 @@ object TemplateRoutes {
|
||||
def serviceWorker =
|
||||
HttpRoutes.of[F] { case GET -> _ =>
|
||||
for {
|
||||
templ <- swTemplate
|
||||
swTemplate <- templates.serviceWorker
|
||||
resp <- Ok(
|
||||
IndexData(cfg).render(templ),
|
||||
IndexData(cfg).render(swTemplate),
|
||||
`Content-Type`(appJavascript, Charset.`UTF-8`)
|
||||
)
|
||||
} yield resp
|
||||
@ -80,31 +70,6 @@ object TemplateRoutes {
|
||||
}
|
||||
}
|
||||
|
||||
def loadResource[F[_]: Sync](name: String): F[URL] =
|
||||
Option(getClass.getResource(name)) match {
|
||||
case None =>
|
||||
Sync[F].raiseError(new Exception("Unknown resource: " + name))
|
||||
case Some(r) =>
|
||||
r.pure[F]
|
||||
}
|
||||
|
||||
def loadUrl[F[_]: Sync](url: URL): F[String] =
|
||||
fs2.io
|
||||
.readInputStream(Sync[F].delay(url.openStream()), 64 * 1024)
|
||||
.through(text.utf8.decode)
|
||||
.compile
|
||||
.string
|
||||
|
||||
def parseTemplate[F[_]: Sync](str: String): F[Template] =
|
||||
Sync[F].pure(mustache.parse(str).leftMap(err => new Exception(err._2))).rethrow
|
||||
|
||||
def loadTemplate[F[_]: Sync](url: URL): F[Template] = {
|
||||
val logger = docspell.logging.getLogger[F]
|
||||
loadUrl[F](url).flatMap(parseTemplate[F]).flatMap { t =>
|
||||
logger.info(s"Compiled template $url") *> t.pure[F]
|
||||
}
|
||||
}
|
||||
|
||||
case class DocData(swaggerRoot: String, openapiSpec: String)
|
||||
object DocData {
|
||||
|
||||
@ -150,18 +115,4 @@ object TemplateRoutes {
|
||||
implicit def yamuscaValueConverter: ValueConverter[IndexData] =
|
||||
deriveValueConverter[IndexData]
|
||||
}
|
||||
|
||||
private def memo[F[_]: Sync, A](fa: => F[A]): F[A] = {
|
||||
val ref = new AtomicReference[A]()
|
||||
Sync[F].defer {
|
||||
Option(ref.get) match {
|
||||
case Some(a) => a.pure[F]
|
||||
case None =>
|
||||
fa.map { a =>
|
||||
ref.set(a)
|
||||
a
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2020 Eike K. & Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package docspell.restserver.webapp
|
||||
|
||||
import java.net.URL
|
||||
|
||||
import cats.effect._
|
||||
import cats.effect.unsafe.implicits._
|
||||
import cats.implicits._
|
||||
import fs2.text
|
||||
|
||||
import yamusca.imports._
|
||||
|
||||
trait Templates[F[_]] {
|
||||
def index: F[Template]
|
||||
def doc: F[Template]
|
||||
def serviceWorker: F[Template]
|
||||
}
|
||||
|
||||
object Templates {
|
||||
|
||||
def apply[F[_]: Sync]: Templates[F] =
|
||||
new Templates[F] {
|
||||
def index = Templates.indexTemplate.pure[F]
|
||||
def doc = Templates.docTemplate.pure[F]
|
||||
def serviceWorker = Templates.swTemplate.pure[F]
|
||||
}
|
||||
|
||||
private lazy val indexTemplate = fromResource[IO]("/index.html").unsafeRunSync()
|
||||
private lazy val docTemplate = fromResource[IO]("/doc.html").unsafeRunSync()
|
||||
private lazy val swTemplate = fromResource[IO]("/sw.js").unsafeRunSync()
|
||||
|
||||
def fromResource[F[_]: Sync](path: String): F[Template] =
|
||||
loadResource[F](path).flatMap(loadTemplate[F](_))
|
||||
|
||||
private def loadResource[F[_]: Sync](name: String): F[URL] =
|
||||
Option(getClass.getResource(name)) match {
|
||||
case None =>
|
||||
Sync[F].raiseError(new Exception("Unknown resource: " + name))
|
||||
case Some(r) =>
|
||||
r.pure[F]
|
||||
}
|
||||
|
||||
private def loadUrl[F[_]: Sync](url: URL): F[String] =
|
||||
fs2.io
|
||||
.readInputStream(Sync[F].delay(url.openStream()), 64 * 1024)
|
||||
.through(text.utf8.decode)
|
||||
.compile
|
||||
.string
|
||||
|
||||
private def parseTemplate[F[_]: Sync](str: String): F[Template] =
|
||||
Sync[F].pure(mustache.parse(str).leftMap(err => new Exception(err._2))).rethrow
|
||||
|
||||
private def loadTemplate[F[_]: Sync](url: URL): F[Template] = {
|
||||
val logger = docspell.logging.getLogger[F]
|
||||
loadUrl[F](url).flatMap(parseTemplate[F]).flatMap { t =>
|
||||
logger.info(s"Compiled template $url") *> t.pure[F]
|
||||
}
|
||||
}
|
||||
}
|
@ -308,7 +308,7 @@ view texts settings model =
|
||||
(Comp.EventSample.viewJson texts.eventSample False model.eventSampleModel)
|
||||
]
|
||||
, div [ class "mt-4" ]
|
||||
[ formHeader "Test Delviery"
|
||||
[ formHeader "Test Delivery"
|
||||
, Html.map DeliveryTestMsg
|
||||
(Comp.NotificationTest.view
|
||||
{ runDisabled = getHook model == Nothing }
|
||||
|
@ -569,7 +569,7 @@ update flags sett msg model =
|
||||
newSettings =
|
||||
case tab of
|
||||
GeneralTab ->
|
||||
{ sett | uiLang = Nothing, sideMenuVisible = Nothing }
|
||||
{ sett | uiLang = Nothing, timeZone = Nothing, sideMenuVisible = Nothing }
|
||||
|
||||
SearchTab ->
|
||||
{ sett
|
||||
|
@ -31,20 +31,22 @@ view texts versionInfo _ model =
|
||||
, menuLink [ Page.href (SearchPage Nothing) ] (Icons.searchIcon "") texts.basics.items
|
||||
, menuLink [ onClick InitUpload, href "#" ] (Icons.fileUploadIcon "") texts.uploadFiles
|
||||
]
|
||||
, h3
|
||||
[ class S.header3
|
||||
, class "italic mt-3"
|
||||
]
|
||||
[ text texts.bookmarks
|
||||
]
|
||||
, div [ class "ml-2" ]
|
||||
[ Html.map BookmarkMsg
|
||||
(Comp.BookmarkChooser.viewWith
|
||||
{ showUser = True, showCollective = True, showShares = False }
|
||||
texts.bookmarkChooser
|
||||
model.sideMenu.bookmarkChooser
|
||||
Comp.BookmarkChooser.emptySelection
|
||||
)
|
||||
, div [ classList [ ( "hidden", Comp.BookmarkChooser.isEmpty model.sideMenu.bookmarkChooser ) ] ]
|
||||
[ h3
|
||||
[ class S.header3
|
||||
, class "italic mt-3"
|
||||
]
|
||||
[ text texts.bookmarks
|
||||
]
|
||||
, div [ class "ml-2" ]
|
||||
[ Html.map BookmarkMsg
|
||||
(Comp.BookmarkChooser.viewWith
|
||||
{ showUser = True, showCollective = True, showShares = False }
|
||||
texts.bookmarkChooser
|
||||
model.sideMenu.bookmarkChooser
|
||||
Comp.BookmarkChooser.emptySelection
|
||||
)
|
||||
]
|
||||
]
|
||||
, h3
|
||||
[ class S.header3
|
||||
|
Loading…
x
Reference in New Issue
Block a user