);
}
diff --git a/client/src/app/admin/panel/articles/admin-panel-list-articles.scss b/client/src/app/admin/panel/articles/admin-panel-list-articles.scss
new file mode 100644
index 00000000..1807e990
--- /dev/null
+++ b/client/src/app/admin/panel/articles/admin-panel-list-articles.scss
@@ -0,0 +1,6 @@
+.admin-panel-list-articles {
+
+ &__list {
+ padding: 0 50px;
+ }
+}
\ No newline at end of file
diff --git a/client/src/app/admin/panel/articles/admin-panel-view-article.js b/client/src/app/admin/panel/articles/admin-panel-view-article.js
index fa026870..a023e8e5 100644
--- a/client/src/app/admin/panel/articles/admin-panel-view-article.js
+++ b/client/src/app/admin/panel/articles/admin-panel-view-article.js
@@ -1,14 +1,148 @@
import React from 'react';
+import _ from 'lodash';
+import {connect} from 'react-redux';
+import RichTextEditor from 'react-rte-browserify';
+
+import ArticlesActions from 'actions/articles-actions';
+import SessionStore from 'lib-app/session-store';
+import i18n from 'lib-app/i18n';
+import API from 'lib-app/api-call';
+import DateTransformer from 'lib-core/date-transformer';
+
+import Header from 'core-components/header';
+import Loading from 'core-components/loading';
+import Button from 'core-components/button';
+import Form from 'core-components/form';
+import FormField from 'core-components/form-field';
+import SubmitButton from 'core-components/submit-button';
class AdminPanelViewArticle extends React.Component {
+ static propTypes = {
+ topics: React.PropTypes.array,
+ loading: React.PropTypes.bool
+ };
+
+ static defaultProps = {
+ topics: [],
+ loading: true
+ };
+
+ state = {
+ editable: false
+ };
+
+ componentDidMount() {
+ if(SessionStore.getItem('topics')) {
+ this.props.dispatch(ArticlesActions.initArticles());
+ } else {
+ this.props.dispatch(ArticlesActions.retrieveArticles());
+ }
+ }
+
render() {
return (
-
- /admin/panel/articles/view-article
+
+ {(this.props.loading) ? : this.renderContent()}
);
}
+
+ renderContent() {
+ let article = this.findArticle();
+
+ return (article) ? this.renderArticle(article) : i18n('ARTICLE_NOT_FOUND');
+ }
+
+ renderArticle(article) {
+ return (this.state.editable) ? this.renderArticleEdit(article) : this.renderArticlePreview(article);
+ }
+
+ renderArticlePreview(article) {
+ return (
+
+
+
+
+
+
+
+ );
+ }
+
+ renderArticleEdit() {
+ return (
+
+ );
+ }
+
+ findArticle() {
+ let article = null;
+
+ _.forEach(this.props.topics, (topic) => {
+ if(!article) {
+ article = _.find(topic.articles, {id: this.props.params.articleId * 1});
+ }
+ });
+
+ return article;
+ }
+
+ onEditClick(article) {
+ this.setState({
+ editable: true,
+ form: {
+ title: article.title,
+ content: RichTextEditor.createValueFromString(article.content, 'html')
+ }
+ });
+ }
+
+ onFormSubmit(form) {
+ API.call({
+ path: '/article/edit',
+ data: {
+ title: form.title,
+ content: form.content
+ }
+ }).then(() => {
+ this.props.dispatch(ArticlesActions.retrieveArticles());
+ this.setState({
+ editable: false
+ });
+ });
+ }
+
+ onFormCancel(event) {
+ event.preventDefault();
+
+ this.setState({
+ editable: false
+ });
+ }
}
-export default AdminPanelViewArticle;
\ No newline at end of file
+export default connect((store) => {
+ return {
+ topics: store.articles.topics,
+ loading: store.articles.loading
+ };
+})(AdminPanelViewArticle);
diff --git a/client/src/app/admin/panel/articles/admin-panel-view-article.scss b/client/src/app/admin/panel/articles/admin-panel-view-article.scss
new file mode 100644
index 00000000..300041c9
--- /dev/null
+++ b/client/src/app/admin/panel/articles/admin-panel-view-article.scss
@@ -0,0 +1,22 @@
+.admin-panel-view-article {
+
+ &__edit-button {
+ text-align: left;
+ margin-bottom: 20px;
+ }
+
+ &__last-edited {
+ font-style: italic;
+ text-align: right;
+ margin-top: 20px;
+ }
+
+ &__buttons {
+ text-align: left;
+ margin-bottom: 20px;
+ }
+
+ &__button {
+ margin-right: 20px;
+ }
+}
\ No newline at end of file
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..aac27f29 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 'lodash';
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/demo/components-demo-page.js b/client/src/app/demo/components-demo-page.js
index ef679cbd..e3f68b67 100644
--- a/client/src/app/demo/components-demo-page.js
+++ b/client/src/app/demo/components-demo-page.js
@@ -107,7 +107,7 @@ let DemoPage = React.createClass({
title: 'Tooltip',
render: (
-
+
hola
diff --git a/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.js b/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.js
index 15d5a134..8aeca485 100644
--- a/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.js
+++ b/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.js
@@ -1,14 +1,114 @@
import React from 'react';
+import _ from 'lodash';
+import {connect} from 'react-redux';
+
+import ArticlesActions from 'actions/articles-actions';
+import SessionStore from 'lib-app/session-store';
+import i18n from 'lib-app/i18n';
+import DateTransformer from 'lib-core/date-transformer';
+
+import Header from 'core-components/header';
+import Loading from 'core-components/loading';
+import BreadCrumb from 'core-components/breadcrumb';
class DashboardArticlePage extends React.Component {
+ static propTypes = {
+ topics: React.PropTypes.array,
+ loading: React.PropTypes.bool
+ };
+
+ static defaultProps = {
+ topics: [],
+ loading: true
+ };
+
+ componentDidMount() {
+ if(SessionStore.getItem('topics')) {
+ this.props.dispatch(ArticlesActions.initArticles());
+ } else {
+ this.props.dispatch(ArticlesActions.retrieveArticles());
+ }
+ }
+
render() {
return (
-
- DASHBOARD ARTICLE
+
+
+
+
+ {(this.props.loading) ?
: this.renderContent()}
);
}
+
+ renderContent() {
+ let article = this.findArticle();
+
+ return (article) ? this.renderArticlePreview(article) : i18n('ARTICLE_NOT_FOUND');
+ }
+
+ renderArticlePreview(article) {
+ return (
+
+ );
+ }
+
+ findArticle() {
+ let article = null;
+
+ _.forEach(this.props.topics, (topic) => {
+ if(!article) {
+ article = _.find(topic.articles, {id: this.props.params.articleId * 1});
+ }
+ });
+
+ return article;
+ }
+
+ findTopic() {
+ let topicFound = {};
+
+ _.forEach(this.props.topics, (topic) => {
+ if(_.find(topic.articles, {id: this.props.params.articleId * 1})) {
+ topicFound = topic;
+ }
+ });
+
+ return topicFound;
+ }
+
+ getBreadCrumbItems() {
+ let article = this.findArticle();
+ let topic = this.findTopic();
+ let items = [
+ {content: i18n('ARTICLES'), url: '/dashboard/articles'}
+ ];
+
+ if(topic && topic.name) {
+ items.push({content: topic.name, url: '/dashboard/articles'});
+ }
+
+ if(article && article.title) {
+ items.push({content: article.title});
+ }
+
+ return items;
+ }
}
-export default DashboardArticlePage;
+export default connect((store) => {
+ return {
+ topics: store.articles.topics,
+ loading: store.articles.loading
+ };
+})(DashboardArticlePage);
diff --git a/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.scss b/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.scss
new file mode 100644
index 00000000..b165a2cd
--- /dev/null
+++ b/client/src/app/main/dashboard/dashboard-article/dashboard-article-page.scss
@@ -0,0 +1,8 @@
+.dashboard-article-page {
+
+ &__last-edited {
+ font-style: italic;
+ text-align: right;
+ margin-top: 20px;
+ }
+}
\ No newline at end of file
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 552b8198..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,14 +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 (
-
- DASHBOARD ARTICLES LIST
+
+
+
+ {(!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/breadcrumb.js b/client/src/core-components/breadcrumb.js
new file mode 100644
index 00000000..8f1382e7
--- /dev/null
+++ b/client/src/core-components/breadcrumb.js
@@ -0,0 +1,42 @@
+import React from 'react';
+import {Link} from 'react-router';
+
+class BreadCrumb extends React.Component {
+ static propTypes = {
+ items: React.PropTypes.arrayOf(React.PropTypes.shape({
+ content: React.PropTypes.string.isRequired,
+ url: React.PropTypes.string
+ }))
+ };
+
+ render() {
+ return (
+
+ {this.props.items.map(this.renderItem.bind(this))}
+
+ );
+ }
+
+ renderItem(item, index) {
+ return (
+
+ {(item.url) ? this.renderItemLink(item) : item.content}
+ {(index < this.props.items.length - 1) ? this.renderArrow() : null}
+
+ );
+ }
+
+ renderItemLink(item) {
+ return (
+ {item.content}
+ );
+ }
+
+ renderArrow() {
+ return (
+ {'>'}
+ );
+ }
+}
+
+export default BreadCrumb;
\ No newline at end of file
diff --git a/client/src/core-components/breadcrumb.scss b/client/src/core-components/breadcrumb.scss
new file mode 100644
index 00000000..df30d414
--- /dev/null
+++ b/client/src/core-components/breadcrumb.scss
@@ -0,0 +1,18 @@
+@import "../scss/vars";
+
+.breadcrumb {
+ padding: 0;
+ text-align: left;
+ margin-bottom: 20px;
+
+ &__item {
+ color: $grey;
+ display: inline-block;
+ text-decoration: none;
+ }
+
+ &__arrow {
+ color: $grey;
+ margin: 0 5px;
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/color-selector.js b/client/src/core-components/color-selector.js
new file mode 100644
index 00000000..64e2c920
--- /dev/null
+++ b/client/src/core-components/color-selector.js
@@ -0,0 +1,57 @@
+import React from 'react';
+
+import Tooltip from 'core-components/tooltip';
+
+const colors = ['#ff6900', '#fcb900', '#7bdcb5', '#00d084', '#8ed1fc', '#0693e3', '#abb8c3', '#eb144c', '#f78da7', '#9900ef'];
+
+class ColorSelector extends React.Component {
+ static propTypes = {
+ value: React.PropTypes.string,
+ onChange: React.PropTypes.func
+ };
+
+ static defaultProps = {
+ value: '#ff6900'
+ };
+
+ state = {
+ show: false
+ };
+
+ render() {
+ return (
+
+ this.setState({show})}>
+
+
+
+ )
+ }
+
+ renderTooltipContent() {
+ return (
+
+ {colors.map(this.renderTooltipColor.bind(this))}
+
+ );
+ }
+
+ renderTooltipColor(color) {
+ return (
+
+ );
+ }
+
+ onColorClick(color) {
+ this.setState({
+ show: false
+ });
+
+ if(this.props.onChange) {
+ this.props.onChange({target: {value: color}});
+ }
+ }
+}
+
+
+export default ColorSelector;
\ No newline at end of file
diff --git a/client/src/core-components/color-selector.scss b/client/src/core-components/color-selector.scss
new file mode 100644
index 00000000..5976e6fc
--- /dev/null
+++ b/client/src/core-components/color-selector.scss
@@ -0,0 +1,21 @@
+.color-selector {
+
+ &__current {
+ cursor: pointer;
+ display: inline-block;
+ width: 30px;
+ height: 30px;
+ }
+
+ &__tooltip {
+ width: 200px;
+ }
+
+ &__tooltip-color {
+ cursor: pointer;
+ display: inline-block;
+ width: 30px;
+ height: 30px;
+ margin: 2px 5px;
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/icon-selector.js b/client/src/core-components/icon-selector.js
new file mode 100644
index 00000000..0ed08563
--- /dev/null
+++ b/client/src/core-components/icon-selector.js
@@ -0,0 +1,61 @@
+import React from 'react';
+
+import Icon from 'core-components/icon';
+import Tooltip from 'core-components/tooltip';
+
+const icons = ['address-card', 'address-card-o', 'adjust', 'american-sign-language-interpreting', 'anchor', 'archive', 'area-chart', 'arrows', 'arrows-h', 'arrows-v', 'asl-interpreting (alias)', 'assistive-listening-systems', 'asterisk', 'audio-description', 'automobile (alias)', 'balance-scale', 'ban', 'bank (alias)', 'bar-chart', 'bar-chart-o (alias)', 'barcode', 'bars', 'bath', 'bathtub (alias)', 'battery (alias)', 'battery-0 (alias)', 'battery-1 (alias)', 'battery-2 (alias)', 'battery-3 (alias)', 'battery-4 (alias)', 'battery-empty', 'battery-full', 'battery-half', 'battery-quarter', 'battery-three-quarters', 'bed', 'beer', 'bell', 'bell-o', 'bell-slash', 'bell-slash-o', 'bicycle', 'binoculars', 'birthday-cake', 'blind', 'bluetooth', 'bluetooth-b', 'bolt', 'bomb', 'book', 'bookmark', 'bookmark-o', 'braille', 'briefcase', 'bug', 'building', 'building-o', 'bullhorn', 'bullseye', 'bus', 'cab (alias)', 'calculator', 'calendar', 'calendar-check-o', 'calendar-minus-o', 'calendar-o', 'calendar-plus-o', 'calendar-times-o', 'camera', 'camera-retro', 'car', 'caret-square-o-down', 'caret-square-o-left', 'caret-square-o-right', 'caret-square-o-up', 'cart-arrow-down', 'cart-plus', 'certificate', 'check', 'check-circle', 'check-circle-o', 'check-square', 'check-square-o', 'child', 'circle', 'circle-o', 'circle-o-notch', 'circle-thin', 'clock-o', 'clone', 'close (alias)', 'cloud', 'cloud-download', 'cloud-upload', 'code', 'code-fork', 'coffee', 'cog', 'cogs', 'comment', 'comment-o', 'commenting', 'commenting-o', 'comments', 'comments-o', 'compass', 'copyright', 'creative-commons', 'credit-card', 'credit-card-alt', 'crop', 'crosshairs', 'cube', 'cubes', 'cutlery', 'dashboard (alias)', 'database', 'deaf', 'deafness (alias)', 'desktop', 'diamond', 'dot-circle-o', 'download', 'drivers-license (alias)', 'drivers-license-o (alias)', 'edit (alias)', 'ellipsis-h', 'ellipsis-v', 'envelope', 'envelope-o', 'envelope-open', 'envelope-open-o', 'envelope-square', 'eraser', 'exchange', 'exclamation', 'exclamation-circle', 'exclamation-triangle', 'external-link', 'external-link-square', 'eye', 'eye-slash', 'eyedropper', 'fax', 'feed (alias)', 'female', 'fighter-jet', 'file-archive-o', 'file-audio-o', 'file-code-o', 'file-excel-o', 'file-image-o', 'file-movie-o (alias)', 'file-pdf-o', 'file-photo-o (alias)', 'file-picture-o (alias)', 'file-powerpoint-o', 'file-sound-o (alias)', 'file-video-o', 'file-word-o', 'file-zip-o (alias)', 'film', 'filter', 'fire', 'fire-extinguisher', 'flag', 'flag-checkered', 'flag-o', 'flash (alias)', 'flask', 'folder', 'folder-o', 'folder-open', 'folder-open-o', 'frown-o', 'futbol-o', 'gamepad', 'gavel', 'gear (alias)', 'gears (alias)', 'gift', 'glass', 'globe', 'graduation-cap', 'group (alias)', 'hand-grab-o (alias)', 'hand-lizard-o', 'hand-paper-o', 'hand-peace-o', 'hand-pointer-o', 'hand-rock-o', 'hand-scissors-o', 'hand-spock-o', 'hand-stop-o (alias)', 'handshake-o', 'hard-of-hearing (alias)', 'hashtag', 'hdd-o', 'headphones', 'heart', 'heart-o', 'heartbeat', 'history', 'home', 'hotel (alias)', 'hourglass', 'hourglass-1 (alias)', 'hourglass-2 (alias)', 'hourglass-3 (alias)', 'hourglass-end', 'hourglass-half', 'hourglass-o', 'hourglass-start', 'i-cursor', 'id-badge', 'id-card', 'id-card-o', 'image (alias)', 'inbox', 'industry', 'info', 'info-circle', 'institution (alias)', 'key', 'keyboard-o', 'language', 'laptop', 'leaf', 'legal (alias)', 'lemon-o', 'level-down', 'level-up', 'life-bouy (alias)', 'life-buoy (alias)', 'life-ring', 'life-saver (alias)', 'lightbulb-o', 'line-chart', 'location-arrow', 'lock', 'low-vision', 'magic', 'magnet', 'mail-forward (alias)', 'mail-reply (alias)', 'mail-reply-all (alias)', 'male', 'map', 'map-marker', 'map-o', 'map-pin', 'map-signs', 'meh-o', 'microchip', 'microphone', 'microphone-slash', 'minus', 'minus-circle', 'minus-square', 'minus-square-o', 'mobile', 'mobile-phone (alias)', 'money', 'moon-o', 'mortar-board (alias)', 'motorcycle', 'mouse-pointer', 'music', 'navicon (alias)', 'newspaper-o', 'object-group', 'object-ungroup', 'paint-brush', 'paper-plane', 'paper-plane-o', 'paw', 'pencil', 'pencil-square', 'pencil-square-o', 'percent', 'phone', 'phone-square', 'photo (alias)', 'picture-o', 'pie-chart', 'plane', 'plug', 'plus', 'plus-circle', 'plus-square', 'plus-square-o', 'podcast', 'power-off', 'print', 'puzzle-piece', 'qrcode', 'question', 'question-circle', 'question-circle-o', 'quote-left', 'quote-right', 'random', 'recycle', 'refresh', 'registered', 'remove (alias)', 'reorder (alias)', 'reply', 'reply-all', 'retweet', 'road', 'rocket', 'rss', 'rss-square', 's15 (alias)', 'search', 'search-minus', 'search-plus', 'send (alias)', 'send-o (alias)', 'server', 'share', 'share-alt', 'share-alt-square', 'share-square', 'share-square-o', 'shield', 'ship', 'shopping-bag', 'shopping-basket', 'shopping-cart', 'shower', 'sign-in', 'sign-language', 'sign-out', 'signal', 'signing (alias)', 'sitemap', 'sliders', 'smile-o', 'snowflake-o', 'soccer-ball-o (alias)', 'sort', 'sort-alpha-asc', 'sort-alpha-desc', 'sort-amount-asc', 'sort-amount-desc', 'sort-asc', 'sort-desc', 'sort-down (alias)', 'sort-numeric-asc', 'sort-numeric-desc', 'sort-up (alias)', 'space-shuttle', 'spinner', 'spoon', 'square', 'square-o', 'star', 'star-half', 'star-half-empty (alias)', 'star-half-full (alias)', 'star-half-o', 'star-o', 'sticky-note', 'sticky-note-o', 'street-view', 'suitcase', 'sun-o', 'support (alias)', 'tablet', 'tachometer', 'tag', 'tags', 'tasks', 'taxi', 'television', 'terminal', 'thermometer (alias)', 'thermometer-0 (alias)', 'thermometer-1 (alias)', 'thermometer-2 (alias)', 'thermometer-3 (alias)', 'thermometer-4 (alias)', 'thermometer-empty', 'thermometer-full', 'thermometer-half', 'thermometer-quarter', 'thermometer-three-quarters', 'thumb-tack', 'thumbs-down', 'thumbs-o-down', 'thumbs-o-up', 'thumbs-up', 'ticket', 'times', 'times-circle', 'times-circle-o', 'times-rectangle (alias)', 'times-rectangle-o (alias)', 'tint', 'toggle-down (alias)', 'toggle-left (alias)', 'toggle-off', 'toggle-on', 'toggle-right (alias)', 'toggle-up (alias)', 'trademark', 'trash', 'trash-o', 'tree', 'trophy', 'truck', 'tty', 'tv (alias)', 'umbrella', 'universal-access', 'university', 'unlock', 'unlock-alt', 'unsorted (alias)', 'upload', 'user', 'user-circle', 'user-circle-o', 'user-o', 'user-plus', 'user-secret', 'user-times', 'users', 'vcard (alias)', 'vcard-o (alias)', 'video-camera', 'volume-control-phone', 'volume-down', 'volume-off', 'volume-up', 'warning (alias)', 'wheelchair', 'wheelchair-alt', 'wifi', 'window-close', 'window-close-o', 'window-maximize', 'window-minimize', 'window-restore', 'wrench'];
+
+class IconSelector extends React.Component {
+ static propTypes = {
+ value: React.PropTypes.string,
+ onChange: React.PropTypes.func
+ };
+
+ static defaultProps = {
+ value: 'adjust'
+ };
+
+ state = {
+ show: false
+ };
+
+ render() {
+ return (
+
+ this.setState({show})}>
+
+
+
+
+
+ );
+ }
+
+ renderTooltipContent() {
+ return (
+
+ {icons.map(this.renderTooltipIcon.bind(this))}
+
+ );
+ }
+
+ renderTooltipIcon(name) {
+ return (
+
+
+
+ );
+ }
+
+ onIconClick(name) {
+ this.setState({
+ show: false
+ });
+
+ if(this.props.onChange) {
+ this.props.onChange({target: {value: name}});
+ }
+ }
+}
+
+export default IconSelector;
\ No newline at end of file
diff --git a/client/src/core-components/icon-selector.scss b/client/src/core-components/icon-selector.scss
new file mode 100644
index 00000000..562535eb
--- /dev/null
+++ b/client/src/core-components/icon-selector.scss
@@ -0,0 +1,37 @@
+@import "../scss/vars";
+
+.icon-selector {
+
+ &__tooltip {
+ width: 400px;
+ height: 200px;
+ overflow-y: scroll;
+ }
+
+ &__tooltip-icon {
+ display: inline-block;
+ cursor: pointer;
+ background-color: $light-grey;
+ padding: 6px 3px;
+ border-radius: 5px;
+ margin: 5px;
+ width: 32px;
+ height: 32px;
+ text-align: center;
+
+ &:hover {
+ background-color: $medium-grey;
+ }
+ }
+
+ &__current-icon {
+ cursor: pointer;
+ display: inline-block;
+ text-align: center;
+ padding: 6px 3px;
+ border-radius: 5px;
+ width: 32px;
+ height: 32px;
+ background-color: $light-grey;
+ }
+}
\ No newline at end of file
diff --git a/client/src/core-components/icon.js b/client/src/core-components/icon.js
index 6570bd90..d26123d1 100644
--- a/client/src/core-components/icon.js
+++ b/client/src/core-components/icon.js
@@ -5,6 +5,7 @@ class Icon extends React.Component {
static propTypes = {
name: React.PropTypes.string.isRequired,
+ color: React.PropTypes.string,
size: React.PropTypes.string
};
@@ -18,7 +19,7 @@ class Icon extends React.Component {
renderFontIcon() {
return (
-
+
);
}
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/core-components/tooltip.js b/client/src/core-components/tooltip.js
index 81faf8d9..04ea97e2 100644
--- a/client/src/core-components/tooltip.js
+++ b/client/src/core-components/tooltip.js
@@ -6,7 +6,9 @@ class Tooltip extends React.Component {
static propTypes = {
children: React.PropTypes.node,
content: React.PropTypes.node,
- openOnHover: React.PropTypes.bool
+ openOnHover: React.PropTypes.bool,
+ show: React.PropTypes.bool,
+ onToggle: React.PropTypes.func
};
state = {
@@ -16,7 +18,7 @@ class Tooltip extends React.Component {
render() {
return (
- {(this.state.show) ? this.renderAnimatedMessage() : null}
+ {(this.getShowValue()) ? this.renderAnimatedMessage() : null}
{this.props.children}
@@ -26,7 +28,7 @@ class Tooltip extends React.Component {
renderAnimatedMessage() {
return (
-
+
{this.renderMessage.bind(this)}
)
@@ -35,10 +37,11 @@ class Tooltip extends React.Component {
renderMessage(animation) {
return (
+
+
{this.props.content}
-
)
}
@@ -58,10 +61,10 @@ class Tooltip extends React.Component {
getChildrenProps() {
let props = {};
- props.className= 'tooltip__children';
+ props.className = 'tooltip__children';
if(!this.props.openOnHover) {
- props.onClick= this.onClick.bind(this);
+ props.onClick = this.onClick.bind(this);
}
return props;
@@ -71,20 +74,35 @@ class Tooltip extends React.Component {
this.setState({
show: true
});
+
+ if(this.props.onToggle) {
+ this.props.onToggle(true);
+ }
}
+
onMouseOut() {
this.setState({
show: false
});
+
+ if(this.props.onToggle) {
+ this.props.onToggle(false);
+ }
}
onClick() {
- if (this.state.show) {
- this.setState({show: false});
- } else {
- this.setState({show: true});
+ this.setState({
+ show: !this.getShowValue()
+ });
+
+ if(this.props.onToggle) {
+ this.props.onToggle(!this.getShowValue());
}
}
+
+ getShowValue() {
+ return (this.props.show !== undefined) ? this.props.show : this.state.show;
+ }
}
export default Tooltip;
\ No newline at end of file
diff --git a/client/src/core-components/tooltip.scss b/client/src/core-components/tooltip.scss
index bbe42bdb..857a917d 100644
--- a/client/src/core-components/tooltip.scss
+++ b/client/src/core-components/tooltip.scss
@@ -1,3 +1,5 @@
+@import "../scss/vars";
+
.tooltip {
position: relative;
display: inline-block;
@@ -10,23 +12,38 @@
position: absolute;
bottom: 100%;
left: -25%;
- margin-bottom: 10px;
- box-shadow: 0 0 4px #8D8D8D;
+ margin-bottom: 15px;
+ margin-left: -10px;
+ border: 0 solid rgba(0, 0, 0, 0.247059);
+ box-shadow: rgba(0, 0, 0, 0.247059) 0 -1px 4px;
border-radius: 4px;
min-width: 200px;
- background-color: #F7F7F7;
+ background-color: white;
color: black;
padding: 10px;
- z-index: 1000;
+ z-index: 900;
}
&__pointer {
border: solid transparent;
position: absolute;
- border-top-color: #8D8D8D;
- border-width: 10px;
- top: -10px;
+ border-top-color: white;
+ border-width: 13px;
+ top: -15px;
left: 50%;
- margin-left: -8px;
+ margin-left: -13px;
+ z-index: 910;
+ pointer-events: none;
+ }
+
+ &__pointer-shadow {
+ border: solid transparent;
+ position: absolute;
+ border-top-color: rgba(black, 0.1);
+ border-width: 14px;
+ top: -15px;
+ left: 50%;
+ margin-left: -14px;
+ pointer-events: none;
}
}
\ No newline at end of file
diff --git a/client/src/data/fixtures/article-fixtures.js b/client/src/data/fixtures/article-fixtures.js
new file mode 100644
index 00000000..ea394582
--- /dev/null
+++ b/client/src/data/fixtures/article-fixtures.js
@@ -0,0 +1,159 @@
+module.exports = [
+ {
+ path: '/article/get-all',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: [
+ {
+ id: 1,
+ name: 'Membership Settings',
+ icon: 'user',
+ iconColor: '#82CA9C',
+ articles: [
+ {
+ id: 1,
+ title: 'Mannaging apps for your account',
+ content: 'Curabitur sed dignissim turpis, sed lacinia urna. Vestibulum semper suscipit interdum. Proin sed sem gravida massa tristique rhoncus auctor eu diam. Donec fringilla in ex non dignissim. Praesent sed ultricies eros. Nullam vel augue eget libero volutpat sodales sit amet et orci.',
+ lastEdited: 20160516,
+ position: 1
+ },
+ {
+ id: 2,
+ title: 'How to assign new task and files',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20150429,
+ position: 2
+ },
+ {
+ id: 3,
+ title: 'Updating your profile picture',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20150429,
+ position: 3
+ },
+ {
+ id: 4,
+ title: 'Deleting your account',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20150929,
+ position: 4
+ },
+ {
+ id: 5,
+ title: 'Upload files to your cloud drive',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20131229,
+ position: 5
+ }
+ ]
+ },
+ {
+ id: 2,
+ name: 'Billing and plans',
+ icon: 'credit-card',
+ iconColor: 'red',
+ articles: [
+ {
+ id: 1,
+ title: 'Mannaging apps for your account',
+ content: 'Curabitur sed dignissim turpis, sed lacinia urna. Vestibulum semper suscipit interdum. Proin sed sem gravida massa tristique rhoncus auctor eu diam. Donec fringilla in ex non dignissim. Praesent sed ultricies eros. Nullam vel augue eget libero volutpat sodales sit amet et orci.',
+ lastEdited: 20160516,
+ position: 1
+ },
+ {
+ id: 2,
+ title: 'How to assign new task and files',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20150429,
+ position: 2
+ },
+ {
+ id: 3,
+ title: 'Updating your profile picture',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20150429,
+ position: 3
+ },
+ {
+ id: 4,
+ title: 'Deleting your account',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20150929,
+ position: 4
+ },
+ {
+ id: 5,
+ title: 'Upload files to your cloud drive',
+ content: 'Aliquam aliquet mi nulla. Nam vel orci diam. Suspendisse euismod orci efficitur nulla mattis eleifend vitae quis neque. Etiam orci dolor, dignissim quis convallis quis, rhoncus eu tellus. Phasellus aliquam ut enim id ultrices. Nunc dolor arcu, viverra vel ullamcorper nec, dignissim a lectus. Praesent fringilla, neque nec suscipit placerat, augue elit suscipit velit, in feugiat leo justo id tortor.',
+ lastEdited: 20131229,
+ position: 5
+ }
+ ]
+ }
+ ]
+ };
+ }
+ },
+ {
+ path: '/article/edit-topic',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/article/edit',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/article/add',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/article/add-topic',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/article/delete',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ },
+ {
+ path: '/article/delete-topic',
+ time: 100,
+ response: function () {
+ return {
+ status: 'success',
+ data: {}
+ };
+ }
+ }
+];
\ No newline at end of file
diff --git a/client/src/data/languages/en.js b/client/src/data/languages/en.js
index da5706d9..e60a8f4e 100644
--- a/client/src/data/languages/en.js
+++ b/client/src/data/languages/en.js
@@ -42,7 +42,7 @@ export default {
'CUSTOM_RESPONSES': 'Custom Responses',
'LIST_USERS': 'List Users',
'BAN_USERS': 'Ban Users',
- 'LIST_ARTICLES': 'List Articles',
+ 'LIST_ARTICLES': 'Article List',
'STAFF_MEMBERS': 'Staff Members',
'DEPARTMENTS': 'Departments',
'SYSTEM_PREFERENCES': 'System Preferences',
@@ -84,6 +84,16 @@ export default {
'SEARCH_USERS': 'Search users...',
'SEARCH_EMAIL': 'Search email...',
'USER_VIEW_TITLE': 'User #{userId}',
+ 'EDIT_TOPIC': 'Edit Topic',
+ 'ADD_TOPIC': 'Add Topic',
+ 'ICON': 'Icon',
+ 'COLOR': 'Color',
+ 'ADD_NEW_ARTICLE': 'Add new article',
+ 'ADD_ARTICLE': 'Add article',
+ 'LAST_EDITED_IN': 'Last edited in {date}',
+ 'EDIT': 'Edit',
+ 'NO_RESULTS': 'No results',
+ 'DELETE_AND_BAN': 'Delete and ban',
//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.',
@@ -101,6 +111,11 @@ export default {
'LIST_USERS_DESCRIPTION': 'This is the list of users that are registered in this platform. You can search for someone in particular, delete it or ban it.',
'USER_VIEW_DESCRIPTION': 'Here you can find all the information about an user and all the tickets sent by the user. You can also delete or ban it.',
'DELETE_USER_DESCRIPTION': 'The user will not be able to log in aging and all its tickets will be erased. Also, the email can not be used any more.',
+ 'DELETE_TOPIC_DESCRIPTION': 'By deleting the topic, all articles on it will be erased.',
+ 'EDIT_TOPIC_DESCRIPTION': 'Here you can change the name, the icon and the icon color of the topic.',
+ 'ADD_ARTICLE_DESCRIPTION': 'Here you can add an article that will be available for every user. It will be added inside the category {category}.',
+ 'LIST_ARTICLES_DESCRIPTION': 'This is a list of articles that includes information about our services.',
+ 'ADD_TOPIC_DESCRIPTION': 'Here you can add a topic that works as a category for articles.',
//ERRORS
'EMAIL_OR_PASSWORD': 'Email or password invalid',
diff --git a/client/src/lib-app/fixtures-loader.js b/client/src/lib-app/fixtures-loader.js
index 896ff338..1850cb34 100644
--- a/client/src/lib-app/fixtures-loader.js
+++ b/client/src/lib-app/fixtures-loader.js
@@ -20,6 +20,7 @@ fixtures.add(require('data/fixtures/user-fixtures'));
fixtures.add(require('data/fixtures/staff-fixtures'));
fixtures.add(require('data/fixtures/ticket-fixtures'));
fixtures.add(require('data/fixtures/system-fixtures'));
+fixtures.add(require('data/fixtures/article-fixtures'));
_.each(fixtures.getAll(), function (fixture) {
mockjax({
diff --git a/client/src/reducers/_reducers.js b/client/src/reducers/_reducers.js
index ea625665..ff73dfc3 100644
--- a/client/src/reducers/_reducers.js
+++ b/client/src/reducers/_reducers.js
@@ -4,12 +4,14 @@ import { routerReducer } from 'react-router-redux';
import sessionReducer from 'reducers/session-reducer';
import configReducer from 'reducers/config-reducer';
import modalReducer from 'reducers/modal-reducer';
+import articlesReducer from 'reducers/articles-reducer';
import adminDataReducer from 'reducers/admin-data-reducer';
export default combineReducers({
session: sessionReducer,
config: configReducer,
modal: modalReducer,
+ articles: articlesReducer,
adminData: adminDataReducer,
routing: routerReducer
});
\ No newline at end of file
diff --git a/client/src/reducers/articles-reducer.js b/client/src/reducers/articles-reducer.js
new file mode 100644
index 00000000..fcc5a537
--- /dev/null
+++ b/client/src/reducers/articles-reducer.js
@@ -0,0 +1,48 @@
+import _ from 'lodash';
+
+import Reducer from 'reducers/reducer';
+import SessionStore from 'lib-app/session-store';
+
+class ArticlesReducer extends Reducer {
+
+ getInitialState() {
+ return {
+ retrieved: false,
+ loading: true,
+ topics: []
+ };
+ }
+
+ getTypeHandlers() {
+ return {
+ 'GET_ARTICLES_FULFILLED': this.onArticlesRetrieved,
+ 'INIT_ARTICLES': this.onInitArticles
+ };
+ }
+
+ onArticlesRetrieved(state, payload) {
+ SessionStore.setItem('topics', JSON.stringify(payload.data));
+
+ return _.extend({}, state, {
+ retrieved: true,
+ loading: false,
+ topics: payload.data
+ });
+ }
+
+ onInitArticles(state) {
+ let topics = SessionStore.getItem('topics');
+
+ if(topics) {
+ topics = JSON.parse(topics);
+ }
+
+ return _.extend({}, state, {
+ retrieved: !!topics,
+ loading: false,
+ topics: topics
+ });
+ }
+}
+
+export default ArticlesReducer.getInstance();
\ No newline at end of file
diff --git a/client/src/scss/_vars.scss b/client/src/scss/_vars.scss
index 6bcdbf59..59793c65 100644
--- a/client/src/scss/_vars.scss
+++ b/client/src/scss/_vars.scss
@@ -23,5 +23,6 @@ $half-space: 20px;
$font-size--xs: 11px;
$font-size--sm: 13px;
$font-size--md: 16px;
+$font-size--bg: 19px;
$font-size--lg: 24px;
$font-size--xl: 32px;
\ No newline at end of file
diff --git a/client/src/scss/font_awesome/_icons.scss b/client/src/scss/font_awesome/_icons.scss
index 62d97677..e63e702c 100644
--- a/client/src/scss/font_awesome/_icons.scss
+++ b/client/src/scss/font_awesome/_icons.scss
@@ -438,7 +438,7 @@
.#{$fa-css-prefix}-stumbleupon:before { content: $fa-var-stumbleupon; }
.#{$fa-css-prefix}-delicious:before { content: $fa-var-delicious; }
.#{$fa-css-prefix}-digg:before { content: $fa-var-digg; }
-.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; }
+.#{$fa-css-prefix}-pied-piper-pp:before { content: $fa-var-pied-piper-pp; }
.#{$fa-css-prefix}-pied-piper-alt:before { content: $fa-var-pied-piper-alt; }
.#{$fa-css-prefix}-drupal:before { content: $fa-var-drupal; }
.#{$fa-css-prefix}-joomla:before { content: $fa-var-joomla; }
@@ -488,6 +488,7 @@
.#{$fa-css-prefix}-life-ring:before { content: $fa-var-life-ring; }
.#{$fa-css-prefix}-circle-o-notch:before { content: $fa-var-circle-o-notch; }
.#{$fa-css-prefix}-ra:before,
+.#{$fa-css-prefix}-resistance:before,
.#{$fa-css-prefix}-rebel:before { content: $fa-var-rebel; }
.#{$fa-css-prefix}-ge:before,
.#{$fa-css-prefix}-empire:before { content: $fa-var-empire; }
@@ -604,6 +605,7 @@
.#{$fa-css-prefix}-opencart:before { content: $fa-var-opencart; }
.#{$fa-css-prefix}-expeditedssl:before { content: $fa-var-expeditedssl; }
.#{$fa-css-prefix}-battery-4:before,
+.#{$fa-css-prefix}-battery:before,
.#{$fa-css-prefix}-battery-full:before { content: $fa-var-battery-full; }
.#{$fa-css-prefix}-battery-3:before,
.#{$fa-css-prefix}-battery-three-quarters:before { content: $fa-var-battery-three-quarters; }
@@ -675,3 +677,113 @@
.#{$fa-css-prefix}-vimeo:before { content: $fa-var-vimeo; }
.#{$fa-css-prefix}-black-tie:before { content: $fa-var-black-tie; }
.#{$fa-css-prefix}-fonticons:before { content: $fa-var-fonticons; }
+.#{$fa-css-prefix}-reddit-alien:before { content: $fa-var-reddit-alien; }
+.#{$fa-css-prefix}-edge:before { content: $fa-var-edge; }
+.#{$fa-css-prefix}-credit-card-alt:before { content: $fa-var-credit-card-alt; }
+.#{$fa-css-prefix}-codiepie:before { content: $fa-var-codiepie; }
+.#{$fa-css-prefix}-modx:before { content: $fa-var-modx; }
+.#{$fa-css-prefix}-fort-awesome:before { content: $fa-var-fort-awesome; }
+.#{$fa-css-prefix}-usb:before { content: $fa-var-usb; }
+.#{$fa-css-prefix}-product-hunt:before { content: $fa-var-product-hunt; }
+.#{$fa-css-prefix}-mixcloud:before { content: $fa-var-mixcloud; }
+.#{$fa-css-prefix}-scribd:before { content: $fa-var-scribd; }
+.#{$fa-css-prefix}-pause-circle:before { content: $fa-var-pause-circle; }
+.#{$fa-css-prefix}-pause-circle-o:before { content: $fa-var-pause-circle-o; }
+.#{$fa-css-prefix}-stop-circle:before { content: $fa-var-stop-circle; }
+.#{$fa-css-prefix}-stop-circle-o:before { content: $fa-var-stop-circle-o; }
+.#{$fa-css-prefix}-shopping-bag:before { content: $fa-var-shopping-bag; }
+.#{$fa-css-prefix}-shopping-basket:before { content: $fa-var-shopping-basket; }
+.#{$fa-css-prefix}-hashtag:before { content: $fa-var-hashtag; }
+.#{$fa-css-prefix}-bluetooth:before { content: $fa-var-bluetooth; }
+.#{$fa-css-prefix}-bluetooth-b:before { content: $fa-var-bluetooth-b; }
+.#{$fa-css-prefix}-percent:before { content: $fa-var-percent; }
+.#{$fa-css-prefix}-gitlab:before { content: $fa-var-gitlab; }
+.#{$fa-css-prefix}-wpbeginner:before { content: $fa-var-wpbeginner; }
+.#{$fa-css-prefix}-wpforms:before { content: $fa-var-wpforms; }
+.#{$fa-css-prefix}-envira:before { content: $fa-var-envira; }
+.#{$fa-css-prefix}-universal-access:before { content: $fa-var-universal-access; }
+.#{$fa-css-prefix}-wheelchair-alt:before { content: $fa-var-wheelchair-alt; }
+.#{$fa-css-prefix}-question-circle-o:before { content: $fa-var-question-circle-o; }
+.#{$fa-css-prefix}-blind:before { content: $fa-var-blind; }
+.#{$fa-css-prefix}-audio-description:before { content: $fa-var-audio-description; }
+.#{$fa-css-prefix}-volume-control-phone:before { content: $fa-var-volume-control-phone; }
+.#{$fa-css-prefix}-braille:before { content: $fa-var-braille; }
+.#{$fa-css-prefix}-assistive-listening-systems:before { content: $fa-var-assistive-listening-systems; }
+.#{$fa-css-prefix}-asl-interpreting:before,
+.#{$fa-css-prefix}-american-sign-language-interpreting:before { content: $fa-var-american-sign-language-interpreting; }
+.#{$fa-css-prefix}-deafness:before,
+.#{$fa-css-prefix}-hard-of-hearing:before,
+.#{$fa-css-prefix}-deaf:before { content: $fa-var-deaf; }
+.#{$fa-css-prefix}-glide:before { content: $fa-var-glide; }
+.#{$fa-css-prefix}-glide-g:before { content: $fa-var-glide-g; }
+.#{$fa-css-prefix}-signing:before,
+.#{$fa-css-prefix}-sign-language:before { content: $fa-var-sign-language; }
+.#{$fa-css-prefix}-low-vision:before { content: $fa-var-low-vision; }
+.#{$fa-css-prefix}-viadeo:before { content: $fa-var-viadeo; }
+.#{$fa-css-prefix}-viadeo-square:before { content: $fa-var-viadeo-square; }
+.#{$fa-css-prefix}-snapchat:before { content: $fa-var-snapchat; }
+.#{$fa-css-prefix}-snapchat-ghost:before { content: $fa-var-snapchat-ghost; }
+.#{$fa-css-prefix}-snapchat-square:before { content: $fa-var-snapchat-square; }
+.#{$fa-css-prefix}-pied-piper:before { content: $fa-var-pied-piper; }
+.#{$fa-css-prefix}-first-order:before { content: $fa-var-first-order; }
+.#{$fa-css-prefix}-yoast:before { content: $fa-var-yoast; }
+.#{$fa-css-prefix}-themeisle:before { content: $fa-var-themeisle; }
+.#{$fa-css-prefix}-google-plus-circle:before,
+.#{$fa-css-prefix}-google-plus-official:before { content: $fa-var-google-plus-official; }
+.#{$fa-css-prefix}-fa:before,
+.#{$fa-css-prefix}-font-awesome:before { content: $fa-var-font-awesome; }
+.#{$fa-css-prefix}-handshake-o:before { content: $fa-var-handshake-o; }
+.#{$fa-css-prefix}-envelope-open:before { content: $fa-var-envelope-open; }
+.#{$fa-css-prefix}-envelope-open-o:before { content: $fa-var-envelope-open-o; }
+.#{$fa-css-prefix}-linode:before { content: $fa-var-linode; }
+.#{$fa-css-prefix}-address-book:before { content: $fa-var-address-book; }
+.#{$fa-css-prefix}-address-book-o:before { content: $fa-var-address-book-o; }
+.#{$fa-css-prefix}-vcard:before,
+.#{$fa-css-prefix}-address-card:before { content: $fa-var-address-card; }
+.#{$fa-css-prefix}-vcard-o:before,
+.#{$fa-css-prefix}-address-card-o:before { content: $fa-var-address-card-o; }
+.#{$fa-css-prefix}-user-circle:before { content: $fa-var-user-circle; }
+.#{$fa-css-prefix}-user-circle-o:before { content: $fa-var-user-circle-o; }
+.#{$fa-css-prefix}-user-o:before { content: $fa-var-user-o; }
+.#{$fa-css-prefix}-id-badge:before { content: $fa-var-id-badge; }
+.#{$fa-css-prefix}-drivers-license:before,
+.#{$fa-css-prefix}-id-card:before { content: $fa-var-id-card; }
+.#{$fa-css-prefix}-drivers-license-o:before,
+.#{$fa-css-prefix}-id-card-o:before { content: $fa-var-id-card-o; }
+.#{$fa-css-prefix}-quora:before { content: $fa-var-quora; }
+.#{$fa-css-prefix}-free-code-camp:before { content: $fa-var-free-code-camp; }
+.#{$fa-css-prefix}-telegram:before { content: $fa-var-telegram; }
+.#{$fa-css-prefix}-thermometer-4:before,
+.#{$fa-css-prefix}-thermometer:before,
+.#{$fa-css-prefix}-thermometer-full:before { content: $fa-var-thermometer-full; }
+.#{$fa-css-prefix}-thermometer-3:before,
+.#{$fa-css-prefix}-thermometer-three-quarters:before { content: $fa-var-thermometer-three-quarters; }
+.#{$fa-css-prefix}-thermometer-2:before,
+.#{$fa-css-prefix}-thermometer-half:before { content: $fa-var-thermometer-half; }
+.#{$fa-css-prefix}-thermometer-1:before,
+.#{$fa-css-prefix}-thermometer-quarter:before { content: $fa-var-thermometer-quarter; }
+.#{$fa-css-prefix}-thermometer-0:before,
+.#{$fa-css-prefix}-thermometer-empty:before { content: $fa-var-thermometer-empty; }
+.#{$fa-css-prefix}-shower:before { content: $fa-var-shower; }
+.#{$fa-css-prefix}-bathtub:before,
+.#{$fa-css-prefix}-s15:before,
+.#{$fa-css-prefix}-bath:before { content: $fa-var-bath; }
+.#{$fa-css-prefix}-podcast:before { content: $fa-var-podcast; }
+.#{$fa-css-prefix}-window-maximize:before { content: $fa-var-window-maximize; }
+.#{$fa-css-prefix}-window-minimize:before { content: $fa-var-window-minimize; }
+.#{$fa-css-prefix}-window-restore:before { content: $fa-var-window-restore; }
+.#{$fa-css-prefix}-times-rectangle:before,
+.#{$fa-css-prefix}-window-close:before { content: $fa-var-window-close; }
+.#{$fa-css-prefix}-times-rectangle-o:before,
+.#{$fa-css-prefix}-window-close-o:before { content: $fa-var-window-close-o; }
+.#{$fa-css-prefix}-bandcamp:before { content: $fa-var-bandcamp; }
+.#{$fa-css-prefix}-grav:before { content: $fa-var-grav; }
+.#{$fa-css-prefix}-etsy:before { content: $fa-var-etsy; }
+.#{$fa-css-prefix}-imdb:before { content: $fa-var-imdb; }
+.#{$fa-css-prefix}-ravelry:before { content: $fa-var-ravelry; }
+.#{$fa-css-prefix}-eercast:before { content: $fa-var-eercast; }
+.#{$fa-css-prefix}-microchip:before { content: $fa-var-microchip; }
+.#{$fa-css-prefix}-snowflake-o:before { content: $fa-var-snowflake-o; }
+.#{$fa-css-prefix}-superpowers:before { content: $fa-var-superpowers; }
+.#{$fa-css-prefix}-wpexplorer:before { content: $fa-var-wpexplorer; }
+.#{$fa-css-prefix}-meetup:before { content: $fa-var-meetup; }
diff --git a/client/src/scss/font_awesome/_mixins.scss b/client/src/scss/font_awesome/_mixins.scss
index f96719b6..c3bbd574 100644
--- a/client/src/scss/font_awesome/_mixins.scss
+++ b/client/src/scss/font_awesome/_mixins.scss
@@ -12,15 +12,49 @@
}
@mixin fa-icon-rotate($degrees, $rotation) {
- filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})";
-webkit-transform: rotate($degrees);
-ms-transform: rotate($degrees);
transform: rotate($degrees);
}
@mixin fa-icon-flip($horiz, $vert, $rotation) {
- filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation});
+ -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)";
-webkit-transform: scale($horiz, $vert);
-ms-transform: scale($horiz, $vert);
transform: scale($horiz, $vert);
}
+
+
+// Only display content to screen readers. A la Bootstrap 4.
+//
+// See: http://a11yproject.com/posts/how-to-hide-content/
+
+@mixin sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ border: 0;
+}
+
+// Use in conjunction with .sr-only to only display content when it's focused.
+//
+// Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
+//
+// Credit: HTML5 Boilerplate
+
+@mixin sr-only-focusable {
+ &:active,
+ &:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+ }
+}
diff --git a/client/src/scss/font_awesome/_screen-reader.scss b/client/src/scss/font_awesome/_screen-reader.scss
new file mode 100644
index 00000000..637426f0
--- /dev/null
+++ b/client/src/scss/font_awesome/_screen-reader.scss
@@ -0,0 +1,5 @@
+// Screen Readers
+// -------------------------
+
+.sr-only { @include sr-only(); }
+.sr-only-focusable { @include sr-only-focusable(); }
diff --git a/client/src/scss/font_awesome/_variables.scss b/client/src/scss/font_awesome/_variables.scss
index c10cd47f..498fc4a0 100644
--- a/client/src/scss/font_awesome/_variables.scss
+++ b/client/src/scss/font_awesome/_variables.scss
@@ -4,14 +4,18 @@
$fa-font-path: "../fonts" !default;
$fa-font-size-base: 14px !default;
$fa-line-height-base: 1 !default;
-//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.4.0/fonts" !default; // for referencing Bootstrap CDN font files directly
+//$fa-font-path: "//netdna.bootstrapcdn.com/font-awesome/4.7.0/fonts" !default; // for referencing Bootstrap CDN font files directly
$fa-css-prefix: fa !default;
-$fa-version: "4.4.0" !default;
+$fa-version: "4.7.0" !default;
$fa-border-color: #eee !default;
$fa-inverse: #fff !default;
$fa-li-width: (30em / 14) !default;
$fa-var-500px: "\f26e";
+$fa-var-address-book: "\f2b9";
+$fa-var-address-book-o: "\f2ba";
+$fa-var-address-card: "\f2bb";
+$fa-var-address-card-o: "\f2bc";
$fa-var-adjust: "\f042";
$fa-var-adn: "\f170";
$fa-var-align-center: "\f037";
@@ -20,6 +24,7 @@ $fa-var-align-left: "\f036";
$fa-var-align-right: "\f038";
$fa-var-amazon: "\f270";
$fa-var-ambulance: "\f0f9";
+$fa-var-american-sign-language-interpreting: "\f2a3";
$fa-var-anchor: "\f13d";
$fa-var-android: "\f17b";
$fa-var-angellist: "\f209";
@@ -50,17 +55,24 @@ $fa-var-arrows: "\f047";
$fa-var-arrows-alt: "\f0b2";
$fa-var-arrows-h: "\f07e";
$fa-var-arrows-v: "\f07d";
+$fa-var-asl-interpreting: "\f2a3";
+$fa-var-assistive-listening-systems: "\f2a2";
$fa-var-asterisk: "\f069";
$fa-var-at: "\f1fa";
+$fa-var-audio-description: "\f29e";
$fa-var-automobile: "\f1b9";
$fa-var-backward: "\f04a";
$fa-var-balance-scale: "\f24e";
$fa-var-ban: "\f05e";
+$fa-var-bandcamp: "\f2d5";
$fa-var-bank: "\f19c";
$fa-var-bar-chart: "\f080";
$fa-var-bar-chart-o: "\f080";
$fa-var-barcode: "\f02a";
$fa-var-bars: "\f0c9";
+$fa-var-bath: "\f2cd";
+$fa-var-bathtub: "\f2cd";
+$fa-var-battery: "\f240";
$fa-var-battery-0: "\f244";
$fa-var-battery-1: "\f243";
$fa-var-battery-2: "\f242";
@@ -86,12 +98,16 @@ $fa-var-bitbucket: "\f171";
$fa-var-bitbucket-square: "\f172";
$fa-var-bitcoin: "\f15a";
$fa-var-black-tie: "\f27e";
+$fa-var-blind: "\f29d";
+$fa-var-bluetooth: "\f293";
+$fa-var-bluetooth-b: "\f294";
$fa-var-bold: "\f032";
$fa-var-bolt: "\f0e7";
$fa-var-bomb: "\f1e2";
$fa-var-book: "\f02d";
$fa-var-bookmark: "\f02e";
$fa-var-bookmark-o: "\f097";
+$fa-var-braille: "\f2a1";
$fa-var-briefcase: "\f0b1";
$fa-var-btc: "\f15a";
$fa-var-bug: "\f188";
@@ -164,6 +180,7 @@ $fa-var-cny: "\f157";
$fa-var-code: "\f121";
$fa-var-code-fork: "\f126";
$fa-var-codepen: "\f1cb";
+$fa-var-codiepie: "\f284";
$fa-var-coffee: "\f0f4";
$fa-var-cog: "\f013";
$fa-var-cogs: "\f085";
@@ -182,6 +199,7 @@ $fa-var-copy: "\f0c5";
$fa-var-copyright: "\f1f9";
$fa-var-creative-commons: "\f25e";
$fa-var-credit-card: "\f09d";
+$fa-var-credit-card-alt: "\f283";
$fa-var-crop: "\f125";
$fa-var-crosshairs: "\f05b";
$fa-var-css3: "\f13c";
@@ -192,6 +210,8 @@ $fa-var-cutlery: "\f0f5";
$fa-var-dashboard: "\f0e4";
$fa-var-dashcube: "\f210";
$fa-var-database: "\f1c0";
+$fa-var-deaf: "\f2a4";
+$fa-var-deafness: "\f2a4";
$fa-var-dedent: "\f03b";
$fa-var-delicious: "\f1a5";
$fa-var-desktop: "\f108";
@@ -202,17 +222,25 @@ $fa-var-dollar: "\f155";
$fa-var-dot-circle-o: "\f192";
$fa-var-download: "\f019";
$fa-var-dribbble: "\f17d";
+$fa-var-drivers-license: "\f2c2";
+$fa-var-drivers-license-o: "\f2c3";
$fa-var-dropbox: "\f16b";
$fa-var-drupal: "\f1a9";
+$fa-var-edge: "\f282";
$fa-var-edit: "\f044";
+$fa-var-eercast: "\f2da";
$fa-var-eject: "\f052";
$fa-var-ellipsis-h: "\f141";
$fa-var-ellipsis-v: "\f142";
$fa-var-empire: "\f1d1";
$fa-var-envelope: "\f0e0";
$fa-var-envelope-o: "\f003";
+$fa-var-envelope-open: "\f2b6";
+$fa-var-envelope-open-o: "\f2b7";
$fa-var-envelope-square: "\f199";
+$fa-var-envira: "\f299";
$fa-var-eraser: "\f12d";
+$fa-var-etsy: "\f2d7";
$fa-var-eur: "\f153";
$fa-var-euro: "\f153";
$fa-var-exchange: "\f0ec";
@@ -226,6 +254,7 @@ $fa-var-external-link-square: "\f14c";
$fa-var-eye: "\f06e";
$fa-var-eye-slash: "\f070";
$fa-var-eyedropper: "\f1fb";
+$fa-var-fa: "\f2b4";
$fa-var-facebook: "\f09a";
$fa-var-facebook-f: "\f09a";
$fa-var-facebook-official: "\f230";
@@ -260,6 +289,7 @@ $fa-var-filter: "\f0b0";
$fa-var-fire: "\f06d";
$fa-var-fire-extinguisher: "\f134";
$fa-var-firefox: "\f269";
+$fa-var-first-order: "\f2b0";
$fa-var-flag: "\f024";
$fa-var-flag-checkered: "\f11e";
$fa-var-flag-o: "\f11d";
@@ -272,10 +302,13 @@ $fa-var-folder-o: "\f114";
$fa-var-folder-open: "\f07c";
$fa-var-folder-open-o: "\f115";
$fa-var-font: "\f031";
+$fa-var-font-awesome: "\f2b4";
$fa-var-fonticons: "\f280";
+$fa-var-fort-awesome: "\f286";
$fa-var-forumbee: "\f211";
$fa-var-forward: "\f04e";
$fa-var-foursquare: "\f180";
+$fa-var-free-code-camp: "\f2c5";
$fa-var-frown-o: "\f119";
$fa-var-futbol-o: "\f1e3";
$fa-var-gamepad: "\f11b";
@@ -294,15 +327,21 @@ $fa-var-git-square: "\f1d2";
$fa-var-github: "\f09b";
$fa-var-github-alt: "\f113";
$fa-var-github-square: "\f092";
+$fa-var-gitlab: "\f296";
$fa-var-gittip: "\f184";
$fa-var-glass: "\f000";
+$fa-var-glide: "\f2a5";
+$fa-var-glide-g: "\f2a6";
$fa-var-globe: "\f0ac";
$fa-var-google: "\f1a0";
$fa-var-google-plus: "\f0d5";
+$fa-var-google-plus-circle: "\f2b3";
+$fa-var-google-plus-official: "\f2b3";
$fa-var-google-plus-square: "\f0d4";
$fa-var-google-wallet: "\f1ee";
$fa-var-graduation-cap: "\f19d";
$fa-var-gratipay: "\f184";
+$fa-var-grav: "\f2d6";
$fa-var-group: "\f0c0";
$fa-var-h-square: "\f0fd";
$fa-var-hacker-news: "\f1d4";
@@ -319,6 +358,9 @@ $fa-var-hand-rock-o: "\f255";
$fa-var-hand-scissors-o: "\f257";
$fa-var-hand-spock-o: "\f259";
$fa-var-hand-stop-o: "\f256";
+$fa-var-handshake-o: "\f2b5";
+$fa-var-hard-of-hearing: "\f2a4";
+$fa-var-hashtag: "\f292";
$fa-var-hdd-o: "\f0a0";
$fa-var-header: "\f1dc";
$fa-var-headphones: "\f025";
@@ -340,8 +382,12 @@ $fa-var-hourglass-start: "\f251";
$fa-var-houzz: "\f27c";
$fa-var-html5: "\f13b";
$fa-var-i-cursor: "\f246";
+$fa-var-id-badge: "\f2c1";
+$fa-var-id-card: "\f2c2";
+$fa-var-id-card-o: "\f2c3";
$fa-var-ils: "\f20b";
$fa-var-image: "\f03e";
+$fa-var-imdb: "\f2d8";
$fa-var-inbox: "\f01c";
$fa-var-indent: "\f03c";
$fa-var-industry: "\f275";
@@ -379,6 +425,7 @@ $fa-var-line-chart: "\f201";
$fa-var-link: "\f0c1";
$fa-var-linkedin: "\f0e1";
$fa-var-linkedin-square: "\f08c";
+$fa-var-linode: "\f2b8";
$fa-var-linux: "\f17c";
$fa-var-list: "\f03a";
$fa-var-list-alt: "\f022";
@@ -390,6 +437,7 @@ $fa-var-long-arrow-down: "\f175";
$fa-var-long-arrow-left: "\f177";
$fa-var-long-arrow-right: "\f178";
$fa-var-long-arrow-up: "\f176";
+$fa-var-low-vision: "\f2a8";
$fa-var-magic: "\f0d0";
$fa-var-magnet: "\f076";
$fa-var-mail-forward: "\f064";
@@ -410,16 +458,20 @@ $fa-var-maxcdn: "\f136";
$fa-var-meanpath: "\f20c";
$fa-var-medium: "\f23a";
$fa-var-medkit: "\f0fa";
+$fa-var-meetup: "\f2e0";
$fa-var-meh-o: "\f11a";
$fa-var-mercury: "\f223";
+$fa-var-microchip: "\f2db";
$fa-var-microphone: "\f130";
$fa-var-microphone-slash: "\f131";
$fa-var-minus: "\f068";
$fa-var-minus-circle: "\f056";
$fa-var-minus-square: "\f146";
$fa-var-minus-square-o: "\f147";
+$fa-var-mixcloud: "\f289";
$fa-var-mobile: "\f10b";
$fa-var-mobile-phone: "\f10b";
+$fa-var-modx: "\f285";
$fa-var-money: "\f0d6";
$fa-var-moon-o: "\f186";
$fa-var-mortar-board: "\f19d";
@@ -446,18 +498,22 @@ $fa-var-paperclip: "\f0c6";
$fa-var-paragraph: "\f1dd";
$fa-var-paste: "\f0ea";
$fa-var-pause: "\f04c";
+$fa-var-pause-circle: "\f28b";
+$fa-var-pause-circle-o: "\f28c";
$fa-var-paw: "\f1b0";
$fa-var-paypal: "\f1ed";
$fa-var-pencil: "\f040";
$fa-var-pencil-square: "\f14b";
$fa-var-pencil-square-o: "\f044";
+$fa-var-percent: "\f295";
$fa-var-phone: "\f095";
$fa-var-phone-square: "\f098";
$fa-var-photo: "\f03e";
$fa-var-picture-o: "\f03e";
$fa-var-pie-chart: "\f200";
-$fa-var-pied-piper: "\f1a7";
+$fa-var-pied-piper: "\f2ae";
$fa-var-pied-piper-alt: "\f1a8";
+$fa-var-pied-piper-pp: "\f1a7";
$fa-var-pinterest: "\f0d2";
$fa-var-pinterest-p: "\f231";
$fa-var-pinterest-square: "\f0d3";
@@ -470,20 +526,26 @@ $fa-var-plus: "\f067";
$fa-var-plus-circle: "\f055";
$fa-var-plus-square: "\f0fe";
$fa-var-plus-square-o: "\f196";
+$fa-var-podcast: "\f2ce";
$fa-var-power-off: "\f011";
$fa-var-print: "\f02f";
+$fa-var-product-hunt: "\f288";
$fa-var-puzzle-piece: "\f12e";
$fa-var-qq: "\f1d6";
$fa-var-qrcode: "\f029";
$fa-var-question: "\f128";
$fa-var-question-circle: "\f059";
+$fa-var-question-circle-o: "\f29c";
+$fa-var-quora: "\f2c4";
$fa-var-quote-left: "\f10d";
$fa-var-quote-right: "\f10e";
$fa-var-ra: "\f1d0";
$fa-var-random: "\f074";
+$fa-var-ravelry: "\f2d9";
$fa-var-rebel: "\f1d0";
$fa-var-recycle: "\f1b8";
$fa-var-reddit: "\f1a1";
+$fa-var-reddit-alien: "\f281";
$fa-var-reddit-square: "\f1a2";
$fa-var-refresh: "\f021";
$fa-var-registered: "\f25d";
@@ -493,6 +555,7 @@ $fa-var-reorder: "\f0c9";
$fa-var-repeat: "\f01e";
$fa-var-reply: "\f112";
$fa-var-reply-all: "\f122";
+$fa-var-resistance: "\f1d0";
$fa-var-retweet: "\f079";
$fa-var-rmb: "\f157";
$fa-var-road: "\f018";
@@ -505,9 +568,11 @@ $fa-var-rss-square: "\f143";
$fa-var-rub: "\f158";
$fa-var-ruble: "\f158";
$fa-var-rupee: "\f156";
+$fa-var-s15: "\f2cd";
$fa-var-safari: "\f267";
$fa-var-save: "\f0c7";
$fa-var-scissors: "\f0c4";
+$fa-var-scribd: "\f28a";
$fa-var-search: "\f002";
$fa-var-search-minus: "\f010";
$fa-var-search-plus: "\f00e";
@@ -525,10 +590,15 @@ $fa-var-sheqel: "\f20b";
$fa-var-shield: "\f132";
$fa-var-ship: "\f21a";
$fa-var-shirtsinbulk: "\f214";
+$fa-var-shopping-bag: "\f290";
+$fa-var-shopping-basket: "\f291";
$fa-var-shopping-cart: "\f07a";
+$fa-var-shower: "\f2cc";
$fa-var-sign-in: "\f090";
+$fa-var-sign-language: "\f2a7";
$fa-var-sign-out: "\f08b";
$fa-var-signal: "\f012";
+$fa-var-signing: "\f2a7";
$fa-var-simplybuilt: "\f215";
$fa-var-sitemap: "\f0e8";
$fa-var-skyatlas: "\f216";
@@ -537,6 +607,10 @@ $fa-var-slack: "\f198";
$fa-var-sliders: "\f1de";
$fa-var-slideshare: "\f1e7";
$fa-var-smile-o: "\f118";
+$fa-var-snapchat: "\f2ab";
+$fa-var-snapchat-ghost: "\f2ac";
+$fa-var-snapchat-square: "\f2ad";
+$fa-var-snowflake-o: "\f2dc";
$fa-var-soccer-ball-o: "\f1e3";
$fa-var-sort: "\f0dc";
$fa-var-sort-alpha-asc: "\f15d";
@@ -572,6 +646,8 @@ $fa-var-stethoscope: "\f0f1";
$fa-var-sticky-note: "\f249";
$fa-var-sticky-note-o: "\f24a";
$fa-var-stop: "\f04d";
+$fa-var-stop-circle: "\f28d";
+$fa-var-stop-circle-o: "\f28e";
$fa-var-street-view: "\f21d";
$fa-var-strikethrough: "\f0cc";
$fa-var-stumbleupon: "\f1a4";
@@ -580,6 +656,7 @@ $fa-var-subscript: "\f12c";
$fa-var-subway: "\f239";
$fa-var-suitcase: "\f0f2";
$fa-var-sun-o: "\f185";
+$fa-var-superpowers: "\f2dd";
$fa-var-superscript: "\f12b";
$fa-var-support: "\f1cd";
$fa-var-table: "\f0ce";
@@ -589,6 +666,7 @@ $fa-var-tag: "\f02b";
$fa-var-tags: "\f02c";
$fa-var-tasks: "\f0ae";
$fa-var-taxi: "\f1ba";
+$fa-var-telegram: "\f2c6";
$fa-var-television: "\f26c";
$fa-var-tencent-weibo: "\f1d5";
$fa-var-terminal: "\f120";
@@ -597,6 +675,18 @@ $fa-var-text-width: "\f035";
$fa-var-th: "\f00a";
$fa-var-th-large: "\f009";
$fa-var-th-list: "\f00b";
+$fa-var-themeisle: "\f2b2";
+$fa-var-thermometer: "\f2c7";
+$fa-var-thermometer-0: "\f2cb";
+$fa-var-thermometer-1: "\f2ca";
+$fa-var-thermometer-2: "\f2c9";
+$fa-var-thermometer-3: "\f2c8";
+$fa-var-thermometer-4: "\f2c7";
+$fa-var-thermometer-empty: "\f2cb";
+$fa-var-thermometer-full: "\f2c7";
+$fa-var-thermometer-half: "\f2c9";
+$fa-var-thermometer-quarter: "\f2ca";
+$fa-var-thermometer-three-quarters: "\f2c8";
$fa-var-thumb-tack: "\f08d";
$fa-var-thumbs-down: "\f165";
$fa-var-thumbs-o-down: "\f088";
@@ -606,6 +696,8 @@ $fa-var-ticket: "\f145";
$fa-var-times: "\f00d";
$fa-var-times-circle: "\f057";
$fa-var-times-circle-o: "\f05c";
+$fa-var-times-rectangle: "\f2d3";
+$fa-var-times-rectangle-o: "\f2d4";
$fa-var-tint: "\f043";
$fa-var-toggle-down: "\f150";
$fa-var-toggle-left: "\f191";
@@ -636,28 +728,38 @@ $fa-var-twitter-square: "\f081";
$fa-var-umbrella: "\f0e9";
$fa-var-underline: "\f0cd";
$fa-var-undo: "\f0e2";
+$fa-var-universal-access: "\f29a";
$fa-var-university: "\f19c";
$fa-var-unlink: "\f127";
$fa-var-unlock: "\f09c";
$fa-var-unlock-alt: "\f13e";
$fa-var-unsorted: "\f0dc";
$fa-var-upload: "\f093";
+$fa-var-usb: "\f287";
$fa-var-usd: "\f155";
$fa-var-user: "\f007";
+$fa-var-user-circle: "\f2bd";
+$fa-var-user-circle-o: "\f2be";
$fa-var-user-md: "\f0f0";
+$fa-var-user-o: "\f2c0";
$fa-var-user-plus: "\f234";
$fa-var-user-secret: "\f21b";
$fa-var-user-times: "\f235";
$fa-var-users: "\f0c0";
+$fa-var-vcard: "\f2bb";
+$fa-var-vcard-o: "\f2bc";
$fa-var-venus: "\f221";
$fa-var-venus-double: "\f226";
$fa-var-venus-mars: "\f228";
$fa-var-viacoin: "\f237";
+$fa-var-viadeo: "\f2a9";
+$fa-var-viadeo-square: "\f2aa";
$fa-var-video-camera: "\f03d";
$fa-var-vimeo: "\f27d";
$fa-var-vimeo-square: "\f194";
$fa-var-vine: "\f1ca";
$fa-var-vk: "\f189";
+$fa-var-volume-control-phone: "\f2a0";
$fa-var-volume-down: "\f027";
$fa-var-volume-off: "\f026";
$fa-var-volume-up: "\f028";
@@ -667,11 +769,20 @@ $fa-var-weibo: "\f18a";
$fa-var-weixin: "\f1d7";
$fa-var-whatsapp: "\f232";
$fa-var-wheelchair: "\f193";
+$fa-var-wheelchair-alt: "\f29b";
$fa-var-wifi: "\f1eb";
$fa-var-wikipedia-w: "\f266";
+$fa-var-window-close: "\f2d3";
+$fa-var-window-close-o: "\f2d4";
+$fa-var-window-maximize: "\f2d0";
+$fa-var-window-minimize: "\f2d1";
+$fa-var-window-restore: "\f2d2";
$fa-var-windows: "\f17a";
$fa-var-won: "\f159";
$fa-var-wordpress: "\f19a";
+$fa-var-wpbeginner: "\f297";
+$fa-var-wpexplorer: "\f2de";
+$fa-var-wpforms: "\f298";
$fa-var-wrench: "\f0ad";
$fa-var-xing: "\f168";
$fa-var-xing-square: "\f169";
@@ -682,6 +793,7 @@ $fa-var-yc: "\f23b";
$fa-var-yc-square: "\f1d4";
$fa-var-yelp: "\f1e9";
$fa-var-yen: "\f157";
+$fa-var-yoast: "\f2b1";
$fa-var-youtube: "\f167";
$fa-var-youtube-play: "\f16a";
$fa-var-youtube-square: "\f166";
diff --git a/client/src/scss/font_awesome/_font-awesome.scss b/client/src/scss/font_awesome/font-awesome.scss
similarity index 79%
rename from client/src/scss/font_awesome/_font-awesome.scss
rename to client/src/scss/font_awesome/font-awesome.scss
index ebd9646c..f1c83aaa 100644
--- a/client/src/scss/font_awesome/_font-awesome.scss
+++ b/client/src/scss/font_awesome/font-awesome.scss
@@ -1,5 +1,5 @@
/*!
- * Font Awesome 4.4.0 by @davegandy - http://fontawesome.io - @fontawesome
+ * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
*/
@@ -15,3 +15,4 @@
@import "rotated-flipped";
@import "stacked";
@import "icons";
+@import "screen-reader";
diff --git a/client/src/scss/font_awesome/fonts/FontAwesome.otf b/client/src/scss/font_awesome/fonts/FontAwesome.otf
index 681bdd4d..401ec0f3 100644
Binary files a/client/src/scss/font_awesome/fonts/FontAwesome.otf and b/client/src/scss/font_awesome/fonts/FontAwesome.otf differ
diff --git a/client/src/scss/font_awesome/fonts/fontawesome-webfont.eot b/client/src/scss/font_awesome/fonts/fontawesome-webfont.eot
index a30335d7..e9f60ca9 100644
Binary files a/client/src/scss/font_awesome/fonts/fontawesome-webfont.eot and b/client/src/scss/font_awesome/fonts/fontawesome-webfont.eot differ
diff --git a/client/src/scss/font_awesome/fonts/fontawesome-webfont.svg b/client/src/scss/font_awesome/fonts/fontawesome-webfont.svg
index 6fd19abc..855c845e 100644
--- a/client/src/scss/font_awesome/fonts/fontawesome-webfont.svg
+++ b/client/src/scss/font_awesome/fonts/fontawesome-webfont.svg
@@ -1,640 +1,2671 @@
-
diff --git a/client/src/scss/font_awesome/fonts/fontawesome-webfont.ttf b/client/src/scss/font_awesome/fonts/fontawesome-webfont.ttf
index d7994e13..35acda2f 100644
Binary files a/client/src/scss/font_awesome/fonts/fontawesome-webfont.ttf and b/client/src/scss/font_awesome/fonts/fontawesome-webfont.ttf differ
diff --git a/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff b/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff
index 6fd4ede0..400014a4 100644
Binary files a/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff and b/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff differ
diff --git a/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff2 b/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff2
index 5560193c..4d13fc60 100644
Binary files a/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff2 and b/client/src/scss/font_awesome/fonts/fontawesome-webfont.woff2 differ