1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-08-08 23:15:29 +02:00

search results UX

This commit is contained in:
Harvey Kandola 2016-07-01 18:53:56 -07:00
parent e173bccf52
commit d17351c6e4
10 changed files with 157 additions and 90 deletions

View file

@ -16,18 +16,28 @@ export default Ember.Component.extend({
resultPhrase: "",
didReceiveAttrs() {
let count = this.get('results').length;
let self = this;
let results = this.get('results');
let temp = _.groupBy(results, 'documentId');
let documents = [];
switch (count) {
case 0:
self.set("resultPhrase", "No results.");
break;
case 1:
self.set("resultPhrase", "1 reference found");
break;
default:
self.set("resultPhrase", `${count} references found`);
_.each(temp, function(document) {
documents.pushObject( {
doc: document[0],
ref: document
});
});
let phrase = 'Nothing found';
if (results.length > 0) {
let places = documents.length === 1 ? "place" : "places";
let references = results.length === 1 ? "secton" : "sections";
let i = results.length;
let j = documents.length;
phrase = `${i} ${references} in ${j} ${places}`;
}
this.set('resultPhrase', phrase);
this.set('documents', documents);
}
});

View file

@ -7,18 +7,16 @@ export default Ember.Controller.extend({
filter: "",
results: [],
filterResults(filter) {
onKeywordChange: function() {
Ember.run.debounce(this, this.fetch, 750);
}.observes('filter'),
fetch() {
this.audit.record('searched');
let self = this;
this.get('searchService').find(filter).then(function(response) {
this.get('searchService').find(this.get('filter')).then(function(response) {
self.set('results', response);
});
},
actions: {
onFilter(filter) {
this.filterResults(filter);
}
}
});

View file

@ -1,7 +1,17 @@
{{#header/page-navigation searchMode=true}}
{{header/search-box filter=filter onFilter=(action 'onFilter')}}
{{/header/page-navigation}}
{{#layout/zone-container}}
{{#layout/page-container}}
{{search/search-results results=results}}
{{/layout/page-container}}
{{layout/zone-navigation}}
{{#layout/zone-header title=session.appMeta.title message=session.appMeta.message}}
{{/layout/zone-header}}
<div class="page-search">
<div class="input-control">
<label>Search</label>
<div class="tip">#tags, keywords, "some phrase", keyword AND keyword, keyword OR keyword</div>
{{focus-input class="input" type="text" value=filter placeholder='start typing...'}}
</div>
{{search/search-results results=results}}
</div>
{{/layout/zone-container}}

View file

@ -12,7 +12,6 @@
padding: 15px 40px 15px 40px;
.content {
> .title {
padding-left: 15px;
font-size: 1rem;

View file

@ -1,44 +1,85 @@
.page-search {
margin: 30px 40px;
.search-results {
.heading {
font-size: 1.5rem;
color: $color-primary;
}
.search-results {
margin-top: 50px;
> .search-list {
@extend .cards-list;
margin-top: 20px;
.heading {
font-size: 1.2rem;
color: $color-blue;
}
> .search-card {
@extend .content-card;
width: 220px;
height: 200px;
cursor: pointer;
> .list {
margin-top: 20px;
list-style: none;
.folder {
font-size: 0.9rem;
margin: 1.7rem 0 0 0;
height: 1.2rem;
overflow: hidden;
color: $color-gray;
}
> .item {
//width: 400px;
//float: left;
cursor: pointer;
margin: 0 30px 30px 0;
.tags {
font-size: 0.9rem;
height: 1.2rem;
overflow: hidden;
color: $color-gray;
> .link {
text-decoration: none;
color: $color-off-black;
.tag {
display: inline-block;
margin-right: 5px;
&:hover {
color: $color-link;
}
> .title {
display: inline-block;
font-size: 1.2rem;
}
> .folder {
display: inline-block;
font-size: 0.8rem;
color: $color-gray;
margin-left: 15px;
}
> .excerpt {
margin-top: 1rem;
font-size: 0.9rem;
margin-left: 20px;
}
> .chips {
margin-top: 1rem;
margin-left: 20px;
}
}
}
a, a:hover {
text-decoration: none;
color: $color-off-black;
}
}
> .references {
margin-top: 1rem;
margin-left: 20px;
> .label {
font-size: 0.9rem;
color: $color-gray;
font-style: italic;
}
> .link {
font-size: 0.9rem;
color: $color-off-black;
&:hover {
color: $color-link;
text-decoration: underline;
}
&:after {
content: '·'
}
&:last-of-type:after {
content: ''
}
}
}
}
}
}
}

View file

@ -1,14 +1,21 @@
<div class="search-results">
<h2 class="heading">{{resultPhrase}}</h2>
<ul class="search-list">
{{#each results key="id" as |result index|}}
<li class="search-card">
<a href="s/{{result.folderId}}/{{result.folderSlug}}/d/{{ result.documentId }}/{{result.documentSlug}}?page={{ result.id }}">
<div class="title">{{ result.documentTitle }}</div>
<div class="snippet">{{ result.pageTitle }}</div>
<div class="folder">{{ result.folderName }}</div>
<div class="tags">{{search/tag-list documentTags=result.documentTags}}</div>
<ul class="list">
{{#each documents key="doc.id" as |result index|}}
<li class="item">
<a class="link" href="s/{{result.doc.folderId}}/{{result.doc.folderSlug}}/d/{{ result.doc.documentId }}/{{result.doc.documentSlug}}?page={{ result.doc.id }}">
<div class="title">{{ result.doc.documentTitle }}</div><div class="folder">{{ result.doc.folderName }}</div>
<div class="excerpt">{{ result.doc.documentExcerpt }}</div>
<div class="chips">{{search/tag-list documentTags=result.doc.documentTags}}</div>
</a>
<div class="references">
<span class="label">referenced &raquo;</span>
{{#each result.ref as |ref index|}}
<a class="link" href="s/{{result.doc.folderId}}/{{result.doc.folderSlug}}/d/{{ result.doc.documentId }}/{{result.doc.documentSlug}}?page={{ ref.id }}">
{{ref.pageTitle}}
</a>
{{/each}}
</div>
</li>
{{/each}}
</ul>

View file

@ -1,5 +1,7 @@
<div class="tags">
<div class="chips">
{{#each tagz as |tg|}}
<div class="tag">#{{tg}}</div>
<div class="chip">
<span class="chip-text">#{{tg}}</span>
</div>
{{/each}}
</div>

View file

@ -18,7 +18,6 @@ import (
"io/ioutil"
"net/http"
"net/url"
"strings"
"github.com/documize/community/documize/api/entity"
"github.com/documize/community/documize/api/plugins"
@ -54,6 +53,10 @@ func SearchDocuments(w http.ResponseWriter, r *http.Request) {
results[key] = result
}
if len(results) == 0 {
results = []entity.DocumentSearch{}
}
data, err := json.Marshal(results)
if err != nil {
@ -61,10 +64,6 @@ func SearchDocuments(w http.ResponseWriter, r *http.Request) {
return
}
if strings.ToLower(string(data)) == "null" {
data = []byte("[ ]")
}
writeSuccessBytes(w, data)
}

View file

@ -275,15 +275,16 @@ type Search struct {
// DocumentSearch represents 'presentable' search results.
type DocumentSearch struct {
ID string `json:"id"`
DocumentID string `json:"documentId"`
DocumentTitle string `json:"documentTitle"`
DocumentSlug string `json:"documentSlug"`
Tags string `json:"documentTags"`
PageTitle string `json:"pageTitle"`
LabelID string `json:"folderId"`
LabelName string `json:"folderName"`
FolderSlug string `json:"folderSlug"`
ID string `json:"id"`
DocumentID string `json:"documentId"`
DocumentTitle string `json:"documentTitle"`
DocumentSlug string `json:"documentSlug"`
DocumentExcerpt string `json:"documentExcerpt"`
Tags string `json:"documentTags"`
PageTitle string `json:"pageTitle"`
LabelID string `json:"folderId"`
LabelName string `json:"folderName"`
FolderSlug string `json:"folderSlug"`
}
// SiteMeta holds information associated with an Organization.

View file

@ -244,7 +244,7 @@ func (p *Persister) SearchDocument(keywords string) (results []entity.DocumentSe
}
sql := `SELECT search.id, documentid, pagetitle, document.labelid, document.title as documenttitle, document.tags,
COALESCE(label.label,'Unknown') AS labelname
COALESCE(label.label,'Unknown') AS labelname, document.excerpt as documentexcerpt
FROM search, document LEFT JOIN label ON label.orgid=document.orgid AND label.refid = document.labelid
WHERE search.documentid = document.refid AND search.orgid=? AND document.template=0 ` + tagQuery +
`AND document.labelid IN