diff --git a/demo/soudan.js b/demo/soudan.js
index 20dc586..f047c83 100644
--- a/demo/soudan.js
+++ b/demo/soudan.js
@@ -1,12 +1,19 @@
+function commentForm(parent) {
+ return `
+
`;
+}
+function commentDisplay(comment, replies) {
+ return ``;
+}
document.getElementById("soudan").innerHTML = `Make a comment
-
+${commentForm()}
`;
const md = window.markdownit().disable("image");
@@ -15,7 +22,8 @@ const form = document.getElementById("soudan-comment-form");
const commentContainer = document.getElementById("soudan-comments");
const commentContainerHeader = document.getElementById("soudan-comments-header");
const contentId = document.querySelector("meta[name=\"soudan-content-id\"]").getAttribute("content");
-form.addEventListener("submit", e => {
+
+function submitForm(form, e) {
let data = {
url: window.location.href,
comment: { contentId }
@@ -23,6 +31,9 @@ form.addEventListener("submit", e => {
new FormData(form).forEach((value, key) => {
data.comment[key] = value === "" ? null : value;
});
+ if (data.comment.parent) {
+ data.comment.parent = parseInt(data.comment.parent);
+ }
fetch(url, {
method: "POST",
body: JSON.stringify(data),
@@ -36,9 +47,9 @@ form.addEventListener("submit", e => {
reloadComments();
})
e.preventDefault();
-});
+}
-function reloadComments() {
+function reloadComments(jump) {
fetch(`${url}/${contentId}`)
.then(response => {
return response.json().then(json => {
@@ -52,11 +63,31 @@ function reloadComments() {
html = "No comments yet! Be the first to make one.
";
} else {
comments.forEach(comment => {
- html += `${comment.author ? comment.author : "Anonymous"} commented ${moment(new Date(comment.timestamp * 1000)).fromNow()}:
${md.render(comment.text)}
`;
+ if (comment.replies) {
+ let replies = "";
+ comment.replies.forEach(reply => {
+ replies += commentDisplay(reply);
+ });
+ html += commentDisplay(comment, replies);
+ } else {
+ html += commentDisplay(comment, "");
+ }
});
}
commentContainer.innerHTML = html;
+ if (jump && window.location.hash) {
+ const target = document.getElementById(window.location.hash.substring(1));
+ if (target) {
+ window.scrollTo(0, target.offsetTop);
+ target.classList.add("soudan-highlighted");
+ }
+ }
});
}
-reloadComments();
+function reply(id) {
+ const replies = document.getElementById(id).querySelector(".soudan-replies");
+ replies.innerHTML = `Reply
${commentForm(id)}${replies.innerHTML}`;
+}
+
+reloadComments(true);
diff --git a/demo/style.css b/demo/style.css
index 598e37a..4d7a2e3 100644
--- a/demo/style.css
+++ b/demo/style.css
@@ -1,10 +1,25 @@
-#soudan-comments > div {
+.soudan-comment {
display: flex;
gap: 0.5em;
}
+.soudan-comment > div {
+ width: 100%;
+}
+@keyframes soudan-highlighted {
+ from { background: rgba(255, 255, 0, 0.25); }
+ to { background: rgba(255, 255, 0, 0); }
+}
+.soudan-highlighted {
+ background: rgba(255, 255, 0, 0.25);
+ border-radius: 0.25em;
+ animation-name: soudan-highlighted;
+ animation-duration: 4s;
+ animation-delay: 2s;
+ animation-fill-mode: forwards;
+}
.soudan-avatar {
border-radius: 100%;
- width: 80px;
- height: 80px;
+ width: 60px;
+ height: 60px;
background-color: gray;
}
diff --git a/src/database.rs b/src/database.rs
index 063f6b9..97736b8 100644
--- a/src/database.rs
+++ b/src/database.rs
@@ -32,7 +32,7 @@ impl Database {
.query_map([], |row| {
let id = row.get::>(0)?.unwrap();
let replies = self.conn
- .prepare(&format!("SELECT id, author, email, text, timestamp FROM comment WHERE parent={id} ORDER BY timestamp DESC"))?
+ .prepare(&format!("SELECT id, author, email, text, timestamp FROM comment WHERE parent={id}"))?
.query_map([], |row| {
Ok(Comment {
id: row.get(0)?,
@@ -62,12 +62,13 @@ impl Database {
pub fn create_comment(&self, comment: &Comment) -> Result<()> {
self.conn.execute(
- "INSERT INTO comment (author, email, text, content_id) VALUES (?1, ?2, ?3, ?4)",
+ "INSERT INTO comment (author, email, text, content_id, parent) VALUES (?1, ?2, ?3, ?4, ?5)",
params![
&comment.author,
&comment.email,
&comment.text,
- &comment.content_id
+ &comment.content_id,
+ &comment.parent,
],
)?;
Ok(())
diff --git a/src/main.rs b/src/main.rs
index 5db64e5..20891c1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -123,7 +123,25 @@ async fn post_comment(
Ok(database) => database,
Err(response) => return response,
};
- database.create_comment(&comment).unwrap();
+ if let Some(parent) = comment.parent {
+ 'outer2: loop {
+ match database.get_comments(&comment.content_id) {
+ Ok(comments) => for other_comment in comments.iter() {
+ if other_comment.id.unwrap() == parent {
+ if other_comment.parent.is_none() {
+ break 'outer2;
+ }
+ break;
+ }
+ },
+ Err(_) => return HttpResponse::InternalServerError().reason("failed to get comments").finish(),
+ }
+ return HttpResponse::BadRequest().reason("invalid comment parent").finish();
+ }
+ }
+ if let Err(_) = database.create_comment(&comment) {
+ return HttpResponse::InternalServerError().reason("failed to create comment").finish();
+ }
HttpResponse::Ok().into()
}
Err(_) => HttpResponse::BadRequest().reason("failed to parse request body").finish(),