From f334fb4b355d90cbf0b8d9e658a87ebeec7fbe90 Mon Sep 17 00:00:00 2001 From: François Schmidts Date: Sat, 30 Jan 2016 01:44:13 +0100 Subject: wip redoing feed panel --- src/web/js/components/MiddlePanel.react.js | 12 +- src/web/js/components/RightPanel.react.js | 252 +++++++++++++++++++++++------ src/web/js/components/time.react.js | 15 ++ src/web/js/stores/MiddlePanelStore.js | 3 +- src/web/js/stores/RightPanelStore.js | 4 +- 5 files changed, 229 insertions(+), 57 deletions(-) create mode 100644 src/web/js/components/time.react.js (limited to 'src/web/js') diff --git a/src/web/js/components/MiddlePanel.react.js b/src/web/js/components/MiddlePanel.react.js index 6b3eb427..6bfdaaa9 100644 --- a/src/web/js/components/MiddlePanel.react.js +++ b/src/web/js/components/MiddlePanel.react.js @@ -1,6 +1,4 @@ var React = require('react'); -var ReactIntl = require('react-intl'); -var FormattedRelative = ReactIntl.FormattedRelative; var Row = require('react-bootstrap/Row'); var Button = require('react-bootstrap/Button'); @@ -11,8 +9,9 @@ var MiddlePanelStore = require('../stores/MiddlePanelStore'); var MiddlePanelActions = require('../actions/MiddlePanelActions'); var RightPanelActions = require('../actions/RightPanelActions'); +var JarrTime = require('./time.react'); + var TableLine = React.createClass({ - mixins: [ReactIntl.IntlMixin], propTypes: {article_id: React.PropTypes.number.isRequired, feed_title: React.PropTypes.string.isRequired, icon_url: React.PropTypes.string, @@ -49,11 +48,10 @@ var TableLine = React.createClass({ } // FIXME https://github.com/yahoo/react-intl/issues/189 // use FormattedRelative when fixed, will have to upgrade to ReactIntlv2 - var date = (); return (
-
{title}
{date} +
{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 a18f0ac3..2e2aac3e 100644 --- a/src/web/js/components/RightPanel.react.js +++ b/src/web/js/components/RightPanel.react.js @@ -1,70 +1,223 @@ var React = require('react'); var Col = require('react-bootstrap/Col'); -var Panel = require('react-bootstrap/Panel'); +var Glyphicon = require('react-bootstrap/Glyphicon'); +var Button = require('react-bootstrap/Button'); +var ButtonGroup = require('react-bootstrap/ButtonGroup'); + var RightPanelStore = require('../stores/RightPanelStore'); +var JarrTime = require('./time.react'); -var Article = React.createClass({ - propTypes: {article: React.PropTypes.object.isRequired}, - render: function() { +var PanelMixin = { + propTypes: {obj: React.PropTypes.object.isRequired}, + getHeader: function() { var icon = null; - if(this.props.article.icon_url){ - icon = (); + if(this.props.obj.icon_url){ + icon = (); + } + var btn_grp = null; + if(this.isEditable() || this.isRemovable()) { + var edit_button = null; + if(this.isEditable()) { + edit_button = (); + } + var rem_button = null; + if(this.isRemovable()) { + rem_button = (); + } + btn_grp = ( + {edit_button} + {rem_button} + ); } - var header = (

- {icon}Title: {this.props.article.title} -

); - return ( -
- + return (
+

{icon}Title: {this.getTitle()}

+ {btn_grp} +
); + }, + getKey: function(prefix, suffix) { + return ((this.state.edit_mode?'edit':'fix') + prefix + + '-' + this.props.obj.id + '-' + suffix); + }, + getCore: function() { + var items = []; + var key; + if(!this.state.edit_mode) { + this.fields.map(function(field) { + key = this.getKey('dt', field.key); + items.push(
{field.title}
); + key = this.getKey('dd', field.key); + if(field.type == 'string') { + items.push(
{this.props.obj[field.key]}
); + } else if(field.type == 'bool') { + if(this.props.obj[field.key]) { + items.push(
); + } else { + items.push(
); + } + } else if (field.type == 'link') { + items.push(
+ + {this.props.obj[field.key]} + +
); + } + }.bind(this)); + } else { + this.fields.map(function(field) { + key = this.getKey('dd', field.key); + items.push(
{field.title}
); + key = this.getKey('dt', field.key); + if(field.type == 'string' || field.type == 'link') { + items.push(
+
); + } else if (field.type == 'bool') { + items.push(
); + } + }.bind(this)); + items.push(
+ +
); + } + return (
{items}
); + }, + render: function() { + return (
+ {this.getHeader()} + {this.getBody()} +
); }, + onClickEdit: function() { + this.setState({edit_mode: !this.state.edit_mode}); + }, + onClickRemove: function() { + }, +}; + +var Article = React.createClass({ + mixins: [PanelMixin], + getInitialState: function() {return {edit_mode: false};}, + fields: [], + isEditable: function() {return false;}, + isRemovable: function() {return true;}, + getTitle: function() {return this.props.obj.title;}, + getBody: function() { + return (
); + }, }); var Feed = React.createClass({ - propTypes: {feed: React.PropTypes.object.isRequired}, - render: function() { - var icon = null; - if(this.props.feed.icon_url){ - icon = (); + mixins: [PanelMixin], + getInitialState: function() { + return {edit_mode: false, filters: this.props.obj.filters}; + }, + isEditable: function() {return true;}, + isRemovable: function() {return true;}, + fields: [{'title': 'Feed title', 'type': 'string', 'key': 'title'}, + {'title': 'Description', 'type': 'string', 'key': 'description'}, + {'title': 'Feed link', 'type': 'link', 'key': 'link'}, + {'title': 'Site link', 'type': 'link', 'key': 'site_link'}, + {'title': 'Enabled', 'type': 'bool', 'key': 'enabled'}, + ], + getTitle: function() {return this.props.obj.title;}, + getFilterRow: function(i, filter) { + return (
+ + + + + + + +
); + }, + getBody: function() { + var filter_rows = []; + for(var i in this.state.filters) { + filter_rows.push(this.getFilterRow(i, this.state.filters[i])); } - var header = (

- {icon}Title: {this.props.feed.title} -

); - return ( + return (
-
Description
-
{this.props.feed.description}
Created on
-
{this.props.feed.created_date}
-
Feed adress
-
- - {this.props.feed.link} - +
+
+
Last fetched
+
-
Site link
+
+ {this.getCore()} +
+
+
Filters
- - {this.props.feed.site_link} - + +
-
Last fetched
-
{this.props.feed.last_retrieved}
-
Enabled
-
{this.props.feed.enabled}
+ {filter_rows} +
- +
); }, + addFilterRow: function() { + var filters = this.state.filters; + filters.push({action: null, action_on: null, + type: null, pattern: null}); + this.setState({filters: filters}); + }, + removeFilterRow: function(evnt) { + var filters = this.state.filters; + delete filters[evnt.target.getAttribute('data-index')]; + this.setState({filters: filters}); + }, }); var Category = React.createClass({ - propTypes: {category: React.PropTypes.object.isRequired}, - render: function() { - return ( - test - - ); + mixins: [PanelMixin], + getInitialState: function() {return {edit_mode: false};}, + isEditable: function() { + if(this.props.obj.id != 0) {return true;} + else {return false;} + }, + isRemovable: function() {return this.isEditable();}, + fields: [{'title': 'Category name', 'type': 'string', 'key': 'name'}], + getTitle: function() {return this.props.obj.name;}, + getBody: function() { + return (
+ {this.getCore()} +
); }, }); @@ -112,18 +265,21 @@ var RightPanel = React.createClass({ ); } if(this.state.current == 'article') { - var content =
; + var cntnt = (
); } else if(this.state.current == 'feed') { - var content = ; + var cntnt = (); } else if(this.state.current == 'category') { - var content = ; + var cntnt = (); } return ( {breadcrum} - {content} + {cntnt} ); }, diff --git a/src/web/js/components/time.react.js b/src/web/js/components/time.react.js new file mode 100644 index 00000000..8b4d47d9 --- /dev/null +++ b/src/web/js/components/time.react.js @@ -0,0 +1,15 @@ +var React = require('react'); +var ReactIntl = require('react-intl'); + +var JarrTime = React.createClass({ + mixins: [ReactIntl.IntlMixin], + propTypes: {stamp: React.PropTypes.number.isRequired, + text: React.PropTypes.string.isRequired}, + render: function() { + return (); + }, +}); + +module.exports = JarrTime; diff --git a/src/web/js/stores/MiddlePanelStore.js b/src/web/js/stores/MiddlePanelStore.js index 1a0a4fab..4a5efd00 100644 --- a/src/web/js/stores/MiddlePanelStore.js +++ b/src/web/js/stores/MiddlePanelStore.js @@ -119,9 +119,10 @@ MiddlePanelStore.dispatchToken = JarrDispatcher.register(function(action) { for (var i in MiddlePanelStore._datas.articles) { if(MiddlePanelStore._datas.articles[i].article_id == action.article.id) { MiddlePanelStore._datas.articles[i].read = true; - console.log(MiddlePanelStore._datas.articles[i]); + break; } } + break; default: // pass } diff --git a/src/web/js/stores/RightPanelStore.js b/src/web/js/stores/RightPanelStore.js index 68d3b7e9..85f336e4 100644 --- a/src/web/js/stores/RightPanelStore.js +++ b/src/web/js/stores/RightPanelStore.js @@ -30,17 +30,19 @@ RightPanelStore.dispatchToken = JarrDispatcher.register(function(action) { if(action.filter_id == null) { RightPanelStore._datas.category = null; RightPanelStore._datas.feed = null; + RightPanelStore._datas.current = null; } else if(action.filter_type == 'category_id') { RightPanelStore._datas.category = MenuStore._datas.categories[action.filter_id]; RightPanelStore._datas.feed = null; RightPanelStore._datas.current = 'category'; + RightPanelStore.emitChange(); } else { RightPanelStore._datas.feed = MenuStore._datas.feeds[action.filter_id]; RightPanelStore._datas.category = MenuStore._datas.categories[RightPanelStore._datas.feed.category_id]; RightPanelStore._datas.current = 'feed'; + RightPanelStore.emitChange(); } - RightPanelStore.emitChange(); break; case ActionTypes.LOAD_ARTICLE: RightPanelStore._datas.feed = MenuStore._datas.feeds[action.article.feed_id]; -- cgit