FEATURE: revamps search-menu layout (#6543)

This commit is contained in:
Joffrey JAFFEUX 2018-10-30 15:44:49 +01:00 committed by Kris
parent e32993f96c
commit 11ee07093c
4 changed files with 325 additions and 191 deletions

View File

@ -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);

View File

@ -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;
}
});

View File

@ -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%;

View File

@ -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;
}
}
}
}