import info.mechyrdia.auth.installCsrfToken
import info.mechyrdia.auth.verifyCsrfToken
import info.mechyrdia.lore.*
+import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.util.*
+import kotlinx.coroutines.flow.take
+import kotlinx.coroutines.flow.toList
import kotlinx.html.*
+import org.litote.kmongo.descending
import java.time.Instant
+suspend fun ApplicationCall.recentCommentsPage(): HTML.() -> Unit {
+ val currNation = currentNation()
+
+ val limit = request.queryParameters["limit"]?.toIntOrNull() ?: redirect("/comment/recent?limit=10")
+
+ val validLimits = listOf(10, 20, 50, 80, 100)
+
+ if (limit !in validLimits)
+ redirect(
+ "/comment/recent?" + listOf(
+ "limit" to "10",
+ "error" to "Invalid limit $limit, must be one of ${validLimits.joinToString()}"
+ ).formUrlEncode()
+ )
+
+ val comments = CommentRenderData(Comment.Table.sorted(descending(Comment::submittedAt)).take(limit).toList())
+
+ return page("Recent Comments", standardNavBar()) {
+ section {
+ h1 { +"Recent Comments" }
+
+ p {
+ +"Number of comments to view: "
+ for ((i, validLimit) in validLimits.withIndex()) {
+ if (i != 0)
+ +Entities.nbsp
+
+ if (limit == validLimit)
+ +"$validLimit"
+ else
+ a(href="/comment/recent?limit=$validLimit") {
+ +"$validLimit"
+ }
+ }
+ }
+
+ for (comment in comments)
+ commentBox(comment, currNation?.id, viewingUserPage = true)
+ }
+ }
+}
+
suspend fun ApplicationCall.newCommentRoute(): Nothing {
val pagePathParts = parameters.getAll("path")!!
val pagePath = pagePathParts.joinToString("/")
Comment.Table.del(commentId)
- redirect("/lore/${comment.submittedIn}")
+ redirect("/lore/${comment.submittedIn}#comments")
}
suspend fun ApplicationCall.commentHelpPage(): HTML.() -> Unit = page("Commenting Help", standardNavBar()) {
)) + listOf(
NavHead("Useful Links"),
NavLink("/comment/help", "Commenting Help"),
+ NavLink("/comment/recent", "Recent Comments"),
+ NavHead("See Also"),
NavLink("https://nationstates.net/$OWNER_NATION", "Mechyrdia on NationStates"),
+ NavLink("https://laniustrolling.dev/", "The Man Behind Mechyrdia"),
)
sealed class NavItem {
border-color: var(--iframe-border);
}
+#error-popup {
+ z-index: 998;
+}
+
#error-popup > .bg {
position: fixed;
width: 100vw;
height: 100vh;
+ left: 0;
+ top: 0;
+
background-color: rgba(0, 0, 0, 40%);
- z-index: 998;
}
#error-popup > .msg {
font-family: 'Noto Sans Gothic', sans-serif;
}
+.comment-input {
+ border: 0.25em solid var(--comment-stroke);
+ background-color: var(--comment-fill);
+ padding: 0.75em;
+ margin: 1em 0;
+}
+
.comment-box {
border: 0.25em solid var(--comment-stroke);
background-color: var(--comment-fill);
}
.comment-box > .comment {
+ margin-top: 0.125em;
border-top: 0.25em solid var(--comment-stroke);
padding-top: 0.5em;
}