diff --git a/client/src/app-components/articles-list.js b/client/src/app-components/articles-list.js
index 732e6ed7..2944b8c0 100644
--- a/client/src/app-components/articles-list.js
+++ b/client/src/app-components/articles-list.js
@@ -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() {
diff --git a/client/src/app/admin/panel/users/admin-panel-ban-users.js b/client/src/app/admin/panel/users/admin-panel-ban-users.js
index a368eeaf..49998052 100644
--- a/client/src/app/admin/panel/users/admin-panel-ban-users.js
+++ b/client/src/app/admin/panel/users/admin-panel-ban-users.js
@@ -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)
});
}
diff --git a/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.js b/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.js
index b798d2c2..36837ab9 100644
--- a/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.js
+++ b/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.js
@@ -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 (
-
+
-
+
+ {(!this.state.showSearchResults) ? this.renderArticleList() : this.renderSearchResults()}
);
}
+
+ renderArticleList() {
+ return (
+
+ );
+ }
+
+ renderSearchResults() {
+ return (
+
+ {(_.isEmpty(this.state.results)) ? i18n('NO_RESULTS') : this.state.results.map(this.renderSearchResultsItem.bind(this))}
+
+ );
+ }
+
+ renderSearchResultsItem(item) {
+ let content = this.stripHTML(item.content);
+ content = content.substring(0, 100);
+ content += '...';
+
+ return (
+
+
+ {item.title}
+
+
{content}
+
{item.topic}
+
+ );
+ }
+
+ 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);
diff --git a/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.scss b/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.scss
new file mode 100644
index 00000000..418797af
--- /dev/null
+++ b/client/src/app/main/dashboard/dashboard-list-articles/dashboard-list-articles-page.scss
@@ -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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/search-box.js b/client/src/core-components/search-box.js
index cdb34936..c3e04c9e 100644
--- a/client/src/core-components/search-box.js
+++ b/client/src/core-components/search-box.js
@@ -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);
}
});
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index 16b489b3..d29f9b03 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -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.',