* Adds beercss (WIP).

* Adds some date formatting.
* Adds favicon.
This commit is contained in:
Stefan Schallerl 2025-02-07 11:25:13 +01:00
parent 1bdce2e9cf
commit 1d68957f96
12 changed files with 71 additions and 26 deletions

View file

@ -1,18 +1,14 @@
plugins {
// Apply the shared build logic from a convention plugin.
// The shared code is located in `buildSrc/src/main/kotlin/kotlin-jvm.gradle.kts`.
id("buildsrc.convention.kotlin-jvm")
alias(libs.plugins.tempolin)
id("app.cash.sqldelight") version "2.0.2"
// Apply the Application plugin to add support for building an executable JVM application.
application
}
dependencies {
implementation("at.favre.lib:bcrypt:0.10.2")
implementation("org.apache.pdfbox:pdfbox:3.0.4")
implementation("app.cash.sqldelight:sqlite-driver:2.0.2")
// implementation("org.xerial:sqlite-jdbc:3.48.0.0")
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.+")
implementation(libs.slf4jsimple)
@ -23,8 +19,6 @@ dependencies {
}
application {
// Define the Fully Qualified Name for the application main class
// (Note that Kotlin compiles `App.kt` to a class with FQN `com.example.app.AppKt`.)
mainClass = "net.h34t.filemure.ServerKt"
}

View file

@ -58,7 +58,8 @@ class FilemureApp(repository: SqliteRepository) {
modifiers = modifiers,
title = "unauthorized",
target = "",
content = Unauthorized()
content = Unauthorized(),
back = ""
)
)
}

View file

@ -6,6 +6,7 @@ import io.javalin.http.HttpStatus
import io.javalin.http.UnauthorizedResponse
import java.io.BufferedOutputStream
import java.io.OutputStreamWriter
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.Month
import java.time.format.DateTimeFormatter
@ -66,3 +67,10 @@ val formDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm")
fun LocalDateTime.formatHuman() = this.format(htmlDtf)
fun LocalDateTime.formatHtmlForm() = this.format(formDtf)
private val dfMonth = DateTimeFormatter.ofPattern("MMMM")
private val dfYearMonth = DateTimeFormatter.ofPattern("MMMM yyyy")
fun LocalDate.formatHumanMonth() = dfMonth.format(this)
fun LocalDate.formatHumanYearMonth() = dfYearMonth.format(this)

View file

@ -28,6 +28,7 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
modifiers = modifiers,
title = document.title,
target = "document-${document.extId}",
back = "/",
content = Document(
modifiers = modifiers,
extId = document.extId.value,
@ -83,6 +84,7 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
title = "new document",
// TODO enable target for new documents in form
target = "",
back = "/",
content = DocumentCreateForm(
modifiers = modifiers,
title = title,
@ -172,6 +174,7 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
modifiers = modifiers,
title = document.title,
target = "",
back = "/document/$extId",
content = DocumentEditForm(
modifiers = modifiers,
extId = extId,

View file

@ -18,6 +18,7 @@ class LimboController(val modifiers: TemplateModifiers, val repository: SqliteRe
modifiers = modifiers,
title = "Filemure Limbo",
target = "limbo",
back = "/",
content = Limbo(
modifiers = modifiers, limboFileCount = files.size.toString(), file = {
files.map { f ->

View file

@ -14,9 +14,8 @@ class LoginController(val modifiers: TemplateModifiers, val repository: SqliteRe
modifiers = modifiers,
title = "Hello to Filemure",
target = "",
content = Login(
)
back = "",
content = Login()
)
)
}

View file

@ -6,8 +6,9 @@ import net.h34t.filemure.repository.SqliteRepository
import net.h34t.filemure.tpl.Frame
import net.h34t.filemure.tpl.Overview
import net.h34t.filemure.tpl.OverviewDocuments
import java.time.LocalDate
class OverviewController(val modifiers: TemplateModifiers, val repository: SqliteRepository) {
class OverviewController(private val modifiers: TemplateModifiers, private val repository: SqliteRepository) {
fun overview(ctx: Context) {
val session = ctx.requireSession()
@ -23,6 +24,7 @@ class OverviewController(val modifiers: TemplateModifiers, val repository: Sqlit
modifiers = modifiers,
title = "Overview",
target = "document",
back = "",
content = Overview(
modifiers = modifiers,
limboFileCount = limboFileCount.toString(),
@ -34,7 +36,8 @@ class OverviewController(val modifiers: TemplateModifiers, val repository: Sqlit
year.value.entries.sortedByDescending { it.key }.map { month ->
MonthBlock(
year = year.key.toString(),
month = (month.key.ordinal + 1).toString(),
month = month.key.value.toString(),
monthHuman = LocalDate.of(year.key, month.key, 1).formatHumanMonth(),
count = month.value.size.toString()
)
}.asSequence()
@ -60,14 +63,15 @@ class OverviewController(val modifiers: TemplateModifiers, val repository: Sqlit
modifiers = modifiers,
title = "Overview",
target = "document",
back = "/",
content = OverviewDocuments(
modifiers = modifiers,
category = "$year-$month",
category = LocalDate.of(year, month, 1).formatHumanYearMonth(),
document = {
documents.sortedBy { it.referenceDate }.map { document ->
DocumentBlock(
extId = document.extId.value,
referenceDate = document.referenceDate.formatHtmlForm(),
referenceDate = document.referenceDate.formatHuman(),
title = document.title.ifBlank { "untitled" },
)
}.asSequence()

View file

@ -23,6 +23,7 @@ class SearchController(val modifiers: TemplateModifiers, val repository: SqliteR
modifiers = modifiers,
title = "Overview",
target = "document",
back = "/",
content = Search(
modifiers = modifiers,
search = q ?: "",

View file

@ -6,14 +6,47 @@
<title>{*$title} :: Filemure</title>
<link rel="stylesheet" type="text/css" href="/filemure.css">
<script src="/filemure.js"></script>
<link rel="icon" href="/favicon.png">
<link href="https://cdn.jsdelivr.net/npm/beercss@3.8.0/dist/cdn/beer.min.css" rel="stylesheet"/>
<script type="module" src="https://cdn.jsdelivr.net/npm/beercss@3.8.0/dist/cdn/beer.min.js"></script>
<script type="module"
src="https://cdn.jsdelivr.net/npm/material-dynamic-colors@1.1.2/dist/cdn/material-dynamic-colors.min.js"></script>
</head>
<body>
{if $target}
<div class="dropzone" data-target="{*$target}"></div>
<dialog id="upload_progress_dialog">
<progress id="upload_progress" max="100"></progress>
</dialog>
{/if}
{template $content}
<main class="responsive">
<header>
<nav>
<!--
<button class="circle transparent">
<i>menu</i>
</button>
-->
{if $back}
<a href="{$back}">
<button class="circle transparent">
<i>arrow_back</i>
</button>
</a>
{/if}
<h5 class="max center-align">{*$title}</h5>
<!--
<button class="circle transparent">
<img class="responsive" src="/favicon.png">
</button>
-->
</nav>
</header>
{if $target}
<div class="dropzone" data-target="{*$target}"></div>
<dialog id="upload_progress_dialog">
<progress id="upload_progress" max="100"></progress>
</dialog>
{/if}
{template $content}
</main>
</body>
</html>

View file

@ -1,4 +1,4 @@
<h1>Hello to Filemure</h1>
<p>To add a document, just drag &amp; drop the file in here.</p>
<p>Files in <a href="/limbo">limbo: {$limboFileCount}</a>.</p>
@ -13,7 +13,7 @@
</tr>
{for $month}
<tr>
<td>{*$month}</td>
<td>{*$monthHuman}</td>
<td><a href="/overview/{*$year}/{*$month}">{*$count} Files</a></td>
</tr>
{/for}

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View file

@ -1,8 +1,9 @@
document.addEventListener("DOMContentLoaded", function () {
const dropzone = document.querySelector('html');
const targetContainer = document.querySelector('#dropzone')
const targetContainer = document.querySelector('.dropzone')
if (targetContainer !== null) {
if (targetContainer != null) {
console.log("target ready")
const target = targetContainer.dataset.target;
const progressDialog = document.querySelector('#upload_progress_dialog')