Forum Discussion

DougS's avatar
DougS
Khoros Oracle
14 years ago

Threads with no replies Skip to end of metadata (Freemarker)

Description

This example shows how to render a list of the 5 most recent threads that have no replies in a custom Freemarker component. This example makes use of a core component that is available for rendering message lists based on a message REST API call. Some important points that this example demonstrates:

  • You can (and should) create custom text keys for all text you want to display in a component – that way you can easily localize for other languages.
  • Many core components can be called from within a custom component by using the <@component> directive.
  • The /search/messages REST API call lets you do a message search using the same query parameters that are used in a normal search through the UI. the openresponse=true query parameter is added to tell the search query to return only messages that have no replies.
  • The use of standard Lithium css classes that start with lia- can allow you to quickly style a component in a way that matches other components on the page.
  • There is a core component with the id forums.widget.message-list-panel that can be used to render a message list when given a valid REST API message list call.

 

Requirements

Lithium version 9.18 or higher, Lithium Studio

 

How to add this to a Lithium community

1.   Navigate to Lithium Studio

 

2.   The first thing we want to do is add a text key that we will pass into our message list component:
2a. Go to the Text Editor tab.
2b. Click the Search button.
2c. Enter the following custom text key and click the save button:

 

 

custom.top_five_threads_with_no_replies.title = Threads with no replies

 

3.  The next thing we will want to do is create our custom component:

3a. Go to the Components tab.
3b. Create a new component – name it whatever you like. I called it top-five-threads-with-no-replies.
3c. Add the following markup to the component and click the save button:

 

 

 

<#assign message_list_title = text.format("custom.top_five_threads_with_no_replies.title") />
<#assign results_list_size = 5 />
<#assign rest_query = "/search/messages?openresponse=true&sort_by=-topicPostDate&page_size=" + results_list_size />
<div class="lia-panel lia-panel-standard top-five-threads-with-no-replies-wrapper">
<@component id="forums.widget.message-list-panel" title="${message_list_title}" messages="rest_v1:"+rest_query style="wide" numMessages="conv:"+results_list_size />
</div>

 
4. Next we want to decide where on the community we want to place the new component we have created. In this example we'll place it only on the community page, in the "side-content" section of the page:

 

4a. Go to the Page tab – the "Community Page" should be selected in the "Page Type" drop-down, but select it if it is not.
4b. In the Components bar on the left, expand "Custom Components" and hover over the component you added, then click the "Add" link to add the component onto the page – the component will appear in the "common-header" section of the page. Hover over your components you just added until you see the 4-directional arrow icon appear then drag and drop the component into the "side-content" section of the page, between the "Admin Links" component and the "Image Moderation" component.
4c. Click the save button at the bottom of the Page tab to save your page changes.

5. Next let's look at our changes so far:

 

5a. Navigate to the community page. You should see the component on the left. If there are not any threads without one or more replies you will not see a message about there being "no posts to display". You will want to add some threads with no replies at this point.
5b. After you have added some threads with no replies, refresh the community page. You will most likely notice that the content of the component bleeds out of the right column – this is because we passed in "wide" to the "style" parameter of the "forums.widget.message-list-panel" component. This would be fine if we were placing the component on the wider left column of the page, but since we are placing it in the right column, we should change it to "slim".
5c. Go to the Components tab and click on the component you created.
5d. Change the "style" parameter of the "forums.widget.message-list-panel" component to "slim" and save – the markup will look like this now:

 

<#assign message_list_title = text.format("custom.top_five_threads_with_no_replies.title") />
<#assign results_list_size = 5 />
<#assign rest_query = "/search/messages?openresponse=true&sort_by=-topicPostDate&page_size=" + results_list_size />
<div class="lia-panel lia-panel-standard top-five-threads-with-no-replies-wrapper">
<@component id="forums.widget.message-list-panel" title="${message_list_title}" messages="rest_v1:"+rest_query style="slim" numMessages="conv:"+results_list_size />
</div>

 

Example

Go to the Code Sample 2 Example Page to see this in action.

 

  • We took this example, and added a widget that does both questions without reply and questions without solutions.  Here's our combined code.

     

    <div class="lia-panel lia-panel-standard custom-combined-unresolved-issues-wrapper">
      <form>
        <select style="margin: 0 0 10px 5px; background: none repeat scroll 0 0 #FFFFFF; border: 1px solid #808080; color: #333333;font-family: Arial; font-size: 12px; font-weight: normal;" id="combined_unresolved_select" name="unresolved_type" onchange="combined_handle_change(this.options[this.selectedIndex].value);">
          <option id="unresolved_issues_option" value="no_solutions">Questions Without Solutions</option>
          <option id="no_reply_option" value="no_replies">Questions Without Replies</option>
        </select>
      </form>
    </div>
    <div id="combined_no_replies_div" class="lia-panel lia-panel-standard top-fifteen-threads-with-no-replies-wrapper" style="visibility: hidden; display: none;">
    <#assign pid = coreNode.id />
    <#if pid != "">
    <#assign messages = rest("/boards/id/" + pid + "/search/messages?openresponse=true&include_forums=true&sort_by=-topicPostDate&page_size=15&restapi.response_style=view").messages />
    <ul>
        <#list messages.message as message>
                <li style="margin: 0 0 5px 10px;"><a href="${message.@view_href}"><img src="${skin.images.icon_thread.url}" class="lia-node-icon" style="float: left; margin-right: 10px;"/> ${message.subject}</a></li>
        </#list>
    </ul>   
    </#if>
    </div>
    <div id="combined_no_solutions_div" class="unresolved-issues-wrapper">
    <#if pid != "">
    <#assign threads = rest("/boards/id/" + pid + "/threads/recent?restapi.response_style=view&page_size=15").threads />
    <ul>
        <#list threads.thread as thread>
            <#if thread.solutions?size == 0 || thread.solutions.solution?size == 0>
                <li style="margin: 0 0 5px 10px;"><a href="${thread.@view_href}"><img src="${skin.images.icon_thread.url}" class="lia-node-icon" style="float: left; margin-right: 10px;"/> ${thread.messages.topic.subject}</a></li>
            </#if>
        </#list>
    </ul>   
    </#if>
    </div>
                                                                                   </div>
      <@liaAddScript>
        function combined_handle_change(option) {
            var no_replies_div = document.getElementById("combined_no_replies_div");
            var no_solutions_div = document.getElementById("combined_no_solutions_div");
            if (option == "no_solutions") {
                no_solutions_div.style.visibility = "visible";
                no_solutions_div.style.display = "inline";
                no_replies_div.style.visibility = "hidden";
                no_replies_div.style.display = "none";
            } else {
                no_replies_div.style.visibility = "visible";
                no_replies_div.style.display = "inline";
                no_solutions_div.style.visibility = "hidden";
                no_solutions_div.style.display = "none";
            }
        }
      </@liaAddScript>

     

  • HI Doug, this is great! I have two follow up questions:

     

    1. Can you provide the code if we wanted to limit the content to a particular board or category.

    2. Also, if we want the widget to exist on its own page, how would we go about doing that?

    • KaelaC's avatar
      KaelaC
      Lithium Alumni (Retired)

      Hi Wali -

       

      To limit the search to a category or board you will need to modify the rest call to include that scope.  For example, the call for a category page would look like this:

       

      /categories/id/[YOUR CATEGORY HERE]/search/messages/[QUERY STRING PARAMETERS]

      https://lithosphere.lithium.com/lithium/restapi/vc/categories/id/Forums/search/messages?openresponse=true&sort_by=-topicPostDate&page_size=10

      A board will be very similiar:

       

      /boards/id/[YOUR BOARD HERE]/search/messages/[QUERY STRING PARAMETERS]

       


      To put the component on a stand alone page, you will need to create a new page in studio (on the Page tab). Then add the component to that page.  Keep in mind custom pages are not tied to particular category/board. 

      • sgyani's avatar
        sgyani
        Mentor

        Hi Kaela,

         

        I am new to the lithosphere but found your post to be exactly what I am looking for - want to enable unanswered thread widget on a particular board. Below is my current component code, but can you please tell me where the board parameter string would go?

         

        <#assign message_list_title = text.format("custom.top_five_threads_with_no_replies.title") />
        <#assign results_list_size = 5 />
        <#assign rest_query = "/search/messages?openresponse=true&sort_by=-topicPostDate&page_size=" + results_list_size />
        <div class="lia-panel lia-panel-standard top-five-threads-with-no-replies-wrapper">
        <@component id="forums.widget.message-list-panel" title="${message_list_title}" messages="rest_v1:"+rest_query style="slim" numMessages="conv:"+results_list_size />
        </div>

  • Thanks for this, Doug. I was struggling to find where "openresponse" is documented. Are there other parameters one can pass to the search context? For example, would it be as trivial to search for threads that do not have an accepted solution? Thanks.
  • Is there a way to add a 'SUBJECT' and 'Posted' header title and a 'View All' link to this Custom Component?

     

    Like shown in the screen shot.

     

    LatestPostsComponent.png