Ivan - Add search article list [skip ci]

This commit is contained in:
Ivan Diaz 2016-12-04 14:10:16 -03:00
parent c774df46f4
commit b4b94a883e
6 changed files with 138 additions and 11 deletions

View File

@ -18,15 +18,19 @@ class ArticlesList extends React.Component {
editable: React.PropTypes.bool,
articlePath: React.PropTypes.string,
loading: React.PropTypes.bool,
topics: React.PropTypes.array
topics: React.PropTypes.array,
retrieveOnMount: React.PropTypes.bool
};
static defaultProps = {
editable: true
editable: true,
retrieveOnMount: true
};
componentDidMount() {
this.retrieveArticles();
if(this.props.retrieveOnMount) {
this.retrieveArticles();
}
}
render() {

View File

@ -1,4 +1,5 @@
import React from 'react';
import _ from 'react';
import i18n from 'lib-app/i18n';
import API from 'lib-app/api-call';
@ -79,7 +80,7 @@ class AdminPanelBanUsers extends React.Component {
onSearch(query) {
this.setState({
filteredEmails: SearchBox.searchQueryInList(this.state.emails, query)
filteredEmails: SearchBox.searchQueryInList(this.state.emails, query, _.startsWith, _.includes)
});
}

View File

@ -1,19 +1,109 @@
import React from 'react';
import {connect} from 'react-redux';
import _ from 'lodash';
import {Link} from 'react-router';
import i18n from 'lib-app/i18n';
import ArticlesList from 'app-components/articles-list';
import ArticlesActions from 'actions/articles-actions';
import Header from 'core-components/header';
import SearchBox from 'core-components/search-box';
class DashboardListArticlesPage extends React.Component {
state = {
results: [],
showSearchResults: false
};
componentDidMount() {
this.props.dispatch(ArticlesActions.retrieveArticles());
}
render() {
return (
<div>
<div classnames="dashboard-list-articles-page">
<Header title={i18n('LIST_ARTICLES')} description={i18n('LIST_ARTICLES_DESCRIPTION')}/>
<ArticlesList editable={false} articlePath="/dashboard/article/"/>
<SearchBox className="dashboard-list-articles-page__search-box" onSearch={this.onSearch.bind(this)} searchOnType />
{(!this.state.showSearchResults) ? this.renderArticleList() : this.renderSearchResults()}
</div>
);
}
renderArticleList() {
return (
<ArticlesList editable={false} articlePath="/dashboard/article/" retrieveOnMount={false}/>
);
}
renderSearchResults() {
return (
<div className="dashboard-list-articles-page__search-results">
{(_.isEmpty(this.state.results)) ? i18n('NO_RESULTS') : this.state.results.map(this.renderSearchResultsItem.bind(this))}
</div>
);
}
renderSearchResultsItem(item) {
let content = this.stripHTML(item.content);
content = content.substring(0, 100);
content += '...';
return (
<div className="dashboard-list-articles-page__search-result">
<div className="dashboard-list-articles-page__search-result-title">
<Link to={'/dashboard/article/' + item.id}>{item.title}</Link>
</div>
<div className="dashboard-list-articles-page__search-result-description">{content}</div>
<div className="dashboard-list-articles-page__search-result-topic">{item.topic}</div>
</div>
);
}
onSearch(query) {
this.setState({
results: SearchBox.searchQueryInList(this.getArticles(), query, this.isQueryInTitle.bind(this), this.isQueryInContent.bind(this)),
showSearchResults: query.length
});
}
getArticles() {
let articles = [];
_.forEach(this.props.topics, (topic) => {
_.forEach(topic.articles, (article) => {
articles.push({
id: article.id,
title: article.title,
content: article.content,
topic: topic.name
});
});
});
return articles;
}
isQueryInTitle(article, query) {
return _.includes(article.title.toLowerCase(), query.toLowerCase());
}
isQueryInContent(article, query) {
return _.includes(article.content.toLowerCase(), query.toLowerCase());
}
stripHTML(html){
let tmp = document.createElement('DIV');
tmp.innerHTML = html;
return tmp.textContent || tmp.innerText || "";
}
}
export default DashboardListArticlesPage;
export default connect((store) => {
return {
topics: store.articles.topics,
loading: store.articles.loading
};
})(DashboardListArticlesPage);

View File

@ -0,0 +1,32 @@
@import "../../../../scss/vars";
.dashboard-list-articles-page {
&__search-results {
}
&__search-box {
margin-bottom: 30px;
}
&__search-result {
margin-bottom: 20px;
text-align: left;
&-title {
}
&-description {
font-size: $font-size--xs;
margin: 5px 0;
}
&-topic {
color: $grey;
font-size: $font-size--sm;
text-transform: uppercase;
}
}
}

View File

@ -1,6 +1,5 @@
import React from 'react';
import classNames from 'classnames';
import _ from 'lodash';
import Input from 'core-components/input';
import Icon from 'core-components/icon';
@ -8,12 +7,12 @@ import keyCode from 'keycode';
class SearchBox extends React.Component {
static searchQueryInList(list, query) {
static searchQueryInList(list, query, startsWith, includes) {
let match = [];
let rest = [];
list.forEach(function (item) {
if(_.startsWith(item, query)) {
if(startsWith(item, query)) {
match.push(item);
} else {
rest.push(item);
@ -21,7 +20,7 @@ class SearchBox extends React.Component {
});
rest.forEach(function (item) {
if(_.includes(item, query)) {
if(includes(item, query)) {
match.push(item);
}
});

View File

@ -92,6 +92,7 @@ export default {
'ADD_ARTICLE': 'Add article',
'LAST_EDITED_IN': 'Last edited in {date}',
'EDIT': 'Edit',
'NO_RESULTS': 'No results',
//VIEW DESCRIPTIONS
'CREATE_TICKET_DESCRIPTION': 'This is a form for creating tickets. Fill the form and send us your issues/doubts/suggestions. Our support system will answer it as soon as possible.',