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.',