From a4ace3f08e8ef16d5465c8eb1df9dc93d68bf6d3 Mon Sep 17 00:00:00 2001 From: Sam Date: Fri, 18 Sep 2015 17:16:10 +1000 Subject: [PATCH] FEATURE: ui for ordering search results in full page mode --- .../controllers/full-page-search.js.es6 | 72 +++++++++++++++++-- .../discourse/templates/full-page-search.hbs | 23 ++++++ .../stylesheets/common/base/search.scss | 39 ++++++++++ app/serializers/search_post_serializer.rb | 2 + config/locales/client.en.yml | 8 +++ 5 files changed, 139 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 b/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 index fa52b4122..ee55b5836 100644 --- a/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 +++ b/app/assets/javascripts/discourse/controllers/full-page-search.js.es6 @@ -3,6 +3,13 @@ import showModal from 'discourse/lib/show-modal'; import { default as computed, observes } from 'ember-addons/ember-computed-decorators'; import Category from 'discourse/models/category'; +const SortOrders = [ + {name: I18n.t('search.relevance'), id: 0}, + {name: I18n.t('search.latest_post'), id: 1, term: 'order:latest'}, + {name: I18n.t('search.most_liked'), id: 2, term: 'order:likes'}, + {name: I18n.t('search.most_viewed'), id: 3, term: 'order:views'}, +]; + export default Ember.Controller.extend({ needs: ["application"], @@ -13,6 +20,13 @@ export default Ember.Controller.extend({ context_id: null, context: null, searching: false, + sortOrder: 0, + sortOrders: SortOrders, + + @computed('model.posts') + resultCount(posts){ + return posts && posts.length; + }, @computed('q') hasAutofocus(q) { @@ -51,18 +65,61 @@ export default Ember.Controller.extend({ return !!(searching || !isValidSearchTerm(searchTerm)); }, + @computed('q') + noSortQ(q) { + if (q) { + SortOrders.forEach((order) => { + if (q.indexOf(order.term) > -1){ + q = q.replace(order.term, ""); + q = q.trim(); + } + }); + } + return q; + }, + + _searchOnSortChange: true, + + setSearchTerm(term) { + this._searchOnSortChange = false; + if (term) { + SortOrders.forEach((order) => { + if (term.indexOf(order.term) > -1){ + this.set('sortOrder', order.id); + term = term.replace(order.term, ""); + term = term.trim(); + } + }); + } + this._searchOnSortChange = true; + this.set('searchTerm', term); + }, + + @observes('sortOrder') + triggerSearch(){ + if (this._searchOnSortChange) { + this.search(); + } + }, + @observes('model') modelChanged() { if (this.get("searchTerm") !== this.get("q")) { - this.set("searchTerm", this.get("q")); + this.setSearchTerm(this.get("q")); } }, + @computed('q') + showLikeCount(q) { + console.log(q); + return q && q.indexOf("order:likes") > -1; + }, + @observes('q') qChanged() { const model = this.get("model"); if (model && this.get("model.q") !== this.get("q")) { - this.set("searchTerm", this.get("q")); + this.setSearchTerm(this.get("q")); this.send("search"); } }, @@ -80,11 +137,16 @@ export default Ember.Controller.extend({ const router = Discourse.__container__.lookup('router:main'); - this.set("q", this.get("searchTerm")); - this.set("model", null); - var args = { q: this.get("searchTerm") }; + const sortOrder = this.get("sortOrder"); + if (sortOrder && SortOrders[sortOrder].term) { + args.q += " " + SortOrders[sortOrder].term; + } + + this.set("q", args.q); + this.set("model", null); + const skip = this.get("skip_context"); if ((!skip && this.get('context')) || skip==="false"){ args.search_context = { diff --git a/app/assets/javascripts/discourse/templates/full-page-search.hbs b/app/assets/javascripts/discourse/templates/full-page-search.hbs index 13a16e145..c85fae3f7 100644 --- a/app/assets/javascripts/discourse/templates/full-page-search.hbs +++ b/app/assets/javascripts/discourse/templates/full-page-search.hbs @@ -37,6 +37,22 @@ {{/unless}} + {{#if model.posts}} +
+
+ + {{{i18n "search.result_count" count=resultCount term=noSortQ}}} + +
+
+ + {{i18n "search.sort_by"}} + + {{combo-box value=sortOrder content=sortOrders castInteger="true"}} +
+
+ {{/if}} + {{#each model.posts as |result|}}
@@ -65,6 +81,13 @@ {{/highlight-text}} {{/if}}
+ {{#if showLikeCount}} + {{#if result.like_count}} + + {{/if}} + {{/if}}
{{/each}} diff --git a/app/assets/stylesheets/common/base/search.scss b/app/assets/stylesheets/common/base/search.scss index d77d57ea1..a22ad9d0c 100644 --- a/app/assets/stylesheets/common/base/search.scss +++ b/app/assets/stylesheets/common/base/search.scss @@ -1,5 +1,10 @@ .fps-result { + .like-count { + color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%)); + .fa { color: $love; font-size: 12px; } + } + .badge-wrapper span.badge-category { max-width: inherit; } @@ -78,3 +83,37 @@ .panel-body-contents .search-context label { float: left; } + +.search-title { + + .term { + font-weight: bold; + } + + position: relative; + .result-count { + float: left; + span { + line-height: 28px; + height: 28px; + display: inline-block; + } + margin-bottom: 4px; + } + margin: 10px 0 15px; + max-width: 675px; + border-bottom: 3px solid dark-light-diff($primary, $secondary, 90%, -75%); + width: 100%; + .sort-by { + .desc { + margin-right: 5px; + } + select { + margin-bottom: 0; + width: auto; + min-width: 150px; + } + float: right; + margin-bottom: 4px; + } +} diff --git a/app/serializers/search_post_serializer.rb b/app/serializers/search_post_serializer.rb index 27fc4cdae..614ba8b79 100644 --- a/app/serializers/search_post_serializer.rb +++ b/app/serializers/search_post_serializer.rb @@ -2,6 +2,8 @@ class SearchPostSerializer < PostSerializer has_one :topic, serializer: TopicListItemSerializer + attributes :like_count + attributes :blurb def blurb options[:result].blurb(object) diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 63f225130..444eff15e 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -968,8 +968,16 @@ en: image_link: "link your image will point to" search: + sort_by: "Sort by" + relevance: "Relevance" + latest_post: "Latest Post" + most_viewed: "Most Viewed" + most_liked: "Most Liked" select_all: "Select All" clear_all: "Clear All" + result_count: + one: "1 result for \"{{term}}\"" + other: "{{count}} results for \"{{term}}\"" title: "search topics, posts, users, or categories" no_results: "No results found." no_more_results: "No more results found."