Skip to content

Threaded post support for NodeBB

Let's Build It
  • Very cool like as already said above and a big thanks for hard work (I see the th function.js and woowwww 🙂 )

    I test it now and I have see this with plugin user-browsers :

    Do you know where it could come from?

    This also breaks the display of the site title

    Can we do the same thing but without expanding the topic toolbar on header ?


    EDIT :

    I see that you seem put other things in the function.js on github like banner, logo, fancybox… 🙂
    I said to myself that I found this file way too long without asking too many questions !

    –> But I have the bug display with user browsers plugin which I will try to solve

    @DownPW said in Threading support for NodeBB:

    Do you know where it could come from?

    Yes, just fixed it in your dev environment. I assumed (probably incorrectly) that people may not have this installed, so omitted it. I fixed it in prod because I do have it there, but wanted to keep DEV as vanilla as possible.

    I’ll need to write a function that checks for the existence of this plugin then determines where to inject the toggle switch

    For now, see the below

    $('.topic .sticky-tools ul .hidden-xs').append(threadView);
    // If you have browsing users plugin, comment out the above line and uncomment the one below
    //$('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);

    Result (might need some position tweaking…)

    b0de4f7a-55bb-4611-93e5-f43f211b8a70-image.png

  • Good, thanks!!!
    Test asap, i’m on intervention AT work

  • @DownPW hmm. Not sure why I copied all of that code, but will change asap. I also have a fix for the browsing users plugin issue but didn’t include it because others might not be using it.

    I’ll get to this as soon as I can.

    EDIT - Done
    EDIT 2 - I just noticed on your DEV box that you have (thanks to me - sorry) a ton of JS code you don’t need. You should probably clean that up.

    @phenomlab said in Threading support for NodeBB:

    EDIT 2 - I just noticed on your DEV box that you have (thanks to me - sorry) a ton of JS code you don’t need. You should probably clean that up.

    no I need it 😉

    @phenomlab said in Threading support for NodeBB:

    @DownPW said in Threading support for NodeBB:

    Can we do the same thing but without expanding the topic toolbar on header ?

    Yes, but then you’ll have elements that are wider than the sticky bar which looks odd on scroll.

    Could you still explain to me how to obtain this result so that I can see what I prefer?

  • @phenomlab said in Threading support for NodeBB:

    EDIT 2 - I just noticed on your DEV box that you have (thanks to me - sorry) a ton of JS code you don’t need. You should probably clean that up.

    no I need it 😉

    @phenomlab said in Threading support for NodeBB:

    @DownPW said in Threading support for NodeBB:

    Can we do the same thing but without expanding the topic toolbar on header ?

    Yes, but then you’ll have elements that are wider than the sticky bar which looks odd on scroll.

    Could you still explain to me how to obtain this result so that I can see what I prefer?

    @DownPW said in Threading support for NodeBB:

    Could you still explain to me how to obtain this result so that I can see what I prefer?

    Yes, of course. Locate the below block in the CSS, and comment out margin-left: -8%;

    .topic .threaded.sticky-tools {
    margin-left: -8%;
    margin-top: 0px;
    margin-bottom: 0px;
    transition: margin-left 0.3s ease, margin-right 0.3s ease;
    }
  • Great, thank you Mark !

    –> I also have a little suggestion to add a tooltip on the button mouse hover like "Thread view On and thread View Off depending on the state or maybe just one?

    What do you think about it ?

  • Great, thank you Mark !

    –> I also have a little suggestion to add a tooltip on the button mouse hover like "Thread view On and thread View Off depending on the state or maybe just one?

    What do you think about it ?

    @DownPW said in Threading support for NodeBB:

    What do you think about it ?

    Great idea. I’ll add that.

  • maybe with an HTML SPAN class like this ?

    <span class="title-tooltip top" tooltip-text="Thread View On">
    
  • maybe with an HTML SPAN class like this ?

    <span class="title-tooltip top" tooltip-text="Thread View On">
    

    @DownPW yes, that should work, although probably better to use one tooltip with on/off text.

  • Small specific request.

    I try to adapt the code to my environment.

    I modified the background of the following classes:

    .page-topic .topic .posts.timeline .timeline-event,
    .page-topic .topic .posts.timeline > [component="post/placeholder"],
    .page-topic .topic .posts.timeline > [component="post"] {
    border-left: none;
    transition: transform 0.3s ease !important;
    background: var(--bs-body-bg);
    background: var(--bs-body-navbar);
    }
    .post-container.threaded {
    background: var(--bs-body-bg) !important;
    background: var(--bs-body-navbar)!important;
    }
    li.pt-4.self-post:not(.self-post .topic-owner-post).threaded {
    transform: translateX(0px) !important;
    transition: transform 0.3s ease !important;
    background: var(--bs-body-bg);
    background: var(--bs-body-navbar)!important;
    padding-right: 30px;
    }

    and other code, for example :

    .page-topic .topic .posts.timeline [component="topic/event"].timeline-event, .page-topic .topic .posts.timeline [component="topic/necro-post"].timeline-event {
    background: transparent;
    }
    .page-topic .topic .posts.timeline .timeline-event:last-child, .page-topic .topic .posts.timeline>[component="post/placeholder"]:last-child, .page-topic .topic .posts.timeline>[component=post]:last-child {
    margin-left: 0.5rem;
    }

    When I activate mode it works without problem but it does not disappear when I deactivate the mode. (Return to vanilla)

    I think I understand by reading the code that it is necessary to specify the classes chnaged in the function.js (with add .threaded) but I don’t really see how to add more

    f0208e5f-2863-48df-98a7-273e8a944377-image.png

  • Small specific request.

    I try to adapt the code to my environment.

    I modified the background of the following classes:

    .page-topic .topic .posts.timeline .timeline-event,
    .page-topic .topic .posts.timeline > [component="post/placeholder"],
    .page-topic .topic .posts.timeline > [component="post"] {
      border-left: none;
      transition: transform 0.3s ease !important;
      background: var(--bs-body-bg);
      background: var(--bs-body-navbar);
    }
    
    .post-container.threaded {
      background: var(--bs-body-bg) !important;
      background: var(--bs-body-navbar)!important;
    }
    
    li.pt-4.self-post:not(.self-post .topic-owner-post).threaded {
      transform: translateX(0px) !important;
      transition: transform 0.3s ease !important;
      background: var(--bs-body-bg);
      background: var(--bs-body-navbar)!important;
      padding-right: 30px;
    }
    

    and other code, for example :

    .page-topic .topic .posts.timeline [component="topic/event"].timeline-event, .page-topic .topic .posts.timeline [component="topic/necro-post"].timeline-event {
        background: transparent;
    }
    
    .page-topic .topic .posts.timeline .timeline-event:last-child, .page-topic .topic .posts.timeline>[component="post/placeholder"]:last-child, .page-topic .topic .posts.timeline>[component=post]:last-child {
        margin-left: 0.5rem;
    }
    

    When I activate mode it works without problem but it does not disappear when I deactivate the mode. (Return to vanilla)

    I think I understand by reading the code that it is necessary to specify the classes chnaged in the function.js (with add .threaded) but I don’t really see how to add more

    f0208e5f-2863-48df-98a7-273e8a944377-image.png

    @DownPW any reason as to why you’ve defined background twice ?

    See

    background: var(--bs-body-bg);
    background: var(--bs-body navbar)!important;
  • I have just forget to delete the first but this nothing change.

  • I have just forget to delete the first but this nothing change.

    @DownPW just curious 🤭

    The second would override the first anyway.

    I’m in transit currently and not in front of a pc but will review this as soon as I can.

  • i have a problem with my codes 😞

    image.png

  • i have a problem with my codes 😞

    image.png

  • undefined phenomlab referenced this topic on 12 Sept 2023, 21:42
  • @phenomlab thank you Mark i did not read this one.

  • @phenomlab thank you Mark i did not read this one.

    @cagatay no problems. Easily missed!!

  • Small specific request.

    I try to adapt the code to my environment.

    I modified the background of the following classes:

    .page-topic .topic .posts.timeline .timeline-event,
    .page-topic .topic .posts.timeline > [component="post/placeholder"],
    .page-topic .topic .posts.timeline > [component="post"] {
      border-left: none;
      transition: transform 0.3s ease !important;
      background: var(--bs-body-bg);
      background: var(--bs-body-navbar);
    }
    
    .post-container.threaded {
      background: var(--bs-body-bg) !important;
      background: var(--bs-body-navbar)!important;
    }
    
    li.pt-4.self-post:not(.self-post .topic-owner-post).threaded {
      transform: translateX(0px) !important;
      transition: transform 0.3s ease !important;
      background: var(--bs-body-bg);
      background: var(--bs-body-navbar)!important;
      padding-right: 30px;
    }
    

    and other code, for example :

    .page-topic .topic .posts.timeline [component="topic/event"].timeline-event, .page-topic .topic .posts.timeline [component="topic/necro-post"].timeline-event {
        background: transparent;
    }
    
    .page-topic .topic .posts.timeline .timeline-event:last-child, .page-topic .topic .posts.timeline>[component="post/placeholder"]:last-child, .page-topic .topic .posts.timeline>[component=post]:last-child {
        margin-left: 0.5rem;
    }
    

    When I activate mode it works without problem but it does not disappear when I deactivate the mode. (Return to vanilla)

    I think I understand by reading the code that it is necessary to specify the classes chnaged in the function.js (with add .threaded) but I don’t really see how to add more

    f0208e5f-2863-48df-98a7-273e8a944377-image.png

    @DownPW said in Threading support for NodeBB:

    I think I understand by reading the code that it is necessary to specify the classes chnaged in the function.js (with add .threaded) but I don’t really see how to add more

    Can you post the current function code you have?

  • sure :

    function threaded() {
    $(document).ready(function () {
    // Check if the screen width is 1200px or more
    if ($(window).width() >= 1200) {
    // Check if the dropdown already exists
    if ($('#enableThreading').length === 0) {
    var threadView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
    <input class="form-check-input" id="enableThreading" type="checkbox" data-field="enableThreading"> \
    <label class=" d-none d-md-inline fw-semibold" for="enableThreading"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
    </div></form></div>');
    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
    // Check if there's a stored state for the checkbox and update it
    var storedState = localStorage.getItem('enableThreadingState');
    if (storedState === 'true') {
    $('#enableThreading').prop('checked', true);
    }
    }
    // Toggle the class 'threaded' on or off when the checkbox changes state
    $('#enableThreading').on('change', function () {
    var isChecked = $(this).is(':checked');
    if (isChecked) {
    console.log('Thread view is active.');
    $('ul[component="topic"]').addClass('threaded');
    $('.posts-container').addClass('threaded')
    $('ul[component="topic"]').addClass('threaded')
    $('.post-container').addClass('threaded')
    $('.timeline-event').addClass('threaded')
    $('[component="post/footer"]').addClass('threaded');
    $('[component="post"]').each(function () {
    // Add the 'threaded' class to matching elements
    if ($(this).hasClass('pt-4') || $(this).hasClass('self-post')) {
    $(this).addClass('threaded');
    $('.topic .sticky-tools').addClass('threaded');
    }
    });
    } else {
    console.log('Thread view is inactive.');
    $('[component="post"]').removeClass('threaded');
    $('ul[component="topic"]').removeClass('threaded');
    $('.posts-container').removeClass('threaded')
    $('ul[component="topic"]').removeClass('threaded')
    $('.post-container').removeClass('threaded')
    $('.timeline-event').removeClass('threaded')
    $('[component="post/footer"]').removeClass('threaded');
    $('.topic .sticky-tools').removeClass('threaded');
    }
    // Store the checkbox state in localStorage
    localStorage.setItem('enableThreadingState', isChecked);
    });
    // Check for changes in the checkbox state when the page loads
    $('#enableThreading').trigger('change');
    }
    });
    }
    function threadedChat() {
    $(document).ready(function () {
    // Check if the screen width is 1200px or more
    if ($(window).width() >= 1200) {
    // Check if the dropdown already exists
    if ($('#enableThreadingChat').length === 0) {
    var chatView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
    <input class="form-check-input" id="enableThreadingChat" type="checkbox" data-field="enableThreading"> \
    <label class=" d-none d-md-inline fw-semibold" for="enableThreadingChat"><span class="title-tooltip top" tooltip-text="Éditer Profil"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
    </div></form></div>');
    $('[component="chat/header"]').prepend(chatView);
    // Check if there's a stored state for the checkbox and update it
    var storedState = localStorage.getItem('enableThreadingStateChat');
    if (storedState === 'true') {
    $('#enableThreadingChat').prop('checked', true);
    }
    }
    // Toggle the class 'threaded' on or off when the checkbox changes state
    $('#enableThreadingChat').on('change', function () {
    var isChecked = $(this).is(':checked');
    if (isChecked) {
    console.log('Thread view is active.');
    $('[component="chat/message"]').each(function () {
    // Add the 'threaded' class to matching elements
    if ($(this).hasClass('chat-message')) {
    $(this).addClass('threaded');
    }
    });
    } else {
    console.log('Thread view is inactive.');
    $('[component="chat/message"]').removeClass('threaded');
    }
    // Store the checkbox state in localStorage
    localStorage.setItem('enableThreadingStateChat', isChecked);
    });
    // Check for changes in the checkbox state when the page loads
    $('#enableThreadingChat').trigger('change');
    }
    });
    }
    $(window).on('action:chat.loaded', function(data) {
    threadedChat();
    });
    $(window).on('action:chat.received', function(data) {
    threadedChat();
    });
    $(window).on('action:ajaxify.end', function (data) {
    threaded();
    });
    $(window).on('action:posts.edited', function (data) {
    threaded();
    });
    $(window).on('action:posts.loaded', function (data) {
    threaded();
    });
  • sure :

    function threaded() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreading').length === 0) {
                    var threadView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreading" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreading"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingState');
                    if (storedState === 'true') {
                        $('#enableThreading').prop('checked', true);
                    }
                }
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreading').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.posts-container').addClass('threaded')
                        $('ul[component="topic"]').addClass('threaded')
                        $('.post-container').addClass('threaded')
                        $('.timeline-event').addClass('threaded')
                        $('[component="post/footer"]').addClass('threaded');
                        $('[component="post"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('pt-4') || $(this).hasClass('self-post')) {
                                $(this).addClass('threaded');
                                $('.topic .sticky-tools').addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="post"]').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.posts-container').removeClass('threaded')
                        $('ul[component="topic"]').removeClass('threaded')
                        $('.post-container').removeClass('threaded')
                        $('.timeline-event').removeClass('threaded')
                        $('[component="post/footer"]').removeClass('threaded');
                        $('.topic .sticky-tools').removeClass('threaded');
                    }
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingState', isChecked);
                });
                // Check for changes in the checkbox state when the page loads
                $('#enableThreading').trigger('change');
            }
        });
    }
    
    function threadedChat() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreadingChat').length === 0) {
                    var chatView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreadingChat" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreadingChat"><span class="title-tooltip top" tooltip-text="Éditer Profil"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('[component="chat/header"]').prepend(chatView);
    
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingStateChat');
                    if (storedState === 'true') {
                        $('#enableThreadingChat').prop('checked', true);
                    }
                }
    
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreadingChat').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('[component="chat/message"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('chat-message')) {
                                $(this).addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="chat/message"]').removeClass('threaded');
                    }
    
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingStateChat', isChecked);
                });
    
                // Check for changes in the checkbox state when the page loads
                $('#enableThreadingChat').trigger('change');
            }
        });
    }
    
    
    $(window).on('action:chat.loaded', function(data) {
            threadedChat();
    });
    $(window).on('action:chat.received', function(data) {
            threadedChat();
    });
    $(window).on('action:ajaxify.end', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.edited', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        threaded();
    });
    

    @DownPW Thanks. You should remove the threadedChat function and these lines

    $(window).on('action:chat.loaded', function(data) {
    threadedChat();
    });
    $(window).on('action:chat.received', function(data) {
    threadedChat();
    });

    That code is not functional yet and is very experimental 🙂

    I’ll have a look at your DEV environment to make the code recommendations.

  • sure :

    function threaded() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreading').length === 0) {
                    var threadView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreading" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreading"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('.topic .sticky-tools ul [component="topic/browsing-users"]:last-of-type').append(threadView);
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingState');
                    if (storedState === 'true') {
                        $('#enableThreading').prop('checked', true);
                    }
                }
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreading').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('ul[component="topic"]').addClass('threaded');
                        $('.posts-container').addClass('threaded')
                        $('ul[component="topic"]').addClass('threaded')
                        $('.post-container').addClass('threaded')
                        $('.timeline-event').addClass('threaded')
                        $('[component="post/footer"]').addClass('threaded');
                        $('[component="post"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('pt-4') || $(this).hasClass('self-post')) {
                                $(this).addClass('threaded');
                                $('.topic .sticky-tools').addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="post"]').removeClass('threaded');
                        $('ul[component="topic"]').removeClass('threaded');
                        $('.posts-container').removeClass('threaded')
                        $('ul[component="topic"]').removeClass('threaded')
                        $('.post-container').removeClass('threaded')
                        $('.timeline-event').removeClass('threaded')
                        $('[component="post/footer"]').removeClass('threaded');
                        $('.topic .sticky-tools').removeClass('threaded');
                    }
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingState', isChecked);
                });
                // Check for changes in the checkbox state when the page loads
                $('#enableThreading').trigger('change');
            }
        });
    }
    
    function threadedChat() {
        $(document).ready(function () {
            // Check if the screen width is 1200px or more
            if ($(window).width() >= 1200) {
                // Check if the dropdown already exists
                if ($('#enableThreadingChat').length === 0) {
                    var chatView = $('<div class="threads-wrapper"><i class="fa fa-fw fa-bars left"></i><form class="form"><div class="form-check form-switch sticky-tools-bar"> \
                        <input class="form-check-input" id="enableThreadingChat" type="checkbox" data-field="enableThreading"> \
                        <label class=" d-none d-md-inline fw-semibold" for="enableThreadingChat"><span class="title-tooltip top" tooltip-text="Éditer Profil"><i class="fa fa-fw fa-bars-staggered right"></i></label> \
                    </div></form></div>');
                    $('[component="chat/header"]').prepend(chatView);
    
                    // Check if there's a stored state for the checkbox and update it
                    var storedState = localStorage.getItem('enableThreadingStateChat');
                    if (storedState === 'true') {
                        $('#enableThreadingChat').prop('checked', true);
                    }
                }
    
                // Toggle the class 'threaded' on or off when the checkbox changes state
                $('#enableThreadingChat').on('change', function () {
                    var isChecked = $(this).is(':checked');
                    if (isChecked) {
                        console.log('Thread view is active.');
                        $('[component="chat/message"]').each(function () {
                            // Add the 'threaded' class to matching elements
                            if ($(this).hasClass('chat-message')) {
                                $(this).addClass('threaded');
                            }
                        });
                    } else {
                        console.log('Thread view is inactive.');
                        $('[component="chat/message"]').removeClass('threaded');
                    }
    
                    // Store the checkbox state in localStorage
                    localStorage.setItem('enableThreadingStateChat', isChecked);
                });
    
                // Check for changes in the checkbox state when the page loads
                $('#enableThreadingChat').trigger('change');
            }
        });
    }
    
    
    $(window).on('action:chat.loaded', function(data) {
            threadedChat();
    });
    $(window).on('action:chat.received', function(data) {
            threadedChat();
    });
    $(window).on('action:ajaxify.end', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.edited', function (data) {
        threaded();
    });
    
    $(window).on('action:posts.loaded', function (data) {
        threaded();
    });
    

    @DownPW I changed your CSS as it was lacking the actual .threaded class which is the target we add and remove

    .page-topic .topic .posts.timeline [component="topic/event"].timeline-event, .page-topic .topic .posts.timeline [component="topic/necro-post"].timeline-event.threaded {
    background: transparent !important;
    margin-bottom: 10px !important;
    }
    .page-topic .topic .posts.timeline .threaded:last-child .timeline-event:last-child,
    .page-topic .topic .posts.timeline .threaded:last-child>[component="post/placeholder"]:last-child,
    .page-topic .topic .posts.timeline .threaded:last-child>[component=post]:last-child {
    margin-left: 0.5rem !important;
    }

    Seems to work, but can you confirm?



47/146

12 Sept 2023, 14:46


Threaded Replies

Related Topics
  • 19 Votes
    31 Posts
    2k Views
    @OT I honestly am not able to replicate this. Can you PM me a link to a post on your forum with the specific issue so I can have a look?
  • 5 Votes
    3 Posts
    1k Views
    Very good like always
  • 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.
  • 7 Votes
    18 Posts
    1k Views
    @Panda Just circling back here with something of an update (which I think you’ll like). I’ve completely restructured the ranking system. There are now less ranks, with a higher point threshold to reach them. More importantly, if you reload the site, you’ll notice that the ranks are now icons. I also removed the “Author” badge, and made this a single icon, which (to me) looks much better.
  • 2 Votes
    2 Posts
    255 Views
    @dave1904 that’s a really good point actually. I know it was there previously on Persona, but you’re right - no such function exists on harmony. However, putting something in place to mimick the behaviour of Persona won’t be hard from the js standpoint, although I wonder if perhaps we should ask the NodeBB developers is this feature was overlooked?
  • 11 Votes
    14 Posts
    1k Views
    @dave1904 excellent news. Thanks for the feedback
  • 3 Votes
    9 Posts
    829 Views
    The real issue here is that most people consider forums to be “dead” in the sense that nobody uses them anymore, and social media groups have taken their place. Their once dominant stance in the 90’s and early 00’s will never be experienced again, but having said that, there are a number of forums that did in fact survive the social media onslaught, and still enjoy a large user base. Forums tend to be niche. One that immediately sticks out is Reddit - despite looking like it was designed in the 80s, it still has an enormous user base. Another is Stack Overflow, which needs no introduction. The key to any forum is the content it offers, and the more people whom contribute in terms of posting , the more popular and widely respected it becomes as a reliable source of information. Forums are still intensely popular with gamers, alongside those that offer tips on hacking etc.
  • 1 Votes
    6 Posts
    1k Views
    @Hari not sure from the consumer perspective, but Skype has been all but completely consumed by Microsoft Teams when it comes to business usage.