mirror of
https://github.com/documize/community.git
synced 2025-08-09 15:35:27 +02:00
search results UX
This commit is contained in:
parent
e173bccf52
commit
d17351c6e4
10 changed files with 157 additions and 90 deletions
|
@ -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);
|
||||
}
|
||||
});
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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}}
|
||||
{{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}}
|
||||
{{/layout/page-container}}
|
||||
</div>
|
||||
|
||||
{{/layout/zone-container}}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
padding: 15px 40px 15px 40px;
|
||||
|
||||
.content {
|
||||
|
||||
> .title {
|
||||
padding-left: 15px;
|
||||
font-size: 1rem;
|
||||
|
|
|
@ -1,43 +1,84 @@
|
|||
.page-search {
|
||||
margin: 30px 40px;
|
||||
|
||||
.search-results {
|
||||
margin-top: 50px;
|
||||
|
||||
.heading {
|
||||
font-size: 1.5rem;
|
||||
color: $color-primary;
|
||||
font-size: 1.2rem;
|
||||
color: $color-blue;
|
||||
}
|
||||
|
||||
> .search-list {
|
||||
@extend .cards-list;
|
||||
> .list {
|
||||
margin-top: 20px;
|
||||
list-style: none;
|
||||
|
||||
> .search-card {
|
||||
@extend .content-card;
|
||||
width: 220px;
|
||||
height: 200px;
|
||||
> .item {
|
||||
//width: 400px;
|
||||
//float: left;
|
||||
cursor: pointer;
|
||||
margin: 0 30px 30px 0;
|
||||
|
||||
.folder {
|
||||
font-size: 0.9rem;
|
||||
margin: 1.7rem 0 0 0;
|
||||
height: 1.2rem;
|
||||
overflow: hidden;
|
||||
color: $color-gray;
|
||||
}
|
||||
|
||||
.tags {
|
||||
font-size: 0.9rem;
|
||||
height: 1.2rem;
|
||||
overflow: hidden;
|
||||
color: $color-gray;
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
a, a:hover {
|
||||
> .link {
|
||||
text-decoration: none;
|
||||
color: $color-off-black;
|
||||
|
||||
&: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;
|
||||
}
|
||||
}
|
||||
|
||||
> .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: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 »</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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -279,6 +279,7 @@ type DocumentSearch struct {
|
|||
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"`
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue