swap jte for htmlflow dependencies
This commit is contained in:
parent
a80473fb35
commit
2b2e610851
21 changed files with 6 additions and 659 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -58,7 +58,6 @@ gradle-app.setting
|
||||||
|
|
||||||
# Allow generated code fragments for Docker builds
|
# Allow generated code fragments for Docker builds
|
||||||
!build/generated-src/**
|
!build/generated-src/**
|
||||||
!build/generated-resources/**
|
|
||||||
|
|
||||||
###################
|
###################
|
||||||
### Environment ###
|
### Environment ###
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,9 @@ COPY --chown=gradle:gradle src ./src
|
||||||
|
|
||||||
# Copy pre-generated code fragments
|
# Copy pre-generated code fragments
|
||||||
COPY --chown=gradle:gradle build/generated-src ./build/generated-src
|
COPY --chown=gradle:gradle build/generated-src ./build/generated-src
|
||||||
COPY --chown=gradle:gradle build/generated-resources ./build/generated-resources
|
|
||||||
|
|
||||||
# Build the fat jar without cleaning (preserves generated code)
|
# Build the fat jar without cleaning (preserves generated code)
|
||||||
RUN ./gradlew build -x clean -x cleanGenerated -x jooqCodegen -x flywayMigrate -x precompileJte --no-daemon
|
RUN ./gradlew build -x clean -x cleanGenerated -x jooqCodegen -x flywayMigrate --no-daemon
|
||||||
|
|
||||||
# --- Stage 2: Run the app ---
|
# --- Stage 2: Run the app ---
|
||||||
FROM eclipse-temurin:21-jdk-alpine
|
FROM eclipse-temurin:21-jdk-alpine
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
import io.github.klahap.dotenv.DotEnv
|
|
||||||
import io.github.klahap.dotenv.DotEnvBuilder
|
import io.github.klahap.dotenv.DotEnvBuilder
|
||||||
import org. gradle.api.JavaVersion.VERSION_21
|
import org. gradle.api.JavaVersion.VERSION_21
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||||
import kotlin.io.path.Path
|
|
||||||
|
|
||||||
// ====================================================================================================
|
// ====================================================================================================
|
||||||
// ENVIRONMENT CONFIGURATION
|
// ENVIRONMENT CONFIGURATION
|
||||||
|
|
@ -33,7 +31,6 @@ plugins {
|
||||||
alias(libs.plugins.kotlin.jvm)
|
alias(libs.plugins.kotlin.jvm)
|
||||||
alias(libs.plugins.shadow)
|
alias(libs.plugins.shadow)
|
||||||
alias(libs.plugins.dotenv.plugin)
|
alias(libs.plugins.dotenv.plugin)
|
||||||
alias(libs.plugins.jte)
|
|
||||||
alias(libs.plugins.tasktree)
|
alias(libs.plugins.tasktree)
|
||||||
alias(libs.plugins.jooq.codegen.gradle)
|
alias(libs.plugins.jooq.codegen.gradle)
|
||||||
alias(libs.plugins.flyway)
|
alias(libs.plugins.flyway)
|
||||||
|
|
@ -62,16 +59,12 @@ repositories {
|
||||||
// GENERATED CODE DIRECTORIES
|
// GENERATED CODE DIRECTORIES
|
||||||
// ====================================================================================================
|
// ====================================================================================================
|
||||||
|
|
||||||
val generatedResourcesDir = layout.buildDirectory.dir("generated-resources")
|
|
||||||
val generatedSourcesDir = layout.buildDirectory.dir("generated-src")
|
val generatedSourcesDir = layout.buildDirectory.dir("generated-src")
|
||||||
val migrationSourceDir = layout.projectDirectory.dir("src/main/resources/db/migration")
|
val migrationSourceDir = layout.projectDirectory.dir("src/main/resources/db/migration")
|
||||||
val jtwSourceDir = layout.projectDirectory.dir("src/main/kte")
|
|
||||||
val jteOutputDir = generatedResourcesDir.get().dir("jte")
|
|
||||||
val jooqOutputDir = generatedSourcesDir.get().dir("jooq")
|
val jooqOutputDir = generatedSourcesDir.get().dir("jooq")
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
resources.srcDir(jteOutputDir)
|
|
||||||
kotlin.srcDir(jooqOutputDir)
|
kotlin.srcDir(jooqOutputDir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +82,7 @@ dependencies {
|
||||||
implementation(libs.dotenv)
|
implementation(libs.dotenv)
|
||||||
|
|
||||||
// Templating
|
// Templating
|
||||||
implementation(libs.jte.kotlin)
|
implementation(libs.htmlflow.kotlin)
|
||||||
|
|
||||||
// Database
|
// Database
|
||||||
implementation(libs.bundles.database)
|
implementation(libs.bundles.database)
|
||||||
|
|
@ -117,27 +110,6 @@ buildscript {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====================================================================================================
|
|
||||||
// JTE TEMPLATE GENERATION
|
|
||||||
// ====================================================================================================
|
|
||||||
|
|
||||||
jte {
|
|
||||||
sourceDirectory.set(Path(jtwSourceDir.asFile.absolutePath))
|
|
||||||
targetDirectory.set(Path(jteOutputDir.asFile.absolutePath))
|
|
||||||
precompile()
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named("precompileJte") {
|
|
||||||
dependsOn("compileKotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register("genJte") {
|
|
||||||
group = "codegen"
|
|
||||||
description = "Precompile jte template into classes"
|
|
||||||
|
|
||||||
dependsOn("precompileJte")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================================================================================================
|
// ====================================================================================================
|
||||||
// JOOQ CODE GENERATION FROM SQL FILES
|
// JOOQ CODE GENERATION FROM SQL FILES
|
||||||
// ====================================================================================================
|
// ====================================================================================================
|
||||||
|
|
@ -263,9 +235,7 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||||
attributes("Main-Class" to "at.dokkae.homepage.HomepageKt")
|
attributes("Main-Class" to "at.dokkae.homepage.HomepageKt")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependsOn("genJte", "genJooq")
|
dependsOn("genJooq")
|
||||||
|
|
||||||
from(jteOutputDir)
|
|
||||||
|
|
||||||
archiveFileName.set("app.jar")
|
archiveFileName.set("app.jar")
|
||||||
|
|
||||||
|
|
@ -296,7 +266,6 @@ tasks.register("cleanGenerated") {
|
||||||
description = "Clean all generated code"
|
description = "Clean all generated code"
|
||||||
|
|
||||||
doLast {
|
doLast {
|
||||||
delete(generatedResourcesDir)
|
|
||||||
delete(generatedSourcesDir)
|
delete(generatedSourcesDir)
|
||||||
logger.lifecycle("✓ Cleaned generated code directories")
|
logger.lifecycle("✓ Cleaned generated code directories")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,35 +0,0 @@
|
||||||
@file:Suppress("ktlint")
|
|
||||||
package gg.jte.generated.precompiled
|
|
||||||
import at.dokkae.homepage.templates.IndexTemplate
|
|
||||||
import at.dokkae.homepage.templates.MessageTemplate
|
|
||||||
import gg.jte.support.ForSupport
|
|
||||||
@Suppress("UNCHECKED_CAST", "UNUSED_PARAMETER")
|
|
||||||
class JteIndexGenerated {
|
|
||||||
companion object {
|
|
||||||
@JvmField val JTE_NAME = "Index.kte"
|
|
||||||
@JvmField val JTE_LINE_INFO = intArrayOf(0,0,0,1,2,4,4,4,4,4,18,18,37,58,88,93,96,96,97,97,98,98,102,108,119,132,146,161,161,161,4,4,4,4,4)
|
|
||||||
@JvmStatic fun render(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, model:IndexTemplate) {
|
|
||||||
jteOutput.writeContent("\n<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <title>Dokkae's Chat</title>\n\n <script src=\"https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js\" integrity=\"sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz\" crossorigin=\"anonymous\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/htmx-ext-sse@2.2.4\" integrity=\"sha384-A986SAtodyH8eg8x8irJnYUk7i9inVQqYigD6qZ9evobksGNIXfeFvDwLSHcp31N\" crossorigin=\"anonymous\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\"></script>\n\n <style>\n ")
|
|
||||||
jteOutput.writeContent("\n .scrollbar-custom::-webkit-scrollbar {\n width: 8px;\n }\n\n .scrollbar-custom::-webkit-scrollbar-track {\n background: #1a1a1a;\n border-radius: 4px;\n }\n\n .scrollbar-custom::-webkit-scrollbar-thumb {\n background: #444;\n border-radius: 4px;\n }\n\n .scrollbar-custom::-webkit-scrollbar-thumb:hover {\n background: #555;\n }\n\n ")
|
|
||||||
jteOutput.writeContent("\n @keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .animate-slide-in.htmx-added {\n opacity: 0;\n }\n\n .animate-slide-in {\n opacity: 1;\n animation: slideIn 0.3s ease-out;\n }\n\n ")
|
|
||||||
jteOutput.writeContent("\n .message-border-red {\n background-color: #ffb3ba !important;\n }\n\n .message-border-orange {\n background-color: #ffdfba !important;\n }\n\n .message-border-yellow {\n background-color: #ffffba !important;\n }\n\n .message-border-green {\n background-color: #baffc9 !important;\n }\n\n .message-border-blue {\n background-color: #bae1ff !important;\n }\n\n .message-border-pink {\n background-color: #fddfdf !important;\n }\n\n\n </style>\n</head>\n<body hx-ext=\"sse\" class=\"bg-neutral-900 text-neutral-100 min-h-screen overflow-hidden\">\n<main class=\"flex flex-col h-screen max-w-6xl mx-auto px-4 md:px-6\">\n ")
|
|
||||||
jteOutput.writeContent("\n <header class=\"py-5 border-b border-neutral-800 shrink-0\">\n <h1 class=\"text-xl md:text-2xl font-bold text-white\">Dokkae's Chat</h1>\n </header>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <div id=\"messages-container\" class=\"flex-1 flex flex-col-reverse overflow-y-auto overflow-x-hidden scrollbar-custom py-4\">\n <div id=\"messages\" class=\"flex flex-col-reverse\" sse-connect=\"/message-events\" sse-swap=\"message\" hx-swap=\"afterbegin\">\n ")
|
|
||||||
for (message in model.messages) {
|
|
||||||
jteOutput.writeContent("\n ")
|
|
||||||
gg.jte.generated.precompiled.partials.JteMessageGenerated.render(jteOutput, jteHtmlInterceptor, MessageTemplate(message));
|
|
||||||
jteOutput.writeContent("\n ")
|
|
||||||
}
|
|
||||||
jteOutput.writeContent("\n </div>\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <form class=\"bg-neutral-800/50 border border-neutral-700 rounded-lg p-4 mb-4 mt-2 shrink-0\"\n hx-post=\"/messages\"\n hx-swap=\"none\"\n hx-on::after-request=\"if(event.detail.successful)document.getElementById('message-input').value = ''\">\n <div class=\"flex flex-col md:flex-row gap-3\">\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"flex-1 md:flex-none md:w-48\">\n <div class=\"relative\">\n <input id=\"username-input\"\n type=\"text\"\n name=\"author\"\n placeholder=\"Name (optional)\"\n class=\"w-full bg-neutral-800 border border-neutral-700 rounded-lg py-3 px-4 text-neutral-100 placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition\">\n </div>\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"flex-1\">\n <div class=\"flex flex-row gap-3\">\n <div class=\"relative flex-1\">\n <input id=\"message-input\"\n type=\"text\"\n name=\"message\"\n placeholder=\"Your message...\"\n required\n autocomplete=\"off\"\n class=\"w-full bg-neutral-800 border border-neutral-700 rounded-lg py-3 px-4 text-neutral-100 placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition\">\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <button type=\"submit\"\n class=\"bg-rose-200 hover:bg-rose-300 text-black font-semibold py-3 px-6 rounded-lg transition duration-200 flex items-center justify-center gap-2\">\n <svg width=\"24px\" height=\"24px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"Communication / Paper_Plane\">\n <path id=\"Vector\" d=\"M10.3078 13.6923L15.1539 8.84619M20.1113 5.88867L16.0207 19.1833C15.6541 20.3747 15.4706 20.9707 15.1544 21.1683C14.8802 21.3396 14.5406 21.3683 14.2419 21.2443C13.8975 21.1014 13.618 20.5433 13.0603 19.428L10.4694 14.2461C10.3809 14.0691 10.3366 13.981 10.2775 13.9043C10.225 13.8363 10.1645 13.7749 10.0965 13.7225C10.0215 13.6647 9.93486 13.6214 9.76577 13.5369L4.57192 10.9399C3.45662 10.3823 2.89892 10.1032 2.75601 9.75879C2.63207 9.4601 2.66033 9.12023 2.83169 8.84597C3.02928 8.52974 3.62523 8.34603 4.81704 7.97932L18.1116 3.88867C19.0486 3.60038 19.5173 3.45635 19.8337 3.57253C20.1094 3.67373 20.3267 3.89084 20.4279 4.16651C20.544 4.48283 20.3999 4.95126 20.1119 5.88729L20.1113 5.88867Z\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n </svg>\n </button>\n </div>\n </div>\n </div>\n </form>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <footer class=\"border-t border-neutral-800 py-4 shrink-0\">\n <p class=\"text-sm text-neutral-500 text-center\">\n No auth — anyone can post. Open source at\n <a href=\"https://github.com/dokkae6949/homepage\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-blue-400 hover:text-blue-300 hover:underline transition\">\n dokkae6949/homepage\n </a>\n </p>\n </footer>\n</main>\n\n</body>\n</html>")
|
|
||||||
}
|
|
||||||
@JvmStatic fun renderMap(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, params:Map<String, Any?>) {
|
|
||||||
val model = params["model"] as IndexTemplate
|
|
||||||
render(jteOutput, jteHtmlInterceptor, model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,46 +0,0 @@
|
||||||
@file:Suppress("ktlint")
|
|
||||||
package gg.jte.generated.precompiled.partials
|
|
||||||
import at.dokkae.homepage.templates.MessageTemplate
|
|
||||||
import java.time.Instant
|
|
||||||
import java.time.ZoneId
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
import kotlin.math.absoluteValue
|
|
||||||
@Suppress("UNCHECKED_CAST", "UNUSED_PARAMETER")
|
|
||||||
class JteMessageGenerated {
|
|
||||||
companion object {
|
|
||||||
@JvmField val JTE_NAME = "partials/Message.kte"
|
|
||||||
@JvmField val JTE_LINE_INFO = intArrayOf(0,0,0,1,2,3,4,6,6,6,6,6,8,8,8,9,9,10,10,14,15,15,15,15,18,21,21,21,24,24,24,24,24,24,28,30,30,30,34,34,34,6,6,6,6,6)
|
|
||||||
@JvmStatic fun render(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, model:MessageTemplate) {
|
|
||||||
jteOutput.writeContent("\n")
|
|
||||||
val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy").withZone(ZoneId.systemDefault())
|
|
||||||
jteOutput.writeContent("\n")
|
|
||||||
val timeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault())
|
|
||||||
jteOutput.writeContent("\n")
|
|
||||||
val borderColors = listOf("red", "orange", "yellow", "green", "blue", "pink" )
|
|
||||||
jteOutput.writeContent("\n\n<div class=\"message-group mb-3 animate-slide-in\">\n <div class=\"flex relative px-3 py-1 hover:bg-neutral-800/30 rounded transition-colors\">\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"absolute left-0 top-1/2 -translate-y-1/2 w-1 h-3/4 rounded-r message-border-")
|
|
||||||
jteOutput.setContext("div", "class")
|
|
||||||
jteOutput.writeUserContent(borderColors[model.message.id.hashCode().absoluteValue % borderColors.size])
|
|
||||||
jteOutput.setContext("div", null)
|
|
||||||
jteOutput.writeContent("\"></div>\n\n <div class=\"flex-1 pl-3 text-ellipsis text-wrap break-all\">\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"flex flex-wrap items-baseline gap-2 mb-1\">\n <span class=\"font-semibold text-white\">\n ")
|
|
||||||
jteOutput.setContext("span", null)
|
|
||||||
jteOutput.writeUserContent(model.message.author)
|
|
||||||
jteOutput.writeContent("\n </span>\n <span class=\"text-xs text-neutral-400\">\n ")
|
|
||||||
jteOutput.setContext("span", null)
|
|
||||||
jteOutput.writeUserContent(dateFormatter.format(model.message.createdAt))
|
|
||||||
jteOutput.writeContent(" • ")
|
|
||||||
jteOutput.setContext("span", null)
|
|
||||||
jteOutput.writeUserContent(timeFormatter.format(model.message.createdAt))
|
|
||||||
jteOutput.writeContent("\n </span>\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"text-neutral-200\">\n ")
|
|
||||||
jteOutput.setContext("div", null)
|
|
||||||
jteOutput.writeUserContent(model.message.content)
|
|
||||||
jteOutput.writeContent("\n </div>\n </div>\n </div>\n</div>")
|
|
||||||
}
|
|
||||||
@JvmStatic fun renderMap(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, params:Map<String, Any?>) {
|
|
||||||
val model = params["model"] as MessageTemplate
|
|
||||||
render(jteOutput, jteHtmlInterceptor, model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq
|
|
||||||
|
|
||||||
|
|
||||||
import kotlin.collections.List
|
|
||||||
|
|
||||||
import org.jooq.Constants
|
|
||||||
import org.jooq.Schema
|
|
||||||
import org.jooq.impl.CatalogImpl
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
@Suppress("warnings")
|
|
||||||
open class DefaultCatalog : CatalogImpl("") {
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reference instance of <code>DEFAULT_CATALOG</code>
|
|
||||||
*/
|
|
||||||
val DEFAULT_CATALOG: DefaultCatalog = DefaultCatalog()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* standard public schema
|
|
||||||
*/
|
|
||||||
val PUBLIC: Public get(): Public = Public.PUBLIC
|
|
||||||
|
|
||||||
override fun getSchemas(): List<Schema> = listOf(
|
|
||||||
Public.PUBLIC
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A reference to the 3.20 minor release of the code generator. If this
|
|
||||||
* doesn't compile, it's because the runtime library uses an older minor
|
|
||||||
* release, namely: 3.20. You can turn off the generation of this reference
|
|
||||||
* by specifying /configuration/generator/generate/jooqVersionReference
|
|
||||||
*/
|
|
||||||
private val REQUIRE_RUNTIME_JOOQ_VERSION = Constants.VERSION_3_20
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq
|
|
||||||
|
|
||||||
|
|
||||||
import at.dokkae.homepage.generated.jooq.tables.Message
|
|
||||||
|
|
||||||
import kotlin.collections.List
|
|
||||||
|
|
||||||
import org.jooq.Catalog
|
|
||||||
import org.jooq.Table
|
|
||||||
import org.jooq.impl.DSL
|
|
||||||
import org.jooq.impl.SchemaImpl
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* standard public schema
|
|
||||||
*/
|
|
||||||
@Suppress("warnings")
|
|
||||||
open class Public : SchemaImpl(DSL.name("public"), DefaultCatalog.DEFAULT_CATALOG, DSL.comment("standard public schema")) {
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reference instance of <code>public</code>
|
|
||||||
*/
|
|
||||||
val PUBLIC: Public = Public()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The table <code>public.message</code>.
|
|
||||||
*/
|
|
||||||
val MESSAGE: Message get() = Message.MESSAGE
|
|
||||||
|
|
||||||
override fun getCatalog(): Catalog = DefaultCatalog.DEFAULT_CATALOG
|
|
||||||
|
|
||||||
override fun getTables(): List<Table<*>> = listOf(
|
|
||||||
Message.MESSAGE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
@file:Suppress("warnings")
|
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq.keys
|
|
||||||
|
|
||||||
|
|
||||||
import at.dokkae.homepage.generated.jooq.tables.Message
|
|
||||||
import at.dokkae.homepage.generated.jooq.tables.records.MessageRecord
|
|
||||||
|
|
||||||
import org.jooq.UniqueKey
|
|
||||||
import org.jooq.impl.DSL
|
|
||||||
import org.jooq.impl.Internal
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
// UNIQUE and PRIMARY KEY definitions
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
val MESSAGE_PKEY: UniqueKey<MessageRecord> = Internal.createUniqueKey(Message.MESSAGE, DSL.name("message_pkey"), arrayOf(Message.MESSAGE.ID), true)
|
|
||||||
|
|
@ -1,187 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq.tables
|
|
||||||
|
|
||||||
|
|
||||||
import at.dokkae.homepage.generated.jooq.Public
|
|
||||||
import at.dokkae.homepage.generated.jooq.keys.MESSAGE_PKEY
|
|
||||||
import at.dokkae.homepage.generated.jooq.tables.records.MessageRecord
|
|
||||||
|
|
||||||
import java.time.OffsetDateTime
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
import kotlin.collections.Collection
|
|
||||||
|
|
||||||
import org.jooq.Condition
|
|
||||||
import org.jooq.Field
|
|
||||||
import org.jooq.ForeignKey
|
|
||||||
import org.jooq.InverseForeignKey
|
|
||||||
import org.jooq.Name
|
|
||||||
import org.jooq.PlainSQL
|
|
||||||
import org.jooq.QueryPart
|
|
||||||
import org.jooq.Record
|
|
||||||
import org.jooq.SQL
|
|
||||||
import org.jooq.Schema
|
|
||||||
import org.jooq.Select
|
|
||||||
import org.jooq.Stringly
|
|
||||||
import org.jooq.Table
|
|
||||||
import org.jooq.TableField
|
|
||||||
import org.jooq.TableOptions
|
|
||||||
import org.jooq.UniqueKey
|
|
||||||
import org.jooq.impl.DSL
|
|
||||||
import org.jooq.impl.SQLDataType
|
|
||||||
import org.jooq.impl.TableImpl
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
@Suppress("warnings")
|
|
||||||
open class Message(
|
|
||||||
alias: Name,
|
|
||||||
path: Table<out Record>?,
|
|
||||||
childPath: ForeignKey<out Record, MessageRecord>?,
|
|
||||||
parentPath: InverseForeignKey<out Record, MessageRecord>?,
|
|
||||||
aliased: Table<MessageRecord>?,
|
|
||||||
parameters: Array<Field<*>?>?,
|
|
||||||
where: Condition?
|
|
||||||
): TableImpl<MessageRecord>(
|
|
||||||
alias,
|
|
||||||
Public.PUBLIC,
|
|
||||||
path,
|
|
||||||
childPath,
|
|
||||||
parentPath,
|
|
||||||
aliased,
|
|
||||||
parameters,
|
|
||||||
DSL.comment(""),
|
|
||||||
TableOptions.table(),
|
|
||||||
where,
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reference instance of <code>public.message</code>
|
|
||||||
*/
|
|
||||||
val MESSAGE: Message = Message()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The class holding records for this type
|
|
||||||
*/
|
|
||||||
override fun getRecordType(): Class<MessageRecord> = MessageRecord::class.java
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The column <code>public.message.id</code>.
|
|
||||||
*/
|
|
||||||
val ID: TableField<MessageRecord, UUID?> = createField(DSL.name("id"), SQLDataType.UUID.nullable(false), this, "")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The column <code>public.message.author</code>.
|
|
||||||
*/
|
|
||||||
val AUTHOR: TableField<MessageRecord, String?> = createField(DSL.name("author"), SQLDataType.VARCHAR(31).nullable(false), this, "")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The column <code>public.message.content</code>.
|
|
||||||
*/
|
|
||||||
val CONTENT: TableField<MessageRecord, String?> = createField(DSL.name("content"), SQLDataType.VARCHAR(255).nullable(false), this, "")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The column <code>public.message.created_at</code>.
|
|
||||||
*/
|
|
||||||
val CREATED_AT: TableField<MessageRecord, OffsetDateTime?> = createField(DSL.name("created_at"), SQLDataType.TIMESTAMPWITHTIMEZONE(6).nullable(false).defaultValue(DSL.field(DSL.raw("CURRENT_TIMESTAMP"), SQLDataType.TIMESTAMPWITHTIMEZONE)), this, "")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The column <code>public.message.updated_at</code>.
|
|
||||||
*/
|
|
||||||
val UPDATED_AT: TableField<MessageRecord, OffsetDateTime?> = createField(DSL.name("updated_at"), SQLDataType.TIMESTAMPWITHTIMEZONE(6), this, "")
|
|
||||||
|
|
||||||
private constructor(alias: Name, aliased: Table<MessageRecord>?): this(alias, null, null, null, aliased, null, null)
|
|
||||||
private constructor(alias: Name, aliased: Table<MessageRecord>?, parameters: Array<Field<*>?>?): this(alias, null, null, null, aliased, parameters, null)
|
|
||||||
private constructor(alias: Name, aliased: Table<MessageRecord>?, where: Condition?): this(alias, null, null, null, aliased, null, where)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an aliased <code>public.message</code> table reference
|
|
||||||
*/
|
|
||||||
constructor(alias: String): this(DSL.name(alias))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an aliased <code>public.message</code> table reference
|
|
||||||
*/
|
|
||||||
constructor(alias: Name): this(alias, null)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a <code>public.message</code> table reference
|
|
||||||
*/
|
|
||||||
constructor(): this(DSL.name("message"), null)
|
|
||||||
override fun getSchema(): Schema? = if (aliased()) null else Public.PUBLIC
|
|
||||||
override fun getPrimaryKey(): UniqueKey<MessageRecord> = MESSAGE_PKEY
|
|
||||||
override fun `as`(alias: String): Message = Message(DSL.name(alias), this)
|
|
||||||
override fun `as`(alias: Name): Message = Message(alias, this)
|
|
||||||
override fun `as`(alias: Table<*>): Message = Message(alias.qualifiedName, this)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rename this table
|
|
||||||
*/
|
|
||||||
override fun rename(name: String): Message = Message(DSL.name(name), null)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rename this table
|
|
||||||
*/
|
|
||||||
override fun rename(name: Name): Message = Message(name, null)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rename this table
|
|
||||||
*/
|
|
||||||
override fun rename(name: Table<*>): Message = Message(name.qualifiedName, null)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
override fun where(condition: Condition?): Message = Message(qualifiedName, if (aliased()) this else null, condition)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
override fun where(conditions: Collection<Condition>): Message = where(DSL.and(conditions))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
override fun where(vararg conditions: Condition?): Message = where(DSL.and(*conditions))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
override fun where(condition: Field<Boolean?>?): Message = where(DSL.condition(condition))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
@PlainSQL override fun where(condition: SQL): Message = where(DSL.condition(condition))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
@PlainSQL override fun where(@Stringly.SQL condition: String): Message = where(DSL.condition(condition))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
@PlainSQL override fun where(@Stringly.SQL condition: String, vararg binds: Any?): Message = where(DSL.condition(condition, *binds))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
@PlainSQL override fun where(@Stringly.SQL condition: String, vararg parts: QueryPart): Message = where(DSL.condition(condition, *parts))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
override fun whereExists(select: Select<*>): Message = where(DSL.exists(select))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an inline derived table from this table
|
|
||||||
*/
|
|
||||||
override fun whereNotExists(select: Select<*>): Message = where(DSL.notExists(select))
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq.tables.pojos
|
|
||||||
|
|
||||||
|
|
||||||
import java.io.Serializable
|
|
||||||
import java.time.OffsetDateTime
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
@Suppress("warnings")
|
|
||||||
data class Message(
|
|
||||||
val id: UUID,
|
|
||||||
val author: String,
|
|
||||||
val content: String,
|
|
||||||
val createdAt: OffsetDateTime? = null,
|
|
||||||
val updatedAt: OffsetDateTime? = null
|
|
||||||
): Serializable {
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other)
|
|
||||||
return true
|
|
||||||
if (other == null)
|
|
||||||
return false
|
|
||||||
if (this::class != other::class)
|
|
||||||
return false
|
|
||||||
val o: Message = other as Message
|
|
||||||
if (this.id != o.id)
|
|
||||||
return false
|
|
||||||
if (this.author != o.author)
|
|
||||||
return false
|
|
||||||
if (this.content != o.content)
|
|
||||||
return false
|
|
||||||
if (this.createdAt == null) {
|
|
||||||
if (o.createdAt != null)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
else if (this.createdAt != o.createdAt)
|
|
||||||
return false
|
|
||||||
if (this.updatedAt == null) {
|
|
||||||
if (o.updatedAt != null)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
else if (this.updatedAt != o.updatedAt)
|
|
||||||
return false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
val prime = 31
|
|
||||||
var result = 1
|
|
||||||
result = prime * result + this.id.hashCode()
|
|
||||||
result = prime * result + this.author.hashCode()
|
|
||||||
result = prime * result + this.content.hashCode()
|
|
||||||
result = prime * result + (if (this.createdAt == null) 0 else this.createdAt.hashCode())
|
|
||||||
result = prime * result + (if (this.updatedAt == null) 0 else this.updatedAt.hashCode())
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
val sb = StringBuilder("Message (")
|
|
||||||
|
|
||||||
sb.append(id)
|
|
||||||
sb.append(", ").append(author)
|
|
||||||
sb.append(", ").append(content)
|
|
||||||
sb.append(", ").append(createdAt)
|
|
||||||
sb.append(", ").append(updatedAt)
|
|
||||||
|
|
||||||
sb.append(")")
|
|
||||||
return sb.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq.tables.records
|
|
||||||
|
|
||||||
|
|
||||||
import at.dokkae.homepage.generated.jooq.tables.Message
|
|
||||||
|
|
||||||
import java.time.OffsetDateTime
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
import org.jooq.Record1
|
|
||||||
import org.jooq.impl.UpdatableRecordImpl
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
@Suppress("warnings")
|
|
||||||
open class MessageRecord private constructor() : UpdatableRecordImpl<MessageRecord>(Message.MESSAGE) {
|
|
||||||
|
|
||||||
open var id: UUID
|
|
||||||
set(value): Unit = set(0, value)
|
|
||||||
get(): UUID = get(0) as UUID
|
|
||||||
|
|
||||||
open var author: String
|
|
||||||
set(value): Unit = set(1, value)
|
|
||||||
get(): String = get(1) as String
|
|
||||||
|
|
||||||
open var content: String
|
|
||||||
set(value): Unit = set(2, value)
|
|
||||||
get(): String = get(2) as String
|
|
||||||
|
|
||||||
open var createdAt: OffsetDateTime?
|
|
||||||
set(value): Unit = set(3, value)
|
|
||||||
get(): OffsetDateTime? = get(3) as OffsetDateTime?
|
|
||||||
|
|
||||||
open var updatedAt: OffsetDateTime?
|
|
||||||
set(value): Unit = set(4, value)
|
|
||||||
get(): OffsetDateTime? = get(4) as OffsetDateTime?
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
// Primary key information
|
|
||||||
// -------------------------------------------------------------------------
|
|
||||||
|
|
||||||
override fun key(): Record1<UUID?> = super.key() as Record1<UUID?>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a detached, initialised MessageRecord
|
|
||||||
*/
|
|
||||||
constructor(id: UUID, author: String, content: String, createdAt: OffsetDateTime? = null, updatedAt: OffsetDateTime? = null): this() {
|
|
||||||
this.id = id
|
|
||||||
this.author = author
|
|
||||||
this.content = content
|
|
||||||
this.createdAt = createdAt
|
|
||||||
this.updatedAt = updatedAt
|
|
||||||
resetTouchedOnNotNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a detached, initialised MessageRecord
|
|
||||||
*/
|
|
||||||
constructor(value: at.dokkae.homepage.generated.jooq.tables.pojos.Message?): this() {
|
|
||||||
if (value != null) {
|
|
||||||
this.id = value.id
|
|
||||||
this.author = value.author
|
|
||||||
this.content = value.content
|
|
||||||
this.createdAt = value.createdAt
|
|
||||||
this.updatedAt = value.updatedAt
|
|
||||||
resetTouchedOnNotNull()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
@file:Suppress("warnings")
|
|
||||||
/*
|
|
||||||
* This file is generated by jOOQ.
|
|
||||||
*/
|
|
||||||
package at.dokkae.homepage.generated.jooq.tables.references
|
|
||||||
|
|
||||||
|
|
||||||
import at.dokkae.homepage.generated.jooq.tables.Message
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The table <code>public.message</code>.
|
|
||||||
*/
|
|
||||||
val MESSAGE: Message = Message.MESSAGE
|
|
||||||
|
|
@ -4,7 +4,7 @@ shadow = "9.3.0"
|
||||||
dotenv-plugin = "1.1.3"
|
dotenv-plugin = "1.1.3"
|
||||||
dotenv = "6.5.1"
|
dotenv = "6.5.1"
|
||||||
http4k = "6.23.1.0"
|
http4k = "6.23.1.0"
|
||||||
jte = "3.2.1"
|
htmlflow = "5.0.1"
|
||||||
flyway = "11.19.0"
|
flyway = "11.19.0"
|
||||||
jooq = "3.20.10"
|
jooq = "3.20.10"
|
||||||
junit = "6.0.0"
|
junit = "6.0.0"
|
||||||
|
|
@ -15,7 +15,6 @@ tasktree = "4.0.1"
|
||||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||||
dotenv-plugin = { id = "io.github.klahap.dotenv", version.ref = "dotenv-plugin" }
|
dotenv-plugin = { id = "io.github.klahap.dotenv", version.ref = "dotenv-plugin" }
|
||||||
jte = { id = "gg.jte.gradle", version.ref = "jte" }
|
|
||||||
jooq-codegen-gradle = { id = "org.jooq.jooq-codegen-gradle", version.ref = "jooq" }
|
jooq-codegen-gradle = { id = "org.jooq.jooq-codegen-gradle", version.ref = "jooq" }
|
||||||
tasktree = { id = "com.dorongold.task-tree", version.ref = "tasktree" }
|
tasktree = { id = "com.dorongold.task-tree", version.ref = "tasktree" }
|
||||||
flyway = { id = "org.flywaydb.flyway", version.ref = "flyway" }
|
flyway = { id = "org.flywaydb.flyway", version.ref = "flyway" }
|
||||||
|
|
@ -25,7 +24,6 @@ http4k = [
|
||||||
"http4k-client-okhttp",
|
"http4k-client-okhttp",
|
||||||
"http4k-core",
|
"http4k-core",
|
||||||
"http4k-server-jetty",
|
"http4k-server-jetty",
|
||||||
"http4k-template-jte",
|
|
||||||
"http4k-web-htmx"
|
"http4k-web-htmx"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -54,11 +52,10 @@ http4k-bom = { module = "org.http4k:http4k-bom", version.ref = "http4k" }
|
||||||
http4k-client-okhttp = { module = "org.http4k:http4k-client-okhttp" }
|
http4k-client-okhttp = { module = "org.http4k:http4k-client-okhttp" }
|
||||||
http4k-core = { module = "org.http4k:http4k-core" }
|
http4k-core = { module = "org.http4k:http4k-core" }
|
||||||
http4k-server-jetty = { module = "org.http4k:http4k-server-jetty" }
|
http4k-server-jetty = { module = "org.http4k:http4k-server-jetty" }
|
||||||
http4k-template-jte = { module = "org.http4k:http4k-template-jte" }
|
|
||||||
http4k-web-htmx = { module = "org.http4k:http4k-web-htmx" }
|
http4k-web-htmx = { module = "org.http4k:http4k-web-htmx" }
|
||||||
|
|
||||||
# JTE Templating
|
# HTML Templating
|
||||||
jte-kotlin = { module = "gg.jte:jte-kotlin", version.ref = "jte" }
|
htmlflow-kotlin = { module = "com.github.xmlet:htmlflow-kotlin", version.ref = "htmlflow" }
|
||||||
|
|
||||||
# Database Driver
|
# Database Driver
|
||||||
postgresql = { module = "org.postgresql:postgresql", version.ref = "postgresql" }
|
postgresql = { module = "org.postgresql:postgresql", version.ref = "postgresql" }
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,35 +0,0 @@
|
||||||
@file:Suppress("ktlint")
|
|
||||||
package gg.jte.generated.ondemand
|
|
||||||
import at.dokkae.homepage.templates.IndexTemplate
|
|
||||||
import at.dokkae.homepage.templates.MessageTemplate
|
|
||||||
import gg.jte.support.ForSupport
|
|
||||||
@Suppress("UNCHECKED_CAST", "UNUSED_PARAMETER")
|
|
||||||
class JteIndexGenerated {
|
|
||||||
companion object {
|
|
||||||
@JvmField val JTE_NAME = "Index.kte"
|
|
||||||
@JvmField val JTE_LINE_INFO = intArrayOf(0,0,0,1,2,4,4,4,4,4,18,18,37,58,88,93,96,96,97,97,98,98,102,108,119,132,146,161,161,161,4,4,4,4,4)
|
|
||||||
@JvmStatic fun render(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, model:IndexTemplate) {
|
|
||||||
jteOutput.writeContent("\n<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <title>Dokkae's Chat</title>\n\n <script src=\"https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js\" integrity=\"sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz\" crossorigin=\"anonymous\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/htmx-ext-sse@2.2.4\" integrity=\"sha384-A986SAtodyH8eg8x8irJnYUk7i9inVQqYigD6qZ9evobksGNIXfeFvDwLSHcp31N\" crossorigin=\"anonymous\"></script>\n <script src=\"https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4\"></script>\n\n <style>\n ")
|
|
||||||
jteOutput.writeContent("\n .scrollbar-custom::-webkit-scrollbar {\n width: 8px;\n }\n\n .scrollbar-custom::-webkit-scrollbar-track {\n background: #1a1a1a;\n border-radius: 4px;\n }\n\n .scrollbar-custom::-webkit-scrollbar-thumb {\n background: #444;\n border-radius: 4px;\n }\n\n .scrollbar-custom::-webkit-scrollbar-thumb:hover {\n background: #555;\n }\n\n ")
|
|
||||||
jteOutput.writeContent("\n @keyframes slideIn {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .animate-slide-in.htmx-added {\n opacity: 0;\n }\n\n .animate-slide-in {\n opacity: 1;\n animation: slideIn 0.3s ease-out;\n }\n\n ")
|
|
||||||
jteOutput.writeContent("\n .message-border-red {\n background-color: #ffb3ba !important;\n }\n\n .message-border-orange {\n background-color: #ffdfba !important;\n }\n\n .message-border-yellow {\n background-color: #ffffba !important;\n }\n\n .message-border-green {\n background-color: #baffc9 !important;\n }\n\n .message-border-blue {\n background-color: #bae1ff !important;\n }\n\n .message-border-pink {\n background-color: #fddfdf !important;\n }\n\n\n </style>\n</head>\n<body hx-ext=\"sse\" class=\"bg-neutral-900 text-neutral-100 min-h-screen overflow-hidden\">\n<main class=\"flex flex-col h-screen max-w-6xl mx-auto px-4 md:px-6\">\n ")
|
|
||||||
jteOutput.writeContent("\n <header class=\"py-5 border-b border-neutral-800 shrink-0\">\n <h1 class=\"text-xl md:text-2xl font-bold text-white\">Dokkae's Chat</h1>\n </header>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <div id=\"messages-container\" class=\"flex-1 flex flex-col-reverse overflow-y-auto overflow-x-hidden scrollbar-custom py-4\">\n <div id=\"messages\" class=\"flex flex-col-reverse\" sse-connect=\"/message-events\" sse-swap=\"message\" hx-swap=\"afterbegin\">\n ")
|
|
||||||
for (message in model.messages) {
|
|
||||||
jteOutput.writeContent("\n ")
|
|
||||||
gg.jte.generated.ondemand.partials.JteMessageGenerated.render(jteOutput, jteHtmlInterceptor, MessageTemplate(message));
|
|
||||||
jteOutput.writeContent("\n ")
|
|
||||||
}
|
|
||||||
jteOutput.writeContent("\n </div>\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <form class=\"bg-neutral-800/50 border border-neutral-700 rounded-lg p-4 mb-4 mt-2 shrink-0\"\n hx-post=\"/messages\"\n hx-swap=\"none\"\n hx-on::after-request=\"if(event.detail.successful)document.getElementById('message-input').value = ''\">\n <div class=\"flex flex-col md:flex-row gap-3\">\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"flex-1 md:flex-none md:w-48\">\n <div class=\"relative\">\n <input id=\"username-input\"\n type=\"text\"\n name=\"author\"\n placeholder=\"Name (optional)\"\n class=\"w-full bg-neutral-800 border border-neutral-700 rounded-lg py-3 px-4 text-neutral-100 placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition\">\n </div>\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"flex-1\">\n <div class=\"flex flex-row gap-3\">\n <div class=\"relative flex-1\">\n <input id=\"message-input\"\n type=\"text\"\n name=\"message\"\n placeholder=\"Your message...\"\n required\n autocomplete=\"off\"\n class=\"w-full bg-neutral-800 border border-neutral-700 rounded-lg py-3 px-4 text-neutral-100 placeholder-neutral-500 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition\">\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <button type=\"submit\"\n class=\"bg-rose-200 hover:bg-rose-300 text-black font-semibold py-3 px-6 rounded-lg transition duration-200 flex items-center justify-center gap-2\">\n <svg width=\"24px\" height=\"24px\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g id=\"Communication / Paper_Plane\">\n <path id=\"Vector\" d=\"M10.3078 13.6923L15.1539 8.84619M20.1113 5.88867L16.0207 19.1833C15.6541 20.3747 15.4706 20.9707 15.1544 21.1683C14.8802 21.3396 14.5406 21.3683 14.2419 21.2443C13.8975 21.1014 13.618 20.5433 13.0603 19.428L10.4694 14.2461C10.3809 14.0691 10.3366 13.981 10.2775 13.9043C10.225 13.8363 10.1645 13.7749 10.0965 13.7225C10.0215 13.6647 9.93486 13.6214 9.76577 13.5369L4.57192 10.9399C3.45662 10.3823 2.89892 10.1032 2.75601 9.75879C2.63207 9.4601 2.66033 9.12023 2.83169 8.84597C3.02928 8.52974 3.62523 8.34603 4.81704 7.97932L18.1116 3.88867C19.0486 3.60038 19.5173 3.45635 19.8337 3.57253C20.1094 3.67373 20.3267 3.89084 20.4279 4.16651C20.544 4.48283 20.3999 4.95126 20.1119 5.88729L20.1113 5.88867Z\" stroke=\"#000000\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n </svg>\n </button>\n </div>\n </div>\n </div>\n </form>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <footer class=\"border-t border-neutral-800 py-4 shrink-0\">\n <p class=\"text-sm text-neutral-500 text-center\">\n No auth — anyone can post. Open source at\n <a href=\"https://github.com/dokkae6949/homepage\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n class=\"text-blue-400 hover:text-blue-300 hover:underline transition\">\n dokkae6949/homepage\n </a>\n </p>\n </footer>\n</main>\n\n</body>\n</html>")
|
|
||||||
}
|
|
||||||
@JvmStatic fun renderMap(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, params:Map<String, Any?>) {
|
|
||||||
val model = params["model"] as IndexTemplate
|
|
||||||
render(jteOutput, jteHtmlInterceptor, model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
@file:Suppress("ktlint")
|
|
||||||
package gg.jte.generated.ondemand.partials
|
|
||||||
import at.dokkae.homepage.templates.MessageTemplate
|
|
||||||
import java.time.Instant
|
|
||||||
import java.time.ZoneId
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
import kotlin.math.absoluteValue
|
|
||||||
@Suppress("UNCHECKED_CAST", "UNUSED_PARAMETER")
|
|
||||||
class JteMessageGenerated {
|
|
||||||
companion object {
|
|
||||||
@JvmField val JTE_NAME = "partials/Message.kte"
|
|
||||||
@JvmField val JTE_LINE_INFO = intArrayOf(0,0,0,1,2,3,4,6,6,6,6,6,8,8,8,9,9,10,10,14,15,15,15,15,18,21,21,21,24,24,24,24,24,24,28,30,30,30,34,34,34,6,6,6,6,6)
|
|
||||||
@JvmStatic fun render(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, model:MessageTemplate) {
|
|
||||||
jteOutput.writeContent("\n")
|
|
||||||
val dateFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("dd.MM.yyyy").withZone(ZoneId.systemDefault())
|
|
||||||
jteOutput.writeContent("\n")
|
|
||||||
val timeFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault())
|
|
||||||
jteOutput.writeContent("\n")
|
|
||||||
val borderColors = listOf("red", "orange", "yellow", "green", "blue", "pink" )
|
|
||||||
jteOutput.writeContent("\n\n<div class=\"message-group mb-3 animate-slide-in\">\n <div class=\"flex relative px-3 py-1 hover:bg-neutral-800/30 rounded transition-colors\">\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"absolute left-0 top-1/2 -translate-y-1/2 w-1 h-3/4 rounded-r message-border-")
|
|
||||||
jteOutput.setContext("div", "class")
|
|
||||||
jteOutput.writeUserContent(borderColors[model.message.id.hashCode().absoluteValue % borderColors.size])
|
|
||||||
jteOutput.setContext("div", null)
|
|
||||||
jteOutput.writeContent("\"></div>\n\n <div class=\"flex-1 pl-3 text-ellipsis text-wrap break-all\">\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"flex flex-wrap items-baseline gap-2 mb-1\">\n <span class=\"font-semibold text-white\">\n ")
|
|
||||||
jteOutput.setContext("span", null)
|
|
||||||
jteOutput.writeUserContent(model.message.author)
|
|
||||||
jteOutput.writeContent("\n </span>\n <span class=\"text-xs text-neutral-400\">\n ")
|
|
||||||
jteOutput.setContext("span", null)
|
|
||||||
jteOutput.writeUserContent(dateFormatter.format(model.message.createdAt))
|
|
||||||
jteOutput.writeContent(" • ")
|
|
||||||
jteOutput.setContext("span", null)
|
|
||||||
jteOutput.writeUserContent(timeFormatter.format(model.message.createdAt))
|
|
||||||
jteOutput.writeContent("\n </span>\n </div>\n\n ")
|
|
||||||
jteOutput.writeContent("\n <div class=\"text-neutral-200\">\n ")
|
|
||||||
jteOutput.setContext("div", null)
|
|
||||||
jteOutput.writeUserContent(model.message.content)
|
|
||||||
jteOutput.writeContent("\n </div>\n </div>\n </div>\n</div>")
|
|
||||||
}
|
|
||||||
@JvmStatic fun renderMap(jteOutput:gg.jte.html.HtmlTemplateOutput, jteHtmlInterceptor:gg.jte.html.HtmlInterceptor?, params:Map<String, Any?>) {
|
|
||||||
val model = params["model"] as MessageTemplate
|
|
||||||
render(jteOutput, jteHtmlInterceptor, model);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue