mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 15:48:43 -05:00
Refactor search results to be components instead of views for reuse
This commit is contained in:
parent
76bfd723f6
commit
7ed309666b
21 changed files with 764 additions and 81 deletions
|
@ -0,0 +1,2 @@
|
|||
import SearchResult from 'discourse/components/search-result';
|
||||
export default SearchResult.extend();
|
|
@ -0,0 +1,2 @@
|
|||
import SearchResult from 'discourse/components/search-result';
|
||||
export default SearchResult.extend();
|
|
@ -0,0 +1,2 @@
|
|||
import SearchResult from 'discourse/components/search-result';
|
||||
export default SearchResult.extend();
|
|
@ -0,0 +1,2 @@
|
|||
import SearchResult from 'discourse/components/search-result';
|
||||
export default SearchResult.extend();
|
|
@ -0,0 +1,11 @@
|
|||
export default Ember.Component.extend({
|
||||
tagName: 'ul',
|
||||
|
||||
_highlightOnInsert: function() {
|
||||
const term = this.get('controller.term');
|
||||
if(!_.isEmpty(term)) {
|
||||
this.$('.blurb').highlight(term.split(/\s+/), {className: 'search-highlight'});
|
||||
this.$('.topic-title').highlight(term.split(/\s+/), {className: 'search-highlight'} );
|
||||
}
|
||||
}.on('didInsertElement')
|
||||
});
|
|
@ -0,0 +1,7 @@
|
|||
import TextField from 'discourse/components/text-field';
|
||||
|
||||
export default TextField.extend({
|
||||
placeholder: function() {
|
||||
return this.get('searchContextEnabled') ? "" : I18n.t('search.title');
|
||||
}.property('searchContextEnabled')
|
||||
});
|
|
@ -4,7 +4,7 @@ function searchForTerm(term, opts) {
|
|||
if (!opts) opts = {};
|
||||
|
||||
// Only include the data we have
|
||||
var data = { term: term, include_blurbs: 'true' };
|
||||
const data = { term: term, include_blurbs: 'true' };
|
||||
if (opts.typeFilter) data.type_filter = opts.typeFilter;
|
||||
if (opts.searchForId) data.search_for_id = true;
|
||||
|
||||
|
@ -22,7 +22,7 @@ function searchForTerm(term, opts) {
|
|||
if (!results.posts) { results.posts = []; }
|
||||
if (!results.categories) { results.categories = []; }
|
||||
|
||||
var topicMap = {};
|
||||
const topicMap = {};
|
||||
results.topics = results.topics.map(function(topic){
|
||||
topic = Topic.create(topic);
|
||||
topicMap[topic.id] = topic;
|
||||
|
@ -44,23 +44,23 @@ function searchForTerm(term, opts) {
|
|||
return Discourse.Category.list().findProperty('id', category.id);
|
||||
}).compact();
|
||||
|
||||
var r = results.grouped_search_result;
|
||||
const r = results.grouped_search_result;
|
||||
results.resultTypes = [];
|
||||
|
||||
// TODO: consider refactoring front end to take a better structure
|
||||
[['topic','posts'],['user','users'],['category','categories']].forEach(function(pair){
|
||||
var type = pair[0], name = pair[1];
|
||||
if(results[name].length > 0) {
|
||||
const type = pair[0], name = pair[1];
|
||||
if (results[name].length > 0) {
|
||||
results.resultTypes.push({
|
||||
results: results[name],
|
||||
displayType: (opts.searchContext && opts.searchContext.type === 'topic' && type === 'topic') ? 'post' : type,
|
||||
type: type,
|
||||
componentName: "search-result-" + ((opts.searchContext && opts.searchContext.type === 'topic' && type === 'topic') ? 'post' : type),
|
||||
type,
|
||||
more: r['more_' + name]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var noResults = !!(results.topics.length === 0 &&
|
||||
const noResults = !!(results.topics.length === 0 &&
|
||||
results.posts.length === 0 &&
|
||||
results.users.length === 0 &&
|
||||
results.categories.length === 0);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{{#each results as |result|}}
|
||||
<li>
|
||||
<a href='{{unbound result.url}}'>
|
||||
{{category-badge result}}
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
|
@ -0,0 +1,12 @@
|
|||
{{#each results as |result|}}
|
||||
<a class='search-link' href='{{unbound result.url}}'>
|
||||
<span class='topic'>
|
||||
{{i18n 'search.post_format' post_number=result.post_number username=result.username}}
|
||||
</span>
|
||||
{{#unless site.mobileView}}
|
||||
<span class='blurb'>
|
||||
{{{unbound result.blurb}}}
|
||||
</span>
|
||||
{{/unless}}
|
||||
</a>
|
||||
{{/each}}
|
|
@ -0,0 +1,14 @@
|
|||
{{#each results as |result|}}
|
||||
<li>
|
||||
<a class='search-link' href='{{unbound url}}'>
|
||||
<span class='topic'>
|
||||
{{topic-status topic=result.topic disableActions=true}}<span class='topic-title'>{{unbound result.topic.title}}</span>{{category-badge result.topic.category}}
|
||||
</span>
|
||||
{{#unless site.mobileView}}
|
||||
<span class='blurb'>
|
||||
{{format-age result.created_at}} - {{{unbound result.blurb}}}
|
||||
</span>
|
||||
{{/unless}}
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
|
@ -0,0 +1,8 @@
|
|||
{{#each results as |result|}}
|
||||
<li>
|
||||
<a href='{{unbound result.path}}'>
|
||||
{{avatar result imageSize="small"}}
|
||||
{{unbound result.username}}
|
||||
</a>
|
||||
</li>
|
||||
{{/each}}
|
|
@ -1,4 +1,5 @@
|
|||
{{view "search-text-field" value=term searchContextEnabled=searchContextEnabled searchContext=searchContext id="search-term"}}
|
||||
{{search-text-field value=term searchContextEnabled=searchContextEnabled id="search-term"}}
|
||||
|
||||
<div class="search-context">
|
||||
{{#if searchContext}}
|
||||
<label>
|
||||
|
@ -16,10 +17,10 @@
|
|||
{{i18n "search.no_results"}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{#each resultType in content.resultTypes}}
|
||||
{{#each content.resultTypes as |resultType|}}
|
||||
<ul>
|
||||
<li class="heading row">{{resultType.name}}</li>
|
||||
{{view "search-results-type" type=resultType.type displayType=resultType.displayType content=resultType.results}}
|
||||
{{component resultType.componentName results=resultType.results term=term}}
|
||||
</ul>
|
||||
<div class="no-results">
|
||||
{{#if resultType.more}}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<a href='{{unbound url}}'>
|
||||
{{category-badge this}}
|
||||
</a>
|
|
@ -1,10 +0,0 @@
|
|||
<a class='search-link' href='{{unbound url}}'>
|
||||
<span class='topic'>
|
||||
{{i18n 'search.post_format' post_number=post_number username=username}}
|
||||
</span>
|
||||
{{#unless controller.site.mobileView}}
|
||||
<span class='blurb'>
|
||||
{{{unbound blurb}}}
|
||||
</span>
|
||||
{{/unless}}
|
||||
</a>
|
|
@ -1,10 +0,0 @@
|
|||
<a class='search-link' href='{{unbound url}}'>
|
||||
<span class='topic'>
|
||||
{{topic-status topic=topic disableActions=true}}<span class='topic-title'>{{unbound topic.title}}</span>{{category-badge topic.category}}
|
||||
</span>
|
||||
{{#unless controller.site.mobileView}}
|
||||
<span class='blurb'>
|
||||
{{format-age created_at}} - {{{unbound blurb}}}
|
||||
</span>
|
||||
{{/unless}}
|
||||
</a>
|
|
@ -1,4 +0,0 @@
|
|||
<a href='{{unbound path}}'>
|
||||
{{avatar this imageSize="small"}}
|
||||
{{unbound username}}
|
||||
</a>
|
|
@ -1,15 +0,0 @@
|
|||
export default Ember.CollectionView.extend({
|
||||
tagName: 'ul',
|
||||
itemViewClass: Discourse.GroupedView.extend({
|
||||
tagName: 'li',
|
||||
classNameBindings: ['selected'],
|
||||
templateName: Discourse.computed.fmt('parentView.displayType', "search/%@_result")
|
||||
}),
|
||||
didInsertElement: function(){
|
||||
var term = this.get('controller.term');
|
||||
if(!_.isEmpty(term)) {
|
||||
this.$('.blurb').highlight(term.split(/\s+/), {className: 'search-highlight'});
|
||||
this.$('.topic-title').highlight(term.split(/\s+/), {className: 'search-highlight'} );
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,27 +0,0 @@
|
|||
/**
|
||||
This is a text field that supports a dynamic placeholder based on search context.
|
||||
|
||||
@class SearchTextField
|
||||
@extends Discourse.TextField
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
|
||||
import TextField from 'discourse/components/text-field';
|
||||
|
||||
export default TextField.extend({
|
||||
|
||||
/**
|
||||
A dynamic placeholder for the search field based on our context
|
||||
|
||||
@property placeholder
|
||||
**/
|
||||
placeholder: function() {
|
||||
|
||||
if(this.get('searchContextEnabled')){
|
||||
return "";
|
||||
}
|
||||
|
||||
return I18n.t('search.title');
|
||||
}.property('searchContextEnabled')
|
||||
});
|
|
@ -45,6 +45,7 @@
|
|||
//= require ./discourse/views/cloaked
|
||||
//= require ./discourse/components/combo-box
|
||||
//= require ./discourse/views/button
|
||||
//= require ./discourse/components/search-result
|
||||
//= require ./discourse/components/dropdown-button
|
||||
//= require ./discourse/components/notifications-button
|
||||
//= require ./discourse/components/topic-notifications-button
|
||||
|
|
18
test/javascripts/acceptance/search-test.js.es6
Normal file
18
test/javascripts/acceptance/search-test.js.es6
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { acceptance } from "helpers/qunit-helpers";
|
||||
acceptance("Search");
|
||||
|
||||
test("search", (assert) => {
|
||||
visit("/");
|
||||
|
||||
click('#search-button');
|
||||
|
||||
andThen(() => {
|
||||
assert.ok(exists('#search-term'), 'it shows the search bar');
|
||||
assert.ok(!exists('#search-dropdown .results ul li'), 'no results by default');
|
||||
});
|
||||
|
||||
fillIn('#search-term', 'dev');
|
||||
andThen(() => {
|
||||
assert.ok(exists('#search-dropdown .results ul li'), 'it shows results');
|
||||
});
|
||||
});
|
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue