FEATURE: Category filtering

This commit is contained in:
Justin DiRose 2019-11-06 11:27:30 -06:00
parent 42ac7bb984
commit 10ec8b47a8
9 changed files with 128 additions and 15 deletions

View File

@ -0,0 +1,12 @@
import { default as computed } from "ember-addons/ember-computed-decorators";
export default Ember.Component.extend({
@computed("category")
categoryName(category) {
return this.site.categories.findBy("id", category.id).name;
},
click() {
this.selectCategory(this.category);
return false;
}
});

View File

@ -16,7 +16,7 @@ function mergeCategories(results) {
export default Ember.Controller.extend({
application: Ember.inject.controller(),
queryParams: {
filterCategory: "category",
filterCategories: "category",
filterTags: "tags",
searchTerm: "search",
selectedTopic: "topic"
@ -25,10 +25,11 @@ export default Ember.Controller.extend({
isLoadingMore: false,
loadMoreUrl: Ember.computed.alias("model.topics.load_more_url"),
isTopicLoading: false,
categories: Ember.computed.readOnly("model.categories"),
topics: Ember.computed.alias("model.topics.topic_list.topics"),
tags: Ember.computed.readOnly("model.tags"),
filterTags: null,
filterCategory: null,
filterCategories: null,
searchTerm: null,
selectedTopic: null,
topic: null,
@ -93,6 +94,26 @@ export default Ember.Controller.extend({
this.send("refreshModel");
},
updateSelectedCategories(category) {
let filter = this.filterCategories;
if (filter && filter.includes(category.id)) {
filter = filter
.replace(category.id, "")
.replace("|", "|")
.replace(/^\|+|\|+$/g, "");
} else if (filter) {
filter = `${filter}|${category.id}`;
} else {
filter = category.id;
}
this.setProperties({
filterCategories: filter,
selectedTopic: null
});
this.send("refreshModel");
},
performSearch(term) {
if (term === "") {
@ -134,7 +155,7 @@ export default Ember.Controller.extend({
this.set("isLoading", true);
const params = this.getProperties(
"filterCategory",
"filterCategories",
"filterTags",
"searchTerm"
);

View File

@ -3,6 +3,8 @@ import { ajax } from "discourse/lib/ajax";
export default {
list(params) {
let filters = [];
if (params.filterCategories)
filters.push(`category=${params.filterCategories}`);
if (params.filterTags) filters.push(`tags=${params.filterTags}`);
if (params.searchTerm) filters.push(`search=${params.searchTerm}`);
if (params.page) filters.push(`page=${params.page}`);

View File

@ -0,0 +1,10 @@
<div class="knowledge-explorer-category {{if category.active 'selected'}}">
{{#unless category.active}}
{{d-icon "plus"}}
{{/unless}}
<span class="category-id">{{categoryName}}</span>
<span class="category-count">({{category.count}})</span>
{{#if category.active}}
{{d-icon "times-circle"}}
{{/if}}
</div>

View File

@ -5,13 +5,25 @@
}}
{{#conditional-loading-spinner condition=isLoading}}
<div class="knowledge-explorer-browse">
<div class="knowledge-explorer-tags">
{{#each tags as |tag|}}
{{knowledge-explorer-tag
tag=tag
selectTag=(action "updateSelectedTags")
}}
{{/each}}
<div class="knowledge-explorer-filters">
<div class="knowledge-explorer-categories">
<h3>{{i18n 'knowledge_explorer.categories'}}</h3>
{{#each categories as |category|}}
{{knowledge-explorer-category
category=category
selectCategory=(action "updateSelectedCategories")
}}
{{/each}}
</div>
<div class="knowledge-explorer-tags">
<h3>{{i18n 'knowledge_explorer.tags'}}</h3>
{{#each tags as |tag|}}
{{knowledge-explorer-tag
tag=tag
selectTag=(action "updateSelectedTags")
}}
{{/each}}
</div>
</div>
{{#if selectedTopic}}
{{#conditional-loading-spinner condition=isTopicLoading}}

View File

@ -28,13 +28,15 @@
padding-left: 10px;
}
}
.knowledge-explorer-tags {
.knowledge-explorer-filters {
flex-basis: 25%;
}
.knowledge-explorer-tags, .knowledge-explorer-categories {
padding: 10px 10px 10px 0;
a {
color: $primary;
}
.knowledge-explorer-tag {
.knowledge-explorer-tag, .knowledge-explorer-category {
display: flex;
align-items: center;
cursor: pointer;

View File

@ -2,6 +2,8 @@ en:
js:
knowledge_explorer:
title: "Knowledge Explorer"
categories: "Categories"
tags: "Tags"
search:
results:
one: "%{count} result found"

View File

@ -25,7 +25,7 @@ module KnowledgeExplorer
# filter results by selected category
if @filters[:category].present?
results = results.where('category_id IN (?)', @filters[:category])
results = results.where('category_id IN (?)', @filters[:category].split('|'))
end
# filter results by selected tags
@ -50,6 +50,7 @@ module KnowledgeExplorer
end
tags = tag_count(results)
categories = categories_count(results)
results_length = results.length
@ -75,7 +76,7 @@ module KnowledgeExplorer
topic_list['load_more_url'] = nil
end
{ tags: tags, topics: topic_list }
{ tags: tags, categories: categories, topics: topic_list }
end
def tag_count(results)
@ -96,6 +97,22 @@ module KnowledgeExplorer
tags.sort_by { |tag| [tag[:active] ? 0 : 1, -tag[:count]] }
end
def categories_count(results)
categories = []
results.each do |topic|
active = @filters[:category].include?(topic.category_id.to_s) if @filters[:category]
if categories.none? { |item| item[:id] == topic.category_id }
categories << { id: topic.category_id, count: 1, active: active || false }
else
category_index = categories.index(categories.find { |item| item[:id] == topic.category_id })
categories[category_index][:count] += 1
end
end
categories.sort_by { |category| [category[:active] ? 0 : 1, -category[:count]] }
end
def load_more_url
filters = []

View File

@ -63,7 +63,7 @@ describe KnowledgeExplorer::KnowledgeExplorerController do
end
context 'when filtering by tag' do
it 'should return a filtered list' do
it 'should return a list filtered by tag' do
get '/knowledge-explorer.json?tags=test'
expect(response.status).to eq(200)
@ -76,5 +76,40 @@ describe KnowledgeExplorer::KnowledgeExplorerController do
expect(topics.size).to eq(1)
end
end
context 'when filtering by category' do
let!(:category2) { Fabricate(:category) }
let!(:topic3) { Fabricate(:topic, category: category2) }
before do
SiteSetting.knowledge_explorer_categories = "#{category.id}|#{category2.id}"
end
it 'should return a list filtered by category' do
get "/knowledge-explorer.json?category=#{category2.id}"
expect(response.status).to eq(200)
json = JSON.parse(response.body)
categories = json['categories']
topics = json['topics']['topic_list']['topics']
expect(categories.size).to eq(1)
expect(topics.size).to eq(1)
end
end
context 'when searching' do
it 'should return a list filtered by search term in title' do
get "/knowledge-explorer.json?search=topic 1"
expect(response.status).to eq(200)
json = JSON.parse(response.body)
topics = json['topics']['topic_list']['topics']
expect(topics.size).to eq(1)
end
end
end
end