Skip to content

v3 & Harmony diary / thoughts / code snippets

Announcements
  • @phenomlab said in v3 / Harmony diary:

    Today’s playground 🙂

    c67e0b6c-b534-4306-8e58-dbe77e30c6a0-image.png

    Here’s a video… still needs a bit more work, but… 🙂 Notice the newer scroll and progress bar I was talking about earlier…

    https://sudonix.com/assets/uploads/files/footer-added.webm

    Hello Mark,

    I just tested the functioning of the scroll bar and I saw this bug:

    https://i.imgur.com/VQw5zw5.mp4

    It should be moved to the left so as not to encroach on the collapse button of the custom footer navbar.

    Then, when we play with the collapse button of the custom footer navbar we should:

    • When the custom footer navbar is deactivated: it sticks to the bottom right while not encroaching on the right sidebar. All this taking into account the collapse of the right sidebar (not obvious, I don’t know if I’m clear 🙂 )

    • When the custom footer navbar is activated: it moves just to the left of the floatright block or can be above the floatright block?

    The solution may be less difficult to code would be to make a vertical scrollbar inside the right sidebar like in topics. There might be less to manage

    Keep the good work my friend 😉

    @DownPW said in v3 / Harmony diary:

    The solution may be less difficult to code would be to make a vertical scrollbar inside the right sidebar like in topics. There might be less to manage

    Nope. The newest version of Harmony appears to have the same pagination as Flarum and Discourse, so it’s been moved into the content area 😁

  • @DownPW said in v3 / Harmony diary:

    The solution may be less difficult to code would be to make a vertical scrollbar inside the right sidebar like in topics. There might be less to manage

    Nope. The newest version of Harmony appears to have the same pagination as Flarum and Discourse, so it’s been moved into the content area 😁

    @phenomlab

    yessss fixed. Love it 😁 😍

  • @phenomlab

    No javascript ?

    I wanted to inspect the code but I can’t find any JS

  • @phenomlab

    No javascript ?

    I wanted to inspect the code but I can’t find any JS

    @DownPW it’s definitely there. Won’t work without it 😉

  • @DownPW it’s definitely there. Won’t work without it 😉

    @phenomlab

    I guess, I don’t find it in inspector lol .I will search 🙂

  • @phenomlab

    I guess, I don’t find it in inspector lol .I will search 🙂

    @phenomlab

    Can I test it on my dev env ?

    EDIT: I test it. If you don’t want tell me Mark

    If I have problem, can I ask you @phenomlab ?

  • @phenomlab

    Can I test it on my dev env ?

    EDIT: I test it. If you don’t want tell me Mark

    If I have problem, can I ask you @phenomlab ?

    @DownPW no problems.

  • @phenomlab said in v3 / Harmony diary:

    @DownPW no problems.

    Seems I miss something 😑 @phenomlab but good start 😉

    [- https://i.imgur.com/cN0YeN0.mp4 -]

    EDIT: Maybe find

    EDIT 2: @phenomlab

    Find --> I have forget toAbove and toBottom css directives
    It’s better now, just seems toBottom doesn’t work :

    b64bdc12-435e-468d-9818-c966b4cbc148-image.png

    .toBottom {
    bottom: 0px !important;
    right: 0px!important;
    }
    .toAbove {
    bottom: -5px !important;
    right: 400px !important;
    }
  • @phenomlab said in v3 / Harmony diary:

    @DownPW no problems.

    Seems I miss something 😑 @phenomlab but good start 😉

    [- https://i.imgur.com/cN0YeN0.mp4 -]

    EDIT: Maybe find

    EDIT 2: @phenomlab

    Find --> I have forget toAbove and toBottom css directives
    It’s better now, just seems toBottom doesn’t work :

    b64bdc12-435e-468d-9818-c966b4cbc148-image.png

    .toBottom {
      bottom: 0px !important;
      right: 0px!important;
    }
    
    .toAbove {
      bottom: -5px !important;
      right: 400px !important;
    }
    

    @DownPW likely you are missing z-index on that class. As you are using position: absolute the index is needed to bring that specific element forward. By default, it’ll sit behind the progress bar meaning it cannot be clicked, but can be seen.

  • @DownPW likely you are missing z-index on that class. As you are using position: absolute the index is needed to bring that specific element forward. By default, it’ll sit behind the progress bar meaning it cannot be clicked, but can be seen.

    @phenomlab

    Thanks for your reply my friend 😉

    I will test tomorrow and again, it’s a very great job, I like it a lot.

  • @phenomlab

    Thanks for your reply my friend 😉

    I will test tomorrow and again, it’s a very great job, I like it a lot.

    @DownPW no problems. Let me know if you have issues and I can take a look. Can’t release the code formally yet as it’s still beta (and does have very minor bugs).

  • @DownPW no problems. Let me know if you have issues and I can take a look. Can’t release the code formally yet as it’s still beta (and does have very minor bugs).

    Not sure why, but for a while I’ve been looking at the size of the CSS file that runs the dev site, and I couldn’t understand why it was almost twice the size of what it should be in terms of overall lines.

    This eventually got the better of me and I landed up going through the file and removing what appears to be a large amount of duplicated CSS. I primarily work offline using VSCode (my go-to editor), but periodically “fix” things on the fly. The problem with this is that if you make changes online then copy these from the CSS editor in the ACP back to VSCode, they seem to be copied twice - in other words, appended to the existing file despite all text being selected, which should in fact overwrite, but it doesn’t 😱

    Just something for everyone else to watch out for. I spent a fair amount of time this afternoon purging duplicate classes, and the end result is a much leaner file.

  • Not sure why, but for a while I’ve been looking at the size of the CSS file that runs the dev site, and I couldn’t understand why it was almost twice the size of what it should be in terms of overall lines.

    This eventually got the better of me and I landed up going through the file and removing what appears to be a large amount of duplicated CSS. I primarily work offline using VSCode (my go-to editor), but periodically “fix” things on the fly. The problem with this is that if you make changes online then copy these from the CSS editor in the ACP back to VSCode, they seem to be copied twice - in other words, appended to the existing file despite all text being selected, which should in fact overwrite, but it doesn’t 😱

    Just something for everyone else to watch out for. I spent a fair amount of time this afternoon purging duplicate classes, and the end result is a much leaner file.

    Thanks to @cagatay for finding a bug with the CSS in relation to tags in DEV. This has been fixed. I also found another bug whilst addressing this one in the sense that the progress bar on mobile (and desktop, but limited intrusion) shows over the tag div when the composer is active.

    Changed the scrollbar function so that it does not fire if the composer is visible. Here’s the block of code that detects if it’s active or not

    if ($(window).scrollTop() > 0 && (!$('[component="composer"]').is(":visible"))) {
    bar.addClass('show');
    } else {
    bar.removeClass('show');
    }

    Above, we now have 2 conditions. The first is to fire only if the top marker is higher than 0 - for example, hide if we are at the top of the screen. The second condition is that we also only fire if the composer isn’t active - detected by is(":visible")

    Keep 'em coming in terms of identified bugs - reporting them is much appreciated.

  • Thanks to @cagatay for finding a bug with the CSS in relation to tags in DEV. This has been fixed. I also found another bug whilst addressing this one in the sense that the progress bar on mobile (and desktop, but limited intrusion) shows over the tag div when the composer is active.

    Changed the scrollbar function so that it does not fire if the composer is visible. Here’s the block of code that detects if it’s active or not

                if ($(window).scrollTop() > 0 && (!$('[component="composer"]').is(":visible"))) {
                    bar.addClass('show');
                } else {
                    bar.removeClass('show');
                }
    

    Above, we now have 2 conditions. The first is to fire only if the top marker is higher than 0 - for example, hide if we are at the top of the screen. The second condition is that we also only fire if the composer isn’t active - detected by is(":visible")

    Keep 'em coming in terms of identified bugs - reporting them is much appreciated.

    Hello @phenomlab

    I keep working on my CSS
    On v2, I displayed user groups in topics like this :

    923b452b-29cc-4ca1-82ac-a4348d3f5312-image.png

    but I can’t seem to get any result. I can’t target the right element

    Ideas ?

    Many thanks

  • Hello @phenomlab

    I keep working on my CSS
    On v2, I displayed user groups in topics like this :

    923b452b-29cc-4ca1-82ac-a4348d3f5312-image.png

    but I can’t seem to get any result. I can’t target the right element

    Ideas ?

    Many thanks

    @DownPW hmm. Haven’t tried this myself (yet) but will have a look later this afternoon.

  • Hello @phenomlab

    I keep working on my CSS
    On v2, I displayed user groups in topics like this :

    923b452b-29cc-4ca1-82ac-a4348d3f5312-image.png

    but I can’t seem to get any result. I can’t target the right element

    Ideas ?

    Many thanks

    @DownPW This should work under v3

    a.badge.rounded-1.text-uppercase.text-truncate.text-decoration-none {
    border-radius: 999px !important;
    margin-left: -10px;
    width: 22px;
    max-width: 22px;
    }
  • @DownPW This should work under v3

    a.badge.rounded-1.text-uppercase.text-truncate.text-decoration-none {
        border-radius: 999px !important;
        margin-left: -10px;
        width: 22px;
        max-width: 22px;
    }
    

    Hi @phenomlab

    Thanks my friend. 👍
    I have this result with code you provided :

    46aa98c7-962e-4301-b90a-6b8add5b1665-image.png

    It’s better but not perfect.
    But it allowed me to target the right element

    –> Here is a code improvement for those who are interested :

    /* Desktop */
    a.badge.rounded-1.text-uppercase.text-truncate.text-decoration-none {
    border-radius: 999px !important;
    margin-right: -10px;
    padding-left: 6px;
    padding-top: 5px;
    width: 20px;
    max-width: 20px !important;
    }
    .d-flex.gap-1.hidden-xs.align-items-center {
    margin-left: 15px;
    }
    i.fa.fa-edit.text-muted.pointer.edit-icon {
    margin-left: 8px;
    }
    /* Smartphone */
    @media (max-width: 767px) {
    a.badge.rounded-1.text-uppercase.text-truncate.text-decoration-none {
    padding-left: 4px;
    }
    }

    Better result :

    5045c227-f295-49b5-b5e4-fa4367878520-image.png

    cya 🙂

  • Hi @phenomlab

    Thanks my friend. 👍
    I have this result with code you provided :

    46aa98c7-962e-4301-b90a-6b8add5b1665-image.png

    It’s better but not perfect.
    But it allowed me to target the right element

    –> Here is a code improvement for those who are interested :

    /* Desktop */
    a.badge.rounded-1.text-uppercase.text-truncate.text-decoration-none {
        border-radius: 999px !important;
        margin-right: -10px;
        padding-left: 6px;
        padding-top: 5px;
        width: 20px;
        max-width: 20px !important; 
    }
    
    .d-flex.gap-1.hidden-xs.align-items-center {
        margin-left: 15px;
    } 
    
    i.fa.fa-edit.text-muted.pointer.edit-icon {
        margin-left: 8px;
    }
    
    /* Smartphone */
    @media (max-width: 767px) {
    a.badge.rounded-1.text-uppercase.text-truncate.text-decoration-none {
        padding-left: 4px;
    }
    }
    
    

    Better result :

    5045c227-f295-49b5-b5e4-fa4367878520-image.png

    cya 🙂

    @DownPW yeah, the CSS I provided was based on my forum, so a little tweaking is necessary. Looks great !

  • 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.

    For example

    ad835bd8-c49e-467a-aa99-8e34ef616280-image.png

    And then, if you are the original poster, have received responses, but are yet to choose the best answer

    4a30728a-8812-4220-a64e-b0345d7e6fae-image.png

    And, what if you were the original poster, but had no responses? We’ve got that covered too 🙂

    49db08d8-8096-490d-9fea-7325ce19985a-image.png

    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.

  • 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

    ad835bd8-c49e-467a-aa99-8e34ef616280-image.png

    And then, if you are the original poster, have received responses, but are yet to choose the best answer

    4a30728a-8812-4220-a64e-b0345d7e6fae-image.png

    And, what if you were the original poster, but had no responses? We’ve got that covered too 🙂

    49db08d8-8096-490d-9fea-7325ce19985a-image.png

    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.

    @phenomlab

    Very good job…

    I must just thinking to where put your first part code on nodeBB ACP but I want to test it!



32/55

13 Feb 2023, 23:35


Threaded Replies

Related Topics
  • Nodebb and emails

    Solved Configure nodebb 21 Dec 2024, 20:45
    5 Votes
    27 Posts
    993 Views
    @Panda it will use SMTP. In all cases, I never use any plugin to send email. I’ll always send it raw.
  • 6 Votes
    4 Posts
    446 Views
    @cagatay these changes aren’t published anywhere presently, so nothing for you to do.
  • Nodebb design

    Solved General nodebb 11 Jul 2023, 10:13
    1 Votes
    2 Posts
    386 Views
    @Panda said in Nodebb design: One negative is not being so good for SEO as more Server side rendered forums, if web crawlers dont run the JS to read the forum. From recollection, Google and Bing have the capability to read and process JS, although it’s not in the same manner as a physical person will consume content on a page. It will be seen as plain text, but will be indexed. However, it’s important to note that Yandex and Baidu will not render JS, although seeing as Google has a 90% share of the content available on the web in terms of indexing, this isn’t something you’ll likely lose sleep over. @Panda said in Nodebb design: The “write api” is preferred for server-to-server interactions. This is mostly based around overall security - you won’t typically want a client machine changing database elements or altering data. This is why you have “client-side” which could be DOM manipulation etc, and “server-side” which performs more complex operations as it can communicate directly with the database whereas the client cannot (and if it can, then you have a serious security flaw). Reading from the API is perfectly acceptable on the client-side, but not being able to write. A paradigm here would be something like SNMP. This protocol exists as a UDP (UDP is very efficient, as it is “fire and forget” and does not wait for a response like TCP does) based service which reads performance data from a remote source, thus enabling an application to parse that data for use in a monitoring application. In all cases, SNMP access should be “RO” (Read Only) and not RW (Read Write). It is completely feasible to assume complete control over a firewall for example by having RW access to SNMP and then exposing it to the entire internet with a weak passphrase. You wouldn’t do it (at least, I hope you wouldn’t) and the same ethic applies to server-side rendering and the execution of commands.
  • 3 Votes
    11 Posts
    654 Views
    For anyone else following this thread https://community.nodebb.org/topic/17402/change-in-reply-to-xxxx-text And https://github.com/NodeBB/NodeBB/commit/f2152953cddd3247746ef393516b0a53ba7750a4
  • 14 Votes
    69 Posts
    15k Views
    @phenomlab Seems to be better with some scaling fix for redis on redis.conf. I haven’t seen the message yet since the changes I made # I increase it to the value of /proc/sys/net/core/somaxconn tcp-backlog 4096 # I'm uncommenting because it can slow down Redis. Uncommented by default !!!!!!!!!!!!!!!!!!! #save 900 1 #save 300 10 #save 60 10000 If you have other Redis optimizations. I take all your advice https://severalnines.com/blog/performance-tuning-redis/
  • 0 Votes
    6 Posts
    749 Views
    @cagatay You should ask in the NodeBB forums. Perhaps reference this post https://discuss.flarum.org/d/23066-who-read
  • 4 Votes
    25 Posts
    3k Views
    Topic open https://sudonix.com/topic/207/nodebb-help-for-my-custom-css
  • nodebb dropdown menu

    Solved Configure nodebb 26 Nov 2021, 15:17
    1
    0 Votes
    5 Posts
    656 Views
    @phenomlab said in nodebb dropdown menu: @kurulumu-net You set it like the below example taken from this site [image: 1637939951821-aae36790-3257-4bb2-ad5a-0d744309876a-image.png] Which presents this [image: 1637939983445-77f47260-2941-4afe-9614-8e17dcfc8c19-image.png] Very interesting… I actually thought this wasn’t possible, as I remember it being asked in the NodeBB forum. Is this something new that’s been implemented? I’ll 100% be doing that when I’m on the laptop over the weekend.