WIP: Customize topic list per category


#1

I know my particular use case goes against some fundamentals of Discourse, so I don’t feel entitled to any help, but since I don’t have the programming chops to pull this off on my own, I had to throw this out there.

I’m trying to create a custom look and feel for my Games category. I have started by [adding thumbnails to the topic list][1]. By modifying [Sam’s personal “minimal” topic list design][2] and using an [example][3] from @JSey I was able to customize it just for that category (which I know is very risky and highly dependent on version changes).

My code so far is this:

<script type='text/x-handlebars' data-template-name='list/topic-list-item.raw'>


{{#if isGame}} //check to see if you are viewing the Games category
<td class='main-link clearfix'>
   {{raw "topic-status" topic=topic}}
    {{#if topic.image_url}}
    <a href="{{topic.url}}" class=topic-thumbnail style="background-image: url({{topic.image_url}});"></a>
     {{topic-link topic}}
    {{else}}
    {{topic-link topic}}
    {{/if}}

  {{#if controller.showTopicPostBadges}}
    {{raw "topic-post-badges" unread=topic.unread newPosts=topic.displayNewPosts unseen=topic.unseen url=topic.lastUnreadUrl}}
  {{/if}}

  {{raw "list/topic-excerpt" topic=model}}
  <div class='creator'>
  {{#if showCategory}}
     {{category-link topic.category}}
   {{/if}}

   {{raw "list/action-list" topic=topic postNumbers=topic.liked_post_numbers className="likes" icon="heart"}}
   </div>
</td>



{{#if controller.showLikes}}
<td class="num likes">
  {{number topic.like_count}} <i class='fa fa-heart'></i>
</td>
{{/if}}
   
{{#if controller.showOpLikes}}
<td class="num likes">
  {{number topic.op_like_count}} <i class='fa fa-heart'></i>
</td>
{{/if}}


{{raw "list/posts-count-column" topic=topic}}

<td class="last-post">
<div class='poster-avatar'>
<a href="{{topic.lastPostUr}}" data-user-card="{{topic.last_poster_username}}">{{avatar topic.lastPoster usernamePath="username" imageSize="medium"}}</a>
</div>

</td>

{{else}} 


{{#if controller.bulkSelectEnabled}}
<td class='star'>
  <input type="checkbox" class="bulk-select">
</td>
{{/if}}

<td class='main-link clearfix' colspan="{{titleColSpan}}">
  {{raw "topic-status" topic=topic}}
  {{topic-link topic}}
  {{#if controller.showTopicPostBadges}}
    {{raw "topic-post-badges" unread=topic.unread newPosts=topic.displayNewPosts unseen=topic.unseen url=topic.lastUnreadUrl}}
  {{/if}}
  {{#if expandPinned}}
    {{raw "list/topic-excerpt" topic=topic}}
  {{/if}}
  {{raw "list/action-list" topic=topic postNumbers=topic.liked_post_numbers className="likes" icon="heart"}}
</td>

{{#unless controller.hideCategory}}
  {{#unless topic.isPinnedUncategorized}}
    {{raw "list/category-column" category=topic.category}}
  {{/unless}}
{{/unless}}

{{#if controller.showPosters}}
  {{raw "list/posters-column" posters=topic.posters}}
{{/if}}

{{raw "list/posts-count-column" topic=topic}}

{{#if controller.showParticipants}}
  {{raw "list/posters-column" posters=topic.participants}}
{{/if}}

<td class="num views {{topic.viewsHeat}}">{{number topic.views numberKey="views_long"}}</td>

{{raw "list/activity-column" topic=topic class="num" tagName="td"}}
{{/if}}
</script>

<script type='text/x-handlebars' data-template-name='topic-list-header.raw'>

{{#if showLikes}}
  {{raw "topic-list-header-column" order='posts' name='topic.title'}}
  
  {{#if showLikes}}
     {{raw "topic-list-header-column" sortable='true' order='likes' number='true' forceName='Likes'}}
  {{/if}}
  {{#if showOpLikes}}
     {{raw "topic-list-header-column" sortable='true' order='op_likes' number='true' forceName='Likes'}}
  {{/if}}
  {{raw "topic-list-header-column" sortable='true' number='true' order='posts' forceName='Replies'}}
  {{raw "topic-list-header-column" sortable='true' order='activity' forceName='Last Post'}}

{{else}}  //use standard topic-list-header view

{{#if bulkSelectEnabled}}
<th class='star'>
  <button class='btn bulk-select' title='{{i18n "topics.bulk.toggle"}}'><i class='fa fa-list'></i></button>
</th>
{{/if}}
{{raw "topic-list-header-column" order='default' name='topic.title' showBulkToggle=toggleInTitle}}
{{#unless hideCategory}}
  {{raw "topic-list-header-column" sortable=sortable order='category' name='category_title'}}
{{/unless}}
{{#if showPosters}}
  {{raw "topic-list-header-column" order='posters' name='users'}}
{{/if}}
{{raw "topic-list-header-column" sortable=sortable number='true' order='posts' name='replies'}}
{{#if showParticipants}}
  {{raw "topic-list-header-column" order='participants' name='users'}}
{{/if}}

{{raw "topic-list-header-column" sortable=sortable number='true' order='views' name='views'}}
{{raw "topic-list-header-column" sortable=sortable number='true' order='activity' name='activity'}}
{{/if}}
</script>

<script>

Discourse.TopicListItemView.reopen({

    showCategory: function(){
        return !this.get('controller.hideCategory') &&
                this.get('topic.creator') &&
                this.get('topic.category.name') !== 'uncategorized';

    }.property(),

    isGame: function(){
        showOpLikes: true;
        return (window.location.pathname == '/c/games' || window.location.pathname == '/c/games/l/latest' || window.location.pathname == '/c/games/l/new' || window.location.pathname == '/c/games/l/unread' || window.location.pathname == '/c/games/l/top');
    }.property()
    
});

   Discourse.Topic.reopen({

       creator: function(){
           var poster = this.get('posters.firstObject');
           if(poster){
             return poster.user;
           }
       }.property(),
       lastPoster: function() {
           var poster = this.get('posters.lastObject');
           if(poster){
             if (this.last_poster_username === poster.user.username){
                 return poster.user;
             } else {
                 return this.get('creator');
             }
           }
       }.property('posters'),
       replyCount: function(){
           return this.get('posts_count') - 1;
       }.property(),
       hasReplies: function(){
           return this.get('posts_count') > 1;
       }.property()
   });
   
</script>

Essentially all I am doing is checking if you are viewing the Games category in a very sloppy way:


Discourse.TopicListItemView.reopen({
    
    isGame: function(){
        return (window.location.pathname == '/c/games' || window.location.pathname == '/c/games/l/latest' || window.location.pathname == '/c/games/l/new' || window.location.pathname == '/c/games/l/unread' || window.location.pathname == '/c/games/l/top');
    }.property()
    
});

###Problem #1: I know there is a cleaner way to do this, but my attempts failed.

I tried to use a similar check to load a different topic list header:

{{#if isGame}}
  {{raw "topic-list-header-column" order='posts' name='topic.title'}}
  
  {{#if showLikes}}
     {{raw "topic-list-header-column" sortable='true' order='likes' number='true' forceName='Likes'}}
  {{/if}}
  {{#if showOpLikes}}
     {{raw "topic-list-header-column" sortable='true' order='op_likes' number='true' forceName='Likes'}}
  {{/if}}
  {{raw "topic-list-header-column" sortable='true' number='true' order='posts' forceName='Replies'}}
  {{raw "topic-list-header-column" sortable='true' order='activity' forceName='Last Post'}}

{{else}}
...

###Problem #2: I don’t have a working check to change the header view

Once that check is done I essentially load a modified version of Sam’s code, with likes turned on using:

  Discourse.TopicListComponent.reopen({
        showLikes: true
 });

###Problem #3: I really would like showOpLikes, but whenever I tried that, the results were always 0, even if original post had a like (if I’m understanding how that is supposed to work).
You can see the end result of this [here][4]:

There are three more things that I would like to add to this if possible.

###Problem 4: I want to change the like column to be interactive so a user can click to like the game without having to enter the topic.

###Problem 5: I want to put a comment icon next to the reply count, but as usual, my attempts failed.

###Problem 6: I want to change “+ New Topic” label to “+ Add Game”

Once again, I don’t feel entitled to receive any help with this since this is very specific to me. I will hopefully be able to solve many of these problems on my own, and I will update my findings as I work on them. I just have been able to learn so much from this community, I didn’t think it would hurt to put this out there in the meantime.
[1]: Reddit Style picture thumbnail on the left
[2]: Sam’s personal “minimal” topic list design
[3]: How to determine category from a header customization?
[4]: http://talk.polygonalweave.com/c/games


(Mittineague) #2

That is fairly easy to do by having a plugin over-ride the client.en.yml file’s text value eg.
* very important. validate the yml file!

# custom-text

en:
  js:
    topic:
      create: "Add a Bear"


(Kane York) #3

Actually, what he wants to do is find the Handlebars file with topic.create and add an if-else.


(Mittineague) #4

Ah, Thanks, any more obvious and it would have my nose :nose: :dragon_face:

I see that in three files all under templates/navigation
category.hbs
categories.hbs
default.hbs
all have the same block

{{#if canCreateTopic}}
  {{d-button id="create-topic" class="btn-default" action="createTopic" icon="plus" label="topic.create"}}
{{/if}}

(Kane York) #5

Yep, @rewphus wants to modify category.hbs.


(Hannah Fordham) #6

I’m having a potentially-similar issue. If I use showOpLikes then I see nothing in the Likes column until I press the header to order by it. Then the Likes show fine.

On loading the page:

Then after clicking the Likes header:

But showLikes seems to work fine (as you found).


(Pad Pors) #7

could you make this customize topic list per category? especially the #4?

may you share the way you do it? or at least give me some hints how to do make such a thing?

thanks,


#8

I actually was never able to solve the majority of these problems, so I kind of gave up on this endeavor. There has been discussion in other topics regarding OpLikes not showing in the JSON, but I’m not sure if it’s related or not.


(Pad Pors) #9

thanks, another question: I want to change the topic-list-item for a specific category and it’s not working. do you have any idea why?

the script is this:

var TopicListComponent = require('discourse/components/topic-list').default;
TopicListComponent.reopen({
     isRamin: function(){
    showLikes: true;
         
     }
});

to show likes for subcategory “Ramin”.