diff options
-rw-r--r-- | package.json | 4 | ||||
-rw-r--r-- | src/web/js/components/MainApp.react.js | 13 | ||||
-rw-r--r-- | src/web/js/components/Menu.react.js | 148 | ||||
-rw-r--r-- | src/web/js/components/MiddlePanel.react.js | 24 | ||||
-rw-r--r-- | src/web/templates/home2.html | 103 |
5 files changed, 199 insertions, 93 deletions
diff --git a/package.json b/package.json index ba072568..64569b63 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "jquery": "^2.2.0", "keymirror": "~0.1.0", "object-assign": "^1.0.0", - "react": "^0.14.0", + "react": "^0.14.6", "react-bootstrap": "^0.14.1", - "react-dom": "^0.14.0" + "react-dom": "^0.14.6" }, "devDependencies": { "browserify": "^6.2.0", diff --git a/src/web/js/components/MainApp.react.js b/src/web/js/components/MainApp.react.js index bd643be1..816e8c82 100644 --- a/src/web/js/components/MainApp.react.js +++ b/src/web/js/components/MainApp.react.js @@ -1,6 +1,6 @@ var React = require('react'); -var Col = require('react-bootstrap/lib/Col'); -var Grid = require('react-bootstrap/lib/Grid'); +var Col = require('react-bootstrap/Col'); +var Row = require('react-bootstrap/Row'); var Menu = require('./Menu.react'); var MiddlePanel = require('./MiddlePanel.react'); @@ -9,11 +9,8 @@ var RightPanel = require('./RightPanel.react'); var MainApp = React.createClass({ render: function() { - return (<Grid fluid> - <Col xsHidden smHidden md={3} lg={2}> - <Menu.MenuFilter /> - <Menu.Menu /> - </Col> + return (<Row> + <Menu /> <Col xs={2} sm={2} md={4} lg={4}> <MiddlePanel.MiddlePanelFilter /> <MiddlePanel.MiddlePanel /> @@ -22,7 +19,7 @@ var MainApp = React.createClass({ <RightPanel.RightPanelMenu /> <RightPanel.RightPanel /> </Col> - </Grid> + </Row> ); }, }); diff --git a/src/web/js/components/Menu.react.js b/src/web/js/components/Menu.react.js index becc7a2e..4b8c167c 100644 --- a/src/web/js/components/Menu.react.js +++ b/src/web/js/components/Menu.react.js @@ -1,11 +1,9 @@ var React = require('react'); -var Row = require('react-bootstrap/lib/Row'); -var Badge = require('react-bootstrap/lib/Badge'); -var Button = require('react-bootstrap/lib/Button'); -var ButtonGroup = require('react-bootstrap/lib/ButtonGroup'); -var ListGroup = require('react-bootstrap/lib/ListGroup'); -var ListGroupItem = require('react-bootstrap/lib/ListGroupItem'); -var Glyphicon = require('react-bootstrap/lib/Glyphicon'); +var Col = require('react-bootstrap/Col'); +var Badge = require('react-bootstrap/Badge'); +var Button = require('react-bootstrap/Button'); +var ButtonGroup = require('react-bootstrap/ButtonGroup'); +var Glyphicon = require('react-bootstrap/Glyphicon'); var MenuStore = require('../stores/MenuStore'); var MenuActions = require('../actions/MenuActions'); @@ -36,10 +34,9 @@ var FeedItem = React.createClass({ } else if(this.props.error_count > 3) { style = "warning"; } - return (<ListGroupItem onMouseDown={this.handleClick} bsStyle={style} - href="#" active={this.props.active}> + return (<li onClick={this.handleClick}> {icon}{this.props.title}{badge_unread} - </ListGroupItem> + </li> ); }, handleClick: function() { @@ -48,6 +45,34 @@ var FeedItem = React.createClass({ }); var Category = React.createClass({ + propTypes: {category_id: React.PropTypes.number.isRequired, + filter: React.PropTypes.string.isRequired, + active_type: React.PropTypes.string, + active_id: React.PropTypes.number}, + render: function() { + if(this.props.active_type == 'active_id' + && this.props.active_id == this.props.category_id) { + var classes = "success active"; + } else { + var classes = "success"; + } + return (<li className={classes}> + <h4 onClick={this.handleClick}> + {this.props.children} + </h4> + </li> + ); + }, + handleClick: function() { + if(this.props.category_id != null) { + MiddlePanelActions.setCategoryFilter(this.props.category_id); + } else { + MiddlePanelActions.removeParentFilter(); + } + }, +}); + +var CategoryGroup = React.createClass({ propTypes: {cat_id: React.PropTypes.number.isRequired, filter: React.PropTypes.string.isRequired, active_type: React.PropTypes.string, @@ -89,19 +114,18 @@ var Category = React.createClass({ if(this.props.unread){ unread = <Badge pullRight>{this.props.unread}</Badge>; } - var active = a_type == 'category_id' && a_id == this.props.cat_id; var ctrl = (<Glyphicon onMouseDown={this.toggleFolding} pullLeft glyph={this.state.unfolded?"menu-down":"menu-right"} /> ); - return (<ListGroup> - <ListGroupItem href="#" bsStyle="success" - active={active} - onMouseDown={this.handleClick}> + return (<ul className="nav nav-sidebar"> + <Category category_id={this.props.cat_id} + active_type={this.props.active_id} + active_type={this.props.active_type}> {ctrl} <strong>{this.props.name}</strong> {unread} - </ListGroupItem> + </Category> {feeds} - </ListGroup> + </ul> ); }, handleClick: function() { @@ -114,43 +138,27 @@ var Category = React.createClass({ }); var MenuFilter = React.createClass({ - getInitialState: function() { - return {filter: 'all', feed_in_error: false}; - }, + propTypes: {feed_in_error: React.PropTypes.bool, + filter: React.PropTypes.string.isRequired}, render: function() { var error_button = null; - if (this.state.feed_in_error) { - error_button = (<Button active={this.state.filter == "error"} - onMouseDown={() => this.setFilter("error")} + if (this.props.feed_in_error) { + error_button = (<Button active={this.props.filter == "error"} + onMouseDown={() => MenuActions.setFilter("error")} bsSize="small" bsStyle="warning">Error</Button> ); } - return (<Row className="show-grid"> - <ButtonGroup> - <Button active={this.state.filter == "all"} - onMouseDown={() => this.setFilter("all")} - bsSize="small">All</Button> - <Button active={this.state.filter == "unread"} - onMouseDown={() => this.setFilter("unread")} - bsSize="small">Unread</Button> - {error_button} - </ButtonGroup> - </Row> + return (<ButtonGroup className="nav nav-sidebar"> + <Button active={this.props.filter == "all"} + onMouseDown={() => MenuActions.setFilter("all")} + bsSize="small">All</Button> + <Button active={this.props.filter == "unread"} + onMouseDown={() => MenuActions.setFilter("unread")} + bsSize="small">Unread</Button> + {error_button} + </ButtonGroup> ); }, - setFilter: function(filter) { - this.setState({filter: filter}); - MenuActions.setFilter(filter); - }, - componentDidMount: function() { - MenuStore.addChangeListener(this._onChange); - }, - componentWillUnmount: function() { - MenuStore.removeChangeListener(this._onChange); - }, - _onChange: function() { - this.setState({feed_in_error: MenuStore._datas.feed_in_error}); - }, }); var Menu = React.createClass({ @@ -160,25 +168,36 @@ var Menu = React.createClass({ }, render: function() { var state = this.state; - var rmPrntFilt = (<ListGroupItem href="#" bsStyle="success" - active={this.state.active_type == null - || this.state.active_id == null} - onMouseDown={MiddlePanelActions.removeParentFilter} - header="All"></ListGroupItem>); + if (this.state.active_type == null || this.state.active_id == null) { + var all_classname = "success active"; + } else { + var all_classname = "success"; + } + var rmPrntFilt = ( + <ul className="nav nav-sidebar"> + <Category category_id={null} + active_type={this.props.active_id} + active_type={this.props.active_type}> + <strong>All</strong> + </Category> + </ul> + ); - return (<Row className="show-grid"> - <ListGroup>{rmPrntFilt}</ListGroup> + return (<Col xsHidden smHidden md={3} lg={2} className="show-grid sidebar"> + <MenuFilter filter={this.state.filter} + feed_in_error={this.state.feed_in_error} /> + {rmPrntFilt} {this.state.categories.map(function(category){ - return (<Category key={"c" + category.id} - filter={state.filter} - active_type={state.active_type} - active_id={state.active_id} - cat_id={category.id} - feeds={category.feeds} - name={category.name} - unread={category.unread} />); + return (<CategoryGroup key={"c" + category.id} + filter={state.filter} + active_type={state.active_type} + active_id={state.active_id} + cat_id={category.id} + feeds={category.feeds} + name={category.name} + unread={category.unread} />); })} - </Row> + </Col> ); }, componentDidMount: function() { @@ -194,8 +213,9 @@ var Menu = React.createClass({ categories: datas.categories, active_type: datas.active_type, active_id: datas.active_id, + feed_in_error: datas.feed_in_error, all_unread_count: datas.all_unread_count}); }, }); -module.exports = {Menu: Menu, MenuFilter: MenuFilter}; +module.exports = Menu; diff --git a/src/web/js/components/MiddlePanel.react.js b/src/web/js/components/MiddlePanel.react.js index 756a811b..0a1dad45 100644 --- a/src/web/js/components/MiddlePanel.react.js +++ b/src/web/js/components/MiddlePanel.react.js @@ -1,10 +1,8 @@ var React = require('react'); -var Row = require('react-bootstrap/lib/Row'); -var Button = require('react-bootstrap/lib/Button'); -var ButtonGroup = require('react-bootstrap/lib/ButtonGroup'); -var ListGroup = require('react-bootstrap/lib/ListGroup'); -var ListGroupItem = require('react-bootstrap/lib/ListGroupItem'); -var Glyphicon = require('react-bootstrap/lib/Glyphicon'); +var Row = require('react-bootstrap/Row'); +var Button = require('react-bootstrap/Button'); +var ButtonGroup = require('react-bootstrap/ButtonGroup'); +var Glyphicon = require('react-bootstrap/Glyphicon'); var MiddlePanelStore = require('../stores/MiddlePanelStore'); var MiddlePanelActions = require('../actions/MiddlePanelActions'); @@ -36,12 +34,10 @@ var TableLine = React.createClass({ onClick={this.toogleRead} />); var liked = (<Glyphicon glyph={this.state.liked?"star":"star-empty"} onClick={this.toogleLike} />); - return ( - <ListGroupItem header={title}> - {read} - {liked} - {this.props.title} - </ListGroupItem> + return (<div className="list-group-item"> + <h4>{title}</h4> + {read} {liked} {this.props.title} + </div> ); }, toogleRead: function() { @@ -92,7 +88,7 @@ var MiddlePanel = React.createClass({ }, render: function() { return (<Row className="show-grid"> - <ListGroup> + <div className="list-group"> {this.state.articles.map(function(article){ return (<TableLine key={"a" + article.article_id} title={article.title} @@ -104,7 +100,7 @@ var MiddlePanel = React.createClass({ feed_id={article.feed_id} category_id={article.category_id} feed_title={article.feed_title} />);})} - </ListGroup> + </div> </Row> ); }, diff --git a/src/web/templates/home2.html b/src/web/templates/home2.html index 3e9d4a6f..673d9041 100644 --- a/src/web/templates/home2.html +++ b/src/web/templates/home2.html @@ -1,6 +1,99 @@ -{% extends "layout.html" %} -{% block content %} -<section id="jarrapp"></section> -<script type="text/javascript" src="{{ url_for("static", filename="js/bundle.min.js") }}"></script> +<!DOCTYPE html> +<html lang="en"> + <head> + {% block head %} + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <meta name="description" content="JARR is a web-based news aggregator." /> + <meta name="author" content="" /> + <title>JARR{% if head_titles %} - {{ ' - '.join(head_titles) }}{% endif %}</title> + <link rel="shortcut icon" href="{{ url_for("static", filename="img/favicon.png") }}" /> + <!-- Bootstrap core CSS --> + <link href="{{ url_for("static", filename="css/bootstrap.min.css") }}" rel="stylesheet" media="screen" /> + <!-- Add custom CSS here --> + <link href="{{ url_for("static", filename="css/customized-bootstrap.css") }}" rel="stylesheet" media="screen" /> + {% endblock %} + </head> + <body> + <nav class="navbar navbar-inverse navbar-fixed-top navbar-custom" role="navigation"> + <div class="container-fluid"> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> + <span class="sr-only">Toggle navigation</span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="{{ url_for("home") }}">JARR</a> + {% if head_titles %} + <p class="navbar-text" style="max-height: 20px; overflow: hidden"> + {{ " - ".join(head_titles) }} + </p> + {% endif %} + </div> -{% endblock %} + <!-- Collect the nav links, forms, and other content for toggling --> + <div class="collapse navbar-collapse navbar-ex1-collapse"> + <ul class="nav navbar-nav navbar-right"> + {% if g.user.is_authenticated %} + <!-- <li><a href="{{ url_for("feed.form") }}"><span class="glyphicon glyphicon-plus-sign"></span> {{ _('Add a feed') }}</a></li> --> + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"> + <div><span class="glyphicon glyphicon-plus-sign"></span> {{ _('Add a feed') }}</div> + </a> + <ul class="dropdown-menu"> + <li> + <form action="{{ url_for('feed.bookmarklet') }}" class="navbar-form navbar-left" method="GET" name="save"> + <div class="input-group input-group-inline"> + <input class="form-control" name="url" type="url" placeholder="{{_("site or feed url")}}" required="required"/> + <span class="input-group-btn"> + <button type="submit" class="btn btn-default" /><span class="glyphicon glyphicon-plus"></span></button> + </span> + </div><!-- /input-group --> + </form> + </li> + </ul> + </li> + {% if conf.CRAWLING_METHOD == "classic" and (not conf.ON_HEROKU or g.user.is_admin()) %} + <li><a href="/fetch"><span class="glyphicon glyphicon-import"></span> {{ _('Fetch') }}</a></li> + {% endif %} + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ _('Feed') }} <b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="{{ url_for("feeds.update", action="read") }}">{{ _('Mark all as read') }}</a></li> + <li><a href="{{ url_for("feeds.update", action="read", nb_days="1") }}">{{ _('Mark all as read older than yesterday') }}</a></li> + <li><a href="{{ url_for("feeds.update", action="read", nb_days="5") }}">{{ gettext('Mark all as read older than %(days)s days', days=5) }}</a></li> + <li><a href="{{ url_for("feeds.update", action="read", nb_days="10") }}">{{ gettext('Mark all as read older than %(days)s days', days=10) }}</a></li> + <li role="presentation" class="divider"></li> + <li><a href="{{ url_for("feeds.inactives") }}">{{ _('Inactive') }}</a></li> + <li><a href="{{ url_for("articles.history") }}">{{ _('History') }}</a></li> + <li><a href="{{ url_for("feeds.feeds") }}">{{ _('All') }}</a></li> + </ul> + </li> + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"> + <div><span class="glyphicon glyphicon-user"></span> <b class="caret"></b></div> + </a> + <ul class="dropdown-menu"> + <li><a href="{{ url_for("user.profile") }}"><span class="glyphicon glyphicon-user"></span> {{ _('Profile') }}</a></li> + <li><a href="{{ url_for("user.management") }}"><span class="glyphicon glyphicon-cog"></span> {{ _('Your data') }}</a></li> + <li><a href="{{ url_for("about") }}"><span class="glyphicon glyphicon-question-sign"></span> {{ _('About') }}</a></li> + {% if g.user.is_admin() %} + <li role="presentation" class="divider"></li> + <li><a href="{{ url_for("admin.dashboard") }}"><span class="glyphicon glyphicon-dashboard"></span> {{ _('Dashboard') }}</a></li> + <li role="presentation" class="divider"></li> + {% endif %} + <li><a href="{{ url_for("logout") }}"><span class="glyphicon glyphicon-log-out"></span> {{ _('Logout') }}</a></li> + </ul> + </li> + {% else %} + <li><a href="{{ url_for("about") }}"><span class="glyphicon glyphicon-question-sign"></span> {{ _('About') }}</a></li> + {% endif %} + </ul> + </div><!-- /.navbar-collapse --> + </div><!-- /.container --> + </nav> + <section id="jarrapp"></section> + <script type="text/javascript" src="{{ url_for('static', filename = 'js/bundle.min.js') }}"></script> + </body> +</html> |