Adding React.js, Redux, revamping dashboard
This commit is contained in:
parent
68c93f8b85
commit
49520d6e62
34 changed files with 297 additions and 75 deletions
0
app/assets/javascripts/components/.gitkeep
Normal file
0
app/assets/javascripts/components/.gitkeep
Normal file
18
app/assets/javascripts/components/actions/statuses.jsx
Normal file
18
app/assets/javascripts/components/actions/statuses.jsx
Normal 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
|
||||
};
|
||||
}
|
19
app/assets/javascripts/components/components/column.jsx
Normal file
19
app/assets/javascripts/components/components/column.jsx
Normal 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;
|
|
@ -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;
|
|
@ -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;
|
16
app/assets/javascripts/components/components/frontend.jsx
Normal file
16
app/assets/javascripts/components/components/frontend.jsx
Normal 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;
|
8
app/assets/javascripts/components/components/nav_bar.jsx
Normal file
8
app/assets/javascripts/components/components/nav_bar.jsx
Normal 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;
|
19
app/assets/javascripts/components/components/status.jsx
Normal file
19
app/assets/javascripts/components/components/status.jsx
Normal 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;
|
22
app/assets/javascripts/components/components/status_list.jsx
Normal file
22
app/assets/javascripts/components/components/status_list.jsx
Normal 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;
|
40
app/assets/javascripts/components/containers/root.jsx
Normal file
40
app/assets/javascripts/components/containers/root.jsx
Normal 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;
|
|
@ -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);
|
6
app/assets/javascripts/components/reducers/index.jsx
Normal file
6
app/assets/javascripts/components/reducers/index.jsx
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { combineReducers } from 'redux-immutable';
|
||||
import statuses from './statuses';
|
||||
|
||||
export default combineReducers({
|
||||
statuses
|
||||
});
|
17
app/assets/javascripts/components/reducers/statuses.jsx
Normal file
17
app/assets/javascripts/components/reducers/statuses.jsx
Normal 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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { createStore } from 'redux';
|
||||
import appReducer from '../reducers';
|
||||
|
||||
export default function configureStore(initialState) {
|
||||
return createStore(appReducer, initialState);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue