diff --git a/src/components/auth-block.js b/src/components/auth-block.js
index 7c28ce7f..6c598213 100644
--- a/src/components/auth-block.js
+++ b/src/components/auth-block.js
@@ -30,10 +30,15 @@ const AuthBlock = ({ current_user, is_logged_in }) => {
if (is_logged_in) {
const logoutUrl = '/api/v1/logout';
+ let user = {};
+ if (current_user) {
+ user = current_user.user;
+ }
+
return (
-
+
Profile settings
);
}
}
diff --git a/src/components/bookmarks/index.js b/src/components/bookmarks/index.js
new file mode 100644
index 00000000..859b5c82
--- /dev/null
+++ b/src/components/bookmarks/index.js
@@ -0,0 +1,22 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import Bookmarks from './bookmarks';
+import Bookmark from './bookmark';
+
+export { Bookmark };
+export default Bookmarks;
diff --git a/src/components/bookmarks/settings-form.js b/src/components/bookmarks/settings-form.js
new file mode 100644
index 00000000..4f7f121d
--- /dev/null
+++ b/src/components/bookmarks/settings-form.js
@@ -0,0 +1,84 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React, { PropTypes } from 'react';
+import { form as inform, from } from 'react-inform';
+
+import Message from '../message';
+
+class BookmarkSettingsForm extends React.Component {
+ static propTypes = {
+ fields: PropTypes.shape({}),
+ form: PropTypes.shape({}),
+ onSave: PropTypes.func,
+ title: PropTypes.string,
+ to: PropTypes.string
+ };
+
+ static defaultProps = {
+ onSave: () => {}
+ };
+
+ componentDidMount() {
+ const { form, title, to } = this.props;
+
+ form.onValues({ title, to });
+ }
+
+ handleSubmit = (e) => {
+ e.preventDefault();
+
+ const { form, onSave } = this.props;
+
+ form.forceValidate();
+ if (!form.isValid()) {
+ return;
+ }
+
+ const newValues = form.values();
+ onSave(newValues);
+ };
+
+ render() {
+ const { fields } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+const WrappedBookmarkSettingsForm = inform(from({
+ icon: {},
+ title: {},
+ to: {}
+}))(BookmarkSettingsForm);
+
+export default WrappedBookmarkSettingsForm;
diff --git a/src/components/bookmarks/settings-modal.js b/src/components/bookmarks/settings-modal.js
new file mode 100644
index 00000000..d8df89fc
--- /dev/null
+++ b/src/components/bookmarks/settings-modal.js
@@ -0,0 +1,48 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React, { PropTypes } from 'react';
+
+import BookmarkSettingsForm from './settings-form';
+import Modal from '../modal-component';
+
+const BookmarkSettingsModal = ({ onClose, onSave, ...props }) => {
+ return (
+
+
+ Bookmark settings
+
+
+
+
+
+ );
+};
+
+BookmarkSettingsModal.propTypes = {
+ onClose: PropTypes.func,
+ onSave: PropTypes.func
+};
+
+BookmarkSettingsModal.defaultProps = {
+ onClose: () => {},
+ onSave: () => {}
+};
+
+export default BookmarkSettingsModal;
diff --git a/src/components/navigation-item.js b/src/components/navigation-item.js
index 0f25324c..b9895731 100644
--- a/src/components/navigation-item.js
+++ b/src/components/navigation-item.js
@@ -18,7 +18,7 @@
import React, { PropTypes } from 'react';
import classNames from 'classnames';
import { Link } from 'react-router';
-import { omit } from 'lodash';
+import { assign, omit } from 'lodash';
import Icon from './icon';
@@ -52,21 +52,26 @@ const NavigationItemPlain = ({
if (theme === '2.0') {
const { icon, badge, ...htmlProps } = props;
+ const finalIcon = assign({}, icon, {
+ className: classNames('navigation-item__icon', {
+ [icon && icon.className]: icon && icon.className
+ })
+ });
+
return (
{icon &&
-
+
}
);
diff --git a/src/components/post/footer.js b/src/components/post/footer.js
index 731ac574..25ed8a2f 100644
--- a/src/components/post/footer.js
+++ b/src/components/post/footer.js
@@ -21,7 +21,7 @@ import { isEmpty } from 'lodash';
import Time from '../time';
import EditPostButton from './edit-post-button';
-import TagLine from './tagline';
+import TagCloud from '../tag-cloud';
import Toolbar from './toolbar';
import User from '../user';
import { URL_NAMES, getUrl } from '../../utils/urlGenerator';
@@ -72,10 +72,16 @@ class PostFooter extends React.Component {
-
{hasTags &&
}
diff --git a/src/components/post/tagline.js b/src/components/post/tagline.js
deleted file mode 100644
index b3025a3a..00000000
--- a/src/components/post/tagline.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- This file is a part of libertysoil.org website
- Copyright (C) 2016 Loki Education (Social Enterprise)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-import React from 'react';
-
-import Tag from '../tag';
-import { TAG_HASHTAG, TAG_SCHOOL, TAG_LOCATION } from '../../consts/tags';
-
-const TagLine = ({ geotags, hashtags, schools }) => {
- if ((geotags && hashtags && schools) && (!geotags.length && !hashtags.length && !schools.length)) {
- return null;
- }
-
- let geotagBlocks;
- if (geotags) {
- geotagBlocks = geotags.map(school => {
- return (
-
- );
- });
- }
-
- let schoolBlocks;
- if (schools) {
- schoolBlocks = schools.map(school => {
- return (
-
- );
- });
- }
-
- let hashtagBlocks;
- if (hashtags) {
- hashtagBlocks = hashtags.map(tag => {
- return (
-
- );
- });
- }
-
- return (
-
- );
-};
-
-TagLine.displayName = 'TagLine';
-
-TagLine.propTypes = {
- geotags: React.PropTypes.arrayOf(React.PropTypes.shape({
- id: React.PropTypes.string,
- name: React.PropTypes.string
- })),
- hashtags: React.PropTypes.arrayOf(React.PropTypes.shape({
- id: React.PropTypes.string,
- name: React.PropTypes.string
- })),
- schools: React.PropTypes.arrayOf(React.PropTypes.shape({
- id: React.PropTypes.string,
- name: React.PropTypes.string,
- url_name: React.PropTypes.string
- }))
-};
-
-export default TagLine;
diff --git a/src/components/sidebar-menu/extended.js b/src/components/sidebar-menu/extended.js
new file mode 100644
index 00000000..5fe4dc2d
--- /dev/null
+++ b/src/components/sidebar-menu/extended.js
@@ -0,0 +1,134 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+
+import { CurrentUser as CurrentUserPropType } from '../../prop-types/users';
+import { MENU_ITEMS } from '../../consts/sidebar-menu';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+
+export default class SidebarMenuExtended extends React.Component {
+ static propTypes = {
+ current_user: CurrentUserPropType
+ };
+
+ renderNews = () => {
+ const { current_user: { user = {} } } = this.props;
+ const { username } = user;
+ const { news: menuItem } = MENU_ITEMS;
+
+ const unreadPosts = 4;
+
+ let menuItemContent = menuItem.title.normal;
+ if (unreadPosts) {
+ menuItemContent += `: ${unreadPosts} new posts`;
+ }
+
+ return (
+
+ {menuItemContent}
+
+ );
+ };
+
+ renderLikes = () => {
+ const { current_user: { likes, user = {} } } = this.props;
+ const { username } = user;
+ const { likes: menuItem } = MENU_ITEMS;
+
+ let menuItemContent = menuItem.title.normal;
+ if (likes.length) {
+ menuItemContent += `: ${likes.length} total`;
+ }
+
+ menuItemContent += `, ${undefined} last week`;
+
+ return (
+
+ {menuItemContent}
+
+ );
+ };
+
+ renderFavorites = () => {
+ const { current_user: { favourites, user = {} } } = this.props;
+ const { username } = user;
+ const { favorites: menuItem } = MENU_ITEMS;
+
+ let menuItemContent = menuItem.title.normal;
+ if (favourites.length) {
+ menuItemContent += `: ${favourites.length} posts`;
+ }
+
+ menuItemContent += `, ${undefined} categories`;
+
+ return (
+
+ {menuItemContent}
+
+ );
+ };
+
+ renderCollections = () => {
+ const { current_user: { following_collections, user = {} } } = this.props;
+ const { username } = user;
+ const { collections: menuItem } = MENU_ITEMS;
+
+ let menuItemContent = menuItem.title.normal;
+ if (following_collections && following_collections.length) {
+ menuItemContent += `: ${following_collections.length} posts`;
+ }
+
+ menuItemContent += `, ${undefined} curated`;
+
+ return (
+
+ {menuItemContent}
+
+ );
+ };
+
+ render() {
+ return (
+
+ {this.renderNews()}
+ {this.renderLikes()}
+ {this.renderFavorites()}
+ {this.renderCollections()}
+
+ );
+ }
+}
diff --git a/src/components/sidebar-link.js b/src/components/sidebar-menu/index.js
similarity index 57%
rename from src/components/sidebar-link.js
rename to src/components/sidebar-menu/index.js
index 39f70b3e..1d609da3 100644
--- a/src/components/sidebar-link.js
+++ b/src/components/sidebar-menu/index.js
@@ -16,29 +16,27 @@
along with this program. If not, see .
*/
import React, { PropTypes } from 'react';
-import { Link } from 'react-router';
-const SidebarLink = ({ activeClassName, children, className, enabled, to }) => {
- if (enabled) {
- return {children};
+import SidebarMenuTruncated from './truncated';
+import SidebarMenuMin from './min';
+import SidebarMenuNormal from './normal';
+import SidebarMenuExtended from './extended';
+
+const SidebarMenu = ({ theme, ...props }) => {
+ switch (theme) {
+ case 'trunc': return ;
+ case 'min': return ;
+ case 'ext': return ;
+ default: return ;
}
-
- let cn = 'disabled';
- if (className) {
- cn += ` ${className}`;
- }
-
- return {children};
};
-SidebarLink.displayName = 'SidebarLink';
+SidebarMenu.propTypes = {
+ theme: PropTypes.string
+};
-SidebarLink.propTypes = {
- activeClassName: PropTypes.string,
- children: PropTypes.node,
- className: PropTypes.string,
- enabled: PropTypes.bool,
- to: PropTypes.string
+SidebarMenu.defaultProps = {
+ theme: 'normal'
};
-export default SidebarLink;
+export default SidebarMenu;
diff --git a/src/components/sidebar-menu/min.js b/src/components/sidebar-menu/min.js
new file mode 100644
index 00000000..e9cf78a5
--- /dev/null
+++ b/src/components/sidebar-menu/min.js
@@ -0,0 +1,58 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+import { values } from 'lodash';
+
+import { CurrentUser as CurrentUserPropTypes } from '../../prop-types/users';
+import { MENU_ITEMS } from '../../consts/sidebar-menu';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+
+const menuItemsArray = values(MENU_ITEMS);
+
+const SidebarMenuMin = ({ current_user }) => {
+ const { user = {} } = current_user;
+ const { username } = user;
+
+ return (
+
+ {menuItemsArray.map((item, i) => (
+
+ {item.title.min}
+
+ ))
+ }
+
+ );
+};
+
+SidebarMenuMin.propTypes = {
+ current_user: CurrentUserPropTypes
+};
+
+SidebarMenuMin.defaultProps = {
+ current_user: {}
+};
+
+export default SidebarMenuMin;
diff --git a/src/components/sidebar-menu/normal.js b/src/components/sidebar-menu/normal.js
new file mode 100644
index 00000000..5e01ad40
--- /dev/null
+++ b/src/components/sidebar-menu/normal.js
@@ -0,0 +1,59 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+import { values } from 'lodash';
+
+import { CurrentUser as CurrentUserPropTypes } from '../../prop-types/users';
+import { MENU_ITEMS } from '../../consts/sidebar-menu';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+
+const menuItemsArray = values(MENU_ITEMS);
+
+const SidebarMenuNormal = ({ current_user }) => {
+ const { user = {} } = current_user;
+ const { username } = user;
+
+ return (
+
+ {menuItemsArray.map((item, i) => (
+
+ {item.title.normal}
+
+ ))
+ }
+
+ );
+};
+
+SidebarMenuNormal.propTypes = {
+ current_user: CurrentUserPropTypes
+};
+
+SidebarMenuNormal.defaultProps = {
+ current_user: {}
+};
+
+export default SidebarMenuNormal;
diff --git a/src/components/sidebar-menu/truncated.js b/src/components/sidebar-menu/truncated.js
new file mode 100644
index 00000000..3dc6ac95
--- /dev/null
+++ b/src/components/sidebar-menu/truncated.js
@@ -0,0 +1,57 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+import { values } from 'lodash';
+
+import { CurrentUser as CurrentUserPropTypes } from '../../prop-types/users';
+import { MENU_ITEMS } from '../../consts/sidebar-menu';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+
+const SidebarMenuTruncated = ({ current_user }) => {
+ const { user = {} } = current_user;
+ const { username } = user;
+ const menuItemsArray = values(MENU_ITEMS);
+
+ return (
+
+ {menuItemsArray.map((item, i) => (
+
+ ))
+ }
+
+ );
+};
+
+SidebarMenuTruncated.propTypes = {
+ current_user: CurrentUserPropTypes
+};
+
+SidebarMenuTruncated.defaultProps = {
+ current_user: {}
+};
+
+export default SidebarMenuTruncated;
diff --git a/src/components/sidebar.js b/src/components/sidebar.js
index 5adfd942..cbd45bf1 100644
--- a/src/components/sidebar.js
+++ b/src/components/sidebar.js
@@ -16,214 +16,48 @@
along with this program. If not, see .
*/
import React, { PropTypes } from 'react';
-import { values, throttle } from 'lodash';
-import { connect } from 'react-redux';
-import { Link } from 'react-router';
-import { Immutable as ImmutablePropType } from '../prop-types/common';
import { CurrentUser as CurrentUserPropType } from '../prop-types/users';
-import { toggleSidebar } from '../actions/ui';
-
-import Navigation from './navigation';
-import NavigationItem from './navigation-item';
-import CurrentUser from './current-user';
-import TagCloud from './tag-cloud';
-import SidebarFollowedTags from './sidebar-followed-tags';
-import currentUserSelector from '../selectors/currentUser';
-import createSelector from '../selectors/createSelector';
-
-class Sidebar extends React.Component {
- static displayName = 'Sidebar';
+import TagsInform from './tags-inform';
+import Bookmarks from './bookmarks';
+import SidebarMenu from './sidebar-menu';
+export default class Sidebar extends React.Component {
static propTypes = {
- current_user: ImmutablePropType(CurrentUserPropType),
- dispatch: PropTypes.func.isRequired,
- is_logged_in: PropTypes.bool.isRequired
- };
-
- static contextTypes = {
- routeLocation: PropTypes.shape({})
+ current_user: CurrentUserPropType,
+ theme: PropTypes.string
};
- constructor(props) {
- super(props);
-
- this.state = {
- clientWidth: 0
- };
- }
-
- componentDidMount() {
- window.addEventListener('resize', this.toggleVisible);
- document.addEventListener('DOMContentLoaded', this.toggleVisible);
- }
-
- componentWillUnmount() {
- window.removeEventListener('resize', this.toggleVisible);
- document.removeEventListener('DOMContentLoaded', this.toggleVisible);
- }
-
- toggleVisible = throttle(() => {
- const {
- dispatch,
- ui
- } = this.props;
- const breakpointWidth = 1330;
+ getClassName = () => {
+ const { theme } = this.props;
+ const finalize = s => `sidebar col col-${s} col-s-${s} col-m-${s} col-l-${s} col-xl-${s}`;
- if (typeof document == 'undefined') {
- return;
+ switch (theme) {
+ case 'trunc': return finalize(1);
+ case 'min': return finalize(2);
+ case 'ext': return finalize(6);
+ default: return finalize(4);
}
-
- const clientWidth = document.body.clientWidth;
-
- if (clientWidth == this.state.clientWidth) {
- return;
- }
-
- if (ui.get('sidebarIsVisible') && (clientWidth <= breakpointWidth) && (clientWidth < this.state.clientWidth)) {
- dispatch(toggleSidebar(false));
- }
-
- if (!ui.get('sidebarIsVisible') && (clientWidth >= breakpointWidth) && (clientWidth > this.state.clientWidth)) {
- dispatch(toggleSidebar(true));
- }
-
- // If DOMContentLoaded event and small screen width
- if (this.state.clientWidth == 0 && clientWidth <= breakpointWidth) {
- dispatch(toggleSidebar(false));
- }
-
- this.setState({ clientWidth });
- }, 100);
+ };
render() {
- const { routeLocation } = this.context;
- const {
- ui,
- is_logged_in
- } = this.props;
- const sidebarClassName = ['sidebar'];
-
- if (!is_logged_in) {
- return null;
- }
-
- if (ui.get('sidebarIsVisible')) {
- sidebarClassName.push('sidebar-visible');
- }
-
- const current_user = this.props.current_user.toJS();
-
- const followedTags = values(current_user.followed_hashtags);
- const followedSchools = values(current_user.followed_schools);
- const followedGeotags = values(current_user.followed_geotags);
-
- const showLikes =
- (current_user.likes && current_user.likes.length)
- || this.props.current_user.get('liked_hashtags').size
- || this.props.current_user.get('liked_geotags').size
- || this.props.current_user.get('liked_schools').size;
- const showFavorites = (current_user.favourites && current_user.favourites.length > 0);
- const showFollowedTags = followedTags.length || followedSchools.length || followedGeotags.length;
- const showUsedTags = current_user.hashtags.length || current_user.geotags.length || current_user.schools.length;
-
- let followedTagsSection;
- if (showFollowedTags) {
- followedTagsSection = (
-
-
I follow
-
-
-
-
- );
- }
-
- let likesSection;
- if (showLikes) {
- likesSection = (
-
- My Likes
-
- );
- }
-
- let favouritesSection;
- if (showFavorites) {
- favouritesSection = (
-
- My Favorites
-
- );
- }
-
- let usedTagsSection;
- if (showUsedTags) {
- usedTagsSection = (
-
);
}
}
-
-const selector = createSelector(
- state => state.get('ui'),
- currentUserSelector,
- (ui, current_user) => ({
- ui,
- ...current_user
- })
-);
-
-export default connect(selector)(Sidebar);
diff --git a/src/components/tags-inform/extended.js b/src/components/tags-inform/extended.js
new file mode 100644
index 00000000..83ef35ea
--- /dev/null
+++ b/src/components/tags-inform/extended.js
@@ -0,0 +1,62 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+import { keys, transform } from 'lodash';
+
+import { TagsToInform as TagsToInformPropType } from './prop-types';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+import TagCloud from '../tag-cloud';
+
+const TagsInformExtended = ({ tags, ...props }) => {
+ return (
+
+ {transform(tags, (acc, tagType, tagTypeTitle) => {
+ if (keys(tagType.list).length) {
+ let unread = tagType.unreadPosts;
+ if (tagType.unreadPosts > 99) {
+ unread = '99+';
+ }
+
+ acc.push(
+
+
+
+ );
+ }
+ }, [])}
+
+ );
+};
+
+TagsInformExtended.propTypes = {
+ tags: TagsToInformPropType
+};
+
+export default TagsInformExtended;
diff --git a/src/components/tags-inform/index.js b/src/components/tags-inform/index.js
new file mode 100644
index 00000000..51009a00
--- /dev/null
+++ b/src/components/tags-inform/index.js
@@ -0,0 +1,92 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React, { PropTypes } from 'react';
+import { omit, values } from 'lodash';
+
+import { CurrentUser as CurrentUserPropType } from '../../prop-types/users';
+
+import TagsInformTrunc from './trunc';
+import TagsInformNormal from './normal';
+import TagsInformExtended from './extended';
+
+/**
+ * Navigation-like block displaying number of unread posts
+ * per each group of tags (geotags, schools, hashtags)
+ */
+export default class TagsInform extends React.Component {
+ static propTypes = {
+ current_user: CurrentUserPropType,
+ theme: PropTypes.string
+ };
+
+ static defaultProps = {
+ theme: 'normal'
+ };
+
+ /**
+ * An example of result:
+ {
+ className: 'navigation-item--color_green',
+ list: values(current_user.followed_geotags) || [],
+ icon: { icon: 'place', className: 'navigation-item__icon--remind_green' },
+ unreadPosts: 44,
+ url: '/geo/'
+ }
+ */
+ getUserPostTags = () => {
+ const { current_user } = this.props;
+
+ return {
+ geotags: {
+ className: 'navigation-item--color_green',
+ list: values(current_user.followed_geotags) || [],
+ icon: { icon: 'place' },
+ url: '/geo/'
+ },
+ hashtags: {
+ className: 'navigation-item--color_blue',
+ list: values(current_user.followed_hashtags) || [],
+ icon: { icon: 'hashtag' },
+ url: '/tag/'
+ },
+ schools: {
+ className: 'navigation-item--color_red',
+ list: values(current_user.followed_schools) || [],
+ icon: { icon: 'school' },
+ url: '/s/'
+ }
+ };
+ }
+
+ render() {
+ const { theme } = this.props;
+ const tags = this.getUserPostTags();
+
+ const childrenProps = {
+ tags,
+ ...omit(this.props, ['current_user', 'theme'])
+ };
+
+ switch (theme) {
+ case 'trunc': return ;
+ case 'ext': return ;
+ case 'normal':
+ default: return ;
+ }
+ }
+}
diff --git a/src/components/tags-inform/normal.js b/src/components/tags-inform/normal.js
new file mode 100644
index 00000000..ebacdc7e
--- /dev/null
+++ b/src/components/tags-inform/normal.js
@@ -0,0 +1,60 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+import { keys, transform } from 'lodash';
+
+import { TagsToInform as TagsToInformPropType } from './prop-types';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+import TagCloud from '../tag-cloud';
+
+const TagsInformNormal = ({ tags, ...props }) => (
+
+ {transform(tags, (acc, tagType, tagTypeTitle) => {
+ if (keys(tagType.list).length) {
+ let unread = tagType.unreadPosts;
+ if (tagType.unreadPosts > 99) {
+ unread = '99+';
+ }
+
+ acc.push(
+
+
+
+ );
+ }
+ }, [])}
+
+);
+
+TagsInformNormal.propTypes = {
+ tags: TagsToInformPropType
+};
+
+export default TagsInformNormal;
diff --git a/src/components/tags-inform/prop-types.js b/src/components/tags-inform/prop-types.js
new file mode 100644
index 00000000..9f7d9952
--- /dev/null
+++ b/src/components/tags-inform/prop-types.js
@@ -0,0 +1,46 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import { PropTypes } from 'react';
+
+import { MapOfGeotags as MapOfGeotagsPropType } from '../../prop-types/geotags';
+import { MapOfHashtags as MapOfHashtagsPropType } from '../../prop-types/hashtags';
+import { MapOfSchools as MapOfSchoolsPropType } from '../../prop-types/schools';
+
+const IconPropType = PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.shape({
+ className: PropTypes.string,
+ icon: PropTypes.string
+ // take more from IconComponent
+ })
+]);
+
+const getTagTypeToInform = (validate) => (
+ PropTypes.shape({
+ icon: IconPropType,
+ list: validate,
+ unreadPosts: PropTypes.number,
+ url: PropTypes.string
+ })
+);
+
+export const TagsToInform = PropTypes.shape({
+ geotags: getTagTypeToInform(MapOfGeotagsPropType),
+ hashtags: getTagTypeToInform(MapOfHashtagsPropType),
+ schools: getTagTypeToInform(MapOfSchoolsPropType)
+});
diff --git a/src/components/tags-inform/trunc.js b/src/components/tags-inform/trunc.js
new file mode 100644
index 00000000..3a46ba09
--- /dev/null
+++ b/src/components/tags-inform/trunc.js
@@ -0,0 +1,56 @@
+/*
+ This file is a part of libertysoil.org website
+ Copyright (C) 2016 Loki Education (Social Enterprise)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see .
+*/
+import React from 'react';
+import classNames from 'classnames';
+import { assign, keys, transform } from 'lodash';
+
+import { TagsToInform as TagsToInformPropType } from './prop-types';
+
+import Navigation from '../navigation';
+import NavigationItem from '../navigation-item';
+
+const TagsInformTrunc = ({ tags, ...props }) => (
+
+ {transform(tags, (acc, tagType, tagTypeTitle) => {
+ if (keys(tagType.list).length) {
+ const finalIcon = assign({}, tagType.icon, {
+ className: classNames({
+ 'navigation-item__icon--remind': tagType.unreadPosts,
+ [tagType.icon.className]: tagType.icon.className
+ })
+ });
+
+ acc.push(
+
+ );
+ }
+ }, [])}
+
+);
+
+TagsInformTrunc.propTypes = {
+ tags: TagsToInformPropType
+};
+
+export default TagsInformTrunc;
diff --git a/src/components/v2/sidebar.js b/src/components/v2/sidebar.js
deleted file mode 100644
index 0fa9876c..00000000
--- a/src/components/v2/sidebar.js
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- This file is a part of libertysoil.org website
- Copyright (C) 2016 Loki Education (Social Enterprise)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see .
-*/
-import React from 'react';
-
-// v1
-import Navigation from '../navigation';
-import NavigationItem from '../navigation-item';
-
-// v2
-import TagsInformer from './tags-informer';
-import Bookmarks from './bookmarks';
-
-export default class SidebarV2 extends React.Component {
- render() {
- const { current_user } = this.props;
- const { user } = current_user;
-
- const mainMenuItems = [
- { title: "News Feed", url: '/', ico: '' },
- { title: "My Likes", url: `/user/${user.username}/likes`, ico: '' },
- { title: "My Favorites", url: `/user/${user.username}/favorites`, ico: '' },
- { title: "Collections", url: '/collections', ico: '' }
- ];
-
- const followedTags = {
- geotags: { list: current_user.followed_geotags },
- hashtags: { list: current_user.followed_hashtags },
- schools: { list: current_user.followed_schools }
- };
-
- return (
-