Been a bit quiet lately, so thought I’d share some new things I’m going to be adding into Sudonix for the v3 release (based on Harmony). As you probably know by now, Sudonix allows you to set the best answer for any questions you ask. I wanted to extend this capability graphically, and came up with these ideas.
First and foremost - say you’re reading a post where someone was able to get the response they needed, and it solved their issue. The next person comes along, and gets the same experience. Wouldn’t it be nice to show your appreciation? Now you can !
Just below the “Accepted Answer” is a newly inserted div
which in fact is just a widget, but leverages the power of the NodeBB API to make decisions around which div should be presented.
https://docs.nodebb.org/api/read/#section/Overview
For example
And then, if you are the original poster, have received responses, but are yet to choose the best answer
And, what if you were the original poster, but had no responses? We’ve got that covered too
The code for all of this is relatively simple - an example is shown below
First things first: This additional code will not work properly if you do not have nodebb-plugin-question-and-answer
installed. It relies on various values being exposed which are not there if the plugin is not installed.
The first element of code to be added needs to be in ACP->Custom Content (HTML/JS/CSS)->Custom Javascript
$(window).on('action:ajaxify.end', function (data) {
function updateUsername() {
$('.getUsername .username').text(app.user.username);
$('.topicUsername').text(app.user.username);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', updateUsername);
} else {
updateUsername();
}
});
Save.
Then, add the below to ACP->Extend-Widgets->Topic.tpl, and use the HTML Widget (which you’ll need to drag into the place where you want it to appear - the optimum is the Topic Footer.
<head>
<style>
span.topicUsername {
text-transform: capitalize;
}
</style>
</head>
{{{ if isSolved }}}
<div id="resolved">
<div class="resolved-wrapper">
<h5 class="resolved-header">Did this solution help you?</h5>
<div class="resolved-body">
<div class="resolved-message">Did you find the suggested solution useful? Why not <a href="https://www.buymeacoffee.com/phenomlab" target=_blank>buy me a coffee<a />? It's a nice gesture, and there's <a href="https://sudonix.com/donate">other ways to donate</a> if you wish <span class="heart">💗</span></div>
</div>
</div>
</div>
<br>
<script>
if (!window.jQuery) {
window.addEventListener('load', function() {
$(document).ready(function() {
$("#resolved").insertAfter('.isSolved');
})
console.log("Total posts = " + ajaxify.data.postcount)
})
} else {
$(document).ready(function() {
$("#resolved").insertAfter('.isSolved');
})
console.log("Total posts = " + ajaxify.data.postcount)
}
</script>
{{{ end }}}
{{{ if (uid == loggedInUser.uid) }}}
{{{ if isQuestion }}}
{{{ if !isSolved }}}
{{{ if !unreplied }}}
<div id="unresolved">
<div class="unresolved-wrapper">
<h5 class="unresolved-header">Did you get the answer you needed?</h5>
<div class="unresolved-body">
<div class="unresolved-message">Hey <span class="topicUsername"><span class="username"></span></span>. It looks as though there have been one or more replies to your original post. <br>If a provided answer resolved an issue for you, Could you please take a moment, and select "Mark this post as the correct answer" in the corresponding response? <br><br>By doing this, it means that original posters help the rest of the community find answers to previously asked questions by identifying the correct answer. </div>
</div>
</div>
</div>
<br>
<script>
if (!window.jQuery) {
window.addEventListener('load', function() {
$(document).ready(function() {
$("#unresolved").insertBefore('[component="topic/quickreply/container"]');
})
})
} else {
$(document).ready(function() {
$("#unresolved").insertBefore('[component="topic/quickreply/container"]');
})
}
</script>
{{{ end }}}
{{{ end }}}
{{{ end }}}
{{{ end }}}
{{{ if unreplied }}}
{{{ if !isSolved }}}
{{{ if isQuestion }}}
{{{ if (uid == loggedInUser.uid) }}}
<div id="unreplied">
<div class="unreplied-wrapper">
<h5 class="unreplied-header">No response yet</h5>
<div class="unreplied-body">
<div class="unreplied-message">Hey <span class="topicUsername"><span class="username"></span></span>. It looks as though there are no responses yet. Don't panic though, as one will be provided as soon as possible.<br>Please do not "bump" posts. </div>
</div>
</div>
</div>
<br>
<script>
if (!window.jQuery) {
window.addEventListener('load', function() {
$(document).ready(function() {
$("#unreplied").insertBefore('[component="topic/quickreply/container"]');
})
})
} else {
$(document).ready(function() {
$("#unreplied").insertBefore('[component="topic/quickreply/container"]');
})
}
</script>
{{{ end }}}
{{{ end }}}
{{{ end }}}
{{{ end }}}
Save.
You’ll notice some interesting features here courtesy of jQuery
(and vanilla js
where if the page is loaded externally, and jQuery
is not loaded, it will fallback to plain, which is this part if (!window.jQuery)
)
There’s also a function that will position the newly inserted div
into the right place - essentially, this command .insertBefore('[component="topic/quickreply/container"]');
. The purpose of this is to place the div
message in where you’d expect to see it - for example, if the post is solved, then it should appear directly underneath the resolution, but if no replies, or if you’re the original poster and you’ve yet to choose an accepted answer, it’ll be at the bottom.
Essentially, we are not only defining a div
structure, but using logic to determine placement to ensure it gets the most attention.
And finally, the CSS used below
div#resolved {
border-radius: 0.375rem;
border: 2px solid var(--bs-resolved-bg) !important;
margin-left: 24px;
}
h5.resolved-header {
color: var(--bs-body-color);
background: var(--bs-resolved-bg);
padding: 6px 8px;
padding-left: 50px;
font-weight: 600;
height: 40px;
line-height: 1.8;
z-index: 1;
position: relative;
}
h5.resolved-header:before {
content: "\f648";
font-family: "Font Awesome 6 Pro";
font-size: 1.5rem;
font-weight: 300;
line-height: 1.2;
vertical-align: bottom;
margin-right: 10px;
margin-left: -35px;
}
.resolved-body {
padding: 20px;
background: var(--bs-resolved-bg-rgba);
margin-top: -10px;
}
div#unresolved {
border-radius: 0.375rem;
border: 2px solid var(--bs-unresolved-bg) !important;
margin-left: 24px;
margin-top: 20px;
}
h5.unresolved-header {
color: var(--bs-body-color);
background: var(--bs-unresolved-bg);
padding: 6px 8px;
padding-left: 50px;
font-weight: 600;
height: 40px;
line-height: 1.8;
z-index: 1;
position: relative;
}
h5.unresolved-header:before {
content: "\f06a";
font-family: "Font Awesome 6 Pro";
font-size: 1.5rem;
font-weight: 300;
line-height: 1.2;
vertical-align: bottom;
margin-right: 10px;
margin-left: -35px;
}
.unresolved-body {
padding: 20px;
background: var(--bs-unresolved-bg-rgba);
margin-top: -10px;
}
div#unreplied {
border-radius: 0.375rem;
border: 2px solid var(--bs-unreplied-bg) !important;
margin-left: 24px;
margin-top: 20px;
}
h5.unreplied-header {
color: var(--bs-body-color);
background: var(--bs-unreplied-bg);
padding: 6px 8px;
padding-left: 50px;
font-weight: 600;
height: 40px;
line-height: 1.8;
z-index: 1;
position: relative;
}
h5.unreplied-header:before {
content: "\e36d";
font-family: "Font Awesome 6 Pro";
font-size: 1.5rem;
font-weight: 300;
line-height: 1.2;
vertical-align: bottom;
margin-right: 10px;
margin-left: -35px;
}
.unreplied-body {
padding: 20px;
background: var(--bs-unreplied-bg-rgba);
margin-top: -10px;
}
Save.
Note that I’m using LESS variables here, so you’ll need to define your own colours if you do not use this standard. I also have a Font Awesome 6 Pro license, so you’ll need to replace that as necessary.