Adding React.js, Redux, revamping dashboard

This commit is contained in:
Eugen Rochko 2016-08-24 17:56:44 +02:00
parent 68c93f8b85
commit 49520d6e62
34 changed files with 297 additions and 75 deletions

View file

@ -0,0 +1,18 @@
export const SET_TIMELINE = 'SET_TIMELINE';
export const ADD_STATUS = 'ADD_STATUS';
export function setTimeline(timeline, statuses) {
return {
type: SET_TIMELINE,
timeline: timeline,
statuses: statuses
};
}
export function addStatus(timeline, status) {
return {
type: ADD_STATUS,
timeline: timeline,
status: status
};
}

View file

@ -0,0 +1,19 @@
import StatusListContainer from '../containers/status_list_container';
import ColumnHeader from './column_header';
const Column = React.createClass({
propTypes: {
type: React.PropTypes.string
},
render: function() {
return (
<div style={{ width: '350px', flex: '0 0 auto', background: '#282c37', margin: '10px', marginRight: '0', display: 'flex', flexDirection: 'column' }}>
<ColumnHeader type={this.props.type} />
<StatusListContainer type={this.props.type} />
</div>
);
}
});
export default Column;

View file

@ -0,0 +1,15 @@
const ColumnHeader = React.createClass({
propTypes: {
type: React.PropTypes.string
},
render: function() {
return (
<div style={{ padding: '15px', fontSize: '16px', background: '#2f3441', flex: '0 0 auto' }}>
{this.props.type}
</div>
);
}
});
export default ColumnHeader;

View file

@ -0,0 +1,15 @@
import Column from './column';
const ColumnsArea = React.createClass({
render: function() {
return (
<div style={{ display: 'flex', flexDirection: 'row', flex: '1' }}>
<Column type='home' />
<Column type='mentions' />
</div>
);
}
});
export default ColumnsArea;

View file

@ -0,0 +1,16 @@
import NavBar from './nav_bar';
import ColumnsArea from './columns_area';
const Frontend = React.createClass({
render: function() {
return (
<div style={{ flex: '0 0 auto', display: 'flex', width: '100%', height: '100%', background: '#1a1c23' }}>
<NavBar />
<ColumnsArea />
</div>
);
}
});
export default Frontend;

View file

@ -0,0 +1,8 @@
const NavBar = React.createClass({
render: function() {
return <div style={{ background: '#2f3441', width: '60px', margin: '10px', marginRight: '0' }} />;
}
});
export default NavBar;

View file

@ -0,0 +1,19 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
const Status = React.createClass({
propTypes: {
status: ImmutablePropTypes.map.isRequired
},
render: function() {
console.log(this.props.status.toJS());
return (
<div style={{ height: '100px' }}>
{this.props.status.getIn(['account', 'username'])}: {this.props.status.get('content')}
</div>
);
}
});
export default Status;

View file

@ -0,0 +1,22 @@
import Status from './status';
import ImmutablePropTypes from 'react-immutable-proptypes';
const StatusList = React.createClass({
propTypes: {
statuses: ImmutablePropTypes.list.isRequired
},
render: function() {
return (
<div style={{ overflowY: 'scroll', flex: '1 1 auto' }}>
<div>
{this.props.statuses.map((status) => {
return <Status key={status.get('id')} status={status} />;
})}
</div>
</div>
);
}
});
export default StatusList;

View file

@ -0,0 +1,40 @@
import { Provider } from 'react-redux';
import configureStore from '../store/configureStore';
import Frontend from '../components/frontend';
import { setTimeline, addStatus } from '../actions/statuses';
const store = configureStore();
const Root = React.createClass({
componentWillMount() {
for (var timelineType in this.props.timelines) {
if (this.props.timelines.hasOwnProperty(timelineType)) {
store.dispatch(setTimeline(timelineType, JSON.parse(this.props.timelines[timelineType])));
}
}
if (typeof App !== 'undefined') {
App.timeline = App.cable.subscriptions.create("TimelineChannel", {
connected: function() {},
disconnected: function() {},
received: function(data) {
return store.dispatch(addStatus(data.timeline, JSON.parse(data.message)));
}
});
}
},
render() {
return (
<Provider store={store}>
<Frontend />
</Provider>
);
}
});
export default Root;

View file

@ -0,0 +1,10 @@
import { connect } from 'react-redux';
import StatusList from '../components/status_list';
const mapStateToProps = function (state, props) {
return {
statuses: state.getIn(['statuses', props.type])
};
};
export default connect(mapStateToProps)(StatusList);

View file

@ -0,0 +1,6 @@
import { combineReducers } from 'redux-immutable';
import statuses from './statuses';
export default combineReducers({
statuses
});

View file

@ -0,0 +1,17 @@
import { SET_TIMELINE, ADD_STATUS } from '../actions/statuses';
import Immutable from 'immutable';
const initialState = Immutable.Map();
export default function statuses(state = initialState, action) {
switch(action.type) {
case SET_TIMELINE:
return state.set(action.timeline, Immutable.fromJS(action.statuses));
case ADD_STATUS:
return state.update(action.timeline, function (list) {
list.unshift(Immutable.fromJS(action.status));
});
default:
return state;
}
}

View file

@ -0,0 +1,6 @@
import { createStore } from 'redux';
import appReducer from '../reducers';
export default function configureStore(initialState) {
return createStore(appReducer, initialState);
}