02.12.2020 software-release open-source webdesign labertasche

Labertasche has now replies!

Good news, everyone! After a bit of tinkering, Labertasche has now replies and also a little teaser-page .

If you are already using Labertasche in production, there was an error which makes it necessary to migrate the database to a new one, as I couldn’t get flask migrate to change the tables properly. If you have a solution, feel free to submit pull request.

Please let me know if anyone is already using it, so I am aware of it and use less radical solutions. My site isn’t very well known, and I don’t expect anyone using my stuff. Anyway, on to the good stuff!

New go template code block necessary

The json placed in your data directory has now this format:

'comments':
[
    // all comments
],
'replies':
[
    // all replies
]

As you can see, replies and comments are 2 different arrays. With the where command from Hugo, we can query the replies belonging to each comment:

{{ $location := .Scratch.Get "location" }} 
{{ if (fileExists $location ) }}
    {{ $dataJ := getJSON  $location }}
        {{ range $dataJ.comments }}
            {# HTML and template codes here #}
            {# This is to display replies to this comment, you can use them same variables #}
            {{ range where $dataJ.replies "replied_to" .comment_id }}
                {# HTML and template codes here for replies #}
            {{end}}       
        {{ end }}
{{ end }}

This was the simplest way to add it, making it possible to get the data in one query. Build time shouldn’t be affected much by this.

New javascript function

You will find a new javascript function in the js folder, making it a breeze to implement the reply to a new comment.

function labertasche_reply_to(comment_id, callback)
{
    let comments = document.getElementById('labertasche-comment-section');
    if (comments){
        if (document.getElementById('labertasche-replied-to')){
            document.getElementById('labertasche-replied-to').remove();
            callback('off', comment_id);
            if (comment_id === -1){
                return false;
            }
        }
        let reply = document.createElement("input");
        reply.setAttribute("type", "text");
        reply.setAttribute("id", "labertasche-replied-to");
        reply.classList.add("is-hidden");
        reply.value = comment_id;
        comments.appendChild(reply);
        callback('on', comment_id);
    }
    else{
        console.log("Missing text input with id labertasche-comment-section");
    }
}

The code adds a new hidden field to your comment-section and writes the id to reply to into that hidden field. If it is already set, it will remove it and re-add, so you can change the parent of your reply on the fly without reload. Additionally, if the comment_id is -1, it will fire an off event to the callback and not re-add the hidden field. This is perfect for implementing a cancel button and reverting to a normal comment instead of a reply. Here is my version of the callback, to give you an idea:


function labertasche_reply_callback(state, comment_id)
{
    if (state === "on"){
        let comment_btn = document.getElementById('labertasche-comment-button');
        let parent = comment_btn.parentElement
        let new_btn = document.createElement("button");
        new_btn.classList.add("button");
        new_btn.classList.add("is-danger");
        new_btn.classList.add("is-medium");
        new_btn.classList.add("px-6");
        new_btn.setAttribute("id", "labertasche-cancel-reply");
        new_btn.onclick = function() { labertasche_reply_to(-1, labertasche_reply_callback); }
        new_btn.innerHTML = '<span class=\"icon is-medium\"><i class=\"fas fa-minus-circle\"></i></span><span>Cancel Reply</span>';
        parent.appendChild(new_btn);

        comment_btn.innerHTML = "<span class=\"icon is-medium\"><i class=\"fas fa-comment\"></i></span><span>Reply to #" + comment_id + "</span>";
    }

    if (state === "off"){
        console.log("off");
        let comment_btn = document.getElementById('labertasche-comment-button');
        comment_btn.innerHTML = '<span class=\"icon is-medium\"><i class=\"fas fa-comment\"></i></span><span>Comment</span>';
        let cancel = document.getElementById('labertasche-cancel-reply');
        if (cancel){
            cancel.remove();
        }
    }
}

Call labertasche_reply_to when you want to initiate a reply to a post. Like a button, or an icon to click. Use the onclick event to call this and don’t forget to add the callback, so you may do more stuff when things happen without changing this function, so you can deploy new versions any time. Here is an example how to add a reply button:

<div class="">
    <a href="#labertasche-comment-section"
       onclick="labertasche_reply_to({{.comment_id}}, labertasche_reply_callback);">
       reply
    </a>
</div>

I hope I am explaining things so everyone can understand it, if not please let me know. I have the tendency to sometimes skip things I ought to write, like many authors out there. If you know how it works, it is sometimes easy to forget the little but important things.

Comment on this post to try it out and let me know what you think. And as always, you can write to contact@tuxstash.de, if you have any questions, flames or well wishes.

Link to the author's twitter Link to the authors ko-fi page

comments

Characters: 0/1000

gravatar portrait

 Pinned by contact@tuxstash.de

Come join the discussion and write something nice. You will have to confirm your comment by mail, so make sure it is legit and not a throwaway. Only the name part of it will be displayed, so don't worry about spam. If it does not show up after confirming it, it may be considered spam, but I curate them manually, so don't worry. Please read the privacy statement for more.

gravatar portrait

#1 Posted by acanalis@ on 2020-12-17 14:02:09

Hello! I'm just here to write a comment, see how it works. Running a server is a no for me, but impressive work! Everything looks neat. I have a question, using Labertasche you need to build the whole site with Hugo each time a new comment appears? Wouldn't that be very costly if you received many coments per day?