FEATURE: revamps search-menu layout (#6543)
This commit is contained in:
parent
e32993f96c
commit
11ee07093c
|
@ -9,24 +9,13 @@ import Post from "discourse/models/post";
|
|||
import Topic from "discourse/models/topic";
|
||||
|
||||
export function translateResults(results, opts) {
|
||||
if (!opts) opts = {};
|
||||
opts = opts || {};
|
||||
|
||||
// Topics might not be included
|
||||
if (!results.topics) {
|
||||
results.topics = [];
|
||||
}
|
||||
if (!results.users) {
|
||||
results.users = [];
|
||||
}
|
||||
if (!results.posts) {
|
||||
results.posts = [];
|
||||
}
|
||||
if (!results.categories) {
|
||||
results.categories = [];
|
||||
}
|
||||
if (!results.tags) {
|
||||
results.tags = [];
|
||||
}
|
||||
results.topics = results.topics || [];
|
||||
results.users = results.users || [];
|
||||
results.posts = results.posts || [];
|
||||
results.categories = results.categories || [];
|
||||
results.tags = results.tags || [];
|
||||
|
||||
const topicMap = {};
|
||||
results.topics = results.topics.map(function(topic) {
|
||||
|
@ -45,8 +34,7 @@ export function translateResults(results, opts) {
|
|||
});
|
||||
|
||||
results.users = results.users.map(function(user) {
|
||||
user = User.create(user);
|
||||
return user;
|
||||
return User.create(user);
|
||||
});
|
||||
|
||||
results.categories = results.categories
|
||||
|
@ -57,7 +45,7 @@ export function translateResults(results, opts) {
|
|||
|
||||
results.tags = results.tags
|
||||
.map(function(tag) {
|
||||
let tagName = Handlebars.Utils.escapeExpression(tag.name);
|
||||
const tagName = Handlebars.Utils.escapeExpression(tag.name);
|
||||
return Ember.Object.create({
|
||||
id: tagName,
|
||||
url: Discourse.getURL("/tags/" + tagName)
|
||||
|
@ -65,31 +53,31 @@ export function translateResults(results, opts) {
|
|||
})
|
||||
.compact();
|
||||
|
||||
const r = results.grouped_search_result;
|
||||
results.resultTypes = [];
|
||||
|
||||
// TODO: consider refactoring front end to take a better structure
|
||||
if (r) {
|
||||
const groupedSearchResult = results.grouped_search_result;
|
||||
if (groupedSearchResult) {
|
||||
[
|
||||
["topic", "posts"],
|
||||
["user", "users"],
|
||||
["category", "categories"],
|
||||
["tag", "tags"]
|
||||
["tag", "tags"],
|
||||
["user", "users"]
|
||||
].forEach(function(pair) {
|
||||
const type = pair[0],
|
||||
name = pair[1];
|
||||
const type = pair[0];
|
||||
const name = pair[1];
|
||||
if (results[name].length > 0) {
|
||||
var result = {
|
||||
const componentName =
|
||||
opts.searchContext &&
|
||||
opts.searchContext.type === "topic" &&
|
||||
type === "topic"
|
||||
? "post"
|
||||
: type;
|
||||
const result = {
|
||||
results: results[name],
|
||||
componentName:
|
||||
"search-result-" +
|
||||
(opts.searchContext &&
|
||||
opts.searchContext.type === "topic" &&
|
||||
type === "topic"
|
||||
? "post"
|
||||
: type),
|
||||
componentName: `search-result-${componentName}`,
|
||||
type,
|
||||
more: r["more_" + name]
|
||||
more: groupedSearchResult[`more_${name}`]
|
||||
};
|
||||
|
||||
if (result.more && name === "posts" && opts.fullSearchUrl) {
|
||||
|
@ -103,10 +91,10 @@ export function translateResults(results, opts) {
|
|||
}
|
||||
|
||||
const noResults = !!(
|
||||
results.topics.length === 0 &&
|
||||
results.posts.length === 0 &&
|
||||
results.users.length === 0 &&
|
||||
results.categories.length === 0
|
||||
!results.topics.length &&
|
||||
!results.posts.length &&
|
||||
!results.users.length &&
|
||||
!results.categories.length
|
||||
);
|
||||
|
||||
return noResults ? null : Em.Object.create(results);
|
||||
|
|
|
@ -3,7 +3,6 @@ import { dateNode } from "discourse/helpers/node";
|
|||
import RawHtml from "discourse/widgets/raw-html";
|
||||
import { createWidget } from "discourse/widgets/widget";
|
||||
import { h } from "virtual-dom";
|
||||
import { iconNode } from "discourse-common/lib/icon-library";
|
||||
import highlightText from "discourse/lib/highlight-text";
|
||||
import { escapeExpression, formatUsername } from "discourse/lib/utilities";
|
||||
|
||||
|
@ -20,6 +19,8 @@ class Highlighted extends RawHtml {
|
|||
|
||||
function createSearchResult({ type, linkField, builder }) {
|
||||
return createWidget(`search-result-${type}`, {
|
||||
tagName: "ul.list",
|
||||
|
||||
html(attrs) {
|
||||
return attrs.results.map(r => {
|
||||
let searchResultId;
|
||||
|
@ -31,7 +32,7 @@ function createSearchResult({ type, linkField, builder }) {
|
|||
}
|
||||
|
||||
return h(
|
||||
"li",
|
||||
"li.item",
|
||||
this.attach("link", {
|
||||
href: r.get(linkField),
|
||||
contents: () => builder.call(this, r, attrs.term),
|
||||
|
@ -54,7 +55,7 @@ function postResult(result, link, term) {
|
|||
html.push(
|
||||
h("span.blurb", [
|
||||
dateNode(result.created_at),
|
||||
" - ",
|
||||
h("span", " - "),
|
||||
new Highlighted(result.blurb, term)
|
||||
])
|
||||
);
|
||||
|
@ -63,20 +64,51 @@ function postResult(result, link, term) {
|
|||
return html;
|
||||
}
|
||||
|
||||
createSearchResult({
|
||||
type: "tag",
|
||||
linkField: "url",
|
||||
builder(t) {
|
||||
const tag = escapeExpression(t.get("id"));
|
||||
return h(
|
||||
"a",
|
||||
{
|
||||
attributes: { href: t.get("url") },
|
||||
className: `widget-link search-link tag-${tag} discourse-tag ${
|
||||
Discourse.SiteSettings.tag_style
|
||||
}`
|
||||
},
|
||||
tag
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
createSearchResult({
|
||||
type: "category",
|
||||
linkField: "url",
|
||||
builder(c) {
|
||||
return this.attach("category-link", { category: c, link: false });
|
||||
}
|
||||
});
|
||||
|
||||
createSearchResult({
|
||||
type: "user",
|
||||
linkField: "path",
|
||||
builder(u) {
|
||||
return [
|
||||
const userTitles = [h("span.username", formatUsername(u.username))];
|
||||
|
||||
if (u.name) {
|
||||
userTitles.push(h("span.name", u.name));
|
||||
}
|
||||
|
||||
const userResultContents = [
|
||||
avatarImg("small", {
|
||||
template: u.avatar_template,
|
||||
username: u.username
|
||||
}),
|
||||
" ",
|
||||
h("span.user-results", h("b", formatUsername(u.username))),
|
||||
" ",
|
||||
h("span.user-results", u.name ? u.name : "")
|
||||
h("div.user-titles", userTitles)
|
||||
];
|
||||
|
||||
return h("div.user-result", userResultContents);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -111,32 +143,6 @@ createSearchResult({
|
|||
}
|
||||
});
|
||||
|
||||
createSearchResult({
|
||||
type: "category",
|
||||
linkField: "url",
|
||||
builder(c) {
|
||||
return this.attach("category-link", { category: c, link: false });
|
||||
}
|
||||
});
|
||||
|
||||
createSearchResult({
|
||||
type: "tag",
|
||||
linkField: "url",
|
||||
builder(t) {
|
||||
const tag = escapeExpression(t.get("id"));
|
||||
return h(
|
||||
"a",
|
||||
{
|
||||
attributes: { href: t.get("url") },
|
||||
className: `tag-${tag} discourse-tag ${
|
||||
Discourse.SiteSettings.tag_style
|
||||
}`
|
||||
},
|
||||
tag
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
createWidget("search-menu-results", {
|
||||
tagName: "div.results",
|
||||
|
||||
|
@ -151,12 +157,26 @@ createWidget("search-menu-results", {
|
|||
|
||||
const results = attrs.results;
|
||||
const resultTypes = results.resultTypes || [];
|
||||
return resultTypes.map(rt => {
|
||||
|
||||
const mainResultsContent = [];
|
||||
const classificationContents = [];
|
||||
const otherContents = [];
|
||||
const assignContainer = (type, node) => {
|
||||
if (["topic"].includes(type)) {
|
||||
mainResultsContent.push(node);
|
||||
} else if (["category", "tag"].includes(type)) {
|
||||
classificationContents.push(node);
|
||||
} else {
|
||||
otherContents.push(node);
|
||||
}
|
||||
};
|
||||
|
||||
resultTypes.forEach(rt => {
|
||||
const more = [];
|
||||
|
||||
const moreArgs = {
|
||||
className: "filter",
|
||||
contents: () => [I18n.t("show_more"), " ", iconNode("chevron-down")]
|
||||
contents: () => [I18n.t("more"), "..."]
|
||||
};
|
||||
|
||||
if (rt.moreUrl) {
|
||||
|
@ -176,22 +196,54 @@ createWidget("search-menu-results", {
|
|||
);
|
||||
}
|
||||
|
||||
let resultNode = [
|
||||
h(
|
||||
"ul",
|
||||
this.attach(rt.componentName, {
|
||||
searchContextEnabled: attrs.searchContextEnabled,
|
||||
searchLogId: attrs.results.grouped_search_result.search_log_id,
|
||||
results: rt.results,
|
||||
term: attrs.term
|
||||
})
|
||||
)
|
||||
const resultNodeContents = [
|
||||
this.attach(rt.componentName, {
|
||||
searchContextEnabled: attrs.searchContextEnabled,
|
||||
searchLogId: attrs.results.grouped_search_result.search_log_id,
|
||||
results: rt.results,
|
||||
term: attrs.term
|
||||
})
|
||||
];
|
||||
|
||||
if (more.length) {
|
||||
resultNode.push(h("div.no-results", more));
|
||||
resultNodeContents.push(h("div.show-more", more));
|
||||
}
|
||||
|
||||
return resultNode;
|
||||
assignContainer(
|
||||
rt.type,
|
||||
h(`div.${rt.componentName}`, resultNodeContents)
|
||||
);
|
||||
});
|
||||
|
||||
const content = [];
|
||||
|
||||
if (mainResultsContent.length) {
|
||||
content.push(h("div.main-results", mainResultsContent));
|
||||
}
|
||||
|
||||
if (classificationContents.length || otherContents.length) {
|
||||
const secondaryResultsContent = [];
|
||||
|
||||
if (classificationContents.length) {
|
||||
secondaryResultsContent.push(
|
||||
h("div.classification-results", classificationContents)
|
||||
);
|
||||
}
|
||||
|
||||
if (otherContents.length) {
|
||||
secondaryResultsContent.push(h("div.other-results", otherContents));
|
||||
}
|
||||
|
||||
content.push(
|
||||
h(
|
||||
`div.secondary-results${
|
||||
mainResultsContent.length ? "" : ".no-main-results"
|
||||
}`,
|
||||
secondaryResultsContent
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -131,110 +131,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.search-menu {
|
||||
.search-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-context .show-help {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.heading {
|
||||
padding: 5px 0 5px 5px;
|
||||
.filter {
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
margin: 0.5em 3px;
|
||||
box-sizing: border-box;
|
||||
width: calc(100% - 6px);
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.search-context {
|
||||
padding: 0 5px;
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.searching {
|
||||
position: absolute;
|
||||
top: 1.15em;
|
||||
right: 1em;
|
||||
|
||||
.spinner {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-width: 2px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
// I am ghetto using this to display "Show More".. be warned
|
||||
.no-results {
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.filter {
|
||||
padding: 0;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.search-link {
|
||||
.badge-category-parent {
|
||||
line-height: $line-height-small;
|
||||
}
|
||||
.topic-title {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.topic-statuses {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
color: dark-light-choose($primary-medium, $secondary-medium);
|
||||
margin: 0;
|
||||
.fa {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li:not(.category):not(.heading) {
|
||||
font-size: $font-0;
|
||||
line-height: $line-height-medium;
|
||||
|
||||
.fa {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
a {
|
||||
&:not(.discourse-tag) {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
}
|
||||
transition: all linear 0.15s;
|
||||
|
||||
.user-results {
|
||||
color: dark-light-choose($primary-high, $secondary-low);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover a:not(.badge-notification) {
|
||||
background-color: $highlight-medium;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-menu {
|
||||
.notifications {
|
||||
width: 100%;
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
.search-menu {
|
||||
.search-input {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-context .show-help {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.heading {
|
||||
padding: 5px 0 5px 5px;
|
||||
.filter {
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
margin: 0.5em 3px;
|
||||
box-sizing: border-box;
|
||||
width: calc(100% - 6px);
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.search-context {
|
||||
padding: 0 5px;
|
||||
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.search-context + .results {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.results {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.list {
|
||||
.item {
|
||||
.blurb {
|
||||
// https://css-tricks.com/snippets/css/prevent-long-urls-from-breaking-out-of-container/
|
||||
overflow-wrap: break-word;
|
||||
word-wrap: break-word;
|
||||
-ms-word-break: break-all;
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
-ms-hyphens: auto;
|
||||
-moz-hyphens: auto;
|
||||
-webkit-hyphens: auto;
|
||||
hyphens: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-results {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.main-results + .secondary-results {
|
||||
border-left: 1px solid $primary-low;
|
||||
margin-left: 1em;
|
||||
padding-left: 1em;
|
||||
max-width: 33%;
|
||||
}
|
||||
|
||||
.secondary-results {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
.classification-results {
|
||||
border-bottom: 1px solid $primary-low;
|
||||
margin-bottom: 1em;
|
||||
padding-bottom: 1em;
|
||||
}
|
||||
|
||||
.search-result-category {
|
||||
}
|
||||
|
||||
.search-result-tag {
|
||||
.list {
|
||||
.item {
|
||||
display: inline-flex;
|
||||
|
||||
.widget-link.search-link {
|
||||
display: inline;
|
||||
font-size: $font-0;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-result-user {
|
||||
.user-result {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.avatar {
|
||||
margin-right: 0.5em;
|
||||
display: block;
|
||||
min-width: 25px;
|
||||
}
|
||||
|
||||
.user-titles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: auto;
|
||||
|
||||
.username,
|
||||
.name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.username {
|
||||
color: dark-light-choose($primary-high, $secondary-low);
|
||||
font-size: $font-0;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.name {
|
||||
color: dark-light-choose($primary-high, $secondary-low);
|
||||
font-size: $font-down-1;
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.no-main-results .search-result-user {
|
||||
.user-titles {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.name {
|
||||
margin: 0 0 0 0.25em;
|
||||
font-size: $font-0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.show-more {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.searching {
|
||||
position: absolute;
|
||||
top: 1.15em;
|
||||
right: 1em;
|
||||
|
||||
.spinner {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-width: 2px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.no-results {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.filter {
|
||||
padding: 0;
|
||||
&:hover {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.search-link {
|
||||
.badge-category-parent {
|
||||
line-height: $line-height-small;
|
||||
}
|
||||
|
||||
.topic-title {
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
|
||||
.topic-statuses {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
color: dark-light-choose($primary-medium, $secondary-medium);
|
||||
margin: 0;
|
||||
|
||||
.fa {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue