From a881023f128f0a0903cb46e298115083b4c427f9 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Wed, 2 Mar 2016 07:30:51 +0100 Subject: minor update to the navbar --- src/web/js/components/Navbar.react.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/web/js/components/Navbar.react.js b/src/web/js/components/Navbar.react.js index 08716977..a5dedcf9 100644 --- a/src/web/js/components/Navbar.react.js +++ b/src/web/js/components/Navbar.react.js @@ -70,7 +70,7 @@ JarrNavBar = React.createClass({ this.setState({showModal: true, modalType: 'addCategory'}); }, render: function() { - return ( + return ( {this.getModal()} @@ -78,6 +78,7 @@ JarrNavBar = React.createClass({ + + ); }, -- cgit From b32ca6c0f5968f5e9f59847db5012e3ef7f98631 Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Wed, 2 Mar 2016 08:25:52 +0100 Subject: Code update. Some problems with CSRF token on Chromium... --- src/web/controllers/user.py | 7 +- src/web/js/actions/RightPanelActions.js | 8 +- src/web/js/components/MainApp.react.js | 2 +- src/web/js/components/Menu.react.js | 8 +- src/web/js/components/MiddlePanel.react.js | 8 +- src/web/js/components/RightPanel.react.js | 30 ++++- src/web/js/stores/MenuStore.js | 6 + src/web/templates/home.html | 2 +- src/web/templates/layout.html | 10 +- src/web/views/admin.py | 153 +++------------------ src/web/views/api/__init__.py | 28 ---- src/web/views/api/article.py | 63 ++++----- src/web/views/api/category.py | 20 ++- src/web/views/api/common.py | 210 +++++++++++++---------------- src/web/views/api/feed.py | 60 +++------ src/web/views/article.py | 10 +- src/web/views/category.py | 2 +- src/web/views/feed.py | 4 +- src/web/views/session_mgmt.py | 57 ++------ src/web/views/views.py | 28 ---- 20 files changed, 234 insertions(+), 482 deletions(-) diff --git a/src/web/controllers/user.py b/src/web/controllers/user.py index ee2eb4c2..1b5c123e 100644 --- a/src/web/controllers/user.py +++ b/src/web/controllers/user.py @@ -1,9 +1,10 @@ -import random -import hashlib +import logging from werkzeug import generate_password_hash, check_password_hash from .abstract import AbstractController from web.models import User +logger = logging.getLogger(__name__) + class UserController(AbstractController): _db_cls = User @@ -11,7 +12,7 @@ class UserController(AbstractController): def _handle_password(self, attrs): if attrs.get('password'): - attrs['pwdhash'] = generate_password_hash(attrs.pop('password')) + attrs['password'] = generate_password_hash(attrs.pop('password')) elif 'password' in attrs: del attrs['password'] diff --git a/src/web/js/actions/RightPanelActions.js b/src/web/js/actions/RightPanelActions.js index 47adad79..5d78e001 100644 --- a/src/web/js/actions/RightPanelActions.js +++ b/src/web/js/actions/RightPanelActions.js @@ -4,8 +4,12 @@ var ActionTypes = require('../constants/JarrConstants'); var MenuActions = require('../actions/MenuActions'); var RightPanelActions = { - loadArticle: function(article_id, was_read_before) { - jquery.getJSON('/getart/' + article_id, + loadArticle: function(article_id, was_read_before, to_parse) { + var suffix = ''; + if(to_parse) { + suffix = '/parse'; + } + jquery.getJSON('/getart/' + article_id + suffix, function(payload) { JarrDispatcher.dispatch({ type: ActionTypes.LOAD_ARTICLE, diff --git a/src/web/js/components/MainApp.react.js b/src/web/js/components/MainApp.react.js index cbdc5833..ffb14589 100644 --- a/src/web/js/components/MainApp.react.js +++ b/src/web/js/components/MainApp.react.js @@ -15,7 +15,7 @@ var MainApp = React.createClass({ + xs={12} sm={4} md={4} lg={4}> diff --git a/src/web/js/components/Menu.react.js b/src/web/js/components/Menu.react.js index 60578f8a..f4ad76d0 100644 --- a/src/web/js/components/Menu.react.js +++ b/src/web/js/components/Menu.react.js @@ -84,13 +84,15 @@ var CategoryGroup = React.createClass({ name: React.PropTypes.string.isRequired, feeds: React.PropTypes.array.isRequired, unread: React.PropTypes.number.isRequired, - folded: React.PropTypes.bool.isRequired, + folded: React.PropTypes.bool, }, getInitialState: function() { - return {folded: this.props.folded}; + return {folded: false}; }, componentWillReceiveProps: function(nextProps) { - this.setState({folded: nextProps.folded}); + if(nextProps.folded != null) { + this.setState({folded: nextProps.folded}); + } }, render: function() { // hidden the no category if empty diff --git a/src/web/js/components/MiddlePanel.react.js b/src/web/js/components/MiddlePanel.react.js index dad33acc..cb5be92d 100644 --- a/src/web/js/components/MiddlePanel.react.js +++ b/src/web/js/components/MiddlePanel.react.js @@ -35,7 +35,7 @@ var TableLine = React.createClass({ icon = ; } var title = ( + onClick={this.openRedirectLink} target="_blank"> {icon} {this.props.feed_title} ); var read = (); icon = ; - var newTab = ( - {icon} - ); var clsses = "list-group-item"; if(this.props.selected) { clsses += " active"; @@ -57,7 +53,7 @@ var TableLine = React.createClass({
{title}
-
{read} {liked} {newTab} {this.props.title}
+
{read} {liked} {this.props.title}
); }, diff --git a/src/web/js/components/RightPanel.react.js b/src/web/js/components/RightPanel.react.js index 39b06f38..6005e954 100644 --- a/src/web/js/components/RightPanel.react.js +++ b/src/web/js/components/RightPanel.react.js @@ -35,6 +35,7 @@ var PanelMixin = { ); } btn_grp = ( + {this.getExtraButton()} {edit_button} {rem_button} ); @@ -169,13 +170,28 @@ var Article = React.createClass({ ], obj_type: 'article', getTitle: function() {return this.props.obj.title;}, + getExtraButton: function() { + if(!this.props.obj.readability_available) { + return null; + } + return (); + }, getBody: function() { return (
{this.getCore()} -
); }, + reloadParsed: function() { + if(this.props.obj.readability_available + && !this.props.obj.readability_parsed) { + RightPanelActions.loadArticle(this.props.obj.id, true, true); + } + }, }); var Feed = React.createClass({ @@ -188,10 +204,13 @@ var Feed = React.createClass({ {'title': 'Feed link', 'type': 'link', 'key': 'link'}, {'title': 'Site link', 'type': 'link', 'key': 'site_link'}, {'title': 'Enabled', 'type': 'bool', 'key': 'enabled'}, + {'title': 'Auto Readability', + 'type': 'bool', 'key': 'readability_auto_parse'}, {'title': 'Filters', 'type': 'ignore', 'key': 'filters'}, {'title': 'Category', 'type': 'ignore', 'key': 'category_id'}, ], getTitle: function() {return this.props.obj.title;}, + getExtraButton: function() {return null;}, getFilterRow: function(i, filter) { return (
@@ -317,8 +336,6 @@ var Feed = React.createClass({
-
Number of articles
-
{this.props.obj.nb_articles}
{this.getErrorFields()} {this.getCategorySelect()} @@ -353,6 +370,7 @@ var Category = React.createClass({ if(this.props.obj.id != 0) {return true;} else {return false;} }, + getExtraButton: function () {return null;}, isRemovable: function() {return this.isEditable();}, obj_type: 'category', fields: [{'title': 'Category name', 'type': 'string', 'key': 'name'}], @@ -423,9 +441,9 @@ var RightPanel = React.createClass({ key={this.state.category.id} />); } - return ( + return ( {breadcrum} {cntnt} diff --git a/src/web/js/stores/MenuStore.js b/src/web/js/stores/MenuStore.js index 49c61bc1..9686ff4a 100644 --- a/src/web/js/stores/MenuStore.js +++ b/src/web/js/stores/MenuStore.js @@ -17,6 +17,7 @@ var MenuStore = assign({}, EventEmitter.prototype, { setFilter: function(value) { if(this._datas.filter != value) { this._datas.filter = value; + this._datas.all_folded = null; this.emitChange(); } }, @@ -24,6 +25,7 @@ var MenuStore = assign({}, EventEmitter.prototype, { if(this._datas.active_id != value || this._datas.active_type != type) { this._datas.active_type = type; this._datas.active_id = value; + this._datas.all_folded = null; this.emitChange(); } }, @@ -53,6 +55,7 @@ MenuStore.dispatchToken = JarrDispatcher.register(function(action) { MenuStore._datas['error_threshold'] = action.error_threshold; MenuStore._datas['crawling_method'] = action.crawling_method; MenuStore._datas['all_unread_count'] = action.all_unread_count; + MenuStore._datas.all_folded = null; MenuStore.emitChange(); break; case ActionTypes.PARENT_FILTER: @@ -81,6 +84,7 @@ MenuStore.dispatchToken = JarrDispatcher.register(function(action) { MenuStore._datas.categories[cat_id].unread += new_unread[feed_id]; } if(changed) { + MenuStore._datas.all_folded = null; MenuStore.emitChange(); } } @@ -98,12 +102,14 @@ MenuStore.dispatchToken = JarrDispatcher.register(function(action) { MenuStore._datas.categories[article.category_id].unread += val; MenuStore._datas.feeds[article.feed_id].unread += val; }); + MenuStore._datas.all_folded = null; MenuStore.emitChange(); break; case ActionTypes.LOAD_ARTICLE: if(!action.was_read_before) { MenuStore._datas.categories[action.article.category_id].unread -= 1; MenuStore._datas.feeds[action.article.feed_id].unread -= 1; + MenuStore._datas.all_folded = null; MenuStore.emitChange(); } break; diff --git a/src/web/templates/home.html b/src/web/templates/home.html index fcb2a042..155742c5 100644 --- a/src/web/templates/home.html +++ b/src/web/templates/home.html @@ -7,7 +7,7 @@ JARR{% if head_titles %} - {{ ' - '.join(head_titles) }}{% endif %} - + diff --git a/src/web/templates/layout.html b/src/web/templates/layout.html index d382a6dd..50f96e8f 100644 --- a/src/web/templates/layout.html +++ b/src/web/templates/layout.html @@ -7,12 +7,12 @@ JARR{% if head_titles %} - {{ ' - '.join(head_titles) }}{% endif %} - + - {% endblock %} + {% endblock %}